xref: /llvm-project/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp (revision 8fb29ba287d72392bd7900c33d2a8d2149126dbe)
12e40cf06SLang Hames //===---- ELF_x86_64.cpp -JIT linker implementation for ELF/x86-64 ----===//
22e40cf06SLang Hames //
32e40cf06SLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42e40cf06SLang Hames // See https://llvm.org/LICENSE.txt for license information.
52e40cf06SLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62e40cf06SLang Hames //
72e40cf06SLang Hames //===----------------------------------------------------------------------===//
82e40cf06SLang Hames //
92e40cf06SLang Hames // ELF/x86-64 jit-link implementation.
102e40cf06SLang Hames //
112e40cf06SLang Hames //===----------------------------------------------------------------------===//
122e40cf06SLang Hames 
132e40cf06SLang Hames #include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h"
14d46409fcSShubham Sandeep Rastogi #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"
152e40cf06SLang Hames #include "llvm/ExecutionEngine/JITLink/JITLink.h"
16bc03a9c0SLang Hames #include "llvm/ExecutionEngine/JITLink/TableManager.h"
17209ceed7SLang Hames #include "llvm/ExecutionEngine/JITLink/x86_64.h"
182e40cf06SLang Hames #include "llvm/Object/ELFObjectFile.h"
192e40cf06SLang Hames 
200a74ec32SLang Hames #include "DefineExternalSectionStartAndEndSymbols.h"
21cda4d3d3SLang Hames #include "EHFrameSupportImpl.h"
22aff57ff2SLang Hames #include "ELFLinkGraphBuilder.h"
23cda4d3d3SLang Hames #include "JITLinkGeneric.h"
24cda4d3d3SLang Hames 
252e40cf06SLang Hames #define DEBUG_TYPE "jitlink"
262e40cf06SLang Hames 
272e40cf06SLang Hames using namespace llvm;
282e40cf06SLang Hames using namespace llvm::jitlink;
29ef454c54SJared Wyles 
309a0689e0SBenjamin Kramer namespace {
31a817f46dSLang Hames 
32cc4ad2c5SLang Hames constexpr StringRef ELFGOTSymbolName = "_GLOBAL_OFFSET_TABLE_";
33ff6069b8Sluxufan constexpr StringRef ELFTLSInfoSectionName = "$__TLSINFO";
34ff6069b8Sluxufan 
35849b36bfSluxufan class TLSInfoTableManager_ELF_x86_64
36849b36bfSluxufan     : public TableManager<TLSInfoTableManager_ELF_x86_64> {
37849b36bfSluxufan public:
38849b36bfSluxufan   static const uint8_t TLSInfoEntryContent[16];
39849b36bfSluxufan 
40cc3115cdSLang Hames   static StringRef getSectionName() { return ELFTLSInfoSectionName; }
41849b36bfSluxufan 
42bc03a9c0SLang Hames   bool visitEdge(LinkGraph &G, Block *B, Edge &E) {
43849b36bfSluxufan     if (E.getKind() == x86_64::RequestTLSDescInGOTAndTransformToDelta32) {
44849b36bfSluxufan       LLVM_DEBUG({
45849b36bfSluxufan         dbgs() << "  Fixing " << G.getEdgeKindName(E.getKind()) << " edge at "
46849b36bfSluxufan                << formatv("{0:x}", B->getFixupAddress(E)) << " ("
47849b36bfSluxufan                << formatv("{0:x}", B->getAddress()) << " + "
48849b36bfSluxufan                << formatv("{0:x}", E.getOffset()) << ")\n";
49849b36bfSluxufan       });
50849b36bfSluxufan       E.setKind(x86_64::Delta32);
51bc03a9c0SLang Hames       E.setTarget(getEntryForTarget(G, E.getTarget()));
52849b36bfSluxufan       return true;
53849b36bfSluxufan     }
54849b36bfSluxufan     return false;
55849b36bfSluxufan   }
56849b36bfSluxufan 
57849b36bfSluxufan   Symbol &createEntry(LinkGraph &G, Symbol &Target) {
58849b36bfSluxufan     // the TLS Info entry's key value will be written by the fixTLVSectionByName
59849b36bfSluxufan     // pass, so create mutable content.
60849b36bfSluxufan     auto &TLSInfoEntry = G.createMutableContentBlock(
61118e953bSLang Hames         getTLSInfoSection(G), G.allocateContent(getTLSInfoEntryContent()),
62118e953bSLang Hames         orc::ExecutorAddr(), 8, 0);
63849b36bfSluxufan     TLSInfoEntry.addEdge(x86_64::Pointer64, 8, Target, 0);
64849b36bfSluxufan     return G.addAnonymousSymbol(TLSInfoEntry, 0, 16, false, false);
65849b36bfSluxufan   }
66849b36bfSluxufan 
67849b36bfSluxufan private:
68849b36bfSluxufan   Section &getTLSInfoSection(LinkGraph &G) {
69849b36bfSluxufan     if (!TLSInfoTable)
70d3d9f7caSLang Hames       TLSInfoTable =
71d3d9f7caSLang Hames           &G.createSection(ELFTLSInfoSectionName, orc::MemProt::Read);
72849b36bfSluxufan     return *TLSInfoTable;
73849b36bfSluxufan   }
74849b36bfSluxufan 
75849b36bfSluxufan   ArrayRef<char> getTLSInfoEntryContent() const {
76849b36bfSluxufan     return {reinterpret_cast<const char *>(TLSInfoEntryContent),
77849b36bfSluxufan             sizeof(TLSInfoEntryContent)};
78849b36bfSluxufan   }
79849b36bfSluxufan 
80849b36bfSluxufan   Section *TLSInfoTable = nullptr;
81ef454c54SJared Wyles };
82a817f46dSLang Hames 
83849b36bfSluxufan const uint8_t TLSInfoTableManager_ELF_x86_64::TLSInfoEntryContent[16] = {
84849b36bfSluxufan     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*pthread key */
85849b36bfSluxufan     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  /*data address*/
86849b36bfSluxufan };
872e40cf06SLang Hames 
88849b36bfSluxufan Error buildTables_ELF_x86_64(LinkGraph &G) {
89849b36bfSluxufan   LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");
90849b36bfSluxufan 
91*8fb29ba2SLang Hames   x86_64::GOTTableManager GOT(G);
92*8fb29ba2SLang Hames   x86_64::PLTTableManager PLT(G, GOT);
93849b36bfSluxufan   TLSInfoTableManager_ELF_x86_64 TLSInfo;
94849b36bfSluxufan   visitExistingEdges(G, GOT, PLT, TLSInfo);
95849b36bfSluxufan   return Error::success();
96849b36bfSluxufan }
97849b36bfSluxufan } // namespace
98b384736bSluxufan 
992e40cf06SLang Hames namespace llvm {
1002e40cf06SLang Hames namespace jitlink {
1013f0841f6SJared Wyles 
102aff57ff2SLang Hames class ELFLinkGraphBuilder_x86_64 : public ELFLinkGraphBuilder<object::ELF64LE> {
1032e40cf06SLang Hames private:
10468914dc9SStefan Gränitz   using ELFT = object::ELF64LE;
1052e40cf06SLang Hames 
1068e66fc43SLang Hames   Error addRelocations() override {
10768914dc9SStefan Gränitz     LLVM_DEBUG(dbgs() << "Processing relocations:\n");
1083f0841f6SJared Wyles 
10968914dc9SStefan Gränitz     using Base = ELFLinkGraphBuilder<ELFT>;
11068914dc9SStefan Gränitz     using Self = ELFLinkGraphBuilder_x86_64;
11168914dc9SStefan Gränitz     for (const auto &RelSect : Base::Sections) {
11259c84774SZarko Todorovski       // Validate the section to read relocation entries from.
11368914dc9SStefan Gränitz       if (RelSect.sh_type == ELF::SHT_REL)
11468914dc9SStefan Gränitz         return make_error<StringError>(
11568914dc9SStefan Gränitz             "No SHT_REL in valid x64 ELF object files",
11668914dc9SStefan Gränitz             inconvertibleErrorCode());
117a817f46dSLang Hames 
1182a3b257aSKshitij Jain       if (Error Err = Base::forEachRelaRelocation(RelSect, this,
11968914dc9SStefan Gränitz                                                   &Self::addSingleRelocation))
12068914dc9SStefan Gränitz         return Err;
121ef454c54SJared Wyles     }
1223f0841f6SJared Wyles 
12368914dc9SStefan Gränitz     return Error::success();
12468914dc9SStefan Gränitz   }
12568914dc9SStefan Gränitz 
12668914dc9SStefan Gränitz   Error addSingleRelocation(const typename ELFT::Rela &Rel,
12768914dc9SStefan Gränitz                             const typename ELFT::Shdr &FixupSection,
128091e3648SSteven Wu                             Block &BlockToFix) {
12968914dc9SStefan Gränitz     using Base = ELFLinkGraphBuilder<ELFT>;
13068914dc9SStefan Gränitz 
1318308e81bSLang Hames     auto ELFReloc = Rel.getType(false);
1328308e81bSLang Hames 
1338308e81bSLang Hames     // R_X86_64_NONE is a no-op.
1348308e81bSLang Hames     if (LLVM_UNLIKELY(ELFReloc == ELF::R_X86_64_NONE))
1358308e81bSLang Hames       return Error::success();
1368308e81bSLang Hames 
13768914dc9SStefan Gränitz     uint32_t SymbolIndex = Rel.getSymbol(false);
13868914dc9SStefan Gränitz     auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);
13968914dc9SStefan Gränitz     if (!ObjSymbol)
14068914dc9SStefan Gränitz       return ObjSymbol.takeError();
14168914dc9SStefan Gränitz 
14268914dc9SStefan Gränitz     Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex);
14368914dc9SStefan Gränitz     if (!GraphSymbol)
14468914dc9SStefan Gränitz       return make_error<StringError>(
14568914dc9SStefan Gränitz           formatv("Could not find symbol at given index, did you add it to "
14668914dc9SStefan Gränitz                   "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",
14768914dc9SStefan Gränitz                   SymbolIndex, (*ObjSymbol)->st_shndx,
14868914dc9SStefan Gränitz                   Base::GraphSymbols.size()),
14968914dc9SStefan Gränitz           inconvertibleErrorCode());
15068914dc9SStefan Gränitz 
15159c84774SZarko Todorovski     // Validate the relocation kind.
15268914dc9SStefan Gränitz     int64_t Addend = Rel.r_addend;
153ee659383Sluxufan     Edge::Kind Kind = Edge::Invalid;
154d3df7b15SLang Hames 
155d3df7b15SLang Hames     switch (ELFReloc) {
156ae6f730bSMaksim Panchenko     case ELF::R_X86_64_PC8:
157ae6f730bSMaksim Panchenko       Kind = x86_64::Delta8;
158ae6f730bSMaksim Panchenko       break;
15957bee1e4SXing Guo     case ELF::R_X86_64_PC16:
16057bee1e4SXing Guo       Kind = x86_64::Delta16;
16157bee1e4SXing Guo       break;
162d3df7b15SLang Hames     case ELF::R_X86_64_PC32:
163e4b6e686SLang Hames     case ELF::R_X86_64_GOTPC32:
164ee659383Sluxufan       Kind = x86_64::Delta32;
165ee659383Sluxufan       break;
166d3df7b15SLang Hames     case ELF::R_X86_64_PC64:
167d3df7b15SLang Hames     case ELF::R_X86_64_GOTPC64:
168ee659383Sluxufan       Kind = x86_64::Delta64;
169ee659383Sluxufan       break;
170d3df7b15SLang Hames     case ELF::R_X86_64_32:
171ede78c17SLang Hames       Kind = x86_64::Pointer32;
172ede78c17SLang Hames       break;
173ad7ab8f4SLang Hames     case ELF::R_X86_64_16:
174ad7ab8f4SLang Hames       Kind = x86_64::Pointer16;
175ad7ab8f4SLang Hames       break;
1769ee16eb5SLang Hames     case ELF::R_X86_64_8:
1779ee16eb5SLang Hames       Kind = x86_64::Pointer8;
1789ee16eb5SLang Hames       break;
179d3df7b15SLang Hames     case ELF::R_X86_64_32S:
180dda116bcSluxufan       Kind = x86_64::Pointer32Signed;
181dda116bcSluxufan       break;
182d3df7b15SLang Hames     case ELF::R_X86_64_64:
183ee659383Sluxufan       Kind = x86_64::Pointer64;
184ee659383Sluxufan       break;
185210140abSXing Guo     case ELF::R_X86_64_SIZE32:
186210140abSXing Guo       Kind = x86_64::Size32;
187210140abSXing Guo       break;
188210140abSXing Guo     case ELF::R_X86_64_SIZE64:
189210140abSXing Guo       Kind = x86_64::Size64;
190210140abSXing Guo       break;
191d3df7b15SLang Hames     case ELF::R_X86_64_GOTPCREL:
192a9095f00Sluxufan       Kind = x86_64::RequestGOTAndTransformToDelta32;
193a9095f00Sluxufan       break;
194d3df7b15SLang Hames     case ELF::R_X86_64_REX_GOTPCRELX:
195a9095f00Sluxufan       Kind = x86_64::RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable;
1964ec32375Sluxufan       Addend = 0;
1974ec32375Sluxufan       break;
198d3df7b15SLang Hames     case ELF::R_X86_64_TLSGD:
19901b097afSGeoffrey Martin-Noble       Kind = x86_64::RequestTLSDescInGOTAndTransformToDelta32;
20001b097afSGeoffrey Martin-Noble       break;
201d3df7b15SLang Hames     case ELF::R_X86_64_GOTPCRELX:
202a9095f00Sluxufan       Kind = x86_64::RequestGOTAndTransformToPCRel32GOTLoadRelaxable;
203ee659383Sluxufan       Addend = 0;
204ee659383Sluxufan       break;
205d3df7b15SLang Hames     case ELF::R_X86_64_GOTPCREL64:
206ee659383Sluxufan       Kind = x86_64::RequestGOTAndTransformToDelta64;
207ee659383Sluxufan       break;
208d3df7b15SLang Hames     case ELF::R_X86_64_GOT64:
209ee659383Sluxufan       Kind = x86_64::RequestGOTAndTransformToDelta64FromGOT;
210ee659383Sluxufan       break;
211d3df7b15SLang Hames     case ELF::R_X86_64_GOTOFF64:
212ee659383Sluxufan       Kind = x86_64::Delta64FromGOT;
213ee659383Sluxufan       break;
214d3df7b15SLang Hames     case ELF::R_X86_64_PLT32:
215ee659383Sluxufan       Kind = x86_64::BranchPCRel32;
21621562c03SLang Hames       // BranchPCRel32 implicitly handles the '-4' PC adjustment, so we have to
21721562c03SLang Hames       // adjust the addend by '+4' to compensate.
21821562c03SLang Hames       Addend += 4;
219ee659383Sluxufan       break;
220d3df7b15SLang Hames     default:
221d3df7b15SLang Hames       return make_error<JITLinkError>(
222d3df7b15SLang Hames           "In " + G->getName() + ": Unsupported x86-64 relocation type " +
223d3df7b15SLang Hames           object::getELFRelocationTypeName(ELF::EM_X86_64, ELFReloc));
224ee659383Sluxufan     }
2253f0841f6SJared Wyles 
226118e953bSLang Hames     auto FixupAddress = orc::ExecutorAddr(FixupSection.sh_addr) + Rel.r_offset;
227091e3648SSteven Wu     Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();
22868914dc9SStefan Gränitz     Edge GE(Kind, Offset, *GraphSymbol, Addend);
2293f0841f6SJared Wyles     LLVM_DEBUG({
23068914dc9SStefan Gränitz       dbgs() << "    ";
231091e3648SSteven Wu       printEdge(dbgs(), BlockToFix, GE, x86_64::getEdgeKindName(Kind));
2323f0841f6SJared Wyles       dbgs() << "\n";
2333f0841f6SJared Wyles     });
23468914dc9SStefan Gränitz 
235091e3648SSteven Wu     BlockToFix.addEdge(std::move(GE));
2363f0841f6SJared Wyles     return Error::success();
2373f0841f6SJared Wyles   }
2383f0841f6SJared Wyles 
2392e40cf06SLang Hames public:
240ec6b71dfSLang Hames   ELFLinkGraphBuilder_x86_64(StringRef FileName,
2412ccf7ed2SJared Wyles                              std::shared_ptr<orc::SymbolStringPool> SSP,
242348d0a6bSJob Noorman                              const object::ELFFile<object::ELF64LE> &Obj,
24352b88457SJob Noorman                              SubtargetFeatures Features)
2442ccf7ed2SJared Wyles       : ELFLinkGraphBuilder(Obj, std::move(SSP), Triple("x86_64-unknown-linux"),
245348d0a6bSJob Noorman                             std::move(Features), FileName,
246ee659383Sluxufan                             x86_64::getEdgeKindName) {}
2472e40cf06SLang Hames };
2482e40cf06SLang Hames 
2492e40cf06SLang Hames class ELFJITLinker_x86_64 : public JITLinker<ELFJITLinker_x86_64> {
2502e40cf06SLang Hames   friend class JITLinker<ELFJITLinker_x86_64>;
2512e40cf06SLang Hames 
2522e40cf06SLang Hames public:
2532e40cf06SLang Hames   ELFJITLinker_x86_64(std::unique_ptr<JITLinkContext> Ctx,
254ec6b71dfSLang Hames                       std::unique_ptr<LinkGraph> G,
2552e40cf06SLang Hames                       PassConfiguration PassConfig)
256fc36a511SLang Hames       : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {
257265d6bdaSLang Hames 
25835c9072cSLang Hames     if (shouldAddDefaultTargetPasses(getGraph().getTargetTriple()))
259fc36a511SLang Hames       getPassConfig().PostAllocationPasses.push_back(
260fc36a511SLang Hames           [this](LinkGraph &G) { return getOrCreateGOTSymbol(G); });
261fc36a511SLang Hames   }
2622e40cf06SLang Hames 
2632e40cf06SLang Hames private:
264fc36a511SLang Hames   Symbol *GOTSymbol = nullptr;
265fc36a511SLang Hames   Error getOrCreateGOTSymbol(LinkGraph &G) {
266fc36a511SLang Hames     auto DefineExternalGOTSymbolIfPresent =
267fc36a511SLang Hames         createDefineExternalSectionStartAndEndSymbolsPass(
268fc36a511SLang Hames             [&](LinkGraph &LG, Symbol &Sym) -> SectionRangeSymbolDesc {
2692ccf7ed2SJared Wyles               if (Sym.getName() != nullptr &&
2702ccf7ed2SJared Wyles                   *Sym.getName() == ELFGOTSymbolName)
271cc3115cdSLang Hames                 if (auto *GOTSection = G.findSectionByName(
272cc3115cdSLang Hames                         x86_64::GOTTableManager::getSectionName())) {
273fc36a511SLang Hames                   GOTSymbol = &Sym;
274fc36a511SLang Hames                   return {*GOTSection, true};
275fc36a511SLang Hames                 }
276fc36a511SLang Hames               return {};
277fc36a511SLang Hames             });
278fc36a511SLang Hames 
279fc36a511SLang Hames     // Try to attach _GLOBAL_OFFSET_TABLE_ to the GOT if it's defined as an
280fc36a511SLang Hames     // external.
281fc36a511SLang Hames     if (auto Err = DefineExternalGOTSymbolIfPresent(G))
282fc36a511SLang Hames       return Err;
283fc36a511SLang Hames 
284cc4ad2c5SLang Hames     // If we succeeded then we're done.
285cc4ad2c5SLang Hames     if (GOTSymbol)
286cc4ad2c5SLang Hames       return Error::success();
287cc4ad2c5SLang Hames 
288cc4ad2c5SLang Hames     // Otherwise look for a GOT section: If it already has a start symbol we'll
289cc4ad2c5SLang Hames     // record it, otherwise we'll create our own.
290fc36a511SLang Hames     // If there's a GOT section but we didn't find an external GOT symbol...
291cc3115cdSLang Hames     if (auto *GOTSection =
292cc3115cdSLang Hames             G.findSectionByName(x86_64::GOTTableManager::getSectionName())) {
293fc36a511SLang Hames 
294fc36a511SLang Hames       // Check for an existing defined symbol.
295fc36a511SLang Hames       for (auto *Sym : GOTSection->symbols())
2962ccf7ed2SJared Wyles         if (Sym->getName() != nullptr && *Sym->getName() == ELFGOTSymbolName) {
297fc36a511SLang Hames           GOTSymbol = Sym;
298fc36a511SLang Hames           return Error::success();
299fc36a511SLang Hames         }
300fc36a511SLang Hames 
301fc36a511SLang Hames       // If there's no defined symbol then create one.
302fc36a511SLang Hames       SectionRange SR(*GOTSection);
303fc36a511SLang Hames       if (SR.empty())
304118e953bSLang Hames         GOTSymbol =
305118e953bSLang Hames             &G.addAbsoluteSymbol(ELFGOTSymbolName, orc::ExecutorAddr(), 0,
306fc36a511SLang Hames                                  Linkage::Strong, Scope::Local, true);
307fc36a511SLang Hames       else
308fc36a511SLang Hames         GOTSymbol =
309fc36a511SLang Hames             &G.addDefinedSymbol(*SR.getFirstBlock(), 0, ELFGOTSymbolName, 0,
310fc36a511SLang Hames                                 Linkage::Strong, Scope::Local, false, true);
311fc36a511SLang Hames     }
312fc36a511SLang Hames 
313e4b6e686SLang Hames     // If we still haven't found a GOT symbol then double check the externals.
314e4b6e686SLang Hames     // We may have a GOT-relative reference but no GOT section, in which case
315e4b6e686SLang Hames     // we just need to point the GOT symbol at some address in this graph.
316e4b6e686SLang Hames     if (!GOTSymbol) {
317e4b6e686SLang Hames       for (auto *Sym : G.external_symbols()) {
3182ccf7ed2SJared Wyles         if (*Sym->getName() == ELFGOTSymbolName) {
319e4b6e686SLang Hames           auto Blocks = G.blocks();
320e4b6e686SLang Hames           if (!Blocks.empty()) {
321e4b6e686SLang Hames             G.makeAbsolute(*Sym, (*Blocks.begin())->getAddress());
322e4b6e686SLang Hames             GOTSymbol = Sym;
323e4b6e686SLang Hames             break;
324e4b6e686SLang Hames           }
325e4b6e686SLang Hames         }
326e4b6e686SLang Hames       }
327e4b6e686SLang Hames     }
328e4b6e686SLang Hames 
329fc36a511SLang Hames     return Error::success();
330fc36a511SLang Hames   }
331fc36a511SLang Hames 
33282ad2b6eSLang Hames   Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
333ee659383Sluxufan     return x86_64::applyFixup(G, B, E, GOTSymbol);
3342e40cf06SLang Hames   }
3352e40cf06SLang Hames };
3362e40cf06SLang Hames 
3372ccf7ed2SJared Wyles Expected<std::unique_ptr<LinkGraph>> createLinkGraphFromELFObject_x86_64(
3382ccf7ed2SJared Wyles     MemoryBufferRef ObjectBuffer, std::shared_ptr<orc::SymbolStringPool> SSP) {
339ec6b71dfSLang Hames   LLVM_DEBUG({
340ec6b71dfSLang Hames     dbgs() << "Building jitlink graph for new input "
341ec6b71dfSLang Hames            << ObjectBuffer.getBufferIdentifier() << "...\n";
342ec6b71dfSLang Hames   });
343ec6b71dfSLang Hames 
344ec6b71dfSLang Hames   auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer);
345ec6b71dfSLang Hames   if (!ELFObj)
346ec6b71dfSLang Hames     return ELFObj.takeError();
347ec6b71dfSLang Hames 
348348d0a6bSJob Noorman   auto Features = (*ELFObj)->getFeatures();
349348d0a6bSJob Noorman   if (!Features)
350348d0a6bSJob Noorman     return Features.takeError();
351348d0a6bSJob Noorman 
352ec6b71dfSLang Hames   auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
3532ccf7ed2SJared Wyles   return ELFLinkGraphBuilder_x86_64((*ELFObj)->getFileName(), std::move(SSP),
354348d0a6bSJob Noorman                                     ELFObjFile.getELFFile(),
35552b88457SJob Noorman                                     std::move(*Features))
356ec6b71dfSLang Hames       .buildGraph();
357ec6b71dfSLang Hames }
358ec6b71dfSLang Hames 
359ec6b71dfSLang Hames void link_ELF_x86_64(std::unique_ptr<LinkGraph> G,
360ec6b71dfSLang Hames                      std::unique_ptr<JITLinkContext> Ctx) {
3612e40cf06SLang Hames   PassConfiguration Config;
362ec6b71dfSLang Hames 
363cda4d3d3SLang Hames   if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) {
364cda4d3d3SLang Hames 
365229d576bSShubham Sandeep Rastogi     Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame"));
36643acef48SLang Hames     Config.PrePrunePasses.push_back(EHFrameEdgeFixer(
36743acef48SLang Hames         ".eh_frame", x86_64::PointerSize, x86_64::Pointer32, x86_64::Pointer64,
36843acef48SLang Hames         x86_64::Delta32, x86_64::Delta64, x86_64::NegDelta32));
369bcb53999SLang Hames     Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame"));
370cda4d3d3SLang Hames 
3712e40cf06SLang Hames     // Construct a JITLinker and run the link function.
3722e40cf06SLang Hames     // Add a mark-live pass.
373ec6b71dfSLang Hames     if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple()))
3742e40cf06SLang Hames       Config.PrePrunePasses.push_back(std::move(MarkLive));
3752e40cf06SLang Hames     else
3762e40cf06SLang Hames       Config.PrePrunePasses.push_back(markAllSymbolsLive);
3772e40cf06SLang Hames 
378849b36bfSluxufan     // Add an in-place GOT/Stubs/TLSInfoEntry build pass.
379849b36bfSluxufan     Config.PostPrunePasses.push_back(buildTables_ELF_x86_64);
380ef454c54SJared Wyles 
3810a74ec32SLang Hames     // Resolve any external section start / end symbols.
382fc36a511SLang Hames     Config.PostAllocationPasses.push_back(
3830a74ec32SLang Hames         createDefineExternalSectionStartAndEndSymbolsPass(
3840a74ec32SLang Hames             identifyELFSectionStartAndEndSymbols));
385fc36a511SLang Hames 
386fc36a511SLang Hames     // Add GOT/Stubs optimizer pass.
387cc3115cdSLang Hames     Config.PreFixupPasses.push_back(x86_64::optimizeGOTAndStubAccesses);
388cda4d3d3SLang Hames   }
389ef454c54SJared Wyles 
3904e30b20bSLang Hames   if (auto Err = Ctx->modifyPassConfig(*G, Config))
391a6deaeecSLang Hames     return Ctx->notifyFailed(std::move(Err));
392a6deaeecSLang Hames 
393ec6b71dfSLang Hames   ELFJITLinker_x86_64::link(std::move(Ctx), std::move(G), std::move(Config));
3942e40cf06SLang Hames }
3952e40cf06SLang Hames } // end namespace jitlink
3962e40cf06SLang Hames } // end namespace llvm
397