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