Take addend into account when making GOT entries for local symbols.
gold/ * 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.
This commit is contained in:
parent
e58c48b4c8
commit
7ef8ae7c5f
@ -1,3 +1,28 @@
|
||||
2015-12-03 Vladimir Radosavljevic <Vladimir.Radosavljevic@imgtec.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2015-11-25 Cary Coutant <ccoutant@gmail.com>
|
||||
|
||||
PR gold/19291
|
||||
|
@ -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;
|
||||
|
126
gold/object.h
126
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
|
||||
|
@ -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, this->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
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user