* gold.h (Incremental_argument_list): Remove (invalid) forward
authorIan Lance Taylor <ian@airs.com>
Fri, 15 May 2009 17:01:04 +0000 (17:01 +0000)
committerIan Lance Taylor <ian@airs.com>
Fri, 15 May 2009 17:01:04 +0000 (17:01 +0000)
declaration.
* incremental.cc (Incremental_inputs::report_achive): New method.
(Incremental_inputs::report_object): New method.
(Incremental_inputs::report_script): New method.
(Incremental_inputs::finalize_inputs): New method.
(Incremental_inputs::finalize): Call finalize_inputs().
(Incremental_inputs::sized_create_incremental_inputs_section_data):
Create inputs entries.
* incremental.h (Incremental_input_type): New enum.
(Incremental_inputs::Incremental_input): Initialize new fields.
(Incremental_inputs::report_inputs): New method.
(Incremental_inputs::report_achive): New method.
(Incremental_inputs::report_object): New method.
(Incremental_inputs::report_script): New method.
(Incremental_inputs::finalize_inputs): New method.
(Incremental_inputs::Input_info): New struct.
(Incremental_inputs::Input_info_map): New typedef.
(Incremental_inputs::lock_): New field.
(Incremental_inputs::Inputs_): New field.
(Incremental_inputs::Inputs_map): New field.
* main.cc (main): Call Incremental_input::report_inputs.
* options.h (Input_argument_list): Typedef moved from
Input_arguments.
(Input_file_group::Files): Remove, use ::Input_argument_list.
(Input_file_group::Input_argument_list): Remove, use
::Input_argument_list.
* plugin.cc (Plugin_manager::add_input_file): Add error in
incremental build.
* read_syms.cc (do_read_syms): Call Incremental_input::report_*
functions.
* script.cc (read_input_script): Call
Incremental_input::report_script.
* script.h (Script_info): New class.

gold/ChangeLog
gold/gold.h
gold/incremental.cc
gold/incremental.h
gold/main.cc
gold/options.h
gold/plugin.cc
gold/readsyms.cc
gold/script.cc
gold/script.h

index 5df808b2d6d32f2f9700da2d34be1358f859d0a4..dd8e3c29faa0d1635a7da0efdeea1d602b4d85ad 100644 (file)
@@ -1,3 +1,40 @@
+2009-05-15  Mikolaj Zalewski  <mikolajz@google.com>
+
+       * gold.h (Incremental_argument_list): Remove (invalid) forward
+       declaration.
+       * incremental.cc (Incremental_inputs::report_achive): New method.
+       (Incremental_inputs::report_object): New method.
+       (Incremental_inputs::report_script): New method.
+       (Incremental_inputs::finalize_inputs): New method.
+       (Incremental_inputs::finalize): Call finalize_inputs().
+       (Incremental_inputs::sized_create_incremental_inputs_section_data):
+       Create inputs entries.
+       * incremental.h (Incremental_input_type): New enum.
+       (Incremental_inputs::Incremental_input): Initialize new fields.
+       (Incremental_inputs::report_inputs): New method.
+       (Incremental_inputs::report_achive): New method.
+       (Incremental_inputs::report_object): New method.
+       (Incremental_inputs::report_script): New method.
+       (Incremental_inputs::finalize_inputs): New method.
+       (Incremental_inputs::Input_info): New struct.
+       (Incremental_inputs::Input_info_map): New typedef.
+       (Incremental_inputs::lock_): New field.
+       (Incremental_inputs::Inputs_): New field.
+       (Incremental_inputs::Inputs_map): New field.
+       * main.cc (main): Call Incremental_input::report_inputs.
+       * options.h (Input_argument_list): Typedef moved from
+       Input_arguments.
+       (Input_file_group::Files): Remove, use ::Input_argument_list.
+       (Input_file_group::Input_argument_list): Remove, use
+       ::Input_argument_list.
+       * plugin.cc (Plugin_manager::add_input_file): Add error in
+       incremental build.
+       * read_syms.cc (do_read_syms): Call Incremental_input::report_*
+       functions.
+       * script.cc (read_input_script): Call
+       Incremental_input::report_script.
+       * script.h (Script_info): New class.
+
 2009-04-27  Ian Lance Taylor  <iant@google.com>
 
        * x86_64.cc (do_adjust_output_section): Set entsize to
