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:
ELFJITLinker_aarch64(std::unique_ptr<JITLinkContext> Ctx,std::unique_ptr<LinkGraph> G,PassConfiguration PassConfig)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:
applyFixup(LinkGraph & G,Block & B,const Edge & E) const40349cc55cSDimitry 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,
5006c3fb27SDimitry Andric     ELFAdrLo21,
5181ad6265SDimitry Andric     ELFAdrPage21,
5281ad6265SDimitry Andric     ELFAddAbs12,
5381ad6265SDimitry Andric     ELFLdSt8Abs12,
5481ad6265SDimitry Andric     ELFLdSt16Abs12,
5581ad6265SDimitry Andric     ELFLdSt32Abs12,
5681ad6265SDimitry Andric     ELFLdSt64Abs12,
5781ad6265SDimitry Andric     ELFLdSt128Abs12,
5881ad6265SDimitry Andric     ELFMovwAbsG0,
5981ad6265SDimitry Andric     ELFMovwAbsG1,
6081ad6265SDimitry Andric     ELFMovwAbsG2,
6181ad6265SDimitry Andric     ELFMovwAbsG3,
6206c3fb27SDimitry Andric     ELFTstBr14,
6306c3fb27SDimitry Andric     ELFCondBr19,
6406c3fb27SDimitry Andric     ELFAbs32,
6581ad6265SDimitry Andric     ELFAbs64,
6681ad6265SDimitry Andric     ELFPrel32,
6781ad6265SDimitry Andric     ELFPrel64,
6881ad6265SDimitry Andric     ELFAdrGOTPage21,
6981ad6265SDimitry Andric     ELFLd64GOTLo12,
70753f127fSDimitry Andric     ELFTLSDescAdrPage21,
71753f127fSDimitry Andric     ELFTLSDescAddLo12,
72753f127fSDimitry Andric     ELFTLSDescLd64Lo12,
73753f127fSDimitry Andric     ELFTLSDescCall,
7481ad6265SDimitry Andric   };
7581ad6265SDimitry Andric 
7681ad6265SDimitry Andric   static Expected<ELFAArch64RelocationKind>
getRelocationKind(const uint32_t Type)77349cc55cSDimitry Andric   getRelocationKind(const uint32_t Type) {
78349cc55cSDimitry Andric     using namespace aarch64;
79349cc55cSDimitry Andric     switch (Type) {
80349cc55cSDimitry Andric     case ELF::R_AARCH64_CALL26:
8181ad6265SDimitry Andric     case ELF::R_AARCH64_JUMP26:
8281ad6265SDimitry Andric       return ELFCall26;
8306c3fb27SDimitry Andric     case ELF::R_AARCH64_ADR_PREL_LO21:
8406c3fb27SDimitry Andric       return ELFAdrLo21;
8581ad6265SDimitry Andric     case ELF::R_AARCH64_ADR_PREL_PG_HI21:
8681ad6265SDimitry Andric       return ELFAdrPage21;
8781ad6265SDimitry Andric     case ELF::R_AARCH64_ADD_ABS_LO12_NC:
8881ad6265SDimitry Andric       return ELFAddAbs12;
8981ad6265SDimitry Andric     case ELF::R_AARCH64_LDST8_ABS_LO12_NC:
9081ad6265SDimitry Andric       return ELFLdSt8Abs12;
9181ad6265SDimitry Andric     case ELF::R_AARCH64_LDST16_ABS_LO12_NC:
9281ad6265SDimitry Andric       return ELFLdSt16Abs12;
9381ad6265SDimitry Andric     case ELF::R_AARCH64_LDST32_ABS_LO12_NC:
9481ad6265SDimitry Andric       return ELFLdSt32Abs12;
9581ad6265SDimitry Andric     case ELF::R_AARCH64_LDST64_ABS_LO12_NC:
9681ad6265SDimitry Andric       return ELFLdSt64Abs12;
9781ad6265SDimitry Andric     case ELF::R_AARCH64_LDST128_ABS_LO12_NC:
9881ad6265SDimitry Andric       return ELFLdSt128Abs12;
9981ad6265SDimitry Andric     case ELF::R_AARCH64_MOVW_UABS_G0_NC:
10081ad6265SDimitry Andric       return ELFMovwAbsG0;
10181ad6265SDimitry Andric     case ELF::R_AARCH64_MOVW_UABS_G1_NC:
10281ad6265SDimitry Andric       return ELFMovwAbsG1;
10381ad6265SDimitry Andric     case ELF::R_AARCH64_MOVW_UABS_G2_NC:
10481ad6265SDimitry Andric       return ELFMovwAbsG2;
10581ad6265SDimitry Andric     case ELF::R_AARCH64_MOVW_UABS_G3:
10681ad6265SDimitry Andric       return ELFMovwAbsG3;
10706c3fb27SDimitry Andric     case ELF::R_AARCH64_TSTBR14:
10806c3fb27SDimitry Andric       return ELFTstBr14;
10906c3fb27SDimitry Andric     case ELF::R_AARCH64_CONDBR19:
11006c3fb27SDimitry Andric       return ELFCondBr19;
11106c3fb27SDimitry Andric     case ELF::R_AARCH64_ABS32:
11206c3fb27SDimitry Andric       return ELFAbs32;
11381ad6265SDimitry Andric     case ELF::R_AARCH64_ABS64:
11481ad6265SDimitry Andric       return ELFAbs64;
11581ad6265SDimitry Andric     case ELF::R_AARCH64_PREL32:
11681ad6265SDimitry Andric       return ELFPrel32;
11781ad6265SDimitry Andric     case ELF::R_AARCH64_PREL64:
11881ad6265SDimitry Andric       return ELFPrel64;
11981ad6265SDimitry Andric     case ELF::R_AARCH64_ADR_GOT_PAGE:
12081ad6265SDimitry Andric       return ELFAdrGOTPage21;
12181ad6265SDimitry Andric     case ELF::R_AARCH64_LD64_GOT_LO12_NC:
12281ad6265SDimitry Andric       return ELFLd64GOTLo12;
123753f127fSDimitry Andric     case ELF::R_AARCH64_TLSDESC_ADR_PAGE21:
124753f127fSDimitry Andric       return ELFTLSDescAdrPage21;
125753f127fSDimitry Andric     case ELF::R_AARCH64_TLSDESC_ADD_LO12:
126753f127fSDimitry Andric       return ELFTLSDescAddLo12;
127753f127fSDimitry Andric     case ELF::R_AARCH64_TLSDESC_LD64_LO12:
128753f127fSDimitry Andric       return ELFTLSDescLd64Lo12;
129753f127fSDimitry Andric     case ELF::R_AARCH64_TLSDESC_CALL:
130753f127fSDimitry Andric       return ELFTLSDescCall;
131349cc55cSDimitry Andric     }
132349cc55cSDimitry Andric 
13381ad6265SDimitry Andric     return make_error<JITLinkError>(
13481ad6265SDimitry Andric         "Unsupported aarch64 relocation:" + formatv("{0:d}: ", Type) +
13581ad6265SDimitry Andric         object::getELFRelocationTypeName(ELF::EM_AARCH64, Type));
136349cc55cSDimitry Andric   }
137349cc55cSDimitry Andric 
addRelocations()138349cc55cSDimitry Andric   Error addRelocations() override {
139349cc55cSDimitry Andric     LLVM_DEBUG(dbgs() << "Processing relocations:\n");
140349cc55cSDimitry Andric 
141349cc55cSDimitry Andric     using Base = ELFLinkGraphBuilder<ELFT>;
142349cc55cSDimitry Andric     using Self = ELFLinkGraphBuilder_aarch64<ELFT>;
143349cc55cSDimitry Andric     for (const auto &RelSect : Base::Sections)
144bdd1243dSDimitry Andric       if (Error Err = Base::forEachRelaRelocation(RelSect, this,
145349cc55cSDimitry Andric                                                   &Self::addSingleRelocation))
146349cc55cSDimitry Andric         return Err;
147349cc55cSDimitry Andric 
148349cc55cSDimitry Andric     return Error::success();
149349cc55cSDimitry Andric   }
150349cc55cSDimitry Andric 
addSingleRelocation(const typename ELFT::Rela & Rel,const typename ELFT::Shdr & FixupSect,Block & BlockToFix)151349cc55cSDimitry Andric   Error addSingleRelocation(const typename ELFT::Rela &Rel,
152349cc55cSDimitry Andric                             const typename ELFT::Shdr &FixupSect,
15304eeddc0SDimitry Andric                             Block &BlockToFix) {
15481ad6265SDimitry Andric     using support::ulittle32_t;
155349cc55cSDimitry Andric     using Base = ELFLinkGraphBuilder<ELFT>;
156349cc55cSDimitry Andric 
157349cc55cSDimitry Andric     uint32_t SymbolIndex = Rel.getSymbol(false);
158349cc55cSDimitry Andric     auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);
159349cc55cSDimitry Andric     if (!ObjSymbol)
160349cc55cSDimitry Andric       return ObjSymbol.takeError();
161349cc55cSDimitry Andric 
162349cc55cSDimitry Andric     Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex);
163349cc55cSDimitry Andric     if (!GraphSymbol)
164349cc55cSDimitry Andric       return make_error<StringError>(
165349cc55cSDimitry Andric           formatv("Could not find symbol at given index, did you add it to "
166349cc55cSDimitry Andric                   "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",
167349cc55cSDimitry Andric                   SymbolIndex, (*ObjSymbol)->st_shndx,
168349cc55cSDimitry Andric                   Base::GraphSymbols.size()),
169349cc55cSDimitry Andric           inconvertibleErrorCode());
170349cc55cSDimitry Andric 
171349cc55cSDimitry Andric     uint32_t Type = Rel.getType(false);
17281ad6265SDimitry Andric     Expected<ELFAArch64RelocationKind> RelocKind = getRelocationKind(Type);
17381ad6265SDimitry Andric     if (!RelocKind)
17481ad6265SDimitry Andric       return RelocKind.takeError();
175349cc55cSDimitry Andric 
176349cc55cSDimitry Andric     int64_t Addend = Rel.r_addend;
17704eeddc0SDimitry Andric     orc::ExecutorAddr FixupAddress =
17804eeddc0SDimitry Andric         orc::ExecutorAddr(FixupSect.sh_addr) + Rel.r_offset;
17904eeddc0SDimitry Andric     Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();
18081ad6265SDimitry Andric 
18181ad6265SDimitry Andric     // Get a pointer to the fixup content.
18281ad6265SDimitry Andric     const void *FixupContent = BlockToFix.getContent().data() +
18381ad6265SDimitry Andric                                (FixupAddress - BlockToFix.getAddress());
18481ad6265SDimitry Andric 
18581ad6265SDimitry Andric     Edge::Kind Kind = Edge::Invalid;
18681ad6265SDimitry Andric 
18781ad6265SDimitry Andric     switch (*RelocKind) {
18881ad6265SDimitry Andric     case ELFCall26: {
189bdd1243dSDimitry Andric       Kind = aarch64::Branch26PCRel;
19081ad6265SDimitry Andric       break;
19181ad6265SDimitry Andric     }
19206c3fb27SDimitry Andric     case ELFAdrLo21: {
19306c3fb27SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
19406c3fb27SDimitry Andric       if (!aarch64::isADR(Instr))
19506c3fb27SDimitry Andric         return make_error<JITLinkError>(
19606c3fb27SDimitry Andric             "R_AARCH64_ADR_PREL_LO21 target is not an ADR instruction");
19706c3fb27SDimitry Andric 
19806c3fb27SDimitry Andric       Kind = aarch64::ADRLiteral21;
19906c3fb27SDimitry Andric       break;
20006c3fb27SDimitry Andric     }
20181ad6265SDimitry Andric     case ELFAdrPage21: {
20281ad6265SDimitry Andric       Kind = aarch64::Page21;
20381ad6265SDimitry Andric       break;
20481ad6265SDimitry Andric     }
20581ad6265SDimitry Andric     case ELFAddAbs12: {
20681ad6265SDimitry Andric       Kind = aarch64::PageOffset12;
20781ad6265SDimitry Andric       break;
20881ad6265SDimitry Andric     }
20981ad6265SDimitry Andric     case ELFLdSt8Abs12: {
21081ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
21181ad6265SDimitry Andric       if (!aarch64::isLoadStoreImm12(Instr) ||
21281ad6265SDimitry Andric           aarch64::getPageOffset12Shift(Instr) != 0)
21381ad6265SDimitry Andric         return make_error<JITLinkError>(
21481ad6265SDimitry Andric             "R_AARCH64_LDST8_ABS_LO12_NC target is not a "
21581ad6265SDimitry Andric             "LDRB/STRB (imm12) instruction");
21681ad6265SDimitry Andric 
21781ad6265SDimitry Andric       Kind = aarch64::PageOffset12;
21881ad6265SDimitry Andric       break;
21981ad6265SDimitry Andric     }
22081ad6265SDimitry Andric     case ELFLdSt16Abs12: {
22181ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
22281ad6265SDimitry Andric       if (!aarch64::isLoadStoreImm12(Instr) ||
22381ad6265SDimitry Andric           aarch64::getPageOffset12Shift(Instr) != 1)
22481ad6265SDimitry Andric         return make_error<JITLinkError>(
22581ad6265SDimitry Andric             "R_AARCH64_LDST16_ABS_LO12_NC target is not a "
22681ad6265SDimitry Andric             "LDRH/STRH (imm12) instruction");
22781ad6265SDimitry Andric 
22881ad6265SDimitry Andric       Kind = aarch64::PageOffset12;
22981ad6265SDimitry Andric       break;
23081ad6265SDimitry Andric     }
23181ad6265SDimitry Andric     case ELFLdSt32Abs12: {
23281ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
23381ad6265SDimitry Andric       if (!aarch64::isLoadStoreImm12(Instr) ||
23481ad6265SDimitry Andric           aarch64::getPageOffset12Shift(Instr) != 2)
23581ad6265SDimitry Andric         return make_error<JITLinkError>(
23681ad6265SDimitry Andric             "R_AARCH64_LDST32_ABS_LO12_NC target is not a "
23781ad6265SDimitry Andric             "LDR/STR (imm12, 32 bit) instruction");
23881ad6265SDimitry Andric 
23981ad6265SDimitry Andric       Kind = aarch64::PageOffset12;
24081ad6265SDimitry Andric       break;
24181ad6265SDimitry Andric     }
24281ad6265SDimitry Andric     case ELFLdSt64Abs12: {
24381ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
24481ad6265SDimitry Andric       if (!aarch64::isLoadStoreImm12(Instr) ||
24581ad6265SDimitry Andric           aarch64::getPageOffset12Shift(Instr) != 3)
24681ad6265SDimitry Andric         return make_error<JITLinkError>(
24781ad6265SDimitry Andric             "R_AARCH64_LDST64_ABS_LO12_NC target is not a "
24881ad6265SDimitry Andric             "LDR/STR (imm12, 64 bit) instruction");
24981ad6265SDimitry Andric 
25081ad6265SDimitry Andric       Kind = aarch64::PageOffset12;
25181ad6265SDimitry Andric       break;
25281ad6265SDimitry Andric     }
25381ad6265SDimitry Andric     case ELFLdSt128Abs12: {
25481ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
25581ad6265SDimitry Andric       if (!aarch64::isLoadStoreImm12(Instr) ||
25681ad6265SDimitry Andric           aarch64::getPageOffset12Shift(Instr) != 4)
25781ad6265SDimitry Andric         return make_error<JITLinkError>(
25881ad6265SDimitry Andric             "R_AARCH64_LDST128_ABS_LO12_NC target is not a "
25981ad6265SDimitry Andric             "LDR/STR (imm12, 128 bit) instruction");
26081ad6265SDimitry Andric 
26181ad6265SDimitry Andric       Kind = aarch64::PageOffset12;
26281ad6265SDimitry Andric       break;
26381ad6265SDimitry Andric     }
26481ad6265SDimitry Andric     case ELFMovwAbsG0: {
26581ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
26681ad6265SDimitry Andric       if (!aarch64::isMoveWideImm16(Instr) ||
26781ad6265SDimitry Andric           aarch64::getMoveWide16Shift(Instr) != 0)
26881ad6265SDimitry Andric         return make_error<JITLinkError>(
26981ad6265SDimitry Andric             "R_AARCH64_MOVW_UABS_G0_NC target is not a "
27081ad6265SDimitry Andric             "MOVK/MOVZ (imm16, LSL #0) instruction");
27181ad6265SDimitry Andric 
27281ad6265SDimitry Andric       Kind = aarch64::MoveWide16;
27381ad6265SDimitry Andric       break;
27481ad6265SDimitry Andric     }
27581ad6265SDimitry Andric     case ELFMovwAbsG1: {
27681ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
27781ad6265SDimitry Andric       if (!aarch64::isMoveWideImm16(Instr) ||
27881ad6265SDimitry Andric           aarch64::getMoveWide16Shift(Instr) != 16)
27981ad6265SDimitry Andric         return make_error<JITLinkError>(
28081ad6265SDimitry Andric             "R_AARCH64_MOVW_UABS_G1_NC target is not a "
28181ad6265SDimitry Andric             "MOVK/MOVZ (imm16, LSL #16) instruction");
28281ad6265SDimitry Andric 
28381ad6265SDimitry Andric       Kind = aarch64::MoveWide16;
28481ad6265SDimitry Andric       break;
28581ad6265SDimitry Andric     }
28681ad6265SDimitry Andric     case ELFMovwAbsG2: {
28781ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
28881ad6265SDimitry Andric       if (!aarch64::isMoveWideImm16(Instr) ||
28981ad6265SDimitry Andric           aarch64::getMoveWide16Shift(Instr) != 32)
29081ad6265SDimitry Andric         return make_error<JITLinkError>(
29181ad6265SDimitry Andric             "R_AARCH64_MOVW_UABS_G2_NC target is not a "
29281ad6265SDimitry Andric             "MOVK/MOVZ (imm16, LSL #32) instruction");
29381ad6265SDimitry Andric 
29481ad6265SDimitry Andric       Kind = aarch64::MoveWide16;
29581ad6265SDimitry Andric       break;
29681ad6265SDimitry Andric     }
29781ad6265SDimitry Andric     case ELFMovwAbsG3: {
29881ad6265SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
29981ad6265SDimitry Andric       if (!aarch64::isMoveWideImm16(Instr) ||
30081ad6265SDimitry Andric           aarch64::getMoveWide16Shift(Instr) != 48)
30181ad6265SDimitry Andric         return make_error<JITLinkError>(
30281ad6265SDimitry Andric             "R_AARCH64_MOVW_UABS_G3 target is not a "
30381ad6265SDimitry Andric             "MOVK/MOVZ (imm16, LSL #48) instruction");
30481ad6265SDimitry Andric 
30581ad6265SDimitry Andric       Kind = aarch64::MoveWide16;
30681ad6265SDimitry Andric       break;
30781ad6265SDimitry Andric     }
30806c3fb27SDimitry Andric     case ELFTstBr14: {
30906c3fb27SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
31006c3fb27SDimitry Andric       if (!aarch64::isTestAndBranchImm14(Instr))
31106c3fb27SDimitry Andric         return make_error<JITLinkError>("R_AARCH64_TSTBR14 target is not a "
31206c3fb27SDimitry Andric                                         "test and branch instruction");
31306c3fb27SDimitry Andric 
31406c3fb27SDimitry Andric       Kind = aarch64::TestAndBranch14PCRel;
31506c3fb27SDimitry Andric       break;
31606c3fb27SDimitry Andric     }
31706c3fb27SDimitry Andric     case ELFCondBr19: {
31806c3fb27SDimitry Andric       uint32_t Instr = *(const ulittle32_t *)FixupContent;
31906c3fb27SDimitry Andric       if (!aarch64::isCondBranchImm19(Instr) &&
32006c3fb27SDimitry Andric           !aarch64::isCompAndBranchImm19(Instr))
32106c3fb27SDimitry Andric         return make_error<JITLinkError>("R_AARCH64_CONDBR19 target is not a "
32206c3fb27SDimitry Andric                                         "conditional branch instruction");
32306c3fb27SDimitry Andric 
32406c3fb27SDimitry Andric       Kind = aarch64::CondBranch19PCRel;
32506c3fb27SDimitry Andric       break;
32606c3fb27SDimitry Andric     }
32706c3fb27SDimitry Andric     case ELFAbs32: {
32806c3fb27SDimitry Andric       Kind = aarch64::Pointer32;
32906c3fb27SDimitry Andric       break;
33006c3fb27SDimitry Andric     }
33181ad6265SDimitry Andric     case ELFAbs64: {
33281ad6265SDimitry Andric       Kind = aarch64::Pointer64;
33381ad6265SDimitry Andric       break;
33481ad6265SDimitry Andric     }
33581ad6265SDimitry Andric     case ELFPrel32: {
33681ad6265SDimitry Andric       Kind = aarch64::Delta32;
33781ad6265SDimitry Andric       break;
33881ad6265SDimitry Andric     }
33981ad6265SDimitry Andric     case ELFPrel64: {
34081ad6265SDimitry Andric       Kind = aarch64::Delta64;
34181ad6265SDimitry Andric       break;
34281ad6265SDimitry Andric     }
34381ad6265SDimitry Andric     case ELFAdrGOTPage21: {
344bdd1243dSDimitry Andric       Kind = aarch64::RequestGOTAndTransformToPage21;
34581ad6265SDimitry Andric       break;
34681ad6265SDimitry Andric     }
34781ad6265SDimitry Andric     case ELFLd64GOTLo12: {
348bdd1243dSDimitry Andric       Kind = aarch64::RequestGOTAndTransformToPageOffset12;
34981ad6265SDimitry Andric       break;
35081ad6265SDimitry Andric     }
351753f127fSDimitry Andric     case ELFTLSDescAdrPage21: {
352bdd1243dSDimitry Andric       Kind = aarch64::RequestTLSDescEntryAndTransformToPage21;
353753f127fSDimitry Andric       break;
354753f127fSDimitry Andric     }
355bdd1243dSDimitry Andric     case ELFTLSDescAddLo12:
356753f127fSDimitry Andric     case ELFTLSDescLd64Lo12: {
357bdd1243dSDimitry Andric       Kind = aarch64::RequestTLSDescEntryAndTransformToPageOffset12;
358753f127fSDimitry Andric       break;
359753f127fSDimitry Andric     }
360753f127fSDimitry Andric     case ELFTLSDescCall: {
361753f127fSDimitry Andric       return Error::success();
362753f127fSDimitry Andric     }
36381ad6265SDimitry Andric     };
36481ad6265SDimitry Andric 
36581ad6265SDimitry Andric     Edge GE(Kind, Offset, *GraphSymbol, Addend);
366349cc55cSDimitry Andric     LLVM_DEBUG({
367349cc55cSDimitry Andric       dbgs() << "    ";
36881ad6265SDimitry Andric       printEdge(dbgs(), BlockToFix, GE, aarch64::getEdgeKindName(Kind));
369349cc55cSDimitry Andric       dbgs() << "\n";
370349cc55cSDimitry Andric     });
371349cc55cSDimitry Andric 
37204eeddc0SDimitry Andric     BlockToFix.addEdge(std::move(GE));
373753f127fSDimitry Andric 
374349cc55cSDimitry Andric     return Error::success();
375349cc55cSDimitry Andric   }
376349cc55cSDimitry Andric 
37781ad6265SDimitry Andric   /// Return the string name of the given ELF aarch64 edge kind.
getELFAArch64RelocationKindName(Edge::Kind R)37881ad6265SDimitry Andric   const char *getELFAArch64RelocationKindName(Edge::Kind R) {
37981ad6265SDimitry Andric     switch (R) {
38081ad6265SDimitry Andric     case ELFCall26:
38181ad6265SDimitry Andric       return "ELFCall26";
38281ad6265SDimitry Andric     case ELFAdrPage21:
38381ad6265SDimitry Andric       return "ELFAdrPage21";
38481ad6265SDimitry Andric     case ELFAddAbs12:
38581ad6265SDimitry Andric       return "ELFAddAbs12";
38681ad6265SDimitry Andric     case ELFLdSt8Abs12:
38781ad6265SDimitry Andric       return "ELFLdSt8Abs12";
38881ad6265SDimitry Andric     case ELFLdSt16Abs12:
38981ad6265SDimitry Andric       return "ELFLdSt16Abs12";
39081ad6265SDimitry Andric     case ELFLdSt32Abs12:
39181ad6265SDimitry Andric       return "ELFLdSt32Abs12";
39281ad6265SDimitry Andric     case ELFLdSt64Abs12:
39381ad6265SDimitry Andric       return "ELFLdSt64Abs12";
39481ad6265SDimitry Andric     case ELFLdSt128Abs12:
39581ad6265SDimitry Andric       return "ELFLdSt128Abs12";
39681ad6265SDimitry Andric     case ELFMovwAbsG0:
39781ad6265SDimitry Andric       return "ELFMovwAbsG0";
39881ad6265SDimitry Andric     case ELFMovwAbsG1:
39981ad6265SDimitry Andric       return "ELFMovwAbsG1";
40081ad6265SDimitry Andric     case ELFMovwAbsG2:
40181ad6265SDimitry Andric       return "ELFMovwAbsG2";
40281ad6265SDimitry Andric     case ELFMovwAbsG3:
40381ad6265SDimitry Andric       return "ELFMovwAbsG3";
40406c3fb27SDimitry Andric     case ELFAbs32:
40506c3fb27SDimitry Andric       return "ELFAbs32";
40681ad6265SDimitry Andric     case ELFAbs64:
40781ad6265SDimitry Andric       return "ELFAbs64";
40881ad6265SDimitry Andric     case ELFPrel32:
40981ad6265SDimitry Andric       return "ELFPrel32";
41081ad6265SDimitry Andric     case ELFPrel64:
41181ad6265SDimitry Andric       return "ELFPrel64";
41281ad6265SDimitry Andric     case ELFAdrGOTPage21:
41381ad6265SDimitry Andric       return "ELFAdrGOTPage21";
41481ad6265SDimitry Andric     case ELFLd64GOTLo12:
41581ad6265SDimitry Andric       return "ELFLd64GOTLo12";
416753f127fSDimitry Andric     case ELFTLSDescAdrPage21:
417753f127fSDimitry Andric       return "ELFTLSDescAdrPage21";
418753f127fSDimitry Andric     case ELFTLSDescAddLo12:
419753f127fSDimitry Andric       return "ELFTLSDescAddLo12";
420753f127fSDimitry Andric     case ELFTLSDescLd64Lo12:
421753f127fSDimitry Andric       return "ELFTLSDescLd64Lo12";
422753f127fSDimitry Andric     case ELFTLSDescCall:
423753f127fSDimitry Andric       return "ELFTLSDescCall";
42481ad6265SDimitry Andric     default:
42581ad6265SDimitry Andric       return getGenericEdgeKindName(static_cast<Edge::Kind>(R));
42681ad6265SDimitry Andric     }
42781ad6265SDimitry Andric   }
42881ad6265SDimitry Andric 
429349cc55cSDimitry Andric public:
ELFLinkGraphBuilder_aarch64(StringRef FileName,const object::ELFFile<ELFT> & Obj,Triple TT,SubtargetFeatures Features)430349cc55cSDimitry Andric   ELFLinkGraphBuilder_aarch64(StringRef FileName,
43106c3fb27SDimitry Andric                               const object::ELFFile<ELFT> &Obj, Triple TT,
43206c3fb27SDimitry Andric                               SubtargetFeatures Features)
43306c3fb27SDimitry Andric       : ELFLinkGraphBuilder<ELFT>(Obj, std::move(TT), std::move(Features),
43406c3fb27SDimitry Andric                                   FileName, aarch64::getEdgeKindName) {}
435349cc55cSDimitry Andric };
436349cc55cSDimitry Andric 
437753f127fSDimitry Andric // TLS Info Builder.
438753f127fSDimitry Andric class TLSInfoTableManager_ELF_aarch64
439753f127fSDimitry Andric     : public TableManager<TLSInfoTableManager_ELF_aarch64> {
440753f127fSDimitry Andric public:
getSectionName()441753f127fSDimitry Andric   static StringRef getSectionName() { return "$__TLSINFO"; }
442753f127fSDimitry Andric 
443753f127fSDimitry Andric   static const uint8_t TLSInfoEntryContent[16];
444753f127fSDimitry Andric 
visitEdge(LinkGraph & G,Block * B,Edge & E)445753f127fSDimitry Andric   bool visitEdge(LinkGraph &G, Block *B, Edge &E) { return false; }
446753f127fSDimitry Andric 
createEntry(LinkGraph & G,Symbol & Target)447753f127fSDimitry Andric   Symbol &createEntry(LinkGraph &G, Symbol &Target) {
448753f127fSDimitry Andric     // the TLS Info entry's key value will be written by the fixTLVSectionByName
449753f127fSDimitry Andric     // pass, so create mutable content.
450753f127fSDimitry Andric     auto &TLSInfoEntry = G.createMutableContentBlock(
451753f127fSDimitry Andric         getTLSInfoSection(G), G.allocateContent(getTLSInfoEntryContent()),
452753f127fSDimitry Andric         orc::ExecutorAddr(), 8, 0);
453753f127fSDimitry Andric     TLSInfoEntry.addEdge(aarch64::Pointer64, 8, Target, 0);
454753f127fSDimitry Andric     return G.addAnonymousSymbol(TLSInfoEntry, 0, 16, false, false);
455753f127fSDimitry Andric   }
456753f127fSDimitry Andric 
457753f127fSDimitry Andric private:
getTLSInfoSection(LinkGraph & G)458753f127fSDimitry Andric   Section &getTLSInfoSection(LinkGraph &G) {
459753f127fSDimitry Andric     if (!TLSInfoTable)
460bdd1243dSDimitry Andric       TLSInfoTable = &G.createSection(getSectionName(), orc::MemProt::Read);
461753f127fSDimitry Andric     return *TLSInfoTable;
462753f127fSDimitry Andric   }
463753f127fSDimitry Andric 
getTLSInfoEntryContent() const464753f127fSDimitry Andric   ArrayRef<char> getTLSInfoEntryContent() const {
465753f127fSDimitry Andric     return {reinterpret_cast<const char *>(TLSInfoEntryContent),
466753f127fSDimitry Andric             sizeof(TLSInfoEntryContent)};
467753f127fSDimitry Andric   }
468753f127fSDimitry Andric 
469753f127fSDimitry Andric   Section *TLSInfoTable = nullptr;
470753f127fSDimitry Andric };
471753f127fSDimitry Andric 
472753f127fSDimitry Andric const uint8_t TLSInfoTableManager_ELF_aarch64::TLSInfoEntryContent[16] = {
473753f127fSDimitry Andric     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*pthread key */
474753f127fSDimitry Andric     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  /*data address*/
475753f127fSDimitry Andric };
476753f127fSDimitry Andric 
477753f127fSDimitry Andric // TLS Descriptor Builder.
478753f127fSDimitry Andric class TLSDescTableManager_ELF_aarch64
479753f127fSDimitry Andric     : public TableManager<TLSDescTableManager_ELF_aarch64> {
480753f127fSDimitry Andric public:
TLSDescTableManager_ELF_aarch64(TLSInfoTableManager_ELF_aarch64 & TLSInfoTableManager)481753f127fSDimitry Andric   TLSDescTableManager_ELF_aarch64(
482753f127fSDimitry Andric       TLSInfoTableManager_ELF_aarch64 &TLSInfoTableManager)
483753f127fSDimitry Andric       : TLSInfoTableManager(TLSInfoTableManager) {}
484753f127fSDimitry Andric 
getSectionName()485753f127fSDimitry Andric   static StringRef getSectionName() { return "$__TLSDESC"; }
486753f127fSDimitry Andric 
487753f127fSDimitry Andric   static const uint8_t TLSDescEntryContent[16];
488753f127fSDimitry Andric 
visitEdge(LinkGraph & G,Block * B,Edge & E)489753f127fSDimitry Andric   bool visitEdge(LinkGraph &G, Block *B, Edge &E) {
490753f127fSDimitry Andric     Edge::Kind KindToSet = Edge::Invalid;
491753f127fSDimitry Andric     switch (E.getKind()) {
492bdd1243dSDimitry Andric     case aarch64::RequestTLSDescEntryAndTransformToPage21: {
493753f127fSDimitry Andric       KindToSet = aarch64::Page21;
494753f127fSDimitry Andric       break;
495753f127fSDimitry Andric     }
496bdd1243dSDimitry Andric     case aarch64::RequestTLSDescEntryAndTransformToPageOffset12: {
497753f127fSDimitry Andric       KindToSet = aarch64::PageOffset12;
498753f127fSDimitry Andric       break;
499753f127fSDimitry Andric     }
500753f127fSDimitry Andric     default:
501753f127fSDimitry Andric       return false;
502753f127fSDimitry Andric     }
503753f127fSDimitry Andric     assert(KindToSet != Edge::Invalid &&
504753f127fSDimitry Andric            "Fell through switch, but no new kind to set");
505753f127fSDimitry Andric     DEBUG_WITH_TYPE("jitlink", {
506753f127fSDimitry Andric       dbgs() << "  Fixing " << G.getEdgeKindName(E.getKind()) << " edge at "
507753f127fSDimitry Andric              << B->getFixupAddress(E) << " (" << B->getAddress() << " + "
508753f127fSDimitry Andric              << formatv("{0:x}", E.getOffset()) << ")\n";
509753f127fSDimitry Andric     });
510753f127fSDimitry Andric     E.setKind(KindToSet);
511753f127fSDimitry Andric     E.setTarget(getEntryForTarget(G, E.getTarget()));
512753f127fSDimitry Andric     return true;
513753f127fSDimitry Andric   }
514753f127fSDimitry Andric 
createEntry(LinkGraph & G,Symbol & Target)515753f127fSDimitry Andric   Symbol &createEntry(LinkGraph &G, Symbol &Target) {
516753f127fSDimitry Andric     auto &EntryBlock =
517753f127fSDimitry Andric         G.createContentBlock(getTLSDescSection(G), getTLSDescBlockContent(),
518753f127fSDimitry Andric                              orc::ExecutorAddr(), 8, 0);
519753f127fSDimitry Andric     EntryBlock.addEdge(aarch64::Pointer64, 0, getTLSDescResolver(G), 0);
520753f127fSDimitry Andric     EntryBlock.addEdge(aarch64::Pointer64, 8,
521753f127fSDimitry Andric                        TLSInfoTableManager.getEntryForTarget(G, Target), 0);
522753f127fSDimitry Andric     return G.addAnonymousSymbol(EntryBlock, 0, 8, false, false);
523753f127fSDimitry Andric   }
524753f127fSDimitry Andric 
525753f127fSDimitry Andric private:
getTLSDescSection(LinkGraph & G)526753f127fSDimitry Andric   Section &getTLSDescSection(LinkGraph &G) {
527753f127fSDimitry Andric     if (!GOTSection)
528bdd1243dSDimitry Andric       GOTSection = &G.createSection(getSectionName(), orc::MemProt::Read);
529753f127fSDimitry Andric     return *GOTSection;
530753f127fSDimitry Andric   }
531753f127fSDimitry Andric 
getTLSDescResolver(LinkGraph & G)532753f127fSDimitry Andric   Symbol &getTLSDescResolver(LinkGraph &G) {
533753f127fSDimitry Andric     if (!TLSDescResolver)
534bdd1243dSDimitry Andric       TLSDescResolver = &G.addExternalSymbol("__tlsdesc_resolver", 8, false);
535753f127fSDimitry Andric     return *TLSDescResolver;
536753f127fSDimitry Andric   }
537753f127fSDimitry Andric 
getTLSDescBlockContent()538753f127fSDimitry Andric   ArrayRef<char> getTLSDescBlockContent() {
539753f127fSDimitry Andric     return {reinterpret_cast<const char *>(TLSDescEntryContent),
540753f127fSDimitry Andric             sizeof(TLSDescEntryContent)};
541753f127fSDimitry Andric   }
542753f127fSDimitry Andric 
543753f127fSDimitry Andric   Section *GOTSection = nullptr;
544753f127fSDimitry Andric   Symbol *TLSDescResolver = nullptr;
545753f127fSDimitry Andric   TLSInfoTableManager_ELF_aarch64 &TLSInfoTableManager;
546753f127fSDimitry Andric };
547753f127fSDimitry Andric 
548753f127fSDimitry Andric const uint8_t TLSDescTableManager_ELF_aarch64::TLSDescEntryContent[16] = {
549753f127fSDimitry Andric     0x00, 0x00, 0x00, 0x00,
550753f127fSDimitry Andric     0x00, 0x00, 0x00, 0x00, /*resolver function pointer*/
551753f127fSDimitry Andric     0x00, 0x00, 0x00, 0x00,
552753f127fSDimitry Andric     0x00, 0x00, 0x00, 0x00 /*pointer to tls info*/
553753f127fSDimitry Andric };
554753f127fSDimitry Andric 
buildTables_ELF_aarch64(LinkGraph & G)55581ad6265SDimitry Andric Error buildTables_ELF_aarch64(LinkGraph &G) {
55681ad6265SDimitry Andric   LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");
55781ad6265SDimitry Andric 
55881ad6265SDimitry Andric   aarch64::GOTTableManager GOT;
55981ad6265SDimitry Andric   aarch64::PLTTableManager PLT(GOT);
560753f127fSDimitry Andric   TLSInfoTableManager_ELF_aarch64 TLSInfo;
561753f127fSDimitry Andric   TLSDescTableManager_ELF_aarch64 TLSDesc(TLSInfo);
562753f127fSDimitry Andric   visitExistingEdges(G, GOT, PLT, TLSDesc, TLSInfo);
56381ad6265SDimitry Andric   return Error::success();
56481ad6265SDimitry Andric }
56581ad6265SDimitry Andric 
56681ad6265SDimitry Andric } // namespace
56781ad6265SDimitry Andric 
56881ad6265SDimitry Andric namespace llvm {
56981ad6265SDimitry Andric namespace jitlink {
57081ad6265SDimitry Andric 
571349cc55cSDimitry Andric Expected<std::unique_ptr<LinkGraph>>
createLinkGraphFromELFObject_aarch64(MemoryBufferRef ObjectBuffer)572349cc55cSDimitry Andric createLinkGraphFromELFObject_aarch64(MemoryBufferRef ObjectBuffer) {
573349cc55cSDimitry Andric   LLVM_DEBUG({
574349cc55cSDimitry Andric     dbgs() << "Building jitlink graph for new input "
575349cc55cSDimitry Andric            << ObjectBuffer.getBufferIdentifier() << "...\n";
576349cc55cSDimitry Andric   });
577349cc55cSDimitry Andric 
578349cc55cSDimitry Andric   auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer);
579349cc55cSDimitry Andric   if (!ELFObj)
580349cc55cSDimitry Andric     return ELFObj.takeError();
581349cc55cSDimitry Andric 
58206c3fb27SDimitry Andric   auto Features = (*ELFObj)->getFeatures();
58306c3fb27SDimitry Andric   if (!Features)
58406c3fb27SDimitry Andric     return Features.takeError();
58506c3fb27SDimitry Andric 
586349cc55cSDimitry Andric   assert((*ELFObj)->getArch() == Triple::aarch64 &&
587349cc55cSDimitry Andric          "Only AArch64 (little endian) is supported for now");
588349cc55cSDimitry Andric 
589349cc55cSDimitry Andric   auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
59006c3fb27SDimitry Andric   return ELFLinkGraphBuilder_aarch64<object::ELF64LE>(
59106c3fb27SDimitry Andric              (*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
59206c3fb27SDimitry Andric              (*ELFObj)->makeTriple(), std::move(*Features))
593349cc55cSDimitry Andric       .buildGraph();
594349cc55cSDimitry Andric }
595349cc55cSDimitry Andric 
link_ELF_aarch64(std::unique_ptr<LinkGraph> G,std::unique_ptr<JITLinkContext> Ctx)596349cc55cSDimitry Andric void link_ELF_aarch64(std::unique_ptr<LinkGraph> G,
597349cc55cSDimitry Andric                       std::unique_ptr<JITLinkContext> Ctx) {
598349cc55cSDimitry Andric   PassConfiguration Config;
599349cc55cSDimitry Andric   const Triple &TT = G->getTargetTriple();
600349cc55cSDimitry Andric   if (Ctx->shouldAddDefaultTargetPasses(TT)) {
601*5f757f3fSDimitry Andric     // Add eh-frame passes.
60281ad6265SDimitry Andric     Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame"));
60381ad6265SDimitry Andric     Config.PrePrunePasses.push_back(EHFrameEdgeFixer(
60481ad6265SDimitry Andric         ".eh_frame", 8, aarch64::Pointer32, aarch64::Pointer64,
60581ad6265SDimitry Andric         aarch64::Delta32, aarch64::Delta64, aarch64::NegDelta32));
6061ac55f4cSDimitry Andric     Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame"));
60781ad6265SDimitry Andric 
60881ad6265SDimitry Andric     // Add a mark-live pass.
609349cc55cSDimitry Andric     if (auto MarkLive = Ctx->getMarkLivePass(TT))
610349cc55cSDimitry Andric       Config.PrePrunePasses.push_back(std::move(MarkLive));
611349cc55cSDimitry Andric     else
612349cc55cSDimitry Andric       Config.PrePrunePasses.push_back(markAllSymbolsLive);
61381ad6265SDimitry Andric 
614753f127fSDimitry Andric     // Add an in-place GOT/TLS/Stubs build pass.
61581ad6265SDimitry Andric     Config.PostPrunePasses.push_back(buildTables_ELF_aarch64);
616349cc55cSDimitry Andric   }
61781ad6265SDimitry Andric 
618349cc55cSDimitry Andric   if (auto Err = Ctx->modifyPassConfig(*G, Config))
619349cc55cSDimitry Andric     return Ctx->notifyFailed(std::move(Err));
620349cc55cSDimitry Andric 
621349cc55cSDimitry Andric   ELFJITLinker_aarch64::link(std::move(Ctx), std::move(G), std::move(Config));
622349cc55cSDimitry Andric }
623349cc55cSDimitry Andric 
624349cc55cSDimitry Andric } // namespace jitlink
625349cc55cSDimitry Andric } // namespace llvm
626