106c3fb27SDimitry Andric //===------- ELF_ppc64.cpp -JIT linker implementation for ELF/ppc64 -------===// 206c3fb27SDimitry Andric // 306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 606c3fb27SDimitry Andric // 706c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 806c3fb27SDimitry Andric // 906c3fb27SDimitry Andric // ELF/ppc64 jit-link implementation. 1006c3fb27SDimitry Andric // 1106c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 1206c3fb27SDimitry Andric 1306c3fb27SDimitry Andric #include "llvm/ExecutionEngine/JITLink/ELF_ppc64.h" 1406c3fb27SDimitry Andric #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h" 1506c3fb27SDimitry Andric #include "llvm/ExecutionEngine/JITLink/TableManager.h" 1606c3fb27SDimitry Andric #include "llvm/ExecutionEngine/JITLink/ppc64.h" 1706c3fb27SDimitry Andric #include "llvm/Object/ELFObjectFile.h" 1806c3fb27SDimitry Andric 1906c3fb27SDimitry Andric #include "EHFrameSupportImpl.h" 2006c3fb27SDimitry Andric #include "ELFLinkGraphBuilder.h" 2106c3fb27SDimitry Andric #include "JITLinkGeneric.h" 2206c3fb27SDimitry Andric 2306c3fb27SDimitry Andric #define DEBUG_TYPE "jitlink" 2406c3fb27SDimitry Andric 2506c3fb27SDimitry Andric namespace { 2606c3fb27SDimitry Andric 2706c3fb27SDimitry Andric using namespace llvm; 2806c3fb27SDimitry Andric using namespace llvm::jitlink; 2906c3fb27SDimitry Andric 3006c3fb27SDimitry Andric constexpr StringRef ELFTOCSymbolName = ".TOC."; 3106c3fb27SDimitry Andric constexpr StringRef TOCSymbolAliasIdent = "__TOC__"; 3206c3fb27SDimitry Andric constexpr uint64_t ELFTOCBaseOffset = 0x8000; 33*5f757f3fSDimitry Andric constexpr StringRef ELFTLSInfoSectionName = "$__TLSINFO"; 3406c3fb27SDimitry Andric 35*5f757f3fSDimitry Andric template <llvm::endianness Endianness> 36*5f757f3fSDimitry Andric class TLSInfoTableManager_ELF_ppc64 37*5f757f3fSDimitry Andric : public TableManager<TLSInfoTableManager_ELF_ppc64<Endianness>> { 38*5f757f3fSDimitry Andric public: 39*5f757f3fSDimitry Andric static const uint8_t TLSInfoEntryContent[16]; 40*5f757f3fSDimitry Andric 41*5f757f3fSDimitry Andric static StringRef getSectionName() { return ELFTLSInfoSectionName; } 42*5f757f3fSDimitry Andric 43*5f757f3fSDimitry Andric bool visitEdge(LinkGraph &G, Block *B, Edge &E) { 44*5f757f3fSDimitry Andric Edge::Kind K = E.getKind(); 45*5f757f3fSDimitry Andric switch (K) { 46*5f757f3fSDimitry Andric case ppc64::RequestTLSDescInGOTAndTransformToTOCDelta16HA: 47*5f757f3fSDimitry Andric E.setKind(ppc64::TOCDelta16HA); 48*5f757f3fSDimitry Andric E.setTarget(this->getEntryForTarget(G, E.getTarget())); 49*5f757f3fSDimitry Andric return true; 50*5f757f3fSDimitry Andric case ppc64::RequestTLSDescInGOTAndTransformToTOCDelta16LO: 51*5f757f3fSDimitry Andric E.setKind(ppc64::TOCDelta16LO); 52*5f757f3fSDimitry Andric E.setTarget(this->getEntryForTarget(G, E.getTarget())); 53*5f757f3fSDimitry Andric return true; 54*5f757f3fSDimitry Andric case ppc64::RequestTLSDescInGOTAndTransformToDelta34: 55*5f757f3fSDimitry Andric E.setKind(ppc64::Delta34); 56*5f757f3fSDimitry Andric E.setTarget(this->getEntryForTarget(G, E.getTarget())); 57*5f757f3fSDimitry Andric return true; 58*5f757f3fSDimitry Andric default: 59*5f757f3fSDimitry Andric return false; 60*5f757f3fSDimitry Andric } 61*5f757f3fSDimitry Andric } 62*5f757f3fSDimitry Andric 63*5f757f3fSDimitry Andric Symbol &createEntry(LinkGraph &G, Symbol &Target) { 64*5f757f3fSDimitry Andric // The TLS Info entry's key value will be written by 65*5f757f3fSDimitry Andric // `fixTLVSectionsAndEdges`, so create mutable content. 66*5f757f3fSDimitry Andric auto &TLSInfoEntry = G.createMutableContentBlock( 67*5f757f3fSDimitry Andric getTLSInfoSection(G), G.allocateContent(getTLSInfoEntryContent()), 68*5f757f3fSDimitry Andric orc::ExecutorAddr(), 8, 0); 69*5f757f3fSDimitry Andric TLSInfoEntry.addEdge(ppc64::Pointer64, 8, Target, 0); 70*5f757f3fSDimitry Andric return G.addAnonymousSymbol(TLSInfoEntry, 0, 16, false, false); 71*5f757f3fSDimitry Andric } 72*5f757f3fSDimitry Andric 73*5f757f3fSDimitry Andric private: 74*5f757f3fSDimitry Andric Section &getTLSInfoSection(LinkGraph &G) { 75*5f757f3fSDimitry Andric if (!TLSInfoTable) 76*5f757f3fSDimitry Andric TLSInfoTable = 77*5f757f3fSDimitry Andric &G.createSection(ELFTLSInfoSectionName, orc::MemProt::Read); 78*5f757f3fSDimitry Andric return *TLSInfoTable; 79*5f757f3fSDimitry Andric } 80*5f757f3fSDimitry Andric 81*5f757f3fSDimitry Andric ArrayRef<char> getTLSInfoEntryContent() const { 82*5f757f3fSDimitry Andric return {reinterpret_cast<const char *>(TLSInfoEntryContent), 83*5f757f3fSDimitry Andric sizeof(TLSInfoEntryContent)}; 84*5f757f3fSDimitry Andric } 85*5f757f3fSDimitry Andric 86*5f757f3fSDimitry Andric Section *TLSInfoTable = nullptr; 87*5f757f3fSDimitry Andric }; 88*5f757f3fSDimitry Andric 89*5f757f3fSDimitry Andric template <> 90*5f757f3fSDimitry Andric const uint8_t TLSInfoTableManager_ELF_ppc64< 91*5f757f3fSDimitry Andric llvm::endianness::little>::TLSInfoEntryContent[16] = { 92*5f757f3fSDimitry Andric 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*pthread key */ 93*5f757f3fSDimitry Andric 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /*data address*/ 94*5f757f3fSDimitry Andric }; 95*5f757f3fSDimitry Andric 96*5f757f3fSDimitry Andric template <> 97*5f757f3fSDimitry Andric const uint8_t TLSInfoTableManager_ELF_ppc64< 98*5f757f3fSDimitry Andric llvm::endianness::big>::TLSInfoEntryContent[16] = { 99*5f757f3fSDimitry Andric 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*pthread key */ 100*5f757f3fSDimitry Andric 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /*data address*/ 101*5f757f3fSDimitry Andric }; 102*5f757f3fSDimitry Andric 103*5f757f3fSDimitry Andric template <llvm::endianness Endianness> 10406c3fb27SDimitry Andric Symbol &createELFGOTHeader(LinkGraph &G, 10506c3fb27SDimitry Andric ppc64::TOCTableManager<Endianness> &TOC) { 10606c3fb27SDimitry Andric Symbol *TOCSymbol = nullptr; 10706c3fb27SDimitry Andric 10806c3fb27SDimitry Andric for (Symbol *Sym : G.defined_symbols()) 10906c3fb27SDimitry Andric if (LLVM_UNLIKELY(Sym->getName() == ELFTOCSymbolName)) { 11006c3fb27SDimitry Andric TOCSymbol = Sym; 11106c3fb27SDimitry Andric break; 11206c3fb27SDimitry Andric } 11306c3fb27SDimitry Andric 11406c3fb27SDimitry Andric if (LLVM_LIKELY(TOCSymbol == nullptr)) { 11506c3fb27SDimitry Andric for (Symbol *Sym : G.external_symbols()) 11606c3fb27SDimitry Andric if (Sym->getName() == ELFTOCSymbolName) { 11706c3fb27SDimitry Andric TOCSymbol = Sym; 11806c3fb27SDimitry Andric break; 11906c3fb27SDimitry Andric } 12006c3fb27SDimitry Andric } 12106c3fb27SDimitry Andric 12206c3fb27SDimitry Andric if (!TOCSymbol) 12306c3fb27SDimitry Andric TOCSymbol = &G.addExternalSymbol(ELFTOCSymbolName, 0, false); 12406c3fb27SDimitry Andric 12506c3fb27SDimitry Andric return TOC.getEntryForTarget(G, *TOCSymbol); 12606c3fb27SDimitry Andric } 12706c3fb27SDimitry Andric 12806c3fb27SDimitry Andric // Register preexisting GOT entries with TOC table manager. 129*5f757f3fSDimitry Andric template <llvm::endianness Endianness> 13006c3fb27SDimitry Andric inline void 13106c3fb27SDimitry Andric registerExistingGOTEntries(LinkGraph &G, 13206c3fb27SDimitry Andric ppc64::TOCTableManager<Endianness> &TOC) { 13306c3fb27SDimitry Andric auto isGOTEntry = [](const Edge &E) { 13406c3fb27SDimitry Andric return E.getKind() == ppc64::Pointer64 && E.getTarget().isExternal(); 13506c3fb27SDimitry Andric }; 13606c3fb27SDimitry Andric if (Section *dotTOCSection = G.findSectionByName(".toc")) { 13706c3fb27SDimitry Andric for (Block *B : dotTOCSection->blocks()) 13806c3fb27SDimitry Andric for (Edge &E : B->edges()) 13906c3fb27SDimitry Andric if (isGOTEntry(E)) 14006c3fb27SDimitry Andric TOC.registerPreExistingEntry(E.getTarget(), 14106c3fb27SDimitry Andric G.addAnonymousSymbol(*B, E.getOffset(), 14206c3fb27SDimitry Andric G.getPointerSize(), 14306c3fb27SDimitry Andric false, false)); 14406c3fb27SDimitry Andric } 14506c3fb27SDimitry Andric } 14606c3fb27SDimitry Andric 147*5f757f3fSDimitry Andric template <llvm::endianness Endianness> 14806c3fb27SDimitry Andric Error buildTables_ELF_ppc64(LinkGraph &G) { 14906c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n"); 15006c3fb27SDimitry Andric ppc64::TOCTableManager<Endianness> TOC; 15106c3fb27SDimitry Andric // Before visiting edges, we create a header containing the address of TOC 15206c3fb27SDimitry Andric // base as ELFABIv2 suggests: 15306c3fb27SDimitry Andric // > The GOT consists of an 8-byte header that contains the TOC base (the 15406c3fb27SDimitry Andric // first TOC base when multiple TOCs are present), followed by an array of 15506c3fb27SDimitry Andric // 8-byte addresses. 15606c3fb27SDimitry Andric createELFGOTHeader(G, TOC); 15706c3fb27SDimitry Andric 15806c3fb27SDimitry Andric // There might be compiler-generated GOT entries in ELF relocatable file. 15906c3fb27SDimitry Andric registerExistingGOTEntries(G, TOC); 16006c3fb27SDimitry Andric 16106c3fb27SDimitry Andric ppc64::PLTTableManager<Endianness> PLT(TOC); 162*5f757f3fSDimitry Andric TLSInfoTableManager_ELF_ppc64<Endianness> TLSInfo; 163*5f757f3fSDimitry Andric visitExistingEdges(G, TOC, PLT, TLSInfo); 16406c3fb27SDimitry Andric 16506c3fb27SDimitry Andric // After visiting edges in LinkGraph, we have GOT entries built in the 16606c3fb27SDimitry Andric // synthesized section. 16706c3fb27SDimitry Andric // Merge sections included in TOC into synthesized TOC section, 16806c3fb27SDimitry Andric // thus TOC is compact and reducing chances of relocation 16906c3fb27SDimitry Andric // overflow. 17006c3fb27SDimitry Andric if (Section *TOCSection = G.findSectionByName(TOC.getSectionName())) { 17106c3fb27SDimitry Andric // .got and .plt are not normally present in a relocatable object file 17206c3fb27SDimitry Andric // because they are linker generated. 17306c3fb27SDimitry Andric if (Section *gotSection = G.findSectionByName(".got")) 17406c3fb27SDimitry Andric G.mergeSections(*TOCSection, *gotSection); 17506c3fb27SDimitry Andric if (Section *tocSection = G.findSectionByName(".toc")) 17606c3fb27SDimitry Andric G.mergeSections(*TOCSection, *tocSection); 17706c3fb27SDimitry Andric if (Section *sdataSection = G.findSectionByName(".sdata")) 17806c3fb27SDimitry Andric G.mergeSections(*TOCSection, *sdataSection); 17906c3fb27SDimitry Andric if (Section *sbssSection = G.findSectionByName(".sbss")) 18006c3fb27SDimitry Andric G.mergeSections(*TOCSection, *sbssSection); 18106c3fb27SDimitry Andric // .tocbss no longer appears in ELFABIv2. Leave it here to be compatible 18206c3fb27SDimitry Andric // with rtdyld. 18306c3fb27SDimitry Andric if (Section *tocbssSection = G.findSectionByName(".tocbss")) 18406c3fb27SDimitry Andric G.mergeSections(*TOCSection, *tocbssSection); 18506c3fb27SDimitry Andric if (Section *pltSection = G.findSectionByName(".plt")) 18606c3fb27SDimitry Andric G.mergeSections(*TOCSection, *pltSection); 18706c3fb27SDimitry Andric } 18806c3fb27SDimitry Andric 18906c3fb27SDimitry Andric return Error::success(); 19006c3fb27SDimitry Andric } 19106c3fb27SDimitry Andric 19206c3fb27SDimitry Andric } // namespace 19306c3fb27SDimitry Andric 19406c3fb27SDimitry Andric namespace llvm::jitlink { 19506c3fb27SDimitry Andric 196*5f757f3fSDimitry Andric template <llvm::endianness Endianness> 19706c3fb27SDimitry Andric class ELFLinkGraphBuilder_ppc64 19806c3fb27SDimitry Andric : public ELFLinkGraphBuilder<object::ELFType<Endianness, true>> { 19906c3fb27SDimitry Andric private: 20006c3fb27SDimitry Andric using ELFT = object::ELFType<Endianness, true>; 20106c3fb27SDimitry Andric using Base = ELFLinkGraphBuilder<ELFT>; 20206c3fb27SDimitry Andric 20306c3fb27SDimitry Andric using Base::G; // Use LinkGraph pointer from base class. 20406c3fb27SDimitry Andric 20506c3fb27SDimitry Andric Error addRelocations() override { 20606c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "Processing relocations:\n"); 20706c3fb27SDimitry Andric 20806c3fb27SDimitry Andric using Self = ELFLinkGraphBuilder_ppc64<Endianness>; 20906c3fb27SDimitry Andric for (const auto &RelSect : Base::Sections) { 21006c3fb27SDimitry Andric // Validate the section to read relocation entries from. 21106c3fb27SDimitry Andric if (RelSect.sh_type == ELF::SHT_REL) 21206c3fb27SDimitry Andric return make_error<StringError>("No SHT_REL in valid " + 21306c3fb27SDimitry Andric G->getTargetTriple().getArchName() + 21406c3fb27SDimitry Andric " ELF object files", 21506c3fb27SDimitry Andric inconvertibleErrorCode()); 21606c3fb27SDimitry Andric 21706c3fb27SDimitry Andric if (Error Err = Base::forEachRelaRelocation(RelSect, this, 21806c3fb27SDimitry Andric &Self::addSingleRelocation)) 21906c3fb27SDimitry Andric return Err; 22006c3fb27SDimitry Andric } 22106c3fb27SDimitry Andric 22206c3fb27SDimitry Andric return Error::success(); 22306c3fb27SDimitry Andric } 22406c3fb27SDimitry Andric 22506c3fb27SDimitry Andric Error addSingleRelocation(const typename ELFT::Rela &Rel, 22606c3fb27SDimitry Andric const typename ELFT::Shdr &FixupSection, 22706c3fb27SDimitry Andric Block &BlockToFix) { 22806c3fb27SDimitry Andric using Base = ELFLinkGraphBuilder<ELFT>; 22906c3fb27SDimitry Andric auto ELFReloc = Rel.getType(false); 23006c3fb27SDimitry Andric 23106c3fb27SDimitry Andric // R_PPC64_NONE is a no-op. 23206c3fb27SDimitry Andric if (LLVM_UNLIKELY(ELFReloc == ELF::R_PPC64_NONE)) 23306c3fb27SDimitry Andric return Error::success(); 23406c3fb27SDimitry Andric 235*5f757f3fSDimitry Andric // TLS model markers. We only support global-dynamic model now. 236*5f757f3fSDimitry Andric if (ELFReloc == ELF::R_PPC64_TLSGD) 237*5f757f3fSDimitry Andric return Error::success(); 238*5f757f3fSDimitry Andric if (ELFReloc == ELF::R_PPC64_TLSLD) 239*5f757f3fSDimitry Andric return make_error<StringError>("Local-dynamic TLS model is not supported", 240*5f757f3fSDimitry Andric inconvertibleErrorCode()); 241*5f757f3fSDimitry Andric 242*5f757f3fSDimitry Andric if (ELFReloc == ELF::R_PPC64_PCREL_OPT) 243*5f757f3fSDimitry Andric // TODO: Support PCREL optimization, now ignore it. 244*5f757f3fSDimitry Andric return Error::success(); 245*5f757f3fSDimitry Andric 246*5f757f3fSDimitry Andric if (ELFReloc == ELF::R_PPC64_TPREL34) 247*5f757f3fSDimitry Andric return make_error<StringError>("Local-exec TLS model is not supported", 248*5f757f3fSDimitry Andric inconvertibleErrorCode()); 249*5f757f3fSDimitry Andric 25006c3fb27SDimitry Andric auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec); 25106c3fb27SDimitry Andric if (!ObjSymbol) 25206c3fb27SDimitry Andric return ObjSymbol.takeError(); 25306c3fb27SDimitry Andric 25406c3fb27SDimitry Andric uint32_t SymbolIndex = Rel.getSymbol(false); 25506c3fb27SDimitry Andric Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex); 25606c3fb27SDimitry Andric if (!GraphSymbol) 25706c3fb27SDimitry Andric return make_error<StringError>( 25806c3fb27SDimitry Andric formatv("Could not find symbol at given index, did you add it to " 25906c3fb27SDimitry Andric "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}", 26006c3fb27SDimitry Andric SymbolIndex, (*ObjSymbol)->st_shndx, 26106c3fb27SDimitry Andric Base::GraphSymbols.size()), 26206c3fb27SDimitry Andric inconvertibleErrorCode()); 26306c3fb27SDimitry Andric 26406c3fb27SDimitry Andric int64_t Addend = Rel.r_addend; 26506c3fb27SDimitry Andric orc::ExecutorAddr FixupAddress = 26606c3fb27SDimitry Andric orc::ExecutorAddr(FixupSection.sh_addr) + Rel.r_offset; 26706c3fb27SDimitry Andric Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress(); 26806c3fb27SDimitry Andric Edge::Kind Kind = Edge::Invalid; 26906c3fb27SDimitry Andric 27006c3fb27SDimitry Andric switch (ELFReloc) { 27106c3fb27SDimitry Andric default: 27206c3fb27SDimitry Andric return make_error<JITLinkError>( 27306c3fb27SDimitry Andric "In " + G->getName() + ": Unsupported ppc64 relocation type " + 27406c3fb27SDimitry Andric object::getELFRelocationTypeName(ELF::EM_PPC64, ELFReloc)); 27506c3fb27SDimitry Andric case ELF::R_PPC64_ADDR64: 27606c3fb27SDimitry Andric Kind = ppc64::Pointer64; 27706c3fb27SDimitry Andric break; 278*5f757f3fSDimitry Andric case ELF::R_PPC64_ADDR32: 279*5f757f3fSDimitry Andric Kind = ppc64::Pointer32; 280*5f757f3fSDimitry Andric break; 281*5f757f3fSDimitry Andric case ELF::R_PPC64_ADDR16: 282*5f757f3fSDimitry Andric Kind = ppc64::Pointer16; 283*5f757f3fSDimitry Andric break; 284*5f757f3fSDimitry Andric case ELF::R_PPC64_ADDR16_DS: 285*5f757f3fSDimitry Andric Kind = ppc64::Pointer16DS; 286*5f757f3fSDimitry Andric break; 287*5f757f3fSDimitry Andric case ELF::R_PPC64_ADDR16_HA: 288*5f757f3fSDimitry Andric Kind = ppc64::Pointer16HA; 289*5f757f3fSDimitry Andric break; 290*5f757f3fSDimitry Andric case ELF::R_PPC64_ADDR16_HI: 291*5f757f3fSDimitry Andric Kind = ppc64::Pointer16HI; 292*5f757f3fSDimitry Andric break; 293*5f757f3fSDimitry Andric case ELF::R_PPC64_ADDR16_HIGH: 294*5f757f3fSDimitry Andric Kind = ppc64::Pointer16HIGH; 295*5f757f3fSDimitry Andric break; 296*5f757f3fSDimitry Andric case ELF::R_PPC64_ADDR16_HIGHA: 297*5f757f3fSDimitry Andric Kind = ppc64::Pointer16HIGHA; 298*5f757f3fSDimitry Andric break; 299*5f757f3fSDimitry Andric case ELF::R_PPC64_ADDR16_HIGHER: 300*5f757f3fSDimitry Andric Kind = ppc64::Pointer16HIGHER; 301*5f757f3fSDimitry Andric break; 302*5f757f3fSDimitry Andric case ELF::R_PPC64_ADDR16_HIGHERA: 303*5f757f3fSDimitry Andric Kind = ppc64::Pointer16HIGHERA; 304*5f757f3fSDimitry Andric break; 305*5f757f3fSDimitry Andric case ELF::R_PPC64_ADDR16_HIGHEST: 306*5f757f3fSDimitry Andric Kind = ppc64::Pointer16HIGHEST; 307*5f757f3fSDimitry Andric break; 308*5f757f3fSDimitry Andric case ELF::R_PPC64_ADDR16_HIGHESTA: 309*5f757f3fSDimitry Andric Kind = ppc64::Pointer16HIGHESTA; 310*5f757f3fSDimitry Andric break; 311*5f757f3fSDimitry Andric case ELF::R_PPC64_ADDR16_LO: 312*5f757f3fSDimitry Andric Kind = ppc64::Pointer16LO; 313*5f757f3fSDimitry Andric break; 314*5f757f3fSDimitry Andric case ELF::R_PPC64_ADDR16_LO_DS: 315*5f757f3fSDimitry Andric Kind = ppc64::Pointer16LODS; 316*5f757f3fSDimitry Andric break; 317*5f757f3fSDimitry Andric case ELF::R_PPC64_ADDR14: 318*5f757f3fSDimitry Andric Kind = ppc64::Pointer14; 319*5f757f3fSDimitry Andric break; 320*5f757f3fSDimitry Andric case ELF::R_PPC64_TOC: 321*5f757f3fSDimitry Andric Kind = ppc64::TOC; 322*5f757f3fSDimitry Andric break; 323*5f757f3fSDimitry Andric case ELF::R_PPC64_TOC16: 324*5f757f3fSDimitry Andric Kind = ppc64::TOCDelta16; 325*5f757f3fSDimitry Andric break; 32606c3fb27SDimitry Andric case ELF::R_PPC64_TOC16_HA: 32706c3fb27SDimitry Andric Kind = ppc64::TOCDelta16HA; 32806c3fb27SDimitry Andric break; 329*5f757f3fSDimitry Andric case ELF::R_PPC64_TOC16_HI: 330*5f757f3fSDimitry Andric Kind = ppc64::TOCDelta16HI; 331*5f757f3fSDimitry Andric break; 33206c3fb27SDimitry Andric case ELF::R_PPC64_TOC16_DS: 33306c3fb27SDimitry Andric Kind = ppc64::TOCDelta16DS; 33406c3fb27SDimitry Andric break; 33506c3fb27SDimitry Andric case ELF::R_PPC64_TOC16_LO: 33606c3fb27SDimitry Andric Kind = ppc64::TOCDelta16LO; 33706c3fb27SDimitry Andric break; 33806c3fb27SDimitry Andric case ELF::R_PPC64_TOC16_LO_DS: 33906c3fb27SDimitry Andric Kind = ppc64::TOCDelta16LODS; 34006c3fb27SDimitry Andric break; 34106c3fb27SDimitry Andric case ELF::R_PPC64_REL16: 34206c3fb27SDimitry Andric Kind = ppc64::Delta16; 34306c3fb27SDimitry Andric break; 34406c3fb27SDimitry Andric case ELF::R_PPC64_REL16_HA: 34506c3fb27SDimitry Andric Kind = ppc64::Delta16HA; 34606c3fb27SDimitry Andric break; 347*5f757f3fSDimitry Andric case ELF::R_PPC64_REL16_HI: 348*5f757f3fSDimitry Andric Kind = ppc64::Delta16HI; 349*5f757f3fSDimitry Andric break; 35006c3fb27SDimitry Andric case ELF::R_PPC64_REL16_LO: 35106c3fb27SDimitry Andric Kind = ppc64::Delta16LO; 35206c3fb27SDimitry Andric break; 35306c3fb27SDimitry Andric case ELF::R_PPC64_REL32: 35406c3fb27SDimitry Andric Kind = ppc64::Delta32; 35506c3fb27SDimitry Andric break; 35606c3fb27SDimitry Andric case ELF::R_PPC64_REL24_NOTOC: 357*5f757f3fSDimitry Andric Kind = ppc64::RequestCallNoTOC; 35806c3fb27SDimitry Andric break; 359*5f757f3fSDimitry Andric case ELF::R_PPC64_REL24: 360*5f757f3fSDimitry Andric Kind = ppc64::RequestCall; 361*5f757f3fSDimitry Andric // Determining a target is external or not is deferred in PostPrunePass. 362*5f757f3fSDimitry Andric // We assume branching to local entry by default, since in PostPrunePass, 363*5f757f3fSDimitry Andric // we don't have any context to determine LocalEntryOffset. If it finally 364*5f757f3fSDimitry Andric // turns out to be an external call, we'll have a stub for the external 365*5f757f3fSDimitry Andric // target, the target of this edge will be the stub and its addend will be 366*5f757f3fSDimitry Andric // set 0. 367*5f757f3fSDimitry Andric Addend += ELF::decodePPC64LocalEntryOffset((*ObjSymbol)->st_other); 368*5f757f3fSDimitry Andric break; 36906c3fb27SDimitry Andric case ELF::R_PPC64_REL64: 37006c3fb27SDimitry Andric Kind = ppc64::Delta64; 37106c3fb27SDimitry Andric break; 372*5f757f3fSDimitry Andric case ELF::R_PPC64_PCREL34: 373*5f757f3fSDimitry Andric Kind = ppc64::Delta34; 374*5f757f3fSDimitry Andric break; 375*5f757f3fSDimitry Andric case ELF::R_PPC64_GOT_PCREL34: 376*5f757f3fSDimitry Andric Kind = ppc64::RequestGOTAndTransformToDelta34; 377*5f757f3fSDimitry Andric break; 378*5f757f3fSDimitry Andric case ELF::R_PPC64_GOT_TLSGD16_HA: 379*5f757f3fSDimitry Andric Kind = ppc64::RequestTLSDescInGOTAndTransformToTOCDelta16HA; 380*5f757f3fSDimitry Andric break; 381*5f757f3fSDimitry Andric case ELF::R_PPC64_GOT_TLSGD16_LO: 382*5f757f3fSDimitry Andric Kind = ppc64::RequestTLSDescInGOTAndTransformToTOCDelta16LO; 383*5f757f3fSDimitry Andric break; 384*5f757f3fSDimitry Andric case ELF::R_PPC64_GOT_TLSGD_PCREL34: 385*5f757f3fSDimitry Andric Kind = ppc64::RequestTLSDescInGOTAndTransformToDelta34; 386*5f757f3fSDimitry Andric break; 38706c3fb27SDimitry Andric } 38806c3fb27SDimitry Andric 38906c3fb27SDimitry Andric Edge GE(Kind, Offset, *GraphSymbol, Addend); 39006c3fb27SDimitry Andric BlockToFix.addEdge(std::move(GE)); 39106c3fb27SDimitry Andric return Error::success(); 39206c3fb27SDimitry Andric } 39306c3fb27SDimitry Andric 39406c3fb27SDimitry Andric public: 39506c3fb27SDimitry Andric ELFLinkGraphBuilder_ppc64(StringRef FileName, 39606c3fb27SDimitry Andric const object::ELFFile<ELFT> &Obj, Triple TT, 39706c3fb27SDimitry Andric SubtargetFeatures Features) 39806c3fb27SDimitry Andric : ELFLinkGraphBuilder<ELFT>(Obj, std::move(TT), std::move(Features), 39906c3fb27SDimitry Andric FileName, ppc64::getEdgeKindName) {} 40006c3fb27SDimitry Andric }; 40106c3fb27SDimitry Andric 402*5f757f3fSDimitry Andric template <llvm::endianness Endianness> 40306c3fb27SDimitry Andric class ELFJITLinker_ppc64 : public JITLinker<ELFJITLinker_ppc64<Endianness>> { 40406c3fb27SDimitry Andric using JITLinkerBase = JITLinker<ELFJITLinker_ppc64<Endianness>>; 40506c3fb27SDimitry Andric friend JITLinkerBase; 40606c3fb27SDimitry Andric 40706c3fb27SDimitry Andric public: 40806c3fb27SDimitry Andric ELFJITLinker_ppc64(std::unique_ptr<JITLinkContext> Ctx, 40906c3fb27SDimitry Andric std::unique_ptr<LinkGraph> G, PassConfiguration PassConfig) 41006c3fb27SDimitry Andric : JITLinkerBase(std::move(Ctx), std::move(G), std::move(PassConfig)) { 41106c3fb27SDimitry Andric JITLinkerBase::getPassConfig().PostAllocationPasses.push_back( 41206c3fb27SDimitry Andric [this](LinkGraph &G) { return defineTOCBase(G); }); 41306c3fb27SDimitry Andric } 41406c3fb27SDimitry Andric 41506c3fb27SDimitry Andric private: 41606c3fb27SDimitry Andric Symbol *TOCSymbol = nullptr; 41706c3fb27SDimitry Andric 41806c3fb27SDimitry Andric Error defineTOCBase(LinkGraph &G) { 41906c3fb27SDimitry Andric for (Symbol *Sym : G.defined_symbols()) { 42006c3fb27SDimitry Andric if (LLVM_UNLIKELY(Sym->getName() == ELFTOCSymbolName)) { 42106c3fb27SDimitry Andric TOCSymbol = Sym; 42206c3fb27SDimitry Andric return Error::success(); 42306c3fb27SDimitry Andric } 42406c3fb27SDimitry Andric } 42506c3fb27SDimitry Andric 42606c3fb27SDimitry Andric assert(TOCSymbol == nullptr && 42706c3fb27SDimitry Andric "TOCSymbol should not be defined at this point"); 42806c3fb27SDimitry Andric 42906c3fb27SDimitry Andric for (Symbol *Sym : G.external_symbols()) { 43006c3fb27SDimitry Andric if (Sym->getName() == ELFTOCSymbolName) { 43106c3fb27SDimitry Andric TOCSymbol = Sym; 43206c3fb27SDimitry Andric break; 43306c3fb27SDimitry Andric } 43406c3fb27SDimitry Andric } 43506c3fb27SDimitry Andric 43606c3fb27SDimitry Andric if (Section *TOCSection = G.findSectionByName( 43706c3fb27SDimitry Andric ppc64::TOCTableManager<Endianness>::getSectionName())) { 43806c3fb27SDimitry Andric assert(!TOCSection->empty() && "TOC section should have reserved an " 43906c3fb27SDimitry Andric "entry for containing the TOC base"); 44006c3fb27SDimitry Andric 44106c3fb27SDimitry Andric SectionRange SR(*TOCSection); 44206c3fb27SDimitry Andric orc::ExecutorAddr TOCBaseAddr(SR.getFirstBlock()->getAddress() + 44306c3fb27SDimitry Andric ELFTOCBaseOffset); 44406c3fb27SDimitry Andric assert(TOCSymbol && TOCSymbol->isExternal() && 44506c3fb27SDimitry Andric ".TOC. should be a external symbol at this point"); 44606c3fb27SDimitry Andric G.makeAbsolute(*TOCSymbol, TOCBaseAddr); 44706c3fb27SDimitry Andric // Create an alias of .TOC. so that rtdyld checker can recognize. 44806c3fb27SDimitry Andric G.addAbsoluteSymbol(TOCSymbolAliasIdent, TOCSymbol->getAddress(), 44906c3fb27SDimitry Andric TOCSymbol->getSize(), TOCSymbol->getLinkage(), 45006c3fb27SDimitry Andric TOCSymbol->getScope(), TOCSymbol->isLive()); 45106c3fb27SDimitry Andric return Error::success(); 45206c3fb27SDimitry Andric } 45306c3fb27SDimitry Andric 45406c3fb27SDimitry Andric // If TOC section doesn't exist, which means no TOC relocation is found, we 45506c3fb27SDimitry Andric // don't need a TOCSymbol. 45606c3fb27SDimitry Andric return Error::success(); 45706c3fb27SDimitry Andric } 45806c3fb27SDimitry Andric 45906c3fb27SDimitry Andric Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const { 46006c3fb27SDimitry Andric return ppc64::applyFixup<Endianness>(G, B, E, TOCSymbol); 46106c3fb27SDimitry Andric } 46206c3fb27SDimitry Andric }; 46306c3fb27SDimitry Andric 464*5f757f3fSDimitry Andric template <llvm::endianness Endianness> 46506c3fb27SDimitry Andric Expected<std::unique_ptr<LinkGraph>> 46606c3fb27SDimitry Andric createLinkGraphFromELFObject_ppc64(MemoryBufferRef ObjectBuffer) { 46706c3fb27SDimitry Andric LLVM_DEBUG({ 46806c3fb27SDimitry Andric dbgs() << "Building jitlink graph for new input " 46906c3fb27SDimitry Andric << ObjectBuffer.getBufferIdentifier() << "...\n"; 47006c3fb27SDimitry Andric }); 47106c3fb27SDimitry Andric 47206c3fb27SDimitry Andric auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer); 47306c3fb27SDimitry Andric if (!ELFObj) 47406c3fb27SDimitry Andric return ELFObj.takeError(); 47506c3fb27SDimitry Andric 47606c3fb27SDimitry Andric auto Features = (*ELFObj)->getFeatures(); 47706c3fb27SDimitry Andric if (!Features) 47806c3fb27SDimitry Andric return Features.takeError(); 47906c3fb27SDimitry Andric 48006c3fb27SDimitry Andric using ELFT = object::ELFType<Endianness, true>; 48106c3fb27SDimitry Andric auto &ELFObjFile = cast<object::ELFObjectFile<ELFT>>(**ELFObj); 48206c3fb27SDimitry Andric return ELFLinkGraphBuilder_ppc64<Endianness>( 48306c3fb27SDimitry Andric (*ELFObj)->getFileName(), ELFObjFile.getELFFile(), 48406c3fb27SDimitry Andric (*ELFObj)->makeTriple(), std::move(*Features)) 48506c3fb27SDimitry Andric .buildGraph(); 48606c3fb27SDimitry Andric } 48706c3fb27SDimitry Andric 488*5f757f3fSDimitry Andric template <llvm::endianness Endianness> 48906c3fb27SDimitry Andric void link_ELF_ppc64(std::unique_ptr<LinkGraph> G, 49006c3fb27SDimitry Andric std::unique_ptr<JITLinkContext> Ctx) { 49106c3fb27SDimitry Andric PassConfiguration Config; 49206c3fb27SDimitry Andric 49306c3fb27SDimitry Andric if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) { 49406c3fb27SDimitry Andric // Construct a JITLinker and run the link function. 49506c3fb27SDimitry Andric 496*5f757f3fSDimitry Andric // Add eh-frame passes. 49706c3fb27SDimitry Andric Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame")); 49806c3fb27SDimitry Andric Config.PrePrunePasses.push_back(EHFrameEdgeFixer( 49906c3fb27SDimitry Andric ".eh_frame", G->getPointerSize(), ppc64::Pointer32, ppc64::Pointer64, 50006c3fb27SDimitry Andric ppc64::Delta32, ppc64::Delta64, ppc64::NegDelta32)); 50106c3fb27SDimitry Andric Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame")); 50206c3fb27SDimitry Andric 50306c3fb27SDimitry Andric // Add a mark-live pass. 50406c3fb27SDimitry Andric if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple())) 50506c3fb27SDimitry Andric Config.PrePrunePasses.push_back(std::move(MarkLive)); 50606c3fb27SDimitry Andric else 50706c3fb27SDimitry Andric Config.PrePrunePasses.push_back(markAllSymbolsLive); 50806c3fb27SDimitry Andric } 50906c3fb27SDimitry Andric 51006c3fb27SDimitry Andric Config.PostPrunePasses.push_back(buildTables_ELF_ppc64<Endianness>); 51106c3fb27SDimitry Andric 51206c3fb27SDimitry Andric if (auto Err = Ctx->modifyPassConfig(*G, Config)) 51306c3fb27SDimitry Andric return Ctx->notifyFailed(std::move(Err)); 51406c3fb27SDimitry Andric 51506c3fb27SDimitry Andric ELFJITLinker_ppc64<Endianness>::link(std::move(Ctx), std::move(G), 51606c3fb27SDimitry Andric std::move(Config)); 51706c3fb27SDimitry Andric } 51806c3fb27SDimitry Andric 51906c3fb27SDimitry Andric Expected<std::unique_ptr<LinkGraph>> 52006c3fb27SDimitry Andric createLinkGraphFromELFObject_ppc64(MemoryBufferRef ObjectBuffer) { 521*5f757f3fSDimitry Andric return createLinkGraphFromELFObject_ppc64<llvm::endianness::big>( 52206c3fb27SDimitry Andric std::move(ObjectBuffer)); 52306c3fb27SDimitry Andric } 52406c3fb27SDimitry Andric 52506c3fb27SDimitry Andric Expected<std::unique_ptr<LinkGraph>> 52606c3fb27SDimitry Andric createLinkGraphFromELFObject_ppc64le(MemoryBufferRef ObjectBuffer) { 527*5f757f3fSDimitry Andric return createLinkGraphFromELFObject_ppc64<llvm::endianness::little>( 52806c3fb27SDimitry Andric std::move(ObjectBuffer)); 52906c3fb27SDimitry Andric } 53006c3fb27SDimitry Andric 53106c3fb27SDimitry Andric /// jit-link the given object buffer, which must be a ELF ppc64 object file. 53206c3fb27SDimitry Andric void link_ELF_ppc64(std::unique_ptr<LinkGraph> G, 53306c3fb27SDimitry Andric std::unique_ptr<JITLinkContext> Ctx) { 534*5f757f3fSDimitry Andric return link_ELF_ppc64<llvm::endianness::big>(std::move(G), std::move(Ctx)); 53506c3fb27SDimitry Andric } 53606c3fb27SDimitry Andric 53706c3fb27SDimitry Andric /// jit-link the given object buffer, which must be a ELF ppc64le object file. 53806c3fb27SDimitry Andric void link_ELF_ppc64le(std::unique_ptr<LinkGraph> G, 53906c3fb27SDimitry Andric std::unique_ptr<JITLinkContext> Ctx) { 540*5f757f3fSDimitry Andric return link_ELF_ppc64<llvm::endianness::little>(std::move(G), std::move(Ctx)); 54106c3fb27SDimitry Andric } 54206c3fb27SDimitry Andric 54306c3fb27SDimitry Andric } // end namespace llvm::jitlink 544