index efebda8a36670cdae8aba514378f7daa9d2bdaca..bf014e8fee9de98530cf31118921562ff8c19834 100644 (file)
@@ -148,7 +148,6 @@ namespace gold
 
 class General_options;
 class Command_line;
-class Input_argument_list;
 class Dirsearch;
 class Input_objects;
 class Mapfile;
@@ -293,7 +292,7 @@ queue_initial_tasks(const General_options&,
 
 // Queue up the set of tasks to be done before
 // the middle set of tasks.  Only used when garbage
-// collection is to be done. 
+// collection is to be done.
 extern void
 queue_middle_gc_tasks(const General_options&,
                       const Task*,
index 7e99e1ef28b143e95c28e1c26254270b14f3e319..8024551d05006549881ff838d00c493f3a8fed23 100644 (file)
@@ -86,7 +86,7 @@ class Incremental_inputs_header_write
   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
@@ -179,12 +179,114 @@ Incremental_inputs::report_command_line(int argc, const char* const* argv)
   this->strtab_->add(args.c_str(), true, &this->command_line_key_);
 }
 
+// Record that the input argument INPUT is an achive ARCHIVE.  This is
+// called by Read_symbols after finding out the type of the file.
+
+void
+Incremental_inputs::report_archive(const Input_argument* input,
+                                   Archive* archive)
+{
+  Hold_lock hl(*this->lock_);
+
+  Input_info info;
+  info.type = INCREMENTAL_INPUT_ARCHIVE;
+  info.archive = archive;
+  inputs_map_.insert(std::make_pair(input, info));
+}
+
+// Record that the input argument INPUT is an object OBJ.  This is
+// called by Read_symbols after finding out the type of the file.
+
+void
+Incremental_inputs::report_object(const Input_argument* input,
+                                  Object* obj)
+{
+  Hold_lock hl(*this->lock_);
+
+  Input_info info;
+  info.type = (obj->is_dynamic()
+              ? INCREMENTAL_INPUT_SHARED_LIBRARY
+              : INCREMENTAL_INPUT_OBJECT);
+  info.object = obj;
+  inputs_map_.insert(std::make_pair(input, info));
+}
+
+// Record that the input argument INPUT is an script SCRIPT.  This is
+// called by read_script after parsing the script and reading the list
+// of inputs added by this script.
+
+void
+Incremental_inputs::report_script(const Input_argument* input,
+                                  Script_info* script)
+{
+  Hold_lock hl(*this->lock_);
+
+  Input_info info;
+  info.type = INCREMENTAL_INPUT_SCRIPT;
+  info.script = script;
+  inputs_map_.insert(std::make_pair(input, info));
+}
+
+// Compute indexes in the order in which the inputs should appear in
+// .gnu_incremental_inputs.  This needs to be done after all the
+// scripts are parsed.  The function is first called for the command
+// line inputs arguments and may call itself recursively for e.g. a
+// list of elements of a group or a list of inputs added by a script.
+// The [BEGIN; END) interval to analyze and *INDEX is the current
+// value of the index (that will be updated).
+
+void
+Incremental_inputs::finalize_inputs(
+    Input_argument_list::const_iterator begin,
+    Input_argument_list::const_iterator end,
+    unsigned int* index)
+{
+  for (Input_argument_list::const_iterator p = begin; p != end; ++p)
+    {
+      if (p->is_group())
+        {
+          finalize_inputs(p->group()->begin(), p->group()->end(), index);
+          continue;
+        }
+
+      Inputs_info_map::iterator it = inputs_map_.find(&(*p));
+      // TODO: turn it into an assert when the code will be more stable.
+      if (it == inputs_map_.end())
+        {
+          gold_error("internal error: %s: incremental build info not provided",
+                    (p->is_file() ? p->file().name() : "[group]"));
+          continue;
+        }
+      Input_info* info = &it->second;
+      info->index = *index;
+      (*index)++;
+      this->strtab_->add(p->file().name(), false, &info->filename_key);
+      if (info->type == INCREMENTAL_INPUT_SCRIPT)
+        {
+          finalize_inputs(info->script->inputs()->begin(),
+                          info->script->inputs()->end(),
+                          index);
+        }
+    }
+}
+
 // Finalize the incremental link information.  Called from
 // Layout::finalize.
 
 void
 Incremental_inputs::finalize()
 {
+  unsigned int index = 0;
+  finalize_inputs(this->inputs_->begin(), this->inputs_->end(), &index);
+
+  // Sanity check.
+  for (Inputs_info_map::const_iterator p = inputs_map_.begin();
+       p != inputs_map_.end();
+       ++p)
+    {
+      gold_assert(p->second.filename_key != 0);
+    }
+
   this->strtab_->set_string_offsets();
 }
 
@@ -213,7 +315,7 @@ Incremental_inputs::create_incremental_inputs_section_data()
 #endif
     default:
       gold_unreachable();
-    }  
+    }
 }
 
 // Sized creation of .gnu_incremental_inputs section.
