[lld] [llvm] [lld][COFF] Add support for IMAGE_REL_ARM64_BRANCH26 (PR #202588)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 9 05:21:36 PDT 2026
https://github.com/eleviant created https://github.com/llvm/llvm-project/pull/202588
Patch calculates branch address computing sum of sign extended relocation addend and PC related offset to a target symbol.
>From 001d150c9a4096e31a1d85ea7bc50ded960f2692 Mon Sep 17 00:00:00 2001
From: Evgeny Leviant <eleviant at accesssoftek.com>
Date: Tue, 9 Jun 2026 14:17:45 +0200
Subject: [PATCH] [lld][COFF] Add support for IMAGE_REL_ARM64_BRANCH26
Patch calculates branch address computing sum of sign extended
relocation addend and PC related offset to a target symbol.
---
lld/COFF/Chunks.cpp | 8 ++++--
lld/test/COFF/arm64-pcrel.s | 27 +++++++++++++++++++
.../MCTargetDesc/AArch64AsmBackend.cpp | 7 -----
.../MC/AArch64/coff-relocations-branch26.s | 18 ++++++-------
4 files changed, 42 insertions(+), 18 deletions(-)
create mode 100644 lld/test/COFF/arm64-pcrel.s
diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
index efc9ff113e623..7cf26708a751e 100644
--- a/lld/COFF/Chunks.cpp
+++ b/lld/COFF/Chunks.cpp
@@ -319,9 +319,13 @@ static void applySecRelLdr(const SectionChunk *sec, uint8_t *off,
}
void applyArm64Branch26(uint8_t *off, int64_t v) {
- if (!isInt<28>(v))
+ int32_t contents = read32le(off);
+ // Original lower 26 bits must be extracted, preserving signed-int-ness, and
+ // fixup value must be shifted right 2.
+ int64_t value = SignExtend64<26>(contents) + (v >> 2);
+ if (!isInt<26>(value))
error("relocation out of range");
- or32(off, (v & 0x0FFFFFFC) >> 2);
+ write32le(off, (contents & 0xFC000000u) | (value & 0x03FFFFFFu));
}
static void applyArm64Branch19(uint8_t *off, int64_t v) {
diff --git a/lld/test/COFF/arm64-pcrel.s b/lld/test/COFF/arm64-pcrel.s
new file mode 100644
index 0000000000000..3e54befd1d539
--- /dev/null
+++ b/lld/test/COFF/arm64-pcrel.s
@@ -0,0 +1,27 @@
+// REQUIRES: aarch64
+// RUN: llvm-mc -triple aarch64-unknown-windows-msvc -filetype obj %s -o %t.o
+// RUN: lld-link -machine:arm64 -dll -noentry -base:0x0 %t.o -out:%t.dll
+// RUN: llvm-objdump -d %t.dll | FileCheck %s
+
+// CHECK: 0000000000001000 <.text>:
+// CHECK-NEXT: 1000: d503201f nop
+// CHECK-NEXT: 1004: 14000002 b 0x100c <.text+0xc>
+// CHECK-NEXT: 1008: d503201f nop
+// CHECK-NEXT: 100c: d503201f nop
+// CHECK-NEXT: 1010: d65f03c0 ret
+
+.globl main
+
+main:
+ nop
+ b .Lpcrel_target-4
+
+ .def .Lpcrel_target
+ .scl 3
+ .type 32
+ .p2align 2
+ .endef
+ nop
+ nop
+.Lpcrel_target:
+ ret
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
index eece54692e18c..a3e88515111dd 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
@@ -318,13 +318,6 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, const MCValue &Target,
return (Value >> 2) & 0xffff;
case AArch64::fixup_aarch64_pcrel_branch26:
case AArch64::fixup_aarch64_pcrel_call26:
- if (TheTriple.isOSBinFormatCOFF() && !IsResolved && SignedValue != 0) {
- // MSVC link.exe and lld do not support this relocation type
- // with a non-zero offset
- Ctx.reportError(Fixup.getLoc(),
- "cannot perform a PC-relative fixup with a non-zero "
- "symbol offset");
- }
// Signed 28-bit immediate
if (!isInt<28>(SignedValue))
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
diff --git a/llvm/test/MC/AArch64/coff-relocations-branch26.s b/llvm/test/MC/AArch64/coff-relocations-branch26.s
index 51bbb4932f231..e8cec153eeb9a 100644
--- a/llvm/test/MC/AArch64/coff-relocations-branch26.s
+++ b/llvm/test/MC/AArch64/coff-relocations-branch26.s
@@ -1,5 +1,4 @@
// RUN: llvm-mc -triple aarch64-unknown-windows-msvc -filetype obj %s -o - | llvm-objdump -D -r - | FileCheck %s
-// RUN: not llvm-mc -triple aarch64-unknown-windows-msvc -filetype obj --defsym ERR=1 %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR
.text
main:
@@ -56,20 +55,21 @@ main:
// CHECK: 0000000000000020 <.Lother_target>:
// CHECK: 20: d65f03c0 ret
-.ifdef ERR
- .section "err"
-err:
+// CHECK: 0000000000000000 <foo>:
+// CHECK: 0: d503201f nop
+// CHECK: 4: 14000001 b 0x8 <.Lpcrel_target>
+// CHECK: 0000000000000004: IMAGE_REL_ARM64_BRANCH26 .Lpcrel_target
+
+ .section "foo"
nop
- b .Lerr_target+4
-// ERR: [[#@LINE-1]]:19: error: cannot perform a PC-relative fixup with a non-zero symbol offset
+ b .Lpcrel_target+4
- .def .Lerr_target
+ .def .Lpcrel_target
.scl 3
.type 32
.p2align 2
.endef
-.Lerr_target:
+.Lpcrel_target:
nop
nop
ret
-.endif
More information about the llvm-commits
mailing list