12ed91da0SStefan Gränitz //===----- ELF_aarch64.cpp - JIT linker implementation for ELF/aarch64 ----===// 22ed91da0SStefan Gränitz // 32ed91da0SStefan Gränitz // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42ed91da0SStefan Gränitz // See https://llvm.org/LICENSE.txt for license information. 52ed91da0SStefan Gränitz // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 62ed91da0SStefan Gränitz // 72ed91da0SStefan Gränitz //===----------------------------------------------------------------------===// 82ed91da0SStefan Gränitz // 92ed91da0SStefan Gränitz // ELF/aarch64 jit-link implementation. 102ed91da0SStefan Gränitz // 112ed91da0SStefan Gränitz //===----------------------------------------------------------------------===// 122ed91da0SStefan Gränitz 132ed91da0SStefan Gränitz #include "llvm/ExecutionEngine/JITLink/ELF_aarch64.h" 142ed91da0SStefan Gränitz #include "llvm/BinaryFormat/ELF.h" 15f8a9536cSSunho Kim #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h" 162ed91da0SStefan Gränitz #include "llvm/ExecutionEngine/JITLink/aarch64.h" 172ed91da0SStefan Gränitz #include "llvm/Object/ELFObjectFile.h" 18ab472c96SSunho Kim #include "llvm/Support/Endian.h" 192ed91da0SStefan Gränitz 20488a1873SLang Hames #include "DefineExternalSectionStartAndEndSymbols.h" 218ef45107SLang Hames #include "EHFrameSupportImpl.h" 228ef45107SLang Hames #include "ELFLinkGraphBuilder.h" 238ef45107SLang Hames #include "JITLinkGeneric.h" 24488a1873SLang Hames 252ed91da0SStefan Gränitz #define DEBUG_TYPE "jitlink" 262ed91da0SStefan Gränitz 272ed91da0SStefan Gränitz using namespace llvm; 282ed91da0SStefan Gränitz using namespace llvm::jitlink; 292ed91da0SStefan Gränitz 30db372258SSunho Kim namespace { 312ed91da0SStefan Gränitz 32199c4003SVladislav Khmelevsky constexpr StringRef ELFGOTSymbolName = "_GLOBAL_OFFSET_TABLE_"; 33199c4003SVladislav Khmelevsky 342ed91da0SStefan Gränitz class ELFJITLinker_aarch64 : public JITLinker<ELFJITLinker_aarch64> { 352ed91da0SStefan Gränitz friend class JITLinker<ELFJITLinker_aarch64>; 362ed91da0SStefan Gränitz 372ed91da0SStefan Gränitz public: 382ed91da0SStefan Gränitz ELFJITLinker_aarch64(std::unique_ptr<JITLinkContext> Ctx, 392ed91da0SStefan Gränitz std::unique_ptr<LinkGraph> G, 402ed91da0SStefan Gränitz PassConfiguration PassConfig) 41199c4003SVladislav Khmelevsky : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) { 42199c4003SVladislav Khmelevsky if (shouldAddDefaultTargetPasses(getGraph().getTargetTriple())) 43199c4003SVladislav Khmelevsky getPassConfig().PostAllocationPasses.push_back( 44199c4003SVladislav Khmelevsky [this](LinkGraph &G) { return getOrCreateGOTSymbol(G); }); 45199c4003SVladislav Khmelevsky } 462ed91da0SStefan Gränitz 472ed91da0SStefan Gränitz private: 48199c4003SVladislav Khmelevsky Symbol *GOTSymbol = nullptr; 49199c4003SVladislav Khmelevsky 502ed91da0SStefan Gränitz Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const { 51199c4003SVladislav Khmelevsky return aarch64::applyFixup(G, B, E, GOTSymbol); 52199c4003SVladislav Khmelevsky } 53199c4003SVladislav Khmelevsky 54199c4003SVladislav Khmelevsky Error getOrCreateGOTSymbol(LinkGraph &G) { 552ccf7ed2SJared Wyles auto InteredGOTSymbolName = 562ccf7ed2SJared Wyles G.getSymbolStringPool()->intern(ELFGOTSymbolName); 572ccf7ed2SJared Wyles 58199c4003SVladislav Khmelevsky auto DefineExternalGOTSymbolIfPresent = 59199c4003SVladislav Khmelevsky createDefineExternalSectionStartAndEndSymbolsPass( 60199c4003SVladislav Khmelevsky [&](LinkGraph &LG, Symbol &Sym) -> SectionRangeSymbolDesc { 612ccf7ed2SJared Wyles if (*Sym.getName() == ELFGOTSymbolName) 62199c4003SVladislav Khmelevsky if (auto *GOTSection = G.findSectionByName( 63199c4003SVladislav Khmelevsky aarch64::GOTTableManager::getSectionName())) { 64199c4003SVladislav Khmelevsky GOTSymbol = &Sym; 65199c4003SVladislav Khmelevsky return {*GOTSection, true}; 66199c4003SVladislav Khmelevsky } 67199c4003SVladislav Khmelevsky return {}; 68199c4003SVladislav Khmelevsky }); 69199c4003SVladislav Khmelevsky 70199c4003SVladislav Khmelevsky // Try to attach _GLOBAL_OFFSET_TABLE_ to the GOT if it's defined as an 71199c4003SVladislav Khmelevsky // external. 72199c4003SVladislav Khmelevsky if (auto Err = DefineExternalGOTSymbolIfPresent(G)) 73199c4003SVladislav Khmelevsky return Err; 74199c4003SVladislav Khmelevsky 75199c4003SVladislav Khmelevsky // If we succeeded then we're done. 76199c4003SVladislav Khmelevsky if (GOTSymbol) 77199c4003SVladislav Khmelevsky return Error::success(); 78199c4003SVladislav Khmelevsky 79199c4003SVladislav Khmelevsky // Otherwise look for a GOT section: If it already has a start symbol we'll 80199c4003SVladislav Khmelevsky // record it, otherwise we'll create our own. 81199c4003SVladislav Khmelevsky // If there's a GOT section but we didn't find an external GOT symbol... 82199c4003SVladislav Khmelevsky if (auto *GOTSection = 83199c4003SVladislav Khmelevsky G.findSectionByName(aarch64::GOTTableManager::getSectionName())) { 84199c4003SVladislav Khmelevsky 85199c4003SVladislav Khmelevsky // Check for an existing defined symbol. 86199c4003SVladislav Khmelevsky for (auto *Sym : GOTSection->symbols()) 872ccf7ed2SJared Wyles if (Sym->getName() == InteredGOTSymbolName) { 88199c4003SVladislav Khmelevsky GOTSymbol = Sym; 89199c4003SVladislav Khmelevsky return Error::success(); 90199c4003SVladislav Khmelevsky } 91199c4003SVladislav Khmelevsky 92199c4003SVladislav Khmelevsky // If there's no defined symbol then create one. 93199c4003SVladislav Khmelevsky SectionRange SR(*GOTSection); 94199c4003SVladislav Khmelevsky if (SR.empty()) 95199c4003SVladislav Khmelevsky GOTSymbol = 962ccf7ed2SJared Wyles // FIXME: we should only do this once 972ccf7ed2SJared Wyles &G.addAbsoluteSymbol(InteredGOTSymbolName, orc::ExecutorAddr(), 0, 98199c4003SVladislav Khmelevsky Linkage::Strong, Scope::Local, true); 99199c4003SVladislav Khmelevsky else 100199c4003SVladislav Khmelevsky GOTSymbol = 1012ccf7ed2SJared Wyles &G.addDefinedSymbol(*SR.getFirstBlock(), 0, InteredGOTSymbolName, 0, 102199c4003SVladislav Khmelevsky Linkage::Strong, Scope::Local, false, true); 103199c4003SVladislav Khmelevsky } 104199c4003SVladislav Khmelevsky 105199c4003SVladislav Khmelevsky // If we still haven't found a GOT symbol then double check the externals. 106199c4003SVladislav Khmelevsky // We may have a GOT-relative reference but no GOT section, in which case 107199c4003SVladislav Khmelevsky // we just need to point the GOT symbol at some address in this graph. 108199c4003SVladislav Khmelevsky if (!GOTSymbol) { 109199c4003SVladislav Khmelevsky for (auto *Sym : G.external_symbols()) { 1102ccf7ed2SJared Wyles if (*Sym->getName() == ELFGOTSymbolName) { 111199c4003SVladislav Khmelevsky auto Blocks = G.blocks(); 112199c4003SVladislav Khmelevsky if (!Blocks.empty()) { 113199c4003SVladislav Khmelevsky G.makeAbsolute(*Sym, (*Blocks.begin())->getAddress()); 114199c4003SVladislav Khmelevsky GOTSymbol = Sym; 115199c4003SVladislav Khmelevsky break; 116199c4003SVladislav Khmelevsky } 117199c4003SVladislav Khmelevsky } 118199c4003SVladislav Khmelevsky } 119199c4003SVladislav Khmelevsky } 120199c4003SVladislav Khmelevsky 121199c4003SVladislav Khmelevsky return Error::success(); 1222ed91da0SStefan Gränitz } 1232ed91da0SStefan Gränitz }; 1242ed91da0SStefan Gränitz 1252ed91da0SStefan Gränitz template <typename ELFT> 1262ed91da0SStefan Gränitz class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> { 1272ed91da0SStefan Gränitz private: 128b6553f59SSunho Kim enum ELFAArch64RelocationKind : Edge::Kind { 12925a9fb12SSunho Kim ELFCall26 = Edge::FirstRelocation, 130d395b56aSPavel Samolysov ELFLdrLo19, 131e9676389SJob Noorman ELFAdrLo21, 13225a9fb12SSunho Kim ELFAdrPage21, 13325a9fb12SSunho Kim ELFAddAbs12, 134ab472c96SSunho Kim ELFLdSt8Abs12, 135ab472c96SSunho Kim ELFLdSt16Abs12, 136ab472c96SSunho Kim ELFLdSt32Abs12, 137ab472c96SSunho Kim ELFLdSt64Abs12, 138ab472c96SSunho Kim ELFLdSt128Abs12, 1393d8061a3SSunho Kim ELFMovwAbsG0, 1403d8061a3SSunho Kim ELFMovwAbsG1, 1413d8061a3SSunho Kim ELFMovwAbsG2, 1423d8061a3SSunho Kim ELFMovwAbsG3, 143a9a2eb81SJob Noorman ELFTstBr14, 144193a8092SJob Noorman ELFCondBr19, 145fb1b9945SLang Hames ELFAbs32, 1461deaa9b8SLang Hames ELFAbs64, 1475d5183b1SSunho Kim ELFPrel32, 1485d5183b1SSunho Kim ELFPrel64, 1492094fad0SSunho Kim ELFAdrGOTPage21, 1502094fad0SSunho Kim ELFLd64GOTLo12, 151199c4003SVladislav Khmelevsky ELFLd64GOTPAGELo15, 15230b6c51fSSunho Kim ELFTLSDescAdrPage21, 15330b6c51fSSunho Kim ELFTLSDescAddLo12, 15430b6c51fSSunho Kim ELFTLSDescLd64Lo12, 15530b6c51fSSunho Kim ELFTLSDescCall, 156b6553f59SSunho Kim }; 157b6553f59SSunho Kim 158b6553f59SSunho Kim static Expected<ELFAArch64RelocationKind> 1592ed91da0SStefan Gränitz getRelocationKind(const uint32_t Type) { 1602ed91da0SStefan Gränitz using namespace aarch64; 1612ed91da0SStefan Gränitz switch (Type) { 1622ed91da0SStefan Gränitz case ELF::R_AARCH64_CALL26: 163175f22d6SSunho Kim case ELF::R_AARCH64_JUMP26: 16425a9fb12SSunho Kim return ELFCall26; 165d395b56aSPavel Samolysov case ELF::R_AARCH64_LD_PREL_LO19: 166d395b56aSPavel Samolysov return ELFLdrLo19; 167e9676389SJob Noorman case ELF::R_AARCH64_ADR_PREL_LO21: 168e9676389SJob Noorman return ELFAdrLo21; 16925a9fb12SSunho Kim case ELF::R_AARCH64_ADR_PREL_PG_HI21: 17025a9fb12SSunho Kim return ELFAdrPage21; 17125a9fb12SSunho Kim case ELF::R_AARCH64_ADD_ABS_LO12_NC: 17225a9fb12SSunho Kim return ELFAddAbs12; 173ab472c96SSunho Kim case ELF::R_AARCH64_LDST8_ABS_LO12_NC: 174ab472c96SSunho Kim return ELFLdSt8Abs12; 175ab472c96SSunho Kim case ELF::R_AARCH64_LDST16_ABS_LO12_NC: 176ab472c96SSunho Kim return ELFLdSt16Abs12; 177ab472c96SSunho Kim case ELF::R_AARCH64_LDST32_ABS_LO12_NC: 178ab472c96SSunho Kim return ELFLdSt32Abs12; 179ab472c96SSunho Kim case ELF::R_AARCH64_LDST64_ABS_LO12_NC: 180ab472c96SSunho Kim return ELFLdSt64Abs12; 181ab472c96SSunho Kim case ELF::R_AARCH64_LDST128_ABS_LO12_NC: 182ab472c96SSunho Kim return ELFLdSt128Abs12; 1833d8061a3SSunho Kim case ELF::R_AARCH64_MOVW_UABS_G0_NC: 1843d8061a3SSunho Kim return ELFMovwAbsG0; 1853d8061a3SSunho Kim case ELF::R_AARCH64_MOVW_UABS_G1_NC: 1863d8061a3SSunho Kim return ELFMovwAbsG1; 1873d8061a3SSunho Kim case ELF::R_AARCH64_MOVW_UABS_G2_NC: 1883d8061a3SSunho Kim return ELFMovwAbsG2; 1893d8061a3SSunho Kim case ELF::R_AARCH64_MOVW_UABS_G3: 1903d8061a3SSunho Kim return ELFMovwAbsG3; 191a9a2eb81SJob Noorman case ELF::R_AARCH64_TSTBR14: 192a9a2eb81SJob Noorman return ELFTstBr14; 193193a8092SJob Noorman case ELF::R_AARCH64_CONDBR19: 194193a8092SJob Noorman return ELFCondBr19; 195fb1b9945SLang Hames case ELF::R_AARCH64_ABS32: 196fb1b9945SLang Hames return ELFAbs32; 1971deaa9b8SLang Hames case ELF::R_AARCH64_ABS64: 1981deaa9b8SLang Hames return ELFAbs64; 1995d5183b1SSunho Kim case ELF::R_AARCH64_PREL32: 2005d5183b1SSunho Kim return ELFPrel32; 2015d5183b1SSunho Kim case ELF::R_AARCH64_PREL64: 2025d5183b1SSunho Kim return ELFPrel64; 2032094fad0SSunho Kim case ELF::R_AARCH64_ADR_GOT_PAGE: 2042094fad0SSunho Kim return ELFAdrGOTPage21; 2052094fad0SSunho Kim case ELF::R_AARCH64_LD64_GOT_LO12_NC: 2062094fad0SSunho Kim return ELFLd64GOTLo12; 207199c4003SVladislav Khmelevsky case ELF::R_AARCH64_LD64_GOTPAGE_LO15: 208199c4003SVladislav Khmelevsky return ELFLd64GOTPAGELo15; 20930b6c51fSSunho Kim case ELF::R_AARCH64_TLSDESC_ADR_PAGE21: 21030b6c51fSSunho Kim return ELFTLSDescAdrPage21; 21130b6c51fSSunho Kim case ELF::R_AARCH64_TLSDESC_ADD_LO12: 21230b6c51fSSunho Kim return ELFTLSDescAddLo12; 21330b6c51fSSunho Kim case ELF::R_AARCH64_TLSDESC_LD64_LO12: 21430b6c51fSSunho Kim return ELFTLSDescLd64Lo12; 21530b6c51fSSunho Kim case ELF::R_AARCH64_TLSDESC_CALL: 21630b6c51fSSunho Kim return ELFTLSDescCall; 2172ed91da0SStefan Gränitz } 2182ed91da0SStefan Gränitz 2199fc0aa45SSunho Kim return make_error<JITLinkError>( 2209fc0aa45SSunho Kim "Unsupported aarch64 relocation:" + formatv("{0:d}: ", Type) + 2219fc0aa45SSunho Kim object::getELFRelocationTypeName(ELF::EM_AARCH64, Type)); 2222ed91da0SStefan Gränitz } 2232ed91da0SStefan Gränitz 2242ed91da0SStefan Gränitz Error addRelocations() override { 22596918515SStefan Gränitz LLVM_DEBUG(dbgs() << "Processing relocations:\n"); 22696918515SStefan Gränitz 2272ed91da0SStefan Gränitz using Base = ELFLinkGraphBuilder<ELFT>; 22896918515SStefan Gränitz using Self = ELFLinkGraphBuilder_aarch64<ELFT>; 22996918515SStefan Gränitz for (const auto &RelSect : Base::Sections) 2302a3b257aSKshitij Jain if (Error Err = Base::forEachRelaRelocation(RelSect, this, 23196918515SStefan Gränitz &Self::addSingleRelocation)) 23296918515SStefan Gränitz return Err; 2332ed91da0SStefan Gränitz 23496918515SStefan Gränitz return Error::success(); 2352ed91da0SStefan Gränitz } 2362ed91da0SStefan Gränitz 23796918515SStefan Gränitz Error addSingleRelocation(const typename ELFT::Rela &Rel, 23896918515SStefan Gränitz const typename ELFT::Shdr &FixupSect, 239091e3648SSteven Wu Block &BlockToFix) { 240ab472c96SSunho Kim using support::ulittle32_t; 24196918515SStefan Gränitz using Base = ELFLinkGraphBuilder<ELFT>; 2422ed91da0SStefan Gränitz 24396918515SStefan Gränitz uint32_t SymbolIndex = Rel.getSymbol(false); 24496918515SStefan Gränitz auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec); 24596918515SStefan Gränitz if (!ObjSymbol) 24696918515SStefan Gränitz return ObjSymbol.takeError(); 2472ed91da0SStefan Gränitz 24896918515SStefan Gränitz Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex); 24996918515SStefan Gränitz if (!GraphSymbol) 25096918515SStefan Gränitz return make_error<StringError>( 25196918515SStefan Gränitz formatv("Could not find symbol at given index, did you add it to " 25296918515SStefan Gränitz "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}", 25396918515SStefan Gränitz SymbolIndex, (*ObjSymbol)->st_shndx, 25496918515SStefan Gränitz Base::GraphSymbols.size()), 25596918515SStefan Gränitz inconvertibleErrorCode()); 2562ed91da0SStefan Gränitz 25796918515SStefan Gränitz uint32_t Type = Rel.getType(false); 258b6553f59SSunho Kim Expected<ELFAArch64RelocationKind> RelocKind = getRelocationKind(Type); 259b6553f59SSunho Kim if (!RelocKind) 260b6553f59SSunho Kim return RelocKind.takeError(); 2612ed91da0SStefan Gränitz 26296918515SStefan Gränitz int64_t Addend = Rel.r_addend; 263118e953bSLang Hames orc::ExecutorAddr FixupAddress = 264118e953bSLang Hames orc::ExecutorAddr(FixupSect.sh_addr) + Rel.r_offset; 265091e3648SSteven Wu Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress(); 266b6553f59SSunho Kim 267ab472c96SSunho Kim // Get a pointer to the fixup content. 268ab472c96SSunho Kim const void *FixupContent = BlockToFix.getContent().data() + 269ab472c96SSunho Kim (FixupAddress - BlockToFix.getAddress()); 270ab472c96SSunho Kim 271b6553f59SSunho Kim Edge::Kind Kind = Edge::Invalid; 272b6553f59SSunho Kim 273b6553f59SSunho Kim switch (*RelocKind) { 27425a9fb12SSunho Kim case ELFCall26: { 275cb33ef7cSLang Hames Kind = aarch64::Branch26PCRel; 276b6553f59SSunho Kim break; 277b6553f59SSunho Kim } 278d395b56aSPavel Samolysov case ELFLdrLo19: { 279d395b56aSPavel Samolysov uint32_t Instr = *(const ulittle32_t *)FixupContent; 280d395b56aSPavel Samolysov if (!aarch64::isLDRLiteral(Instr)) 281d395b56aSPavel Samolysov return make_error<JITLinkError>( 282d395b56aSPavel Samolysov "R_AARCH64_LDR_PREL_LO19 target is not an LDR Literal instruction"); 283d395b56aSPavel Samolysov 284d395b56aSPavel Samolysov Kind = aarch64::LDRLiteral19; 285d395b56aSPavel Samolysov break; 286d395b56aSPavel Samolysov } 287e9676389SJob Noorman case ELFAdrLo21: { 288e9676389SJob Noorman uint32_t Instr = *(const ulittle32_t *)FixupContent; 289e9676389SJob Noorman if (!aarch64::isADR(Instr)) 290e9676389SJob Noorman return make_error<JITLinkError>( 291e9676389SJob Noorman "R_AARCH64_ADR_PREL_LO21 target is not an ADR instruction"); 292e9676389SJob Noorman 293e9676389SJob Noorman Kind = aarch64::ADRLiteral21; 294e9676389SJob Noorman break; 295e9676389SJob Noorman } 29625a9fb12SSunho Kim case ELFAdrPage21: { 29725a9fb12SSunho Kim Kind = aarch64::Page21; 29825a9fb12SSunho Kim break; 29925a9fb12SSunho Kim } 30025a9fb12SSunho Kim case ELFAddAbs12: { 30125a9fb12SSunho Kim Kind = aarch64::PageOffset12; 30225a9fb12SSunho Kim break; 30325a9fb12SSunho Kim } 304ab472c96SSunho Kim case ELFLdSt8Abs12: { 305ab472c96SSunho Kim uint32_t Instr = *(const ulittle32_t *)FixupContent; 306ab472c96SSunho Kim if (!aarch64::isLoadStoreImm12(Instr) || 307ab472c96SSunho Kim aarch64::getPageOffset12Shift(Instr) != 0) 308ab472c96SSunho Kim return make_error<JITLinkError>( 309ab472c96SSunho Kim "R_AARCH64_LDST8_ABS_LO12_NC target is not a " 310ab472c96SSunho Kim "LDRB/STRB (imm12) instruction"); 311ab472c96SSunho Kim 312ab472c96SSunho Kim Kind = aarch64::PageOffset12; 313ab472c96SSunho Kim break; 314ab472c96SSunho Kim } 315ab472c96SSunho Kim case ELFLdSt16Abs12: { 316ab472c96SSunho Kim uint32_t Instr = *(const ulittle32_t *)FixupContent; 317ab472c96SSunho Kim if (!aarch64::isLoadStoreImm12(Instr) || 318ab472c96SSunho Kim aarch64::getPageOffset12Shift(Instr) != 1) 319ab472c96SSunho Kim return make_error<JITLinkError>( 320ab472c96SSunho Kim "R_AARCH64_LDST16_ABS_LO12_NC target is not a " 321ab472c96SSunho Kim "LDRH/STRH (imm12) instruction"); 322ab472c96SSunho Kim 323ab472c96SSunho Kim Kind = aarch64::PageOffset12; 324ab472c96SSunho Kim break; 325ab472c96SSunho Kim } 326ab472c96SSunho Kim case ELFLdSt32Abs12: { 327ab472c96SSunho Kim uint32_t Instr = *(const ulittle32_t *)FixupContent; 328ab472c96SSunho Kim if (!aarch64::isLoadStoreImm12(Instr) || 329ab472c96SSunho Kim aarch64::getPageOffset12Shift(Instr) != 2) 330ab472c96SSunho Kim return make_error<JITLinkError>( 331ab472c96SSunho Kim "R_AARCH64_LDST32_ABS_LO12_NC target is not a " 332ab472c96SSunho Kim "LDR/STR (imm12, 32 bit) instruction"); 333ab472c96SSunho Kim 334ab472c96SSunho Kim Kind = aarch64::PageOffset12; 335ab472c96SSunho Kim break; 336ab472c96SSunho Kim } 337ab472c96SSunho Kim case ELFLdSt64Abs12: { 338ab472c96SSunho Kim uint32_t Instr = *(const ulittle32_t *)FixupContent; 339ab472c96SSunho Kim if (!aarch64::isLoadStoreImm12(Instr) || 340ab472c96SSunho Kim aarch64::getPageOffset12Shift(Instr) != 3) 341ab472c96SSunho Kim return make_error<JITLinkError>( 342ab472c96SSunho Kim "R_AARCH64_LDST64_ABS_LO12_NC target is not a " 343ab472c96SSunho Kim "LDR/STR (imm12, 64 bit) instruction"); 344ab472c96SSunho Kim 345ab472c96SSunho Kim Kind = aarch64::PageOffset12; 346ab472c96SSunho Kim break; 347ab472c96SSunho Kim } 348ab472c96SSunho Kim case ELFLdSt128Abs12: { 349ab472c96SSunho Kim uint32_t Instr = *(const ulittle32_t *)FixupContent; 350ab472c96SSunho Kim if (!aarch64::isLoadStoreImm12(Instr) || 351ab472c96SSunho Kim aarch64::getPageOffset12Shift(Instr) != 4) 352ab472c96SSunho Kim return make_error<JITLinkError>( 353ab472c96SSunho Kim "R_AARCH64_LDST128_ABS_LO12_NC target is not a " 354ab472c96SSunho Kim "LDR/STR (imm12, 128 bit) instruction"); 355ab472c96SSunho Kim 356ab472c96SSunho Kim Kind = aarch64::PageOffset12; 357ab472c96SSunho Kim break; 358ab472c96SSunho Kim } 3593d8061a3SSunho Kim case ELFMovwAbsG0: { 3603d8061a3SSunho Kim uint32_t Instr = *(const ulittle32_t *)FixupContent; 3613d8061a3SSunho Kim if (!aarch64::isMoveWideImm16(Instr) || 3623d8061a3SSunho Kim aarch64::getMoveWide16Shift(Instr) != 0) 3633d8061a3SSunho Kim return make_error<JITLinkError>( 3643d8061a3SSunho Kim "R_AARCH64_MOVW_UABS_G0_NC target is not a " 3653d8061a3SSunho Kim "MOVK/MOVZ (imm16, LSL #0) instruction"); 3663d8061a3SSunho Kim 3673d8061a3SSunho Kim Kind = aarch64::MoveWide16; 3683d8061a3SSunho Kim break; 3693d8061a3SSunho Kim } 3703d8061a3SSunho Kim case ELFMovwAbsG1: { 3713d8061a3SSunho Kim uint32_t Instr = *(const ulittle32_t *)FixupContent; 3723d8061a3SSunho Kim if (!aarch64::isMoveWideImm16(Instr) || 3733d8061a3SSunho Kim aarch64::getMoveWide16Shift(Instr) != 16) 3743d8061a3SSunho Kim return make_error<JITLinkError>( 3753d8061a3SSunho Kim "R_AARCH64_MOVW_UABS_G1_NC target is not a " 3763d8061a3SSunho Kim "MOVK/MOVZ (imm16, LSL #16) instruction"); 3773d8061a3SSunho Kim 3783d8061a3SSunho Kim Kind = aarch64::MoveWide16; 3793d8061a3SSunho Kim break; 3803d8061a3SSunho Kim } 3813d8061a3SSunho Kim case ELFMovwAbsG2: { 3823d8061a3SSunho Kim uint32_t Instr = *(const ulittle32_t *)FixupContent; 3833d8061a3SSunho Kim if (!aarch64::isMoveWideImm16(Instr) || 3843d8061a3SSunho Kim aarch64::getMoveWide16Shift(Instr) != 32) 3853d8061a3SSunho Kim return make_error<JITLinkError>( 3863d8061a3SSunho Kim "R_AARCH64_MOVW_UABS_G2_NC target is not a " 3873d8061a3SSunho Kim "MOVK/MOVZ (imm16, LSL #32) instruction"); 3883d8061a3SSunho Kim 3893d8061a3SSunho Kim Kind = aarch64::MoveWide16; 3903d8061a3SSunho Kim break; 3913d8061a3SSunho Kim } 3923d8061a3SSunho Kim case ELFMovwAbsG3: { 3933d8061a3SSunho Kim uint32_t Instr = *(const ulittle32_t *)FixupContent; 3943d8061a3SSunho Kim if (!aarch64::isMoveWideImm16(Instr) || 3953d8061a3SSunho Kim aarch64::getMoveWide16Shift(Instr) != 48) 3963d8061a3SSunho Kim return make_error<JITLinkError>( 3973d8061a3SSunho Kim "R_AARCH64_MOVW_UABS_G3 target is not a " 3983d8061a3SSunho Kim "MOVK/MOVZ (imm16, LSL #48) instruction"); 3993d8061a3SSunho Kim 4003d8061a3SSunho Kim Kind = aarch64::MoveWide16; 4013d8061a3SSunho Kim break; 4023d8061a3SSunho Kim } 403a9a2eb81SJob Noorman case ELFTstBr14: { 404a9a2eb81SJob Noorman uint32_t Instr = *(const ulittle32_t *)FixupContent; 405a9a2eb81SJob Noorman if (!aarch64::isTestAndBranchImm14(Instr)) 406a9a2eb81SJob Noorman return make_error<JITLinkError>("R_AARCH64_TSTBR14 target is not a " 407a9a2eb81SJob Noorman "test and branch instruction"); 408a9a2eb81SJob Noorman 409a9a2eb81SJob Noorman Kind = aarch64::TestAndBranch14PCRel; 410a9a2eb81SJob Noorman break; 411a9a2eb81SJob Noorman } 412193a8092SJob Noorman case ELFCondBr19: { 413193a8092SJob Noorman uint32_t Instr = *(const ulittle32_t *)FixupContent; 414193a8092SJob Noorman if (!aarch64::isCondBranchImm19(Instr) && 415193a8092SJob Noorman !aarch64::isCompAndBranchImm19(Instr)) 416193a8092SJob Noorman return make_error<JITLinkError>("R_AARCH64_CONDBR19 target is not a " 417193a8092SJob Noorman "conditional branch instruction"); 418193a8092SJob Noorman 419193a8092SJob Noorman Kind = aarch64::CondBranch19PCRel; 420193a8092SJob Noorman break; 421193a8092SJob Noorman } 422fb1b9945SLang Hames case ELFAbs32: { 423fb1b9945SLang Hames Kind = aarch64::Pointer32; 424fb1b9945SLang Hames break; 425fb1b9945SLang Hames } 4261deaa9b8SLang Hames case ELFAbs64: { 4271deaa9b8SLang Hames Kind = aarch64::Pointer64; 4281deaa9b8SLang Hames break; 4291deaa9b8SLang Hames } 4305d5183b1SSunho Kim case ELFPrel32: { 4315d5183b1SSunho Kim Kind = aarch64::Delta32; 4325d5183b1SSunho Kim break; 4335d5183b1SSunho Kim } 4345d5183b1SSunho Kim case ELFPrel64: { 4355d5183b1SSunho Kim Kind = aarch64::Delta64; 4365d5183b1SSunho Kim break; 4375d5183b1SSunho Kim } 4382094fad0SSunho Kim case ELFAdrGOTPage21: { 439cb33ef7cSLang Hames Kind = aarch64::RequestGOTAndTransformToPage21; 4402094fad0SSunho Kim break; 4412094fad0SSunho Kim } 4422094fad0SSunho Kim case ELFLd64GOTLo12: { 443cb33ef7cSLang Hames Kind = aarch64::RequestGOTAndTransformToPageOffset12; 4442094fad0SSunho Kim break; 4452094fad0SSunho Kim } 446199c4003SVladislav Khmelevsky case ELFLd64GOTPAGELo15: { 447199c4003SVladislav Khmelevsky Kind = aarch64::RequestGOTAndTransformToPageOffset15; 448199c4003SVladislav Khmelevsky break; 449199c4003SVladislav Khmelevsky } 45030b6c51fSSunho Kim case ELFTLSDescAdrPage21: { 451cb33ef7cSLang Hames Kind = aarch64::RequestTLSDescEntryAndTransformToPage21; 45230b6c51fSSunho Kim break; 45330b6c51fSSunho Kim } 454cb33ef7cSLang Hames case ELFTLSDescAddLo12: 45530b6c51fSSunho Kim case ELFTLSDescLd64Lo12: { 456cb33ef7cSLang Hames Kind = aarch64::RequestTLSDescEntryAndTransformToPageOffset12; 45730b6c51fSSunho Kim break; 45830b6c51fSSunho Kim } 45930b6c51fSSunho Kim case ELFTLSDescCall: { 46030b6c51fSSunho Kim return Error::success(); 46130b6c51fSSunho Kim } 462b6553f59SSunho Kim }; 463b6553f59SSunho Kim 464b6553f59SSunho Kim Edge GE(Kind, Offset, *GraphSymbol, Addend); 46596918515SStefan Gränitz LLVM_DEBUG({ 46696918515SStefan Gränitz dbgs() << " "; 467b6553f59SSunho Kim printEdge(dbgs(), BlockToFix, GE, aarch64::getEdgeKindName(Kind)); 46896918515SStefan Gränitz dbgs() << "\n"; 46996918515SStefan Gränitz }); 47096918515SStefan Gränitz 471091e3648SSteven Wu BlockToFix.addEdge(std::move(GE)); 47230b6c51fSSunho Kim 4732ed91da0SStefan Gränitz return Error::success(); 4742ed91da0SStefan Gränitz } 4752ed91da0SStefan Gränitz 476b6553f59SSunho Kim /// Return the string name of the given ELF aarch64 edge kind. 477b6553f59SSunho Kim const char *getELFAArch64RelocationKindName(Edge::Kind R) { 478b6553f59SSunho Kim switch (R) { 47925a9fb12SSunho Kim case ELFCall26: 48025a9fb12SSunho Kim return "ELFCall26"; 48125a9fb12SSunho Kim case ELFAdrPage21: 48225a9fb12SSunho Kim return "ELFAdrPage21"; 48325a9fb12SSunho Kim case ELFAddAbs12: 48425a9fb12SSunho Kim return "ELFAddAbs12"; 485ab472c96SSunho Kim case ELFLdSt8Abs12: 486ab472c96SSunho Kim return "ELFLdSt8Abs12"; 487ab472c96SSunho Kim case ELFLdSt16Abs12: 488ab472c96SSunho Kim return "ELFLdSt16Abs12"; 489ab472c96SSunho Kim case ELFLdSt32Abs12: 490ab472c96SSunho Kim return "ELFLdSt32Abs12"; 491ab472c96SSunho Kim case ELFLdSt64Abs12: 492ab472c96SSunho Kim return "ELFLdSt64Abs12"; 493ab472c96SSunho Kim case ELFLdSt128Abs12: 494ab472c96SSunho Kim return "ELFLdSt128Abs12"; 4953d8061a3SSunho Kim case ELFMovwAbsG0: 4963d8061a3SSunho Kim return "ELFMovwAbsG0"; 4973d8061a3SSunho Kim case ELFMovwAbsG1: 4983d8061a3SSunho Kim return "ELFMovwAbsG1"; 4993d8061a3SSunho Kim case ELFMovwAbsG2: 5003d8061a3SSunho Kim return "ELFMovwAbsG2"; 5013d8061a3SSunho Kim case ELFMovwAbsG3: 5023d8061a3SSunho Kim return "ELFMovwAbsG3"; 503fb1b9945SLang Hames case ELFAbs32: 504fb1b9945SLang Hames return "ELFAbs32"; 5051deaa9b8SLang Hames case ELFAbs64: 5061deaa9b8SLang Hames return "ELFAbs64"; 5075d5183b1SSunho Kim case ELFPrel32: 5085d5183b1SSunho Kim return "ELFPrel32"; 5095d5183b1SSunho Kim case ELFPrel64: 5105d5183b1SSunho Kim return "ELFPrel64"; 5112094fad0SSunho Kim case ELFAdrGOTPage21: 5122094fad0SSunho Kim return "ELFAdrGOTPage21"; 5132094fad0SSunho Kim case ELFLd64GOTLo12: 5142094fad0SSunho Kim return "ELFLd64GOTLo12"; 515199c4003SVladislav Khmelevsky case ELFLd64GOTPAGELo15: 516199c4003SVladislav Khmelevsky return "ELFLd64GOTPAGELo15"; 51730b6c51fSSunho Kim case ELFTLSDescAdrPage21: 51830b6c51fSSunho Kim return "ELFTLSDescAdrPage21"; 51930b6c51fSSunho Kim case ELFTLSDescAddLo12: 52030b6c51fSSunho Kim return "ELFTLSDescAddLo12"; 52130b6c51fSSunho Kim case ELFTLSDescLd64Lo12: 52230b6c51fSSunho Kim return "ELFTLSDescLd64Lo12"; 52330b6c51fSSunho Kim case ELFTLSDescCall: 52430b6c51fSSunho Kim return "ELFTLSDescCall"; 525b6553f59SSunho Kim default: 526b6553f59SSunho Kim return getGenericEdgeKindName(static_cast<Edge::Kind>(R)); 527b6553f59SSunho Kim } 528b6553f59SSunho Kim } 529b6553f59SSunho Kim 5302ed91da0SStefan Gränitz public: 5312ed91da0SStefan Gränitz ELFLinkGraphBuilder_aarch64(StringRef FileName, 5322ccf7ed2SJared Wyles const object::ELFFile<ELFT> &Obj, 5332ccf7ed2SJared Wyles std::shared_ptr<orc::SymbolStringPool> SSP, 5342ccf7ed2SJared Wyles Triple TT, SubtargetFeatures Features) 5352ccf7ed2SJared Wyles 5362ccf7ed2SJared Wyles : ELFLinkGraphBuilder<ELFT>(Obj, std::move(SSP), std::move(TT), 5372ccf7ed2SJared Wyles std::move(Features), FileName, 5382ccf7ed2SJared Wyles aarch64::getEdgeKindName) {} 5392ed91da0SStefan Gränitz }; 5402ed91da0SStefan Gränitz 54130b6c51fSSunho Kim // TLS Info Builder. 54230b6c51fSSunho Kim class TLSInfoTableManager_ELF_aarch64 54330b6c51fSSunho Kim : public TableManager<TLSInfoTableManager_ELF_aarch64> { 54430b6c51fSSunho Kim public: 54530b6c51fSSunho Kim static StringRef getSectionName() { return "$__TLSINFO"; } 54630b6c51fSSunho Kim 54730b6c51fSSunho Kim static const uint8_t TLSInfoEntryContent[16]; 54830b6c51fSSunho Kim 54930b6c51fSSunho Kim bool visitEdge(LinkGraph &G, Block *B, Edge &E) { return false; } 55030b6c51fSSunho Kim 55130b6c51fSSunho Kim Symbol &createEntry(LinkGraph &G, Symbol &Target) { 55230b6c51fSSunho Kim // the TLS Info entry's key value will be written by the fixTLVSectionByName 55330b6c51fSSunho Kim // pass, so create mutable content. 55430b6c51fSSunho Kim auto &TLSInfoEntry = G.createMutableContentBlock( 55530b6c51fSSunho Kim getTLSInfoSection(G), G.allocateContent(getTLSInfoEntryContent()), 55630b6c51fSSunho Kim orc::ExecutorAddr(), 8, 0); 55730b6c51fSSunho Kim TLSInfoEntry.addEdge(aarch64::Pointer64, 8, Target, 0); 55830b6c51fSSunho Kim return G.addAnonymousSymbol(TLSInfoEntry, 0, 16, false, false); 55930b6c51fSSunho Kim } 56030b6c51fSSunho Kim 56130b6c51fSSunho Kim private: 56230b6c51fSSunho Kim Section &getTLSInfoSection(LinkGraph &G) { 56330b6c51fSSunho Kim if (!TLSInfoTable) 564d3d9f7caSLang Hames TLSInfoTable = &G.createSection(getSectionName(), orc::MemProt::Read); 56530b6c51fSSunho Kim return *TLSInfoTable; 56630b6c51fSSunho Kim } 56730b6c51fSSunho Kim 56830b6c51fSSunho Kim ArrayRef<char> getTLSInfoEntryContent() const { 56930b6c51fSSunho Kim return {reinterpret_cast<const char *>(TLSInfoEntryContent), 57030b6c51fSSunho Kim sizeof(TLSInfoEntryContent)}; 57130b6c51fSSunho Kim } 57230b6c51fSSunho Kim 57330b6c51fSSunho Kim Section *TLSInfoTable = nullptr; 57430b6c51fSSunho Kim }; 57530b6c51fSSunho Kim 57630b6c51fSSunho Kim const uint8_t TLSInfoTableManager_ELF_aarch64::TLSInfoEntryContent[16] = { 57730b6c51fSSunho Kim 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*pthread key */ 57830b6c51fSSunho Kim 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /*data address*/ 57930b6c51fSSunho Kim }; 58030b6c51fSSunho Kim 58130b6c51fSSunho Kim // TLS Descriptor Builder. 58230b6c51fSSunho Kim class TLSDescTableManager_ELF_aarch64 58330b6c51fSSunho Kim : public TableManager<TLSDescTableManager_ELF_aarch64> { 58430b6c51fSSunho Kim public: 58530b6c51fSSunho Kim TLSDescTableManager_ELF_aarch64( 58630b6c51fSSunho Kim TLSInfoTableManager_ELF_aarch64 &TLSInfoTableManager) 58730b6c51fSSunho Kim : TLSInfoTableManager(TLSInfoTableManager) {} 58830b6c51fSSunho Kim 58930b6c51fSSunho Kim static StringRef getSectionName() { return "$__TLSDESC"; } 59030b6c51fSSunho Kim 59130b6c51fSSunho Kim static const uint8_t TLSDescEntryContent[16]; 59230b6c51fSSunho Kim 59330b6c51fSSunho Kim bool visitEdge(LinkGraph &G, Block *B, Edge &E) { 59430b6c51fSSunho Kim Edge::Kind KindToSet = Edge::Invalid; 59530b6c51fSSunho Kim switch (E.getKind()) { 596cb33ef7cSLang Hames case aarch64::RequestTLSDescEntryAndTransformToPage21: { 59730b6c51fSSunho Kim KindToSet = aarch64::Page21; 59830b6c51fSSunho Kim break; 59930b6c51fSSunho Kim } 600cb33ef7cSLang Hames case aarch64::RequestTLSDescEntryAndTransformToPageOffset12: { 60130b6c51fSSunho Kim KindToSet = aarch64::PageOffset12; 60230b6c51fSSunho Kim break; 60330b6c51fSSunho Kim } 60430b6c51fSSunho Kim default: 60530b6c51fSSunho Kim return false; 60630b6c51fSSunho Kim } 60730b6c51fSSunho Kim assert(KindToSet != Edge::Invalid && 60830b6c51fSSunho Kim "Fell through switch, but no new kind to set"); 60930b6c51fSSunho Kim DEBUG_WITH_TYPE("jitlink", { 61030b6c51fSSunho Kim dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at " 61130b6c51fSSunho Kim << B->getFixupAddress(E) << " (" << B->getAddress() << " + " 61230b6c51fSSunho Kim << formatv("{0:x}", E.getOffset()) << ")\n"; 61330b6c51fSSunho Kim }); 61430b6c51fSSunho Kim E.setKind(KindToSet); 61530b6c51fSSunho Kim E.setTarget(getEntryForTarget(G, E.getTarget())); 61630b6c51fSSunho Kim return true; 61730b6c51fSSunho Kim } 61830b6c51fSSunho Kim 61930b6c51fSSunho Kim Symbol &createEntry(LinkGraph &G, Symbol &Target) { 62030b6c51fSSunho Kim auto &EntryBlock = 62130b6c51fSSunho Kim G.createContentBlock(getTLSDescSection(G), getTLSDescBlockContent(), 62230b6c51fSSunho Kim orc::ExecutorAddr(), 8, 0); 62330b6c51fSSunho Kim EntryBlock.addEdge(aarch64::Pointer64, 0, getTLSDescResolver(G), 0); 62430b6c51fSSunho Kim EntryBlock.addEdge(aarch64::Pointer64, 8, 62530b6c51fSSunho Kim TLSInfoTableManager.getEntryForTarget(G, Target), 0); 62630b6c51fSSunho Kim return G.addAnonymousSymbol(EntryBlock, 0, 8, false, false); 62730b6c51fSSunho Kim } 62830b6c51fSSunho Kim 62930b6c51fSSunho Kim private: 63030b6c51fSSunho Kim Section &getTLSDescSection(LinkGraph &G) { 63130b6c51fSSunho Kim if (!GOTSection) 632d3d9f7caSLang Hames GOTSection = &G.createSection(getSectionName(), orc::MemProt::Read); 63330b6c51fSSunho Kim return *GOTSection; 63430b6c51fSSunho Kim } 63530b6c51fSSunho Kim 63630b6c51fSSunho Kim Symbol &getTLSDescResolver(LinkGraph &G) { 63730b6c51fSSunho Kim if (!TLSDescResolver) 63875404e9eSLang Hames TLSDescResolver = &G.addExternalSymbol("__tlsdesc_resolver", 8, false); 63930b6c51fSSunho Kim return *TLSDescResolver; 64030b6c51fSSunho Kim } 64130b6c51fSSunho Kim 64230b6c51fSSunho Kim ArrayRef<char> getTLSDescBlockContent() { 64330b6c51fSSunho Kim return {reinterpret_cast<const char *>(TLSDescEntryContent), 64430b6c51fSSunho Kim sizeof(TLSDescEntryContent)}; 64530b6c51fSSunho Kim } 64630b6c51fSSunho Kim 64730b6c51fSSunho Kim Section *GOTSection = nullptr; 64830b6c51fSSunho Kim Symbol *TLSDescResolver = nullptr; 64930b6c51fSSunho Kim TLSInfoTableManager_ELF_aarch64 &TLSInfoTableManager; 65030b6c51fSSunho Kim }; 65130b6c51fSSunho Kim 65230b6c51fSSunho Kim const uint8_t TLSDescTableManager_ELF_aarch64::TLSDescEntryContent[16] = { 65330b6c51fSSunho Kim 0x00, 0x00, 0x00, 0x00, 65430b6c51fSSunho Kim 0x00, 0x00, 0x00, 0x00, /*resolver function pointer*/ 65530b6c51fSSunho Kim 0x00, 0x00, 0x00, 0x00, 65630b6c51fSSunho Kim 0x00, 0x00, 0x00, 0x00 /*pointer to tls info*/ 65730b6c51fSSunho Kim }; 65830b6c51fSSunho Kim 659db372258SSunho Kim Error buildTables_ELF_aarch64(LinkGraph &G) { 660db372258SSunho Kim LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n"); 6612094fad0SSunho Kim 662*42595bdaSLang Hames aarch64::GOTTableManager GOT(G); 663*42595bdaSLang Hames aarch64::PLTTableManager PLT(G, GOT); 66430b6c51fSSunho Kim TLSInfoTableManager_ELF_aarch64 TLSInfo; 66530b6c51fSSunho Kim TLSDescTableManager_ELF_aarch64 TLSDesc(TLSInfo); 66630b6c51fSSunho Kim visitExistingEdges(G, GOT, PLT, TLSDesc, TLSInfo); 667db372258SSunho Kim return Error::success(); 6682094fad0SSunho Kim } 6692094fad0SSunho Kim 670db372258SSunho Kim } // namespace 6712094fad0SSunho Kim 672db372258SSunho Kim namespace llvm { 673db372258SSunho Kim namespace jitlink { 6742094fad0SSunho Kim 6752ccf7ed2SJared Wyles Expected<std::unique_ptr<LinkGraph>> createLinkGraphFromELFObject_aarch64( 6762ccf7ed2SJared Wyles MemoryBufferRef ObjectBuffer, std::shared_ptr<orc::SymbolStringPool> SSP) { 6772ed91da0SStefan Gränitz LLVM_DEBUG({ 6782ed91da0SStefan Gränitz dbgs() << "Building jitlink graph for new input " 6792ed91da0SStefan Gränitz << ObjectBuffer.getBufferIdentifier() << "...\n"; 6802ed91da0SStefan Gränitz }); 6812ed91da0SStefan Gränitz 6822ed91da0SStefan Gränitz auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer); 6832ed91da0SStefan Gränitz if (!ELFObj) 6842ed91da0SStefan Gränitz return ELFObj.takeError(); 6852ed91da0SStefan Gränitz 686348d0a6bSJob Noorman auto Features = (*ELFObj)->getFeatures(); 687348d0a6bSJob Noorman if (!Features) 688348d0a6bSJob Noorman return Features.takeError(); 689348d0a6bSJob Noorman 6902ed91da0SStefan Gränitz assert((*ELFObj)->getArch() == Triple::aarch64 && 6912ed91da0SStefan Gränitz "Only AArch64 (little endian) is supported for now"); 6922ed91da0SStefan Gränitz 6932ed91da0SStefan Gränitz auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj); 694348d0a6bSJob Noorman return ELFLinkGraphBuilder_aarch64<object::ELF64LE>( 6952ccf7ed2SJared Wyles (*ELFObj)->getFileName(), ELFObjFile.getELFFile(), std::move(SSP), 69652b88457SJob Noorman (*ELFObj)->makeTriple(), std::move(*Features)) 6972ed91da0SStefan Gränitz .buildGraph(); 6982ed91da0SStefan Gränitz } 6992ed91da0SStefan Gränitz 7002ed91da0SStefan Gränitz void link_ELF_aarch64(std::unique_ptr<LinkGraph> G, 7012ed91da0SStefan Gränitz std::unique_ptr<JITLinkContext> Ctx) { 7022ed91da0SStefan Gränitz PassConfiguration Config; 7032ed91da0SStefan Gränitz const Triple &TT = G->getTargetTriple(); 7042ed91da0SStefan Gränitz if (Ctx->shouldAddDefaultTargetPasses(TT)) { 70594239712SEymen Ünay // Add eh-frame passes. 706f8a9536cSSunho Kim Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame")); 707f8a9536cSSunho Kim Config.PrePrunePasses.push_back(EHFrameEdgeFixer( 708f8a9536cSSunho Kim ".eh_frame", 8, aarch64::Pointer32, aarch64::Pointer64, 709f8a9536cSSunho Kim aarch64::Delta32, aarch64::Delta64, aarch64::NegDelta32)); 71068c14f58STom Stellard Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame")); 711db372258SSunho Kim 712db372258SSunho Kim // Add a mark-live pass. 7132ed91da0SStefan Gränitz if (auto MarkLive = Ctx->getMarkLivePass(TT)) 7142ed91da0SStefan Gränitz Config.PrePrunePasses.push_back(std::move(MarkLive)); 7152ed91da0SStefan Gränitz else 7162ed91da0SStefan Gränitz Config.PrePrunePasses.push_back(markAllSymbolsLive); 7172094fad0SSunho Kim 718488a1873SLang Hames // Resolve any external section start / end symbols. 719488a1873SLang Hames Config.PostAllocationPasses.push_back( 720488a1873SLang Hames createDefineExternalSectionStartAndEndSymbolsPass( 721488a1873SLang Hames identifyELFSectionStartAndEndSymbols)); 722488a1873SLang Hames 72330b6c51fSSunho Kim // Add an in-place GOT/TLS/Stubs build pass. 724db372258SSunho Kim Config.PostPrunePasses.push_back(buildTables_ELF_aarch64); 725db372258SSunho Kim } 7262094fad0SSunho Kim 7272ed91da0SStefan Gränitz if (auto Err = Ctx->modifyPassConfig(*G, Config)) 7282ed91da0SStefan Gränitz return Ctx->notifyFailed(std::move(Err)); 7292ed91da0SStefan Gränitz 7302ed91da0SStefan Gränitz ELFJITLinker_aarch64::link(std::move(Ctx), std::move(G), std::move(Config)); 7312ed91da0SStefan Gränitz } 7322ed91da0SStefan Gränitz 7332ed91da0SStefan Gränitz } // namespace jitlink 7342ed91da0SStefan Gränitz } // namespace llvm 735