This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH 3/6] gold: Take addend into account for calculating value of the local symbol for GOT.
- From: Vladimir Radosavljevic <Vladimir dot Radosavljevic at imgtec dot com>
- To: "binutils at sourceware dot org" <binutils at sourceware dot org>
- Date: Tue, 3 Nov 2015 16:20:50 +0000
- Subject: [PATCH 3/6] gold: Take addend into account for calculating value of the local symbol for GOT.
- Authentication-results: sourceware.org; auth=none
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;