23#define DEBUG_TYPE "jitlink"
30class ELFJITLinker_aarch64 :
public JITLinker<ELFJITLinker_aarch64> {
31 friend class JITLinker<ELFJITLinker_aarch64>;
34 ELFJITLinker_aarch64(std::unique_ptr<JITLinkContext> Ctx,
35 std::unique_ptr<LinkGraph>
G,
37 :
JITLinker(std::move(Ctx), std::move(
G), std::move(PassConfig)) {}
45template <
typename ELFT>
74 using namespace aarch64;
76 case ELF::R_AARCH64_CALL26:
77 case ELF::R_AARCH64_JUMP26:
79 case ELF::R_AARCH64_ADR_PREL_PG_HI21:
81 case ELF::R_AARCH64_ADD_ABS_LO12_NC:
83 case ELF::R_AARCH64_LDST8_ABS_LO12_NC:
85 case ELF::R_AARCH64_LDST16_ABS_LO12_NC:
86 return ELFLdSt16Abs12;
87 case ELF::R_AARCH64_LDST32_ABS_LO12_NC:
88 return ELFLdSt32Abs12;
89 case ELF::R_AARCH64_LDST64_ABS_LO12_NC:
90 return ELFLdSt64Abs12;
91 case ELF::R_AARCH64_LDST128_ABS_LO12_NC:
92 return ELFLdSt128Abs12;
93 case ELF::R_AARCH64_MOVW_UABS_G0_NC:
95 case ELF::R_AARCH64_MOVW_UABS_G1_NC:
97 case ELF::R_AARCH64_MOVW_UABS_G2_NC:
99 case ELF::R_AARCH64_MOVW_UABS_G3:
101 case ELF::R_AARCH64_ABS64:
103 case ELF::R_AARCH64_PREL32:
105 case ELF::R_AARCH64_PREL64:
107 case ELF::R_AARCH64_ADR_GOT_PAGE:
108 return ELFAdrGOTPage21;
109 case ELF::R_AARCH64_LD64_GOT_LO12_NC:
110 return ELFLd64GOTLo12;
111 case ELF::R_AARCH64_TLSDESC_ADR_PAGE21:
112 return ELFTLSDescAdrPage21;
113 case ELF::R_AARCH64_TLSDESC_ADD_LO12:
114 return ELFTLSDescAddLo12;
115 case ELF::R_AARCH64_TLSDESC_LD64_LO12:
116 return ELFTLSDescLd64Lo12;
117 case ELF::R_AARCH64_TLSDESC_CALL:
118 return ELFTLSDescCall;
121 return make_error<JITLinkError>(
122 "Unsupported aarch64 relocation:" +
formatv(
"{0:d}: ",
Type) +
130 using Self = ELFLinkGraphBuilder_aarch64<ELFT>;
131 for (
const auto &RelSect : Base::Sections)
132 if (
Error Err = Base::forEachRelaRelocation(RelSect,
this,
133 &Self::addSingleRelocation))
139 Error addSingleRelocation(
const typename ELFT::Rela &Rel,
140 const typename ELFT::Shdr &FixupSect,
145 uint32_t SymbolIndex = Rel.getSymbol(
false);
146 auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);
148 return ObjSymbol.takeError();
150 Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex);
152 return make_error<StringError>(
153 formatv(
"Could not find symbol at given index, did you add it to "
154 "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",
155 SymbolIndex, (*ObjSymbol)->st_shndx,
156 Base::GraphSymbols.size()),
164 int64_t Addend = Rel.r_addend;
175 switch (*RelocKind) {
188 case ELFLdSt8Abs12: {
189 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
192 return make_error<JITLinkError>(
193 "R_AARCH64_LDST8_ABS_LO12_NC target is not a "
194 "LDRB/STRB (imm12) instruction");
199 case ELFLdSt16Abs12: {
200 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
203 return make_error<JITLinkError>(
204 "R_AARCH64_LDST16_ABS_LO12_NC target is not a "
205 "LDRH/STRH (imm12) instruction");
210 case ELFLdSt32Abs12: {
211 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
214 return make_error<JITLinkError>(
215 "R_AARCH64_LDST32_ABS_LO12_NC target is not a "
216 "LDR/STR (imm12, 32 bit) instruction");
221 case ELFLdSt64Abs12: {
222 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
225 return make_error<JITLinkError>(
226 "R_AARCH64_LDST64_ABS_LO12_NC target is not a "
227 "LDR/STR (imm12, 64 bit) instruction");
232 case ELFLdSt128Abs12: {
233 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
236 return make_error<JITLinkError>(
237 "R_AARCH64_LDST128_ABS_LO12_NC target is not a "
238 "LDR/STR (imm12, 128 bit) instruction");
244 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
247 return make_error<JITLinkError>(
248 "R_AARCH64_MOVW_UABS_G0_NC target is not a "
249 "MOVK/MOVZ (imm16, LSL #0) instruction");
255 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
258 return make_error<JITLinkError>(
259 "R_AARCH64_MOVW_UABS_G1_NC target is not a "
260 "MOVK/MOVZ (imm16, LSL #16) instruction");
266 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
269 return make_error<JITLinkError>(
270 "R_AARCH64_MOVW_UABS_G2_NC target is not a "
271 "MOVK/MOVZ (imm16, LSL #32) instruction");
277 uint32_t Instr = *(
const ulittle32_t *)FixupContent;
280 return make_error<JITLinkError>(
281 "R_AARCH64_MOVW_UABS_G3 target is not a "
282 "MOVK/MOVZ (imm16, LSL #48) instruction");
299 case ELFAdrGOTPage21: {
303 case ELFLd64GOTLo12: {
307 case ELFTLSDescAdrPage21: {
311 case ELFTLSDescAddLo12:
312 case ELFTLSDescLd64Lo12: {
316 case ELFTLSDescCall: {
328 BlockToFix.
addEdge(std::move(GE));
334 const char *getELFAArch64RelocationKindName(
Edge::Kind R) {
339 return "ELFAdrPage21";
341 return "ELFAddAbs12";
343 return "ELFLdSt8Abs12";
345 return "ELFLdSt16Abs12";
347 return "ELFLdSt32Abs12";
349 return "ELFLdSt64Abs12";
350 case ELFLdSt128Abs12:
351 return "ELFLdSt128Abs12";
353 return "ELFMovwAbsG0";
355 return "ELFMovwAbsG1";
357 return "ELFMovwAbsG2";
359 return "ELFMovwAbsG3";
366 case ELFAdrGOTPage21:
367 return "ELFAdrGOTPage21";
369 return "ELFLd64GOTLo12";
370 case ELFTLSDescAdrPage21:
371 return "ELFTLSDescAdrPage21";
372 case ELFTLSDescAddLo12:
373 return "ELFTLSDescAddLo12";
374 case ELFTLSDescLd64Lo12:
375 return "ELFTLSDescLd64Lo12";
377 return "ELFTLSDescCall";
384 ELFLinkGraphBuilder_aarch64(
StringRef FileName,
391class TLSInfoTableManager_ELF_aarch64
392 :
public TableManager<TLSInfoTableManager_ELF_aarch64> {
394 static StringRef getSectionName() {
return "$__TLSINFO"; }
396 static const uint8_t TLSInfoEntryContent[16];
403 auto &TLSInfoEntry =
G.createMutableContentBlock(
404 getTLSInfoSection(
G),
G.allocateContent(getTLSInfoEntryContent()),
407 return G.addAnonymousSymbol(TLSInfoEntry, 0, 16,
false,
false);
413 TLSInfoTable = &
G.createSection(getSectionName(), orc::MemProt::Read);
414 return *TLSInfoTable;
418 return {
reinterpret_cast<const char *
>(TLSInfoEntryContent),
419 sizeof(TLSInfoEntryContent)};
422 Section *TLSInfoTable =
nullptr;
425const uint8_t TLSInfoTableManager_ELF_aarch64::TLSInfoEntryContent[16] = {
426 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
427 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
431class TLSDescTableManager_ELF_aarch64
432 :
public TableManager<TLSDescTableManager_ELF_aarch64> {
434 TLSDescTableManager_ELF_aarch64(
435 TLSInfoTableManager_ELF_aarch64 &TLSInfoTableManager)
436 : TLSInfoTableManager(TLSInfoTableManager) {}
438 static StringRef getSectionName() {
return "$__TLSDESC"; }
440 static const uint8_t TLSDescEntryContent[16];
444 switch (
E.getKind()) {
456 assert(KindToSet != Edge::Invalid &&
457 "Fell through switch, but no new kind to set");
459 dbgs() <<
" Fixing " <<
G.getEdgeKindName(
E.getKind()) <<
" edge at "
460 <<
B->getFixupAddress(
E) <<
" (" <<
B->getAddress() <<
" + "
461 <<
formatv(
"{0:x}",
E.getOffset()) <<
")\n";
463 E.setKind(KindToSet);
470 G.createContentBlock(getTLSDescSection(
G), getTLSDescBlockContent(),
474 TLSInfoTableManager.getEntryForTarget(
G,
Target), 0);
475 return G.addAnonymousSymbol(EntryBlock, 0, 8,
false,
false);
481 GOTSection = &
G.createSection(getSectionName(), orc::MemProt::Read);
486 if (!TLSDescResolver)
487 TLSDescResolver = &
G.addExternalSymbol(
"__tlsdesc_resolver", 8,
false);
488 return *TLSDescResolver;
492 return {
reinterpret_cast<const char *
>(TLSDescEntryContent),
493 sizeof(TLSDescEntryContent)};
497 Symbol *TLSDescResolver =
nullptr;
498 TLSInfoTableManager_ELF_aarch64 &TLSInfoTableManager;
501const uint8_t TLSDescTableManager_ELF_aarch64::TLSDescEntryContent[16] = {
502 0x00, 0x00, 0x00, 0x00,
503 0x00, 0x00, 0x00, 0x00,
504 0x00, 0x00, 0x00, 0x00,
505 0x00, 0x00, 0x00, 0x00
513 TLSInfoTableManager_ELF_aarch64 TLSInfo;
514 TLSDescTableManager_ELF_aarch64 TLSDesc(TLSInfo);
527 dbgs() <<
"Building jitlink graph for new input "
533 return ELFObj.takeError();
536 "Only AArch64 (little endian) is supported for now");
538 auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
539 return ELFLinkGraphBuilder_aarch64<object::ELF64LE>((*ELFObj)->getFileName(),
540 ELFObjFile.getELFFile(),
541 (*ELFObj)->makeTriple())
546 std::unique_ptr<JITLinkContext> Ctx) {
548 const Triple &TT =
G->getTargetTriple();
549 if (Ctx->shouldAddDefaultTargetPasses(TT)) {
557 if (
auto MarkLive = Ctx->getMarkLivePass(TT))
566 if (
auto Err = Ctx->modifyPassConfig(*
G, Config))
567 return Ctx->notifyFailed(std::move(Err));
569 ELFJITLinker_aarch64::link(std::move(Ctx), std::move(
G), std::move(Config));
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define DEBUG_WITH_TYPE(TYPE, X)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef - 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
StringRef - Represent a constant reference to a string, i.e.
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.
Ling-graph building code that's specific to the given ELFT, but common across all architectures.
virtual Error addRelocations()=0
Call to derived class to handle relocations.
Represents fixups and constraints in the LinkGraph.
Represents an object file section.
A CRTP base for tables that are built on demand, e.g.
Symbol & getEntryForTarget(LinkGraph &G, Symbol &Target)
Return the constructed entry.
Global Offset Table Builder.
Procedure Linkage Table Builder.
static Expected< std::unique_ptr< ObjectFile > > createELFObjectFile(MemoryBufferRef Object, bool InitContent=true)
Represents an address in the executor process.
bool isMoveWideImm16(uint32_t Instr)
Error applyFixup(LinkGraph &G, Block &B, const Edge &E)
Apply fixup expression for edge to block content.
bool isLoadStoreImm12(uint32_t Instr)
const char * getEdgeKindName(Edge::Kind K)
Returns a string name for the given aarch64 edge.
@ 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).
@ RequestGOTAndTransformToPage21
A GOT entry getter/constructor, transformed to Page21 pointing at the GOT entry for the original targ...
@ 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.
unsigned getPageOffset12Shift(uint32_t Instr)
unsigned getMoveWide16Shift(uint32_t Instr)
const char * getGenericEdgeKindName(Edge::Kind K)
Returns the string name of the given generic edge kind, or "unknown" otherwise.
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...
Error markAllSymbolsLive(LinkGraph &G)
Marks all symbols in a graph live.
Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromELFObject_aarch64(MemoryBufferRef ObjectBuffer)
Create a LinkGraph from an ELF/aarch64 relocatable object.
void link_ELF_aarch64(std::unique_ptr< LinkGraph > G, std::unique_ptr< JITLinkContext > Ctx)
jit-link the given object buffer, which must be a ELF aarch64 relocatable object file.
void printEdge(raw_ostream &OS, const Block &B, const Edge &E, StringRef EdgeKindName)
void visitEdge(LinkGraph &G, Block *B, Edge &E)
Base case for edge-visitors where the visitor-list is empty.
StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type)
This is an optimization pass for GlobalISel generic memory operations.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
An LinkGraph pass configuration, consisting of a list of pre-prune, post-prune, and post-fixup passes...
LinkGraphPassList PostPrunePasses
Post-prune passes.
LinkGraphPassList PrePrunePasses
Pre-prune passes.