aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFangrui Song <maskray@google.com>2019-02-06 02:00:24 +0000
committerFangrui Song <maskray@google.com>2019-02-06 02:00:24 +0000
commit2a295842a96e4d2f4ee2b4137a274564d54f1e6e (patch)
treec1abee89619c322c23a796da8d6f3e86dcd8b080
parentc8f96fdf2f71396b5ee06cd1c1a0972808dbf305 (diff)
downloadlld-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.cpp15
-rw-r--r--ELF/Arch/X86.cpp6
-rw-r--r--ELF/Arch/X86_64.cpp7
-rw-r--r--ELF/Relocations.cpp4
-rw-r--r--ELF/Target.h2
-rw-r--r--test/ELF/ppc64-gd-to-ie.s4
-rw-r--r--test/ELF/ppc64-tls-gd-le.s4
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