aboutsummaryrefslogtreecommitdiff
path: root/gold/incremental.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>2009-04-24 15:44:02 +0000
committerIan Lance Taylor <ian@airs.com>2009-04-24 15:44:02 +0000
commit3ce2c28e3f647d0771a197b76477ddc8cbb611b2 (patch)
tree14d493e1d69102339db0ded1b5e365584dd79986 /gold/incremental.cc
parentf50230ae440d80638167b5520afbe4dc6480df4f (diff)
downloadgdb-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.cc123
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.