public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [GOLD] Got_offset_list: addend field
@ 2021-09-02  3:28 Alan Modra
  2021-09-02  3:29 ` [GOLD] Remove addend from Local_got_entry_key Alan Modra
                   ` (5 more replies)
  0 siblings, 6 replies; 9+ messages in thread
From: Alan Modra @ 2021-09-02  3:28 UTC (permalink / raw)
  To: binutils

This is the first in a series of patches aimed at supporting GOT
entries against symbol plus addend generally for PowerPC64 rather than
just section symbol plus addend as gold has currently.

This patch adds an addend field to Got_offset_list, so that both local
and global symbols can have GOT entries with addend.  Note the FIXME
in incremental.cc, which will need attention if powerpc is to ever
support incremental linking.

As per the recommendation in
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-default-args
the changes to symtab.h Symbol methods could be done with what looks
like a good use of default arguments but they seem to be against the
gold maintainers' coding practice.  So instead we get more overloads.

Tested with a power10 gcc-11 bootstrap and regression test where
ld.gold was the default linker.  The series cures an enormous number
of testsuite failures (4656) without introducing regressions other
than some in the guality testsuite.

	PR 28192
	* object.h (Got_offset_list): Add addend_ field, init in both
	constructors.  Adjust all accessors to suit.
	(Sized_relobj::do_local_has_got_offset): Adjust to suit.
	(Sized_relobj::do_local_got_offset): Likewise.
	(Sized_relobj::do_set_local_got_offset): Likewise.
	* symtab.h (Symbol::has_got_offset): New overload with addend
	param.  Make old overload call this one.
	(Symbol::got_offset, Symbol::set_got_offset): Likewise.
	* incremental.cc (Local_got_offset_visitor::visit): Add unused
	uint64_t parameter with FIXME.
	(Global_got_offset_visitor::visit): Add unused uint64_t parameter.

diff --git a/gold/incremental.cc b/gold/incremental.cc
index ab258dd1896..52941985e6f 100644
--- a/gold/incremental.cc
+++ b/gold/incremental.cc
@@ -1848,7 +1848,7 @@ class Local_got_offset_visitor : public Got_offset_list::Visitor
   { }
 
   void
-  visit(unsigned int got_type, unsigned int got_offset)
+  visit(unsigned int got_type, unsigned int got_offset, uint64_t)
   {
     unsigned int got_index = got_offset / this->info_.got_entry_size;
     gold_assert(got_index < this->info_.got_count);
@@ -1860,6 +1860,12 @@ class Local_got_offset_visitor : public Got_offset_list::Visitor
     unsigned char* pov = this->info_.got_desc_p + got_index * 8;
     elfcpp::Swap<32, big_endian>::writeval(pov, this->info_.sym_index);
     elfcpp::Swap<32, big_endian>::writeval(pov + 4, this->info_.input_index);
+    // FIXME: the uint64_t addend should be written here if powerpc64
+    // sym+addend got entries are to be supported, with similar changes
+    // to Global_got_offset_visitor and support to read them back in
+    // do_process_got_plt.
+    // FIXME: don't we need this for section symbol plus addend anyway?
+    // (See 2015-12-03 commit 7ef8ae7c5f35)
   }
 
  private:
@@ -1879,7 +1885,7 @@ class Global_got_offset_visitor : public Got_offset_list::Visitor
   { }
 
   void
-  visit(unsigned int got_type, unsigned int got_offset)
+  visit(unsigned int got_type, unsigned int got_offset, uint64_t)
   {
     unsigned int got_index = got_offset / this->info_.got_entry_size;
     gold_assert(got_index < this->info_.got_count);
diff --git a/gold/object.h b/gold/object.h
index 38f4a2fd3ff..66e565c1b4c 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -214,11 +214,13 @@ class Got_offset_list
 {
  public:
   Got_offset_list()
-    : got_type_(-1U), got_offset_(0), got_next_(NULL)
+    : got_type_(-1U), got_offset_(0), addend_(0), got_next_(NULL)
   { }
 
-  Got_offset_list(unsigned int got_type, unsigned int got_offset)
-    : got_type_(got_type), got_offset_(got_offset), got_next_(NULL)
+  Got_offset_list(unsigned int got_type, unsigned int got_offset,
+		  uint64_t addend)
+    : got_type_(got_type), got_offset_(got_offset), addend_(addend),
+      got_next_(NULL)
   { }
 
   ~Got_offset_list()
@@ -236,29 +238,31 @@ class Got_offset_list
   {
     this->got_type_ = -1U;
     this->got_offset_ = 0;
+    this->addend_ = 0;
     this->got_next_ = NULL;
   }
 
   // Set the offset for the GOT entry of type GOT_TYPE.
   void
-  set_offset(unsigned int got_type, unsigned int got_offset)
+  set_offset(unsigned int got_type, unsigned int got_offset, uint64_t addend)
   {
     if (this->got_type_ == -1U)
       {
         this->got_type_ = got_type;
         this->got_offset_ = got_offset;
+        this->addend_ = addend;
       }
     else
       {
         for (Got_offset_list* g = this; g != NULL; g = g->got_next_)
           {
-            if (g->got_type_ == got_type)
+            if (g->got_type_ == got_type && g->addend_ == addend)
               {
                 g->got_offset_ = got_offset;
                 return;
               }
           }
-        Got_offset_list* g = new Got_offset_list(got_type, got_offset);
+        Got_offset_list* g = new Got_offset_list(got_type, got_offset, addend);
         g->got_next_ = this->got_next_;
         this->got_next_ = g;
       }
@@ -266,11 +270,11 @@ class Got_offset_list
 
   // Return the offset for a GOT entry of type GOT_TYPE.
   unsigned int
-  get_offset(unsigned int got_type) const
+  get_offset(unsigned int got_type, uint64_t addend) const
   {
     for (const Got_offset_list* g = this; g != NULL; g = g->got_next_)
       {
-        if (g->got_type_ == got_type)
+        if (g->got_type_ == got_type && g->addend_ == addend)
           return g->got_offset_;
       }
     return -1U;
@@ -297,7 +301,7 @@ class Got_offset_list
     { }
 
     virtual void
-    visit(unsigned int, unsigned int) = 0;
+    visit(unsigned int, unsigned int, uint64_t) = 0;
   };
 
   // Loop over all GOT offset entries, calling a visitor class V for each.
@@ -307,12 +311,13 @@ class Got_offset_list
     if (this->got_type_ == -1U)
       return;
     for (const Got_offset_list* g = this; g != NULL; g = g->got_next_)
-      v->visit(g->got_type_, g->got_offset_);
+      v->visit(g->got_type_, g->got_offset_, g->addend_);
   }
 
  private:
   unsigned int got_type_;
   unsigned int got_offset_;
+  uint64_t addend_;
   Got_offset_list* got_next_;
 };
 
@@ -2134,7 +2139,7 @@ class Sized_relobj : public Relobj
     Local_got_offsets::const_iterator p =
         this->local_got_offsets_.find(key);
     return (p != this->local_got_offsets_.end()
-            && p->second->get_offset(got_type) != -1U);
+            && p->second->get_offset(got_type, addend) != -1U);
   }
 
   // Return the GOT offset of type GOT_TYPE of the local symbol
@@ -2147,7 +2152,7 @@ class Sized_relobj : public Relobj
     Local_got_offsets::const_iterator p =
         this->local_got_offsets_.find(key);
     gold_assert(p != this->local_got_offsets_.end());
-    unsigned int off = p->second->get_offset(got_type);
+    unsigned int off = p->second->get_offset(got_type, addend);
     gold_assert(off != -1U);
     return off;
   }
@@ -2162,10 +2167,10 @@ class Sized_relobj : public Relobj
     Local_got_offsets::const_iterator p =
         this->local_got_offsets_.find(key);
     if (p != this->local_got_offsets_.end())