@@ -221,22 +323,49 @@ Incremental_inputs::create_incremental_inputs_section_data()
 template<int size, bool big_endian>
 Output_section_data*
 Incremental_inputs::sized_create_inputs_section_data()
-{  
-  unsigned int sz =
+{
+  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 sz = header_size + entry_size * this->inputs_map_.size();
   unsigned char* buffer = new unsigned char[sz];
+  unsigned char* inputs_base = buffer + header_size;
+
   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_input_file_count(this->inputs_map_.size());
   header_writer.put_command_line_offset(cmd_offset);
   header_writer.put_reserved(0);
-  
+
+  for (Inputs_info_map::const_iterator it = this->inputs_map_.begin();
+       it != this->inputs_map_.end();
+       ++it)
+    {
+      gold_assert(it->second.index < this->inputs_map_.size());
+
+      unsigned char* entry_buffer =
+          inputs_base + it->second.index * entry_size;
+      Incremental_inputs_entry_write<size, big_endian> entry(entry_buffer);
+      int filename_offset =
+          this->strtab_->get_offset_from_key(it->second.filename_key);
+      entry.put_filename_offset(filename_offset);
+      // TODO: add per input data and timestamp.  Currently we store
+      // an out-of-bounds offset for future version of gold to reject
+      // such an incremental_inputs section.
+      entry.put_data_offset(0xffffffff);
+      entry.put_timestamp_sec(0);
+      entry.put_timestamp_usec(0);
+      entry.put_input_type(it->second.type);
+      entry.put_reserved(0);
+    }
+
   return new Output_data_const_buffer(buffer, sz, 8,
-      "** incremental link inputs list");
+                                     "** incremental link inputs list");
 }
 
 } // End namespace gold.
index dd9ebc5ac7cbfe00a0a15d8e999adbcaddf0b83f..ed074ae946a9155e0ce1be59ecff9f774f17498f 100644 (file)
@@ -23,6 +23,7 @@
 #ifndef GOLD_INCREMENTAL_H
 #define GOLD_INCREMENTAL_H
 
+#include <map>
 #include <vector>
 
 #include "stringpool.h"
@@ -37,20 +38,49 @@ class Incremental_inputs_checker;
 class Object;
 class Output_section_data;
 
+// Incremental input type as stored in .gnu_incremental_inputs.
+
+enum Incremental_input_type
+{
+  INCREMENTAL_INPUT_INVALID = 0,
+  INCREMENTAL_INPUT_OBJECT = 1,
+  INCREMENTAL_INPUT_ARCHIVE = 2,
+  INCREMENTAL_INPUT_SHARED_LIBRARY = 3,
+  INCREMENTAL_INPUT_SCRIPT = 4
+};
+
 // 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())
+    : lock_(new Lock()), inputs_(NULL), 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);
-  
+
+  // Record the input arguments obtained from parsing the command line.
+  void
+  report_inputs(const Input_arguments& inputs)
+  { this->inputs_ = &inputs; }
+
+  // Record that the input argument INPUT is an archive ARCHIVE.
+  void
+  report_archive(const Input_argument* input, Archive* archive);
+
+  // Record that the input argument INPUT is to an object OBJ.
+  void
+  report_object(const Input_argument* input, Object* obj);
+
+  // Record that the input argument INPUT is to an script SCRIPT.
+  void
+  report_script(const Input_argument* input, Script_info* script);
+
   // Prepare for layout.  Called from Layout::finalize.
   void
   finalize();
