diff options
author | Vladimir Radosavljevic <Vladimir.Radosavljevic@imgtec.com> | 2015-12-03 15:29:17 -0800 |
---|---|---|
committer | Cary Coutant <ccoutant@gmail.com> | 2015-12-03 15:29:17 -0800 |
commit | 7ef8ae7c5f352bb1ef166af0fe6a09a3d3b39f67 (patch) | |
tree | 26bf34449c9d504a4b6dfcf872eafa655ef80a92 /gold/object.h | |
parent | e58c48b4c81f25ec08174f324990d021aad0e96e (diff) | |
download | gdb-7ef8ae7c5f352bb1ef166af0fe6a09a3d3b39f67.zip gdb-7ef8ae7c5f352bb1ef166af0fe6a09a3d3b39f67.tar.gz gdb-7ef8ae7c5f352bb1ef166af0fe6a09a3d3b39f67.tar.bz2 |
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.
Diffstat (limited to 'gold/object.h')
-rw-r--r-- | gold/object.h | 126 |
1 files changed, 104 insertions, 22 deletions
diff --git a/gold/object.h b/gold/object.h index f796fb5..c2bef90 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 |