1349cc55cSDimitry Andric //===----- ELF_aarch64.cpp - JIT linker implementation for ELF/aarch64 ----===//
2349cc55cSDimitry Andric //
3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6349cc55cSDimitry Andric //
7349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
8349cc55cSDimitry Andric //
9349cc55cSDimitry Andric // ELF/aarch64 jit-link implementation.
10349cc55cSDimitry Andric //
11349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
12349cc55cSDimitry Andric 
13349cc55cSDimitry Andric #include "llvm/ExecutionEngine/JITLink/ELF_aarch64.h"
14*81ad6265SDimitry Andric #include "EHFrameSupportImpl.h"
15349cc55cSDimitry Andric #include "ELFLinkGraphBuilder.h"
16349cc55cSDimitry Andric #include "JITLinkGeneric.h"
17349cc55cSDimitry Andric #include "llvm/BinaryFormat/ELF.h"
18*81ad6265SDimitry Andric #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"
19349cc55cSDimitry Andric #include "llvm/ExecutionEngine/JITLink/aarch64.h"
20349cc55cSDimitry Andric #include "llvm/Object/ELFObjectFile.h"
21*81ad6265SDimitry Andric #include "llvm/Support/Endian.h"
22349cc55cSDimitry Andric 
23349cc55cSDimitry Andric #define DEBUG_TYPE "jitlink"
24349cc55cSDimitry Andric 
25349cc55cSDimitry Andric using namespace llvm;
26349cc55cSDimitry Andric using namespace llvm::jitlink;
27349cc55cSDimitry Andric 
28*81ad6265SDimitry Andric namespace {
29349cc55cSDimitry Andric 
30349cc55cSDimitry Andric class ELFJITLinker_aarch64 : public JITLinker<ELFJITLinker_aarch64> {
31349cc55cSDimitry Andric   friend class JITLinker<ELFJITLinker_aarch64>;
32349cc55cSDimitry Andric 
33349cc55cSDimitry Andric public:
34349cc55cSDimitry Andric   ELFJITLinker_aarch64(std::unique_ptr<JITLinkContext> Ctx,
35349cc55cSDimitry Andric                        std::unique_ptr<LinkGraph> G,
36349cc55cSDimitry Andric                        PassConfiguration PassConfig)
37349cc55cSDimitry Andric       : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
38349cc55cSDimitry Andric 
39349cc55cSDimitry Andric private:
40349cc55cSDimitry Andric   Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
41*81ad6265SDimitry Andric     return aarch64::applyFixup(G, B, E);
42349cc55cSDimitry Andric   }
43349cc55cSDimitry Andric };
44349cc55cSDimitry Andric 
45349cc55cSDimitry Andric template <typename ELFT>
46349cc55cSDimitry Andric class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
47349cc55cSDimitry Andric private:
48*81ad6265SDimitry Andric   enum ELFAArch64RelocationKind : Edge::Kind {
49*81ad6265SDimitry Andric     ELFCall26 = Edge::FirstRelocation,
50*81ad6265SDimitry Andric     ELFAdrPage21,
51*81ad6265SDimitry Andric     ELFAddAbs12,
52*81ad6265SDimitry Andric     ELFLdSt8Abs12,
53*81ad6265SDimitry Andric     ELFLdSt16Abs12,
54*81ad6265SDimitry Andric     ELFLdSt32Abs12,
55*81ad6265SDimitry Andric     ELFLdSt64Abs12,
56*81ad6265SDimitry Andric     ELFLdSt128Abs12,
57*81ad6265SDimitry Andric     ELFMovwAbsG0,
58*81ad6265SDimitry Andric     ELFMovwAbsG1,
59*81ad6265SDimitry Andric     ELFMovwAbsG2,
60*81ad6265SDimitry Andric     ELFMovwAbsG3,
61*81ad6265SDimitry Andric     ELFAbs64,
62*81ad6265SDimitry Andric     ELFPrel32,
63*81ad6265SDimitry Andric     ELFPrel64,
64*81ad6265SDimitry Andric     ELFAdrGOTPage21,
65*81ad6265SDimitry Andric     ELFLd64GOTLo12,
66*81ad6265SDimitry Andric   };
67*81ad6265SDimitry Andric 
68*81ad6265SDimitry Andric   static Expected<ELFAArch64RelocationKind>
69349cc55cSDimitry Andric   getRelocationKind(const uint32_t Type) {
70349cc55cSDimitry Andric     using namespace aarch64;
71349cc55cSDimitry Andric     switch (Type) {
72349cc55cSDimitry Andric     case ELF::R_AARCH64_CALL26:
73*81ad6265SDimitry Andric     case ELF::R_AARCH64_JUMP26:
74*81ad6265SDimitry Andric       return ELFCall26;
75*81ad6265SDimitry Andric     case ELF::R_AARCH64_ADR_PREL_PG_HI21:
76*81ad6265SDimitry Andric       return ELFAdrPage21;
77*81ad6265SDimitry Andric     case ELF::R_AARCH64_ADD_ABS_LO12_NC:
78*81ad6265SDimitry Andric       return ELFAddAbs12;
79*81ad6265SDimitry Andric     case ELF::R_AARCH64_LDST8_ABS_LO12_NC:
80*81ad6265SDimitry Andric       return ELFLdSt8Abs12;
81*81ad6265SDimitry Andric     case ELF::R_AARCH64_LDST16_ABS_LO12_NC:
82*81ad6265SDimitry Andric       return ELFLdSt16Abs12;
83*81ad6265SDimitry Andric     case ELF::R_AARCH64_LDST32_ABS_LO12_NC:
84*81ad6265SDimitry Andric       return ELFLdSt32Abs12;
85*81ad6265SDimitry Andric     case ELF::R_AARCH64_LDST64_ABS_LO12_NC:
86*81ad6265SDimitry Andric       return ELFLdSt64Abs12;
87*81ad6265SDimitry Andric     case ELF::R_AARCH64_LDST128_ABS_LO12_NC:
88*81ad6265SDimitry Andric       return ELFLdSt128Abs12;
89*81ad6265SDimitry Andric     case ELF::R_AARCH64_MOVW_UABS_G0_NC:
90*81ad6265SDimitry Andric       return ELFMovwAbsG0;
91*81ad6265SDimitry Andric     case ELF::R_AARCH64_MOVW_UABS_G1_NC:
92*81ad6265SDimitry Andric       return ELFMovwAbsG1;
93*81ad6265SDimitry Andric     case ELF::R_AARCH64_MOVW_UABS_G2_NC:
94*81ad6265SDimitry Andric       return ELFMovwAbsG2;
95*81ad6265SDimitry Andric     case ELF::R_AARCH64_MOVW_UABS_G3:
96*81ad6265SDimitry Andric       return ELFMovwAbsG3;
97*81ad6265SDimitry Andric     case ELF::R_AARCH64_ABS64:
98*81ad6265SDimitry Andric       return ELFAbs64;
99*81ad6265SDimitry Andric     case ELF::R_AARCH64_PREL32:
100*81ad6265SDimitry Andric       return ELFPrel32;
101*81ad6265SDimitry Andric     case ELF::R_AARCH64_PREL64:
102*81ad6265SDimitry Andric       return ELFPrel64;
103*81ad6265SDimitry Andric     case ELF::R_AARCH64_ADR_GOT_PAGE:
104*81ad6265SDimitry Andric       return ELFAdrGOTPage21;
105*81ad6265SDimitry Andric     case ELF::R_AARCH64_LD64_GOT_LO12_NC:
106*81ad6265SDimitry Andric       return ELFLd64GOTLo12;
107349cc55cSDimitry Andric     }
108349cc55cSDimitry Andric 
109*81ad6265SDimitry Andric     return make_error<JITLinkError>(
110*81ad6265SDimitry Andric         "Unsupported aarch64 relocation:" + formatv("{0:d}: ", Type) +
111*81ad6265SDimitry Andric         object::getELFRelocationTypeName(ELF::EM_AARCH64, Type));
112349cc55cSDimitry Andric   }
113349cc55cSDimitry Andric 
114349cc55cSDimitry Andric   Error addRelocations() override {
115349cc55cSDimitry Andric     LLVM_DEBUG(dbgs() << "Processing relocations:\n");
116349cc55cSDimitry Andric 
117349cc55cSDimitry Andric     using Base = ELFLinkGraphBuilder<ELFT>;
118349cc55cSDimitry Andric     using Self = ELFLinkGraphBuilder_aarch64<ELFT>;
119349cc55cSDimitry Andric     for (const auto &RelSect : Base::Sections)
120349cc55cSDimitry Andric       if (Error Err = Base::forEachRelocation(RelSect, this,
121349cc55cSDimitry Andric                                               &Self::addSingleRelocation))
122349cc55cSDimitry Andric         return Err;
123349cc55cSDimitry Andric 
124349cc55cSDimitry Andric     return Error::success();
125349cc55cSDimitry Andric   }
126349cc55cSDimitry Andric 
127349cc55cSDimitry Andric   Error addSingleRelocation(const typename ELFT::Rela &Rel,
128349cc55cSDimitry Andric                             const typename ELFT::Shdr &FixupSect,
12904eeddc0SDimitry Andric                             Block &BlockToFix) {
130*81ad6265SDimitry Andric     using support::ulittle32_t;
131349cc55cSDimitry Andric     using Base = ELFLinkGraphBuilder<ELFT>;
132349cc55cSDimitry Andric 
133349cc55cSDimitry Andric     uint32_t SymbolIndex = Rel.getSymbol(false);
134349cc55cSDimitry Andric     auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);
135349cc55cSDimitry Andric     if (!ObjSymbol)
136349cc55cSDimitry Andric       return ObjSymbol.takeError();
137349cc55cSDimitry Andric 
138349cc55cSDimitry Andric     Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex);
139349cc55cSDimitry Andric     if (!GraphSymbol)
140349cc55cSDimitry Andric       return make_error<StringError>(
141349cc55cSDimitry Andric           formatv("Could not find symbol at given index, did you add it to "
142349cc55cSDimitry Andric                   "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",
143349cc55cSDimitry Andric                   SymbolIndex, (*ObjSymbol)->st_shndx,
144349cc55cSDimitry Andric                   Base::GraphSymbols.size()),
145349cc55cSDimitry Andric           inconvertibleErrorCode());
146349cc55cSDimitry Andric 
147349cc55cSDimitry Andric     uint32_t Type = Rel.getType(false);
148*81ad6265SDimitry Andric     Expected<ELFAArch64RelocationKind> RelocKind = getRelocationKind(Type);
149*81ad6265SDimitry Andric     if (!RelocKind)
150*81ad6265SDimitry Andric       return RelocKind.takeError();
151349cc55cSDimitry Andric 
152349cc55cSDimitry Andric     int64_t Addend = Rel.r_addend;
15304eeddc0SDimitry Andric     orc::ExecutorAddr FixupAddress =
15404eeddc0SDimitry Andric         orc::ExecutorAddr(FixupSect.sh_addr) + Rel.r_offset;
15504eeddc0SDimitry Andric     Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();
156*81ad6265SDimitry Andric 
157*81ad6265SDimitry Andric     // Get a pointer to the fixup content.
158*81ad6265SDimitry Andric     const void *FixupContent = BlockToFix.getContent().data() +
159*81ad6265SDimitry Andric                                (FixupAddress - BlockToFix.getAddress());
160*81ad6265SDimitry Andric 
161*81ad6265SDimitry Andric     Edge::Kind Kind = Edge::Invalid;
162*81ad6265SDimitry Andric 
163*81ad6265SDimitry Andric     switch (*RelocKind) {
164*81ad6265SDimitry Andric     case ELFCall26: {
165*81ad6265SDimitry Andric       Kind = aarch64::Branch26;
166*81ad6265SDimitry Andric       break;
167*81ad6265SDimitry Andric     }
168*81ad6265SDimitry Andric     case ELFAdrPage21: {
169*81ad6265SDimitry Andric       Kind = aarch64::Page21;
170*81ad6265SDimitry Andric       break;
171*81ad6265SDimitry Andric     }
172*81ad6265SDimitry Andric     case ELFAddAbs12: {
173*81ad6265SDimitry Andric       Kind = aarch64::PageOffset12;
174*81ad6265SDimitry Andric       break;
175*81ad6265SDimitry Andric     }
176*81ad6265SDimitry Andric     case ELFLdSt8Abs12: {
177*81ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
178*81ad6265SDimitry Andric       if (!aarch64::isLoadStoreImm12(Instr) ||
179*81ad6265SDimitry Andric           aarch64::getPageOffset12Shift(Instr) != 0)
180*81ad6265SDimitry Andric         return make_error<JITLinkError>(
181*81ad6265SDimitry Andric             "R_AARCH64_LDST8_ABS_LO12_NC target is not a "
182*81ad6265SDimitry Andric             "LDRB/STRB (imm12) instruction");
183*81ad6265SDimitry Andric 
184*81ad6265SDimitry Andric       Kind = aarch64::PageOffset12;
185*81ad6265SDimitry Andric       break;
186*81ad6265SDimitry Andric     }
187*81ad6265SDimitry Andric     case ELFLdSt16Abs12: {
188*81ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
189*81ad6265SDimitry Andric       if (!aarch64::isLoadStoreImm12(Instr) ||
190*81ad6265SDimitry Andric           aarch64::getPageOffset12Shift(Instr) != 1)
191*81ad6265SDimitry Andric         return make_error<JITLinkError>(
192*81ad6265SDimitry Andric             "R_AARCH64_LDST16_ABS_LO12_NC target is not a "
193*81ad6265SDimitry Andric             "LDRH/STRH (imm12) instruction");
194*81ad6265SDimitry Andric 
195*81ad6265SDimitry Andric       Kind = aarch64::PageOffset12;
196*81ad6265SDimitry Andric       break;
197*81ad6265SDimitry Andric     }
198*81ad6265SDimitry Andric     case ELFLdSt32Abs12: {
199*81ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
200*81ad6265SDimitry Andric       if (!aarch64::isLoadStoreImm12(Instr) ||
201*81ad6265SDimitry Andric           aarch64::getPageOffset12Shift(Instr) != 2)
202*81ad6265SDimitry Andric         return make_error<JITLinkError>(
203*81ad6265SDimitry Andric             "R_AARCH64_LDST32_ABS_LO12_NC target is not a "
204*81ad6265SDimitry Andric             "LDR/STR (imm12, 32 bit) instruction");
205*81ad6265SDimitry Andric 
206*81ad6265SDimitry Andric       Kind = aarch64::PageOffset12;
207*81ad6265SDimitry Andric       break;
208*81ad6265SDimitry Andric     }
209*81ad6265SDimitry Andric     case ELFLdSt64Abs12: {
210*81ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
211*81ad6265SDimitry Andric       if (!aarch64::isLoadStoreImm12(Instr) ||
212*81ad6265SDimitry Andric           aarch64::getPageOffset12Shift(Instr) != 3)
213*81ad6265SDimitry Andric         return make_error<JITLinkError>(
214*81ad6265SDimitry Andric             "R_AARCH64_LDST64_ABS_LO12_NC target is not a "
215*81ad6265SDimitry Andric             "LDR/STR (imm12, 64 bit) instruction");
216*81ad6265SDimitry Andric 
217*81ad6265SDimitry Andric       Kind = aarch64::PageOffset12;
218*81ad6265SDimitry Andric       break;
219*81ad6265SDimitry Andric     }
220*81ad6265SDimitry Andric     case ELFLdSt128Abs12: {
221*81ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
222*81ad6265SDimitry Andric       if (!aarch64::isLoadStoreImm12(Instr) ||
223*81ad6265SDimitry Andric           aarch64::getPageOffset12Shift(Instr) != 4)
224*81ad6265SDimitry Andric         return make_error<JITLinkError>(
225*81ad6265SDimitry Andric             "R_AARCH64_LDST128_ABS_LO12_NC target is not a "
226*81ad6265SDimitry Andric             "LDR/STR (imm12, 128 bit) instruction");
227*81ad6265SDimitry Andric 
228*81ad6265SDimitry Andric       Kind = aarch64::PageOffset12;
229*81ad6265SDimitry Andric       break;
230*81ad6265SDimitry Andric     }
231*81ad6265SDimitry Andric     case ELFMovwAbsG0: {
232*81ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
233*81ad6265SDimitry Andric       if (!aarch64::isMoveWideImm16(Instr) ||
234*81ad6265SDimitry Andric           aarch64::getMoveWide16Shift(Instr) != 0)
235*81ad6265SDimitry Andric         return make_error<JITLinkError>(
236*81ad6265SDimitry Andric             "R_AARCH64_MOVW_UABS_G0_NC target is not a "
237*81ad6265SDimitry Andric             "MOVK/MOVZ (imm16, LSL #0) instruction");
238*81ad6265SDimitry Andric 
239*81ad6265SDimitry Andric       Kind = aarch64::MoveWide16;
240*81ad6265SDimitry Andric       break;
241*81ad6265SDimitry Andric     }
242*81ad6265SDimitry Andric     case ELFMovwAbsG1: {
243*81ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
244*81ad6265SDimitry Andric       if (!aarch64::isMoveWideImm16(Instr) ||
245*81ad6265SDimitry Andric           aarch64::getMoveWide16Shift(Instr) != 16)
246*81ad6265SDimitry Andric         return make_error<JITLinkError>(
247*81ad6265SDimitry Andric             "R_AARCH64_MOVW_UABS_G1_NC target is not a "
248*81ad6265SDimitry Andric             "MOVK/MOVZ (imm16, LSL #16) instruction");
249*81ad6265SDimitry Andric 
250*81ad6265SDimitry Andric       Kind = aarch64::MoveWide16;
251*81ad6265SDimitry Andric       break;
252*81ad6265SDimitry Andric     }
253*81ad6265SDimitry Andric     case ELFMovwAbsG2: {
254*81ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
255*81ad6265SDimitry Andric       if (!aarch64::isMoveWideImm16(Instr) ||
256*81ad6265SDimitry Andric           aarch64::getMoveWide16Shift(Instr) != 32)
257*81ad6265SDimitry Andric         return make_error<JITLinkError>(
258*81ad6265SDimitry Andric             "R_AARCH64_MOVW_UABS_G2_NC target is not a "
259*81ad6265SDimitry Andric             "MOVK/MOVZ (imm16, LSL #32) instruction");
260*81ad6265SDimitry Andric 
261*81ad6265SDimitry Andric       Kind = aarch64::MoveWide16;
262*81ad6265SDimitry Andric       break;
263*81ad6265SDimitry Andric     }
264*81ad6265SDimitry Andric     case ELFMovwAbsG3: {
265*81ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
266*81ad6265SDimitry Andric       if (!aarch64::isMoveWideImm16(Instr) ||
267*81ad6265SDimitry Andric           aarch64::getMoveWide16Shift(Instr) != 48)
268*81ad6265SDimitry Andric         return make_error<JITLinkError>(
269*81ad6265SDimitry Andric             "R_AARCH64_MOVW_UABS_G3 target is not a "
270*81ad6265SDimitry Andric             "MOVK/MOVZ (imm16, LSL #48) instruction");
271*81ad6265SDimitry Andric 
272*81ad6265SDimitry Andric       Kind = aarch64::MoveWide16;
273*81ad6265SDimitry Andric       break;
274*81ad6265SDimitry Andric     }
275*81ad6265SDimitry Andric     case ELFAbs64: {
276*81ad6265SDimitry Andric       Kind = aarch64::Pointer64;
277*81ad6265SDimitry Andric       break;
278*81ad6265SDimitry Andric     }
279*81ad6265SDimitry Andric     case ELFPrel32: {
280*81ad6265SDimitry Andric       Kind = aarch64::Delta32;
281*81ad6265SDimitry Andric       break;
282*81ad6265SDimitry Andric     }
283*81ad6265SDimitry Andric     case ELFPrel64: {
284*81ad6265SDimitry Andric       Kind = aarch64::Delta64;
285*81ad6265SDimitry Andric       break;
286*81ad6265SDimitry Andric     }
287*81ad6265SDimitry Andric     case ELFAdrGOTPage21: {
288*81ad6265SDimitry Andric       Kind = aarch64::GOTPage21;
289*81ad6265SDimitry Andric       break;
290*81ad6265SDimitry Andric     }
291*81ad6265SDimitry Andric     case ELFLd64GOTLo12: {
292*81ad6265SDimitry Andric       Kind = aarch64::GOTPageOffset12;
293*81ad6265SDimitry Andric       break;
294*81ad6265SDimitry Andric     }
295*81ad6265SDimitry Andric     };
296*81ad6265SDimitry Andric 
297*81ad6265SDimitry Andric     Edge GE(Kind, Offset, *GraphSymbol, Addend);
298349cc55cSDimitry Andric     LLVM_DEBUG({
299349cc55cSDimitry Andric       dbgs() << "    ";
300*81ad6265SDimitry Andric       printEdge(dbgs(), BlockToFix, GE, aarch64::getEdgeKindName(Kind));
301349cc55cSDimitry Andric       dbgs() << "\n";
302349cc55cSDimitry Andric     });
303349cc55cSDimitry Andric 
30404eeddc0SDimitry Andric     BlockToFix.addEdge(std::move(GE));
305349cc55cSDimitry Andric     return Error::success();
306349cc55cSDimitry Andric   }
307349cc55cSDimitry Andric 
308*81ad6265SDimitry Andric   /// Return the string name of the given ELF aarch64 edge kind.
309*81ad6265SDimitry Andric   const char *getELFAArch64RelocationKindName(Edge::Kind R) {
310*81ad6265SDimitry Andric     switch (R) {
311*81ad6265SDimitry Andric     case ELFCall26:
312*81ad6265SDimitry Andric       return "ELFCall26";
313*81ad6265SDimitry Andric     case ELFAdrPage21:
314*81ad6265SDimitry Andric       return "ELFAdrPage21";
315*81ad6265SDimitry Andric     case ELFAddAbs12:
316*81ad6265SDimitry Andric       return "ELFAddAbs12";
317*81ad6265SDimitry Andric     case ELFLdSt8Abs12:
318*81ad6265SDimitry Andric       return "ELFLdSt8Abs12";
319*81ad6265SDimitry Andric     case ELFLdSt16Abs12:
320*81ad6265SDimitry Andric       return "ELFLdSt16Abs12";
321*81ad6265SDimitry Andric     case ELFLdSt32Abs12:
322*81ad6265SDimitry Andric       return "ELFLdSt32Abs12";
323*81ad6265SDimitry Andric     case ELFLdSt64Abs12:
324*81ad6265SDimitry Andric       return "ELFLdSt64Abs12";
325*81ad6265SDimitry Andric     case ELFLdSt128Abs12:
326*81ad6265SDimitry Andric       return "ELFLdSt128Abs12";
327*81ad6265SDimitry Andric     case ELFMovwAbsG0:
328*81ad6265SDimitry Andric       return "ELFMovwAbsG0";
329*81ad6265SDimitry Andric     case ELFMovwAbsG1:
330*81ad6265SDimitry Andric       return "ELFMovwAbsG1";
331*81ad6265SDimitry Andric     case ELFMovwAbsG2:
332*81ad6265SDimitry Andric       return "ELFMovwAbsG2";
333*81ad6265SDimitry Andric     case ELFMovwAbsG3:
334*81ad6265SDimitry Andric       return "ELFMovwAbsG3";
335*81ad6265SDimitry Andric     case ELFAbs64:
336*81ad6265SDimitry Andric       return "ELFAbs64";
337*81ad6265SDimitry Andric     case ELFPrel32:
338*81ad6265SDimitry Andric       return "ELFPrel32";
339*81ad6265SDimitry Andric     case ELFPrel64:
340*81ad6265SDimitry Andric       return "ELFPrel64";
341*81ad6265SDimitry Andric     case ELFAdrGOTPage21:
342*81ad6265SDimitry Andric       return "ELFAdrGOTPage21";
343*81ad6265SDimitry Andric     case ELFLd64GOTLo12:
344*81ad6265SDimitry Andric       return "ELFLd64GOTLo12";
345*81ad6265SDimitry Andric     default:
346*81ad6265SDimitry Andric       return getGenericEdgeKindName(static_cast<Edge::Kind>(R));
347*81ad6265SDimitry Andric     }
348*81ad6265SDimitry Andric   }
349*81ad6265SDimitry Andric 
350349cc55cSDimitry Andric public:
351349cc55cSDimitry Andric   ELFLinkGraphBuilder_aarch64(StringRef FileName,
352349cc55cSDimitry Andric                               const object::ELFFile<ELFT> &Obj, const Triple T)
353349cc55cSDimitry Andric       : ELFLinkGraphBuilder<ELFT>(Obj, std::move(T), FileName,
354349cc55cSDimitry Andric                                   aarch64::getEdgeKindName) {}
355349cc55cSDimitry Andric };
356349cc55cSDimitry Andric 
357*81ad6265SDimitry Andric Error buildTables_ELF_aarch64(LinkGraph &G) {
358*81ad6265SDimitry Andric   LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");
359*81ad6265SDimitry Andric 
360*81ad6265SDimitry Andric   aarch64::GOTTableManager GOT;
361*81ad6265SDimitry Andric   aarch64::PLTTableManager PLT(GOT);
362*81ad6265SDimitry Andric   visitExistingEdges(G, GOT, PLT);
363*81ad6265SDimitry Andric   return Error::success();
364*81ad6265SDimitry Andric }
365*81ad6265SDimitry Andric 
366*81ad6265SDimitry Andric } // namespace
367*81ad6265SDimitry Andric 
368*81ad6265SDimitry Andric namespace llvm {
369*81ad6265SDimitry Andric namespace jitlink {
370*81ad6265SDimitry Andric 
371349cc55cSDimitry Andric Expected<std::unique_ptr<LinkGraph>>
372349cc55cSDimitry Andric createLinkGraphFromELFObject_aarch64(MemoryBufferRef ObjectBuffer) {
373349cc55cSDimitry Andric   LLVM_DEBUG({
374349cc55cSDimitry Andric     dbgs() << "Building jitlink graph for new input "
375349cc55cSDimitry Andric            << ObjectBuffer.getBufferIdentifier() << "...\n";
376349cc55cSDimitry Andric   });
377349cc55cSDimitry Andric 
378349cc55cSDimitry Andric   auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer);
379349cc55cSDimitry Andric   if (!ELFObj)
380349cc55cSDimitry Andric     return ELFObj.takeError();
381349cc55cSDimitry Andric 
382349cc55cSDimitry Andric   assert((*ELFObj)->getArch() == Triple::aarch64 &&
383349cc55cSDimitry Andric          "Only AArch64 (little endian) is supported for now");
384349cc55cSDimitry Andric 
385349cc55cSDimitry Andric   auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
386349cc55cSDimitry Andric   return ELFLinkGraphBuilder_aarch64<object::ELF64LE>((*ELFObj)->getFileName(),
387349cc55cSDimitry Andric                                                       ELFObjFile.getELFFile(),
388349cc55cSDimitry Andric                                                       (*ELFObj)->makeTriple())
389349cc55cSDimitry Andric       .buildGraph();
390349cc55cSDimitry Andric }
391349cc55cSDimitry Andric 
392349cc55cSDimitry Andric void link_ELF_aarch64(std::unique_ptr<LinkGraph> G,
393349cc55cSDimitry Andric                       std::unique_ptr<JITLinkContext> Ctx) {
394349cc55cSDimitry Andric   PassConfiguration Config;
395349cc55cSDimitry Andric   const Triple &TT = G->getTargetTriple();
396349cc55cSDimitry Andric   if (Ctx->shouldAddDefaultTargetPasses(TT)) {
397*81ad6265SDimitry Andric     // Add eh-frame passses.
398*81ad6265SDimitry Andric     Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame"));
399*81ad6265SDimitry Andric     Config.PrePrunePasses.push_back(EHFrameEdgeFixer(
400*81ad6265SDimitry Andric         ".eh_frame", 8, aarch64::Pointer32, aarch64::Pointer64,
401*81ad6265SDimitry Andric         aarch64::Delta32, aarch64::Delta64, aarch64::NegDelta32));
402*81ad6265SDimitry Andric 
403*81ad6265SDimitry Andric     // Add a mark-live pass.
404349cc55cSDimitry Andric     if (auto MarkLive = Ctx->getMarkLivePass(TT))
405349cc55cSDimitry Andric       Config.PrePrunePasses.push_back(std::move(MarkLive));
406349cc55cSDimitry Andric     else
407349cc55cSDimitry Andric       Config.PrePrunePasses.push_back(markAllSymbolsLive);
408*81ad6265SDimitry Andric 
409*81ad6265SDimitry Andric     // Add an in-place GOT/Stubs build pass.
410*81ad6265SDimitry Andric     Config.PostPrunePasses.push_back(buildTables_ELF_aarch64);
411349cc55cSDimitry Andric   }
412*81ad6265SDimitry Andric 
413349cc55cSDimitry Andric   if (auto Err = Ctx->modifyPassConfig(*G, Config))
414349cc55cSDimitry Andric     return Ctx->notifyFailed(std::move(Err));
415349cc55cSDimitry Andric 
416349cc55cSDimitry Andric   ELFJITLinker_aarch64::link(std::move(Ctx), std::move(G), std::move(Config));
417349cc55cSDimitry Andric }
418349cc55cSDimitry Andric 
419349cc55cSDimitry Andric } // namespace jitlink
420349cc55cSDimitry Andric } // namespace llvm
421