diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -906,12 +906,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 @@ -923,6 +918,10 @@ // to resolve an address attribute (which may have a non-zero addend) to // -1+addend (wrap around to a low address). // + // R_DTPREL typed 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.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,27 @@ +# 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 + +.globl _start +_start: + ret + +.section .tbss,"awT" +.globl global +local: +global: + .quad 0 + +.section .debug_info +## On ppc64, 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. Many other architectures don't use an offset. + .quad local+0x8000 + .quad global+0x8000 diff --git a/lld/test/ELF/gc-debuginfo-tls.s b/lld/test/ELF/gc-debuginfo-tls.s --- a/lld/test/ELF/gc-debuginfo-tls.s +++ b/lld/test/ELF/gc-debuginfo-tls.s @@ -1,10 +1,11 @@ # 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: not ld.lld %t.o --gc-sections -shared -o %t1 2>&1 | FileCheck %s --check-prefix=ERR # 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 +# ERR: error: {{.*}}.o has an STT_TLS symbol but doesn't have an SHF_TL + # NOGC: Symbol { # NOGC: Name: patatino # NOGC-NEXT: Value: 0x0 @@ -15,8 +16,6 @@ # NOGC-NEXT: Section: .tbss # NOGC-NEXT: } -# GC-NOT: tbss - .section .tbss,"awT",@nobits patatino: .long 0