735 lines · cpp
1//===----- ELF_aarch64.cpp - JIT linker implementation for ELF/aarch64 ----===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// ELF/aarch64 jit-link implementation.10//11//===----------------------------------------------------------------------===//12 13#include "llvm/ExecutionEngine/JITLink/ELF_aarch64.h"14#include "llvm/BinaryFormat/ELF.h"15#include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"16#include "llvm/ExecutionEngine/JITLink/aarch64.h"17#include "llvm/Object/ELFObjectFile.h"18#include "llvm/Support/Endian.h"19 20#include "DefineExternalSectionStartAndEndSymbols.h"21#include "EHFrameSupportImpl.h"22#include "ELFLinkGraphBuilder.h"23#include "JITLinkGeneric.h"24 25#define DEBUG_TYPE "jitlink"26 27using namespace llvm;28using namespace llvm::jitlink;29 30namespace {31 32constexpr StringRef ELFGOTSymbolName = "_GLOBAL_OFFSET_TABLE_";33 34class ELFJITLinker_aarch64 : public JITLinker<ELFJITLinker_aarch64> {35 friend class JITLinker<ELFJITLinker_aarch64>;36 37public:38 ELFJITLinker_aarch64(std::unique_ptr<JITLinkContext> Ctx,39 std::unique_ptr<LinkGraph> G,40 PassConfiguration PassConfig)41 : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {42 if (shouldAddDefaultTargetPasses(getGraph().getTargetTriple()))43 getPassConfig().PostAllocationPasses.push_back(44 [this](LinkGraph &G) { return getOrCreateGOTSymbol(G); });45 }46 47private:48 Symbol *GOTSymbol = nullptr;49 50 Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {51 return aarch64::applyFixup(G, B, E, GOTSymbol);52 }53 54 Error getOrCreateGOTSymbol(LinkGraph &G) {55 auto InteredGOTSymbolName =56 G.getSymbolStringPool()->intern(ELFGOTSymbolName);57 58 auto DefineExternalGOTSymbolIfPresent =59 createDefineExternalSectionStartAndEndSymbolsPass(60 [&](LinkGraph &LG, Symbol &Sym) -> SectionRangeSymbolDesc {61 if (*Sym.getName() == ELFGOTSymbolName)62 if (auto *GOTSection = G.findSectionByName(63 aarch64::GOTTableManager::getSectionName())) {64 GOTSymbol = &Sym;65 return {*GOTSection, true};66 }67 return {};68 });69 70 // Try to attach _GLOBAL_OFFSET_TABLE_ to the GOT if it's defined as an71 // external.72 if (auto Err = DefineExternalGOTSymbolIfPresent(G))73 return Err;74 75 // If we succeeded then we're done.76 if (GOTSymbol)77 return Error::success();78 79 // Otherwise look for a GOT section: If it already has a start symbol we'll80 // record it, otherwise we'll create our own.81 // If there's a GOT section but we didn't find an external GOT symbol...82 if (auto *GOTSection =83 G.findSectionByName(aarch64::GOTTableManager::getSectionName())) {84 85 // Check for an existing defined symbol.86 for (auto *Sym : GOTSection->symbols())87 if (Sym->getName() == InteredGOTSymbolName) {88 GOTSymbol = Sym;89 return Error::success();90 }91 92 // If there's no defined symbol then create one.93 SectionRange SR(*GOTSection);94 if (SR.empty())95 GOTSymbol =96 // FIXME: we should only do this once97 &G.addAbsoluteSymbol(InteredGOTSymbolName, orc::ExecutorAddr(), 0,98 Linkage::Strong, Scope::Local, true);99 else100 GOTSymbol =101 &G.addDefinedSymbol(*SR.getFirstBlock(), 0, InteredGOTSymbolName, 0,102 Linkage::Strong, Scope::Local, false, true);103 }104 105 // If we still haven't found a GOT symbol then double check the externals.106 // We may have a GOT-relative reference but no GOT section, in which case107 // we just need to point the GOT symbol at some address in this graph.108 if (!GOTSymbol) {109 for (auto *Sym : G.external_symbols()) {110 if (*Sym->getName() == ELFGOTSymbolName) {111 auto Blocks = G.blocks();112 if (!Blocks.empty()) {113 G.makeAbsolute(*Sym, (*Blocks.begin())->getAddress());114 GOTSymbol = Sym;115 break;116 }117 }118 }119 }120 121 return Error::success();122 }123};124 125template <typename ELFT>126class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {127private:128 enum ELFAArch64RelocationKind : Edge::Kind {129 ELFCall26 = Edge::FirstRelocation,130 ELFLdrLo19,131 ELFAdrLo21,132 ELFAdrPage21,133 ELFAddAbs12,134 ELFLdSt8Abs12,135 ELFLdSt16Abs12,136 ELFLdSt32Abs12,137 ELFLdSt64Abs12,138 ELFLdSt128Abs12,139 ELFMovwAbsG0,140 ELFMovwAbsG1,141 ELFMovwAbsG2,142 ELFMovwAbsG3,143 ELFTstBr14,144 ELFCondBr19,145 ELFAbs32,146 ELFAbs64,147 ELFPrel32,148 ELFPrel64,149 ELFAdrGOTPage21,150 ELFLd64GOTLo12,151 ELFLd64GOTPAGELo15,152 ELFTLSDescAdrPage21,153 ELFTLSDescAddLo12,154 ELFTLSDescLd64Lo12,155 ELFTLSDescCall,156 };157 158 static Expected<ELFAArch64RelocationKind>159 getRelocationKind(const uint32_t Type) {160 using namespace aarch64;161 switch (Type) {162 case ELF::R_AARCH64_CALL26:163 case ELF::R_AARCH64_JUMP26:164 return ELFCall26;165 case ELF::R_AARCH64_LD_PREL_LO19:166 return ELFLdrLo19;167 case ELF::R_AARCH64_ADR_PREL_LO21:168 return ELFAdrLo21;169 case ELF::R_AARCH64_ADR_PREL_PG_HI21:170 return ELFAdrPage21;171 case ELF::R_AARCH64_ADD_ABS_LO12_NC:172 return ELFAddAbs12;173 case ELF::R_AARCH64_LDST8_ABS_LO12_NC:174 return ELFLdSt8Abs12;175 case ELF::R_AARCH64_LDST16_ABS_LO12_NC:176 return ELFLdSt16Abs12;177 case ELF::R_AARCH64_LDST32_ABS_LO12_NC:178 return ELFLdSt32Abs12;179 case ELF::R_AARCH64_LDST64_ABS_LO12_NC:180 return ELFLdSt64Abs12;181 case ELF::R_AARCH64_LDST128_ABS_LO12_NC:182 return ELFLdSt128Abs12;183 case ELF::R_AARCH64_MOVW_UABS_G0_NC:184 return ELFMovwAbsG0;185 case ELF::R_AARCH64_MOVW_UABS_G1_NC:186 return ELFMovwAbsG1;187 case ELF::R_AARCH64_MOVW_UABS_G2_NC:188 return ELFMovwAbsG2;189 case ELF::R_AARCH64_MOVW_UABS_G3:190 return ELFMovwAbsG3;191 case ELF::R_AARCH64_TSTBR14:192 return ELFTstBr14;193 case ELF::R_AARCH64_CONDBR19:194 return ELFCondBr19;195 case ELF::R_AARCH64_ABS32:196 return ELFAbs32;197 case ELF::R_AARCH64_ABS64:198 return ELFAbs64;199 case ELF::R_AARCH64_PREL32:200 return ELFPrel32;201 case ELF::R_AARCH64_PREL64:202 return ELFPrel64;203 case ELF::R_AARCH64_ADR_GOT_PAGE:204 return ELFAdrGOTPage21;205 case ELF::R_AARCH64_LD64_GOT_LO12_NC:206 return ELFLd64GOTLo12;207 case ELF::R_AARCH64_LD64_GOTPAGE_LO15:208 return ELFLd64GOTPAGELo15;209 case ELF::R_AARCH64_TLSDESC_ADR_PAGE21:210 return ELFTLSDescAdrPage21;211 case ELF::R_AARCH64_TLSDESC_ADD_LO12:212 return ELFTLSDescAddLo12;213 case ELF::R_AARCH64_TLSDESC_LD64_LO12:214 return ELFTLSDescLd64Lo12;215 case ELF::R_AARCH64_TLSDESC_CALL:216 return ELFTLSDescCall;217 }218 219 return make_error<JITLinkError>(220 "Unsupported aarch64 relocation:" + formatv("{0:d}: ", Type) +221 object::getELFRelocationTypeName(ELF::EM_AARCH64, Type));222 }223 224 Error addRelocations() override {225 LLVM_DEBUG(dbgs() << "Processing relocations:\n");226 227 using Base = ELFLinkGraphBuilder<ELFT>;228 using Self = ELFLinkGraphBuilder_aarch64<ELFT>;229 for (const auto &RelSect : Base::Sections)230 if (Error Err = Base::forEachRelaRelocation(RelSect, this,231 &Self::addSingleRelocation))232 return Err;233 234 return Error::success();235 }236 237 Error addSingleRelocation(const typename ELFT::Rela &Rel,238 const typename ELFT::Shdr &FixupSect,239 Block &BlockToFix) {240 using support::ulittle32_t;241 using Base = ELFLinkGraphBuilder<ELFT>;242 243 uint32_t SymbolIndex = Rel.getSymbol(false);244 auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);245 if (!ObjSymbol)246 return ObjSymbol.takeError();247 248 Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex);249 if (!GraphSymbol)250 return make_error<StringError>(251 formatv("Could not find symbol at given index, did you add it to "252 "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",253 SymbolIndex, (*ObjSymbol)->st_shndx,254 Base::GraphSymbols.size()),255 inconvertibleErrorCode());256 257 uint32_t Type = Rel.getType(false);258 Expected<ELFAArch64RelocationKind> RelocKind = getRelocationKind(Type);259 if (!RelocKind)260 return RelocKind.takeError();261 262 int64_t Addend = Rel.r_addend;263 orc::ExecutorAddr FixupAddress =264 orc::ExecutorAddr(FixupSect.sh_addr) + Rel.r_offset;265 Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();266 267 // Get a pointer to the fixup content.268 const void *FixupContent = BlockToFix.getContent().data() +269 (FixupAddress - BlockToFix.getAddress());270 271 Edge::Kind Kind = Edge::Invalid;272 273 switch (*RelocKind) {274 case ELFCall26: {275 Kind = aarch64::Branch26PCRel;276 break;277 }278 case ELFLdrLo19: {279 uint32_t Instr = *(const ulittle32_t *)FixupContent;280 if (!aarch64::isLDRLiteral(Instr))281 return make_error<JITLinkError>(282 "R_AARCH64_LDR_PREL_LO19 target is not an LDR Literal instruction");283 284 Kind = aarch64::LDRLiteral19;285 break;286 }287 case ELFAdrLo21: {288 uint32_t Instr = *(const ulittle32_t *)FixupContent;289 if (!aarch64::isADR(Instr))290 return make_error<JITLinkError>(291 "R_AARCH64_ADR_PREL_LO21 target is not an ADR instruction");292 293 Kind = aarch64::ADRLiteral21;294 break;295 }296 case ELFAdrPage21: {297 Kind = aarch64::Page21;298 break;299 }300 case ELFAddAbs12: {301 Kind = aarch64::PageOffset12;302 break;303 }304 case ELFLdSt8Abs12: {305 uint32_t Instr = *(const ulittle32_t *)FixupContent;306 if (!aarch64::isLoadStoreImm12(Instr) ||307 aarch64::getPageOffset12Shift(Instr) != 0)308 return make_error<JITLinkError>(309 "R_AARCH64_LDST8_ABS_LO12_NC target is not a "310 "LDRB/STRB (imm12) instruction");311 312 Kind = aarch64::PageOffset12;313 break;314 }315 case ELFLdSt16Abs12: {316 uint32_t Instr = *(const ulittle32_t *)FixupContent;317 if (!aarch64::isLoadStoreImm12(Instr) ||318 aarch64::getPageOffset12Shift(Instr) != 1)319 return make_error<JITLinkError>(320 "R_AARCH64_LDST16_ABS_LO12_NC target is not a "321 "LDRH/STRH (imm12) instruction");322 323 Kind = aarch64::PageOffset12;324 break;325 }326 case ELFLdSt32Abs12: {327 uint32_t Instr = *(const ulittle32_t *)FixupContent;328 if (!aarch64::isLoadStoreImm12(Instr) ||329 aarch64::getPageOffset12Shift(Instr) != 2)330 return make_error<JITLinkError>(331 "R_AARCH64_LDST32_ABS_LO12_NC target is not a "332 "LDR/STR (imm12, 32 bit) instruction");333 334 Kind = aarch64::PageOffset12;335 break;336 }337 case ELFLdSt64Abs12: {338 uint32_t Instr = *(const ulittle32_t *)FixupContent;339 if (!aarch64::isLoadStoreImm12(Instr) ||340 aarch64::getPageOffset12Shift(Instr) != 3)341 return make_error<JITLinkError>(342 "R_AARCH64_LDST64_ABS_LO12_NC target is not a "343 "LDR/STR (imm12, 64 bit) instruction");344 345 Kind = aarch64::PageOffset12;346 break;347 }348 case ELFLdSt128Abs12: {349 uint32_t Instr = *(const ulittle32_t *)FixupContent;350 if (!aarch64::isLoadStoreImm12(Instr) ||351 aarch64::getPageOffset12Shift(Instr) != 4)352 return make_error<JITLinkError>(353 "R_AARCH64_LDST128_ABS_LO12_NC target is not a "354 "LDR/STR (imm12, 128 bit) instruction");355 356 Kind = aarch64::PageOffset12;357 break;358 }359 case ELFMovwAbsG0: {360 uint32_t Instr = *(const ulittle32_t *)FixupContent;361 if (!aarch64::isMoveWideImm16(Instr) ||362 aarch64::getMoveWide16Shift(Instr) != 0)363 return make_error<JITLinkError>(364 "R_AARCH64_MOVW_UABS_G0_NC target is not a "365 "MOVK/MOVZ (imm16, LSL #0) instruction");366 367 Kind = aarch64::MoveWide16;368 break;369 }370 case ELFMovwAbsG1: {371 uint32_t Instr = *(const ulittle32_t *)FixupContent;372 if (!aarch64::isMoveWideImm16(Instr) ||373 aarch64::getMoveWide16Shift(Instr) != 16)374 return make_error<JITLinkError>(375 "R_AARCH64_MOVW_UABS_G1_NC target is not a "376 "MOVK/MOVZ (imm16, LSL #16) instruction");377 378 Kind = aarch64::MoveWide16;379 break;380 }381 case ELFMovwAbsG2: {382 uint32_t Instr = *(const ulittle32_t *)FixupContent;383 if (!aarch64::isMoveWideImm16(Instr) ||384 aarch64::getMoveWide16Shift(Instr) != 32)385 return make_error<JITLinkError>(386 "R_AARCH64_MOVW_UABS_G2_NC target is not a "387 "MOVK/MOVZ (imm16, LSL #32) instruction");388 389 Kind = aarch64::MoveWide16;390 break;391 }392 case ELFMovwAbsG3: {393 uint32_t Instr = *(const ulittle32_t *)FixupContent;394 if (!aarch64::isMoveWideImm16(Instr) ||395 aarch64::getMoveWide16Shift(Instr) != 48)396 return make_error<JITLinkError>(397 "R_AARCH64_MOVW_UABS_G3 target is not a "398 "MOVK/MOVZ (imm16, LSL #48) instruction");399 400 Kind = aarch64::MoveWide16;401 break;402 }403 case ELFTstBr14: {404 uint32_t Instr = *(const ulittle32_t *)FixupContent;405 if (!aarch64::isTestAndBranchImm14(Instr))406 return make_error<JITLinkError>("R_AARCH64_TSTBR14 target is not a "407 "test and branch instruction");408 409 Kind = aarch64::TestAndBranch14PCRel;410 break;411 }412 case ELFCondBr19: {413 uint32_t Instr = *(const ulittle32_t *)FixupContent;414 if (!aarch64::isCondBranchImm19(Instr) &&415 !aarch64::isCompAndBranchImm19(Instr))416 return make_error<JITLinkError>("R_AARCH64_CONDBR19 target is not a "417 "conditional branch instruction");418 419 Kind = aarch64::CondBranch19PCRel;420 break;421 }422 case ELFAbs32: {423 Kind = aarch64::Pointer32;424 break;425 }426 case ELFAbs64: {427 Kind = aarch64::Pointer64;428 break;429 }430 case ELFPrel32: {431 Kind = aarch64::Delta32;432 break;433 }434 case ELFPrel64: {435 Kind = aarch64::Delta64;436 break;437 }438 case ELFAdrGOTPage21: {439 Kind = aarch64::RequestGOTAndTransformToPage21;440 break;441 }442 case ELFLd64GOTLo12: {443 Kind = aarch64::RequestGOTAndTransformToPageOffset12;444 break;445 }446 case ELFLd64GOTPAGELo15: {447 Kind = aarch64::RequestGOTAndTransformToPageOffset15;448 break;449 }450 case ELFTLSDescAdrPage21: {451 Kind = aarch64::RequestTLSDescEntryAndTransformToPage21;452 break;453 }454 case ELFTLSDescAddLo12:455 case ELFTLSDescLd64Lo12: {456 Kind = aarch64::RequestTLSDescEntryAndTransformToPageOffset12;457 break;458 }459 case ELFTLSDescCall: {460 return Error::success();461 }462 };463 464 Edge GE(Kind, Offset, *GraphSymbol, Addend);465 LLVM_DEBUG({466 dbgs() << " ";467 printEdge(dbgs(), BlockToFix, GE, aarch64::getEdgeKindName(Kind));468 dbgs() << "\n";469 });470 471 BlockToFix.addEdge(std::move(GE));472 473 return Error::success();474 }475 476 /// Return the string name of the given ELF aarch64 edge kind.477 const char *getELFAArch64RelocationKindName(Edge::Kind R) {478 switch (R) {479 case ELFCall26:480 return "ELFCall26";481 case ELFAdrPage21:482 return "ELFAdrPage21";483 case ELFAddAbs12:484 return "ELFAddAbs12";485 case ELFLdSt8Abs12:486 return "ELFLdSt8Abs12";487 case ELFLdSt16Abs12:488 return "ELFLdSt16Abs12";489 case ELFLdSt32Abs12:490 return "ELFLdSt32Abs12";491 case ELFLdSt64Abs12:492 return "ELFLdSt64Abs12";493 case ELFLdSt128Abs12:494 return "ELFLdSt128Abs12";495 case ELFMovwAbsG0:496 return "ELFMovwAbsG0";497 case ELFMovwAbsG1:498 return "ELFMovwAbsG1";499 case ELFMovwAbsG2:500 return "ELFMovwAbsG2";501 case ELFMovwAbsG3:502 return "ELFMovwAbsG3";503 case ELFAbs32:504 return "ELFAbs32";505 case ELFAbs64:506 return "ELFAbs64";507 case ELFPrel32:508 return "ELFPrel32";509 case ELFPrel64:510 return "ELFPrel64";511 case ELFAdrGOTPage21:512 return "ELFAdrGOTPage21";513 case ELFLd64GOTLo12:514 return "ELFLd64GOTLo12";515 case ELFLd64GOTPAGELo15:516 return "ELFLd64GOTPAGELo15";517 case ELFTLSDescAdrPage21:518 return "ELFTLSDescAdrPage21";519 case ELFTLSDescAddLo12:520 return "ELFTLSDescAddLo12";521 case ELFTLSDescLd64Lo12:522 return "ELFTLSDescLd64Lo12";523 case ELFTLSDescCall:524 return "ELFTLSDescCall";525 default:526 return getGenericEdgeKindName(R);527 }528 }529 530public:531 ELFLinkGraphBuilder_aarch64(StringRef FileName,532 const object::ELFFile<ELFT> &Obj,533 std::shared_ptr<orc::SymbolStringPool> SSP,534 Triple TT, SubtargetFeatures Features)535 536 : ELFLinkGraphBuilder<ELFT>(Obj, std::move(SSP), std::move(TT),537 std::move(Features), FileName,538 aarch64::getEdgeKindName) {}539};540 541// TLS Info Builder.542class TLSInfoTableManager_ELF_aarch64543 : public TableManager<TLSInfoTableManager_ELF_aarch64> {544public:545 static StringRef getSectionName() { return "$__TLSINFO"; }546 547 static const uint8_t TLSInfoEntryContent[16];548 549 bool visitEdge(LinkGraph &G, Block *B, Edge &E) { return false; }550 551 Symbol &createEntry(LinkGraph &G, Symbol &Target) {552 // the TLS Info entry's key value will be written by the fixTLVSectionByName553 // pass, so create mutable content.554 auto &TLSInfoEntry = G.createMutableContentBlock(555 getTLSInfoSection(G), G.allocateContent(getTLSInfoEntryContent()),556 orc::ExecutorAddr(), 8, 0);557 TLSInfoEntry.addEdge(aarch64::Pointer64, 8, Target, 0);558 return G.addAnonymousSymbol(TLSInfoEntry, 0, 16, false, false);559 }560 561private:562 Section &getTLSInfoSection(LinkGraph &G) {563 if (!TLSInfoTable)564 TLSInfoTable = &G.createSection(getSectionName(), orc::MemProt::Read);565 return *TLSInfoTable;566 }567 568 ArrayRef<char> getTLSInfoEntryContent() const {569 return {reinterpret_cast<const char *>(TLSInfoEntryContent),570 sizeof(TLSInfoEntryContent)};571 }572 573 Section *TLSInfoTable = nullptr;574};575 576const uint8_t TLSInfoTableManager_ELF_aarch64::TLSInfoEntryContent[16] = {577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*pthread key */578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /*data address*/579};580 581// TLS Descriptor Builder.582class TLSDescTableManager_ELF_aarch64583 : public TableManager<TLSDescTableManager_ELF_aarch64> {584public:585 TLSDescTableManager_ELF_aarch64(586 TLSInfoTableManager_ELF_aarch64 &TLSInfoTableManager)587 : TLSInfoTableManager(TLSInfoTableManager) {}588 589 static StringRef getSectionName() { return "$__TLSDESC"; }590 591 static const uint8_t TLSDescEntryContent[16];592 593 bool visitEdge(LinkGraph &G, Block *B, Edge &E) {594 Edge::Kind KindToSet = Edge::Invalid;595 switch (E.getKind()) {596 case aarch64::RequestTLSDescEntryAndTransformToPage21: {597 KindToSet = aarch64::Page21;598 break;599 }600 case aarch64::RequestTLSDescEntryAndTransformToPageOffset12: {601 KindToSet = aarch64::PageOffset12;602 break;603 }604 default:605 return false;606 }607 assert(KindToSet != Edge::Invalid &&608 "Fell through switch, but no new kind to set");609 DEBUG_WITH_TYPE("jitlink", {610 dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at "611 << B->getFixupAddress(E) << " (" << B->getAddress() << " + "612 << formatv("{0:x}", E.getOffset()) << ")\n";613 });614 E.setKind(KindToSet);615 E.setTarget(getEntryForTarget(G, E.getTarget()));616 return true;617 }618 619 Symbol &createEntry(LinkGraph &G, Symbol &Target) {620 auto &EntryBlock =621 G.createContentBlock(getTLSDescSection(G), getTLSDescBlockContent(),622 orc::ExecutorAddr(), 8, 0);623 EntryBlock.addEdge(aarch64::Pointer64, 0, getTLSDescResolver(G), 0);624 EntryBlock.addEdge(aarch64::Pointer64, 8,625 TLSInfoTableManager.getEntryForTarget(G, Target), 0);626 return G.addAnonymousSymbol(EntryBlock, 0, 8, false, false);627 }628 629private:630 Section &getTLSDescSection(LinkGraph &G) {631 if (!GOTSection)632 GOTSection = &G.createSection(getSectionName(), orc::MemProt::Read);633 return *GOTSection;634 }635 636 Symbol &getTLSDescResolver(LinkGraph &G) {637 if (!TLSDescResolver)638 TLSDescResolver = &G.addExternalSymbol("__tlsdesc_resolver", 8, false);639 return *TLSDescResolver;640 }641 642 ArrayRef<char> getTLSDescBlockContent() {643 return {reinterpret_cast<const char *>(TLSDescEntryContent),644 sizeof(TLSDescEntryContent)};645 }646 647 Section *GOTSection = nullptr;648 Symbol *TLSDescResolver = nullptr;649 TLSInfoTableManager_ELF_aarch64 &TLSInfoTableManager;650};651 652const uint8_t TLSDescTableManager_ELF_aarch64::TLSDescEntryContent[16] = {653 0x00, 0x00, 0x00, 0x00,654 0x00, 0x00, 0x00, 0x00, /*resolver function pointer*/655 0x00, 0x00, 0x00, 0x00,656 0x00, 0x00, 0x00, 0x00 /*pointer to tls info*/657};658 659Error buildTables_ELF_aarch64(LinkGraph &G) {660 LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");661 662 aarch64::GOTTableManager GOT(G);663 aarch64::PLTTableManager PLT(G, GOT);664 TLSInfoTableManager_ELF_aarch64 TLSInfo;665 TLSDescTableManager_ELF_aarch64 TLSDesc(TLSInfo);666 visitExistingEdges(G, GOT, PLT, TLSDesc, TLSInfo);667 return Error::success();668}669 670} // namespace671 672namespace llvm {673namespace jitlink {674 675Expected<std::unique_ptr<LinkGraph>> createLinkGraphFromELFObject_aarch64(676 MemoryBufferRef ObjectBuffer, std::shared_ptr<orc::SymbolStringPool> SSP) {677 LLVM_DEBUG({678 dbgs() << "Building jitlink graph for new input "679 << ObjectBuffer.getBufferIdentifier() << "...\n";680 });681 682 auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer);683 if (!ELFObj)684 return ELFObj.takeError();685 686 auto Features = (*ELFObj)->getFeatures();687 if (!Features)688 return Features.takeError();689 690 assert((*ELFObj)->getArch() == Triple::aarch64 &&691 "Only AArch64 (little endian) is supported for now");692 693 auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);694 return ELFLinkGraphBuilder_aarch64<object::ELF64LE>(695 (*ELFObj)->getFileName(), ELFObjFile.getELFFile(), std::move(SSP),696 (*ELFObj)->makeTriple(), std::move(*Features))697 .buildGraph();698}699 700void link_ELF_aarch64(std::unique_ptr<LinkGraph> G,701 std::unique_ptr<JITLinkContext> Ctx) {702 PassConfiguration Config;703 const Triple &TT = G->getTargetTriple();704 if (Ctx->shouldAddDefaultTargetPasses(TT)) {705 // Add eh-frame passes.706 Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame"));707 Config.PrePrunePasses.push_back(EHFrameEdgeFixer(708 ".eh_frame", 8, aarch64::Pointer32, aarch64::Pointer64,709 aarch64::Delta32, aarch64::Delta64, aarch64::NegDelta32));710 Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame"));711 712 // Add a mark-live pass.713 if (auto MarkLive = Ctx->getMarkLivePass(TT))714 Config.PrePrunePasses.push_back(std::move(MarkLive));715 else716 Config.PrePrunePasses.push_back(markAllSymbolsLive);717 718 // Resolve any external section start / end symbols.719 Config.PostAllocationPasses.push_back(720 createDefineExternalSectionStartAndEndSymbolsPass(721 identifyELFSectionStartAndEndSymbols));722 723 // Add an in-place GOT/TLS/Stubs build pass.724 Config.PostPrunePasses.push_back(buildTables_ELF_aarch64);725 }726 727 if (auto Err = Ctx->modifyPassConfig(*G, Config))728 return Ctx->notifyFailed(std::move(Err));729 730 ELFJITLinker_aarch64::link(std::move(Ctx), std::move(G), std::move(Config));731}732 733} // namespace jitlink734} // namespace llvm735