* output.h (Output_data_got::add_global_tls, add_local_tls,
add_local_tls_pair): New functions. (Output_data_got::add_local_pair_with_rel): Remove second reloc param. Expand comment. (Output_data_got::Got_entry): Rename use_plt_offset_ to use_plt_or_tls_offset_, similarly for constructor param. (Output_data_got::Got_entry::write): Add got_index param. * output.cc (Output_data_got::add_global_tls, add_local_tls, add_local_tls_pair): New functions. (Output_data_got::Got_entry::write): Handle tls symbols with use_plt_or_tls_offset_ set specially. (Output_data_got::add_local_pair_with_rel): Only one reloc. (Output_data_got::do_write): Replace iterator with index, pass index to entry write function. * target.h (Target::tls_offset_for_local, tls_offset_for_global, do_tls_offset_for_local, do_tls_offset_for_global): New functions. * arm.cc (Target_arm::Scan::local): Update add_local_pair_with_rel call. * i386.cc (Target_i386::Scan::local): Likewise. * sparc.cc (Target_sparc::Scan::local): Likewise. * x86_64.cc (Target_x86_64::Scan::local): Likewise. * powerpc.cc (Target_powerpc::do_tls_offset_for_local, do_tls_offset_for_global): New functions. (Target_powerpc::Scan::local): Correct TLS relocations and got entry values. (Target_powerpc::Scan::global): Don't emit unnecessary dynamic relocations on TLS GOT entries.
This commit is contained in:
parent
00716ab174
commit
bd73a62d77
@ -1,3 +1,33 @@
|
||||
2012-09-11 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* output.h (Output_data_got::add_global_tls, add_local_tls,
|
||||
add_local_tls_pair): New functions.
|
||||
(Output_data_got::add_local_pair_with_rel): Remove second
|
||||
reloc param. Expand comment.
|
||||
(Output_data_got::Got_entry): Rename use_plt_offset_ to
|
||||
use_plt_or_tls_offset_, similarly for constructor param.
|
||||
(Output_data_got::Got_entry::write): Add got_index param.
|
||||
* output.cc (Output_data_got::add_global_tls, add_local_tls,
|
||||
add_local_tls_pair): New functions.
|
||||
(Output_data_got::Got_entry::write): Handle tls symbols
|
||||
with use_plt_or_tls_offset_ set specially.
|
||||
(Output_data_got::add_local_pair_with_rel): Only one reloc.
|
||||
(Output_data_got::do_write): Replace iterator with index, pass
|
||||
index to entry write function.
|
||||
* target.h (Target::tls_offset_for_local, tls_offset_for_global,
|
||||
do_tls_offset_for_local, do_tls_offset_for_global): New functions.
|
||||
* arm.cc (Target_arm::Scan::local): Update add_local_pair_with_rel
|
||||
call.
|
||||
* i386.cc (Target_i386::Scan::local): Likewise.
|
||||
* sparc.cc (Target_sparc::Scan::local): Likewise.
|
||||
* x86_64.cc (Target_x86_64::Scan::local): Likewise.
|
||||
* powerpc.cc (Target_powerpc::do_tls_offset_for_local,
|
||||
do_tls_offset_for_global): New functions.
|
||||
(Target_powerpc::Scan::local): Correct TLS relocations and got
|
||||
entry values.
|
||||
(Target_powerpc::Scan::global): Don't emit unnecessary
|
||||
dynamic relocations on TLS GOT entries.
|
||||
|
||||
2012-09-10 Matthias Klose <doko@ubuntu.com>
|
||||
|
||||
* config.in: Disable sanity check for kfreebsd.
|
||||
|
@ -8068,7 +8068,7 @@ Target_arm<big_endian>::Scan::local(Symbol_table* symtab,
|
||||
got->add_local_pair_with_rel(object, r_sym, shndx,
|
||||
GOT_TYPE_TLS_PAIR,
|
||||
target->rel_dyn_section(layout),
|
||||
elfcpp::R_ARM_TLS_DTPMOD32, 0);
|
||||
elfcpp::R_ARM_TLS_DTPMOD32);
|
||||
else
|
||||
got->add_tls_gd32_with_static_reloc(GOT_TYPE_TLS_PAIR,
|
||||
object, r_sym);
|
||||
|
@ -1874,7 +1874,7 @@ Target_i386::Scan::local(Symbol_table* symtab,
|
||||
got->add_local_pair_with_rel(object, r_sym, shndx,
|
||||
GOT_TYPE_TLS_PAIR,
|
||||
target->rel_dyn_section(layout),
|
||||
elfcpp::R_386_TLS_DTPMOD32, 0);
|
||||
elfcpp::R_386_TLS_DTPMOD32);
|
||||
}
|
||||
else if (optimized_type != tls::TLSOPT_TO_LE)
|
||||
unsupported_reloc_local(object, r_type);
|
||||
|
@ -1369,7 +1369,9 @@ Output_data_group<size, big_endian>::do_write(Output_file* of)
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Output_data_got<size, big_endian>::Got_entry::write(unsigned char* pov) const
|
||||
Output_data_got<size, big_endian>::Got_entry::write(
|
||||
unsigned int got_indx,
|
||||
unsigned char* pov) const
|
||||
{
|
||||
Valtype val = 0;
|
||||
|
||||
@ -1381,7 +1383,7 @@ Output_data_got<size, big_endian>::Got_entry::write(unsigned char* pov) const
|
||||
// link-time value, which will be relocated dynamically by a
|
||||
// RELATIVE relocation.
|
||||
Symbol* gsym = this->u_.gsym;
|
||||
if (this->use_plt_offset_ && gsym->has_plt_offset())
|
||||
if (this->use_plt_or_tls_offset_ && gsym->has_plt_offset())
|
||||
val = (parameters->target().plt_address_for_global(gsym)
|
||||
+ gsym->plt_offset());
|
||||
else
|
||||
@ -1392,6 +1394,9 @@ Output_data_got<size, big_endian>::Got_entry::write(unsigned char* pov) const
|
||||
// as small as possible.
|
||||
sgsym = static_cast<Sized_symbol<size>*>(gsym);
|
||||
val = sgsym->value();
|
||||
if (this->use_plt_or_tls_offset_ && gsym->type() == elfcpp::STT_TLS)
|
||||
val += parameters->target().tls_offset_for_global(gsym,
|
||||
got_indx);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -1409,19 +1414,24 @@ Output_data_got<size, big_endian>::Got_entry::write(unsigned char* pov) const
|
||||
|
||||
default:
|
||||
{
|
||||
const Relobj* object = this->u_.object;
|
||||
const Sized_relobj_file<size, big_endian>* object
|
||||
= static_cast<Sized_relobj_file<size, big_endian>*>(this->u_.object);
|
||||
const unsigned int lsi = this->local_sym_index_;
|
||||
if (!this->use_plt_offset_)
|
||||
{
|
||||
uint64_t lval = object->local_symbol_value(lsi, 0);
|
||||
val = convert_types<Valtype, uint64_t>(lval);
|
||||
}
|
||||
else
|
||||
bool is_tls = object->local_symbol(lsi)->is_tls_symbol();
|
||||
if (this->use_plt_or_tls_offset_ && !is_tls)
|
||||
{
|
||||
uint64_t plt_address =
|
||||
parameters->target().plt_address_for_local(object, lsi);
|
||||
val = plt_address + object->local_plt_offset(lsi);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64_t lval = object->local_symbol_value(lsi, 0);
|
||||
val = convert_types<Valtype, uint64_t>(lval);
|
||||
if (this->use_plt_or_tls_offset_ && is_tls)
|
||||
val += parameters->target().tls_offset_for_local(object, lsi,
|
||||
got_indx);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1566,8 +1576,10 @@ Output_data_got<size, big_endian>::add_local_with_rel(
|
||||
}
|
||||
|
||||
// Add a pair of entries for a local symbol to the GOT, and add
|
||||
// dynamic relocations of type R_TYPE_1 and R_TYPE_2, respectively.
|
||||
// If R_TYPE_2 == 0, add the second entry with no relocation.
|
||||
// a dynamic relocation of type R_TYPE using the section symbol of
|
||||
// the output section to which input section SHNDX maps, on the first.
|
||||
// The first got entry will have a value of zero, the second the
|
||||
// value of the local symbol.
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Output_data_got<size, big_endian>::add_local_pair_with_rel(
|
||||
@ -1576,8 +1588,7 @@ Output_data_got<size, big_endian>::add_local_pair_with_rel(
|
||||
unsigned int shndx,
|
||||
unsigned int got_type,
|
||||
Output_data_reloc_generic* rel_dyn,
|
||||
unsigned int r_type_1,
|
||||
unsigned int r_type_2)
|
||||
unsigned int r_type)
|
||||
{
|
||||
if (object->local_has_got_offset(symndx, got_type))
|
||||
return;
|
||||
@ -1587,11 +1598,30 @@ Output_data_got<size, big_endian>::add_local_pair_with_rel(
|
||||
Got_entry(object, symndx, false));
|
||||
object->set_local_got_offset(symndx, got_type, got_offset);
|
||||
Output_section* os = object->output_section(shndx);
|
||||
rel_dyn->add_output_section_generic(os, r_type_1, this, got_offset, 0);
|
||||
rel_dyn->add_output_section_generic(os, r_type, this, got_offset, 0);
|
||||
}
|
||||
|
||||
if (r_type_2 != 0)
|
||||
rel_dyn->add_output_section_generic(os, r_type_2, this,
|
||||
got_offset + size / 8, 0);
|
||||
// Add a pair of entries for a local symbol to the GOT, and add
|
||||
// a dynamic relocation of type R_TYPE using STN_UNDEF on the first.
|
||||
// The first got entry will have a value of zero, the second the
|
||||
// value of the local symbol offset by Target::tls_offset_for_local.
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Output_data_got<size, big_endian>::add_local_tls_pair(
|
||||
Relobj* object,
|
||||
unsigned int symndx,
|
||||
unsigned int got_type,
|
||||
Output_data_reloc_generic* rel_dyn,
|
||||
unsigned int r_type)
|
||||
{
|
||||
if (object->local_has_got_offset(symndx, got_type))
|
||||
return;
|
||||
|
||||
unsigned int got_offset
|
||||
= this->add_got_entry_pair(Got_entry(),
|
||||
Got_entry(object, symndx, true));
|
||||
object->set_local_got_offset(symndx, got_type, got_offset);
|
||||
rel_dyn->add_local_generic(object, 0, r_type, this, got_offset, 0);
|
||||
}
|
||||
|
||||
// Reserve a slot in the GOT for a local symbol or the second slot of a pair.
|
||||
@ -1634,11 +1664,9 @@ Output_data_got<size, big_endian>::do_write(Output_file* of)
|
||||
unsigned char* const oview = of->get_output_view(off, oview_size);
|
||||
|
||||
unsigned char* pov = oview;
|
||||
for (typename Got_entries::const_iterator p = this->entries_.begin();
|
||||
p != this->entries_.end();
|
||||
++p)
|
||||
for (unsigned int i = 0; i < this->entries_.size(); ++i)
|
||||
{
|
||||
p->write(pov);
|
||||
this->entries_[i].write(i, pov);
|
||||
pov += add;
|
||||
}
|
||||
|
||||
|
@ -2246,6 +2246,12 @@ class Output_data_got : public Output_data_got_base
|
||||
bool
|
||||
add_global_plt(Symbol* gsym, unsigned int got_type);
|
||||
|
||||
// Like add_global, but for a TLS symbol where the value will be
|
||||
// offset using Target::tls_offset_for_global
|
||||
bool
|
||||
add_global_tls(Symbol* gsym, unsigned int got_type)
|
||||
{ return add_global_plt(gsym, got_type); }
|
||||
|
||||
// Add an entry for a global symbol to the GOT, and add a dynamic
|
||||
// relocation of type R_TYPE for the GOT entry.
|
||||
void
|
||||
@ -2270,6 +2276,12 @@ class Output_data_got : public Output_data_got_base
|
||||
bool
|
||||
add_local_plt(Relobj* object, unsigned int sym_index, unsigned int got_type);
|
||||
|
||||
// Like add_local, but for a TLS symbol where the value will be
|
||||
// offset using Target::tls_offset_for_local
|
||||
bool
|
||||
add_local_tls(Relobj* object, unsigned int sym_index, unsigned int got_type)
|
||||
{ return add_local_plt(object, sym_index, got_type); }
|
||||
|
||||
// Add an entry for a local symbol to the GOT, and add a dynamic
|
||||
// relocation of type R_TYPE for the GOT entry.
|
||||
void
|
||||
@ -2278,12 +2290,25 @@ class Output_data_got : public Output_data_got_base
|
||||
unsigned int r_type);
|
||||
|
||||
// Add a pair of entries for a local symbol to the GOT, and add
|
||||
// dynamic relocations of type R_TYPE_1 and R_TYPE_2, respectively.
|
||||
// a dynamic relocation of type R_TYPE using the section symbol of
|
||||
// the output section to which input section SHNDX maps, on the first.
|
||||
// The first got entry will have a value of zero, the second the
|
||||
// value of the local symbol.
|
||||
void
|
||||
add_local_pair_with_rel(Relobj* object, unsigned int sym_index,
|
||||
unsigned int shndx, unsigned int got_type,
|
||||
Output_data_reloc_generic* rel_dyn,
|
||||
unsigned int r_type_1, unsigned int r_type_2);
|
||||
unsigned int r_type);
|
||||
|
||||
// Add a pair of entries for a local symbol to the GOT, and add
|
||||
// a dynamic relocation of type R_TYPE using STN_UNDEF on the first.
|
||||
// The first got entry will have a value of zero, the second the
|
||||
// value of the local symbol offset by Target::tls_offset_for_local.
|
||||
void
|
||||
add_local_tls_pair(Relobj* object, unsigned int sym_index,
|
||||
unsigned int got_type,
|
||||
Output_data_reloc_generic* rel_dyn,
|
||||
unsigned int r_type);
|
||||
|
||||
// Add a constant to the GOT. This returns the offset of the new
|
||||
// entry from the start of the GOT.
|
||||
@ -2342,18 +2367,20 @@ class Output_data_got : public Output_data_got_base
|
||||
public:
|
||||
// Create a zero entry.
|
||||
Got_entry()
|
||||
: local_sym_index_(RESERVED_CODE), use_plt_offset_(false)
|
||||
: local_sym_index_(RESERVED_CODE), use_plt_or_tls_offset_(false)
|
||||
{ this->u_.constant = 0; }
|
||||
|
||||
// Create a global symbol entry.
|
||||
Got_entry(Symbol* gsym, bool use_plt_offset)
|
||||
: local_sym_index_(GSYM_CODE), use_plt_offset_(use_plt_offset)
|
||||
Got_entry(Symbol* gsym, bool use_plt_or_tls_offset)
|
||||
: local_sym_index_(GSYM_CODE),
|
||||
use_plt_or_tls_offset_(use_plt_or_tls_offset)
|
||||
{ this->u_.gsym = gsym; }
|
||||
|
||||
// Create a local symbol entry.
|
||||
Got_entry(Relobj* object, unsigned int local_sym_index,
|
||||
bool use_plt_offset)
|
||||
: local_sym_index_(local_sym_index), use_plt_offset_(use_plt_offset)
|
||||
bool use_plt_or_tls_offset)
|
||||
: local_sym_index_(local_sym_index),
|
||||
use_plt_or_tls_offset_(use_plt_or_tls_offset)
|
||||
{
|
||||
gold_assert(local_sym_index != GSYM_CODE
|
||||
&& local_sym_index != CONSTANT_CODE
|
||||
@ -2365,12 +2392,12 @@ class Output_data_got : public Output_data_got_base
|
||||
// Create a constant entry. The constant is a host value--it will
|
||||
// be swapped, if necessary, when it is written out.
|
||||
explicit Got_entry(Valtype constant)
|
||||
: local_sym_index_(CONSTANT_CODE), use_plt_offset_(false)
|
||||
: local_sym_index_(CONSTANT_CODE), use_plt_or_tls_offset_(false)
|
||||
{ this->u_.constant = constant; }
|
||||
|
||||
// Write the GOT entry to an output view.
|
||||
void
|
||||
write(unsigned char* pov) const;
|
||||
write(unsigned int got_indx, unsigned char* pov) const;
|
||||
|
||||
private:
|
||||
enum
|
||||
@ -2393,7 +2420,8 @@ class Output_data_got : public Output_data_got_base
|
||||
// for a global symbol, or CONSTANT_CODE for a constant.
|
||||
unsigned int local_sym_index_ : 31;
|
||||
// Whether to use the PLT offset of the symbol if it has one.
|
||||
bool use_plt_offset_ : 1;
|
||||
// For TLS symbols, whether to offset the symbol value.
|
||||
bool use_plt_or_tls_offset_ : 1;
|
||||
};
|
||||
|
||||
typedef std::vector<Got_entry> Got_entries;
|
||||
|
122
gold/powerpc.cc
122
gold/powerpc.cc
@ -270,6 +270,18 @@ class Target_powerpc : public Sized_target<size, big_endian>
|
||||
uint64_t
|
||||
do_dynsym_value(const Symbol*) const;
|
||||
|
||||
// Return the offset to use for the GOT_INDX'th got entry which is
|
||||
// for a local tls symbol specified by OBJECT, SYMNDX.
|
||||
int64_t
|
||||
do_tls_offset_for_local(const Relobj* object,
|
||||
unsigned int symndx,
|
||||
unsigned int got_indx) const;
|
||||
|
||||
// Return the offset to use for the GOT_INDX'th got entry which is
|
||||
// for global tls symbol GSYM.
|
||||
int64_t
|
||||
do_tls_offset_for_global(Symbol* gsym, unsigned int got_indx) const;
|
||||
|
||||
// Relocate a section.
|
||||
void
|
||||
relocate_section(const Relocate_info<size, big_endian>*,
|
||||
@ -2349,7 +2361,7 @@ Target_powerpc<size, big_endian>::Scan::local(
|
||||
Output_section* output_section,
|
||||
const elfcpp::Rela<size, big_endian>& reloc,
|
||||
unsigned int r_type,
|
||||
const elfcpp::Sym<size, big_endian>& lsym)
|
||||
const elfcpp::Sym<size, big_endian>& /* lsym */)
|
||||
{
|
||||
Powerpc_relobj<size, big_endian>* ppc_object
|
||||
= static_cast<Powerpc_relobj<size, big_endian>*>(object);
|
||||
@ -2523,16 +2535,9 @@ Target_powerpc<size, big_endian>::Scan::local(
|
||||
Output_data_got_powerpc<size, big_endian>* got
|
||||
= target->got_section(symtab, layout);
|
||||
unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
|
||||
unsigned int shndx = lsym.get_st_shndx();
|
||||
bool is_ordinary;
|
||||
shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary);
|
||||
gold_assert(is_ordinary);
|
||||
got->add_local_pair_with_rel(object, r_sym,
|
||||
shndx,
|
||||
GOT_TYPE_TLSGD,
|
||||
target->rela_dyn_section(layout),
|
||||
elfcpp::R_POWERPC_DTPMOD,
|
||||
elfcpp::R_POWERPC_DTPREL);
|
||||
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
|
||||
got->add_local_tls_pair(object, r_sym, GOT_TYPE_TLSGD,
|
||||
rela_dyn, elfcpp::R_POWERPC_DTPMOD);
|
||||
}
|
||||
else if (tls_type == tls::TLSOPT_TO_LE)
|
||||
{
|
||||
@ -2574,9 +2579,7 @@ Target_powerpc<size, big_endian>::Scan::local(
|
||||
Output_data_got_powerpc<size, big_endian>* got
|
||||
= target->got_section(symtab, layout);
|
||||
unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
|
||||
got->add_local_with_rel(object, r_sym, GOT_TYPE_DTPREL,
|
||||
target->rela_dyn_section(layout),
|
||||
elfcpp::R_POWERPC_DTPREL);
|
||||
got->add_local_tls(object, r_sym, GOT_TYPE_DTPREL);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -2591,9 +2594,7 @@ Target_powerpc<size, big_endian>::Scan::local(
|
||||
Output_data_got_powerpc<size, big_endian>* got
|
||||
= target->got_section(symtab, layout);
|
||||
unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
|
||||
got->add_local_with_rel(object, r_sym, GOT_TYPE_TPREL,
|
||||
target->rela_dyn_section(layout),
|
||||
elfcpp::R_POWERPC_TPREL);
|
||||
got->add_local_tls(object, r_sym, GOT_TYPE_TPREL);
|
||||
}
|
||||
else if (tls_type == tls::TLSOPT_TO_LE)
|
||||
{
|
||||
@ -2913,9 +2914,15 @@ Target_powerpc<size, big_endian>::Scan::global(
|
||||
{
|
||||
Output_data_got_powerpc<size, big_endian>* got
|
||||
= target->got_section(symtab, layout);
|
||||
got->add_global_with_rel(gsym, GOT_TYPE_DTPREL,
|
||||
target->rela_dyn_section(layout),
|
||||
elfcpp::R_POWERPC_DTPREL);
|
||||
if (!gsym->final_value_is_known()
|
||||
&& (gsym->is_from_dynobj()
|
||||
|| gsym->is_undefined()
|
||||
|| gsym->is_preemptible()))
|
||||
got->add_global_with_rel(gsym, GOT_TYPE_DTPREL,
|
||||
target->rela_dyn_section(layout),
|
||||
elfcpp::R_POWERPC_DTPREL);
|
||||
else
|
||||
got->add_global_tls(gsym, GOT_TYPE_DTPREL);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -2930,9 +2937,15 @@ Target_powerpc<size, big_endian>::Scan::global(
|
||||
{
|
||||
Output_data_got_powerpc<size, big_endian>* got
|
||||
= target->got_section(symtab, layout);
|
||||
got->add_global_with_rel(gsym, GOT_TYPE_TPREL,
|
||||
target->rela_dyn_section(layout),
|
||||
elfcpp::R_POWERPC_TPREL);
|
||||
if (!gsym->final_value_is_known()
|
||||
&& (gsym->is_from_dynobj()
|
||||
|| gsym->is_undefined()
|
||||
|| gsym->is_preemptible()))
|
||||
got->add_global_with_rel(gsym, GOT_TYPE_TPREL,
|
||||
target->rela_dyn_section(layout),
|
||||
elfcpp::R_POWERPC_TPREL);
|
||||
else
|
||||
got->add_global_tls(gsym, GOT_TYPE_TPREL);
|
||||
}
|
||||
else if (tls_type == tls::TLSOPT_TO_LE)
|
||||
{
|
||||
@ -4421,6 +4434,69 @@ Target_powerpc<size, big_endian>::do_dynsym_value(const Symbol* gsym) const
|
||||
gold_unreachable();
|
||||
}
|
||||
|
||||
// Return the offset to use for the GOT_INDX'th got entry which is
|
||||
// for a local tls symbol specified by OBJECT, SYMNDX.
|
||||
template<int size, bool big_endian>
|
||||
int64_t
|
||||
Target_powerpc<size, big_endian>::do_tls_offset_for_local(
|
||||
const Relobj* object,
|
||||
unsigned int symndx,
|
||||
unsigned int got_indx) const
|
||||
{
|
||||
const Powerpc_relobj<size, big_endian>* ppc_object
|
||||
= static_cast<const Powerpc_relobj<size, big_endian>*>(object);
|
||||
if (ppc_object->local_symbol(symndx)->is_tls_symbol())
|
||||
{
|
||||
for (Got_type got_type = GOT_TYPE_TLSGD;
|
||||
got_type <= GOT_TYPE_TPREL;
|
||||
got_type = Got_type(got_type + 1))
|
||||
if (ppc_object->local_has_got_offset(symndx, got_type))
|
||||
{
|
||||
unsigned int off = ppc_object->local_got_offset(symndx, got_type);
|
||||
if (got_type == GOT_TYPE_TLSGD)
|
||||
off += size / 8;
|
||||
if (off == got_indx * (size / 8))
|
||||
{
|
||||
if (got_type == GOT_TYPE_TPREL)
|
||||
return -tp_offset;
|
||||
else
|
||||
return -dtp_offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
gold_unreachable();
|
||||
}
|
||||
|
||||
// Return the offset to use for the GOT_INDX'th got entry which is
|
||||
// for global tls symbol GSYM.
|
||||
template<int size, bool big_endian>
|
||||
int64_t
|
||||
Target_powerpc<size, big_endian>::do_tls_offset_for_global(
|
||||
Symbol* gsym,
|
||||
unsigned int got_indx) const
|
||||
{
|
||||
if (gsym->type() == elfcpp::STT_TLS)
|
||||
{
|
||||
for (Got_type got_type = GOT_TYPE_TLSGD;
|
||||
got_type <= GOT_TYPE_TPREL;
|
||||
got_type = Got_type(got_type + 1))
|
||||
if (gsym->has_got_offset(got_type))
|
||||
{
|
||||
unsigned int off = gsym->got_offset(got_type);
|
||||
if (got_type == GOT_TYPE_TLSGD)
|
||||
off += size / 8;
|
||||
if (off == got_indx * (size / 8))
|
||||
{
|
||||
if (got_type == GOT_TYPE_TPREL)
|
||||
return -tp_offset;
|
||||
else
|
||||
return -dtp_offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
gold_unreachable();
|
||||
}
|
||||
|
||||
// The selector for powerpc object files.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
|
@ -2429,8 +2429,7 @@ Target_sparc<size, big_endian>::Scan::local(
|
||||
target->rela_dyn_section(layout),
|
||||
(size == 64
|
||||
? elfcpp::R_SPARC_TLS_DTPMOD64
|
||||
: elfcpp::R_SPARC_TLS_DTPMOD32),
|
||||
0);
|
||||
: elfcpp::R_SPARC_TLS_DTPMOD32));
|
||||
if (r_type == elfcpp::R_SPARC_TLS_GD_CALL)
|
||||
generate_tls_call(symtab, layout, target);
|
||||
}
|
||||
|
@ -270,6 +270,20 @@ class Target
|
||||
plt_address_for_local(const Relobj* object, unsigned int symndx) const
|
||||
{ return this->do_plt_address_for_local(object, symndx); }
|
||||
|
||||
// Return the offset to use for the GOT_INDX'th got entry which is
|
||||
// for a local tls symbol specified by OBJECT, SYMNDX.
|
||||
int64_t
|
||||
tls_offset_for_local(const Relobj* object,
|
||||
unsigned int symndx,
|
||||
unsigned int got_indx) const
|
||||
{ return do_tls_offset_for_local(object, symndx, got_indx); }
|
||||
|
||||
// Return the offset to use for the GOT_INDX'th got entry which is
|
||||
// for global tls symbol GSYM.
|
||||
int64_t
|
||||
tls_offset_for_global(Symbol* gsym, unsigned int got_indx) const
|
||||
{ return do_tls_offset_for_global(gsym, got_indx); }
|
||||
|
||||
// Return whether this target can use relocation types to determine
|
||||
// if a function's address is taken.
|
||||
bool
|
||||
@ -546,6 +560,14 @@ class Target
|
||||
do_plt_address_for_local(const Relobj*, unsigned int) const
|
||||
{ gold_unreachable(); }
|
||||
|
||||
virtual int64_t
|
||||
do_tls_offset_for_local(const Relobj*, unsigned int, unsigned int) const
|
||||
{ gold_unreachable(); }
|
||||
|
||||
virtual int64_t
|
||||
do_tls_offset_for_global(Symbol*, unsigned int) const
|
||||
{ gold_unreachable(); }
|
||||
|
||||
// Virtual function which may be overriden by the child class.
|
||||
virtual bool
|
||||
do_can_check_for_function_pointers() const
|
||||
|
@ -2477,7 +2477,7 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
|
||||
shndx,
|
||||
GOT_TYPE_TLS_PAIR,
|
||||
target->rela_dyn_section(layout),
|
||||
elfcpp::R_X86_64_DTPMOD64, 0);
|
||||
elfcpp::R_X86_64_DTPMOD64);
|
||||
}
|
||||
else if (optimized_type != tls::TLSOPT_TO_LE)
|
||||
unsupported_reloc_local(object, r_type);
|
||||
|
Loading…
Reference in New Issue
Block a user