diff options
author | Cary Coutant <ccoutant@google.com> | 2010-08-12 22:01:11 +0000 |
---|---|---|
committer | Cary Coutant <ccoutant@google.com> | 2010-08-12 22:01:11 +0000 |
commit | 09ec0418c0d4144afba5947499425e27900d953f (patch) | |
tree | b50da7eeed399f6421cdc6027cbf2dabd8652c83 /gold/reloc.cc | |
parent | 98bfdba52e7a8f7f9a19cafe59538341929be301 (diff) | |
download | gdb-09ec0418c0d4144afba5947499425e27900d953f.zip gdb-09ec0418c0d4144afba5947499425e27900d953f.tar.gz gdb-09ec0418c0d4144afba5947499425e27900d953f.tar.bz2 |
elfcpp/ChangeLog:
* elfcpp.h (enum SHT): Add SHT_GNU_INCREMENTAL_SYMTAB,
SHT_GNU_INCREMENTAL_RELOCS.
gold/ChangeLog:
* archive.cc: Include incremental.h.
(Archive::Archive): Initialize incremental_info_.
(Archive::include_member): Record archive members in incremental info.
(Add_archive_symbols::run): Record begin and end of an archive in
incremental info.
(Lib_group::include_member): Record objects in incremental info.
* archive.h (Incremental_archive_entry): Forward declaration.
(Archive::set_incremental_info): New member function.
(Archive::incremental_info): New member function.
(Archive::Unused_symbol_iterator): New class.
(Archive::unused_symbols_begin): New member function.
(Archive::unused_symbols_end): New member function.
(Archive::incremental_info_): New data member.
* incremental-dump.cc (find_input_containing_global): New function.
(dump_incremental_inputs): Dump new incremental info sections.
* incremental.cc: Include symtab.h.
(Output_section_incremental_inputs): New class.
(Sized_incremental_binary::do_find_incremental_inputs_sections): Support
new incremental info sections.
(Sized_incremental_binary::do_check_inputs): Likewise.
(Incremental_inputs::report_archive): Remove.
(Incremental_inputs::report_archive_begin): New function.
(Incremental_inputs::report_archive_end): New function.
(Incremental_inputs::report_object): New function.
(Incremental_inputs::finalize_inputs): Remove.
(Incremental_inputs::report_input_section): New function.
(Incremental_inputs::report_script): Rewrite.
(Incremental_inputs::finalize): Do nothing but finalize string table.
(Incremental_inputs::create_incremental_inputs_section_data): Remove.
(Incremental_inputs::sized_create_inputs_section_data): Remove.
(Incremental_inputs::create_data_sections): New function.
(Incremental_inputs::relocs_entsize): New function.
(Output_section_incremental_inputs::set_final_data_size): New function.
(Output_section_incremental_inputs::do_write): New function.
(Output_section_incremental_inputs::write_header): New function.
(Output_section_incremental_inputs::write_input_files): New function.
(Output_section_incremental_inputs::write_info_blocks): New function.
(Output_section_incremental_inputs::write_symtab): New function.
* incremental.h (Incremental_script_entry): Forward declaration.
(Incremental_object_entry): Forward declaration.
(Incremental_archive_entry): Forward declaration.
(Incremental_inputs): Forward declaration.
(Incremental_inputs_header_data): Remove.
(Incremental_inputs_header): Remove.
(Incremental_inputs_header_write): Remove.
(Incremental_inputs_entry_data): Remove.
(Incremental_inputs_entry): Remove.
(Incremental_inputs_entry_write): Remove.
(enum Incremental_input_type): Add INCREMENTAL_INPUT_ARCHIVE_MEMBER.
(Incremental_binary::find_incremental_inputs_sections): Add parameters.
(Incremental_binary::do_find_incremental_inputs_sections): Likewise.
(Sized_ncremental_binary::do_find_incremental_inputs_sections):
Likewise.
(Incremental_input_entry): New class.
(Incremental_script_entry): New class.
(Incremental_object_entry): New class.
(Incremental_archive_entry): New class.
(Incremental_inputs::Incremental_inputs): Initialize new data members.
(Incremental_inputs::report_inputs): Remove.
(Incremental_inputs::report_archive): Remove.
(Incremental_inputs::report_archive_begin): New function.
(Incremental_inputs::report_archive_end): New function.
(Incremental_inputs::report_object): Change prototype.
(Incremental_inputs::report_input_section): New function.
(Incremental_inputs::report_script): Change prototype.
(Incremental_inputs::get_reloc_count): New function.
(Incremental_inputs::set_reloc_count): New function.
(Incremental_inputs::create_data_sections): New function.
(Incremental_inputs::create_incremental_inputs_section_data): Remove.
(Incremental_inputs::inputs_section): New function.
(Incremental_inputs::symtab_section): New function.
(Incremental_inputs::relocs_section): New function.
(Incremental_inputs::get_stringpool): Add const.
(Incremental_inputs::command_line): Add const.
(Incremental_inputs::inputs): Remove.
(Incremental_inputs::command_line_key): New function.
(Incremental_inputs::input_file_count): New function.
(Incremental_inputs::input_files): New function.
(Incremental_inputs::relocs_entsize): New function.
(Incremental_inputs::sized_create_inputs_section_data): Remove.
(Incremental_inputs::finalize_inputs): Remove.
(Incremental_inputs::Input_info): Remove.
(Incremental_inputs::lock_): Remove.
(Incremental_inputs::inputs_): Change type.
(Incremental_inputs::inputs_map_): Remove.
(Incremental_inputs::current_object_entry_): New data member.
(Incremental_inputs::inputs_section_): New data member.
(Incremental_inputs::symtab_section_): New data member.
(Incremental_inputs::relocs_section_): New data member.
(Incremental_inputs::reloc_count_): New data member.
(Incremental_inputs_reader): New class.
(Incremental_symtab_reader): New class.
(Incremental_relocs_reader): New class.
* layout.cc (Layout::finalize): Move finalization of incremental info
and creation of incremental info sections to follow finalization of
symbol table. Set offsets for postprocessing sections.
(Layout::create_incremental_info_sections): Call
Incremental_inputs::create_data_sections. Add incremental symtab
and relocs sections. Set sh_entsize and sh_link fields. Arrange for
sections to layout after input sections.
* layout.h (struct Timespec): Forward declaration.
(Layout::incremental_inputs): Add const.
(Layout::create_incremental_info_sections): Add parameter.
* main.cc (main): Remove call to Incremental_inputs::report_inputs.
* object.cc: Include incremental.h.
(Relobj::finalize_incremental_relocs): New function.
(Sized_relobj::do_layout): Record input sections in incremental info.
* object.h (Object::output_section): New function.
(Object::output_section_offset): Moved from Relobj.
(Object::get_incremental_reloc_base): New function.
(Object::get_incremental_reloc_count): New function.
(Object::do_output_section): New function.
(Object::do_output_section_offset): Moved from Relobj.
(Object::do_get_incremental_reloc_base): New function.
(Object::do_get_incremental_reloc_count): New function.
(Object::Object): Initialize new data members.
(Relobj::output_section): Renamed do_output_section and moved to
protected.
(Relobj::output_section_offset): Moved to Object.
(Relobj::do_get_incremental_reloc_base): New function.
(Relobj::do_get_incremental_reloc_count): New function.
(Relobj::allocate_incremental_reloc_counts): New function.
(Relobj::count_incremental_reloc): New function.
(Relobj::finalize_incremental_relocs): New function.
(Relobj::next_incremental_reloc_index): New function.
(Relobj::reloc_counts_): New data member.
(Relobj::reloc_bases_): New data member.
(Sized_relobj::do_relocate_sections): Add parameter. Change caller.
(Sized_relobj::relocate_sections): Add parameter. Change all callers.
(Sized_relobj::incremental_relocs_scan): New function.
(Sized_relobj::incremental_relocs_scan_reltype): New function.
(Sized_relobj::incremental_relocs_write): New function.
(Sized_relobj::incremental_relocs_write_reltype): New function.
* plugin.cc (Plugin_manager::add_input_file): Rewrite test for
incremental link.
* readsyms.cc (Read_symbols::do_read_symbols): Move reporting of
archives and object files elsewhere.
(Add_symbols::run): Report object files here.
(Finish_group::run): Report end of archive at end of group.
* reloc.cc: Include layout.h, incremental.h.
(Sized_relobj::do_read_relocs): Need relocations for incremental link.
(Sized_relobj::do_scan_relocs): Record relocations for incremental link.
(Sized_relobj::incremental_relocs_scan): New function.
(Sized_relobj::incremental_relocs_scan_reltype): New function.
(Sized_relobj::do_relocate_sections): Write incremental relocations.
(Sized_relobj::incremental_relocs_write): New function.
(Sized_relobj::incremental_relocs_write_reltype): New function.
* script.cc (read_input_script): Rewrite test for incremental link.
Change call to Incremental_inputs::report_script.
* symtab.h (Symbol_table::first_global_index): New function.
(Symbol_table::output_count): New function.
Diffstat (limited to 'gold/reloc.cc')
-rw-r--r-- | gold/reloc.cc | 193 |
1 files changed, 191 insertions, 2 deletions
diff --git a/gold/reloc.cc b/gold/reloc.cc index 9f7355e..8938988 100644 --- a/gold/reloc.cc +++ b/gold/reloc.cc @@ -25,6 +25,7 @@ #include <algorithm> #include "workqueue.h" +#include "layout.h" #include "symtab.h" #include "output.h" #include "merge.h" @@ -33,6 +34,7 @@ #include "reloc.h" #include "icf.h" #include "compressed_output.h" +#include "incremental.h" namespace gold { @@ -300,7 +302,8 @@ Sized_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd) != 0); if (!is_section_allocated && !parameters->options().relocatable() - && !parameters->options().emit_relocs()) + && !parameters->options().emit_relocs() + && !parameters->options().incremental()) continue; if (this->adjust_shndx(shdr.get_sh_link()) != this->symtab_shndx_) @@ -424,6 +427,10 @@ Sized_relobj<size, big_endian>::do_scan_relocs(Symbol_table* symtab, else local_symbols = rd->local_symbols->data(); + // For incremental links, allocate the counters for incremental relocations. + if (layout->incremental_inputs() != NULL) + this->allocate_incremental_reloc_counts(); + for (Read_relocs_data::Relocs_list::iterator p = rd->relocs.begin(); p != rd->relocs.end(); ++p) @@ -451,6 +458,8 @@ Sized_relobj<size, big_endian>::do_scan_relocs(Symbol_table* symtab, local_symbols); if (parameters->options().emit_relocs()) this->emit_relocs_scan(symtab, layout, local_symbols, p); + if (layout->incremental_inputs() != NULL) + this->incremental_relocs_scan(p); } else { @@ -472,6 +481,10 @@ Sized_relobj<size, big_endian>::do_scan_relocs(Symbol_table* symtab, p->contents = NULL; } + // For incremental links, finalize the allocation of relocations. + if (layout->incremental_inputs() != NULL) + this->finalize_incremental_relocs(layout); + if (rd->local_symbols != NULL) { delete rd->local_symbols; @@ -567,6 +580,54 @@ Sized_relobj<size, big_endian>::emit_relocs_scan_reltype( rr); } +// Scan the input relocations for --incremental. + +template<int size, bool big_endian> +void +Sized_relobj<size, big_endian>::incremental_relocs_scan( + const Read_relocs_data::Relocs_list::iterator& p) +{ + if (p->sh_type == elfcpp::SHT_REL) + this->incremental_relocs_scan_reltype<elfcpp::SHT_REL>(p); + else + { + gold_assert(p->sh_type == elfcpp::SHT_RELA); + this->incremental_relocs_scan_reltype<elfcpp::SHT_RELA>(p); + } +} + +// Scan the input relocation for --emit-relocs, templatized on the +// type of the relocation section. + +template<int size, bool big_endian> +template<int sh_type> +void +Sized_relobj<size, big_endian>::incremental_relocs_scan_reltype( + const Read_relocs_data::Relocs_list::iterator& p) +{ + typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype; + const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size; + const unsigned char* prelocs = p->contents->data(); + size_t reloc_count = p->reloc_count; + + for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size) + { + Reltype reloc(prelocs); + + if (p->needs_special_offset_handling + && !p->output_section->is_input_address_mapped(this, p->data_shndx, + reloc.get_r_offset())) + continue; + + typename elfcpp::Elf_types<size>::Elf_WXword r_info = + reloc.get_r_info(); + const unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info); + + if (r_sym >= this->local_symbol_count_) + this->count_incremental_reloc(r_sym - this->local_symbol_count_); + } +} + // Relocate the input sections and write out the local symbols. template<int size, bool big_endian> @@ -597,7 +658,7 @@ Sized_relobj<size, big_endian>::do_relocate(const Symbol_table* symtab, // Apply relocations. - this->relocate_sections(symtab, layout, pshdrs, &views); + this->relocate_sections(symtab, layout, pshdrs, of, &views); // After we've done the relocations, we release the hash tables, // since we no longer need them. @@ -827,6 +888,7 @@ Sized_relobj<size, big_endian>::do_relocate_sections( const Symbol_table* symtab, const Layout* layout, const unsigned char* pshdrs, + Output_file* of, Views* pviews) { unsigned int shnum = this->shnum(); @@ -938,6 +1000,9 @@ Sized_relobj<size, big_endian>::do_relocate_sections( this->emit_relocs(&relinfo, i, sh_type, prelocs, reloc_count, os, output_offset, view, address, view_size, (*pviews)[i].view, (*pviews)[i].view_size); + if (parameters->options().incremental()) + this->incremental_relocs_write(&relinfo, sh_type, prelocs, + reloc_count, os, output_offset, of); } else { @@ -1020,6 +1085,126 @@ Sized_relobj<size, big_endian>::emit_relocs_reltype( reloc_view_size); } +// Write the incremental relocs. + +template<int size, bool big_endian> +void +Sized_relobj<size, big_endian>::incremental_relocs_write( + const Relocate_info<size, big_endian>* relinfo, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + Address output_offset, + Output_file* of) +{ + if (sh_type == elfcpp::SHT_REL) + this->incremental_relocs_write_reltype<elfcpp::SHT_REL>( + relinfo, + prelocs, + reloc_count, + output_section, + output_offset, + of); + else + { + gold_assert(sh_type == elfcpp::SHT_RELA); + this->incremental_relocs_write_reltype<elfcpp::SHT_RELA>( + relinfo, + prelocs, + reloc_count, + output_section, + output_offset, + of); + } +} + +// Write the incremental relocs, templatized on the type of the +// relocation section. + +template<int size, bool big_endian> +template<int sh_type> +void +Sized_relobj<size, big_endian>::incremental_relocs_write_reltype( + const Relocate_info<size, big_endian>* relinfo, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + Address output_offset, + Output_file* of) +{ + typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reloc; + const unsigned int reloc_size = + Reloc_types<sh_type, size, big_endian>::reloc_size; + const unsigned int sizeof_addr = size / 8; + const unsigned int incr_reloc_size = 8 + 2 * sizeof_addr; + + unsigned int out_shndx = output_section->out_shndx(); + + // Get a view for the .gnu_incremental_relocs section. + + Incremental_inputs* inputs = relinfo->layout->incremental_inputs(); + gold_assert(inputs != NULL); + const off_t relocs_off = inputs->relocs_section()->offset(); + const off_t relocs_size = inputs->relocs_section()->data_size(); + unsigned char* const view = of->get_output_view(relocs_off, relocs_size); + + for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size) + { + Reloc reloc(prelocs); + + typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info(); + const unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info); + const unsigned int r_type = elfcpp::elf_r_type<size>(r_info); + + if (r_sym < this->local_symbol_count_) + continue; + + // Get the new offset--the location in the output section where + // this relocation should be applied. + + Address offset = reloc.get_r_offset(); + if (output_offset != invalid_address) + offset += output_offset; + else + { + section_offset_type sot_offset = + convert_types<section_offset_type, Address>(offset); + section_offset_type new_sot_offset = + output_section->output_offset(relinfo->object, + relinfo->data_shndx, + sot_offset); + gold_assert(new_sot_offset != -1); + offset += new_sot_offset; + } + + // Get the addend. + typename elfcpp::Elf_types<size>::Elf_Swxword addend; + if (sh_type == elfcpp::SHT_RELA) + addend = + Reloc_types<sh_type, size, big_endian>::get_reloc_addend(&reloc); + else + { + // FIXME: Get the addend for SHT_REL. + addend = 0; + } + + // Get the index of the output relocation. + + unsigned int reloc_index = + this->next_incremental_reloc_index(r_sym - this->local_symbol_count_); + + // Write the relocation. + + unsigned char* pov = view + reloc_index * incr_reloc_size; + elfcpp::Swap<32, big_endian>::writeval(pov, r_type); + elfcpp::Swap<32, big_endian>::writeval(pov + 4, out_shndx); + elfcpp::Swap<size, big_endian>::writeval(pov + 8, offset); + elfcpp::Swap<size, big_endian>::writeval(pov + 8 + sizeof_addr, addend); + of->write_output_view(pov - view, incr_reloc_size, view); + } +} + // Create merge hash tables for the local symbols. These are used to // speed up relocations. @@ -1556,6 +1741,7 @@ Sized_relobj<32, false>::do_relocate_sections( const Symbol_table* symtab, const Layout* layout, const unsigned char* pshdrs, + Output_file* of, Views* pviews); #endif @@ -1566,6 +1752,7 @@ Sized_relobj<32, true>::do_relocate_sections( const Symbol_table* symtab, const Layout* layout, const unsigned char* pshdrs, + Output_file* of, Views* pviews); #endif @@ -1576,6 +1763,7 @@ Sized_relobj<64, false>::do_relocate_sections( const Symbol_table* symtab, const Layout* layout, const unsigned char* pshdrs, + Output_file* of, Views* pviews); #endif @@ -1586,6 +1774,7 @@ Sized_relobj<64, true>::do_relocate_sections( const Symbol_table* symtab, const Layout* layout, const unsigned char* pshdrs, + Output_file* of, Views* pviews); #endif |