mirror of
https://github.com/intel/llvm.git
synced 2026-01-23 07:58:23 +08:00
[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:
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user