diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h b/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h --- a/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/ELF_x86_64.h @@ -21,6 +21,7 @@ namespace ELF_x86_64_Edges { enum ELFX86RelocationKind : Edge::Kind { Branch32 = Edge::FirstRelocation, + Pointer32Signed, Pointer64, PCRel32, PCRel32GOTLoad, diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/x86_64.h b/llvm/include/llvm/ExecutionEngine/JITLink/x86_64.h --- a/llvm/include/llvm/ExecutionEngine/JITLink/x86_64.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/x86_64.h @@ -42,6 +42,16 @@ /// Pointer32, + /// A signed 32-bit pointer value relocation + /// + /// Fixup expression: + /// Fixup <- Target + Addend : int32 + /// + /// Errors: + /// - The target must reside in the signed 32-bits([-2**31, 2**32 - 1]) of + /// the address space, otherwise an out-of-range error will be returned. + Pointer32Signed, + /// A 64-bit delta. /// /// Delta from the fixup to the target. @@ -380,6 +390,14 @@ return makeTargetOutOfRangeError(G, B, E); break; } + case Pointer32Signed: { + int64_t Value = E.getTarget().getAddress() + E.getAddend(); + if (LLVM_LIKELY(isInRangeForImmS32(Value))) + *(little32_t *)FixupPtr = Value; + else + return makeTargetOutOfRangeError(G, B, E); + break; + } case BranchPCRel32: case BranchPCRel32ToPtrJumpStub: diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp --- a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp @@ -176,6 +176,8 @@ static Expected getRelocationKind(const uint32_t Type) { switch (Type) { + case ELF::R_X86_64_32S: + return ELF_x86_64_Edges::ELFX86RelocationKind::Pointer32Signed; case ELF::R_X86_64_PC32: return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel32; case ELF::R_X86_64_PC64: @@ -298,6 +300,9 @@ case Delta64: Kind = x86_64::Delta64; break; + case Pointer32Signed: + Kind = x86_64::Pointer32Signed; + break; case Pointer64: Kind = x86_64::Pointer64; break; @@ -497,6 +502,8 @@ switch (R) { case Branch32: return "Branch32"; + case Pointer32Signed: + return "Pointer32Signed"; case Pointer64: return "Pointer64"; case PCRel32: diff --git a/llvm/lib/ExecutionEngine/JITLink/x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/x86_64.cpp --- a/llvm/lib/ExecutionEngine/JITLink/x86_64.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/x86_64.cpp @@ -24,6 +24,8 @@ return "Pointer64"; case Pointer32: return "Pointer32"; + case Pointer32Signed: + return "Pointer32Signed"; case Delta64: return "Delta64"; case Delta32: diff --git a/llvm/test/ExecutionEngine/JITLink/X86/ELF_x86_64_absolute_relocations.s b/llvm/test/ExecutionEngine/JITLink/X86/ELF_x86_64_absolute_relocations.s new file mode 100644 --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/X86/ELF_x86_64_absolute_relocations.s @@ -0,0 +1,35 @@ +# RUN: rm -rf %t && mkdir -p %t +# RUN: llvm-mc -triple=x86_64-unknown-linux -position-independent -filetype=obj \ +# RUN: -o %t/elf_abs_reloc.o %s +# RUN: llvm-jitlink -noexec -slab-allocate 100Kb -slab-address 0xfff00000 \ +# RUN: -define-abs external_data_low=0x1 \ +# RUN: -define-abs external_data_high=0xffffffff80000000 \ +# RUN: -check %s %t/elf_abs_reloc.o +# +# Test ELF absolute relocations. + + + .text + .file "testcase.c" + +# Empty main entry point. + .globl main + .p2align 4, 0x90 + .type main,@function +main: + retq + + .size main, .-main + +# R_X86_64_32S handling +# Test the target value is in range of signed 32-bits imm +# jitlink-check: decode_operand(test_abs_32S, 4) = external_data_low +# jitlink-check: decode_operand(test_abs_32S+7, 4)[31:0] = external_data_high[31:0] + .globl test_abs_32S + .p2align 4, 0x90 + .type test_abs_32S,@function +test_abs_32S: + movl external_data_low, %eax + movl external_data_high, %esi + + .size test_abs_32S, .-test_abs_32S