-      p->second->set_offset(got_type, got_offset);
+      p->second->set_offset(got_type, got_offset, addend);
     else
       {
-        Got_offset_list* g = new Got_offset_list(got_type, got_offset);
+	Got_offset_list* g = new Got_offset_list(got_type, got_offset, addend);
         std::pair<Local_got_offsets::iterator, bool> ins =
             this->local_got_offsets_.insert(std::make_pair(key, g));
         gold_assert(ins.second);
diff --git a/gold/symtab.h b/gold/symtab.h
index 104429a5af1..45e0842f593 100644
--- a/gold/symtab.h
+++ b/gold/symtab.h
@@ -427,23 +427,35 @@ class Symbol
 
   // Return whether this symbol has an entry in the GOT section.
   // For a TLS symbol, this GOT entry will hold its tp-relative offset.
+  bool
+  has_got_offset(unsigned int got_type, uint64_t addend) const
+  { return this->got_offsets_.get_offset(got_type, addend) != -1U; }
+
   bool
   has_got_offset(unsigned int got_type) const
-  { return this->got_offsets_.get_offset(got_type) != -1U; }
+  { return this->has_got_offset(got_type, 0); }
 
   // Return the offset into the GOT section of this symbol.
   unsigned int
-  got_offset(unsigned int got_type) const
+  got_offset(unsigned int got_type, uint64_t addend) const
   {
-    unsigned int got_offset = this->got_offsets_.get_offset(got_type);
+    unsigned int got_offset = this->got_offsets_.get_offset(got_type, addend);
     gold_assert(got_offset != -1U);
     return got_offset;
   }
 
+  unsigned int
+  got_offset(unsigned int got_type) const
+  { return this->got_offset(got_type, 0); }
+
   // Set the GOT offset of this symbol.
+  void
+  set_got_offset(unsigned int got_type, unsigned int got_offset, uint64_t addend)
+  { this->got_offsets_.set_offset(got_type, got_offset, addend); }
+
   void
   set_got_offset(unsigned int got_type, unsigned int got_offset)
-  { this->got_offsets_.set_offset(got_type, got_offset); }
+  { this->set_got_offset(got_type, got_offset, 0); }
 
   // Return the GOT offset list.
   const Got_offset_list*

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [GOLD] Remove addend from Local_got_entry_key
  2021-09-02  3:28 [GOLD] Got_offset_list: addend field Alan Modra
@ 2021-09-02  3:29 ` Alan Modra
  2021-09-02  3:30 ` [GOLD] Output_data_got tidy Alan Modra
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Alan Modra @ 2021-09-02  3:29 UTC (permalink / raw)
  To: binutils

This patch removes the addend from Local_got_entry_key, which is
unnecessary now that Got_offset_list has an addend.  Note that it
might be advantageous to keep the addend in Local_got_entry_key when
linking objects containing a large number of section_sym+addend@got
relocations.  I opted to save some memory by removing the field but
left the class there in case we might need to restore {sym,addend}
lookup.  That's also why this change is split out from the
Got_offset_list change.

	PR 28192
	* object.h (Local_got_entry_key): Delete addend_ field.
	Adjust constructor and methods to suit.
	* object.cc (Sized_relobj::do_for_all_local_got_entries):
	Update key.

diff --git a/gold/object.cc b/gold/object.cc
index 45cf30d4aaf..b7a2a6cfdfa 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -427,7 +427,7 @@ Sized_relobj<size, big_endian>::do_for_all_local_got_entries(
   unsigned int nsyms = this->local_symbol_count();
   for (unsigned int i = 0; i < nsyms; i++)
     {
-      Local_got_entry_key key(i, 0);
+      Local_got_entry_key key(i);
       Local_got_offsets::const_iterator p = this->local_got_offsets_.find(key);
       if (p != this->local_got_offsets_.end())
 	{
diff --git a/gold/object.h b/gold/object.h
index 66e565c1b4c..2dbe4b3e1be 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -327,15 +327,15 @@ class Got_offset_list
 class Local_got_entry_key
 {
  public:
-  Local_got_entry_key(unsigned int symndx, uint64_t addend)
-    : symndx_(symndx), addend_(addend)
+  Local_got_entry_key(unsigned int symndx)
+    : symndx_(symndx)
   {}
 
   // Whether this equals to another Local_got_entry_key.
   bool
   eq(const Local_got_entry_key& key) const
   {
-    return (this->symndx_ == key.symndx_ && this->addend_ == key.addend_);
+    return this->symndx_ == key.symndx_;
   }
 
   // Compute a hash value for this using 64-bit FNV-1a hash.
@@ -345,7 +345,6 @@ class Local_got_entry_key
     uint64_t h = 14695981039346656037ULL; // FNV offset basis.
     uint64_t prime = 1099511628211ULL;
     h = (h ^ static_cast<uint64_t>(this->symndx_)) * prime;
-    h = (h ^ static_cast<uint64_t>(this->addend_)) * prime;
     return h;
   }
 
@@ -368,8 +367,6 @@ class Local_got_entry_key
  private:
   // The local symbol index.
   unsigned int symndx_;
-  // The addend.
-  uint64_t addend_;
 };
 
 // Type for mapping section index to uncompressed size and contents.
@@ -2135,7 +2132,7 @@ class Sized_relobj : public Relobj
   do_local_has_got_offset(unsigned int symndx, unsigned int got_type,
 			  uint64_t addend) const
   {
-    Local_got_entry_key key(symndx, addend);
+    Local_got_entry_key key(symndx);
     Local_got_offsets::const_iterator p =
         this->local_got_offsets_.find(key);
     return (p != this->local_got_offsets_.end()
@@ -2148,7 +2145,7 @@ class Sized_relobj : public Relobj
   do_local_got_offset(unsigned int symndx, unsigned int got_type,
 			  uint64_t addend) const
   {
-    Local_got_entry_key key(symndx, addend);
+    Local_got_entry_key key(symndx);
     Local_got_offsets::const_iterator p =
         this->local_got_offsets_.find(key);
     gold_assert(p != this->local_got_offsets_.end());
@@ -2163,7 +2160,7 @@ class Sized_relobj : public Relobj
   do_set_local_got_offset(unsigned int symndx, unsigned int got_type,
 			  unsigned int got_offset, uint64_t addend)
   {
-    Local_got_entry_key key(symndx, addend);
+    Local_got_entry_key key(symndx);
     Local_got_offsets::const_iterator p =
         this->local_got_offsets_.find(key);
     if (p != this->local_got_offsets_.end())

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [GOLD] Output_data_got tidy
  2021-09-02  3:28 [GOLD] Got_offset_list: addend field Alan Modra
  2021-09-02  3:29 ` [GOLD] Remove addend from Local_got_entry_key Alan Modra
@ 2021-09-02  3:30 ` Alan Modra
  2021-09-02  3:31 ` [GOLD] Output_data_got create entry method addends Alan Modra
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Alan Modra @ 2021-09-02  3:30 UTC (permalink / raw)
  To: binutils

Some Output_data_got methods already have support for addends, but
were implemented as separate methods.  This removes unnecessary code
duplication by making the overloads without an addend inline calls of
the overload with addend.

Relobj::local_has_got_offset and others there get a similar treatment.
Comments are removed since it should be obvious without a comment, and
the existing comments are not precisely what the code does.  For
example, a local_has_got_offset call without an addend does not return
whether the local symbol has *a* GOT offset of type GOT_TYPE, it
returns whether there is a GOT entry of type GOT_TYPE for the symbol
with addend of zero.

	PR 28192
	* output.h (Output_data_got::add_local): Make overload without
	addend call overload with addend.
	(Output_data_got::add_local_with_rel): Likewise.
	(Output_data_got::add_local_pair_with_rel): Likewise.
	* output.cc (Output_data_got::add_local): Delete overload
	without addend.
	(Output_data_got::add_local_with_rel): Likewise.
	(Output_data_got::add_local_pair_with_rel): Likewise.
	* object.h (Relobj::local_has_got_offset): Move overload without
	addend later, and call version with addend rather than expanding
	that version.  Update comment.
	(Relobj::local_got_offset): Likewise.
	(Relobj::set_local_got_offset): Likewise.

diff --git a/gold/object.h b/gold/object.h
index 2dbe4b3e1be..1d68f2a53a2 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -1216,48 +1216,42 @@ class Relobj : public Object
   local_plt_offset(unsigned int symndx) const
   { return this->do_local_plt_offset(symndx); }
 
-  // Return whether the local symbol SYMNDX has a GOT offset of type
-  // GOT_TYPE.
-  bool
-  local_has_got_offset(unsigned int symndx, unsigned int got_type) const
-  { return this->do_local_has_got_offset(symndx, got_type, 0); }
-
-  // Return whether the local symbol SYMNDX plus ADDEND has a GOT offset
-  // of type GOT_TYPE.
+  // Return whether there is a GOT entry of type GOT_TYPE for the
+  // local symbol SYMNDX with given ADDEND.
   bool
   local_has_got_offset(unsigned int symndx, unsigned int got_type,
 		       uint64_t addend) const
   { return this->do_local_has_got_offset(symndx, got_type, addend); }
 
-  // Return the GOT offset of type GOT_TYPE of the local symbol
-  // SYMNDX.  It is an error to call this if the symbol does not have
-  // a GOT offset of the specified type.
-  unsigned int
-  local_got_offset(unsigned int symndx, unsigned int got_type) const
-  { return this->do_local_got_offset(symndx, got_type, 0); }
+  bool
+  local_has_got_offset(unsigned int symndx, unsigned int got_type) const
+  { return this->local_has_got_offset(symndx, got_type, 0); }
 
-  // Return the GOT offset of type GOT_TYPE of the local symbol
-  // SYMNDX plus ADDEND.  It is an error to call this if the symbol
-  // does not have a GOT offset of the specified type.
+  // Return the GOT offset of the GOT entry with type GOT_TYPE for the
+  // local symbol SYMNDX with given ADDEND.  It is an error to call
+  // this function if the symbol does not have such a GOT entry.
   unsigned int
   local_got_offset(unsigned int symndx, unsigned int got_type,
-		       uint64_t addend) const
+		   uint64_t addend) const
   { return this->do_local_got_offset(symndx, got_type, addend); }
 
-  // Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX
-  // to GOT_OFFSET.
-  void
-  set_local_got_offset(unsigned int symndx, unsigned int got_type,
-		       unsigned int got_offset)
-  { this->do_set_local_got_offset(symndx, got_type, got_offset, 0); }
+  unsigned int
+  local_got_offset(unsigned int symndx, unsigned int got_type) const
+  { return this->local_got_offset(symndx, got_type, 0); }
 
-  // Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX
-  // plus ADDEND to GOT_OFFSET.
+  // Set the GOT offset for a GOT entry with type GOT_TYPE for the
+  // local symbol SYMNDX with ADDEND to GOT_OFFSET.  Create such an
+  // entry if none exists.
   void
   set_local_got_offset(unsigned int symndx, unsigned int got_type,
 		       unsigned int got_offset, uint64_t addend)
   { this->do_set_local_got_offset(symndx, got_type, got_offset, addend); }
 
+  void
+  set_local_got_offset(unsigned int symndx, unsigned int got_type,
+		       unsigned int got_offset)
+  { this->set_local_got_offset(symndx, got_type, got_offset, 0); }
+
   // Return whether the local symbol SYMNDX is a TLS symbol.
   bool
   local_is_tls(unsigned int symndx) const
diff --git a/gold/output.cc b/gold/output.cc
index afdba06753e..75f54f02f23 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -1531,26 +1531,6 @@ Output_data_got<got_size, big_endian>::add_global_pair_with_rel(
 				got_offset + got_size / 8, 0);
 }
 
-// Add an entry for a local symbol to the GOT.  This returns true if
-// this is a new GOT entry, false if the symbol already has a GOT
-// entry.
-
-template<int got_size, bool big_endian>
-bool
-Output_data_got<got_size, big_endian>::add_local(
-    Relobj* object,
-    unsigned int symndx,
-    unsigned int got_type)
-{
-  if (object->local_has_got_offset(symndx, got_type))
-    return false;
-
-  unsigned int got_offset = this->add_got_entry(Got_entry(object, symndx,
-							  false));
-  object->set_local_got_offset(symndx, got_type, got_offset);
-  return true;
-}
-
 // Add an entry for a local symbol plus ADDEND to the GOT.  This returns
 // true if this is a new GOT entry, false if the symbol already has a GOT
 // entry.
@@ -1590,26 +1570,6 @@ Output_data_got<got_size, big_endian>::add_local_plt(
   return true;
 }
 
-// Add an entry for a local symbol to the GOT, and add a dynamic
-// relocation of type R_TYPE for the GOT entry.
-
-template<int got_size, bool big_endian>
-void
-Output_data_got<got_size, big_endian>::add_local_with_rel(
-    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(Got_entry());
-  object->set_local_got_offset(symndx, got_type, got_offset);
-  rel_dyn->add_local_generic(object, symndx, r_type, this, got_offset, 0);
-}
-
 // Add an entry for a local symbol plus ADDEND to the GOT, and add a dynamic
 // relocation of type R_TYPE for the GOT entry.
 
@@ -1631,32 +1591,6 @@ Output_data_got<got_size, big_endian>::add_local_with_rel(
                              addend);
 }
 
-// Add a pair of entries for a local symbol to the GOT, and add
-// 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 got_size, bool big_endian>
-void
-Output_data_got<got_size, big_endian>::add_local_pair_with_rel(
-    Relobj* object,
-    unsigned int symndx,
-    unsigned int shndx,
-    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, 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, this, got_offset, 0);
-}
-
 // Add a pair of entries for a local symbol plus ADDEND to the GOT, and add
 // a dynamic relocation of type R_TYPE using the section symbol of
 // the output section to which input section SHNDX maps, on the first.
diff --git a/gold/output.h b/gold/output.h
index 9c44f6259a2..9c7bfd84dcc 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -2488,12 +2488,6 @@ class Output_data_got : public Output_data_got_base
 			   Output_data_reloc_generic* rel_dyn,
 			   unsigned int r_type_1, unsigned int r_type_2);
 
-  // Add an entry for a local symbol to the GOT.  This returns true if
-  // this is a new GOT entry, false if the symbol already has a GOT
-  // entry.
-  bool
-  add_local(Relobj* object, unsigned int sym_index, unsigned int got_type);
-
   // Add an entry for a local symbol plus ADDEND to the GOT.  This returns
   // true if this is a new GOT entry, false if the symbol already has a GOT
   // entry.
@@ -2501,6 +2495,10 @@ class Output_data_got : public Output_data_got_base
   add_local(Relobj* object, unsigned int sym_index, unsigned int got_type,
 	    uint64_t addend);
 
+  bool
+  add_local(Relobj* object, unsigned int sym_index, unsigned int got_type)
+  { return this->add_local(object, sym_index, got_type, 0); }
+
   // Like add_local, but use the PLT offset of the local symbol if it
   // has one.
   bool
@@ -2512,21 +2510,20 @@ class Output_data_got : public Output_data_got_base
   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
+  // Add an entry for a local symbol plus ADDEND to the GOT, and add a dynamic
   // relocation of type R_TYPE for the GOT entry.
   void
   add_local_with_rel(Relobj* object, unsigned int sym_index,
 		     unsigned int got_type, Output_data_reloc_generic* rel_dyn,
-		     unsigned int r_type);
+		     unsigned int r_type, uint64_t addend);
 
-  // Add an entry for a local symbol plus ADDEND to the GOT, and add a dynamic
-  // relocation of type R_TYPE for the GOT entry.
   void
   add_local_with_rel(Relobj* object, unsigned int sym_index,
 		     unsigned int got_type, Output_data_reloc_generic* rel_dyn,
-		     unsigned int r_type, uint64_t addend);
+		     unsigned int r_type)
+  { this->add_local_with_rel(object, sym_index, got_type, rel_dyn, r_type, 0); }
 
-  // Add a pair of entries for a local symbol to the GOT, and add
+  // Add a pair of entries for a local symbol plus ADDEND to the GOT, and add
   // 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
@@ -2535,18 +2532,15 @@ class Output_data_got : public Output_data_got_base
   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);
+			  unsigned int r_type, uint64_t addend);
 
-  // Add a pair of entries for a local symbol plus ADDEND to the GOT, and add
-  // 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, uint64_t addend);
+			  unsigned int r_type)
+  { this->add_local_pair_with_rel(object, sym_index, shndx, got_type,
+				  rel_dyn, r_type, 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.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [GOLD] Output_data_got create entry method addends
  2021-09-02  3:28 [GOLD] Got_offset_list: addend field Alan Modra
  2021-09-02  3:29 ` [GOLD] Remove addend from Local_got_entry_key Alan Modra
  2021-09-02  3:30 ` [GOLD] Output_data_got tidy Alan Modra
@ 2021-09-02  3:31 ` Alan Modra
  2021-09-02  3:32 ` [GOLD] Got_entry::write addends Alan Modra
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Alan Modra @ 2021-09-02  3:31 UTC (permalink / raw)
  To: binutils

This patch makes all the Output_data_got methods that create new
entries accept an optional addend.

	PR 28192
	* output.h (Output_data_got::add_global): Add overload with
	addend parameter.  Update comment.  Make overload without
	addend call overload with addend.
	(Output_data_got::add_global_plt): Likewise.
	(Output_data_got::add_global_tls): Likewise.
	(Output_data_got::add_global_with_rel): Likewise.
	(Output_data_got::add_global_pair_with_rel): Likewise.
	(Output_data_got::add_local_plt): Likewise.
	(Output_data_got::add_local_tls): Likewise.
	(Output_data_got::add_local_tls_pair): Likewise.
	(Output_data_got::reserve_local): Likewise.
	(Output_data_got::reserve_global): Likewise.
	(Output_data_got::Got_entry): Include addend in global sym
	constructor.  Delete local sym constructor without addend.
	* output.cc (Output_data_got::add_global): Add addend param,
	pass to got handling methods.
	(Output_data_got::add_global_plt): Likewise.
	(Output_data_got::add_global_with_rel): Likewise.
	(Output_data_got::add_global_pair_with_rel): Likewise.
	(Output_data_got::add_local_plt): Likewise.
	(Output_data_got::add_local_tls_pair): Likewise.
	(Output_data_got::reserve_local): Likewise.
	(Output_data_got::reserve_global): Likewise.

diff --git a/gold/output.cc b/gold/output.cc
index 75f54f02f23..c5f7eef0fbb 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -1461,15 +1461,15 @@ Output_data_got<got_size, big_endian>::Got_entry::write(
 
 template<int got_size, bool big_endian>
 bool
-Output_data_got<got_size, big_endian>::add_global(
-    Symbol* gsym,
-    unsigned int got_type)
+Output_data_got<got_size, big_endian>::add_global(Symbol* gsym,
+						  unsigned int got_type,
+						  uint64_t addend)
 {
-  if (gsym->has_got_offset(got_type))
+  if (gsym->has_got_offset(got_type, addend))
     return false;
 
-  unsigned int got_offset = this->add_got_entry(Got_entry(gsym, false));
-  gsym->set_got_offset(got_type, got_offset);
+  unsigned int got_offset = this->add_got_entry(Got_entry(gsym, false, addend));
+  gsym->set_got_offset(got_type, got_offset, addend);
   return true;
 }
 
@@ -1478,13 +1478,14 @@ Output_data_got<got_size, big_endian>::add_global(
 template<int got_size, bool big_endian>
 bool
 Output_data_got<got_size, big_endian>::add_global_plt(Symbol* gsym,
-						      unsigned int got_type)
+						      unsigned int got_type,
+						      uint64_t addend)
 {
-  if (gsym->has_got_offset(got_type))
+  if (gsym->has_got_offset(got_type, addend))
     return false;
 
-  unsigned int got_offset = this->add_got_entry(Got_entry(gsym, true));
-  gsym->set_got_offset(got_type, got_offset);
+  unsigned int got_offset = this->add_got_entry(Got_entry(gsym, true, addend));
+  gsym->set_got_offset(got_type, got_offset, addend);
   return true;
 }
 
@@ -1497,14 +1498,15 @@ Output_data_got<got_size, big_endian>::add_global_with_rel(
     Symbol* gsym,
     unsigned int got_type,
     Output_data_reloc_generic* rel_dyn,
-    unsigned int r_type)
+    unsigned int r_type,
+    uint64_t addend)
 {
-  if (gsym->has_got_offset(got_type))
+  if (gsym->has_got_offset(got_type, addend))
     return;
 
   unsigned int got_offset = this->add_got_entry(Got_entry());
-  gsym->set_got_offset(got_type, got_offset);
-  rel_dyn->add_global_generic(gsym, r_type, this, got_offset, 0);
+  gsym->set_got_offset(got_type, got_offset, addend);
+  rel_dyn->add_global_generic(gsym, r_type, this, got_offset, addend);
 }
 
 // Add a pair of entries for a global symbol to the GOT, and add
@@ -1517,18 +1519,19 @@ Output_data_got<got_size, big_endian>::add_global_pair_with_rel(
     unsigned int got_type,
     Output_data_reloc_generic* rel_dyn,
     unsigned int r_type_1,
-    unsigned int r_type_2)
+    unsigned int r_type_2,
+    uint64_t addend)
 {
-  if (gsym->has_got_offset(got_type))
+  if (gsym->has_got_offset(got_type, addend))
     return;
 
   unsigned int got_offset = this->add_got_entry_pair(Got_entry(), Got_entry());
-  gsym->set_got_offset(got_type, got_offset);
-  rel_dyn->add_global_generic(gsym, r_type_1, this, got_offset, 0);
+  gsym->set_got_offset(got_type, got_offset, addend);
+  rel_dyn->add_global_generic(gsym, r_type_1, this, got_offset, addend);
 
   if (r_type_2 != 0)
     rel_dyn->add_global_generic(gsym, r_type_2, this,
-				got_offset + got_size / 8, 0);
+				got_offset + got_size / 8, addend);
 }
 
 // Add an entry for a local symbol plus ADDEND to the GOT.  This returns
@@ -1559,14 +1562,15 @@ bool
 Output_data_got<got_size, big_endian>::add_local_plt(
     Relobj* object,
     unsigned int symndx,
-    unsigned int got_type)
+    unsigned int got_type,
+    uint64_t addend)
 {
-  if (object->local_has_got_offset(symndx, got_type))
+  if (object->local_has_got_offset(symndx, got_type, addend))
     return false;
 
   unsigned int got_offset = this->add_got_entry(Got_entry(object, symndx,
-							  true));
-  object->set_local_got_offset(symndx, got_type, got_offset);
+							  true, addend));
+  object->set_local_got_offset(symndx, got_type, got_offset, addend);
   return true;
 }
 
@@ -1580,7 +1584,8 @@ Output_data_got<got_size, big_endian>::add_local_with_rel(
     unsigned int symndx,
     unsigned int got_type,
     Output_data_reloc_generic* rel_dyn,
-    unsigned int r_type, uint64_t addend)
+    unsigned int r_type,
+    uint64_t addend)
 {
   if (object->local_has_got_offset(symndx, got_type, addend))
     return;
@@ -1604,7 +1609,8 @@ Output_data_got<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, uint64_t addend)
+    unsigned int r_type,
+    uint64_t addend)
 {
   if (object->local_has_got_offset(symndx, got_type, addend))
     return;
@@ -1628,16 +1634,17 @@ Output_data_got<got_size, big_endian>::add_local_tls_pair(
     unsigned int symndx,
     unsigned int got_type,
     Output_data_reloc_generic* rel_dyn,
-    unsigned int r_type)
+    unsigned int r_type,
+    uint64_t addend)
 {
-  if (object->local_has_got_offset(symndx, got_type))
+  if (object->local_has_got_offset(symndx, got_type, addend))
     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);
+			       Got_entry(object, symndx, true, addend));
+  object->set_local_got_offset(symndx, got_type, got_offset, addend);
+  rel_dyn->add_local_generic(object, 0, r_type, this, got_offset, addend);
 }
 
 // Reserve a slot in the GOT for a local symbol or the second slot of a pair.
@@ -1648,10 +1655,11 @@ Output_data_got<got_size, big_endian>::reserve_local(
     unsigned int i,
     Relobj* object,
     unsigned int sym_index,
-    unsigned int got_type)
+    unsigned int got_type,
+    uint64_t addend)
 {
   this->do_reserve_slot(i);
-  object->set_local_got_offset(sym_index, got_type, this->got_offset(i));
+  object->set_local_got_offset(sym_index, got_type, this->got_offset(i), addend);
 }
 
 // Reserve a slot in the GOT for a global symbol.
@@ -1661,10 +1669,11 @@ void
 Output_data_got<got_size, big_endian>::reserve_global(
     unsigned int i,
     Symbol* gsym,
-    unsigned int got_type)
+    unsigned int got_type,
+    uint64_t addend)
 {
   this->do_reserve_slot(i);
-  gsym->set_got_offset(got_type, this->got_offset(i));
+  gsym->set_got_offset(got_type, this->got_offset(i), addend);
 }
 
 // Write out the GOT.
diff --git a/gold/output.h b/gold/output.h
index 9c7bfd84dcc..4058963a8f5 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -2459,34 +2459,61 @@ class Output_data_got : public Output_data_got_base
     this->free_list_.init(data_size, false);
   }
 
-  // Add an entry for a global symbol to the GOT.  Return true if this
-  // is a new GOT entry, false if the symbol was already in the GOT.
+  // Add an entry for a global symbol GSYM plus ADDEND to the GOT.
+  // Return true if this is a new GOT entry, false if the symbol plus
+  // addend was already in the GOT.
   bool
-  add_global(Symbol* gsym, unsigned int got_type);
+  add_global(Symbol* gsym, unsigned int got_type, uint64_t addend);
+
+  bool
+  add_global(Symbol* gsym, unsigned int got_type)
+  { return this->add_global(gsym, got_type, 0); }
 
   // Like add_global, but use the PLT offset of the global symbol if
   // it has one.
   bool
-  add_global_plt(Symbol* gsym, unsigned int got_type);
+  add_global_plt(Symbol* gsym, unsigned int got_type, uint64_t addend);
+
+  bool
+  add_global_plt(Symbol* gsym, unsigned int got_type)
+  { return this->add_global_plt(gsym, got_type, 0); }
 
   // 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, uint64_t addend)
+  { return this->add_global_plt(gsym, got_type, addend); }
+
   bool
   add_global_tls(Symbol* gsym, unsigned int got_type)
-  { return add_global_plt(gsym, got_type); }
+  { return this->add_global_tls(gsym, got_type, 0); }
 
-  // Add an entry for a global symbol to the GOT, and add a dynamic
-  // relocation of type R_TYPE for the GOT entry.
+  // Add an entry for a global symbol GSYM plus ADDEND to the GOT, and
+  // add a dynamic relocation of type R_TYPE for the GOT entry.
   void
   add_global_with_rel(Symbol* gsym, unsigned int got_type,
-		      Output_data_reloc_generic* rel_dyn, unsigned int r_type);
+		      Output_data_reloc_generic* rel_dyn, unsigned int r_type,
+		      uint64_t addend);
 
-  // Add a pair of entries for a global symbol to the GOT, and add
-  // dynamic relocations of type R_TYPE_1 and R_TYPE_2, respectively.
+  void
+  add_global_with_rel(Symbol* gsym, unsigned int got_type,
+		      Output_data_reloc_generic* rel_dyn, unsigned int r_type)
+  { this->add_global_with_rel(gsym, got_type, rel_dyn, r_type, 0); }
+
+  // Add a pair of entries for a global symbol GSYM plus ADDEND to the
+  // GOT, and add dynamic relocations of type R_TYPE_1 and R_TYPE_2,
+  // respectively.
   void
   add_global_pair_with_rel(Symbol* gsym, unsigned int got_type,
 			   Output_data_reloc_generic* rel_dyn,
-			   unsigned int r_type_1, unsigned int r_type_2);
+			   unsigned int r_type_1, unsigned int r_type_2,
+			   uint64_t addend);
+
+  void
+  add_global_pair_with_rel(Symbol* gsym, unsigned int got_type,
+			   Output_data_reloc_generic* rel_dyn,
+			   unsigned int r_type_1, unsigned int r_type_2)
+  { this->add_global_pair_with_rel(gsym, got_type, rel_dyn, r_type_1, r_type_2, 0); }
 
   // Add an entry for a local symbol plus ADDEND to the GOT.  This returns
   // true if this is a new GOT entry, false if the symbol already has a GOT
@@ -2502,13 +2529,23 @@ class Output_data_got : public Output_data_got_base
   // Like add_local, but use the PLT offset of the local symbol if it
   // has one.
   bool
-  add_local_plt(Relobj* object, unsigned int sym_index, unsigned int got_type);
+  add_local_plt(Relobj* object, unsigned int sym_index, unsigned int got_type,
+		uint64_t addend);
+
+  bool
+  add_local_plt(Relobj* object, unsigned int sym_index, unsigned int got_type)
+  { return this->add_local_plt(object, sym_index, got_type, 0); }
 
   // 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,
+		uint64_t addend)
+  { return this->add_local_plt(object, sym_index, got_type, addend); }
+
   bool
   add_local_tls(Relobj* object, unsigned int sym_index, unsigned int got_type)
-  { return add_local_plt(object, sym_index, got_type); }
+  { return this->add_local_tls(object, sym_index, got_type, 0); }
 
   // Add an entry for a local symbol plus ADDEND to the GOT, and add a dynamic
   // relocation of type R_TYPE for the GOT entry.
@@ -2542,15 +2579,23 @@ class Output_data_got : public Output_data_got_base
   { this->add_local_pair_with_rel(object, sym_index, shndx, got_type,
 				  rel_dyn, r_type, 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.
+  // Add a pair of entries for a local symbol plus ADDEND 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 plus ADDEND 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);
+		     unsigned int r_type, uint64_t addend);
+
+  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)
+  { this->add_local_tls_pair(object, sym_index, got_type, rel_dyn, r_type, 0); }
 
   // Add a constant to the GOT.  This returns the offset of the new
   // entry from the start of the GOT.
@@ -2571,14 +2616,24 @@ class Output_data_got : public Output_data_got_base
     this->replace_got_entry(i, Got_entry(constant));
   }
 
-  // Reserve a slot in the GOT for a local symbol.
+  // Reserve a slot in the GOT for a local symbol plus ADDEND.
   void
   reserve_local(unsigned int i, Relobj* object, unsigned int sym_index,
-		unsigned int got_type);
+		unsigned int got_type, uint64_t addend);
+
+  void
+  reserve_local(unsigned int i, Relobj* object, unsigned int sym_index,
+		unsigned int got_type)
+  { this->reserve_local(i, object, sym_index, got_type, 0); }
+
+  // Reserve a slot in the GOT for a global symbol plus ADDEND.
+  void
+  reserve_global(unsigned int i, Symbol* gsym, unsigned int got_type,
+		 uint64_t addend);
 
-  // Reserve a slot in the GOT for a global symbol.
   void
-  reserve_global(unsigned int i, Symbol* gsym, unsigned int got_type);
+  reserve_global(unsigned int i, Symbol* gsym, unsigned int got_type)
+  { this->reserve_global(i, gsym, got_type, 0); }
 
  protected:
   // Write out the GOT table.
@@ -2617,16 +2672,16 @@ class Output_data_got : public Output_data_got_base
     { this->u_.constant = 0; }
 
     // Create a global symbol entry.
-    Got_entry(Symbol* gsym, bool use_plt_or_tls_offset)
+    Got_entry(Symbol* gsym, bool use_plt_or_tls_offset, uint64_t addend)
       : local_sym_index_(GSYM_CODE),
-	use_plt_or_tls_offset_(use_plt_or_tls_offset), addend_(0)
+	use_plt_or_tls_offset_(use_plt_or_tls_offset), addend_(addend)
     { this->u_.gsym = gsym; }
 
     // Create a local symbol entry.
     Got_entry(Relobj* object, unsigned int local_sym_index,
-	      bool use_plt_or_tls_offset)
+	      bool use_plt_or_tls_offset, uint64_t addend)
       : local_sym_index_(local_sym_index),
-	use_plt_or_tls_offset_(use_plt_or_tls_offset), addend_(0)
+	use_plt_or_tls_offset_(use_plt_or_tls_offset), addend_(addend)
     {
       gold_assert(local_sym_index != GSYM_CODE
 		  && local_sym_index != CONSTANT_CODE
@@ -2635,19 +2690,6 @@ class Output_data_got : public Output_data_got_base
       this->u_.object = object;
     }
 
-    // Create a local symbol entry plus addend.
-    Got_entry(Relobj* object, unsigned int local_sym_index,
-	bool use_plt_or_tls_offset, uint64_t addend)
-      : local_sym_index_(local_sym_index),
-	use_plt_or_tls_offset_(use_plt_or_tls_offset), addend_(addend)
-    {
-      gold_assert(local_sym_index != GSYM_CODE
-      && local_sym_index != CONSTANT_CODE
-      && local_sym_index != RESERVED_CODE
-      && local_sym_index == this->local_sym_index_);
-      this->u_.object = object;
-    }
-
     // 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)

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [GOLD] Got_entry::write addends
  2021-09-02  3:28 [GOLD] Got_offset_list: addend field Alan Modra
                   ` (2 preceding siblings ...)
  2021-09-02  3:31 ` [GOLD] Output_data_got create entry method addends Alan Modra
@ 2021-09-02  3:32 ` Alan Modra
  2021-09-02  3:33 ` [GOLD] PowerPC64 support for sym+addend GOT entries Alan Modra
  2021-09-03  1:13 ` [GOLD] Got_offset_list: addend field Cary Coutant
  5 siblings, 0 replies; 9+ messages in thread
From: Alan Modra @ 2021-09-02  3:32 UTC (permalink / raw)
  To: binutils

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.

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_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;
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<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))
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<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();
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

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [GOLD] PowerPC64 support for sym+addend GOT entries
  2021-09-02  3:28 [GOLD] Got_offset_list: addend field Alan Modra
                   ` (3 preceding siblings ...)
  2021-09-02  3:32 ` [GOLD] Got_entry::write addends Alan Modra
@ 2021-09-02  3:33 ` Alan Modra
  2021-09-03  1:13 ` [GOLD] Got_offset_list: addend field Cary Coutant
  5 siblings, 0 replies; 9+ messages in thread
From: Alan Modra @ 2021-09-02  3:33 UTC (permalink / raw)
  To: binutils

Pass addends to all the GOT handling functions, plus remove some
extraneous asserts.

	PR 28192
	* powerpc.cc (Output_data_got_powerpc): Add addend parameter to
	all methods creating got entries.
	(Target_powerpc::Scan::local): Pass reloc addend to got handling
	functions, and when creating dynamic got relocations.
	(Target_powerpc::Scan::global): Likewise.
	(Target_powerpc::Relocate::relocate): Likewise.  Remove extraneous
	assertions.

diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index 0b6405915c2..0cee975f8bd 100644
--- a/gold/powerpc.cc
+++ b/gold/powerpc.cc
@@ -2970,77 +2970,85 @@ public:
   // Override all the Output_data_got methods we use so as to first call
   // reserve_ent().
   bool
-  add_global(Symbol* gsym, unsigned int got_type)
+  add_global(Symbol* gsym, unsigned int got_type, uint64_t addend)
   {
     this->reserve_ent();
-    return Output_data_got<size, big_endian>::add_global(gsym, got_type);
+    return Output_data_got<size, big_endian>::add_global(gsym, got_type,
+							 addend);
   }
 
   bool
-  add_global_plt(Symbol* gsym, unsigned int got_type)
+  add_global_plt(Symbol* gsym, unsigned int got_type, uint64_t addend)
   {
     this->reserve_ent();
-    return Output_data_got<size, big_endian>::add_global_plt(gsym, got_type);
+    return Output_data_got<size, big_endian>::add_global_plt(gsym, got_type,
+							     addend);
   }
 
   bool
-  add_global_tls(Symbol* gsym, unsigned int got_type)
-  { return this->add_global_plt(gsym, got_type); }
+  add_global_tls(Symbol* gsym, unsigned int got_type, uint64_t addend)
+  { return this->add_global_plt(gsym, got_type, addend); }
 
   void
   add_global_with_rel(Symbol* gsym, unsigned int got_type,
-		      Output_data_reloc_generic* rel_dyn, unsigned int r_type)
+		      Output_data_reloc_generic* rel_dyn,
+		      unsigned int r_type, uint64_t addend)
   {
     this->reserve_ent();
     Output_data_got<size, big_endian>::
-      add_global_with_rel(gsym, got_type, rel_dyn, r_type);
+      add_global_with_rel(gsym, got_type, rel_dyn, r_type, addend);
   }
 
   void
   add_global_pair_with_rel(Symbol* gsym, unsigned int got_type,
 			   Output_data_reloc_generic* rel_dyn,
-			   unsigned int r_type_1, unsigned int r_type_2)
+			   unsigned int r_type_1, unsigned int r_type_2,
+			   uint64_t addend)
   {
     if (gsym->has_got_offset(got_type))
       return;
 
     this->reserve_ent(2);
     Output_data_got<size, big_endian>::
-      add_global_pair_with_rel(gsym, got_type, rel_dyn, r_type_1, r_type_2);
+      add_global_pair_with_rel(gsym, got_type, rel_dyn, r_type_1, r_type_2,
+			       addend);
   }
 
   bool
-  add_local(Relobj* object, unsigned int sym_index, unsigned int got_type)
+  add_local(Relobj* object, unsigned int sym_index, unsigned int got_type,
+	    uint64_t addend)
   {
     this->reserve_ent();
     return Output_data_got<size, big_endian>::add_local(object, sym_index,
-							got_type);
+							got_type, addend);
   }
 
   bool
-  add_local_plt(Relobj* object, unsigned int sym_index, unsigned int got_type)
+  add_local_plt(Relobj* object, unsigned int sym_index,
+		unsigned int got_type, uint64_t addend)
   {
     this->reserve_ent();
     return Output_data_got<size, big_endian>::add_local_plt(object, sym_index,
-							    got_type);
+							    got_type, addend);
   }
 
   bool
-  add_local_tls(Relobj* object, unsigned int sym_index, unsigned int got_type)
-  { return this->add_local_plt(object, sym_index, got_type); }
+  add_local_tls(Relobj* object, unsigned int sym_index,
+		unsigned int got_type, uint64_t addend)
+  { return this->add_local_plt(object, sym_index, got_type, addend); }
 
   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)
