* incremental-dump.cc (dump_incremental_inputs): Change signature
authorCary Coutant <ccoutant@google.com>
Tue, 5 Apr 2011 20:16:17 +0000 (20:16 +0000)
committerCary Coutant <ccoutant@google.com>
Tue, 5 Apr 2011 20:16:17 +0000 (20:16 +0000)
to take a Sized_incremental_binary; change caller.  Use readers
in Sized_incremental_binary.
* incremental.cc
(Sized_incremental_binary::find_incremental_inputs_sections):
Rename do_find_incremental_inputs_sections to this.
(Sized_incremental_binary::setup_readers): New function.
(Sized_incremental_binary::do_check_inputs): Check
has_incremental_info_ flag; move setup code to setup_readers;
use input readers.
(Sized_incremental_binary::do_file_is_unchanged): New function.
(Sized_incremental_binary::do_get_input_reader): New function.
* incremental.h (class Incremental_binary): Move to end of file.
(Incremental_binary::file_is_unchanged): New function.
(Incremental_binary::do_file_is_unchanged): New function.
(Incremental_binary::Input_reader): New class.
(Incremental_binary::get_input_reader): New function.
(class Sized_incremental_binary): Move to end of file.
(Sized_incremental_binary::Sized_incremental_binary): Setup the
input section reader classes.
(Sized_incremental_binary::has_incremental_info): New function.
(Sized_incremental_binary::inputs_reader): New function.
(Sized_incremental_binary::symtab_reader): New function.
(Sized_incremental_binary::relocs_reader): New function.
(Sized_incremental_binary::got_plt_reader): New function.
(Sized_incremental_binary::do_file_is_unchanged): New function.
(Sized_incremental_binary::Sized_input_reader): New class.
(Sized_incremental_binary::get_input_reader): New function.
(Sized_incremental_binary::find_incremental_inputs_sections):
Rename do_find_incremental_inputs_sections to this.
(Sized_incremental_binary::setup_readers): New function.
(Sized_incremental_binary::has_incremental_info_): New data member.
(Sized_incremental_binary::inputs_reader_): New data member.
(Sized_incremental_binary::symtab_reader_): New data member.
(Sized_incremental_binary::relocs_reader_): New data member.
(Sized_incremental_binary::got_plt_reader_): New data member.
(Sized_incremental_binary::current_input_file_): New data member.

gold/ChangeLog
gold/incremental-dump.cc
gold/incremental.cc
gold/incremental.h

index ec595089a84d102bd4050ac10db5c25e568950bf..98c7a6f1dca6d09235f49b2753293388a998b8aa 100644 (file)
@@ -1,3 +1,43 @@
+2011-04-05  Cary Coutant  <ccoutant@google.com>
+
+       * incremental-dump.cc (dump_incremental_inputs): Change signature
+       to take a Sized_incremental_binary; change caller.  Use readers
+       in Sized_incremental_binary.
+       * incremental.cc
+       (Sized_incremental_binary::find_incremental_inputs_sections):
+       Rename do_find_incremental_inputs_sections to this.
+       (Sized_incremental_binary::setup_readers): New function.
+       (Sized_incremental_binary::do_check_inputs): Check
+       has_incremental_info_ flag; move setup code to setup_readers;
+       use input readers.
+       (Sized_incremental_binary::do_file_is_unchanged): New function.
+       (Sized_incremental_binary::do_get_input_reader): New function.
+       * incremental.h (class Incremental_binary): Move to end of file.
+       (Incremental_binary::file_is_unchanged): New function.
+       (Incremental_binary::do_file_is_unchanged): New function.
+       (Incremental_binary::Input_reader): New class.
+       (Incremental_binary::get_input_reader): New function.
+       (class Sized_incremental_binary): Move to end of file.
+       (Sized_incremental_binary::Sized_incremental_binary): Setup the
+       input section reader classes.
+       (Sized_incremental_binary::has_incremental_info): New function.
+       (Sized_incremental_binary::inputs_reader): New function.
+       (Sized_incremental_binary::symtab_reader): New function.
+       (Sized_incremental_binary::relocs_reader): New function.
+       (Sized_incremental_binary::got_plt_reader): New function.
+       (Sized_incremental_binary::do_file_is_unchanged): New function.
+       (Sized_incremental_binary::Sized_input_reader): New class.
+       (Sized_incremental_binary::get_input_reader): New function.
+       (Sized_incremental_binary::find_incremental_inputs_sections):
+       Rename do_find_incremental_inputs_sections to this.
+       (Sized_incremental_binary::setup_readers): New function.
+       (Sized_incremental_binary::has_incremental_info_): New data member.
+       (Sized_incremental_binary::inputs_reader_): New data member.
+       (Sized_incremental_binary::symtab_reader_): New data member.
+       (Sized_incremental_binary::relocs_reader_): New data member.
+       (Sized_incremental_binary::got_plt_reader_): New data member.
+       (Sized_incremental_binary::current_input_file_): New data member.
+
 2011-04-05  Paul Pluzhnikov  <ppluzhnikov@google.com>
 
        PR gold/12640
