1*06c3fb27SDimitry Andric //===------- ELF_ppc64.cpp -JIT linker implementation for ELF/ppc64 -------===// 2*06c3fb27SDimitry Andric // 3*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*06c3fb27SDimitry Andric // 7*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 8*06c3fb27SDimitry Andric // 9*06c3fb27SDimitry Andric // ELF/ppc64 jit-link implementation. 10*06c3fb27SDimitry Andric // 11*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 12*06c3fb27SDimitry Andric 13*06c3fb27SDimitry Andric #include "llvm/ExecutionEngine/JITLink/ELF_ppc64.h" 14*06c3fb27SDimitry Andric #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h" 15*06c3fb27SDimitry Andric #include "llvm/ExecutionEngine/JITLink/TableManager.h" 16*06c3fb27SDimitry Andric #include "llvm/ExecutionEngine/JITLink/ppc64.h" 17*06c3fb27SDimitry Andric #include "llvm/Object/ELFObjectFile.h" 18*06c3fb27SDimitry Andric #include "llvm/Support/Endian.h" 19*06c3fb27SDimitry Andric 20*06c3fb27SDimitry Andric #include "EHFrameSupportImpl.h" 21*06c3fb27SDimitry Andric #include "ELFLinkGraphBuilder.h" 22*06c3fb27SDimitry Andric #include "JITLinkGeneric.h" 23*06c3fb27SDimitry Andric 24*06c3fb27SDimitry Andric #define DEBUG_TYPE "jitlink" 25*06c3fb27SDimitry Andric 26*06c3fb27SDimitry Andric namespace { 27*06c3fb27SDimitry Andric 28*06c3fb27SDimitry Andric using namespace llvm; 29*06c3fb27SDimitry Andric using namespace llvm::jitlink; 30*06c3fb27SDimitry Andric 31*06c3fb27SDimitry Andric constexpr StringRef ELFTOCSymbolName = ".TOC."; 32*06c3fb27SDimitry Andric constexpr StringRef TOCSymbolAliasIdent = "__TOC__"; 33*06c3fb27SDimitry Andric constexpr uint64_t ELFTOCBaseOffset = 0x8000; 34*06c3fb27SDimitry Andric 35*06c3fb27SDimitry Andric template <support::endianness Endianness> 36*06c3fb27SDimitry Andric Symbol &createELFGOTHeader(LinkGraph &G, 37*06c3fb27SDimitry Andric ppc64::TOCTableManager<Endianness> &TOC) { 38*06c3fb27SDimitry Andric Symbol *TOCSymbol = nullptr; 39*06c3fb27SDimitry Andric 40*06c3fb27SDimitry Andric for (Symbol *Sym : G.defined_symbols()) 41*06c3fb27SDimitry Andric if (LLVM_UNLIKELY(Sym->getName() == ELFTOCSymbolName)) { 42*06c3fb27SDimitry Andric TOCSymbol = Sym; 43*06c3fb27SDimitry Andric break; 44*06c3fb27SDimitry Andric } 45*06c3fb27SDimitry Andric 46*06c3fb27SDimitry Andric if (LLVM_LIKELY(TOCSymbol == nullptr)) { 47*06c3fb27SDimitry Andric for (Symbol *Sym : G.external_symbols()) 48*06c3fb27SDimitry Andric if (Sym->getName() == ELFTOCSymbolName) { 49*06c3fb27SDimitry Andric TOCSymbol = Sym; 50*06c3fb27SDimitry Andric break; 51*06c3fb27SDimitry Andric } 52*06c3fb27SDimitry Andric } 53*06c3fb27SDimitry Andric 54*06c3fb27SDimitry Andric if (!TOCSymbol) 55*06c3fb27SDimitry Andric TOCSymbol = &G.addExternalSymbol(ELFTOCSymbolName, 0, false); 56*06c3fb27SDimitry Andric 57*06c3fb27SDimitry Andric return TOC.getEntryForTarget(G, *TOCSymbol); 58*06c3fb27SDimitry Andric } 59*06c3fb27SDimitry Andric 60*06c3fb27SDimitry Andric // Register preexisting GOT entries with TOC table manager. 61*06c3fb27SDimitry Andric template <support::endianness Endianness> 62*06c3fb27SDimitry Andric inline void 63*06c3fb27SDimitry Andric registerExistingGOTEntries(LinkGraph &G, 64*06c3fb27SDimitry Andric ppc64::TOCTableManager<Endianness> &TOC) { 65*06c3fb27SDimitry Andric auto isGOTEntry = [](const Edge &E) { 66*06c3fb27SDimitry Andric return E.getKind() == ppc64::Pointer64 && E.getTarget().isExternal(); 67*06c3fb27SDimitry Andric }; 68*06c3fb27SDimitry Andric if (Section *dotTOCSection = G.findSectionByName(".toc")) { 69*06c3fb27SDimitry Andric for (Block *B : dotTOCSection->blocks()) 70*06c3fb27SDimitry Andric for (Edge &E : B->edges()) 71*06c3fb27SDimitry Andric if (isGOTEntry(E)) 72*06c3fb27SDimitry Andric TOC.registerPreExistingEntry(E.getTarget(), 73*06c3fb27SDimitry Andric G.addAnonymousSymbol(*B, E.getOffset(), 74*06c3fb27SDimitry Andric G.getPointerSize(), 75*06c3fb27SDimitry Andric false, false)); 76*06c3fb27SDimitry Andric } 77*06c3fb27SDimitry Andric } 78*06c3fb27SDimitry Andric 79*06c3fb27SDimitry Andric template <support::endianness Endianness> 80*06c3fb27SDimitry Andric Error buildTables_ELF_ppc64(LinkGraph &G) { 81*06c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n"); 82*06c3fb27SDimitry Andric ppc64::TOCTableManager<Endianness> TOC; 83*06c3fb27SDimitry Andric // Before visiting edges, we create a header containing the address of TOC 84*06c3fb27SDimitry Andric // base as ELFABIv2 suggests: 85*06c3fb27SDimitry Andric // > The GOT consists of an 8-byte header that contains the TOC base (the 86*06c3fb27SDimitry Andric // first TOC base when multiple TOCs are present), followed by an array of 87*06c3fb27SDimitry Andric // 8-byte addresses. 88*06c3fb27SDimitry Andric createELFGOTHeader(G, TOC); 89*06c3fb27SDimitry Andric 90*06c3fb27SDimitry Andric // There might be compiler-generated GOT entries in ELF relocatable file. 91*06c3fb27SDimitry Andric registerExistingGOTEntries(G, TOC); 92*06c3fb27SDimitry Andric 93*06c3fb27SDimitry Andric ppc64::PLTTableManager<Endianness> PLT(TOC); 94*06c3fb27SDimitry Andric visitExistingEdges(G, TOC, PLT); 95*06c3fb27SDimitry Andric // TODO: Add TLS support. 96*06c3fb27SDimitry Andric 97*06c3fb27SDimitry Andric // After visiting edges in LinkGraph, we have GOT entries built in the 98*06c3fb27SDimitry Andric // synthesized section. 99*06c3fb27SDimitry Andric // Merge sections included in TOC into synthesized TOC section, 100*06c3fb27SDimitry Andric // thus TOC is compact and reducing chances of relocation 101*06c3fb27SDimitry Andric // overflow. 102*06c3fb27SDimitry Andric if (Section *TOCSection = G.findSectionByName(TOC.getSectionName())) { 103*06c3fb27SDimitry Andric // .got and .plt are not normally present in a relocatable object file 104*06c3fb27SDimitry Andric // because they are linker generated. 105*06c3fb27SDimitry Andric if (Section *gotSection = G.findSectionByName(".got")) 106*06c3fb27SDimitry Andric G.mergeSections(*TOCSection, *gotSection); 107*06c3fb27SDimitry Andric if (Section *tocSection = G.findSectionByName(".toc")) 108*06c3fb27SDimitry Andric G.mergeSections(*TOCSection, *tocSection); 109*06c3fb27SDimitry Andric if (Section *sdataSection = G.findSectionByName(".sdata")) 110*06c3fb27SDimitry Andric G.mergeSections(*TOCSection, *sdataSection); 111*06c3fb27SDimitry Andric if (Section *sbssSection = G.findSectionByName(".sbss")) 112*06c3fb27SDimitry Andric G.mergeSections(*TOCSection, *sbssSection); 113*06c3fb27SDimitry Andric // .tocbss no longer appears in ELFABIv2. Leave it here to be compatible 114*06c3fb27SDimitry Andric // with rtdyld. 115*06c3fb27SDimitry Andric if (Section *tocbssSection = G.findSectionByName(".tocbss")) 116*06c3fb27SDimitry Andric G.mergeSections(*TOCSection, *tocbssSection); 117*06c3fb27SDimitry Andric if (Section *pltSection = G.findSectionByName(".plt")) 118*06c3fb27SDimitry Andric G.mergeSections(*TOCSection, *pltSection); 119*06c3fb27SDimitry Andric } 120*06c3fb27SDimitry Andric 121*06c3fb27SDimitry Andric return Error::success(); 122*06c3fb27SDimitry Andric } 123*06c3fb27SDimitry Andric 124*06c3fb27SDimitry Andric } // namespace 125*06c3fb27SDimitry Andric 126*06c3fb27SDimitry Andric namespace llvm::jitlink { 127*06c3fb27SDimitry Andric 128*06c3fb27SDimitry Andric template <support::endianness Endianness> 129*06c3fb27SDimitry Andric class ELFLinkGraphBuilder_ppc64 130*06c3fb27SDimitry Andric : public ELFLinkGraphBuilder<object::ELFType<Endianness, true>> { 131*06c3fb27SDimitry Andric private: 132*06c3fb27SDimitry Andric using ELFT = object::ELFType<Endianness, true>; 133*06c3fb27SDimitry Andric using Base = ELFLinkGraphBuilder<ELFT>; 134*06c3fb27SDimitry Andric 135*06c3fb27SDimitry Andric using Base::G; // Use LinkGraph pointer from base class. 136*06c3fb27SDimitry Andric 137*06c3fb27SDimitry Andric Error addRelocations() override { 138*06c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "Processing relocations:\n"); 139*06c3fb27SDimitry Andric 140*06c3fb27SDimitry Andric using Self = ELFLinkGraphBuilder_ppc64<Endianness>; 141*06c3fb27SDimitry Andric for (const auto &RelSect : Base::Sections) { 142*06c3fb27SDimitry Andric // Validate the section to read relocation entries from. 143*06c3fb27SDimitry Andric if (RelSect.sh_type == ELF::SHT_REL) 144*06c3fb27SDimitry Andric return make_error<StringError>("No SHT_REL in valid " + 145*06c3fb27SDimitry Andric G->getTargetTriple().getArchName() + 146*06c3fb27SDimitry Andric " ELF object files", 147*06c3fb27SDimitry Andric inconvertibleErrorCode()); 148*06c3fb27SDimitry Andric 149*06c3fb27SDimitry Andric if (Error Err = Base::forEachRelaRelocation(RelSect, this, 150*06c3fb27SDimitry Andric &Self::addSingleRelocation)) 151*06c3fb27SDimitry Andric return Err; 152*06c3fb27SDimitry Andric } 153*06c3fb27SDimitry Andric 154*06c3fb27SDimitry Andric return Error::success(); 155*06c3fb27SDimitry Andric } 156*06c3fb27SDimitry Andric 157*06c3fb27SDimitry Andric Error addSingleRelocation(const typename ELFT::Rela &Rel, 158*06c3fb27SDimitry Andric const typename ELFT::Shdr &FixupSection, 159*06c3fb27SDimitry Andric Block &BlockToFix) { 160*06c3fb27SDimitry Andric using Base = ELFLinkGraphBuilder<ELFT>; 161*06c3fb27SDimitry Andric auto ELFReloc = Rel.getType(false); 162*06c3fb27SDimitry Andric 163*06c3fb27SDimitry Andric // R_PPC64_NONE is a no-op. 164*06c3fb27SDimitry Andric if (LLVM_UNLIKELY(ELFReloc == ELF::R_PPC64_NONE)) 165*06c3fb27SDimitry Andric return Error::success(); 166*06c3fb27SDimitry Andric 167*06c3fb27SDimitry Andric auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec); 168*06c3fb27SDimitry Andric if (!ObjSymbol) 169*06c3fb27SDimitry Andric return ObjSymbol.takeError(); 170*06c3fb27SDimitry Andric 171*06c3fb27SDimitry Andric uint32_t SymbolIndex = Rel.getSymbol(false); 172*06c3fb27SDimitry Andric Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex); 173*06c3fb27SDimitry Andric if (!GraphSymbol) 174*06c3fb27SDimitry Andric return make_error<StringError>( 175*06c3fb27SDimitry Andric formatv("Could not find symbol at given index, did you add it to " 176*06c3fb27SDimitry Andric "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}", 177*06c3fb27SDimitry Andric SymbolIndex, (*ObjSymbol)->st_shndx, 178*06c3fb27SDimitry Andric Base::GraphSymbols.size()), 179*06c3fb27SDimitry Andric inconvertibleErrorCode()); 180*06c3fb27SDimitry Andric 181*06c3fb27SDimitry Andric int64_t Addend = Rel.r_addend; 182*06c3fb27SDimitry Andric orc::ExecutorAddr FixupAddress = 183*06c3fb27SDimitry Andric orc::ExecutorAddr(FixupSection.sh_addr) + Rel.r_offset; 184*06c3fb27SDimitry Andric Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress(); 185*06c3fb27SDimitry Andric Edge::Kind Kind = Edge::Invalid; 186*06c3fb27SDimitry Andric 187*06c3fb27SDimitry Andric switch (ELFReloc) { 188*06c3fb27SDimitry Andric default: 189*06c3fb27SDimitry Andric return make_error<JITLinkError>( 190*06c3fb27SDimitry Andric "In " + G->getName() + ": Unsupported ppc64 relocation type " + 191*06c3fb27SDimitry Andric object::getELFRelocationTypeName(ELF::EM_PPC64, ELFReloc)); 192*06c3fb27SDimitry Andric case ELF::R_PPC64_ADDR64: 193*06c3fb27SDimitry Andric Kind = ppc64::Pointer64; 194*06c3fb27SDimitry Andric break; 195*06c3fb27SDimitry Andric case ELF::R_PPC64_TOC16_HA: 196*06c3fb27SDimitry Andric Kind = ppc64::TOCDelta16HA; 197*06c3fb27SDimitry Andric break; 198*06c3fb27SDimitry Andric case ELF::R_PPC64_TOC16_DS: 199*06c3fb27SDimitry Andric Kind = ppc64::TOCDelta16DS; 200*06c3fb27SDimitry Andric break; 201*06c3fb27SDimitry Andric case ELF::R_PPC64_TOC16_LO: 202*06c3fb27SDimitry Andric Kind = ppc64::TOCDelta16LO; 203*06c3fb27SDimitry Andric break; 204*06c3fb27SDimitry Andric case ELF::R_PPC64_TOC16_LO_DS: 205*06c3fb27SDimitry Andric Kind = ppc64::TOCDelta16LODS; 206*06c3fb27SDimitry Andric break; 207*06c3fb27SDimitry Andric case ELF::R_PPC64_REL16: 208*06c3fb27SDimitry Andric Kind = ppc64::Delta16; 209*06c3fb27SDimitry Andric break; 210*06c3fb27SDimitry Andric case ELF::R_PPC64_REL16_HA: 211*06c3fb27SDimitry Andric Kind = ppc64::Delta16HA; 212*06c3fb27SDimitry Andric break; 213*06c3fb27SDimitry Andric case ELF::R_PPC64_REL16_LO: 214*06c3fb27SDimitry Andric Kind = ppc64::Delta16LO; 215*06c3fb27SDimitry Andric break; 216*06c3fb27SDimitry Andric case ELF::R_PPC64_REL32: 217*06c3fb27SDimitry Andric Kind = ppc64::Delta32; 218*06c3fb27SDimitry Andric break; 219*06c3fb27SDimitry Andric case ELF::R_PPC64_REL24_NOTOC: 220*06c3fb27SDimitry Andric case ELF::R_PPC64_REL24: { 221*06c3fb27SDimitry Andric bool isLocal = !GraphSymbol->isExternal(); 222*06c3fb27SDimitry Andric if (isLocal) { 223*06c3fb27SDimitry Andric // TODO: There are cases a local function call need a call stub. 224*06c3fb27SDimitry Andric // 1. Caller uses TOC, the callee doesn't, need a r2 save stub. 225*06c3fb27SDimitry Andric // 2. Caller doesn't use TOC, the callee does, need a r12 setup stub. 226*06c3fb27SDimitry Andric // FIXME: For a local call, we might need a thunk if branch target is 227*06c3fb27SDimitry Andric // out of range. 228*06c3fb27SDimitry Andric Kind = ppc64::CallBranchDelta; 229*06c3fb27SDimitry Andric // Branch to local entry. 230*06c3fb27SDimitry Andric Addend += ELF::decodePPC64LocalEntryOffset((*ObjSymbol)->st_other); 231*06c3fb27SDimitry Andric } else { 232*06c3fb27SDimitry Andric Kind = ELFReloc == ELF::R_PPC64_REL24 ? ppc64::RequestPLTCallStubSaveTOC 233*06c3fb27SDimitry Andric : ppc64::RequestPLTCallStubNoTOC; 234*06c3fb27SDimitry Andric } 235*06c3fb27SDimitry Andric break; 236*06c3fb27SDimitry Andric } 237*06c3fb27SDimitry Andric case ELF::R_PPC64_REL64: 238*06c3fb27SDimitry Andric Kind = ppc64::Delta64; 239*06c3fb27SDimitry Andric break; 240*06c3fb27SDimitry Andric } 241*06c3fb27SDimitry Andric 242*06c3fb27SDimitry Andric Edge GE(Kind, Offset, *GraphSymbol, Addend); 243*06c3fb27SDimitry Andric BlockToFix.addEdge(std::move(GE)); 244*06c3fb27SDimitry Andric return Error::success(); 245*06c3fb27SDimitry Andric } 246*06c3fb27SDimitry Andric 247*06c3fb27SDimitry Andric public: 248*06c3fb27SDimitry Andric ELFLinkGraphBuilder_ppc64(StringRef FileName, 249*06c3fb27SDimitry Andric const object::ELFFile<ELFT> &Obj, Triple TT, 250*06c3fb27SDimitry Andric SubtargetFeatures Features) 251*06c3fb27SDimitry Andric : ELFLinkGraphBuilder<ELFT>(Obj, std::move(TT), std::move(Features), 252*06c3fb27SDimitry Andric FileName, ppc64::getEdgeKindName) {} 253*06c3fb27SDimitry Andric }; 254*06c3fb27SDimitry Andric 255*06c3fb27SDimitry Andric template <support::endianness Endianness> 256*06c3fb27SDimitry Andric class ELFJITLinker_ppc64 : public JITLinker<ELFJITLinker_ppc64<Endianness>> { 257*06c3fb27SDimitry Andric using JITLinkerBase = JITLinker<ELFJITLinker_ppc64<Endianness>>; 258*06c3fb27SDimitry Andric friend JITLinkerBase; 259*06c3fb27SDimitry Andric 260*06c3fb27SDimitry Andric public: 261*06c3fb27SDimitry Andric ELFJITLinker_ppc64(std::unique_ptr<JITLinkContext> Ctx, 262*06c3fb27SDimitry Andric std::unique_ptr<LinkGraph> G, PassConfiguration PassConfig) 263*06c3fb27SDimitry Andric : JITLinkerBase(std::move(Ctx), std::move(G), std::move(PassConfig)) { 264*06c3fb27SDimitry Andric JITLinkerBase::getPassConfig().PostAllocationPasses.push_back( 265*06c3fb27SDimitry Andric [this](LinkGraph &G) { return defineTOCBase(G); }); 266*06c3fb27SDimitry Andric } 267*06c3fb27SDimitry Andric 268*06c3fb27SDimitry Andric private: 269*06c3fb27SDimitry Andric Symbol *TOCSymbol = nullptr; 270*06c3fb27SDimitry Andric 271*06c3fb27SDimitry Andric Error defineTOCBase(LinkGraph &G) { 272*06c3fb27SDimitry Andric for (Symbol *Sym : G.defined_symbols()) { 273*06c3fb27SDimitry Andric if (LLVM_UNLIKELY(Sym->getName() == ELFTOCSymbolName)) { 274*06c3fb27SDimitry Andric TOCSymbol = Sym; 275*06c3fb27SDimitry Andric return Error::success(); 276*06c3fb27SDimitry Andric } 277*06c3fb27SDimitry Andric } 278*06c3fb27SDimitry Andric 279*06c3fb27SDimitry Andric assert(TOCSymbol == nullptr && 280*06c3fb27SDimitry Andric "TOCSymbol should not be defined at this point"); 281*06c3fb27SDimitry Andric 282*06c3fb27SDimitry Andric for (Symbol *Sym : G.external_symbols()) { 283*06c3fb27SDimitry Andric if (Sym->getName() == ELFTOCSymbolName) { 284*06c3fb27SDimitry Andric TOCSymbol = Sym; 285*06c3fb27SDimitry Andric break; 286*06c3fb27SDimitry Andric } 287*06c3fb27SDimitry Andric } 288*06c3fb27SDimitry Andric 289*06c3fb27SDimitry Andric if (Section *TOCSection = G.findSectionByName( 290*06c3fb27SDimitry Andric ppc64::TOCTableManager<Endianness>::getSectionName())) { 291*06c3fb27SDimitry Andric assert(!TOCSection->empty() && "TOC section should have reserved an " 292*06c3fb27SDimitry Andric "entry for containing the TOC base"); 293*06c3fb27SDimitry Andric 294*06c3fb27SDimitry Andric SectionRange SR(*TOCSection); 295*06c3fb27SDimitry Andric orc::ExecutorAddr TOCBaseAddr(SR.getFirstBlock()->getAddress() + 296*06c3fb27SDimitry Andric ELFTOCBaseOffset); 297*06c3fb27SDimitry Andric assert(TOCSymbol && TOCSymbol->isExternal() && 298*06c3fb27SDimitry Andric ".TOC. should be a external symbol at this point"); 299*06c3fb27SDimitry Andric G.makeAbsolute(*TOCSymbol, TOCBaseAddr); 300*06c3fb27SDimitry Andric // Create an alias of .TOC. so that rtdyld checker can recognize. 301*06c3fb27SDimitry Andric G.addAbsoluteSymbol(TOCSymbolAliasIdent, TOCSymbol->getAddress(), 302*06c3fb27SDimitry Andric TOCSymbol->getSize(), TOCSymbol->getLinkage(), 303*06c3fb27SDimitry Andric TOCSymbol->getScope(), TOCSymbol->isLive()); 304*06c3fb27SDimitry Andric return Error::success(); 305*06c3fb27SDimitry Andric } 306*06c3fb27SDimitry Andric 307*06c3fb27SDimitry Andric // If TOC section doesn't exist, which means no TOC relocation is found, we 308*06c3fb27SDimitry Andric // don't need a TOCSymbol. 309*06c3fb27SDimitry Andric return Error::success(); 310*06c3fb27SDimitry Andric } 311*06c3fb27SDimitry Andric 312*06c3fb27SDimitry Andric Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const { 313*06c3fb27SDimitry Andric return ppc64::applyFixup<Endianness>(G, B, E, TOCSymbol); 314*06c3fb27SDimitry Andric } 315*06c3fb27SDimitry Andric }; 316*06c3fb27SDimitry Andric 317*06c3fb27SDimitry Andric template <support::endianness Endianness> 318*06c3fb27SDimitry Andric Expected<std::unique_ptr<LinkGraph>> 319*06c3fb27SDimitry Andric createLinkGraphFromELFObject_ppc64(MemoryBufferRef ObjectBuffer) { 320*06c3fb27SDimitry Andric LLVM_DEBUG({ 321*06c3fb27SDimitry Andric dbgs() << "Building jitlink graph for new input " 322*06c3fb27SDimitry Andric << ObjectBuffer.getBufferIdentifier() << "...\n"; 323*06c3fb27SDimitry Andric }); 324*06c3fb27SDimitry Andric 325*06c3fb27SDimitry Andric auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer); 326*06c3fb27SDimitry Andric if (!ELFObj) 327*06c3fb27SDimitry Andric return ELFObj.takeError(); 328*06c3fb27SDimitry Andric 329*06c3fb27SDimitry Andric auto Features = (*ELFObj)->getFeatures(); 330*06c3fb27SDimitry Andric if (!Features) 331*06c3fb27SDimitry Andric return Features.takeError(); 332*06c3fb27SDimitry Andric 333*06c3fb27SDimitry Andric using ELFT = object::ELFType<Endianness, true>; 334*06c3fb27SDimitry Andric auto &ELFObjFile = cast<object::ELFObjectFile<ELFT>>(**ELFObj); 335*06c3fb27SDimitry Andric return ELFLinkGraphBuilder_ppc64<Endianness>( 336*06c3fb27SDimitry Andric (*ELFObj)->getFileName(), ELFObjFile.getELFFile(), 337*06c3fb27SDimitry Andric (*ELFObj)->makeTriple(), std::move(*Features)) 338*06c3fb27SDimitry Andric .buildGraph(); 339*06c3fb27SDimitry Andric } 340*06c3fb27SDimitry Andric 341*06c3fb27SDimitry Andric template <support::endianness Endianness> 342*06c3fb27SDimitry Andric void link_ELF_ppc64(std::unique_ptr<LinkGraph> G, 343*06c3fb27SDimitry Andric std::unique_ptr<JITLinkContext> Ctx) { 344*06c3fb27SDimitry Andric PassConfiguration Config; 345*06c3fb27SDimitry Andric 346*06c3fb27SDimitry Andric if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) { 347*06c3fb27SDimitry Andric // Construct a JITLinker and run the link function. 348*06c3fb27SDimitry Andric 349*06c3fb27SDimitry Andric // Add eh-frame passses. 350*06c3fb27SDimitry Andric Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame")); 351*06c3fb27SDimitry Andric Config.PrePrunePasses.push_back(EHFrameEdgeFixer( 352*06c3fb27SDimitry Andric ".eh_frame", G->getPointerSize(), ppc64::Pointer32, ppc64::Pointer64, 353*06c3fb27SDimitry Andric ppc64::Delta32, ppc64::Delta64, ppc64::NegDelta32)); 354*06c3fb27SDimitry Andric Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame")); 355*06c3fb27SDimitry Andric 356*06c3fb27SDimitry Andric // Add a mark-live pass. 357*06c3fb27SDimitry Andric if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple())) 358*06c3fb27SDimitry Andric Config.PrePrunePasses.push_back(std::move(MarkLive)); 359*06c3fb27SDimitry Andric else 360*06c3fb27SDimitry Andric Config.PrePrunePasses.push_back(markAllSymbolsLive); 361*06c3fb27SDimitry Andric } 362*06c3fb27SDimitry Andric 363*06c3fb27SDimitry Andric Config.PostPrunePasses.push_back(buildTables_ELF_ppc64<Endianness>); 364*06c3fb27SDimitry Andric 365*06c3fb27SDimitry Andric if (auto Err = Ctx->modifyPassConfig(*G, Config)) 366*06c3fb27SDimitry Andric return Ctx->notifyFailed(std::move(Err)); 367*06c3fb27SDimitry Andric 368*06c3fb27SDimitry Andric ELFJITLinker_ppc64<Endianness>::link(std::move(Ctx), std::move(G), 369*06c3fb27SDimitry Andric std::move(Config)); 370*06c3fb27SDimitry Andric } 371*06c3fb27SDimitry Andric 372*06c3fb27SDimitry Andric Expected<std::unique_ptr<LinkGraph>> 373*06c3fb27SDimitry Andric createLinkGraphFromELFObject_ppc64(MemoryBufferRef ObjectBuffer) { 374*06c3fb27SDimitry Andric return createLinkGraphFromELFObject_ppc64<support::big>( 375*06c3fb27SDimitry Andric std::move(ObjectBuffer)); 376*06c3fb27SDimitry Andric } 377*06c3fb27SDimitry Andric 378*06c3fb27SDimitry Andric Expected<std::unique_ptr<LinkGraph>> 379*06c3fb27SDimitry Andric createLinkGraphFromELFObject_ppc64le(MemoryBufferRef ObjectBuffer) { 380*06c3fb27SDimitry Andric return createLinkGraphFromELFObject_ppc64<support::little>( 381*06c3fb27SDimitry Andric std::move(ObjectBuffer)); 382*06c3fb27SDimitry Andric } 383*06c3fb27SDimitry Andric 384*06c3fb27SDimitry Andric /// jit-link the given object buffer, which must be a ELF ppc64 object file. 385*06c3fb27SDimitry Andric void link_ELF_ppc64(std::unique_ptr<LinkGraph> G, 386*06c3fb27SDimitry Andric std::unique_ptr<JITLinkContext> Ctx) { 387*06c3fb27SDimitry Andric return link_ELF_ppc64<support::big>(std::move(G), std::move(Ctx)); 388*06c3fb27SDimitry Andric } 389*06c3fb27SDimitry Andric 390*06c3fb27SDimitry Andric /// jit-link the given object buffer, which must be a ELF ppc64le object file. 391*06c3fb27SDimitry Andric void link_ELF_ppc64le(std::unique_ptr<LinkGraph> G, 392*06c3fb27SDimitry Andric std::unique_ptr<JITLinkContext> Ctx) { 393*06c3fb27SDimitry Andric return link_ELF_ppc64<support::little>(std::move(G), std::move(Ctx)); 394*06c3fb27SDimitry Andric } 395*06c3fb27SDimitry Andric 396*06c3fb27SDimitry Andric } // end namespace llvm::jitlink 397