mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-23 18:14:13 +08:00
[GOLD] Got_entry::write addends
This takes care of writing out GOT entries with addends. The local symbol case was already largely handled, except for passing the addend to tls_offset_for_local which might need the addend in a local_got_offset call. That's needed also in tls_offset_for_global. I'm assuming here that GOT entries for function symbols won't ever have addends, and in particular that a GOT entry referencing PLT call stub code won't want an offset into the code. PR 28192 * output.cc (Output_data_got::Got_entry::write): Include addend in global symbol value. Pass addend to tls_offset_for_*. * powerpc.cc (Target_powerpc::do_tls_offset_for_local): Handle addend. (Target_powerpc::do_tls_offset_for_global): Likewise. * s390.cc (Target_s390::do_tls_offset_for_local): Likewise. (Target_s390::do_tls_offset_for_global): Likewise. * target.h (Target::tls_offset_for_local): Add addend param. (Target::tls_offset_for_global): Likewise. (Target::do_tls_offset_for_local): Likewise. (Target::do_tls_offset_for_global): Likewise.
This commit is contained in:
parent
2cc9ed14fa
commit
e4d49a0f90
@ -1412,10 +1412,17 @@ Output_data_got<got_size, big_endian>::Got_entry::write(
|
||||
default:
|
||||
gold_unreachable();
|
||||
}
|
||||
// If this is a GOT entry for a known value global symbol,
|
||||
// then the value should include the addend. If the value
|
||||
// is not known leave the value as zero; The GOT entry
|
||||
// will be set by a dynamic relocation.
|
||||
if (this->addend_ && gsym->final_value_is_known())
|
||||
val += this->addend_;
|
||||
if (this->use_plt_or_tls_offset_
|
||||
&& gsym->type() == elfcpp::STT_TLS)
|
||||
val += parameters->target().tls_offset_for_global(gsym,
|
||||
got_indx);
|
||||
got_indx,
|
||||
this->addend_);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -1444,7 +1451,8 @@ Output_data_got<got_size, big_endian>::Got_entry::write(
|
||||
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);
|
||||
got_indx,
|
||||
this->addend_);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -825,12 +825,14 @@ class Target_powerpc : public Sized_target<size, big_endian>
|
||||
int64_t
|
||||
do_tls_offset_for_local(const Relobj* object,
|
||||
unsigned int symndx,
|
||||
unsigned int got_indx) const;
|
||||
unsigned int got_indx,
|
||||
uint64_t addend) 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;
|
||||
do_tls_offset_for_global(Symbol* gsym, unsigned int got_indx,
|
||||
uint64_t addend) const;
|
||||
|
||||
void
|
||||
do_function_location(Symbol_location*) const;
|
||||
@ -12790,7 +12792,8 @@ int64_t
|
||||
Target_powerpc<size, big_endian>::do_tls_offset_for_local(
|
||||
const Relobj* object,
|
||||
unsigned int symndx,
|
||||
unsigned int got_indx) const
|
||||
unsigned int got_indx,
|
||||
uint64_t addend) const
|
||||
{
|
||||
const Powerpc_relobj<size, big_endian>* ppc_object
|
||||
= static_cast<const Powerpc_relobj<size, big_endian>*>(object);
|
||||
@ -12799,9 +12802,10 @@ Target_powerpc<size, big_endian>::do_tls_offset_for_local(
|
||||
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))
|
||||
if (ppc_object->local_has_got_offset(symndx, got_type, addend))
|
||||
{
|
||||
unsigned int off = ppc_object->local_got_offset(symndx, got_type);
|
||||
unsigned int off
|
||||
= ppc_object->local_got_offset(symndx, got_type, addend);
|
||||
if (got_type == GOT_TYPE_TLSGD)
|
||||
off += size / 8;
|
||||
if (off == got_indx * (size / 8))
|
||||
@ -12822,16 +12826,17 @@ 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
|
||||
unsigned int got_indx,
|
||||
uint64_t addend) 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))
|
||||
if (gsym->has_got_offset(got_type, addend))
|
||||
{
|
||||
unsigned int off = gsym->got_offset(got_type);
|
||||
unsigned int off = gsym->got_offset(got_type, addend);
|
||||
if (got_type == GOT_TYPE_TLSGD)
|
||||
off += size / 8;
|
||||
if (off == got_indx * (size / 8))
|
||||
|
12
gold/s390.cc
12
gold/s390.cc
@ -401,12 +401,14 @@ class Target_s390 : public Sized_target<size, true>
|
||||
int64_t
|
||||
do_tls_offset_for_local(const Relobj* object,
|
||||
unsigned int symndx,
|
||||
unsigned int got_indx) const;
|
||||
unsigned int got_indx,
|
||||
uint64_t addend) 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;
|
||||
do_tls_offset_for_global(Symbol* gsym, unsigned int got_indx,
|
||||
uint64_t addend) const;
|
||||
|
||||
// This function should be defined in targets that can use relocation
|
||||
// types to determine (implemented in local_reloc_may_be_function_pointer
|
||||
@ -4218,7 +4220,8 @@ int64_t
|
||||
Target_s390<size>::do_tls_offset_for_local(
|
||||
const Relobj*,
|
||||
unsigned int,
|
||||
unsigned int) const
|
||||
unsigned int,
|
||||
uint64_t) const
|
||||
{
|
||||
// The only way we can get called is when IEENT/GOTIE12/GOTIE20
|
||||
// couldn't be optimised to LE.
|
||||
@ -4232,7 +4235,8 @@ template<int size>
|
||||
int64_t
|
||||
Target_s390<size>::do_tls_offset_for_global(
|
||||
Symbol*,
|
||||
unsigned int) const
|
||||
unsigned int,
|
||||
uint64_t) const
|
||||
{
|
||||
Output_segment* tls_segment = layout_->tls_segment();
|
||||
return -tls_segment->memsz();
|
||||
|
@ -289,14 +289,16 @@ class Target
|
||||
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); }
|
||||
unsigned int got_indx,
|
||||
uint64_t addend) const
|
||||
{ return do_tls_offset_for_local(object, symndx, got_indx, addend); }
|
||||
|
||||
// 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); }
|
||||
tls_offset_for_global(Symbol* gsym, unsigned int got_indx,
|
||||
uint64_t addend) const
|
||||
{ return do_tls_offset_for_global(gsym, got_indx, addend); }
|
||||
|
||||
// For targets that use function descriptors, if LOC is the location
|
||||
// of a function, modify it to point at the function entry location.
|
||||
@ -648,11 +650,12 @@ class Target
|
||||
{ gold_unreachable(); }
|
||||
|
||||
virtual int64_t
|
||||
do_tls_offset_for_local(const Relobj*, unsigned int, unsigned int) const
|
||||
do_tls_offset_for_local(const Relobj*, unsigned int, unsigned int,
|
||||
uint64_t) const
|
||||
{ gold_unreachable(); }
|
||||
|
||||
virtual int64_t
|
||||
do_tls_offset_for_global(Symbol*, unsigned int) const
|
||||
do_tls_offset_for_global(Symbol*, unsigned int, uint64_t) const
|
||||
{ gold_unreachable(); }
|
||||
|
||||
virtual void
|
||||
|
Loading…
Reference in New Issue
Block a user