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