Index: llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h =================================================================== --- llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h +++ llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h @@ -25,6 +25,28 @@ /// Set a CALL immediate field to bits [27:2] of X = Target - Fixup + Addend R_AARCH64_CALL26 = Edge::FirstRelocation, + /// Set an ADRP immediate value to bits [32:12] of the X + /// + /// Fixup experssion + /// Fixup <- Page(Target + Addend) - Page(Fixup) + /// + /// Overflow + /// -2^32 <= X <= 2^32 + /// + /// Attentions: + /// According to the arm/aarch64 document: + /// Page(expr) is the page address of the expression expr, defined as (expr & + /// ~0xFFF). (This applies even if the machine page size supported by the + /// platform has a different value.) + /// + R_AARCH64_ADR_PREL_PG_HI21, + + /// Set an ADD immediate value to bits [11:0] of X. No overflow check. Used + /// with relocations ADR_PREL_PG_HI21 and ADR_PREL_PG_HI21_NC + /// Fixup expression: + /// Fixup <- Target + Addend + /// + R_AARCH64_ADD_ABS_LO12_NC, }; /// Returns a string name for the given aarch64 edge. For debugging purposes Index: llvm/include/llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h =================================================================== --- llvm/include/llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h +++ llvm/include/llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h @@ -101,6 +101,11 @@ return *this; } + ExecutorAddr &operator&(const ExecutorAddrDiff Mask) { + Addr &= Mask; + return *this; + } + private: uint64_t Addr = 0; }; Index: llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp =================================================================== --- llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp +++ llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp @@ -15,6 +15,7 @@ #include "JITLinkGeneric.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/ExecutionEngine/JITLink/aarch64.h" +#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/MathExtras.h" @@ -42,9 +43,12 @@ char *BlockWorkingMem = B.getAlreadyMutableContent().data(); char *FixupPtr = BlockWorkingMem + E.getOffset(); + uint32_t RawInstr = *(little32_t *)FixupPtr; + auto Addend = E.getAddend(); + auto SymbolAddress = E.getTarget().getAddress(); auto FixupAddress = B.getAddress() + E.getOffset(); switch (E.getKind()) { - case aarch64::R_AARCH64_CALL26: { + case R_AARCH64_CALL26: { assert((FixupAddress.getValue() & 0x3) == 0 && "Call-inst is not 32-bit aligned"); int64_t Value = E.getTarget().getAddress() - FixupAddress + E.getAddend(); @@ -55,7 +59,6 @@ if (!isInt<28>(Value)) return makeTargetOutOfRangeError(G, B, E); - uint32_t RawInstr = *(little32_t *)FixupPtr; assert((RawInstr & 0x7fffffff) == 0x14000000 && "RawInstr isn't a B or BR immediate instruction"); uint32_t Imm = (static_cast(Value) & ((1 << 28) - 1)) >> 2; @@ -63,6 +66,36 @@ *(little32_t *)FixupPtr = FixedInstr; break; } + case R_AARCH64_ADR_PREL_PG_HI21: { + auto PagedSymbolAddr = (SymbolAddress + Addend) & ~0xFFFLL; + auto PagedFixupAddr = FixupAddress & ~0xFFFLL; + int64_t Value = PagedSymbolAddr - PagedFixupAddr; + if (!isInt<33>(Value)) + return makeTargetOutOfRangeError(G, B, E); + + // Set value to the imm field of adrp instruction + // adrp format: + // C6.2.9 in ARM Architecture Reference Manual - ARMv8, for ARMv8-A + // architecture profile + uint32_t Imm32_12 = (static_cast(Value) >> 11) & 0x3FFFFF; + uint32_t ImmLo = (Imm32_12 & 0x3) << 29; + uint32_t ImmHi = ((Imm32_12 & 0x1FFFFC) >> 2) << 5; + uint32_t Mask = ((0x1FFFFC >> 2) << 5) | (0x3U << 29); + RawInstr |= ~Mask; + *(little32_t *)FixupPtr = RawInstr | ImmLo | ImmHi; + break; + } + case R_AARCH64_ADD_ABS_LO12_NC: { + // set value to the imm field of add* instruction + // add format: + // C6.2.4 in ARM Architecture Reference Manual - ARMv8, for ARMv8-A + // architecture profile + int64_t Value = (SymbolAddress + Addend).getValue(); + Value = (Value & 0x7FFLL) << 10; // instr{21-10} is imm field + uint32_t Imm11_0 = static_cast(Value); + *(little32_t *)FixupPtr = RawInstr | Imm11_0; + break; + } } return Error::success(); } @@ -71,14 +104,16 @@ template class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder { private: - static Expected - getRelocationKind(const uint32_t Type) { + Expected getRelocationKind(const uint32_t Type) { using namespace aarch64; switch (Type) { case ELF::R_AARCH64_CALL26: return EdgeKind_aarch64::R_AARCH64_CALL26; + case ELF::R_AARCH64_ADR_PREL_PG_HI21: + return EdgeKind_aarch64::R_AARCH64_ADR_PREL_PG_HI21; + case ELF::R_AARCH64_ADD_ABS_LO12_NC: + return EdgeKind_aarch64::R_AARCH64_ADD_ABS_LO12_NC; } - return make_error("Unsupported aarch64 relocation:" + formatv("{0:d}", Type)); } Index: llvm/lib/ExecutionEngine/JITLink/aarch64.cpp =================================================================== --- llvm/lib/ExecutionEngine/JITLink/aarch64.cpp +++ llvm/lib/ExecutionEngine/JITLink/aarch64.cpp @@ -22,6 +22,10 @@ switch (K) { case R_AARCH64_CALL26: return "R_AARCH64_CALL26"; + case R_AARCH64_ADR_PREL_PG_HI21: + return "R_AARCH64_ADR_PREL_PG_HI21"; + case R_AARCH64_ADD_ABS_LO12_NC: + return "R_AARCH64_ADD_ABS_LO12_NC"; } return getGenericEdgeKindName(K); } Index: llvm/test/ExecutionEngine/JITLink/AArch64/ELF_aarch64_adrp.s =================================================================== --- /dev/null +++ llvm/test/ExecutionEngine/JITLink/AArch64/ELF_aarch64_adrp.s @@ -0,0 +1,27 @@ +# RUN: rm -rf %t && mkdir -p %t +# RUN: llvm-mc -triple=aarch64-unknown-linux-gnu -relax-relocations=false -position-independent -filetype=obj -o %t/elf_aarch64_adrp.o %s +# RUN: llvm-jitlink -noexec -check %s %t/elf_aarch64_adrp.o + + .text + +# Test Case 1: R_AARCH64_ADR_PREL_PG_HI21 +# jitlink-check: decode_operand(main, 1) = (((str + 0) & 0xFFFFFFFFFFFFF000) - (main & 0xFFFFFFFFFFFFF000))[32:12] +# +# Test Case 2: R_AARCH64_ADD_ABS_LO12_NC +# jitlink-check: decode_operand(main + 4, 2) = (str + 0)[11:0] + + + .globl main + .p2align 2 + .type main,@function +main: + adrp x0, str + add x0, x0, :lo12:str + ret + .size main, .-main + + .globl str + .type str,@object +str: + .asciz "hello world" + .size str, 12