[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