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