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