diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/x86_64.h b/llvm/include/llvm/ExecutionEngine/JITLink/x86_64.h index 24cf982fc3ab0..0d7e0fdb5820b 100644 --- a/llvm/include/llvm/ExecutionEngine/JITLink/x86_64.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/x86_64.h @@ -142,6 +142,24 @@ enum EdgeKind_x86_64 : Edge::Kind { /// an out-of-range error will be returned. NegDelta32, + /// A 64-bit size relocation. + /// + /// Fixup expression: + /// Fixup <- Size + Addend : uint64 + /// + Size64, + + /// A 32-bit size relocation. + /// + /// Fixup expression: + /// Fixup <- Size + Addend : uint32 + /// + /// Errors: + /// - The result of the fixup expression must fit into an uint32, otherwise + /// an out-of-range error will be returned. + /// + Size32, + /// A 64-bit GOT delta. /// /// Delta from the global offset table to the target @@ -531,6 +549,22 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, return makeTargetOutOfRangeError(G, B, E); break; } + + case Size64: { + uint64_t Value = E.getTarget().getSize() + E.getAddend(); + *(ulittle64_t *)FixupPtr = Value; + break; + } + + case Size32: { + uint64_t Value = E.getTarget().getSize() + E.getAddend(); + if (LLVM_LIKELY(isUInt<32>(Value))) + *(ulittle32_t *)FixupPtr = Value; + else + return makeTargetOutOfRangeError(G, B, E); + break; + } + case Delta64FromGOT: { assert(GOTSymbol && "No GOT section symbol"); int64_t Value = diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp index 6a32ccc377651..44122726fb5c0 100644 --- a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp @@ -182,6 +182,12 @@ class ELFLinkGraphBuilder_x86_64 : public ELFLinkGraphBuilder { case ELF::R_X86_64_64: Kind = x86_64::Pointer64; break; + case ELF::R_X86_64_SIZE32: + Kind = x86_64::Size32; + break; + case ELF::R_X86_64_SIZE64: + Kind = x86_64::Size64; + break; case ELF::R_X86_64_GOTPCREL: Kind = x86_64::RequestGOTAndTransformToDelta32; break; diff --git a/llvm/lib/ExecutionEngine/JITLink/x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/x86_64.cpp index cca4358a37766..e5b48d2c3fab0 100644 --- a/llvm/lib/ExecutionEngine/JITLink/x86_64.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/x86_64.cpp @@ -42,6 +42,10 @@ const char *getEdgeKindName(Edge::Kind K) { return "NegDelta64"; case NegDelta32: return "NegDelta32"; + case Size64: + return "Size64"; + case Size32: + return "Size32"; case Delta64FromGOT: return "Delta64FromGOT"; case PCRel32: diff --git a/llvm/test/ExecutionEngine/JITLink/x86-64/ELF_R_X86_64_SIZE.s b/llvm/test/ExecutionEngine/JITLink/x86-64/ELF_R_X86_64_SIZE.s new file mode 100644 index 0000000000000..abde122f76e23 --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/x86-64/ELF_R_X86_64_SIZE.s @@ -0,0 +1,27 @@ +# Checks that JITLink is able to handle R_X86_64_SIZE32/R_X86_64_SIZE64 relocations. +# RUN: llvm-mc -triple=x86_64-unknown-linux -position-independent \ +# RUN: -filetype=obj -o %t.1.o %s +# RUN: llvm-jitlink -noexec %t.1.o + +# Checks that JITLink emits an error message when the fixup cannot fit into a 32-bit value. +# RUN: llvm-mc -triple=x86_64-unknown-linux -position-independent --defsym=OVERFLOW=1 \ +# RUN: -filetype=obj -o %t.2.o %s +# RUN: not llvm-jitlink -noexec %t.2.o 2>&1 | FileCheck %s +# CHECK: llvm-jitlink error: In graph {{.*}}, section .text: relocation target "main" at address {{.*}} is out of range of Size32 fixup at {{.*}} (main, {{.*}}) + + .text + .globl main + .type main,@function +main: + xorl %eax, %eax + movq main@SIZE + 2, %rbx # Generate R_X86_64_SIZE32 relocation. +.ifndef OVERFLOW + movl main@SIZE + 1, %ebx # Generate R_X86_64_SIZE32 relocation. +.else + movl main@SIZE - 32, %ebx # Generate R_X86_64_SIZE32 relocation whose fixup overflows. +.endif + retq + .size main, .-main + + .data + .quad main@SIZE + 1 # Generate R_X86_64_SIZE64 relocation.