Index: copy-relocs.cc =================================================================== RCS file: /cvs/src/src/gold/copy-relocs.cc,v retrieving revision 1.14 diff -p -u -r1.14 copy-relocs.cc --- copy-relocs.cc 8 Jun 2011 03:50:10 -0000 1.14 +++ copy-relocs.cc 17 Dec 2011 06:16:38 -0000 @@ -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 . // This file is part of gold. @@ -41,10 +41,10 @@ Copy_relocs:: // 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:: 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. Index: expression.cc =================================================================== RCS file: /cvs/src/src/gold/expression.cc,v retrieving revision 1.19 diff -p -u -r1.19 expression.cc --- expression.cc 31 Oct 2011 22:51:03 -0000 1.19 +++ expression.cc 17 Dec 2011 06:16:38 -0000 @@ -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 . // This file is part of gold. Index: incremental.h =================================================================== RCS file: /cvs/src/src/gold/incremental.h,v retrieving revision 1.29 diff -p -u -r1.29 incremental.h --- incremental.h 10 Oct 2011 17:38:07 -0000 1.29 +++ incremental.h 17 Dec 2011 06:16:39 -0000 @@ -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 . // This file is part of gold. @@ -1924,6 +1924,15 @@ class Sized_relobj_incr : public Sized_r 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 Index: object.cc =================================================================== RCS file: /cvs/src/src/gold/object.cc,v retrieving revision 1.150 diff -p -u -r1.150 object.cc --- object.cc 18 Sep 2011 15:06:28 -0000 1.150 +++ object.cc 17 Dec 2011 06:16:39 -0000 @@ -1819,7 +1819,8 @@ Sized_relobj_file::loc template unsigned int -Sized_relobj_file::local_plt_offset(unsigned int symndx) const +Sized_relobj_file::do_local_plt_offset( + unsigned int symndx) const { typename Local_plt_offsets::const_iterator p = this->local_plt_offsets_.find(symndx); Index: object.h =================================================================== RCS file: /cvs/src/src/gold/object.h,v retrieving revision 1.113 diff -p -u -r1.113 object.h --- object.h 1 Aug 2011 18:25:21 -0000 1.113 +++ object.h 17 Dec 2011 06:16:39 -0000 @@ -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 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(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 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_r 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_r 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* 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 Index: output.cc =================================================================== RCS file: /cvs/src/src/gold/output.cc,v retrieving revision 1.163 diff -p -u -r1.163 output.cc --- output.cc 18 Oct 2011 21:36:29 -0000 1.163 +++ output.cc 17 Dec 2011 06:16:41 -0000 @@ -1387,11 +1387,13 @@ Output_data_got::Got_e default: { - const Sized_relobj_file* object = this->u_.object; + const Relobj* object = this->u_.object; const unsigned int lsi = this->local_sym_index_; - const Symbol_value* 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(lval); + } else { uint64_t plt_address = @@ -1448,23 +1450,7 @@ void Output_data_got::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 -void -Output_data_got::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::add_g 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::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 -void -Output_data_got::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::add_g 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::add_g template bool Output_data_got::add_local( - Sized_relobj_file* object, + Relobj* object, unsigned int symndx, unsigned int got_type) { @@ -1543,7 +1510,7 @@ Output_data_got::add_l template bool Output_data_got::add_local_plt( - Sized_relobj_file* object, + Relobj* object, unsigned int symndx, unsigned int got_type) { @@ -1562,27 +1529,10 @@ Output_data_got::add_l template void Output_data_got::add_local_with_rel( - Sized_relobj_file* 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 -void -Output_data_got::add_local_with_rela( - Sized_relobj_file* 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::add_l 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::add_l template void Output_data_got::add_local_pair_with_rel( - Sized_relobj_file* 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 -void -Output_data_got::add_local_pair_with_rela( - Sized_relobj_file* 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::add_l 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 void Output_data_got::reserve_local( unsigned int i, - Sized_relobj* object, + Relobj* object, unsigned int sym_index, unsigned int got_type) { Index: output.h =================================================================== RCS file: /cvs/src/src/gold/output.h,v retrieving revision 1.131 diff -p -u -r1.131 output.h --- output.h 16 Dec 2011 23:47:03 -0000 1.131 +++ output.h 17 Dec 2011 06:16:41 -0000 @@ -1397,6 +1397,55 @@ class Output_data_reloc_generic : public 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_relocadd(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), + false, false)); } void - add_global(Symbol* gsym, unsigned int type, Output_data* od, - Sized_relobj* 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* sized_relobj = + static_cast*>(relobj); + this->add(od, Output_reloc_type(gsym, type, sized_relobj, shndx, + convert_types(address), + false, false)); } // Add a RELATIVE reloc against a global symbol. The final relocation @@ -1592,6 +1645,32 @@ class Output_data_reloc* sized_relobj = + static_cast *>(relobj); + this->add(od, Output_reloc_type(sized_relobj, local_sym_index, type, od, + convert_types(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* sized_relobj = + static_cast*>(relobj); + this->add(od, Output_reloc_type(sized_relobj, local_sym_index, type, shndx, + convert_types(address), + false, false, false, false)); + } + // Add a RELATIVE reloc against a local symbol. void @@ -1671,6 +1750,29 @@ class Output_data_relocadd(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))); + } + + 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* sized_relobj = + static_cast*>(relobj); + this->add(od, Output_reloc_type(os, type, sized_relobj, shndx, + convert_types(address))); + } + // Add an absolute relocation. void @@ -1733,6 +1835,29 @@ class Output_data_relocadd(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), + convert_types(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* sized_relobj = + static_cast*>(relobj); + this->add(od, Output_reloc_type(gsym, type, sized_relobj, shndx, + convert_types(address), + convert_types(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* sized_relobj = + static_cast *>(relobj); + this->add(od, Output_reloc_type(sized_relobj, local_sym_index, type, od, + convert_types(address), + convert_types(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* sized_relobj = + static_cast*>(relobj); + this->add(od, Output_reloc_type(sized_relobj, local_sym_index, type, shndx, + convert_types(address), + convert_types(addend), + false, false, false, false)); + } + // Add a RELATIVE reloc against a local symbol. void @@ -1875,6 +2026,29 @@ class Output_data_relocadd(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), + convert_types(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* sized_relobj = + static_cast*>(relobj); + this->add(od, Output_reloc_type(os, type, sized_relobj, shndx, + convert_types(address), + convert_types(addend))); + } + // Add an absolute relocation. void @@ -1974,29 +2148,28 @@ class Output_data_group : public Output_ // 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 +template class Output_data_got : public Output_section_data_build { public: - typedef typename elfcpp::Elf_types::Elf_Addr Valtype; - typedef Output_data_reloc Rel_dyn; - typedef Output_data_reloc Rela_dyn; + typedef typename elfcpp::Elf_types::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_se // 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* 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* 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* 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* 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* 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* 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_se // 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* 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_se { this->u_.gsym = gsym; } // Create a local symbol entry. - Got_entry(Sized_relobj_file* 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_se union { // For a local symbol, the object. - Sized_relobj_file* 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_se // 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 Index: powerpc.cc =================================================================== RCS file: /cvs/src/src/gold/powerpc.cc,v retrieving revision 1.40 diff -p -u -r1.40 powerpc.cc --- powerpc.cc 10 Oct 2011 17:29:52 -0000 1.40 +++ powerpc.cc 17 Dec 2011 06:16:41 -0000 @@ -1566,8 +1566,8 @@ Target_powerpc::Scan:: 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); Index: sparc.cc =================================================================== RCS file: /cvs/src/src/gold/sparc.cc,v retrieving revision 1.50 diff -p -u -r1.50 sparc.cc --- sparc.cc 19 Oct 2011 00:32:24 -0000 1.50 +++ sparc.cc 17 Dec 2011 06:16:41 -0000 @@ -1998,14 +1998,14 @@ Target_sparc::Scan::lo 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::Scan::gl 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::Scan::gl // dtv-relative offset. Output_data_got* 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::Scan::gl // Create a GOT entry for the tp-relative offset. Output_data_got* 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::Scan::gl // Create a GOT entry for the tp-relative offset. Output_data_got* 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); Index: x86_64.cc =================================================================== RCS file: /cvs/src/src/gold/x86_64.cc,v retrieving revision 1.141 diff -p -u -r1.141 x86_64.cc --- x86_64.cc 31 Oct 2011 22:33:04 -0000 1.141 +++ x86_64.cc 17 Dec 2011 06:16:42 -0000 @@ -2137,11 +2137,11 @@ Target_x86_64::Scan::local(Symbol_table* 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* 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 && 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 // 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 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 // 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);