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
9 #include "EHFrameSupportImpl.h"
10
11 #include "llvm/BinaryFormat/Dwarf.h"
12 #include "llvm/Config/config.h"
13 #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"
14 #include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
15 #include "llvm/Support/DynamicLibrary.h"
16
17 #define DEBUG_TYPE "jitlink"
18
19 namespace llvm {
20 namespace jitlink {
21
EHFrameEdgeFixer(StringRef EHFrameSectionName,unsigned PointerSize,Edge::Kind Pointer32,Edge::Kind Pointer64,Edge::Kind Delta32,Edge::Kind Delta64,Edge::Kind NegDelta32)22 EHFrameEdgeFixer::EHFrameEdgeFixer(StringRef EHFrameSectionName,
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
operator ()(LinkGraph & G)30 Error EHFrameEdgeFixer::operator()(LinkGraph &G) {
31 auto *EHFrame = G.findSectionByName(EHFrameSectionName);
32
33 if (!EHFrame) {
34 LLVM_DEBUG({
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
46 LLVM_DEBUG({
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(),
67 BlockAddressMap::includeNonNull))
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
processBlock(ParseContext & PC,Block & B)88 Error EHFrameEdgeFixer::processBlock(ParseContext &PC, Block &B) {
89
90 LLVM_DEBUG(dbgs() << " Processing block at " << B.getAddress() << "\n");
91
92 // eh-frame should not contain zero-fill blocks.
93 if (B.isZeroFill())
94 return make_error<JITLinkError>("Unexpected zero-fill block in " +
95 EHFrameSectionName + " section");
96
97 if (B.getSize() == 0) {
98 LLVM_DEBUG(dbgs() << " Block is empty. Skipping.\n");
99 return Error::success();
100 }
101
102 // Find the offsets of any existing edges from this block.
103 BlockEdgeMap BlockEdges;
104 for (auto &E : B.edges())
105 if (E.isRelocation()) {
106 if (BlockEdges.count(E.getOffset()))
107 return make_error<JITLinkError>(
108 "Multiple relocations at offset " +
109 formatv("{0:x16}", E.getOffset()) + " in " + EHFrameSectionName +
110 " block at address " + formatv("{0:x16}", B.getAddress()));
111
112 BlockEdges[E.getOffset()] = EdgeTarget(E);
113 }
114
115 CIEInfosMap CIEInfos;
116 BinaryStreamReader BlockReader(
117 StringRef(B.getContent().data(), B.getContent().size()),
118 PC.G.getEndianness());
119 while (!BlockReader.empty()) {
120 size_t RecordStartOffset = BlockReader.getOffset();
121
122 LLVM_DEBUG({
123 dbgs() << " Processing CFI record at "
124 << (B.getAddress() + RecordStartOffset) << "\n";
125 });
126
127 // Get the record length.
128 size_t RecordRemaining;
129 {
130 uint32_t Length;
131 if (auto Err = BlockReader.readInteger(Length))
132 return Err;
133 // If Length < 0xffffffff then use the regular length field, otherwise
134 // read the extended length field.
135 if (Length != 0xffffffff)
136 RecordRemaining = Length;
137 else {
138 uint64_t ExtendedLength;
139 if (auto Err = BlockReader.readInteger(ExtendedLength))
140 return Err;
141 RecordRemaining = ExtendedLength;
142 }
143 }
144
145 if (BlockReader.bytesRemaining() < RecordRemaining)
146 return make_error<JITLinkError>(
147 "Incomplete CFI record at " +
148 formatv("{0:x16}", B.getAddress() + RecordStartOffset));
149
150 // Read the CIE delta for this record.
151 uint64_t CIEDeltaFieldOffset = BlockReader.getOffset() - RecordStartOffset;
152 uint32_t CIEDelta;
153 if (auto Err = BlockReader.readInteger(CIEDelta))
154 return Err;
155
156 if (CIEDelta == 0) {
157 if (auto Err = processCIE(PC, B, RecordStartOffset,
158 CIEDeltaFieldOffset + RecordRemaining,
159 CIEDeltaFieldOffset, BlockEdges))
160 return Err;
161 } else {
162 if (auto Err = processFDE(PC, B, RecordStartOffset,
163 CIEDeltaFieldOffset + RecordRemaining,
164 CIEDeltaFieldOffset, CIEDelta, BlockEdges))
165 return Err;
166 }
167
168 // Move to the next record.
169 BlockReader.setOffset(RecordStartOffset + CIEDeltaFieldOffset +
170 RecordRemaining);
171 }
172
173 return Error::success();
174 }
175
processCIE(ParseContext & PC,Block & B,size_t RecordOffset,size_t RecordLength,size_t CIEDeltaFieldOffset,const BlockEdgeMap & BlockEdges)176 Error EHFrameEdgeFixer::processCIE(ParseContext &PC, Block &B,
177 size_t RecordOffset, size_t RecordLength,
178 size_t CIEDeltaFieldOffset,
179 const BlockEdgeMap &BlockEdges) {
180
181 LLVM_DEBUG(dbgs() << " Record is CIE\n");
182
183 auto RecordContent = B.getContent().slice(RecordOffset, RecordLength);
184 BinaryStreamReader RecordReader(
185 StringRef(RecordContent.data(), RecordContent.size()),
186 PC.G.getEndianness());
187
188 // Skip past the CIE delta field: we've already processed this far.
189 RecordReader.setOffset(CIEDeltaFieldOffset + 4);
190
191 auto &CIESymbol =
192 PC.G.addAnonymousSymbol(B, RecordOffset, RecordLength, false, false);
193 CIEInformation CIEInfo(CIESymbol);
194
195 uint8_t Version = 0;
196 if (auto Err = RecordReader.readInteger(Version))
197 return Err;
198
199 if (Version != 0x01)
200 return make_error<JITLinkError>("Bad CIE version " + Twine(Version) +
201 " (should be 0x01) in eh-frame");
202
203 auto AugInfo = parseAugmentationString(RecordReader);
204 if (!AugInfo)
205 return AugInfo.takeError();
206
207 // Skip the EH Data field if present.
208 if (AugInfo->EHDataFieldPresent)
209 if (auto Err = RecordReader.skip(PC.G.getPointerSize()))
210 return Err;
211
212 // Read and validate the code alignment factor.
213 {
214 uint64_t CodeAlignmentFactor = 0;
215 if (auto Err = RecordReader.readULEB128(CodeAlignmentFactor))
216 return Err;
217 }
218
219 // Read and validate the data alignment factor.
220 {
221 int64_t DataAlignmentFactor = 0;
222 if (auto Err = RecordReader.readSLEB128(DataAlignmentFactor))
223 return Err;
224 }
225
226 // Skip the return address register field.
227 if (auto Err = RecordReader.skip(1))
228 return Err;
229
230 if (AugInfo->AugmentationDataPresent) {
231
232 CIEInfo.AugmentationDataPresent = true;
233
234 uint64_t AugmentationDataLength = 0;
235 if (auto Err = RecordReader.readULEB128(AugmentationDataLength))
236 return Err;
237
238 uint32_t AugmentationDataStartOffset = RecordReader.getOffset();
239
240 uint8_t *NextField = &AugInfo->Fields[0];
241 while (uint8_t Field = *NextField++) {
242 switch (Field) {
243 case 'L':
244 CIEInfo.LSDAPresent = true;
245 if (auto PE = readPointerEncoding(RecordReader, B, "LSDA"))
246 CIEInfo.LSDAEncoding = *PE;
247 else
248 return PE.takeError();
249 break;
250 case 'P': {
251 auto PersonalityPointerEncoding =
252 readPointerEncoding(RecordReader, B, "personality");
253 if (!PersonalityPointerEncoding)
254 return PersonalityPointerEncoding.takeError();
255 if (auto Err =
256 getOrCreateEncodedPointerEdge(
257 PC, BlockEdges, *PersonalityPointerEncoding, RecordReader,
258 B, RecordOffset + RecordReader.getOffset(), "personality")
259 .takeError())
260 return Err;
261 break;
262 }
263 case 'R':
264 if (auto PE = readPointerEncoding(RecordReader, B, "address")) {
265 CIEInfo.AddressEncoding = *PE;
266 if (CIEInfo.AddressEncoding == dwarf::DW_EH_PE_omit)
267 return make_error<JITLinkError>(
268 "Invalid address encoding DW_EH_PE_omit in CIE at " +
269 formatv("{0:x}", (B.getAddress() + RecordOffset).getValue()));
270 } else
271 return PE.takeError();
272 break;
273 default:
274 llvm_unreachable("Invalid augmentation string field");
275 }
276 }
277
278 if (RecordReader.getOffset() - AugmentationDataStartOffset >
279 AugmentationDataLength)
280 return make_error<JITLinkError>("Read past the end of the augmentation "
281 "data while parsing fields");
282 }
283
284 assert(!PC.CIEInfos.count(CIESymbol.getAddress()) &&
285 "Multiple CIEs recorded at the same address?");
286 PC.CIEInfos[CIESymbol.getAddress()] = std::move(CIEInfo);
287
288 return Error::success();
289 }
290
processFDE(ParseContext & PC,Block & B,size_t RecordOffset,size_t RecordLength,size_t CIEDeltaFieldOffset,uint32_t CIEDelta,const BlockEdgeMap & BlockEdges)291 Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,
292 size_t RecordOffset, size_t RecordLength,
293 size_t CIEDeltaFieldOffset,
294 uint32_t CIEDelta,
295 const BlockEdgeMap &BlockEdges) {
296 LLVM_DEBUG(dbgs() << " Record is FDE\n");
297
298 orc::ExecutorAddr RecordAddress = B.getAddress() + RecordOffset;
299
300 auto RecordContent = B.getContent().slice(RecordOffset, RecordLength);
301 BinaryStreamReader RecordReader(
302 StringRef(RecordContent.data(), RecordContent.size()),
303 PC.G.getEndianness());
304
305 // Skip past the CIE delta field: we've already read this far.
306 RecordReader.setOffset(CIEDeltaFieldOffset + 4);
307
308 auto &FDESymbol =
309 PC.G.addAnonymousSymbol(B, RecordOffset, RecordLength, false, false);
310
311 CIEInformation *CIEInfo = nullptr;
312
313 {
314 // Process the CIE pointer field.
315 auto CIEEdgeItr = BlockEdges.find(RecordOffset + CIEDeltaFieldOffset);
316 orc::ExecutorAddr CIEAddress =
317 RecordAddress + orc::ExecutorAddrDiff(CIEDeltaFieldOffset) -
318 orc::ExecutorAddrDiff(CIEDelta);
319 if (CIEEdgeItr == BlockEdges.end()) {
320
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, RecordOffset + CIEDeltaFieldOffset,
332 *CIEInfo->CIESymbol, 0);
333 } else {
334 LLVM_DEBUG({
335 dbgs() << " Already has edge at "
336 << (RecordAddress + CIEDeltaFieldOffset) << " to CIE at "
337 << CIEAddress << "\n";
338 });
339 auto &EI = CIEEdgeItr->second;
340 if (EI.Addend)
341 return make_error<JITLinkError>(
342 "CIE edge at " +
343 formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset) +
344 " has non-zero addend");
345 if (auto CIEInfoOrErr = PC.findCIEInfo(EI.Target->getAddress()))
346 CIEInfo = *CIEInfoOrErr;
347 else
348 return CIEInfoOrErr.takeError();
349 }
350 }
351
352 // Process the PC-Begin field.
353 LLVM_DEBUG({
354 dbgs() << " Processing PC-begin at "
355 << (RecordAddress + RecordReader.getOffset()) << "\n";
356 });
357 if (auto PCBegin = getOrCreateEncodedPointerEdge(
358 PC, BlockEdges, CIEInfo->AddressEncoding, RecordReader, B,
359 RecordReader.getOffset(), "PC begin")) {
360 assert(*PCBegin && "PC-begin symbol not set");
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 return PCBegin.takeError();
371
372 // Skip over the PC range size field.
373 if (auto Err = skipEncodedPointer(CIEInfo->AddressEncoding, RecordReader))
374 return Err;
375
376 if (CIEInfo->AugmentationDataPresent) {
377 uint64_t AugmentationDataSize;
378 if (auto Err = RecordReader.readULEB128(AugmentationDataSize))
379 return Err;
380
381 if (CIEInfo->LSDAPresent)
382 if (auto Err = getOrCreateEncodedPointerEdge(
383 PC, BlockEdges, CIEInfo->LSDAEncoding, RecordReader, B,
384 RecordReader.getOffset(), "LSDA")
385 .takeError())
386 return Err;
387 } else {
388 LLVM_DEBUG(dbgs() << " Record does not have LSDA field.\n");
389 }
390
391 return Error::success();
392 }
393
394 Expected<EHFrameEdgeFixer::AugmentationInfo>
parseAugmentationString(BinaryStreamReader & RecordReader)395 EHFrameEdgeFixer::parseAugmentationString(BinaryStreamReader &RecordReader) {
396 AugmentationInfo AugInfo;
397 uint8_t NextChar;
398 uint8_t *NextField = &AugInfo.Fields[0];
399
400 if (auto Err = RecordReader.readInteger(NextChar))
401 return std::move(Err);
402
403 while (NextChar != 0) {
404 switch (NextChar) {
405 case 'z':
406 AugInfo.AugmentationDataPresent = true;
407 break;
408 case 'e':
409 if (auto Err = RecordReader.readInteger(NextChar))
410 return std::move(Err);
411 if (NextChar != 'h')
412 return make_error<JITLinkError>("Unrecognized substring e" +
413 Twine(NextChar) +
414 " in augmentation string");
415 AugInfo.EHDataFieldPresent = true;
416 break;
417 case 'L':
418 case 'P':
419 case 'R':
420 *NextField++ = NextChar;
421 break;
422 default:
423 return make_error<JITLinkError>("Unrecognized character " +
424 Twine(NextChar) +
425 " in augmentation string");
426 }
427
428 if (auto Err = RecordReader.readInteger(NextChar))
429 return std::move(Err);
430 }
431
432 return std::move(AugInfo);
433 }
434
readPointerEncoding(BinaryStreamReader & R,Block & InBlock,const char * FieldName)435 Expected<uint8_t> EHFrameEdgeFixer::readPointerEncoding(BinaryStreamReader &R,
436 Block &InBlock,
437 const char *FieldName) {
438 using namespace dwarf;
439
440 uint8_t PointerEncoding;
441 if (auto Err = R.readInteger(PointerEncoding))
442 return std::move(Err);
443
444 bool Supported = true;
445 switch (PointerEncoding & 0xf) {
446 case DW_EH_PE_uleb128:
447 case DW_EH_PE_udata2:
448 case DW_EH_PE_sleb128:
449 case DW_EH_PE_sdata2:
450 Supported = false;
451 break;
452 }
453 if (Supported) {
454 switch (PointerEncoding & 0x70) {
455 case DW_EH_PE_textrel:
456 case DW_EH_PE_datarel:
457 case DW_EH_PE_funcrel:
458 case DW_EH_PE_aligned:
459 Supported = false;
460 break;
461 }
462 }
463
464 if (Supported)
465 return PointerEncoding;
466
467 return make_error<JITLinkError>("Unsupported pointer encoding " +
468 formatv("{0:x2}", PointerEncoding) + " for " +
469 FieldName + "in CFI record at " +
470 formatv("{0:x16}", InBlock.getAddress()));
471 }
472
skipEncodedPointer(uint8_t PointerEncoding,BinaryStreamReader & RecordReader)473 Error EHFrameEdgeFixer::skipEncodedPointer(uint8_t PointerEncoding,
474 BinaryStreamReader &RecordReader) {
475 using namespace dwarf;
476
477 // Switch absptr to corresponding udata encoding.
478 if ((PointerEncoding & 0xf) == DW_EH_PE_absptr)
479 PointerEncoding |= (PointerSize == 8) ? DW_EH_PE_udata8 : DW_EH_PE_udata4;
480
481 switch (PointerEncoding & 0xf) {
482 case DW_EH_PE_udata4:
483 case DW_EH_PE_sdata4:
484 if (auto Err = RecordReader.skip(4))
485 return Err;
486 break;
487 case DW_EH_PE_udata8:
488 case DW_EH_PE_sdata8:
489 if (auto Err = RecordReader.skip(8))
490 return Err;
491 break;
492 default:
493 llvm_unreachable("Unrecognized encoding");
494 }
495 return Error::success();
496 }
497
getOrCreateEncodedPointerEdge(ParseContext & PC,const BlockEdgeMap & BlockEdges,uint8_t PointerEncoding,BinaryStreamReader & RecordReader,Block & BlockToFix,size_t PointerFieldOffset,const char * FieldName)498 Expected<Symbol *> EHFrameEdgeFixer::getOrCreateEncodedPointerEdge(
499 ParseContext &PC, const BlockEdgeMap &BlockEdges, uint8_t PointerEncoding,
500 BinaryStreamReader &RecordReader, Block &BlockToFix,
501 size_t PointerFieldOffset, const char *FieldName) {
502 using namespace dwarf;
503
504 if (PointerEncoding == DW_EH_PE_omit)
505 return nullptr;
506
507 // If there's already an edge here then just skip the encoded pointer and
508 // return the edge's target.
509 {
510 auto EdgeI = BlockEdges.find(PointerFieldOffset);
511 if (EdgeI != BlockEdges.end()) {
512 LLVM_DEBUG({
513 dbgs() << " Existing edge at "
514 << (BlockToFix.getAddress() + PointerFieldOffset) << " to "
515 << FieldName << " at " << EdgeI->second.Target->getAddress();
516 if (EdgeI->second.Target->hasName())
517 dbgs() << " (" << EdgeI->second.Target->getName() << ")";
518 dbgs() << "\n";
519 });
520 if (auto Err = skipEncodedPointer(PointerEncoding, RecordReader))
521 return std::move(Err);
522 return EdgeI->second.Target;
523 }
524 }
525
526 // Switch absptr to corresponding udata encoding.
527 if ((PointerEncoding & 0xf) == DW_EH_PE_absptr)
528 PointerEncoding |= (PointerSize == 8) ? DW_EH_PE_udata8 : DW_EH_PE_udata4;
529
530 // We need to create an edge. Start by reading the field value.
531 uint64_t FieldValue;
532 bool Is64Bit = false;
533 switch (PointerEncoding & 0xf) {
534 case DW_EH_PE_udata4: {
535 uint32_t Val;
536 if (auto Err = RecordReader.readInteger(Val))
537 return std::move(Err);
538 FieldValue = Val;
539 break;
540 }
541 case DW_EH_PE_sdata4: {
542 uint32_t Val;
543 if (auto Err = RecordReader.readInteger(Val))
544 return std::move(Err);
545 FieldValue = Val;
546 break;
547 }
548 case DW_EH_PE_udata8:
549 case DW_EH_PE_sdata8:
550 Is64Bit = true;
551 if (auto Err = RecordReader.readInteger(FieldValue))
552 return std::move(Err);
553 break;
554 default:
555 llvm_unreachable("Unsupported encoding");
556 }
557
558 // Find the edge target and edge kind to use.
559 orc::ExecutorAddr Target;
560 Edge::Kind PtrEdgeKind = Edge::Invalid;
561 if ((PointerEncoding & 0x70) == DW_EH_PE_pcrel) {
562 Target = BlockToFix.getAddress() + PointerFieldOffset;
563 PtrEdgeKind = Is64Bit ? Delta64 : Delta32;
564 } else
565 PtrEdgeKind = Is64Bit ? Pointer64 : Pointer32;
566 Target += FieldValue;
567
568 // Find or create a symbol to point the edge at.
569 auto TargetSym = getOrCreateSymbol(PC, Target);
570 if (!TargetSym)
571 return TargetSym.takeError();
572 BlockToFix.addEdge(PtrEdgeKind, PointerFieldOffset, *TargetSym, 0);
573
574 LLVM_DEBUG({
575 dbgs() << " Adding edge at "
576 << (BlockToFix.getAddress() + PointerFieldOffset) << " to "
577 << FieldName << " at " << TargetSym->getAddress();
578 if (TargetSym->hasName())
579 dbgs() << " (" << TargetSym->getName() << ")";
580 dbgs() << "\n";
581 });
582
583 return &*TargetSym;
584 }
585
getOrCreateSymbol(ParseContext & PC,orc::ExecutorAddr Addr)586 Expected<Symbol &> EHFrameEdgeFixer::getOrCreateSymbol(ParseContext &PC,
587 orc::ExecutorAddr Addr) {
588 // See whether we have a canonical symbol for the given address already.
589 auto CanonicalSymI = PC.AddrToSym.find(Addr);
590 if (CanonicalSymI != PC.AddrToSym.end())
591 return *CanonicalSymI->second;
592
593 // Otherwise search for a block covering the address and create a new symbol.
594 auto *B = PC.AddrToBlock.getBlockCovering(Addr);
595 if (!B)
596 return make_error<JITLinkError>("No symbol or block covering address " +
597 formatv("{0:x16}", Addr));
598
599 auto &S =
600 PC.G.addAnonymousSymbol(*B, Addr - B->getAddress(), 0, false, false);
601 PC.AddrToSym[S.getAddress()] = &S;
602 return S;
603 }
604
605 char EHFrameNullTerminator::NullTerminatorBlockContent[4] = {0, 0, 0, 0};
606
EHFrameNullTerminator(StringRef EHFrameSectionName)607 EHFrameNullTerminator::EHFrameNullTerminator(StringRef EHFrameSectionName)
608 : EHFrameSectionName(EHFrameSectionName) {}
609
operator ()(LinkGraph & G)610 Error EHFrameNullTerminator::operator()(LinkGraph &G) {
611 auto *EHFrame = G.findSectionByName(EHFrameSectionName);
612
613 if (!EHFrame)
614 return Error::success();
615
616 LLVM_DEBUG({
617 dbgs() << "EHFrameNullTerminator adding null terminator to "
618 << EHFrameSectionName << "\n";
619 });
620
621 auto &NullTerminatorBlock =
622 G.createContentBlock(*EHFrame, NullTerminatorBlockContent,
623 orc::ExecutorAddr(~uint64_t(4)), 1, 0);
624 G.addAnonymousSymbol(NullTerminatorBlock, 0, 4, false, true);
625 return Error::success();
626 }
627
628 EHFrameRegistrar::~EHFrameRegistrar() = default;
629
registerEHFrames(orc::ExecutorAddrRange EHFrameSection)630 Error InProcessEHFrameRegistrar::registerEHFrames(
631 orc::ExecutorAddrRange EHFrameSection) {
632 return orc::registerEHFrameSection(EHFrameSection.Start.toPtr<void *>(),
633 EHFrameSection.size());
634 }
635
deregisterEHFrames(orc::ExecutorAddrRange EHFrameSection)636 Error InProcessEHFrameRegistrar::deregisterEHFrames(
637 orc::ExecutorAddrRange EHFrameSection) {
638 return orc::deregisterEHFrameSection(EHFrameSection.Start.toPtr<void *>(),
639 EHFrameSection.size());
640 }
641
642 LinkGraphPassFunction
createEHFrameRecorderPass(const Triple & TT,StoreFrameRangeFunction StoreRangeAddress)643 createEHFrameRecorderPass(const Triple &TT,
644 StoreFrameRangeFunction StoreRangeAddress) {
645 const char *EHFrameSectionName = nullptr;
646 if (TT.getObjectFormat() == Triple::MachO)
647 EHFrameSectionName = "__TEXT,__eh_frame";
648 else
649 EHFrameSectionName = ".eh_frame";
650
651 auto RecordEHFrame =
652 [EHFrameSectionName,
653 StoreFrameRange = std::move(StoreRangeAddress)](LinkGraph &G) -> Error {
654 // Search for a non-empty eh-frame and record the address of the first
655 // symbol in it.
656 orc::ExecutorAddr Addr;
657 size_t Size = 0;
658 if (auto *S = G.findSectionByName(EHFrameSectionName)) {
659 auto R = SectionRange(*S);
660 Addr = R.getStart();
661 Size = R.getSize();
662 }
663 if (!Addr && Size != 0)
664 return make_error<JITLinkError>(
665 StringRef(EHFrameSectionName) +
666 " section can not have zero address with non-zero size");
667 StoreFrameRange(Addr, Size);
668 return Error::success();
669 };
670
671 return RecordEHFrame;
672 }
673
674 } // end namespace jitlink
675 } // end namespace llvm
676