From e4d49a0f908415edb7a7e718ef2008a96dd43f9b Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 25 Aug 2021 21:58:51 +0930 Subject: [PATCH] [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. --- gold/output.cc | 12 ++++++++++-- gold/powerpc.cc | 21 +++++++++++++-------- gold/s390.cc | 12 ++++++++---- gold/target.h | 15 +++++++++------ 4 files changed, 40 insertions(+), 20 deletions(-) diff --git a/gold/output.cc b/gold/output.cc index c5f7eef0fbb..7ad8750aa36 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -1412,10 +1412,17 @@ Output_data_got::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_entry::write( val = convert_types(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; diff --git a/gold/powerpc.cc b/gold/powerpc.cc index 11b98695e64..0b6405915c2 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -825,12 +825,14 @@ class Target_powerpc : public Sized_target 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::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* ppc_object = static_cast*>(object); @@ -12799,9 +12802,10 @@ Target_powerpc::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 int64_t Target_powerpc::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)) diff --git a/gold/s390.cc b/gold/s390.cc index 600e70810d3..3095320524f 100644 --- a/gold/s390.cc +++ b/gold/s390.cc @@ -401,12 +401,14 @@ class Target_s390 : public Sized_target 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::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 int64_t Target_s390::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(); diff --git a/gold/target.h b/gold/target.h index 24f7111e922..4fce9fdf2c7 100644 --- a/gold/target.h +++ b/gold/target.h @@ -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