diff options
author | Ian Lance Taylor <ian@airs.com> | 2009-10-09 22:38:07 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 2009-10-09 22:38:07 +0000 |
commit | c4aa1e2d740d76a37730514749c6ff2ef9f748f1 (patch) | |
tree | 1a65a3a215ee78941e8c64f57305980a55cefdc2 /gold/incremental.cc | |
parent | c549a6949c8cbbbeafa79ab903b172bbc5f2b8ea (diff) | |
download | fsf-binutils-gdb-c4aa1e2d740d76a37730514749c6ff2ef9f748f1.zip fsf-binutils-gdb-c4aa1e2d740d76a37730514749c6ff2ef9f748f1.tar.gz fsf-binutils-gdb-c4aa1e2d740d76a37730514749c6ff2ef9f748f1.tar.bz2 |
elfcpp/:
* elf_file.h: (class Elf_strtab): New class.
gold/:
* gold.cc: (queue_initial_tasks): Pass incremental_inputs to
Incremental_checker.
* incremental.cc: (INCREMENTAL_LINK_VERSION): Change type to
unsigned int.
(class Incremental_inputs_header): New class.
(Incremental_inputs_header_writer): Edit comment.
(Incremental_inputs_entry): New class.
(Incremental_inputs_entry_writer): Edit comment.
(Sized_incremental_binary::do_find_incremental_inputs_section):
Add *strtab_shndx parameter, fill it.
(Sized_incremental_binary::do_check_inputs): New method.
(Incremental_checker::can_incrementally_link_output_file): Use
Sized_incremental_binary::check_inputs.
(Incremental_inputs::report_command_line): Save command line in
command_line_.
* incremental.h:
(Incremental_binary::find_incremental_inputs_section): New
method.
(Incremental_binary::do_find_incremental_inputs_section): Add
strtab_shndx parameter.
(Incremental_binary::do_check_inputs): New pure virtual method.
(Sized_incremental_binary::do_check_inputs): Declare.
(Incremental_checker::Incremental_checker): Add incremental_inputs
parameter, use it to initialize incremental_inputs_.
(Incremental_checker::incremental_inputs_): New field.
(Incremental_checker::command_line): New method.
(Incremental_checker::inputs): New method.
(Incremental_checker::command_line_): New field.
Diffstat (limited to 'gold/incremental.cc')
-rw-r--r-- | gold/incremental.cc | 159 |
1 files changed, 146 insertions, 13 deletions
diff --git a/gold/incremental.cc b/gold/incremental.cc index 9f7c4c2..519f35f 100644 --- a/gold/incremental.cc +++ b/gold/incremental.cc @@ -37,7 +37,7 @@ namespace gold { // Version information. Will change frequently during the development, later // we could think about backward (and forward?) compatibility. -const int INCREMENTAL_LINK_VERSION = 1; +const unsigned int INCREMENTAL_LINK_VERSION = 1; namespace internal { @@ -84,7 +84,42 @@ struct Incremental_inputs_entry_data // Accessors. -// See internal::Incremental_input_header for fields descriptions. +// Reader class for .gnu_incremental_inputs header. See +// internal::Incremental_input_header for fields descriptions. + +template<int size, bool big_endian> +class Incremental_inputs_header +{ + public: + Incremental_inputs_header(const unsigned char *p) + : p_(reinterpret_cast<const internal::Incremental_inputs_header_data*>(p)) + { } + + static const int data_size = sizeof(internal::Incremental_inputs_header_data); + + elfcpp::Elf_Word + get_version() const + { return Convert<32, big_endian>::convert_host(this->p_->version); } + + elfcpp::Elf_Word + get_input_file_count() const + { return Convert<32, big_endian>::convert_host(this->p_->input_file_count); } + + elfcpp::Elf_Word + get_command_line_offset() const + { return Convert<32, big_endian>::convert_host(this->p_->command_line_offset); } + + elfcpp::Elf_Word + get_reserved() const + { return Convert<32, big_endian>::convert_host(this->p_->reserved); } + + private: + const internal::Incremental_inputs_header_data* p_; +}; + +// Writer class for .gnu_incremental_inputs header. See +// internal::Incremental_input_header for fields descriptions. + template<int size, bool big_endian> class Incremental_inputs_header_write { @@ -115,7 +150,48 @@ class Incremental_inputs_header_write internal::Incremental_inputs_header_data* p_; }; -// See internal::Incremental_input_entry for fields descriptions. +// Reader class for an .gnu_incremental_inputs entry. See +// internal::Incremental_input_entry for fields descriptions. +template<int size, bool big_endian> +class Incremental_inputs_entry +{ + public: + Incremental_inputs_entry(const unsigned char *p) + : p_(reinterpret_cast<const internal::Incremental_inputs_entry_data*>(p)) + { } + + static const int data_size = sizeof(internal::Incremental_inputs_entry_data); + + elfcpp::Elf_Word + get_filename_offset(elfcpp::Elf_Word v) + { return Convert<32, big_endian>::convert_host(this->p_->filename_offset); } + + elfcpp::Elf_Word + get_data_offset(elfcpp::Elf_Word v) + { return Convert<32, big_endian>::convert_host(this->p_->data_offset); } + + elfcpp::Elf_Xword + get_timestamp_sec(elfcpp::Elf_Xword v) + { return Convert<64, big_endian>::convert_host(this->p_->timestamp_sec); } + + elfcpp::Elf_Word + get_timestamp_nsec(elfcpp::Elf_Word v) + { return Convert<32, big_endian>::convert_host(this->p_->timestamp_nsec); } + + elfcpp::Elf_Word + get_input_type(elfcpp::Elf_Word v) + { return Convert<32, big_endian>::convert_host(this->p_->input_type); } + + elfcpp::Elf_Word + get_reserved(elfcpp::Elf_Word v) + { return Convert<32, big_endian>::convert_host(this->p_->reserved); } + + private: + const internal::Incremental_inputs_entry_data* p_; +}; + +// Writer class for an .gnu_incremental_inputs entry. See +// internal::Incremental_input_entry for fields descriptions. template<int size, bool big_endian> class Incremental_inputs_entry_write { @@ -196,16 +272,77 @@ Incremental_binary::error(const char* format, ...) const template<int size, bool big_endian> bool Sized_incremental_binary<size, big_endian>::do_find_incremental_inputs_section( - Location* location) + Location* location, + unsigned int* strtab_shndx) { unsigned int shndx = this->elf_file_.find_section_by_type( elfcpp::SHT_GNU_INCREMENTAL_INPUTS); if (shndx == elfcpp::SHN_UNDEF) // Not found. return false; + *strtab_shndx = this->elf_file_.section_link(shndx); *location = this->elf_file_.section_contents(shndx); return true; } +template<int size, bool big_endian> +bool +Sized_incremental_binary<size, big_endian>::do_check_inputs( + Incremental_inputs* incremental_inputs) +{ + const int entry_size = + Incremental_inputs_entry_write<size, big_endian>::data_size; + const int header_size = + Incremental_inputs_header_write<size, big_endian>::data_size; + + unsigned int strtab_shndx; + Location location; + + if (!do_find_incremental_inputs_section(&location, &strtab_shndx)) + { + explain_no_incremental(_("no incremental data from previous build")); + return false; + } + if (location.data_size < header_size + || strtab_shndx >= this->elf_file_.shnum() + || this->elf_file_.section_type(strtab_shndx) != elfcpp::SHT_STRTAB) + { + explain_no_incremental(_("invalid incremental build data")); + return false; + } + + Location strtab_location(this->elf_file_.section_contents(strtab_shndx)); + View data_view(view(location)); + View strtab_view(view(strtab_location)); + elfcpp::Elf_strtab strtab(strtab_view.data(), strtab_location.data_size); + Incremental_inputs_header<size, big_endian> header(data_view.data()); + + if (header.get_version() != INCREMENTAL_LINK_VERSION) + { + explain_no_incremental(_("different version of incremental build data")); + return false; + } + + const char* command_line; + // We divide instead of multiplying to make sure there is no integer + // overflow. + size_t max_input_entries = (location.data_size - header_size) / entry_size; + if (header.get_input_file_count() > max_input_entries + || !strtab.get_c_string(header.get_command_line_offset(), &command_line)) + { + explain_no_incremental(_("invalid incremental build data")); + return false; + } + + if (incremental_inputs->command_line() != command_line) + { + explain_no_incremental(_("command line changed")); + return false; + } + + // TODO: compare incremental_inputs->inputs() with entries in data_view. + return true; +} + namespace { @@ -322,14 +459,7 @@ Incremental_checker::can_incrementally_link_output_file() Incremental_binary* binary = open_incremental_binary(&output); if (binary == NULL) return false; - Incremental_binary::Location inputs_location; - if (!binary->find_incremental_inputs_section(&inputs_location)) - { - explain_no_incremental("no incremental data from previous build"); - delete binary; - return false; - } - return true; + return binary->check_inputs(this->incremental_inputs_); } // Add the command line to the string table, setting @@ -366,7 +496,10 @@ Incremental_inputs::report_command_line(int argc, const char* const* argv) } args.append("'"); } - this->strtab_->add(args.c_str(), true, &this->command_line_key_); + + this->command_line_ = args; + this->strtab_->add(this->command_line_.c_str(), false, + &this->command_line_key_); } // Record that the input argument INPUT is an achive ARCHIVE. This is |