diff options
author | Ian Lance Taylor <ian@airs.com> | 2009-04-24 15:44:02 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 2009-04-24 15:44:02 +0000 |
commit | 3ce2c28e3f647d0771a197b76477ddc8cbb611b2 (patch) | |
tree | 14d493e1d69102339db0ded1b5e365584dd79986 /gold/incremental.cc | |
parent | f50230ae440d80638167b5520afbe4dc6480df4f (diff) | |
download | gdb-3ce2c28e3f647d0771a197b76477ddc8cbb611b2.zip gdb-3ce2c28e3f647d0771a197b76477ddc8cbb611b2.tar.gz gdb-3ce2c28e3f647d0771a197b76477ddc8cbb611b2.tar.bz2 |
* incremental.cc (Incremental_inputs_header_data): Renamed from
Incremental_input_header_data.
(Incremental_inputs_header_data::data_size): New field.
(Incremental_inputs_header_data::put_input_file_count): Renamed
from input_file_count.
(Incremental_inputs_header_data::put_command_line_offset): Renamed
from command_line_offset.
(Incremental_inputs_header_data::put_reserved): Renamed from
put_reserved.
(Incremental_inputs_entry_data): Renamed from
Incremental_input_entry_data.
(Incremental_inputs_entry_data::data_size): New field.
(Incremental_inputs::report_command_line): New method.
(Incremental_inputs::finalize): New method.
(Incremental_inputs::create_incremental_inputs_data): New method.
(Incremental_inputs::sized_create_incremental_inputs_data): New method.
* incremental.h: New file.
* layout.cc (Layout::Layout): Handle new incremental_inputs_.
(Layout::finalize): Create incremental inputs section in
incremental builds.
(Layout::create_incremental_info_sections): New method.
* layout.h (Layout::incremental_inputs): New method.
(Layout::create_incremental_info_sections): New method.
(Layout::incremental_inputs_): New field.
* main.cc (main): Notify Incremental_input of the command line.
Diffstat (limited to 'gold/incremental.cc')
-rw-r--r-- | gold/incremental.cc | 123 |
1 files changed, 110 insertions, 13 deletions
diff --git a/gold/incremental.cc b/gold/incremental.cc index 665822d..7e99e1e 100644 --- a/gold/incremental.cc +++ b/gold/incremental.cc @@ -22,6 +22,8 @@ #include "gold.h" #include "elfcpp.h" +#include "output.h" +#include "incremental.h" using elfcpp::Convert; @@ -34,7 +36,7 @@ const int INCREMENTAL_LINK_VERSION = 1; namespace internal { // Header of the .gnu_incremental_input section. -struct Incremental_input_header_data +struct Incremental_inputs_header_data { // Incremental linker version. elfcpp::Elf_Word version; @@ -51,7 +53,7 @@ struct Incremental_input_header_data // Data stored in .gnu_incremental_input after the header for each of the // Incremental_input_header_data::input_file_count input entries. -struct Incremental_input_entry_data +struct Incremental_inputs_entry_data { // Offset of file name in .gnu_incremental_strtab section. elfcpp::Elf_Word filename_offset; @@ -78,42 +80,46 @@ struct Incremental_input_entry_data // See internal::Incremental_input_header for fields descriptions. template<int size, bool big_endian> -class Incremental_input_header_write +class Incremental_inputs_header_write { public: - Incremental_input_header_write(unsigned char *p) - : p_(reinterpret_cast<internal::Incremental_input_header_data>(p)) + Incremental_inputs_header_write(unsigned char *p) + : p_(reinterpret_cast<internal::Incremental_inputs_header_data*>(p)) { } + + static const int data_size = sizeof(internal::Incremental_inputs_header_data); void put_version(elfcpp::Elf_Word v) { this->p_->version = Convert<32, big_endian>::convert_host(v); } void - input_file_count(elfcpp::Elf_Word v) + put_input_file_count(elfcpp::Elf_Word v) { this->p_->input_file_count = Convert<32, big_endian>::convert_host(v); } void - command_line_offset(elfcpp::Elf_Word v) + put_command_line_offset(elfcpp::Elf_Word v) { this->p_->command_line_offset = Convert<32, big_endian>::convert_host(v); } void - reserved(elfcpp::Elf_Word v) + put_reserved(elfcpp::Elf_Word v) { this->p_->reserved = Convert<32, big_endian>::convert_host(v); } private: - internal::Incremental_input_header_data* p_; + internal::Incremental_inputs_header_data* p_; }; // See internal::Incremental_input_entry for fields descriptions. template<int size, bool big_endian> -class Incremental_input_entry_write +class Incremental_inputs_entry_write { public: - Incremental_input_entry_write(unsigned char *p) - : p_(reinterpret_cast<internal::Incremental_input_entry_data>(p)) + Incremental_inputs_entry_write(unsigned char *p) + : p_(reinterpret_cast<internal::Incremental_inputs_entry_data*>(p)) { } + static const int data_size = sizeof(internal::Incremental_inputs_entry_data); + void put_filename_offset(elfcpp::Elf_Word v) { this->p_->filename_offset = Convert<32, big_endian>::convert_host(v); } @@ -139,7 +145,98 @@ class Incremental_input_entry_write { this->p_->reserved = Convert<32, big_endian>::convert_host(v); } private: - internal::Incremental_input_entry_data* p_; + internal::Incremental_inputs_entry_data* p_; }; +// Add the command line to the string table, setting +// command_line_key_. In incremental builds, the command line is +// stored in .gnu_incremental_inputs so that the next linker run can +// check if the command line options didn't change. + +void +Incremental_inputs::report_command_line(int argc, const char* const* argv) +{ + // Always store 'gold' as argv[0] to avoid a full relink if the user used a + // different path to the linker. + std::string args("gold"); + // Copied from collect_argv in main.cc. + for (int i = 1; i < argc; ++i) + { + args.append(" '"); + // Now append argv[i], but with all single-quotes escaped + const char* argpos = argv[i]; + while (1) + { + const int len = strcspn(argpos, "'"); + args.append(argpos, len); + if (argpos[len] == '\0') + break; + args.append("'\"'\"'"); + argpos += len + 1; + } + args.append("'"); + } + this->strtab_->add(args.c_str(), true, &this->command_line_key_); +} + +// Finalize the incremental link information. Called from +// Layout::finalize. + +void +Incremental_inputs::finalize() +{ + this->strtab_->set_string_offsets(); +} + +// Create the content of the .gnu_incremental_inputs section. + +Output_section_data* +Incremental_inputs::create_incremental_inputs_section_data() +{ + switch (parameters->size_and_endianness()) + { +#ifdef HAVE_TARGET_32_LITTLE + case Parameters::TARGET_32_LITTLE: + return this->sized_create_inputs_section_data<32, false>(); +#endif +#ifdef HAVE_TARGET_32_BIG + case Parameters::TARGET_32_BIG: + return this->sized_create_inputs_section_data<32, true>(); +#endif +#ifdef HAVE_TARGET_64_LITTLE + case Parameters::TARGET_64_LITTLE: + return this->sized_create_inputs_section_data<64, false>(); +#endif +#ifdef HAVE_TARGET_64_BIG + case Parameters::TARGET_64_BIG: + return this->sized_create_inputs_section_data<64, true>(); +#endif + default: + gold_unreachable(); + } +} + +// Sized creation of .gnu_incremental_inputs section. + +template<int size, bool big_endian> +Output_section_data* +Incremental_inputs::sized_create_inputs_section_data() +{ + unsigned int sz = + Incremental_inputs_header_write<size, big_endian>::data_size; + unsigned char* buffer = new unsigned char[sz]; + Incremental_inputs_header_write<size, big_endian> header_writer(buffer); + + gold_assert(this->command_line_key_ > 0); + int cmd_offset = this->strtab_->get_offset_from_key(this->command_line_key_); + + header_writer.put_version(INCREMENTAL_LINK_VERSION); + header_writer.put_input_file_count(0); // TODO: store input files data. + header_writer.put_command_line_offset(cmd_offset); + header_writer.put_reserved(0); + + return new Output_data_const_buffer(buffer, sz, 8, + "** incremental link inputs list"); +} + } // End namespace gold. |