X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gold%2Foutput.cc;h=077e2c4481ecb8445028c773eba51506846e957e;hb=712ec27916b5604d29d928dec060fd1ba0fd9edb;hp=f34a7d82573e7aab10e56912d46c44693a8fb3d4;hpb=cfbf0e3c5b637d66b2b1aeadecae9c187b825b2f;p=deliverable%2Fbinutils-gdb.git diff --git a/gold/output.cc b/gold/output.cc index f34a7d8257..077e2c4481 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -1,6 +1,6 @@ // output.cc -- manage the output file for gold -// Copyright (C) 2006-2015 Free Software Foundation, Inc. +// Copyright (C) 2006-2016 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // This file is part of gold. @@ -1252,6 +1252,19 @@ Output_data_reloc_base os->set_should_link_to_dynsym(); } +// Standard relocation writer, which just calls Output_reloc::write(). + +template +struct Output_reloc_writer +{ + typedef Output_reloc Output_reloc_type; + typedef std::vector Relocs; + + static void + write(typename Relocs::const_iterator p, unsigned char* pov) + { p->write(pov); } +}; + // Write out relocation data. template @@ -1259,32 +1272,8 @@ void Output_data_reloc_base::do_write( Output_file* of) { - const off_t off = this->offset(); - const off_t oview_size = this->data_size(); - unsigned char* const oview = of->get_output_view(off, oview_size); - - if (this->sort_relocs()) - { - gold_assert(dynamic); - std::sort(this->relocs_.begin(), this->relocs_.end(), - Sort_relocs_comparison()); - } - - unsigned char* pov = oview; - for (typename Relocs::const_iterator p = this->relocs_.begin(); - p != this->relocs_.end(); - ++p) - { - p->write(pov); - pov += reloc_size; - } - - gold_assert(pov - oview == oview_size); - - of->write_output_view(off, oview_size, oview); - - // We no longer need the relocation entries. - this->relocs_.clear(); + typedef Output_reloc_writer Writer; + this->do_write_generic(of); } // Class Output_relocatable_relocs. @@ -1437,7 +1426,7 @@ Output_data_got::Got_entry::write( val = parameters->target().plt_address_for_local(object, lsi); else { - uint64_t lval = object->local_symbol_value(lsi, 0); + uint64_t lval = object->local_symbol_value(lsi, this->addend_); val = convert_types(lval); if (this->use_plt_or_tls_offset_ && is_tls) val += parameters->target().tls_offset_for_local(object, lsi, @@ -1548,6 +1537,27 @@ Output_data_got::add_local( return true; } +// Add an entry for a local symbol plus ADDEND to the GOT. This returns +// true if this is a new GOT entry, false if the symbol already has a GOT +// entry. + +template +bool +Output_data_got::add_local( + Relobj* object, + unsigned int symndx, + unsigned int got_type, + uint64_t addend) +{ + if (object->local_has_got_offset(symndx, got_type, addend)) + return false; + + unsigned int got_offset = this->add_got_entry(Got_entry(object, symndx, + false, addend)); + object->set_local_got_offset(symndx, got_type, got_offset, addend); + return true; +} + // Like add_local, but use the PLT offset. template @@ -1586,6 +1596,27 @@ Output_data_got::add_local_with_rel( rel_dyn->add_local_generic(object, symndx, r_type, this, got_offset, 0); } +// Add an entry for a local symbol plus ADDEND to the GOT, and add a dynamic +// relocation of type R_TYPE for the GOT entry. + +template +void +Output_data_got::add_local_with_rel( + Relobj* object, + unsigned int symndx, + unsigned int got_type, + Output_data_reloc_generic* rel_dyn, + unsigned int r_type, uint64_t addend) +{ + if (object->local_has_got_offset(symndx, got_type, addend)) + return; + + unsigned int got_offset = this->add_got_entry(Got_entry()); + object->set_local_got_offset(symndx, got_type, got_offset, addend); + rel_dyn->add_local_generic(object, symndx, r_type, this, got_offset, + addend); +} + // Add a pair of entries for a local symbol to the GOT, and add // a dynamic relocation of type R_TYPE using the section symbol of // the output section to which input section SHNDX maps, on the first. @@ -1612,6 +1643,32 @@ Output_data_got::add_local_pair_with_rel( rel_dyn->add_output_section_generic(os, r_type, this, got_offset, 0); } +// Add a pair of entries for a local symbol plus ADDEND to the GOT, and add +// a dynamic relocation of type R_TYPE using the section symbol of +// the output section to which input section SHNDX maps, on the first. +// The first got entry will have a value of zero, the second the +// value of the local symbol. +template +void +Output_data_got::add_local_pair_with_rel( + Relobj* object, + unsigned int symndx, + unsigned int shndx, + unsigned int got_type, + Output_data_reloc_generic* rel_dyn, + unsigned int r_type, uint64_t addend) +{ + if (object->local_has_got_offset(symndx, got_type, addend)) + return; + + unsigned int got_offset = + this->add_got_entry_pair(Got_entry(), + Got_entry(object, symndx, false, addend)); + object->set_local_got_offset(symndx, got_type, got_offset, addend); + Output_section* os = object->output_section(shndx); + rel_dyn->add_output_section_generic(os, r_type, this, got_offset, addend); +} + // Add a pair of entries for a local symbol to the GOT, and add // a dynamic relocation of type R_TYPE using STN_UNDEF on the first. // The first got entry will have a value of zero, the second the @@ -3503,7 +3560,7 @@ Output_section::update_section_layout( if (p->is_input_section() || p->is_relaxed_input_section()) { - Object* obj = (p->is_input_section() + Relobj* obj = (p->is_input_section() ? p->relobj() : p->relaxed_input_section()->relobj()); unsigned int shndx = p->shndx();