1 //===------- ELF_ppc64.cpp -JIT linker implementation for ELF/ppc64 -------===// 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/ppc64 jit-link implementation. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/ExecutionEngine/JITLink/ELF_ppc64.h" 14 #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h" 15 #include "llvm/ExecutionEngine/JITLink/TableManager.h" 16 #include "llvm/ExecutionEngine/JITLink/ppc64.h" 17 #include "llvm/Object/ELFObjectFile.h" 18 #include "llvm/Support/Endian.h" 19 20 #include "EHFrameSupportImpl.h" 21 #include "ELFLinkGraphBuilder.h" 22 #include "JITLinkGeneric.h" 23 24 #define DEBUG_TYPE "jitlink" 25 26 namespace { 27 28 using namespace llvm; 29 using namespace llvm::jitlink; 30 31 constexpr StringRef ELFTOCSymbolName = ".TOC."; 32 constexpr StringRef TOCSymbolAliasIdent = "__TOC__"; 33 constexpr uint64_t ELFTOCBaseOffset = 0x8000; 34 constexpr StringRef ELFTLSInfoSectionName = "$__TLSINFO"; 35 36 template <support::endianness Endianness> 37 class TLSInfoTableManager_ELF_ppc64 38 : public TableManager<TLSInfoTableManager_ELF_ppc64<Endianness>> { 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 Edge::Kind K = E.getKind(); 46 if (K == ppc64::RequestTLSDescInGOTAndTransformToTOCDelta16HA) { 47 E.setKind(ppc64::TOCDelta16HA); 48 E.setTarget(this->getEntryForTarget(G, E.getTarget())); 49 return true; 50 } 51 if (K == ppc64::RequestTLSDescInGOTAndTransformToTOCDelta16LO) { 52 E.setKind(ppc64::TOCDelta16LO); 53 E.setTarget(this->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 61 // `fixTLVSectionsAndEdges`, so create mutable content. 62 auto &TLSInfoEntry = G.createMutableContentBlock( 63 getTLSInfoSection(G), G.allocateContent(getTLSInfoEntryContent()), 64 orc::ExecutorAddr(), 8, 0); 65 TLSInfoEntry.addEdge(ppc64::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 = 73 &G.createSection(ELFTLSInfoSectionName, orc::MemProt::Read); 74 return *TLSInfoTable; 75 } 76 77 ArrayRef<char> getTLSInfoEntryContent() const { 78 return {reinterpret_cast<const char *>(TLSInfoEntryContent), 79 sizeof(TLSInfoEntryContent)}; 80 } 81 82 Section *TLSInfoTable = nullptr; 83 }; 84 85 template <> 86 const uint8_t TLSInfoTableManager_ELF_ppc64< 87 llvm::endianness::little>::TLSInfoEntryContent[16] = { 88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*pthread key */ 89 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /*data address*/ 90 }; 91 92 template <> 93 const uint8_t TLSInfoTableManager_ELF_ppc64< 94 llvm::endianness::big>::TLSInfoEntryContent[16] = { 95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*pthread key */ 96 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /*data address*/ 97 }; 98 99 template <support::endianness Endianness> 100 Symbol &createELFGOTHeader(LinkGraph &G, 101 ppc64::TOCTableManager<Endianness> &TOC) { 102 Symbol *TOCSymbol = nullptr; 103 104 for (Symbol *Sym : G.defined_symbols()) 105 if (LLVM_UNLIKELY(Sym->getName() == ELFTOCSymbolName)) { 106 TOCSymbol = Sym; 107 break; 108 } 109 110 if (LLVM_LIKELY(TOCSymbol == nullptr)) { 111 for (Symbol *Sym : G.external_symbols()) 112 if (Sym->getName() == ELFTOCSymbolName) { 113 TOCSymbol = Sym; 114 break; 115 } 116 } 117 118 if (!TOCSymbol) 119 TOCSymbol = &G.addExternalSymbol(ELFTOCSymbolName, 0, false); 120 121 return TOC.getEntryForTarget(G, *TOCSymbol); 122 } 123 124 // Register preexisting GOT entries with TOC table manager. 125 template <support::endianness Endianness> 126 inline void 127 registerExistingGOTEntries(LinkGraph &G, 128 ppc64::TOCTableManager<Endianness> &TOC) { 129 auto isGOTEntry = [](const Edge &E) { 130 return E.getKind() == ppc64::Pointer64 && E.getTarget().isExternal(); 131 }; 132 if (Section *dotTOCSection = G.findSectionByName(".toc")) { 133 for (Block *B : dotTOCSection->blocks()) 134 for (Edge &E : B->edges()) 135 if (isGOTEntry(E)) 136 TOC.registerPreExistingEntry(E.getTarget(), 137 G.addAnonymousSymbol(*B, E.getOffset(), 138 G.getPointerSize(), 139 false, false)); 140 } 141 } 142 143 template <support::endianness Endianness> 144 Error buildTables_ELF_ppc64(LinkGraph &G) { 145 LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n"); 146 ppc64::TOCTableManager<Endianness> TOC; 147 // Before visiting edges, we create a header containing the address of TOC 148 // base as ELFABIv2 suggests: 149 // > The GOT consists of an 8-byte header that contains the TOC base (the 150 // first TOC base when multiple TOCs are present), followed by an array of 151 // 8-byte addresses. 152 createELFGOTHeader(G, TOC); 153 154 // There might be compiler-generated GOT entries in ELF relocatable file. 155 registerExistingGOTEntries(G, TOC); 156 157 ppc64::PLTTableManager<Endianness> PLT(TOC); 158 TLSInfoTableManager_ELF_ppc64<Endianness> TLSInfo; 159 visitExistingEdges(G, TOC, PLT, TLSInfo); 160 161 // After visiting edges in LinkGraph, we have GOT entries built in the 162 // synthesized section. 163 // Merge sections included in TOC into synthesized TOC section, 164 // thus TOC is compact and reducing chances of relocation 165 // overflow. 166 if (Section *TOCSection = G.findSectionByName(TOC.getSectionName())) { 167 // .got and .plt are not normally present in a relocatable object file 168 // because they are linker generated. 169 if (Section *gotSection = G.findSectionByName(".got")) 170 G.mergeSections(*TOCSection, *gotSection); 171 if (Section *tocSection = G.findSectionByName(".toc")) 172 G.mergeSections(*TOCSection, *tocSection); 173 if (Section *sdataSection = G.findSectionByName(".sdata")) 174 G.mergeSections(*TOCSection, *sdataSection); 175 if (Section *sbssSection = G.findSectionByName(".sbss")) 176 G.mergeSections(*TOCSection, *sbssSection); 177 // .tocbss no longer appears in ELFABIv2. Leave it here to be compatible 178 // with rtdyld. 179 if (Section *tocbssSection = G.findSectionByName(".tocbss")) 180 G.mergeSections(*TOCSection, *tocbssSection); 181 if (Section *pltSection = G.findSectionByName(".plt")) 182 G.mergeSections(*TOCSection, *pltSection); 183 } 184 185 return Error::success(); 186 } 187 188 } // namespace 189 190 namespace llvm::jitlink { 191 192 template <support::endianness Endianness> 193 class ELFLinkGraphBuilder_ppc64 194 : public ELFLinkGraphBuilder<object::ELFType<Endianness, true>> { 195 private: 196 using ELFT = object::ELFType<Endianness, true>; 197 using Base = ELFLinkGraphBuilder<ELFT>; 198 199 using Base::G; // Use LinkGraph pointer from base class. 200 201 Error addRelocations() override { 202 LLVM_DEBUG(dbgs() << "Processing relocations:\n"); 203 204 using Self = ELFLinkGraphBuilder_ppc64<Endianness>; 205 for (const auto &RelSect : Base::Sections) { 206 // Validate the section to read relocation entries from. 207 if (RelSect.sh_type == ELF::SHT_REL) 208 return make_error<StringError>("No SHT_REL in valid " + 209 G->getTargetTriple().getArchName() + 210 " ELF object files", 211 inconvertibleErrorCode()); 212 213 if (Error Err = Base::forEachRelaRelocation(RelSect, this, 214 &Self::addSingleRelocation)) 215 return Err; 216 } 217 218 return Error::success(); 219 } 220 221 Error addSingleRelocation(const typename ELFT::Rela &Rel, 222 const typename ELFT::Shdr &FixupSection, 223 Block &BlockToFix) { 224 using Base = ELFLinkGraphBuilder<ELFT>; 225 auto ELFReloc = Rel.getType(false); 226 227 // R_PPC64_NONE is a no-op. 228 if (LLVM_UNLIKELY(ELFReloc == ELF::R_PPC64_NONE)) 229 return Error::success(); 230 231 // TLS model markers. We only support global-dynamic model now. 232 if (ELFReloc == ELF::R_PPC64_TLSGD) 233 return Error::success(); 234 if (ELFReloc == ELF::R_PPC64_TLSLD) 235 return make_error<StringError>("Local-dynamic TLS model is not supported", 236 inconvertibleErrorCode()); 237 238 auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec); 239 if (!ObjSymbol) 240 return ObjSymbol.takeError(); 241 242 uint32_t SymbolIndex = Rel.getSymbol(false); 243 Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex); 244 if (!GraphSymbol) 245 return make_error<StringError>( 246 formatv("Could not find symbol at given index, did you add it to " 247 "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}", 248 SymbolIndex, (*ObjSymbol)->st_shndx, 249 Base::GraphSymbols.size()), 250 inconvertibleErrorCode()); 251 252 int64_t Addend = Rel.r_addend; 253 orc::ExecutorAddr FixupAddress = 254 orc::ExecutorAddr(FixupSection.sh_addr) + Rel.r_offset; 255 Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress(); 256 Edge::Kind Kind = Edge::Invalid; 257 258 switch (ELFReloc) { 259 default: 260 return make_error<JITLinkError>( 261 "In " + G->getName() + ": Unsupported ppc64 relocation type " + 262 object::getELFRelocationTypeName(ELF::EM_PPC64, ELFReloc)); 263 case ELF::R_PPC64_ADDR64: 264 Kind = ppc64::Pointer64; 265 break; 266 case ELF::R_PPC64_ADDR32: 267 Kind = ppc64::Pointer32; 268 break; 269 case ELF::R_PPC64_ADDR16: 270 Kind = ppc64::Pointer16; 271 break; 272 case ELF::R_PPC64_ADDR16_DS: 273 Kind = ppc64::Pointer16DS; 274 break; 275 case ELF::R_PPC64_ADDR16_HA: 276 Kind = ppc64::Pointer16HA; 277 break; 278 case ELF::R_PPC64_ADDR16_HI: 279 Kind = ppc64::Pointer16HI; 280 break; 281 case ELF::R_PPC64_ADDR16_HIGH: 282 Kind = ppc64::Pointer16HIGH; 283 break; 284 case ELF::R_PPC64_ADDR16_HIGHA: 285 Kind = ppc64::Pointer16HIGHA; 286 break; 287 case ELF::R_PPC64_ADDR16_HIGHER: 288 Kind = ppc64::Pointer16HIGHER; 289 break; 290 case ELF::R_PPC64_ADDR16_HIGHERA: 291 Kind = ppc64::Pointer16HIGHERA; 292 break; 293 case ELF::R_PPC64_ADDR16_HIGHEST: 294 Kind = ppc64::Pointer16HIGHEST; 295 break; 296 case ELF::R_PPC64_ADDR16_HIGHESTA: 297 Kind = ppc64::Pointer16HIGHESTA; 298 break; 299 case ELF::R_PPC64_ADDR16_LO: 300 Kind = ppc64::Pointer16LO; 301 break; 302 case ELF::R_PPC64_ADDR16_LO_DS: 303 Kind = ppc64::Pointer16LODS; 304 break; 305 case ELF::R_PPC64_ADDR14: 306 Kind = ppc64::Pointer14; 307 break; 308 case ELF::R_PPC64_TOC: 309 Kind = ppc64::TOC; 310 break; 311 case ELF::R_PPC64_TOC16: 312 Kind = ppc64::TOCDelta16; 313 break; 314 case ELF::R_PPC64_TOC16_HA: 315 Kind = ppc64::TOCDelta16HA; 316 break; 317 case ELF::R_PPC64_TOC16_HI: 318 Kind = ppc64::TOCDelta16HI; 319 break; 320 case ELF::R_PPC64_TOC16_DS: 321 Kind = ppc64::TOCDelta16DS; 322 break; 323 case ELF::R_PPC64_TOC16_LO: 324 Kind = ppc64::TOCDelta16LO; 325 break; 326 case ELF::R_PPC64_TOC16_LO_DS: 327 Kind = ppc64::TOCDelta16LODS; 328 break; 329 case ELF::R_PPC64_REL16: 330 Kind = ppc64::Delta16; 331 break; 332 case ELF::R_PPC64_REL16_HA: 333 Kind = ppc64::Delta16HA; 334 break; 335 case ELF::R_PPC64_REL16_HI: 336 Kind = ppc64::Delta16HI; 337 break; 338 case ELF::R_PPC64_REL16_LO: 339 Kind = ppc64::Delta16LO; 340 break; 341 case ELF::R_PPC64_REL32: 342 Kind = ppc64::Delta32; 343 break; 344 case ELF::R_PPC64_REL24_NOTOC: 345 Kind = ppc64::RequestCallNoTOC; 346 break; 347 case ELF::R_PPC64_REL24: 348 Kind = ppc64::RequestCall; 349 // Determining a target is external or not is deferred in PostPrunePass. 350 // We assume branching to local entry by default, since in PostPrunePass, 351 // we don't have any context to determine LocalEntryOffset. If it finally 352 // turns out to be an external call, we'll have a stub for the external 353 // target, the target of this edge will be the stub and its addend will be 354 // set 0. 355 Addend += ELF::decodePPC64LocalEntryOffset((*ObjSymbol)->st_other); 356 break; 357 case ELF::R_PPC64_REL64: 358 Kind = ppc64::Delta64; 359 break; 360 case ELF::R_PPC64_PCREL34: 361 Kind = ppc64::Delta34; 362 break; 363 case ELF::R_PPC64_GOT_TLSGD16_HA: 364 Kind = ppc64::RequestTLSDescInGOTAndTransformToTOCDelta16HA; 365 break; 366 case ELF::R_PPC64_GOT_TLSGD16_LO: 367 Kind = ppc64::RequestTLSDescInGOTAndTransformToTOCDelta16LO; 368 break; 369 } 370 371 Edge GE(Kind, Offset, *GraphSymbol, Addend); 372 BlockToFix.addEdge(std::move(GE)); 373 return Error::success(); 374 } 375 376 public: 377 ELFLinkGraphBuilder_ppc64(StringRef FileName, 378 const object::ELFFile<ELFT> &Obj, Triple TT, 379 SubtargetFeatures Features) 380 : ELFLinkGraphBuilder<ELFT>(Obj, std::move(TT), std::move(Features), 381 FileName, ppc64::getEdgeKindName) {} 382 }; 383 384 template <support::endianness Endianness> 385 class ELFJITLinker_ppc64 : public JITLinker<ELFJITLinker_ppc64<Endianness>> { 386 using JITLinkerBase = JITLinker<ELFJITLinker_ppc64<Endianness>>; 387 friend JITLinkerBase; 388 389 public: 390 ELFJITLinker_ppc64(std::unique_ptr<JITLinkContext> Ctx, 391 std::unique_ptr<LinkGraph> G, PassConfiguration PassConfig) 392 : JITLinkerBase(std::move(Ctx), std::move(G), std::move(PassConfig)) { 393 JITLinkerBase::getPassConfig().PostAllocationPasses.push_back( 394 [this](LinkGraph &G) { return defineTOCBase(G); }); 395 } 396 397 private: 398 Symbol *TOCSymbol = nullptr; 399 400 Error defineTOCBase(LinkGraph &G) { 401 for (Symbol *Sym : G.defined_symbols()) { 402 if (LLVM_UNLIKELY(Sym->getName() == ELFTOCSymbolName)) { 403 TOCSymbol = Sym; 404 return Error::success(); 405 } 406 } 407 408 assert(TOCSymbol == nullptr && 409 "TOCSymbol should not be defined at this point"); 410 411 for (Symbol *Sym : G.external_symbols()) { 412 if (Sym->getName() == ELFTOCSymbolName) { 413 TOCSymbol = Sym; 414 break; 415 } 416 } 417 418 if (Section *TOCSection = G.findSectionByName( 419 ppc64::TOCTableManager<Endianness>::getSectionName())) { 420 assert(!TOCSection->empty() && "TOC section should have reserved an " 421 "entry for containing the TOC base"); 422 423 SectionRange SR(*TOCSection); 424 orc::ExecutorAddr TOCBaseAddr(SR.getFirstBlock()->getAddress() + 425 ELFTOCBaseOffset); 426 assert(TOCSymbol && TOCSymbol->isExternal() && 427 ".TOC. should be a external symbol at this point"); 428 G.makeAbsolute(*TOCSymbol, TOCBaseAddr); 429 // Create an alias of .TOC. so that rtdyld checker can recognize. 430 G.addAbsoluteSymbol(TOCSymbolAliasIdent, TOCSymbol->getAddress(), 431 TOCSymbol->getSize(), TOCSymbol->getLinkage(), 432 TOCSymbol->getScope(), TOCSymbol->isLive()); 433 return Error::success(); 434 } 435 436 // If TOC section doesn't exist, which means no TOC relocation is found, we 437 // don't need a TOCSymbol. 438 return Error::success(); 439 } 440 441 Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const { 442 return ppc64::applyFixup<Endianness>(G, B, E, TOCSymbol); 443 } 444 }; 445 446 template <support::endianness Endianness> 447 Expected<std::unique_ptr<LinkGraph>> 448 createLinkGraphFromELFObject_ppc64(MemoryBufferRef ObjectBuffer) { 449 LLVM_DEBUG({ 450 dbgs() << "Building jitlink graph for new input " 451 << ObjectBuffer.getBufferIdentifier() << "...\n"; 452 }); 453 454 auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer); 455 if (!ELFObj) 456 return ELFObj.takeError(); 457 458 auto Features = (*ELFObj)->getFeatures(); 459 if (!Features) 460 return Features.takeError(); 461 462 using ELFT = object::ELFType<Endianness, true>; 463 auto &ELFObjFile = cast<object::ELFObjectFile<ELFT>>(**ELFObj); 464 return ELFLinkGraphBuilder_ppc64<Endianness>( 465 (*ELFObj)->getFileName(), ELFObjFile.getELFFile(), 466 (*ELFObj)->makeTriple(), std::move(*Features)) 467 .buildGraph(); 468 } 469 470 template <support::endianness Endianness> 471 void link_ELF_ppc64(std::unique_ptr<LinkGraph> G, 472 std::unique_ptr<JITLinkContext> Ctx) { 473 PassConfiguration Config; 474 475 if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) { 476 // Construct a JITLinker and run the link function. 477 478 // Add eh-frame passes. 479 Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame")); 480 Config.PrePrunePasses.push_back(EHFrameEdgeFixer( 481 ".eh_frame", G->getPointerSize(), ppc64::Pointer32, ppc64::Pointer64, 482 ppc64::Delta32, ppc64::Delta64, ppc64::NegDelta32)); 483 Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame")); 484 485 // Add a mark-live pass. 486 if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple())) 487 Config.PrePrunePasses.push_back(std::move(MarkLive)); 488 else 489 Config.PrePrunePasses.push_back(markAllSymbolsLive); 490 } 491 492 Config.PostPrunePasses.push_back(buildTables_ELF_ppc64<Endianness>); 493 494 if (auto Err = Ctx->modifyPassConfig(*G, Config)) 495 return Ctx->notifyFailed(std::move(Err)); 496 497 ELFJITLinker_ppc64<Endianness>::link(std::move(Ctx), std::move(G), 498 std::move(Config)); 499 } 500 501 Expected<std::unique_ptr<LinkGraph>> 502 createLinkGraphFromELFObject_ppc64(MemoryBufferRef ObjectBuffer) { 503 return createLinkGraphFromELFObject_ppc64<support::big>( 504 std::move(ObjectBuffer)); 505 } 506 507 Expected<std::unique_ptr<LinkGraph>> 508 createLinkGraphFromELFObject_ppc64le(MemoryBufferRef ObjectBuffer) { 509 return createLinkGraphFromELFObject_ppc64<support::little>( 510 std::move(ObjectBuffer)); 511 } 512 513 /// jit-link the given object buffer, which must be a ELF ppc64 object file. 514 void link_ELF_ppc64(std::unique_ptr<LinkGraph> G, 515 std::unique_ptr<JITLinkContext> Ctx) { 516 return link_ELF_ppc64<support::big>(std::move(G), std::move(Ctx)); 517 } 518 519 /// jit-link the given object buffer, which must be a ELF ppc64le object file. 520 void link_ELF_ppc64le(std::unique_ptr<LinkGraph> G, 521 std::unique_ptr<JITLinkContext> Ctx) { 522 return link_ELF_ppc64<support::little>(std::move(G), std::move(Ctx)); 523 } 524 525 } // end namespace llvm::jitlink 526