[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

llvm-svn: 353262
This commit is contained in:
Fangrui Song
2019-02-06 02:00:24 +00:00
parent 54c82886cb
commit f55e9a2d2e
7 changed files with 29 additions and 13 deletions

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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).
@@ -73,6 +73,11 @@ template <class ELFT> X86_64<ELFT>::X86_64() {
DefaultImageBase = 0x200000;
}
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 {

View File

@@ -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

View File

@@ -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;

View File

@@ -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.

View File

@@ -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