diff options
| author | Fangrui Song <maskray@google.com> | 2019-04-22 03:10:40 +0000 |
|---|---|---|
| committer | Fangrui Song <maskray@google.com> | 2019-04-22 03:10:40 +0000 |
| commit | bc4b159bb1121ed9e1c00df35a4f5dd5712de8de (patch) | |
| tree | 591072d2a422da89a52897c0241aeb7ba0095ff3 /lld/ELF/InputSection.cpp | |
| parent | 1233c15be59160eb48bec08327db012bc3f2aedf (diff) | |
| download | bcm5719-llvm-bc4b159bb1121ed9e1c00df35a4f5dd5712de8de.tar.gz bcm5719-llvm-bc4b159bb1121ed9e1c00df35a4f5dd5712de8de.zip | |
[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
Diffstat (limited to 'lld/ELF/InputSection.cpp')
| -rw-r--r-- | lld/ELF/InputSection.cpp | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index a32015f4b14..060374ad6d4 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -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) + "'"; |