@@ -58,8 +88,8 @@ class Incremental_inputs
   // Create the content of the .gnu_incremental_inputs section.
   Output_section_data*
   create_incremental_inputs_section_data();
-  
-  // Return the .gnu_incremental_strtab stringpool. 
+
+  // Return the .gnu_incremental_strtab stringpool.
   Stringpool*
   get_stringpool()
   { return this->strtab_; }
@@ -68,7 +98,57 @@ class Incremental_inputs
   // 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();  
+  sized_create_inputs_section_data();
+
+  // Compute indexes in the order in which the inputs should appear in
+  // .gnu_incremental_inputs and put file names to the stringtable.
+  // This needs to be done after all the scripts are parsed.
+
+  void
+  finalize_inputs(Input_argument_list::const_iterator begin,
+                 Input_argument_list::const_iterator end,
+                 unsigned int* index);
+
+  // Additional data about an input needed for an incremental link.
+  // None of these pointers is owned by the structure.
+  struct Input_info
+  {
+    Input_info()
+      : type(INCREMENTAL_INPUT_INVALID), archive(NULL), object(NULL),
+        script(NULL), filename_key(0), index(0)
+    { }
+
+    // Type of the file pointed by this argument.
+    Incremental_input_type type;
+
+    // Present if type == INCREMENTAL_INPUT_ARCHIVE.
+    Archive* archive;
+
+    // Present if type == INCREMENTAL_INPUT_OBJECT or
+    // INCREMENTAL_INPUT_SHARED_LIBRARY.
+    Object* object;
+
+    // Present if type == INCREMENTAL_INPUT_SCRIPT.
+    Script_info* script;
+
+    // Key of the filename string in the section stringtable.
+    Stringpool::Key filename_key;
+
+    // Position of the entry information in the output section.
+    unsigned int index;
+  };
+
+  typedef std::map<const Input_argument*, Input_info> Inputs_info_map;
+
+  // A lock guarding access to inputs_ during the first phase of linking, when
+  // report_ function may be called from multiple threads.
+  Lock* lock_;
+  
+  // The list of input arguments obtained from parsing the command line.
+  const Input_arguments* inputs_;
+
+  // A map containing additional information about the input elements.
+  Inputs_info_map inputs_map_;
 
   // The key of the command line string in the string pool.
   Stringpool::Key command_line_key_;
index c2d3c3062aaae863faa9ee5157d5af1961067636..84b4ae91eef7e94c774de4dbd5532dd97797f5cf 100644 (file)
@@ -221,7 +221,10 @@ main(int argc, char** argv)
                &command_line.script_options());
 
   if (layout.incremental_inputs() != NULL)
-    layout.incremental_inputs()->report_command_line(argc, argv);
+    {
+      layout.incremental_inputs()->report_command_line(argc, argv);
+      layout.incremental_inputs()->report_inputs(command_line.inputs());
+    }
 
   // Get the search path from the -L options.
   Dirsearch search_path;
index 904743e9c8759dfe1c5a5d0e4d33a5f26ce7a08d..b811332406f92dc95ab85061c7197f900db4b6dc 100644 (file)
@@ -1275,14 +1275,15 @@ class Input_argument
   Input_file_group* group_;
 };
 
+typedef std::vector<Input_argument> Input_argument_list;
+
 // A group from the command line.  This is a set of arguments within
 // --start-group ... --end-group.
 
 class Input_file_group
 {
  public:
-  typedef std::vector<Input_argument> Files;
-  typedef Files::const_iterator const_iterator;
+  typedef Input_argument_list::const_iterator const_iterator;
 
   Input_file_group()
     : files_()
@@ -1304,7 +1305,7 @@ class Input_file_group
   { return this->files_.end(); }
 
  private:
-  Files files_;
+  Input_argument_list files_;
 };
 
 // A list of files from the command line or a script.
