[lld] [ELF][RISCV] Do not range-check R_RISCV_SET32 (PR #219532)
Shaoce SUN via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 28 10:02:26 PDT 2026
https://github.com/sunshaoce created https://github.com/llvm/llvm-project/pull/219532
The psABI defines `R_RISCV_SET32` as a word32 local label assignment,
`SET32`: `word32` `S + A` `Local label assignment`
https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc
The `checkInt(ctx, loc, val, 32, rel);` incorrectly required the intermediate value to fit in a signed 32-bit integer. A following `R_RISCV_SUB32` may still make the final result fit, so handle `R_RISCV_SET32` separately.
>From 6dd5461bef22bc2dd9c668272398dd3ec1d7d842 Mon Sep 17 00:00:00 2001
From: Shaoce SUN <sunshaoce at outlook.com>
Date: Sat, 29 Aug 2026 00:56:51 +0800
Subject: [PATCH] [ELF][RISCV] Do not range-check R_RISCV_SET32
---
lld/ELF/Arch/RISCV.cpp | 2 ++
lld/test/ELF/riscv64-reloc-set32.s | 18 ++++++++++++++++++
2 files changed, 20 insertions(+)
create mode 100644 lld/test/ELF/riscv64-reloc-set32.s
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 49c41ff9ebe84..13c919c195e2e 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -702,6 +702,8 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
write16le(loc, val);
return;
case R_RISCV_SET32:
+ write32le(loc, val);
+ return;
case R_RISCV_32_PCREL:
case R_RISCV_PLT32:
case R_RISCV_GOT32_PCREL:
diff --git a/lld/test/ELF/riscv64-reloc-set32.s b/lld/test/ELF/riscv64-reloc-set32.s
new file mode 100644
index 0000000000000..7d0800802ea23
--- /dev/null
+++ b/lld/test/ELF/riscv64-reloc-set32.s
@@ -0,0 +1,18 @@
+# REQUIRES: riscv
+# RUN: llvm-mc -filetype=obj -triple=riscv64 %s -o %t.o
+# RUN: ld.lld -Ttext=0x100000000 %t.o -o %t
+# RUN: llvm-readelf -x .text %t | FileCheck %s
+
+# CHECK: section '.text':
+# CHECK-NEXT: 0x{{[0-9a-f]+}} 04000000
+
+## R_RISCV_SET32/R_RISCV_SUB32 pairs are used for some CFI label differences.
+## Above 4 GiB, the SET32 intermediate value exceeds 32 bits, but the final
+## difference is representable.
+
+.globl _start
+_start:
+ .reloc ., R_RISCV_SET32, .Lend
+ .reloc ., R_RISCV_SUB32, _start
+ .word 0
+.Lend:
More information about the llvm-commits
mailing list