+		     unsigned int r_type, uint64_t addend)
   {
-    if (object->local_has_got_offset(sym_index, got_type))
+    if (object->local_has_got_offset(sym_index, got_type, addend))
       return;
 
     this->reserve_ent(2);
     Output_data_got<size, big_endian>::
-      add_local_tls_pair(object, sym_index, got_type, rel_dyn, r_type);
+      add_local_tls_pair(object, sym_index, got_type, rel_dyn, r_type, addend);
   }
 
   unsigned int
@@ -8195,29 +8203,30 @@ 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());
+	uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
 
 	if (!parameters->options().output_is_position_independent())
 	  {
 	    if (is_ifunc
 		&& (size == 32 || target->abiversion() >= 2))
-	      got->add_local_plt(object, r_sym, GOT_TYPE_STANDARD);
+	      got->add_local_plt(object, r_sym, GOT_TYPE_STANDARD, addend);
 	    else
-	      got->add_local(object, r_sym, GOT_TYPE_STANDARD);
+	      got->add_local(object, r_sym, GOT_TYPE_STANDARD, addend);
 	  }
-	else if (!object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD))
+	else if (!object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD, addend))
 	  {
 	    // If we are generating a shared object or a pie, this
 	    // symbol's GOT entry will be set by a dynamic relocation.
 	    unsigned int off;
 	    off = got->add_constant(0);
-	    object->set_local_got_offset(r_sym, GOT_TYPE_STANDARD, off);
+	    object->set_local_got_offset(r_sym, GOT_TYPE_STANDARD, off, addend);
 
 	    Reloc_section* rela_dyn = target->rela_dyn_section(symtab, layout,
 							       is_ifunc);
 	    unsigned int dynrel = (is_ifunc ? elfcpp::R_POWERPC_IRELATIVE
 				   : elfcpp::R_POWERPC_RELATIVE);
 	    rela_dyn->add_local_relative(object, r_sym, dynrel,
-					 got, off, 0, false);
+					 got, off, addend, false);
 	  }
       }
       break;
