forked from OSchip/llvm-project
[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 llvm-svn: 358870
This commit is contained in:
parent
1233c15be5
commit
bc4b159bb1
|
@ -84,8 +84,9 @@ RelExpr X86::getRelExpr(RelType Type, const Symbol &S,
|
|||
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:
|
||||
|
|
|
@ -82,9 +82,10 @@ RelExpr X86_64::getRelExpr(RelType Type, const Symbol &S,
|
|||
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:
|
||||
|
|
|
@ -616,6 +616,8 @@ static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A,
|
|||
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(uint8_t *Buf, ArrayRef<RelTy> Rels) {
|
|||
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) + "'";
|
||||
|
|
|
@ -248,7 +248,8 @@ handleTlsRelocation(RelType Type, Symbol &Sym, InputSectionBase &C,
|
|||
}
|
||||
|
||||
// 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
|
||||
|
|
|
@ -31,6 +31,7 @@ using RelType = uint32_t;
|
|||
enum RelExpr {
|
||||
R_ABS,
|
||||
R_ADDEND,
|
||||
R_DTPREL,
|
||||
R_GOT,
|
||||
R_GOT_OFF,
|
||||
R_GOT_PC,
|
||||
|
|
|
@ -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@TLSLDM(%ebx), %eax
|
||||
calll __tls_get_addr@PLT
|
||||
movl i@DTPOFF(%eax), %eax # R_386_TLS_LDO_32
|
||||
|
||||
.section .tbss,"awT",@nobits
|
||||
.globl i
|
||||
i:
|
||||
.long 0
|
||||
.size i, 4
|
|
@ -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@TLSLD(%rip), %rdi
|
||||
callq __tls_get_addr@PLT
|
||||
leaq i@DTPOFF(%rax), %rax # R_X86_64_DTPOFF32
|
||||
movabsq i@DTPOFF, %rax # R_X86_64_DTPOFF64
|
||||
|
||||
.section .tbss,"awT",@nobits
|
||||
.globl i
|
||||
i:
|
||||
.long 0
|
||||
.size i, 4
|
Loading…
Reference in New Issue