[lld] 8b90c3e - [lld][AArch64] Support R_AARCH64_TLSLE_ADD_TPREL_LO12 (#227173)

via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 29 18:26:03 PDT 2026


Author: dong jianqiang
Date: 2026-09-30T01:25:54Z
New Revision: 8b90c3edb7d025154f5228853fa38b97c54d17d5

URL: https://github.com/llvm/llvm-project/commit/8b90c3edb7d025154f5228853fa38b97c54d17d5
DIFF: https://github.com/llvm/llvm-project/commit/8b90c3edb7d025154f5228853fa38b97c54d17d5.diff

LOG: [lld][AArch64] Support R_AARCH64_TLSLE_ADD_TPREL_LO12 (#227173)

AArch64 local-exec TLS code sequences compiled with -mtls-size=12 use
the non-NC R_AARCH64_TLSLE_ADD_TPREL_LO12 relocation (emitted for 'add
xN, xN, :tprel_lo12:sym'), but lld only handles the _NC variant, so
linking such objects fails with 'unknown relocation'.

Add the relocation to the TLS LE group in scanSectionImpl (R_TPREL, same
group as the other TLSLE relocations, so it is also rejected for
-shared) and resolve it like the _NC variant, but with an unsigned
12-bit range check as the non-NC form requires the full offset to fit
into the imm12 field.

Added: 
    lld/test/ELF/aarch64-tls-le-12.s

Modified: 
    lld/ELF/Arch/AArch64.cpp
    lld/test/ELF/aarch64-tls-le.s

Removed: 
    


################################################################################
diff  --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index 5a9f306e9b47e..1d24084d82762 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -335,6 +335,7 @@ void AArch64::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
 
     // TLS LE relocations:
     case R_AARCH64_TLSLE_ADD_TPREL_HI12:
+    case R_AARCH64_TLSLE_ADD_TPREL_LO12:
     case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
     case R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC:
     case R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC:
@@ -830,6 +831,10 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel,
     }
     write32Imm12(loc, val >> 12);
     break;
+  case R_AARCH64_TLSLE_ADD_TPREL_LO12:
+    checkUInt(ctx, loc, val, 12, rel);
+    write32Imm12(loc, val);
+    break;
   case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
   case R_AARCH64_TLSDESC_ADD_LO12:
   case R_AARCH64_AUTH_TLSDESC_ADD_LO12:

diff  --git a/lld/test/ELF/aarch64-tls-le-12.s b/lld/test/ELF/aarch64-tls-le-12.s
new file mode 100644
index 0000000000000..2850464b7fd9d
--- /dev/null
+++ b/lld/test/ELF/aarch64-tls-le-12.s
@@ -0,0 +1,34 @@
+# REQUIRES: aarch64
+# RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: llvm-objdump --no-print-imm-hex -d --no-show-raw-insn %t | FileCheck %s
+
+## The non-NC R_AARCH64_TLSLE_ADD_TPREL_LO12 relocation requires the full
+## offset from the thread pointer to fit into an unsigned 12-bit immediate.
+# RUN: llvm-mc -filetype=obj -triple=aarch64 %s -defsym=OOR=1 -o %t.bad.o
+# RUN: not ld.lld %t.bad.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=OOR --implicit-check-not=error:
+
+# OOR: error: {{.*}}:(.text+0x4): relocation R_AARCH64_TLSLE_ADD_TPREL_LO12 out of range: 4096 is not in [0, 4095]; references 'v1'
+
+.globl _start
+_start:
+ mrs x0, TPIDR_EL0
+ add x0, x0, :tprel_lo12:v1
+
+#CHECK: Disassembly of section .text:
+#CHECK:      <_start>:
+#CHECK-NEXT:   mrs     x0, TPIDR_EL0
+#CHECK-NEXT:   add     x0, x0, #32
+
+.section        .tbss,"awT", at nobits
+.ifdef OOR
+.space (0x1000 - 0x10)
+.else
+.space 0x10
+.endif
+
+.type   v1, at object
+.globl  v1
+v1:
+.word  0
+.size  v1, 4

diff  --git a/lld/test/ELF/aarch64-tls-le.s b/lld/test/ELF/aarch64-tls-le.s
index feb269c30b2ab..91c52525b9422 100644
--- a/lld/test/ELF/aarch64-tls-le.s
+++ b/lld/test/ELF/aarch64-tls-le.s
@@ -15,6 +15,7 @@
 
 # ERR: error: relocation R_AARCH64_TLSLE_ADD_TPREL_HI12 against v1 cannot be used with -shared
 # ERR: error: relocation R_AARCH64_TLSLE_ADD_TPREL_LO12_NC against v1 cannot be used with -shared
+# ERR: error: relocation R_AARCH64_TLSLE_ADD_TPREL_LO12 against v3 cannot be used with -shared
 # ERR: error: relocation R_AARCH64_TLSLE_ADD_TPREL_HI12 against v2 cannot be used with -shared
 # ERR: error: relocation R_AARCH64_TLSLE_ADD_TPREL_LO12_NC against v2 cannot be used with -shared
 # ERR: error: relocation R_AARCH64_TLSLE_ADD_TPREL_HI12 against v1 cannot be used with -shared
@@ -27,6 +28,8 @@ _start:
  add x0, x0, :tprel_hi12:v1
  add x0, x0, :tprel_lo12_nc:v1
  mrs x0, TPIDR_EL0
+ add x0, x0, :tprel_lo12:v3
+ mrs x0, TPIDR_EL0
  add x0, x0, :tprel_hi12:v2
  add x0, x0, :tprel_lo12_nc:v2
  add x2, x1, :tprel_hi12:v1
@@ -41,6 +44,8 @@ _start:
 #NORELAX-NEXT:   add     x0, x0, #0, lsl #12
 #CHECK-NEXT:   add     x0, x0, #16
 #CHECK-NEXT:   mrs     x0, TPIDR_EL0
+#CHECK-NEXT:   add     x0, x0, #20
+#CHECK-NEXT:   mrs     x0, TPIDR_EL0
 #CHECK-NEXT:   add     x0, x0, #4095, lsl #12
 #CHECK-NEXT:   add     x0, x0, #4088
 #CHECK-NEXT:   add     x2, x1, #0, lsl #12
@@ -57,9 +62,16 @@ v1:
 .word  0
 .size  v1, 4
 
-# The current offset from the thread pointer is 20. Raise it to just below the
-# 24-bit limit.
-.space (0xfffff8 - 20)
+.type   v3, at object
+.globl  v3
+.p2align 2
+v3:
+.word  0
+.size  v3, 4
+
+## The current offset from the thread pointer is 24. Raise it to just below the
+## 24-bit limit.
+.space (0xfffff8 - 24)
 
 .type   v2, at object
 .globl  v2


        


More information about the llvm-commits mailing list