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/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" 20 21 #include "DefineExternalSectionStartAndEndSymbols.h" 22 #include "EHFrameSupportImpl.h" 23 #include "ELFLinkGraphBuilder.h" 24 #include "JITLinkGeneric.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 ELFGOTSymbolName = "_GLOBAL_OFFSET_TABLE_"; 35 constexpr StringRef ELFTLSInfoSectionName = "$__TLSINFO"; 36 37 class TLSInfoTableManager_ELF_x86_64 38 : public TableManager<TLSInfoTableManager_ELF_x86_64> { 39 public: 40 static const uint8_t TLSInfoEntryContent[16]; 41 42 static StringRef getSectionName() { return ELFTLSInfoSectionName; } 43 44 bool visitEdge(LinkGraph &G, Block *B, Edge &E) { 45 if (E.getKind() == x86_64::RequestTLSDescInGOTAndTransformToDelta32) { 46 LLVM_DEBUG({ 47 dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at " 48 << formatv("{0:x}", B->getFixupAddress(E)) << " (" 49 << formatv("{0:x}", B->getAddress()) << " + " 50 << formatv("{0:x}", E.getOffset()) << ")\n"; 51 }); 52 E.setKind(x86_64::Delta32); 53 E.setTarget(getEntryForTarget(G, E.getTarget())); 54 return true; 55 } 56 return false; 57 } 58 59 Symbol &createEntry(LinkGraph &G, Symbol &Target) { 60 // the TLS Info entry's key value will be written by the fixTLVSectionByName 61 // pass, so create mutable content. 62 auto &TLSInfoEntry = G.createMutableContentBlock( 63 getTLSInfoSection(G), G.allocateContent(getTLSInfoEntryContent()), 64 orc::ExecutorAddr(), 8, 0); 65 TLSInfoEntry.addEdge(x86_64::Pointer64, 8, Target, 0); 66 return G.addAnonymousSymbol(TLSInfoEntry, 0, 16, false, false); 67 } 68 69 private: 70 Section &getTLSInfoSection(LinkGraph &G) { 71 if (!TLSInfoTable) 72 TLSInfoTable = &G.createSection(ELFTLSInfoSectionName, MemProt::Read); 73 return *TLSInfoTable; 74 } 75 76 ArrayRef<char> getTLSInfoEntryContent() const { 77 return {reinterpret_cast<const char *>(TLSInfoEntryContent), 78 sizeof(TLSInfoEntryContent)}; 79 } 80 81 Section *TLSInfoTable = nullptr; 82 }; 83 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*/ 87 }; 88 89 Error buildTables_ELF_x86_64(LinkGraph &G) { 90 LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n"); 91 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(); 97 } 98 } // namespace 99 100 static const char *getELFX86_64RelocName(uint32_t Type) { 101 switch (Type) { 102 #define ELF_RELOC(Name, Number) \ 103 case Number: \ 104 return #Name; 105 #include "llvm/BinaryFormat/ELFRelocs/x86_64.def" 106 #undef ELF_RELOC 107 } 108 return "Unrecognized ELF/x86-64 relocation type"; 109 } 110 111 namespace llvm { 112 namespace jitlink { 113 114 // This should become a template as the ELFFile is so a lot of this could become 115 // generic 116 class ELFLinkGraphBuilder_x86_64 : public ELFLinkGraphBuilder<object::ELF64LE> { 117 private: 118 using ELFT = object::ELF64LE; 119 120 static Expected<ELF_x86_64_Edges::ELFX86RelocationKind> 121 getRelocationKind(const uint32_t Type) { 122 switch (Type) { 123 case ELF::R_X86_64_32S: 124 return ELF_x86_64_Edges::ELFX86RelocationKind::Pointer32Signed; 125 case ELF::R_X86_64_PC32: 126 return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel32; 127 case ELF::R_X86_64_PC64: 128 case ELF::R_X86_64_GOTPC64: 129 return ELF_x86_64_Edges::ELFX86RelocationKind::Delta64; 130 case ELF::R_X86_64_64: 131 return ELF_x86_64_Edges::ELFX86RelocationKind::Pointer64; 132 case ELF::R_X86_64_GOTPCREL: 133 return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel32GOTLoad; 134 case ELF::R_X86_64_GOTPCRELX: 135 return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel32GOTLoadRelaxable; 136 case ELF::R_X86_64_REX_GOTPCRELX: 137 return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel32REXGOTLoadRelaxable; 138 case ELF::R_X86_64_GOTPCREL64: 139 return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel64GOT; 140 case ELF::R_X86_64_GOT64: 141 return ELF_x86_64_Edges::ELFX86RelocationKind::GOT64; 142 case ELF::R_X86_64_GOTOFF64: 143 return ELF_x86_64_Edges::ELFX86RelocationKind::GOTOFF64; 144 case ELF::R_X86_64_PLT32: 145 return ELF_x86_64_Edges::ELFX86RelocationKind::Branch32; 146 case ELF::R_X86_64_TLSGD: 147 return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel32TLV; 148 } 149 return make_error<JITLinkError>("Unsupported x86-64 relocation type " + 150 formatv("{0:d}: ", Type) + 151 getELFX86_64RelocName(Type)); 152 } 153 154 Error addRelocations() override { 155 LLVM_DEBUG(dbgs() << "Processing relocations:\n"); 156 157 using Base = ELFLinkGraphBuilder<ELFT>; 158 using Self = ELFLinkGraphBuilder_x86_64; 159 for (const auto &RelSect : Base::Sections) { 160 // Validate the section to read relocation entries from. 161 if (RelSect.sh_type == ELF::SHT_REL) 162 return make_error<StringError>( 163 "No SHT_REL in valid x64 ELF object files", 164 inconvertibleErrorCode()); 165 166 if (Error Err = Base::forEachRelocation(RelSect, this, 167 &Self::addSingleRelocation)) 168 return Err; 169 } 170 171 return Error::success(); 172 } 173 174 Error addSingleRelocation(const typename ELFT::Rela &Rel, 175 const typename ELFT::Shdr &FixupSection, 176 Block &BlockToFix) { 177 using Base = ELFLinkGraphBuilder<ELFT>; 178 179 uint32_t SymbolIndex = Rel.getSymbol(false); 180 auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec); 181 if (!ObjSymbol) 182 return ObjSymbol.takeError(); 183 184 Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex); 185 if (!GraphSymbol) 186 return make_error<StringError>( 187 formatv("Could not find symbol at given index, did you add it to " 188 "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}", 189 SymbolIndex, (*ObjSymbol)->st_shndx, 190 Base::GraphSymbols.size()), 191 inconvertibleErrorCode()); 192 193 // Validate the relocation kind. 194 auto ELFRelocKind = getRelocationKind(Rel.getType(false)); 195 if (!ELFRelocKind) 196 return ELFRelocKind.takeError(); 197 198 int64_t Addend = Rel.r_addend; 199 Edge::Kind Kind = Edge::Invalid; 200 switch (*ELFRelocKind) { 201 case PCRel32: 202 Kind = x86_64::Delta32; 203 break; 204 case Delta64: 205 Kind = x86_64::Delta64; 206 break; 207 case Pointer32Signed: 208 Kind = x86_64::Pointer32Signed; 209 break; 210 case Pointer64: 211 Kind = x86_64::Pointer64; 212 break; 213 case PCRel32GOTLoad: { 214 Kind = x86_64::RequestGOTAndTransformToDelta32; 215 break; 216 } 217 case PCRel32REXGOTLoadRelaxable: { 218 Kind = x86_64::RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable; 219 Addend = 0; 220 break; 221 } 222 case PCRel32TLV: { 223 Kind = x86_64::RequestTLSDescInGOTAndTransformToDelta32; 224 break; 225 } 226 case PCRel32GOTLoadRelaxable: { 227 Kind = x86_64::RequestGOTAndTransformToPCRel32GOTLoadRelaxable; 228 Addend = 0; 229 break; 230 } 231 case PCRel64GOT: { 232 Kind = x86_64::RequestGOTAndTransformToDelta64; 233 break; 234 } 235 case GOT64: { 236 Kind = x86_64::RequestGOTAndTransformToDelta64FromGOT; 237 break; 238 } 239 case GOTOFF64: { 240 Kind = x86_64::Delta64FromGOT; 241 break; 242 } 243 case Branch32: { 244 Kind = x86_64::BranchPCRel32; 245 // BranchPCRel32 implicitly handles the '-4' PC adjustment, so we have to 246 // adjust the addend by '+4' to compensate. 247 Addend += 4; 248 break; 249 } 250 } 251 252 auto FixupAddress = orc::ExecutorAddr(FixupSection.sh_addr) + Rel.r_offset; 253 Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress(); 254 Edge GE(Kind, Offset, *GraphSymbol, Addend); 255 LLVM_DEBUG({ 256 dbgs() << " "; 257 printEdge(dbgs(), BlockToFix, GE, x86_64::getEdgeKindName(Kind)); 258 dbgs() << "\n"; 259 }); 260 261 BlockToFix.addEdge(std::move(GE)); 262 return Error::success(); 263 } 264 265 public: 266 ELFLinkGraphBuilder_x86_64(StringRef FileName, 267 const object::ELFFile<object::ELF64LE> &Obj) 268 : ELFLinkGraphBuilder(Obj, Triple("x86_64-unknown-linux"), FileName, 269 x86_64::getEdgeKindName) {} 270 }; 271 272 class ELFJITLinker_x86_64 : public JITLinker<ELFJITLinker_x86_64> { 273 friend class JITLinker<ELFJITLinker_x86_64>; 274 275 public: 276 ELFJITLinker_x86_64(std::unique_ptr<JITLinkContext> Ctx, 277 std::unique_ptr<LinkGraph> G, 278 PassConfiguration PassConfig) 279 : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) { 280 getPassConfig().PostAllocationPasses.push_back( 281 [this](LinkGraph &G) { return getOrCreateGOTSymbol(G); }); 282 } 283 284 private: 285 Symbol *GOTSymbol = nullptr; 286 287 Error getOrCreateGOTSymbol(LinkGraph &G) { 288 auto DefineExternalGOTSymbolIfPresent = 289 createDefineExternalSectionStartAndEndSymbolsPass( 290 [&](LinkGraph &LG, Symbol &Sym) -> SectionRangeSymbolDesc { 291 if (Sym.getName() == ELFGOTSymbolName) 292 if (auto *GOTSection = G.findSectionByName( 293 x86_64::GOTTableManager::getSectionName())) { 294 GOTSymbol = &Sym; 295 return {*GOTSection, true}; 296 } 297 return {}; 298 }); 299 300 // Try to attach _GLOBAL_OFFSET_TABLE_ to the GOT if it's defined as an 301 // external. 302 if (auto Err = DefineExternalGOTSymbolIfPresent(G)) 303 return Err; 304 305 // If we succeeded then we're done. 306 if (GOTSymbol) 307 return Error::success(); 308 309 // Otherwise look for a GOT section: If it already has a start symbol we'll 310 // record it, otherwise we'll create our own. 311 // If there's a GOT section but we didn't find an external GOT symbol... 312 if (auto *GOTSection = 313 G.findSectionByName(x86_64::GOTTableManager::getSectionName())) { 314 315 // Check for an existing defined symbol. 316 for (auto *Sym : GOTSection->symbols()) 317 if (Sym->getName() == ELFGOTSymbolName) { 318 GOTSymbol = Sym; 319 return Error::success(); 320 } 321 322 // If there's no defined symbol then create one. 323 SectionRange SR(*GOTSection); 324 if (SR.empty()) 325 GOTSymbol = 326 &G.addAbsoluteSymbol(ELFGOTSymbolName, orc::ExecutorAddr(), 0, 327 Linkage::Strong, Scope::Local, true); 328 else 329 GOTSymbol = 330 &G.addDefinedSymbol(*SR.getFirstBlock(), 0, ELFGOTSymbolName, 0, 331 Linkage::Strong, Scope::Local, false, true); 332 } 333 334 return Error::success(); 335 } 336 337 Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const { 338 return x86_64::applyFixup(G, B, E, GOTSymbol); 339 } 340 }; 341 342 Expected<std::unique_ptr<LinkGraph>> 343 createLinkGraphFromELFObject_x86_64(MemoryBufferRef ObjectBuffer) { 344 LLVM_DEBUG({ 345 dbgs() << "Building jitlink graph for new input " 346 << ObjectBuffer.getBufferIdentifier() << "...\n"; 347 }); 348 349 auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer); 350 if (!ELFObj) 351 return ELFObj.takeError(); 352 353 auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj); 354 return ELFLinkGraphBuilder_x86_64((*ELFObj)->getFileName(), 355 ELFObjFile.getELFFile()) 356 .buildGraph(); 357 } 358 359 static SectionRangeSymbolDesc 360 identifyELFSectionStartAndEndSymbols(LinkGraph &G, Symbol &Sym) { 361 constexpr StringRef StartSymbolPrefix = "__start"; 362 constexpr StringRef EndSymbolPrefix = "__end"; 363 364 auto SymName = Sym.getName(); 365 if (SymName.startswith(StartSymbolPrefix)) { 366 if (auto *Sec = 367 G.findSectionByName(SymName.drop_front(StartSymbolPrefix.size()))) 368 return {*Sec, true}; 369 } else if (SymName.startswith(EndSymbolPrefix)) { 370 if (auto *Sec = 371 G.findSectionByName(SymName.drop_front(EndSymbolPrefix.size()))) 372 return {*Sec, false}; 373 } 374 return {}; 375 } 376 377 void link_ELF_x86_64(std::unique_ptr<LinkGraph> G, 378 std::unique_ptr<JITLinkContext> Ctx) { 379 PassConfiguration Config; 380 381 if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) { 382 383 Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame")); 384 Config.PrePrunePasses.push_back(EHFrameEdgeFixer( 385 ".eh_frame", x86_64::PointerSize, x86_64::Pointer32, x86_64::Pointer64, 386 x86_64::Delta32, x86_64::Delta64, x86_64::NegDelta32)); 387 Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame")); 388 389 // Construct a JITLinker and run the link function. 390 // Add a mark-live pass. 391 if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple())) 392 Config.PrePrunePasses.push_back(std::move(MarkLive)); 393 else 394 Config.PrePrunePasses.push_back(markAllSymbolsLive); 395 396 // Add an in-place GOT/Stubs/TLSInfoEntry build pass. 397 Config.PostPrunePasses.push_back(buildTables_ELF_x86_64); 398 399 // Resolve any external section start / end symbols. 400 Config.PostAllocationPasses.push_back( 401 createDefineExternalSectionStartAndEndSymbolsPass( 402 identifyELFSectionStartAndEndSymbols)); 403 404 // Add GOT/Stubs optimizer pass. 405 Config.PreFixupPasses.push_back(x86_64::optimizeGOTAndStubAccesses); 406 } 407 408 if (auto Err = Ctx->modifyPassConfig(*G, Config)) 409 return Ctx->notifyFailed(std::move(Err)); 410 411 ELFJITLinker_x86_64::link(std::move(Ctx), std::move(G), std::move(Config)); 412 } 413 const char *getELFX86RelocationKindName(Edge::Kind R) { 414 switch (R) { 415 case Branch32: 416 return "Branch32"; 417 case Pointer32Signed: 418 return "Pointer32Signed"; 419 case Pointer64: 420 return "Pointer64"; 421 case PCRel32: 422 return "PCRel32"; 423 case PCRel32GOTLoad: 424 return "PCRel32GOTLoad"; 425 case PCRel32GOTLoadRelaxable: 426 return "PCRel32GOTLoadRelaxable"; 427 case PCRel32REXGOTLoadRelaxable: 428 return "PCRel32REXGOTLoad"; 429 case PCRel64GOT: 430 return "PCRel64GOT"; 431 case Delta64: 432 return "Delta64"; 433 case GOT64: 434 return "GOT64"; 435 case GOTOFF64: 436 return "GOTOFF64"; 437 } 438 return getGenericEdgeKindName(static_cast<Edge::Kind>(R)); 439 } 440 } // end namespace jitlink 441 } // end namespace llvm 442