diff options
author | Vladimir Radosavljevic <vladimir.radosavljevic@imgtec.com> | 2016-05-19 14:57:14 -0700 |
---|---|---|
committer | Cary Coutant <ccoutant@gmail.com> | 2016-05-19 15:04:51 -0700 |
commit | 15eb1bebe1525ba8baf1f56e9df791cff146a352 (patch) | |
tree | 1f0d08b062d9c808eac9d5fb63204cb8b4b2eaa2 /gold/mips.cc | |
parent | 7d4d970973c4735dcdd2a69d645309f167a1d9d4 (diff) | |
download | gdb-15eb1bebe1525ba8baf1f56e9df791cff146a352.zip gdb-15eb1bebe1525ba8baf1f56e9df791cff146a352.tar.gz gdb-15eb1bebe1525ba8baf1f56e9df791cff146a352.tar.bz2 |
Fix non-deterministic behavior when generating MIPS GOT.
* mips.cc (Mips_got_entry::Mips_got_entry): Remove object argument
for global got symbols, and set addend to 0.
(Mips_got_entry::hash): Change hash algorithm.
(Mips_got_entry::equals): Refactor.
(Mips_got_entry::object): Return input object for local got symbols
from union d.
(Mips_got_entry::addend): Change return of the relocation addend.
(Mips_got_entry::addend_): Move from union d.
(Mips_got_entry::object_): Move into union d.
(class Mips_symbol_hash): New class.
(Mips_got_info::Global_got_entry_set): New type.
(Mips_got_info::global_got_symbols): Change return type to
Global_got_entry_set.
(Mips_got_info::global_got_symbols_): Change type to
Global_got_entry_set.
(Mips_symbol::hash): New method.
(Mips_output_data_la25_stub::symbols_): Change type to std::vector.
(Mips_output_data_mips_stubs::Mips_stubs_entry_set): New type.
(Mips_output_data_mips_stubs::symbols_): Change type to
Mips_stubs_entry_set.
(Mips_got_info::record_global_got_symbol): Don't pass object
argument when creating global got symbol.
(Mips_got_info::record_got_entry): Remove find before inserting
got entries.
(Mips_got_info::add_reloc_only_entries): Change type of iterator
to Global_got_entry_set.
(Mips_got_info::count_got_symbols): Likewise.
(Mips_output_data_la25_stub::create_la25_stub): Use push_back
for adding entries to symbols_.
(Mips_output_data_la25_stub::do_write): Change type of iterator
to std::vector.
(Mips_output_data_mips_stubs::set_lazy_stub_offsets): Change type
of iterator to Mips_stubs_entry_set.
(Mips_output_data_mips_stubs::set_needs_dynsym_value): Likewise.
(Mips_output_data_mips_stubs::do_write): Likewise.
Diffstat (limited to 'gold/mips.cc')
-rw-r--r-- | gold/mips.cc | 120 |
1 files changed, 68 insertions, 52 deletions
diff --git a/gold/mips.cc b/gold/mips.cc index ffaad45..e622e29 100644 --- a/gold/mips.cc +++ b/gold/mips.cc @@ -420,8 +420,8 @@ is_matching_lo16_reloc(unsigned int high_reloc, unsigned int lo16_reloc) // (1) a SYMBOL + OFFSET address, where SYMBOL is local to an input object // (object != NULL, symndx >= 0, tls_type != GOT_TLS_LDM) // (2) a SYMBOL address, where SYMBOL is not local to an input object -// (object != NULL, symndx == -1) -// (3) a TLS LDM slot +// (sym != NULL, symndx == -1) +// (3) a TLS LDM slot (there's only one of these per GOT.) // (object != NULL, symndx == 0, tls_type == GOT_TLS_LDM) template<int size, bool big_endian> @@ -433,13 +433,12 @@ class Mips_got_entry Mips_got_entry(Mips_relobj<size, big_endian>* object, unsigned int symndx, Mips_address addend, unsigned char tls_type, unsigned int shndx, bool is_section_symbol) - : object_(object), symndx_(symndx), tls_type_(tls_type), + : addend_(addend), symndx_(symndx), tls_type_(tls_type), is_section_symbol_(is_section_symbol), shndx_(shndx) - { this->d.addend = addend; } + { this->d.object = object; } - Mips_got_entry(Mips_relobj<size, big_endian>* object, Mips_symbol<size>* sym, - unsigned char tls_type) - : object_(object), symndx_(-1U), tls_type_(tls_type), + Mips_got_entry(Mips_symbol<size>* sym, unsigned char tls_type) + : addend_(0), symndx_(-1U), tls_type_(tls_type), is_section_symbol_(false), shndx_(-1U) { this->d.sym = sym; } @@ -459,40 +458,36 @@ class Mips_got_entry { if (this->tls_type_ == GOT_TLS_LDM) return this->symndx_ + (1 << 18); - if (this->symndx_ != -1U) - { - uintptr_t object_id = reinterpret_cast<uintptr_t>(this->object()); - return this->symndx_ + object_id + this->d.addend; - } - else - { - uintptr_t sym_id = reinterpret_cast<uintptr_t>(this->d.sym); - return this->symndx_ + sym_id; - } + + size_t name_hash_value = gold::string_hash<char>( + (this->symndx_ != -1U) + ? this->d.object->name().c_str() + : this->d.sym->name()); + size_t addend = this->addend_; + return name_hash_value ^ this->symndx_ ^ addend; } // Return whether this entry is equal to OTHER. bool equals(Mips_got_entry<size, big_endian>* other) const { - if (this->symndx_ != other->symndx_ - || this->tls_type_ != other->tls_type_) - return false; if (this->tls_type_ == GOT_TLS_LDM) return true; - if (this->symndx_ != -1U) - return (this->object() == other->object() - && this->d.addend == other->d.addend); - else - return this->d.sym == other->d.sym; + + return ((this->tls_type_ == other->tls_type_) + && (this->symndx_ == other->symndx_) + && ((this->symndx_ != -1U) + ? (this->d.object == other->d.object) + : (this->d.sym == other->d.sym)) + && (this->addend_ == other->addend_)); } // Return input object that needs this GOT entry. Mips_relobj<size, big_endian>* object() const { - gold_assert(this->object_ != NULL); - return this->object_; + gold_assert(this->symndx_ != -1U); + return this->d.object; } // Return local symbol index for local GOT entries. @@ -506,10 +501,7 @@ class Mips_got_entry // Return the relocation addend for local GOT entries. Mips_address addend() const - { - gold_assert(this->symndx_ != -1U); - return this->d.addend; - } + { return this->addend_; } // Return global symbol for global GOT entries. Mips_symbol<size>* @@ -540,16 +532,16 @@ class Mips_got_entry { return this->is_section_symbol_; } private: - // The input object that needs the GOT entry. - Mips_relobj<size, big_endian>* object_; + // The addend. + Mips_address addend_; + // The index of the symbol if we have a local symbol; -1 otherwise. unsigned int symndx_; union { - // If symndx != -1, the addend of the relocation that should be added to the - // symbol value. - Mips_address addend; + // The input object for local symbols that needs the GOT entry. + Mips_relobj<size, big_endian>* object; // If symndx == -1, the global symbol corresponding to this GOT entry. The // symbol's entry is in the local area if mips_sym->global_got_area is // GGA_NONE, otherwise it is in the global area. @@ -590,6 +582,17 @@ class Mips_got_entry_eq { return e1->equals(e2); } }; +// Hash for Mips_symbol. + +template<int size> +class Mips_symbol_hash +{ + public: + size_t + operator()(Mips_symbol<size>* sym) const + { return sym->hash(); } +}; + // Got_page_range. This class describes a range of addends: [MIN_ADDEND, // MAX_ADDEND]. The instances form a non-overlapping list that is sorted by // increasing MIN_ADDEND. @@ -672,6 +675,10 @@ class Mips_got_info typedef Unordered_set<Got_page_entry*, Got_page_entry_hash, Got_page_entry_eq> Got_page_entry_set; + // Unordered set of global GOT entries. + typedef Unordered_set<Mips_symbol<size>*, Mips_symbol_hash<size> > + Global_got_entry_set; + public: Mips_got_info() : local_gotno_(0), page_gotno_(0), global_gotno_(0), reloc_only_gotno_(0), @@ -851,7 +858,7 @@ class Mips_got_info set_tls_ldm_offset(unsigned int tls_ldm_offset) { this->tls_ldm_offset_ = tls_ldm_offset; } - Unordered_set<Mips_symbol<size>*>& + Global_got_entry_set& global_got_symbols() { return this->global_got_symbols_; } @@ -906,7 +913,7 @@ class Mips_got_info // The offset of TLS LDM entry for this GOT. unsigned int tls_ldm_offset_; // All symbols that have global GOT entry. - Unordered_set<Mips_symbol<size>*> global_got_symbols_; + Global_got_entry_set global_got_symbols_; // A hash table holding GOT entries. Got_entry_set got_entries_; // A hash table of GOT page entries. @@ -1284,6 +1291,13 @@ class Mips_symbol : public Sized_symbol<size> set_applied_secondary_got_fixup() { this->applied_secondary_got_fixup_ = true; } + // Return the hash of this symbol. + size_t + hash() const + { + return gold::string_hash<char>(this->name()); + } + private: // Whether the symbol needs MIPS16 fn_stub. This is true if this symbol // appears in any relocs other than a 16 bit call. @@ -2302,7 +2316,7 @@ class Mips_output_data_la25_stub : public Output_section_data do_write(Output_file*); // Symbols that have LA25 stubs. - Unordered_set<Mips_symbol<size>*> symbols_; + std::vector<Mips_symbol<size>*> symbols_; }; // MIPS-specific relocation writer. @@ -2577,6 +2591,10 @@ class Mips_output_data_mips_stubs : public Output_section_data { typedef typename elfcpp::Elf_types<size>::Elf_Addr Mips_address; + // Unordered set of .MIPS.stubs entries. + typedef Unordered_set<Mips_symbol<size>*, Mips_symbol_hash<size> > + Mips_stubs_entry_set; + public: Mips_output_data_mips_stubs(Target_mips<size, big_endian>* target) : Output_section_data(size == 32 ? 4 : 8), symbols_(), dynsym_count_(-1U), @@ -2683,7 +2701,7 @@ class Mips_output_data_mips_stubs : public Output_section_data do_write(Output_file*); // .MIPS.stubs symbols - Unordered_set<Mips_symbol<size>*> symbols_; + Mips_stubs_entry_set symbols_; // Number of entries in dynamic symbol table. unsigned int dynsym_count_; // Whether the stub offsets are set. @@ -5277,7 +5295,7 @@ Mips_got_info<size, big_endian>::record_global_got_symbol( } Mips_got_entry<size, big_endian>* entry = - new Mips_got_entry<size, big_endian>(object, mips_sym, tls_type); + new Mips_got_entry<size, big_endian>(mips_sym, tls_type); this->record_got_entry(entry, object); } @@ -5290,16 +5308,14 @@ Mips_got_info<size, big_endian>::record_got_entry( Mips_got_entry<size, big_endian>* entry, Mips_relobj<size, big_endian>* object) { - if (this->got_entries_.find(entry) == this->got_entries_.end()) - this->got_entries_.insert(entry); + this->got_entries_.insert(entry); // Create the GOT entry for the OBJECT's GOT. Mips_got_info<size, big_endian>* g = object->get_or_create_got_info(); Mips_got_entry<size, big_endian>* entry2 = new Mips_got_entry<size, big_endian>(*entry); - if (g->got_entries_.find(entry2) == g->got_entries_.end()) - g->got_entries_.insert(entry2); + g->got_entries_.insert(entry2); } // Record that OBJECT has a page relocation against symbol SYMNDX and @@ -5573,7 +5589,7 @@ void Mips_got_info<size, big_endian>::add_reloc_only_entries( Mips_output_data_got<size, big_endian>* got) { - for (typename Unordered_set<Mips_symbol<size>*>::iterator + for (typename Global_got_entry_set::iterator p = this->global_got_symbols_.begin(); p != this->global_got_symbols_.end(); ++p) @@ -5757,7 +5773,7 @@ template<int size, bool big_endian> void Mips_got_info<size, big_endian>::count_got_symbols(Symbol_table* symtab) { - for (typename Unordered_set<Mips_symbol<size>*>::iterator + for (typename Global_got_entry_set::iterator p = this->global_got_symbols_.begin(); p != this->global_got_symbols_.end(); ++p) @@ -6635,7 +6651,7 @@ Mips_output_data_la25_stub<size, big_endian>::create_la25_stub( if (!gsym->has_la25_stub()) { gsym->set_la25_stub_offset(this->symbols_.size() * 16); - this->symbols_.insert(gsym); + this->symbols_.push_back(gsym); this->create_stub_symbol(gsym, symtab, target, 16); } } @@ -6679,7 +6695,7 @@ Mips_output_data_la25_stub<size, big_endian>::do_write(Output_file* of) convert_to_section_size_type(this->data_size()); unsigned char* const oview = of->get_output_view(offset, oview_size); - for (typename Unordered_set<Mips_symbol<size>*>::iterator + for (typename std::vector<Mips_symbol<size>*>::iterator p = this->symbols_.begin(); p != this->symbols_.end(); ++p) @@ -7478,7 +7494,7 @@ Mips_output_data_mips_stubs<size, big_endian>::set_lazy_stub_offsets() unsigned int stub_size = this->stub_size(); unsigned int offset = 0; - for (typename Unordered_set<Mips_symbol<size>*>::const_iterator + for (typename Mips_stubs_entry_set::const_iterator p = this->symbols_.begin(); p != this->symbols_.end(); ++p, offset += stub_size) @@ -7493,7 +7509,7 @@ template<int size, bool big_endian> void Mips_output_data_mips_stubs<size, big_endian>::set_needs_dynsym_value() { - for (typename Unordered_set<Mips_symbol<size>*>::const_iterator + for (typename Mips_stubs_entry_set::const_iterator p = this->symbols_.begin(); p != this->symbols_.end(); ++p) { Mips_symbol<size>* sym = *p; @@ -7517,7 +7533,7 @@ Mips_output_data_mips_stubs<size, big_endian>::do_write(Output_file* of) bool big_stub = this->dynsym_count_ > 0x10000; unsigned char* pov = oview; - for (typename Unordered_set<Mips_symbol<size>*>::const_iterator + for (typename Mips_stubs_entry_set::const_iterator p = this->symbols_.begin(); p != this->symbols_.end(); ++p) { Mips_symbol<size>* sym = *p; |