diff options
author | Cary Coutant <ccoutant@google.com> | 2011-04-05 20:16:17 +0000 |
---|---|---|
committer | Cary Coutant <ccoutant@google.com> | 2011-04-05 20:16:17 +0000 |
commit | b961d0d7b65a2bdfd465f774db948c199fddaa06 (patch) | |
tree | fac883ba6bfa4b2a6bb87a79326f3b5747590140 /gold | |
parent | a869183fab276723f2f7eb55af604e106007285f (diff) | |
download | gdb-b961d0d7b65a2bdfd465f774db948c199fddaa06.zip gdb-b961d0d7b65a2bdfd465f774db948c199fddaa06.tar.gz gdb-b961d0d7b65a2bdfd465f774db948c199fddaa06.tar.bz2 |
* incremental-dump.cc (dump_incremental_inputs): Change signature
to take a Sized_incremental_binary; change caller. Use readers
in Sized_incremental_binary.
* incremental.cc
(Sized_incremental_binary::find_incremental_inputs_sections):
Rename do_find_incremental_inputs_sections to this.
(Sized_incremental_binary::setup_readers): New function.
(Sized_incremental_binary::do_check_inputs): Check
has_incremental_info_ flag; move setup code to setup_readers;
use input readers.
(Sized_incremental_binary::do_file_is_unchanged): New function.
(Sized_incremental_binary::do_get_input_reader): New function.
* incremental.h (class Incremental_binary): Move to end of file.
(Incremental_binary::file_is_unchanged): New function.
(Incremental_binary::do_file_is_unchanged): New function.
(Incremental_binary::Input_reader): New class.
(Incremental_binary::get_input_reader): New function.
(class Sized_incremental_binary): Move to end of file.
(Sized_incremental_binary::Sized_incremental_binary): Setup the
input section reader classes.
(Sized_incremental_binary::has_incremental_info): New function.
(Sized_incremental_binary::inputs_reader): New function.
(Sized_incremental_binary::symtab_reader): New function.
(Sized_incremental_binary::relocs_reader): New function.
(Sized_incremental_binary::got_plt_reader): New function.
(Sized_incremental_binary::do_file_is_unchanged): New function.
(Sized_incremental_binary::Sized_input_reader): New class.
(Sized_incremental_binary::get_input_reader): New function.
(Sized_incremental_binary::find_incremental_inputs_sections):
Rename do_find_incremental_inputs_sections to this.
(Sized_incremental_binary::setup_readers): New function.
(Sized_incremental_binary::has_incremental_info_): New data member.
(Sized_incremental_binary::inputs_reader_): New data member.
(Sized_incremental_binary::symtab_reader_): New data member.
(Sized_incremental_binary::relocs_reader_): New data member.
(Sized_incremental_binary::got_plt_reader_): New data member.
(Sized_incremental_binary::current_input_file_): New data member.
Diffstat (limited to 'gold')
-rw-r--r-- | gold/ChangeLog | 40 | ||||
-rw-r--r-- | gold/incremental-dump.cc | 74 | ||||
-rw-r--r-- | gold/incremental.cc | 96 | ||||
-rw-r--r-- | gold/incremental.h | 429 |
4 files changed, 417 insertions, 222 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index ec59508..98c7a6f 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,43 @@ +2011-04-05 Cary Coutant <ccoutant@google.com> + + * incremental-dump.cc (dump_incremental_inputs): Change signature + to take a Sized_incremental_binary; change caller. Use readers + in Sized_incremental_binary. + * incremental.cc + (Sized_incremental_binary::find_incremental_inputs_sections): + Rename do_find_incremental_inputs_sections to this. + (Sized_incremental_binary::setup_readers): New function. + (Sized_incremental_binary::do_check_inputs): Check + has_incremental_info_ flag; move setup code to setup_readers; + use input readers. + (Sized_incremental_binary::do_file_is_unchanged): New function. + (Sized_incremental_binary::do_get_input_reader): New function. + * incremental.h (class Incremental_binary): Move to end of file. + (Incremental_binary::file_is_unchanged): New function. + (Incremental_binary::do_file_is_unchanged): New function. + (Incremental_binary::Input_reader): New class. + (Incremental_binary::get_input_reader): New function. + (class Sized_incremental_binary): Move to end of file. + (Sized_incremental_binary::Sized_incremental_binary): Setup the + input section reader classes. + (Sized_incremental_binary::has_incremental_info): New function. + (Sized_incremental_binary::inputs_reader): New function. + (Sized_incremental_binary::symtab_reader): New function. + (Sized_incremental_binary::relocs_reader): New function. + (Sized_incremental_binary::got_plt_reader): New function. + (Sized_incremental_binary::do_file_is_unchanged): New function. + (Sized_incremental_binary::Sized_input_reader): New class. + (Sized_incremental_binary::get_input_reader): New function. + (Sized_incremental_binary::find_incremental_inputs_sections): + Rename do_find_incremental_inputs_sections to this. + (Sized_incremental_binary::setup_readers): New function. + (Sized_incremental_binary::has_incremental_info_): New data member. + (Sized_incremental_binary::inputs_reader_): New data member. + (Sized_incremental_binary::symtab_reader_): New data member. + (Sized_incremental_binary::relocs_reader_): New data member. + (Sized_incremental_binary::got_plt_reader_): New data member. + (Sized_incremental_binary::current_input_file_): New data member. + 2011-04-05 Paul Pluzhnikov <ppluzhnikov@google.com> PR gold/12640 diff --git a/gold/incremental-dump.cc b/gold/incremental-dump.cc index e59b1c5..6f79f4d 100644 --- a/gold/incremental-dump.cc +++ b/gold/incremental-dump.cc @@ -73,48 +73,24 @@ find_input_containing_global( template<int size, bool big_endian> static void dump_incremental_inputs(const char* argv0, const char* filename, - Incremental_binary* inc) + Sized_incremental_binary<size, big_endian>* inc) { - bool t; - unsigned int inputs_shndx; - unsigned int isymtab_shndx; - unsigned int irelocs_shndx; - unsigned int igot_plt_shndx; - unsigned int istrtab_shndx; typedef Incremental_binary::Location Location; typedef Incremental_binary::View View; typedef Incremental_inputs_reader<size, big_endian> Inputs_reader; typedef typename Inputs_reader::Incremental_input_entry_reader Entry_reader; - // Find the .gnu_incremental_inputs, _symtab, _relocs, and _strtab sections. - - t = inc->find_incremental_inputs_sections(&inputs_shndx, &isymtab_shndx, - &irelocs_shndx, &igot_plt_shndx, - &istrtab_shndx); - if (!t) + if (!inc->has_incremental_info()) { fprintf(stderr, "%s: %s: no .gnu_incremental_inputs section\n", argv0, filename); exit(1); } - elfcpp::Elf_file<size, big_endian, Incremental_binary> elf_file(inc); - - // Get a view of the .gnu_incremental_inputs section. - - Location inputs_location(elf_file.section_contents(inputs_shndx)); - View inputs_view(inc->view(inputs_location)); - - // Get the .gnu_incremental_strtab section as a string table. - - Location istrtab_location(elf_file.section_contents(istrtab_shndx)); - View istrtab_view(inc->view(istrtab_location)); - elfcpp::Elf_strtab istrtab(istrtab_view.data(), istrtab_location.data_size); - // Create a reader object for the .gnu_incremental_inputs section. Incremental_inputs_reader<size, big_endian> - incremental_inputs(inputs_view.data(), istrtab); + incremental_inputs(inc->inputs_reader()); if (incremental_inputs.version() != 1) { @@ -265,6 +241,8 @@ dump_incremental_inputs(const char* argv0, const char* filename, // Get a view of the .symtab section. + elfcpp::Elf_file<size, big_endian, Incremental_binary> elf_file(inc); + unsigned int symtab_shndx = elf_file.find_section_by_type(elfcpp::SHT_SYMTAB); if (symtab_shndx == elfcpp::SHN_UNDEF) // Not found. { @@ -288,16 +266,6 @@ dump_incremental_inputs(const char* argv0, const char* filename, View strtab_view(inc->view(strtab_location)); elfcpp::Elf_strtab strtab(strtab_view.data(), strtab_location.data_size); - // Get a view of the .gnu_incremental_symtab section. - - Location isymtab_location(elf_file.section_contents(isymtab_shndx)); - View isymtab_view(inc->view(isymtab_location)); - - // Get a view of the .gnu_incremental_relocs section. - - Location irelocs_location(elf_file.section_contents(irelocs_shndx)); - View irelocs_view(inc->view(irelocs_location)); - // The .gnu_incremental_symtab section contains entries that parallel // the global symbols of the main symbol table. The sh_info field // of the main symbol table's section header tells us how many global @@ -306,15 +274,13 @@ dump_incremental_inputs(const char* argv0, const char* filename, // use the size of the .gnu_incremental_symtab section to deduce // the number of global symbols + forced-local symbols there are // in the symbol table. + Incremental_symtab_reader<big_endian> isymtab(inc->symtab_reader()); + Incremental_relocs_reader<size, big_endian> irelocs(inc->relocs_reader()); unsigned int sym_size = elfcpp::Elf_sizes<size>::sym_size; unsigned int nsyms = symtab_location.data_size / sym_size; - unsigned int nglobals = isymtab_location.data_size / 4; + unsigned int nglobals = isymtab.symbol_count(); unsigned int first_global = nsyms - nglobals; unsigned const char* sym_p = symtab_view.data() + first_global * sym_size; - unsigned const char* isym_p = isymtab_view.data(); - - Incremental_symtab_reader<big_endian> isymtab(isymtab_view.data()); - Incremental_relocs_reader<size, big_endian> irelocs(irelocs_view.data()); printf("\nGlobal symbol table:\n"); for (unsigned int i = 0; i < nglobals; i++) @@ -356,15 +322,9 @@ dump_incremental_inputs(const char* argv0, const char* filename, offset = sym_info.next_offset; } sym_p += sym_size; - isym_p += 4; } - // Get a view of the .gnu_incremental_got_plt section. - - Location igot_plt_location(elf_file.section_contents(igot_plt_shndx)); - View igot_plt_view(inc->view(igot_plt_location)); - - Incremental_got_plt_reader<big_endian> igot_plt(igot_plt_view.data()); + Incremental_got_plt_reader<big_endian> igot_plt(inc->got_plt_reader()); unsigned int ngot = igot_plt.get_got_entry_count(); unsigned int nplt = igot_plt.get_plt_entry_count(); @@ -464,22 +424,30 @@ main(int argc, char** argv) { #ifdef HAVE_TARGET_32_LITTLE case Parameters::TARGET_32_LITTLE: - dump_incremental_inputs<32, false>(argv[0], filename, inc); + dump_incremental_inputs<32, false>( + argv[0], filename, + static_cast<Sized_incremental_binary<32, false>*>(inc)); break; #endif #ifdef HAVE_TARGET_32_BIG case Parameters::TARGET_32_BIG: - dump_incremental_inputs<32, true>(argv[0], filename, inc); + dump_incremental_inputs<32, true>( + argv[0], filename, + static_cast<Sized_incremental_binary<32, true>*>(inc)); break; #endif #ifdef HAVE_TARGET_64_LITTLE case Parameters::TARGET_64_LITTLE: - dump_incremental_inputs<64, false>(argv[0], filename, inc); + dump_incremental_inputs<64, false>( + argv[0], filename, + static_cast<Sized_incremental_binary<64, false>*>(inc)); break; #endif #ifdef HAVE_TARGET_64_BIG case Parameters::TARGET_64_BIG: - dump_incremental_inputs<64, true>(argv[0], filename, inc); + dump_incremental_inputs<64, true>( + argv[0], filename, + static_cast<Sized_incremental_binary<64, true>*>(inc)); break; #endif default: diff --git a/gold/incremental.cc b/gold/incremental.cc index e5f71f5..a38b12b 100644 --- a/gold/incremental.cc +++ b/gold/incremental.cc @@ -154,7 +154,7 @@ Incremental_binary::error(const char* format, ...) const template<int size, bool big_endian> bool -Sized_incremental_binary<size, big_endian>::do_find_incremental_inputs_sections( +Sized_incremental_binary<size, big_endian>::find_incremental_inputs_sections( unsigned int* p_inputs_shndx, unsigned int* p_symtab_shndx, unsigned int* p_relocs_shndx, @@ -206,60 +206,108 @@ Sized_incremental_binary<size, big_endian>::do_find_incremental_inputs_sections( return true; } -// Determine whether an incremental link based on the existing output file -// can be done. +// Set up the readers into the incremental info sections. template<int size, bool big_endian> -bool -Sized_incremental_binary<size, big_endian>::do_check_inputs( - Incremental_inputs* incremental_inputs) +void +Sized_incremental_binary<size, big_endian>::setup_readers() { unsigned int inputs_shndx; unsigned int symtab_shndx; unsigned int relocs_shndx; - unsigned int plt_got_shndx; + unsigned int got_plt_shndx; unsigned int strtab_shndx; - if (!do_find_incremental_inputs_sections(&inputs_shndx, &symtab_shndx, - &relocs_shndx, &plt_got_shndx, - &strtab_shndx)) - { - explain_no_incremental(_("no incremental data from previous build")); - return false; - } + if (!this->find_incremental_inputs_sections(&inputs_shndx, &symtab_shndx, + &relocs_shndx, &got_plt_shndx, + &strtab_shndx)) + return; Location inputs_location(this->elf_file_.section_contents(inputs_shndx)); Location symtab_location(this->elf_file_.section_contents(symtab_shndx)); Location relocs_location(this->elf_file_.section_contents(relocs_shndx)); + Location got_plt_location(this->elf_file_.section_contents(got_plt_shndx)); Location strtab_location(this->elf_file_.section_contents(strtab_shndx)); - View inputs_view(view(inputs_location)); - View symtab_view(view(symtab_location)); - View relocs_view(view(relocs_location)); - View strtab_view(view(strtab_location)); + View inputs_view = this->view(inputs_location); + View symtab_view = this->view(symtab_location); + View relocs_view = this->view(relocs_location); + View got_plt_view = this->view(got_plt_location); + View strtab_view = this->view(strtab_location); elfcpp::Elf_strtab strtab(strtab_view.data(), strtab_location.data_size); - Incremental_inputs_reader<size, big_endian> - incoming_inputs(inputs_view.data(), strtab); + this->inputs_reader_ = + Incremental_inputs_reader<size, big_endian>(inputs_view.data(), strtab); + this->symtab_reader_ = + Incremental_symtab_reader<big_endian>(symtab_view.data(), + symtab_location.data_size); + this->relocs_reader_ = + Incremental_relocs_reader<size, big_endian>(relocs_view.data(), + relocs_location.data_size); + this->got_plt_reader_ = + Incremental_got_plt_reader<big_endian>(got_plt_view.data()); + this->has_incremental_info_ = true; +} + +// Determine whether an incremental link based on the existing output file +// can be done. + +template<int size, bool big_endian> +bool +Sized_incremental_binary<size, big_endian>::do_check_inputs( + Incremental_inputs* incremental_inputs) +{ + if (!this->has_incremental_info_) + { + explain_no_incremental(_("no incremental data from previous build")); + return false; + } - if (incoming_inputs.version() != INCREMENTAL_LINK_VERSION) + if (this->inputs_reader_.version() != INCREMENTAL_LINK_VERSION) { explain_no_incremental(_("different version of incremental build data")); return false; } - if (incremental_inputs->command_line() != incoming_inputs.command_line()) + if (incremental_inputs->command_line() != this->inputs_reader_.command_line()) { explain_no_incremental(_("command line changed")); return false; } - // TODO: compare incremental_inputs->inputs() with entries in data_view. - return true; } +// Return TRUE if the file specified by INPUT_ARGUMENT is unchanged +// with respect to the base file. + +template<int size, bool big_endian> +bool +Sized_incremental_binary<size, big_endian>::do_file_is_unchanged( + const Input_argument* input_argument) const +{ + Incremental_disposition disp = + input_argument->file().options().incremental_disposition(); + + if (disp != INCREMENTAL_CHECK) + return disp == INCREMENTAL_UNCHANGED; + + // FIXME: Handle INCREMENTAL_CHECK. + return false; +} + + +template<int size, bool big_endian> +Incremental_binary::Input_reader* +Sized_incremental_binary<size, big_endian>::do_get_input_reader( + const char*) +{ + unsigned int file_index = this->current_input_file_++; + gold_assert(file_index < this->inputs_reader_.input_file_count()); + return new Sized_input_reader(this->inputs_reader_.input_file(file_index)); +} + namespace { diff --git a/gold/incremental.h b/gold/incremental.h index b799f7b..815f761 100644 --- a/gold/incremental.h +++ b/gold/incremental.h @@ -42,6 +42,7 @@ class Incremental_script_entry; class Incremental_object_entry; class Incremental_archive_entry; class Incremental_inputs; +class Incremental_binary; class Object; // Incremental input type as stored in .gnu_incremental_inputs. @@ -55,147 +56,6 @@ enum Incremental_input_type INCREMENTAL_INPUT_SCRIPT = 5 }; -// An object representing the ELF file we edit during an incremental build. -// Similar to Object or Dynobj, but operates on Output_file and contains -// method specific to file edition (TBD). This is the abstract parent class -// implemented in Sized_incremental_binary<size, big_endian> for a specific -// endianness and size. - -class Incremental_binary -{ - public: - Incremental_binary(Output_file* output, Target* target) - : output_(output), target_(target) - { } - - virtual - ~Incremental_binary() - { } - - // Functions and types for the elfcpp::Elf_file interface. This - // permit us to use Incremental_binary as the File template parameter for - // elfcpp::Elf_file. - - // The View class is returned by view. It must support a single - // method, data(). This is trivial, because Output_file::get_output_view - // does what we need. - class View - { - public: - View(const unsigned char* p) - : p_(p) - { } - - const unsigned char* - data() const - { return this->p_; } - - private: - const unsigned char* p_; - }; - - // Return a View. - View - view(off_t file_offset, section_size_type data_size) - { return View(this->output_->get_input_view(file_offset, data_size)); } - - // A location in the file. - struct Location - { - off_t file_offset; - off_t data_size; - - Location(off_t fo, section_size_type ds) - : file_offset(fo), data_size(ds) - { } - - Location() - : file_offset(0), data_size(0) - { } - }; - - // Get a View given a Location. - View - view(Location loc) - { return View(this->view(loc.file_offset, loc.data_size)); } - - // Report an error. - void - error(const char* format, ...) const ATTRIBUTE_PRINTF_2; - - // Find the .gnu_incremental_inputs and related sections. It selects the - // first section of type SHT_GNU_INCREMENTAL_INPUTS, - // SHT_GNU_INCREMENTAL_SYMTAB, and SHT_GNU_INCREMENTAL_RELOCS. - // Returns false if the sections are not found. - bool - find_incremental_inputs_sections(unsigned int* p_inputs_shndx, - unsigned int* p_symtab_shndx, - unsigned int* p_relocs_shndx, - unsigned int* p_got_plt_shndx, - unsigned int* p_strtab_shndx) - { - return do_find_incremental_inputs_sections(p_inputs_shndx, p_symtab_shndx, - p_relocs_shndx, p_got_plt_shndx, - p_strtab_shndx); - } - - // Check the .gnu_incremental_inputs section to see whether an incremental - // build is possible. - // TODO: on success, should report what files needs to be rebuilt. - // INCREMENTAL_INPUTS is used to read the canonical form of the command line - // and read the input arguments. TODO: for items that don't need to be - // rebuilt, we should also copy the incremental input information. - virtual bool - check_inputs(Incremental_inputs* incremental_inputs) - { return do_check_inputs(incremental_inputs); } - - protected: - // Find incremental inputs section. - virtual bool - do_find_incremental_inputs_sections(unsigned int* p_inputs_shndx, - unsigned int* p_symtab_shndx, - unsigned int* p_relocs_shndx, - unsigned int* p_got_plt_shndx, - unsigned int* p_strtab_shndx) = 0; - - // Check the .gnu_incremental_inputs section to see whether an incremental - // build is possible. - virtual bool - do_check_inputs(Incremental_inputs* incremental_inputs) = 0; - - private: - // Edited output file object. - Output_file* output_; - // Target of the output file. - Target* target_; -}; - -template<int size, bool big_endian> -class Sized_incremental_binary : public Incremental_binary -{ - public: - Sized_incremental_binary(Output_file* output, - const elfcpp::Ehdr<size, big_endian>& ehdr, - Target* target) - : Incremental_binary(output, target), elf_file_(this, ehdr) - { } - - protected: - virtual bool - do_find_incremental_inputs_sections(unsigned int* p_inputs_shndx, - unsigned int* p_symtab_shndx, - unsigned int* p_relocs_shndx, - unsigned int* p_got_plt_shndx, - unsigned int* p_strtab_shndx); - - virtual bool - do_check_inputs(Incremental_inputs* incremental_inputs); - - private: - // Output as an ELF file. - elfcpp::Elf_file<size, big_endian, Incremental_binary> elf_file_; -}; - // Create an Incremental_binary object for FILE. Returns NULL is this is not // possible, e.g. FILE is not an ELF file or has an unsupported target. @@ -689,7 +549,12 @@ class Incremental_inputs_reader typedef elfcpp::Swap<64, big_endian> Swap64; public: - Incremental_inputs_reader(const unsigned char* p, elfcpp::Elf_strtab& strtab) + Incremental_inputs_reader() + : p_(NULL), strtab_(NULL, 0), input_file_count_(0) + { } + + Incremental_inputs_reader(const unsigned char* p, + const elfcpp::Elf_strtab& strtab) : p_(p), strtab_(strtab) { this->input_file_count_ = Swap32::readval(this->p_ + 4); } @@ -939,16 +804,29 @@ template<bool big_endian> class Incremental_symtab_reader { public: - Incremental_symtab_reader(const unsigned char* p) : p_(p) + Incremental_symtab_reader() + : p_(NULL), len_(0) + { } + + Incremental_symtab_reader(const unsigned char* p, off_t len) + : p_(p), len_(len) { } + // Return the count of symbols in this section. + unsigned int + symbol_count() const + { return static_cast<unsigned int>(this->len_ / 4); } + // Return the list head for symbol table entry N. - unsigned int get_list_head(unsigned int n) const + unsigned int + get_list_head(unsigned int n) const { return elfcpp::Swap<32, big_endian>::readval(this->p_ + 4 * n); } private: // Base address of the .gnu_incremental_relocs section. const unsigned char* p_; + // Size of the section. + off_t len_; }; // Reader class for the .gnu_incremental_relocs section. @@ -967,9 +845,19 @@ class Incremental_relocs_reader // Size of each entry. static const unsigned int reloc_size = 8 + 2 * field_size; - Incremental_relocs_reader(const unsigned char* p) : p_(p) + Incremental_relocs_reader() + : p_(NULL), len_(0) + { } + + Incremental_relocs_reader(const unsigned char* p, off_t len) + : p_(p), len_(len) { } + // Return the count of relocations in this section. + unsigned int + reloc_count() const + { return static_cast<unsigned int>(this->len_ / reloc_size); } + // Return the relocation type for relocation entry at offset OFF. unsigned int get_r_type(unsigned int off) const @@ -1002,6 +890,8 @@ class Incremental_relocs_reader private: // Base address of the .gnu_incremental_relocs section. const unsigned char* p_; + // Size of the section. + off_t len_; }; // Reader class for the .gnu_incremental_got_plt section. @@ -1010,6 +900,10 @@ template<bool big_endian> class Incremental_got_plt_reader { public: + Incremental_got_plt_reader() + : p_(NULL), got_count_(0), got_desc_p_(NULL), plt_desc_p_(NULL) + { } + Incremental_got_plt_reader(const unsigned char* p) : p_(p) { this->got_count_ = elfcpp::Swap<32, big_endian>::readval(p); @@ -1063,6 +957,251 @@ class Incremental_got_plt_reader const unsigned char* plt_desc_p_; }; +// An object representing the ELF file we edit during an incremental build. +// Similar to Object or Dynobj, but operates on Output_file and contains +// methods to support incremental updating. This is the abstract parent class +// implemented in Sized_incremental_binary<size, big_endian> for a specific +// endianness and size. + +class Incremental_binary +{ + public: + Incremental_binary(Output_file* output, Target* target) + : output_(output), target_(target) + { } + + virtual + ~Incremental_binary() + { } + + // Check the .gnu_incremental_inputs section to see whether an incremental + // build is possible. + bool + check_inputs(Incremental_inputs* incremental_inputs) + { return this->do_check_inputs(incremental_inputs); } + + // Return TRUE if the file specified by INPUT_ARGUMENT is unchanged + // with respect to the base file. + bool + file_is_unchanged(const Input_argument* input_argument) const + { return this->do_file_is_unchanged(input_argument); } + + // Report an error. + void + error(const char* format, ...) const ATTRIBUTE_PRINTF_2; + + // Wrapper class for a sized Incremental_input_entry_reader. + + class Input_reader + { + public: + Input_reader() + { } + + virtual + ~Input_reader() + { } + + const char* + filename() const + { return this->do_filename(); } + + Timespec + get_mtime() const + { return this->do_get_mtime(); } + + Incremental_input_type + type() const + { return this->do_type(); } + + protected: + virtual const char* + do_filename() const = 0; + + virtual Timespec + do_get_mtime() const = 0; + + virtual Incremental_input_type + do_type() const = 0; + }; + + Input_reader* + get_input_reader(const char* filename) + { return this->do_get_input_reader(filename); } + + // Functions and types for the elfcpp::Elf_file interface. This + // permit us to use Incremental_binary as the File template parameter for + // elfcpp::Elf_file. + + // The View class is returned by view. It must support a single + // method, data(). This is trivial, because Output_file::get_output_view + // does what we need. + class View + { + public: + View(const unsigned char* p) + : p_(p) + { } + + const unsigned char* + data() const + { return this->p_; } + + private: + const unsigned char* p_; + }; + + // Return a View. + View + view(off_t file_offset, section_size_type data_size) + { return View(this->output_->get_input_view(file_offset, data_size)); } + + // A location in the file. + struct Location + { + off_t file_offset; + off_t data_size; + + Location(off_t fo, section_size_type ds) + : file_offset(fo), data_size(ds) + { } + + Location() + : file_offset(0), data_size(0) + { } + }; + + // Get a View given a Location. + View + view(Location loc) + { return View(this->view(loc.file_offset, loc.data_size)); } + + protected: + // Check the .gnu_incremental_inputs section to see whether an incremental + // build is possible. + virtual bool + do_check_inputs(Incremental_inputs* incremental_inputs) = 0; + + // Return TRUE if the file specified by INPUT_ARGUMENT is unchanged + // with respect to the base file. + virtual bool + do_file_is_unchanged(const Input_argument* input_argument) const = 0; + + virtual Input_reader* + do_get_input_reader(const char* filename) = 0; + + private: + // Edited output file object. + Output_file* output_; + // Target of the output file. + Target* target_; +}; + +template<int size, bool big_endian> +class Sized_incremental_binary : public Incremental_binary +{ + public: + Sized_incremental_binary(Output_file* output, + const elfcpp::Ehdr<size, big_endian>& ehdr, + Target* target) + : Incremental_binary(output, target), elf_file_(this, ehdr), + has_incremental_info_(false), inputs_reader_(), symtab_reader_(), + relocs_reader_(), got_plt_reader_(), current_input_file_(0) + { this->setup_readers(); } + + // Returns TRUE if the file contains incremental info. + bool + has_incremental_info() const + { return this->has_incremental_info_; } + + // Readers for the incremental info sections. + + Incremental_inputs_reader<size, big_endian> + inputs_reader() const + { return this->inputs_reader_; } + + Incremental_symtab_reader<big_endian> + symtab_reader() const + { return this->symtab_reader_; } + + Incremental_relocs_reader<size, big_endian> + relocs_reader() const + { return this->relocs_reader_; } + + Incremental_got_plt_reader<big_endian> + got_plt_reader() const + { return this->got_plt_reader_; } + + protected: + virtual bool + do_check_inputs(Incremental_inputs* incremental_inputs); + + // Return TRUE if the file specified by INPUT_ARGUMENT is unchanged + // with respect to the base file. + virtual bool + do_file_is_unchanged(const Input_argument* input_argument) const; + + // Wrapper class for a sized Incremental_input_entry_reader. + + class Sized_input_reader : public Input_reader + { + public: + typedef Incremental_inputs_reader<size, big_endian> Inputs_reader; + typedef typename Inputs_reader::Incremental_input_entry_reader + Input_entry_reader; + + Sized_input_reader(Input_entry_reader r) + : Input_reader(), reader_(r) + { } + + virtual + ~Sized_input_reader() + { } + + private: + const char* + do_filename() const + { return this->reader_.filename(); } + + Timespec + do_get_mtime() const + { return this->reader_.get_mtime(); } + + Incremental_input_type + do_type() const + { return this->reader_.type(); } + + Input_entry_reader reader_; + }; + + virtual Input_reader* + do_get_input_reader(const char* filename); + + private: + bool + find_incremental_inputs_sections(unsigned int* p_inputs_shndx, + unsigned int* p_symtab_shndx, + unsigned int* p_relocs_shndx, + unsigned int* p_got_plt_shndx, + unsigned int* p_strtab_shndx); + + void + setup_readers(); + + // Output as an ELF file. + elfcpp::Elf_file<size, big_endian, Incremental_binary> elf_file_; + + // Readers for the incremental info sections. + bool has_incremental_info_; + Incremental_inputs_reader<size, big_endian> inputs_reader_; + Incremental_symtab_reader<big_endian> symtab_reader_; + Incremental_relocs_reader<size, big_endian> relocs_reader_; + Incremental_got_plt_reader<big_endian> got_plt_reader_; + + // Index of the current input file entry. + int current_input_file_; +}; + } // End namespace gold. #endif // !defined(GOLD_INCREMENTAL_H) |