xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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