xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp (revision 1ac55f4cb0001fed92329746c730aa9a947c09a5)
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"
1481ad6265SDimitry Andric #include "EHFrameSupportImpl.h"
15349cc55cSDimitry Andric #include "ELFLinkGraphBuilder.h"
16349cc55cSDimitry Andric #include "JITLinkGeneric.h"
17349cc55cSDimitry Andric #include "llvm/BinaryFormat/ELF.h"
1881ad6265SDimitry Andric #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"
19349cc55cSDimitry Andric #include "llvm/ExecutionEngine/JITLink/aarch64.h"
20349cc55cSDimitry Andric #include "llvm/Object/ELFObjectFile.h"
2181ad6265SDimitry 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 
2881ad6265SDimitry 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 {
4181ad6265SDimitry 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:
4881ad6265SDimitry Andric   enum ELFAArch64RelocationKind : Edge::Kind {
4981ad6265SDimitry Andric     ELFCall26 = Edge::FirstRelocation,
5081ad6265SDimitry Andric     ELFAdrPage21,
5181ad6265SDimitry Andric     ELFAddAbs12,
5281ad6265SDimitry Andric     ELFLdSt8Abs12,
5381ad6265SDimitry Andric     ELFLdSt16Abs12,
5481ad6265SDimitry Andric     ELFLdSt32Abs12,
5581ad6265SDimitry Andric     ELFLdSt64Abs12,
5681ad6265SDimitry Andric     ELFLdSt128Abs12,
5781ad6265SDimitry Andric     ELFMovwAbsG0,
5881ad6265SDimitry Andric     ELFMovwAbsG1,
5981ad6265SDimitry Andric     ELFMovwAbsG2,
6081ad6265SDimitry Andric     ELFMovwAbsG3,
6181ad6265SDimitry Andric     ELFAbs64,
6281ad6265SDimitry Andric     ELFPrel32,
6381ad6265SDimitry Andric     ELFPrel64,
6481ad6265SDimitry Andric     ELFAdrGOTPage21,
6581ad6265SDimitry Andric     ELFLd64GOTLo12,
66753f127fSDimitry Andric     ELFTLSDescAdrPage21,
67753f127fSDimitry Andric     ELFTLSDescAddLo12,
68753f127fSDimitry Andric     ELFTLSDescLd64Lo12,
69753f127fSDimitry Andric     ELFTLSDescCall,
7081ad6265SDimitry Andric   };
7181ad6265SDimitry Andric 
7281ad6265SDimitry Andric   static Expected<ELFAArch64RelocationKind>
73349cc55cSDimitry Andric   getRelocationKind(const uint32_t Type) {
74349cc55cSDimitry Andric     using namespace aarch64;
75349cc55cSDimitry Andric     switch (Type) {
76349cc55cSDimitry Andric     case ELF::R_AARCH64_CALL26:
7781ad6265SDimitry Andric     case ELF::R_AARCH64_JUMP26:
7881ad6265SDimitry Andric       return ELFCall26;
7981ad6265SDimitry Andric     case ELF::R_AARCH64_ADR_PREL_PG_HI21:
8081ad6265SDimitry Andric       return ELFAdrPage21;
8181ad6265SDimitry Andric     case ELF::R_AARCH64_ADD_ABS_LO12_NC:
8281ad6265SDimitry Andric       return ELFAddAbs12;
8381ad6265SDimitry Andric     case ELF::R_AARCH64_LDST8_ABS_LO12_NC:
8481ad6265SDimitry Andric       return ELFLdSt8Abs12;
8581ad6265SDimitry Andric     case ELF::R_AARCH64_LDST16_ABS_LO12_NC:
8681ad6265SDimitry Andric       return ELFLdSt16Abs12;
8781ad6265SDimitry Andric     case ELF::R_AARCH64_LDST32_ABS_LO12_NC:
8881ad6265SDimitry Andric       return ELFLdSt32Abs12;
8981ad6265SDimitry Andric     case ELF::R_AARCH64_LDST64_ABS_LO12_NC:
9081ad6265SDimitry Andric       return ELFLdSt64Abs12;
9181ad6265SDimitry Andric     case ELF::R_AARCH64_LDST128_ABS_LO12_NC:
9281ad6265SDimitry Andric       return ELFLdSt128Abs12;
9381ad6265SDimitry Andric     case ELF::R_AARCH64_MOVW_UABS_G0_NC:
9481ad6265SDimitry Andric       return ELFMovwAbsG0;
9581ad6265SDimitry Andric     case ELF::R_AARCH64_MOVW_UABS_G1_NC:
9681ad6265SDimitry Andric       return ELFMovwAbsG1;
9781ad6265SDimitry Andric     case ELF::R_AARCH64_MOVW_UABS_G2_NC:
9881ad6265SDimitry Andric       return ELFMovwAbsG2;
9981ad6265SDimitry Andric     case ELF::R_AARCH64_MOVW_UABS_G3:
10081ad6265SDimitry Andric       return ELFMovwAbsG3;
10181ad6265SDimitry Andric     case ELF::R_AARCH64_ABS64:
10281ad6265SDimitry Andric       return ELFAbs64;
10381ad6265SDimitry Andric     case ELF::R_AARCH64_PREL32:
10481ad6265SDimitry Andric       return ELFPrel32;
10581ad6265SDimitry Andric     case ELF::R_AARCH64_PREL64:
10681ad6265SDimitry Andric       return ELFPrel64;
10781ad6265SDimitry Andric     case ELF::R_AARCH64_ADR_GOT_PAGE:
10881ad6265SDimitry Andric       return ELFAdrGOTPage21;
10981ad6265SDimitry Andric     case ELF::R_AARCH64_LD64_GOT_LO12_NC:
11081ad6265SDimitry Andric       return ELFLd64GOTLo12;
111753f127fSDimitry Andric     case ELF::R_AARCH64_TLSDESC_ADR_PAGE21:
112753f127fSDimitry Andric       return ELFTLSDescAdrPage21;
113753f127fSDimitry Andric     case ELF::R_AARCH64_TLSDESC_ADD_LO12:
114753f127fSDimitry Andric       return ELFTLSDescAddLo12;
115753f127fSDimitry Andric     case ELF::R_AARCH64_TLSDESC_LD64_LO12:
116753f127fSDimitry Andric       return ELFTLSDescLd64Lo12;
117753f127fSDimitry Andric     case ELF::R_AARCH64_TLSDESC_CALL:
118753f127fSDimitry Andric       return ELFTLSDescCall;
119349cc55cSDimitry Andric     }
120349cc55cSDimitry Andric 
12181ad6265SDimitry Andric     return make_error<JITLinkError>(
12281ad6265SDimitry Andric         "Unsupported aarch64 relocation:" + formatv("{0:d}: ", Type) +
12381ad6265SDimitry Andric         object::getELFRelocationTypeName(ELF::EM_AARCH64, Type));
124349cc55cSDimitry Andric   }
125349cc55cSDimitry Andric 
126349cc55cSDimitry Andric   Error addRelocations() override {
127349cc55cSDimitry Andric     LLVM_DEBUG(dbgs() << "Processing relocations:\n");
128349cc55cSDimitry Andric 
129349cc55cSDimitry Andric     using Base = ELFLinkGraphBuilder<ELFT>;
130349cc55cSDimitry Andric     using Self = ELFLinkGraphBuilder_aarch64<ELFT>;
131349cc55cSDimitry Andric     for (const auto &RelSect : Base::Sections)
132bdd1243dSDimitry Andric       if (Error Err = Base::forEachRelaRelocation(RelSect, this,
133349cc55cSDimitry Andric                                                   &Self::addSingleRelocation))
134349cc55cSDimitry Andric         return Err;
135349cc55cSDimitry Andric 
136349cc55cSDimitry Andric     return Error::success();
137349cc55cSDimitry Andric   }
138349cc55cSDimitry Andric 
139349cc55cSDimitry Andric   Error addSingleRelocation(const typename ELFT::Rela &Rel,
140349cc55cSDimitry Andric                             const typename ELFT::Shdr &FixupSect,
14104eeddc0SDimitry Andric                             Block &BlockToFix) {
14281ad6265SDimitry Andric     using support::ulittle32_t;
143349cc55cSDimitry Andric     using Base = ELFLinkGraphBuilder<ELFT>;
144349cc55cSDimitry Andric 
145349cc55cSDimitry Andric     uint32_t SymbolIndex = Rel.getSymbol(false);
146349cc55cSDimitry Andric     auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);
147349cc55cSDimitry Andric     if (!ObjSymbol)
148349cc55cSDimitry Andric       return ObjSymbol.takeError();
149349cc55cSDimitry Andric 
150349cc55cSDimitry Andric     Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex);
151349cc55cSDimitry Andric     if (!GraphSymbol)
152349cc55cSDimitry Andric       return make_error<StringError>(
153349cc55cSDimitry Andric           formatv("Could not find symbol at given index, did you add it to "
154349cc55cSDimitry Andric                   "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",
155349cc55cSDimitry Andric                   SymbolIndex, (*ObjSymbol)->st_shndx,
156349cc55cSDimitry Andric                   Base::GraphSymbols.size()),
157349cc55cSDimitry Andric           inconvertibleErrorCode());
158349cc55cSDimitry Andric 
159349cc55cSDimitry Andric     uint32_t Type = Rel.getType(false);
16081ad6265SDimitry Andric     Expected<ELFAArch64RelocationKind> RelocKind = getRelocationKind(Type);
16181ad6265SDimitry Andric     if (!RelocKind)
16281ad6265SDimitry Andric       return RelocKind.takeError();
163349cc55cSDimitry Andric 
164349cc55cSDimitry Andric     int64_t Addend = Rel.r_addend;
16504eeddc0SDimitry Andric     orc::ExecutorAddr FixupAddress =
16604eeddc0SDimitry Andric         orc::ExecutorAddr(FixupSect.sh_addr) + Rel.r_offset;
16704eeddc0SDimitry Andric     Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();
16881ad6265SDimitry Andric 
16981ad6265SDimitry Andric     // Get a pointer to the fixup content.
17081ad6265SDimitry Andric     const void *FixupContent = BlockToFix.getContent().data() +
17181ad6265SDimitry Andric                                (FixupAddress - BlockToFix.getAddress());
17281ad6265SDimitry Andric 
17381ad6265SDimitry Andric     Edge::Kind Kind = Edge::Invalid;
17481ad6265SDimitry Andric 
17581ad6265SDimitry Andric     switch (*RelocKind) {
17681ad6265SDimitry Andric     case ELFCall26: {
177bdd1243dSDimitry Andric       Kind = aarch64::Branch26PCRel;
17881ad6265SDimitry Andric       break;
17981ad6265SDimitry Andric     }
18081ad6265SDimitry Andric     case ELFAdrPage21: {
18181ad6265SDimitry Andric       Kind = aarch64::Page21;
18281ad6265SDimitry Andric       break;
18381ad6265SDimitry Andric     }
18481ad6265SDimitry Andric     case ELFAddAbs12: {
18581ad6265SDimitry Andric       Kind = aarch64::PageOffset12;
18681ad6265SDimitry Andric       break;
18781ad6265SDimitry Andric     }
18881ad6265SDimitry Andric     case ELFLdSt8Abs12: {
18981ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
19081ad6265SDimitry Andric       if (!aarch64::isLoadStoreImm12(Instr) ||
19181ad6265SDimitry Andric           aarch64::getPageOffset12Shift(Instr) != 0)
19281ad6265SDimitry Andric         return make_error<JITLinkError>(
19381ad6265SDimitry Andric             "R_AARCH64_LDST8_ABS_LO12_NC target is not a "
19481ad6265SDimitry Andric             "LDRB/STRB (imm12) instruction");
19581ad6265SDimitry Andric 
19681ad6265SDimitry Andric       Kind = aarch64::PageOffset12;
19781ad6265SDimitry Andric       break;
19881ad6265SDimitry Andric     }
19981ad6265SDimitry Andric     case ELFLdSt16Abs12: {
20081ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
20181ad6265SDimitry Andric       if (!aarch64::isLoadStoreImm12(Instr) ||
20281ad6265SDimitry Andric           aarch64::getPageOffset12Shift(Instr) != 1)
20381ad6265SDimitry Andric         return make_error<JITLinkError>(
20481ad6265SDimitry Andric             "R_AARCH64_LDST16_ABS_LO12_NC target is not a "
20581ad6265SDimitry Andric             "LDRH/STRH (imm12) instruction");
20681ad6265SDimitry Andric 
20781ad6265SDimitry Andric       Kind = aarch64::PageOffset12;
20881ad6265SDimitry Andric       break;
20981ad6265SDimitry Andric     }
21081ad6265SDimitry Andric     case ELFLdSt32Abs12: {
21181ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
21281ad6265SDimitry Andric       if (!aarch64::isLoadStoreImm12(Instr) ||
21381ad6265SDimitry Andric           aarch64::getPageOffset12Shift(Instr) != 2)
21481ad6265SDimitry Andric         return make_error<JITLinkError>(
21581ad6265SDimitry Andric             "R_AARCH64_LDST32_ABS_LO12_NC target is not a "
21681ad6265SDimitry Andric             "LDR/STR (imm12, 32 bit) instruction");
21781ad6265SDimitry Andric 
21881ad6265SDimitry Andric       Kind = aarch64::PageOffset12;
21981ad6265SDimitry Andric       break;
22081ad6265SDimitry Andric     }
22181ad6265SDimitry Andric     case ELFLdSt64Abs12: {
22281ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
22381ad6265SDimitry Andric       if (!aarch64::isLoadStoreImm12(Instr) ||
22481ad6265SDimitry Andric           aarch64::getPageOffset12Shift(Instr) != 3)
22581ad6265SDimitry Andric         return make_error<JITLinkError>(
22681ad6265SDimitry Andric             "R_AARCH64_LDST64_ABS_LO12_NC target is not a "
22781ad6265SDimitry Andric             "LDR/STR (imm12, 64 bit) instruction");
22881ad6265SDimitry Andric 
22981ad6265SDimitry Andric       Kind = aarch64::PageOffset12;
23081ad6265SDimitry Andric       break;
23181ad6265SDimitry Andric     }
23281ad6265SDimitry Andric     case ELFLdSt128Abs12: {
23381ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
23481ad6265SDimitry Andric       if (!aarch64::isLoadStoreImm12(Instr) ||
23581ad6265SDimitry Andric           aarch64::getPageOffset12Shift(Instr) != 4)
23681ad6265SDimitry Andric         return make_error<JITLinkError>(
23781ad6265SDimitry Andric             "R_AARCH64_LDST128_ABS_LO12_NC target is not a "
23881ad6265SDimitry Andric             "LDR/STR (imm12, 128 bit) instruction");
23981ad6265SDimitry Andric 
24081ad6265SDimitry Andric       Kind = aarch64::PageOffset12;
24181ad6265SDimitry Andric       break;
24281ad6265SDimitry Andric     }
24381ad6265SDimitry Andric     case ELFMovwAbsG0: {
24481ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
24581ad6265SDimitry Andric       if (!aarch64::isMoveWideImm16(Instr) ||
24681ad6265SDimitry Andric           aarch64::getMoveWide16Shift(Instr) != 0)
24781ad6265SDimitry Andric         return make_error<JITLinkError>(
24881ad6265SDimitry Andric             "R_AARCH64_MOVW_UABS_G0_NC target is not a "
24981ad6265SDimitry Andric             "MOVK/MOVZ (imm16, LSL #0) instruction");
25081ad6265SDimitry Andric 
25181ad6265SDimitry Andric       Kind = aarch64::MoveWide16;
25281ad6265SDimitry Andric       break;
25381ad6265SDimitry Andric     }
25481ad6265SDimitry Andric     case ELFMovwAbsG1: {
25581ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
25681ad6265SDimitry Andric       if (!aarch64::isMoveWideImm16(Instr) ||
25781ad6265SDimitry Andric           aarch64::getMoveWide16Shift(Instr) != 16)
25881ad6265SDimitry Andric         return make_error<JITLinkError>(
25981ad6265SDimitry Andric             "R_AARCH64_MOVW_UABS_G1_NC target is not a "
26081ad6265SDimitry Andric             "MOVK/MOVZ (imm16, LSL #16) instruction");
26181ad6265SDimitry Andric 
26281ad6265SDimitry Andric       Kind = aarch64::MoveWide16;
26381ad6265SDimitry Andric       break;
26481ad6265SDimitry Andric     }
26581ad6265SDimitry Andric     case ELFMovwAbsG2: {
26681ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
26781ad6265SDimitry Andric       if (!aarch64::isMoveWideImm16(Instr) ||
26881ad6265SDimitry Andric           aarch64::getMoveWide16Shift(Instr) != 32)
26981ad6265SDimitry Andric         return make_error<JITLinkError>(
27081ad6265SDimitry Andric             "R_AARCH64_MOVW_UABS_G2_NC target is not a "
27181ad6265SDimitry Andric             "MOVK/MOVZ (imm16, LSL #32) instruction");
27281ad6265SDimitry Andric 
27381ad6265SDimitry Andric       Kind = aarch64::MoveWide16;
27481ad6265SDimitry Andric       break;
27581ad6265SDimitry Andric     }
27681ad6265SDimitry Andric     case ELFMovwAbsG3: {
27781ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
27881ad6265SDimitry Andric       if (!aarch64::isMoveWideImm16(Instr) ||
27981ad6265SDimitry Andric           aarch64::getMoveWide16Shift(Instr) != 48)
28081ad6265SDimitry Andric         return make_error<JITLinkError>(
28181ad6265SDimitry Andric             "R_AARCH64_MOVW_UABS_G3 target is not a "
28281ad6265SDimitry Andric             "MOVK/MOVZ (imm16, LSL #48) instruction");
28381ad6265SDimitry Andric 
28481ad6265SDimitry Andric       Kind = aarch64::MoveWide16;
28581ad6265SDimitry Andric       break;
28681ad6265SDimitry Andric     }
28781ad6265SDimitry Andric     case ELFAbs64: {
28881ad6265SDimitry Andric       Kind = aarch64::Pointer64;
28981ad6265SDimitry Andric       break;
29081ad6265SDimitry Andric     }
29181ad6265SDimitry Andric     case ELFPrel32: {
29281ad6265SDimitry Andric       Kind = aarch64::Delta32;
29381ad6265SDimitry Andric       break;
29481ad6265SDimitry Andric     }
29581ad6265SDimitry Andric     case ELFPrel64: {
29681ad6265SDimitry Andric       Kind = aarch64::Delta64;
29781ad6265SDimitry Andric       break;
29881ad6265SDimitry Andric     }
29981ad6265SDimitry Andric     case ELFAdrGOTPage21: {
300bdd1243dSDimitry Andric       Kind = aarch64::RequestGOTAndTransformToPage21;
30181ad6265SDimitry Andric       break;
30281ad6265SDimitry Andric     }
30381ad6265SDimitry Andric     case ELFLd64GOTLo12: {
304bdd1243dSDimitry Andric       Kind = aarch64::RequestGOTAndTransformToPageOffset12;
30581ad6265SDimitry Andric       break;
30681ad6265SDimitry Andric     }
307753f127fSDimitry Andric     case ELFTLSDescAdrPage21: {
308bdd1243dSDimitry Andric       Kind = aarch64::RequestTLSDescEntryAndTransformToPage21;
309753f127fSDimitry Andric       break;
310753f127fSDimitry Andric     }
311bdd1243dSDimitry Andric     case ELFTLSDescAddLo12:
312753f127fSDimitry Andric     case ELFTLSDescLd64Lo12: {
313bdd1243dSDimitry Andric       Kind = aarch64::RequestTLSDescEntryAndTransformToPageOffset12;
314753f127fSDimitry Andric       break;
315753f127fSDimitry Andric     }
316753f127fSDimitry Andric     case ELFTLSDescCall: {
317753f127fSDimitry Andric       return Error::success();
318753f127fSDimitry Andric     }
31981ad6265SDimitry Andric     };
32081ad6265SDimitry Andric 
32181ad6265SDimitry Andric     Edge GE(Kind, Offset, *GraphSymbol, Addend);
322349cc55cSDimitry Andric     LLVM_DEBUG({
323349cc55cSDimitry Andric       dbgs() << "    ";
32481ad6265SDimitry Andric       printEdge(dbgs(), BlockToFix, GE, aarch64::getEdgeKindName(Kind));
325349cc55cSDimitry Andric       dbgs() << "\n";
326349cc55cSDimitry Andric     });
327349cc55cSDimitry Andric 
32804eeddc0SDimitry Andric     BlockToFix.addEdge(std::move(GE));
329753f127fSDimitry Andric 
330349cc55cSDimitry Andric     return Error::success();
331349cc55cSDimitry Andric   }
332349cc55cSDimitry Andric 
33381ad6265SDimitry Andric   /// Return the string name of the given ELF aarch64 edge kind.
33481ad6265SDimitry Andric   const char *getELFAArch64RelocationKindName(Edge::Kind R) {
33581ad6265SDimitry Andric     switch (R) {
33681ad6265SDimitry Andric     case ELFCall26:
33781ad6265SDimitry Andric       return "ELFCall26";
33881ad6265SDimitry Andric     case ELFAdrPage21:
33981ad6265SDimitry Andric       return "ELFAdrPage21";
34081ad6265SDimitry Andric     case ELFAddAbs12:
34181ad6265SDimitry Andric       return "ELFAddAbs12";
34281ad6265SDimitry Andric     case ELFLdSt8Abs12:
34381ad6265SDimitry Andric       return "ELFLdSt8Abs12";
34481ad6265SDimitry Andric     case ELFLdSt16Abs12:
34581ad6265SDimitry Andric       return "ELFLdSt16Abs12";
34681ad6265SDimitry Andric     case ELFLdSt32Abs12:
34781ad6265SDimitry Andric       return "ELFLdSt32Abs12";
34881ad6265SDimitry Andric     case ELFLdSt64Abs12:
34981ad6265SDimitry Andric       return "ELFLdSt64Abs12";
35081ad6265SDimitry Andric     case ELFLdSt128Abs12:
35181ad6265SDimitry Andric       return "ELFLdSt128Abs12";
35281ad6265SDimitry Andric     case ELFMovwAbsG0:
35381ad6265SDimitry Andric       return "ELFMovwAbsG0";
35481ad6265SDimitry Andric     case ELFMovwAbsG1:
35581ad6265SDimitry Andric       return "ELFMovwAbsG1";
35681ad6265SDimitry Andric     case ELFMovwAbsG2:
35781ad6265SDimitry Andric       return "ELFMovwAbsG2";
35881ad6265SDimitry Andric     case ELFMovwAbsG3:
35981ad6265SDimitry Andric       return "ELFMovwAbsG3";
36081ad6265SDimitry Andric     case ELFAbs64:
36181ad6265SDimitry Andric       return "ELFAbs64";
36281ad6265SDimitry Andric     case ELFPrel32:
36381ad6265SDimitry Andric       return "ELFPrel32";
36481ad6265SDimitry Andric     case ELFPrel64:
36581ad6265SDimitry Andric       return "ELFPrel64";
36681ad6265SDimitry Andric     case ELFAdrGOTPage21:
36781ad6265SDimitry Andric       return "ELFAdrGOTPage21";
36881ad6265SDimitry Andric     case ELFLd64GOTLo12:
36981ad6265SDimitry Andric       return "ELFLd64GOTLo12";
370753f127fSDimitry Andric     case ELFTLSDescAdrPage21:
371753f127fSDimitry Andric       return "ELFTLSDescAdrPage21";
372753f127fSDimitry Andric     case ELFTLSDescAddLo12:
373753f127fSDimitry Andric       return "ELFTLSDescAddLo12";
374753f127fSDimitry Andric     case ELFTLSDescLd64Lo12:
375753f127fSDimitry Andric       return "ELFTLSDescLd64Lo12";
376753f127fSDimitry Andric     case ELFTLSDescCall:
377753f127fSDimitry Andric       return "ELFTLSDescCall";
37881ad6265SDimitry Andric     default:
37981ad6265SDimitry Andric       return getGenericEdgeKindName(static_cast<Edge::Kind>(R));
38081ad6265SDimitry Andric     }
38181ad6265SDimitry Andric   }
38281ad6265SDimitry Andric 
383349cc55cSDimitry Andric public:
384349cc55cSDimitry Andric   ELFLinkGraphBuilder_aarch64(StringRef FileName,
385349cc55cSDimitry Andric                               const object::ELFFile<ELFT> &Obj, const Triple T)
386349cc55cSDimitry Andric       : ELFLinkGraphBuilder<ELFT>(Obj, std::move(T), FileName,
387349cc55cSDimitry Andric                                   aarch64::getEdgeKindName) {}
388349cc55cSDimitry Andric };
389349cc55cSDimitry Andric 
390753f127fSDimitry Andric // TLS Info Builder.
391753f127fSDimitry Andric class TLSInfoTableManager_ELF_aarch64
392753f127fSDimitry Andric     : public TableManager<TLSInfoTableManager_ELF_aarch64> {
393753f127fSDimitry Andric public:
394753f127fSDimitry Andric   static StringRef getSectionName() { return "$__TLSINFO"; }
395753f127fSDimitry Andric 
396753f127fSDimitry Andric   static const uint8_t TLSInfoEntryContent[16];
397753f127fSDimitry Andric 
398753f127fSDimitry Andric   bool visitEdge(LinkGraph &G, Block *B, Edge &E) { return false; }
399753f127fSDimitry Andric 
400753f127fSDimitry Andric   Symbol &createEntry(LinkGraph &G, Symbol &Target) {
401753f127fSDimitry Andric     // the TLS Info entry's key value will be written by the fixTLVSectionByName
402753f127fSDimitry Andric     // pass, so create mutable content.
403753f127fSDimitry Andric     auto &TLSInfoEntry = G.createMutableContentBlock(
404753f127fSDimitry Andric         getTLSInfoSection(G), G.allocateContent(getTLSInfoEntryContent()),
405753f127fSDimitry Andric         orc::ExecutorAddr(), 8, 0);
406753f127fSDimitry Andric     TLSInfoEntry.addEdge(aarch64::Pointer64, 8, Target, 0);
407753f127fSDimitry Andric     return G.addAnonymousSymbol(TLSInfoEntry, 0, 16, false, false);
408753f127fSDimitry Andric   }
409753f127fSDimitry Andric 
410753f127fSDimitry Andric private:
411753f127fSDimitry Andric   Section &getTLSInfoSection(LinkGraph &G) {
412753f127fSDimitry Andric     if (!TLSInfoTable)
413bdd1243dSDimitry Andric       TLSInfoTable = &G.createSection(getSectionName(), orc::MemProt::Read);
414753f127fSDimitry Andric     return *TLSInfoTable;
415753f127fSDimitry Andric   }
416753f127fSDimitry Andric 
417753f127fSDimitry Andric   ArrayRef<char> getTLSInfoEntryContent() const {
418753f127fSDimitry Andric     return {reinterpret_cast<const char *>(TLSInfoEntryContent),
419753f127fSDimitry Andric             sizeof(TLSInfoEntryContent)};
420753f127fSDimitry Andric   }
421753f127fSDimitry Andric 
422753f127fSDimitry Andric   Section *TLSInfoTable = nullptr;
423753f127fSDimitry Andric };
424753f127fSDimitry Andric 
425753f127fSDimitry Andric const uint8_t TLSInfoTableManager_ELF_aarch64::TLSInfoEntryContent[16] = {
426753f127fSDimitry Andric     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*pthread key */
427753f127fSDimitry Andric     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  /*data address*/
428753f127fSDimitry Andric };
429753f127fSDimitry Andric 
430753f127fSDimitry Andric // TLS Descriptor Builder.
431753f127fSDimitry Andric class TLSDescTableManager_ELF_aarch64
432753f127fSDimitry Andric     : public TableManager<TLSDescTableManager_ELF_aarch64> {
433753f127fSDimitry Andric public:
434753f127fSDimitry Andric   TLSDescTableManager_ELF_aarch64(
435753f127fSDimitry Andric       TLSInfoTableManager_ELF_aarch64 &TLSInfoTableManager)
436753f127fSDimitry Andric       : TLSInfoTableManager(TLSInfoTableManager) {}
437753f127fSDimitry Andric 
438753f127fSDimitry Andric   static StringRef getSectionName() { return "$__TLSDESC"; }
439753f127fSDimitry Andric 
440753f127fSDimitry Andric   static const uint8_t TLSDescEntryContent[16];
441753f127fSDimitry Andric 
442753f127fSDimitry Andric   bool visitEdge(LinkGraph &G, Block *B, Edge &E) {
443753f127fSDimitry Andric     Edge::Kind KindToSet = Edge::Invalid;
444753f127fSDimitry Andric     switch (E.getKind()) {
445bdd1243dSDimitry Andric     case aarch64::RequestTLSDescEntryAndTransformToPage21: {
446753f127fSDimitry Andric       KindToSet = aarch64::Page21;
447753f127fSDimitry Andric       break;
448753f127fSDimitry Andric     }
449bdd1243dSDimitry Andric     case aarch64::RequestTLSDescEntryAndTransformToPageOffset12: {
450753f127fSDimitry Andric       KindToSet = aarch64::PageOffset12;
451753f127fSDimitry Andric       break;
452753f127fSDimitry Andric     }
453753f127fSDimitry Andric     default:
454753f127fSDimitry Andric       return false;
455753f127fSDimitry Andric     }
456753f127fSDimitry Andric     assert(KindToSet != Edge::Invalid &&
457753f127fSDimitry Andric            "Fell through switch, but no new kind to set");
458753f127fSDimitry Andric     DEBUG_WITH_TYPE("jitlink", {
459753f127fSDimitry Andric       dbgs() << "  Fixing " << G.getEdgeKindName(E.getKind()) << " edge at "
460753f127fSDimitry Andric              << B->getFixupAddress(E) << " (" << B->getAddress() << " + "
461753f127fSDimitry Andric              << formatv("{0:x}", E.getOffset()) << ")\n";
462753f127fSDimitry Andric     });
463753f127fSDimitry Andric     E.setKind(KindToSet);
464753f127fSDimitry Andric     E.setTarget(getEntryForTarget(G, E.getTarget()));
465753f127fSDimitry Andric     return true;
466753f127fSDimitry Andric   }
467753f127fSDimitry Andric 
468753f127fSDimitry Andric   Symbol &createEntry(LinkGraph &G, Symbol &Target) {
469753f127fSDimitry Andric     auto &EntryBlock =
470753f127fSDimitry Andric         G.createContentBlock(getTLSDescSection(G), getTLSDescBlockContent(),
471753f127fSDimitry Andric                              orc::ExecutorAddr(), 8, 0);
472753f127fSDimitry Andric     EntryBlock.addEdge(aarch64::Pointer64, 0, getTLSDescResolver(G), 0);
473753f127fSDimitry Andric     EntryBlock.addEdge(aarch64::Pointer64, 8,
474753f127fSDimitry Andric                        TLSInfoTableManager.getEntryForTarget(G, Target), 0);
475753f127fSDimitry Andric     return G.addAnonymousSymbol(EntryBlock, 0, 8, false, false);
476753f127fSDimitry Andric   }
477753f127fSDimitry Andric 
478753f127fSDimitry Andric private:
479753f127fSDimitry Andric   Section &getTLSDescSection(LinkGraph &G) {
480753f127fSDimitry Andric     if (!GOTSection)
481bdd1243dSDimitry Andric       GOTSection = &G.createSection(getSectionName(), orc::MemProt::Read);
482753f127fSDimitry Andric     return *GOTSection;
483753f127fSDimitry Andric   }
484753f127fSDimitry Andric 
485753f127fSDimitry Andric   Symbol &getTLSDescResolver(LinkGraph &G) {
486753f127fSDimitry Andric     if (!TLSDescResolver)
487bdd1243dSDimitry Andric       TLSDescResolver = &G.addExternalSymbol("__tlsdesc_resolver", 8, false);
488753f127fSDimitry Andric     return *TLSDescResolver;
489753f127fSDimitry Andric   }
490753f127fSDimitry Andric 
491753f127fSDimitry Andric   ArrayRef<char> getTLSDescBlockContent() {
492753f127fSDimitry Andric     return {reinterpret_cast<const char *>(TLSDescEntryContent),
493753f127fSDimitry Andric             sizeof(TLSDescEntryContent)};
494753f127fSDimitry Andric   }
495753f127fSDimitry Andric 
496753f127fSDimitry Andric   Section *GOTSection = nullptr;
497753f127fSDimitry Andric   Symbol *TLSDescResolver = nullptr;
498753f127fSDimitry Andric   TLSInfoTableManager_ELF_aarch64 &TLSInfoTableManager;
499753f127fSDimitry Andric };
500753f127fSDimitry Andric 
501753f127fSDimitry Andric const uint8_t TLSDescTableManager_ELF_aarch64::TLSDescEntryContent[16] = {
502753f127fSDimitry Andric     0x00, 0x00, 0x00, 0x00,
503753f127fSDimitry Andric     0x00, 0x00, 0x00, 0x00, /*resolver function pointer*/
504753f127fSDimitry Andric     0x00, 0x00, 0x00, 0x00,
505753f127fSDimitry Andric     0x00, 0x00, 0x00, 0x00 /*pointer to tls info*/
506753f127fSDimitry Andric };
507753f127fSDimitry Andric 
50881ad6265SDimitry Andric Error buildTables_ELF_aarch64(LinkGraph &G) {
50981ad6265SDimitry Andric   LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");
51081ad6265SDimitry Andric 
51181ad6265SDimitry Andric   aarch64::GOTTableManager GOT;
51281ad6265SDimitry Andric   aarch64::PLTTableManager PLT(GOT);
513753f127fSDimitry Andric   TLSInfoTableManager_ELF_aarch64 TLSInfo;
514753f127fSDimitry Andric   TLSDescTableManager_ELF_aarch64 TLSDesc(TLSInfo);
515753f127fSDimitry Andric   visitExistingEdges(G, GOT, PLT, TLSDesc, TLSInfo);
51681ad6265SDimitry Andric   return Error::success();
51781ad6265SDimitry Andric }
51881ad6265SDimitry Andric 
51981ad6265SDimitry Andric } // namespace
52081ad6265SDimitry Andric 
52181ad6265SDimitry Andric namespace llvm {
52281ad6265SDimitry Andric namespace jitlink {
52381ad6265SDimitry Andric 
524349cc55cSDimitry Andric Expected<std::unique_ptr<LinkGraph>>
525349cc55cSDimitry Andric createLinkGraphFromELFObject_aarch64(MemoryBufferRef ObjectBuffer) {
526349cc55cSDimitry Andric   LLVM_DEBUG({
527349cc55cSDimitry Andric     dbgs() << "Building jitlink graph for new input "
528349cc55cSDimitry Andric            << ObjectBuffer.getBufferIdentifier() << "...\n";
529349cc55cSDimitry Andric   });
530349cc55cSDimitry Andric 
531349cc55cSDimitry Andric   auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer);
532349cc55cSDimitry Andric   if (!ELFObj)
533349cc55cSDimitry Andric     return ELFObj.takeError();
534349cc55cSDimitry Andric 
535349cc55cSDimitry Andric   assert((*ELFObj)->getArch() == Triple::aarch64 &&
536349cc55cSDimitry Andric          "Only AArch64 (little endian) is supported for now");
537349cc55cSDimitry Andric 
538349cc55cSDimitry Andric   auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
539349cc55cSDimitry Andric   return ELFLinkGraphBuilder_aarch64<object::ELF64LE>((*ELFObj)->getFileName(),
540349cc55cSDimitry Andric                                                       ELFObjFile.getELFFile(),
541349cc55cSDimitry Andric                                                       (*ELFObj)->makeTriple())
542349cc55cSDimitry Andric       .buildGraph();
543349cc55cSDimitry Andric }
544349cc55cSDimitry Andric 
545349cc55cSDimitry Andric void link_ELF_aarch64(std::unique_ptr<LinkGraph> G,
546349cc55cSDimitry Andric                       std::unique_ptr<JITLinkContext> Ctx) {
547349cc55cSDimitry Andric   PassConfiguration Config;
548349cc55cSDimitry Andric   const Triple &TT = G->getTargetTriple();
549349cc55cSDimitry Andric   if (Ctx->shouldAddDefaultTargetPasses(TT)) {
55081ad6265SDimitry Andric     // Add eh-frame passses.
55181ad6265SDimitry Andric     Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame"));
55281ad6265SDimitry Andric     Config.PrePrunePasses.push_back(EHFrameEdgeFixer(
55381ad6265SDimitry Andric         ".eh_frame", 8, aarch64::Pointer32, aarch64::Pointer64,
55481ad6265SDimitry Andric         aarch64::Delta32, aarch64::Delta64, aarch64::NegDelta32));
555*1ac55f4cSDimitry Andric     Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame"));
55681ad6265SDimitry Andric 
55781ad6265SDimitry Andric     // Add a mark-live pass.
558349cc55cSDimitry Andric     if (auto MarkLive = Ctx->getMarkLivePass(TT))
559349cc55cSDimitry Andric       Config.PrePrunePasses.push_back(std::move(MarkLive));
560349cc55cSDimitry Andric     else
561349cc55cSDimitry Andric       Config.PrePrunePasses.push_back(markAllSymbolsLive);
56281ad6265SDimitry Andric 
563753f127fSDimitry Andric     // Add an in-place GOT/TLS/Stubs build pass.
56481ad6265SDimitry Andric     Config.PostPrunePasses.push_back(buildTables_ELF_aarch64);
565349cc55cSDimitry Andric   }
56681ad6265SDimitry Andric 
567349cc55cSDimitry Andric   if (auto Err = Ctx->modifyPassConfig(*G, Config))
568349cc55cSDimitry Andric     return Ctx->notifyFailed(std::move(Err));
569349cc55cSDimitry Andric 
570349cc55cSDimitry Andric   ELFJITLinker_aarch64::link(std::move(Ctx), std::move(G), std::move(Config));
571349cc55cSDimitry Andric }
572349cc55cSDimitry Andric 
573349cc55cSDimitry Andric } // namespace jitlink
574349cc55cSDimitry Andric } // namespace llvm
575