[JITLink] Add support for R_X86_64_SIZE* relocations. (#110081)

This patch adds support for R_X86_64_SIZE32/R_X86_64_SIZE64 relocation
types by introducing edge kinds x86_64::Size32/x86_64::Size64. The
calculation for these relocations is: Z + A, where:

Z - Represents the size of the symbol whose index resides in the
    relocation entry.

A - Represents the addend used to compute the value of the relocation
    field.

Ref: [System V Application Binary Interface
x86-64](https://gitlab.com/x86-psABIs/x86-64-ABI/-/jobs/artifacts/master/raw/x86-64-ABI/abi.pdf?job=build)
This commit is contained in:
Xing Guo
2024-10-16 09:42:40 +08:00
committed by GitHub
parent 69f7758ddb
commit 210140ab6a
4 changed files with 71 additions and 0 deletions

View File

@@ -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 =

View File

@@ -182,6 +182,12 @@ private:
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;

View File

@@ -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:

View File

@@ -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.