xref: /llvm-project/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp (revision 42595bdaefb6b066896c20b69ab66ff2a7fe8477)
12ed91da0SStefan Gränitz //===----- ELF_aarch64.cpp - JIT linker implementation for ELF/aarch64 ----===//
22ed91da0SStefan Gränitz //
32ed91da0SStefan Gränitz // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42ed91da0SStefan Gränitz // See https://llvm.org/LICENSE.txt for license information.
52ed91da0SStefan Gränitz // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62ed91da0SStefan Gränitz //
72ed91da0SStefan Gränitz //===----------------------------------------------------------------------===//
82ed91da0SStefan Gränitz //
92ed91da0SStefan Gränitz // ELF/aarch64 jit-link implementation.
102ed91da0SStefan Gränitz //
112ed91da0SStefan Gränitz //===----------------------------------------------------------------------===//
122ed91da0SStefan Gränitz 
132ed91da0SStefan Gränitz #include "llvm/ExecutionEngine/JITLink/ELF_aarch64.h"
142ed91da0SStefan Gränitz #include "llvm/BinaryFormat/ELF.h"
15f8a9536cSSunho Kim #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"
162ed91da0SStefan Gränitz #include "llvm/ExecutionEngine/JITLink/aarch64.h"
172ed91da0SStefan Gränitz #include "llvm/Object/ELFObjectFile.h"
18ab472c96SSunho Kim #include "llvm/Support/Endian.h"
192ed91da0SStefan Gränitz 
20488a1873SLang Hames #include "DefineExternalSectionStartAndEndSymbols.h"
218ef45107SLang Hames #include "EHFrameSupportImpl.h"
228ef45107SLang Hames #include "ELFLinkGraphBuilder.h"
238ef45107SLang Hames #include "JITLinkGeneric.h"
24488a1873SLang Hames 
252ed91da0SStefan Gränitz #define DEBUG_TYPE "jitlink"
262ed91da0SStefan Gränitz 
272ed91da0SStefan Gränitz using namespace llvm;
282ed91da0SStefan Gränitz using namespace llvm::jitlink;
292ed91da0SStefan Gränitz 
30db372258SSunho Kim namespace {
312ed91da0SStefan Gränitz 
32199c4003SVladislav Khmelevsky constexpr StringRef ELFGOTSymbolName = "_GLOBAL_OFFSET_TABLE_";
33199c4003SVladislav Khmelevsky 
342ed91da0SStefan Gränitz class ELFJITLinker_aarch64 : public JITLinker<ELFJITLinker_aarch64> {
352ed91da0SStefan Gränitz   friend class JITLinker<ELFJITLinker_aarch64>;
362ed91da0SStefan Gränitz 
372ed91da0SStefan Gränitz public:
382ed91da0SStefan Gränitz   ELFJITLinker_aarch64(std::unique_ptr<JITLinkContext> Ctx,
392ed91da0SStefan Gränitz                        std::unique_ptr<LinkGraph> G,
402ed91da0SStefan Gränitz                        PassConfiguration PassConfig)
41199c4003SVladislav Khmelevsky       : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {
42199c4003SVladislav Khmelevsky     if (shouldAddDefaultTargetPasses(getGraph().getTargetTriple()))
43199c4003SVladislav Khmelevsky       getPassConfig().PostAllocationPasses.push_back(
44199c4003SVladislav Khmelevsky           [this](LinkGraph &G) { return getOrCreateGOTSymbol(G); });
45199c4003SVladislav Khmelevsky   }
462ed91da0SStefan Gränitz 
472ed91da0SStefan Gränitz private:
48199c4003SVladislav Khmelevsky   Symbol *GOTSymbol = nullptr;
49199c4003SVladislav Khmelevsky 
502ed91da0SStefan Gränitz   Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
51199c4003SVladislav Khmelevsky     return aarch64::applyFixup(G, B, E, GOTSymbol);
52199c4003SVladislav Khmelevsky   }
53199c4003SVladislav Khmelevsky 
54199c4003SVladislav Khmelevsky   Error getOrCreateGOTSymbol(LinkGraph &G) {
552ccf7ed2SJared Wyles     auto InteredGOTSymbolName =
562ccf7ed2SJared Wyles         G.getSymbolStringPool()->intern(ELFGOTSymbolName);
572ccf7ed2SJared Wyles 
58199c4003SVladislav Khmelevsky     auto DefineExternalGOTSymbolIfPresent =
59199c4003SVladislav Khmelevsky         createDefineExternalSectionStartAndEndSymbolsPass(
60199c4003SVladislav Khmelevsky             [&](LinkGraph &LG, Symbol &Sym) -> SectionRangeSymbolDesc {
612ccf7ed2SJared Wyles               if (*Sym.getName() == ELFGOTSymbolName)
62199c4003SVladislav Khmelevsky                 if (auto *GOTSection = G.findSectionByName(
63199c4003SVladislav Khmelevsky                         aarch64::GOTTableManager::getSectionName())) {
64199c4003SVladislav Khmelevsky                   GOTSymbol = &Sym;
65199c4003SVladislav Khmelevsky                   return {*GOTSection, true};
66199c4003SVladislav Khmelevsky                 }
67199c4003SVladislav Khmelevsky               return {};
68199c4003SVladislav Khmelevsky             });
69199c4003SVladislav Khmelevsky 
70199c4003SVladislav Khmelevsky     // Try to attach _GLOBAL_OFFSET_TABLE_ to the GOT if it's defined as an
71199c4003SVladislav Khmelevsky     // external.
72199c4003SVladislav Khmelevsky     if (auto Err = DefineExternalGOTSymbolIfPresent(G))
73199c4003SVladislav Khmelevsky       return Err;
74199c4003SVladislav Khmelevsky 
75199c4003SVladislav Khmelevsky     // If we succeeded then we're done.
76199c4003SVladislav Khmelevsky     if (GOTSymbol)
77199c4003SVladislav Khmelevsky       return Error::success();
78199c4003SVladislav Khmelevsky 
79199c4003SVladislav Khmelevsky     // Otherwise look for a GOT section: If it already has a start symbol we'll
80199c4003SVladislav Khmelevsky     // record it, otherwise we'll create our own.
81199c4003SVladislav Khmelevsky     // If there's a GOT section but we didn't find an external GOT symbol...
82199c4003SVladislav Khmelevsky     if (auto *GOTSection =
83199c4003SVladislav Khmelevsky             G.findSectionByName(aarch64::GOTTableManager::getSectionName())) {
84199c4003SVladislav Khmelevsky 
85199c4003SVladislav Khmelevsky       // Check for an existing defined symbol.
86199c4003SVladislav Khmelevsky       for (auto *Sym : GOTSection->symbols())
872ccf7ed2SJared Wyles         if (Sym->getName() == InteredGOTSymbolName) {
88199c4003SVladislav Khmelevsky           GOTSymbol = Sym;
89199c4003SVladislav Khmelevsky           return Error::success();
90199c4003SVladislav Khmelevsky         }
91199c4003SVladislav Khmelevsky 
92199c4003SVladislav Khmelevsky       // If there's no defined symbol then create one.
93199c4003SVladislav Khmelevsky       SectionRange SR(*GOTSection);
94199c4003SVladislav Khmelevsky       if (SR.empty())
95199c4003SVladislav Khmelevsky         GOTSymbol =
962ccf7ed2SJared Wyles             // FIXME: we should only do this once
972ccf7ed2SJared Wyles             &G.addAbsoluteSymbol(InteredGOTSymbolName, orc::ExecutorAddr(), 0,
98199c4003SVladislav Khmelevsky                                  Linkage::Strong, Scope::Local, true);
99199c4003SVladislav Khmelevsky       else
100199c4003SVladislav Khmelevsky         GOTSymbol =
1012ccf7ed2SJared Wyles             &G.addDefinedSymbol(*SR.getFirstBlock(), 0, InteredGOTSymbolName, 0,
102199c4003SVladislav Khmelevsky                                 Linkage::Strong, Scope::Local, false, true);
103199c4003SVladislav Khmelevsky     }
104199c4003SVladislav Khmelevsky 
105199c4003SVladislav Khmelevsky     // If we still haven't found a GOT symbol then double check the externals.
106199c4003SVladislav Khmelevsky     // We may have a GOT-relative reference but no GOT section, in which case
107199c4003SVladislav Khmelevsky     // we just need to point the GOT symbol at some address in this graph.
108199c4003SVladislav Khmelevsky     if (!GOTSymbol) {
109199c4003SVladislav Khmelevsky       for (auto *Sym : G.external_symbols()) {
1102ccf7ed2SJared Wyles         if (*Sym->getName() == ELFGOTSymbolName) {
111199c4003SVladislav Khmelevsky           auto Blocks = G.blocks();
112199c4003SVladislav Khmelevsky           if (!Blocks.empty()) {
113199c4003SVladislav Khmelevsky             G.makeAbsolute(*Sym, (*Blocks.begin())->getAddress());
114199c4003SVladislav Khmelevsky             GOTSymbol = Sym;
115199c4003SVladislav Khmelevsky             break;
116199c4003SVladislav Khmelevsky           }
117199c4003SVladislav Khmelevsky         }
118199c4003SVladislav Khmelevsky       }
119199c4003SVladislav Khmelevsky     }
120199c4003SVladislav Khmelevsky 
121199c4003SVladislav Khmelevsky     return Error::success();
1222ed91da0SStefan Gränitz   }
1232ed91da0SStefan Gränitz };
1242ed91da0SStefan Gränitz 
1252ed91da0SStefan Gränitz template <typename ELFT>
1262ed91da0SStefan Gränitz class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
1272ed91da0SStefan Gränitz private:
128b6553f59SSunho Kim   enum ELFAArch64RelocationKind : Edge::Kind {
12925a9fb12SSunho Kim     ELFCall26 = Edge::FirstRelocation,
130d395b56aSPavel Samolysov     ELFLdrLo19,
131e9676389SJob Noorman     ELFAdrLo21,
13225a9fb12SSunho Kim     ELFAdrPage21,
13325a9fb12SSunho Kim     ELFAddAbs12,
134ab472c96SSunho Kim     ELFLdSt8Abs12,
135ab472c96SSunho Kim     ELFLdSt16Abs12,
136ab472c96SSunho Kim     ELFLdSt32Abs12,
137ab472c96SSunho Kim     ELFLdSt64Abs12,
138ab472c96SSunho Kim     ELFLdSt128Abs12,
1393d8061a3SSunho Kim     ELFMovwAbsG0,
1403d8061a3SSunho Kim     ELFMovwAbsG1,
1413d8061a3SSunho Kim     ELFMovwAbsG2,
1423d8061a3SSunho Kim     ELFMovwAbsG3,
143a9a2eb81SJob Noorman     ELFTstBr14,
144193a8092SJob Noorman     ELFCondBr19,
145fb1b9945SLang Hames     ELFAbs32,
1461deaa9b8SLang Hames     ELFAbs64,
1475d5183b1SSunho Kim     ELFPrel32,
1485d5183b1SSunho Kim     ELFPrel64,
1492094fad0SSunho Kim     ELFAdrGOTPage21,
1502094fad0SSunho Kim     ELFLd64GOTLo12,
151199c4003SVladislav Khmelevsky     ELFLd64GOTPAGELo15,
15230b6c51fSSunho Kim     ELFTLSDescAdrPage21,
15330b6c51fSSunho Kim     ELFTLSDescAddLo12,
15430b6c51fSSunho Kim     ELFTLSDescLd64Lo12,
15530b6c51fSSunho Kim     ELFTLSDescCall,
156b6553f59SSunho Kim   };
157b6553f59SSunho Kim 
158b6553f59SSunho Kim   static Expected<ELFAArch64RelocationKind>
1592ed91da0SStefan Gränitz   getRelocationKind(const uint32_t Type) {
1602ed91da0SStefan Gränitz     using namespace aarch64;
1612ed91da0SStefan Gränitz     switch (Type) {
1622ed91da0SStefan Gränitz     case ELF::R_AARCH64_CALL26:
163175f22d6SSunho Kim     case ELF::R_AARCH64_JUMP26:
16425a9fb12SSunho Kim       return ELFCall26;
165d395b56aSPavel Samolysov     case ELF::R_AARCH64_LD_PREL_LO19:
166d395b56aSPavel Samolysov       return ELFLdrLo19;
167e9676389SJob Noorman     case ELF::R_AARCH64_ADR_PREL_LO21:
168e9676389SJob Noorman       return ELFAdrLo21;
16925a9fb12SSunho Kim     case ELF::R_AARCH64_ADR_PREL_PG_HI21:
17025a9fb12SSunho Kim       return ELFAdrPage21;
17125a9fb12SSunho Kim     case ELF::R_AARCH64_ADD_ABS_LO12_NC:
17225a9fb12SSunho Kim       return ELFAddAbs12;
173ab472c96SSunho Kim     case ELF::R_AARCH64_LDST8_ABS_LO12_NC:
174ab472c96SSunho Kim       return ELFLdSt8Abs12;
175ab472c96SSunho Kim     case ELF::R_AARCH64_LDST16_ABS_LO12_NC:
176ab472c96SSunho Kim       return ELFLdSt16Abs12;
177ab472c96SSunho Kim     case ELF::R_AARCH64_LDST32_ABS_LO12_NC:
178ab472c96SSunho Kim       return ELFLdSt32Abs12;
179ab472c96SSunho Kim     case ELF::R_AARCH64_LDST64_ABS_LO12_NC:
180ab472c96SSunho Kim       return ELFLdSt64Abs12;
181ab472c96SSunho Kim     case ELF::R_AARCH64_LDST128_ABS_LO12_NC:
182ab472c96SSunho Kim       return ELFLdSt128Abs12;
1833d8061a3SSunho Kim     case ELF::R_AARCH64_MOVW_UABS_G0_NC:
1843d8061a3SSunho Kim       return ELFMovwAbsG0;
1853d8061a3SSunho Kim     case ELF::R_AARCH64_MOVW_UABS_G1_NC:
1863d8061a3SSunho Kim       return ELFMovwAbsG1;
1873d8061a3SSunho Kim     case ELF::R_AARCH64_MOVW_UABS_G2_NC:
1883d8061a3SSunho Kim       return ELFMovwAbsG2;
1893d8061a3SSunho Kim     case ELF::R_AARCH64_MOVW_UABS_G3:
1903d8061a3SSunho Kim       return ELFMovwAbsG3;
191a9a2eb81SJob Noorman     case ELF::R_AARCH64_TSTBR14:
192a9a2eb81SJob Noorman       return ELFTstBr14;
193193a8092SJob Noorman     case ELF::R_AARCH64_CONDBR19:
194193a8092SJob Noorman       return ELFCondBr19;
195fb1b9945SLang Hames     case ELF::R_AARCH64_ABS32:
196fb1b9945SLang Hames       return ELFAbs32;
1971deaa9b8SLang Hames     case ELF::R_AARCH64_ABS64:
1981deaa9b8SLang Hames       return ELFAbs64;
1995d5183b1SSunho Kim     case ELF::R_AARCH64_PREL32:
2005d5183b1SSunho Kim       return ELFPrel32;
2015d5183b1SSunho Kim     case ELF::R_AARCH64_PREL64:
2025d5183b1SSunho Kim       return ELFPrel64;
2032094fad0SSunho Kim     case ELF::R_AARCH64_ADR_GOT_PAGE:
2042094fad0SSunho Kim       return ELFAdrGOTPage21;
2052094fad0SSunho Kim     case ELF::R_AARCH64_LD64_GOT_LO12_NC:
2062094fad0SSunho Kim       return ELFLd64GOTLo12;
207199c4003SVladislav Khmelevsky     case ELF::R_AARCH64_LD64_GOTPAGE_LO15:
208199c4003SVladislav Khmelevsky       return ELFLd64GOTPAGELo15;
20930b6c51fSSunho Kim     case ELF::R_AARCH64_TLSDESC_ADR_PAGE21:
21030b6c51fSSunho Kim       return ELFTLSDescAdrPage21;
21130b6c51fSSunho Kim     case ELF::R_AARCH64_TLSDESC_ADD_LO12:
21230b6c51fSSunho Kim       return ELFTLSDescAddLo12;
21330b6c51fSSunho Kim     case ELF::R_AARCH64_TLSDESC_LD64_LO12:
21430b6c51fSSunho Kim       return ELFTLSDescLd64Lo12;
21530b6c51fSSunho Kim     case ELF::R_AARCH64_TLSDESC_CALL:
21630b6c51fSSunho Kim       return ELFTLSDescCall;
2172ed91da0SStefan Gränitz     }
2182ed91da0SStefan Gränitz 
2199fc0aa45SSunho Kim     return make_error<JITLinkError>(
2209fc0aa45SSunho Kim         "Unsupported aarch64 relocation:" + formatv("{0:d}: ", Type) +
2219fc0aa45SSunho Kim         object::getELFRelocationTypeName(ELF::EM_AARCH64, Type));
2222ed91da0SStefan Gränitz   }
2232ed91da0SStefan Gränitz 
2242ed91da0SStefan Gränitz   Error addRelocations() override {
22596918515SStefan Gränitz     LLVM_DEBUG(dbgs() << "Processing relocations:\n");
22696918515SStefan Gränitz 
2272ed91da0SStefan Gränitz     using Base = ELFLinkGraphBuilder<ELFT>;
22896918515SStefan Gränitz     using Self = ELFLinkGraphBuilder_aarch64<ELFT>;
22996918515SStefan Gränitz     for (const auto &RelSect : Base::Sections)
2302a3b257aSKshitij Jain       if (Error Err = Base::forEachRelaRelocation(RelSect, this,
23196918515SStefan Gränitz                                                   &Self::addSingleRelocation))
23296918515SStefan Gränitz         return Err;
2332ed91da0SStefan Gränitz 
23496918515SStefan Gränitz     return Error::success();
2352ed91da0SStefan Gränitz   }
2362ed91da0SStefan Gränitz 
23796918515SStefan Gränitz   Error addSingleRelocation(const typename ELFT::Rela &Rel,
23896918515SStefan Gränitz                             const typename ELFT::Shdr &FixupSect,
239091e3648SSteven Wu                             Block &BlockToFix) {
240ab472c96SSunho Kim     using support::ulittle32_t;
24196918515SStefan Gränitz     using Base = ELFLinkGraphBuilder<ELFT>;
2422ed91da0SStefan Gränitz 
24396918515SStefan Gränitz     uint32_t SymbolIndex = Rel.getSymbol(false);
24496918515SStefan Gränitz     auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);
24596918515SStefan Gränitz     if (!ObjSymbol)
24696918515SStefan Gränitz       return ObjSymbol.takeError();
2472ed91da0SStefan Gränitz 
24896918515SStefan Gränitz     Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex);
24996918515SStefan Gränitz     if (!GraphSymbol)
25096918515SStefan Gränitz       return make_error<StringError>(
25196918515SStefan Gränitz           formatv("Could not find symbol at given index, did you add it to "
25296918515SStefan Gränitz                   "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",
25396918515SStefan Gränitz                   SymbolIndex, (*ObjSymbol)->st_shndx,
25496918515SStefan Gränitz                   Base::GraphSymbols.size()),
25596918515SStefan Gränitz           inconvertibleErrorCode());
2562ed91da0SStefan Gränitz 
25796918515SStefan Gränitz     uint32_t Type = Rel.getType(false);
258b6553f59SSunho Kim     Expected<ELFAArch64RelocationKind> RelocKind = getRelocationKind(Type);
259b6553f59SSunho Kim     if (!RelocKind)
260b6553f59SSunho Kim       return RelocKind.takeError();
2612ed91da0SStefan Gränitz 
26296918515SStefan Gränitz     int64_t Addend = Rel.r_addend;
263118e953bSLang Hames     orc::ExecutorAddr FixupAddress =
264118e953bSLang Hames         orc::ExecutorAddr(FixupSect.sh_addr) + Rel.r_offset;
265091e3648SSteven Wu     Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();
266b6553f59SSunho Kim 
267ab472c96SSunho Kim     // Get a pointer to the fixup content.
268ab472c96SSunho Kim     const void *FixupContent = BlockToFix.getContent().data() +
269ab472c96SSunho Kim                                (FixupAddress - BlockToFix.getAddress());
270ab472c96SSunho Kim 
271b6553f59SSunho Kim     Edge::Kind Kind = Edge::Invalid;
272b6553f59SSunho Kim 
273b6553f59SSunho Kim     switch (*RelocKind) {
27425a9fb12SSunho Kim     case ELFCall26: {
275cb33ef7cSLang Hames       Kind = aarch64::Branch26PCRel;
276b6553f59SSunho Kim       break;
277b6553f59SSunho Kim     }
278d395b56aSPavel Samolysov     case ELFLdrLo19: {
279d395b56aSPavel Samolysov       uint32_t Instr = *(const ulittle32_t *)FixupContent;
280d395b56aSPavel Samolysov       if (!aarch64::isLDRLiteral(Instr))
281d395b56aSPavel Samolysov         return make_error<JITLinkError>(
282d395b56aSPavel Samolysov             "R_AARCH64_LDR_PREL_LO19 target is not an LDR Literal instruction");
283d395b56aSPavel Samolysov 
284d395b56aSPavel Samolysov       Kind = aarch64::LDRLiteral19;
285d395b56aSPavel Samolysov       break;
286d395b56aSPavel Samolysov     }
287e9676389SJob Noorman     case ELFAdrLo21: {
288e9676389SJob Noorman       uint32_t Instr = *(const ulittle32_t *)FixupContent;
289e9676389SJob Noorman       if (!aarch64::isADR(Instr))
290e9676389SJob Noorman         return make_error<JITLinkError>(
291e9676389SJob Noorman             "R_AARCH64_ADR_PREL_LO21 target is not an ADR instruction");
292e9676389SJob Noorman 
293e9676389SJob Noorman       Kind = aarch64::ADRLiteral21;
294e9676389SJob Noorman       break;
295e9676389SJob Noorman     }
29625a9fb12SSunho Kim     case ELFAdrPage21: {
29725a9fb12SSunho Kim       Kind = aarch64::Page21;
29825a9fb12SSunho Kim       break;
29925a9fb12SSunho Kim     }
30025a9fb12SSunho Kim     case ELFAddAbs12: {
30125a9fb12SSunho Kim       Kind = aarch64::PageOffset12;
30225a9fb12SSunho Kim       break;
30325a9fb12SSunho Kim     }
304ab472c96SSunho Kim     case ELFLdSt8Abs12: {
305ab472c96SSunho Kim       uint32_t Instr = *(const ulittle32_t *)FixupContent;
306ab472c96SSunho Kim       if (!aarch64::isLoadStoreImm12(Instr) ||
307ab472c96SSunho Kim           aarch64::getPageOffset12Shift(Instr) != 0)
308ab472c96SSunho Kim         return make_error<JITLinkError>(
309ab472c96SSunho Kim             "R_AARCH64_LDST8_ABS_LO12_NC target is not a "
310ab472c96SSunho Kim             "LDRB/STRB (imm12) instruction");
311ab472c96SSunho Kim 
312ab472c96SSunho Kim       Kind = aarch64::PageOffset12;
313ab472c96SSunho Kim       break;
314ab472c96SSunho Kim     }
315ab472c96SSunho Kim     case ELFLdSt16Abs12: {
316ab472c96SSunho Kim       uint32_t Instr = *(const ulittle32_t *)FixupContent;
317ab472c96SSunho Kim       if (!aarch64::isLoadStoreImm12(Instr) ||
318ab472c96SSunho Kim           aarch64::getPageOffset12Shift(Instr) != 1)
319ab472c96SSunho Kim         return make_error<JITLinkError>(
320ab472c96SSunho Kim             "R_AARCH64_LDST16_ABS_LO12_NC target is not a "
321ab472c96SSunho Kim             "LDRH/STRH (imm12) instruction");
322ab472c96SSunho Kim 
323ab472c96SSunho Kim       Kind = aarch64::PageOffset12;
324ab472c96SSunho Kim       break;
325ab472c96SSunho Kim     }
326ab472c96SSunho Kim     case ELFLdSt32Abs12: {
327ab472c96SSunho Kim       uint32_t Instr = *(const ulittle32_t *)FixupContent;
328ab472c96SSunho Kim       if (!aarch64::isLoadStoreImm12(Instr) ||
329ab472c96SSunho Kim           aarch64::getPageOffset12Shift(Instr) != 2)
330ab472c96SSunho Kim         return make_error<JITLinkError>(
331ab472c96SSunho Kim             "R_AARCH64_LDST32_ABS_LO12_NC target is not a "
332ab472c96SSunho Kim             "LDR/STR (imm12, 32 bit) instruction");
333ab472c96SSunho Kim 
334ab472c96SSunho Kim       Kind = aarch64::PageOffset12;
335ab472c96SSunho Kim       break;
336ab472c96SSunho Kim     }
337ab472c96SSunho Kim     case ELFLdSt64Abs12: {
338ab472c96SSunho Kim       uint32_t Instr = *(const ulittle32_t *)FixupContent;
339ab472c96SSunho Kim       if (!aarch64::isLoadStoreImm12(Instr) ||
340ab472c96SSunho Kim           aarch64::getPageOffset12Shift(Instr) != 3)
341ab472c96SSunho Kim         return make_error<JITLinkError>(
342ab472c96SSunho Kim             "R_AARCH64_LDST64_ABS_LO12_NC target is not a "
343ab472c96SSunho Kim             "LDR/STR (imm12, 64 bit) instruction");
344ab472c96SSunho Kim 
345ab472c96SSunho Kim       Kind = aarch64::PageOffset12;
346ab472c96SSunho Kim       break;
347ab472c96SSunho Kim     }
348ab472c96SSunho Kim     case ELFLdSt128Abs12: {
349ab472c96SSunho Kim       uint32_t Instr = *(const ulittle32_t *)FixupContent;
350ab472c96SSunho Kim       if (!aarch64::isLoadStoreImm12(Instr) ||
351ab472c96SSunho Kim           aarch64::getPageOffset12Shift(Instr) != 4)
352ab472c96SSunho Kim         return make_error<JITLinkError>(
353ab472c96SSunho Kim             "R_AARCH64_LDST128_ABS_LO12_NC target is not a "
354ab472c96SSunho Kim             "LDR/STR (imm12, 128 bit) instruction");
355ab472c96SSunho Kim 
356ab472c96SSunho Kim       Kind = aarch64::PageOffset12;
357ab472c96SSunho Kim       break;
358ab472c96SSunho Kim     }
3593d8061a3SSunho Kim     case ELFMovwAbsG0: {
3603d8061a3SSunho Kim       uint32_t Instr = *(const ulittle32_t *)FixupContent;
3613d8061a3SSunho Kim       if (!aarch64::isMoveWideImm16(Instr) ||
3623d8061a3SSunho Kim           aarch64::getMoveWide16Shift(Instr) != 0)
3633d8061a3SSunho Kim         return make_error<JITLinkError>(
3643d8061a3SSunho Kim             "R_AARCH64_MOVW_UABS_G0_NC target is not a "
3653d8061a3SSunho Kim             "MOVK/MOVZ (imm16, LSL #0) instruction");
3663d8061a3SSunho Kim 
3673d8061a3SSunho Kim       Kind = aarch64::MoveWide16;
3683d8061a3SSunho Kim       break;
3693d8061a3SSunho Kim     }
3703d8061a3SSunho Kim     case ELFMovwAbsG1: {
3713d8061a3SSunho Kim       uint32_t Instr = *(const ulittle32_t *)FixupContent;
3723d8061a3SSunho Kim       if (!aarch64::isMoveWideImm16(Instr) ||
3733d8061a3SSunho Kim           aarch64::getMoveWide16Shift(Instr) != 16)
3743d8061a3SSunho Kim         return make_error<JITLinkError>(
3753d8061a3SSunho Kim             "R_AARCH64_MOVW_UABS_G1_NC target is not a "
3763d8061a3SSunho Kim             "MOVK/MOVZ (imm16, LSL #16) instruction");
3773d8061a3SSunho Kim 
3783d8061a3SSunho Kim       Kind = aarch64::MoveWide16;
3793d8061a3SSunho Kim       break;
3803d8061a3SSunho Kim     }
3813d8061a3SSunho Kim     case ELFMovwAbsG2: {
3823d8061a3SSunho Kim       uint32_t Instr = *(const ulittle32_t *)FixupContent;
3833d8061a3SSunho Kim       if (!aarch64::isMoveWideImm16(Instr) ||
3843d8061a3SSunho Kim           aarch64::getMoveWide16Shift(Instr) != 32)
3853d8061a3SSunho Kim         return make_error<JITLinkError>(
3863d8061a3SSunho Kim             "R_AARCH64_MOVW_UABS_G2_NC target is not a "
3873d8061a3SSunho Kim             "MOVK/MOVZ (imm16, LSL #32) instruction");
3883d8061a3SSunho Kim 
3893d8061a3SSunho Kim       Kind = aarch64::MoveWide16;
3903d8061a3SSunho Kim       break;
3913d8061a3SSunho Kim     }
3923d8061a3SSunho Kim     case ELFMovwAbsG3: {
3933d8061a3SSunho Kim       uint32_t Instr = *(const ulittle32_t *)FixupContent;
3943d8061a3SSunho Kim       if (!aarch64::isMoveWideImm16(Instr) ||
3953d8061a3SSunho Kim           aarch64::getMoveWide16Shift(Instr) != 48)
3963d8061a3SSunho Kim         return make_error<JITLinkError>(
3973d8061a3SSunho Kim             "R_AARCH64_MOVW_UABS_G3 target is not a "
3983d8061a3SSunho Kim             "MOVK/MOVZ (imm16, LSL #48) instruction");
3993d8061a3SSunho Kim 
4003d8061a3SSunho Kim       Kind = aarch64::MoveWide16;
4013d8061a3SSunho Kim       break;
4023d8061a3SSunho Kim     }
403a9a2eb81SJob Noorman     case ELFTstBr14: {
404a9a2eb81SJob Noorman       uint32_t Instr = *(const ulittle32_t *)FixupContent;
405a9a2eb81SJob Noorman       if (!aarch64::isTestAndBranchImm14(Instr))
406a9a2eb81SJob Noorman         return make_error<JITLinkError>("R_AARCH64_TSTBR14 target is not a "
407a9a2eb81SJob Noorman                                         "test and branch instruction");
408a9a2eb81SJob Noorman 
409a9a2eb81SJob Noorman       Kind = aarch64::TestAndBranch14PCRel;
410a9a2eb81SJob Noorman       break;
411a9a2eb81SJob Noorman     }
412193a8092SJob Noorman     case ELFCondBr19: {
413193a8092SJob Noorman       uint32_t Instr = *(const ulittle32_t *)FixupContent;
414193a8092SJob Noorman       if (!aarch64::isCondBranchImm19(Instr) &&
415193a8092SJob Noorman           !aarch64::isCompAndBranchImm19(Instr))
416193a8092SJob Noorman         return make_error<JITLinkError>("R_AARCH64_CONDBR19 target is not a "
417193a8092SJob Noorman                                         "conditional branch instruction");
418193a8092SJob Noorman 
419193a8092SJob Noorman       Kind = aarch64::CondBranch19PCRel;
420193a8092SJob Noorman       break;
421193a8092SJob Noorman     }
422fb1b9945SLang Hames     case ELFAbs32: {
423fb1b9945SLang Hames       Kind = aarch64::Pointer32;
424fb1b9945SLang Hames       break;
425fb1b9945SLang Hames     }
4261deaa9b8SLang Hames     case ELFAbs64: {
4271deaa9b8SLang Hames       Kind = aarch64::Pointer64;
4281deaa9b8SLang Hames       break;
4291deaa9b8SLang Hames     }
4305d5183b1SSunho Kim     case ELFPrel32: {
4315d5183b1SSunho Kim       Kind = aarch64::Delta32;
4325d5183b1SSunho Kim       break;
4335d5183b1SSunho Kim     }
4345d5183b1SSunho Kim     case ELFPrel64: {
4355d5183b1SSunho Kim       Kind = aarch64::Delta64;
4365d5183b1SSunho Kim       break;
4375d5183b1SSunho Kim     }
4382094fad0SSunho Kim     case ELFAdrGOTPage21: {
439cb33ef7cSLang Hames       Kind = aarch64::RequestGOTAndTransformToPage21;
4402094fad0SSunho Kim       break;
4412094fad0SSunho Kim     }
4422094fad0SSunho Kim     case ELFLd64GOTLo12: {
443cb33ef7cSLang Hames       Kind = aarch64::RequestGOTAndTransformToPageOffset12;
4442094fad0SSunho Kim       break;
4452094fad0SSunho Kim     }
446199c4003SVladislav Khmelevsky     case ELFLd64GOTPAGELo15: {
447199c4003SVladislav Khmelevsky       Kind = aarch64::RequestGOTAndTransformToPageOffset15;
448199c4003SVladislav Khmelevsky       break;
449199c4003SVladislav Khmelevsky     }
45030b6c51fSSunho Kim     case ELFTLSDescAdrPage21: {
451cb33ef7cSLang Hames       Kind = aarch64::RequestTLSDescEntryAndTransformToPage21;
45230b6c51fSSunho Kim       break;
45330b6c51fSSunho Kim     }
454cb33ef7cSLang Hames     case ELFTLSDescAddLo12:
45530b6c51fSSunho Kim     case ELFTLSDescLd64Lo12: {
456cb33ef7cSLang Hames       Kind = aarch64::RequestTLSDescEntryAndTransformToPageOffset12;
45730b6c51fSSunho Kim       break;
45830b6c51fSSunho Kim     }
45930b6c51fSSunho Kim     case ELFTLSDescCall: {
46030b6c51fSSunho Kim       return Error::success();
46130b6c51fSSunho Kim     }
462b6553f59SSunho Kim     };
463b6553f59SSunho Kim 
464b6553f59SSunho Kim     Edge GE(Kind, Offset, *GraphSymbol, Addend);
46596918515SStefan Gränitz     LLVM_DEBUG({
46696918515SStefan Gränitz       dbgs() << "    ";
467b6553f59SSunho Kim       printEdge(dbgs(), BlockToFix, GE, aarch64::getEdgeKindName(Kind));
46896918515SStefan Gränitz       dbgs() << "\n";
46996918515SStefan Gränitz     });
47096918515SStefan Gränitz 
471091e3648SSteven Wu     BlockToFix.addEdge(std::move(GE));
47230b6c51fSSunho Kim 
4732ed91da0SStefan Gränitz     return Error::success();
4742ed91da0SStefan Gränitz   }
4752ed91da0SStefan Gränitz 
476b6553f59SSunho Kim   /// Return the string name of the given ELF aarch64 edge kind.
477b6553f59SSunho Kim   const char *getELFAArch64RelocationKindName(Edge::Kind R) {
478b6553f59SSunho Kim     switch (R) {
47925a9fb12SSunho Kim     case ELFCall26:
48025a9fb12SSunho Kim       return "ELFCall26";
48125a9fb12SSunho Kim     case ELFAdrPage21:
48225a9fb12SSunho Kim       return "ELFAdrPage21";
48325a9fb12SSunho Kim     case ELFAddAbs12:
48425a9fb12SSunho Kim       return "ELFAddAbs12";
485ab472c96SSunho Kim     case ELFLdSt8Abs12:
486ab472c96SSunho Kim       return "ELFLdSt8Abs12";
487ab472c96SSunho Kim     case ELFLdSt16Abs12:
488ab472c96SSunho Kim       return "ELFLdSt16Abs12";
489ab472c96SSunho Kim     case ELFLdSt32Abs12:
490ab472c96SSunho Kim       return "ELFLdSt32Abs12";
491ab472c96SSunho Kim     case ELFLdSt64Abs12:
492ab472c96SSunho Kim       return "ELFLdSt64Abs12";
493ab472c96SSunho Kim     case ELFLdSt128Abs12:
494ab472c96SSunho Kim       return "ELFLdSt128Abs12";
4953d8061a3SSunho Kim     case ELFMovwAbsG0:
4963d8061a3SSunho Kim       return "ELFMovwAbsG0";
4973d8061a3SSunho Kim     case ELFMovwAbsG1:
4983d8061a3SSunho Kim       return "ELFMovwAbsG1";
4993d8061a3SSunho Kim     case ELFMovwAbsG2:
5003d8061a3SSunho Kim       return "ELFMovwAbsG2";
5013d8061a3SSunho Kim     case ELFMovwAbsG3:
5023d8061a3SSunho Kim       return "ELFMovwAbsG3";
503fb1b9945SLang Hames     case ELFAbs32:
504fb1b9945SLang Hames       return "ELFAbs32";
5051deaa9b8SLang Hames     case ELFAbs64:
5061deaa9b8SLang Hames       return "ELFAbs64";
5075d5183b1SSunho Kim     case ELFPrel32:
5085d5183b1SSunho Kim       return "ELFPrel32";
5095d5183b1SSunho Kim     case ELFPrel64:
5105d5183b1SSunho Kim       return "ELFPrel64";
5112094fad0SSunho Kim     case ELFAdrGOTPage21:
5122094fad0SSunho Kim       return "ELFAdrGOTPage21";
5132094fad0SSunho Kim     case ELFLd64GOTLo12:
5142094fad0SSunho Kim       return "ELFLd64GOTLo12";
515199c4003SVladislav Khmelevsky     case ELFLd64GOTPAGELo15:
516199c4003SVladislav Khmelevsky       return "ELFLd64GOTPAGELo15";
51730b6c51fSSunho Kim     case ELFTLSDescAdrPage21:
51830b6c51fSSunho Kim       return "ELFTLSDescAdrPage21";
51930b6c51fSSunho Kim     case ELFTLSDescAddLo12:
52030b6c51fSSunho Kim       return "ELFTLSDescAddLo12";
52130b6c51fSSunho Kim     case ELFTLSDescLd64Lo12:
52230b6c51fSSunho Kim       return "ELFTLSDescLd64Lo12";
52330b6c51fSSunho Kim     case ELFTLSDescCall:
52430b6c51fSSunho Kim       return "ELFTLSDescCall";
525b6553f59SSunho Kim     default:
526b6553f59SSunho Kim       return getGenericEdgeKindName(static_cast<Edge::Kind>(R));
527b6553f59SSunho Kim     }
528b6553f59SSunho Kim   }
529b6553f59SSunho Kim 
5302ed91da0SStefan Gränitz public:
5312ed91da0SStefan Gränitz   ELFLinkGraphBuilder_aarch64(StringRef FileName,
5322ccf7ed2SJared Wyles                               const object::ELFFile<ELFT> &Obj,
5332ccf7ed2SJared Wyles                               std::shared_ptr<orc::SymbolStringPool> SSP,
5342ccf7ed2SJared Wyles                               Triple TT, SubtargetFeatures Features)
5352ccf7ed2SJared Wyles 
5362ccf7ed2SJared Wyles       : ELFLinkGraphBuilder<ELFT>(Obj, std::move(SSP), std::move(TT),
5372ccf7ed2SJared Wyles                                   std::move(Features), FileName,
5382ccf7ed2SJared Wyles                                   aarch64::getEdgeKindName) {}
5392ed91da0SStefan Gränitz };
5402ed91da0SStefan Gränitz 
54130b6c51fSSunho Kim // TLS Info Builder.
54230b6c51fSSunho Kim class TLSInfoTableManager_ELF_aarch64
54330b6c51fSSunho Kim     : public TableManager<TLSInfoTableManager_ELF_aarch64> {
54430b6c51fSSunho Kim public:
54530b6c51fSSunho Kim   static StringRef getSectionName() { return "$__TLSINFO"; }
54630b6c51fSSunho Kim 
54730b6c51fSSunho Kim   static const uint8_t TLSInfoEntryContent[16];
54830b6c51fSSunho Kim 
54930b6c51fSSunho Kim   bool visitEdge(LinkGraph &G, Block *B, Edge &E) { return false; }
55030b6c51fSSunho Kim 
55130b6c51fSSunho Kim   Symbol &createEntry(LinkGraph &G, Symbol &Target) {
55230b6c51fSSunho Kim     // the TLS Info entry's key value will be written by the fixTLVSectionByName
55330b6c51fSSunho Kim     // pass, so create mutable content.
55430b6c51fSSunho Kim     auto &TLSInfoEntry = G.createMutableContentBlock(
55530b6c51fSSunho Kim         getTLSInfoSection(G), G.allocateContent(getTLSInfoEntryContent()),
55630b6c51fSSunho Kim         orc::ExecutorAddr(), 8, 0);
55730b6c51fSSunho Kim     TLSInfoEntry.addEdge(aarch64::Pointer64, 8, Target, 0);
55830b6c51fSSunho Kim     return G.addAnonymousSymbol(TLSInfoEntry, 0, 16, false, false);
55930b6c51fSSunho Kim   }
56030b6c51fSSunho Kim 
56130b6c51fSSunho Kim private:
56230b6c51fSSunho Kim   Section &getTLSInfoSection(LinkGraph &G) {
56330b6c51fSSunho Kim     if (!TLSInfoTable)
564d3d9f7caSLang Hames       TLSInfoTable = &G.createSection(getSectionName(), orc::MemProt::Read);
56530b6c51fSSunho Kim     return *TLSInfoTable;
56630b6c51fSSunho Kim   }
56730b6c51fSSunho Kim 
56830b6c51fSSunho Kim   ArrayRef<char> getTLSInfoEntryContent() const {
56930b6c51fSSunho Kim     return {reinterpret_cast<const char *>(TLSInfoEntryContent),
57030b6c51fSSunho Kim             sizeof(TLSInfoEntryContent)};
57130b6c51fSSunho Kim   }
57230b6c51fSSunho Kim 
57330b6c51fSSunho Kim   Section *TLSInfoTable = nullptr;
57430b6c51fSSunho Kim };
57530b6c51fSSunho Kim 
57630b6c51fSSunho Kim const uint8_t TLSInfoTableManager_ELF_aarch64::TLSInfoEntryContent[16] = {
57730b6c51fSSunho Kim     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*pthread key */
57830b6c51fSSunho Kim     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  /*data address*/
57930b6c51fSSunho Kim };
58030b6c51fSSunho Kim 
58130b6c51fSSunho Kim // TLS Descriptor Builder.
58230b6c51fSSunho Kim class TLSDescTableManager_ELF_aarch64
58330b6c51fSSunho Kim     : public TableManager<TLSDescTableManager_ELF_aarch64> {
58430b6c51fSSunho Kim public:
58530b6c51fSSunho Kim   TLSDescTableManager_ELF_aarch64(
58630b6c51fSSunho Kim       TLSInfoTableManager_ELF_aarch64 &TLSInfoTableManager)
58730b6c51fSSunho Kim       : TLSInfoTableManager(TLSInfoTableManager) {}
58830b6c51fSSunho Kim 
58930b6c51fSSunho Kim   static StringRef getSectionName() { return "$__TLSDESC"; }
59030b6c51fSSunho Kim 
59130b6c51fSSunho Kim   static const uint8_t TLSDescEntryContent[16];
59230b6c51fSSunho Kim 
59330b6c51fSSunho Kim   bool visitEdge(LinkGraph &G, Block *B, Edge &E) {
59430b6c51fSSunho Kim     Edge::Kind KindToSet = Edge::Invalid;
59530b6c51fSSunho Kim     switch (E.getKind()) {
596cb33ef7cSLang Hames     case aarch64::RequestTLSDescEntryAndTransformToPage21: {
59730b6c51fSSunho Kim       KindToSet = aarch64::Page21;
59830b6c51fSSunho Kim       break;
59930b6c51fSSunho Kim     }
600cb33ef7cSLang Hames     case aarch64::RequestTLSDescEntryAndTransformToPageOffset12: {
60130b6c51fSSunho Kim       KindToSet = aarch64::PageOffset12;
60230b6c51fSSunho Kim       break;
60330b6c51fSSunho Kim     }
60430b6c51fSSunho Kim     default:
60530b6c51fSSunho Kim       return false;
60630b6c51fSSunho Kim     }
60730b6c51fSSunho Kim     assert(KindToSet != Edge::Invalid &&
60830b6c51fSSunho Kim            "Fell through switch, but no new kind to set");
60930b6c51fSSunho Kim     DEBUG_WITH_TYPE("jitlink", {
61030b6c51fSSunho Kim       dbgs() << "  Fixing " << G.getEdgeKindName(E.getKind()) << " edge at "
61130b6c51fSSunho Kim              << B->getFixupAddress(E) << " (" << B->getAddress() << " + "
61230b6c51fSSunho Kim              << formatv("{0:x}", E.getOffset()) << ")\n";
61330b6c51fSSunho Kim     });
61430b6c51fSSunho Kim     E.setKind(KindToSet);
61530b6c51fSSunho Kim     E.setTarget(getEntryForTarget(G, E.getTarget()));
61630b6c51fSSunho Kim     return true;
61730b6c51fSSunho Kim   }
61830b6c51fSSunho Kim 
61930b6c51fSSunho Kim   Symbol &createEntry(LinkGraph &G, Symbol &Target) {
62030b6c51fSSunho Kim     auto &EntryBlock =
62130b6c51fSSunho Kim         G.createContentBlock(getTLSDescSection(G), getTLSDescBlockContent(),
62230b6c51fSSunho Kim                              orc::ExecutorAddr(), 8, 0);
62330b6c51fSSunho Kim     EntryBlock.addEdge(aarch64::Pointer64, 0, getTLSDescResolver(G), 0);
62430b6c51fSSunho Kim     EntryBlock.addEdge(aarch64::Pointer64, 8,
62530b6c51fSSunho Kim                        TLSInfoTableManager.getEntryForTarget(G, Target), 0);
62630b6c51fSSunho Kim     return G.addAnonymousSymbol(EntryBlock, 0, 8, false, false);
62730b6c51fSSunho Kim   }
62830b6c51fSSunho Kim 
62930b6c51fSSunho Kim private:
63030b6c51fSSunho Kim   Section &getTLSDescSection(LinkGraph &G) {
63130b6c51fSSunho Kim     if (!GOTSection)
632d3d9f7caSLang Hames       GOTSection = &G.createSection(getSectionName(), orc::MemProt::Read);
63330b6c51fSSunho Kim     return *GOTSection;
63430b6c51fSSunho Kim   }
63530b6c51fSSunho Kim 
63630b6c51fSSunho Kim   Symbol &getTLSDescResolver(LinkGraph &G) {
63730b6c51fSSunho Kim     if (!TLSDescResolver)
63875404e9eSLang Hames       TLSDescResolver = &G.addExternalSymbol("__tlsdesc_resolver", 8, false);
63930b6c51fSSunho Kim     return *TLSDescResolver;
64030b6c51fSSunho Kim   }
64130b6c51fSSunho Kim 
64230b6c51fSSunho Kim   ArrayRef<char> getTLSDescBlockContent() {
64330b6c51fSSunho Kim     return {reinterpret_cast<const char *>(TLSDescEntryContent),
64430b6c51fSSunho Kim             sizeof(TLSDescEntryContent)};
64530b6c51fSSunho Kim   }
64630b6c51fSSunho Kim 
64730b6c51fSSunho Kim   Section *GOTSection = nullptr;
64830b6c51fSSunho Kim   Symbol *TLSDescResolver = nullptr;
64930b6c51fSSunho Kim   TLSInfoTableManager_ELF_aarch64 &TLSInfoTableManager;
65030b6c51fSSunho Kim };
65130b6c51fSSunho Kim 
65230b6c51fSSunho Kim const uint8_t TLSDescTableManager_ELF_aarch64::TLSDescEntryContent[16] = {
65330b6c51fSSunho Kim     0x00, 0x00, 0x00, 0x00,
65430b6c51fSSunho Kim     0x00, 0x00, 0x00, 0x00, /*resolver function pointer*/
65530b6c51fSSunho Kim     0x00, 0x00, 0x00, 0x00,
65630b6c51fSSunho Kim     0x00, 0x00, 0x00, 0x00 /*pointer to tls info*/
65730b6c51fSSunho Kim };
65830b6c51fSSunho Kim 
659db372258SSunho Kim Error buildTables_ELF_aarch64(LinkGraph &G) {
660db372258SSunho Kim   LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");
6612094fad0SSunho Kim 
662*42595bdaSLang Hames   aarch64::GOTTableManager GOT(G);
663*42595bdaSLang Hames   aarch64::PLTTableManager PLT(G, GOT);
66430b6c51fSSunho Kim   TLSInfoTableManager_ELF_aarch64 TLSInfo;
66530b6c51fSSunho Kim   TLSDescTableManager_ELF_aarch64 TLSDesc(TLSInfo);
66630b6c51fSSunho Kim   visitExistingEdges(G, GOT, PLT, TLSDesc, TLSInfo);
667db372258SSunho Kim   return Error::success();
6682094fad0SSunho Kim }
6692094fad0SSunho Kim 
670db372258SSunho Kim } // namespace
6712094fad0SSunho Kim 
672db372258SSunho Kim namespace llvm {
673db372258SSunho Kim namespace jitlink {
6742094fad0SSunho Kim 
6752ccf7ed2SJared Wyles Expected<std::unique_ptr<LinkGraph>> createLinkGraphFromELFObject_aarch64(
6762ccf7ed2SJared Wyles     MemoryBufferRef ObjectBuffer, std::shared_ptr<orc::SymbolStringPool> SSP) {
6772ed91da0SStefan Gränitz   LLVM_DEBUG({
6782ed91da0SStefan Gränitz     dbgs() << "Building jitlink graph for new input "
6792ed91da0SStefan Gränitz            << ObjectBuffer.getBufferIdentifier() << "...\n";
6802ed91da0SStefan Gränitz   });
6812ed91da0SStefan Gränitz 
6822ed91da0SStefan Gränitz   auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer);
6832ed91da0SStefan Gränitz   if (!ELFObj)
6842ed91da0SStefan Gränitz     return ELFObj.takeError();
6852ed91da0SStefan Gränitz 
686348d0a6bSJob Noorman   auto Features = (*ELFObj)->getFeatures();
687348d0a6bSJob Noorman   if (!Features)
688348d0a6bSJob Noorman     return Features.takeError();
689348d0a6bSJob Noorman 
6902ed91da0SStefan Gränitz   assert((*ELFObj)->getArch() == Triple::aarch64 &&
6912ed91da0SStefan Gränitz          "Only AArch64 (little endian) is supported for now");
6922ed91da0SStefan Gränitz 
6932ed91da0SStefan Gränitz   auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
694348d0a6bSJob Noorman   return ELFLinkGraphBuilder_aarch64<object::ELF64LE>(
6952ccf7ed2SJared Wyles              (*ELFObj)->getFileName(), ELFObjFile.getELFFile(), std::move(SSP),
69652b88457SJob Noorman              (*ELFObj)->makeTriple(), std::move(*Features))
6972ed91da0SStefan Gränitz       .buildGraph();
6982ed91da0SStefan Gränitz }
6992ed91da0SStefan Gränitz 
7002ed91da0SStefan Gränitz void link_ELF_aarch64(std::unique_ptr<LinkGraph> G,
7012ed91da0SStefan Gränitz                       std::unique_ptr<JITLinkContext> Ctx) {
7022ed91da0SStefan Gränitz   PassConfiguration Config;
7032ed91da0SStefan Gränitz   const Triple &TT = G->getTargetTriple();
7042ed91da0SStefan Gränitz   if (Ctx->shouldAddDefaultTargetPasses(TT)) {
70594239712SEymen Ünay     // Add eh-frame passes.
706f8a9536cSSunho Kim     Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame"));
707f8a9536cSSunho Kim     Config.PrePrunePasses.push_back(EHFrameEdgeFixer(
708f8a9536cSSunho Kim         ".eh_frame", 8, aarch64::Pointer32, aarch64::Pointer64,
709f8a9536cSSunho Kim         aarch64::Delta32, aarch64::Delta64, aarch64::NegDelta32));
71068c14f58STom Stellard     Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame"));
711db372258SSunho Kim 
712db372258SSunho Kim     // Add a mark-live pass.
7132ed91da0SStefan Gränitz     if (auto MarkLive = Ctx->getMarkLivePass(TT))
7142ed91da0SStefan Gränitz       Config.PrePrunePasses.push_back(std::move(MarkLive));
7152ed91da0SStefan Gränitz     else
7162ed91da0SStefan Gränitz       Config.PrePrunePasses.push_back(markAllSymbolsLive);
7172094fad0SSunho Kim 
718488a1873SLang Hames     // Resolve any external section start / end symbols.
719488a1873SLang Hames     Config.PostAllocationPasses.push_back(
720488a1873SLang Hames         createDefineExternalSectionStartAndEndSymbolsPass(
721488a1873SLang Hames             identifyELFSectionStartAndEndSymbols));
722488a1873SLang Hames 
72330b6c51fSSunho Kim     // Add an in-place GOT/TLS/Stubs build pass.
724db372258SSunho Kim     Config.PostPrunePasses.push_back(buildTables_ELF_aarch64);
725db372258SSunho Kim   }
7262094fad0SSunho Kim 
7272ed91da0SStefan Gränitz   if (auto Err = Ctx->modifyPassConfig(*G, Config))
7282ed91da0SStefan Gränitz     return Ctx->notifyFailed(std::move(Err));
7292ed91da0SStefan Gränitz 
7302ed91da0SStefan Gränitz   ELFJITLinker_aarch64::link(std::move(Ctx), std::move(G), std::move(Config));
7312ed91da0SStefan Gränitz }
7322ed91da0SStefan Gränitz 
7332ed91da0SStefan Gränitz } // namespace jitlink
7342ed91da0SStefan Gränitz } // namespace llvm
735