686 lines · cpp
1//===-------- JITLink_EHFrameSupport.cpp - JITLink eh-frame utils ---------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "EHFrameSupportImpl.h"10 11#include "llvm/BinaryFormat/Dwarf.h"12#include "llvm/Config/config.h"13#include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"14#include "llvm/Support/DynamicLibrary.h"15 16#define DEBUG_TYPE "jitlink"17 18namespace llvm {19namespace jitlink {20 21EHFrameEdgeFixer::EHFrameEdgeFixer(StringRef EHFrameSectionName,22 unsigned PointerSize, Edge::Kind Pointer32,23 Edge::Kind Pointer64, Edge::Kind Delta32,24 Edge::Kind Delta64, Edge::Kind NegDelta32)25 : EHFrameSectionName(EHFrameSectionName), PointerSize(PointerSize),26 Pointer32(Pointer32), Pointer64(Pointer64), Delta32(Delta32),27 Delta64(Delta64), NegDelta32(NegDelta32) {}28 29Error EHFrameEdgeFixer::operator()(LinkGraph &G) {30 auto *EHFrame = G.findSectionByName(EHFrameSectionName);31 32 if (!EHFrame) {33 LLVM_DEBUG({34 dbgs() << "EHFrameEdgeFixer: No " << EHFrameSectionName35 << " section in \"" << G.getName() << "\". Nothing to do.\n";36 });37 return Error::success();38 }39 40 // Check that we support the graph's pointer size.41 if (G.getPointerSize() != 4 && G.getPointerSize() != 8)42 return make_error<JITLinkError>(43 "EHFrameEdgeFixer only supports 32 and 64 bit targets");44 45 LLVM_DEBUG({46 dbgs() << "EHFrameEdgeFixer: Processing " << EHFrameSectionName << " in \""47 << G.getName() << "\"...\n";48 });49 50 ParseContext PC(G);51 52 // Build a map of all blocks and symbols in the text sections. We will use53 // these for finding / building edge targets when processing FDEs.54 for (auto &Sec : G.sections()) {55 // Just record the most-canonical symbol (for eh-frame purposes) at each56 // address.57 for (auto *Sym : Sec.symbols()) {58 auto &CurSym = PC.AddrToSym[Sym->getAddress()];59 if (!CurSym || (std::make_tuple(Sym->getLinkage(), Sym->getScope(),60 !Sym->hasName(), Sym->getName()) <61 std::make_tuple(CurSym->getLinkage(), CurSym->getScope(),62 !CurSym->hasName(), CurSym->getName())))63 CurSym = Sym;64 }65 if (auto Err = PC.AddrToBlock.addBlocks(Sec.blocks(),66 BlockAddressMap::includeNonNull))67 return Err;68 }69 70 // Sort eh-frame blocks into address order to ensure we visit CIEs before71 // their child FDEs.72 std::vector<Block *> EHFrameBlocks;73 llvm::append_range(EHFrameBlocks, EHFrame->blocks());74 llvm::sort(EHFrameBlocks, [](const Block *LHS, const Block *RHS) {75 return LHS->getAddress() < RHS->getAddress();76 });77 78 // Loop over the blocks in address order.79 for (auto *B : EHFrameBlocks)80 if (auto Err = processBlock(PC, *B))81 return Err;82 83 return Error::success();84}85 86static Expected<size_t> readCFIRecordLength(const Block &B,87 BinaryStreamReader &R) {88 uint32_t Length;89 if (auto Err = R.readInteger(Length))90 return std::move(Err);91 92 // If Length < 0xffffffff then use the regular length field, otherwise93 // read the extended length field.94 if (Length != 0xffffffff)95 return Length;96 97 uint64_t ExtendedLength;98 if (auto Err = R.readInteger(ExtendedLength))99 return std::move(Err);100 101 if (ExtendedLength > std::numeric_limits<size_t>::max())102 return make_error<JITLinkError>(103 "In CFI record at " +104 formatv("{0:x}", B.getAddress() + R.getOffset() - 12) +105 ", extended length of " + formatv("{0:x}", ExtendedLength) +106 " exceeds address-range max (" +107 formatv("{0:x}", std::numeric_limits<size_t>::max()));108 109 return ExtendedLength;110}111 112Error EHFrameEdgeFixer::processBlock(ParseContext &PC, Block &B) {113 114 LLVM_DEBUG(dbgs() << " Processing block at " << B.getAddress() << "\n");115 116 // eh-frame should not contain zero-fill blocks.117 if (B.isZeroFill())118 return make_error<JITLinkError>("Unexpected zero-fill block in " +119 EHFrameSectionName + " section");120 121 if (B.getSize() == 0) {122 LLVM_DEBUG(dbgs() << " Block is empty. Skipping.\n");123 return Error::success();124 }125 126 // Find the offsets of any existing edges from this block.127 BlockEdgesInfo BlockEdges;128 for (auto &E : B.edges())129 if (E.isRelocation()) {130 // Check if we already saw more than one relocation at this offset.131 if (BlockEdges.Multiple.contains(E.getOffset()))132 continue;133 134 // Otherwise check if we previously had exactly one relocation at this135 // offset. If so, we now have a second one and move it from the TargetMap136 // into the Multiple set.137 auto [It, Inserted] = BlockEdges.TargetMap.try_emplace(E.getOffset(), E);138 if (!Inserted) {139 BlockEdges.TargetMap.erase(It);140 BlockEdges.Multiple.insert(E.getOffset());141 }142 }143 144 BinaryStreamReader BlockReader(145 StringRef(B.getContent().data(), B.getContent().size()),146 PC.G.getEndianness());147 148 // Get the record length.149 Expected<size_t> RecordRemaining = readCFIRecordLength(B, BlockReader);150 if (!RecordRemaining)151 return RecordRemaining.takeError();152 153 // We expect DWARFRecordSectionSplitter to split each CFI record into its own154 // block.155 if (BlockReader.bytesRemaining() != *RecordRemaining)156 return make_error<JITLinkError>("Incomplete CFI record at " +157 formatv("{0:x16}", B.getAddress()));158 159 // Read the CIE delta for this record.160 uint64_t CIEDeltaFieldOffset = BlockReader.getOffset();161 uint32_t CIEDelta;162 if (auto Err = BlockReader.readInteger(CIEDelta))163 return Err;164 165 if (CIEDelta == 0) {166 if (auto Err = processCIE(PC, B, CIEDeltaFieldOffset, BlockEdges))167 return Err;168 } else {169 if (auto Err = processFDE(PC, B, CIEDeltaFieldOffset, CIEDelta, BlockEdges))170 return Err;171 }172 173 return Error::success();174}175 176Error EHFrameEdgeFixer::processCIE(ParseContext &PC, Block &B,177 size_t CIEDeltaFieldOffset,178 const BlockEdgesInfo &BlockEdges) {179 180 LLVM_DEBUG(dbgs() << " Record is CIE\n");181 182 BinaryStreamReader RecordReader(183 StringRef(B.getContent().data(), B.getContent().size()),184 PC.G.getEndianness());185 186 // Skip past the CIE delta field: we've already processed this far.187 RecordReader.setOffset(CIEDeltaFieldOffset + 4);188 189 auto &CIESymbol = PC.G.addAnonymousSymbol(B, 0, B.getSize(), false, false);190 CIEInformation CIEInfo(CIESymbol);191 192 uint8_t Version = 0;193 if (auto Err = RecordReader.readInteger(Version))194 return Err;195 196 if (Version != 0x01)197 return make_error<JITLinkError>("Bad CIE version " + Twine(Version) +198 " (should be 0x01) in eh-frame");199 200 auto AugInfo = parseAugmentationString(RecordReader);201 if (!AugInfo)202 return AugInfo.takeError();203 204 // Skip the EH Data field if present.205 if (AugInfo->EHDataFieldPresent)206 if (auto Err = RecordReader.skip(PC.G.getPointerSize()))207 return Err;208 209 // Read and validate the code alignment factor.210 {211 uint64_t CodeAlignmentFactor = 0;212 if (auto Err = RecordReader.readULEB128(CodeAlignmentFactor))213 return Err;214 }215 216 // Read and validate the data alignment factor.217 {218 int64_t DataAlignmentFactor = 0;219 if (auto Err = RecordReader.readSLEB128(DataAlignmentFactor))220 return Err;221 }222 223 // Skip the return address register field.224 if (auto Err = RecordReader.skip(1))225 return Err;226 227 if (AugInfo->AugmentationDataPresent) {228 229 CIEInfo.AugmentationDataPresent = true;230 231 uint64_t AugmentationDataLength = 0;232 if (auto Err = RecordReader.readULEB128(AugmentationDataLength))233 return Err;234 235 uint32_t AugmentationDataStartOffset = RecordReader.getOffset();236 237 uint8_t *NextField = &AugInfo->Fields[0];238 while (uint8_t Field = *NextField++) {239 switch (Field) {240 case 'L':241 CIEInfo.LSDAPresent = true;242 if (auto PE = readPointerEncoding(RecordReader, B, "LSDA"))243 CIEInfo.LSDAEncoding = *PE;244 else245 return PE.takeError();246 break;247 case 'P': {248 auto PersonalityPointerEncoding =249 readPointerEncoding(RecordReader, B, "personality");250 if (!PersonalityPointerEncoding)251 return PersonalityPointerEncoding.takeError();252 if (auto Err =253 getOrCreateEncodedPointerEdge(254 PC, BlockEdges, *PersonalityPointerEncoding, RecordReader,255 B, RecordReader.getOffset(), "personality")256 .takeError())257 return Err;258 break;259 }260 case 'R':261 if (auto PE = readPointerEncoding(RecordReader, B, "address")) {262 CIEInfo.AddressEncoding = *PE;263 if (CIEInfo.AddressEncoding == dwarf::DW_EH_PE_omit)264 return make_error<JITLinkError>(265 "Invalid address encoding DW_EH_PE_omit in CIE at " +266 formatv("{0:x}", B.getAddress().getValue()));267 } else268 return PE.takeError();269 break;270 default:271 llvm_unreachable("Invalid augmentation string field");272 }273 }274 275 if (RecordReader.getOffset() - AugmentationDataStartOffset >276 AugmentationDataLength)277 return make_error<JITLinkError>("Read past the end of the augmentation "278 "data while parsing fields");279 }280 281 assert(!PC.CIEInfos.count(CIESymbol.getAddress()) &&282 "Multiple CIEs recorded at the same address?");283 PC.CIEInfos[CIESymbol.getAddress()] = std::move(CIEInfo);284 285 return Error::success();286}287 288Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,289 size_t CIEDeltaFieldOffset,290 uint32_t CIEDelta,291 const BlockEdgesInfo &BlockEdges) {292 LLVM_DEBUG(dbgs() << " Record is FDE\n");293 294 orc::ExecutorAddr RecordAddress = B.getAddress();295 296 BinaryStreamReader RecordReader(297 StringRef(B.getContent().data(), B.getContent().size()),298 PC.G.getEndianness());299 300 // Skip past the CIE delta field: we've already read this far.301 RecordReader.setOffset(CIEDeltaFieldOffset + 4);302 303 auto &FDESymbol = PC.G.addAnonymousSymbol(B, 0, B.getSize(), false, false);304 305 CIEInformation *CIEInfo = nullptr;306 307 {308 // Process the CIE pointer field.309 if (BlockEdges.Multiple.contains(CIEDeltaFieldOffset))310 return make_error<JITLinkError>(311 "CIE pointer field already has multiple edges at " +312 formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset));313 314 auto CIEEdgeItr = BlockEdges.TargetMap.find(CIEDeltaFieldOffset);315 316 orc::ExecutorAddr CIEAddress =317 RecordAddress + orc::ExecutorAddrDiff(CIEDeltaFieldOffset) -318 orc::ExecutorAddrDiff(CIEDelta);319 if (CIEEdgeItr == BlockEdges.TargetMap.end()) {320 LLVM_DEBUG({321 dbgs() << " Adding edge at "322 << (RecordAddress + CIEDeltaFieldOffset)323 << " to CIE at: " << CIEAddress << "\n";324 });325 if (auto CIEInfoOrErr = PC.findCIEInfo(CIEAddress))326 CIEInfo = *CIEInfoOrErr;327 else328 return CIEInfoOrErr.takeError();329 assert(CIEInfo->CIESymbol && "CIEInfo has no CIE symbol set");330 B.addEdge(NegDelta32, CIEDeltaFieldOffset, *CIEInfo->CIESymbol, 0);331 } else {332 LLVM_DEBUG({333 dbgs() << " Already has edge at "334 << (RecordAddress + CIEDeltaFieldOffset) << " to CIE at "335 << CIEAddress << "\n";336 });337 auto &EI = CIEEdgeItr->second;338 if (EI.Addend)339 return make_error<JITLinkError>(340 "CIE edge at " +341 formatv("{0:x16}", RecordAddress + CIEDeltaFieldOffset) +342 " has non-zero addend");343 if (auto CIEInfoOrErr = PC.findCIEInfo(EI.Target->getAddress()))344 CIEInfo = *CIEInfoOrErr;345 else346 return CIEInfoOrErr.takeError();347 }348 }349 350 // Process the PC-Begin field.351 LLVM_DEBUG({352 dbgs() << " Processing PC-begin at "353 << (RecordAddress + RecordReader.getOffset()) << "\n";354 });355 if (auto PCBegin = getOrCreateEncodedPointerEdge(356 PC, BlockEdges, CIEInfo->AddressEncoding, RecordReader, B,357 RecordReader.getOffset(), "PC begin")) {358 assert(*PCBegin && "PC-begin symbol not set");359 if ((*PCBegin)->isDefined()) {360 // Add a keep-alive edge from the FDE target to the FDE to ensure that the361 // FDE is kept alive if its target is.362 LLVM_DEBUG({363 dbgs() << " Adding keep-alive edge from target at "364 << (*PCBegin)->getBlock().getAddress() << " to FDE at "365 << RecordAddress << "\n";366 });367 (*PCBegin)->getBlock().addEdge(Edge::KeepAlive, 0, FDESymbol, 0);368 } else {369 LLVM_DEBUG({370 dbgs() << " WARNING: Not adding keep-alive edge to FDE at "371 << RecordAddress << ", which points to "372 << ((*PCBegin)->isExternal() ? "external" : "absolute")373 << " symbol \"" << (*PCBegin)->getName()374 << "\" -- FDE must be kept alive manually or it will be "375 << "dead stripped.\n";376 });377 }378 } else379 return PCBegin.takeError();380 381 // Skip over the PC range size field.382 if (auto Err = skipEncodedPointer(CIEInfo->AddressEncoding, RecordReader))383 return Err;384 385 if (CIEInfo->AugmentationDataPresent) {386 uint64_t AugmentationDataSize;387 if (auto Err = RecordReader.readULEB128(AugmentationDataSize))388 return Err;389 390 if (CIEInfo->LSDAPresent)391 if (auto Err = getOrCreateEncodedPointerEdge(392 PC, BlockEdges, CIEInfo->LSDAEncoding, RecordReader, B,393 RecordReader.getOffset(), "LSDA")394 .takeError())395 return Err;396 } else {397 LLVM_DEBUG(dbgs() << " Record does not have LSDA field.\n");398 }399 400 return Error::success();401}402 403Expected<EHFrameEdgeFixer::AugmentationInfo>404EHFrameEdgeFixer::parseAugmentationString(BinaryStreamReader &RecordReader) {405 AugmentationInfo AugInfo;406 uint8_t NextChar;407 uint8_t *NextField = &AugInfo.Fields[0];408 409 if (auto Err = RecordReader.readInteger(NextChar))410 return std::move(Err);411 412 while (NextChar != 0) {413 switch (NextChar) {414 case 'z':415 AugInfo.AugmentationDataPresent = true;416 break;417 case 'e':418 if (auto Err = RecordReader.readInteger(NextChar))419 return std::move(Err);420 if (NextChar != 'h')421 return make_error<JITLinkError>("Unrecognized substring e" +422 Twine(NextChar) +423 " in augmentation string");424 AugInfo.EHDataFieldPresent = true;425 break;426 case 'L':427 case 'P':428 case 'R':429 *NextField++ = NextChar;430 break;431 default:432 return make_error<JITLinkError>("Unrecognized character " +433 Twine(NextChar) +434 " in augmentation string");435 }436 437 if (auto Err = RecordReader.readInteger(NextChar))438 return std::move(Err);439 }440 441 return std::move(AugInfo);442}443 444Expected<uint8_t> EHFrameEdgeFixer::readPointerEncoding(BinaryStreamReader &R,445 Block &InBlock,446 const char *FieldName) {447 using namespace dwarf;448 449 uint8_t PointerEncoding;450 if (auto Err = R.readInteger(PointerEncoding))451 return std::move(Err);452 453 bool Supported = true;454 switch (PointerEncoding & 0xf) {455 case DW_EH_PE_uleb128:456 case DW_EH_PE_udata2:457 case DW_EH_PE_sleb128:458 case DW_EH_PE_sdata2:459 Supported = false;460 break;461 }462 if (Supported) {463 switch (PointerEncoding & 0x70) {464 case DW_EH_PE_textrel:465 case DW_EH_PE_datarel:466 case DW_EH_PE_funcrel:467 case DW_EH_PE_aligned:468 Supported = false;469 break;470 }471 }472 473 if (Supported)474 return PointerEncoding;475 476 return make_error<JITLinkError>("Unsupported pointer encoding " +477 formatv("{0:x2}", PointerEncoding) + " for " +478 FieldName + "in CFI record at " +479 formatv("{0:x16}", InBlock.getAddress()));480}481 482Error EHFrameEdgeFixer::skipEncodedPointer(uint8_t PointerEncoding,483 BinaryStreamReader &RecordReader) {484 using namespace dwarf;485 486 // Switch absptr to corresponding udata encoding.487 if ((PointerEncoding & 0xf) == DW_EH_PE_absptr)488 PointerEncoding |= (PointerSize == 8) ? DW_EH_PE_udata8 : DW_EH_PE_udata4;489 490 switch (PointerEncoding & 0xf) {491 case DW_EH_PE_udata4:492 case DW_EH_PE_sdata4:493 if (auto Err = RecordReader.skip(4))494 return Err;495 break;496 case DW_EH_PE_udata8:497 case DW_EH_PE_sdata8:498 if (auto Err = RecordReader.skip(8))499 return Err;500 break;501 default:502 llvm_unreachable("Unrecognized encoding");503 }504 return Error::success();505}506 507Expected<Symbol *> EHFrameEdgeFixer::getOrCreateEncodedPointerEdge(508 ParseContext &PC, const BlockEdgesInfo &BlockEdges, uint8_t PointerEncoding,509 BinaryStreamReader &RecordReader, Block &BlockToFix,510 size_t PointerFieldOffset, const char *FieldName) {511 using namespace dwarf;512 513 if (PointerEncoding == DW_EH_PE_omit)514 return nullptr;515 516 // If there's already an edge here then just skip the encoded pointer and517 // return the edge's target.518 {519 auto EdgeI = BlockEdges.TargetMap.find(PointerFieldOffset);520 if (EdgeI != BlockEdges.TargetMap.end()) {521 LLVM_DEBUG({522 dbgs() << " Existing edge at "523 << (BlockToFix.getAddress() + PointerFieldOffset) << " to "524 << FieldName << " at " << EdgeI->second.Target->getAddress();525 if (EdgeI->second.Target->hasName())526 dbgs() << " (" << EdgeI->second.Target->getName() << ")";527 dbgs() << "\n";528 });529 if (auto Err = skipEncodedPointer(PointerEncoding, RecordReader))530 return std::move(Err);531 return EdgeI->second.Target;532 }533 534 if (BlockEdges.Multiple.contains(PointerFieldOffset))535 return make_error<JITLinkError>("Multiple relocations at offset " +536 formatv("{0:x16}", PointerFieldOffset));537 }538 539 // Switch absptr to corresponding udata encoding.540 if ((PointerEncoding & 0xf) == DW_EH_PE_absptr)541 PointerEncoding |= (PointerSize == 8) ? DW_EH_PE_udata8 : DW_EH_PE_udata4;542 543 // We need to create an edge. Start by reading the field value.544 uint64_t FieldValue;545 bool Is64Bit = false;546 switch (PointerEncoding & 0xf) {547 case DW_EH_PE_udata4: {548 uint32_t Val;549 if (auto Err = RecordReader.readInteger(Val))550 return std::move(Err);551 FieldValue = Val;552 break;553 }554 case DW_EH_PE_sdata4: {555 uint32_t Val;556 if (auto Err = RecordReader.readInteger(Val))557 return std::move(Err);558 FieldValue = Val;559 break;560 }561 case DW_EH_PE_udata8:562 case DW_EH_PE_sdata8:563 Is64Bit = true;564 if (auto Err = RecordReader.readInteger(FieldValue))565 return std::move(Err);566 break;567 default:568 llvm_unreachable("Unsupported encoding");569 }570 571 // Find the edge target and edge kind to use.572 orc::ExecutorAddr Target;573 Edge::Kind PtrEdgeKind = Edge::Invalid;574 if ((PointerEncoding & 0x70) == DW_EH_PE_pcrel) {575 Target = BlockToFix.getAddress() + PointerFieldOffset;576 PtrEdgeKind = Is64Bit ? Delta64 : Delta32;577 } else578 PtrEdgeKind = Is64Bit ? Pointer64 : Pointer32;579 Target += FieldValue;580 581 // Find or create a symbol to point the edge at.582 auto TargetSym = getOrCreateSymbol(PC, Target);583 if (!TargetSym)584 return TargetSym.takeError();585 BlockToFix.addEdge(PtrEdgeKind, PointerFieldOffset, *TargetSym, 0);586 587 LLVM_DEBUG({588 dbgs() << " Adding edge at "589 << (BlockToFix.getAddress() + PointerFieldOffset) << " to "590 << FieldName << " at " << TargetSym->getAddress();591 if (TargetSym->hasName())592 dbgs() << " (" << TargetSym->getName() << ")";593 dbgs() << "\n";594 });595 596 return &*TargetSym;597}598 599Expected<Symbol &> EHFrameEdgeFixer::getOrCreateSymbol(ParseContext &PC,600 orc::ExecutorAddr Addr) {601 // See whether we have a canonical symbol for the given address already.602 auto CanonicalSymI = PC.AddrToSym.find(Addr);603 if (CanonicalSymI != PC.AddrToSym.end())604 return *CanonicalSymI->second;605 606 // Otherwise search for a block covering the address and create a new symbol.607 auto *B = PC.AddrToBlock.getBlockCovering(Addr);608 if (!B)609 return make_error<JITLinkError>("No symbol or block covering address " +610 formatv("{0:x16}", Addr));611 612 auto &S =613 PC.G.addAnonymousSymbol(*B, Addr - B->getAddress(), 0, false, false);614 PC.AddrToSym[S.getAddress()] = &S;615 return S;616}617 618char EHFrameNullTerminator::NullTerminatorBlockContent[4] = {0, 0, 0, 0};619 620EHFrameNullTerminator::EHFrameNullTerminator(StringRef EHFrameSectionName)621 : EHFrameSectionName(EHFrameSectionName) {}622 623Error EHFrameNullTerminator::operator()(LinkGraph &G) {624 auto *EHFrame = G.findSectionByName(EHFrameSectionName);625 626 if (!EHFrame)627 return Error::success();628 629 LLVM_DEBUG({630 dbgs() << "EHFrameNullTerminator adding null terminator to "631 << EHFrameSectionName << "\n";632 });633 634 auto &NullTerminatorBlock =635 G.createContentBlock(*EHFrame, NullTerminatorBlockContent,636 orc::ExecutorAddr(~uint64_t(4)), 1, 0);637 G.addAnonymousSymbol(NullTerminatorBlock, 0, 4, false, true);638 return Error::success();639}640 641EHFrameCFIBlockInspector EHFrameCFIBlockInspector::FromEdgeScan(Block &B) {642 if (B.edges_empty())643 return EHFrameCFIBlockInspector(nullptr);644 if (B.edges_size() == 1)645 return EHFrameCFIBlockInspector(&*B.edges().begin());646 SmallVector<Edge *, 3> Es(llvm::make_pointer_range(B.edges()));647 assert(Es.size() >= 2 && Es.size() <= 3 && "Unexpected number of edges");648 llvm::sort(Es, [](const Edge *LHS, const Edge *RHS) {649 return LHS->getOffset() < RHS->getOffset();650 });651 return EHFrameCFIBlockInspector(*Es[0], *Es[1],652 Es.size() == 3 ? Es[2] : nullptr);653 return EHFrameCFIBlockInspector(nullptr);654}655 656EHFrameCFIBlockInspector::EHFrameCFIBlockInspector(Edge *PersonalityEdge)657 : PersonalityEdge(PersonalityEdge) {}658 659EHFrameCFIBlockInspector::EHFrameCFIBlockInspector(Edge &CIEEdge,660 Edge &PCBeginEdge,661 Edge *LSDAEdge)662 : CIEEdge(&CIEEdge), PCBeginEdge(&PCBeginEdge), LSDAEdge(LSDAEdge) {}663 664Section *getEHFrameSection(LinkGraph &G) {665 const char *EHFrameSectionName = nullptr;666 switch (G.getTargetTriple().getObjectFormat()) {667 case Triple::MachO:668 EHFrameSectionName = "__TEXT,__eh_frame";669 break;670 case Triple::ELF:671 EHFrameSectionName = ".eh_frame";672 break;673 default:674 return nullptr;675 }676 677 if (auto *S = G.findSectionByName(EHFrameSectionName))678 if (!S->empty())679 return S;680 681 return nullptr;682}683 684} // end namespace jitlink685} // end namespace llvm686