From b961d0d7b65a2bdfd465f774db948c199fddaa06 Mon Sep 17 00:00:00 2001 From: Cary Coutant Date: Tue, 5 Apr 2011 20:16:17 +0000 Subject: * 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. --- gold/incremental.h | 429 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 284 insertions(+), 145 deletions(-) (limited to 'gold/incremental.h') 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 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 -class Sized_incremental_binary : public Incremental_binary -{ - public: - Sized_incremental_binary(Output_file* output, - const elfcpp::Ehdr& 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 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 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(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(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 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 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 +class Sized_incremental_binary : public Incremental_binary +{ + public: + Sized_incremental_binary(Output_file* output, + const elfcpp::Ehdr& 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 + inputs_reader() const + { return this->inputs_reader_; } + + Incremental_symtab_reader + symtab_reader() const + { return this->symtab_reader_; } + + Incremental_relocs_reader + relocs_reader() const + { return this->relocs_reader_; } + + Incremental_got_plt_reader + 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 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 elf_file_; + + // Readers for the incremental info sections. + bool has_incremental_info_; + Incremental_inputs_reader inputs_reader_; + Incremental_symtab_reader symtab_reader_; + Incremental_relocs_reader relocs_reader_; + Incremental_got_plt_reader got_plt_reader_; + + // Index of the current input file entry. + int current_input_file_; +}; + } // End namespace gold. #endif // !defined(GOLD_INCREMENTAL_H) -- cgit v1.1