index e59b1c5f5b1d2431c7e1085de649e4327fc8de70..6f79f4d5ff123ef48706e6220d2e046f1af200a8 100644 (file)
@@ -73,48 +73,24 @@ find_input_containing_global(
 template<int size, bool big_endian>
 static void
 dump_incremental_inputs(const char* argv0, const char* filename,
-                       Incremental_binary* inc)
+                       Sized_incremental_binary<size, big_endian>* inc)
 {
-  bool t;
-  unsigned int inputs_shndx;
-  unsigned int isymtab_shndx;
-  unsigned int irelocs_shndx;
-  unsigned int igot_plt_shndx;
-  unsigned int istrtab_shndx;
   typedef Incremental_binary::Location Location;
   typedef Incremental_binary::View View;
   typedef Incremental_inputs_reader<size, big_endian> Inputs_reader;
   typedef typename Inputs_reader::Incremental_input_entry_reader Entry_reader;
 
-  // Find the .gnu_incremental_inputs, _symtab, _relocs, and _strtab sections.
-
-  t = inc->find_incremental_inputs_sections(&inputs_shndx, &isymtab_shndx,
-                                           &irelocs_shndx, &igot_plt_shndx,
-                                           &istrtab_shndx);
-  if (!t)
+  if (!inc->has_incremental_info())
     {
       fprintf(stderr, "%s: %s: no .gnu_incremental_inputs section\n", argv0,
               filename);
       exit(1);
     }
 
-  elfcpp::Elf_file<size, big_endian, Incremental_binary> elf_file(inc);
-
-  // Get a view of the .gnu_incremental_inputs section.
-
-  Location inputs_location(elf_file.section_contents(inputs_shndx));
-  View inputs_view(inc->view(inputs_location));
-
-  // Get the .gnu_incremental_strtab section as a string table.
-
-  Location istrtab_location(elf_file.section_contents(istrtab_shndx));
-  View istrtab_view(inc->view(istrtab_location));
-  elfcpp::Elf_strtab istrtab(istrtab_view.data(), istrtab_location.data_size);
-
   // Create a reader object for the .gnu_incremental_inputs section.
 
   Incremental_inputs_reader<size, big_endian>
-      incremental_inputs(inputs_view.data(), istrtab);
+      incremental_inputs(inc->inputs_reader());
 
   if (incremental_inputs.version() != 1)
     {
@@ -265,6 +241,8 @@ dump_incremental_inputs(const char* argv0, const char* filename,
 
   // Get a view of the .symtab section.
 
+  elfcpp::Elf_file<size, big_endian, Incremental_binary> elf_file(inc);
+
   unsigned int symtab_shndx = elf_file.find_section_by_type(elfcpp::SHT_SYMTAB);
   if (symtab_shndx == elfcpp::SHN_UNDEF)  // Not found.
     {
@@ -288,16 +266,6 @@ dump_incremental_inputs(const char* argv0, const char* filename,
   View strtab_view(inc->view(strtab_location));
   elfcpp::Elf_strtab strtab(strtab_view.data(), strtab_location.data_size);
 
-  // Get a view of the .gnu_incremental_symtab section.
-
-  Location isymtab_location(elf_file.section_contents(isymtab_shndx));
-  View isymtab_view(inc->view(isymtab_location));
-
-  // Get a view of the .gnu_incremental_relocs section.
-
-  Location irelocs_location(elf_file.section_contents(irelocs_shndx));
-  View irelocs_view(inc->view(irelocs_location));
-
   // The .gnu_incremental_symtab section contains entries that parallel
   // the global symbols of the main symbol table.  The sh_info field
   // of the main symbol table's section header tells us how many global
@@ -306,15 +274,13 @@ dump_incremental_inputs(const char* argv0, const char* filename,
   // use the size of the .gnu_incremental_symtab section to deduce
   // the number of global symbols + forced-local symbols there are
   // in the symbol table.
+  Incremental_symtab_reader<big_endian> isymtab(inc->symtab_reader());
+  Incremental_relocs_reader<size, big_endian> irelocs(inc->relocs_reader());
   unsigned int sym_size = elfcpp::Elf_sizes<size>::sym_size;
   unsigned int nsyms = symtab_location.data_size / sym_size;
-  unsigned int nglobals = isymtab_location.data_size / 4;
+  unsigned int nglobals = isymtab.symbol_count();
   unsigned int first_global = nsyms - nglobals;
   unsigned const char* sym_p = symtab_view.data() + first_global * sym_size;
-  unsigned const char* isym_p = isymtab_view.data();
-
-  Incremental_symtab_reader<big_endian> isymtab(isymtab_view.data());
-  Incremental_relocs_reader<size, big_endian> irelocs(irelocs_view.data());
 
   printf("\nGlobal symbol table:\n");
   for (unsigned int i = 0; i < nglobals; i++)
@@ -356,15 +322,9 @@ dump_incremental_inputs(const char* argv0, const char* filename,
          offset = sym_info.next_offset;
        }
       sym_p += sym_size;
-      isym_p += 4;
     }
 
-  // Get a view of the .gnu_incremental_got_plt section.
-
-  Location igot_plt_location(elf_file.section_contents(igot_plt_shndx));
-  View igot_plt_view(inc->view(igot_plt_location));
-
-  Incremental_got_plt_reader<big_endian> igot_plt(igot_plt_view.data());
+  Incremental_got_plt_reader<big_endian> igot_plt(inc->got_plt_reader());
   unsigned int ngot = igot_plt.get_got_entry_count();
   unsigned int nplt = igot_plt.get_plt_entry_count();
   
@@ -464,22 +424,30 @@ main(int argc, char** argv)
     {
 #ifdef HAVE_TARGET_32_LITTLE
     case Parameters::TARGET_32_LITTLE:
-      dump_incremental_inputs<32, false>(argv[0], filename, inc);
+      dump_incremental_inputs<32, false>(
+          argv[0], filename,
+          static_cast<Sized_incremental_binary<32, false>*>(inc));
       break;
 #endif
 #ifdef HAVE_TARGET_32_BIG
     case Parameters::TARGET_32_BIG:
-      dump_incremental_inputs<32, true>(argv[0], filename, inc);
+      dump_incremental_inputs<32, true>(
+         argv[0], filename,
+          static_cast<Sized_incremental_binary<32, true>*>(inc));
       break;
 #endif
 #ifdef HAVE_TARGET_64_LITTLE
     case Parameters::TARGET_64_LITTLE:
-      dump_incremental_inputs<64, false>(argv[0], filename, inc);
+      dump_incremental_inputs<64, false>(
+         argv[0], filename,
+          static_cast<Sized_incremental_binary<64, false>*>(inc));
       break;
 #endif
 #ifdef HAVE_TARGET_64_BIG
     case Parameters::TARGET_64_BIG:
-      dump_incremental_inputs<64, true>(argv[0], filename, inc);
+      dump_incremental_inputs<64, true>(
+         argv[0], filename,
+          static_cast<Sized_incremental_binary<64, true>*>(inc));
       break;
 #endif
     default:
index e5f71f5ed6676e8f7c6b0459fda83d2139d5a63a..a38b12b6cd8cde786b6a87d3567d7df0a105e81e 100644 (file)
@@ -154,7 +154,7 @@ Incremental_binary::error(const char* format, ...) const
 
 template<int size, bool big_endian>
 bool
-Sized_incremental_binary<size, big_endian>::do_find_incremental_inputs_sections(
+Sized_incremental_binary<size, big_endian>::find_incremental_inputs_sections(
     unsigned int* p_inputs_shndx,
     unsigned int* p_symtab_shndx,
     unsigned int* p_relocs_shndx,
@@ -206,60 +206,108 @@ Sized_incremental_binary<size, big_endian>::do_find_incremental_inputs_sections(
   return true;
 }
 
-// Determine whether an incremental link based on the existing output file
-// can be done.
+// Set up the readers into the incremental info sections.
 
 template<int size, bool big_endian>
-bool
-Sized_incremental_binary<size, big_endian>::do_check_inputs(
-    Incremental_inputs* incremental_inputs)
+void
+Sized_incremental_binary<size, big_endian>::setup_readers()
 {
   unsigned int inputs_shndx;
   unsigned int symtab_shndx;
   unsigned int relocs_shndx;
-  unsigned int plt_got_shndx;
+  unsigned int got_plt_shndx;
   unsigned int strtab_shndx;
 
-  if (!do_find_incremental_inputs_sections(&inputs_shndx, &symtab_shndx,
-                                          &relocs_shndx, &plt_got_shndx,
-                                          &strtab_shndx))
-    {
-      explain_no_incremental(_("no incremental data from previous build"));
-      return false;
-    }
+  if (!this->find_incremental_inputs_sections(&inputs_shndx, &symtab_shndx,
+                                             &relocs_shndx, &got_plt_shndx,
+                                             &strtab_shndx))
+    return;
 
   Location inputs_location(this->elf_file_.section_contents(inputs_shndx));
   Location symtab_location(this->elf_file_.section_contents(symtab_shndx));
   Location relocs_location(this->elf_file_.section_contents(relocs_shndx));
+  Location got_plt_location(this->elf_file_.section_contents(got_plt_shndx));
   Location strtab_location(this->elf_file_.section_contents(strtab_shndx));
 
-  View inputs_view(view(inputs_location));
-  View symtab_view(view(symtab_location));
-  View relocs_view(view(relocs_location));
-  View strtab_view(view(strtab_location));
+  View inputs_view = this->view(inputs_location);
+  View symtab_view = this->view(symtab_location);
+  View relocs_view = this->view(relocs_location);
+  View got_plt_view = this->view(got_plt_location);
+  View strtab_view = this->view(strtab_location);
 
   elfcpp::Elf_strtab strtab(strtab_view.data(), strtab_location.data_size);
 
-  Incremental_inputs_reader<size, big_endian>
-      incoming_inputs(inputs_view.data(), strtab);
+  this->inputs_reader_ =
+      Incremental_inputs_reader<size, big_endian>(inputs_view.data(), strtab);
+  this->symtab_reader_ =
+      Incremental_symtab_reader<big_endian>(symtab_view.data(),
+                                           symtab_location.data_size);
+  this->relocs_reader_ =
+      Incremental_relocs_reader<size, big_endian>(relocs_view.data(),
+                                                 relocs_location.data_size);
+  this->got_plt_reader_ =
+      Incremental_got_plt_reader<big_endian>(got_plt_view.data());
+  this->has_incremental_info_ = true;
+}
+
+// Determine whether an incremental link based on the existing output file
+// can be done.
+
+template<int size, bool big_endian>
+bool
+Sized_incremental_binary<size, big_endian>::do_check_inputs(
+    Incremental_inputs* incremental_inputs)
+{
+  if (!this->has_incremental_info_)
+    {
+      explain_no_incremental(_("no incremental data from previous build"));
+      return false;
+    }
 
-  if (incoming_inputs.version() != INCREMENTAL_LINK_VERSION)
+  if (this->inputs_reader_.version() != INCREMENTAL_LINK_VERSION)
     {
       explain_no_incremental(_("different version of incremental build data"));
       return false;
     }
 
-  if (incremental_inputs->command_line() != incoming_inputs.command_line())
+  if (incremental_inputs->command_line() != this->inputs_reader_.command_line())
     {
       explain_no_incremental(_("command line changed"));
       return false;
     }
 
-  // TODO: compare incremental_inputs->inputs() with entries in data_view.
-
   return true;
 }
 
+// Return TRUE if the file specified by INPUT_ARGUMENT is unchanged
+// with respect to the base file.
+
+template<int size, bool big_endian>
+bool
+Sized_incremental_binary<size, big_endian>::do_file_is_unchanged(
+    const Input_argument* input_argument) const
+{
+  Incremental_disposition disp =
+      input_argument->file().options().incremental_disposition();
+
+  if (disp != INCREMENTAL_CHECK)
+    return disp == INCREMENTAL_UNCHANGED;
+
+  // FIXME: Handle INCREMENTAL_CHECK.
+  return false;
+}
+
+
+template<int size, bool big_endian>
+Incremental_binary::Input_reader*
+Sized_incremental_binary<size, big_endian>::do_get_input_reader(
+    const char*)
+{
+  unsigned int file_index = this->current_input_file_++;
+  gold_assert(file_index < this->inputs_reader_.input_file_count());
+  return new Sized_input_reader(this->inputs_reader_.input_file(file_index));
+}
+
 namespace
 {
 
index b799f7bcffb4fb01513f415af088d62ee5b36bc5..815f761ff33b0adc84aeeef1a319519c9d7afe7d 100644 (file)
@@ -42,6 +42,7 @@ class Incremental_script_entry;
 class Incremental_object_entry;
 class Incremental_archive_entry;
 class Incremental_inputs;
+class Incremental_binary;
 class Object;
 
 // Incremental input type as stored in .gnu_incremental_inputs.
@@ -55,147 +56,6 @@ enum Incremental_input_type
   INCREMENTAL_INPUT_SCRIPT = 5
 };
 
-// An object representing the ELF file we edit during an incremental build.
-// Similar to Object or Dynobj, but operates on Output_file and contains
-// method specific to file edition (TBD). This is the abstract parent class
-// implemented in Sized_incremental_binary<size, big_endian> for a specific
-// endianness and size.
-
-class Incremental_binary
-{
- public:
-  Incremental_binary(Output_file* output, Target* target)
-    : output_(output), target_(target)
-  { }
-
-  virtual
-  ~Incremental_binary()
-  { }
-
-  // Functions and types for the elfcpp::Elf_file interface.  This
-  // permit us to use Incremental_binary as the File template parameter for
-  // elfcpp::Elf_file.
-
-  // The View class is returned by view.  It must support a single
-  // method, data().  This is trivial, because Output_file::get_output_view
-  // does what we need.
-  class View
-  {
-   public:
-    View(const unsigned char* p)
-      : p_(p)
-    { }
-
-    const unsigned char*
-    data() const
-    { return this->p_; }
-
-   private:
-    const unsigned char* p_;
-  };
-
-  // Return a View.
-  View
-  view(off_t file_offset, section_size_type data_size)
-  { return View(this->output_->get_input_view(file_offset, data_size)); }
-
-  // A location in the file.
-  struct Location
-  {
-    off_t file_offset;
-    off_t data_size;
-
-    Location(off_t fo, section_size_type ds)
-      : file_offset(fo), data_size(ds)
-    { }
-
-    Location()
-      : file_offset(0), data_size(0)
-    { }
-  };
-
-  // Get a View given a Location.
-  View
-  view(Location loc)
-  { return View(this->view(loc.file_offset, loc.data_size)); }
-
-  // Report an error.
-  void
-  error(const char* format, ...) const ATTRIBUTE_PRINTF_2;
-
-  // Find the .gnu_incremental_inputs and related sections.  It selects the
-  // first section of type SHT_GNU_INCREMENTAL_INPUTS,
-  // SHT_GNU_INCREMENTAL_SYMTAB, and SHT_GNU_INCREMENTAL_RELOCS.
-  // Returns false if the sections are not found.
-  bool
-  find_incremental_inputs_sections(unsigned int* p_inputs_shndx,
-                                  unsigned int* p_symtab_shndx,
-                                  unsigned int* p_relocs_shndx,
-                                  unsigned int* p_got_plt_shndx,
-                                  unsigned int* p_strtab_shndx)
-  {
-    return do_find_incremental_inputs_sections(p_inputs_shndx, p_symtab_shndx,
-                                              p_relocs_shndx, p_got_plt_shndx,
-                                              p_strtab_shndx);
-  }
-
-  // Check the .gnu_incremental_inputs section to see whether an incremental
-  // build is possible.
-  // TODO: on success, should report what files needs to be rebuilt.
-  // INCREMENTAL_INPUTS is used to read the canonical form of the command line
-  // and read the input arguments.  TODO: for items that don't need to be
-  // rebuilt, we should also copy the incremental input information.
-  virtual bool
-  check_inputs(Incremental_inputs* incremental_inputs)
-  { return do_check_inputs(incremental_inputs); }
-
- protected:
-  // Find incremental inputs section.
-  virtual bool
-  do_find_incremental_inputs_sections(unsigned int* p_inputs_shndx,
-                                     unsigned int* p_symtab_shndx,
-                                     unsigned int* p_relocs_shndx,
-                                     unsigned int* p_got_plt_shndx,
-                                     unsigned int* p_strtab_shndx) = 0;
-
-  // Check the .gnu_incremental_inputs section to see whether an incremental
-  // build is possible.
-  virtual bool
-  do_check_inputs(Incremental_inputs* incremental_inputs) = 0;
-
- private:
-  // Edited output file object.
-  Output_file* output_;
-  // Target of the output file.
-  Target* target_;
-};
-
-template<int size, bool big_endian>
-class Sized_incremental_binary : public Incremental_binary
-{
- public:
-  Sized_incremental_binary(Output_file* output,
-                           const elfcpp::Ehdr<size, big_endian>& ehdr,
-                           Target* target)
-    : Incremental_binary(output, target), elf_file_(this, ehdr)
-  { }
-
- protected:
-  virtual bool
-  do_find_incremental_inputs_sections(unsigned int* p_inputs_shndx,
-                                     unsigned int* p_symtab_shndx,
-                                     unsigned int* p_relocs_shndx,
-                                     unsigned int* p_got_plt_shndx,
-                                     unsigned int* p_strtab_shndx);
-
-  virtual bool
-  do_check_inputs(Incremental_inputs* incremental_inputs);
-
- private:
-  // Output as an ELF file.
-  elfcpp::Elf_file<size, big_endian, Incremental_binary> elf_file_;
-};
-
 // Create an Incremental_binary object for FILE. Returns NULL is this is not
 // possible, e.g. FILE is not an ELF file or has an unsupported target.
 
@@ -689,7 +549,12 @@ class Incremental_inputs_reader
   typedef elfcpp::Swap<64, big_endian> Swap64;
 
  public:
-  Incremental_inputs_reader(const unsigned char* p, elfcpp::Elf_strtab& strtab)
+  Incremental_inputs_reader()
+    : p_(NULL), strtab_(NULL, 0), input_file_count_(0)
+  { }
+
+  Incremental_inputs_reader(const unsigned char* p,
+                           const elfcpp::Elf_strtab& strtab)
     : p_(p), strtab_(strtab)
   { this->input_file_count_ = Swap32::readval(this->p_ + 4); }
 
@@ -939,16 +804,29 @@ template<bool big_endian>
 class Incremental_symtab_reader
 {
  public:
-  Incremental_symtab_reader(const unsigned char* p) : p_(p)
+  Incremental_symtab_reader()
+    : p_(NULL), len_(0)
+  { }
+
+  Incremental_symtab_reader(const unsigned char* p, off_t len)
+    : p_(p), len_(len)
   { }
 
+  // Return the count of symbols in this section.
+  unsigned int
+  symbol_count() const
+  { return static_cast<unsigned int>(this->len_ / 4); }
+
   // Return the list head for symbol table entry N.
-  unsigned int get_list_head(unsigned int n) const
+  unsigned int
+  get_list_head(unsigned int n) const
   { return elfcpp::Swap<32, big_endian>::readval(this->p_ + 4 * n); }
 
  private:
   // Base address of the .gnu_incremental_relocs section.
   const unsigned char* p_;
+  // Size of the section.
+  off_t len_;
 };
 
 // Reader class for the .gnu_incremental_relocs section.
@@ -967,9 +845,19 @@ class Incremental_relocs_reader
   // Size of each entry.
   static const unsigned int reloc_size = 8 + 2 * field_size;
 
-  Incremental_relocs_reader(const unsigned char* p) : p_(p)
+  Incremental_relocs_reader()
+    : p_(NULL), len_(0)
+  { }
+
+  Incremental_relocs_reader(const unsigned char* p, off_t len)
+    : p_(p), len_(len)
   { }
 
+  // Return the count of relocations in this section.
+  unsigned int
+  reloc_count() const
+  { return static_cast<unsigned int>(this->len_ / reloc_size); }
+
   // Return the relocation type for relocation entry at offset OFF.
   unsigned int
   get_r_type(unsigned int off) const
@@ -1002,6 +890,8 @@ class Incremental_relocs_reader
  private:
   // Base address of the .gnu_incremental_relocs section.
   const unsigned char* p_;
+  // Size of the section.
+  off_t len_;
 };
 
 // Reader class for the .gnu_incremental_got_plt section.
@@ -1010,6 +900,10 @@ template<bool big_endian>
 class Incremental_got_plt_reader
 {
  public:
+  Incremental_got_plt_reader()
+    : p_(NULL), got_count_(0), got_desc_p_(NULL), plt_desc_p_(NULL)
+  { }
+
   Incremental_got_plt_reader(const unsigned char* p) : p_(p)
   {
     this->got_count_ = elfcpp::Swap<32, big_endian>::readval(p);
@@ -1063,6 +957,251 @@ class Incremental_got_plt_reader
   const unsigned char* plt_desc_p_;
 };
 
+// An object representing the ELF file we edit during an incremental build.
+// Similar to Object or Dynobj, but operates on Output_file and contains
+// methods to support incremental updating. This is the abstract parent class
+// implemented in Sized_incremental_binary<size, big_endian> for a specific
+// endianness and size.
+
+class Incremental_binary
+{
+ public:
+  Incremental_binary(Output_file* output, Target* target)
+    : output_(output), target_(target)
+  { }
+
+  virtual
+  ~Incremental_binary()
+  { }
+
+  // Check the .gnu_incremental_inputs section to see whether an incremental
+  // build is possible.
+  bool
+  check_inputs(Incremental_inputs* incremental_inputs)
+  { return this->do_check_inputs(incremental_inputs); }
+
+  // Return TRUE if the file specified by INPUT_ARGUMENT is unchanged
+  // with respect to the base file.
+  bool
+  file_is_unchanged(const Input_argument* input_argument) const
+  { return this->do_file_is_unchanged(input_argument); }
+
+  // Report an error.
+  void
+  error(const char* format, ...) const ATTRIBUTE_PRINTF_2;
+
+  // Wrapper class for a sized Incremental_input_entry_reader.
+  
+  class Input_reader
+  {
+   public:
+    Input_reader()
+    { }
+
+    virtual
+    ~Input_reader()
+    { }
+
+    const char*
+    filename() const
+    { return this->do_filename(); }
+
+    Timespec
+    get_mtime() const
+    { return this->do_get_mtime(); }
+
+    Incremental_input_type
+    type() const
+    { return this->do_type(); }
+
+   protected:
+    virtual const char*
+    do_filename() const = 0;
+
+    virtual Timespec
+    do_get_mtime() const = 0;
+
+    virtual Incremental_input_type
+    do_type() const = 0;
+  };
+
+  Input_reader*
+  get_input_reader(const char* filename)
+  { return this->do_get_input_reader(filename); }
+
+  // Functions and types for the elfcpp::Elf_file interface.  This
+  // permit us to use Incremental_binary as the File template parameter for
+  // elfcpp::Elf_file.
+
+  // The View class is returned by view.  It must support a single
+  // method, data().  This is trivial, because Output_file::get_output_view
+  // does what we need.
+  class View
+  {
+   public:
+    View(const unsigned char* p)
+      : p_(p)
+    { }
+
+    const unsigned char*
+    data() const
+    { return this->p_; }
+
+   private:
+    const unsigned char* p_;
+  };
+
+  // Return a View.
+  View
+  view(off_t file_offset, section_size_type data_size)
+  { return View(this->output_->get_input_view(file_offset, data_size)); }
+
+  // A location in the file.
+  struct Location
+  {
+    off_t file_offset;
+    off_t data_size;
+
+    Location(off_t fo, section_size_type ds)
+      : file_offset(fo), data_size(ds)
+    { }
+
+    Location()
+      : file_offset(0), data_size(0)
+    { }
+  };
+
+  // Get a View given a Location.
+  View
+  view(Location loc)
+  { return View(this->view(loc.file_offset, loc.data_size)); }
+
+ protected:
+  // Check the .gnu_incremental_inputs section to see whether an incremental
+  // build is possible.
+  virtual bool
+  do_check_inputs(Incremental_inputs* incremental_inputs) = 0;
+
+  // Return TRUE if the file specified by INPUT_ARGUMENT is unchanged
+  // with respect to the base file.
+  virtual bool
+  do_file_is_unchanged(const Input_argument* input_argument) const = 0;
+
+  virtual Input_reader*
+  do_get_input_reader(const char* filename) = 0;
+
+ private:
+  // Edited output file object.
+  Output_file* output_;
+  // Target of the output file.
+  Target* target_;
+};
+
+template<int size, bool big_endian>
+class Sized_incremental_binary : public Incremental_binary
+{
+ public:
+  Sized_incremental_binary(Output_file* output,
+                           const elfcpp::Ehdr<size, big_endian>& ehdr,
+                           Target* target)
+    : Incremental_binary(output, target), elf_file_(this, ehdr),
+      has_incremental_info_(false), inputs_reader_(), symtab_reader_(),
+      relocs_reader_(), got_plt_reader_(), current_input_file_(0)
+  { this->setup_readers(); }
+
+  // Returns TRUE if the file contains incremental info.
+  bool
+  has_incremental_info() const
+  { return this->has_incremental_info_; }
+
+  // Readers for the incremental info sections.
+
+  Incremental_inputs_reader<size, big_endian>
+  inputs_reader() const
+  { return this->inputs_reader_; }
+
+  Incremental_symtab_reader<big_endian>
+  symtab_reader() const
+  { return this->symtab_reader_; }
+
+  Incremental_relocs_reader<size, big_endian>
+  relocs_reader() const
+  { return this->relocs_reader_; }
+
+  Incremental_got_plt_reader<big_endian>
+  got_plt_reader() const
+  { return this->got_plt_reader_; }
+
+ protected:
+  virtual bool
+  do_check_inputs(Incremental_inputs* incremental_inputs);
+
+  // Return TRUE if the file specified by INPUT_ARGUMENT is unchanged
+  // with respect to the base file.
+  virtual bool
+  do_file_is_unchanged(const Input_argument* input_argument) const;
+
+  // Wrapper class for a sized Incremental_input_entry_reader.
+  
+  class Sized_input_reader : public Input_reader
+  {
+   public:
+    typedef Incremental_inputs_reader<size, big_endian> Inputs_reader;
+    typedef typename Inputs_reader::Incremental_input_entry_reader
+        Input_entry_reader;
+
+    Sized_input_reader(Input_entry_reader r)
+      : Input_reader(), reader_(r)
+    { }
+
+    virtual
+    ~Sized_input_reader()
+    { }
+
+   private:
+    const char*
+    do_filename() const
+    { return this->reader_.filename(); }
+
+    Timespec
+    do_get_mtime() const
+    { return this->reader_.get_mtime(); }
+
+    Incremental_input_type
+    do_type() const
+    { return this->reader_.type(); }
+
+    Input_entry_reader reader_;
+  };
+
+  virtual Input_reader*
+  do_get_input_reader(const char* filename);
+
+ private:
+  bool
+  find_incremental_inputs_sections(unsigned int* p_inputs_shndx,
+                                  unsigned int* p_symtab_shndx,
+                                  unsigned int* p_relocs_shndx,
+                                  unsigned int* p_got_plt_shndx,
+                                  unsigned int* p_strtab_shndx);
+
+  void
+  setup_readers();
+
+  // Output as an ELF file.
+  elfcpp::Elf_file<size, big_endian, Incremental_binary> elf_file_;
+
+  // Readers for the incremental info sections.
+  bool has_incremental_info_;
+  Incremental_inputs_reader<size, big_endian> inputs_reader_;
+  Incremental_symtab_reader<big_endian> symtab_reader_;
+  Incremental_relocs_reader<size, big_endian> relocs_reader_;
+  Incremental_got_plt_reader<big_endian> got_plt_reader_;
+
+  // Index of the current input file entry.
+  int current_input_file_;
+};
+
 } // End namespace gold.
 
 #endif // !defined(GOLD_INCREMENTAL_H)