@@ -8246,9 +8255,11 @@ 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());
+	    uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
 	    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);
+				    rela_dyn, elfcpp::R_POWERPC_DTPMOD,
+				    addend);
 	  }
 	else if (tls_type == tls::TLSOPT_TO_LE)
 	  {
@@ -8296,7 +8307,8 @@ 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_tls(object, r_sym, GOT_TYPE_DTPREL);
+	uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
+	got->add_local_tls(object, r_sym, GOT_TYPE_DTPREL, addend);
       }
       break;
 
@@ -8310,17 +8322,18 @@ Target_powerpc<size, big_endian>::Scan::local(
 	if (tls_type == tls::TLSOPT_NONE)
 	  {
 	    unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
-	    if (!object->local_has_got_offset(r_sym, GOT_TYPE_TPREL))
+	    uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
+	    if (!object->local_has_got_offset(r_sym, GOT_TYPE_TPREL, addend))
 	      {
 		Output_data_got_powerpc<size, big_endian>* got
 		  = target->got_section(symtab, layout);
 		unsigned int off = got->add_constant(0);
-		object->set_local_got_offset(r_sym, GOT_TYPE_TPREL, off);
+		object->set_local_got_offset(r_sym, GOT_TYPE_TPREL, off, addend);
 
 		Reloc_section* rela_dyn = target->rela_dyn_section(layout);
 		rela_dyn->add_symbolless_local_addend(object, r_sym,
 						      elfcpp::R_POWERPC_TPREL,
-						      got, off, 0);
+						      got, off, addend);
 	      }
 	  }
 	else if (tls_type == tls::TLSOPT_TO_LE)
