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