* incremental.cc (Incremental_inputs_header_data): Renamed from
authorIan Lance Taylor <ian@airs.com>
Fri, 24 Apr 2009 15:44:02 +0000 (15:44 +0000)
committerIan Lance Taylor <ian@airs.com>
Fri, 24 Apr 2009 15:44:02 +0000 (15:44 +0000)
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.

gold/ChangeLog
gold/incremental.cc
gold/incremental.h [new file with mode: 0644]
gold/layout.cc
gold/layout.h
gold/main.cc

index f8ea0e51e13b4a6fd1ca274d9574671480868c64..3841da29336bfce561114828a4bf3780893f1b82 100644 (file)
@@ -1,3 +1,31 @@
+2009-04-21  Mikolaj Zalewski  <mikolajz@google.com>
+
+       * 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.
+
 2009-04-01  Ian Lance Taylor  <iant@google.com>
            Mikolaj Zalewski  <mikolajz@google.com>
 
index 665822df5eaf82ff4a61623352814ecaf5339acb..7e99e1ef28b143e95c28e1c26254270b14f3e319 100644 (file)
@@ -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.
diff --git a/gold/incremental.h b/gold/incremental.h
new file mode 100644 (file)
index 0000000..dd9ebc5
--- /dev/null
@@ -0,0 +1,82 @@
+// inremental.h -- incremental linking support for gold   -*- C++ -*-
+
+// Copyright 2009 Free Software Foundation, Inc.
+// Written by Mikolaj Zalewski <mikolajz@google.com>.
+
+// This file is part of gold.
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+// MA 02110-1301, USA.
+
+#ifndef GOLD_INCREMENTAL_H
+#define GOLD_INCREMENTAL_H
+
+#include <vector>
+
+#include "stringpool.h"
+#include "workqueue.h"
+
+namespace gold
+{
+
+class Archive;
+class Input_argument;
+class Incremental_inputs_checker;
+class Object;
+class Output_section_data;
+
+// This class contains the information needed during an incremental
+// build about the inputs necessary to build the .gnu_incremental_inputs.
+class Incremental_inputs
+{
+ public:
+  Incremental_inputs()
+    : command_line_key_(0), strtab_(new Stringpool())
+  { }
+  ~Incremental_inputs() { delete this->strtab_; }
+
+  // Record the command line.
+  void
+  report_command_line(int argc, const char* const* argv);
+  
+  // Prepare for layout.  Called from Layout::finalize.
+  void
+  finalize();
+
+  // Create the content of the .gnu_incremental_inputs section.
+  Output_section_data*
+  create_incremental_inputs_section_data();
+  
+  // Return the .gnu_incremental_strtab stringpool. 
+  Stringpool*
+  get_stringpool()
+  { return this->strtab_; }
+
+ private:
+  // Code for each of the four possible variants of create_inputs_section_data.
+  template<int size, bool big_endian>
+  Output_section_data*
+  sized_create_inputs_section_data();  
+
+  // The key of the command line string in the string pool.
+  Stringpool::Key command_line_key_;
+  // The .gnu_incremental_strtab string pool associated with the
+  // .gnu_incremental_inputs.
+  Stringpool* strtab_;
+};
+
+} // End namespace gold.
+
+#endif // !defined(GOLD_INCREMENTAL_H)
index c70e11c557c58e53486f9e94bb373bac8e2ba5e7..a651d0650d9cc96a066bad2ee80f3fb6bdfa7fd1 100644 (file)
@@ -46,8 +46,9 @@
 #include "reduced_debug_output.h"
 #include "reloc.h"
 #include "descriptors.h"
-#include "layout.h"
 #include "plugin.h"
+#include "incremental.h"
+#include "layout.h"
 
 namespace gold
 {
@@ -122,7 +123,8 @@ Layout::Layout(int number_of_input_files, Script_options* script_options)
     input_without_gnu_stack_note_(false),
     has_static_tls_(false),
     any_postprocessing_sections_(false),
-    resized_signatures_(false)
+    resized_signatures_(false),
+    incremental_inputs_(NULL)
 {
   // Make space for more than enough segments for a typical file.
   // This is just for efficiency--it's OK if we wind up needing more.
@@ -131,6 +133,10 @@ Layout::Layout(int number_of_input_files, Script_options* script_options)
   // We expect two unattached Output_data objects: the file header and
   // the segment headers.
   this->special_output_list_.reserve(2);
+
+  // Initialize structure needed for an incremental build.
+  if (parameters->options().incremental())
+    this->incremental_inputs_ = new Incremental_inputs;
 }
 
 // Hash a key we use to look up an output section mapping.
@@ -1215,6 +1221,12 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
       this->create_version_sections(&versions, symtab, local_dynamic_count,
                                    dynamic_symbols, dynstr);
     }
