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