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