25#define DEBUG_TYPE "jitlink"
32constexpr StringRef ELFGOTSymbolName =
"_GLOBAL_OFFSET_TABLE_";
34template <llvm::endianness Endianness>
35class ELFJITLinker_aarch64
36 :
public JITLinker<ELFJITLinker_aarch64<Endianness>> {
41 ELFJITLinker_aarch64(std::unique_ptr<JITLinkContext> Ctx,
42 std::unique_ptr<LinkGraph>
G,
44 :
JITLinkerBase(std::move(Ctx), std::move(
G), std::move(PassConfig)) {
45 if (this->shouldAddDefaultTargetPasses(this->getGraph().getTargetTriple()))
46 this->getPassConfig().PostAllocationPasses.push_back(
47 [
this](
LinkGraph &
G) {
return getOrCreateGOTSymbol(
G); });
51 Symbol *GOTSymbol =
nullptr;
58 auto InteredGOTSymbolName =
59 G.getSymbolStringPool()->intern(ELFGOTSymbolName);
61 auto DefineExternalGOTSymbolIfPresent =
64 if (*Sym.
getName() == ELFGOTSymbolName)
65 if (
auto *GOTSection =
G.findSectionByName(
68 return {*GOTSection,
true};
75 if (
auto Err = DefineExternalGOTSymbolIfPresent(
G))
85 if (
auto *GOTSection =
89 for (
auto *Sym : GOTSection->symbols())
90 if (Sym->
getName() == InteredGOTSymbolName) {
104 &
G.addDefinedSymbol(*SR.
getFirstBlock(), 0, InteredGOTSymbolName, 0,
112 for (
auto *Sym :
G.external_symbols()) {
113 if (*Sym->
getName() == ELFGOTSymbolName) {
114 auto Blocks =
G.blocks();
115 if (!Blocks.empty()) {
116 G.makeAbsolute(*Sym, (*Blocks.begin())->
getAddress());
128template <
typename ELFT>
131 enum ELFAArch64RelocationKind : Edge::Kind {
132 ELFCall26 = Edge::FirstRelocation,
165 case ELF::R_AARCH64_CALL26:
166 case ELF::R_AARCH64_JUMP26:
168 case ELF::R_AARCH64_LD_PREL_LO19:
170 case ELF::R_AARCH64_ADR_PREL_LO21:
172 case ELF::R_AARCH64_ADR_PREL_PG_HI21:
174 case ELF::R_AARCH64_ADD_ABS_LO12_NC:
176 case ELF::R_AARCH64_LDST8_ABS_LO12_NC:
177 return ELFLdSt8Abs12;
178 case ELF::R_AARCH64_LDST16_ABS_LO12_NC:
179 return ELFLdSt16Abs12;
180 case ELF::R_AARCH64_LDST32_ABS_LO12_NC:
181 return ELFLdSt32Abs12;
182 case ELF::R_AARCH64_LDST64_ABS_LO12_NC:
183 return ELFLdSt64Abs12;
184 case ELF::R_AARCH64_LDST128_ABS_LO12_NC:
185 return ELFLdSt128Abs12;
186 case ELF::R_AARCH64_MOVW_UABS_G0_NC:
188 case ELF::R_AARCH64_MOVW_UABS_G1_NC:
190 case ELF::R_AARCH64_MOVW_UABS_G2_NC:
192 case ELF::R_AARCH64_MOVW_UABS_G3:
194 case ELF::R_AARCH64_TSTBR14:
196 case ELF::R_AARCH64_CONDBR19:
198 case ELF::R_AARCH64_ABS32:
200 case ELF::R_AARCH64_ABS64:
202 case ELF::R_AARCH64_PREL32:
204 case ELF::R_AARCH64_PREL64:
206 case ELF::R_AARCH64_ADR_GOT_PAGE:
207 return ELFAdrGOTPage21;
208 case ELF::R_AARCH64_LD64_GOT_LO12_NC:
209 return ELFLd64GOTLo12;
210 case ELF::R_AARCH64_LD64_GOTPAGE_LO15:
211 return ELFLd64GOTPAGELo15;
212 case ELF::R_AARCH64_TLSDESC_ADR_PAGE21:
213 return ELFTLSDescAdrPage21;
214 case ELF::R_AARCH64_TLSDESC_ADD_LO12:
215 return ELFTLSDescAddLo12;
216 case ELF::R_AARCH64_TLSDESC_LD64_LO12:
217 return ELFTLSDescLd64Lo12;
218 case ELF::R_AARCH64_TLSDESC_CALL:
219 return ELFTLSDescCall;
223 "Unsupported aarch64 relocation:" +
formatv(
"{0:d}: ",
Type) +
227 Error addRelocations()
override {
231 using Self = ELFLinkGraphBuilder_aarch64<ELFT>;
232 for (
const auto &RelSect : Base::Sections)
233 if (
Error Err = Base::forEachRelaRelocation(RelSect,
this,
234 &Self::addSingleRelocation))
240 Error addSingleRelocation(
const typename ELFT::Rela &Rel,
241 const typename ELFT::Shdr &FixupSect,
248 uint32_t SymbolIndex = Rel.getSymbol(
false);
249 auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);
251 return ObjSymbol.takeError();
253 Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex);
256 formatv(
"Could not find symbol at given index, did you add it to "
257 "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",
258 SymbolIndex, (*ObjSymbol)->st_shndx,
259 Base::GraphSymbols.size()),
267 int64_t Addend = Rel.r_addend;
276 Edge::Kind Kind = Edge::Invalid;
278 switch (*RelocKind) {
284 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
287 "R_AARCH64_LDR_PREL_LO19 target is not an LDR Literal instruction");
293 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
296 "R_AARCH64_ADR_PREL_LO21 target is not an ADR instruction");
309 case ELFLdSt8Abs12: {
310 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
314 "R_AARCH64_LDST8_ABS_LO12_NC target is not a "
315 "LDRB/STRB (imm12) instruction");
320 case ELFLdSt16Abs12: {
321 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
325 "R_AARCH64_LDST16_ABS_LO12_NC target is not a "
326 "LDRH/STRH (imm12) instruction");
331 case ELFLdSt32Abs12: {
332 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
336 "R_AARCH64_LDST32_ABS_LO12_NC target is not a "
337 "LDR/STR (imm12, 32 bit) instruction");
342 case ELFLdSt64Abs12: {
343 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
347 "R_AARCH64_LDST64_ABS_LO12_NC target is not a "
348 "LDR/STR (imm12, 64 bit) instruction");
353 case ELFLdSt128Abs12: {
354 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
358 "R_AARCH64_LDST128_ABS_LO12_NC target is not a "
359 "LDR/STR (imm12, 128 bit) instruction");
365 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
369 "R_AARCH64_MOVW_UABS_G0_NC target is not a "
370 "MOVK/MOVZ (imm16, LSL #0) instruction");
376 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
380 "R_AARCH64_MOVW_UABS_G1_NC target is not a "
381 "MOVK/MOVZ (imm16, LSL #16) instruction");
387 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
391 "R_AARCH64_MOVW_UABS_G2_NC target is not a "
392 "MOVK/MOVZ (imm16, LSL #32) instruction");
398 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
402 "R_AARCH64_MOVW_UABS_G3 target is not a "
403 "MOVK/MOVZ (imm16, LSL #48) instruction");
409 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
412 "test and branch instruction");
418 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
422 "conditional branch instruction");
443 case ELFAdrGOTPage21: {
447 case ELFLd64GOTLo12: {
451 case ELFLd64GOTPAGELo15: {
455 case ELFTLSDescAdrPage21: {
459 case ELFTLSDescAddLo12:
460 case ELFTLSDescLd64Lo12: {
464 case ELFTLSDescCall: {
476 BlockToFix.
addEdge(std::move(GE));
482 const char *getELFAArch64RelocationKindName(Edge::Kind R) {
487 return "ELFAdrPage21";
489 return "ELFAddAbs12";
491 return "ELFLdSt8Abs12";
493 return "ELFLdSt16Abs12";
495 return "ELFLdSt32Abs12";
497 return "ELFLdSt64Abs12";
498 case ELFLdSt128Abs12:
499 return "ELFLdSt128Abs12";
501 return "ELFMovwAbsG0";
503 return "ELFMovwAbsG1";
505 return "ELFMovwAbsG2";
507 return "ELFMovwAbsG3";
516 case ELFAdrGOTPage21:
517 return "ELFAdrGOTPage21";
519 return "ELFLd64GOTLo12";
520 case ELFLd64GOTPAGELo15:
521 return "ELFLd64GOTPAGELo15";
522 case ELFTLSDescAdrPage21:
523 return "ELFTLSDescAdrPage21";
524 case ELFTLSDescAddLo12:
525 return "ELFTLSDescAddLo12";
526 case ELFTLSDescLd64Lo12:
527 return "ELFTLSDescLd64Lo12";
529 return "ELFTLSDescCall";
536 ELFLinkGraphBuilder_aarch64(
StringRef FileName,
538 std::shared_ptr<orc::SymbolStringPool> SSP,
542 std::move(Features), FileName,
547class TLSInfoTableManager_ELF_aarch64
548 :
public TableManager<TLSInfoTableManager_ELF_aarch64> {
552 static const uint8_t TLSInfoEntryContent[16];
559 auto &TLSInfoEntry =
G.createMutableContentBlock(
560 getTLSInfoSection(
G),
G.allocateContent(getTLSInfoEntryContent()),
563 return G.addAnonymousSymbol(TLSInfoEntry, 0, 16,
false,
false);
570 return *TLSInfoTable;
574 return {
reinterpret_cast<const char *
>(TLSInfoEntryContent),
575 sizeof(TLSInfoEntryContent)};
578 Section *TLSInfoTable =
nullptr;
581const uint8_t TLSInfoTableManager_ELF_aarch64::TLSInfoEntryContent[16] = {
582 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
583 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
587class TLSDescTableManager_ELF_aarch64
588 :
public TableManager<TLSDescTableManager_ELF_aarch64> {
590 TLSDescTableManager_ELF_aarch64(
591 TLSInfoTableManager_ELF_aarch64 &TLSInfoTableManager)
592 : TLSInfoTableManager(TLSInfoTableManager) {}
596 static const uint8_t TLSDescEntryContent[16];
599 Edge::Kind KindToSet = Edge::Invalid;
600 switch (
E.getKind()) {
612 assert(KindToSet != Edge::Invalid &&
613 "Fell through switch, but no new kind to set");
615 dbgs() <<
" Fixing " <<
G.getEdgeKindName(
E.getKind()) <<
" edge at "
616 <<
B->getFixupAddress(
E) <<
" (" <<
B->getAddress() <<
" + "
617 <<
formatv(
"{0:x}",
E.getOffset()) <<
")\n";
619 E.setKind(KindToSet);
620 E.setTarget(getEntryForTarget(
G,
E.getTarget()));
626 G.createContentBlock(getTLSDescSection(
G), getTLSDescBlockContent(),
630 TLSInfoTableManager.getEntryForTarget(
G,
Target), 0);
631 return G.addAnonymousSymbol(EntryBlock, 0, 8,
false,
false);
642 if (!TLSDescResolver)
643 TLSDescResolver = &
G.addExternalSymbol(
"__tlsdesc_resolver", 8,
false);
644 return *TLSDescResolver;
648 return {
reinterpret_cast<const char *
>(TLSDescEntryContent),
649 sizeof(TLSDescEntryContent)};
653 Symbol *TLSDescResolver =
nullptr;
654 TLSInfoTableManager_ELF_aarch64 &TLSInfoTableManager;
657const uint8_t TLSDescTableManager_ELF_aarch64::TLSDescEntryContent[16] = {
658 0x00, 0x00, 0x00, 0x00,
659 0x00, 0x00, 0x00, 0x00,
660 0x00, 0x00, 0x00, 0x00,
661 0x00, 0x00, 0x00, 0x00
669 TLSInfoTableManager_ELF_aarch64 TLSInfo;
670 TLSDescTableManager_ELF_aarch64 TLSDesc(TLSInfo);
680template <llvm::endianness Endianness>
682 MemoryBufferRef ObjectBuffer, std::shared_ptr<orc::SymbolStringPool> SSP) {
684 dbgs() <<
"Building jitlink graph for new input "
690 return ELFObj.takeError();
692 auto Features = (*ELFObj)->getFeatures();
694 return Features.takeError();
698 return ELFLinkGraphBuilder_aarch64<ELFT>(
699 (*ELFObj)->getFileName(), ELFObjFile.getELFFile(), std::move(SSP),
700 (*ELFObj)->makeTriple(), std::move(*Features))
705 MemoryBufferRef ObjectBuffer, std::shared_ptr<orc::SymbolStringPool> SSP) {
707 std::move(ObjectBuffer), std::move(SSP));
711 MemoryBufferRef ObjectBuffer, std::shared_ptr<orc::SymbolStringPool> SSP) {
713 std::move(ObjectBuffer), std::move(SSP));
716template <llvm::endianness Endianness>
718 std::unique_ptr<JITLinkContext> Ctx) {
720 const Triple &TT =
G->getTargetTriple();
721 if (Ctx->shouldAddDefaultTargetPasses(TT)) {
730 if (
auto MarkLive = Ctx->getMarkLivePass(TT))
744 if (
auto Err = Ctx->modifyPassConfig(*
G, Config))
745 return Ctx->notifyFailed(std::move(Err));
747 ELFJITLinker_aarch64<Endianness>::link(std::move(Ctx), std::move(
G),
752 std::unique_ptr<JITLinkContext> Ctx) {
757 std::unique_ptr<JITLinkContext> Ctx) {
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
StringRef getBufferIdentifier() const
Represent a constant reference to a string, i.e.
Manages the enabling and disabling of subtarget specific features.
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
The instances of the Type class are immutable: once they are created, they are never changed.
orc::ExecutorAddr getAddress() const
An Addressable with content and edges.
ArrayRef< char > getContent() const
Get the content for this block. Block must not be a zero-fill block.
void addEdge(Edge::Kind K, Edge::OffsetT Offset, Symbol &Target, Edge::AddendT Addend)
Add an edge to this block.
A LinkGraph pass that splits blocks in a section that follows the DWARF Record format into sub-blocks...
A LinkGraph pass that adds missing FDE-to-CIE, FDE-to-PC and FDE-to-LSDA edges.
LinkGraph building code that's specific to the given ELFT, but common across all architectures.
Represents fixups and constraints in the LinkGraph.
Base class for a JIT linker.
Represents a section address range via a pair of Block pointers to the first and last Blocks in the s...
Block * getFirstBlock() const
Represents an object file section.
const orc::SymbolStringPtr & getName() const
Returns the name of this symbol (empty if the symbol is anonymous).
orc::ExecutorAddr getAddress() const
Returns the address of this symbol.
A CRTP base for tables that are built on demand, e.g.
Global Offset Table Builder.
static StringRef getSectionName()
Procedure Linkage Table Builder.
static Expected< std::unique_ptr< ObjectFile > > createELFObjectFile(MemoryBufferRef Object, bool InitContent=true)
Represents an address in the executor process.
static constexpr const StringLiteral & getSectionName(DebugSectionKind SectionKind)
Return the name of the section.
bool isLDRLiteral(uint32_t Instr)
bool isADR(uint32_t Instr)
bool isCondBranchImm19(uint32_t Instr)
Error applyFixup(LinkGraph &G, Block &B, const Edge &E, const Symbol *GOTSymbol)
Apply fixup expression for edge to block content.
bool isMoveWideImm16(uint32_t Instr)
bool isCompAndBranchImm19(uint32_t Instr)
bool isLoadStoreImm12(uint32_t Instr)
LLVM_ABI const char * getEdgeKindName(Edge::Kind K)
Returns a string name for the given aarch64 edge.
@ LDRLiteral19
The signed 21-bit delta from the fixup to the target.
@ RequestGOTAndTransformToPageOffset15
A GOT entry getter/constructor, transformed to Pageoffset15 pointing at the GOT entry for the origina...
@ CondBranch19PCRel
A 19-bit PC-relative conditional branch.
@ RequestTLSDescEntryAndTransformToPageOffset12
A TLSDesc entry getter/constructor, transformed to PageOffset12.
@ Page21
The signed 21-bit delta from the fixup page to the page containing the target.
@ Branch26PCRel
A 26-bit PC-relative branch.
@ Pointer64
A plain 64-bit pointer value relocation.
@ Pointer32
A plain 32-bit pointer value relocation.
@ MoveWide16
A 16-bit slice of the target address (which slice depends on the instruction at the fixup location).
@ TestAndBranch14PCRel
A 14-bit PC-relative test and branch.
@ RequestGOTAndTransformToPage21
A GOT entry getter/constructor, transformed to Page21 pointing at the GOT entry for the original targ...
@ ADRLiteral21
The signed 21-bit delta from the fixup to the target.
@ RequestGOTAndTransformToPageOffset12
A GOT entry getter/constructor, transformed to Pageoffset12 pointing at the GOT entry for the origina...
@ NegDelta32
A 32-bit negative delta.
@ PageOffset12
The 12-bit (potentially shifted) offset of the target within its page.
@ RequestTLSDescEntryAndTransformToPage21
A TLSDesc entry getter/constructor, transformed to Page21.
bool isTestAndBranchImm14(uint32_t Instr)
unsigned getPageOffset12Shift(uint32_t Instr)
unsigned getMoveWide16Shift(uint32_t Instr)
LLVM_ABI const char * getGenericEdgeKindName(Edge::Kind K)
Returns the string name of the given generic edge kind, or "unknown" otherwise.
LLVM_ABI void link_ELF_aarch64_be(std::unique_ptr< LinkGraph > G, std::unique_ptr< JITLinkContext > Ctx)
jit-link the given object buffer, which must be an ELF aarch64_be (BE8) relocatable object file.
void visitExistingEdges(LinkGraph &G, VisitorTs &&...Vs)
For each edge in the given graph, apply a list of visitors to the edge, stopping when the first visit...
LLVM_ABI Error markAllSymbolsLive(LinkGraph &G)
Marks all symbols in a graph live.
LLVM_ABI void link_ELF_aarch64(std::unique_ptr< LinkGraph > G, std::unique_ptr< JITLinkContext > Ctx)
jit-link the given object buffer, which must be an ELF aarch64 (little-endian) relocatable object fil...
LLVM_ABI Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromELFObject_aarch64_be(MemoryBufferRef ObjectBuffer, std::shared_ptr< orc::SymbolStringPool > SSP)
Create a LinkGraph from an ELF/aarch64_be (BE8) relocatable object.
LLVM_ABI Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromELFObject_aarch64(MemoryBufferRef ObjectBuffer, std::shared_ptr< orc::SymbolStringPool > SSP)
Create a LinkGraph from an ELF/aarch64 (little-endian) relocatable object.
LLVM_ABI void printEdge(raw_ostream &OS, const Block &B, const Edge &E, StringRef EdgeKindName)
SectionRangeSymbolDesc identifyELFSectionStartAndEndSymbols(LinkGraph &G, Symbol &Sym)
ELF section start/end symbol detection.
void visitEdge(LinkGraph &G, Block *B, Edge &E)
Base case for edge-visitors where the visitor-list is empty.
DefineExternalSectionStartAndEndSymbols< SymbolIdentifierFunction > createDefineExternalSectionStartAndEndSymbolsPass(SymbolIdentifierFunction &&F)
Returns a JITLink pass (as a function class) that uses the given symbol identification function to id...
LLVM_ABI StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type)
detail::packed_endian_specific_integral< uint32_t, llvm::endianness::little, unaligned > ulittle32_t
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
An LinkGraph pass configuration, consisting of a list of pre-prune, post-prune, and post-fixup passes...
LinkGraphPassList PostAllocationPasses
Post-allocation passes.
LinkGraphPassList PostPrunePasses
Post-prune passes.
LinkGraphPassList PrePrunePasses
Pre-prune passes.