LLVM: lib/ExecutionEngine/JITLink/ELF_x86_64.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
19
24
25#define DEBUG_TYPE "jitlink"
26
27using namespace llvm;
29
30namespace {
31
32constexpr StringRef ELFGOTSymbolName = "_GLOBAL_OFFSET_TABLE_";
33constexpr StringRef ELFTLSInfoSectionName = "$__TLSINFO";
34
35class TLSInfoTableManager_ELF_x86_64
36 : public TableManager<TLSInfoTableManager_ELF_x86_64> {
37public:
38 static const uint8_t TLSInfoEntryContent[16];
39
41
45 dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at "
46 << formatv("{0:x}", B->getFixupAddress(E)) << " ("
47 << formatv("{0:x}", B->getAddress()) << " + "
48 << formatv("{0:x}", E.getOffset()) << ")\n";
49 });
51 E.setTarget(getEntryForTarget(G, E.getTarget()));
52 return true;
53 }
54 return false;
55 }
56
58
59
60 auto &TLSInfoEntry = G.createMutableContentBlock(
61 getTLSInfoSection(G), G.allocateContent(getTLSInfoEntryContent()),
64 return G.addAnonymousSymbol(TLSInfoEntry, 0, 16, false, false);
65 }
66
67private:
69 if (!TLSInfoTable)
70 TLSInfoTable =
72 return *TLSInfoTable;
73 }
74
76 return {reinterpret_cast<const char *>(TLSInfoEntryContent),
77 sizeof(TLSInfoEntryContent)};
78 }
79
80 Section *TLSInfoTable = nullptr;
81};
82
83const uint8_t TLSInfoTableManager_ELF_x86_64::TLSInfoEntryContent[16] = {
84 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
86};
87
90
93 TLSInfoTableManager_ELF_x86_64 TLSInfo;
96}
97}
98
99namespace llvm {
101
103private:
105
108
111 for (const auto &RelSect : Base::Sections) {
112
115 "No SHT_REL in valid x64 ELF object files",
117
118 if (Error Err = Base::forEachRelaRelocation(RelSect, this,
119 &Self::addSingleRelocation))
120 return Err;
121 }
122
124 }
125
126 Error addSingleRelocation(const typename ELFT::Rela &Rel,
127 const typename ELFT::Shdr &FixupSection,
128 Block &BlockToFix) {
130
131 auto ELFReloc = Rel.getType(false);
132
133
134 if (LLVM_UNLIKELY(ELFReloc == ELF::R_X86_64_NONE))
136
137 uint32_t SymbolIndex = Rel.getSymbol(false);
138 auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);
139 if (!ObjSymbol)
140 return ObjSymbol.takeError();
141
142 Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex);
143 if (!GraphSymbol)
145 formatv("Could not find symbol at given index, did you add it to "
146 "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",
147 SymbolIndex, (*ObjSymbol)->st_shndx,
148 Base::GraphSymbols.size()),
150
151
152 int64_t Addend = Rel.r_addend;
153 Edge::Kind Kind = Edge::Invalid;
154
155 switch (ELFReloc) {
156 case ELF::R_X86_64_PC8:
158 break;
159 case ELF::R_X86_64_PC16:
161 break;
162 case ELF::R_X86_64_PC32:
163 case ELF::R_X86_64_GOTPC32:
165 break;
166 case ELF::R_X86_64_PC64:
167 case ELF::R_X86_64_GOTPC64:
169 break;
170 case ELF::R_X86_64_32:
172 break;
173 case ELF::R_X86_64_16:
175 break;
176 case ELF::R_X86_64_8:
178 break;
179 case ELF::R_X86_64_32S:
181 break;
182 case ELF::R_X86_64_64:
184 break;
185 case ELF::R_X86_64_SIZE32:
187 break;
188 case ELF::R_X86_64_SIZE64:
190 break;
191 case ELF::R_X86_64_GOTPCREL:
193 break;
194 case ELF::R_X86_64_REX_GOTPCRELX:
196 Addend = 0;
197 break;
198 case ELF::R_X86_64_TLSGD:
200 break;
201 case ELF::R_X86_64_GOTPCRELX:
203 Addend = 0;
204 break;
205 case ELF::R_X86_64_GOTPCREL64:
207 break;
208 case ELF::R_X86_64_GOT64:
210 break;
211 case ELF::R_X86_64_GOTOFF64:
213 break;
214 case ELF::R_X86_64_PLT32:
216
217
218 Addend += 4;
219 break;
220 default:
222 "In " + G->getName() + ": Unsupported x86-64 relocation type " +
224 }
225
226 auto FixupAddress = orc::ExecutorAddr(FixupSection.sh_addr) + Rel.r_offset;
227 Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();
228 Edge GE(Kind, Offset, *GraphSymbol, Addend);
230 dbgs() << " ";
232 dbgs() << "\n";
233 });
234
235 BlockToFix.addEdge(std::move(GE));
237 }
238
239public:
241 std::shared_ptrorc::SymbolStringPool SSP,
245 std::move(Features), FileName,
246 x86_64::getEdgeKindName) {}
247};
248
251
252public:
254 std::unique_ptr G,
257
260 [this](LinkGraph &G) { return getOrCreateGOTSymbol(G); });
261 }
262
263private:
264 Symbol *GOTSymbol = nullptr;
266 auto DefineExternalGOTSymbolIfPresent =
269 if (Sym.getName() != nullptr &&
270 *Sym.getName() == ELFGOTSymbolName)
271 if (auto *GOTSection = G.findSectionByName(
273 GOTSymbol = &Sym;
274 return {*GOTSection, true};
275 }
276 return {};
277 });
278
279
280
281 if (auto Err = DefineExternalGOTSymbolIfPresent(G))
282 return Err;
283
284
285 if (GOTSymbol)
287
288
289
290
291 if (auto *GOTSection =
293
294
295 for (auto *Sym : GOTSection->symbols())
296 if (Sym->getName() != nullptr && *Sym->getName() == ELFGOTSymbolName) {
297 GOTSymbol = Sym;
299 }
300
301
302 SectionRange SR(*GOTSection);
303 if (SR.empty())
304 GOTSymbol =
305 &G.addAbsoluteSymbol(ELFGOTSymbolName, orc::ExecutorAddr(), 0,
307 else
308 GOTSymbol =
309 &G.addDefinedSymbol(*SR.getFirstBlock(), 0, ELFGOTSymbolName, 0,
311 }
312
313
314
315
316 if (!GOTSymbol) {
317 for (auto *Sym : G.external_symbols()) {
318 if (*Sym->getName() == ELFGOTSymbolName) {
319 auto Blocks = G.blocks();
320 if (!Blocks.empty()) {
321 G.makeAbsolute(*Sym, (*Blocks.begin())->getAddress());
322 GOTSymbol = Sym;
323 break;
324 }
325 }
326 }
327 }
328
330 }
331
332 Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
334 }
335};
336
338 MemoryBufferRef ObjectBuffer, std::shared_ptrorc::SymbolStringPool SSP) {
340 dbgs() << "Building jitlink graph for new input "
342 });
343
345 if (!ELFObj)
346 return ELFObj.takeError();
347
348 auto Features = (*ELFObj)->getFeatures();
349 if (!Features)
350 return Features.takeError();
351
354 ELFObjFile.getELFFile(),
355 std::move(*Features))
357}
358
360 std::unique_ptr Ctx) {
362
363 if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) {
364
370
371
372
373 if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple()))
374 Config.PrePrunePasses.push_back(std::move(MarkLive));
375 else
377
378
379 Config.PostPrunePasses.push_back(buildTables_ELF_x86_64);
380
381
385
386
388 }
389
390 if (auto Err = Ctx->modifyPassConfig(*G, Config))
391 return Ctx->notifyFailed(std::move(Err));
392
394}
395}
396}
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_UNLIKELY(EXPR)
std::pair< BasicBlock *, BasicBlock * > Edge
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
StringRef getBufferIdentifier() const
StringRef - Represent a constant reference to a string, i.e.
Manages the enabling and disabling of subtarget specific features.
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
orc::ExecutorAddr getAddress() const
An Addressable with content and edges.
void addEdge(Edge::Kind K, Edge::OffsetT Offset, Symbol &Target, Edge::AddendT Addend)
Add an edge to this block.
A LinkGraph pass that splits blocks in a section that follows the DWARF Record format into sub-blocks...
A LinkGraph pass that adds missing FDE-to-CIE, FDE-to-PC and FDE-to-LSDA edges.
ELFJITLinker_x86_64(std::unique_ptr< JITLinkContext > Ctx, std::unique_ptr< LinkGraph > G, PassConfiguration PassConfig)
Definition ELF_x86_64.cpp:253
std::unique_ptr< LinkGraph > G
Definition ELF_x86_64.cpp:102
ELFLinkGraphBuilder_x86_64(StringRef FileName, std::shared_ptr< orc::SymbolStringPool > SSP, const object::ELFFile< object::ELF64LE > &Obj, SubtargetFeatures Features)
Definition ELF_x86_64.cpp:240
virtual Error addRelocations()=0
ELFLinkGraphBuilder(const object::ELFFile< object::ELF64LE > &Obj, std::shared_ptr< orc::SymbolStringPool > SSP, Triple TT, SubtargetFeatures Features, StringRef FileName, LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
Expected< std::unique_ptr< LinkGraph > > buildGraph()
Attempt to construct and return the LinkGraph.
Represents fixups and constraints in the LinkGraph.
PassConfiguration & getPassConfig()
bool shouldAddDefaultTargetPasses(const Triple &TT)
static void link(ArgTs &&... Args)
Represents an object file section.
const orc::SymbolStringPtr & getName() const
Returns the name of this symbol (empty if the symbol is anonymous).
A CRTP base for tables that are built on demand, e.g.
Global Offset Table Builder.
static StringRef getSectionName()
Procedure Linkage Table Builder.
static Expected< std::unique_ptr< ObjectFile > > createELFObjectFile(MemoryBufferRef Object, bool InitContent=true)
Represents an address in the executor process.
static constexpr const StringLiteral & getSectionName(DebugSectionKind SectionKind)
Return the name of the section.
LLVM_ABI const char * getEdgeKindName(Edge::Kind K)
Returns a string name for the given x86-64 edge.
Error applyFixup(LinkGraph &G, Block &B, const Edge &E, const Symbol *GOTSymbol)
Apply fixup expression for edge to block content.
constexpr uint64_t PointerSize
x86_64 pointer size.
LLVM_ABI Error optimizeGOTAndStubAccesses(LinkGraph &G)
Optimize the GOT and Stub relocations if the edge target address is in range.
@ Delta64FromGOT
A 64-bit GOT delta.
@ RequestTLSDescInGOTAndTransformToDelta32
TODO: Explain the generic edge kind.
@ Pointer32
A plain 32-bit pointer value relocation.
@ RequestGOTAndTransformToDelta32
A GOT entry getter/constructor, transformed to Delta32 pointing at the GOT entry for the original tar...
@ Pointer8
A plain 8-bit pointer value relocation.
@ Pointer32Signed
A signed 32-bit pointer value relocation.
@ BranchPCRel32
A 32-bit PC-relative branch.
@ RequestGOTAndTransformToDelta64
A GOT entry getter/constructor, transformed to Delta64 pointing at the GOT entry for the original tar...
@ RequestGOTAndTransformToDelta64FromGOT
A GOT entry offset within GOT getter/constructor, transformed to Delta64FromGOT pointing at the GOT e...
@ Size64
A 64-bit size relocation.
@ Pointer16
A plain 16-bit pointer value relocation.
@ RequestGOTAndTransformToPCRel32GOTLoadRelaxable
A GOT entry getter/constructor, transformed to PCRel32ToGOTLoadRelaxable pointing at the GOT entry fo...
@ Pointer64
A plain 64-bit pointer value relocation.
@ Size32
A 32-bit size relocation.
@ RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable
A GOT entry getter/constructor, transformed to PCRel32ToGOTLoadREXRelaxable pointing at the GOT entry...
@ NegDelta32
A 32-bit negative delta.
void visitExistingEdges(LinkGraph &G, VisitorTs &&...Vs)
For each edge in the given graph, apply a list of visitors to the edge, stopping when the first visit...
LLVM_ABI Error markAllSymbolsLive(LinkGraph &G)
Marks all symbols in a graph live.
LLVM_ABI void printEdge(raw_ostream &OS, const Block &B, const Edge &E, StringRef EdgeKindName)
SectionRangeSymbolDesc identifyELFSectionStartAndEndSymbols(LinkGraph &G, Symbol &Sym)
ELF section start/end symbol detection.
Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromELFObject_x86_64(MemoryBufferRef ObjectBuffer, std::shared_ptr< orc::SymbolStringPool > SSP)
Create a LinkGraph from an ELF/x86-64 relocatable object.
Definition ELF_x86_64.cpp:337
void link_ELF_x86_64(std::unique_ptr< LinkGraph > G, std::unique_ptr< JITLinkContext > Ctx)
jit-link the given object buffer, which must be a ELF x86-64 object file.
Definition ELF_x86_64.cpp:359
void visitEdge(LinkGraph &G, Block *B, Edge &E)
Base case for edge-visitors where the visitor-list is empty.
DefineExternalSectionStartAndEndSymbols< SymbolIdentifierFunction > createDefineExternalSectionStartAndEndSymbolsPass(SymbolIdentifierFunction &&F)
Returns a JITLink pass (as a function class) that uses the given symbol identification function to id...
LLVM_ABI StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type)
ELFType< llvm::endianness::little, true > ELF64LE
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
Implement std::hash so that hash_code can be used in STL containers.
An LinkGraph pass configuration, consisting of a list of pre-prune, post-prune, and post-fixup passes...
LinkGraphPassList PostAllocationPasses
Post-allocation passes.
LinkGraphPassList PreFixupPasses
Pre-fixup passes.
LinkGraphPassList PostPrunePasses
Post-prune passes.
LinkGraphPassList PrePrunePasses
Pre-prune passes.
Elf_Rel_Impl< ELFType< E, Is64 >, true > Rela
Elf_Shdr_Impl< ELFType< E, Is64 > > Shdr