This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH v2 1/4] gold: Take addend into account for calculating value of the local symbol for GOT.


Hash algorithm for Local_got_entry_key is the same as in Merge_section_properties.

Regards,
Vladimir.

Changelog -

        * object.cc (Sized_relobj::do_for_all_local_got_entries): Use Local_got_entry_key for searching in local_got_offsets_.
	* object.h (class Local_got_entry_key): New class.
        (Relobj::local_has_got_offset): New overloaded method.
	(Relobj::local_got_offset): Likewise.
	(Relobj::set_local_got_offset): Likewise.
        (Relobj::do_local_has_got_offset): Add addend argument.
	(Relobj::do_local_got_offset): Likewise.
	(Relobj::do_set_local_got_offset): Likewise.
	(Sized_relobj::do_local_has_got_offset): Add addend argument, and use Local_got_entry_key for searching through local_got_offsets_.
	(Sized_relobj::do_local_got_offset): Likewise.
	(Sized_relobj::do_set_local_got_offset): Likewise.
        (Sized_relobj::Local_got_offsets): Change type of the key from unsigned int to Local_got_entry_key, and add hash and equal_to.
	* output.cc (Got_entry::write): Take addend into account for calculating value of the local symbol for GOT.
	(Output_data_got::add_local): New definition of overloaded method.
	(Output_data_got::add_local_with_rel): Likewise.
	(Output_data_got::add_local_pair_with_rel): Likewise.
	* output.h (Output_data_got::add_local): New declaration of overloaded method.
	(Output_data_got::add_local_with_rel): Likewise.
	(Output_data_got::add_local_pair_with_rel): Likewise.
	(class Got_entry): Add new constructor.
	(Got_entry::addend_): New member.
diff --git a/gold/object.cc b/gold/object.cc
index 76d4630..8d50f50 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -427,7 +427,8 @@ 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_offsets::const_iterator p = this->local_got_offsets_.find(i);
+      Local_got_entry_key key(i, 0);
+      Local_got_offsets::const_iterator p = this->local_got_offsets_.find(key);
       if (p != this->local_got_offsets_.end())
 	{
 	  const Got_offset_list* got_offsets = p->second;
diff --git a/gold/object.h b/gold/object.h
index f796fb5..35fae4f 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -315,6 +315,57 @@ class Got_offset_list
   Got_offset_list* got_next_;
 };
 
+// The Local_got_entry_key used to index the GOT offsets for local
+// non-TLS symbols, and tp-relative offsets for TLS symbols.
+class Local_got_entry_key
+{
+ public:
+  Local_got_entry_key(unsigned int symndx, uint64_t addend)
+    : symndx_(symndx), addend_(addend)
+  {}
+
+  // 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_));
+  }
+
+  // Compute a hash value for this using 64-bit FNV-1a hash.
+  size_t
+  hash_value() const
+  {
+    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;
+  }
+
+  // Functors for associative containers.
+  struct equal_to
+  {
+    bool
+    operator()(const Local_got_entry_key& key1,
+               const Local_got_entry_key& key2) const
+    { return key1.eq(key2); }
+  };
+
+  struct hash
+  {
+    size_t
+    operator()(const Local_got_entry_key& key) const
+    { return key.hash_value(); }
+  };
+
+ private:
+  // The local symbol index.
+  unsigned int symndx_;
+  // The addend.
+  uint64_t addend_;
+};
+
 // Type for mapping section index to uncompressed size and contents.
 
 struct Compressed_section_info
@@ -1111,21 +1162,43 @@ class Relobj : public Object
   // 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); }
+  { 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.
+  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); }
+  { return this->do_local_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.
+  unsigned int
+  local_got_offset(unsigned int symndx, unsigned int got_type,
+		       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); }
+  { this->do_set_local_got_offset(symndx, got_type, got_offset, 0); }
+
+  // Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX
+  // plus ADDEND to GOT_OFFSET.
+  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); }
 
   // Return whether the local symbol SYMNDX is a TLS symbol.
   bool
@@ -1318,19 +1391,21 @@ class Relobj : public Object
   virtual unsigned int
   do_local_plt_offset(unsigned int symndx) const = 0;
 
