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 3/6] gold: Take addend into account for calculating value of the local symbol for GOT.


Regards,
Vladimir

Changelog -

	* object.h (Relobj::local_has_got_offset): New overloaded function.
	(Relobj::local_got_offset): Likewise.
	(Relobj::set_local_got_offset): Likewise.
    (Relobj::do_local_has_got_offset): Likewise.
	(Relobj::do_local_got_offset): Likewise.
	(Relobj::do_set_local_got_offset): Likewise.
	(Sized_relobj::do_local_has_got_offset): Likewise.
	(Sized_relobj::do_local_got_offset): Likewise.
	(Sized_relobj::do_set_local_got_offset): Likewise.
	* 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 function.
	(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 function.
	(Output_data_got::add_local_with_rel): Likewise.
	(Output_data_got::add_local_pair_with_rel): Likewise.
	(Output_reloc<SHT_REL>::get_address): Change from private to public.
	(Output_reloc<SHT_REL>::get_symbol_index): Likewise.
	(Output_data_reloc_base::add): Make virtual.
	(class Got_entry): Add new constructor.
	(Got_entry::addend_): New member.

Patch - 

 object.h  |   57 +++++++++++++++++++++++++++++++++++++++++++++++++
 output.cc |   72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 output.h  |   59 +++++++++++++++++++++++++++++++++++++++++++-------
 3 files changed, 177 insertions(+), 11 deletions(-)

diff --git a/gold/object.h b/gold/object.h
index f796fb5..971014c 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -1113,6 +1113,13 @@ class Relobj : public Object
   local_has_got_offset(unsigned int symndx, unsigned int got_type) const
   { return this->do_local_has_got_offset(symndx, got_type); }
 
+  // Return whether the local symbol SYMNDX with 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.
@@ -1120,6 +1127,14 @@ class Relobj : public Object
   local_got_offset(unsigned int symndx, unsigned int got_type) const
   { return this->do_local_got_offset(symndx, got_type); }
 
+  // Return the GOT offset of type GOT_TYPE of the local symbol
+  // SYMNDX with 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
@@ -1127,6 +1142,13 @@ class Relobj : public Object
 		       unsigned int got_offset)
   { this->do_set_local_got_offset(symndx, got_type, got_offset); }
 
+  // Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX
+  // with 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
   local_is_tls(unsigned int symndx) const
@@ -1323,15 +1345,31 @@ class Relobj : public Object
   do_local_has_got_offset(unsigned int symndx,
 			  unsigned int got_type) const = 0;
 
+  // Return whether a local symbol with addend has a GOT offset
+  // of a given type.
+  virtual bool
+  do_local_has_got_offset(unsigned int symndx,
+			  unsigned int got_type, uint64_t addend) const = 0;
+
   // Return the GOT offset of a given type of a local symbol.
   virtual unsigned int
   do_local_got_offset(unsigned int symndx, unsigned int got_type) const = 0;
 
+  // Return the GOT offset of a given type of a local symbol with addend.
+  virtual unsigned int
+  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.
   virtual void
   do_set_local_got_offset(unsigned int symndx, unsigned int got_type,
 			  unsigned int got_offset) = 0;
 
+  // Set the GOT offset with a given type for a local symbol with addend.
+  virtual void
+  do_set_local_got_offset(unsigned int symndx, unsigned int got_type,
+			  unsigned int got_offset, uint64_t addend) = 0;
+
   // Return whether local symbol SYMNDX is a TLS symbol.
   virtual bool
   do_local_is_tls(unsigned int symndx) const = 0;
@@ -2004,6 +2042,12 @@ class Sized_relobj : public Relobj
             && p->second->get_offset(got_type) != -1U);
   }
 
+  // Return whether the local symbol SYMNDX with ADDEND has a GOT offset
+  // of type GOT_TYPE.
+  bool
+  do_local_has_got_offset(unsigned int, unsigned int, uint64_t) const
+  { gold_unreachable(); }
+
   // Return the GOT offset of type GOT_TYPE of the local symbol
   // SYMNDX.
   unsigned int
@@ -2017,6 +2061,12 @@ class Sized_relobj : public Relobj
     return off;
   }
 
+  // Return the GOT offset of type GOT_TYPE of the local symbol
+  // SYMNDX with ADDEND.
+  unsigned int
+  do_local_got_offset(unsigned int, unsigned int, uint64_t) const
+  { gold_unreachable(); }
+
   // Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX
   // to GOT_OFFSET.
   void
@@ -2036,6 +2086,13 @@ class Sized_relobj : public Relobj
       }
   }
 
+  // Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX
+  // with ADDEND to GOT_OFFSET.
+  void
+  do_set_local_got_offset(unsigned int, unsigned int,
+			  unsigned int, uint64_t)
+  { gold_unreachable(); }
+
   // Return the word size of the object file.
   virtual int
   do_elfsize() const
diff --git a/gold/output.cc b/gold/output.cc
index 5cc3629..b8cc613 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 with 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,7 +1607,28 @@ 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 a pair of entries for a local symbol to the GOT, and add
+// Add an entry for a local symbol with 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 with 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
@@ -1613,6 +1655,32 @@ Output_data_got<got_size, big_endian>::add_local_pair_with_rel(
 }
 
 // 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, 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
 // value of the local symbol offset by Target::tls_offset_for_local.
diff --git a/gold/output.h b/gold/output.h
index c7ad54e..343119c 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -1150,11 +1150,6 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
 	      r2) const
   { return this->compare(r2) < 0; }
 
- private:
-  // Record that we need a dynamic symbol index.
-  void
-  set_needs_dynsym_index();
-
   // Return the symbol index.
   unsigned int
   get_symbol_index() const;
@@ -1163,6 +1158,11 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   Address
   get_address() const;
 
+ private:
+  // Record that we need a dynamic symbol index.
+  void
+  set_needs_dynsym_index();
+
   // Codes for local_sym_index_.
   enum
   {
@@ -1502,7 +1502,7 @@ class Output_data_reloc_base : public Output_data_reloc_generic
   }
 
   // Add a relocation entry.
-  void
+  virtual void
   add(Output_data* od, const Output_reloc_type& reloc)
   {
     this->relocs_.push_back(reloc);
@@ -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 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 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.
@@ -2365,6 +2379,17 @@ class Output_data_got : public Output_data_got_base
 			  unsigned int r_type);
 
   // Add a pair of entries for a local symbol to the GOT, and add
+  // 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
   // value of the local symbol offset by Target::tls_offset_for_local.
@@ -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 with 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]