@@ -8980,22 +8993,23 @@ Target_powerpc<size, big_endian>::Scan::global(
       {
 	// The symbol requires a GOT entry.
 	Output_data_got_powerpc<size, big_endian>* got;
+	uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
 
 	got = target->got_section(symtab, layout);
 	if (gsym->final_value_is_known())
 	  {
 	    if (is_ifunc
 		&& (size == 32 || target->abiversion() >= 2))
-	      got->add_global_plt(gsym, GOT_TYPE_STANDARD);
+	      got->add_global_plt(gsym, GOT_TYPE_STANDARD, addend);
 	    else
-	      got->add_global(gsym, GOT_TYPE_STANDARD);
+	      got->add_global(gsym, GOT_TYPE_STANDARD, addend);
 	  }
-	else if (!gsym->has_got_offset(GOT_TYPE_STANDARD))
+	else if (!gsym->has_got_offset(GOT_TYPE_STANDARD, addend))
 	  {
 	    // If we are generating a shared object or a pie, this
 	    // symbol's GOT entry will be set by a dynamic relocation.
 	    unsigned int off = got->add_constant(0);
-	    gsym->set_got_offset(GOT_TYPE_STANDARD, off);
+	    gsym->set_got_offset(GOT_TYPE_STANDARD, off, addend);
 
 	    Reloc_section* rela_dyn
 	      = target->rela_dyn_section(symtab, layout, is_ifunc);
@@ -9008,12 +9022,13 @@ Target_powerpc<size, big_endian>::Scan::global(
 	      {
 		unsigned int dynrel = (is_ifunc ? elfcpp::R_POWERPC_IRELATIVE
 				       : elfcpp::R_POWERPC_RELATIVE);
-		rela_dyn->add_global_relative(gsym, dynrel, got, off, 0, false);
+		rela_dyn->add_global_relative(gsym, dynrel, got, off,
+					      addend, false);
 	      }
 	    else
 	      {
 		unsigned int dynrel = elfcpp::R_POWERPC_GLOB_DAT;
-		rela_dyn->add_global(gsym, dynrel, got, off, 0);
+		rela_dyn->add_global(gsym, dynrel, got, off, addend);
 	      }
 	  }
       }
@@ -9046,9 +9061,11 @@ Target_powerpc<size, big_endian>::Scan::global(
 	    Output_data_got_powerpc<size, big_endian>* got
 	      = target->got_section(symtab, layout);
 	    Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+	    uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
 	    got->add_global_pair_with_rel(gsym, GOT_TYPE_TLSGD, rela_dyn,
 					  elfcpp::R_POWERPC_DTPMOD,
-					  elfcpp::R_POWERPC_DTPREL);
+					  elfcpp::R_POWERPC_DTPREL,
+					  addend);
 	  }
 	else if (tls_type == tls::TLSOPT_TO_IE)
 	  {
@@ -9057,11 +9074,12 @@ Target_powerpc<size, big_endian>::Scan::global(
 		Output_data_got_powerpc<size, big_endian>* got
 		  = target->got_section(symtab, layout);
 		Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+		uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
 		if (gsym->is_undefined()
 		    || gsym->is_from_dynobj())
 		  {
 		    got->add_global_with_rel(gsym, GOT_TYPE_TPREL, rela_dyn,
-					     elfcpp::R_POWERPC_TPREL);
+					     elfcpp::R_POWERPC_TPREL, addend);
 		  }
 		else
 		  {
@@ -9069,7 +9087,7 @@ Target_powerpc<size, big_endian>::Scan::global(
 		    gsym->set_got_offset(GOT_TYPE_TPREL, off);
 		    unsigned int dynrel = elfcpp::R_POWERPC_TPREL;
 		    rela_dyn->add_symbolless_global_addend(gsym, dynrel,
-							   got, off, 0);
+							   got, off, addend);
 		  }
 	      }
 	    ppc_object->set_tls_marker();
@@ -9119,15 +9137,16 @@ Target_powerpc<size, big_endian>::Scan::global(
       {
 	Output_data_got_powerpc<size, big_endian>* got
 	  = target->got_section(symtab, layout);
+	uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
 	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);
+				   elfcpp::R_POWERPC_DTPREL, addend);
 	else
-	  got->add_global_tls(gsym, GOT_TYPE_DTPREL);
+	  got->add_global_tls(gsym, GOT_TYPE_DTPREL, addend);
       }
       break;
 
