diff options
-rw-r--r-- | gold/object.cc | 14 | ||||
-rw-r--r-- | gold/object.h | 70 | ||||
-rw-r--r-- | gold/output.cc | 21 | ||||
-rw-r--r-- | gold/output.h | 19 |
4 files changed, 94 insertions, 30 deletions
diff --git a/gold/object.cc b/gold/object.cc index 9986383..cfdb17c 100644 --- a/gold/object.cc +++ b/gold/object.cc @@ -147,7 +147,8 @@ Sized_relobj<size, big_endian>::Sized_relobj( output_local_symbol_count_(0), symbols_(NULL), local_symbol_offset_(0), - local_values_() + local_values_(), + local_got_offsets_() { } @@ -662,6 +663,17 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index, return index; } +// Return the value of the local symbol symndx. +template<int size, bool big_endian> +typename elfcpp::Elf_types<size>::Elf_Addr +Sized_relobj<size, big_endian>::local_symbol_value(unsigned int symndx) const +{ + gold_assert(symndx < this->local_symbol_count_); + gold_assert(symndx < this->local_values_.size()); + const Symbol_value<size>& lv(this->local_values_[symndx]); + return lv.value(this, 0); +} + // Return the value of a local symbol defined in input section SHNDX, // with value VALUE, adding addend ADDEND. IS_SECTION_SYMBOL // indicates whether the symbol is a section symbol. This handles diff --git a/gold/object.h b/gold/object.h index e4359ac..2baf2da 100644 --- a/gold/object.h +++ b/gold/object.h @@ -612,6 +612,54 @@ class Sized_relobj : public Relobj return this->local_values_[sym].output_symtab_index(); } + // Return the appropriate Sized_target structure. + Sized_target<size, big_endian>* + sized_target() + { + return this->Object::sized_target + SELECT_SIZE_ENDIAN_NAME(size, big_endian) ( + SELECT_SIZE_ENDIAN_ONLY(size, big_endian)); + } + + // Return the value of the local symbol symndx. + Address + local_symbol_value(unsigned int symndx) const; + + // Return the value of a local symbol defined in input section + // SHNDX, with value VALUE, adding addend ADDEND. IS_SECTION_SYMBOL + // indicates whether the symbol is a section symbol. This handles + // SHF_MERGE sections. + Address + local_value(unsigned int shndx, Address value, bool is_section_symbol, + Address addend) const; + + // Return whether the local symbol SYMNDX has a GOT offset. + bool + local_has_got_offset(unsigned int symndx) const + { + return (this->local_got_offsets_.find(symndx) + != this->local_got_offsets_.end()); + } + + // Return the GOT offset of the local symbol SYMNDX. + unsigned int + local_got_offset(unsigned int symndx) const + { + Local_got_offsets::const_iterator p = + this->local_got_offsets_.find(symndx); + gold_assert(p != this->local_got_offsets_.end()); + return p->second; + } + + // Set the GOT offset of the local symbol SYMNDX to GOT_OFFSET. + void + set_local_got_offset(unsigned int symndx, unsigned int got_offset) + { + std::pair<Local_got_offsets::iterator, bool> ins = + this->local_got_offsets_.insert(std::make_pair(symndx, got_offset)); + gold_assert(ins.second); + } + // Read the symbols. void do_read_symbols(Read_symbols_data*); @@ -658,23 +706,6 @@ class Sized_relobj : public Relobj do_section_flags(unsigned int shndx) { return this->elf_file_.section_flags(shndx); } - // Return the appropriate Sized_target structure. - Sized_target<size, big_endian>* - sized_target() - { - return this->Object::sized_target - SELECT_SIZE_ENDIAN_NAME(size, big_endian) ( - SELECT_SIZE_ENDIAN_ONLY(size, big_endian)); - } - - // Return the value of a local symbol define in input section SHNDX, - // with value VALUE, adding addend ADDEND. IS_SECTION_SYMBOL - // indicates whether the symbol is a section symbol. This handles - // SHF_MERGE sections. - Address - local_value(unsigned int shndx, Address value, bool is_section_symbol, - Address addend) const; - private: // For convenience. typedef Sized_relobj<size, big_endian> This; @@ -724,6 +755,9 @@ class Sized_relobj : public Relobj write_local_symbols(Output_file*, const Stringpool_template<char>*); + // The GOT offsets of local symbols. + typedef Unordered_map<unsigned int, unsigned int> Local_got_offsets; + // General access to the ELF file. elfcpp::Elf_file<size, big_endian, Object> elf_file_; // Index of SHT_SYMTAB section. @@ -738,6 +772,8 @@ class Sized_relobj : public Relobj off_t local_symbol_offset_; // Values of local symbols. Local_values local_values_; + // GOT offsets for local symbols, indexed by symbol number. + Local_got_offsets local_got_offsets_; }; // A class to manage the list of all objects. diff --git a/gold/output.cc b/gold/output.cc index 34fdc67..f217b03 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -679,7 +679,8 @@ Output_data_got<size, big_endian>::Got_entry::write(unsigned char* pov) const break; default: - gold_unreachable(); + val = this->u_.object->local_symbol_value(this->local_sym_index_); + break; } elfcpp::Swap<size, big_endian>::writeval(pov, val); @@ -704,6 +705,24 @@ Output_data_got<size, big_endian>::add_global(Symbol* gsym) return true; } +// 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. + +template<int size, bool big_endian> +bool +Output_data_got<size, big_endian>::add_local( + Sized_relobj<size, big_endian>* object, + unsigned int symndx) +{ + if (object->local_has_got_offset(symndx)) + return false; + this->entries_.push_back(Got_entry(object, symndx)); + this->set_got_size(); + object->set_local_got_offset(symndx, this->last_got_offset()); + return true; +} + // Write out the GOT. template<int size, bool big_endian> diff --git a/gold/output.h b/gold/output.h index 7f783d6..997a821 100644 --- a/gold/output.h +++ b/gold/output.h @@ -909,15 +909,11 @@ class Output_data_got : public Output_section_data bool add_global(Symbol* gsym); - // Add an entry for a local symbol to the GOT. This returns the - // offset of the new entry from the start of the GOT. - unsigned int - add_local(Object* object, unsigned int sym_index) - { - this->entries_.push_back(Got_entry(object, sym_index)); - this->set_got_size(); - return this->last_got_offset(); - } + // 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(Sized_relobj<size, big_endian>* object, unsigned int sym_index); // Add a constant to the GOT. This returns the offset of the new // entry from the start of the GOT. @@ -949,7 +945,8 @@ class Output_data_got : public Output_section_data { this->u_.gsym = gsym; } // Create a local symbol entry. - Got_entry(Object* object, unsigned int local_sym_index) + Got_entry(Sized_relobj<size, big_endian>* object, + unsigned int local_sym_index) : local_sym_index_(local_sym_index) { gold_assert(local_sym_index != GSYM_CODE @@ -977,7 +974,7 @@ class Output_data_got : public Output_section_data union { // For a local symbol, the object. - Object* object; + Sized_relobj<size, big_endian>* object; // For a global symbol, the symbol. Symbol* gsym; // For a constant, the constant. |