xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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"
14349cc55cSDimitry Andric #include "llvm/BinaryFormat/ELF.h"
1581ad6265SDimitry Andric #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"
16349cc55cSDimitry Andric #include "llvm/ExecutionEngine/JITLink/aarch64.h"
17349cc55cSDimitry Andric #include "llvm/Object/ELFObjectFile.h"
1881ad6265SDimitry Andric #include "llvm/Support/Endian.h"
19349cc55cSDimitry Andric 
20*0fca6ea1SDimitry Andric #include "DefineExternalSectionStartAndEndSymbols.h"
21*0fca6ea1SDimitry Andric #include "EHFrameSupportImpl.h"
22*0fca6ea1SDimitry Andric #include "ELFLinkGraphBuilder.h"
23*0fca6ea1SDimitry Andric #include "JITLinkGeneric.h"
24*0fca6ea1SDimitry Andric 
25349cc55cSDimitry Andric #define DEBUG_TYPE "jitlink"
26349cc55cSDimitry Andric 
27349cc55cSDimitry Andric using namespace llvm;
28349cc55cSDimitry Andric using namespace llvm::jitlink;
29349cc55cSDimitry Andric 
3081ad6265SDimitry Andric namespace {
31349cc55cSDimitry Andric 
32349cc55cSDimitry Andric class ELFJITLinker_aarch64 : public JITLinker<ELFJITLinker_aarch64> {
33349cc55cSDimitry Andric   friend class JITLinker<ELFJITLinker_aarch64>;
34349cc55cSDimitry Andric 
35349cc55cSDimitry Andric public:
36349cc55cSDimitry Andric   ELFJITLinker_aarch64(std::unique_ptr<JITLinkContext> Ctx,
37349cc55cSDimitry Andric                        std::unique_ptr<LinkGraph> G,
38349cc55cSDimitry Andric                        PassConfiguration PassConfig)
39349cc55cSDimitry Andric       : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
40349cc55cSDimitry Andric 
41349cc55cSDimitry Andric private:
42349cc55cSDimitry Andric   Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
4381ad6265SDimitry Andric     return aarch64::applyFixup(G, B, E);
44349cc55cSDimitry Andric   }
45349cc55cSDimitry Andric };
46349cc55cSDimitry Andric 
47349cc55cSDimitry Andric template <typename ELFT>
48349cc55cSDimitry Andric class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
49349cc55cSDimitry Andric private:
5081ad6265SDimitry Andric   enum ELFAArch64RelocationKind : Edge::Kind {
5181ad6265SDimitry Andric     ELFCall26 = Edge::FirstRelocation,
52*0fca6ea1SDimitry Andric     ELFLdrLo19,
5306c3fb27SDimitry Andric     ELFAdrLo21,
5481ad6265SDimitry Andric     ELFAdrPage21,
5581ad6265SDimitry Andric     ELFAddAbs12,
5681ad6265SDimitry Andric     ELFLdSt8Abs12,
5781ad6265SDimitry Andric     ELFLdSt16Abs12,
5881ad6265SDimitry Andric     ELFLdSt32Abs12,
5981ad6265SDimitry Andric     ELFLdSt64Abs12,
6081ad6265SDimitry Andric     ELFLdSt128Abs12,
6181ad6265SDimitry Andric     ELFMovwAbsG0,
6281ad6265SDimitry Andric     ELFMovwAbsG1,
6381ad6265SDimitry Andric     ELFMovwAbsG2,
6481ad6265SDimitry Andric     ELFMovwAbsG3,
6506c3fb27SDimitry Andric     ELFTstBr14,
6606c3fb27SDimitry Andric     ELFCondBr19,
6706c3fb27SDimitry Andric     ELFAbs32,
6881ad6265SDimitry Andric     ELFAbs64,
6981ad6265SDimitry Andric     ELFPrel32,
7081ad6265SDimitry Andric     ELFPrel64,
7181ad6265SDimitry Andric     ELFAdrGOTPage21,
7281ad6265SDimitry Andric     ELFLd64GOTLo12,
73753f127fSDimitry Andric     ELFTLSDescAdrPage21,
74753f127fSDimitry Andric     ELFTLSDescAddLo12,
75753f127fSDimitry Andric     ELFTLSDescLd64Lo12,
76753f127fSDimitry Andric     ELFTLSDescCall,
7781ad6265SDimitry Andric   };
7881ad6265SDimitry Andric 
7981ad6265SDimitry Andric   static Expected<ELFAArch64RelocationKind>
80349cc55cSDimitry Andric   getRelocationKind(const uint32_t Type) {
81349cc55cSDimitry Andric     using namespace aarch64;
82349cc55cSDimitry Andric     switch (Type) {
83349cc55cSDimitry Andric     case ELF::R_AARCH64_CALL26:
8481ad6265SDimitry Andric     case ELF::R_AARCH64_JUMP26:
8581ad6265SDimitry Andric       return ELFCall26;
86*0fca6ea1SDimitry Andric     case ELF::R_AARCH64_LD_PREL_LO19:
87*0fca6ea1SDimitry Andric       return ELFLdrLo19;
8806c3fb27SDimitry Andric     case ELF::R_AARCH64_ADR_PREL_LO21:
8906c3fb27SDimitry Andric       return ELFAdrLo21;
9081ad6265SDimitry Andric     case ELF::R_AARCH64_ADR_PREL_PG_HI21:
9181ad6265SDimitry Andric       return ELFAdrPage21;
9281ad6265SDimitry Andric     case ELF::R_AARCH64_ADD_ABS_LO12_NC:
9381ad6265SDimitry Andric       return ELFAddAbs12;
9481ad6265SDimitry Andric     case ELF::R_AARCH64_LDST8_ABS_LO12_NC:
9581ad6265SDimitry Andric       return ELFLdSt8Abs12;
9681ad6265SDimitry Andric     case ELF::R_AARCH64_LDST16_ABS_LO12_NC:
9781ad6265SDimitry Andric       return ELFLdSt16Abs12;
9881ad6265SDimitry Andric     case ELF::R_AARCH64_LDST32_ABS_LO12_NC:
9981ad6265SDimitry Andric       return ELFLdSt32Abs12;
10081ad6265SDimitry Andric     case ELF::R_AARCH64_LDST64_ABS_LO12_NC:
10181ad6265SDimitry Andric       return ELFLdSt64Abs12;
10281ad6265SDimitry Andric     case ELF::R_AARCH64_LDST128_ABS_LO12_NC:
10381ad6265SDimitry Andric       return ELFLdSt128Abs12;
10481ad6265SDimitry Andric     case ELF::R_AARCH64_MOVW_UABS_G0_NC:
10581ad6265SDimitry Andric       return ELFMovwAbsG0;
10681ad6265SDimitry Andric     case ELF::R_AARCH64_MOVW_UABS_G1_NC:
10781ad6265SDimitry Andric       return ELFMovwAbsG1;
10881ad6265SDimitry Andric     case ELF::R_AARCH64_MOVW_UABS_G2_NC:
10981ad6265SDimitry Andric       return ELFMovwAbsG2;
11081ad6265SDimitry Andric     case ELF::R_AARCH64_MOVW_UABS_G3:
11181ad6265SDimitry Andric       return ELFMovwAbsG3;
11206c3fb27SDimitry Andric     case ELF::R_AARCH64_TSTBR14:
11306c3fb27SDimitry Andric       return ELFTstBr14;
11406c3fb27SDimitry Andric     case ELF::R_AARCH64_CONDBR19:
11506c3fb27SDimitry Andric       return ELFCondBr19;
11606c3fb27SDimitry Andric     case ELF::R_AARCH64_ABS32:
11706c3fb27SDimitry Andric       return ELFAbs32;
11881ad6265SDimitry Andric     case ELF::R_AARCH64_ABS64:
11981ad6265SDimitry Andric       return ELFAbs64;
12081ad6265SDimitry Andric     case ELF::R_AARCH64_PREL32:
12181ad6265SDimitry Andric       return ELFPrel32;
12281ad6265SDimitry Andric     case ELF::R_AARCH64_PREL64:
12381ad6265SDimitry Andric       return ELFPrel64;
12481ad6265SDimitry Andric     case ELF::R_AARCH64_ADR_GOT_PAGE:
12581ad6265SDimitry Andric       return ELFAdrGOTPage21;
12681ad6265SDimitry Andric     case ELF::R_AARCH64_LD64_GOT_LO12_NC:
12781ad6265SDimitry Andric       return ELFLd64GOTLo12;
128753f127fSDimitry Andric     case ELF::R_AARCH64_TLSDESC_ADR_PAGE21:
129753f127fSDimitry Andric       return ELFTLSDescAdrPage21;
130753f127fSDimitry Andric     case ELF::R_AARCH64_TLSDESC_ADD_LO12:
131753f127fSDimitry Andric       return ELFTLSDescAddLo12;
132753f127fSDimitry Andric     case ELF::R_AARCH64_TLSDESC_LD64_LO12:
133753f127fSDimitry Andric       return ELFTLSDescLd64Lo12;
134753f127fSDimitry Andric     case ELF::R_AARCH64_TLSDESC_CALL:
135753f127fSDimitry Andric       return ELFTLSDescCall;
136349cc55cSDimitry Andric     }
137349cc55cSDimitry Andric 
13881ad6265SDimitry Andric     return make_error<JITLinkError>(
13981ad6265SDimitry Andric         "Unsupported aarch64 relocation:" + formatv("{0:d}: ", Type) +
14081ad6265SDimitry Andric         object::getELFRelocationTypeName(ELF::EM_AARCH64, Type));
141349cc55cSDimitry Andric   }
142349cc55cSDimitry Andric 
143349cc55cSDimitry Andric   Error addRelocations() override {
144349cc55cSDimitry Andric     LLVM_DEBUG(dbgs() << "Processing relocations:\n");
145349cc55cSDimitry Andric 
146349cc55cSDimitry Andric     using Base = ELFLinkGraphBuilder<ELFT>;
147349cc55cSDimitry Andric     using Self = ELFLinkGraphBuilder_aarch64<ELFT>;
148349cc55cSDimitry Andric     for (const auto &RelSect : Base::Sections)
149bdd1243dSDimitry Andric       if (Error Err = Base::forEachRelaRelocation(RelSect, this,
150349cc55cSDimitry Andric                                                   &Self::addSingleRelocation))
151349cc55cSDimitry Andric         return Err;
152349cc55cSDimitry Andric 
153349cc55cSDimitry Andric     return Error::success();
154349cc55cSDimitry Andric   }
155349cc55cSDimitry Andric 
156349cc55cSDimitry Andric   Error addSingleRelocation(const typename ELFT::Rela &Rel,
157349cc55cSDimitry Andric                             const typename ELFT::Shdr &FixupSect,
15804eeddc0SDimitry Andric                             Block &BlockToFix) {
15981ad6265SDimitry Andric     using support::ulittle32_t;
160349cc55cSDimitry Andric     using Base = ELFLinkGraphBuilder<ELFT>;
161349cc55cSDimitry Andric 
162349cc55cSDimitry Andric     uint32_t SymbolIndex = Rel.getSymbol(false);
163349cc55cSDimitry Andric     auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);
164349cc55cSDimitry Andric     if (!ObjSymbol)
165349cc55cSDimitry Andric       return ObjSymbol.takeError();
166349cc55cSDimitry Andric 
167349cc55cSDimitry Andric     Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex);
168349cc55cSDimitry Andric     if (!GraphSymbol)
169349cc55cSDimitry Andric       return make_error<StringError>(
170349cc55cSDimitry Andric           formatv("Could not find symbol at given index, did you add it to "
171349cc55cSDimitry Andric                   "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",
172349cc55cSDimitry Andric                   SymbolIndex, (*ObjSymbol)->st_shndx,
173349cc55cSDimitry Andric                   Base::GraphSymbols.size()),
174349cc55cSDimitry Andric           inconvertibleErrorCode());
175349cc55cSDimitry Andric 
176349cc55cSDimitry Andric     uint32_t Type = Rel.getType(false);
17781ad6265SDimitry Andric     Expected<ELFAArch64RelocationKind> RelocKind = getRelocationKind(Type);
17881ad6265SDimitry Andric     if (!RelocKind)
17981ad6265SDimitry Andric       return RelocKind.takeError();
180349cc55cSDimitry Andric 
181349cc55cSDimitry Andric     int64_t Addend = Rel.r_addend;
18204eeddc0SDimitry Andric     orc::ExecutorAddr FixupAddress =
18304eeddc0SDimitry Andric         orc::ExecutorAddr(FixupSect.sh_addr) + Rel.r_offset;
18404eeddc0SDimitry Andric     Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();
18581ad6265SDimitry Andric 
18681ad6265SDimitry Andric     // Get a pointer to the fixup content.
18781ad6265SDimitry Andric     const void *FixupContent = BlockToFix.getContent().data() +
18881ad6265SDimitry Andric                                (FixupAddress - BlockToFix.getAddress());
18981ad6265SDimitry Andric 
19081ad6265SDimitry Andric     Edge::Kind Kind = Edge::Invalid;
19181ad6265SDimitry Andric 
19281ad6265SDimitry Andric     switch (*RelocKind) {
19381ad6265SDimitry Andric     case ELFCall26: {
194bdd1243dSDimitry Andric       Kind = aarch64::Branch26PCRel;
19581ad6265SDimitry Andric       break;
19681ad6265SDimitry Andric     }
197*0fca6ea1SDimitry Andric     case ELFLdrLo19: {
198*0fca6ea1SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
199*0fca6ea1SDimitry Andric       if (!aarch64::isLDRLiteral(Instr))
200*0fca6ea1SDimitry Andric         return make_error<JITLinkError>(
201*0fca6ea1SDimitry Andric             "R_AARCH64_LDR_PREL_LO19 target is not an LDR Literal instruction");
202*0fca6ea1SDimitry Andric 
203*0fca6ea1SDimitry Andric       Kind = aarch64::LDRLiteral19;
204*0fca6ea1SDimitry Andric       break;
205*0fca6ea1SDimitry Andric     }
20606c3fb27SDimitry Andric     case ELFAdrLo21: {
20706c3fb27SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
20806c3fb27SDimitry Andric       if (!aarch64::isADR(Instr))
20906c3fb27SDimitry Andric         return make_error<JITLinkError>(
21006c3fb27SDimitry Andric             "R_AARCH64_ADR_PREL_LO21 target is not an ADR instruction");
21106c3fb27SDimitry Andric 
21206c3fb27SDimitry Andric       Kind = aarch64::ADRLiteral21;
21306c3fb27SDimitry Andric       break;
21406c3fb27SDimitry Andric     }
21581ad6265SDimitry Andric     case ELFAdrPage21: {
21681ad6265SDimitry Andric       Kind = aarch64::Page21;
21781ad6265SDimitry Andric       break;
21881ad6265SDimitry Andric     }
21981ad6265SDimitry Andric     case ELFAddAbs12: {
22081ad6265SDimitry Andric       Kind = aarch64::PageOffset12;
22181ad6265SDimitry Andric       break;
22281ad6265SDimitry Andric     }
22381ad6265SDimitry Andric     case ELFLdSt8Abs12: {
22481ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
22581ad6265SDimitry Andric       if (!aarch64::isLoadStoreImm12(Instr) ||
22681ad6265SDimitry Andric           aarch64::getPageOffset12Shift(Instr) != 0)
22781ad6265SDimitry Andric         return make_error<JITLinkError>(
22881ad6265SDimitry Andric             "R_AARCH64_LDST8_ABS_LO12_NC target is not a "
22981ad6265SDimitry Andric             "LDRB/STRB (imm12) instruction");
23081ad6265SDimitry Andric 
23181ad6265SDimitry Andric       Kind = aarch64::PageOffset12;
23281ad6265SDimitry Andric       break;
23381ad6265SDimitry Andric     }
23481ad6265SDimitry Andric     case ELFLdSt16Abs12: {
23581ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
23681ad6265SDimitry Andric       if (!aarch64::isLoadStoreImm12(Instr) ||
23781ad6265SDimitry Andric           aarch64::getPageOffset12Shift(Instr) != 1)
23881ad6265SDimitry Andric         return make_error<JITLinkError>(
23981ad6265SDimitry Andric             "R_AARCH64_LDST16_ABS_LO12_NC target is not a "
24081ad6265SDimitry Andric             "LDRH/STRH (imm12) instruction");
24181ad6265SDimitry Andric 
24281ad6265SDimitry Andric       Kind = aarch64::PageOffset12;
24381ad6265SDimitry Andric       break;
24481ad6265SDimitry Andric     }
24581ad6265SDimitry Andric     case ELFLdSt32Abs12: {
24681ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
24781ad6265SDimitry Andric       if (!aarch64::isLoadStoreImm12(Instr) ||
24881ad6265SDimitry Andric           aarch64::getPageOffset12Shift(Instr) != 2)
24981ad6265SDimitry Andric         return make_error<JITLinkError>(
25081ad6265SDimitry Andric             "R_AARCH64_LDST32_ABS_LO12_NC target is not a "
25181ad6265SDimitry Andric             "LDR/STR (imm12, 32 bit) instruction");
25281ad6265SDimitry Andric 
25381ad6265SDimitry Andric       Kind = aarch64::PageOffset12;
25481ad6265SDimitry Andric       break;
25581ad6265SDimitry Andric     }
25681ad6265SDimitry Andric     case ELFLdSt64Abs12: {
25781ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
25881ad6265SDimitry Andric       if (!aarch64::isLoadStoreImm12(Instr) ||
25981ad6265SDimitry Andric           aarch64::getPageOffset12Shift(Instr) != 3)
26081ad6265SDimitry Andric         return make_error<JITLinkError>(
26181ad6265SDimitry Andric             "R_AARCH64_LDST64_ABS_LO12_NC target is not a "
26281ad6265SDimitry Andric             "LDR/STR (imm12, 64 bit) instruction");
26381ad6265SDimitry Andric 
26481ad6265SDimitry Andric       Kind = aarch64::PageOffset12;
26581ad6265SDimitry Andric       break;
26681ad6265SDimitry Andric     }
26781ad6265SDimitry Andric     case ELFLdSt128Abs12: {
26881ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
26981ad6265SDimitry Andric       if (!aarch64::isLoadStoreImm12(Instr) ||
27081ad6265SDimitry Andric           aarch64::getPageOffset12Shift(Instr) != 4)
27181ad6265SDimitry Andric         return make_error<JITLinkError>(
27281ad6265SDimitry Andric             "R_AARCH64_LDST128_ABS_LO12_NC target is not a "
27381ad6265SDimitry Andric             "LDR/STR (imm12, 128 bit) instruction");
27481ad6265SDimitry Andric 
27581ad6265SDimitry Andric       Kind = aarch64::PageOffset12;
27681ad6265SDimitry Andric       break;
27781ad6265SDimitry Andric     }
27881ad6265SDimitry Andric     case ELFMovwAbsG0: {
27981ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
28081ad6265SDimitry Andric       if (!aarch64::isMoveWideImm16(Instr) ||
28181ad6265SDimitry Andric           aarch64::getMoveWide16Shift(Instr) != 0)
28281ad6265SDimitry Andric         return make_error<JITLinkError>(
28381ad6265SDimitry Andric             "R_AARCH64_MOVW_UABS_G0_NC target is not a "
28481ad6265SDimitry Andric             "MOVK/MOVZ (imm16, LSL #0) instruction");
28581ad6265SDimitry Andric 
28681ad6265SDimitry Andric       Kind = aarch64::MoveWide16;
28781ad6265SDimitry Andric       break;
28881ad6265SDimitry Andric     }
28981ad6265SDimitry Andric     case ELFMovwAbsG1: {
29081ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
29181ad6265SDimitry Andric       if (!aarch64::isMoveWideImm16(Instr) ||
29281ad6265SDimitry Andric           aarch64::getMoveWide16Shift(Instr) != 16)
29381ad6265SDimitry Andric         return make_error<JITLinkError>(
29481ad6265SDimitry Andric             "R_AARCH64_MOVW_UABS_G1_NC target is not a "
29581ad6265SDimitry Andric             "MOVK/MOVZ (imm16, LSL #16) instruction");
29681ad6265SDimitry Andric 
29781ad6265SDimitry Andric       Kind = aarch64::MoveWide16;
29881ad6265SDimitry Andric       break;
29981ad6265SDimitry Andric     }
30081ad6265SDimitry Andric     case ELFMovwAbsG2: {
30181ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
30281ad6265SDimitry Andric       if (!aarch64::isMoveWideImm16(Instr) ||
30381ad6265SDimitry Andric           aarch64::getMoveWide16Shift(Instr) != 32)
30481ad6265SDimitry Andric         return make_error<JITLinkError>(
30581ad6265SDimitry Andric             "R_AARCH64_MOVW_UABS_G2_NC target is not a "
30681ad6265SDimitry Andric             "MOVK/MOVZ (imm16, LSL #32) instruction");
30781ad6265SDimitry Andric 
30881ad6265SDimitry Andric       Kind = aarch64::MoveWide16;
30981ad6265SDimitry Andric       break;
31081ad6265SDimitry Andric     }
31181ad6265SDimitry Andric     case ELFMovwAbsG3: {
31281ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
31381ad6265SDimitry Andric       if (!aarch64::isMoveWideImm16(Instr) ||
31481ad6265SDimitry Andric           aarch64::getMoveWide16Shift(Instr) != 48)
31581ad6265SDimitry Andric         return make_error<JITLinkError>(
31681ad6265SDimitry Andric             "R_AARCH64_MOVW_UABS_G3 target is not a "
31781ad6265SDimitry Andric             "MOVK/MOVZ (imm16, LSL #48) instruction");
31881ad6265SDimitry Andric 
31981ad6265SDimitry Andric       Kind = aarch64::MoveWide16;
32081ad6265SDimitry Andric       break;
32181ad6265SDimitry Andric     }
32206c3fb27SDimitry Andric     case ELFTstBr14: {
32306c3fb27SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
32406c3fb27SDimitry Andric       if (!aarch64::isTestAndBranchImm14(Instr))
32506c3fb27SDimitry Andric         return make_error<JITLinkError>("R_AARCH64_TSTBR14 target is not a "
32606c3fb27SDimitry Andric                                         "test and branch instruction");
32706c3fb27SDimitry Andric 
32806c3fb27SDimitry Andric       Kind = aarch64::TestAndBranch14PCRel;
32906c3fb27SDimitry Andric       break;
33006c3fb27SDimitry Andric     }
33106c3fb27SDimitry Andric     case ELFCondBr19: {
33206c3fb27SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
33306c3fb27SDimitry Andric       if (!aarch64::isCondBranchImm19(Instr) &&
33406c3fb27SDimitry Andric           !aarch64::isCompAndBranchImm19(Instr))
33506c3fb27SDimitry Andric         return make_error<JITLinkError>("R_AARCH64_CONDBR19 target is not a "
33606c3fb27SDimitry Andric                                         "conditional branch instruction");
33706c3fb27SDimitry Andric 
33806c3fb27SDimitry Andric       Kind = aarch64::CondBranch19PCRel;
33906c3fb27SDimitry Andric       break;
34006c3fb27SDimitry Andric     }
34106c3fb27SDimitry Andric     case ELFAbs32: {
34206c3fb27SDimitry Andric       Kind = aarch64::Pointer32;
34306c3fb27SDimitry Andric       break;
34406c3fb27SDimitry Andric     }
34581ad6265SDimitry Andric     case ELFAbs64: {
34681ad6265SDimitry Andric       Kind = aarch64::Pointer64;
34781ad6265SDimitry Andric       break;
34881ad6265SDimitry Andric     }
34981ad6265SDimitry Andric     case ELFPrel32: {
35081ad6265SDimitry Andric       Kind = aarch64::Delta32;
35181ad6265SDimitry Andric       break;
35281ad6265SDimitry Andric     }
35381ad6265SDimitry Andric     case ELFPrel64: {
35481ad6265SDimitry Andric       Kind = aarch64::Delta64;
35581ad6265SDimitry Andric       break;
35681ad6265SDimitry Andric     }
35781ad6265SDimitry Andric     case ELFAdrGOTPage21: {
358bdd1243dSDimitry Andric       Kind = aarch64::RequestGOTAndTransformToPage21;
35981ad6265SDimitry Andric       break;
36081ad6265SDimitry Andric     }
36181ad6265SDimitry Andric     case ELFLd64GOTLo12: {
362bdd1243dSDimitry Andric       Kind = aarch64::RequestGOTAndTransformToPageOffset12;
36381ad6265SDimitry Andric       break;
36481ad6265SDimitry Andric     }
365753f127fSDimitry Andric     case ELFTLSDescAdrPage21: {
366bdd1243dSDimitry Andric       Kind = aarch64::RequestTLSDescEntryAndTransformToPage21;
367753f127fSDimitry Andric       break;
368753f127fSDimitry Andric     }
369bdd1243dSDimitry Andric     case ELFTLSDescAddLo12:
370753f127fSDimitry Andric     case ELFTLSDescLd64Lo12: {
371bdd1243dSDimitry Andric       Kind = aarch64::RequestTLSDescEntryAndTransformToPageOffset12;
372753f127fSDimitry Andric       break;
373753f127fSDimitry Andric     }
374753f127fSDimitry Andric     case ELFTLSDescCall: {
375753f127fSDimitry Andric       return Error::success();
376753f127fSDimitry Andric     }
37781ad6265SDimitry Andric     };
37881ad6265SDimitry Andric 
37981ad6265SDimitry Andric     Edge GE(Kind, Offset, *GraphSymbol, Addend);
380349cc55cSDimitry Andric     LLVM_DEBUG({
381349cc55cSDimitry Andric       dbgs() << "    ";
38281ad6265SDimitry Andric       printEdge(dbgs(), BlockToFix, GE, aarch64::getEdgeKindName(Kind));
383349cc55cSDimitry Andric       dbgs() << "\n";
384349cc55cSDimitry Andric     });
385349cc55cSDimitry Andric 
38604eeddc0SDimitry Andric     BlockToFix.addEdge(std::move(GE));
387753f127fSDimitry Andric 
388349cc55cSDimitry Andric     return Error::success();
389349cc55cSDimitry Andric   }
390349cc55cSDimitry Andric 
39181ad6265SDimitry Andric   /// Return the string name of the given ELF aarch64 edge kind.
39281ad6265SDimitry Andric   const char *getELFAArch64RelocationKindName(Edge::Kind R) {
39381ad6265SDimitry Andric     switch (R) {
39481ad6265SDimitry Andric     case ELFCall26:
39581ad6265SDimitry Andric       return "ELFCall26";
39681ad6265SDimitry Andric     case ELFAdrPage21:
39781ad6265SDimitry Andric       return "ELFAdrPage21";
39881ad6265SDimitry Andric     case ELFAddAbs12:
39981ad6265SDimitry Andric       return "ELFAddAbs12";
40081ad6265SDimitry Andric     case ELFLdSt8Abs12:
40181ad6265SDimitry Andric       return "ELFLdSt8Abs12";
40281ad6265SDimitry Andric     case ELFLdSt16Abs12:
40381ad6265SDimitry Andric       return "ELFLdSt16Abs12";
40481ad6265SDimitry Andric     case ELFLdSt32Abs12:
40581ad6265SDimitry Andric       return "ELFLdSt32Abs12";
40681ad6265SDimitry Andric     case ELFLdSt64Abs12:
40781ad6265SDimitry Andric       return "ELFLdSt64Abs12";
40881ad6265SDimitry Andric     case ELFLdSt128Abs12:
40981ad6265SDimitry Andric       return "ELFLdSt128Abs12";
41081ad6265SDimitry Andric     case ELFMovwAbsG0:
41181ad6265SDimitry Andric       return "ELFMovwAbsG0";
41281ad6265SDimitry Andric     case ELFMovwAbsG1:
41381ad6265SDimitry Andric       return "ELFMovwAbsG1";
41481ad6265SDimitry Andric     case ELFMovwAbsG2:
41581ad6265SDimitry Andric       return "ELFMovwAbsG2";
41681ad6265SDimitry Andric     case ELFMovwAbsG3:
41781ad6265SDimitry Andric       return "ELFMovwAbsG3";
41806c3fb27SDimitry Andric     case ELFAbs32:
41906c3fb27SDimitry Andric       return "ELFAbs32";
42081ad6265SDimitry Andric     case ELFAbs64:
42181ad6265SDimitry Andric       return "ELFAbs64";
42281ad6265SDimitry Andric     case ELFPrel32:
42381ad6265SDimitry Andric       return "ELFPrel32";
42481ad6265SDimitry Andric     case ELFPrel64:
42581ad6265SDimitry Andric       return "ELFPrel64";
42681ad6265SDimitry Andric     case ELFAdrGOTPage21:
42781ad6265SDimitry Andric       return "ELFAdrGOTPage21";
42881ad6265SDimitry Andric     case ELFLd64GOTLo12:
42981ad6265SDimitry Andric       return "ELFLd64GOTLo12";
430753f127fSDimitry Andric     case ELFTLSDescAdrPage21:
431753f127fSDimitry Andric       return "ELFTLSDescAdrPage21";
432753f127fSDimitry Andric     case ELFTLSDescAddLo12:
433753f127fSDimitry Andric       return "ELFTLSDescAddLo12";
434753f127fSDimitry Andric     case ELFTLSDescLd64Lo12:
435753f127fSDimitry Andric       return "ELFTLSDescLd64Lo12";
436753f127fSDimitry Andric     case ELFTLSDescCall:
437753f127fSDimitry Andric       return "ELFTLSDescCall";
43881ad6265SDimitry Andric     default:
43981ad6265SDimitry Andric       return getGenericEdgeKindName(static_cast<Edge::Kind>(R));
44081ad6265SDimitry Andric     }
44181ad6265SDimitry Andric   }
44281ad6265SDimitry Andric 
443349cc55cSDimitry Andric public:
444349cc55cSDimitry Andric   ELFLinkGraphBuilder_aarch64(StringRef FileName,
44506c3fb27SDimitry Andric                               const object::ELFFile<ELFT> &Obj, Triple TT,
44606c3fb27SDimitry Andric                               SubtargetFeatures Features)
44706c3fb27SDimitry Andric       : ELFLinkGraphBuilder<ELFT>(Obj, std::move(TT), std::move(Features),
44806c3fb27SDimitry Andric                                   FileName, aarch64::getEdgeKindName) {}
449349cc55cSDimitry Andric };
450349cc55cSDimitry Andric 
451753f127fSDimitry Andric // TLS Info Builder.
452753f127fSDimitry Andric class TLSInfoTableManager_ELF_aarch64
453753f127fSDimitry Andric     : public TableManager<TLSInfoTableManager_ELF_aarch64> {
454753f127fSDimitry Andric public:
455753f127fSDimitry Andric   static StringRef getSectionName() { return "$__TLSINFO"; }
456753f127fSDimitry Andric 
457753f127fSDimitry Andric   static const uint8_t TLSInfoEntryContent[16];
458753f127fSDimitry Andric 
459753f127fSDimitry Andric   bool visitEdge(LinkGraph &G, Block *B, Edge &E) { return false; }
460753f127fSDimitry Andric 
461753f127fSDimitry Andric   Symbol &createEntry(LinkGraph &G, Symbol &Target) {
462753f127fSDimitry Andric     // the TLS Info entry's key value will be written by the fixTLVSectionByName
463753f127fSDimitry Andric     // pass, so create mutable content.
464753f127fSDimitry Andric     auto &TLSInfoEntry = G.createMutableContentBlock(
465753f127fSDimitry Andric         getTLSInfoSection(G), G.allocateContent(getTLSInfoEntryContent()),
466753f127fSDimitry Andric         orc::ExecutorAddr(), 8, 0);
467753f127fSDimitry Andric     TLSInfoEntry.addEdge(aarch64::Pointer64, 8, Target, 0);
468753f127fSDimitry Andric     return G.addAnonymousSymbol(TLSInfoEntry, 0, 16, false, false);
469753f127fSDimitry Andric   }
470753f127fSDimitry Andric 
471753f127fSDimitry Andric private:
472753f127fSDimitry Andric   Section &getTLSInfoSection(LinkGraph &G) {
473753f127fSDimitry Andric     if (!TLSInfoTable)
474bdd1243dSDimitry Andric       TLSInfoTable = &G.createSection(getSectionName(), orc::MemProt::Read);
475753f127fSDimitry Andric     return *TLSInfoTable;
476753f127fSDimitry Andric   }
477753f127fSDimitry Andric 
478753f127fSDimitry Andric   ArrayRef<char> getTLSInfoEntryContent() const {
479753f127fSDimitry Andric     return {reinterpret_cast<const char *>(TLSInfoEntryContent),
480753f127fSDimitry Andric             sizeof(TLSInfoEntryContent)};
481753f127fSDimitry Andric   }
482753f127fSDimitry Andric 
483753f127fSDimitry Andric   Section *TLSInfoTable = nullptr;
484753f127fSDimitry Andric };
485753f127fSDimitry Andric 
486753f127fSDimitry Andric const uint8_t TLSInfoTableManager_ELF_aarch64::TLSInfoEntryContent[16] = {
487753f127fSDimitry Andric     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*pthread key */
488753f127fSDimitry Andric     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  /*data address*/
489753f127fSDimitry Andric };
490753f127fSDimitry Andric 
491753f127fSDimitry Andric // TLS Descriptor Builder.
492753f127fSDimitry Andric class TLSDescTableManager_ELF_aarch64
493753f127fSDimitry Andric     : public TableManager<TLSDescTableManager_ELF_aarch64> {
494753f127fSDimitry Andric public:
495753f127fSDimitry Andric   TLSDescTableManager_ELF_aarch64(
496753f127fSDimitry Andric       TLSInfoTableManager_ELF_aarch64 &TLSInfoTableManager)
497753f127fSDimitry Andric       : TLSInfoTableManager(TLSInfoTableManager) {}
498753f127fSDimitry Andric 
499753f127fSDimitry Andric   static StringRef getSectionName() { return "$__TLSDESC"; }
500753f127fSDimitry Andric 
501753f127fSDimitry Andric   static const uint8_t TLSDescEntryContent[16];
502753f127fSDimitry Andric 
503753f127fSDimitry Andric   bool visitEdge(LinkGraph &G, Block *B, Edge &E) {
504753f127fSDimitry Andric     Edge::Kind KindToSet = Edge::Invalid;
505753f127fSDimitry Andric     switch (E.getKind()) {
506bdd1243dSDimitry Andric     case aarch64::RequestTLSDescEntryAndTransformToPage21: {
507753f127fSDimitry Andric       KindToSet = aarch64::Page21;
508753f127fSDimitry Andric       break;
509753f127fSDimitry Andric     }
510bdd1243dSDimitry Andric     case aarch64::RequestTLSDescEntryAndTransformToPageOffset12: {
511753f127fSDimitry Andric       KindToSet = aarch64::PageOffset12;
512753f127fSDimitry Andric       break;
513753f127fSDimitry Andric     }
514753f127fSDimitry Andric     default:
515753f127fSDimitry Andric       return false;
516753f127fSDimitry Andric     }
517753f127fSDimitry Andric     assert(KindToSet != Edge::Invalid &&
518753f127fSDimitry Andric            "Fell through switch, but no new kind to set");
519753f127fSDimitry Andric     DEBUG_WITH_TYPE("jitlink", {
520753f127fSDimitry Andric       dbgs() << "  Fixing " << G.getEdgeKindName(E.getKind()) << " edge at "
521753f127fSDimitry Andric              << B->getFixupAddress(E) << " (" << B->getAddress() << " + "
522753f127fSDimitry Andric              << formatv("{0:x}", E.getOffset()) << ")\n";
523753f127fSDimitry Andric     });
524753f127fSDimitry Andric     E.setKind(KindToSet);
525753f127fSDimitry Andric     E.setTarget(getEntryForTarget(G, E.getTarget()));
526753f127fSDimitry Andric     return true;
527753f127fSDimitry Andric   }
528753f127fSDimitry Andric 
529753f127fSDimitry Andric   Symbol &createEntry(LinkGraph &G, Symbol &Target) {
530753f127fSDimitry Andric     auto &EntryBlock =
531753f127fSDimitry Andric         G.createContentBlock(getTLSDescSection(G), getTLSDescBlockContent(),
532753f127fSDimitry Andric                              orc::ExecutorAddr(), 8, 0);
533753f127fSDimitry Andric     EntryBlock.addEdge(aarch64::Pointer64, 0, getTLSDescResolver(G), 0);
534753f127fSDimitry Andric     EntryBlock.addEdge(aarch64::Pointer64, 8,
535753f127fSDimitry Andric                        TLSInfoTableManager.getEntryForTarget(G, Target), 0);
536753f127fSDimitry Andric     return G.addAnonymousSymbol(EntryBlock, 0, 8, false, false);
537753f127fSDimitry Andric   }
538753f127fSDimitry Andric 
539753f127fSDimitry Andric private:
540753f127fSDimitry Andric   Section &getTLSDescSection(LinkGraph &G) {
541753f127fSDimitry Andric     if (!GOTSection)
542bdd1243dSDimitry Andric       GOTSection = &G.createSection(getSectionName(), orc::MemProt::Read);
543753f127fSDimitry Andric     return *GOTSection;
544753f127fSDimitry Andric   }
545753f127fSDimitry Andric 
546753f127fSDimitry Andric   Symbol &getTLSDescResolver(LinkGraph &G) {
547753f127fSDimitry Andric     if (!TLSDescResolver)
548bdd1243dSDimitry Andric       TLSDescResolver = &G.addExternalSymbol("__tlsdesc_resolver", 8, false);
549753f127fSDimitry Andric     return *TLSDescResolver;
550753f127fSDimitry Andric   }
551753f127fSDimitry Andric 
552753f127fSDimitry Andric   ArrayRef<char> getTLSDescBlockContent() {
553753f127fSDimitry Andric     return {reinterpret_cast<const char *>(TLSDescEntryContent),
554753f127fSDimitry Andric             sizeof(TLSDescEntryContent)};
555753f127fSDimitry Andric   }
556753f127fSDimitry Andric 
557753f127fSDimitry Andric   Section *GOTSection = nullptr;
558753f127fSDimitry Andric   Symbol *TLSDescResolver = nullptr;
559753f127fSDimitry Andric   TLSInfoTableManager_ELF_aarch64 &TLSInfoTableManager;
560753f127fSDimitry Andric };
561753f127fSDimitry Andric 
562753f127fSDimitry Andric const uint8_t TLSDescTableManager_ELF_aarch64::TLSDescEntryContent[16] = {
563753f127fSDimitry Andric     0x00, 0x00, 0x00, 0x00,
564753f127fSDimitry Andric     0x00, 0x00, 0x00, 0x00, /*resolver function pointer*/
565753f127fSDimitry Andric     0x00, 0x00, 0x00, 0x00,
566753f127fSDimitry Andric     0x00, 0x00, 0x00, 0x00 /*pointer to tls info*/
567753f127fSDimitry Andric };
568753f127fSDimitry Andric 
56981ad6265SDimitry Andric Error buildTables_ELF_aarch64(LinkGraph &G) {
57081ad6265SDimitry Andric   LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");
57181ad6265SDimitry Andric 
57281ad6265SDimitry Andric   aarch64::GOTTableManager GOT;
57381ad6265SDimitry Andric   aarch64::PLTTableManager PLT(GOT);
574753f127fSDimitry Andric   TLSInfoTableManager_ELF_aarch64 TLSInfo;
575753f127fSDimitry Andric   TLSDescTableManager_ELF_aarch64 TLSDesc(TLSInfo);
576753f127fSDimitry Andric   visitExistingEdges(G, GOT, PLT, TLSDesc, TLSInfo);
57781ad6265SDimitry Andric   return Error::success();
57881ad6265SDimitry Andric }
57981ad6265SDimitry Andric 
58081ad6265SDimitry Andric } // namespace
58181ad6265SDimitry Andric 
58281ad6265SDimitry Andric namespace llvm {
58381ad6265SDimitry Andric namespace jitlink {
58481ad6265SDimitry Andric 
585349cc55cSDimitry Andric Expected<std::unique_ptr<LinkGraph>>
586349cc55cSDimitry Andric createLinkGraphFromELFObject_aarch64(MemoryBufferRef ObjectBuffer) {
587349cc55cSDimitry Andric   LLVM_DEBUG({
588349cc55cSDimitry Andric     dbgs() << "Building jitlink graph for new input "
589349cc55cSDimitry Andric            << ObjectBuffer.getBufferIdentifier() << "...\n";
590349cc55cSDimitry Andric   });
591349cc55cSDimitry Andric 
592349cc55cSDimitry Andric   auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer);
593349cc55cSDimitry Andric   if (!ELFObj)
594349cc55cSDimitry Andric     return ELFObj.takeError();
595349cc55cSDimitry Andric 
59606c3fb27SDimitry Andric   auto Features = (*ELFObj)->getFeatures();
59706c3fb27SDimitry Andric   if (!Features)
59806c3fb27SDimitry Andric     return Features.takeError();
59906c3fb27SDimitry Andric 
600349cc55cSDimitry Andric   assert((*ELFObj)->getArch() == Triple::aarch64 &&
601349cc55cSDimitry Andric          "Only AArch64 (little endian) is supported for now");
602349cc55cSDimitry Andric 
603349cc55cSDimitry Andric   auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
60406c3fb27SDimitry Andric   return ELFLinkGraphBuilder_aarch64<object::ELF64LE>(
60506c3fb27SDimitry Andric              (*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
60606c3fb27SDimitry Andric              (*ELFObj)->makeTriple(), std::move(*Features))
607349cc55cSDimitry Andric       .buildGraph();
608349cc55cSDimitry Andric }
609349cc55cSDimitry Andric 
610349cc55cSDimitry Andric void link_ELF_aarch64(std::unique_ptr<LinkGraph> G,
611349cc55cSDimitry Andric                       std::unique_ptr<JITLinkContext> Ctx) {
612349cc55cSDimitry Andric   PassConfiguration Config;
613349cc55cSDimitry Andric   const Triple &TT = G->getTargetTriple();
614349cc55cSDimitry Andric   if (Ctx->shouldAddDefaultTargetPasses(TT)) {
6155f757f3fSDimitry Andric     // Add eh-frame passes.
61681ad6265SDimitry Andric     Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame"));
61781ad6265SDimitry Andric     Config.PrePrunePasses.push_back(EHFrameEdgeFixer(
61881ad6265SDimitry Andric         ".eh_frame", 8, aarch64::Pointer32, aarch64::Pointer64,
61981ad6265SDimitry Andric         aarch64::Delta32, aarch64::Delta64, aarch64::NegDelta32));
6201ac55f4cSDimitry Andric     Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame"));
62181ad6265SDimitry Andric 
62281ad6265SDimitry Andric     // Add a mark-live pass.
623349cc55cSDimitry Andric     if (auto MarkLive = Ctx->getMarkLivePass(TT))
624349cc55cSDimitry Andric       Config.PrePrunePasses.push_back(std::move(MarkLive));
625349cc55cSDimitry Andric     else
626349cc55cSDimitry Andric       Config.PrePrunePasses.push_back(markAllSymbolsLive);
62781ad6265SDimitry Andric 
628*0fca6ea1SDimitry Andric     // Resolve any external section start / end symbols.
629*0fca6ea1SDimitry Andric     Config.PostAllocationPasses.push_back(
630*0fca6ea1SDimitry Andric         createDefineExternalSectionStartAndEndSymbolsPass(
631*0fca6ea1SDimitry Andric             identifyELFSectionStartAndEndSymbols));
632*0fca6ea1SDimitry Andric 
633753f127fSDimitry Andric     // Add an in-place GOT/TLS/Stubs build pass.
63481ad6265SDimitry Andric     Config.PostPrunePasses.push_back(buildTables_ELF_aarch64);
635349cc55cSDimitry Andric   }
63681ad6265SDimitry Andric 
637349cc55cSDimitry Andric   if (auto Err = Ctx->modifyPassConfig(*G, Config))
638349cc55cSDimitry Andric     return Ctx->notifyFailed(std::move(Err));
639349cc55cSDimitry Andric 
640349cc55cSDimitry Andric   ELFJITLinker_aarch64::link(std::move(Ctx), std::move(G), std::move(Config));
641349cc55cSDimitry Andric }
642349cc55cSDimitry Andric 
643349cc55cSDimitry Andric } // namespace jitlink
644349cc55cSDimitry Andric } // namespace llvm
645