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
getSectionName()40349cc55cSDimitry Andric static StringRef getSectionName() { return ELFTLSInfoSectionName; }
41e8d8bef9SDimitry Andric
visitEdge(LinkGraph & G,Block * B,Edge & E)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
createEntry(LinkGraph & G,Symbol & Target)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:
getTLSInfoSection(LinkGraph & G)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
getTLSInfoEntryContent() const75349cc55cSDimitry 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
buildTables_ELF_x86_64(LinkGraph & G)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
addRelocations()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
addSingleRelocation(const typename ELFT::Rela & Rel,const typename ELFT::Shdr & FixupSection,Block & BlockToFix)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:
ELFLinkGraphBuilder_x86_64(StringRef FileName,const object::ELFFile<object::ELF64LE> & Obj,SubtargetFeatures Features)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:
ELFJITLinker_x86_64(std::unique_ptr<JITLinkContext> Ctx,std::unique_ptr<LinkGraph> G,PassConfiguration PassConfig)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
getOrCreateGOTSymbol(LinkGraph & G)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
applyFixup(LinkGraph & G,Block & B,const Edge & E) const322fe6060f1SDimitry 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>>
createLinkGraphFromELFObject_x86_64(MemoryBufferRef ObjectBuffer)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
link_ELF_x86_64(std::unique_ptr<LinkGraph> G,std::unique_ptr<JITLinkContext> Ctx)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