@@ -1312,7 +1313,6 @@ class Input_file_group
 class Input_arguments
 {
  public:
-  typedef std::vector<Input_argument> Input_argument_list;
   typedef Input_argument_list::const_iterator const_iterator;
 
   Input_arguments()
index 3c4d4aef50285fd56dcfbabc54a343e6a69bdfb9..b1007a7e63fe74174533a1d002e588010ef7927c 100644 (file)
@@ -407,6 +407,9 @@ Plugin_manager::add_input_file(char *pathname)
   Input_argument* input_argument = new Input_argument(file);
   Task_token* next_blocker = new Task_token(true);
   next_blocker->add_blocker();
+  if (this->layout_->incremental_inputs())
+    gold_error(_("Input files added by plug-ins in --incremental mode not "
+                "supported yet.\n"));
   this->workqueue_->queue_soon(new Read_symbols(this->input_objects_,
                                                 this->symtab_,
                                                 this->layout_,
index b6da88d45ce4f5ddd9bf13f5d766040c2e86bd5c..c05d5a39aefa0c4b82cb92d83e3757fac722f939 100644 (file)
@@ -33,6 +33,8 @@
 #include "script.h"
 #include "readsyms.h"
 #include "plugin.h"
+#include "layout.h"
+#include "incremental.h"
 
 namespace gold
 {
@@ -199,7 +201,7 @@ Read_symbols::do_read_symbols(Workqueue* workqueue)
     {
       bool is_thin_archive
           = memcmp(ehdr, Archive::armagt, Archive::sarmag) == 0;
-      if (is_thin_archive 
+      if (is_thin_archive
           || memcmp(ehdr, Archive::armag, Archive::sarmag) == 0)
        {
          // This is an archive.
@@ -207,7 +209,13 @@ Read_symbols::do_read_symbols(Workqueue* workqueue)
                                      input_file, is_thin_archive,
                                      this->dirpath_, this);
          arch->setup();
-         
+
+         if (this->layout_->incremental_inputs())
+           {
+             const Input_argument* ia = this->input_argument_;       
+             this->layout_->incremental_inputs()->report_archive(ia, arch);
+           }
+
          // Unlock the archive so it can be used in the next task.
          arch->unlock(this);
 
@@ -280,6 +288,12 @@ Read_symbols::do_read_symbols(Workqueue* workqueue)
       Read_symbols_data* sd = new Read_symbols_data;
       obj->read_symbols(sd);
 
+      if (this->layout_->incremental_inputs())
+       {
+         const Input_argument* ia = this->input_argument_;
+         this->layout_->incremental_inputs()->report_object(ia, obj);
+       }
+
       // Opening the file locked it, so now we need to unlock it.  We
       // need to unlock it before queuing the Add_symbols task,
       // because the workqueue doesn't know about our lock on the
index 30b4e3c351a923e4b57e8aff1cd727f514631ba6..86ce13bf7fe89777d3784511e58a780a5a70bb22 100644 (file)
@@ -43,6 +43,7 @@
 #include "target-select.h"
 #include "script.h"
 #include "script-c.h"
+#include "incremental.h"
 
 namespace gold
 {
@@ -1414,6 +1415,13 @@ read_input_script(Workqueue* workqueue, Symbol_table* symtab, Layout* layout,
       this_blocker = nb;
     }
 
+  if (layout->incremental_inputs())
+    {
+      // Like new Read_symbols(...) above, we rely on close.inputs()
+      // getting leaked by closure.
+      Script_info* info = new Script_info(closure.inputs());
+      layout->incremental_inputs()->report_script(input_argument, info);
+    }
   *used_next_blocker = true;
 
   return true;
index e4554d0dcaca359e23b93729928fd394ea9019b4..781d24ddec183fff3fc2cac2534ed38433ef66d9 100644 (file)
@@ -45,6 +45,7 @@ class Symbol_table;
 class Layout;
 class Mapfile;
 class Input_argument;
+class Input_arguments;
 class Input_objects;
 class Input_group;
 class Input_file;
@@ -382,6 +383,26 @@ class Script_options
   Script_sections script_sections_;
 };
 
+// Information about a script input that will persist during the whole linker
+// run. Needed only during an incremental build to retrieve the input files
+// added by this script.
+
+class Script_info
+{
+ public:
+  Script_info(Input_arguments* inputs)
+    : inputs_(inputs)
+  { }
+
+  // Returns the input files included because of this script.
+  Input_arguments*
+  inputs()
+  { return inputs_; }
+
+ private:
+  Input_arguments* inputs_;
+};
+
 // FILE was found as an argument on the command line, but was not
 // recognized as an ELF file.  Try to read it as a script.  Return
 // true if the file was handled.  This has to handle /usr/lib/libc.so
This page took 0.037127 seconds and 4 git commands to generate.