1 //===---- ELF_x86_64.cpp -JIT linker implementation for ELF/x86-64 ----===// 2 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // ELF/x86-64 jit-link implementation. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h" 14 #include "llvm/ExecutionEngine/JITLink/JITLink.h" 15 #include "llvm/ExecutionEngine/JITLink/x86_64.h" 16 #include "llvm/Object/ELFObjectFile.h" 17 #include "llvm/Support/Endian.h" 18 19 #include "DefineExternalSectionStartAndEndSymbols.h" 20 #include "EHFrameSupportImpl.h" 21 #include "ELFLinkGraphBuilder.h" 22 #include "JITLinkGeneric.h" 23 #include "PerGraphGOTAndPLTStubsBuilder.h" 24 #include "TableManager.h" 25 26 #define DEBUG_TYPE "jitlink" 27 28 using namespace llvm; 29 using namespace llvm::jitlink; 30 using namespace llvm::jitlink::ELF_x86_64_Edges; 31 32 namespace { 33 34 constexpr StringRef ELFGOTSectionName = "$__GOT"; 35 constexpr StringRef ELFGOTSymbolName = "_GLOBAL_OFFSET_TABLE_"; 36 constexpr StringRef ELFTLSInfoSectionName = "$__TLSINFO"; 37 38 class GOTTableManager_ELF_x86_64 39 : public TableManager<GOTTableManager_ELF_x86_64> { 40 public: 41 static const uint8_t NullGOTEntryContent[8]; 42 43 // Nice name for table 44 StringRef getTableName() { return "GOT"; } 45 46 bool fixEdgeKind(LinkGraph &G, Block *B, Edge &E) { 47 Edge::Kind KindToSet = E.getKind(); 48 switch (E.getKind()) { 49 case x86_64::Delta64FromGOT: { 50 // we need to make sure that the GOT section exists, but don't otherwise 51 // need to fix up this edge 52 getGOTSection(G); 53 return false; 54 } 55 case x86_64::RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable: 56 KindToSet = x86_64::PCRel32GOTLoadREXRelaxable; 57 break; 58 case x86_64::RequestGOTAndTransformToPCRel32GOTLoadRelaxable: 59 KindToSet = x86_64::PCRel32GOTLoadRelaxable; 60 break; 61 case x86_64::RequestGOTAndTransformToDelta64: 62 KindToSet = x86_64::Delta64; 63 break; 64 case x86_64::RequestGOTAndTransformToDelta64FromGOT: 65 KindToSet = x86_64::Delta64FromGOT; 66 break; 67 case x86_64::RequestGOTAndTransformToDelta32: 68 KindToSet = x86_64::Delta32; 69 break; 70 default: 71 return false; 72 } 73 LLVM_DEBUG({ 74 dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at " 75 << formatv("{0:x}", B->getFixupAddress(E)) << " (" 76 << formatv("{0:x}", B->getAddress()) << " + " 77 << formatv("{0:x}", E.getOffset()) << ")\n"; 78 }); 79 E.setKind(KindToSet); 80 return true; 81 } 82 83 Symbol &createEntry(LinkGraph &G, Symbol &Target) { 84 auto &GOTEntryBlock = G.createContentBlock( 85 getGOTSection(G), getGOTEntryBlockContent(), 0, 8, 0); 86 GOTEntryBlock.addEdge(x86_64::Pointer64, 0, Target, 0); 87 return G.addAnonymousSymbol(GOTEntryBlock, 0, 8, false, false); 88 } 89 90 private: 91 Section &getGOTSection(LinkGraph &G) { 92 if (!GOTSection) 93 GOTSection = &G.createSection(ELFGOTSectionName, MemProt::Read); 94 return *GOTSection; 95 } 96 ArrayRef<char> getGOTEntryBlockContent() const { 97 return {reinterpret_cast<const char *>(NullGOTEntryContent), 98 sizeof(NullGOTEntryContent)}; 99 } 100 Section *GOTSection = nullptr; 101 }; 102 const uint8_t GOTTableManager_ELF_x86_64::NullGOTEntryContent[8] = { 103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 104 105 class PLTTableManager_ELF_x86_64 106 : public TableManager<PLTTableManager_ELF_x86_64> { 107 public: 108 PLTTableManager_ELF_x86_64(GOTTableManager_ELF_x86_64 &GOTTable) 109 : GOTTable(GOTTable) {} 110 111 StringRef getTableName() { return "PLT"; } 112 113 static const uint8_t StubContent[6]; 114 bool fixEdgeKind(LinkGraph &G, Block *B, Edge &E) { 115 if (E.getKind() == x86_64::BranchPCRel32 && !E.getTarget().isDefined()) { 116 LLVM_DEBUG({ 117 dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at " 118 << formatv("{0:x}", B->getFixupAddress(E)) << " (" 119 << formatv("{0:x}", B->getAddress()) << " + " 120 << formatv("{0:x}", E.getOffset()) << ")\n"; 121 }); 122 // Set the edge kind to Branch32ToPtrJumpStubBypassable to enable it to 123 // be optimized when the target is in-range. 124 E.setKind(x86_64::BranchPCRel32ToPtrJumpStubBypassable); 125 return true; 126 } 127 return false; 128 } 129 130 Symbol &createEntry(LinkGraph &G, Symbol &Target) { 131 auto &StubContentBlock = G.createContentBlock( 132 getStubsSection(G), getStubBlockContent(), 0, 1, 0); 133 // Re-use GOT entries for stub targets. 134 auto &GOTEntrySymbol = GOTTable.getEntryForTarget(G, Target); 135 StubContentBlock.addEdge(x86_64::Delta32, 2, GOTEntrySymbol, -4); 136 return G.addAnonymousSymbol(StubContentBlock, 0, 6, true, false); 137 } 138 139 private: 140 Section &getStubsSection(LinkGraph &G) { 141 if (!StubsSection) 142 StubsSection = 143 &G.createSection("$__STUBS", MemProt::Read | MemProt::Exec); 144 return *StubsSection; 145 } 146 147 ArrayRef<char> getStubBlockContent() { 148 return {reinterpret_cast<const char *>(StubContent), sizeof(StubContent)}; 149 } 150 151 Section *StubsSection = nullptr; 152 GOTTableManager_ELF_x86_64 &GOTTable; 153 }; 154 const uint8_t PLTTableManager_ELF_x86_64::StubContent[6] = {0xFF, 0x25, 0x00, 155 0x00, 0x00, 0x00}; 156 157 class TLSInfoTableManager_ELF_x86_64 158 : public TableManager<TLSInfoTableManager_ELF_x86_64> { 159 public: 160 static const uint8_t TLSInfoEntryContent[16]; 161 162 StringRef getTableName() { return "TLSInfo"; } 163 164 bool fixEdgeKind(LinkGraph &G, Block *B, Edge &E) { 165 if (E.getKind() == x86_64::RequestTLSDescInGOTAndTransformToDelta32) { 166 LLVM_DEBUG({ 167 dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at " 168 << formatv("{0:x}", B->getFixupAddress(E)) << " (" 169 << formatv("{0:x}", B->getAddress()) << " + " 170 << formatv("{0:x}", E.getOffset()) << ")\n"; 171 }); 172 E.setKind(x86_64::Delta32); 173 return true; 174 } 175 return false; 176 } 177 178 Symbol &createEntry(LinkGraph &G, Symbol &Target) { 179 // the TLS Info entry's key value will be written by the fixTLVSectionByName 180 // pass, so create mutable content. 181 auto &TLSInfoEntry = G.createMutableContentBlock( 182 getTLSInfoSection(G), G.allocateContent(getTLSInfoEntryContent()), 0, 8, 183 0); 184 TLSInfoEntry.addEdge(x86_64::Pointer64, 8, Target, 0); 185 return G.addAnonymousSymbol(TLSInfoEntry, 0, 16, false, false); 186 } 187 188 private: 189 Section &getTLSInfoSection(LinkGraph &G) { 190 if (!TLSInfoTable) 191 TLSInfoTable = &G.createSection(ELFTLSInfoSectionName, MemProt::Read); 192 return *TLSInfoTable; 193 } 194 195 ArrayRef<char> getTLSInfoEntryContent() const { 196 return {reinterpret_cast<const char *>(TLSInfoEntryContent), 197 sizeof(TLSInfoEntryContent)}; 198 } 199 200 Section *TLSInfoTable = nullptr; 201 }; 202 203 const uint8_t TLSInfoTableManager_ELF_x86_64::TLSInfoEntryContent[16] = { 204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*pthread key */ 205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /*data address*/ 206 }; 207 208 Error buildTables_ELF_x86_64(LinkGraph &G) { 209 LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n"); 210 211 GOTTableManager_ELF_x86_64 GOT; 212 PLTTableManager_ELF_x86_64 PLT(GOT); 213 TLSInfoTableManager_ELF_x86_64 TLSInfo; 214 visitExistingEdges(G, GOT, PLT, TLSInfo); 215 return Error::success(); 216 } 217 } // namespace 218 219 static const char *getELFX86_64RelocName(uint32_t Type) { 220 switch (Type) { 221 #define ELF_RELOC(Name, Number) \ 222 case Number: \ 223 return #Name; 224 #include "llvm/BinaryFormat/ELFRelocs/x86_64.def" 225 #undef ELF_RELOC 226 } 227 return "Unrecognized ELF/x86-64 relocation type"; 228 } 229 230 namespace llvm { 231 namespace jitlink { 232 233 // This should become a template as the ELFFile is so a lot of this could become 234 // generic 235 class ELFLinkGraphBuilder_x86_64 : public ELFLinkGraphBuilder<object::ELF64LE> { 236 private: 237 using ELFT = object::ELF64LE; 238 239 static Expected<ELF_x86_64_Edges::ELFX86RelocationKind> 240 getRelocationKind(const uint32_t Type) { 241 switch (Type) { 242 case ELF::R_X86_64_32S: 243 return ELF_x86_64_Edges::ELFX86RelocationKind::Pointer32Signed; 244 case ELF::R_X86_64_PC32: 245 return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel32; 246 case ELF::R_X86_64_PC64: 247 case ELF::R_X86_64_GOTPC64: 248 return ELF_x86_64_Edges::ELFX86RelocationKind::Delta64; 249 case ELF::R_X86_64_64: 250 return ELF_x86_64_Edges::ELFX86RelocationKind::Pointer64; 251 case ELF::R_X86_64_GOTPCREL: 252 return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel32GOTLoad; 253 case ELF::R_X86_64_GOTPCRELX: 254 return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel32GOTLoadRelaxable; 255 case ELF::R_X86_64_REX_GOTPCRELX: 256 return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel32REXGOTLoadRelaxable; 257 case ELF::R_X86_64_GOTPCREL64: 258 return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel64GOT; 259 case ELF::R_X86_64_GOT64: 260 return ELF_x86_64_Edges::ELFX86RelocationKind::GOT64; 261 case ELF::R_X86_64_GOTOFF64: 262 return ELF_x86_64_Edges::ELFX86RelocationKind::GOTOFF64; 263 case ELF::R_X86_64_PLT32: 264 return ELF_x86_64_Edges::ELFX86RelocationKind::Branch32; 265 case ELF::R_X86_64_TLSGD: 266 return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel32TLV; 267 } 268 return make_error<JITLinkError>("Unsupported x86-64 relocation type " + 269 formatv("{0:d}: ", Type) + 270 getELFX86_64RelocName(Type)); 271 } 272 273 Error addRelocations() override { 274 LLVM_DEBUG(dbgs() << "Processing relocations:\n"); 275 276 using Base = ELFLinkGraphBuilder<ELFT>; 277 using Self = ELFLinkGraphBuilder_x86_64; 278 for (const auto &RelSect : Base::Sections) { 279 // Sanity check the section to read relocation entries from. 280 if (RelSect.sh_type == ELF::SHT_REL) 281 return make_error<StringError>( 282 "No SHT_REL in valid x64 ELF object files", 283 inconvertibleErrorCode()); 284 285 if (Error Err = Base::forEachRelocation(RelSect, this, 286 &Self::addSingleRelocation)) 287 return Err; 288 } 289 290 return Error::success(); 291 } 292 293 Error addSingleRelocation(const typename ELFT::Rela &Rel, 294 const typename ELFT::Shdr &FixupSection, 295 Section &GraphSection) { 296 using Base = ELFLinkGraphBuilder<ELFT>; 297 298 uint32_t SymbolIndex = Rel.getSymbol(false); 299 auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec); 300 if (!ObjSymbol) 301 return ObjSymbol.takeError(); 302 303 Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex); 304 if (!GraphSymbol) 305 return make_error<StringError>( 306 formatv("Could not find symbol at given index, did you add it to " 307 "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}", 308 SymbolIndex, (*ObjSymbol)->st_shndx, 309 Base::GraphSymbols.size()), 310 inconvertibleErrorCode()); 311 312 // Sanity check the relocation kind. 313 auto ELFRelocKind = getRelocationKind(Rel.getType(false)); 314 if (!ELFRelocKind) 315 return ELFRelocKind.takeError(); 316 317 int64_t Addend = Rel.r_addend; 318 Edge::Kind Kind = Edge::Invalid; 319 switch (*ELFRelocKind) { 320 case PCRel32: 321 Kind = x86_64::Delta32; 322 break; 323 case Delta64: 324 Kind = x86_64::Delta64; 325 break; 326 case Pointer32Signed: 327 Kind = x86_64::Pointer32Signed; 328 break; 329 case Pointer64: 330 Kind = x86_64::Pointer64; 331 break; 332 case PCRel32GOTLoad: { 333 Kind = x86_64::RequestGOTAndTransformToDelta32; 334 break; 335 } 336 case PCRel32REXGOTLoadRelaxable: { 337 Kind = x86_64::RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable; 338 Addend = 0; 339 break; 340 } 341 case PCRel32TLV: { 342 Kind = x86_64::RequestTLSDescInGOTAndTransformToDelta32; 343 break; 344 } 345 case PCRel32GOTLoadRelaxable: { 346 Kind = x86_64::RequestGOTAndTransformToPCRel32GOTLoadRelaxable; 347 Addend = 0; 348 break; 349 } 350 case PCRel64GOT: { 351 Kind = x86_64::RequestGOTAndTransformToDelta64; 352 break; 353 } 354 case GOT64: { 355 Kind = x86_64::RequestGOTAndTransformToDelta64FromGOT; 356 break; 357 } 358 case GOTOFF64: { 359 Kind = x86_64::Delta64FromGOT; 360 break; 361 } 362 case Branch32: { 363 Kind = x86_64::BranchPCRel32; 364 Addend = 0; 365 break; 366 } 367 } 368 369 Block *BlockToFix = *(GraphSection.blocks().begin()); 370 JITTargetAddress FixupAddress = FixupSection.sh_addr + Rel.r_offset; 371 Edge::OffsetT Offset = FixupAddress - BlockToFix->getAddress(); 372 Edge GE(Kind, Offset, *GraphSymbol, Addend); 373 LLVM_DEBUG({ 374 dbgs() << " "; 375 printEdge(dbgs(), *BlockToFix, GE, getELFX86RelocationKindName(Kind)); 376 dbgs() << "\n"; 377 }); 378 379 BlockToFix->addEdge(std::move(GE)); 380 return Error::success(); 381 } 382 383 public: 384 ELFLinkGraphBuilder_x86_64(StringRef FileName, 385 const object::ELFFile<object::ELF64LE> &Obj) 386 : ELFLinkGraphBuilder(Obj, Triple("x86_64-unknown-linux"), FileName, 387 x86_64::getEdgeKindName) {} 388 }; 389 390 class ELFJITLinker_x86_64 : public JITLinker<ELFJITLinker_x86_64> { 391 friend class JITLinker<ELFJITLinker_x86_64>; 392 393 public: 394 ELFJITLinker_x86_64(std::unique_ptr<JITLinkContext> Ctx, 395 std::unique_ptr<LinkGraph> G, 396 PassConfiguration PassConfig) 397 : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) { 398 getPassConfig().PostAllocationPasses.push_back( 399 [this](LinkGraph &G) { return getOrCreateGOTSymbol(G); }); 400 } 401 402 private: 403 Symbol *GOTSymbol = nullptr; 404 405 Error getOrCreateGOTSymbol(LinkGraph &G) { 406 auto DefineExternalGOTSymbolIfPresent = 407 createDefineExternalSectionStartAndEndSymbolsPass( 408 [&](LinkGraph &LG, Symbol &Sym) -> SectionRangeSymbolDesc { 409 if (Sym.getName() == ELFGOTSymbolName) 410 if (auto *GOTSection = G.findSectionByName(ELFGOTSectionName)) { 411 GOTSymbol = &Sym; 412 return {*GOTSection, true}; 413 } 414 return {}; 415 }); 416 417 // Try to attach _GLOBAL_OFFSET_TABLE_ to the GOT if it's defined as an 418 // external. 419 if (auto Err = DefineExternalGOTSymbolIfPresent(G)) 420 return Err; 421 422 // If we succeeded then we're done. 423 if (GOTSymbol) 424 return Error::success(); 425 426 // Otherwise look for a GOT section: If it already has a start symbol we'll 427 // record it, otherwise we'll create our own. 428 // If there's a GOT section but we didn't find an external GOT symbol... 429 if (auto *GOTSection = G.findSectionByName(ELFGOTSectionName)) { 430 431 // Check for an existing defined symbol. 432 for (auto *Sym : GOTSection->symbols()) 433 if (Sym->getName() == ELFGOTSymbolName) { 434 GOTSymbol = Sym; 435 return Error::success(); 436 } 437 438 // If there's no defined symbol then create one. 439 SectionRange SR(*GOTSection); 440 if (SR.empty()) 441 GOTSymbol = &G.addAbsoluteSymbol(ELFGOTSymbolName, 0, 0, 442 Linkage::Strong, Scope::Local, true); 443 else 444 GOTSymbol = 445 &G.addDefinedSymbol(*SR.getFirstBlock(), 0, ELFGOTSymbolName, 0, 446 Linkage::Strong, Scope::Local, false, true); 447 } 448 449 return Error::success(); 450 } 451 452 Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const { 453 return x86_64::applyFixup(G, B, E, GOTSymbol); 454 } 455 }; 456 457 Expected<std::unique_ptr<LinkGraph>> 458 createLinkGraphFromELFObject_x86_64(MemoryBufferRef ObjectBuffer) { 459 LLVM_DEBUG({ 460 dbgs() << "Building jitlink graph for new input " 461 << ObjectBuffer.getBufferIdentifier() << "...\n"; 462 }); 463 464 auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer); 465 if (!ELFObj) 466 return ELFObj.takeError(); 467 468 auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj); 469 return ELFLinkGraphBuilder_x86_64((*ELFObj)->getFileName(), 470 ELFObjFile.getELFFile()) 471 .buildGraph(); 472 } 473 474 static SectionRangeSymbolDesc 475 identifyELFSectionStartAndEndSymbols(LinkGraph &G, Symbol &Sym) { 476 constexpr StringRef StartSymbolPrefix = "__start"; 477 constexpr StringRef EndSymbolPrefix = "__end"; 478 479 auto SymName = Sym.getName(); 480 if (SymName.startswith(StartSymbolPrefix)) { 481 if (auto *Sec = 482 G.findSectionByName(SymName.drop_front(StartSymbolPrefix.size()))) 483 return {*Sec, true}; 484 } else if (SymName.startswith(EndSymbolPrefix)) { 485 if (auto *Sec = 486 G.findSectionByName(SymName.drop_front(EndSymbolPrefix.size()))) 487 return {*Sec, false}; 488 } 489 return {}; 490 } 491 492 void link_ELF_x86_64(std::unique_ptr<LinkGraph> G, 493 std::unique_ptr<JITLinkContext> Ctx) { 494 PassConfiguration Config; 495 496 if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) { 497 498 Config.PrePrunePasses.push_back(EHFrameSplitter(".eh_frame")); 499 Config.PrePrunePasses.push_back( 500 EHFrameEdgeFixer(".eh_frame", x86_64::PointerSize, x86_64::Delta64, 501 x86_64::Delta32, x86_64::NegDelta32)); 502 Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame")); 503 504 // Construct a JITLinker and run the link function. 505 // Add a mark-live pass. 506 if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple())) 507 Config.PrePrunePasses.push_back(std::move(MarkLive)); 508 else 509 Config.PrePrunePasses.push_back(markAllSymbolsLive); 510 511 // Add an in-place GOT/Stubs/TLSInfoEntry build pass. 512 Config.PostPrunePasses.push_back(buildTables_ELF_x86_64); 513 514 // Resolve any external section start / end symbols. 515 Config.PostAllocationPasses.push_back( 516 createDefineExternalSectionStartAndEndSymbolsPass( 517 identifyELFSectionStartAndEndSymbols)); 518 519 // Add GOT/Stubs optimizer pass. 520 Config.PreFixupPasses.push_back(x86_64::optimize_x86_64_GOTAndStubs); 521 } 522 523 if (auto Err = Ctx->modifyPassConfig(*G, Config)) 524 return Ctx->notifyFailed(std::move(Err)); 525 526 ELFJITLinker_x86_64::link(std::move(Ctx), std::move(G), std::move(Config)); 527 } 528 const char *getELFX86RelocationKindName(Edge::Kind R) { 529 switch (R) { 530 case Branch32: 531 return "Branch32"; 532 case Pointer32Signed: 533 return "Pointer32Signed"; 534 case Pointer64: 535 return "Pointer64"; 536 case PCRel32: 537 return "PCRel32"; 538 case PCRel32GOTLoad: 539 return "PCRel32GOTLoad"; 540 case PCRel32GOTLoadRelaxable: 541 return "PCRel32GOTLoadRelaxable"; 542 case PCRel32REXGOTLoadRelaxable: 543 return "PCRel32REXGOTLoad"; 544 case PCRel64GOT: 545 return "PCRel64GOT"; 546 case Delta64: 547 return "Delta64"; 548 case GOT64: 549 return "GOT64"; 550 case GOTOFF64: 551 return "GOTOFF64"; 552 } 553 return getGenericEdgeKindName(static_cast<Edge::Kind>(R)); 554 } 555 } // end namespace jitlink 556 } // end namespace llvm 557