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