xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/ELF_ppc64.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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