@@ -9146,11 +9165,12 @@ Target_powerpc<size, big_endian>::Scan::global(
 		Output_data_got_powerpc<size, big_endian>* got
 		  = target->got_section(symtab, layout);
 		Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+		uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
 		if (gsym->is_undefined()
 		    || gsym->is_from_dynobj())
 		  {
 		    got->add_global_with_rel(gsym, GOT_TYPE_TPREL, rela_dyn,
-					     elfcpp::R_POWERPC_TPREL);
+					     elfcpp::R_POWERPC_TPREL, addend);
 		  }
 		else
 		  {
@@ -9158,7 +9178,7 @@ Target_powerpc<size, big_endian>::Scan::global(
 		    gsym->set_got_offset(GOT_TYPE_TPREL, off);
 		    unsigned int dynrel = elfcpp::R_POWERPC_TPREL;
 		    rela_dyn->add_symbolless_global_addend(gsym, dynrel,
-							   got, off, 0);
+							   got, off, addend);
 		  }
 	      }
 	  }
@@ -10655,16 +10675,11 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
     }
   else if (is_got_reloc(r_type))
     {
+      uint64_t addend = size == 32 ? 0 : rela.get_r_addend();
       if (gsym != NULL)
-	{
-	  gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
-	  value = gsym->got_offset(GOT_TYPE_STANDARD);
-	}
+	value = gsym->got_offset(GOT_TYPE_STANDARD, addend);
       else
-	{
-	  gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
-	  value = object->local_got_offset(r_sym, GOT_TYPE_STANDARD);
-	}
+	value = object->local_got_offset(r_sym, GOT_TYPE_STANDARD, addend);
       if (r_type == elfcpp::R_PPC64_GOT_PCREL34)
 	value += target->got_section()->address();
       else
@@ -10764,16 +10779,11 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
 	got_type = GOT_TYPE_TPREL;
       if (got_type != GOT_TYPE_STANDARD)
 	{
+	  uint64_t addend = size == 32 ? 0 : rela.get_r_addend();
 	  if (gsym != NULL)
-	    {
-	      gold_assert(gsym->has_got_offset(got_type));
-	      value = gsym->got_offset(got_type);
-	    }
+	    value = gsym->got_offset(got_type, addend);
 	  else
-	    {
-	      gold_assert(object->local_has_got_offset(r_sym, got_type));
-	      value = object->local_got_offset(r_sym, got_type);
-	    }
+	    value = object->local_got_offset(r_sym, got_type, addend);
 	  if (r_type == elfcpp::R_PPC64_GOT_TLSGD_PCREL34)
 	    value += target->got_section()->address();
 	  else
@@ -10920,16 +10930,11 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
     {
       // Accesses relative to a local dynamic sequence address,
       // no optimisation here.
+      uint64_t addend = size == 32 ? 0 : rela.get_r_addend();
       if (gsym != NULL)
-	{
-	  gold_assert(gsym->has_got_offset(GOT_TYPE_DTPREL));
-	  value = gsym->got_offset(GOT_TYPE_DTPREL);
-	}
+	value = gsym->got_offset(GOT_TYPE_DTPREL, addend);
       else
-	{
-	  gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_DTPREL));
-	  value = object->local_got_offset(r_sym, GOT_TYPE_DTPREL);
-	}
+	value = object->local_got_offset(r_sym, GOT_TYPE_DTPREL, addend);
       if (r_type == elfcpp::R_PPC64_GOT_DTPREL_PCREL34)
 	value += target->got_section()->address();
       else
@@ -10946,16 +10951,11 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
       tls::Tls_optimization tls_type = target->optimize_tls_ie(final);
       if (tls_type == tls::TLSOPT_NONE)
 	{
+	  uint64_t addend = size == 32 ? 0 : rela.get_r_addend();
 	  if (gsym != NULL)
-	    {
-	      gold_assert(gsym->has_got_offset(GOT_TYPE_TPREL));
-	      value = gsym->got_offset(GOT_TYPE_TPREL);
-	    }
+	    value = gsym->got_offset(GOT_TYPE_TPREL, addend);
 	  else
-	    {
-	      gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_TPREL));
-	      value = object->local_got_offset(r_sym, GOT_TYPE_TPREL);
-	    }
+	    value = object->local_got_offset(r_sym, GOT_TYPE_TPREL, addend);
 	  if (r_type == elfcpp::R_PPC64_GOT_TPREL_PCREL34)
 	    value += target->got_section()->address();
 	  else

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [GOLD] Got_offset_list: addend field
  2021-09-02  3:28 [GOLD] Got_offset_list: addend field Alan Modra
                   ` (4 preceding siblings ...)
  2021-09-02  3:33 ` [GOLD] PowerPC64 support for sym+addend GOT entries Alan Modra
