Index: ELF/Arch/X86.cpp =================================================================== --- ELF/Arch/X86.cpp +++ ELF/Arch/X86.cpp @@ -84,8 +84,9 @@ 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: Index: ELF/Arch/X86_64.cpp =================================================================== --- ELF/Arch/X86_64.cpp +++ ELF/Arch/X86_64.cpp @@ -82,9 +82,10 @@ case R_X86_64_32: case R_X86_64_32S: case R_X86_64_64: - case R_X86_64_DTPOFF32: - case R_X86_64_DTPOFF64: return R_ABS; + case R_X86_64_DTPOFF32: + case R_X86_64_DTPOFF64: + return R_DTPREL; case R_X86_64_TPOFF32: return R_TLS; case R_X86_64_TLSLD: Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -620,6 +620,8 @@ return A; case R_ARM_SBREL: return Sym.getVA(A) - getARMStaticBase(Sym); + case R_DTPREL: + return Sym.getVA(A); case R_GOT: case R_RELAX_TLS_GD_TO_IE_ABS: return Sym.getGotVA() + A; @@ -806,7 +808,7 @@ if (Expr == R_NONE) continue; - if (Expr != R_ABS) { + if (Expr != R_ABS && Expr != R_DTPREL) { std::string Msg = getLocation(Offset) + ": has non-ABS relocation " + toString(Type) + " against symbol '" + toString(Sym) + "'"; Index: ELF/Relocations.h =================================================================== --- ELF/Relocations.h +++ ELF/Relocations.h @@ -31,6 +31,7 @@ enum RelExpr { R_ABS, R_ADDEND, + R_DTPREL, R_GOT, R_GOT_OFF, R_GOT_PC, Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -248,7 +248,8 @@ } // 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 isStaticLinkTimeConstant(RelExpr E, RelType Type, const Symbol &Sym, InputSectionBase &S, uint64_t RelOff) { // These expressions always compute a constant - if (oneof(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 Index: test/ELF/i386-tls-ld-preemptable.s =================================================================== --- /dev/null +++ test/ELF/i386-tls-ld-preemptable.s @@ -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_DTPOFF32 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_DTPOFF32 + +.section .tbss,"awT",@nobits +.globl i +i: + .long 0 + .size i, 4 Index: test/ELF/x86-64-tls-ld-preemptable.s =================================================================== --- /dev/null +++ test/ELF/x86-64-tls-ld-preemptable.s @@ -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