From 15eb1bebe1525ba8baf1f56e9df791cff146a352 Mon Sep 17 00:00:00 2001 From: Vladimir Radosavljevic Date: Thu, 19 May 2016 14:57:14 -0700 Subject: [PATCH] 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. --- gold/ChangeLog | 38 ++++++++++++++++ gold/mips.cc | 120 ++++++++++++++++++++++++++++--------------------- 2 files changed, 106 insertions(+), 52 deletions(-) diff --git a/gold/ChangeLog b/gold/ChangeLog index 0bc160aaa86..6a9b045d11f 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,41 @@ +2016-05-19 Vladimir Radosavljevic + + * 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. + 2016-05-06 Han Shen PR gold/19987. diff --git a/gold/mips.cc b/gold/mips.cc index ffaad453822..e622e2975d8 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 @@ -433,13 +433,12 @@ class Mips_got_entry Mips_got_entry(Mips_relobj* 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* object, Mips_symbol* sym, - unsigned char tls_type) - : object_(object), symndx_(-1U), tls_type_(tls_type), + Mips_got_entry(Mips_symbol* 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(this->object()); - return this->symndx_ + object_id + this->d.addend; - } - else - { - uintptr_t sym_id = reinterpret_cast(this->d.sym); - return this->symndx_ + sym_id; - } + + size_t name_hash_value = gold::string_hash( + (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* 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* 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* @@ -540,16 +532,16 @@ class Mips_got_entry { return this->is_section_symbol_; } private: - // The input object that needs the GOT entry. - Mips_relobj* 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* 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 +class Mips_symbol_hash +{ + public: + size_t + operator()(Mips_symbol* 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_set; + // Unordered set of global GOT entries. + typedef Unordered_set*, Mips_symbol_hash > + 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*>& + 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*> 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 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(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*> symbols_; + std::vector*> symbols_; }; // MIPS-specific relocation writer. @@ -2577,6 +2591,10 @@ class Mips_output_data_mips_stubs : public Output_section_data { typedef typename elfcpp::Elf_types::Elf_Addr Mips_address; + // Unordered set of .MIPS.stubs entries. + typedef Unordered_set*, Mips_symbol_hash > + Mips_stubs_entry_set; + public: Mips_output_data_mips_stubs(Target_mips* 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*> 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::record_global_got_symbol( } Mips_got_entry* entry = - new Mips_got_entry(object, mips_sym, tls_type); + new Mips_got_entry(mips_sym, tls_type); this->record_got_entry(entry, object); } @@ -5290,16 +5308,14 @@ Mips_got_info::record_got_entry( Mips_got_entry* entry, Mips_relobj* 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* g = object->get_or_create_got_info(); Mips_got_entry* entry2 = new Mips_got_entry(*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::add_reloc_only_entries( Mips_output_data_got* got) { - for (typename Unordered_set*>::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 void Mips_got_info::count_got_symbols(Symbol_table* symtab) { - for (typename Unordered_set*>::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::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::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*>::iterator + for (typename std::vector*>::iterator p = this->symbols_.begin(); p != this->symbols_.end(); ++p) @@ -7478,7 +7494,7 @@ Mips_output_data_mips_stubs::set_lazy_stub_offsets() unsigned int stub_size = this->stub_size(); unsigned int offset = 0; - for (typename Unordered_set*>::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 void Mips_output_data_mips_stubs::set_needs_dynsym_value() { - for (typename Unordered_set*>::const_iterator + for (typename Mips_stubs_entry_set::const_iterator p = this->symbols_.begin(); p != this->symbols_.end(); ++p) { Mips_symbol* sym = *p; @@ -7517,7 +7533,7 @@ Mips_output_data_mips_stubs::do_write(Output_file* of) bool big_stub = this->dynsym_count_ > 0x10000; unsigned char* pov = oview; - for (typename Unordered_set*>::const_iterator + for (typename Mips_stubs_entry_set::const_iterator p = this->symbols_.begin(); p != this->symbols_.end(); ++p) { Mips_symbol* sym = *p; -- 2.30.2