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