[llvm-branch-commits] [lld] release/23.x: [lld][LoongArch] Fix crash with TLS IE relocations in extreme code model (#234508) (PR #234554)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Oct 22 02:38:48 PDT 2026
https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/234554
Backport c98ead286790d9ed6d02a10b02129e63c66c965c
Requested by: @wangleiat
>From 78f748663a5f8ac92fb6813e6b82c1b259cc7148 Mon Sep 17 00:00:00 2001
From: wanglei <wanglei at loongson.cn>
Date: Thu, 22 Oct 2026 17:07:22 +0800
Subject: [PATCH] [lld][LoongArch] Fix crash with TLS IE relocations in extreme
code model (#234508)
Restore TLS IE and DESC relocation expressions needed by the extreme
code model fallback in relocateAlloc().
Fixes: #234507
(cherry picked from commit c98ead286790d9ed6d02a10b02129e63c66c965c)
---
lld/ELF/Arch/LoongArch.cpp | 15 ++++
lld/test/ELF/loongarch-tls-ie64.s | 71 +++++++++++++++++
lld/test/ELF/loongarch-tlsdesc64.s | 120 +++++++++++++++++++++++++++++
3 files changed, 206 insertions(+)
create mode 100644 lld/test/ELF/loongarch-tls-ie64.s
create mode 100644 lld/test/ELF/loongarch-tlsdesc64.s
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index 6c65b74b716f26..584432ed432f88 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -457,6 +457,21 @@ RelExpr LoongArch::getRelExpr(const RelType type, const Symbol &s,
case R_LARCH_TLS_DTPREL32:
case R_LARCH_TLS_DTPREL64:
return R_DTPREL;
+ // TLS IE relocations, reverted by the extreme code model fallback in
+ // relocateAlloc() .
+ case R_LARCH_TLS_IE_PC_HI20:
+ return RE_LOONGARCH_GOT_PAGE_PC;
+ case R_LARCH_TLS_IE_PC_LO12:
+ return RE_LOONGARCH_GOT;
+ // TLS DESC relocations, similarly reverted by the extreme code model
+ // fallback in relocateAlloc().
+ case R_LARCH_TLS_DESC_PC_HI20:
+ return RE_LOONGARCH_TLSDESC_PAGE_PC;
+ case R_LARCH_TLS_DESC_PC_LO12:
+ case R_LARCH_TLS_DESC_LD:
+ return R_TLSDESC;
+ case R_LARCH_TLS_DESC_PCREL20_S2:
+ return R_TLSDESC_PC;
default:
Err(ctx) << getErrorLoc(ctx, loc) << "unknown relocation (" << type.v
<< ") against symbol " << &s;
diff --git a/lld/test/ELF/loongarch-tls-ie64.s b/lld/test/ELF/loongarch-tls-ie64.s
new file mode 100644
index 00000000000000..188acb74bb32ba
--- /dev/null
+++ b/lld/test/ELF/loongarch-tls-ie64.s
@@ -0,0 +1,71 @@
+# REQUIRES: loongarch
+## Test for `TLS IE` with extreme code model.
+
+# RUN: rm -rf %t && split-file %s %t
+# RUN: llvm-mc --filetype=obj --triple=loongarch64 %t/ie64.s -o %t/ie64.o
+
+## IE
+# RUN: ld.lld -shared %t/ie64.o -o %t/ie64.so
+# RUN: llvm-readobj -r -d %t/ie64.so | FileCheck %s --check-prefix=IE64-REL
+# RUN: llvm-objdump -d --no-show-raw-insn %t/ie64.so | FileCheck %s --check-prefixes=IE64
+
+## IE -> LE
+# RUN: ld.lld %t/ie64.o -o %t/64
+# RUN: llvm-readelf -r %t/64 | FileCheck %s --check-prefix=NOREL
+# RUN: llvm-readelf -x .got %t/64 2>&1 | FileCheck --check-prefix=LE64-GOT %s
+# RUN: llvm-objdump -d --no-show-raw-insn %t/64 | FileCheck %s --check-prefixes=LE64
+
+# IE64-REL: FLAGS STATIC_TLS
+# IE64-REL: .rela.dyn {
+# IE64-REL-NEXT: 0x20388 R_LARCH_TLS_TPREL64 - 0xC
+# IE64-REL-NEXT: 0x20380 R_LARCH_TLS_TPREL64 a 0x0
+# IE64-REL-NEXT: }
+
+## &.got[0] - . = 0x20380 - 0x102a0: 0x10 pages, page offset 0x380
+## &.got[1] - . = 0x20388 - 0x102b8: 0x10 pages, page offset 0x388
+# IE64: 102a0: pcalau12i $a0, 16
+# IE64-NEXT: addi.d $a1, $zero, 896
+# IE64-NEXT: lu32i.d $a1, 0
+# IE64-NEXT: lu52i.d $a1, $a1, 0
+# IE64-NEXT: ldx.d $a0, $a0, $a1
+# IE64-NEXT: add.d $a0, $a0, $tp
+# IE64-NEXT: pcalau12i $a1, 16
+# IE64-NEXT: addi.d $a2, $zero, 904
+# IE64-NEXT: lu32i.d $a2, 0
+# IE64-NEXT: lu52i.d $a2, $a2, 0
+# IE64-NEXT: ldx.d $a1, $a1, $a2
+# IE64-NEXT: add.d $a1, $a1, $tp
+
+# NOREL: no relocations
+
+# a at tprel = st_value(a) = 0x8
+# b at tprel = st_value(a) = 0xc
+# LE64-GOT: section '.got':
+# LE64-GOT-NEXT: 0x000301f8 08000000 00000000 0c000000 00000000
+
+# LE64: 201c8: pcalau12i $a0, 16
+# LE64-NEXT: addi.d $a1, $zero, 504
+# LE64-NEXT: lu32i.d $a1, 0
+# LE64-NEXT: lu52i.d $a1, $a1, 0
+# LE64-NEXT: ldx.d $a0, $a0, $a1
+# LE64: 201e0: pcalau12i $a1, 16
+# LE64-NEXT: addi.d $a2, $zero, 512
+# LE64-NEXT: lu32i.d $a2, 0
+# LE64-NEXT: lu52i.d $a2, $a2, 0
+# LE64-NEXT: ldx.d $a1, $a1, $a2
+
+#--- ie64.s
+## la.tls.ie $a0, $a1, a expands to the 5-instruction extreme form:
+## pcalau12i/addi.d/lu32i.d/lu52i.d + ldx.d with R_LARCH_TLS_IE_PC_HI20/LO12,
+## R_LARCH_TLS_IE64_PC_LO20/HI12.
+la.tls.ie $a0, $a1, a
+add.d $a0, $a0, $tp
+la.tls.ie $a1, $a2, b
+add.d $a1, $a1, $tp
+
+.section .tbss,"awT", at nobits
+.global a
+.zero 8
+a:
+.zero 4
+b:
diff --git a/lld/test/ELF/loongarch-tlsdesc64.s b/lld/test/ELF/loongarch-tlsdesc64.s
new file mode 100644
index 00000000000000..5f833a633151fa
--- /dev/null
+++ b/lld/test/ELF/loongarch-tlsdesc64.s
@@ -0,0 +1,120 @@
+# REQUIRES: loongarch
+## Test for `TLS DESC` with extreme code model.
+
+# RUN: rm -rf %t && split-file %s %t && cd %t
+# RUN: llvm-mc -filetype=obj -triple=loongarch64 a.s -o a.64.o
+# RUN: llvm-mc -filetype=obj -triple=loongarch64 c.s -o c.64.o
+# RUN: ld.lld -shared -soname=c.64.so c.64.o -o c.64.so
+
+# RUN: ld.lld -shared -z now a.64.o c.64.o -o a.64.so
+# RUN: llvm-readobj -r -x .got a.64.so | FileCheck --check-prefix=GD64-RELA %s
+# RUN: llvm-objdump --no-show-raw-insn -h -d a.64.so | FileCheck %s --check-prefix=GD64
+
+# RUN: ld.lld -shared -z now a.64.o c.64.o -o rel.64.so -z rel
+# RUN: llvm-readobj -r -x .got rel.64.so | FileCheck --check-prefix=GD64-REL %s
+
+## Cannot convert TLSDESC to IE/LE with the extreme code model.
+## Only check the GOT slot.
+# RUN: ld.lld -e 0 -z now a.64.o c.64.o -o a.64.le
+# RUN: llvm-readobj -r -x .got a.64.le 2>&1 | FileCheck --check-prefix=LE64-RELA %s
+
+# RUN: ld.lld -e 0 -z now a.64.o c.64.so -o a.64.ie
+# RUN: llvm-readobj -r -x .got a.64.ie | FileCheck --check-prefix=IE64-RELA %s
+
+# GD64-RELA: .rela.dyn {
+# GD64-RELA-NEXT: 0x20420 R_LARCH_TLS_DESC64 - 0x7FF
+# GD64-RELA-NEXT: 0x20400 R_LARCH_TLS_DESC64 a 0x0
+# GD64-RELA-NEXT: 0x20410 R_LARCH_TLS_DESC64 c 0x0
+# GD64-RELA-NEXT: }
+
+# GD64-RELA: Hex dump of section '.got':
+# GD64-RELA-NEXT: 0x00020400 00000000 00000000 00000000 00000000 .
+# GD64-RELA-NEXT: 0x00020410 00000000 00000000 00000000 00000000 .
+# GD64-RELA-NEXT: 0x00020420 00000000 00000000 00000000 00000000 .
+
+# GD64-REL: .rel.dyn {
+# GD64-REL-NEXT: 0x20408 R_LARCH_TLS_DESC64 -
+# GD64-REL-NEXT: 0x203E8 R_LARCH_TLS_DESC64 a
+# GD64-REL-NEXT: 0x203F8 R_LARCH_TLS_DESC64 c
+# GD64-REL-NEXT: }
+# GD64-REL: Hex dump of section '.got':
+# GD64-REL-NEXT: 0x000203e8 00000000 00000000 00000000 00000000 .
+# GD64-REL-NEXT: 0x000203f8 00000000 00000000 00000000 00000000 .
+# GD64-REL-NEXT: 0x00020408 00000000 00000000 ff070000 00000000 .
+
+# GD64: .got 00000030 0000000000020400
+## &.got[a]-. = 0x20400 - 0x102e0: 0x10 pages, page offset 0x400
+# GD64: 102e0: pcalau12i $a0, 16
+# GD64-NEXT: addi.d $a1, $zero, 1024
+# GD64-NEXT: lu32i.d $a1, 0
+# GD64-NEXT: lu52i.d $a1, $a1, 0
+# GD64-NEXT: add.d $a0, $a0, $a1
+# GD64-NEXT: ld.d $ra, $a0, 0
+# GD64-NEXT: jirl $ra, $ra, 0
+# GD64-NEXT: add.d $a1, $a0, $tp
+## &.got[b]-. = 0x20400+32 - 0x10300: 0x10 pages, page offset 0x420
+# GD64-NEXT: 10300: pcalau12i $a0, 16
+# GD64-NEXT: addi.d $a2, $zero, 1056
+# GD64-NEXT: lu32i.d $a2, 0
+# GD64-NEXT: lu52i.d $a2, $a2, 0
+# GD64-NEXT: add.d $a0, $a0, $a2
+# GD64-NEXT: ld.d $ra, $a0, 0
+# GD64-NEXT: jirl $ra, $ra, 0
+# GD64-NEXT: add.d $a2, $a1, $tp
+## &.got[b]-. = 0x20400+16 - 0x10320: 0x10 pages, page offset 0x410
+# GD64-NEXT: 10320: pcalau12i $a0, 16
+# GD64-NEXT: addi.d $a3, $zero, 1040
+# GD64-NEXT: lu32i.d $a3, 0
+# GD64-NEXT: lu52i.d $a3, $a3, 0
+# GD64-NEXT: add.d $a0, $a0, $a3
+# GD64-NEXT: ld.d $ra, $a0, 0
+# GD64-NEXT: jirl $ra, $ra, 0
+# GD64-NEXT: add.d $a3, $a2, $tp
+
+# LE64-RELA: .rela.dyn {
+# LE64-RELA-NEXT: 0x30270 R_LARCH_TLS_DESC64 - 0x8
+# LE64-RELA-NEXT: 0x30280 R_LARCH_TLS_DESC64 - 0x800
+# LE64-RELA-NEXT: 0x30290 R_LARCH_TLS_DESC64 - 0x7FF
+# LE64-RELA-NEXT: }
+# LE64-RELA: Hex dump of section '.got':
+# LE64-RELA-NEXT: 0x00030270 00000000 00000000 00000000 00000000 .
+# LE64-RELA-NEXT: 0x00030280 00000000 00000000 00000000 00000000 .
+# LE64-RELA-NEXT: 0x00030290 00000000 00000000 00000000 00000000 .
+
+# IE64-RELA: .rela.dyn {
+# IE64-RELA-NEXT: 0x30410 R_LARCH_TLS_DESC64 - 0x8
+# IE64-RELA-NEXT: 0x30438 R_LARCH_TLS_DESC64 - 0x7FF
+# IE64-RELA-NEXT: 0x30420 R_LARCH_TLS_DESC64 c 0x0
+# IE64-RELA-NEXT: 0x30430 R_LARCH_TLS_TPREL64 c 0x0
+# IE64-RELA-NEXT: }
+# IE64-RELA: Hex dump of section '.got':
+# IE64-RELA-NEXT: 0x00030410 00000000 00000000 00000000 00000000 .
+# IE64-RELA-NEXT: 0x00030420 00000000 00000000 00000000 00000000 .
+# IE64-RELA-NEXT: 0x00030430 00000000 00000000 00000000 00000000 .
+# IE64-RELA-NEXT: 0x00030440 00000000 00000000 .
+
+#--- a.s
+## The extreme TLSDESC form: pcalau12i/addi.d/lu32i.d/lu52i.d build the address,
+## then ld.d + jirl call the resolvers, with R_LARCH_TLS_DESC_PC_HI20/LO12,
+## R_LARCH_TLS_DESC64_PC_LO20/HI12, R_LARCH_TLS_DESC_LD and CALL.
+la.tls.desc $a0, $a1, a
+add.d $a1, $a0, $tp
+
+la.tls.desc $a0, $a2, b
+add.d $a2, $a1, $tp
+
+la.tls.desc $a0, $a3, c
+add.d $a3, $a2, $tp
+
+.section .tbss,"awT", at nobits
+.globl a
+.zero 8
+a:
+.zero 2039 ## Place b at 0x7ff
+b:
+.zero 1
+
+#--- c.s
+.section .tbss,"awT", at nobits
+.globl c
+c: .zero 4
More information about the llvm-branch-commits
mailing list