1 //===---- ELF_x86_64.cpp -JIT linker implementation for ELF/x86-64 ----===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // ELF/x86-64 jit-link implementation.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h"
14 #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"
15 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
16 #include "llvm/ExecutionEngine/JITLink/TableManager.h"
17 #include "llvm/ExecutionEngine/JITLink/x86_64.h"
18 #include "llvm/Object/ELFObjectFile.h"
19 #include "llvm/Support/Endian.h"
21 #include "DefineExternalSectionStartAndEndSymbols.h"
22 #include "EHFrameSupportImpl.h"
23 #include "ELFLinkGraphBuilder.h"
24 #include "JITLinkGeneric.h"
26 #define DEBUG_TYPE "jitlink"
29 using namespace llvm::jitlink
;
33 constexpr StringRef ELFGOTSymbolName
= "_GLOBAL_OFFSET_TABLE_";
34 constexpr StringRef ELFTLSInfoSectionName
= "$__TLSINFO";
36 class TLSInfoTableManager_ELF_x86_64
37 : public TableManager
<TLSInfoTableManager_ELF_x86_64
> {
39 static const uint8_t TLSInfoEntryContent
[16];
41 static StringRef
getSectionName() { return ELFTLSInfoSectionName
; }
43 bool visitEdge(LinkGraph
&G
, Block
*B
, Edge
&E
) {
44 if (E
.getKind() == x86_64::RequestTLSDescInGOTAndTransformToDelta32
) {
46 dbgs() << " Fixing " << G
.getEdgeKindName(E
.getKind()) << " edge at "
47 << formatv("{0:x}", B
->getFixupAddress(E
)) << " ("
48 << formatv("{0:x}", B
->getAddress()) << " + "
49 << formatv("{0:x}", E
.getOffset()) << ")\n";
51 E
.setKind(x86_64::Delta32
);
52 E
.setTarget(getEntryForTarget(G
, E
.getTarget()));
58 Symbol
&createEntry(LinkGraph
&G
, Symbol
&Target
) {
59 // the TLS Info entry's key value will be written by the fixTLVSectionByName
60 // pass, so create mutable content.
61 auto &TLSInfoEntry
= G
.createMutableContentBlock(
62 getTLSInfoSection(G
), G
.allocateContent(getTLSInfoEntryContent()),
63 orc::ExecutorAddr(), 8, 0);
64 TLSInfoEntry
.addEdge(x86_64::Pointer64
, 8, Target
, 0);
65 return G
.addAnonymousSymbol(TLSInfoEntry
, 0, 16, false, false);
69 Section
&getTLSInfoSection(LinkGraph
&G
) {
72 &G
.createSection(ELFTLSInfoSectionName
, orc::MemProt::Read
);
76 ArrayRef
<char> getTLSInfoEntryContent() const {
77 return {reinterpret_cast<const char *>(TLSInfoEntryContent
),
78 sizeof(TLSInfoEntryContent
)};
81 Section
*TLSInfoTable
= nullptr;
84 const uint8_t TLSInfoTableManager_ELF_x86_64::TLSInfoEntryContent
[16] = {
85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*pthread key */
86 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /*data address*/
89 Error
buildTables_ELF_x86_64(LinkGraph
&G
) {
90 LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");
92 x86_64::GOTTableManager GOT
;
93 x86_64::PLTTableManager
PLT(GOT
);
94 TLSInfoTableManager_ELF_x86_64 TLSInfo
;
95 visitExistingEdges(G
, GOT
, PLT
, TLSInfo
);
96 return Error::success();
103 class ELFLinkGraphBuilder_x86_64
: public ELFLinkGraphBuilder
<object::ELF64LE
> {
105 using ELFT
= object::ELF64LE
;
107 Error
addRelocations() override
{
108 LLVM_DEBUG(dbgs() << "Processing relocations:\n");
110 using Base
= ELFLinkGraphBuilder
<ELFT
>;
111 using Self
= ELFLinkGraphBuilder_x86_64
;
112 for (const auto &RelSect
: Base::Sections
) {
113 // Validate the section to read relocation entries from.
114 if (RelSect
.sh_type
== ELF::SHT_REL
)
115 return make_error
<StringError
>(
116 "No SHT_REL in valid x64 ELF object files",
117 inconvertibleErrorCode());
119 if (Error Err
= Base::forEachRelaRelocation(RelSect
, this,
120 &Self::addSingleRelocation
))
124 return Error::success();
127 Error
addSingleRelocation(const typename
ELFT::Rela
&Rel
,
128 const typename
ELFT::Shdr
&FixupSection
,
130 using Base
= ELFLinkGraphBuilder
<ELFT
>;
132 auto ELFReloc
= Rel
.getType(false);
134 // R_X86_64_NONE is a no-op.
135 if (LLVM_UNLIKELY(ELFReloc
== ELF::R_X86_64_NONE
))
136 return Error::success();
138 uint32_t SymbolIndex
= Rel
.getSymbol(false);
139 auto ObjSymbol
= Base::Obj
.getRelocationSymbol(Rel
, Base::SymTabSec
);
141 return ObjSymbol
.takeError();
143 Symbol
*GraphSymbol
= Base::getGraphSymbol(SymbolIndex
);
145 return make_error
<StringError
>(
146 formatv("Could not find symbol at given index, did you add it to "
147 "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",
148 SymbolIndex
, (*ObjSymbol
)->st_shndx
,
149 Base::GraphSymbols
.size()),
150 inconvertibleErrorCode());
152 // Validate the relocation kind.
153 int64_t Addend
= Rel
.r_addend
;
154 Edge::Kind Kind
= Edge::Invalid
;
157 case ELF::R_X86_64_PC32
:
158 case ELF::R_X86_64_GOTPC32
:
159 Kind
= x86_64::Delta32
;
161 case ELF::R_X86_64_PC64
:
162 case ELF::R_X86_64_GOTPC64
:
163 Kind
= x86_64::Delta64
;
165 case ELF::R_X86_64_32
:
166 Kind
= x86_64::Pointer32
;
168 case ELF::R_X86_64_16
:
169 Kind
= x86_64::Pointer16
;
171 case ELF::R_X86_64_8
:
172 Kind
= x86_64::Pointer8
;
174 case ELF::R_X86_64_32S
:
175 Kind
= x86_64::Pointer32Signed
;
177 case ELF::R_X86_64_64
:
178 Kind
= x86_64::Pointer64
;
180 case ELF::R_X86_64_GOTPCREL
:
181 Kind
= x86_64::RequestGOTAndTransformToDelta32
;
183 case ELF::R_X86_64_REX_GOTPCRELX
:
184 Kind
= x86_64::RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable
;
187 case ELF::R_X86_64_TLSGD
:
188 Kind
= x86_64::RequestTLSDescInGOTAndTransformToDelta32
;
190 case ELF::R_X86_64_GOTPCRELX
:
191 Kind
= x86_64::RequestGOTAndTransformToPCRel32GOTLoadRelaxable
;
194 case ELF::R_X86_64_GOTPCREL64
:
195 Kind
= x86_64::RequestGOTAndTransformToDelta64
;
197 case ELF::R_X86_64_GOT64
:
198 Kind
= x86_64::RequestGOTAndTransformToDelta64FromGOT
;
200 case ELF::R_X86_64_GOTOFF64
:
201 Kind
= x86_64::Delta64FromGOT
;
203 case ELF::R_X86_64_PLT32
:
204 Kind
= x86_64::BranchPCRel32
;
205 // BranchPCRel32 implicitly handles the '-4' PC adjustment, so we have to
206 // adjust the addend by '+4' to compensate.
210 return make_error
<JITLinkError
>(
211 "In " + G
->getName() + ": Unsupported x86-64 relocation type " +
212 object::getELFRelocationTypeName(ELF::EM_X86_64
, ELFReloc
));
215 auto FixupAddress
= orc::ExecutorAddr(FixupSection
.sh_addr
) + Rel
.r_offset
;
216 Edge::OffsetT Offset
= FixupAddress
- BlockToFix
.getAddress();
217 Edge
GE(Kind
, Offset
, *GraphSymbol
, Addend
);
220 printEdge(dbgs(), BlockToFix
, GE
, x86_64::getEdgeKindName(Kind
));
224 BlockToFix
.addEdge(std::move(GE
));
225 return Error::success();
229 ELFLinkGraphBuilder_x86_64(StringRef FileName
,
230 const object::ELFFile
<object::ELF64LE
> &Obj
,
231 SubtargetFeatures Features
)
232 : ELFLinkGraphBuilder(Obj
, Triple("x86_64-unknown-linux"),
233 std::move(Features
), FileName
,
234 x86_64::getEdgeKindName
) {}
237 class ELFJITLinker_x86_64
: public JITLinker
<ELFJITLinker_x86_64
> {
238 friend class JITLinker
<ELFJITLinker_x86_64
>;
241 ELFJITLinker_x86_64(std::unique_ptr
<JITLinkContext
> Ctx
,
242 std::unique_ptr
<LinkGraph
> G
,
243 PassConfiguration PassConfig
)
244 : JITLinker(std::move(Ctx
), std::move(G
), std::move(PassConfig
)) {
246 if (shouldAddDefaultTargetPasses(getGraph().getTargetTriple()))
247 getPassConfig().PostAllocationPasses
.push_back(
248 [this](LinkGraph
&G
) { return getOrCreateGOTSymbol(G
); });
252 Symbol
*GOTSymbol
= nullptr;
254 Error
getOrCreateGOTSymbol(LinkGraph
&G
) {
255 auto DefineExternalGOTSymbolIfPresent
=
256 createDefineExternalSectionStartAndEndSymbolsPass(
257 [&](LinkGraph
&LG
, Symbol
&Sym
) -> SectionRangeSymbolDesc
{
258 if (Sym
.getName() == ELFGOTSymbolName
)
259 if (auto *GOTSection
= G
.findSectionByName(
260 x86_64::GOTTableManager::getSectionName())) {
262 return {*GOTSection
, true};
267 // Try to attach _GLOBAL_OFFSET_TABLE_ to the GOT if it's defined as an
269 if (auto Err
= DefineExternalGOTSymbolIfPresent(G
))
272 // If we succeeded then we're done.
274 return Error::success();
276 // Otherwise look for a GOT section: If it already has a start symbol we'll
277 // record it, otherwise we'll create our own.
278 // If there's a GOT section but we didn't find an external GOT symbol...
279 if (auto *GOTSection
=
280 G
.findSectionByName(x86_64::GOTTableManager::getSectionName())) {
282 // Check for an existing defined symbol.
283 for (auto *Sym
: GOTSection
->symbols())
284 if (Sym
->getName() == ELFGOTSymbolName
) {
286 return Error::success();
289 // If there's no defined symbol then create one.
290 SectionRange
SR(*GOTSection
);
293 &G
.addAbsoluteSymbol(ELFGOTSymbolName
, orc::ExecutorAddr(), 0,
294 Linkage::Strong
, Scope::Local
, true);
297 &G
.addDefinedSymbol(*SR
.getFirstBlock(), 0, ELFGOTSymbolName
, 0,
298 Linkage::Strong
, Scope::Local
, false, true);
301 // If we still haven't found a GOT symbol then double check the externals.
302 // We may have a GOT-relative reference but no GOT section, in which case
303 // we just need to point the GOT symbol at some address in this graph.
305 for (auto *Sym
: G
.external_symbols()) {
306 if (Sym
->getName() == ELFGOTSymbolName
) {
307 auto Blocks
= G
.blocks();
308 if (!Blocks
.empty()) {
309 G
.makeAbsolute(*Sym
, (*Blocks
.begin())->getAddress());
317 return Error::success();
320 Error
applyFixup(LinkGraph
&G
, Block
&B
, const Edge
&E
) const {
321 return x86_64::applyFixup(G
, B
, E
, GOTSymbol
);
325 Expected
<std::unique_ptr
<LinkGraph
>>
326 createLinkGraphFromELFObject_x86_64(MemoryBufferRef ObjectBuffer
) {
328 dbgs() << "Building jitlink graph for new input "
329 << ObjectBuffer
.getBufferIdentifier() << "...\n";
332 auto ELFObj
= object::ObjectFile::createELFObjectFile(ObjectBuffer
);
334 return ELFObj
.takeError();
336 auto Features
= (*ELFObj
)->getFeatures();
338 return Features
.takeError();
340 auto &ELFObjFile
= cast
<object::ELFObjectFile
<object::ELF64LE
>>(**ELFObj
);
341 return ELFLinkGraphBuilder_x86_64((*ELFObj
)->getFileName(),
342 ELFObjFile
.getELFFile(),
343 std::move(*Features
))
347 static SectionRangeSymbolDesc
348 identifyELFSectionStartAndEndSymbols(LinkGraph
&G
, Symbol
&Sym
) {
349 constexpr StringRef StartSymbolPrefix
= "__start";
350 constexpr StringRef EndSymbolPrefix
= "__end";
352 auto SymName
= Sym
.getName();
353 if (SymName
.startswith(StartSymbolPrefix
)) {
355 G
.findSectionByName(SymName
.drop_front(StartSymbolPrefix
.size())))
357 } else if (SymName
.startswith(EndSymbolPrefix
)) {
359 G
.findSectionByName(SymName
.drop_front(EndSymbolPrefix
.size())))
360 return {*Sec
, false};
365 void link_ELF_x86_64(std::unique_ptr
<LinkGraph
> G
,
366 std::unique_ptr
<JITLinkContext
> Ctx
) {
367 PassConfiguration Config
;
369 if (Ctx
->shouldAddDefaultTargetPasses(G
->getTargetTriple())) {
371 Config
.PrePrunePasses
.push_back(DWARFRecordSectionSplitter(".eh_frame"));
372 Config
.PrePrunePasses
.push_back(EHFrameEdgeFixer(
373 ".eh_frame", x86_64::PointerSize
, x86_64::Pointer32
, x86_64::Pointer64
,
374 x86_64::Delta32
, x86_64::Delta64
, x86_64::NegDelta32
));
375 Config
.PrePrunePasses
.push_back(EHFrameNullTerminator(".eh_frame"));
377 // Construct a JITLinker and run the link function.
378 // Add a mark-live pass.
379 if (auto MarkLive
= Ctx
->getMarkLivePass(G
->getTargetTriple()))
380 Config
.PrePrunePasses
.push_back(std::move(MarkLive
));
382 Config
.PrePrunePasses
.push_back(markAllSymbolsLive
);
384 // Add an in-place GOT/Stubs/TLSInfoEntry build pass.
385 Config
.PostPrunePasses
.push_back(buildTables_ELF_x86_64
);
387 // Resolve any external section start / end symbols.
388 Config
.PostAllocationPasses
.push_back(
389 createDefineExternalSectionStartAndEndSymbolsPass(
390 identifyELFSectionStartAndEndSymbols
));
392 // Add GOT/Stubs optimizer pass.
393 Config
.PreFixupPasses
.push_back(x86_64::optimizeGOTAndStubAccesses
);
396 if (auto Err
= Ctx
->modifyPassConfig(*G
, Config
))
397 return Ctx
->notifyFailed(std::move(Err
));
399 ELFJITLinker_x86_64::link(std::move(Ctx
), std::move(G
), std::move(Config
));
401 } // end namespace jitlink
402 } // end namespace llvm