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

Xing Guo via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 26 00:53:32 PDT 2024


https://github.com/higuoxing updated https://github.com/llvm/llvm-project/pull/110081

>From f1f0e9cdbb7da601774185dac6af50f677b73654 Mon Sep 17 00:00:00 2001
From: Xing Guo <higuoxing at gmail.com>
Date: Thu, 26 Sep 2024 07:52:07 +0800
Subject: [PATCH] [JITLink] Add support for R_X86_64_SIZE* relocations.

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)
---
 .../llvm/ExecutionEngine/JITLink/x86_64.h     | 34 +++++++++++++++++++
 .../ExecutionEngine/JITLink/ELF_x86_64.cpp    |  6 ++++
 llvm/lib/ExecutionEngine/JITLink/x86_64.cpp   |  4 +++
 .../JITLink/x86-64/ELF_R_X86_64_SIZE.s        | 27 +++++++++++++++
 4 files changed, 71 insertions(+)
 create mode 100644 llvm/test/ExecutionEngine/JITLink/x86-64/ELF_R_X86_64_SIZE.s

diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/x86_64.h b/llvm/include/llvm/ExecutionEngine/JITLink/x86_64.h
index 24cf982fc3ab0f..0d7e0fdb5820b5 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 6a32ccc3776510..44122726fb5c08 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<object::ELF64LE> {
     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 cca4358a377660..e5b48d2c3fab0e 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 00000000000000..abde122f76e237
--- /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, at function
+main:
+	xorl	%eax, %eax
+	movq	main at SIZE + 2, %rbx  # Generate R_X86_64_SIZE32 relocation.
+.ifndef OVERFLOW
+	movl	main at SIZE + 1, %ebx  # Generate R_X86_64_SIZE32 relocation.
+.else
+	movl	main at SIZE - 32, %ebx # Generate R_X86_64_SIZE32 relocation whose fixup overflows.
+.endif	
+	retq
+	.size	main, .-main
+
+	.data
+	.quad	main at SIZE + 1 # Generate R_X86_64_SIZE64 relocation.



More information about the llvm-commits mailing list