18313507aSLang Hames //===------- ELF_ppc64.cpp -JIT linker implementation for ELF/ppc64 -------===// 28313507aSLang Hames // 38313507aSLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 48313507aSLang Hames // See https://llvm.org/LICENSE.txt for license information. 58313507aSLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 68313507aSLang Hames // 78313507aSLang Hames //===----------------------------------------------------------------------===// 88313507aSLang Hames // 98313507aSLang Hames // ELF/ppc64 jit-link implementation. 108313507aSLang Hames // 118313507aSLang Hames //===----------------------------------------------------------------------===// 128313507aSLang Hames 138313507aSLang Hames #include "llvm/ExecutionEngine/JITLink/ELF_ppc64.h" 1461358d4fSKai Luo #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h" 1561358d4fSKai Luo #include "llvm/ExecutionEngine/JITLink/TableManager.h" 168313507aSLang Hames #include "llvm/ExecutionEngine/JITLink/ppc64.h" 178313507aSLang Hames #include "llvm/Object/ELFObjectFile.h" 188313507aSLang Hames 1961358d4fSKai Luo #include "EHFrameSupportImpl.h" 208313507aSLang Hames #include "ELFLinkGraphBuilder.h" 218313507aSLang Hames #include "JITLinkGeneric.h" 228313507aSLang Hames 238313507aSLang Hames #define DEBUG_TYPE "jitlink" 248313507aSLang Hames 2561358d4fSKai Luo namespace { 2661358d4fSKai Luo 2761358d4fSKai Luo using namespace llvm; 2861358d4fSKai Luo using namespace llvm::jitlink; 2961358d4fSKai Luo 3061358d4fSKai Luo constexpr StringRef ELFTOCSymbolName = ".TOC."; 3161358d4fSKai Luo constexpr StringRef TOCSymbolAliasIdent = "__TOC__"; 3261358d4fSKai Luo constexpr uint64_t ELFTOCBaseOffset = 0x8000; 339c38a178SKai Luo constexpr StringRef ELFTLSInfoSectionName = "$__TLSINFO"; 349c38a178SKai Luo 35a9d50568SKazu Hirata template <llvm::endianness Endianness> 369c38a178SKai Luo class TLSInfoTableManager_ELF_ppc64 379c38a178SKai Luo : public TableManager<TLSInfoTableManager_ELF_ppc64<Endianness>> { 389c38a178SKai Luo public: 399c38a178SKai Luo static const uint8_t TLSInfoEntryContent[16]; 409c38a178SKai Luo 419c38a178SKai Luo static StringRef getSectionName() { return ELFTLSInfoSectionName; } 429c38a178SKai Luo 439c38a178SKai Luo bool visitEdge(LinkGraph &G, Block *B, Edge &E) { 449c38a178SKai Luo Edge::Kind K = E.getKind(); 4518dc8dcdSKai Luo switch (K) { 4618dc8dcdSKai Luo case ppc64::RequestTLSDescInGOTAndTransformToTOCDelta16HA: 479c38a178SKai Luo E.setKind(ppc64::TOCDelta16HA); 489c38a178SKai Luo E.setTarget(this->getEntryForTarget(G, E.getTarget())); 499c38a178SKai Luo return true; 5018dc8dcdSKai Luo case ppc64::RequestTLSDescInGOTAndTransformToTOCDelta16LO: 519c38a178SKai Luo E.setKind(ppc64::TOCDelta16LO); 529c38a178SKai Luo E.setTarget(this->getEntryForTarget(G, E.getTarget())); 539c38a178SKai Luo return true; 5418dc8dcdSKai Luo case ppc64::RequestTLSDescInGOTAndTransformToDelta34: 5518dc8dcdSKai Luo E.setKind(ppc64::Delta34); 5618dc8dcdSKai Luo E.setTarget(this->getEntryForTarget(G, E.getTarget())); 5718dc8dcdSKai Luo return true; 5818dc8dcdSKai Luo default: 599c38a178SKai Luo return false; 609c38a178SKai Luo } 6118dc8dcdSKai Luo } 629c38a178SKai Luo 639c38a178SKai Luo Symbol &createEntry(LinkGraph &G, Symbol &Target) { 649c38a178SKai Luo // The TLS Info entry's key value will be written by 659c38a178SKai Luo // `fixTLVSectionsAndEdges`, so create mutable content. 669c38a178SKai Luo auto &TLSInfoEntry = G.createMutableContentBlock( 679c38a178SKai Luo getTLSInfoSection(G), G.allocateContent(getTLSInfoEntryContent()), 689c38a178SKai Luo orc::ExecutorAddr(), 8, 0); 699c38a178SKai Luo TLSInfoEntry.addEdge(ppc64::Pointer64, 8, Target, 0); 709c38a178SKai Luo return G.addAnonymousSymbol(TLSInfoEntry, 0, 16, false, false); 719c38a178SKai Luo } 729c38a178SKai Luo 739c38a178SKai Luo private: 749c38a178SKai Luo Section &getTLSInfoSection(LinkGraph &G) { 759c38a178SKai Luo if (!TLSInfoTable) 769c38a178SKai Luo TLSInfoTable = 779c38a178SKai Luo &G.createSection(ELFTLSInfoSectionName, orc::MemProt::Read); 789c38a178SKai Luo return *TLSInfoTable; 799c38a178SKai Luo } 809c38a178SKai Luo 819c38a178SKai Luo ArrayRef<char> getTLSInfoEntryContent() const { 829c38a178SKai Luo return {reinterpret_cast<const char *>(TLSInfoEntryContent), 839c38a178SKai Luo sizeof(TLSInfoEntryContent)}; 849c38a178SKai Luo } 859c38a178SKai Luo 869c38a178SKai Luo Section *TLSInfoTable = nullptr; 879c38a178SKai Luo }; 889c38a178SKai Luo 899c38a178SKai Luo template <> 909c38a178SKai Luo const uint8_t TLSInfoTableManager_ELF_ppc64< 91b05dbc4dSKazu Hirata llvm::endianness::little>::TLSInfoEntryContent[16] = { 929c38a178SKai Luo 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*pthread key */ 939c38a178SKai Luo 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /*data address*/ 949c38a178SKai Luo }; 959c38a178SKai Luo 969c38a178SKai Luo template <> 979c38a178SKai Luo const uint8_t TLSInfoTableManager_ELF_ppc64< 98b05dbc4dSKazu Hirata llvm::endianness::big>::TLSInfoEntryContent[16] = { 999c38a178SKai Luo 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*pthread key */ 1009c38a178SKai Luo 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /*data address*/ 1019c38a178SKai Luo }; 10261358d4fSKai Luo 103a9d50568SKazu Hirata template <llvm::endianness Endianness> 10461358d4fSKai Luo Symbol &createELFGOTHeader(LinkGraph &G, 10561358d4fSKai Luo ppc64::TOCTableManager<Endianness> &TOC) { 10661358d4fSKai Luo Symbol *TOCSymbol = nullptr; 10761358d4fSKai Luo 10861358d4fSKai Luo for (Symbol *Sym : G.defined_symbols()) 109*2ccf7ed2SJared Wyles if (LLVM_UNLIKELY(Sym->hasName() && *Sym->getName() == ELFTOCSymbolName)) { 11061358d4fSKai Luo TOCSymbol = Sym; 11161358d4fSKai Luo break; 11261358d4fSKai Luo } 11361358d4fSKai Luo 11461358d4fSKai Luo if (LLVM_LIKELY(TOCSymbol == nullptr)) { 11561358d4fSKai Luo for (Symbol *Sym : G.external_symbols()) 116*2ccf7ed2SJared Wyles if (Sym->hasName() && *Sym->getName() == ELFTOCSymbolName) { 11761358d4fSKai Luo TOCSymbol = Sym; 11861358d4fSKai Luo break; 11961358d4fSKai Luo } 12061358d4fSKai Luo } 12161358d4fSKai Luo 12261358d4fSKai Luo if (!TOCSymbol) 12361358d4fSKai Luo TOCSymbol = &G.addExternalSymbol(ELFTOCSymbolName, 0, false); 12461358d4fSKai Luo 12561358d4fSKai Luo return TOC.getEntryForTarget(G, *TOCSymbol); 12661358d4fSKai Luo } 12761358d4fSKai Luo 12861358d4fSKai Luo // Register preexisting GOT entries with TOC table manager. 129a9d50568SKazu Hirata template <llvm::endianness Endianness> 13061358d4fSKai Luo inline void 13161358d4fSKai Luo registerExistingGOTEntries(LinkGraph &G, 13261358d4fSKai Luo ppc64::TOCTableManager<Endianness> &TOC) { 13361358d4fSKai Luo auto isGOTEntry = [](const Edge &E) { 13461358d4fSKai Luo return E.getKind() == ppc64::Pointer64 && E.getTarget().isExternal(); 13561358d4fSKai Luo }; 13661358d4fSKai Luo if (Section *dotTOCSection = G.findSectionByName(".toc")) { 13761358d4fSKai Luo for (Block *B : dotTOCSection->blocks()) 13861358d4fSKai Luo for (Edge &E : B->edges()) 13961358d4fSKai Luo if (isGOTEntry(E)) 14074f2a769SLang Hames TOC.registerPreExistingEntry(E.getTarget(), 14174f2a769SLang Hames G.addAnonymousSymbol(*B, E.getOffset(), 14274f2a769SLang Hames G.getPointerSize(), 14374f2a769SLang Hames false, false)); 14461358d4fSKai Luo } 14561358d4fSKai Luo } 14661358d4fSKai Luo 147a9d50568SKazu Hirata template <llvm::endianness Endianness> 14861358d4fSKai Luo Error buildTables_ELF_ppc64(LinkGraph &G) { 14961358d4fSKai Luo LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n"); 15061358d4fSKai Luo ppc64::TOCTableManager<Endianness> TOC; 15161358d4fSKai Luo // Before visiting edges, we create a header containing the address of TOC 15261358d4fSKai Luo // base as ELFABIv2 suggests: 15361358d4fSKai Luo // > The GOT consists of an 8-byte header that contains the TOC base (the 15461358d4fSKai Luo // first TOC base when multiple TOCs are present), followed by an array of 15561358d4fSKai Luo // 8-byte addresses. 15661358d4fSKai Luo createELFGOTHeader(G, TOC); 15761358d4fSKai Luo 15861358d4fSKai Luo // There might be compiler-generated GOT entries in ELF relocatable file. 15961358d4fSKai Luo registerExistingGOTEntries(G, TOC); 16061358d4fSKai Luo 16161358d4fSKai Luo ppc64::PLTTableManager<Endianness> PLT(TOC); 1629c38a178SKai Luo TLSInfoTableManager_ELF_ppc64<Endianness> TLSInfo; 1639c38a178SKai Luo visitExistingEdges(G, TOC, PLT, TLSInfo); 16461358d4fSKai Luo 16561358d4fSKai Luo // After visiting edges in LinkGraph, we have GOT entries built in the 16661358d4fSKai Luo // synthesized section. 16761358d4fSKai Luo // Merge sections included in TOC into synthesized TOC section, 16861358d4fSKai Luo // thus TOC is compact and reducing chances of relocation 16961358d4fSKai Luo // overflow. 17061358d4fSKai Luo if (Section *TOCSection = G.findSectionByName(TOC.getSectionName())) { 17161358d4fSKai Luo // .got and .plt are not normally present in a relocatable object file 17261358d4fSKai Luo // because they are linker generated. 17361358d4fSKai Luo if (Section *gotSection = G.findSectionByName(".got")) 17461358d4fSKai Luo G.mergeSections(*TOCSection, *gotSection); 17561358d4fSKai Luo if (Section *tocSection = G.findSectionByName(".toc")) 17661358d4fSKai Luo G.mergeSections(*TOCSection, *tocSection); 17761358d4fSKai Luo if (Section *sdataSection = G.findSectionByName(".sdata")) 17861358d4fSKai Luo G.mergeSections(*TOCSection, *sdataSection); 17961358d4fSKai Luo if (Section *sbssSection = G.findSectionByName(".sbss")) 18061358d4fSKai Luo G.mergeSections(*TOCSection, *sbssSection); 18161358d4fSKai Luo // .tocbss no longer appears in ELFABIv2. Leave it here to be compatible 18261358d4fSKai Luo // with rtdyld. 18361358d4fSKai Luo if (Section *tocbssSection = G.findSectionByName(".tocbss")) 18461358d4fSKai Luo G.mergeSections(*TOCSection, *tocbssSection); 18561358d4fSKai Luo if (Section *pltSection = G.findSectionByName(".plt")) 18661358d4fSKai Luo G.mergeSections(*TOCSection, *pltSection); 18761358d4fSKai Luo } 18861358d4fSKai Luo 18961358d4fSKai Luo return Error::success(); 19061358d4fSKai Luo } 19161358d4fSKai Luo 19261358d4fSKai Luo } // namespace 19361358d4fSKai Luo 1948313507aSLang Hames namespace llvm::jitlink { 1958313507aSLang Hames 196a9d50568SKazu Hirata template <llvm::endianness Endianness> 1978313507aSLang Hames class ELFLinkGraphBuilder_ppc64 1988313507aSLang Hames : public ELFLinkGraphBuilder<object::ELFType<Endianness, true>> { 1998313507aSLang Hames private: 2008313507aSLang Hames using ELFT = object::ELFType<Endianness, true>; 2018313507aSLang Hames using Base = ELFLinkGraphBuilder<ELFT>; 2028313507aSLang Hames 2038313507aSLang Hames using Base::G; // Use LinkGraph pointer from base class. 2048313507aSLang Hames 2058313507aSLang Hames Error addRelocations() override { 2068313507aSLang Hames LLVM_DEBUG(dbgs() << "Processing relocations:\n"); 2078313507aSLang Hames 2088313507aSLang Hames using Self = ELFLinkGraphBuilder_ppc64<Endianness>; 2098313507aSLang Hames for (const auto &RelSect : Base::Sections) { 2108313507aSLang Hames // Validate the section to read relocation entries from. 2118313507aSLang Hames if (RelSect.sh_type == ELF::SHT_REL) 2128313507aSLang Hames return make_error<StringError>("No SHT_REL in valid " + 2138313507aSLang Hames G->getTargetTriple().getArchName() + 2148313507aSLang Hames " ELF object files", 2158313507aSLang Hames inconvertibleErrorCode()); 2168313507aSLang Hames 2178313507aSLang Hames if (Error Err = Base::forEachRelaRelocation(RelSect, this, 2188313507aSLang Hames &Self::addSingleRelocation)) 2198313507aSLang Hames return Err; 2208313507aSLang Hames } 2218313507aSLang Hames 2228313507aSLang Hames return Error::success(); 2238313507aSLang Hames } 2248313507aSLang Hames 2258313507aSLang Hames Error addSingleRelocation(const typename ELFT::Rela &Rel, 2268313507aSLang Hames const typename ELFT::Shdr &FixupSection, 2278313507aSLang Hames Block &BlockToFix) { 22861358d4fSKai Luo using Base = ELFLinkGraphBuilder<ELFT>; 2298313507aSLang Hames auto ELFReloc = Rel.getType(false); 23061358d4fSKai Luo 23161358d4fSKai Luo // R_PPC64_NONE is a no-op. 23261358d4fSKai Luo if (LLVM_UNLIKELY(ELFReloc == ELF::R_PPC64_NONE)) 23361358d4fSKai Luo return Error::success(); 23461358d4fSKai Luo 2359c38a178SKai Luo // TLS model markers. We only support global-dynamic model now. 2369c38a178SKai Luo if (ELFReloc == ELF::R_PPC64_TLSGD) 2379c38a178SKai Luo return Error::success(); 2389c38a178SKai Luo if (ELFReloc == ELF::R_PPC64_TLSLD) 2399c38a178SKai Luo return make_error<StringError>("Local-dynamic TLS model is not supported", 2409c38a178SKai Luo inconvertibleErrorCode()); 24118dc8dcdSKai Luo 242a712244fSKai Luo if (ELFReloc == ELF::R_PPC64_PCREL_OPT) 243a712244fSKai Luo // TODO: Support PCREL optimization, now ignore it. 244a712244fSKai Luo return Error::success(); 2459c38a178SKai Luo 24618dc8dcdSKai Luo if (ELFReloc == ELF::R_PPC64_TPREL34) 24718dc8dcdSKai Luo return make_error<StringError>("Local-exec TLS model is not supported", 24818dc8dcdSKai Luo inconvertibleErrorCode()); 24918dc8dcdSKai Luo 25061358d4fSKai Luo auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec); 25161358d4fSKai Luo if (!ObjSymbol) 25261358d4fSKai Luo return ObjSymbol.takeError(); 25361358d4fSKai Luo 25461358d4fSKai Luo uint32_t SymbolIndex = Rel.getSymbol(false); 25561358d4fSKai Luo Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex); 25661358d4fSKai Luo if (!GraphSymbol) 25761358d4fSKai Luo return make_error<StringError>( 25861358d4fSKai Luo formatv("Could not find symbol at given index, did you add it to " 25961358d4fSKai Luo "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}", 26061358d4fSKai Luo SymbolIndex, (*ObjSymbol)->st_shndx, 26161358d4fSKai Luo Base::GraphSymbols.size()), 26261358d4fSKai Luo inconvertibleErrorCode()); 26361358d4fSKai Luo 26461358d4fSKai Luo int64_t Addend = Rel.r_addend; 26561358d4fSKai Luo orc::ExecutorAddr FixupAddress = 26661358d4fSKai Luo orc::ExecutorAddr(FixupSection.sh_addr) + Rel.r_offset; 26761358d4fSKai Luo Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress(); 26861358d4fSKai Luo Edge::Kind Kind = Edge::Invalid; 26961358d4fSKai Luo 27061358d4fSKai Luo switch (ELFReloc) { 27161358d4fSKai Luo default: 2728313507aSLang Hames return make_error<JITLinkError>( 2738313507aSLang Hames "In " + G->getName() + ": Unsupported ppc64 relocation type " + 2748313507aSLang Hames object::getELFRelocationTypeName(ELF::EM_PPC64, ELFReloc)); 27561358d4fSKai Luo case ELF::R_PPC64_ADDR64: 27661358d4fSKai Luo Kind = ppc64::Pointer64; 27761358d4fSKai Luo break; 2785cb2a78aSKai Luo case ELF::R_PPC64_ADDR32: 2795cb2a78aSKai Luo Kind = ppc64::Pointer32; 2805cb2a78aSKai Luo break; 281b6e2eac2SKai Luo case ELF::R_PPC64_ADDR16: 282b6e2eac2SKai Luo Kind = ppc64::Pointer16; 283b6e2eac2SKai Luo break; 284b6e2eac2SKai Luo case ELF::R_PPC64_ADDR16_DS: 285b6e2eac2SKai Luo Kind = ppc64::Pointer16DS; 286b6e2eac2SKai Luo break; 287b6e2eac2SKai Luo case ELF::R_PPC64_ADDR16_HA: 288b6e2eac2SKai Luo Kind = ppc64::Pointer16HA; 289b6e2eac2SKai Luo break; 290b6e2eac2SKai Luo case ELF::R_PPC64_ADDR16_HI: 291b6e2eac2SKai Luo Kind = ppc64::Pointer16HI; 292b6e2eac2SKai Luo break; 293b6e2eac2SKai Luo case ELF::R_PPC64_ADDR16_HIGH: 294b6e2eac2SKai Luo Kind = ppc64::Pointer16HIGH; 295b6e2eac2SKai Luo break; 296b6e2eac2SKai Luo case ELF::R_PPC64_ADDR16_HIGHA: 297b6e2eac2SKai Luo Kind = ppc64::Pointer16HIGHA; 298b6e2eac2SKai Luo break; 299b6e2eac2SKai Luo case ELF::R_PPC64_ADDR16_HIGHER: 300b6e2eac2SKai Luo Kind = ppc64::Pointer16HIGHER; 301b6e2eac2SKai Luo break; 302b6e2eac2SKai Luo case ELF::R_PPC64_ADDR16_HIGHERA: 303b6e2eac2SKai Luo Kind = ppc64::Pointer16HIGHERA; 304b6e2eac2SKai Luo break; 305b6e2eac2SKai Luo case ELF::R_PPC64_ADDR16_HIGHEST: 306b6e2eac2SKai Luo Kind = ppc64::Pointer16HIGHEST; 307b6e2eac2SKai Luo break; 308b6e2eac2SKai Luo case ELF::R_PPC64_ADDR16_HIGHESTA: 309b6e2eac2SKai Luo Kind = ppc64::Pointer16HIGHESTA; 310b6e2eac2SKai Luo break; 311b6e2eac2SKai Luo case ELF::R_PPC64_ADDR16_LO: 312b6e2eac2SKai Luo Kind = ppc64::Pointer16LO; 313b6e2eac2SKai Luo break; 314b6e2eac2SKai Luo case ELF::R_PPC64_ADDR16_LO_DS: 315b6e2eac2SKai Luo Kind = ppc64::Pointer16LODS; 316b6e2eac2SKai Luo break; 317b6e2eac2SKai Luo case ELF::R_PPC64_ADDR14: 318b6e2eac2SKai Luo Kind = ppc64::Pointer14; 319b6e2eac2SKai Luo break; 320b6e2eac2SKai Luo case ELF::R_PPC64_TOC: 321b6e2eac2SKai Luo Kind = ppc64::TOC; 322b6e2eac2SKai Luo break; 323b6e2eac2SKai Luo case ELF::R_PPC64_TOC16: 324b6e2eac2SKai Luo Kind = ppc64::TOCDelta16; 325b6e2eac2SKai Luo break; 32661358d4fSKai Luo case ELF::R_PPC64_TOC16_HA: 32761358d4fSKai Luo Kind = ppc64::TOCDelta16HA; 32861358d4fSKai Luo break; 329b6e2eac2SKai Luo case ELF::R_PPC64_TOC16_HI: 330b6e2eac2SKai Luo Kind = ppc64::TOCDelta16HI; 331b6e2eac2SKai Luo break; 33261358d4fSKai Luo case ELF::R_PPC64_TOC16_DS: 33361358d4fSKai Luo Kind = ppc64::TOCDelta16DS; 33461358d4fSKai Luo break; 33561358d4fSKai Luo case ELF::R_PPC64_TOC16_LO: 33661358d4fSKai Luo Kind = ppc64::TOCDelta16LO; 33761358d4fSKai Luo break; 33861358d4fSKai Luo case ELF::R_PPC64_TOC16_LO_DS: 33961358d4fSKai Luo Kind = ppc64::TOCDelta16LODS; 34061358d4fSKai Luo break; 34161358d4fSKai Luo case ELF::R_PPC64_REL16: 34261358d4fSKai Luo Kind = ppc64::Delta16; 34361358d4fSKai Luo break; 34461358d4fSKai Luo case ELF::R_PPC64_REL16_HA: 34561358d4fSKai Luo Kind = ppc64::Delta16HA; 34661358d4fSKai Luo break; 347b6e2eac2SKai Luo case ELF::R_PPC64_REL16_HI: 348b6e2eac2SKai Luo Kind = ppc64::Delta16HI; 349b6e2eac2SKai Luo break; 35061358d4fSKai Luo case ELF::R_PPC64_REL16_LO: 35161358d4fSKai Luo Kind = ppc64::Delta16LO; 35261358d4fSKai Luo break; 35361358d4fSKai Luo case ELF::R_PPC64_REL32: 35461358d4fSKai Luo Kind = ppc64::Delta32; 35561358d4fSKai Luo break; 35661358d4fSKai Luo case ELF::R_PPC64_REL24_NOTOC: 35711a02de7SKai Luo Kind = ppc64::RequestCallNoTOC; 35861358d4fSKai Luo break; 35911a02de7SKai Luo case ELF::R_PPC64_REL24: 36011a02de7SKai Luo Kind = ppc64::RequestCall; 3611dae4dd0SKai Luo // Determining a target is external or not is deferred in PostPrunePass. 3621dae4dd0SKai Luo // We assume branching to local entry by default, since in PostPrunePass, 3631dae4dd0SKai Luo // we don't have any context to determine LocalEntryOffset. If it finally 3641dae4dd0SKai Luo // turns out to be an external call, we'll have a stub for the external 3651dae4dd0SKai Luo // target, the target of this edge will be the stub and its addend will be 3661dae4dd0SKai Luo // set 0. 3671dae4dd0SKai Luo Addend += ELF::decodePPC64LocalEntryOffset((*ObjSymbol)->st_other); 36811a02de7SKai Luo break; 36961358d4fSKai Luo case ELF::R_PPC64_REL64: 37061358d4fSKai Luo Kind = ppc64::Delta64; 37161358d4fSKai Luo break; 372ca6d86f6SKai Luo case ELF::R_PPC64_PCREL34: 373ca6d86f6SKai Luo Kind = ppc64::Delta34; 374ca6d86f6SKai Luo break; 375a712244fSKai Luo case ELF::R_PPC64_GOT_PCREL34: 376a712244fSKai Luo Kind = ppc64::RequestGOTAndTransformToDelta34; 377a712244fSKai Luo break; 3789c38a178SKai Luo case ELF::R_PPC64_GOT_TLSGD16_HA: 3799c38a178SKai Luo Kind = ppc64::RequestTLSDescInGOTAndTransformToTOCDelta16HA; 3809c38a178SKai Luo break; 3819c38a178SKai Luo case ELF::R_PPC64_GOT_TLSGD16_LO: 3829c38a178SKai Luo Kind = ppc64::RequestTLSDescInGOTAndTransformToTOCDelta16LO; 3839c38a178SKai Luo break; 38418dc8dcdSKai Luo case ELF::R_PPC64_GOT_TLSGD_PCREL34: 38518dc8dcdSKai Luo Kind = ppc64::RequestTLSDescInGOTAndTransformToDelta34; 38618dc8dcdSKai Luo break; 38761358d4fSKai Luo } 38861358d4fSKai Luo 38961358d4fSKai Luo Edge GE(Kind, Offset, *GraphSymbol, Addend); 39061358d4fSKai Luo BlockToFix.addEdge(std::move(GE)); 39161358d4fSKai Luo return Error::success(); 3928313507aSLang Hames } 3938313507aSLang Hames 3948313507aSLang Hames public: 3958313507aSLang Hames ELFLinkGraphBuilder_ppc64(StringRef FileName, 396*2ccf7ed2SJared Wyles const object::ELFFile<ELFT> &Obj, 397*2ccf7ed2SJared Wyles std::shared_ptr<orc::SymbolStringPool> SSP, 398*2ccf7ed2SJared Wyles Triple TT, SubtargetFeatures Features) 399*2ccf7ed2SJared Wyles : ELFLinkGraphBuilder<ELFT>(Obj, std::move(SSP), std::move(TT), 400*2ccf7ed2SJared Wyles std::move(Features), FileName, 401*2ccf7ed2SJared Wyles ppc64::getEdgeKindName) {} 4028313507aSLang Hames }; 4038313507aSLang Hames 404a9d50568SKazu Hirata template <llvm::endianness Endianness> 4058313507aSLang Hames class ELFJITLinker_ppc64 : public JITLinker<ELFJITLinker_ppc64<Endianness>> { 4068313507aSLang Hames using JITLinkerBase = JITLinker<ELFJITLinker_ppc64<Endianness>>; 4078313507aSLang Hames friend JITLinkerBase; 4088313507aSLang Hames 4098313507aSLang Hames public: 4108313507aSLang Hames ELFJITLinker_ppc64(std::unique_ptr<JITLinkContext> Ctx, 4118313507aSLang Hames std::unique_ptr<LinkGraph> G, PassConfiguration PassConfig) 41261358d4fSKai Luo : JITLinkerBase(std::move(Ctx), std::move(G), std::move(PassConfig)) { 41361358d4fSKai Luo JITLinkerBase::getPassConfig().PostAllocationPasses.push_back( 41461358d4fSKai Luo [this](LinkGraph &G) { return defineTOCBase(G); }); 41561358d4fSKai Luo } 4168313507aSLang Hames 4178313507aSLang Hames private: 41861358d4fSKai Luo Symbol *TOCSymbol = nullptr; 41961358d4fSKai Luo 42061358d4fSKai Luo Error defineTOCBase(LinkGraph &G) { 42161358d4fSKai Luo for (Symbol *Sym : G.defined_symbols()) { 422*2ccf7ed2SJared Wyles if (LLVM_UNLIKELY(Sym->hasName() && 423*2ccf7ed2SJared Wyles *Sym->getName() == ELFTOCSymbolName)) { 42461358d4fSKai Luo TOCSymbol = Sym; 42561358d4fSKai Luo return Error::success(); 42661358d4fSKai Luo } 42761358d4fSKai Luo } 42861358d4fSKai Luo 42961358d4fSKai Luo assert(TOCSymbol == nullptr && 43061358d4fSKai Luo "TOCSymbol should not be defined at this point"); 43161358d4fSKai Luo 43261358d4fSKai Luo for (Symbol *Sym : G.external_symbols()) { 433*2ccf7ed2SJared Wyles if (Sym->hasName() && *Sym->getName() == ELFTOCSymbolName) { 43461358d4fSKai Luo TOCSymbol = Sym; 43561358d4fSKai Luo break; 43661358d4fSKai Luo } 43761358d4fSKai Luo } 43861358d4fSKai Luo 43961358d4fSKai Luo if (Section *TOCSection = G.findSectionByName( 44061358d4fSKai Luo ppc64::TOCTableManager<Endianness>::getSectionName())) { 44161358d4fSKai Luo assert(!TOCSection->empty() && "TOC section should have reserved an " 44261358d4fSKai Luo "entry for containing the TOC base"); 44361358d4fSKai Luo 44461358d4fSKai Luo SectionRange SR(*TOCSection); 44561358d4fSKai Luo orc::ExecutorAddr TOCBaseAddr(SR.getFirstBlock()->getAddress() + 44661358d4fSKai Luo ELFTOCBaseOffset); 44761358d4fSKai Luo assert(TOCSymbol && TOCSymbol->isExternal() && 44861358d4fSKai Luo ".TOC. should be a external symbol at this point"); 44961358d4fSKai Luo G.makeAbsolute(*TOCSymbol, TOCBaseAddr); 45061358d4fSKai Luo // Create an alias of .TOC. so that rtdyld checker can recognize. 45161358d4fSKai Luo G.addAbsoluteSymbol(TOCSymbolAliasIdent, TOCSymbol->getAddress(), 45261358d4fSKai Luo TOCSymbol->getSize(), TOCSymbol->getLinkage(), 45361358d4fSKai Luo TOCSymbol->getScope(), TOCSymbol->isLive()); 45461358d4fSKai Luo return Error::success(); 45561358d4fSKai Luo } 45661358d4fSKai Luo 45761358d4fSKai Luo // If TOC section doesn't exist, which means no TOC relocation is found, we 45861358d4fSKai Luo // don't need a TOCSymbol. 45961358d4fSKai Luo return Error::success(); 46061358d4fSKai Luo } 4618313507aSLang Hames 4628313507aSLang Hames Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const { 46361358d4fSKai Luo return ppc64::applyFixup<Endianness>(G, B, E, TOCSymbol); 4648313507aSLang Hames } 4658313507aSLang Hames }; 4668313507aSLang Hames 467a9d50568SKazu Hirata template <llvm::endianness Endianness> 4688313507aSLang Hames Expected<std::unique_ptr<LinkGraph>> 469*2ccf7ed2SJared Wyles createLinkGraphFromELFObject_ppc64(MemoryBufferRef ObjectBuffer, 470*2ccf7ed2SJared Wyles std::shared_ptr<orc::SymbolStringPool> SSP) { 4718313507aSLang Hames LLVM_DEBUG({ 4728313507aSLang Hames dbgs() << "Building jitlink graph for new input " 4738313507aSLang Hames << ObjectBuffer.getBufferIdentifier() << "...\n"; 4748313507aSLang Hames }); 4758313507aSLang Hames 4768313507aSLang Hames auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer); 4778313507aSLang Hames if (!ELFObj) 4788313507aSLang Hames return ELFObj.takeError(); 4798313507aSLang Hames 4808313507aSLang Hames auto Features = (*ELFObj)->getFeatures(); 4818313507aSLang Hames if (!Features) 4828313507aSLang Hames return Features.takeError(); 4838313507aSLang Hames 4848313507aSLang Hames using ELFT = object::ELFType<Endianness, true>; 4858313507aSLang Hames auto &ELFObjFile = cast<object::ELFObjectFile<ELFT>>(**ELFObj); 4868313507aSLang Hames return ELFLinkGraphBuilder_ppc64<Endianness>( 487*2ccf7ed2SJared Wyles (*ELFObj)->getFileName(), ELFObjFile.getELFFile(), std::move(SSP), 48852b88457SJob Noorman (*ELFObj)->makeTriple(), std::move(*Features)) 4898313507aSLang Hames .buildGraph(); 4908313507aSLang Hames } 4918313507aSLang Hames 492a9d50568SKazu Hirata template <llvm::endianness Endianness> 4938313507aSLang Hames void link_ELF_ppc64(std::unique_ptr<LinkGraph> G, 4948313507aSLang Hames std::unique_ptr<JITLinkContext> Ctx) { 4958313507aSLang Hames PassConfiguration Config; 4968313507aSLang Hames 4978313507aSLang Hames if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) { 4988313507aSLang Hames // Construct a JITLinker and run the link function. 49961358d4fSKai Luo 50094239712SEymen Ünay // Add eh-frame passes. 50161358d4fSKai Luo Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame")); 50261358d4fSKai Luo Config.PrePrunePasses.push_back(EHFrameEdgeFixer( 50361358d4fSKai Luo ".eh_frame", G->getPointerSize(), ppc64::Pointer32, ppc64::Pointer64, 50461358d4fSKai Luo ppc64::Delta32, ppc64::Delta64, ppc64::NegDelta32)); 50561358d4fSKai Luo Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame")); 50661358d4fSKai Luo 5078313507aSLang Hames // Add a mark-live pass. 5088313507aSLang Hames if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple())) 5098313507aSLang Hames Config.PrePrunePasses.push_back(std::move(MarkLive)); 5108313507aSLang Hames else 5118313507aSLang Hames Config.PrePrunePasses.push_back(markAllSymbolsLive); 5128313507aSLang Hames } 5138313507aSLang Hames 51461358d4fSKai Luo Config.PostPrunePasses.push_back(buildTables_ELF_ppc64<Endianness>); 51561358d4fSKai Luo 5168313507aSLang Hames if (auto Err = Ctx->modifyPassConfig(*G, Config)) 5178313507aSLang Hames return Ctx->notifyFailed(std::move(Err)); 5188313507aSLang Hames 5198313507aSLang Hames ELFJITLinker_ppc64<Endianness>::link(std::move(Ctx), std::move(G), 5208313507aSLang Hames std::move(Config)); 5218313507aSLang Hames } 5228313507aSLang Hames 5238313507aSLang Hames Expected<std::unique_ptr<LinkGraph>> 524*2ccf7ed2SJared Wyles createLinkGraphFromELFObject_ppc64(MemoryBufferRef ObjectBuffer, 525*2ccf7ed2SJared Wyles std::shared_ptr<orc::SymbolStringPool> SSP) { 5264a0ccfa8SKazu Hirata return createLinkGraphFromELFObject_ppc64<llvm::endianness::big>( 527*2ccf7ed2SJared Wyles std::move(ObjectBuffer), std::move(SSP)); 5288313507aSLang Hames } 5298313507aSLang Hames 530*2ccf7ed2SJared Wyles Expected<std::unique_ptr<LinkGraph>> createLinkGraphFromELFObject_ppc64le( 531*2ccf7ed2SJared Wyles MemoryBufferRef ObjectBuffer, std::shared_ptr<orc::SymbolStringPool> SSP) { 5324a0ccfa8SKazu Hirata return createLinkGraphFromELFObject_ppc64<llvm::endianness::little>( 533*2ccf7ed2SJared Wyles std::move(ObjectBuffer), std::move(SSP)); 5348313507aSLang Hames } 5358313507aSLang Hames 5368313507aSLang Hames /// jit-link the given object buffer, which must be a ELF ppc64 object file. 5378313507aSLang Hames void link_ELF_ppc64(std::unique_ptr<LinkGraph> G, 5388313507aSLang Hames std::unique_ptr<JITLinkContext> Ctx) { 5394a0ccfa8SKazu Hirata return link_ELF_ppc64<llvm::endianness::big>(std::move(G), std::move(Ctx)); 5408313507aSLang Hames } 5418313507aSLang Hames 5428313507aSLang Hames /// jit-link the given object buffer, which must be a ELF ppc64le object file. 5438313507aSLang Hames void link_ELF_ppc64le(std::unique_ptr<LinkGraph> G, 5448313507aSLang Hames std::unique_ptr<JITLinkContext> Ctx) { 5454a0ccfa8SKazu Hirata return link_ELF_ppc64<llvm::endianness::little>(std::move(G), std::move(Ctx)); 5468313507aSLang Hames } 5478313507aSLang Hames 5488313507aSLang Hames } // end namespace llvm::jitlink 549