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