10b57cec5SDimitry Andric //===-------- JITLink_EHFrameSupport.cpp - JITLink eh-frame utils ---------===// 20b57cec5SDimitry Andric // 3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "EHFrameSupportImpl.h" 100b57cec5SDimitry Andric 110b57cec5SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h" 12e8d8bef9SDimitry Andric #include "llvm/Config/config.h" 1381ad6265SDimitry Andric #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h" 14e8d8bef9SDimitry Andric #include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h" 150b57cec5SDimitry Andric #include "llvm/Support/DynamicLibrary.h" 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric #define DEBUG_TYPE "jitlink" 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric namespace llvm { 200b57cec5SDimitry Andric namespace jitlink { 210b57cec5SDimitry Andric 22480093f4SDimitry Andric EHFrameEdgeFixer::EHFrameEdgeFixer(StringRef EHFrameSectionName, 2381ad6265SDimitry Andric unsigned PointerSize, Edge::Kind Pointer32, 2481ad6265SDimitry Andric Edge::Kind Pointer64, Edge::Kind Delta32, 2581ad6265SDimitry Andric Edge::Kind Delta64, Edge::Kind NegDelta32) 26e8d8bef9SDimitry Andric : EHFrameSectionName(EHFrameSectionName), PointerSize(PointerSize), 2781ad6265SDimitry Andric Pointer32(Pointer32), Pointer64(Pointer64), Delta32(Delta32), 2881ad6265SDimitry Andric Delta64(Delta64), NegDelta32(NegDelta32) {} 29480093f4SDimitry Andric 30480093f4SDimitry Andric Error EHFrameEdgeFixer::operator()(LinkGraph &G) { 31480093f4SDimitry Andric auto *EHFrame = G.findSectionByName(EHFrameSectionName); 32480093f4SDimitry Andric 33480093f4SDimitry Andric if (!EHFrame) { 34480093f4SDimitry Andric LLVM_DEBUG({ 35480093f4SDimitry Andric dbgs() << "EHFrameEdgeFixer: No " << EHFrameSectionName 36753f127fSDimitry Andric << " section in \"" << G.getName() << "\". Nothing to do.\n"; 37480093f4SDimitry Andric }); 38480093f4SDimitry Andric return Error::success(); 39480093f4SDimitry Andric } 40480093f4SDimitry Andric 41e8d8bef9SDimitry Andric // Check that we support the graph's pointer size. 42e8d8bef9SDimitry Andric if (G.getPointerSize() != 4 && G.getPointerSize() != 8) 43e8d8bef9SDimitry Andric return make_error<JITLinkError>( 44e8d8bef9SDimitry Andric "EHFrameEdgeFixer only supports 32 and 64 bit targets"); 45e8d8bef9SDimitry Andric 46480093f4SDimitry Andric LLVM_DEBUG({ 47753f127fSDimitry Andric dbgs() << "EHFrameEdgeFixer: Processing " << EHFrameSectionName << " in \"" 48753f127fSDimitry Andric << G.getName() << "\"...\n"; 49480093f4SDimitry Andric }); 50480093f4SDimitry Andric 51480093f4SDimitry Andric ParseContext PC(G); 52480093f4SDimitry Andric 53480093f4SDimitry Andric // Build a map of all blocks and symbols in the text sections. We will use 54480093f4SDimitry Andric // these for finding / building edge targets when processing FDEs. 55480093f4SDimitry Andric for (auto &Sec : G.sections()) { 5681ad6265SDimitry Andric // Just record the most-canonical symbol (for eh-frame purposes) at each 5781ad6265SDimitry Andric // address. 5881ad6265SDimitry Andric for (auto *Sym : Sec.symbols()) { 5981ad6265SDimitry Andric auto &CurSym = PC.AddrToSym[Sym->getAddress()]; 6081ad6265SDimitry Andric if (!CurSym || (std::make_tuple(Sym->getLinkage(), Sym->getScope(), 6181ad6265SDimitry Andric !Sym->hasName(), Sym->getName()) < 6281ad6265SDimitry Andric std::make_tuple(CurSym->getLinkage(), CurSym->getScope(), 6381ad6265SDimitry Andric !CurSym->hasName(), CurSym->getName()))) 6481ad6265SDimitry Andric CurSym = Sym; 6581ad6265SDimitry Andric } 66480093f4SDimitry Andric if (auto Err = PC.AddrToBlock.addBlocks(Sec.blocks(), 67480093f4SDimitry Andric BlockAddressMap::includeNonNull)) 68480093f4SDimitry Andric return Err; 69480093f4SDimitry Andric } 70480093f4SDimitry Andric 71480093f4SDimitry Andric // Sort eh-frame blocks into address order to ensure we visit CIEs before 72480093f4SDimitry Andric // their child FDEs. 73480093f4SDimitry Andric std::vector<Block *> EHFrameBlocks; 74480093f4SDimitry Andric for (auto *B : EHFrame->blocks()) 75480093f4SDimitry Andric EHFrameBlocks.push_back(B); 76480093f4SDimitry Andric llvm::sort(EHFrameBlocks, [](const Block *LHS, const Block *RHS) { 77480093f4SDimitry Andric return LHS->getAddress() < RHS->getAddress(); 78480093f4SDimitry Andric }); 79480093f4SDimitry Andric 80480093f4SDimitry Andric // Loop over the blocks in address order. 81480093f4SDimitry Andric for (auto *B : EHFrameBlocks) 82480093f4SDimitry Andric if (auto Err = processBlock(PC, *B)) 83480093f4SDimitry Andric return Err; 84480093f4SDimitry Andric 85480093f4SDimitry Andric return Error::success(); 86480093f4SDimitry Andric } 87480093f4SDimitry Andric 88bdd1243dSDimitry Andric static Expected<size_t> readCFIRecordLength(const Block &B, 89bdd1243dSDimitry Andric BinaryStreamReader &R) { 90bdd1243dSDimitry Andric uint32_t Length; 91bdd1243dSDimitry Andric if (auto Err = R.readInteger(Length)) 92bdd1243dSDimitry Andric return std::move(Err); 93bdd1243dSDimitry Andric 94bdd1243dSDimitry Andric // If Length < 0xffffffff then use the regular length field, otherwise 95bdd1243dSDimitry Andric // read the extended length field. 96bdd1243dSDimitry Andric if (Length != 0xffffffff) 97bdd1243dSDimitry Andric return Length; 98bdd1243dSDimitry Andric 99bdd1243dSDimitry Andric uint64_t ExtendedLength; 100bdd1243dSDimitry Andric if (auto Err = R.readInteger(ExtendedLength)) 101bdd1243dSDimitry Andric return std::move(Err); 102bdd1243dSDimitry Andric 103bdd1243dSDimitry Andric if (ExtendedLength > std::numeric_limits<size_t>::max()) 104bdd1243dSDimitry Andric return make_error<JITLinkError>( 105bdd1243dSDimitry Andric "In CFI record at " + 106bdd1243dSDimitry Andric formatv("{0:x}", B.getAddress() + R.getOffset() - 12) + 107bdd1243dSDimitry Andric ", extended length of " + formatv("{0:x}", ExtendedLength) + 108bdd1243dSDimitry Andric " exceeds address-range max (" + 109bdd1243dSDimitry Andric formatv("{0:x}", std::numeric_limits<size_t>::max())); 110bdd1243dSDimitry Andric 111bdd1243dSDimitry Andric return ExtendedLength; 112bdd1243dSDimitry Andric } 113bdd1243dSDimitry Andric 114480093f4SDimitry Andric Error EHFrameEdgeFixer::processBlock(ParseContext &PC, Block &B) { 115480093f4SDimitry Andric 11681ad6265SDimitry Andric LLVM_DEBUG(dbgs() << " Processing block at " << B.getAddress() << "\n"); 117480093f4SDimitry Andric 118480093f4SDimitry Andric // eh-frame should not contain zero-fill blocks. 119480093f4SDimitry Andric if (B.isZeroFill()) 120480093f4SDimitry Andric return make_error<JITLinkError>("Unexpected zero-fill block in " + 121480093f4SDimitry Andric EHFrameSectionName + " section"); 122480093f4SDimitry Andric 123480093f4SDimitry Andric if (B.getSize() == 0) { 124480093f4SDimitry Andric LLVM_DEBUG(dbgs() << " Block is empty. Skipping.\n"); 125480093f4SDimitry Andric return Error::success(); 126480093f4SDimitry Andric } 127480093f4SDimitry Andric 128480093f4SDimitry Andric // Find the offsets of any existing edges from this block. 129*5f757f3fSDimitry Andric BlockEdgesInfo BlockEdges; 130480093f4SDimitry Andric for (auto &E : B.edges()) 131480093f4SDimitry Andric if (E.isRelocation()) { 132*5f757f3fSDimitry Andric // Check if we already saw more than one relocation at this offset. 133*5f757f3fSDimitry Andric if (BlockEdges.Multiple.contains(E.getOffset())) 134*5f757f3fSDimitry Andric continue; 135480093f4SDimitry Andric 136*5f757f3fSDimitry Andric // Otherwise check if we previously had exactly one relocation at this 137*5f757f3fSDimitry Andric // offset. If so, we now have a second one and move it from the TargetMap 138*5f757f3fSDimitry Andric // into the Multiple set. 139*5f757f3fSDimitry Andric auto It = BlockEdges.TargetMap.find(E.getOffset()); 140*5f757f3fSDimitry Andric if (It != BlockEdges.TargetMap.end()) { 141*5f757f3fSDimitry Andric BlockEdges.TargetMap.erase(It); 142*5f757f3fSDimitry Andric BlockEdges.Multiple.insert(E.getOffset()); 143*5f757f3fSDimitry Andric } else { 144*5f757f3fSDimitry Andric BlockEdges.TargetMap[E.getOffset()] = EdgeTarget(E); 145*5f757f3fSDimitry Andric } 146480093f4SDimitry Andric } 147480093f4SDimitry Andric 148fe6060f1SDimitry Andric BinaryStreamReader BlockReader( 149fe6060f1SDimitry Andric StringRef(B.getContent().data(), B.getContent().size()), 150fe6060f1SDimitry Andric PC.G.getEndianness()); 151480093f4SDimitry Andric 152480093f4SDimitry Andric // Get the record length. 153bdd1243dSDimitry Andric Expected<size_t> RecordRemaining = readCFIRecordLength(B, BlockReader); 154bdd1243dSDimitry Andric if (!RecordRemaining) 155bdd1243dSDimitry Andric return RecordRemaining.takeError(); 156480093f4SDimitry Andric 157*5f757f3fSDimitry Andric // We expect DWARFRecordSectionSplitter to split each CFI record into its own 158*5f757f3fSDimitry Andric // block. 159*5f757f3fSDimitry Andric if (BlockReader.bytesRemaining() != *RecordRemaining) 160*5f757f3fSDimitry Andric return make_error<JITLinkError>("Incomplete CFI record at " + 161*5f757f3fSDimitry Andric formatv("{0:x16}", B.getAddress())); 162480093f4SDimitry Andric 163480093f4SDimitry Andric // Read the CIE delta for this record. 164*5f757f3fSDimitry Andric uint64_t CIEDeltaFieldOffset = BlockReader.getOffset(); 165480093f4SDimitry Andric uint32_t CIEDelta; 166480093f4SDimitry Andric if (auto Err = BlockReader.readInteger(CIEDelta)) 167480093f4SDimitry Andric return Err; 168480093f4SDimitry Andric 169480093f4SDimitry Andric if (CIEDelta == 0) { 170*5f757f3fSDimitry Andric if (auto Err = processCIE(PC, B, CIEDeltaFieldOffset, BlockEdges)) 171480093f4SDimitry Andric return Err; 172480093f4SDimitry Andric } else { 173*5f757f3fSDimitry Andric if (auto Err = processFDE(PC, B, CIEDeltaFieldOffset, CIEDelta, BlockEdges)) 174480093f4SDimitry Andric return Err; 175480093f4SDimitry Andric } 176480093f4SDimitry Andric 177480093f4SDimitry Andric return Error::success(); 178480093f4SDimitry Andric } 179480093f4SDimitry Andric 180480093f4SDimitry Andric Error EHFrameEdgeFixer::processCIE(ParseContext &PC, Block &B, 18181ad6265SDimitry Andric size_t CIEDeltaFieldOffset, 182*5f757f3fSDimitry Andric const BlockEdgesInfo &BlockEdges) { 183480093f4SDimitry Andric 184480093f4SDimitry Andric LLVM_DEBUG(dbgs() << " Record is CIE\n"); 185480093f4SDimitry Andric 186fe6060f1SDimitry Andric BinaryStreamReader RecordReader( 187*5f757f3fSDimitry Andric StringRef(B.getContent().data(), B.getContent().size()), 188fe6060f1SDimitry Andric PC.G.getEndianness()); 189480093f4SDimitry Andric 190480093f4SDimitry Andric // Skip past the CIE delta field: we've already processed this far. 191480093f4SDimitry Andric RecordReader.setOffset(CIEDeltaFieldOffset + 4); 192480093f4SDimitry Andric 193*5f757f3fSDimitry Andric auto &CIESymbol = PC.G.addAnonymousSymbol(B, 0, B.getSize(), false, false); 194480093f4SDimitry Andric CIEInformation CIEInfo(CIESymbol); 195480093f4SDimitry Andric 196480093f4SDimitry Andric uint8_t Version = 0; 197480093f4SDimitry Andric if (auto Err = RecordReader.readInteger(Version)) 198480093f4SDimitry Andric return Err; 199480093f4SDimitry Andric 200480093f4SDimitry Andric if (Version != 0x01) 201480093f4SDimitry Andric return make_error<JITLinkError>("Bad CIE version " + Twine(Version) + 202480093f4SDimitry Andric " (should be 0x01) in eh-frame"); 203480093f4SDimitry Andric 204480093f4SDimitry Andric auto AugInfo = parseAugmentationString(RecordReader); 205480093f4SDimitry Andric if (!AugInfo) 206480093f4SDimitry Andric return AugInfo.takeError(); 207480093f4SDimitry Andric 208480093f4SDimitry Andric // Skip the EH Data field if present. 209480093f4SDimitry Andric if (AugInfo->EHDataFieldPresent) 210480093f4SDimitry Andric if (auto Err = RecordReader.skip(PC.G.getPointerSize())) 211480093f4SDimitry Andric return Err; 212480093f4SDimitry Andric 213349cc55cSDimitry Andric // Read and validate the code alignment factor. 214480093f4SDimitry Andric { 215480093f4SDimitry Andric uint64_t CodeAlignmentFactor = 0; 216480093f4SDimitry Andric if (auto Err = RecordReader.readULEB128(CodeAlignmentFactor)) 217480093f4SDimitry Andric return Err; 218480093f4SDimitry Andric } 219480093f4SDimitry Andric 220349cc55cSDimitry Andric // Read and validate the data alignment factor. 221480093f4SDimitry Andric { 222480093f4SDimitry Andric int64_t DataAlignmentFactor = 0; 223480093f4SDimitry Andric if (auto Err = RecordReader.readSLEB128(DataAlignmentFactor)) 224480093f4SDimitry Andric return Err; 225480093f4SDimitry Andric } 226480093f4SDimitry Andric 227480093f4SDimitry Andric // Skip the return address register field. 228480093f4SDimitry Andric if (auto Err = RecordReader.skip(1)) 229480093f4SDimitry Andric return Err; 230480093f4SDimitry Andric 23181ad6265SDimitry Andric if (AugInfo->AugmentationDataPresent) { 23281ad6265SDimitry Andric 23381ad6265SDimitry Andric CIEInfo.AugmentationDataPresent = true; 23481ad6265SDimitry Andric 235480093f4SDimitry Andric uint64_t AugmentationDataLength = 0; 236480093f4SDimitry Andric if (auto Err = RecordReader.readULEB128(AugmentationDataLength)) 237480093f4SDimitry Andric return Err; 238480093f4SDimitry Andric 239480093f4SDimitry Andric uint32_t AugmentationDataStartOffset = RecordReader.getOffset(); 240480093f4SDimitry Andric 241480093f4SDimitry Andric uint8_t *NextField = &AugInfo->Fields[0]; 242480093f4SDimitry Andric while (uint8_t Field = *NextField++) { 243480093f4SDimitry Andric switch (Field) { 24481ad6265SDimitry Andric case 'L': 24581ad6265SDimitry Andric CIEInfo.LSDAPresent = true; 24681ad6265SDimitry Andric if (auto PE = readPointerEncoding(RecordReader, B, "LSDA")) 24781ad6265SDimitry Andric CIEInfo.LSDAEncoding = *PE; 24881ad6265SDimitry Andric else 24981ad6265SDimitry Andric return PE.takeError(); 250480093f4SDimitry Andric break; 251480093f4SDimitry Andric case 'P': { 25281ad6265SDimitry Andric auto PersonalityPointerEncoding = 25381ad6265SDimitry Andric readPointerEncoding(RecordReader, B, "personality"); 25481ad6265SDimitry Andric if (!PersonalityPointerEncoding) 25581ad6265SDimitry Andric return PersonalityPointerEncoding.takeError(); 25681ad6265SDimitry Andric if (auto Err = 25781ad6265SDimitry Andric getOrCreateEncodedPointerEdge( 25881ad6265SDimitry Andric PC, BlockEdges, *PersonalityPointerEncoding, RecordReader, 259*5f757f3fSDimitry Andric B, RecordReader.getOffset(), "personality") 26081ad6265SDimitry Andric .takeError()) 261480093f4SDimitry Andric return Err; 262480093f4SDimitry Andric break; 263480093f4SDimitry Andric } 26481ad6265SDimitry Andric case 'R': 26581ad6265SDimitry Andric if (auto PE = readPointerEncoding(RecordReader, B, "address")) { 26681ad6265SDimitry Andric CIEInfo.AddressEncoding = *PE; 26781ad6265SDimitry Andric if (CIEInfo.AddressEncoding == dwarf::DW_EH_PE_omit) 268480093f4SDimitry Andric return make_error<JITLinkError>( 26981ad6265SDimitry Andric "Invalid address encoding DW_EH_PE_omit in CIE at " + 270*5f757f3fSDimitry Andric formatv("{0:x}", B.getAddress().getValue())); 27181ad6265SDimitry Andric } else 27281ad6265SDimitry Andric return PE.takeError(); 273480093f4SDimitry Andric break; 274480093f4SDimitry Andric default: 275480093f4SDimitry Andric llvm_unreachable("Invalid augmentation string field"); 276480093f4SDimitry Andric } 277480093f4SDimitry Andric } 278480093f4SDimitry Andric 279480093f4SDimitry Andric if (RecordReader.getOffset() - AugmentationDataStartOffset > 280480093f4SDimitry Andric AugmentationDataLength) 281480093f4SDimitry Andric return make_error<JITLinkError>("Read past the end of the augmentation " 282480093f4SDimitry Andric "data while parsing fields"); 28381ad6265SDimitry Andric } 284480093f4SDimitry Andric 285480093f4SDimitry Andric assert(!PC.CIEInfos.count(CIESymbol.getAddress()) && 286480093f4SDimitry Andric "Multiple CIEs recorded at the same address?"); 287480093f4SDimitry Andric PC.CIEInfos[CIESymbol.getAddress()] = std::move(CIEInfo); 288480093f4SDimitry Andric 289480093f4SDimitry Andric return Error::success(); 290480093f4SDimitry Andric } 291480093f4SDimitry Andric 292480093f4SDimitry Andric Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B, 293480093f4SDimitry Andric size_t CIEDeltaFieldOffset, 294480093f4SDimitry Andric uint32_t CIEDelta, 295*5f757f3fSDimitry Andric const BlockEdgesInfo &BlockEdges) { 296480093f4SDimitry Andric LLVM_DEBUG(dbgs() << " Record is FDE\n"); 297480093f4SDimitry Andric 298*5f757f3fSDimitry Andric orc::ExecutorAddr RecordAddress = B.getAddress(); 299480093f4SDimitry Andric 300fe6060f1SDimitry Andric BinaryStreamReader RecordReader( 301*5f757f3fSDimitry Andric StringRef(B.getContent().data(), B.getContent().size()), 302fe6060f1SDimitry Andric PC.G.getEndianness()); 303480093f4SDimitry Andric 304480093f4SDimitry Andric // Skip past the CIE delta field: we've already read this far. 305480093f4SDimitry Andric RecordReader.setOffset(CIEDeltaFieldOffset + 4); 306480093f4SDimitry Andric 307*5f757f3fSDimitry Andric auto &FDESymbol = PC.G.addAnonymousSymbol(B, 0, B.getSize(), false, false); 308480093f4SDimitry Andric 309480093f4SDimitry Andric CIEInformation *CIEInfo = nullptr; 310480093f4SDimitry Andric 311480093f4SDimitry Andric { 312480093f4SDimitry Andric // Process the CIE pointer field. 313*5f757f3fSDimitry Andric if (BlockEdges.Multiple.contains(CIEDeltaFieldOffset)) 314*5f757f3fSDimitry Andric return make_error<JITLinkError>( 315*5f757f3fSDimitry Andric "CIE pointer field already has multiple edges at " + 316*5f757f3fSDimitry Andric formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset)); 317*5f757f3fSDimitry Andric 318*5f757f3fSDimitry Andric auto CIEEdgeItr = BlockEdges.TargetMap.find(CIEDeltaFieldOffset); 319*5f757f3fSDimitry Andric 32004eeddc0SDimitry Andric orc::ExecutorAddr CIEAddress = 32104eeddc0SDimitry Andric RecordAddress + orc::ExecutorAddrDiff(CIEDeltaFieldOffset) - 32204eeddc0SDimitry Andric orc::ExecutorAddrDiff(CIEDelta); 323*5f757f3fSDimitry Andric if (CIEEdgeItr == BlockEdges.TargetMap.end()) { 324480093f4SDimitry Andric LLVM_DEBUG({ 325480093f4SDimitry Andric dbgs() << " Adding edge at " 32681ad6265SDimitry Andric << (RecordAddress + CIEDeltaFieldOffset) 32781ad6265SDimitry Andric << " to CIE at: " << CIEAddress << "\n"; 328480093f4SDimitry Andric }); 329480093f4SDimitry Andric if (auto CIEInfoOrErr = PC.findCIEInfo(CIEAddress)) 330480093f4SDimitry Andric CIEInfo = *CIEInfoOrErr; 331480093f4SDimitry Andric else 332480093f4SDimitry Andric return CIEInfoOrErr.takeError(); 333480093f4SDimitry Andric assert(CIEInfo->CIESymbol && "CIEInfo has no CIE symbol set"); 334*5f757f3fSDimitry Andric B.addEdge(NegDelta32, CIEDeltaFieldOffset, *CIEInfo->CIESymbol, 0); 335480093f4SDimitry Andric } else { 336480093f4SDimitry Andric LLVM_DEBUG({ 337480093f4SDimitry Andric dbgs() << " Already has edge at " 33881ad6265SDimitry Andric << (RecordAddress + CIEDeltaFieldOffset) << " to CIE at " 33981ad6265SDimitry Andric << CIEAddress << "\n"; 340480093f4SDimitry Andric }); 341480093f4SDimitry Andric auto &EI = CIEEdgeItr->second; 342480093f4SDimitry Andric if (EI.Addend) 343480093f4SDimitry Andric return make_error<JITLinkError>( 344480093f4SDimitry Andric "CIE edge at " + 345480093f4SDimitry Andric formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset) + 346480093f4SDimitry Andric " has non-zero addend"); 347480093f4SDimitry Andric if (auto CIEInfoOrErr = PC.findCIEInfo(EI.Target->getAddress())) 348480093f4SDimitry Andric CIEInfo = *CIEInfoOrErr; 349480093f4SDimitry Andric else 350480093f4SDimitry Andric return CIEInfoOrErr.takeError(); 351480093f4SDimitry Andric } 352480093f4SDimitry Andric } 353480093f4SDimitry Andric 354480093f4SDimitry Andric // Process the PC-Begin field. 355480093f4SDimitry Andric LLVM_DEBUG({ 35681ad6265SDimitry Andric dbgs() << " Processing PC-begin at " 35781ad6265SDimitry Andric << (RecordAddress + RecordReader.getOffset()) << "\n"; 358480093f4SDimitry Andric }); 35981ad6265SDimitry Andric if (auto PCBegin = getOrCreateEncodedPointerEdge( 36081ad6265SDimitry Andric PC, BlockEdges, CIEInfo->AddressEncoding, RecordReader, B, 36181ad6265SDimitry Andric RecordReader.getOffset(), "PC begin")) { 36281ad6265SDimitry Andric assert(*PCBegin && "PC-begin symbol not set"); 363bdd1243dSDimitry Andric if ((*PCBegin)->isDefined()) { 364480093f4SDimitry Andric // Add a keep-alive edge from the FDE target to the FDE to ensure that the 365480093f4SDimitry Andric // FDE is kept alive if its target is. 366e8d8bef9SDimitry Andric LLVM_DEBUG({ 367e8d8bef9SDimitry Andric dbgs() << " Adding keep-alive edge from target at " 36881ad6265SDimitry Andric << (*PCBegin)->getBlock().getAddress() << " to FDE at " 36981ad6265SDimitry Andric << RecordAddress << "\n"; 370e8d8bef9SDimitry Andric }); 37181ad6265SDimitry Andric (*PCBegin)->getBlock().addEdge(Edge::KeepAlive, 0, FDESymbol, 0); 372bdd1243dSDimitry Andric } else { 373bdd1243dSDimitry Andric LLVM_DEBUG({ 374bdd1243dSDimitry Andric dbgs() << " WARNING: Not adding keep-alive edge to FDE at " 375bdd1243dSDimitry Andric << RecordAddress << ", which points to " 376bdd1243dSDimitry Andric << ((*PCBegin)->isExternal() ? "external" : "absolute") 377bdd1243dSDimitry Andric << " symbol \"" << (*PCBegin)->getName() 378bdd1243dSDimitry Andric << "\" -- FDE must be kept alive manually or it will be " 379bdd1243dSDimitry Andric << "dead stripped.\n"; 380bdd1243dSDimitry Andric }); 381bdd1243dSDimitry Andric } 38281ad6265SDimitry Andric } else 38381ad6265SDimitry Andric return PCBegin.takeError(); 384480093f4SDimitry Andric 385480093f4SDimitry Andric // Skip over the PC range size field. 38681ad6265SDimitry Andric if (auto Err = skipEncodedPointer(CIEInfo->AddressEncoding, RecordReader)) 387480093f4SDimitry Andric return Err; 388480093f4SDimitry Andric 38981ad6265SDimitry Andric if (CIEInfo->AugmentationDataPresent) { 390480093f4SDimitry Andric uint64_t AugmentationDataSize; 391480093f4SDimitry Andric if (auto Err = RecordReader.readULEB128(AugmentationDataSize)) 392480093f4SDimitry Andric return Err; 393480093f4SDimitry Andric 39481ad6265SDimitry Andric if (CIEInfo->LSDAPresent) 39581ad6265SDimitry Andric if (auto Err = getOrCreateEncodedPointerEdge( 39681ad6265SDimitry Andric PC, BlockEdges, CIEInfo->LSDAEncoding, RecordReader, B, 39781ad6265SDimitry Andric RecordReader.getOffset(), "LSDA") 39881ad6265SDimitry Andric .takeError()) 399480093f4SDimitry Andric return Err; 400480093f4SDimitry Andric } else { 401480093f4SDimitry Andric LLVM_DEBUG(dbgs() << " Record does not have LSDA field.\n"); 402480093f4SDimitry Andric } 403480093f4SDimitry Andric 404480093f4SDimitry Andric return Error::success(); 405480093f4SDimitry Andric } 406480093f4SDimitry Andric 407480093f4SDimitry Andric Expected<EHFrameEdgeFixer::AugmentationInfo> 408480093f4SDimitry Andric EHFrameEdgeFixer::parseAugmentationString(BinaryStreamReader &RecordReader) { 4090b57cec5SDimitry Andric AugmentationInfo AugInfo; 4100b57cec5SDimitry Andric uint8_t NextChar; 4110b57cec5SDimitry Andric uint8_t *NextField = &AugInfo.Fields[0]; 4120b57cec5SDimitry Andric 413480093f4SDimitry Andric if (auto Err = RecordReader.readInteger(NextChar)) 4140b57cec5SDimitry Andric return std::move(Err); 4150b57cec5SDimitry Andric 4160b57cec5SDimitry Andric while (NextChar != 0) { 4170b57cec5SDimitry Andric switch (NextChar) { 4180b57cec5SDimitry Andric case 'z': 4190b57cec5SDimitry Andric AugInfo.AugmentationDataPresent = true; 4200b57cec5SDimitry Andric break; 4210b57cec5SDimitry Andric case 'e': 422480093f4SDimitry Andric if (auto Err = RecordReader.readInteger(NextChar)) 4230b57cec5SDimitry Andric return std::move(Err); 4240b57cec5SDimitry Andric if (NextChar != 'h') 4250b57cec5SDimitry Andric return make_error<JITLinkError>("Unrecognized substring e" + 4260b57cec5SDimitry Andric Twine(NextChar) + 4270b57cec5SDimitry Andric " in augmentation string"); 4280b57cec5SDimitry Andric AugInfo.EHDataFieldPresent = true; 4290b57cec5SDimitry Andric break; 4300b57cec5SDimitry Andric case 'L': 4310b57cec5SDimitry Andric case 'P': 4320b57cec5SDimitry Andric case 'R': 4330b57cec5SDimitry Andric *NextField++ = NextChar; 4340b57cec5SDimitry Andric break; 4350b57cec5SDimitry Andric default: 4360b57cec5SDimitry Andric return make_error<JITLinkError>("Unrecognized character " + 4370b57cec5SDimitry Andric Twine(NextChar) + 4380b57cec5SDimitry Andric " in augmentation string"); 4390b57cec5SDimitry Andric } 4400b57cec5SDimitry Andric 441480093f4SDimitry Andric if (auto Err = RecordReader.readInteger(NextChar)) 4420b57cec5SDimitry Andric return std::move(Err); 4430b57cec5SDimitry Andric } 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric return std::move(AugInfo); 4460b57cec5SDimitry Andric } 4470b57cec5SDimitry Andric 44881ad6265SDimitry Andric Expected<uint8_t> EHFrameEdgeFixer::readPointerEncoding(BinaryStreamReader &R, 44981ad6265SDimitry Andric Block &InBlock, 45081ad6265SDimitry Andric const char *FieldName) { 451e8d8bef9SDimitry Andric using namespace dwarf; 452e8d8bef9SDimitry Andric 45381ad6265SDimitry Andric uint8_t PointerEncoding; 45481ad6265SDimitry Andric if (auto Err = R.readInteger(PointerEncoding)) 45581ad6265SDimitry Andric return std::move(Err); 456e8d8bef9SDimitry Andric 45781ad6265SDimitry Andric bool Supported = true; 458e8d8bef9SDimitry Andric switch (PointerEncoding & 0xf) { 45981ad6265SDimitry Andric case DW_EH_PE_uleb128: 46081ad6265SDimitry Andric case DW_EH_PE_udata2: 46181ad6265SDimitry Andric case DW_EH_PE_sleb128: 46281ad6265SDimitry Andric case DW_EH_PE_sdata2: 46381ad6265SDimitry Andric Supported = false; 46481ad6265SDimitry Andric break; 465e8d8bef9SDimitry Andric } 46681ad6265SDimitry Andric if (Supported) { 46781ad6265SDimitry Andric switch (PointerEncoding & 0x70) { 46881ad6265SDimitry Andric case DW_EH_PE_textrel: 46981ad6265SDimitry Andric case DW_EH_PE_datarel: 47081ad6265SDimitry Andric case DW_EH_PE_funcrel: 47181ad6265SDimitry Andric case DW_EH_PE_aligned: 47281ad6265SDimitry Andric Supported = false; 47381ad6265SDimitry Andric break; 474e8d8bef9SDimitry Andric } 475e8d8bef9SDimitry Andric } 476e8d8bef9SDimitry Andric 47781ad6265SDimitry Andric if (Supported) 47881ad6265SDimitry Andric return PointerEncoding; 47981ad6265SDimitry Andric 48081ad6265SDimitry Andric return make_error<JITLinkError>("Unsupported pointer encoding " + 48181ad6265SDimitry Andric formatv("{0:x2}", PointerEncoding) + " for " + 48281ad6265SDimitry Andric FieldName + "in CFI record at " + 48381ad6265SDimitry Andric formatv("{0:x16}", InBlock.getAddress())); 48481ad6265SDimitry Andric } 48581ad6265SDimitry Andric 48681ad6265SDimitry Andric Error EHFrameEdgeFixer::skipEncodedPointer(uint8_t PointerEncoding, 487480093f4SDimitry Andric BinaryStreamReader &RecordReader) { 488e8d8bef9SDimitry Andric using namespace dwarf; 489e8d8bef9SDimitry Andric 49081ad6265SDimitry Andric // Switch absptr to corresponding udata encoding. 49181ad6265SDimitry Andric if ((PointerEncoding & 0xf) == DW_EH_PE_absptr) 49281ad6265SDimitry Andric PointerEncoding |= (PointerSize == 8) ? DW_EH_PE_udata8 : DW_EH_PE_udata4; 493e8d8bef9SDimitry Andric 49481ad6265SDimitry Andric switch (PointerEncoding & 0xf) { 49581ad6265SDimitry Andric case DW_EH_PE_udata4: 49681ad6265SDimitry Andric case DW_EH_PE_sdata4: 49781ad6265SDimitry Andric if (auto Err = RecordReader.skip(4)) 49881ad6265SDimitry Andric return Err; 49981ad6265SDimitry Andric break; 50081ad6265SDimitry Andric case DW_EH_PE_udata8: 50181ad6265SDimitry Andric case DW_EH_PE_sdata8: 50281ad6265SDimitry Andric if (auto Err = RecordReader.skip(8)) 50381ad6265SDimitry Andric return Err; 50481ad6265SDimitry Andric break; 50581ad6265SDimitry Andric default: 50681ad6265SDimitry Andric llvm_unreachable("Unrecognized encoding"); 50781ad6265SDimitry Andric } 50881ad6265SDimitry Andric return Error::success(); 50981ad6265SDimitry Andric } 51081ad6265SDimitry Andric 51181ad6265SDimitry Andric Expected<Symbol *> EHFrameEdgeFixer::getOrCreateEncodedPointerEdge( 512*5f757f3fSDimitry Andric ParseContext &PC, const BlockEdgesInfo &BlockEdges, uint8_t PointerEncoding, 51381ad6265SDimitry Andric BinaryStreamReader &RecordReader, Block &BlockToFix, 51481ad6265SDimitry Andric size_t PointerFieldOffset, const char *FieldName) { 51581ad6265SDimitry Andric using namespace dwarf; 51681ad6265SDimitry Andric 51781ad6265SDimitry Andric if (PointerEncoding == DW_EH_PE_omit) 51881ad6265SDimitry Andric return nullptr; 51981ad6265SDimitry Andric 52081ad6265SDimitry Andric // If there's already an edge here then just skip the encoded pointer and 52181ad6265SDimitry Andric // return the edge's target. 52281ad6265SDimitry Andric { 523*5f757f3fSDimitry Andric auto EdgeI = BlockEdges.TargetMap.find(PointerFieldOffset); 524*5f757f3fSDimitry Andric if (EdgeI != BlockEdges.TargetMap.end()) { 52581ad6265SDimitry Andric LLVM_DEBUG({ 52681ad6265SDimitry Andric dbgs() << " Existing edge at " 52781ad6265SDimitry Andric << (BlockToFix.getAddress() + PointerFieldOffset) << " to " 52881ad6265SDimitry Andric << FieldName << " at " << EdgeI->second.Target->getAddress(); 52981ad6265SDimitry Andric if (EdgeI->second.Target->hasName()) 53081ad6265SDimitry Andric dbgs() << " (" << EdgeI->second.Target->getName() << ")"; 53181ad6265SDimitry Andric dbgs() << "\n"; 53281ad6265SDimitry Andric }); 53381ad6265SDimitry Andric if (auto Err = skipEncodedPointer(PointerEncoding, RecordReader)) 53481ad6265SDimitry Andric return std::move(Err); 53581ad6265SDimitry Andric return EdgeI->second.Target; 53681ad6265SDimitry Andric } 537*5f757f3fSDimitry Andric 538*5f757f3fSDimitry Andric if (BlockEdges.Multiple.contains(PointerFieldOffset)) 539*5f757f3fSDimitry Andric return make_error<JITLinkError>("Multiple relocations at offset " + 540*5f757f3fSDimitry Andric formatv("{0:x16}", PointerFieldOffset)); 54181ad6265SDimitry Andric } 54281ad6265SDimitry Andric 54381ad6265SDimitry Andric // Switch absptr to corresponding udata encoding. 54481ad6265SDimitry Andric if ((PointerEncoding & 0xf) == DW_EH_PE_absptr) 54581ad6265SDimitry Andric PointerEncoding |= (PointerSize == 8) ? DW_EH_PE_udata8 : DW_EH_PE_udata4; 54681ad6265SDimitry Andric 54781ad6265SDimitry Andric // We need to create an edge. Start by reading the field value. 54881ad6265SDimitry Andric uint64_t FieldValue; 54981ad6265SDimitry Andric bool Is64Bit = false; 55081ad6265SDimitry Andric switch (PointerEncoding & 0xf) { 551e8d8bef9SDimitry Andric case DW_EH_PE_udata4: { 552e8d8bef9SDimitry Andric uint32_t Val; 553e8d8bef9SDimitry Andric if (auto Err = RecordReader.readInteger(Val)) 5540b57cec5SDimitry Andric return std::move(Err); 55581ad6265SDimitry Andric FieldValue = Val; 556e8d8bef9SDimitry Andric break; 557e8d8bef9SDimitry Andric } 558e8d8bef9SDimitry Andric case DW_EH_PE_sdata4: { 55981ad6265SDimitry Andric uint32_t Val; 560e8d8bef9SDimitry Andric if (auto Err = RecordReader.readInteger(Val)) 561e8d8bef9SDimitry Andric return std::move(Err); 56281ad6265SDimitry Andric FieldValue = Val; 563e8d8bef9SDimitry Andric break; 564e8d8bef9SDimitry Andric } 56581ad6265SDimitry Andric case DW_EH_PE_udata8: 56681ad6265SDimitry Andric case DW_EH_PE_sdata8: 56781ad6265SDimitry Andric Is64Bit = true; 56881ad6265SDimitry Andric if (auto Err = RecordReader.readInteger(FieldValue)) 569e8d8bef9SDimitry Andric return std::move(Err); 570e8d8bef9SDimitry Andric break; 57181ad6265SDimitry Andric default: 57281ad6265SDimitry Andric llvm_unreachable("Unsupported encoding"); 573e8d8bef9SDimitry Andric } 574e8d8bef9SDimitry Andric 57581ad6265SDimitry Andric // Find the edge target and edge kind to use. 57681ad6265SDimitry Andric orc::ExecutorAddr Target; 57781ad6265SDimitry Andric Edge::Kind PtrEdgeKind = Edge::Invalid; 57881ad6265SDimitry Andric if ((PointerEncoding & 0x70) == DW_EH_PE_pcrel) { 57981ad6265SDimitry Andric Target = BlockToFix.getAddress() + PointerFieldOffset; 58081ad6265SDimitry Andric PtrEdgeKind = Is64Bit ? Delta64 : Delta32; 58181ad6265SDimitry Andric } else 58281ad6265SDimitry Andric PtrEdgeKind = Is64Bit ? Pointer64 : Pointer32; 58381ad6265SDimitry Andric Target += FieldValue; 584e8d8bef9SDimitry Andric 58581ad6265SDimitry Andric // Find or create a symbol to point the edge at. 58681ad6265SDimitry Andric auto TargetSym = getOrCreateSymbol(PC, Target); 58781ad6265SDimitry Andric if (!TargetSym) 58881ad6265SDimitry Andric return TargetSym.takeError(); 58981ad6265SDimitry Andric BlockToFix.addEdge(PtrEdgeKind, PointerFieldOffset, *TargetSym, 0); 59081ad6265SDimitry Andric 59181ad6265SDimitry Andric LLVM_DEBUG({ 59281ad6265SDimitry Andric dbgs() << " Adding edge at " 59381ad6265SDimitry Andric << (BlockToFix.getAddress() + PointerFieldOffset) << " to " 59481ad6265SDimitry Andric << FieldName << " at " << TargetSym->getAddress(); 59581ad6265SDimitry Andric if (TargetSym->hasName()) 59681ad6265SDimitry Andric dbgs() << " (" << TargetSym->getName() << ")"; 59781ad6265SDimitry Andric dbgs() << "\n"; 59881ad6265SDimitry Andric }); 59981ad6265SDimitry Andric 60081ad6265SDimitry Andric return &*TargetSym; 6010b57cec5SDimitry Andric } 6020b57cec5SDimitry Andric 603480093f4SDimitry Andric Expected<Symbol &> EHFrameEdgeFixer::getOrCreateSymbol(ParseContext &PC, 60404eeddc0SDimitry Andric orc::ExecutorAddr Addr) { 60581ad6265SDimitry Andric // See whether we have a canonical symbol for the given address already. 60681ad6265SDimitry Andric auto CanonicalSymI = PC.AddrToSym.find(Addr); 60781ad6265SDimitry Andric if (CanonicalSymI != PC.AddrToSym.end()) 60881ad6265SDimitry Andric return *CanonicalSymI->second; 6090b57cec5SDimitry Andric 610480093f4SDimitry Andric // Otherwise search for a block covering the address and create a new symbol. 611480093f4SDimitry Andric auto *B = PC.AddrToBlock.getBlockCovering(Addr); 612480093f4SDimitry Andric if (!B) 613480093f4SDimitry Andric return make_error<JITLinkError>("No symbol or block covering address " + 614480093f4SDimitry Andric formatv("{0:x16}", Addr)); 6150b57cec5SDimitry Andric 61681ad6265SDimitry Andric auto &S = 61781ad6265SDimitry Andric PC.G.addAnonymousSymbol(*B, Addr - B->getAddress(), 0, false, false); 61881ad6265SDimitry Andric PC.AddrToSym[S.getAddress()] = &S; 61981ad6265SDimitry Andric return S; 6200b57cec5SDimitry Andric } 6210b57cec5SDimitry Andric 622fe6060f1SDimitry Andric char EHFrameNullTerminator::NullTerminatorBlockContent[4] = {0, 0, 0, 0}; 623fe6060f1SDimitry Andric 624fe6060f1SDimitry Andric EHFrameNullTerminator::EHFrameNullTerminator(StringRef EHFrameSectionName) 625fe6060f1SDimitry Andric : EHFrameSectionName(EHFrameSectionName) {} 626fe6060f1SDimitry Andric 627fe6060f1SDimitry Andric Error EHFrameNullTerminator::operator()(LinkGraph &G) { 628fe6060f1SDimitry Andric auto *EHFrame = G.findSectionByName(EHFrameSectionName); 629fe6060f1SDimitry Andric 630fe6060f1SDimitry Andric if (!EHFrame) 631fe6060f1SDimitry Andric return Error::success(); 632fe6060f1SDimitry Andric 633fe6060f1SDimitry Andric LLVM_DEBUG({ 634fe6060f1SDimitry Andric dbgs() << "EHFrameNullTerminator adding null terminator to " 635fe6060f1SDimitry Andric << EHFrameSectionName << "\n"; 636fe6060f1SDimitry Andric }); 637fe6060f1SDimitry Andric 63804eeddc0SDimitry Andric auto &NullTerminatorBlock = 63904eeddc0SDimitry Andric G.createContentBlock(*EHFrame, NullTerminatorBlockContent, 64004eeddc0SDimitry Andric orc::ExecutorAddr(~uint64_t(4)), 1, 0); 641fe6060f1SDimitry Andric G.addAnonymousSymbol(NullTerminatorBlock, 0, 4, false, true); 642fe6060f1SDimitry Andric return Error::success(); 643fe6060f1SDimitry Andric } 644fe6060f1SDimitry Andric 64581ad6265SDimitry Andric EHFrameRegistrar::~EHFrameRegistrar() = default; 6460b57cec5SDimitry Andric 647e8d8bef9SDimitry Andric Error InProcessEHFrameRegistrar::registerEHFrames( 64804eeddc0SDimitry Andric orc::ExecutorAddrRange EHFrameSection) { 64904eeddc0SDimitry Andric return orc::registerEHFrameSection(EHFrameSection.Start.toPtr<void *>(), 65004eeddc0SDimitry Andric EHFrameSection.size()); 6510b57cec5SDimitry Andric } 6520b57cec5SDimitry Andric 653e8d8bef9SDimitry Andric Error InProcessEHFrameRegistrar::deregisterEHFrames( 65404eeddc0SDimitry Andric orc::ExecutorAddrRange EHFrameSection) { 65504eeddc0SDimitry Andric return orc::deregisterEHFrameSection(EHFrameSection.Start.toPtr<void *>(), 65604eeddc0SDimitry Andric EHFrameSection.size()); 657e8d8bef9SDimitry Andric } 6580b57cec5SDimitry Andric 659bdd1243dSDimitry Andric EHFrameCFIBlockInspector EHFrameCFIBlockInspector::FromEdgeScan(Block &B) { 660bdd1243dSDimitry Andric if (B.edges_empty()) 661bdd1243dSDimitry Andric return EHFrameCFIBlockInspector(nullptr); 662bdd1243dSDimitry Andric if (B.edges_size() == 1) 663bdd1243dSDimitry Andric return EHFrameCFIBlockInspector(&*B.edges().begin()); 664bdd1243dSDimitry Andric SmallVector<Edge *, 3> Es; 665bdd1243dSDimitry Andric for (auto &E : B.edges()) 666bdd1243dSDimitry Andric Es.push_back(&E); 667bdd1243dSDimitry Andric assert(Es.size() >= 2 && Es.size() <= 3 && "Unexpected number of edges"); 668bdd1243dSDimitry Andric llvm::sort(Es, [](const Edge *LHS, const Edge *RHS) { 669bdd1243dSDimitry Andric return LHS->getOffset() < RHS->getOffset(); 670bdd1243dSDimitry Andric }); 671bdd1243dSDimitry Andric return EHFrameCFIBlockInspector(*Es[0], *Es[1], 672bdd1243dSDimitry Andric Es.size() == 3 ? Es[2] : nullptr); 673bdd1243dSDimitry Andric return EHFrameCFIBlockInspector(nullptr); 674bdd1243dSDimitry Andric } 675bdd1243dSDimitry Andric 676bdd1243dSDimitry Andric EHFrameCFIBlockInspector::EHFrameCFIBlockInspector(Edge *PersonalityEdge) 677bdd1243dSDimitry Andric : PersonalityEdge(PersonalityEdge) {} 678bdd1243dSDimitry Andric 679bdd1243dSDimitry Andric EHFrameCFIBlockInspector::EHFrameCFIBlockInspector(Edge &CIEEdge, 680bdd1243dSDimitry Andric Edge &PCBeginEdge, 681bdd1243dSDimitry Andric Edge *LSDAEdge) 682bdd1243dSDimitry Andric : CIEEdge(&CIEEdge), PCBeginEdge(&PCBeginEdge), LSDAEdge(LSDAEdge) {} 683bdd1243dSDimitry Andric 6848bcb0991SDimitry Andric LinkGraphPassFunction 6850b57cec5SDimitry Andric createEHFrameRecorderPass(const Triple &TT, 6868bcb0991SDimitry Andric StoreFrameRangeFunction StoreRangeAddress) { 6870b57cec5SDimitry Andric const char *EHFrameSectionName = nullptr; 6880b57cec5SDimitry Andric if (TT.getObjectFormat() == Triple::MachO) 689fe6060f1SDimitry Andric EHFrameSectionName = "__TEXT,__eh_frame"; 6900b57cec5SDimitry Andric else 6910b57cec5SDimitry Andric EHFrameSectionName = ".eh_frame"; 6920b57cec5SDimitry Andric 6938bcb0991SDimitry Andric auto RecordEHFrame = 6948bcb0991SDimitry Andric [EHFrameSectionName, 6958bcb0991SDimitry Andric StoreFrameRange = std::move(StoreRangeAddress)](LinkGraph &G) -> Error { 6968bcb0991SDimitry Andric // Search for a non-empty eh-frame and record the address of the first 6978bcb0991SDimitry Andric // symbol in it. 69804eeddc0SDimitry Andric orc::ExecutorAddr Addr; 6998bcb0991SDimitry Andric size_t Size = 0; 7008bcb0991SDimitry Andric if (auto *S = G.findSectionByName(EHFrameSectionName)) { 7018bcb0991SDimitry Andric auto R = SectionRange(*S); 7028bcb0991SDimitry Andric Addr = R.getStart(); 7038bcb0991SDimitry Andric Size = R.getSize(); 7048bcb0991SDimitry Andric } 70504eeddc0SDimitry Andric if (!Addr && Size != 0) 706fe6060f1SDimitry Andric return make_error<JITLinkError>( 707fe6060f1SDimitry Andric StringRef(EHFrameSectionName) + 708fe6060f1SDimitry Andric " section can not have zero address with non-zero size"); 7098bcb0991SDimitry Andric StoreFrameRange(Addr, Size); 7100b57cec5SDimitry Andric return Error::success(); 7110b57cec5SDimitry Andric }; 7120b57cec5SDimitry Andric 7130b57cec5SDimitry Andric return RecordEHFrame; 7140b57cec5SDimitry Andric } 7150b57cec5SDimitry Andric 7160b57cec5SDimitry Andric } // end namespace jitlink 7170b57cec5SDimitry Andric } // end namespace llvm 718