diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h b/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h --- a/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h @@ -24,6 +24,14 @@ /// 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 = Page(Target + + // Addend) - Page(Fixup), Page(x) = x & ~0xFFF + R_AARCH64_ADR_PREL_PG_HI21, + // Set an ADRP immediate value to bits [32:12] of the X = Page(Target + + // Addend) - Page(Fixup), Page(x) = x & ~0xFFF + R_AARCH64_ADR_PREL_PG_HI21_NC, + // Set an ADD immediate value to bits [11:0] of X = Target + Addend + R_AARCH64_ADD_ABS_LO12_NC }; diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp --- a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp @@ -56,15 +56,58 @@ 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; + uint32_t Imm = extractBit<27, 2>(Value); uint32_t FixedInstr = RawInstr | Imm; *(little32_t *)FixupPtr = FixedInstr; break; } + case aarch64::R_AARCH64_ADR_PREL_PG_HI21: { + int64_t value = + getPageAddress(E.getTarget().getAddress() + E.getAddend()) - + getPageAddress(FixupAddress); + + if (!fitsRangeSignedInt<32>(value)) + return makeTargetOutOfRangeError(G, B, E); + + uint32_t Imm = extractBit<32, 12>(value); + uint32_t RawInstr = *(little32_t *)FixupPtr; + uint32_t result = RawInstr | Imm; + + *(little32_t *)FixupPtr = result; + break; + } + case aarch64::R_AARCH64_ADR_PREL_PG_HI21_NC: { + int64_t value = + getPageAddress(E.getTarget().getAddress() + E.getAddend()) - + getPageAddress(FixupAddress); + + uint32_t Imm = extractBit<32, 12>(value); + uint32_t RawInstr = *(little32_t *)FixupPtr; + uint32_t result = RawInstr | Imm; + + *(little32_t *)FixupPtr = result; + break; + } + case aarch64::R_AARCH64_ADD_ABS_LO12_NC: { + int64_t value = E.getTarget().getAddress() + E.getAddend(); + + uint32_t Imm = extractBit<11, 0>(value); + uint32_t RawInstr = *(little32_t *)FixupPtr; + uint32_t result = RawInstr | Imm; + break; + } } return Error::success(); } + template static uint32_t extractBit(uint64_t num) { + return (static_cast(num) & ((1 << (hi + 1)) - 1)) >> lo; + } + + constexpr JITTargetAddress getPageAddress(JITTargetAddress expr) const { + return expr & ~0xfff; + } + template static bool fitsRangeSignedInt(int64_t Value) { return Value >= -(1 << Bits) && Value < (1 << Bits); } @@ -79,6 +122,12 @@ 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_ADR_PREL_PG_HI21_NC: + return EdgeKind_aarch64::R_AARCH64_ADR_PREL_PG_HI21_NC; + case ELF::R_AARCH64_ADD_ABS_LO12_NC: + return EdgeKind_aarch64::R_AARCH64_ADD_ABS_LO12_NC; } return make_error("Unsupported aarch64 relocation:" + diff --git a/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_aarch64_test1.s b/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_aarch64_test1.s new file mode 100644 --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_aarch64_test1.s @@ -0,0 +1,37 @@ +# REQUIRES: asserts +# RUN: llvm-mc -triple=aarch64 -filetype=obj -o %t %s +# RUN: llvm-jitlink -debug-only=jitlink -noexec %t 2>&1 | FileCheck %s + .text + .file "test1.c" + .globl main // -- Begin function main + .p2align 2 + .type main,@function +main: // @main +// %bb.0: + sub sp, sp, #16 // =16 + adrp x8, g + add x8, x8, :lo12:g + mov w9, wzr + str w0, [sp, #12] + str x1, [sp] + ldr w10, [x8] + add w10, w10, #1 // =1 + str w10, [x8] + mov w0, w9 + add sp, sp, #16 // =16 + ret +.Lfunc_end0: + .size main, .Lfunc_end0-main + // -- End function + .type g,@object // @g + .data + .globl g + .p2align 2 +g: + .word 1 // 0x1 + .size g, 4 + + .ident "clang version 10.0.0-4ubuntu1 " + .section ".note.GNU-stack","",@progbits + .addrsig + .addrsig_sym g