diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -907,12 +907,7 @@ continue; } - if (sym.isTls() && !Out::tlsPhdr) { - target->relocateNoSym(bufLoc, type, 0); - continue; - } - - if (isDebug && type == target->symbolicRel) { + if (isDebug && (type == target->symbolicRel || expr == R_DTPREL)) { // Resolve relocations in .debug_* referencing (discarded symbols or ICF // folded section symbols) to a tombstone value. Resolving to addend is // unsatisfactory because the result address range may collide with a @@ -924,6 +919,10 @@ // to resolve an address attribute (which may have a non-zero addend) to // -1+addend (wrap around to a low address). // + // R_DTPREL type relocations represent an offset into the dynamic thread + // vector. The computed value is st_value plus a non-negative offset. + // Negative values are invalid, so -1 can be used as the tombstone value. + // // If the referenced symbol is discarded (made Undefined), or the // section defining the referenced symbol is garbage collected, // sym.getOutputSection() is nullptr. `ds->section->repl != ds->section` diff --git a/lld/test/ELF/debug-dead-reloc-tls-arm.s b/lld/test/ELF/debug-dead-reloc-tls-arm.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/debug-dead-reloc-tls-arm.s @@ -0,0 +1,22 @@ +# REQUIRES: arm +## Test we resolve relocations referencing TLS symbols in .debug_* sections to +## a tombstone value if the referenced TLS symbol is discarded. + +# RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o +# RUN: ld.lld --gc-sections %t.o -o %t +# RUN: llvm-objdump -s %t | FileCheck %s + +# CHECK: Contents of section .debug_info: +# CHECK-NEXT: 0000 ffffffff + +.globl _start +_start: + bx lr + +.section .tbss,"awT",%nobits +.globl tls + .long 0 + +.section .debug_info +## R_ARM_TLS_LDO32 + .long tls(tlsldo) diff --git a/lld/test/ELF/debug-dead-reloc-tls.s b/lld/test/ELF/debug-dead-reloc-tls.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/debug-dead-reloc-tls.s @@ -0,0 +1,32 @@ +# REQUIRES: x86 +## Test we resolve relocations referencing TLS symbols in .debug_* sections to +## a tombstone value if the referenced TLS symbol is discarded. + +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o +# RUN: ld.lld --gc-sections %t.o -o %t +# RUN: llvm-objdump -s %t | FileCheck %s + +# CHECK: Contents of section .debug_info: +# CHECK-NEXT: 0000 ffffffff ffffffff ffffffff ffffffff +# CHECK-NEXT: 0010 ffffffff ffffffff + +.globl _start +_start: + ret + +.section .tbss,"awT",@nobits +.globl global +local: +global: + .quad 0 + +.section .debug_info +## On ppc64, .quad local@dtprel+0x8000 (st_value 0 is supposed to point to +## 0x8000 bytes past the start of ## the dynamic TLS vector. References usually +## have an addend of 0x8000). MIPS is similar. RISC-V uses 0x800. + .quad local@dtpoff+0x8000 + .quad global@dtpoff+0x8000 + +## Many other architectures don't use an offset. GCC x86-64 uses a 32-bit value. + .long global@dtpoff + .long -1 diff --git a/lld/test/ELF/gc-debuginfo-tls.s b/lld/test/ELF/gc-debuginfo-tls.s deleted file mode 100644 --- a/lld/test/ELF/gc-debuginfo-tls.s +++ /dev/null @@ -1,24 +0,0 @@ -# REQUIRES: x86 -# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o -# RUN: ld.lld %t.o --gc-sections -shared -o %t1 -# RUN: ld.lld %t.o -shared -o %t2 -# RUN: llvm-readobj --symbols %t1 | FileCheck %s --check-prefix=GC -# RUN: llvm-readobj --symbols %t2 | FileCheck %s --check-prefix=NOGC - -# NOGC: Symbol { -# NOGC: Name: patatino -# NOGC-NEXT: Value: 0x0 -# NOGC-NEXT: Size: 0 -# NOGC-NEXT: Binding: Local -# NOGC-NEXT: Type: TLS -# NOGC-NEXT: Other: 0 -# NOGC-NEXT: Section: .tbss -# NOGC-NEXT: } - -# GC-NOT: tbss - -.section .tbss,"awT",@nobits -patatino: - .long 0 - .section .noalloc,"" - .quad patatino diff --git a/lld/test/ELF/gc-sections-tls.s b/lld/test/ELF/gc-sections-tls.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/gc-sections-tls.s @@ -0,0 +1,25 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o + +## Relocation in a non .debug_* referencing a discarded TLS symbol is invalid. +## If we happen to have no PT_TLS, we will emit an error. +# RUN: not ld.lld %t.o --gc-sections -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR + +# ERR: error: {{.*}}.o has an STT_TLS symbol but doesn't have an SHF_TLS section + +## If we happen to have a PT_TLS, we will resolve the relocation to +## an arbitrary value (current implementation uses a negative value). +# RUN: echo '.section .tbss,"awT"; .globl root; root: .long 0' | \ +# RUN: llvm-mc -filetype=obj -triple=x86_64 - -o %t1.o +# RUN: ld.lld --gc-sections -u root %t.o %t1.o -o %t +# RUN: llvm-readelf -x .noalloc %t | FileCheck %s + +# CHECK: Hex dump of section '.noalloc': +# CHECK-NEXT: 0x00000000 {{[0-9a-f]+}} ffffffff + +.section .tbss,"awT",@nobits +tls: + .long 0 + +.section .noalloc,"" + .quad tls+0x8000