+  
+  if (this->incremental_inputs_)
+    {
+      this->incremental_inputs_->finalize();
+      this->create_incremental_info_sections();
+    }
 
   // If there is a SECTIONS clause, put all the input sections into
   // the required order.
@@ -1593,6 +1605,37 @@ Layout::create_build_id()
     }
 }
 
+// Create .gnu_incremental_inputs and .gnu_incremental_strtab sections needed
+// for the next run of incremental linking to check what has changed.
+
+void
+Layout::create_incremental_info_sections()
+{
+  gold_assert(this->incremental_inputs_ != NULL);
+
+  // Add the .gnu_incremental_inputs section.
+  const char *incremental_inputs_name =
+    this->namepool_.add(".gnu_incremental_inputs", false, NULL);
+  Output_section* inputs_os =
+    this->make_output_section(incremental_inputs_name,
+                             elfcpp::SHT_GNU_INCREMENTAL_INPUTS, 0);
+  Output_section_data* posd =
+      this->incremental_inputs_->create_incremental_inputs_section_data();
+  inputs_os->add_output_section_data(posd);
+  
+  // Add the .gnu_incremental_strtab section.
+  const char *incremental_strtab_name =
+    this->namepool_.add(".gnu_incremental_strtab", false, NULL);
+  Output_section* strtab_os = this->make_output_section(incremental_strtab_name,
+                                                        elfcpp::SHT_STRTAB,
+                                                        0);
+  Output_data_strtab* strtab_data =
+    new Output_data_strtab(this->incremental_inputs_->get_stringpool());
+  strtab_os->add_output_section_data(strtab_data);
+  
+  inputs_os->set_link_section(strtab_data);
+}
+
 // Return whether SEG1 should be before SEG2 in the output file.  This
 // is based entirely on the segment type and flags.  When this is
 // called the segment addresses has normally not yet been set.
index 52be1d462feca70b50f62d63ed452e6a22f2066e..0a9146bdf4f60254f7856a23633e4a38dd5e9706 100644 (file)
@@ -39,6 +39,7 @@ namespace gold
 {
 
 class General_options;
+class Incremental_inputs;
 class Input_objects;
 class Mapfile;
 class Symbol_table;
@@ -368,6 +369,12 @@ class Layout
   script_options() const
   { return this->script_options_; }
 
+  // Return the object managing inputs in incremental build. NULL in
+  // non-incremental builds.
+  Incremental_inputs*
+  incremental_inputs()
+  { return this->incremental_inputs_; }
+
   // Compute and write out the build ID if needed.
   void
   write_build_id(Output_file*) const;
@@ -473,6 +480,11 @@ class Layout
   void
   create_build_id();
 
+  // Create .gnu_incremental_inputs and .gnu_incremental_strtab sections needed
+  // for the next run of incremental linking to check what has changed.
+  void
+  create_incremental_info_sections();
+
   // Find the first read-only PT_LOAD segment, creating one if
   // necessary.
   Output_segment*
@@ -717,6 +729,9 @@ class Layout
   bool any_postprocessing_sections_;
   // Whether we have resized the signatures_ hash table.
   bool resized_signatures_;
+  // In incremental build, holds information check the inputs and build the
+  // .gnu_incremental_inputs section.
+  Incremental_inputs* incremental_inputs_;
 };
 
 // This task handles writing out data in output sections which is not
index 2985a84ff2e52e1cbe9a7a04ed01068654e2596c..c2d3c3062aaae863faa9ee5157d5af1961067636 100644 (file)
@@ -44,6 +44,7 @@
 #include "layout.h"
 #include "plugin.h"
 #include "gc.h"
+#include "incremental.h"
 
 using namespace gold;
 
@@ -219,6 +220,9 @@ main(int argc, char** argv)
   Layout layout(command_line.number_of_input_files(),
                &command_line.script_options());
 
+  if (layout.incremental_inputs() != NULL)
+    layout.incremental_inputs()->report_command_line(argc, argv);
+
   // Get the search path from the -L options.
   Dirsearch search_path;
   search_path.initialize(&workqueue, &command_line.options().library_path());