mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-27 20:14:06 +08:00
PR27625, powerpc64 gold __tls_get_addr calls
This patch supports linking powerpc64 glibc with gold, specifically the __tls_get_addr call in elf/dl-sym.c. That call lacks marker relocations tying it to the arg setup instructions, but the arg setup insns are also contructed lacking the usual relocations on a Global Dynamic TLS code sequence. So there is no chance that anything in that sequence might be wrongly edited by the linker. In fact, the aim of linking glibc could have been supported by simply omitting the error whenever TLS optimisation is disabled, as it is when linking a shared library. The patch goes further than that, disabling TLS GD and LD sequence optimisation on a per-object basis for object files lacking marker relocs. PR gold/27625 * powerpc.cc (Powerpc_relobj): Add no_tls_marker_, tls_marker_, and tls_opt_error_ variables and accessors. (Target_powerpc::Scan::local, global): Call set_tls_marker and set_no_tls_marker for GD and LD code sequence relocations. (Target_powerpc::Relocate::relocate): Downgrade the "lacks marker reloc" error to a warning when safe to do so, and omit the error entirely if not optimising TLS sequences. Do not optimise GD and LD sequences for objects lacking marker relocs. (Target_powerpc::relocate_relocs): Heed no_tls_marker here too.
This commit is contained in:
parent
1b82252e8c
commit
0af4fcc25d
@ -1,3 +1,16 @@
|
|||||||
|
2021-03-30 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
PR gold/27625
|
||||||
|
* powerpc.cc (Powerpc_relobj): Add no_tls_marker_, tls_marker_,
|
||||||
|
and tls_opt_error_ variables and accessors.
|
||||||
|
(Target_powerpc::Scan::local, global): Call set_tls_marker and
|
||||||
|
set_no_tls_marker for GD and LD code sequence relocations.
|
||||||
|
(Target_powerpc::Relocate::relocate): Downgrade the "lacks marker
|
||||||
|
reloc" error to a warning when safe to do so, and omit the error
|
||||||
|
entirely if not optimising TLS sequences. Do not optimise GD and
|
||||||
|
LD sequences for objects lacking marker relocs.
|
||||||
|
(Target_powerpc::relocate_relocs): Heed no_tls_marker here too.
|
||||||
|
|
||||||
2021-03-19 Cary Coutant <ccoutant@gmail.com>
|
2021-03-19 Cary Coutant <ccoutant@gmail.com>
|
||||||
|
|
||||||
PR gold/27615
|
PR gold/27615
|
||||||
|
237
gold/powerpc.cc
237
gold/powerpc.cc
@ -101,6 +101,7 @@ public:
|
|||||||
: Sized_relobj_file<size, big_endian>(name, input_file, offset, ehdr),
|
: Sized_relobj_file<size, big_endian>(name, input_file, offset, ehdr),
|
||||||
uniq_(object_id++), special_(0), relatoc_(0), toc_(0),
|
uniq_(object_id++), special_(0), relatoc_(0), toc_(0),
|
||||||
has_small_toc_reloc_(false), opd_valid_(false),
|
has_small_toc_reloc_(false), opd_valid_(false),
|
||||||
|
no_tls_marker_(false), tls_marker_(false), tls_opt_error_(false),
|
||||||
e_flags_(ehdr.get_e_flags()), no_toc_opt_(), opd_ent_(),
|
e_flags_(ehdr.get_e_flags()), no_toc_opt_(), opd_ent_(),
|
||||||
access_from_map_(), has14_(), stub_table_index_(), st_other_(),
|
access_from_map_(), has14_(), stub_table_index_(), st_other_(),
|
||||||
attributes_section_data_(NULL)
|
attributes_section_data_(NULL)
|
||||||
@ -161,6 +162,30 @@ public:
|
|||||||
return this->no_toc_opt_[off];
|
return this->no_toc_opt_[off];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_no_tls_marker()
|
||||||
|
{
|
||||||
|
if (!this->no_tls_marker_ && this->tls_marker_)
|
||||||
|
this->tls_opt_error_ = true;
|
||||||
|
this->no_tls_marker_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
no_tls_marker() const
|
||||||
|
{ return this->no_tls_marker_; }
|
||||||
|
|
||||||
|
void
|
||||||
|
set_tls_marker()
|
||||||
|
{ this->tls_marker_ = true; }
|
||||||
|
|
||||||
|
bool
|
||||||
|
tls_marker() const
|
||||||
|
{ return this->tls_marker_; }
|
||||||
|
|
||||||
|
bool
|
||||||
|
tls_opt_error() const
|
||||||
|
{ return this->tls_opt_error_; }
|
||||||
|
|
||||||
// The .got2 section shndx.
|
// The .got2 section shndx.
|
||||||
unsigned int
|
unsigned int
|
||||||
got2_shndx() const
|
got2_shndx() const
|
||||||
@ -454,6 +479,19 @@ private:
|
|||||||
// access_from_map_.
|
// access_from_map_.
|
||||||
bool opd_valid_;
|
bool opd_valid_;
|
||||||
|
|
||||||
|
// Set when finding a __tls_get_addr call without marker relocs.
|
||||||
|
// Such a call disables GD and LD tls optimisations for the object file.
|
||||||
|
bool no_tls_marker_;
|
||||||
|
|
||||||
|
// Set when finding a __tls_get_addr call with marker relocs, or
|
||||||
|
// when finding a relocation that needs __tls_get_addr calls with
|
||||||
|
// marker relocs.
|
||||||
|
bool tls_marker_;
|
||||||
|
|
||||||
|
// Set when seeing a __tls_get_addr call without marker relocs after
|
||||||
|
// seeing some __tls_get_addr calls with marker relocs.
|
||||||
|
bool tls_opt_error_;
|
||||||
|
|
||||||
// Header e_flags
|
// Header e_flags
|
||||||
elfcpp::Elf_Word e_flags_;
|
elfcpp::Elf_Word e_flags_;
|
||||||
|
|
||||||
@ -7863,28 +7901,47 @@ Target_powerpc<size, big_endian>::Scan::local(
|
|||||||
const elfcpp::Sym<size, big_endian>& lsym,
|
const elfcpp::Sym<size, big_endian>& lsym,
|
||||||
bool is_discarded)
|
bool is_discarded)
|
||||||
{
|
{
|
||||||
this->maybe_skip_tls_get_addr_call(target, r_type, NULL);
|
Powerpc_relobj<size, big_endian>* ppc_object
|
||||||
|
= static_cast<Powerpc_relobj<size, big_endian>*>(object);
|
||||||
|
|
||||||
|
switch (this->maybe_skip_tls_get_addr_call(target, r_type, NULL))
|
||||||
|
{
|
||||||
|
case Track_tls::NOT_EXPECTED:
|
||||||
|
ppc_object->set_no_tls_marker();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if ((size == 64 && r_type == elfcpp::R_PPC64_TLSGD)
|
if ((size == 64 && r_type == elfcpp::R_PPC64_TLSGD)
|
||||||
|| (size == 32 && r_type == elfcpp::R_PPC_TLSGD))
|
|| (size == 32 && r_type == elfcpp::R_PPC_TLSGD))
|
||||||
{
|
{
|
||||||
this->expect_tls_get_addr_call();
|
this->expect_tls_get_addr_call();
|
||||||
const tls::Tls_optimization tls_type = target->optimize_tls_gd(true);
|
if (!ppc_object->no_tls_marker())
|
||||||
if (tls_type != tls::TLSOPT_NONE)
|
{
|
||||||
this->skip_next_tls_get_addr_call();
|
tls::Tls_optimization tls_type = target->optimize_tls_gd(true);
|
||||||
|
if (tls_type != tls::TLSOPT_NONE)
|
||||||
|
{
|
||||||
|
this->skip_next_tls_get_addr_call();
|
||||||
|
ppc_object->set_tls_marker();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ((size == 64 && r_type == elfcpp::R_PPC64_TLSLD)
|
else if ((size == 64 && r_type == elfcpp::R_PPC64_TLSLD)
|
||||||
|| (size == 32 && r_type == elfcpp::R_PPC_TLSLD))
|
|| (size == 32 && r_type == elfcpp::R_PPC_TLSLD))
|
||||||
{
|
{
|
||||||
this->expect_tls_get_addr_call();
|
this->expect_tls_get_addr_call();
|
||||||
const tls::Tls_optimization tls_type = target->optimize_tls_ld();
|
if (!ppc_object->no_tls_marker())
|
||||||
if (tls_type != tls::TLSOPT_NONE)
|
{
|
||||||
this->skip_next_tls_get_addr_call();
|
tls::Tls_optimization tls_type = target->optimize_tls_ld();
|
||||||
|
if (tls_type != tls::TLSOPT_NONE)
|
||||||
|
{
|
||||||
|
this->skip_next_tls_get_addr_call();
|
||||||
|
ppc_object->set_tls_marker();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Powerpc_relobj<size, big_endian>* ppc_object
|
|
||||||
= static_cast<Powerpc_relobj<size, big_endian>*>(object);
|
|
||||||
|
|
||||||
if (is_discarded)
|
if (is_discarded)
|
||||||
{
|
{
|
||||||
if (size == 64
|
if (size == 64
|
||||||
@ -8179,7 +8236,9 @@ Target_powerpc<size, big_endian>::Scan::local(
|
|||||||
case elfcpp::R_POWERPC_GOT_TLSGD16_HI:
|
case elfcpp::R_POWERPC_GOT_TLSGD16_HI:
|
||||||
case elfcpp::R_POWERPC_GOT_TLSGD16_HA:
|
case elfcpp::R_POWERPC_GOT_TLSGD16_HA:
|
||||||
{
|
{
|
||||||
const tls::Tls_optimization tls_type = target->optimize_tls_gd(true);
|
tls::Tls_optimization tls_type = tls::TLSOPT_NONE;
|
||||||
|
if (!ppc_object->no_tls_marker())
|
||||||
|
tls_type = target->optimize_tls_gd(true);
|
||||||
if (tls_type == tls::TLSOPT_NONE)
|
if (tls_type == tls::TLSOPT_NONE)
|
||||||
{
|
{
|
||||||
Output_data_got_powerpc<size, big_endian>* got
|
Output_data_got_powerpc<size, big_endian>* got
|
||||||
@ -8192,6 +8251,7 @@ Target_powerpc<size, big_endian>::Scan::local(
|
|||||||
else if (tls_type == tls::TLSOPT_TO_LE)
|
else if (tls_type == tls::TLSOPT_TO_LE)
|
||||||
{
|
{
|
||||||
// no GOT relocs needed for Local Exec.
|
// no GOT relocs needed for Local Exec.
|
||||||
|
ppc_object->set_tls_marker();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
gold_unreachable();
|
gold_unreachable();
|
||||||
@ -8204,7 +8264,9 @@ Target_powerpc<size, big_endian>::Scan::local(
|
|||||||
case elfcpp::R_POWERPC_GOT_TLSLD16_HI:
|
case elfcpp::R_POWERPC_GOT_TLSLD16_HI:
|
||||||
case elfcpp::R_POWERPC_GOT_TLSLD16_HA:
|
case elfcpp::R_POWERPC_GOT_TLSLD16_HA:
|
||||||
{
|
{
|
||||||
const tls::Tls_optimization tls_type = target->optimize_tls_ld();
|
tls::Tls_optimization tls_type = tls::TLSOPT_NONE;
|
||||||
|
if (!ppc_object->no_tls_marker())
|
||||||
|
tls_type = target->optimize_tls_ld();
|
||||||
if (tls_type == tls::TLSOPT_NONE)
|
if (tls_type == tls::TLSOPT_NONE)
|
||||||
target->tlsld_got_offset(symtab, layout, object);
|
target->tlsld_got_offset(symtab, layout, object);
|
||||||
else if (tls_type == tls::TLSOPT_TO_LE)
|
else if (tls_type == tls::TLSOPT_TO_LE)
|
||||||
@ -8216,6 +8278,7 @@ Target_powerpc<size, big_endian>::Scan::local(
|
|||||||
gold_assert(os != NULL);
|
gold_assert(os != NULL);
|
||||||
os->set_needs_symtab_index();
|
os->set_needs_symtab_index();
|
||||||
}
|
}
|
||||||
|
ppc_object->set_tls_marker();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
gold_unreachable();
|
gold_unreachable();
|
||||||
@ -8241,7 +8304,7 @@ Target_powerpc<size, big_endian>::Scan::local(
|
|||||||
case elfcpp::R_POWERPC_GOT_TPREL16_HI:
|
case elfcpp::R_POWERPC_GOT_TPREL16_HI:
|
||||||
case elfcpp::R_POWERPC_GOT_TPREL16_HA:
|
case elfcpp::R_POWERPC_GOT_TPREL16_HA:
|
||||||
{
|
{
|
||||||
const tls::Tls_optimization tls_type = target->optimize_tls_ie(true);
|
tls::Tls_optimization tls_type = target->optimize_tls_ie(true);
|
||||||
if (tls_type == tls::TLSOPT_NONE)
|
if (tls_type == tls::TLSOPT_NONE)
|
||||||
{
|
{
|
||||||
unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
|
unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
|
||||||
@ -8545,9 +8608,19 @@ Target_powerpc<size, big_endian>::Scan::global(
|
|||||||
unsigned int r_type,
|
unsigned int r_type,
|
||||||
Symbol* gsym)
|
Symbol* gsym)
|
||||||
{
|
{
|
||||||
if (this->maybe_skip_tls_get_addr_call(target, r_type, gsym)
|
Powerpc_relobj<size, big_endian>* ppc_object
|
||||||
== Track_tls::SKIP)
|
= static_cast<Powerpc_relobj<size, big_endian>*>(object);
|
||||||
return;
|
|
||||||
|
switch (this->maybe_skip_tls_get_addr_call(target, r_type, gsym))
|
||||||
|
{
|
||||||
|
case Track_tls::NOT_EXPECTED:
|
||||||
|
ppc_object->set_no_tls_marker();
|
||||||
|
break;
|
||||||
|
case Track_tls::SKIP:
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (target->replace_tls_get_addr(gsym))
|
if (target->replace_tls_get_addr(gsym))
|
||||||
// Change a __tls_get_addr reference to __tls_get_addr_opt
|
// Change a __tls_get_addr reference to __tls_get_addr_opt
|
||||||
@ -8558,23 +8631,32 @@ Target_powerpc<size, big_endian>::Scan::global(
|
|||||||
|| (size == 32 && r_type == elfcpp::R_PPC_TLSGD))
|
|| (size == 32 && r_type == elfcpp::R_PPC_TLSGD))
|
||||||
{
|
{
|
||||||
this->expect_tls_get_addr_call();
|
this->expect_tls_get_addr_call();
|
||||||
const bool final = gsym->final_value_is_known();
|
if (!ppc_object->no_tls_marker())
|
||||||
const tls::Tls_optimization tls_type = target->optimize_tls_gd(final);
|
{
|
||||||
if (tls_type != tls::TLSOPT_NONE)
|
bool final = gsym->final_value_is_known();
|
||||||
this->skip_next_tls_get_addr_call();
|
tls::Tls_optimization tls_type = target->optimize_tls_gd(final);
|
||||||
|
if (tls_type != tls::TLSOPT_NONE)
|
||||||
|
{
|
||||||
|
this->skip_next_tls_get_addr_call();
|
||||||
|
ppc_object->set_tls_marker();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ((size == 64 && r_type == elfcpp::R_PPC64_TLSLD)
|
else if ((size == 64 && r_type == elfcpp::R_PPC64_TLSLD)
|
||||||
|| (size == 32 && r_type == elfcpp::R_PPC_TLSLD))
|
|| (size == 32 && r_type == elfcpp::R_PPC_TLSLD))
|
||||||
{
|
{
|
||||||
this->expect_tls_get_addr_call();
|
this->expect_tls_get_addr_call();
|
||||||
const tls::Tls_optimization tls_type = target->optimize_tls_ld();
|
if (!ppc_object->no_tls_marker())
|
||||||
if (tls_type != tls::TLSOPT_NONE)
|
{
|
||||||
this->skip_next_tls_get_addr_call();
|
tls::Tls_optimization tls_type = target->optimize_tls_ld();
|
||||||
|
if (tls_type != tls::TLSOPT_NONE)
|
||||||
|
{
|
||||||
|
this->skip_next_tls_get_addr_call();
|
||||||
|
ppc_object->set_tls_marker();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Powerpc_relobj<size, big_endian>* ppc_object
|
|
||||||
= static_cast<Powerpc_relobj<size, big_endian>*>(object);
|
|
||||||
|
|
||||||
// A STT_GNU_IFUNC symbol may require a PLT entry.
|
// A STT_GNU_IFUNC symbol may require a PLT entry.
|
||||||
bool is_ifunc = gsym->type() == elfcpp::STT_GNU_IFUNC;
|
bool is_ifunc = gsym->type() == elfcpp::STT_GNU_IFUNC;
|
||||||
bool pushed_ifunc = false;
|
bool pushed_ifunc = false;
|
||||||
@ -8951,8 +9033,12 @@ Target_powerpc<size, big_endian>::Scan::global(
|
|||||||
case elfcpp::R_POWERPC_GOT_TLSGD16_HI:
|
case elfcpp::R_POWERPC_GOT_TLSGD16_HI:
|
||||||
case elfcpp::R_POWERPC_GOT_TLSGD16_HA:
|
case elfcpp::R_POWERPC_GOT_TLSGD16_HA:
|
||||||
{
|
{
|
||||||
const bool final = gsym->final_value_is_known();
|
tls::Tls_optimization tls_type = tls::TLSOPT_NONE;
|
||||||
const tls::Tls_optimization tls_type = target->optimize_tls_gd(final);
|
if (!ppc_object->no_tls_marker())
|
||||||
|
{
|
||||||
|
bool final = gsym->final_value_is_known();
|
||||||
|
tls_type = target->optimize_tls_gd(final);
|
||||||
|
}
|
||||||
if (tls_type == tls::TLSOPT_NONE)
|
if (tls_type == tls::TLSOPT_NONE)
|
||||||
{
|
{
|
||||||
Output_data_got_powerpc<size, big_endian>* got
|
Output_data_got_powerpc<size, big_endian>* got
|
||||||
@ -8984,10 +9070,12 @@ Target_powerpc<size, big_endian>::Scan::global(
|
|||||||
got, off, 0);
|
got, off, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ppc_object->set_tls_marker();
|
||||||
}
|
}
|
||||||
else if (tls_type == tls::TLSOPT_TO_LE)
|
else if (tls_type == tls::TLSOPT_TO_LE)
|
||||||
{
|
{
|
||||||
// no GOT relocs needed for Local Exec.
|
// no GOT relocs needed for Local Exec.
|
||||||
|
ppc_object->set_tls_marker();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
gold_unreachable();
|
gold_unreachable();
|
||||||
@ -9000,7 +9088,9 @@ Target_powerpc<size, big_endian>::Scan::global(
|
|||||||
case elfcpp::R_POWERPC_GOT_TLSLD16_HI:
|
case elfcpp::R_POWERPC_GOT_TLSLD16_HI:
|
||||||
case elfcpp::R_POWERPC_GOT_TLSLD16_HA:
|
case elfcpp::R_POWERPC_GOT_TLSLD16_HA:
|
||||||
{
|
{
|
||||||
const tls::Tls_optimization tls_type = target->optimize_tls_ld();
|
tls::Tls_optimization tls_type = tls::TLSOPT_NONE;
|
||||||
|
if (!ppc_object->no_tls_marker())
|
||||||
|
tls_type = target->optimize_tls_ld();
|
||||||
if (tls_type == tls::TLSOPT_NONE)
|
if (tls_type == tls::TLSOPT_NONE)
|
||||||
target->tlsld_got_offset(symtab, layout, object);
|
target->tlsld_got_offset(symtab, layout, object);
|
||||||
else if (tls_type == tls::TLSOPT_TO_LE)
|
else if (tls_type == tls::TLSOPT_TO_LE)
|
||||||
@ -9012,6 +9102,7 @@ Target_powerpc<size, big_endian>::Scan::global(
|
|||||||
gold_assert(os != NULL);
|
gold_assert(os != NULL);
|
||||||
os->set_needs_symtab_index();
|
os->set_needs_symtab_index();
|
||||||
}
|
}
|
||||||
|
ppc_object->set_tls_marker();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
gold_unreachable();
|
gold_unreachable();
|
||||||
@ -9044,8 +9135,8 @@ Target_powerpc<size, big_endian>::Scan::global(
|
|||||||
case elfcpp::R_POWERPC_GOT_TPREL16_HI:
|
case elfcpp::R_POWERPC_GOT_TPREL16_HI:
|
||||||
case elfcpp::R_POWERPC_GOT_TPREL16_HA:
|
case elfcpp::R_POWERPC_GOT_TPREL16_HA:
|
||||||
{
|
{
|
||||||
const bool final = gsym->final_value_is_known();
|
bool final = gsym->final_value_is_known();
|
||||||
const tls::Tls_optimization tls_type = target->optimize_tls_ie(final);
|
tls::Tls_optimization tls_type = target->optimize_tls_ie(final);
|
||||||
if (tls_type == tls::TLSOPT_NONE)
|
if (tls_type == tls::TLSOPT_NONE)
|
||||||
{
|
{
|
||||||
if (!gsym->has_got_offset(GOT_TYPE_TPREL))
|
if (!gsym->has_got_offset(GOT_TYPE_TPREL))
|
||||||
@ -10357,11 +10448,25 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
|
|||||||
|
|
||||||
const elfcpp::Rela<size, big_endian> rela(preloc);
|
const elfcpp::Rela<size, big_endian> rela(preloc);
|
||||||
unsigned int r_type = elfcpp::elf_r_type<size>(rela.get_r_info());
|
unsigned int r_type = elfcpp::elf_r_type<size>(rela.get_r_info());
|
||||||
|
Powerpc_relobj<size, big_endian>* const object
|
||||||
|
= static_cast<Powerpc_relobj<size, big_endian>*>(relinfo->object);
|
||||||
switch (this->maybe_skip_tls_get_addr_call(target, r_type, gsym))
|
switch (this->maybe_skip_tls_get_addr_call(target, r_type, gsym))
|
||||||
{
|
{
|
||||||
case Track_tls::NOT_EXPECTED:
|
case Track_tls::NOT_EXPECTED:
|
||||||
gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
|
if (!parameters->options().shared()
|
||||||
_("__tls_get_addr call lacks marker reloc"));
|
&& parameters->options().tls_optimize())
|
||||||
|
{
|
||||||
|
// It is a hard error to see a __tls_get_addr call without
|
||||||
|
// marker relocs after seeing calls with marker relocs in the
|
||||||
|
// same object file, because dynamic relocation accounting
|
||||||
|
// will be wrong.
|
||||||
|
if (object->tls_opt_error())
|
||||||
|
gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
|
||||||
|
_("__tls_get_addr call lacks marker reloc"));
|
||||||
|
else
|
||||||
|
gold_warning_at_location(relinfo, relnum, rela.get_r_offset(),
|
||||||
|
_("__tls_get_addr call lacks marker reloc"));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case Track_tls::EXPECTED:
|
case Track_tls::EXPECTED:
|
||||||
// We have already complained.
|
// We have already complained.
|
||||||
@ -10394,8 +10499,6 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
|
|||||||
// Offset from start of insn to d-field reloc.
|
// Offset from start of insn to d-field reloc.
|
||||||
const int d_offset = big_endian ? 2 : 0;
|
const int d_offset = big_endian ? 2 : 0;
|
||||||
|
|
||||||
Powerpc_relobj<size, big_endian>* const object
|
|
||||||
= static_cast<Powerpc_relobj<size, big_endian>*>(relinfo->object);
|
|
||||||
Address value = 0;
|
Address value = 0;
|
||||||
bool has_stub_value = false;
|
bool has_stub_value = false;
|
||||||
bool localentry0 = false;
|
bool localentry0 = false;
|
||||||
@ -10646,8 +10749,12 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
|
|||||||
|| r_type == elfcpp::R_PPC64_GOT_TLSGD_PCREL34)
|
|| r_type == elfcpp::R_PPC64_GOT_TLSGD_PCREL34)
|
||||||
{
|
{
|
||||||
// First instruction of a global dynamic sequence, arg setup insn.
|
// First instruction of a global dynamic sequence, arg setup insn.
|
||||||
const bool final = gsym == NULL || gsym->final_value_is_known();
|
tls::Tls_optimization tls_type = tls::TLSOPT_NONE;
|
||||||
const tls::Tls_optimization tls_type = target->optimize_tls_gd(final);
|
if (!object->no_tls_marker())
|
||||||
|
{
|
||||||
|
bool final = gsym == NULL || gsym->final_value_is_known();
|
||||||
|
tls_type = target->optimize_tls_gd(final);
|
||||||
|
}
|
||||||
enum Got_type got_type = GOT_TYPE_STANDARD;
|
enum Got_type got_type = GOT_TYPE_STANDARD;
|
||||||
if (tls_type == tls::TLSOPT_NONE)
|
if (tls_type == tls::TLSOPT_NONE)
|
||||||
got_type = GOT_TYPE_TLSGD;
|
got_type = GOT_TYPE_TLSGD;
|
||||||
@ -10752,7 +10859,9 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
|
|||||||
|| r_type == elfcpp::R_PPC64_GOT_TLSLD_PCREL34)
|
|| r_type == elfcpp::R_PPC64_GOT_TLSLD_PCREL34)
|
||||||
{
|
{
|
||||||
// First instruction of a local dynamic sequence, arg setup insn.
|
// First instruction of a local dynamic sequence, arg setup insn.
|
||||||
const tls::Tls_optimization tls_type = target->optimize_tls_ld();
|
tls::Tls_optimization tls_type = tls::TLSOPT_NONE;
|
||||||
|
if (!object->no_tls_marker())
|
||||||
|
tls_type = target->optimize_tls_ld();
|
||||||
if (tls_type == tls::TLSOPT_NONE)
|
if (tls_type == tls::TLSOPT_NONE)
|
||||||
{
|
{
|
||||||
value = target->tlsld_got_offset();
|
value = target->tlsld_got_offset();
|
||||||
@ -10831,8 +10940,8 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
|
|||||||
|| r_type == elfcpp::R_PPC64_GOT_TPREL_PCREL34)
|
|| r_type == elfcpp::R_PPC64_GOT_TPREL_PCREL34)
|
||||||
{
|
{
|
||||||
// First instruction of initial exec sequence.
|
// First instruction of initial exec sequence.
|
||||||
const bool final = gsym == NULL || gsym->final_value_is_known();
|
bool final = gsym == NULL || gsym->final_value_is_known();
|
||||||
const tls::Tls_optimization tls_type = target->optimize_tls_ie(final);
|
tls::Tls_optimization tls_type = target->optimize_tls_ie(final);
|
||||||
if (tls_type == tls::TLSOPT_NONE)
|
if (tls_type == tls::TLSOPT_NONE)
|
||||||
{
|
{
|
||||||
if (gsym != NULL)
|
if (gsym != NULL)
|
||||||
@ -10897,8 +11006,12 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
|
|||||||
// Second instruction of a global dynamic sequence,
|
// Second instruction of a global dynamic sequence,
|
||||||
// the __tls_get_addr call
|
// the __tls_get_addr call
|
||||||
this->expect_tls_get_addr_call(relinfo, relnum, rela.get_r_offset());
|
this->expect_tls_get_addr_call(relinfo, relnum, rela.get_r_offset());
|
||||||
const bool final = gsym == NULL || gsym->final_value_is_known();
|
tls::Tls_optimization tls_type = tls::TLSOPT_NONE;
|
||||||
const tls::Tls_optimization tls_type = target->optimize_tls_gd(final);
|
if (!object->no_tls_marker())
|
||||||
|
{
|
||||||
|
bool final = gsym == NULL || gsym->final_value_is_known();
|
||||||
|
tls_type = target->optimize_tls_gd(final);
|
||||||
|
}
|
||||||
if (tls_type != tls::TLSOPT_NONE)
|
if (tls_type != tls::TLSOPT_NONE)
|
||||||
{
|
{
|
||||||
if (tls_type == tls::TLSOPT_TO_IE)
|
if (tls_type == tls::TLSOPT_TO_IE)
|
||||||
@ -10949,7 +11062,9 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
|
|||||||
// Second instruction of a local dynamic sequence,
|
// Second instruction of a local dynamic sequence,
|
||||||
// the __tls_get_addr call
|
// the __tls_get_addr call
|
||||||
this->expect_tls_get_addr_call(relinfo, relnum, rela.get_r_offset());
|
this->expect_tls_get_addr_call(relinfo, relnum, rela.get_r_offset());
|
||||||
const tls::Tls_optimization tls_type = target->optimize_tls_ld();
|
tls::Tls_optimization tls_type = tls::TLSOPT_NONE;
|
||||||
|
if (!object->no_tls_marker())
|
||||||
|
tls_type = target->optimize_tls_ld();
|
||||||
if (tls_type == tls::TLSOPT_TO_LE)
|
if (tls_type == tls::TLSOPT_TO_LE)
|
||||||
{
|
{
|
||||||
bool is_pcrel = false;
|
bool is_pcrel = false;
|
||||||
@ -10985,8 +11100,8 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
|
|||||||
else if (r_type == elfcpp::R_POWERPC_TLS)
|
else if (r_type == elfcpp::R_POWERPC_TLS)
|
||||||
{
|
{
|
||||||
// Second instruction of an initial exec sequence
|
// Second instruction of an initial exec sequence
|
||||||
const bool final = gsym == NULL || gsym->final_value_is_known();
|
bool final = gsym == NULL || gsym->final_value_is_known();
|
||||||
const tls::Tls_optimization tls_type = target->optimize_tls_ie(final);
|
tls::Tls_optimization tls_type = target->optimize_tls_ie(final);
|
||||||
if (tls_type == tls::TLSOPT_TO_LE)
|
if (tls_type == tls::TLSOPT_TO_LE)
|
||||||
{
|
{
|
||||||
Address roff = rela.get_r_offset() & 3;
|
Address roff = rela.get_r_offset() & 3;
|
||||||
@ -12439,8 +12554,13 @@ Target_powerpc<size, big_endian>::relocate_relocs(
|
|||||||
{
|
{
|
||||||
// First instruction of a global dynamic sequence,
|
// First instruction of a global dynamic sequence,
|
||||||
// arg setup insn.
|
// arg setup insn.
|
||||||
const bool final = gsym == NULL || gsym->final_value_is_known();
|
tls::Tls_optimization tls_type = tls::TLSOPT_NONE;
|
||||||
switch (this->optimize_tls_gd(final))
|
if (!object->no_tls_marker())
|
||||||
|
{
|
||||||
|
bool final = gsym == NULL || gsym->final_value_is_known();
|
||||||
|
tls_type = this->optimize_tls_gd(final);
|
||||||
|
}
|
||||||
|
switch (tls_type)
|
||||||
{
|
{
|
||||||
case tls::TLSOPT_TO_IE:
|
case tls::TLSOPT_TO_IE:
|
||||||
r_type += (elfcpp::R_POWERPC_GOT_TPREL16
|
r_type += (elfcpp::R_POWERPC_GOT_TPREL16
|
||||||
@ -12467,7 +12587,10 @@ Target_powerpc<size, big_endian>::relocate_relocs(
|
|||||||
{
|
{
|
||||||
// First instruction of a local dynamic sequence,
|
// First instruction of a local dynamic sequence,
|
||||||
// arg setup insn.
|
// arg setup insn.
|
||||||
if (this->optimize_tls_ld() == tls::TLSOPT_TO_LE)
|
tls::Tls_optimization tls_type = tls::TLSOPT_NONE;
|
||||||
|
if (!object->no_tls_marker())
|
||||||
|
tls_type = this->optimize_tls_ld();
|
||||||
|
if (tls_type == tls::TLSOPT_TO_LE)
|
||||||
{
|
{
|
||||||
if (r_type == elfcpp::R_POWERPC_GOT_TLSLD16
|
if (r_type == elfcpp::R_POWERPC_GOT_TLSLD16
|
||||||
|| r_type == elfcpp::R_POWERPC_GOT_TLSLD16_LO)
|
|| r_type == elfcpp::R_POWERPC_GOT_TLSLD16_LO)
|
||||||
@ -12493,7 +12616,7 @@ Target_powerpc<size, big_endian>::relocate_relocs(
|
|||||||
|| r_type == elfcpp::R_POWERPC_GOT_TPREL16_HA)
|
|| r_type == elfcpp::R_POWERPC_GOT_TPREL16_HA)
|
||||||
{
|
{
|
||||||
// First instruction of initial exec sequence.
|
// First instruction of initial exec sequence.
|
||||||
const bool final = gsym == NULL || gsym->final_value_is_known();
|
bool final = gsym == NULL || gsym->final_value_is_known();
|
||||||
if (this->optimize_tls_ie(final) == tls::TLSOPT_TO_LE)
|
if (this->optimize_tls_ie(final) == tls::TLSOPT_TO_LE)
|
||||||
{
|
{
|
||||||
if (r_type == elfcpp::R_POWERPC_GOT_TPREL16
|
if (r_type == elfcpp::R_POWERPC_GOT_TPREL16
|
||||||
@ -12511,8 +12634,13 @@ Target_powerpc<size, big_endian>::relocate_relocs(
|
|||||||
{
|
{
|
||||||
// Second instruction of a global dynamic sequence,
|
// Second instruction of a global dynamic sequence,
|
||||||
// the __tls_get_addr call
|
// the __tls_get_addr call
|
||||||
const bool final = gsym == NULL || gsym->final_value_is_known();
|
tls::Tls_optimization tls_type = tls::TLSOPT_NONE;
|
||||||
switch (this->optimize_tls_gd(final))
|
if (!object->no_tls_marker())
|
||||||
|
{
|
||||||
|
bool final = gsym == NULL || gsym->final_value_is_known();
|
||||||
|
tls_type = this->optimize_tls_gd(final);
|
||||||
|
}
|
||||||
|
switch (tls_type)
|
||||||
{
|
{
|
||||||
case tls::TLSOPT_TO_IE:
|
case tls::TLSOPT_TO_IE:
|
||||||
r_type = elfcpp::R_POWERPC_NONE;
|
r_type = elfcpp::R_POWERPC_NONE;
|
||||||
@ -12532,7 +12660,10 @@ Target_powerpc<size, big_endian>::relocate_relocs(
|
|||||||
{
|
{
|
||||||
// Second instruction of a local dynamic sequence,
|
// Second instruction of a local dynamic sequence,
|
||||||
// the __tls_get_addr call
|
// the __tls_get_addr call
|
||||||
if (this->optimize_tls_ld() == tls::TLSOPT_TO_LE)
|
tls::Tls_optimization tls_type = tls::TLSOPT_NONE;
|
||||||
|
if (!object->no_tls_marker())
|
||||||
|
tls_type = this->optimize_tls_ld();
|
||||||
|
if (tls_type == tls::TLSOPT_TO_LE)
|
||||||
{
|
{
|
||||||
const Output_section* os = relinfo->layout->tls_segment()
|
const Output_section* os = relinfo->layout->tls_segment()
|
||||||
->first_section();
|
->first_section();
|
||||||
@ -12548,7 +12679,7 @@ Target_powerpc<size, big_endian>::relocate_relocs(
|
|||||||
else if (r_type == elfcpp::R_POWERPC_TLS)
|
else if (r_type == elfcpp::R_POWERPC_TLS)
|
||||||
{
|
{
|
||||||
// Second instruction of an initial exec sequence
|
// Second instruction of an initial exec sequence
|
||||||
const bool final = gsym == NULL || gsym->final_value_is_known();
|
bool final = gsym == NULL || gsym->final_value_is_known();
|
||||||
if (this->optimize_tls_ie(final) == tls::TLSOPT_TO_LE)
|
if (this->optimize_tls_ie(final) == tls::TLSOPT_TO_LE)
|
||||||
{
|
{
|
||||||
r_type = elfcpp::R_POWERPC_TPREL16_LO;
|
r_type = elfcpp::R_POWERPC_TPREL16_LO;
|
||||||
|
Loading…
Reference in New Issue
Block a user