LLVM 22.0.0git
EHFrameSupport.cpp
Go to the documentation of this file.
1//===-------- JITLink_EHFrameSupport.cpp - JITLink eh-frame utils ---------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10
12#include "llvm/Config/config.h"
15
16#define DEBUG_TYPE "jitlink"
17
18namespace llvm {
19namespace jitlink {
20
22 unsigned PointerSize, Edge::Kind Pointer32,
23 Edge::Kind Pointer64, Edge::Kind Delta32,
24 Edge::Kind Delta64, Edge::Kind NegDelta32)
25 : EHFrameSectionName(EHFrameSectionName), PointerSize(PointerSize),
26 Pointer32(Pointer32), Pointer64(Pointer64), Delta32(Delta32),
27 Delta64(Delta64), NegDelta32(NegDelta32) {}
28
30 auto *EHFrame = G.findSectionByName(EHFrameSectionName);
31
32 if (!EHFrame) {
34 dbgs() << "EHFrameEdgeFixer: No " << EHFrameSectionName
35 << " section in \"" << G.getName() << "\". Nothing to do.\n";
36 });
37 return Error::success();
38 }
39
40 // Check that we support the graph's pointer size.
41 if (G.getPointerSize() != 4 && G.getPointerSize() != 8)
42 return make_error<JITLinkError>(
43 "EHFrameEdgeFixer only supports 32 and 64 bit targets");
44
46 dbgs() << "EHFrameEdgeFixer: Processing " << EHFrameSectionName << " in \""
47 << G.getName() << "\"...\n";
48 });
49
50 ParseContext PC(G);
51
52 // Build a map of all blocks and symbols in the text sections. We will use
53 // these for finding / building edge targets when processing FDEs.
54 for (auto &Sec : G.sections()) {
55 // Just record the most-canonical symbol (for eh-frame purposes) at each
56 // address.
57 for (auto *Sym : Sec.symbols()) {
58 auto &CurSym = PC.AddrToSym[Sym->getAddress()];
59 if (!CurSym || (std::make_tuple(Sym->getLinkage(), Sym->getScope(),
60 !Sym->hasName(), Sym->getName()) <
61 std::make_tuple(CurSym->getLinkage(), CurSym->getScope(),
62 !CurSym->hasName(), CurSym->getName())))
63 CurSym = Sym;
64 }
65 if (auto Err = PC.AddrToBlock.addBlocks(Sec.blocks(),
67 return Err;
68 }
69
70 // Sort eh-frame blocks into address order to ensure we visit CIEs before
71 // their child FDEs.
72 std::vector<Block *> EHFrameBlocks;
73 llvm::append_range(EHFrameBlocks, EHFrame->blocks());
74 llvm::sort(EHFrameBlocks, [](const Block *LHS, const Block *RHS) {
75 return LHS->getAddress() < RHS->getAddress();
76 });
77
78 // Loop over the blocks in address order.
79 for (auto *B : EHFrameBlocks)
80 if (auto Err = processBlock(PC, *B))
81 return Err;
82
83 return Error::success();
84}
85
89 if (auto Err = R.readInteger(Length))
90 return std::move(Err);
91
92 // If Length < 0xffffffff then use the regular length field, otherwise
93 // read the extended length field.
94 if (Length != 0xffffffff)
95 return Length;
96
97 uint64_t ExtendedLength;
98 if (auto Err = R.readInteger(ExtendedLength))
99 return std::move(Err);
100
101 if (ExtendedLength > std::numeric_limits<size_t>::max())
102 return make_error<JITLinkError>(
103 "In CFI record at " +
104 formatv("{0:x}", B.getAddress() + R.getOffset() - 12) +
105 ", extended length of " + formatv("{0:x}", ExtendedLength) +
106 " exceeds address-range max (" +
107 formatv("{0:x}", std::numeric_limits<size_t>::max()));
108
109 return ExtendedLength;
110}
111
112Error EHFrameEdgeFixer::processBlock(ParseContext &PC, Block &B) {
113
114 LLVM_DEBUG(dbgs() << " Processing block at " << B.getAddress() << "\n");
115
116 // eh-frame should not contain zero-fill blocks.
117 if (B.isZeroFill())
118 return make_error<JITLinkError>("Unexpected zero-fill block in " +
119 EHFrameSectionName + " section");
120
121 if (B.getSize() == 0) {
122 LLVM_DEBUG(dbgs() << " Block is empty. Skipping.\n");
123 return Error::success();
124 }
125
126 // Find the offsets of any existing edges from this block.
127 BlockEdgesInfo BlockEdges;
128 for (auto &E : B.edges())
129 if (E.isRelocation()) {
130 // Check if we already saw more than one relocation at this offset.
131 if (BlockEdges.Multiple.contains(E.getOffset()))
132 continue;
133
134 // Otherwise check if we previously had exactly one relocation at this
135 // offset. If so, we now have a second one and move it from the TargetMap
136 // into the Multiple set.
137 auto [It, Inserted] = BlockEdges.TargetMap.try_emplace(E.getOffset(), E);
138 if (!Inserted) {
139 BlockEdges.TargetMap.erase(It);
140 BlockEdges.Multiple.insert(E.getOffset());
141 }
142 }
143
144 BinaryStreamReader BlockReader(
145 StringRef(B.getContent().data(), B.getContent().size()),
146 PC.G.getEndianness());
147
148 // Get the record length.
149 Expected<size_t> RecordRemaining = readCFIRecordLength(B, BlockReader);
150 if (!RecordRemaining)
151 return RecordRemaining.takeError();
152
153 // We expect DWARFRecordSectionSplitter to split each CFI record into its own
154 // block.
155 if (BlockReader.bytesRemaining() != *RecordRemaining)
156 return make_error<JITLinkError>("Incomplete CFI record at " +
157 formatv("{0:x16}", B.getAddress()));
158
159 // Read the CIE delta for this record.
160 uint64_t CIEDeltaFieldOffset = BlockReader.getOffset();
161 uint32_t CIEDelta;
162 if (auto Err = BlockReader.readInteger(CIEDelta))
163 return Err;
164
165 if (CIEDelta == 0) {
166 if (auto Err = processCIE(PC, B, CIEDeltaFieldOffset, BlockEdges))
167 return Err;
168 } else {
169 if (auto Err = processFDE(PC, B, CIEDeltaFieldOffset, CIEDelta, BlockEdges))
170 return Err;
171 }
172
173 return Error::success();
174}
175
176Error EHFrameEdgeFixer::processCIE(ParseContext &PC, Block &B,
177 size_t CIEDeltaFieldOffset,
178 const BlockEdgesInfo &BlockEdges) {
179
180 LLVM_DEBUG(dbgs() << " Record is CIE\n");
181
182 BinaryStreamReader RecordReader(
183 StringRef(B.getContent().data(), B.getContent().size()),
184 PC.G.getEndianness());
185
186 // Skip past the CIE delta field: we've already processed this far.
187 RecordReader.setOffset(CIEDeltaFieldOffset + 4);
188
189 auto &CIESymbol = PC.G.addAnonymousSymbol(B, 0, B.getSize(), false, false);
190 CIEInformation CIEInfo(CIESymbol);
191
192 uint8_t Version = 0;
193 if (auto Err = RecordReader.readInteger(Version))
194 return Err;
195
196 if (Version != 0x01)
197 return make_error<JITLinkError>("Bad CIE version " + Twine(Version) +
198 " (should be 0x01) in eh-frame");
199
200 auto AugInfo = parseAugmentationString(RecordReader);
201 if (!AugInfo)
202 return AugInfo.takeError();
203
204 // Skip the EH Data field if present.
205 if (AugInfo->EHDataFieldPresent)
206 if (auto Err = RecordReader.skip(PC.G.getPointerSize()))
207 return Err;
208
209 // Read and validate the code alignment factor.
210 {
211 uint64_t CodeAlignmentFactor = 0;
212 if (auto Err = RecordReader.readULEB128(CodeAlignmentFactor))
213 return Err;
214 }
215
216 // Read and validate the data alignment factor.
217 {
218 int64_t DataAlignmentFactor = 0;
219 if (auto Err = RecordReader.readSLEB128(DataAlignmentFactor))
220 return Err;
221 }
222
223 // Skip the return address register field.
224 if (auto Err = RecordReader.skip(1))
225 return Err;
226
227 if (AugInfo->AugmentationDataPresent) {
228
229 CIEInfo.AugmentationDataPresent = true;
230
231 uint64_t AugmentationDataLength = 0;
232 if (auto Err = RecordReader.readULEB128(AugmentationDataLength))
233 return Err;
234
235 uint32_t AugmentationDataStartOffset = RecordReader.getOffset();
236
237 uint8_t *NextField = &AugInfo->Fields[0];
238 while (uint8_t Field = *NextField++) {
239 switch (Field) {
240 case 'L':
241 CIEInfo.LSDAPresent = true;
242 if (auto PE = readPointerEncoding(RecordReader, B, "LSDA"))
243 CIEInfo.LSDAEncoding = *PE;
244 else
245 return PE.takeError();
246 break;
247 case 'P': {
248 auto PersonalityPointerEncoding =
249 readPointerEncoding(RecordReader, B, "personality");
250 if (!PersonalityPointerEncoding)
251 return PersonalityPointerEncoding.takeError();
252 if (auto Err =
253 getOrCreateEncodedPointerEdge(
254 PC, BlockEdges, *PersonalityPointerEncoding, RecordReader,
255 B, RecordReader.getOffset(), "personality")
256 .takeError())
257 return Err;
258 break;
259 }
260 case 'R':
261 if (auto PE = readPointerEncoding(RecordReader, B, "address")) {
262 CIEInfo.AddressEncoding = *PE;
263 if (CIEInfo.AddressEncoding == dwarf::DW_EH_PE_omit)
264 return make_error<JITLinkError>(
265 "Invalid address encoding DW_EH_PE_omit in CIE at " +
266 formatv("{0:x}", B.getAddress().getValue()));
267 } else
268 return PE.takeError();
269 break;
270 default:
271 llvm_unreachable("Invalid augmentation string field");
272 }
273 }
274
275 if (RecordReader.getOffset() - AugmentationDataStartOffset >
276 AugmentationDataLength)
277 return make_error<JITLinkError>("Read past the end of the augmentation "
278 "data while parsing fields");
279 }
280
281 assert(!PC.CIEInfos.count(CIESymbol.getAddress()) &&
282 "Multiple CIEs recorded at the same address?");
283 PC.CIEInfos[CIESymbol.getAddress()] = std::move(CIEInfo);
284
285 return Error::success();
286}
287
288Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,
289 size_t CIEDeltaFieldOffset,
290 uint32_t CIEDelta,
291 const BlockEdgesInfo &BlockEdges) {
292 LLVM_DEBUG(dbgs() << " Record is FDE\n");
293
294 orc::ExecutorAddr RecordAddress = B.getAddress();
295
296 BinaryStreamReader RecordReader(
297 StringRef(B.getContent().data(), B.getContent().size()),
298 PC.G.getEndianness());
299
300 // Skip past the CIE delta field: we've already read this far.
301 RecordReader.setOffset(CIEDeltaFieldOffset + 4);
302
303 auto &FDESymbol = PC.G.addAnonymousSymbol(B, 0, B.getSize(), false, false);
304
305 CIEInformation *CIEInfo = nullptr;
306
307 {
308 // Process the CIE pointer field.
309 if (BlockEdges.Multiple.contains(CIEDeltaFieldOffset))
310 return make_error<JITLinkError>(
311 "CIE pointer field already has multiple edges at " +
312 formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset));
313
314 auto CIEEdgeItr = BlockEdges.TargetMap.find(CIEDeltaFieldOffset);
315
316 orc::ExecutorAddr CIEAddress =
317 RecordAddress + orc::ExecutorAddrDiff(CIEDeltaFieldOffset) -
318 orc::ExecutorAddrDiff(CIEDelta);
319 if (CIEEdgeItr == BlockEdges.TargetMap.end()) {
320 LLVM_DEBUG({
321 dbgs() << " Adding edge at "
322 << (RecordAddress + CIEDeltaFieldOffset)
323 << " to CIE at: " << CIEAddress << "\n";
324 });
325 if (auto CIEInfoOrErr = PC.findCIEInfo(CIEAddress))
326 CIEInfo = *CIEInfoOrErr;
327 else
328 return CIEInfoOrErr.takeError();
329 assert(CIEInfo->CIESymbol && "CIEInfo has no CIE symbol set");
330 B.addEdge(NegDelta32, CIEDeltaFieldOffset, *CIEInfo->CIESymbol, 0);
331 } else {
332 LLVM_DEBUG({
333 dbgs() << " Already has edge at "
334 << (RecordAddress + CIEDeltaFieldOffset) << " to CIE at "
335 << CIEAddress << "\n";
336 });
337 auto &EI = CIEEdgeItr->second;
338 if (EI.Addend)
339 return make_error<JITLinkError>(
340 "CIE edge at " +
341 formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset) +
342 " has non-zero addend");
343 if (auto CIEInfoOrErr = PC.findCIEInfo(EI.Target->getAddress()))
344 CIEInfo = *CIEInfoOrErr;
345 else
346 return CIEInfoOrErr.takeError();
347 }
348 }
349
350 // Process the PC-Begin field.
351 LLVM_DEBUG({
352 dbgs() << " Processing PC-begin at "
353 << (RecordAddress + RecordReader.getOffset()) << "\n";
354 });
355 if (auto PCBegin = getOrCreateEncodedPointerEdge(
356 PC, BlockEdges, CIEInfo->AddressEncoding, RecordReader, B,
357 RecordReader.getOffset(), "PC begin")) {
358 assert(*PCBegin && "PC-begin symbol not set");
359 if ((*PCBegin)->isDefined()) {
360 // Add a keep-alive edge from the FDE target to the FDE to ensure that the
361 // FDE is kept alive if its target is.
362 LLVM_DEBUG({
363 dbgs() << " Adding keep-alive edge from target at "
364 << (*PCBegin)->getBlock().getAddress() << " to FDE at "
365 << RecordAddress << "\n";
366 });
367 (*PCBegin)->getBlock().addEdge(Edge::KeepAlive, 0, FDESymbol, 0);
368 } else {
369 LLVM_DEBUG({
370 dbgs() << " WARNING: Not adding keep-alive edge to FDE at "
371 << RecordAddress << ", which points to "
372 << ((*PCBegin)->isExternal() ? "external" : "absolute")
373 << " symbol \"" << (*PCBegin)->getName()
374 << "\" -- FDE must be kept alive manually or it will be "
375 << "dead stripped.\n";
376 });
377 }
378 } else
379 return PCBegin.takeError();
380
381 // Skip over the PC range size field.
382 if (auto Err = skipEncodedPointer(CIEInfo->AddressEncoding, RecordReader))
383 return Err;
384
385 if (CIEInfo->AugmentationDataPresent) {
386 uint64_t AugmentationDataSize;
387 if (auto Err = RecordReader.readULEB128(AugmentationDataSize))
388 return Err;
389
390 if (CIEInfo->LSDAPresent)
391 if (auto Err = getOrCreateEncodedPointerEdge(
392 PC, BlockEdges, CIEInfo->LSDAEncoding, RecordReader, B,
393 RecordReader.getOffset(), "LSDA")
394 .takeError())
395 return Err;
396 } else {
397 LLVM_DEBUG(dbgs() << " Record does not have LSDA field.\n");
398 }
399
400 return Error::success();
401}
402
403Expected<EHFrameEdgeFixer::AugmentationInfo>
404EHFrameEdgeFixer::parseAugmentationString(BinaryStreamReader &RecordReader) {
405 AugmentationInfo AugInfo;
406 uint8_t NextChar;
407 uint8_t *NextField = &AugInfo.Fields[0];
408
409 if (auto Err = RecordReader.readInteger(NextChar))
410 return std::move(Err);
411
412 while (NextChar != 0) {
413 switch (NextChar) {
414 case 'z':
415 AugInfo.AugmentationDataPresent = true;
416 break;
417 case 'e':
418 if (auto Err = RecordReader.readInteger(NextChar))
419 return std::move(Err);
420 if (NextChar != 'h')
421 return make_error<JITLinkError>("Unrecognized substring e" +
422 Twine(NextChar) +
423 " in augmentation string");
424 AugInfo.EHDataFieldPresent = true;
425 break;
426 case 'L':
427 case 'P':
428 case 'R':
429 *NextField++ = NextChar;
430 break;
431 default:
432 return make_error<JITLinkError>("Unrecognized character " +
433 Twine(NextChar) +
434 " in augmentation string");
435 }
436
437 if (auto Err = RecordReader.readInteger(NextChar))
438 return std::move(Err);
439 }
440
441 return std::move(AugInfo);
442}
443
444Expected<uint8_t> EHFrameEdgeFixer::readPointerEncoding(BinaryStreamReader &R,
445 Block &InBlock,
446 const char *FieldName) {
447 using namespace dwarf;
448
449 uint8_t PointerEncoding;
450 if (auto Err = R.readInteger(PointerEncoding))
451 return std::move(Err);
452
453 bool Supported = true;
454 switch (PointerEncoding & 0xf) {
455 case DW_EH_PE_uleb128:
456 case DW_EH_PE_udata2:
457 case DW_EH_PE_sleb128:
458 case DW_EH_PE_sdata2:
459 Supported = false;
460 break;
461 }
462 if (Supported) {
463 switch (PointerEncoding & 0x70) {
464 case DW_EH_PE_textrel:
465 case DW_EH_PE_datarel:
466 case DW_EH_PE_funcrel:
467 case DW_EH_PE_aligned:
468 Supported = false;
469 break;
470 }
471 }
472
473 if (Supported)
474 return PointerEncoding;
475
476 return make_error<JITLinkError>("Unsupported pointer encoding " +
477 formatv("{0:x2}", PointerEncoding) + " for " +
478 FieldName + "in CFI record at " +
479 formatv("{0:x16}", InBlock.getAddress()));
480}
481
482Error EHFrameEdgeFixer::skipEncodedPointer(uint8_t PointerEncoding,
483 BinaryStreamReader &RecordReader) {
484 using namespace dwarf;
485
486 // Switch absptr to corresponding udata encoding.
487 if ((PointerEncoding & 0xf) == DW_EH_PE_absptr)
488 PointerEncoding |= (PointerSize == 8) ? DW_EH_PE_udata8 : DW_EH_PE_udata4;
489
490 switch (PointerEncoding & 0xf) {
491 case DW_EH_PE_udata4:
492 case DW_EH_PE_sdata4:
493 if (auto Err = RecordReader.skip(4))
494 return Err;
495 break;
496 case DW_EH_PE_udata8:
497 case DW_EH_PE_sdata8:
498 if (auto Err = RecordReader.skip(8))
499 return Err;
500 break;
501 default:
502 llvm_unreachable("Unrecognized encoding");
503 }
504 return Error::success();
505}
506
507Expected<Symbol *> EHFrameEdgeFixer::getOrCreateEncodedPointerEdge(
508 ParseContext &PC, const BlockEdgesInfo &BlockEdges, uint8_t PointerEncoding,
509 BinaryStreamReader &RecordReader, Block &BlockToFix,
510 size_t PointerFieldOffset, const char *FieldName) {
511 using namespace dwarf;
512
513 if (PointerEncoding == DW_EH_PE_omit)
514 return nullptr;
515
516 // If there's already an edge here then just skip the encoded pointer and
517 // return the edge's target.
518 {
519 auto EdgeI = BlockEdges.TargetMap.find(PointerFieldOffset);
520 if (EdgeI != BlockEdges.TargetMap.end()) {
521 LLVM_DEBUG({
522 dbgs() << " Existing edge at "
523 << (BlockToFix.getAddress() + PointerFieldOffset) << " to "
524 << FieldName << " at " << EdgeI->second.Target->getAddress();
525 if (EdgeI->second.Target->hasName())
526 dbgs() << " (" << EdgeI->second.Target->getName() << ")";
527 dbgs() << "\n";
528 });
529 if (auto Err = skipEncodedPointer(PointerEncoding, RecordReader))
530 return std::move(Err);
531 return EdgeI->second.Target;
532 }
533
534 if (BlockEdges.Multiple.contains(PointerFieldOffset))
535 return make_error<JITLinkError>("Multiple relocations at offset " +
536 formatv("{0:x16}", PointerFieldOffset));
537 }
538
539 // Switch absptr to corresponding udata encoding.
540 if ((PointerEncoding & 0xf) == DW_EH_PE_absptr)
541 PointerEncoding |= (PointerSize == 8) ? DW_EH_PE_udata8 : DW_EH_PE_udata4;
542
543 // We need to create an edge. Start by reading the field value.
544 uint64_t FieldValue;
545 bool Is64Bit = false;
546 switch (PointerEncoding & 0xf) {
547 case DW_EH_PE_udata4: {
548 uint32_t Val;
549 if (auto Err = RecordReader.readInteger(Val))
550 return std::move(Err);
551 FieldValue = Val;
552 break;
553 }
554 case DW_EH_PE_sdata4: {
555 uint32_t Val;
556 if (auto Err = RecordReader.readInteger(Val))
557 return std::move(Err);
558 FieldValue = Val;
559 break;
560 }
561 case DW_EH_PE_udata8:
562 case DW_EH_PE_sdata8:
563 Is64Bit = true;
564 if (auto Err = RecordReader.readInteger(FieldValue))
565 return std::move(Err);
566 break;
567 default:
568 llvm_unreachable("Unsupported encoding");
569 }
570
571 // Find the edge target and edge kind to use.
572 orc::ExecutorAddr Target;
573 Edge::Kind PtrEdgeKind = Edge::Invalid;
574 if ((PointerEncoding & 0x70) == DW_EH_PE_pcrel) {
575 Target = BlockToFix.getAddress() + PointerFieldOffset;
576 PtrEdgeKind = Is64Bit ? Delta64 : Delta32;
577 } else
578 PtrEdgeKind = Is64Bit ? Pointer64 : Pointer32;
579 Target += FieldValue;
580
581 // Find or create a symbol to point the edge at.
582 auto TargetSym = getOrCreateSymbol(PC, Target);
583 if (!TargetSym)
584 return TargetSym.takeError();
585 BlockToFix.addEdge(PtrEdgeKind, PointerFieldOffset, *TargetSym, 0);
586
587 LLVM_DEBUG({
588 dbgs() << " Adding edge at "
589 << (BlockToFix.getAddress() + PointerFieldOffset) << " to "
590 << FieldName << " at " << TargetSym->getAddress();
591 if (TargetSym->hasName())
592 dbgs() << " (" << TargetSym->getName() << ")";
593 dbgs() << "\n";
594 });
595
596 return &*TargetSym;
597}
598
599Expected<Symbol &> EHFrameEdgeFixer::getOrCreateSymbol(ParseContext &PC,
600 orc::ExecutorAddr Addr) {
601 // See whether we have a canonical symbol for the given address already.
602 auto CanonicalSymI = PC.AddrToSym.find(Addr);
603 if (CanonicalSymI != PC.AddrToSym.end())
604 return *CanonicalSymI->second;
605
606 // Otherwise search for a block covering the address and create a new symbol.
607 auto *B = PC.AddrToBlock.getBlockCovering(Addr);
608 if (!B)
609 return make_error<JITLinkError>("No symbol or block covering address " +
610 formatv("{0:x16}", Addr));
611
612 auto &S =
613 PC.G.addAnonymousSymbol(*B, Addr - B->getAddress(), 0, false, false);
614 PC.AddrToSym[S.getAddress()] = &S;
615 return S;
616}
617
618char EHFrameNullTerminator::NullTerminatorBlockContent[4] = {0, 0, 0, 0};
619
621 : EHFrameSectionName(EHFrameSectionName) {}
622
624 auto *EHFrame = G.findSectionByName(EHFrameSectionName);
625
626 if (!EHFrame)
627 return Error::success();
628
629 LLVM_DEBUG({
630 dbgs() << "EHFrameNullTerminator adding null terminator to "
631 << EHFrameSectionName << "\n";
632 });
633
634 auto &NullTerminatorBlock =
635 G.createContentBlock(*EHFrame, NullTerminatorBlockContent,
636 orc::ExecutorAddr(~uint64_t(4)), 1, 0);
637 G.addAnonymousSymbol(NullTerminatorBlock, 0, 4, false, true);
638 return Error::success();
639}
640
642 if (B.edges_empty())
643 return EHFrameCFIBlockInspector(nullptr);
644 if (B.edges_size() == 1)
645 return EHFrameCFIBlockInspector(&*B.edges().begin());
647 assert(Es.size() >= 2 && Es.size() <= 3 && "Unexpected number of edges");
648 llvm::sort(Es, [](const Edge *LHS, const Edge *RHS) {
649 return LHS->getOffset() < RHS->getOffset();
650 });
651 return EHFrameCFIBlockInspector(*Es[0], *Es[1],
652 Es.size() == 3 ? Es[2] : nullptr);
653 return EHFrameCFIBlockInspector(nullptr);
654}
655
656EHFrameCFIBlockInspector::EHFrameCFIBlockInspector(Edge *PersonalityEdge)
657 : PersonalityEdge(PersonalityEdge) {}
658
659EHFrameCFIBlockInspector::EHFrameCFIBlockInspector(Edge &CIEEdge,
660 Edge &PCBeginEdge,
661 Edge *LSDAEdge)
662 : CIEEdge(&CIEEdge), PCBeginEdge(&PCBeginEdge), LSDAEdge(LSDAEdge) {}
663
665 const char *EHFrameSectionName = nullptr;
666 switch (G.getTargetTriple().getObjectFormat()) {
667 case Triple::MachO:
668 EHFrameSectionName = "__TEXT,__eh_frame";
669 break;
670 case Triple::ELF:
671 EHFrameSectionName = ".eh_frame";
672 break;
673 default:
674 return nullptr;
675 }
676
677 if (auto *S = G.findSectionByName(EHFrameSectionName))
678 if (!S->empty())
679 return S;
680
681 return nullptr;
682}
683
684} // end namespace jitlink
685} // end namespace llvm
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains constants used for implementing Dwarf debug support.
uint64_t Addr
Symbol * Sym
Definition: ELF_riscv.cpp:479
#define G(x, y, z)
Definition: MD5.cpp:56
static bool InBlock(const Value *V, const BasicBlock *BB)
#define LLVM_DEBUG(...)
Definition: Debug.h:119
Value * RHS
Value * LHS
Provides read only access to a subclass of BinaryStream.
Lightweight error class with error context and mandatory checking.
Definition: Error.h:159
static ErrorSuccess success()
Create a success value.
Definition: Error.h:336
Tagged union holding either a T or a Error.
Definition: Error.h:485
size_t size() const
Definition: SmallVector.h:79
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
Represents an address in the executor process.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ DW_EH_PE_textrel
Definition: Dwarf.h:866
@ DW_EH_PE_datarel
Definition: Dwarf.h:867
@ DW_EH_PE_sdata4
Definition: Dwarf.h:862
@ DW_EH_PE_funcrel
Definition: Dwarf.h:868
@ DW_EH_PE_aligned
Definition: Dwarf.h:869
@ DW_EH_PE_udata2
Definition: Dwarf.h:857
@ DW_EH_PE_sdata8
Definition: Dwarf.h:863
@ DW_EH_PE_absptr
Definition: Dwarf.h:854
@ DW_EH_PE_sdata2
Definition: Dwarf.h:861
@ DW_EH_PE_udata4
Definition: Dwarf.h:858
@ DW_EH_PE_udata8
Definition: Dwarf.h:859
@ DW_EH_PE_uleb128
Definition: Dwarf.h:856
@ DW_EH_PE_sleb128
Definition: Dwarf.h:860
@ DW_EH_PE_omit
Definition: Dwarf.h:855
uint64_t ExecutorAddrDiff
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Length
Definition: DWP.cpp:477
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition: STLExtras.h:2155
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1669
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:207
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
Definition: iterator.h:363