[ELF] Fix a null pointer dereference when relocating a Local-Exec TLS relocation...
authorFangrui Song <maskray@google.com>
Tue, 21 Apr 2020 21:44:03 +0000 (14:44 -0700)
committerFangrui Song <maskray@google.com>
Tue, 21 Apr 2020 22:39:31 +0000 (15:39 -0700)
If there is no SHF_TLS section, there will be no PT_TLS and Out::tlsPhdr may be a nullptr.
If the symbol referenced by an R_TLS is lazy, we should treat the symbol as undefined.

Also reorganize tls-in-archive.s and tls-weak-undef.s . They do not test what they intended to test.

lld/ELF/InputSection.cpp
lld/test/ELF/Inputs/tls-in-archive.s [deleted file]
lld/test/ELF/tls-in-archive.s [deleted file]
lld/test/ELF/tls-le-weak-undef.s [new file with mode: 0644]
lld/test/ELF/tls-weak-undef.s [deleted file]
lld/test/ELF/x86-64-tls-le-undef.s

index e150cb8..b9b6fef 100644 (file)
@@ -807,7 +807,7 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
     // --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())
+    if (sym.isUndefined() || sym.isLazy())
       return a;
     return getTlsTpOffset(sym) + a;
   case R_RELAX_TLS_GD_TO_LE_NEG:
diff --git a/lld/test/ELF/Inputs/tls-in-archive.s b/lld/test/ELF/Inputs/tls-in-archive.s
deleted file mode 100644 (file)
index 0474a41..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-        .type foo, @tls_object
-        .globl  foo
-foo:
diff --git a/lld/test/ELF/tls-in-archive.s b/lld/test/ELF/tls-in-archive.s
deleted file mode 100644 (file)
index 5a8791d..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// REQUIRES: x86
-// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/tls-in-archive.s -o %t1.o
-// RUN: rm -f %t.a
-// RUN: llvm-ar cru %t.a %t1.o
-// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2.o
-// RUN: ld.lld %t2.o %t.a -o /dev/null
-
-        .globl  _start
-_start:
-        movq    foo@gottpoff(%rip), %rax
-        .section        .tbss,"awT",@nobits
-        .weak   foo
diff --git a/lld/test/ELF/tls-le-weak-undef.s b/lld/test/ELF/tls-le-weak-undef.s
new file mode 100644 (file)
index 0000000..fefda9d
--- /dev/null
@@ -0,0 +1,18 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
+# RUN: echo '.tbss; .globl tls; tls:' | llvm-mc -filetype=obj -triple=x86_64 - -o %tdef.o
+# RUN: ld.lld %t.o -o - | llvm-objdump -d - | FileCheck %s
+
+## A weak symbol does not fetch a lazy definition.
+# RUN: ld.lld %t.o --start-lib %tdef.o --end-lib -o - | llvm-objdump -d - | FileCheck %s
+
+## Undefined TLS symbols arbitrarily resolve to 0.
+# CHECK:  leaq 16(%rax), %rdx
+
+# RUN: ld.lld -shared %tdef.o -o %tdef.so
+# RUN: not ld.lld %t.o %tdef.so -o /dev/null 2>&1 | FileCheck --check-prefix=COPYRELOC %s
+
+# COPYRELOC: symbol 'tls' has no type
+
+.weak tls
+leaq tls@tpoff+16(%rax), %rdx
diff --git a/lld/test/ELF/tls-weak-undef.s b/lld/test/ELF/tls-weak-undef.s
deleted file mode 100644 (file)
index 1023aeb..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// REQUIRES: x86
-// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
-// RUN: ld.lld %t.o -o %t --gc-sections
-
-// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux \
-// RUN:   %p/Inputs/tls-in-archive.s -o %t1.o
-// RUN: rm -f %t.a
-// RUN: llvm-ar cru %t.a %t1.o
-// RUN: ld.lld %t.o %t.a -o %t
-
-// Check that lld doesn't crash because we don't reference
-// the TLS phdr when it's not created.
-        .globl  _start
-_start:
-        movq    foo@gottpoff(%rip), %rax
-        .section        .tbss,"awT",@nobits
-        .weak   foo
index 8feb267..4c8e1c5 100644 (file)
@@ -6,10 +6,7 @@
 ## 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
+# CHECK: leaq 32(%rax), %rdx
 
-.weak weak
 movq %fs:0, %rax
-leaq weak@tpoff+16(%rax), %rdx
 leaq global@tpoff+32(%rax), %rdx