Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -738,17 +738,17 @@ case R_RELAX_TLS_IE_TO_LE: case R_RELAX_TLS_LD_TO_LE: case R_TLS: - // A weak undefined TLS symbol resolves to the base of the TLS - // block, i.e. gets a value of zero. If we pass --gc-sections to - // lld and .tbss is not referenced, it gets reclaimed and we don't - // create a TLS program header. Therefore, we resolve this - // statically to zero. - if (Sym.isTls() && Sym.isUndefWeak()) - return 0; + // It is not very clear what to return if the symbol is undefined. With + // --noinhibit-exec, even a non-weak undefined reference may reach here. + // Just return A, which matches R_ABS, and many dynamic loaders. + if (Sym.isUndefined()) + return A; return Sym.getVA(A) + getTlsTpOffset(); case R_RELAX_TLS_GD_TO_LE_NEG: case R_NEG_TLS: - return -(Sym.getVA(A) + getTlsTpOffset()); + if (Sym.isUndefined()) + return A; + return -(Sym.getVA(0) + getTlsTpOffset()) + A; case R_SIZE: return Sym.getSize() + A; case R_TLSDESC: Index: test/ELF/i386-tls-le-undef.s =================================================================== --- /dev/null +++ test/ELF/i386-tls-le-undef.s @@ -0,0 +1,16 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=i386 %s -o %t.o +# RUN: ld.lld --noinhibit-exec %t.o -o %t 2>&1 +# RUN: llvm-objdump -d %t | FileCheck %s + +## Undefined TLS symbols resolve to 0. +## In --noinhibit-exec mode, a non-weak undefined symbol is not an error. + +# CHECK: subl $0, %eax +# CHECK: subl $0, %eax + +.weak weak_undef +movl %gs:0, %eax +subl $weak_undef@tpoff,%eax +movl %gs:0, %eax +subl $undef@tpoff,%eax Index: test/ELF/x86-64-tls-le-undef.s =================================================================== --- /dev/null +++ test/ELF/x86-64-tls-le-undef.s @@ -0,0 +1,15 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o +# RUN: ld.lld --noinhibit-exec %t.o -o %t 2>&1 +# RUN: llvm-objdump -d %t | FileCheck %s + +## Undefined TLS symbols resolve to 0. +## In --noinhibit-exec mode, a non-weak undefined symbol is not an error. + +# CHECK: leaq 16(%rax), %rdx +# CHECK-NEXT: leaq 32(%rax), %rdx + +.weak weak +movq %fs:0, %rax +leaq weak@tpoff+16(%rax), %rdx +leaq global@tpoff+32(%rax), %rdx