@ 2021-09-03  1:13 ` Cary Coutant
  2021-09-03  3:22   ` Alan Modra
  5 siblings, 1 reply; 9+ messages in thread
From: Cary Coutant @ 2021-09-03  1:13 UTC (permalink / raw)
  To: Alan Modra; +Cc: Binutils

> This is the first in a series of patches aimed at supporting GOT
> entries against symbol plus addend generally for PowerPC64 rather than
> just section symbol plus addend as gold has currently.
>
> This patch adds an addend field to Got_offset_list, so that both local
> and global symbols can have GOT entries with addend.  Note the FIXME
> in incremental.cc, which will need attention if powerpc is to ever
> support incremental linking.

Do you think you'd ever want incremental linking on powerpc? Frankly,
the effort for just the one target platform was pretty high, the
maintenance on it is burdensome, and I'm tempted to deprecate it and
rip it out at some point in the future.

> As per the recommendation in
> https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-default-args
> the changes to symtab.h Symbol methods could be done with what looks
> like a good use of default arguments but they seem to be against the
> gold maintainers' coding practice.  So instead we get more overloads.

For the record, I've got nothing against default parameter values, as
long as they're obvious default values that shouldn't ever need to be
changed. I'm not sure what Ian's position was, but he did use a
default parameter value in at least one place (Descriptors::open in
descriptors.h). I wouldn't be surprised to find places where I
probably should have used a default parameter value instead of an
overload.

