[PATCH] D62098: [ELF] Fix getRelocTargetVA formulae of R_TLS and R_NEG_TLS

Fangrui Song via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sat May 18 02:29:06 PDT 2019


MaskRay created this revision.
MaskRay added reviewers: grimar, rprichard, ruiu.
Herald added subscribers: llvm-commits, arichardson, emaste.
Herald added a reviewer: espindola.
Herald added a project: LLVM.

1. Delete the test Sym.isTls() . The assembler ensure the symbol is STT_TLS, if not (the input is broken enough), we would crash if we access the null Out::TlsPhdr.
2. Return A instead of 0 in the case of a weak undefined TLS symbol. This is PR40570. It is probably unrealistic but returning A matches Sym.getVA(A), we just drop the getTlsTpOffset() item.
3. Use Sym.isUndefined(), otherwise with --noinhibit-exec we still evaluate the symbol and would crash.
4. Add Sym.isUndefined() test to the R_RELAX_TLS_GD_TO_LE_NEG and R_NEG_TLS case. i386-tls-le-undef.s crashes without the change. (This is obsoleted Sun TLS we don't fully support, but it improves similarity with the R_TLS case).
5. The R_RELAX_TLS_GD_TO_LE_NEG and R_NEG_TLS case should add the addend. Unfortunately I can't test it as compilers don't seem to generate non-zero implicit addends. R_NEG_TLS is used by the obsoleted Sun TLS. R_RELAX_TLS_GD_TO_LE_NEG is used in the relaxation (subl $var at tpoff,%eax) that always gets 0 addend.


Repository:
  rLLD LLVM Linker

https://reviews.llvm.org/D62098

Files:
  ELF/InputSection.cpp
  test/ELF/i386-tls-le-undef.s
  test/ELF/x86-64-tls-le-undef.s


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 at tpoff+16(%rax), %rdx
+leaq global at tpoff+32(%rax), %rdx
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 at tpoff,%eax
+movl %gs:0, %eax
+subl $undef at tpoff,%eax
Index: ELF/InputSection.cpp
===================================================================
--- ELF/InputSection.cpp
+++ ELF/InputSection.cpp
@@ -738,17 +738,18 @@
   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;
+    // A weak undefined TLS reference resolves to 0. With --noinhibit-exec, a
+    // global undefined reference may also reach here. It is not very clear what
+    // we should return, just resolve the symbol to zero and return A. This
+    // matches the formula of the non-TLS R_ABS: Sym.getVA(A).
+    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:


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D62098.200138.patch
Type: text/x-patch
Size: 2488 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190518/5a54d174/attachment.bin>


More information about the llvm-commits mailing list