[lld] r358870 - [ELF][X86] Allow R_386_TLS_LDO_32 and R_X86_64_DTPOFF{32, 64} to preemptable local-dynamic symbols
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Sun Apr 21 20:10:40 PDT 2019
Author: maskray
Date: Sun Apr 21 20:10:40 2019
New Revision: 358870
URL: http://llvm.org/viewvc/llvm-project?rev=358870&view=rev
Log:
[ELF][X86] Allow R_386_TLS_LDO_32 and R_X86_64_DTPOFF{32,64} to preemptable local-dynamic symbols
Summary:
Fixes PR35242. A simplified reproduce:
thread_local int i; int f() { return i; }
% {g++,clang++} -fPIC -shared -ftls-model=local-dynamic -fuse-ld=lld a.cc
ld.lld: error: can't create dynamic relocation R_X86_64_DTPOFF32 against symbol: i in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
In isStaticLinkTimeConstant(), Syn.IsPreemptible is true, so it is not
seen as a constant. The error is then issued in processRelocAux().
A symbol of the local-dynamic TLS model cannot be preempted but it can
preempt symbols of the global-dynamic TLS model in other DSOs.
So it makes some sense that the variable is not static.
This patch fixes the linking error by changing getRelExpr() on
R_386_TLS_LDO_32 and R_X86_64_DTPOFF{32,64} from R_ABS to R_DTPREL.
R_PPC64_DTPREL_* and R_MIPS_TLS_DTPREL_* need similar fixes, but they are not handled in this patch.
As a bonus, we use `if (Expr == R_ABS && !Config->Shared)` to find
ld-to-le opportunities. R_ABS is overloaded here for such STT_TLS symbols.
A dedicated R_DTPREL is clearer.
Differential Revision: https://reviews.llvm.org/D60945
Added:
lld/trunk/test/ELF/i386-tls-ld-preemptable.s
lld/trunk/test/ELF/x86-64-tls-ld-preemptable.s
Modified:
lld/trunk/ELF/Arch/X86.cpp
lld/trunk/ELF/Arch/X86_64.cpp
lld/trunk/ELF/InputSection.cpp
lld/trunk/ELF/Relocations.cpp
lld/trunk/ELF/Relocations.h
Modified: lld/trunk/ELF/Arch/X86.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/X86.cpp?rev=358870&r1=358869&r2=358870&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/X86.cpp (original)
+++ lld/trunk/ELF/Arch/X86.cpp Sun Apr 21 20:10:40 2019
@@ -84,8 +84,9 @@ RelExpr X86::getRelExpr(RelType Type, co
case R_386_8:
case R_386_16:
case R_386_32:
- case R_386_TLS_LDO_32:
return R_ABS;
+ case R_386_TLS_LDO_32:
+ return R_DTPREL;
case R_386_TLS_GD:
return R_TLSGD_GOTPLT;
case R_386_TLS_LDM:
Modified: lld/trunk/ELF/Arch/X86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/X86_64.cpp?rev=358870&r1=358869&r2=358870&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/X86_64.cpp (original)
+++ lld/trunk/ELF/Arch/X86_64.cpp Sun Apr 21 20:10:40 2019
@@ -82,9 +82,10 @@ RelExpr X86_64::getRelExpr(RelType Type,
case R_X86_64_32:
case R_X86_64_32S:
case R_X86_64_64:
+ return R_ABS;
case R_X86_64_DTPOFF32:
case R_X86_64_DTPOFF64:
- return R_ABS;
+ return R_DTPREL;
case R_X86_64_TPOFF32:
return R_TLS;
case R_X86_64_TLSLD:
Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=358870&r1=358869&r2=358870&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Sun Apr 21 20:10:40 2019
@@ -616,6 +616,8 @@ static uint64_t getRelocTargetVA(const I
case R_RELAX_TLS_LD_TO_LE_ABS:
case R_RELAX_GOT_PC_NOPIC:
return Sym.getVA(A);
+ case R_DTPREL:
+ return Sym.getVA(A);
case R_ADDEND:
return A;
case R_ARM_SBREL:
@@ -806,7 +808,7 @@ void InputSection::relocateNonAlloc(uint
if (Expr == R_NONE)
continue;
- if (Expr != R_ABS) {
+ if (Expr != R_ABS && Expr != R_DTPREL) {
std::string Msg = getLocation<ELFT>(Offset) +
": has non-ABS relocation " + toString(Type) +
" against symbol '" + toString(Sym) + "'";
Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=358870&r1=358869&r2=358870&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Sun Apr 21 20:10:40 2019
@@ -248,7 +248,8 @@ handleTlsRelocation(RelType Type, Symbol
}
// Local-Dynamic relocs can be relaxed to Local-Exec.
- if (Expr == R_ABS && !Config->Shared) {
+ // TODO Delete R_ABS after all R_*_DTPREL_* relocations migrate to R_DTPREL.
+ if ((Expr == R_ABS || Expr == R_DTPREL) && !Config->Shared) {
C.Relocations.push_back(
{Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_LD_TO_LE), Type,
Offset, Addend, &Sym});
@@ -398,13 +399,13 @@ static bool isRelExpr(RelExpr Expr) {
static bool isStaticLinkTimeConstant(RelExpr E, RelType Type, const Symbol &Sym,
InputSectionBase &S, uint64_t RelOff) {
// These expressions always compute a constant
- if (oneof<R_GOTPLT, R_GOT_OFF, R_HEXAGON_GOT, R_TLSLD_GOT_OFF,
+ if (oneof<R_DTPREL, R_GOTPLT, R_GOT_OFF, R_HEXAGON_GOT, R_TLSLD_GOT_OFF,
R_MIPS_GOT_LOCAL_PAGE, R_MIPS_GOTREL, R_MIPS_GOT_OFF,
R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC, R_MIPS_TLSGD,
- R_AARCH64_GOT_PAGE_PC, R_GOT_PC, R_GOTONLY_PC,
- R_GOTPLTONLY_PC, R_PLT_PC, R_TLSGD_GOT, R_TLSGD_GOTPLT,
- R_TLSGD_PC, R_PPC_CALL_PLT, R_TLSDESC_CALL, R_AARCH64_TLSDESC_PAGE,
- R_HINT, R_TLSLD_HINT, R_TLSIE_HINT>(E))
+ R_AARCH64_GOT_PAGE_PC, R_GOT_PC, R_GOTONLY_PC, R_GOTPLTONLY_PC,
+ R_PLT_PC, R_TLSGD_GOT, R_TLSGD_GOTPLT, R_TLSGD_PC, R_PPC_CALL_PLT,
+ R_TLSDESC_CALL, R_AARCH64_TLSDESC_PAGE, R_HINT, R_TLSLD_HINT,
+ R_TLSIE_HINT>(E))
return true;
// These never do, except if the entire file is position dependent or if
Modified: lld/trunk/ELF/Relocations.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.h?rev=358870&r1=358869&r2=358870&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.h (original)
+++ lld/trunk/ELF/Relocations.h Sun Apr 21 20:10:40 2019
@@ -31,6 +31,7 @@ using RelType = uint32_t;
enum RelExpr {
R_ABS,
R_ADDEND,
+ R_DTPREL,
R_GOT,
R_GOT_OFF,
R_GOT_PC,
Added: lld/trunk/test/ELF/i386-tls-ld-preemptable.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/i386-tls-ld-preemptable.s?rev=358870&view=auto
==============================================================================
--- lld/trunk/test/ELF/i386-tls-ld-preemptable.s (added)
+++ lld/trunk/test/ELF/i386-tls-ld-preemptable.s Sun Apr 21 20:10:40 2019
@@ -0,0 +1,18 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=i386 %s -o %t.o
+# RUN: ld.lld %t.o -shared -o %t.so
+# RUN: llvm-objdump -d --no-show-raw-insn %t.so | FileCheck %s
+
+# CHECK: 100b: movl (%eax), %eax
+
+# We used to error on R_386_TLS_LDO_32 to preemptable symbols.
+# i is STB_GLOBAL and preemptable.
+ leal i at TLSLDM(%ebx), %eax
+ calll __tls_get_addr at PLT
+ movl i at DTPOFF(%eax), %eax # R_386_TLS_LDO_32
+
+.section .tbss,"awT", at nobits
+.globl i
+i:
+ .long 0
+ .size i, 4
Added: lld/trunk/test/ELF/x86-64-tls-ld-preemptable.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/x86-64-tls-ld-preemptable.s?rev=358870&view=auto
==============================================================================
--- lld/trunk/test/ELF/x86-64-tls-ld-preemptable.s (added)
+++ lld/trunk/test/ELF/x86-64-tls-ld-preemptable.s Sun Apr 21 20:10:40 2019
@@ -0,0 +1,20 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
+# RUN: ld.lld %t.o -shared -o %t.so
+# RUN: llvm-objdump -d --no-show-raw-insn %t.so | FileCheck %s
+
+# CHECK: 100c: leaq (%rax), %rax
+# CHECK-NEXT: 1013: movabsq 0, %rax
+
+# We used to error on R_X86_64_DTPOFF{32,64} to preemptable symbols.
+# i is STB_GLOBAL and preemptable.
+ leaq i at TLSLD(%rip), %rdi
+ callq __tls_get_addr at PLT
+ leaq i at DTPOFF(%rax), %rax # R_X86_64_DTPOFF32
+ movabsq i at DTPOFF, %rax # R_X86_64_DTPOFF64
+
+.section .tbss,"awT", at nobits
+.globl i
+i:
+ .long 0
+ .size i, 4
More information about the llvm-commits
mailing list