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