diff options
author | Fangrui Song <maskray@google.com> | 2019-02-06 02:00:24 +0000 |
---|---|---|
committer | Fangrui Song <maskray@google.com> | 2019-02-06 02:00:24 +0000 |
commit | 2a295842a96e4d2f4ee2b4137a274564d54f1e6e (patch) | |
tree | c1abee89619c322c23a796da8d6f3e86dcd8b080 | |
parent | c8f96fdf2f71396b5ee06cd1c1a0972808dbf305 (diff) | |
download | lld-2a295842a96e4d2f4ee2b4137a274564d54f1e6e.tar.gz |
[PPC64] Set the number of relocations processed for R_PPC64_TLS[GL]D to 2
Summary:
R_PPC64_TLSGD and R_PPC64_TLSLD are used as markers on TLS code sequences. After GD-to-IE or GD-to-LE relaxation, the next relocation R_PPC64_REL24 should be skipped to not create a false dependency on __tls_get_addr. When linking statically, the false dependency may cause an "undefined symbol: __tls_get_addr" error.
R_PPC64_GOT_TLSGD16_HA
R_PPC64_GOT_TLSGD16_LO
R_PPC64_TLSGD R_TLSDESC_CALL
R_PPC64_REL24 __tls_get_addr
Reviewers: ruiu, sfertile, syzaara, espindola
Reviewed By: sfertile
Subscribers: emaste, nemanjai, arichardson, kbarton, jsji, llvm-commits, tamur
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D57673
git-svn-id: https://llvm.org/svn/llvm-project/lld/trunk@353262 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | ELF/Arch/PPC64.cpp | 15 | ||||
-rw-r--r-- | ELF/Arch/X86.cpp | 6 | ||||
-rw-r--r-- | ELF/Arch/X86_64.cpp | 7 | ||||
-rw-r--r-- | ELF/Relocations.cpp | 4 | ||||
-rw-r--r-- | ELF/Target.h | 2 | ||||
-rw-r--r-- | test/ELF/ppc64-gd-to-ie.s | 4 | ||||
-rw-r--r-- | test/ELF/ppc64-tls-gd-le.s | 4 |
7 files changed, 29 insertions, 13 deletions
diff --git a/ELF/Arch/PPC64.cpp b/ELF/Arch/PPC64.cpp index e3df5b114..c40c97878 100644 --- a/ELF/Arch/PPC64.cpp +++ b/ELF/Arch/PPC64.cpp @@ -111,6 +111,7 @@ namespace { class PPC64 final : public TargetInfo { public: PPC64(); + int getTlsGdRelaxSkip(RelType Type) const override; uint32_t calcEFlags() const override; RelExpr getRelExpr(RelType Type, const Symbol &S, const uint8_t *Loc) const override; @@ -241,6 +242,20 @@ PPC64::PPC64() { write32(TrapInstr.data(), 0x7fe00008); } +int PPC64::getTlsGdRelaxSkip(RelType Type) const { + // A __tls_get_addr call instruction is marked with 2 relocations: + // + // R_PPC64_TLSGD / R_PPC64_TLSLD: marker relocation + // R_PPC64_REL24: __tls_get_addr + // + // After the relaxation we no longer call __tls_get_addr and should skip both + // relocations to not create a false dependence on __tls_get_addr being + // defined. + if (Type == R_PPC64_TLSGD || Type == R_PPC64_TLSLD) + return 2; + return 1; +} + static uint32_t getEFlags(InputFile *File) { if (Config->EKind == ELF64BEKind) return cast<ObjFile<ELF64BE>>(File)->getObj().getHeader()->e_flags; diff --git a/ELF/Arch/X86.cpp b/ELF/Arch/X86.cpp index 0af3c4d99..061538d22 100644 --- a/ELF/Arch/X86.cpp +++ b/ELF/Arch/X86.cpp @@ -23,6 +23,7 @@ namespace { class X86 : public TargetInfo { public: X86(); + int getTlsGdRelaxSkip(RelType Type) const override; RelExpr getRelExpr(RelType Type, const Symbol &S, const uint8_t *Loc) const override; int64_t getImplicitAddend(const uint8_t *Buf, RelType Type) const override; @@ -58,7 +59,6 @@ X86::X86() { GotPltEntrySize = 4; PltEntrySize = 16; PltHeaderSize = 16; - TlsGdRelaxSkip = 2; TrapInstr = {0xcc, 0xcc, 0xcc, 0xcc}; // 0xcc = INT3 // Align to the non-PAE large page size (known as a superpage or huge page). @@ -66,6 +66,10 @@ X86::X86() { DefaultImageBase = 0x400000; } +int X86::getTlsGdRelaxSkip(RelType Type) const { + return 2; +} + RelExpr X86::getRelExpr(RelType Type, const Symbol &S, const uint8_t *Loc) const { switch (Type) { diff --git a/ELF/Arch/X86_64.cpp b/ELF/Arch/X86_64.cpp index 9c76dd905..863686311 100644 --- a/ELF/Arch/X86_64.cpp +++ b/ELF/Arch/X86_64.cpp @@ -25,6 +25,7 @@ namespace { template <class ELFT> class X86_64 : public TargetInfo { public: X86_64(); + int getTlsGdRelaxSkip(RelType Type) const override; RelExpr getRelExpr(RelType Type, const Symbol &S, const uint8_t *Loc) const override; RelType getDynRel(RelType Type) const override; @@ -65,7 +66,6 @@ template <class ELFT> X86_64<ELFT>::X86_64() { GotPltEntrySize = 8; PltEntrySize = 16; PltHeaderSize = 16; - TlsGdRelaxSkip = 2; TrapInstr = {0xcc, 0xcc, 0xcc, 0xcc}; // 0xcc = INT3 // Align to the large page size (known as a superpage or huge page). @@ -74,6 +74,11 @@ template <class ELFT> X86_64<ELFT>::X86_64() { } template <class ELFT> +int X86_64<ELFT>::getTlsGdRelaxSkip(RelType Type) const { + return 2; +} + +template <class ELFT> RelExpr X86_64<ELFT>::getRelExpr(RelType Type, const Symbol &S, const uint8_t *Loc) const { switch (Type) { diff --git a/ELF/Relocations.cpp b/ELF/Relocations.cpp index 884257280..ee4f4769f 100644 --- a/ELF/Relocations.cpp +++ b/ELF/Relocations.cpp @@ -205,7 +205,7 @@ handleTlsRelocation(RelType Type, Symbol &Sym, InputSectionBase &C, C.Relocations.push_back( {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_LD_TO_LE), Type, Offset, Addend, &Sym}); - return Target->TlsGdRelaxSkip; + return Target->getTlsGdRelaxSkip(Type); } if (Expr == R_TLSLD_HINT) return 1; @@ -278,7 +278,7 @@ handleTlsRelocation(RelType Type, Symbol &Sym, InputSectionBase &C, {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_GD_TO_LE), Type, Offset, Addend, &Sym}); } - return Target->TlsGdRelaxSkip; + return Target->getTlsGdRelaxSkip(Type); } // Initial-Exec relocs can be relaxed to Local-Exec if the symbol is locally diff --git a/ELF/Target.h b/ELF/Target.h index ace0705ad..9f26f132e 100644 --- a/ELF/Target.h +++ b/ELF/Target.h @@ -32,6 +32,7 @@ public: virtual void writeGotPlt(uint8_t *Buf, const Symbol &S) const {}; virtual void writeIgotPlt(uint8_t *Buf, const Symbol &S) const; virtual int64_t getImplicitAddend(const uint8_t *Buf, RelType Type) const; + virtual int getTlsGdRelaxSkip(RelType Type) const { return 1; } // If lazy binding is supported, the first entry of the PLT has code // to call the dynamic linker to resolve PLT entries the first time @@ -80,7 +81,6 @@ public: virtual ~TargetInfo(); - unsigned TlsGdRelaxSkip = 1; unsigned PageSize = 4096; unsigned DefaultMaxPageSize = 4096; diff --git a/test/ELF/ppc64-gd-to-ie.s b/test/ELF/ppc64-gd-to-ie.s index 121032caf..a11024a58 100644 --- a/test/ELF/ppc64-gd-to-ie.s +++ b/test/ELF/ppc64-gd-to-ie.s @@ -69,10 +69,6 @@ other_reg: mtlr 0 blr - .globl __tls_get_addr - .type __tls_get_addr,@function -__tls_get_addr: - # CheckGot: .got 00000018 00000000100200c0 DATA # .got is at 0x100200c0 so the toc-base is 100280c0. diff --git a/test/ELF/ppc64-tls-gd-le.s b/test/ELF/ppc64-tls-gd-le.s index 7907d1104..78bffb2c4 100644 --- a/test/ELF/ppc64-tls-gd-le.s +++ b/test/ELF/ppc64-tls-gd-le.s @@ -50,10 +50,6 @@ _start: # @_start .Lfunc_end0: .size _start, .Lfunc_end0-.Lfunc_begin0 -.globl __tls_get_addr -.type __tls_get_addr,@function -__tls_get_addr: - # -- End function .type a,@object # @a .section .tdata,"awT",@progbits |