15ffd83dbSDimitry Andric //===---- ELF_x86_64.cpp -JIT linker implementation for ELF/x86-64 ----===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric // 95ffd83dbSDimitry Andric // ELF/x86-64 jit-link implementation. 105ffd83dbSDimitry Andric // 115ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 125ffd83dbSDimitry Andric 135ffd83dbSDimitry Andric #include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h" 1481ad6265SDimitry Andric #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h" 155ffd83dbSDimitry Andric #include "llvm/ExecutionEngine/JITLink/JITLink.h" 16349cc55cSDimitry Andric #include "llvm/ExecutionEngine/JITLink/TableManager.h" 17fe6060f1SDimitry Andric #include "llvm/ExecutionEngine/JITLink/x86_64.h" 185ffd83dbSDimitry Andric #include "llvm/Object/ELFObjectFile.h" 19e8d8bef9SDimitry Andric 20fe6060f1SDimitry Andric #include "DefineExternalSectionStartAndEndSymbols.h" 21e8d8bef9SDimitry Andric #include "EHFrameSupportImpl.h" 22fe6060f1SDimitry Andric #include "ELFLinkGraphBuilder.h" 23e8d8bef9SDimitry Andric #include "JITLinkGeneric.h" 245ffd83dbSDimitry Andric 255ffd83dbSDimitry Andric #define DEBUG_TYPE "jitlink" 265ffd83dbSDimitry Andric 275ffd83dbSDimitry Andric using namespace llvm; 285ffd83dbSDimitry Andric using namespace llvm::jitlink; 29e8d8bef9SDimitry Andric 30e8d8bef9SDimitry Andric namespace { 31e8d8bef9SDimitry Andric 32fe6060f1SDimitry Andric constexpr StringRef ELFGOTSymbolName = "_GLOBAL_OFFSET_TABLE_"; 33349cc55cSDimitry Andric constexpr StringRef ELFTLSInfoSectionName = "$__TLSINFO"; 34fe6060f1SDimitry Andric 35349cc55cSDimitry Andric class TLSInfoTableManager_ELF_x86_64 36349cc55cSDimitry Andric : public TableManager<TLSInfoTableManager_ELF_x86_64> { 37e8d8bef9SDimitry Andric public: 38349cc55cSDimitry Andric static const uint8_t TLSInfoEntryContent[16]; 39e8d8bef9SDimitry Andric 40349cc55cSDimitry Andric static StringRef getSectionName() { return ELFTLSInfoSectionName; } 41e8d8bef9SDimitry Andric 42349cc55cSDimitry Andric bool visitEdge(LinkGraph &G, Block *B, Edge &E) { 43349cc55cSDimitry Andric if (E.getKind() == x86_64::RequestTLSDescInGOTAndTransformToDelta32) { 44349cc55cSDimitry Andric LLVM_DEBUG({ 45349cc55cSDimitry Andric dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at " 46349cc55cSDimitry Andric << formatv("{0:x}", B->getFixupAddress(E)) << " (" 47349cc55cSDimitry Andric << formatv("{0:x}", B->getAddress()) << " + " 48349cc55cSDimitry Andric << formatv("{0:x}", E.getOffset()) << ")\n"; 49349cc55cSDimitry Andric }); 50349cc55cSDimitry Andric E.setKind(x86_64::Delta32); 51349cc55cSDimitry Andric E.setTarget(getEntryForTarget(G, E.getTarget())); 52349cc55cSDimitry Andric return true; 53349cc55cSDimitry Andric } 54fe6060f1SDimitry Andric return false; 55fe6060f1SDimitry Andric } 56fe6060f1SDimitry Andric 57349cc55cSDimitry Andric Symbol &createEntry(LinkGraph &G, Symbol &Target) { 58349cc55cSDimitry Andric // the TLS Info entry's key value will be written by the fixTLVSectionByName 59349cc55cSDimitry Andric // pass, so create mutable content. 60349cc55cSDimitry Andric auto &TLSInfoEntry = G.createMutableContentBlock( 6104eeddc0SDimitry Andric getTLSInfoSection(G), G.allocateContent(getTLSInfoEntryContent()), 6204eeddc0SDimitry Andric orc::ExecutorAddr(), 8, 0); 63349cc55cSDimitry Andric TLSInfoEntry.addEdge(x86_64::Pointer64, 8, Target, 0); 64349cc55cSDimitry Andric return G.addAnonymousSymbol(TLSInfoEntry, 0, 16, false, false); 65e8d8bef9SDimitry Andric } 66e8d8bef9SDimitry Andric 67e8d8bef9SDimitry Andric private: 68349cc55cSDimitry Andric Section &getTLSInfoSection(LinkGraph &G) { 69349cc55cSDimitry Andric if (!TLSInfoTable) 70bdd1243dSDimitry Andric TLSInfoTable = 71bdd1243dSDimitry Andric &G.createSection(ELFTLSInfoSectionName, orc::MemProt::Read); 72349cc55cSDimitry Andric return *TLSInfoTable; 73e8d8bef9SDimitry Andric } 74e8d8bef9SDimitry Andric 75349cc55cSDimitry Andric ArrayRef<char> getTLSInfoEntryContent() const { 76349cc55cSDimitry Andric return {reinterpret_cast<const char *>(TLSInfoEntryContent), 77349cc55cSDimitry Andric sizeof(TLSInfoEntryContent)}; 78e8d8bef9SDimitry Andric } 79e8d8bef9SDimitry Andric 80349cc55cSDimitry Andric Section *TLSInfoTable = nullptr; 81e8d8bef9SDimitry Andric }; 82e8d8bef9SDimitry Andric 83349cc55cSDimitry Andric const uint8_t TLSInfoTableManager_ELF_x86_64::TLSInfoEntryContent[16] = { 84349cc55cSDimitry Andric 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*pthread key */ 85349cc55cSDimitry Andric 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /*data address*/ 86349cc55cSDimitry Andric }; 87349cc55cSDimitry Andric 88349cc55cSDimitry Andric Error buildTables_ELF_x86_64(LinkGraph &G) { 89349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n"); 90349cc55cSDimitry Andric 91349cc55cSDimitry Andric x86_64::GOTTableManager GOT; 92349cc55cSDimitry Andric x86_64::PLTTableManager PLT(GOT); 93349cc55cSDimitry Andric TLSInfoTableManager_ELF_x86_64 TLSInfo; 94349cc55cSDimitry Andric visitExistingEdges(G, GOT, PLT, TLSInfo); 95349cc55cSDimitry Andric return Error::success(); 96349cc55cSDimitry Andric } 97e8d8bef9SDimitry Andric } // namespace 98e8d8bef9SDimitry Andric 995ffd83dbSDimitry Andric namespace llvm { 1005ffd83dbSDimitry Andric namespace jitlink { 1015ffd83dbSDimitry Andric 102fe6060f1SDimitry Andric class ELFLinkGraphBuilder_x86_64 : public ELFLinkGraphBuilder<object::ELF64LE> { 1035ffd83dbSDimitry Andric private: 104349cc55cSDimitry Andric using ELFT = object::ELF64LE; 1055ffd83dbSDimitry Andric 106fe6060f1SDimitry Andric Error addRelocations() override { 107349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << "Processing relocations:\n"); 1085ffd83dbSDimitry Andric 109349cc55cSDimitry Andric using Base = ELFLinkGraphBuilder<ELFT>; 110349cc55cSDimitry Andric using Self = ELFLinkGraphBuilder_x86_64; 111349cc55cSDimitry Andric for (const auto &RelSect : Base::Sections) { 112349cc55cSDimitry Andric // Validate the section to read relocation entries from. 113349cc55cSDimitry Andric if (RelSect.sh_type == ELF::SHT_REL) 114349cc55cSDimitry Andric return make_error<StringError>( 115349cc55cSDimitry Andric "No SHT_REL in valid x64 ELF object files", 116349cc55cSDimitry Andric inconvertibleErrorCode()); 117e8d8bef9SDimitry Andric 118bdd1243dSDimitry Andric if (Error Err = Base::forEachRelaRelocation(RelSect, this, 119349cc55cSDimitry Andric &Self::addSingleRelocation)) 120349cc55cSDimitry Andric return Err; 121e8d8bef9SDimitry Andric } 1225ffd83dbSDimitry Andric 123349cc55cSDimitry Andric return Error::success(); 124349cc55cSDimitry Andric } 1255ffd83dbSDimitry Andric 126349cc55cSDimitry Andric Error addSingleRelocation(const typename ELFT::Rela &Rel, 127349cc55cSDimitry Andric const typename ELFT::Shdr &FixupSection, 12804eeddc0SDimitry Andric Block &BlockToFix) { 129349cc55cSDimitry Andric using Base = ELFLinkGraphBuilder<ELFT>; 130349cc55cSDimitry Andric 13106c3fb27SDimitry Andric auto ELFReloc = Rel.getType(false); 13206c3fb27SDimitry Andric 13306c3fb27SDimitry Andric // R_X86_64_NONE is a no-op. 13406c3fb27SDimitry Andric if (LLVM_UNLIKELY(ELFReloc == ELF::R_X86_64_NONE)) 13506c3fb27SDimitry Andric return Error::success(); 13606c3fb27SDimitry Andric 137349cc55cSDimitry Andric uint32_t SymbolIndex = Rel.getSymbol(false); 138349cc55cSDimitry Andric auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec); 139349cc55cSDimitry Andric if (!ObjSymbol) 140349cc55cSDimitry Andric return ObjSymbol.takeError(); 141349cc55cSDimitry Andric 142349cc55cSDimitry Andric Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex); 143349cc55cSDimitry Andric if (!GraphSymbol) 144349cc55cSDimitry Andric return make_error<StringError>( 145349cc55cSDimitry Andric formatv("Could not find symbol at given index, did you add it to " 146349cc55cSDimitry Andric "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}", 147349cc55cSDimitry Andric SymbolIndex, (*ObjSymbol)->st_shndx, 148349cc55cSDimitry Andric Base::GraphSymbols.size()), 149349cc55cSDimitry Andric inconvertibleErrorCode()); 150349cc55cSDimitry Andric 151349cc55cSDimitry Andric // Validate the relocation kind. 152349cc55cSDimitry Andric int64_t Addend = Rel.r_addend; 153349cc55cSDimitry Andric Edge::Kind Kind = Edge::Invalid; 15406c3fb27SDimitry Andric 15506c3fb27SDimitry Andric switch (ELFReloc) { 156*0fca6ea1SDimitry Andric case ELF::R_X86_64_PC8: 157*0fca6ea1SDimitry Andric Kind = x86_64::Delta8; 158*0fca6ea1SDimitry Andric break; 15906c3fb27SDimitry Andric case ELF::R_X86_64_PC32: 16006c3fb27SDimitry Andric case ELF::R_X86_64_GOTPC32: 161349cc55cSDimitry Andric Kind = x86_64::Delta32; 162349cc55cSDimitry Andric break; 16306c3fb27SDimitry Andric case ELF::R_X86_64_PC64: 16406c3fb27SDimitry Andric case ELF::R_X86_64_GOTPC64: 165349cc55cSDimitry Andric Kind = x86_64::Delta64; 166349cc55cSDimitry Andric break; 16706c3fb27SDimitry Andric case ELF::R_X86_64_32: 16806c3fb27SDimitry Andric Kind = x86_64::Pointer32; 16906c3fb27SDimitry Andric break; 17006c3fb27SDimitry Andric case ELF::R_X86_64_16: 17106c3fb27SDimitry Andric Kind = x86_64::Pointer16; 17206c3fb27SDimitry Andric break; 17306c3fb27SDimitry Andric case ELF::R_X86_64_8: 17406c3fb27SDimitry Andric Kind = x86_64::Pointer8; 17506c3fb27SDimitry Andric break; 17606c3fb27SDimitry Andric case ELF::R_X86_64_32S: 177349cc55cSDimitry Andric Kind = x86_64::Pointer32Signed; 178349cc55cSDimitry Andric break; 17906c3fb27SDimitry Andric case ELF::R_X86_64_64: 180349cc55cSDimitry Andric Kind = x86_64::Pointer64; 181349cc55cSDimitry Andric break; 18206c3fb27SDimitry Andric case ELF::R_X86_64_GOTPCREL: 183349cc55cSDimitry Andric Kind = x86_64::RequestGOTAndTransformToDelta32; 184349cc55cSDimitry Andric break; 18506c3fb27SDimitry Andric case ELF::R_X86_64_REX_GOTPCRELX: 186349cc55cSDimitry Andric Kind = x86_64::RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable; 187349cc55cSDimitry Andric Addend = 0; 188349cc55cSDimitry Andric break; 18906c3fb27SDimitry Andric case ELF::R_X86_64_TLSGD: 190349cc55cSDimitry Andric Kind = x86_64::RequestTLSDescInGOTAndTransformToDelta32; 191349cc55cSDimitry Andric break; 19206c3fb27SDimitry Andric case ELF::R_X86_64_GOTPCRELX: 193349cc55cSDimitry Andric Kind = x86_64::RequestGOTAndTransformToPCRel32GOTLoadRelaxable; 194349cc55cSDimitry Andric Addend = 0; 195349cc55cSDimitry Andric break; 19606c3fb27SDimitry Andric case ELF::R_X86_64_GOTPCREL64: 197349cc55cSDimitry Andric Kind = x86_64::RequestGOTAndTransformToDelta64; 198349cc55cSDimitry Andric break; 19906c3fb27SDimitry Andric case ELF::R_X86_64_GOT64: 200349cc55cSDimitry Andric Kind = x86_64::RequestGOTAndTransformToDelta64FromGOT; 201349cc55cSDimitry Andric break; 20206c3fb27SDimitry Andric case ELF::R_X86_64_GOTOFF64: 203349cc55cSDimitry Andric Kind = x86_64::Delta64FromGOT; 204349cc55cSDimitry Andric break; 20506c3fb27SDimitry Andric case ELF::R_X86_64_PLT32: 206349cc55cSDimitry Andric Kind = x86_64::BranchPCRel32; 2070eae32dcSDimitry Andric // BranchPCRel32 implicitly handles the '-4' PC adjustment, so we have to 2080eae32dcSDimitry Andric // adjust the addend by '+4' to compensate. 2090eae32dcSDimitry Andric Addend += 4; 210349cc55cSDimitry Andric break; 21106c3fb27SDimitry Andric default: 21206c3fb27SDimitry Andric return make_error<JITLinkError>( 21306c3fb27SDimitry Andric "In " + G->getName() + ": Unsupported x86-64 relocation type " + 21406c3fb27SDimitry Andric object::getELFRelocationTypeName(ELF::EM_X86_64, ELFReloc)); 215349cc55cSDimitry Andric } 216349cc55cSDimitry Andric 21704eeddc0SDimitry Andric auto FixupAddress = orc::ExecutorAddr(FixupSection.sh_addr) + Rel.r_offset; 21804eeddc0SDimitry Andric Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress(); 219349cc55cSDimitry Andric Edge GE(Kind, Offset, *GraphSymbol, Addend); 2205ffd83dbSDimitry Andric LLVM_DEBUG({ 221349cc55cSDimitry Andric dbgs() << " "; 22204eeddc0SDimitry Andric printEdge(dbgs(), BlockToFix, GE, x86_64::getEdgeKindName(Kind)); 2235ffd83dbSDimitry Andric dbgs() << "\n"; 2245ffd83dbSDimitry Andric }); 225349cc55cSDimitry Andric 22604eeddc0SDimitry Andric BlockToFix.addEdge(std::move(GE)); 2275ffd83dbSDimitry Andric return Error::success(); 2285ffd83dbSDimitry Andric } 2295ffd83dbSDimitry Andric 2305ffd83dbSDimitry Andric public: 231e8d8bef9SDimitry Andric ELFLinkGraphBuilder_x86_64(StringRef FileName, 23206c3fb27SDimitry Andric const object::ELFFile<object::ELF64LE> &Obj, 23306c3fb27SDimitry Andric SubtargetFeatures Features) 23406c3fb27SDimitry Andric : ELFLinkGraphBuilder(Obj, Triple("x86_64-unknown-linux"), 23506c3fb27SDimitry Andric std::move(Features), FileName, 236349cc55cSDimitry Andric x86_64::getEdgeKindName) {} 2375ffd83dbSDimitry Andric }; 2385ffd83dbSDimitry Andric 2395ffd83dbSDimitry Andric class ELFJITLinker_x86_64 : public JITLinker<ELFJITLinker_x86_64> { 2405ffd83dbSDimitry Andric friend class JITLinker<ELFJITLinker_x86_64>; 2415ffd83dbSDimitry Andric 2425ffd83dbSDimitry Andric public: 2435ffd83dbSDimitry Andric ELFJITLinker_x86_64(std::unique_ptr<JITLinkContext> Ctx, 244e8d8bef9SDimitry Andric std::unique_ptr<LinkGraph> G, 2455ffd83dbSDimitry Andric PassConfiguration PassConfig) 246fe6060f1SDimitry Andric : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) { 2475f757f3fSDimitry Andric 2485f757f3fSDimitry Andric if (shouldAddDefaultTargetPasses(getGraph().getTargetTriple())) 249fe6060f1SDimitry Andric getPassConfig().PostAllocationPasses.push_back( 250fe6060f1SDimitry Andric [this](LinkGraph &G) { return getOrCreateGOTSymbol(G); }); 251fe6060f1SDimitry Andric } 2525ffd83dbSDimitry Andric 2535ffd83dbSDimitry Andric private: 254fe6060f1SDimitry Andric Symbol *GOTSymbol = nullptr; 255fe6060f1SDimitry Andric 256fe6060f1SDimitry Andric Error getOrCreateGOTSymbol(LinkGraph &G) { 257fe6060f1SDimitry Andric auto DefineExternalGOTSymbolIfPresent = 258fe6060f1SDimitry Andric createDefineExternalSectionStartAndEndSymbolsPass( 259fe6060f1SDimitry Andric [&](LinkGraph &LG, Symbol &Sym) -> SectionRangeSymbolDesc { 260fe6060f1SDimitry Andric if (Sym.getName() == ELFGOTSymbolName) 261349cc55cSDimitry Andric if (auto *GOTSection = G.findSectionByName( 262349cc55cSDimitry Andric x86_64::GOTTableManager::getSectionName())) { 263fe6060f1SDimitry Andric GOTSymbol = &Sym; 264fe6060f1SDimitry Andric return {*GOTSection, true}; 265fe6060f1SDimitry Andric } 266fe6060f1SDimitry Andric return {}; 267fe6060f1SDimitry Andric }); 268fe6060f1SDimitry Andric 269fe6060f1SDimitry Andric // Try to attach _GLOBAL_OFFSET_TABLE_ to the GOT if it's defined as an 270fe6060f1SDimitry Andric // external. 271fe6060f1SDimitry Andric if (auto Err = DefineExternalGOTSymbolIfPresent(G)) 272fe6060f1SDimitry Andric return Err; 273fe6060f1SDimitry Andric 274fe6060f1SDimitry Andric // If we succeeded then we're done. 275fe6060f1SDimitry Andric if (GOTSymbol) 276fe6060f1SDimitry Andric return Error::success(); 277fe6060f1SDimitry Andric 278fe6060f1SDimitry Andric // Otherwise look for a GOT section: If it already has a start symbol we'll 279fe6060f1SDimitry Andric // record it, otherwise we'll create our own. 280fe6060f1SDimitry Andric // If there's a GOT section but we didn't find an external GOT symbol... 281349cc55cSDimitry Andric if (auto *GOTSection = 282349cc55cSDimitry Andric G.findSectionByName(x86_64::GOTTableManager::getSectionName())) { 283fe6060f1SDimitry Andric 284fe6060f1SDimitry Andric // Check for an existing defined symbol. 285fe6060f1SDimitry Andric for (auto *Sym : GOTSection->symbols()) 286fe6060f1SDimitry Andric if (Sym->getName() == ELFGOTSymbolName) { 287fe6060f1SDimitry Andric GOTSymbol = Sym; 288fe6060f1SDimitry Andric return Error::success(); 289e8d8bef9SDimitry Andric } 2905ffd83dbSDimitry Andric 291fe6060f1SDimitry Andric // If there's no defined symbol then create one. 292fe6060f1SDimitry Andric SectionRange SR(*GOTSection); 293fe6060f1SDimitry Andric if (SR.empty()) 29404eeddc0SDimitry Andric GOTSymbol = 29504eeddc0SDimitry Andric &G.addAbsoluteSymbol(ELFGOTSymbolName, orc::ExecutorAddr(), 0, 296fe6060f1SDimitry Andric Linkage::Strong, Scope::Local, true); 297fe6060f1SDimitry Andric else 298fe6060f1SDimitry Andric GOTSymbol = 299fe6060f1SDimitry Andric &G.addDefinedSymbol(*SR.getFirstBlock(), 0, ELFGOTSymbolName, 0, 300fe6060f1SDimitry Andric Linkage::Strong, Scope::Local, false, true); 3015ffd83dbSDimitry Andric } 3025ffd83dbSDimitry Andric 30306c3fb27SDimitry Andric // If we still haven't found a GOT symbol then double check the externals. 30406c3fb27SDimitry Andric // We may have a GOT-relative reference but no GOT section, in which case 30506c3fb27SDimitry Andric // we just need to point the GOT symbol at some address in this graph. 30606c3fb27SDimitry Andric if (!GOTSymbol) { 30706c3fb27SDimitry Andric for (auto *Sym : G.external_symbols()) { 30806c3fb27SDimitry Andric if (Sym->getName() == ELFGOTSymbolName) { 30906c3fb27SDimitry Andric auto Blocks = G.blocks(); 31006c3fb27SDimitry Andric if (!Blocks.empty()) { 31106c3fb27SDimitry Andric G.makeAbsolute(*Sym, (*Blocks.begin())->getAddress()); 31206c3fb27SDimitry Andric GOTSymbol = Sym; 31306c3fb27SDimitry Andric break; 31406c3fb27SDimitry Andric } 31506c3fb27SDimitry Andric } 31606c3fb27SDimitry Andric } 31706c3fb27SDimitry Andric } 31806c3fb27SDimitry Andric 319fe6060f1SDimitry Andric return Error::success(); 320fe6060f1SDimitry Andric } 321fe6060f1SDimitry Andric 322fe6060f1SDimitry Andric Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const { 323349cc55cSDimitry Andric return x86_64::applyFixup(G, B, E, GOTSymbol); 3245ffd83dbSDimitry Andric } 3255ffd83dbSDimitry Andric }; 3265ffd83dbSDimitry Andric 327e8d8bef9SDimitry Andric Expected<std::unique_ptr<LinkGraph>> 328e8d8bef9SDimitry Andric createLinkGraphFromELFObject_x86_64(MemoryBufferRef ObjectBuffer) { 329e8d8bef9SDimitry Andric LLVM_DEBUG({ 330e8d8bef9SDimitry Andric dbgs() << "Building jitlink graph for new input " 331e8d8bef9SDimitry Andric << ObjectBuffer.getBufferIdentifier() << "...\n"; 332e8d8bef9SDimitry Andric }); 333e8d8bef9SDimitry Andric 334e8d8bef9SDimitry Andric auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer); 335e8d8bef9SDimitry Andric if (!ELFObj) 336e8d8bef9SDimitry Andric return ELFObj.takeError(); 337e8d8bef9SDimitry Andric 33806c3fb27SDimitry Andric auto Features = (*ELFObj)->getFeatures(); 33906c3fb27SDimitry Andric if (!Features) 34006c3fb27SDimitry Andric return Features.takeError(); 34106c3fb27SDimitry Andric 342e8d8bef9SDimitry Andric auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj); 343e8d8bef9SDimitry Andric return ELFLinkGraphBuilder_x86_64((*ELFObj)->getFileName(), 34406c3fb27SDimitry Andric ELFObjFile.getELFFile(), 34506c3fb27SDimitry Andric std::move(*Features)) 346e8d8bef9SDimitry Andric .buildGraph(); 347e8d8bef9SDimitry Andric } 348e8d8bef9SDimitry Andric 349e8d8bef9SDimitry Andric void link_ELF_x86_64(std::unique_ptr<LinkGraph> G, 350e8d8bef9SDimitry Andric std::unique_ptr<JITLinkContext> Ctx) { 3515ffd83dbSDimitry Andric PassConfiguration Config; 352e8d8bef9SDimitry Andric 353e8d8bef9SDimitry Andric if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) { 354e8d8bef9SDimitry Andric 35581ad6265SDimitry Andric Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame")); 35681ad6265SDimitry Andric Config.PrePrunePasses.push_back(EHFrameEdgeFixer( 35781ad6265SDimitry Andric ".eh_frame", x86_64::PointerSize, x86_64::Pointer32, x86_64::Pointer64, 35881ad6265SDimitry Andric x86_64::Delta32, x86_64::Delta64, x86_64::NegDelta32)); 359fe6060f1SDimitry Andric Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame")); 360e8d8bef9SDimitry Andric 3615ffd83dbSDimitry Andric // Construct a JITLinker and run the link function. 3625ffd83dbSDimitry Andric // Add a mark-live pass. 363e8d8bef9SDimitry Andric if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple())) 3645ffd83dbSDimitry Andric Config.PrePrunePasses.push_back(std::move(MarkLive)); 3655ffd83dbSDimitry Andric else 3665ffd83dbSDimitry Andric Config.PrePrunePasses.push_back(markAllSymbolsLive); 3675ffd83dbSDimitry Andric 368349cc55cSDimitry Andric // Add an in-place GOT/Stubs/TLSInfoEntry build pass. 369349cc55cSDimitry Andric Config.PostPrunePasses.push_back(buildTables_ELF_x86_64); 370fe6060f1SDimitry Andric 371fe6060f1SDimitry Andric // Resolve any external section start / end symbols. 372fe6060f1SDimitry Andric Config.PostAllocationPasses.push_back( 373fe6060f1SDimitry Andric createDefineExternalSectionStartAndEndSymbolsPass( 374fe6060f1SDimitry Andric identifyELFSectionStartAndEndSymbols)); 375e8d8bef9SDimitry Andric 376e8d8bef9SDimitry Andric // Add GOT/Stubs optimizer pass. 377349cc55cSDimitry Andric Config.PreFixupPasses.push_back(x86_64::optimizeGOTAndStubAccesses); 378e8d8bef9SDimitry Andric } 379e8d8bef9SDimitry Andric 380fe6060f1SDimitry Andric if (auto Err = Ctx->modifyPassConfig(*G, Config)) 3815ffd83dbSDimitry Andric return Ctx->notifyFailed(std::move(Err)); 3825ffd83dbSDimitry Andric 383e8d8bef9SDimitry Andric ELFJITLinker_x86_64::link(std::move(Ctx), std::move(G), std::move(Config)); 384e8d8bef9SDimitry Andric } 3855ffd83dbSDimitry Andric } // end namespace jitlink 3865ffd83dbSDimitry Andric } // end namespace llvm 387