diff options
author | Fangrui Song <maskray@google.com> | 2019-05-20 11:47:31 +0000 |
---|---|---|
committer | Fangrui Song <maskray@google.com> | 2019-05-20 11:47:31 +0000 |
commit | 2109572464da69eb96eda27a0fe5735da1405a9c (patch) | |
tree | fa8489b9638356c6f116358e18d6e4b8c2ed344c | |
parent | 3b6b2e331fea16b375d12747f3030c6187e86c2c (diff) | |
download | bcm5719-llvm-2109572464da69eb96eda27a0fe5735da1405a9c.tar.gz bcm5719-llvm-2109572464da69eb96eda27a0fe5735da1405a9c.zip |
[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@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
llvm-svn: 361146
-rw-r--r-- | lld/ELF/InputSection.cpp | 17 | ||||
-rw-r--r-- | lld/test/ELF/i386-tls-le-undef.s | 16 | ||||
-rw-r--r-- | lld/test/ELF/x86-64-tls-le-undef.s | 15 |
3 files changed, 40 insertions, 8 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 4749d9d360c..07a30ed57c4 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -738,17 +738,18 @@ static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A, 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: diff --git a/lld/test/ELF/i386-tls-le-undef.s b/lld/test/ELF/i386-tls-le-undef.s new file mode 100644 index 00000000000..95d097d6c63 --- /dev/null +++ b/lld/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 diff --git a/lld/test/ELF/x86-64-tls-le-undef.s b/lld/test/ELF/x86-64-tls-le-undef.s new file mode 100644 index 00000000000..8feb267c091 --- /dev/null +++ b/lld/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 |