-  // Return whether a local symbol has a GOT offset of a given type.
+  // Return whether a local symbol plus addend has a GOT offset
+  // of a given type.
   virtual bool
   do_local_has_got_offset(unsigned int symndx,
-			  unsigned int got_type) const = 0;
+			  unsigned int got_type, uint64_t addend) const = 0;
 
-  // Return the GOT offset of a given type of a local symbol.
+  // Return the GOT offset of a given type of a local symbol plus addend.
   virtual unsigned int
-  do_local_got_offset(unsigned int symndx, unsigned int got_type) const = 0;
+  do_local_got_offset(unsigned int symndx, unsigned int got_type,
+			  uint64_t addend) const = 0;
 
-  // Set the GOT offset with a given type for a local symbol.
+  // Set the GOT offset with a given type for a local symbol plus addend.
   virtual void
   do_set_local_got_offset(unsigned int symndx, unsigned int got_type,
-			  unsigned int got_offset) = 0;
+			  unsigned int got_offset, uint64_t addend) = 0;
 
   // Return whether local symbol SYMNDX is a TLS symbol.
   virtual bool
@@ -1993,24 +2068,28 @@ class Sized_relobj : public Relobj
        : convert_types<Address, uint64_t>(off));
   }
 
-  // Return whether the local symbol SYMNDX has a GOT offset of type
-  // GOT_TYPE.
+  // Return whether the local symbol SYMNDX plus ADDEND has a GOT offset
+  // of type GOT_TYPE.
   bool
-  do_local_has_got_offset(unsigned int symndx, unsigned int got_type) const
+  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_offsets::const_iterator p =
-        this->local_got_offsets_.find(symndx);
+        this->local_got_offsets_.find(key);
     return (p != this->local_got_offsets_.end()
             && p->second->get_offset(got_type) != -1U);
   }
 
   // Return the GOT offset of type GOT_TYPE of the local symbol
-  // SYMNDX.
+  // SYMNDX plus ADDEND.
   unsigned int
-  do_local_got_offset(unsigned int symndx, unsigned int got_type) const
+  do_local_got_offset(unsigned int symndx, unsigned int got_type,
+			  uint64_t addend) const
   {
+    Local_got_entry_key key(symndx, addend);
     Local_got_offsets::const_iterator p =
-        this->local_got_offsets_.find(symndx);
+        this->local_got_offsets_.find(key);
     gold_assert(p != this->local_got_offsets_.end());
     unsigned int off = p->second->get_offset(got_type);
     gold_assert(off != -1U);
@@ -2018,20 +2097,21 @@ class Sized_relobj : public Relobj
   }
 
   // Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX
-  // to GOT_OFFSET.
+  // plus ADDEND to GOT_OFFSET.
   void
   do_set_local_got_offset(unsigned int symndx, unsigned int got_type,
-			  unsigned int got_offset)
+			  unsigned int got_offset, uint64_t addend)
   {
+    Local_got_entry_key key(symndx, addend);
     Local_got_offsets::const_iterator p =
-        this->local_got_offsets_.find(symndx);
+        this->local_got_offsets_.find(key);
     if (p != this->local_got_offsets_.end())
       p->second->set_offset(got_type, got_offset);
     else
       {
         Got_offset_list* g = new Got_offset_list(got_type, got_offset);
         std::pair<Local_got_offsets::iterator, bool> ins =
-            this->local_got_offsets_.insert(std::make_pair(symndx, g));
+            this->local_got_offsets_.insert(std::make_pair(key, g));
         gold_assert(ins.second);
       }
   }
@@ -2049,10 +2129,12 @@ class Sized_relobj : public Relobj
  private:
   // The GOT offsets of local symbols. This map also stores GOT offsets
   // for tp-relative offsets for TLS symbols.
-  typedef Unordered_map<unsigned int, Got_offset_list*> Local_got_offsets;
+  typedef Unordered_map<Local_got_entry_key, Got_offset_list*,
+                        Local_got_entry_key::hash,
+                        Local_got_entry_key::equal_to> Local_got_offsets;
 
   // GOT offsets for local non-TLS symbols, and tp-relative offsets
-  // for TLS symbols, indexed by symbol number.
+  // for TLS symbols, indexed by local got entry key class.
   Local_got_offsets local_got_offsets_;
   // For each input section, the offset of the input section in its
   // output section.  This is INVALID_ADDRESS if the input section requires a
