[lld] [ELF] Fix TLSDESC=>IE when there is no TLS section (PR #98569)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 11 17:39:18 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lld-elf
Author: Fangrui Song (MaskRay)
<details>
<summary>Changes</summary>
See the comment in handleTlsRelocation. For TLSDESC=>IE (the TLS symbol
is defined in another DSO), R_RISCV_TLSDESC_{LOAD_LO12,ADD_LO12_I,CALL}
referencing a non-preemptible label uses the `R_RELAX_TLS_GD_TO_LE` code
path.
If there is no TLS section, `getTlsTpOffset` will be called with null
`Out::tlsPhdr`, leading to a null pointer dereference. Since the return
value is ignored by `RISCV::relocateAlloc`, just return 0.
---
Full diff: https://github.com/llvm/llvm-project/pull/98569.diff
3 Files Affected:
- (modified) lld/ELF/Arch/RISCV.cpp (+2-2)
- (modified) lld/ELF/InputSection.cpp (+6-1)
- (modified) lld/test/ELF/riscv-tlsdesc.s (+23)
``````````diff
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index faacc8f834be7..6af89ce3517b7 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -631,8 +631,8 @@ void RISCV::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
continue;
case R_RELAX_TLS_GD_TO_LE:
// See the comment in handleTlsRelocation. For TLSDESC=>IE,
- // R_RISCV_TLSDESC_{LOAD_LO12,ADD_LO12,CALL} also reach here. If isToIe is
- // true, this is actually TLSDESC=>IE optimization.
+ // R_RISCV_TLSDESC_{LOAD_LO12,ADD_LO12,CALL} also reach here. If isToLe is
+ // false, this is actually TLSDESC=>IE optimization.
if (rel.type == R_RISCV_TLSDESC_HI20) {
tlsdescVal = val;
isToLe = true;
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 4420be77f6685..6ea4453581894 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -660,7 +660,12 @@ static int64_t getTlsTpOffset(const Symbol &s) {
return s.getVA(0) + (tls->p_vaddr & (tls->p_align - 1)) - 0x7000;
case EM_LOONGARCH:
case EM_RISCV:
- return s.getVA(0) + (tls->p_vaddr & (tls->p_align - 1));
+ // See the comment in handleTlsRelocation. For TLSDESC=>IE,
+ // R_RISCV_TLSDESC_{LOAD_LO12,ADD_LO12_I,CALL} also reach here. While
+ // `tls` may be null, the return value is ignored.
+ if (s.type != STT_TLS)
+ return 0;
+ return s.getVA(0) + (tls ? tls->p_vaddr & (tls->p_align - 1) : 0);
// Variant 2.
case EM_HEXAGON:
diff --git a/lld/test/ELF/riscv-tlsdesc.s b/lld/test/ELF/riscv-tlsdesc.s
index 935ecbddfbfff..05d94d7538f92 100644
--- a/lld/test/ELF/riscv-tlsdesc.s
+++ b/lld/test/ELF/riscv-tlsdesc.s
@@ -37,6 +37,11 @@
# RUN: llvm-mc -triple=riscv32 -filetype=obj d.s -o d.32.o --defsym ELF32=1
# RUN: ld.lld -shared -soname=d.32.so -o d.32.so d.32.o --fatal-warnings
+## The output has no TLS section.
+# RUN: llvm-mc -filetype=obj -triple=riscv64 a1.s -o a1.64.o
+# RUN: ld.lld -pie a1.64.o c.64.so -o a1.64
+# RUN: llvm-objdump --no-show-raw-insn -M no-aliases -Rd a1.64 | FileCheck %s --check-prefix=IE64A
+
# GD64-RELA: .rela.dyn {
# GD64-RELA-NEXT: 0x2408 R_RISCV_TLSDESC - 0x7FF
# GD64-RELA-NEXT: 0x23E8 R_RISCV_TLSDESC a 0x0
@@ -164,6 +169,15 @@
# IE32-NEXT: lw a0, 0x80(a0)
# IE32-NEXT: add a0, a0, tp
+# IE64A-LABEL: 0000000000002340 R_RISCV_TLS_TPREL64 c
+## &.got[c]-. = 0x2340 - 0x1258 = 0x10e8
+# IE64A-LABEL: <.Ltlsdesc_hi2>:
+# IE64A-NEXT: addi zero, zero, 0x0
+# IE64A-NEXT: addi zero, zero, 0x0
+# IE64A-NEXT: 1258: auipc a0, 0x1
+# IE64A-NEXT: ld a0, 0xe8(a0)
+# IE64A-NEXT: add a0, a0, tp
+
#--- a.s
.macro load dst, src
.ifdef ELF32
@@ -202,6 +216,15 @@ a:
b:
.zero 1
+#--- a1.s
+## a.s without TLS definitions.
+.Ltlsdesc_hi2:
+ auipc a4, %tlsdesc_hi(c)
+ ld a5, %tlsdesc_load_lo(.Ltlsdesc_hi2)(a4)
+ addi a0, a4, %tlsdesc_add_lo(.Ltlsdesc_hi2)
+ jalr t0, 0(a5), %tlsdesc_call(.Ltlsdesc_hi2)
+ add a0, a0, tp
+
#--- c.s
.tbss
.globl c
``````````
</details>
https://github.com/llvm/llvm-project/pull/98569
More information about the llvm-commits
mailing list