xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/ELF_ppc64.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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 
getSectionName()41*5f757f3fSDimitry Andric   static StringRef getSectionName() { return ELFTLSInfoSectionName; }
42*5f757f3fSDimitry Andric 
visitEdge(LinkGraph & G,Block * B,Edge & E)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 
createEntry(LinkGraph & G,Symbol & Target)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:
getTLSInfoSection(LinkGraph & G)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 
getTLSInfoEntryContent() const81*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>
createELFGOTHeader(LinkGraph & G,ppc64::TOCTableManager<Endianness> & TOC)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
registerExistingGOTEntries(LinkGraph & G,ppc64::TOCTableManager<Endianness> & TOC)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>
buildTables_ELF_ppc64(LinkGraph & G)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 
addRelocations()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 
addSingleRelocation(const typename ELFT::Rela & Rel,const typename ELFT::Shdr & FixupSection,Block & BlockToFix)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:
ELFLinkGraphBuilder_ppc64(StringRef FileName,const object::ELFFile<ELFT> & Obj,Triple TT,SubtargetFeatures Features)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:
ELFJITLinker_ppc64(std::unique_ptr<JITLinkContext> Ctx,std::unique_ptr<LinkGraph> G,PassConfiguration PassConfig)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 
defineTOCBase(LinkGraph & G)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 
applyFixup(LinkGraph & G,Block & B,const Edge & E) const45906c3fb27SDimitry 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>>
createLinkGraphFromELFObject_ppc64(MemoryBufferRef ObjectBuffer)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>
link_ELF_ppc64(std::unique_ptr<LinkGraph> G,std::unique_ptr<JITLinkContext> Ctx)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>>
createLinkGraphFromELFObject_ppc64(MemoryBufferRef ObjectBuffer)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>>
createLinkGraphFromELFObject_ppc64le(MemoryBufferRef ObjectBuffer)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.
link_ELF_ppc64(std::unique_ptr<LinkGraph> G,std::unique_ptr<JITLinkContext> Ctx)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.
link_ELF_ppc64le(std::unique_ptr<LinkGraph> G,std::unique_ptr<JITLinkContext> Ctx)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