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