[lld] r361146 - [ELF] Fix getRelocTargetVA formulae of R_TLS and R_NEG_TLS

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Mon May 20 04:47:31 PDT 2019


Author: maskray
Date: Mon May 20 04:47:31 2019
New Revision: 361146

URL: http://llvm.org/viewvc/llvm-project?rev=361146&view=rev
Log:
[ELF] Fix getRelocTargetVA formulae of R_TLS and R_NEG_TLS

For R_TLS:
1) Delete Sym.isTls() . The assembler ensures the symbol is STT_TLS.
   If not (the input is broken), we would crash (dereferencing null Out::TlsPhdr).
2) Change Sym.isUndefWeak() to Sym.isUndefined(), otherwise with --noinhibit-exec
   we would still evaluate the symbol and crash.
3) Return A if the symbol is undefined. This is PR40570.
   The case is probably unrealistic but returning A matches R_ABS and the
   behavior of several dynamic loaders.

R_NEG_TLS is obsoleted Sun TLS we don't fully support, but
R_RELAX_TLS_GD_TO_LE_NEG is still used by GD->LE relaxation (subl $var at tpoff,%eax).

They should add the addend. Unfortunately I can't test it as compilers don't seem to generate non-zero implicit addends.

Reviewed By: ruiu

Differential Revision: https://reviews.llvm.org/D62098

Added:
    lld/trunk/test/ELF/i386-tls-le-undef.s
    lld/trunk/test/ELF/x86-64-tls-le-undef.s
Modified:
    lld/trunk/ELF/InputSection.cpp

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=361146&r1=361145&r2=361146&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Mon May 20 04:47:31 2019
@@ -738,17 +738,18 @@ static uint64_t getRelocTargetVA(const I
   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 the behavior of some 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:

Added: lld/trunk/test/ELF/i386-tls-le-undef.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/i386-tls-le-undef.s?rev=361146&view=auto
==============================================================================
--- lld/trunk/test/ELF/i386-tls-le-undef.s (added)
+++ lld/trunk/test/ELF/i386-tls-le-undef.s Mon May 20 04:47:31 2019
@@ -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 at tpoff,%eax
+movl %gs:0, %eax
+subl $undef at tpoff,%eax

Added: lld/trunk/test/ELF/x86-64-tls-le-undef.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/x86-64-tls-le-undef.s?rev=361146&view=auto
==============================================================================
--- lld/trunk/test/ELF/x86-64-tls-le-undef.s (added)
+++ lld/trunk/test/ELF/x86-64-tls-le-undef.s Mon May 20 04:47:31 2019
@@ -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 at tpoff+16(%rax), %rdx
+leaq global at tpoff+32(%rax), %rdx




More information about the llvm-commits mailing list