xref: /llvm-project/llvm/lib/ExecutionEngine/JITLink/ELF_ppc64.cpp (revision 2ccf7ed277df28651b94bbee9fccefdf22fb074f)
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