1 //===-------- JITLink_EHFrameSupport.cpp - JITLink eh-frame utils ---------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "EHFrameSupportImpl.h"
11
12 #include "llvm/BinaryFormat/Dwarf.h"
13 #include "llvm/Support/DynamicLibrary.h"
14
15 #define DEBUG_TYPE "jitlink"
16
17 namespace llvm {
18 namespace jitlink {
19
EHFrameSplitter(StringRef EHFrameSectionName)20 EHFrameSplitter::EHFrameSplitter(StringRef EHFrameSectionName)
21 : EHFrameSectionName(EHFrameSectionName) {}
22
operator ()(LinkGraph & G)23 Error EHFrameSplitter::operator()(LinkGraph &G) {
24 auto *EHFrame = G.findSectionByName(EHFrameSectionName);
25
26 if (!EHFrame) {
27 LLVM_DEBUG({
28 dbgs() << "EHFrameSplitter: No " << EHFrameSectionName
29 << " section. Nothing to do\n";
30 });
31 return Error::success();
32 }
33
34 LLVM_DEBUG({
35 dbgs() << "EHFrameSplitter: Processing " << EHFrameSectionName << "...\n";
36 });
37
38 DenseMap<Block *, LinkGraph::SplitBlockCache> Caches;
39
40 {
41 // Pre-build the split caches.
42 for (auto *B : EHFrame->blocks())
43 Caches[B] = LinkGraph::SplitBlockCache::value_type();
44 for (auto *Sym : EHFrame->symbols())
45 Caches[&Sym->getBlock()]->push_back(Sym);
46 for (auto *B : EHFrame->blocks())
47 llvm::sort(*Caches[B], [](const Symbol *LHS, const Symbol *RHS) {
48 return LHS->getOffset() > RHS->getOffset();
49 });
50 }
51
52 // Iterate over blocks (we do this by iterating over Caches entries rather
53 // than EHFrame->blocks() as we will be inserting new blocks along the way,
54 // which would invalidate iterators in the latter sequence.
55 for (auto &KV : Caches) {
56 auto &B = *KV.first;
57 auto &BCache = KV.second;
58 if (auto Err = processBlock(G, B, BCache))
59 return Err;
60 }
61
62 return Error::success();
63 }
64
processBlock(LinkGraph & G,Block & B,LinkGraph::SplitBlockCache & Cache)65 Error EHFrameSplitter::processBlock(LinkGraph &G, Block &B,
66 LinkGraph::SplitBlockCache &Cache) {
67 LLVM_DEBUG({
68 dbgs() << " Processing block at " << formatv("{0:x16}", B.getAddress())
69 << "\n";
70 });
71
72 // eh-frame should not contain zero-fill blocks.
73 if (B.isZeroFill())
74 return make_error<JITLinkError>("Unexpected zero-fill block in " +
75 EHFrameSectionName + " section");
76
77 if (B.getSize() == 0) {
78 LLVM_DEBUG(dbgs() << " Block is empty. Skipping.\n");
79 return Error::success();
80 }
81
82 BinaryStreamReader BlockReader(B.getContent(), G.getEndianness());
83
84 while (true) {
85 uint64_t RecordStartOffset = BlockReader.getOffset();
86
87 LLVM_DEBUG({
88 dbgs() << " Processing CFI record at "
89 << formatv("{0:x16}", B.getAddress()) << "\n";
90 });
91
92 uint32_t Length;
93 if (auto Err = BlockReader.readInteger(Length))
94 return Err;
95 if (Length != 0xffffffff) {
96 if (auto Err = BlockReader.skip(Length))
97 return Err;
98 } else {
99 uint64_t ExtendedLength;
100 if (auto Err = BlockReader.readInteger(ExtendedLength))
101 return Err;
102 if (auto Err = BlockReader.skip(ExtendedLength))
103 return Err;
104 }
105
106 // If this was the last block then there's nothing to split
107 if (BlockReader.empty()) {
108 LLVM_DEBUG(dbgs() << " Extracted " << B << "\n");
109 return Error::success();
110 }
111
112 uint64_t BlockSize = BlockReader.getOffset() - RecordStartOffset;
113 auto &NewBlock = G.splitBlock(B, BlockSize);
114 (void)NewBlock;
115 LLVM_DEBUG(dbgs() << " Extracted " << NewBlock << "\n");
116 }
117 }
118
EHFrameEdgeFixer(StringRef EHFrameSectionName,Edge::Kind FDEToCIE,Edge::Kind FDEToPCBegin,Edge::Kind FDEToLSDA)119 EHFrameEdgeFixer::EHFrameEdgeFixer(StringRef EHFrameSectionName,
120 Edge::Kind FDEToCIE, Edge::Kind FDEToPCBegin,
121 Edge::Kind FDEToLSDA)
122 : EHFrameSectionName(EHFrameSectionName), FDEToCIE(FDEToCIE),
123 FDEToPCBegin(FDEToPCBegin), FDEToLSDA(FDEToLSDA) {}
124
operator ()(LinkGraph & G)125 Error EHFrameEdgeFixer::operator()(LinkGraph &G) {
126 auto *EHFrame = G.findSectionByName(EHFrameSectionName);
127
128 if (!EHFrame) {
129 LLVM_DEBUG({
130 dbgs() << "EHFrameEdgeFixer: No " << EHFrameSectionName
131 << " section. Nothing to do\n";
132 });
133 return Error::success();
134 }
135
136 LLVM_DEBUG({
137 dbgs() << "EHFrameEdgeFixer: Processing " << EHFrameSectionName << "...\n";
138 });
139
140 ParseContext PC(G);
141
142 // Build a map of all blocks and symbols in the text sections. We will use
143 // these for finding / building edge targets when processing FDEs.
144 for (auto &Sec : G.sections()) {
145 PC.AddrToSyms.addSymbols(Sec.symbols());
146 if (auto Err = PC.AddrToBlock.addBlocks(Sec.blocks(),
147 BlockAddressMap::includeNonNull))
148 return Err;
149 }
150
151 // Sort eh-frame blocks into address order to ensure we visit CIEs before
152 // their child FDEs.
153 std::vector<Block *> EHFrameBlocks;
154 for (auto *B : EHFrame->blocks())
155 EHFrameBlocks.push_back(B);
156 llvm::sort(EHFrameBlocks, [](const Block *LHS, const Block *RHS) {
157 return LHS->getAddress() < RHS->getAddress();
158 });
159
160 // Loop over the blocks in address order.
161 for (auto *B : EHFrameBlocks)
162 if (auto Err = processBlock(PC, *B))
163 return Err;
164
165 return Error::success();
166 }
167
processBlock(ParseContext & PC,Block & B)168 Error EHFrameEdgeFixer::processBlock(ParseContext &PC, Block &B) {
169
170 LLVM_DEBUG({
171 dbgs() << " Processing block at " << formatv("{0:x16}", B.getAddress())
172 << "\n";
173 });
174
175 // eh-frame should not contain zero-fill blocks.
176 if (B.isZeroFill())
177 return make_error<JITLinkError>("Unexpected zero-fill block in " +
178 EHFrameSectionName + " section");
179
180 if (B.getSize() == 0) {
181 LLVM_DEBUG(dbgs() << " Block is empty. Skipping.\n");
182 return Error::success();
183 }
184
185 // Find the offsets of any existing edges from this block.
186 BlockEdgeMap BlockEdges;
187 for (auto &E : B.edges())
188 if (E.isRelocation()) {
189 if (BlockEdges.count(E.getOffset()))
190 return make_error<JITLinkError>(
191 "Multiple relocations at offset " +
192 formatv("{0:x16}", E.getOffset()) + " in " + EHFrameSectionName +
193 " block at address " + formatv("{0:x16}", B.getAddress()));
194
195 BlockEdges[E.getOffset()] = EdgeTarget(E);
196 }
197
198 CIEInfosMap CIEInfos;
199 BinaryStreamReader BlockReader(B.getContent(), PC.G.getEndianness());
200 while (!BlockReader.empty()) {
201 size_t RecordStartOffset = BlockReader.getOffset();
202
203 LLVM_DEBUG({
204 dbgs() << " Processing CFI record at "
205 << formatv("{0:x16}", B.getAddress() + RecordStartOffset) << "\n";
206 });
207
208 // Get the record length.
209 size_t RecordRemaining;
210 {
211 uint32_t Length;
212 if (auto Err = BlockReader.readInteger(Length))
213 return Err;
214 // If Length < 0xffffffff then use the regular length field, otherwise
215 // read the extended length field.
216 if (Length != 0xffffffff)
217 RecordRemaining = Length;
218 else {
219 uint64_t ExtendedLength;
220 if (auto Err = BlockReader.readInteger(ExtendedLength))
221 return Err;
222 RecordRemaining = ExtendedLength;
223 }
224 }
225
226 if (BlockReader.bytesRemaining() < RecordRemaining)
227 return make_error<JITLinkError>(
228 "Incomplete CFI record at " +
229 formatv("{0:x16}", B.getAddress() + RecordStartOffset));
230
231 // Read the CIE delta for this record.
232 uint64_t CIEDeltaFieldOffset = BlockReader.getOffset() - RecordStartOffset;
233 uint32_t CIEDelta;
234 if (auto Err = BlockReader.readInteger(CIEDelta))
235 return Err;
236
237 if (CIEDelta == 0) {
238 if (auto Err = processCIE(PC, B, RecordStartOffset,
239 CIEDeltaFieldOffset + RecordRemaining,
240 CIEDeltaFieldOffset))
241 return Err;
242 } else {
243 if (auto Err = processFDE(PC, B, RecordStartOffset,
244 CIEDeltaFieldOffset + RecordRemaining,
245 CIEDeltaFieldOffset, CIEDelta, BlockEdges))
246 return Err;
247 }
248
249 // Move to the next record.
250 BlockReader.setOffset(RecordStartOffset + CIEDeltaFieldOffset +
251 RecordRemaining);
252 }
253
254 return Error::success();
255 }
256
processCIE(ParseContext & PC,Block & B,size_t RecordOffset,size_t RecordLength,size_t CIEDeltaFieldOffset)257 Error EHFrameEdgeFixer::processCIE(ParseContext &PC, Block &B,
258 size_t RecordOffset, size_t RecordLength,
259 size_t CIEDeltaFieldOffset) {
260 using namespace dwarf;
261
262 LLVM_DEBUG(dbgs() << " Record is CIE\n");
263
264 auto RecordContent = B.getContent().substr(RecordOffset, RecordLength);
265 BinaryStreamReader RecordReader(RecordContent, PC.G.getEndianness());
266
267 // Skip past the CIE delta field: we've already processed this far.
268 RecordReader.setOffset(CIEDeltaFieldOffset + 4);
269
270 auto &CIESymbol =
271 PC.G.addAnonymousSymbol(B, RecordOffset, RecordLength, false, false);
272 CIEInformation CIEInfo(CIESymbol);
273
274 uint8_t Version = 0;
275 if (auto Err = RecordReader.readInteger(Version))
276 return Err;
277
278 if (Version != 0x01)
279 return make_error<JITLinkError>("Bad CIE version " + Twine(Version) +
280 " (should be 0x01) in eh-frame");
281
282 auto AugInfo = parseAugmentationString(RecordReader);
283 if (!AugInfo)
284 return AugInfo.takeError();
285
286 // Skip the EH Data field if present.
287 if (AugInfo->EHDataFieldPresent)
288 if (auto Err = RecordReader.skip(PC.G.getPointerSize()))
289 return Err;
290
291 // Read and sanity check the code alignment factor.
292 {
293 uint64_t CodeAlignmentFactor = 0;
294 if (auto Err = RecordReader.readULEB128(CodeAlignmentFactor))
295 return Err;
296 if (CodeAlignmentFactor != 1)
297 return make_error<JITLinkError>("Unsupported CIE code alignment factor " +
298 Twine(CodeAlignmentFactor) +
299 " (expected 1)");
300 }
301
302 // Read and sanity check the data alignment factor.
303 {
304 int64_t DataAlignmentFactor = 0;
305 if (auto Err = RecordReader.readSLEB128(DataAlignmentFactor))
306 return Err;
307 if (DataAlignmentFactor != -8)
308 return make_error<JITLinkError>("Unsupported CIE data alignment factor " +
309 Twine(DataAlignmentFactor) +
310 " (expected -8)");
311 }
312
313 // Skip the return address register field.
314 if (auto Err = RecordReader.skip(1))
315 return Err;
316
317 uint64_t AugmentationDataLength = 0;
318 if (auto Err = RecordReader.readULEB128(AugmentationDataLength))
319 return Err;
320
321 uint32_t AugmentationDataStartOffset = RecordReader.getOffset();
322
323 uint8_t *NextField = &AugInfo->Fields[0];
324 while (uint8_t Field = *NextField++) {
325 switch (Field) {
326 case 'L': {
327 CIEInfo.FDEsHaveLSDAField = true;
328 uint8_t LSDAPointerEncoding;
329 if (auto Err = RecordReader.readInteger(LSDAPointerEncoding))
330 return Err;
331 if (LSDAPointerEncoding != (DW_EH_PE_pcrel | DW_EH_PE_absptr))
332 return make_error<JITLinkError>(
333 "Unsupported LSDA pointer encoding " +
334 formatv("{0:x2}", LSDAPointerEncoding) + " in CIE at " +
335 formatv("{0:x16}", CIESymbol.getAddress()));
336 break;
337 }
338 case 'P': {
339 uint8_t PersonalityPointerEncoding = 0;
340 if (auto Err = RecordReader.readInteger(PersonalityPointerEncoding))
341 return Err;
342 if (PersonalityPointerEncoding !=
343 (DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4))
344 return make_error<JITLinkError>(
345 "Unspported personality pointer "
346 "encoding " +
347 formatv("{0:x2}", PersonalityPointerEncoding) + " in CIE at " +
348 formatv("{0:x16}", CIESymbol.getAddress()));
349 uint32_t PersonalityPointerAddress;
350 if (auto Err = RecordReader.readInteger(PersonalityPointerAddress))
351 return Err;
352 break;
353 }
354 case 'R': {
355 uint8_t FDEPointerEncoding;
356 if (auto Err = RecordReader.readInteger(FDEPointerEncoding))
357 return Err;
358 if (FDEPointerEncoding != (DW_EH_PE_pcrel | DW_EH_PE_absptr))
359 return make_error<JITLinkError>(
360 "Unsupported FDE address pointer "
361 "encoding " +
362 formatv("{0:x2}", FDEPointerEncoding) + " in CIE at " +
363 formatv("{0:x16}", CIESymbol.getAddress()));
364 break;
365 }
366 default:
367 llvm_unreachable("Invalid augmentation string field");
368 }
369 }
370
371 if (RecordReader.getOffset() - AugmentationDataStartOffset >
372 AugmentationDataLength)
373 return make_error<JITLinkError>("Read past the end of the augmentation "
374 "data while parsing fields");
375
376 assert(!PC.CIEInfos.count(CIESymbol.getAddress()) &&
377 "Multiple CIEs recorded at the same address?");
378 PC.CIEInfos[CIESymbol.getAddress()] = std::move(CIEInfo);
379
380 return Error::success();
381 }
382
processFDE(ParseContext & PC,Block & B,size_t RecordOffset,size_t RecordLength,size_t CIEDeltaFieldOffset,uint32_t CIEDelta,BlockEdgeMap & BlockEdges)383 Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,
384 size_t RecordOffset, size_t RecordLength,
385 size_t CIEDeltaFieldOffset,
386 uint32_t CIEDelta,
387 BlockEdgeMap &BlockEdges) {
388 LLVM_DEBUG(dbgs() << " Record is FDE\n");
389
390 JITTargetAddress RecordAddress = B.getAddress() + RecordOffset;
391
392 auto RecordContent = B.getContent().substr(RecordOffset, RecordLength);
393 BinaryStreamReader RecordReader(RecordContent, PC.G.getEndianness());
394
395 // Skip past the CIE delta field: we've already read this far.
396 RecordReader.setOffset(CIEDeltaFieldOffset + 4);
397
398 auto &FDESymbol =
399 PC.G.addAnonymousSymbol(B, RecordOffset, RecordLength, false, false);
400
401 CIEInformation *CIEInfo = nullptr;
402
403 {
404 // Process the CIE pointer field.
405 auto CIEEdgeItr = BlockEdges.find(RecordOffset + CIEDeltaFieldOffset);
406 JITTargetAddress CIEAddress =
407 RecordAddress + CIEDeltaFieldOffset - CIEDelta;
408 if (CIEEdgeItr == BlockEdges.end()) {
409
410 LLVM_DEBUG({
411 dbgs() << " Adding edge at "
412 << formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset)
413 << " to CIE at: " << formatv("{0:x16}", CIEAddress) << "\n";
414 });
415 if (auto CIEInfoOrErr = PC.findCIEInfo(CIEAddress))
416 CIEInfo = *CIEInfoOrErr;
417 else
418 return CIEInfoOrErr.takeError();
419 assert(CIEInfo->CIESymbol && "CIEInfo has no CIE symbol set");
420 B.addEdge(FDEToCIE, RecordOffset + CIEDeltaFieldOffset,
421 *CIEInfo->CIESymbol, 0);
422 } else {
423 LLVM_DEBUG({
424 dbgs() << " Already has edge at "
425 << formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset)
426 << " to CIE at " << formatv("{0:x16}", CIEAddress) << "\n";
427 });
428 auto &EI = CIEEdgeItr->second;
429 if (EI.Addend)
430 return make_error<JITLinkError>(
431 "CIE edge at " +
432 formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset) +
433 " has non-zero addend");
434 if (auto CIEInfoOrErr = PC.findCIEInfo(EI.Target->getAddress()))
435 CIEInfo = *CIEInfoOrErr;
436 else
437 return CIEInfoOrErr.takeError();
438 }
439 }
440
441 {
442 // Process the PC-Begin field.
443 Block *PCBeginBlock = nullptr;
444 JITTargetAddress PCBeginFieldOffset = RecordReader.getOffset();
445 auto PCEdgeItr = BlockEdges.find(RecordOffset + PCBeginFieldOffset);
446 if (PCEdgeItr == BlockEdges.end()) {
447 auto PCBeginDelta = readAbsolutePointer(PC.G, RecordReader);
448 if (!PCBeginDelta)
449 return PCBeginDelta.takeError();
450 JITTargetAddress PCBegin =
451 RecordAddress + PCBeginFieldOffset + *PCBeginDelta;
452 LLVM_DEBUG({
453 dbgs() << " Adding edge at "
454 << formatv("{0:x16}", RecordAddress + PCBeginFieldOffset)
455 << " to PC at " << formatv("{0:x16}", PCBegin) << "\n";
456 });
457 auto PCBeginSym = getOrCreateSymbol(PC, PCBegin);
458 if (!PCBeginSym)
459 return PCBeginSym.takeError();
460 B.addEdge(FDEToPCBegin, RecordOffset + PCBeginFieldOffset, *PCBeginSym,
461 0);
462 PCBeginBlock = &PCBeginSym->getBlock();
463 } else {
464 auto &EI = PCEdgeItr->second;
465 LLVM_DEBUG({
466 dbgs() << " Already has edge at "
467 << formatv("{0:x16}", RecordAddress + PCBeginFieldOffset)
468 << " to PC at " << formatv("{0:x16}", EI.Target->getAddress());
469 if (EI.Addend)
470 dbgs() << " + " << formatv("{0:x16}", EI.Addend);
471 dbgs() << "\n";
472 });
473
474 // Make sure the existing edge points at a defined block.
475 if (!EI.Target->isDefined()) {
476 auto EdgeAddr = RecordAddress + PCBeginFieldOffset;
477 return make_error<JITLinkError>("FDE edge at " +
478 formatv("{0:x16}", EdgeAddr) +
479 " points at external block");
480 }
481 PCBeginBlock = &EI.Target->getBlock();
482 if (auto Err = RecordReader.skip(PC.G.getPointerSize()))
483 return Err;
484 }
485
486 // Add a keep-alive edge from the FDE target to the FDE to ensure that the
487 // FDE is kept alive if its target is.
488 assert(PCBeginBlock && "PC-begin block not recorded");
489 PCBeginBlock->addEdge(Edge::KeepAlive, 0, FDESymbol, 0);
490 }
491
492 // Skip over the PC range size field.
493 if (auto Err = RecordReader.skip(PC.G.getPointerSize()))
494 return Err;
495
496 if (CIEInfo->FDEsHaveLSDAField) {
497 uint64_t AugmentationDataSize;
498 if (auto Err = RecordReader.readULEB128(AugmentationDataSize))
499 return Err;
500 if (AugmentationDataSize != PC.G.getPointerSize())
501 return make_error<JITLinkError>(
502 "Unexpected FDE augmentation data size (expected " +
503 Twine(PC.G.getPointerSize()) + ", got " +
504 Twine(AugmentationDataSize) + ") for FDE at " +
505 formatv("{0:x16}", RecordAddress));
506
507 JITTargetAddress LSDAFieldOffset = RecordReader.getOffset();
508 auto LSDAEdgeItr = BlockEdges.find(RecordOffset + LSDAFieldOffset);
509 if (LSDAEdgeItr == BlockEdges.end()) {
510 auto LSDADelta = readAbsolutePointer(PC.G, RecordReader);
511 if (!LSDADelta)
512 return LSDADelta.takeError();
513 JITTargetAddress LSDA = RecordAddress + LSDAFieldOffset + *LSDADelta;
514 auto LSDASym = getOrCreateSymbol(PC, LSDA);
515 if (!LSDASym)
516 return LSDASym.takeError();
517 LLVM_DEBUG({
518 dbgs() << " Adding edge at "
519 << formatv("{0:x16}", RecordAddress + LSDAFieldOffset)
520 << " to LSDA at " << formatv("{0:x16}", LSDA) << "\n";
521 });
522 B.addEdge(FDEToLSDA, RecordOffset + LSDAFieldOffset, *LSDASym, 0);
523 } else {
524 LLVM_DEBUG({
525 auto &EI = LSDAEdgeItr->second;
526 dbgs() << " Already has edge at "
527 << formatv("{0:x16}", RecordAddress + LSDAFieldOffset)
528 << " to LSDA at " << formatv("{0:x16}", EI.Target->getAddress());
529 if (EI.Addend)
530 dbgs() << " + " << formatv("{0:x16}", EI.Addend);
531 dbgs() << "\n";
532 });
533 if (auto Err = RecordReader.skip(PC.G.getPointerSize()))
534 return Err;
535 }
536 } else {
537 LLVM_DEBUG(dbgs() << " Record does not have LSDA field.\n");
538 }
539
540 return Error::success();
541 }
542
543 Expected<EHFrameEdgeFixer::AugmentationInfo>
parseAugmentationString(BinaryStreamReader & RecordReader)544 EHFrameEdgeFixer::parseAugmentationString(BinaryStreamReader &RecordReader) {
545 AugmentationInfo AugInfo;
546 uint8_t NextChar;
547 uint8_t *NextField = &AugInfo.Fields[0];
548
549 if (auto Err = RecordReader.readInteger(NextChar))
550 return std::move(Err);
551
552 while (NextChar != 0) {
553 switch (NextChar) {
554 case 'z':
555 AugInfo.AugmentationDataPresent = true;
556 break;
557 case 'e':
558 if (auto Err = RecordReader.readInteger(NextChar))
559 return std::move(Err);
560 if (NextChar != 'h')
561 return make_error<JITLinkError>("Unrecognized substring e" +
562 Twine(NextChar) +
563 " in augmentation string");
564 AugInfo.EHDataFieldPresent = true;
565 break;
566 case 'L':
567 case 'P':
568 case 'R':
569 *NextField++ = NextChar;
570 break;
571 default:
572 return make_error<JITLinkError>("Unrecognized character " +
573 Twine(NextChar) +
574 " in augmentation string");
575 }
576
577 if (auto Err = RecordReader.readInteger(NextChar))
578 return std::move(Err);
579 }
580
581 return std::move(AugInfo);
582 }
583
584 Expected<JITTargetAddress>
readAbsolutePointer(LinkGraph & G,BinaryStreamReader & RecordReader)585 EHFrameEdgeFixer::readAbsolutePointer(LinkGraph &G,
586 BinaryStreamReader &RecordReader) {
587 static_assert(sizeof(JITTargetAddress) == sizeof(uint64_t),
588 "Result must be able to hold a uint64_t");
589 JITTargetAddress Addr;
590 if (G.getPointerSize() == 8) {
591 if (auto Err = RecordReader.readInteger(Addr))
592 return std::move(Err);
593 } else if (G.getPointerSize() == 4) {
594 uint32_t Addr32;
595 if (auto Err = RecordReader.readInteger(Addr32))
596 return std::move(Err);
597 Addr = Addr32;
598 } else
599 llvm_unreachable("Pointer size is not 32-bit or 64-bit");
600 return Addr;
601 }
602
getOrCreateSymbol(ParseContext & PC,JITTargetAddress Addr)603 Expected<Symbol &> EHFrameEdgeFixer::getOrCreateSymbol(ParseContext &PC,
604 JITTargetAddress Addr) {
605 Symbol *CanonicalSym = nullptr;
606
607 auto UpdateCanonicalSym = [&](Symbol *Sym) {
608 if (!CanonicalSym || Sym->getLinkage() < CanonicalSym->getLinkage() ||
609 Sym->getScope() < CanonicalSym->getScope() ||
610 (Sym->hasName() && !CanonicalSym->hasName()) ||
611 Sym->getName() < CanonicalSym->getName())
612 CanonicalSym = Sym;
613 };
614
615 if (auto *SymbolsAtAddr = PC.AddrToSyms.getSymbolsAt(Addr))
616 for (auto *Sym : *SymbolsAtAddr)
617 UpdateCanonicalSym(Sym);
618
619 // If we found an existing symbol at the given address then use it.
620 if (CanonicalSym)
621 return *CanonicalSym;
622
623 // Otherwise search for a block covering the address and create a new symbol.
624 auto *B = PC.AddrToBlock.getBlockCovering(Addr);
625 if (!B)
626 return make_error<JITLinkError>("No symbol or block covering address " +
627 formatv("{0:x16}", Addr));
628
629 return PC.G.addAnonymousSymbol(*B, Addr - B->getAddress(), 0, false, false);
630 }
631
632 // Determine whether we can register EH tables.
633 #if (defined(__GNUC__) && !defined(__ARM_EABI__) && !defined(__ia64__) && \
634 !(defined(_AIX) && defined(__ibmxl__)) && !defined(__SEH__) && \
635 !defined(__USING_SJLJ_EXCEPTIONS__))
636 #define HAVE_EHTABLE_SUPPORT 1
637 #else
638 #define HAVE_EHTABLE_SUPPORT 0
639 #endif
640
641 #if HAVE_EHTABLE_SUPPORT
642 extern "C" void __register_frame(const void *);
643 extern "C" void __deregister_frame(const void *);
644
registerFrameWrapper(const void * P)645 Error registerFrameWrapper(const void *P) {
646 __register_frame(P);
647 return Error::success();
648 }
649
deregisterFrameWrapper(const void * P)650 Error deregisterFrameWrapper(const void *P) {
651 __deregister_frame(P);
652 return Error::success();
653 }
654
655 #else
656
657 // The building compiler does not have __(de)register_frame but
658 // it may be found at runtime in a dynamically-loaded library.
659 // For example, this happens when building LLVM with Visual C++
660 // but using the MingW runtime.
registerFrameWrapper(const void * P)661 static Error registerFrameWrapper(const void *P) {
662 static void((*RegisterFrame)(const void *)) = 0;
663
664 if (!RegisterFrame)
665 *(void **)&RegisterFrame =
666 llvm::sys::DynamicLibrary::SearchForAddressOfSymbol("__register_frame");
667
668 if (RegisterFrame) {
669 RegisterFrame(P);
670 return Error::success();
671 }
672
673 return make_error<JITLinkError>("could not register eh-frame: "
674 "__register_frame function not found");
675 }
676
deregisterFrameWrapper(const void * P)677 static Error deregisterFrameWrapper(const void *P) {
678 static void((*DeregisterFrame)(const void *)) = 0;
679
680 if (!DeregisterFrame)
681 *(void **)&DeregisterFrame =
682 llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(
683 "__deregister_frame");
684
685 if (DeregisterFrame) {
686 DeregisterFrame(P);
687 return Error::success();
688 }
689
690 return make_error<JITLinkError>("could not deregister eh-frame: "
691 "__deregister_frame function not found");
692 }
693 #endif
694
695 #ifdef __APPLE__
696
697 template <typename HandleFDEFn>
walkAppleEHFrameSection(const char * const SectionStart,size_t SectionSize,HandleFDEFn HandleFDE)698 Error walkAppleEHFrameSection(const char *const SectionStart,
699 size_t SectionSize,
700 HandleFDEFn HandleFDE) {
701 const char *CurCFIRecord = SectionStart;
702 const char *End = SectionStart + SectionSize;
703 uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
704
705 while (CurCFIRecord != End && Size != 0) {
706 const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 : 4);
707 if (Size == 0xffffffff)
708 Size = *reinterpret_cast<const uint64_t *>(CurCFIRecord + 4) + 12;
709 else
710 Size += 4;
711 uint32_t Offset = *reinterpret_cast<const uint32_t *>(OffsetField);
712
713 LLVM_DEBUG({
714 dbgs() << "Registering eh-frame section:\n";
715 dbgs() << "Processing " << (Offset ? "FDE" : "CIE") << " @"
716 << (void *)CurCFIRecord << ": [";
717 for (unsigned I = 0; I < Size; ++I)
718 dbgs() << format(" 0x%02" PRIx8, *(CurCFIRecord + I));
719 dbgs() << " ]\n";
720 });
721
722 if (Offset != 0)
723 if (auto Err = HandleFDE(CurCFIRecord))
724 return Err;
725
726 CurCFIRecord += Size;
727
728 Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
729 }
730
731 return Error::success();
732 }
733
734 #endif // __APPLE__
735
registerEHFrameSection(const void * EHFrameSectionAddr,size_t EHFrameSectionSize)736 Error registerEHFrameSection(const void *EHFrameSectionAddr,
737 size_t EHFrameSectionSize) {
738 #ifdef __APPLE__
739 // On Darwin __register_frame has to be called for each FDE entry.
740 return walkAppleEHFrameSection(static_cast<const char *>(EHFrameSectionAddr),
741 EHFrameSectionSize,
742 registerFrameWrapper);
743 #else
744 // On Linux __register_frame takes a single argument:
745 // a pointer to the start of the .eh_frame section.
746
747 // How can it find the end? Because crtendS.o is linked
748 // in and it has an .eh_frame section with four zero chars.
749 return registerFrameWrapper(EHFrameSectionAddr);
750 #endif
751 }
752
deregisterEHFrameSection(const void * EHFrameSectionAddr,size_t EHFrameSectionSize)753 Error deregisterEHFrameSection(const void *EHFrameSectionAddr,
754 size_t EHFrameSectionSize) {
755 #ifdef __APPLE__
756 return walkAppleEHFrameSection(static_cast<const char *>(EHFrameSectionAddr),
757 EHFrameSectionSize,
758 deregisterFrameWrapper);
759 #else
760 return deregisterFrameWrapper(EHFrameSectionAddr);
761 #endif
762 }
763
~EHFrameRegistrar()764 EHFrameRegistrar::~EHFrameRegistrar() {}
765
getInstance()766 InProcessEHFrameRegistrar &InProcessEHFrameRegistrar::getInstance() {
767 static InProcessEHFrameRegistrar Instance;
768 return Instance;
769 }
770
InProcessEHFrameRegistrar()771 InProcessEHFrameRegistrar::InProcessEHFrameRegistrar() {}
772
773 LinkGraphPassFunction
createEHFrameRecorderPass(const Triple & TT,StoreFrameRangeFunction StoreRangeAddress)774 createEHFrameRecorderPass(const Triple &TT,
775 StoreFrameRangeFunction StoreRangeAddress) {
776 const char *EHFrameSectionName = nullptr;
777 if (TT.getObjectFormat() == Triple::MachO)
778 EHFrameSectionName = "__eh_frame";
779 else
780 EHFrameSectionName = ".eh_frame";
781
782 auto RecordEHFrame =
783 [EHFrameSectionName,
784 StoreFrameRange = std::move(StoreRangeAddress)](LinkGraph &G) -> Error {
785 // Search for a non-empty eh-frame and record the address of the first
786 // symbol in it.
787 JITTargetAddress Addr = 0;
788 size_t Size = 0;
789 if (auto *S = G.findSectionByName(EHFrameSectionName)) {
790 auto R = SectionRange(*S);
791 Addr = R.getStart();
792 Size = R.getSize();
793 }
794 if (Addr == 0 && Size != 0)
795 return make_error<JITLinkError>("__eh_frame section can not have zero "
796 "address with non-zero size");
797 StoreFrameRange(Addr, Size);
798 return Error::success();
799 };
800
801 return RecordEHFrame;
802 }
803
804 } // end namespace jitlink
805 } // end namespace llvm
806