diff --git a/gold/output.cc b/gold/output.cc
index 5cc3629..5bcb6f3 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -1437,7 +1437,7 @@ Output_data_got<got_size, big_endian>::Got_entry::write(
 	  val = parameters->target().plt_address_for_local(object, lsi);
 	else
 	  {
-	    uint64_t lval = object->local_symbol_value(lsi, 0);
+	    uint64_t lval = object->local_symbol_value(lsi, addend_);
 	    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,
@@ -1548,6 +1548,27 @@ Output_data_got<got_size, big_endian>::add_local(
   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.
+
+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,
+    uint64_t addend)
+{
+  if (object->local_has_got_offset(symndx, got_type, addend))
+    return false;
+
+  unsigned int got_offset = this->add_got_entry(Got_entry(object, symndx,
+							  false, addend));
+  object->set_local_got_offset(symndx, got_type, got_offset, addend);
+  return true;
+}
+
 // Like add_local, but use the PLT offset.
 
 template<int got_size, bool big_endian>
@@ -1586,6 +1607,27 @@ Output_data_got<got_size, big_endian>::add_local_with_rel(
   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.
+
+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, uint64_t addend)
+{
+  if (object->local_has_got_offset(symndx, got_type, addend))
+    return;
+
+  unsigned int got_offset = this->add_got_entry(Got_entry());
+  object->set_local_got_offset(symndx, got_type, got_offset, addend);
+  rel_dyn->add_local_generic(object, symndx, r_type, this, got_offset,
+                             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.
@@ -1612,6 +1654,32 @@ Output_data_got<got_size, big_endian>::add_local_pair_with_rel(
   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.
+// 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, uint64_t addend)
+{
+  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, false, addend));
+  object->set_local_got_offset(symndx, got_type, got_offset, addend);
+  Output_section* os = object->output_section(shndx);
+  rel_dyn->add_output_section_generic(os, r_type, this, got_offset, addend);
+}
+
 // 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
diff --git a/gold/output.h b/gold/output.h
index c7ad54e..5b8c01c 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -2335,6 +2335,13 @@ class Output_data_got : public Output_data_got_base
   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.
+  bool
+  add_local(Relobj* object, unsigned int sym_index, unsigned int got_type,
+            uint64_t addend);
+
   // Like add_local, but use the PLT offset of the local symbol if it
   // has one.
   bool
@@ -2353,6 +2360,13 @@ class Output_data_got : public Output_data_got_base
 		     unsigned int got_type, Output_data_reloc_generic* rel_dyn,
 		     unsigned int r_type);
 
+  // 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);
+
   // 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.
@@ -2364,6 +2378,17 @@ class Output_data_got : public Output_data_got_base
 			  Output_data_reloc_generic* rel_dyn,
 			  unsigned int r_type);
 
+  // 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);
+
   // 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
@@ -2434,20 +2459,21 @@ class Output_data_got : public Output_data_got_base
    public:
     // Create a zero entry.
     Got_entry()
-      : local_sym_index_(RESERVED_CODE), use_plt_or_tls_offset_(false)
+      : local_sym_index_(RESERVED_CODE), use_plt_or_tls_offset_(false),
+	addend_(0)
     { this->u_.constant = 0; }
 
     // Create a global symbol entry.
     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)
+	use_plt_or_tls_offset_(use_plt_or_tls_offset), addend_(0)
     { this->u_.gsym = gsym; }
 
     // Create a local symbol entry.
     Got_entry(Relobj* object, unsigned int local_sym_index,
 	      bool use_plt_or_tls_offset)
       : local_sym_index_(local_sym_index),
-	use_plt_or_tls_offset_(use_plt_or_tls_offset)
+	use_plt_or_tls_offset_(use_plt_or_tls_offset), addend_(0)
     {
       gold_assert(local_sym_index != GSYM_CODE
 		  && local_sym_index != CONSTANT_CODE
@@ -2456,6 +2482,19 @@ 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)
@@ -2489,6 +2528,8 @@ class Output_data_got : public Output_data_got_base
     // Whether to use the PLT offset of the symbol if it has one.
     // For TLS symbols, whether to offset the symbol value.
     bool use_plt_or_tls_offset_ : 1;
+    // The addend.
+    uint64_t addend_;
   };
 
   typedef std::vector<Got_entry> Got_entries;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]