This is an archive of the discontinued LLVM Phabricator instance.

[ELF][X86] Allow R_386_TLS_LDO_32 and R_X86_64_DTPOFF{32,64} to preemptable local-dynamic symbols
ClosedPublic

Authored by MaskRay on Apr 21 2019, 3:51 AM.

Details

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.

Diff Detail

Repository
rLLD LLVM Linker

Event Timeline

MaskRay created this revision.Apr 21 2019, 3:51 AM
MaskRay updated this revision to Diff 196027.Apr 21 2019, 7:09 PM

Add objdump -d to test zero displacement

ruiu accepted this revision.Apr 21 2019, 7:39 PM

LGTM

ELF/InputSection.cpp
618–620

case R_DTPREL can be moved here.

This revision is now accepted and ready to land.Apr 21 2019, 7:39 PM
MaskRay updated this revision to Diff 196028.Apr 21 2019, 7:49 PM

Address review comment case R_DTPREL can be moved here.

MaskRay updated this revision to Diff 196031.Apr 21 2019, 8:06 PM
MaskRay edited the summary of this revision. (Show Details)

Update description

This revision was automatically updated to reflect the committed changes.
ruiu added inline comments.Apr 21 2019, 10:41 PM
ELF/InputSection.cpp
618

I mean you could merge with this expression as this is the same expression as yours.

MaskRay marked an inline comment as done.Apr 21 2019, 10:58 PM
MaskRay added inline comments.
ELF/InputSection.cpp
618

It will be changed. In PPC64 and MIPS there is an offset.

ruiu added a comment.Apr 21 2019, 11:06 PM

OK, then moving just below

ELF/InputSection.cpp
618

OK, but then moving this expression here doesn't make sense. I guess my point is to not make the code too future-proof. You can merge them and split it later, so that the code doesn't odd when you submit this. It's already committed, and it's not important, so I'm fine with this code for now though.

MaskRay marked an inline comment as done.Apr 21 2019, 11:24 PM
MaskRay added inline comments.
ELF/InputSection.cpp
618

I have realized the problem after I committed it. I will fix it soon when I create the patch for PPC.

It may look like return Sym.getVA(A) + getDTPOffset();