[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:22:14 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-aarch64

Author: eleviant

<details>
<summary>Changes</summary>

Patch calculates branch address computing sum of sign extended relocation addend and PC related offset to a target symbol.

---
Full diff: https://github.com/llvm/llvm-project/pull/202588.diff


4 Files Affected:

- (modified) lld/COFF/Chunks.cpp (+6-2) 
- (added) lld/test/COFF/arm64-pcrel.s (+27) 
- (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp (-7) 
- (modified) llvm/test/MC/AArch64/coff-relocations-branch26.s (+9-9) 


``````````diff
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

``````````

</details>


https://github.com/llvm/llvm-project/pull/202588


More information about the llvm-commits mailing list