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