LLVM 18.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 BlockEdgeMap BlockEdges;
130 for (auto &E : B.edges())
131 if (E.isRelocation()) {
132 if (BlockEdges.count(E.getOffset()))
133 return make_error<JITLinkError>(
134 "Multiple relocations at offset " +
135 formatv("{0:x16}", E.getOffset()) + " in " + EHFrameSectionName +
136 " block at address " + formatv("{0:x16}", B.getAddress()));
137
138 BlockEdges[E.getOffset()] = EdgeTarget(E);
139 }
140
141 CIEInfosMap CIEInfos;
142 BinaryStreamReader BlockReader(
143 StringRef(B.getContent().data(), B.getContent().size()),
144 PC.G.getEndianness());
145 while (!BlockReader.empty()) {
146 size_t RecordStartOffset = BlockReader.getOffset();
147
148 LLVM_DEBUG({
149 dbgs() << " Processing CFI record at "
150 << (B.getAddress() + RecordStartOffset) << "\n";
151 });
152
153 // Get the record length.
154 Expected<size_t> RecordRemaining = readCFIRecordLength(B, BlockReader);
155 if (!RecordRemaining)
156 return RecordRemaining.takeError();
157
158 if (BlockReader.bytesRemaining() < *RecordRemaining)
159 return make_error<JITLinkError>(
160 "Incomplete CFI record at " +
161 formatv("{0:x16}", B.getAddress() + RecordStartOffset));
162
163 // Read the CIE delta for this record.
164 uint64_t CIEDeltaFieldOffset = BlockReader.getOffset() - RecordStartOffset;
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, RecordStartOffset,
171 CIEDeltaFieldOffset + *RecordRemaining,
172 CIEDeltaFieldOffset, BlockEdges))
173 return Err;
174 } else {
175 if (auto Err = processFDE(PC, B, RecordStartOffset,
176 CIEDeltaFieldOffset + *RecordRemaining,
177 CIEDeltaFieldOffset, CIEDelta, BlockEdges))
178 return Err;
179 }
180
181 // Move to the next record.
182 BlockReader.setOffset(RecordStartOffset + CIEDeltaFieldOffset +
183 *RecordRemaining);
184 }
185
186 return Error::success();
187}
188
189Error EHFrameEdgeFixer::processCIE(ParseContext &PC, Block &B,
190 size_t RecordOffset, size_t RecordLength,
191 size_t CIEDeltaFieldOffset,
192 const BlockEdgeMap &BlockEdges) {
193
194 LLVM_DEBUG(dbgs() << " Record is CIE\n");
195
196 auto RecordContent = B.getContent().slice(RecordOffset, RecordLength);
197 BinaryStreamReader RecordReader(
198 StringRef(RecordContent.data(), RecordContent.size()),
199 PC.G.getEndianness());
200
201 // Skip past the CIE delta field: we've already processed this far.
202 RecordReader.setOffset(CIEDeltaFieldOffset + 4);
203
204 auto &CIESymbol =
205 PC.G.addAnonymousSymbol(B, RecordOffset, RecordLength, false, false);
206 CIEInformation CIEInfo(CIESymbol);
207
208 uint8_t Version = 0;
209 if (auto Err = RecordReader.readInteger(Version))
210 return Err;
211
212 if (Version != 0x01)
213 return make_error<JITLinkError>("Bad CIE version " + Twine(Version) +
214 " (should be 0x01) in eh-frame");
215
216 auto AugInfo = parseAugmentationString(RecordReader);
217 if (!AugInfo)
218 return AugInfo.takeError();
219
220 // Skip the EH Data field if present.
221 if (AugInfo->EHDataFieldPresent)
222 if (auto Err = RecordReader.skip(PC.G.getPointerSize()))
223 return Err;
224
225 // Read and validate the code alignment factor.
226 {
227 uint64_t CodeAlignmentFactor = 0;
228 if (auto Err = RecordReader.readULEB128(CodeAlignmentFactor))
229 return Err;
230 }
231
232 // Read and validate the data alignment factor.
233 {
234 int64_t DataAlignmentFactor = 0;
235 if (auto Err = RecordReader.readSLEB128(DataAlignmentFactor))
236 return Err;
237 }
238
239 // Skip the return address register field.
240 if (auto Err = RecordReader.skip(1))
241 return Err;
242
243 if (AugInfo->AugmentationDataPresent) {
244
245 CIEInfo.AugmentationDataPresent = true;
246
247 uint64_t AugmentationDataLength = 0;
248 if (auto Err = RecordReader.readULEB128(AugmentationDataLength))
249 return Err;
250
251 uint32_t AugmentationDataStartOffset = RecordReader.getOffset();
252
253 uint8_t *NextField = &AugInfo->Fields[0];
254 while (uint8_t Field = *NextField++) {
255 switch (Field) {
256 case 'L':
257 CIEInfo.LSDAPresent = true;
258 if (auto PE = readPointerEncoding(RecordReader, B, "LSDA"))
259 CIEInfo.LSDAEncoding = *PE;
260 else
261 return PE.takeError();
262 break;
263 case 'P': {
264 auto PersonalityPointerEncoding =
265 readPointerEncoding(RecordReader, B, "personality");
266 if (!PersonalityPointerEncoding)
267 return PersonalityPointerEncoding.takeError();
268 if (auto Err =
269 getOrCreateEncodedPointerEdge(
270 PC, BlockEdges, *PersonalityPointerEncoding, RecordReader,
271 B, RecordOffset + RecordReader.getOffset(), "personality")
272 .takeError())
273 return Err;
274 break;
275 }
276 case 'R':
277 if (auto PE = readPointerEncoding(RecordReader, B, "address")) {
278 CIEInfo.AddressEncoding = *PE;
279 if (CIEInfo.AddressEncoding == dwarf::DW_EH_PE_omit)
280 return make_error<JITLinkError>(
281 "Invalid address encoding DW_EH_PE_omit in CIE at " +
282 formatv("{0:x}", (B.getAddress() + RecordOffset).getValue()));
283 } else
284 return PE.takeError();
285 break;
286 default:
287 llvm_unreachable("Invalid augmentation string field");
288 }
289 }
290
291 if (RecordReader.getOffset() - AugmentationDataStartOffset >
292 AugmentationDataLength)
293 return make_error<JITLinkError>("Read past the end of the augmentation "
294 "data while parsing fields");
295 }
296
297 assert(!PC.CIEInfos.count(CIESymbol.getAddress()) &&
298 "Multiple CIEs recorded at the same address?");
299 PC.CIEInfos[CIESymbol.getAddress()] = std::move(CIEInfo);
300
301 return Error::success();
302}
303
304Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,
305 size_t RecordOffset, size_t RecordLength,
306 size_t CIEDeltaFieldOffset,
307 uint32_t CIEDelta,
308 const BlockEdgeMap &BlockEdges) {
309 LLVM_DEBUG(dbgs() << " Record is FDE\n");
310
311 orc::ExecutorAddr RecordAddress = B.getAddress() + RecordOffset;
312
313 auto RecordContent = B.getContent().slice(RecordOffset, RecordLength);
314 BinaryStreamReader RecordReader(
315 StringRef(RecordContent.data(), RecordContent.size()),
316 PC.G.getEndianness());
317
318 // Skip past the CIE delta field: we've already read this far.
319 RecordReader.setOffset(CIEDeltaFieldOffset + 4);
320
321 auto &FDESymbol =
322 PC.G.addAnonymousSymbol(B, RecordOffset, RecordLength, false, false);
323
324 CIEInformation *CIEInfo = nullptr;
325
326 {
327 // Process the CIE pointer field.
328 auto CIEEdgeItr = BlockEdges.find(RecordOffset + CIEDeltaFieldOffset);
329 orc::ExecutorAddr CIEAddress =
330 RecordAddress + orc::ExecutorAddrDiff(CIEDeltaFieldOffset) -
331 orc::ExecutorAddrDiff(CIEDelta);
332 if (CIEEdgeItr == BlockEdges.end()) {
333
334 LLVM_DEBUG({
335 dbgs() << " Adding edge at "
336 << (RecordAddress + CIEDeltaFieldOffset)
337 << " to CIE at: " << CIEAddress << "\n";
338 });
339 if (auto CIEInfoOrErr = PC.findCIEInfo(CIEAddress))
340 CIEInfo = *CIEInfoOrErr;
341 else
342 return CIEInfoOrErr.takeError();
343 assert(CIEInfo->CIESymbol && "CIEInfo has no CIE symbol set");
344 B.addEdge(NegDelta32, RecordOffset + CIEDeltaFieldOffset,
345 *CIEInfo->CIESymbol, 0);
346 } else {
347 LLVM_DEBUG({
348 dbgs() << " Already has edge at "
349 << (RecordAddress + CIEDeltaFieldOffset) << " to CIE at "
350 << CIEAddress << "\n";
351 });
352 auto &EI = CIEEdgeItr->second;
353 if (EI.Addend)
354 return make_error<JITLinkError>(
355 "CIE edge at " +
356 formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset) +
357 " has non-zero addend");
358 if (auto CIEInfoOrErr = PC.findCIEInfo(EI.Target->getAddress()))
359 CIEInfo = *CIEInfoOrErr;
360 else
361 return CIEInfoOrErr.takeError();
362 }
363 }
364
365 // Process the PC-Begin field.
366 LLVM_DEBUG({
367 dbgs() << " Processing PC-begin at "
368 << (RecordAddress + RecordReader.getOffset()) << "\n";
369 });
370 if (auto PCBegin = getOrCreateEncodedPointerEdge(
371 PC, BlockEdges, CIEInfo->AddressEncoding, RecordReader, B,
372 RecordReader.getOffset(), "PC begin")) {
373 assert(*PCBegin && "PC-begin symbol not set");
374 if ((*PCBegin)->isDefined()) {
375 // Add a keep-alive edge from the FDE target to the FDE to ensure that the
376 // FDE is kept alive if its target is.
377 LLVM_DEBUG({
378 dbgs() << " Adding keep-alive edge from target at "
379 << (*PCBegin)->getBlock().getAddress() << " to FDE at "
380 << RecordAddress << "\n";
381 });
382 (*PCBegin)->getBlock().addEdge(Edge::KeepAlive, 0, FDESymbol, 0);
383 } else {
384 LLVM_DEBUG({
385 dbgs() << " WARNING: Not adding keep-alive edge to FDE at "
386 << RecordAddress << ", which points to "
387 << ((*PCBegin)->isExternal() ? "external" : "absolute")
388 << " symbol \"" << (*PCBegin)->getName()
389 << "\" -- FDE must be kept alive manually or it will be "
390 << "dead stripped.\n";
391 });
392 }
393 } else
394 return PCBegin.takeError();
395
396 // Skip over the PC range size field.
397 if (auto Err = skipEncodedPointer(CIEInfo->AddressEncoding, RecordReader))
398 return Err;
399
400 if (CIEInfo->AugmentationDataPresent) {
401 uint64_t AugmentationDataSize;
402 if (auto Err = RecordReader.readULEB128(AugmentationDataSize))
403 return Err;
404
405 if (CIEInfo->LSDAPresent)
406 if (auto Err = getOrCreateEncodedPointerEdge(
407 PC, BlockEdges, CIEInfo->LSDAEncoding, RecordReader, B,
408 RecordReader.getOffset(), "LSDA")
409 .takeError())
410 return Err;
411 } else {
412 LLVM_DEBUG(dbgs() << " Record does not have LSDA field.\n");
413 }
414
415 return Error::success();
416}
417
418Expected<EHFrameEdgeFixer::AugmentationInfo>
419EHFrameEdgeFixer::parseAugmentationString(BinaryStreamReader &RecordReader) {
420 AugmentationInfo AugInfo;
421 uint8_t NextChar;
422 uint8_t *NextField = &AugInfo.Fields[0];
423
424 if (auto Err = RecordReader.readInteger(NextChar))
425 return std::move(Err);
426
427 while (NextChar != 0) {
428 switch (NextChar) {
429 case 'z':
430 AugInfo.AugmentationDataPresent = true;
431 break;
432 case 'e':
433 if (auto Err = RecordReader.readInteger(NextChar))
434 return std::move(Err);
435 if (NextChar != 'h')
436 return make_error<JITLinkError>("Unrecognized substring e" +
437 Twine(NextChar) +
438 " in augmentation string");
439 AugInfo.EHDataFieldPresent = true;
440 break;
441 case 'L':
442 case 'P':
443 case 'R':
444 *NextField++ = NextChar;
445 break;
446 default:
447 return make_error<JITLinkError>("Unrecognized character " +
448 Twine(NextChar) +
449 " in augmentation string");
450 }
451
452 if (auto Err = RecordReader.readInteger(NextChar))
453 return std::move(Err);
454 }
455
456 return std::move(AugInfo);
457}
458
459Expected<uint8_t> EHFrameEdgeFixer::readPointerEncoding(BinaryStreamReader &R,
460 Block &InBlock,
461 const char *FieldName) {
462 using namespace dwarf;
463
464 uint8_t PointerEncoding;
465 if (auto Err = R.readInteger(PointerEncoding))
466 return std::move(Err);
467
468 bool Supported = true;
469 switch (PointerEncoding & 0xf) {
470 case DW_EH_PE_uleb128:
471 case DW_EH_PE_udata2:
472 case DW_EH_PE_sleb128:
473 case DW_EH_PE_sdata2:
474 Supported = false;
475 break;
476 }
477 if (Supported) {
478 switch (PointerEncoding & 0x70) {
479 case DW_EH_PE_textrel:
480 case DW_EH_PE_datarel:
481 case DW_EH_PE_funcrel:
482 case DW_EH_PE_aligned:
483 Supported = false;
484 break;
485 }
486 }
487
488 if (Supported)
489 return PointerEncoding;
490
491 return make_error<JITLinkError>("Unsupported pointer encoding " +
492 formatv("{0:x2}", PointerEncoding) + " for " +
493 FieldName + "in CFI record at " +
494 formatv("{0:x16}", InBlock.getAddress()));
495}
496
497Error EHFrameEdgeFixer::skipEncodedPointer(uint8_t PointerEncoding,
498 BinaryStreamReader &RecordReader) {
499 using namespace dwarf;
500
501 // Switch absptr to corresponding udata encoding.
502 if ((PointerEncoding & 0xf) == DW_EH_PE_absptr)
503 PointerEncoding |= (PointerSize == 8) ? DW_EH_PE_udata8 : DW_EH_PE_udata4;
504
505 switch (PointerEncoding & 0xf) {
506 case DW_EH_PE_udata4:
507 case DW_EH_PE_sdata4:
508 if (auto Err = RecordReader.skip(4))
509 return Err;
510 break;
511 case DW_EH_PE_udata8:
512 case DW_EH_PE_sdata8:
513 if (auto Err = RecordReader.skip(8))
514 return Err;
515 break;
516 default:
517 llvm_unreachable("Unrecognized encoding");
518 }
519 return Error::success();
520}
521
522Expected<Symbol *> EHFrameEdgeFixer::getOrCreateEncodedPointerEdge(
523 ParseContext &PC, const BlockEdgeMap &BlockEdges, uint8_t PointerEncoding,
524 BinaryStreamReader &RecordReader, Block &BlockToFix,
525 size_t PointerFieldOffset, const char *FieldName) {
526 using namespace dwarf;
527
528 if (PointerEncoding == DW_EH_PE_omit)
529 return nullptr;
530
531 // If there's already an edge here then just skip the encoded pointer and
532 // return the edge's target.
533 {
534 auto EdgeI = BlockEdges.find(PointerFieldOffset);
535 if (EdgeI != BlockEdges.end()) {
536 LLVM_DEBUG({
537 dbgs() << " Existing edge at "
538 << (BlockToFix.getAddress() + PointerFieldOffset) << " to "
539 << FieldName << " at " << EdgeI->second.Target->getAddress();
540 if (EdgeI->second.Target->hasName())
541 dbgs() << " (" << EdgeI->second.Target->getName() << ")";
542 dbgs() << "\n";
543 });
544 if (auto Err = skipEncodedPointer(PointerEncoding, RecordReader))
545 return std::move(Err);
546 return EdgeI->second.Target;
547 }
548 }
549
550 // Switch absptr to corresponding udata encoding.
551 if ((PointerEncoding & 0xf) == DW_EH_PE_absptr)
552 PointerEncoding |= (PointerSize == 8) ? DW_EH_PE_udata8 : DW_EH_PE_udata4;
553
554 // We need to create an edge. Start by reading the field value.
555 uint64_t FieldValue;
556 bool Is64Bit = false;
557 switch (PointerEncoding & 0xf) {
558 case DW_EH_PE_udata4: {
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_sdata4: {
566 uint32_t Val;
567 if (auto Err = RecordReader.readInteger(Val))
568 return std::move(Err);
569 FieldValue = Val;
570 break;
571 }
572 case DW_EH_PE_udata8:
573 case DW_EH_PE_sdata8:
574 Is64Bit = true;
575 if (auto Err = RecordReader.readInteger(FieldValue))
576 return std::move(Err);
577 break;
578 default:
579 llvm_unreachable("Unsupported encoding");
580 }
581
582 // Find the edge target and edge kind to use.
583 orc::ExecutorAddr Target;
584 Edge::Kind PtrEdgeKind = Edge::Invalid;
585 if ((PointerEncoding & 0x70) == DW_EH_PE_pcrel) {
586 Target = BlockToFix.getAddress() + PointerFieldOffset;
587 PtrEdgeKind = Is64Bit ? Delta64 : Delta32;
588 } else
589 PtrEdgeKind = Is64Bit ? Pointer64 : Pointer32;
590 Target += FieldValue;
591
592 // Find or create a symbol to point the edge at.
593 auto TargetSym = getOrCreateSymbol(PC, Target);
594 if (!TargetSym)
595 return TargetSym.takeError();
596 BlockToFix.addEdge(PtrEdgeKind, PointerFieldOffset, *TargetSym, 0);
597
598 LLVM_DEBUG({
599 dbgs() << " Adding edge at "
600 << (BlockToFix.getAddress() + PointerFieldOffset) << " to "
601 << FieldName << " at " << TargetSym->getAddress();
602 if (TargetSym->hasName())
603 dbgs() << " (" << TargetSym->getName() << ")";
604 dbgs() << "\n";
605 });
606
607 return &*TargetSym;
608}
609
610Expected<Symbol &> EHFrameEdgeFixer::getOrCreateSymbol(ParseContext &PC,
611 orc::ExecutorAddr Addr) {
612 // See whether we have a canonical symbol for the given address already.
613 auto CanonicalSymI = PC.AddrToSym.find(Addr);
614 if (CanonicalSymI != PC.AddrToSym.end())
615 return *CanonicalSymI->second;
616
617 // Otherwise search for a block covering the address and create a new symbol.
618 auto *B = PC.AddrToBlock.getBlockCovering(Addr);
619 if (!B)
620 return make_error<JITLinkError>("No symbol or block covering address " +
621 formatv("{0:x16}", Addr));
622
623 auto &S =
624 PC.G.addAnonymousSymbol(*B, Addr - B->getAddress(), 0, false, false);
625 PC.AddrToSym[S.getAddress()] = &S;
626 return S;
627}
628
629char EHFrameNullTerminator::NullTerminatorBlockContent[4] = {0, 0, 0, 0};
630
632 : EHFrameSectionName(EHFrameSectionName) {}
633
635 auto *EHFrame = G.findSectionByName(EHFrameSectionName);
636
637 if (!EHFrame)
638 return Error::success();
639
640 LLVM_DEBUG({
641 dbgs() << "EHFrameNullTerminator adding null terminator to "
642 << EHFrameSectionName << "\n";
643 });
644
645 auto &NullTerminatorBlock =
646 G.createContentBlock(*EHFrame, NullTerminatorBlockContent,
647 orc::ExecutorAddr(~uint64_t(4)), 1, 0);
648 G.addAnonymousSymbol(NullTerminatorBlock, 0, 4, false, true);
649 return Error::success();
650}
651
653
655 orc::ExecutorAddrRange EHFrameSection) {
656 return orc::registerEHFrameSection(EHFrameSection.Start.toPtr<void *>(),
657 EHFrameSection.size());
658}
659
661 orc::ExecutorAddrRange EHFrameSection) {
662 return orc::deregisterEHFrameSection(EHFrameSection.Start.toPtr<void *>(),
663 EHFrameSection.size());
664}
665
667 if (B.edges_empty())
668 return EHFrameCFIBlockInspector(nullptr);
669 if (B.edges_size() == 1)
670 return EHFrameCFIBlockInspector(&*B.edges().begin());
672 for (auto &E : B.edges())
673 Es.push_back(&E);
674 assert(Es.size() >= 2 && Es.size() <= 3 && "Unexpected number of edges");
675 llvm::sort(Es, [](const Edge *LHS, const Edge *RHS) {
676 return LHS->getOffset() < RHS->getOffset();
677 });
678 return EHFrameCFIBlockInspector(*Es[0], *Es[1],
679 Es.size() == 3 ? Es[2] : nullptr);
680 return EHFrameCFIBlockInspector(nullptr);
681}
682
683EHFrameCFIBlockInspector::EHFrameCFIBlockInspector(Edge *PersonalityEdge)
684 : PersonalityEdge(PersonalityEdge) {}
685
686EHFrameCFIBlockInspector::EHFrameCFIBlockInspector(Edge &CIEEdge,
687 Edge &PCBeginEdge,
688 Edge *LSDAEdge)
689 : CIEEdge(&CIEEdge), PCBeginEdge(&PCBeginEdge), LSDAEdge(LSDAEdge) {}
690
693 StoreFrameRangeFunction StoreRangeAddress) {
694 const char *EHFrameSectionName = nullptr;
695 if (TT.getObjectFormat() == Triple::MachO)
696 EHFrameSectionName = "__TEXT,__eh_frame";
697 else
698 EHFrameSectionName = ".eh_frame";
699
700 auto RecordEHFrame =
701 [EHFrameSectionName,
702 StoreFrameRange = std::move(StoreRangeAddress)](LinkGraph &G) -> Error {
703 // Search for a non-empty eh-frame and record the address of the first
704 // symbol in it.
706 size_t Size = 0;
707 if (auto *S = G.findSectionByName(EHFrameSectionName)) {
708 auto R = SectionRange(*S);
709 Addr = R.getStart();
710 Size = R.getSize();
711 }
712 if (!Addr && Size != 0)
713 return make_error<JITLinkError>(
714 StringRef(EHFrameSectionName) +
715 " section can not have zero address with non-zero size");
716 StoreFrameRange(Addr, Size);
717 return Error::success();
718 };
719
720 return RecordEHFrame;
721}
722
723} // end namespace jitlink
724} // 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:468
#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:334
Tagged union holding either a T or a Error.
Definition: Error.h:474
size_t size() const
Definition: SmallVector.h:91
void push_back(const T &Elt)
Definition: SmallVector.h:416
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
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.
const uint64_t Version
Definition: InstrProf.h:1021
@ DW_EH_PE_textrel
Definition: Dwarf.h:535
@ DW_EH_PE_datarel
Definition: Dwarf.h:536
@ DW_EH_PE_pcrel
Definition: Dwarf.h:534
@ DW_EH_PE_sdata4
Definition: Dwarf.h:531
@ DW_EH_PE_funcrel
Definition: Dwarf.h:537
@ DW_EH_PE_aligned
Definition: Dwarf.h:538
@ DW_EH_PE_udata2
Definition: Dwarf.h:526
@ DW_EH_PE_sdata8
Definition: Dwarf.h:532
@ DW_EH_PE_absptr
Definition: Dwarf.h:523
@ DW_EH_PE_sdata2
Definition: Dwarf.h:530
@ DW_EH_PE_udata4
Definition: Dwarf.h:527
@ DW_EH_PE_udata8
Definition: Dwarf.h:528
@ DW_EH_PE_uleb128
Definition: Dwarf.h:525
@ DW_EH_PE_sleb128
Definition: Dwarf.h:529
@ DW_EH_PE_omit
Definition: Dwarf.h:524
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:440
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1652
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