> Tested with a power10 gcc-11 bootstrap and regression test where
> ld.gold was the default linker.  The series cures an enormous number
> of testsuite failures (4656) without introducing regressions other
> than some in the guality testsuite.
>
>         PR 28192
>         * object.h (Got_offset_list): Add addend_ field, init in both
>         constructors.  Adjust all accessors to suit.
>         (Sized_relobj::do_local_has_got_offset): Adjust to suit.
>         (Sized_relobj::do_local_got_offset): Likewise.
>         (Sized_relobj::do_set_local_got_offset): Likewise.
>         * symtab.h (Symbol::has_got_offset): New overload with addend
>         param.  Make old overload call this one.
>         (Symbol::got_offset, Symbol::set_got_offset): Likewise.
>         * incremental.cc (Local_got_offset_visitor::visit): Add unused
>         uint64_t parameter with FIXME.
>         (Global_got_offset_visitor::visit): Add unused uint64_t parameter.

OK, with or without your suggestion to use a default parameter value
for has_got_offset.

Thanks!

-cary

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [GOLD] Got_offset_list: addend field
  2021-09-03  1:13 ` [GOLD] Got_offset_list: addend field Cary Coutant
@ 2021-09-03  3:22   ` Alan Modra
  2021-09-03 18:24     ` Cary Coutant
  0 siblings, 1 reply; 9+ messages in thread
From: Alan Modra @ 2021-09-03  3:22 UTC (permalink / raw)
  To: Cary Coutant; +Cc: Binutils

On Thu, Sep 02, 2021 at 06:13:57PM -0700, Cary Coutant wrote:
> > This is the first in a series of patches aimed at supporting GOT
> > entries against symbol plus addend generally for PowerPC64 rather than
> > just section symbol plus addend as gold has currently.
> >
> > This patch adds an addend field to Got_offset_list, so that both local
> > and global symbols can have GOT entries with addend.  Note the FIXME
> > in incremental.cc, which will need attention if powerpc is to ever
> > support incremental linking.
> 
> Do you think you'd ever want incremental linking on powerpc?

No, I don't think so.  And I'll argue against it if someone tries to
talk me into implementing it.  :-)

> Frankly,
> the effort for just the one target platform was pretty high, the
> maintenance on it is burdensome, and I'm tempted to deprecate it and
> rip it out at some point in the future.
> 
> > As per the recommendation in
> > https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-default-args
> > the changes to symtab.h Symbol methods could be done with what looks
> > like a good use of default arguments but they seem to be against the
> > gold maintainers' coding practice.  So instead we get more overloads.
> 
> For the record, I've got nothing against default parameter values, as
> long as they're obvious default values that shouldn't ever need to be
> changed. I'm not sure what Ian's position was,

There's this:
https://sourceware.org/pipermail/binutils/2010-October/069026.html

> but he did use a
> default parameter value in at least one place (Descriptors::open in
> descriptors.h).

Heh.

> OK, with or without your suggestion to use a default parameter value
> for has_got_offset.

Thanks.  I wrote the patch initially with default parameter values so
it will be easy to go back to that.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [GOLD] Got_offset_list: addend field
  2021-09-03  3:22   ` Alan Modra
@ 2021-09-03 18:24     ` Cary Coutant
  0 siblings, 0 replies; 9+ messages in thread
From: Cary Coutant @ 2021-09-03 18:24 UTC (permalink / raw)
  To: Alan Modra; +Cc: Binutils

> > > As per the recommendation in
> > > https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-default-args
> > > the changes to symtab.h Symbol methods could be done with what looks
> > > like a good use of default arguments but they seem to be against the
> > > gold maintainers' coding practice.  So instead we get more overloads.
> >
> > For the record, I've got nothing against default parameter values, as
> > long as they're obvious default values that shouldn't ever need to be
> > changed. I'm not sure what Ian's position was,
>
> There's this:
> https://sourceware.org/pipermail/binutils/2010-October/069026.html

Ah, good find!

I think I'd take exception to that, as introducing a new version of
the function with the same name is exactly what adding an overload
does.

-cary

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2021-09-03 18:24 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-02  3:28 [GOLD] Got_offset_list: addend field Alan Modra
2021-09-02  3:29 ` [GOLD] Remove addend from Local_got_entry_key Alan Modra
2021-09-02  3:30 ` [GOLD] Output_data_got tidy Alan Modra
2021-09-02  3:31 ` [GOLD] Output_data_got create entry method addends Alan Modra
2021-09-02  3:32 ` [GOLD] Got_entry::write addends Alan Modra
2021-09-02  3:33 ` [GOLD] PowerPC64 support for sym+addend GOT entries Alan Modra
2021-09-03  1:13 ` [GOLD] Got_offset_list: addend field Cary Coutant
2021-09-03  3:22   ` Alan Modra
2021-09-03 18:24     ` Cary Coutant

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).