diff options
-rw-r--r-- | gold/ChangeLog | 59 | ||||
-rw-r--r-- | gold/copy-relocs.cc | 13 | ||||
-rw-r--r-- | gold/expression.cc | 2 | ||||
-rw-r--r-- | gold/incremental.h | 11 | ||||
-rw-r--r-- | gold/object.cc | 3 | ||||
-rw-r--r-- | gold/object.h | 157 | ||||
-rw-r--r-- | gold/output.cc | 118 | ||||
-rw-r--r-- | gold/output.h | 266 | ||||
-rw-r--r-- | gold/powerpc.cc | 4 | ||||
-rw-r--r-- | gold/sparc.cc | 56 | ||||
-rw-r--r-- | gold/x86_64.cc | 50 |
11 files changed, 475 insertions, 264 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index fed9a65..790d8d3 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,62 @@ +2011-12-18 Ian Lance Taylor <iant@google.com> + + * object.h (Relobj::local_symbol_value): New function. + (Relobj::local_plt_offset): New function. + (Relobj::local_has_got_offset): New function. + (Relobj::local_got_offset): New function. + (Relobj::set_local_got_offset): New function. + (Relobj::do_local_symbol_value): New pure virtual function. + (Relobj::do_local_plt_offset): Likewise. + (Relobj::do_local_has_got_offset): Likewise. + (Relobj::do_local_got_offset): Likewise. + (Relobj::do_set_local_got_offset): Likewise. + (Sized_relobj::do_local_has_got_offset): Rename from + local_has_got_offset. + (Sized_relobj::do_local_got_offset): Rename from local_got_offset. + (Sized_relobj::do_set_local_got_offset): Rename from + set_local_got_offset. + (Sized_relobj_file::do_local_plt_offset): Rename from + local_plt_offset. + (Sized_relobj_file::do_local_symbol_value): New function. + * object.cc (Sized_relobj_file::do_local_plt_offset): Rename from + local_plt_offset. + * output.cc (Output_data_got::Got_entry::write): Change object to + Relobj. Use local_symbol_value. + (Output_data_got::add_global_with_rel): Change rel_dyn to + Output_data_reloc_generic*. Use add_global_generic. + (Output_data_got::add_global_with_rela): Remove. Change all + callers to use add_global_with_rel. + (Output_data_got::add_global_pair_with_rel): Change rel_dyn to + Output_data_reloc_generic*. Use add_global_generic. + (Output_data_got::add_global_pair_with_rela): Remove. Change all + callers to use add_global_pair_with_rel. + (Output_data_got::add_local): Change object to Relobj*. + (Output_data_got::add_local_plt): Likewise. + (Output_data_got::add_local_with_rel): Change object to Relobj*, + change rel_dyn to Output_data_reloc_generic*. Use + add_local_generic. + (Output_data_got::add_local_with_rela): Remove. Change all + callers to use all_local_with_rel. + (Output_data_got::add_local_pair_with_rel): Change object to + Relobj*, change rel_dyn to Output_data_reloc_generic*. Use + add_output_section_generic. + (Output_data_got::add_local_pair_with_rela): Remove. Change all + callers to use add_local_pair_with_rel. + (Output_data_got::reserve_local): Change object to Relobj*. + * output.h: (class Output_data_reloc_generic): Add pure virtual + declarations for add_global_generic, add_local_generic, + add_output_section_generic. + (class Output_data_reloc) [SHT_REL, SHT_RELA]: Implement new + functions for Output_data_reloc_generic. Update declarations for + changes listed in output.cc. + (class Output_data_got): Change template parameter to got_size. + Don't define Rel_dyn or Rela_dyn. Update declarations per above. + * incremental.h (Sized_relobj_incr::do_local_symbol_value): New + function. + (Sized_relobj_incr::do_local_plt_offset): New function. + * copy-relocs.cc (Copy_relocs::Copy_reloc_entry::emit): Call + add_global_generic. + 2011-12-17 Cary Coutant <ccoutant@google.com> * dwarf_reader.cc (Sized_dwarf_line_info::read_lines): Add casts. diff --git a/gold/copy-relocs.cc b/gold/copy-relocs.cc index 20b110d..92c5aea 100644 --- a/gold/copy-relocs.cc +++ b/gold/copy-relocs.cc @@ -1,6 +1,6 @@ // copy-relocs.cc -- handle COPY relocations for gold. -// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -41,10 +41,10 @@ Copy_relocs<sh_type, size, big_endian>::Copy_reloc_entry::emit( // emitted a COPY relocation, and we do not want to emit this // dynamic relocation. if (this->sym_->is_from_dynobj()) - reloc_section->add_global(this->sym_, this->reloc_type_, - this->output_section_, this->relobj_, - this->shndx_, this->address_, - this->addend_); + reloc_section->add_global_generic(this->sym_, this->reloc_type_, + this->output_section_, this->relobj_, + this->shndx_, this->address_, + this->addend_); } // Copy_relocs methods. @@ -115,7 +115,8 @@ Copy_relocs<sh_type, size, big_endian>::emit_copy_reloc( symtab->define_with_copy_reloc(sym, posd, offset); // Add the COPY relocation to the dynamic reloc section. - reloc_section->add_global(sym, this->copy_reloc_type_, posd, offset, 0); + reloc_section->add_global_generic(sym, this->copy_reloc_type_, posd, + offset, 0); } // Make a COPY relocation for SYM and emit it. diff --git a/gold/expression.cc b/gold/expression.cc index b611a68..e31c151 100644 --- a/gold/expression.cc +++ b/gold/expression.cc @@ -1,6 +1,6 @@ // expression.cc -- expressions in linker scripts for gold -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. diff --git a/gold/incremental.h b/gold/incremental.h index 56fc52b..0edb190 100644 --- a/gold/incremental.h +++ b/gold/incremental.h @@ -1,6 +1,6 @@ // inremental.h -- incremental linking support for gold -*- C++ -*- -// Copyright 2009, 2010 Free Software Foundation, Inc. +// Copyright 2009, 2010, 2011 Free Software Foundation, Inc. // Written by Mikolaj Zalewski <mikolajz@google.com>. // This file is part of gold. @@ -1924,6 +1924,15 @@ class Sized_relobj_incr : public Sized_relobj<size, big_endian> do_get_global_symbols() const { return &this->symbols_; } + // Return the value of a local symbol. + uint64_t + do_local_symbol_value(unsigned int, uint64_t) const + { gold_unreachable(); } + + unsigned int + do_local_plt_offset(unsigned int) const + { gold_unreachable(); } + // Return the number of local symbols. unsigned int do_local_symbol_count() const diff --git a/gold/object.cc b/gold/object.cc index 84a9646..bbeb9af 100644 --- a/gold/object.cc +++ b/gold/object.cc @@ -1819,7 +1819,8 @@ Sized_relobj_file<size, big_endian>::local_has_plt_offset( template<int size, bool big_endian> unsigned int -Sized_relobj_file<size, big_endian>::local_plt_offset(unsigned int symndx) const +Sized_relobj_file<size, big_endian>::do_local_plt_offset( + unsigned int symndx) const { typename Local_plt_offsets::const_iterator p = this->local_plt_offsets_.find(symndx); diff --git a/gold/object.h b/gold/object.h index a389c54..48aff5a 100644 --- a/gold/object.h +++ b/gold/object.h @@ -1009,6 +1009,39 @@ class Relobj : public Object scan_relocs(Symbol_table* symtab, Layout* layout, Read_relocs_data* rd) { return this->do_scan_relocs(symtab, layout, rd); } + // Return the value of the local symbol whose index is SYMNDX, plus + // ADDEND. ADDEND is passed in so that we can correctly handle the + // section symbol for a merge section. + uint64_t + local_symbol_value(unsigned int symndx, uint64_t addend) const + { return this->do_local_symbol_value(symndx, addend); } + + // Return the PLT offset for a local symbol. It is an error to call + // this if it doesn't have one. + unsigned int + local_plt_offset(unsigned int symndx) const + { return this->do_local_plt_offset(symndx); } + + // Return whether the local symbol SYMNDX has a GOT offset of type + // 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 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); } + + // 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); } + // The number of local symbols in the input symbol table. virtual unsigned int local_symbol_count() const @@ -1167,6 +1200,28 @@ class Relobj : public Object virtual void do_scan_relocs(Symbol_table*, Layout*, Read_relocs_data*) = 0; + // Return the value of a local symbol. + virtual uint64_t + do_local_symbol_value(unsigned int symndx, uint64_t addend) const = 0; + + // Return the PLT offset of a local symbol. + 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. + virtual bool + do_local_has_got_offset(unsigned int symndx, + unsigned int got_type) const = 0; + + // Return the GOT offset of a given type of a local symbol. + virtual unsigned int + do_local_got_offset(unsigned int symndx, unsigned int got_type) const = 0; + + // Set the GOT offset with a given type for a local symbol. + virtual void + do_set_local_got_offset(unsigned int symndx, unsigned int got_type, + unsigned int got_offset) = 0; + // Return the number of local symbols--implemented by child class. virtual unsigned int do_local_symbol_count() const = 0; @@ -1775,47 +1830,6 @@ class Sized_relobj : public Relobj return this->section_offsets_[shndx]; } - // Return whether the local symbol SYMNDX has a GOT offset. - // For TLS symbols, the GOT entry will hold its tp-relative offset. - bool - local_has_got_offset(unsigned int symndx, unsigned int got_type) const - { - Local_got_offsets::const_iterator p = - this->local_got_offsets_.find(symndx); - return (p != this->local_got_offsets_.end() - && p->second->get_offset(got_type) != -1U); - } - - // Return the GOT offset of the local symbol SYMNDX. - unsigned int - local_got_offset(unsigned int symndx, unsigned int got_type) const - { - Local_got_offsets::const_iterator p = - this->local_got_offsets_.find(symndx); - gold_assert(p != this->local_got_offsets_.end()); - unsigned int off = p->second->get_offset(got_type); - gold_assert(off != -1U); - return off; - } - - // Set the GOT offset of the local symbol SYMNDX to GOT_OFFSET. - void - set_local_got_offset(unsigned int symndx, unsigned int got_type, - unsigned int got_offset) - { - Local_got_offsets::const_iterator p = - this->local_got_offsets_.find(symndx); - 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)); - gold_assert(ins.second); - } - } - // Iterate over local symbols, calling a visitor class V for each GOT offset // associated with a local symbol. void @@ -1855,6 +1869,49 @@ 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. + bool + do_local_has_got_offset(unsigned int symndx, unsigned int got_type) const + { + Local_got_offsets::const_iterator p = + this->local_got_offsets_.find(symndx); + 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. + unsigned int + do_local_got_offset(unsigned int symndx, unsigned int got_type) const + { + Local_got_offsets::const_iterator p = + this->local_got_offsets_.find(symndx); + gold_assert(p != this->local_got_offsets_.end()); + unsigned int off = p->second->get_offset(got_type); + gold_assert(off != -1U); + return off; + } + + // Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX + // to GOT_OFFSET. + void + do_set_local_got_offset(unsigned int symndx, unsigned int got_type, + unsigned int got_offset) + { + Local_got_offsets::const_iterator p = + this->local_got_offsets_.find(symndx); + 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)); + gold_assert(ins.second); + } + } + private: // The GOT offsets of local symbols. This map also stores GOT offsets // for tp-relative offsets for TLS symbols. @@ -2000,11 +2057,6 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian> bool local_has_plt_offset(unsigned int symndx) const; - // Return the PLT offset for a local symbol. It is an error to call - // this if it doesn't have one. - unsigned int - local_plt_offset(unsigned int symndx) const; - // Set the PLT offset of the local symbol SYMNDX. void set_local_plt_offset(unsigned int symndx, unsigned int plt_offset); @@ -2050,6 +2102,19 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian> void do_read_symbols(Read_symbols_data*); + // Return the value of a local symbol. + uint64_t + do_local_symbol_value(unsigned int symndx, uint64_t addend) const + { + const Symbol_value<size>* symval = this->local_symbol(symndx); + return symval->value(this, addend); + } + + // Return the PLT offset for a local symbol. It is an error to call + // this if it doesn't have one. + unsigned int + do_local_plt_offset(unsigned int symndx) const; + // Return the number of local symbols. unsigned int do_local_symbol_count() const diff --git a/gold/output.cc b/gold/output.cc index 7633c73..6e46fd5 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -1387,11 +1387,13 @@ Output_data_got<size, big_endian>::Got_entry::write(unsigned char* pov) const default: { - const Sized_relobj_file<size, big_endian>* object = this->u_.object; + const Relobj* object = this->u_.object; const unsigned int lsi = this->local_sym_index_; - const Symbol_value<size>* symval = object->local_symbol(lsi); if (!this->use_plt_offset_) - val = symval->value(this->u_.object, 0); + { + uint64_t lval = object->local_symbol_value(lsi, 0); + val = convert_types<Valtype, uint64_t>(lval); + } else { uint64_t plt_address = @@ -1448,23 +1450,7 @@ void Output_data_got<size, big_endian>::add_global_with_rel( Symbol* gsym, unsigned int got_type, - Rel_dyn* rel_dyn, - unsigned int r_type) -{ - if (gsym->has_got_offset(got_type)) - return; - - unsigned int got_offset = this->add_got_entry(Got_entry()); - gsym->set_got_offset(got_type, got_offset); - rel_dyn->add_global(gsym, r_type, this, got_offset); -} - -template<int size, bool big_endian> -void -Output_data_got<size, big_endian>::add_global_with_rela( - Symbol* gsym, - unsigned int got_type, - Rela_dyn* rela_dyn, + Output_data_reloc_generic* rel_dyn, unsigned int r_type) { if (gsym->has_got_offset(got_type)) @@ -1472,7 +1458,7 @@ Output_data_got<size, big_endian>::add_global_with_rela( unsigned int got_offset = this->add_got_entry(Got_entry()); gsym->set_got_offset(got_type, got_offset); - rela_dyn->add_global(gsym, r_type, this, got_offset, 0); + rel_dyn->add_global_generic(gsym, r_type, this, got_offset, 0); } // Add a pair of entries for a global symbol to the GOT, and add @@ -1483,27 +1469,7 @@ void Output_data_got<size, big_endian>::add_global_pair_with_rel( Symbol* gsym, unsigned int got_type, - Rel_dyn* rel_dyn, - unsigned int r_type_1, - unsigned int r_type_2) -{ - if (gsym->has_got_offset(got_type)) - return; - - unsigned int got_offset = this->add_got_entry_pair(Got_entry(), Got_entry()); - gsym->set_got_offset(got_type, got_offset); - rel_dyn->add_global(gsym, r_type_1, this, got_offset); - - if (r_type_2 != 0) - rel_dyn->add_global(gsym, r_type_2, this, got_offset + size / 8); -} - -template<int size, bool big_endian> -void -Output_data_got<size, big_endian>::add_global_pair_with_rela( - Symbol* gsym, - unsigned int got_type, - Rela_dyn* rela_dyn, + Output_data_reloc_generic* rel_dyn, unsigned int r_type_1, unsigned int r_type_2) { @@ -1512,10 +1478,11 @@ Output_data_got<size, big_endian>::add_global_pair_with_rela( unsigned int got_offset = this->add_got_entry_pair(Got_entry(), Got_entry()); gsym->set_got_offset(got_type, got_offset); - rela_dyn->add_global(gsym, r_type_1, this, got_offset, 0); + rel_dyn->add_global_generic(gsym, r_type_1, this, got_offset, 0); if (r_type_2 != 0) - rela_dyn->add_global(gsym, r_type_2, this, got_offset + size / 8, 0); + rel_dyn->add_global_generic(gsym, r_type_2, this, + got_offset + size / 8, 0); } // Add an entry for a local symbol to the GOT. This returns true if @@ -1525,7 +1492,7 @@ Output_data_got<size, big_endian>::add_global_pair_with_rela( template<int size, bool big_endian> bool Output_data_got<size, big_endian>::add_local( - Sized_relobj_file<size, big_endian>* object, + Relobj* object, unsigned int symndx, unsigned int got_type) { @@ -1543,7 +1510,7 @@ Output_data_got<size, big_endian>::add_local( template<int size, bool big_endian> bool Output_data_got<size, big_endian>::add_local_plt( - Sized_relobj_file<size, big_endian>* object, + Relobj* object, unsigned int symndx, unsigned int got_type) { @@ -1562,27 +1529,10 @@ Output_data_got<size, big_endian>::add_local_plt( template<int size, bool big_endian> void Output_data_got<size, big_endian>::add_local_with_rel( - Sized_relobj_file<size, big_endian>* object, - unsigned int symndx, - unsigned int got_type, - Rel_dyn* rel_dyn, - unsigned int r_type) -{ - if (object->local_has_got_offset(symndx, got_type)) - return; - - unsigned int got_offset = this->add_got_entry(Got_entry()); - object->set_local_got_offset(symndx, got_type, got_offset); - rel_dyn->add_local(object, symndx, r_type, this, got_offset); -} - -template<int size, bool big_endian> -void -Output_data_got<size, big_endian>::add_local_with_rela( - Sized_relobj_file<size, big_endian>* object, + Relobj* object, unsigned int symndx, unsigned int got_type, - Rela_dyn* rela_dyn, + Output_data_reloc_generic* rel_dyn, unsigned int r_type) { if (object->local_has_got_offset(symndx, got_type)) @@ -1590,7 +1540,7 @@ Output_data_got<size, big_endian>::add_local_with_rela( unsigned int got_offset = this->add_got_entry(Got_entry()); object->set_local_got_offset(symndx, got_type, got_offset); - rela_dyn->add_local(object, symndx, r_type, this, got_offset, 0); + rel_dyn->add_local_generic(object, symndx, r_type, this, got_offset, 0); } // Add a pair of entries for a local symbol to the GOT, and add @@ -1599,36 +1549,11 @@ Output_data_got<size, big_endian>::add_local_with_rela( template<int size, bool big_endian> void Output_data_got<size, big_endian>::add_local_pair_with_rel( - Sized_relobj_file<size, big_endian>* object, - unsigned int symndx, - unsigned int shndx, - unsigned int got_type, - Rel_dyn* rel_dyn, - unsigned int r_type_1, - unsigned int r_type_2) -{ - if (object->local_has_got_offset(symndx, got_type)) - return; - - unsigned int got_offset = - this->add_got_entry_pair(Got_entry(), - Got_entry(object, symndx, false)); - object->set_local_got_offset(symndx, got_type, got_offset); - Output_section* os = object->output_section(shndx); - rel_dyn->add_output_section(os, r_type_1, this, got_offset); - - if (r_type_2 != 0) - rel_dyn->add_output_section(os, r_type_2, this, got_offset + size / 8); -} - -template<int size, bool big_endian> -void -Output_data_got<size, big_endian>::add_local_pair_with_rela( - Sized_relobj_file<size, big_endian>* object, + Relobj* object, unsigned int symndx, unsigned int shndx, unsigned int got_type, - Rela_dyn* rela_dyn, + Output_data_reloc_generic* rel_dyn, unsigned int r_type_1, unsigned int r_type_2) { @@ -1640,10 +1565,11 @@ Output_data_got<size, big_endian>::add_local_pair_with_rela( Got_entry(object, symndx, false)); object->set_local_got_offset(symndx, got_type, got_offset); Output_section* os = object->output_section(shndx); - rela_dyn->add_output_section(os, r_type_1, this, got_offset, 0); + rel_dyn->add_output_section_generic(os, r_type_1, this, got_offset, 0); if (r_type_2 != 0) - rela_dyn->add_output_section(os, r_type_2, this, got_offset + size / 8, 0); + rel_dyn->add_output_section_generic(os, r_type_2, this, + got_offset + size / 8, 0); } // Reserve a slot in the GOT for a local symbol or the second slot of a pair. @@ -1652,7 +1578,7 @@ template<int size, bool big_endian> void Output_data_got<size, big_endian>::reserve_local( unsigned int i, - Sized_relobj<size, big_endian>* object, + Relobj* object, unsigned int sym_index, unsigned int got_type) { diff --git a/gold/output.h b/gold/output.h index ef6fea1..db38236 100644 --- a/gold/output.h +++ b/gold/output.h @@ -1397,6 +1397,55 @@ class Output_data_reloc_generic : public Output_section_data_build sort_relocs() const { return this->sort_relocs_; } + // Add a reloc of type TYPE against the global symbol GSYM. The + // relocation applies to the data at offset ADDRESS within OD. + virtual void + add_global_generic(Symbol* gsym, unsigned int type, Output_data* od, + uint64_t address, uint64_t addend) = 0; + + // Add a reloc of type TYPE against the global symbol GSYM. The + // relocation applies to data at offset ADDRESS within section SHNDX + // of object file RELOBJ. OD is the associated output section. + virtual void + add_global_generic(Symbol* gsym, unsigned int type, Output_data* od, + Relobj* relobj, unsigned int shndx, uint64_t address, + uint64_t addend) = 0; + + // Add a reloc of type TYPE against the local symbol LOCAL_SYM_INDEX + // in RELOBJ. The relocation applies to the data at offset ADDRESS + // within OD. + virtual void + add_local_generic(Relobj* relobj, unsigned int local_sym_index, + unsigned int type, Output_data* od, uint64_t address, + uint64_t addend) = 0; + + // Add a reloc of type TYPE against the local symbol LOCAL_SYM_INDEX + // in RELOBJ. The relocation applies to the data at offset ADDRESS + // within section SHNDX of RELOBJ. OD is the associated output + // section. + virtual void + add_local_generic(Relobj* relobj, unsigned int local_sym_index, + unsigned int type, Output_data* od, unsigned int shndx, + uint64_t address, uint64_t addend) = 0; + + // Add a reloc of type TYPE against the STT_SECTION symbol of the + // output section OS. The relocation applies to the data at offset + // ADDRESS within OD. + virtual void + add_output_section_generic(Output_section *os, unsigned int type, + Output_data* od, uint64_t address, + uint64_t addend) = 0; + + // Add a reloc of type TYPE against the STT_SECTION symbol of the + // output section OS. The relocation applies to the data at offset + // ADDRESS within section SHNDX of RELOBJ. OD is the associated + // output section. + virtual void + add_output_section_generic(Output_section* os, unsigned int type, + Output_data* od, Relobj* relobj, + unsigned int shndx, uint64_t address, + uint64_t addend) = 0; + protected: // Note that we've added another relative reloc. void @@ -1518,23 +1567,27 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address, false, false)); } - // These are to simplify the Copy_relocs class. - void - add_global(Symbol* gsym, unsigned int type, Output_data* od, Address address, - Address addend) + add_global_generic(Symbol* gsym, unsigned int type, Output_data* od, + uint64_t address, uint64_t addend) { gold_assert(addend == 0); - this->add_global(gsym, type, od, address); + this->add(od, Output_reloc_type(gsym, type, od, + convert_types<Address, uint64_t>(address), + false, false)); } void - add_global(Symbol* gsym, unsigned int type, Output_data* od, - Sized_relobj<size, big_endian>* relobj, - unsigned int shndx, Address address, Address addend) + add_global_generic(Symbol* gsym, unsigned int type, Output_data* od, + Relobj* relobj, unsigned int shndx, uint64_t address, + uint64_t addend) { gold_assert(addend == 0); - this->add_global(gsym, type, od, relobj, shndx, address); + Sized_relobj<size, big_endian>* sized_relobj = + static_cast<Sized_relobj<size, big_endian>*>(relobj); + this->add(od, Output_reloc_type(gsym, type, sized_relobj, shndx, + convert_types<Address, uint64_t>(address), + false, false)); } // Add a RELATIVE reloc against a global symbol. The final relocation @@ -1592,6 +1645,32 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> address, false, false, false, false)); } + void + add_local_generic(Relobj* relobj, unsigned int local_sym_index, + unsigned int type, Output_data* od, uint64_t address, + uint64_t addend) + { + gold_assert(addend == 0); + Sized_relobj<size, big_endian>* sized_relobj = + static_cast<Sized_relobj<size, big_endian> *>(relobj); + this->add(od, Output_reloc_type(sized_relobj, local_sym_index, type, od, + convert_types<Address, uint64_t>(address), + false, false, false, false)); + } + + void + add_local_generic(Relobj* relobj, unsigned int local_sym_index, + unsigned int type, Output_data* od, unsigned int shndx, + uint64_t address, uint64_t addend) + { + gold_assert(addend == 0); + Sized_relobj<size, big_endian>* sized_relobj = + static_cast<Sized_relobj<size, big_endian>*>(relobj); + this->add(od, Output_reloc_type(sized_relobj, local_sym_index, type, shndx, + convert_types<Address, uint64_t>(address), + false, false, false, false)); + } + // Add a RELATIVE reloc against a local symbol. void @@ -1671,6 +1750,29 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> unsigned int shndx, Address address) { this->add(od, Output_reloc_type(os, type, relobj, shndx, address)); } + void + add_output_section_generic(Output_section* os, unsigned int type, + Output_data* od, uint64_t address, + uint64_t addend) + { + gold_assert(addend == 0); + this->add(od, Output_reloc_type(os, type, od, + convert_types<Address, uint64_t>(address))); + } + + void + add_output_section_generic(Output_section* os, unsigned int type, + Output_data* od, Relobj* relobj, + unsigned int shndx, uint64_t address, + uint64_t addend) + { + gold_assert(addend == 0); + Sized_relobj<size, big_endian>* sized_relobj = + static_cast<Sized_relobj<size, big_endian>*>(relobj); + this->add(od, Output_reloc_type(os, type, sized_relobj, shndx, + convert_types<Address, uint64_t>(address))); + } + // Add an absolute relocation. void @@ -1733,6 +1835,29 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address, addend, false, false)); } + void + add_global_generic(Symbol* gsym, unsigned int type, Output_data* od, + uint64_t address, uint64_t addend) + { + this->add(od, Output_reloc_type(gsym, type, od, + convert_types<Address, uint64_t>(address), + convert_types<Addend, uint64_t>(addend), + false, false)); + } + + void + add_global_generic(Symbol* gsym, unsigned int type, Output_data* od, + Relobj* relobj, unsigned int shndx, uint64_t address, + uint64_t addend) + { + Sized_relobj<size, big_endian>* sized_relobj = + static_cast<Sized_relobj<size, big_endian>*>(relobj); + this->add(od, Output_reloc_type(gsym, type, sized_relobj, shndx, + convert_types<Address, uint64_t>(address), + convert_types<Addend, uint64_t>(addend), + false, false)); + } + // Add a RELATIVE reloc against a global symbol. The final output // relocation will not reference the symbol, but we must keep the symbol // information long enough to set the addend of the relocation correctly @@ -1790,6 +1915,32 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> false)); } + void + add_local_generic(Relobj* relobj, unsigned int local_sym_index, + unsigned int type, Output_data* od, uint64_t address, + uint64_t addend) + { + Sized_relobj<size, big_endian>* sized_relobj = + static_cast<Sized_relobj<size, big_endian> *>(relobj); + this->add(od, Output_reloc_type(sized_relobj, local_sym_index, type, od, + convert_types<Address, uint64_t>(address), + convert_types<Addend, uint64_t>(addend), + false, false, false, false)); + } + + void + add_local_generic(Relobj* relobj, unsigned int local_sym_index, + unsigned int type, Output_data* od, unsigned int shndx, + uint64_t address, uint64_t addend) + { + Sized_relobj<size, big_endian>* sized_relobj = + static_cast<Sized_relobj<size, big_endian>*>(relobj); + this->add(od, Output_reloc_type(sized_relobj, local_sym_index, type, shndx, + convert_types<Address, uint64_t>(address), + convert_types<Addend, uint64_t>(addend), + false, false, false, false)); + } + // Add a RELATIVE reloc against a local symbol. void @@ -1875,6 +2026,29 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> { this->add(od, Output_reloc_type(os, type, relobj, shndx, address, addend)); } + void + add_output_section_generic(Output_section* os, unsigned int type, + Output_data* od, uint64_t address, + uint64_t addend) + { + this->add(od, Output_reloc_type(os, type, od, + convert_types<Address, uint64_t>(address), + convert_types<Addend, uint64_t>(addend))); + } + + void + add_output_section_generic(Output_section* os, unsigned int type, + Output_data* od, Relobj* relobj, + unsigned int shndx, uint64_t address, + uint64_t addend) + { + Sized_relobj<size, big_endian>* sized_relobj = + static_cast<Sized_relobj<size, big_endian>*>(relobj); + this->add(od, Output_reloc_type(os, type, sized_relobj, shndx, + convert_types<Address, uint64_t>(address), + convert_types<Addend, uint64_t>(addend))); + } + // Add an absolute relocation. void @@ -1974,29 +2148,28 @@ class Output_data_group : public Output_section_data // Output_data_got is used to manage a GOT. Each entry in the GOT is // for one symbol--either a global symbol or a local symbol in an // object. The target specific code adds entries to the GOT as -// needed. +// needed. The GOT_SIZE template parameter is the size in bits of a +// GOT entry, typically 32 or 64. -template<int size, bool big_endian> +template<int got_size, bool big_endian> class Output_data_got : public Output_section_data_build { public: - typedef typename elfcpp::Elf_types<size>::Elf_Addr Valtype; - typedef Output_data_reloc<elfcpp::SHT_REL, true, size, big_endian> Rel_dyn; - typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian> Rela_dyn; + typedef typename elfcpp::Elf_types<got_size>::Elf_Addr Valtype; Output_data_got() - : Output_section_data_build(Output_data::default_alignment_for_size(size)), + : Output_section_data_build(Output_data::default_alignment_for_size(got_size)), entries_(), free_list_() { } Output_data_got(off_t data_size) : Output_section_data_build(data_size, - Output_data::default_alignment_for_size(size)), + Output_data::default_alignment_for_size(got_size)), entries_(), free_list_() { // For an incremental update, we have an existing GOT section. // Initialize the list of entries and the free list. - this->entries_.resize(data_size / (size / 8)); + this->entries_.resize(data_size / (got_size / 8)); this->free_list_.init(data_size, false); } @@ -2014,62 +2187,39 @@ class Output_data_got : public Output_section_data_build // relocation of type R_TYPE for the GOT entry. void add_global_with_rel(Symbol* gsym, unsigned int got_type, - Rel_dyn* rel_dyn, unsigned int r_type); - - void - add_global_with_rela(Symbol* gsym, unsigned int got_type, - Rela_dyn* rela_dyn, unsigned int r_type); + Output_data_reloc_generic* rel_dyn, unsigned int r_type); // Add a pair of entries for a global symbol to the GOT, and add // dynamic relocations of type R_TYPE_1 and R_TYPE_2, respectively. void add_global_pair_with_rel(Symbol* gsym, unsigned int got_type, - Rel_dyn* rel_dyn, unsigned int r_type_1, - unsigned int r_type_2); - - void - add_global_pair_with_rela(Symbol* gsym, unsigned int got_type, - Rela_dyn* rela_dyn, unsigned int r_type_1, - unsigned int r_type_2); + Output_data_reloc_generic* rel_dyn, + unsigned int r_type_1, unsigned int r_type_2); // 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_file<size, big_endian>* object, unsigned int sym_index, - unsigned int got_type); + add_local(Relobj* object, unsigned int sym_index, unsigned int got_type); // Like add_local, but use the PLT offset of the local symbol if it // has one. bool - add_local_plt(Sized_relobj_file<size, big_endian>* object, - unsigned int sym_index, - unsigned int got_type); + add_local_plt(Relobj* object, unsigned int sym_index, unsigned int got_type); // Add an entry for a local symbol to the GOT, and add a dynamic // relocation of type R_TYPE for the GOT entry. void - add_local_with_rel(Sized_relobj_file<size, big_endian>* object, - unsigned int sym_index, unsigned int got_type, - Rel_dyn* rel_dyn, unsigned int r_type); - - void - add_local_with_rela(Sized_relobj_file<size, big_endian>* object, - unsigned int sym_index, unsigned int got_type, - Rela_dyn* rela_dyn, unsigned int r_type); + add_local_with_rel(Relobj* object, unsigned int sym_index, + unsigned int got_type, Output_data_reloc_generic* rel_dyn, + unsigned int r_type); // Add a pair of entries for a local symbol to the GOT, and add // dynamic relocations of type R_TYPE_1 and R_TYPE_2, respectively. void - add_local_pair_with_rel(Sized_relobj_file<size, big_endian>* object, - unsigned int sym_index, unsigned int shndx, - unsigned int got_type, Rel_dyn* rel_dyn, - unsigned int r_type_1, unsigned int r_type_2); - - void - add_local_pair_with_rela(Sized_relobj_file<size, big_endian>* object, - unsigned int sym_index, unsigned int shndx, - unsigned int got_type, Rela_dyn* rela_dyn, + 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_1, unsigned int r_type_2); // Add a constant to the GOT. This returns the offset of the new @@ -2084,12 +2234,12 @@ class Output_data_got : public Output_section_data_build // Reserve a slot in the GOT. void reserve_slot(unsigned int i) - { this->free_list_.remove(i * size / 8, (i + 1) * size / 8); } + { this->free_list_.remove(i * got_size / 8, (i + 1) * got_size / 8); } // Reserve a slot in the GOT for a local symbol. void - reserve_local(unsigned int i, Sized_relobj<size, big_endian>* object, - unsigned int sym_index, unsigned int got_type); + reserve_local(unsigned int i, Relobj* object, unsigned int sym_index, + unsigned int got_type); // Reserve a slot in the GOT for a global symbol. void @@ -2121,8 +2271,8 @@ class Output_data_got : public Output_section_data_build { this->u_.gsym = gsym; } // Create a local symbol entry. - Got_entry(Sized_relobj_file<size, big_endian>* object, - unsigned int local_sym_index, bool use_plt_offset) + Got_entry(Relobj* object, unsigned int local_sym_index, + bool use_plt_offset) : local_sym_index_(local_sym_index), use_plt_offset_(use_plt_offset) { gold_assert(local_sym_index != GSYM_CODE @@ -2153,7 +2303,7 @@ class Output_data_got : public Output_section_data_build union { // For a local symbol, the object. - Sized_relobj_file<size, big_endian>* object; + Relobj* object; // For a global symbol, the symbol. Symbol* gsym; // For a constant, the constant. @@ -2179,7 +2329,7 @@ class Output_data_got : public Output_section_data_build // Return the offset into the GOT of GOT entry I. unsigned int got_offset(unsigned int i) const - { return i * (size / 8); } + { return i * (got_size / 8); } // Return the offset into the GOT of the last entry added. unsigned int diff --git a/gold/powerpc.cc b/gold/powerpc.cc index 62a17ca..372443f 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -1566,8 +1566,8 @@ Target_powerpc<size, big_endian>::Scan::global( if (gsym->is_from_dynobj() || gsym->is_undefined() || gsym->is_preemptible()) - got->add_global_with_rela(gsym, GOT_TYPE_STANDARD, rela_dyn, - elfcpp::R_POWERPC_GLOB_DAT); + got->add_global_with_rel(gsym, GOT_TYPE_STANDARD, rela_dyn, + elfcpp::R_POWERPC_GLOB_DAT); else if (!gsym->has_got_offset(GOT_TYPE_STANDARD)) { unsigned int off = got->add_constant(0); diff --git a/gold/sparc.cc b/gold/sparc.cc index 12e1dee..39c7e7c 100644 --- a/gold/sparc.cc +++ b/gold/sparc.cc @@ -1998,14 +1998,14 @@ Target_sparc<size, big_endian>::Scan::local( object->error(_("local symbol %u has bad shndx %u"), r_sym, shndx); else - got->add_local_pair_with_rela(object, r_sym, - lsym.get_st_shndx(), - GOT_TYPE_TLS_PAIR, - target->rela_dyn_section(layout), - (size == 64 - ? elfcpp::R_SPARC_TLS_DTPMOD64 - : elfcpp::R_SPARC_TLS_DTPMOD32), - 0); + got->add_local_pair_with_rel(object, r_sym, + lsym.get_st_shndx(), + GOT_TYPE_TLS_PAIR, + target->rela_dyn_section(layout), + (size == 64 + ? elfcpp::R_SPARC_TLS_DTPMOD64 + : elfcpp::R_SPARC_TLS_DTPMOD32), + 0); if (r_type == elfcpp::R_SPARC_TLS_GD_CALL) generate_tls_call(symtab, layout, target); } @@ -2339,8 +2339,8 @@ Target_sparc<size, big_endian>::Scan::global( if (gsym->is_from_dynobj() || gsym->is_undefined() || gsym->is_preemptible()) - got->add_global_with_rela(gsym, GOT_TYPE_STANDARD, rela_dyn, - elfcpp::R_SPARC_GLOB_DAT); + got->add_global_with_rel(gsym, GOT_TYPE_STANDARD, rela_dyn, + elfcpp::R_SPARC_GLOB_DAT); else if (!gsym->has_got_offset(GOT_TYPE_STANDARD)) { unsigned int off = got->add_constant(0); @@ -2389,14 +2389,14 @@ Target_sparc<size, big_endian>::Scan::global( // dtv-relative offset. Output_data_got<size, big_endian>* got = target->got_section(symtab, layout); - got->add_global_pair_with_rela(gsym, GOT_TYPE_TLS_PAIR, - target->rela_dyn_section(layout), - (size == 64 ? - elfcpp::R_SPARC_TLS_DTPMOD64 : - elfcpp::R_SPARC_TLS_DTPMOD32), - (size == 64 ? - elfcpp::R_SPARC_TLS_DTPOFF64 : - elfcpp::R_SPARC_TLS_DTPOFF32)); + got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR, + target->rela_dyn_section(layout), + (size == 64 + ? elfcpp::R_SPARC_TLS_DTPMOD64 + : elfcpp::R_SPARC_TLS_DTPMOD32), + (size == 64 + ? elfcpp::R_SPARC_TLS_DTPOFF64 + : elfcpp::R_SPARC_TLS_DTPOFF32)); // Emit R_SPARC_WPLT30 against "__tls_get_addr" if (r_type == elfcpp::R_SPARC_TLS_GD_CALL) @@ -2407,11 +2407,11 @@ Target_sparc<size, big_endian>::Scan::global( // Create a GOT entry for the tp-relative offset. Output_data_got<size, big_endian>* got = target->got_section(symtab, layout); - got->add_global_with_rela(gsym, GOT_TYPE_TLS_OFFSET, - target->rela_dyn_section(layout), - (size == 64 ? - elfcpp::R_SPARC_TLS_TPOFF64 : - elfcpp::R_SPARC_TLS_TPOFF32)); + got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET, + target->rela_dyn_section(layout), + (size == 64 ? + elfcpp::R_SPARC_TLS_TPOFF64 : + elfcpp::R_SPARC_TLS_TPOFF32)); } else if (optimized_type != tls::TLSOPT_TO_LE) unsupported_reloc_global(object, r_type, gsym); @@ -2462,11 +2462,11 @@ Target_sparc<size, big_endian>::Scan::global( // Create a GOT entry for the tp-relative offset. Output_data_got<size, big_endian>* got = target->got_section(symtab, layout); - got->add_global_with_rela(gsym, GOT_TYPE_TLS_OFFSET, - target->rela_dyn_section(layout), - (size == 64 ? - elfcpp::R_SPARC_TLS_TPOFF64 : - elfcpp::R_SPARC_TLS_TPOFF32)); + got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET, + target->rela_dyn_section(layout), + (size == 64 + ? elfcpp::R_SPARC_TLS_TPOFF64 + : elfcpp::R_SPARC_TLS_TPOFF32)); } else if (optimized_type != tls::TLSOPT_TO_LE) unsupported_reloc_global(object, r_type, gsym); diff --git a/gold/x86_64.cc b/gold/x86_64.cc index e7c981b..552e9d1 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -2137,11 +2137,11 @@ Target_x86_64::Scan::local(Symbol_table* symtab, object->error(_("local symbol %u has bad shndx %u"), r_sym, shndx); else - got->add_local_pair_with_rela(object, r_sym, - shndx, - GOT_TYPE_TLS_PAIR, - target->rela_dyn_section(layout), - elfcpp::R_X86_64_DTPMOD64, 0); + got->add_local_pair_with_rel(object, r_sym, + shndx, + GOT_TYPE_TLS_PAIR, + target->rela_dyn_section(layout), + elfcpp::R_X86_64_DTPMOD64, 0); } else if (optimized_type != tls::TLSOPT_TO_LE) unsupported_reloc_local(object, r_type); @@ -2207,9 +2207,9 @@ Target_x86_64::Scan::local(Symbol_table* symtab, Output_data_got<64, false>* got = target->got_section(symtab, layout); unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info()); - got->add_local_with_rela(object, r_sym, GOT_TYPE_TLS_OFFSET, - target->rela_dyn_section(layout), - elfcpp::R_X86_64_TPOFF64); + got->add_local_with_rel(object, r_sym, GOT_TYPE_TLS_OFFSET, + target->rela_dyn_section(layout), + elfcpp::R_X86_64_TPOFF64); } else if (optimized_type != tls::TLSOPT_TO_LE) unsupported_reloc_local(object, r_type); @@ -2481,8 +2481,8 @@ Target_x86_64::Scan::global(Symbol_table* symtab, && parameters->options().shared()) || (gsym->type() == elfcpp::STT_GNU_IFUNC && parameters->options().output_is_position_independent())) - got->add_global_with_rela(gsym, GOT_TYPE_STANDARD, rela_dyn, - elfcpp::R_X86_64_GLOB_DAT); + got->add_global_with_rel(gsym, GOT_TYPE_STANDARD, rela_dyn, + elfcpp::R_X86_64_GLOB_DAT); else { // For a STT_GNU_IFUNC symbol we want to write the PLT @@ -2580,19 +2580,19 @@ Target_x86_64::Scan::global(Symbol_table* symtab, // dtv-relative offset. Output_data_got<64, false>* got = target->got_section(symtab, layout); - got->add_global_pair_with_rela(gsym, GOT_TYPE_TLS_PAIR, - target->rela_dyn_section(layout), - elfcpp::R_X86_64_DTPMOD64, - elfcpp::R_X86_64_DTPOFF64); + got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR, + target->rela_dyn_section(layout), + elfcpp::R_X86_64_DTPMOD64, + elfcpp::R_X86_64_DTPOFF64); } else if (optimized_type == tls::TLSOPT_TO_IE) { // Create a GOT entry for the tp-relative offset. Output_data_got<64, false>* got = target->got_section(symtab, layout); - got->add_global_with_rela(gsym, GOT_TYPE_TLS_OFFSET, - target->rela_dyn_section(layout), - elfcpp::R_X86_64_TPOFF64); + got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET, + target->rela_dyn_section(layout), + elfcpp::R_X86_64_TPOFF64); } else if (optimized_type != tls::TLSOPT_TO_LE) unsupported_reloc_global(object, r_type, gsym); @@ -2613,17 +2613,17 @@ Target_x86_64::Scan::global(Symbol_table* symtab, target->got_section(symtab, layout); Output_data_got<64, false>* got = target->got_tlsdesc_section(); Reloc_section* rt = target->rela_tlsdesc_section(layout); - got->add_global_pair_with_rela(gsym, GOT_TYPE_TLS_DESC, rt, - elfcpp::R_X86_64_TLSDESC, 0); + got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_DESC, rt, + elfcpp::R_X86_64_TLSDESC, 0); } else if (optimized_type == tls::TLSOPT_TO_IE) { // Create a GOT entry for the tp-relative offset. Output_data_got<64, false>* got = target->got_section(symtab, layout); - got->add_global_with_rela(gsym, GOT_TYPE_TLS_OFFSET, - target->rela_dyn_section(layout), - elfcpp::R_X86_64_TPOFF64); + got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET, + target->rela_dyn_section(layout), + elfcpp::R_X86_64_TPOFF64); } else if (optimized_type != tls::TLSOPT_TO_LE) unsupported_reloc_global(object, r_type, gsym); @@ -2653,9 +2653,9 @@ Target_x86_64::Scan::global(Symbol_table* symtab, // Create a GOT entry for the tp-relative offset. Output_data_got<64, false>* got = target->got_section(symtab, layout); - got->add_global_with_rela(gsym, GOT_TYPE_TLS_OFFSET, - target->rela_dyn_section(layout), - elfcpp::R_X86_64_TPOFF64); + got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET, + target->rela_dyn_section(layout), + elfcpp::R_X86_64_TPOFF64); } else if (optimized_type != tls::TLSOPT_TO_LE) unsupported_reloc_global(object, r_type, gsym); |