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