// inremental.h -- incremental linking support for gold   -*- C++ -*-

// Copyright 2009, 2010 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 <map>
#include <vector>

#include "elfcpp_file.h"
#include "stringpool.h"
#include "workqueue.h"
#include "fileread.h"
#include "output.h"
#include "archive.h"

namespace gold
{

class Input_argument;
class Incremental_inputs_checker;
class Incremental_script_entry;
class Incremental_object_entry;
class Incremental_dynobj_entry;
class Incremental_archive_entry;
class Incremental_inputs;
class Incremental_binary;
class Incremental_library;
class Object;

// Incremental input type as stored in .gnu_incremental_inputs.

enum Incremental_input_type
{
  INCREMENTAL_INPUT_OBJECT = 1,
  INCREMENTAL_INPUT_ARCHIVE_MEMBER = 2,
  INCREMENTAL_INPUT_ARCHIVE = 3,
  INCREMENTAL_INPUT_SHARED_LIBRARY = 4,
  INCREMENTAL_INPUT_SCRIPT = 5
};

// Incremental input file flags.
// The input file type is stored in the lower eight bits.

enum Incremental_input_flags
{
  INCREMENTAL_INPUT_IN_SYSTEM_DIR = 0x8000,
  INCREMENTAL_INPUT_AS_NEEDED = 0x4000
};

// Symbol flags for the incremental symbol table.
// These flags are stored in the top two bits of
// the symbol index field.

enum Incremental_shlib_symbol_flags
{
  // Symbol is defined in this library.
  INCREMENTAL_SHLIB_SYM_DEF = 2,
  // Symbol is defined in this library, with a COPY relocation.
  INCREMENTAL_SHLIB_SYM_COPY = 3
};

static const int INCREMENTAL_SHLIB_SYM_FLAGS_SHIFT = 30;

// Return TRUE if a section of type SH_TYPE can be updated in place
// during an incremental update.
bool
can_incremental_update(unsigned int sh_type);

// 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.

Incremental_binary*
open_incremental_binary(Output_file* file);

// Base class for recording each input file.

class Incremental_input_entry
{
 public:
  Incremental_input_entry(Stringpool::Key filename_key, unsigned int arg_serial,
			  Timespec mtime)
    : filename_key_(filename_key), file_index_(0), offset_(0), info_offset_(0),
      arg_serial_(arg_serial), mtime_(mtime), is_in_system_directory_(false),
      as_needed_(false)
  { }

  virtual
  ~Incremental_input_entry()
  { }

  // Return the type of input file.
  Incremental_input_type
  type() const
  { return this->do_type(); }

  // Set the index and section offset of this input file entry.
  void
  set_offset(unsigned int file_index, unsigned int offset)
  {
    this->file_index_ = file_index;
    this->offset_ = offset;
  }

  // Set the section offset of the supplemental information for this entry.
  void
  set_info_offset(unsigned int info_offset)
  { this->info_offset_ = info_offset; }

  // Get the index of this input file entry.
  unsigned int
  get_file_index() const
  { return this->file_index_; }

  // Get the section offset of this input file entry.
  unsigned int
  get_offset() const
  { return this->offset_; }

  // Get the section offset of the supplemental information for this entry.
  unsigned int
  get_info_offset() const
  { return this->info_offset_; }

  // Get the stringpool key for the input filename.
  Stringpool::Key
  get_filename_key() const
  { return this->filename_key_; }

  // Get the serial number of the input file.
  unsigned int
  arg_serial() const
  { return this->arg_serial_; }

  // Get the modification time of the input file.
  const Timespec&
  get_mtime() const
  { return this->mtime_; }

  // Record that the file was found in a system directory.
  void
  set_is_in_system_directory()
  { this->is_in_system_directory_ = true; }

  // Return TRUE if the file was found in a system directory.
  bool
  is_in_system_directory() const
  { return this->is_in_system_directory_; }

  // Record that the file was linked with --as-needed.
  void
  set_as_needed()
  { this->as_needed_ = true; }

  // Return TRUE if the file was linked with --as-needed.
  bool
  as_needed() const
  { return this->as_needed_; }

  // Return a pointer to the derived Incremental_script_entry object.
  // Return NULL for input entries that are not script files.
  Incremental_script_entry*
  script_entry()
  { return this->do_script_entry(); }

  // Return a pointer to the derived Incremental_object_entry object.
  // Return NULL for input entries that are not object files.
  Incremental_object_entry*
  object_entry()
  { return this->do_object_entry(); }

  // Return a pointer to the derived Incremental_dynobj_entry object.
  // Return NULL for input entries that are not shared object files.
  Incremental_dynobj_entry*
  dynobj_entry()
  { return this->do_dynobj_entry(); }

  // Return a pointer to the derived Incremental_archive_entry object.
  // Return NULL for input entries that are not archive files.
  Incremental_archive_entry*
  archive_entry()
  { return this->do_archive_entry(); }

 protected:
  // Return the type of input file.
  virtual Incremental_input_type
  do_type() const = 0;

  // Return a pointer to the derived Incremental_script_entry object.
  // Return NULL for input entries that are not script files.
  virtual Incremental_script_entry*
  do_script_entry()
  { return NULL; }

  // Return a pointer to the derived Incremental_object_entry object.
  // Return NULL for input entries that are not object files.
  virtual Incremental_object_entry*
  do_object_entry()
  { return NULL; }

  // Return a pointer to the derived Incremental_dynobj_entry object.
  // Return NULL for input entries that are not shared object files.
  virtual Incremental_dynobj_entry*
  do_dynobj_entry()
  { return NULL; }

  // Return a pointer to the derived Incremental_archive_entry object.
  // Return NULL for input entries that are not archive files.
  virtual Incremental_archive_entry*
  do_archive_entry()
  { return NULL; }

 private:
  // Key of the filename string in the section stringtable.
  Stringpool::Key filename_key_;

  // Index of the entry in the output section.
  unsigned int file_index_;

  // Offset of the entry in the output section.
  unsigned int offset_;

  // Offset of the extra information in the output section.
  unsigned int info_offset_;

  // Serial number of the file in the argument list.
  unsigned int arg_serial_;

  // Last modification time of the file.
  Timespec mtime_;

  // TRUE if the file was found in a system directory.
  bool is_in_system_directory_;

  // TRUE if the file was linked with --as-needed.
  bool as_needed_;
};

// 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(const std::string& filename)
    : filename_(filename), input_file_index_(0),
      incremental_script_entry_(NULL)
  { }

  Script_info(const std::string& filename, unsigned int input_file_index)
    : filename_(filename), input_file_index_(input_file_index),
      incremental_script_entry_(NULL)
  { }

  // Store a pointer to the incremental information for this script.
  void
  set_incremental_info(Incremental_script_entry* entry)
  { this->incremental_script_entry_ = entry; }

  // Return the filename.
  const std::string&
  filename() const
  { return this->filename_; }

  // Return the input file index.
  unsigned int
  input_file_index() const
  { return this->input_file_index_; }

  // Return the pointer to the incremental information for this script.
  Incremental_script_entry*
  incremental_info() const
  { return this->incremental_script_entry_; }

 private:
  const std::string filename_;
  unsigned int input_file_index_;
  Incremental_script_entry* incremental_script_entry_;
};

// Class for recording input scripts.

class Incremental_script_entry : public Incremental_input_entry
{
 public:
  Incremental_script_entry(Stringpool::Key filename_key,
			   unsigned int arg_serial, Script_info* script,
			   Timespec mtime)
    : Incremental_input_entry(filename_key, arg_serial, mtime),
      script_(script), objects_()
  { }

  // Add a member object to the archive.
  void
  add_object(Incremental_input_entry* obj_entry)
  {
    this->objects_.push_back(obj_entry);
  }

  // Return the number of objects included by this script.
  unsigned int
  get_object_count()
  { return this->objects_.size(); }

  // Return the Nth object.
  Incremental_input_entry*
  get_object(unsigned int n)
  {
    gold_assert(n < this->objects_.size());
    return this->objects_[n];
  }

 protected:
  virtual Incremental_input_type
  do_type() const
  { return INCREMENTAL_INPUT_SCRIPT; }

  // Return a pointer to the derived Incremental_script_entry object.
  virtual Incremental_script_entry*
  do_script_entry()
  { return this; }

 private:
  // Information about the script file.
  Script_info* script_;
  // Objects that have been included by this script.
  std::vector<Incremental_input_entry*> objects_;
};

// Class for recording input object files.

class Incremental_object_entry : public Incremental_input_entry
{
 public:
  Incremental_object_entry(Stringpool::Key filename_key, Object* obj,
			   unsigned int arg_serial, Timespec mtime)
    : Incremental_input_entry(filename_key, arg_serial, mtime), obj_(obj),
      is_member_(false), sections_(), groups_()
  { this->sections_.reserve(obj->shnum()); }

  // Get the object.
  Object*
  object() const
  { return this->obj_; }

  // Record that this object is an archive member.
  void
  set_is_member()
  { this->is_member_ = true; }

  // Return true if this object is an archive member.
  bool
  is_member() const
  { return this->is_member_; }

  // Add an input section.
  void
  add_input_section(unsigned int shndx, Stringpool::Key name_key, off_t sh_size)
  { this->sections_.push_back(Input_section(shndx, name_key, sh_size)); }

  // Return the number of input sections in this object.
  unsigned int
  get_input_section_count() const
  { return this->sections_.size(); }

  // Return the input section index for the Nth input section.
  Stringpool::Key
  get_input_section_index(unsigned int n) const
  { return this->sections_[n].shndx_; }

  // Return the stringpool key of the Nth input section.
  Stringpool::Key
  get_input_section_name_key(unsigned int n) const
  { return this->sections_[n].name_key_; }

  // Return the size of the Nth input section.
  off_t
  get_input_section_size(unsigned int n) const
  { return this->sections_[n].sh_size_; }

  // Add a kept COMDAT group.
  void
  add_comdat_group(Stringpool::Key signature_key)
  { this->groups_.push_back(signature_key); }

  // Return the number of COMDAT groups.
  unsigned int
  get_comdat_group_count() const
  { return this->groups_.size(); }

  // Return the stringpool key for the signature of the Nth comdat group.
  Stringpool::Key
  get_comdat_signature_key(unsigned int n) const
  { return this->groups_[n]; }

 protected:
  virtual Incremental_input_type
  do_type() const
  {
    return (this->is_member_
	    ? INCREMENTAL_INPUT_ARCHIVE_MEMBER
	    : INCREMENTAL_INPUT_OBJECT);
  }

  // Return a pointer to the derived Incremental_object_entry object.
  virtual Incremental_object_entry*
  do_object_entry()
  { return this; }

 private:
  // The object file itself.
  Object* obj_;

  // Whether this object is an archive member.
  bool is_member_;

  // Input sections.
  struct Input_section
  {
    Input_section(unsigned int shndx, Stringpool::Key name_key, off_t sh_size)
      : shndx_(shndx), name_key_(name_key), sh_size_(sh_size)
    { }
    unsigned int shndx_;
    Stringpool::Key name_key_;
    off_t sh_size_;
  };
  std::vector<Input_section> sections_;

  // COMDAT groups.
  std::vector<Stringpool::Key> groups_;
};

// Class for recording shared library input files.

class Incremental_dynobj_entry : public Incremental_input_entry
{
 public:
  Incremental_dynobj_entry(Stringpool::Key filename_key,
  			   Stringpool::Key soname_key, Object* obj,
			   unsigned int arg_serial, Timespec mtime)
    : Incremental_input_entry(filename_key, arg_serial, mtime),
      soname_key_(soname_key), obj_(obj)
  { }

  // Get the object.
  Object*
  object() const
  { return this->obj_; }

  // Get the stringpool key for the soname.
  Stringpool::Key
  get_soname_key() const
  { return this->soname_key_; }

 protected:
  virtual Incremental_input_type
  do_type() const
  { return INCREMENTAL_INPUT_SHARED_LIBRARY; }

  // Return a pointer to the derived Incremental_dynobj_entry object.
  virtual Incremental_dynobj_entry*
  do_dynobj_entry()
  { return this; }

 private:
  // Key of the soname string in the section stringtable.
  Stringpool::Key soname_key_;

  // The object file itself.
  Object* obj_;
};

// Class for recording archive library input files.

class Incremental_archive_entry : public Incremental_input_entry
{
 public:
  Incremental_archive_entry(Stringpool::Key filename_key,
			    unsigned int arg_serial, Timespec mtime)
    : Incremental_input_entry(filename_key, arg_serial, mtime), members_(),
      unused_syms_()
  { }

  // Add a member object to the archive.
  void
  add_object(Incremental_object_entry* obj_entry)
  {
    this->members_.push_back(obj_entry);
    obj_entry->set_is_member();
  }

  // Add an unused global symbol to the archive.
  void
  add_unused_global_symbol(Stringpool::Key symbol_key)
  { this->unused_syms_.push_back(symbol_key); }

  // Return the number of member objects included in the link.
  unsigned int
  get_member_count()
  { return this->members_.size(); }

  // Return the Nth member object.
  Incremental_object_entry*
  get_member(unsigned int n)
  { return this->members_[n]; }

  // Return the number of unused global symbols in this archive.
  unsigned int
  get_unused_global_symbol_count()
  { return this->unused_syms_.size(); }

  // Return the Nth unused global symbol.
  Stringpool::Key
  get_unused_global_symbol(unsigned int n)
  { return this->unused_syms_[n]; }

 protected:
  virtual Incremental_input_type
  do_type() const
  { return INCREMENTAL_INPUT_ARCHIVE; }

  // Return a pointer to the derived Incremental_archive_entry object.
  virtual Incremental_archive_entry*
  do_archive_entry()
  { return this; }

 private:
  // Members of the archive that have been included in the link.
  std::vector<Incremental_object_entry*> members_;

  // Unused global symbols from this archive.
  std::vector<Stringpool::Key> unused_syms_;
};

// This class contains the information needed during an incremental
// build about the inputs necessary to build the .gnu_incremental_inputs.

class Incremental_inputs
{
 public:
  typedef std::vector<Incremental_input_entry*> Input_list;

  Incremental_inputs()
    : inputs_(), command_line_(), command_line_key_(0),
      strtab_(new Stringpool()), current_object_(NULL),
      current_object_entry_(NULL), inputs_section_(NULL),
      symtab_section_(NULL), relocs_section_(NULL),
      reloc_count_(0)
  { }

  ~Incremental_inputs() { delete this->strtab_; }

  // Record the command line.
  void
  report_command_line(int argc, const char* const* argv);

  // Record the initial info for archive file ARCHIVE.
  void
  report_archive_begin(Library_base* arch, unsigned int arg_serial,
		       Script_info* script_info);

  // Record the final info for archive file ARCHIVE.
  void
  report_archive_end(Library_base* arch);

  // Record the info for object file OBJ.  If ARCH is not NULL,
  // attach the object file to the archive.
  void
  report_object(Object* obj, unsigned int arg_serial, Library_base* arch,
		Script_info* script_info);

  // Record an input section belonging to object file OBJ.
  void
  report_input_section(Object* obj, unsigned int shndx, const char* name,
		       off_t sh_size);

  // Record a kept COMDAT group belonging to object file OBJ.
  void
  report_comdat_group(Object* obj, const char* name);

  // Record the info for input script SCRIPT.
  void
  report_script(Script_info* script, unsigned int arg_serial,
		Timespec mtime);

  // Return the running count of incremental relocations.
  unsigned int
  get_reloc_count() const
  { return this->reloc_count_; }

  // Update the running count of incremental relocations.
  void
  set_reloc_count(unsigned int count)
  { this->reloc_count_ = count; }

  // Prepare for layout.  Called from Layout::finalize.
  void
  finalize();

  // Create the .gnu_incremental_inputs and related sections.
  void
  create_data_sections(Symbol_table* symtab);

  // Return the .gnu_incremental_inputs section.
  Output_section_data*
  inputs_section() const
  { return this->inputs_section_; }

  // Return the .gnu_incremental_symtab section.
  Output_data_space*
  symtab_section() const
  { return this->symtab_section_; }

  // Return the .gnu_incremental_relocs section.
  Output_data_space*
  relocs_section() const
  { return this->relocs_section_; }

  // Return the .gnu_incremental_got_plt section.
  Output_data_space*
  got_plt_section() const
  { return this->got_plt_section_; }

  // Return the .gnu_incremental_strtab stringpool.
  Stringpool*
  get_stringpool() const
  { return this->strtab_; }

  // Return the canonical form of the command line, as will be stored in
  // .gnu_incremental_strtab.
  const std::string&
  command_line() const
  { return this->command_line_; }

  // Return the stringpool key of the command line.
  Stringpool::Key
  command_line_key() const
  { return this->command_line_key_; }

  // Return the number of input files.
  int
  input_file_count() const
  { return this->inputs_.size(); }

  // Return the input files.
  const Input_list&
  input_files() const
  { return this->inputs_; }

  // Return the sh_entsize value for the .gnu_incremental_relocs section.
  unsigned int
  relocs_entsize() const;

 private:
  // The list of input files.
  Input_list inputs_;

  // Canonical form of the command line, as will be stored in
  // .gnu_incremental_strtab.
  std::string command_line_;

  // 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_;

  // Keep track of the object currently being processed.
  Object* current_object_;
  Incremental_object_entry* current_object_entry_;

  // The .gnu_incremental_inputs section.
  Output_section_data* inputs_section_;

  // The .gnu_incremental_symtab section.
  Output_data_space* symtab_section_;

  // The .gnu_incremental_relocs section.
  Output_data_space* relocs_section_;

  // The .gnu_incremental_got_plt section.
  Output_data_space* got_plt_section_;

  // Total count of incremental relocations.  Updated during Scan_relocs
  // phase at the completion of each object file.
  unsigned int reloc_count_;
};

// Reader class for global symbol info from an object file entry in
// the .gnu_incremental_inputs section.

template<bool big_endian>
class Incremental_global_symbol_reader
{
 private:
  typedef elfcpp::Swap<32, big_endian> Swap32;

 public:
  Incremental_global_symbol_reader(const unsigned char* p)
    : p_(p)
  { }

  unsigned int
  output_symndx() const
  { return Swap32::readval(this->p_); }

  unsigned int
  shndx() const
  { return Swap32::readval(this->p_ + 4); }

  unsigned int
  next_offset() const
  { return Swap32::readval(this->p_ + 8); }

  unsigned int
  reloc_count() const
  { return Swap32::readval(this->p_ + 12); }

  unsigned int
  reloc_offset() const
  { return Swap32::readval(this->p_ + 16); }

 private:
  // Base address of the symbol entry.
  const unsigned char* p_;
};

// Reader class for .gnu_incremental_inputs section.

template<int size, bool big_endian>
class Incremental_inputs_reader
{
 private:
  typedef elfcpp::Swap<size, big_endian> Swap;
  typedef elfcpp::Swap<16, big_endian> Swap16;
  typedef elfcpp::Swap<32, big_endian> Swap32;
  typedef elfcpp::Swap<64, big_endian> Swap64;

 public:
  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); }

  // Return the version number.
  unsigned int
  version() const
  { return Swap32::readval(this->p_); }

  // Return the count of input file entries.
  unsigned int
  input_file_count() const
  { return this->input_file_count_; }

  // Return the command line.
  const char*
  command_line() const
  {
    unsigned int offset = Swap32::readval(this->p_ + 8);
    return this->get_string(offset);
  }

  // Reader class for an input file entry and its supplemental info.
  class Incremental_input_entry_reader
  {
   public:
    Incremental_input_entry_reader(const Incremental_inputs_reader* inputs,
				   unsigned int offset)
      : inputs_(inputs), offset_(offset)
    {
      this->info_offset_ = Swap32::readval(inputs->p_ + offset + 4);
      this->flags_ = Swap16::readval(this->inputs_->p_ + offset + 20);
    }

    // Return the filename.
    const char*
    filename() const
    {
      unsigned int offset = Swap32::readval(this->inputs_->p_ + this->offset_);
      return this->inputs_->get_string(offset);
    }

    // Return the argument serial number.
    unsigned int
    arg_serial() const
    {
      return Swap16::readval(this->inputs_->p_ + this->offset_ + 22);
    }

    // Return the timestamp.
    Timespec
    get_mtime() const
    {
      Timespec t;
      const unsigned char* p = this->inputs_->p_ + this->offset_ + 8;
      t.seconds = Swap64::readval(p);
      t.nanoseconds = Swap32::readval(p+8);
      return t;
    }

    // Return the type of input file.
    Incremental_input_type
    type() const
    { return static_cast<Incremental_input_type>(this->flags_ & 0xff); }

    // Return TRUE if the file was found in a system directory.
    bool
    is_in_system_directory() const
    { return (this->flags_ & INCREMENTAL_INPUT_IN_SYSTEM_DIR) != 0; }

    // Return TRUE if the file was linked with --as-needed.
    bool
    as_needed() const
    { return (this->flags_ & INCREMENTAL_INPUT_AS_NEEDED) != 0; }

    // Return the input section count -- for objects only.
    unsigned int
    get_input_section_count() const
    {
      gold_assert(this->type() == INCREMENTAL_INPUT_OBJECT
		  || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);
      return Swap32::readval(this->inputs_->p_ + this->info_offset_);
    }

    // Return the soname -- for shared libraries only.
    const char*
    get_soname() const
    {
      gold_assert(this->type() == INCREMENTAL_INPUT_SHARED_LIBRARY);
      unsigned int offset = Swap32::readval(this->inputs_->p_
					    + this->info_offset_);
      return this->inputs_->get_string(offset);
    }

    // Return the offset of the supplemental info for symbol SYMNDX --
    // for objects only.
    unsigned int
    get_symbol_offset(unsigned int symndx) const
    {
      gold_assert(this->type() == INCREMENTAL_INPUT_OBJECT
		  || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);

      unsigned int section_count = this->get_input_section_count();
      return (this->info_offset_ + 28
	      + section_count * input_section_entry_size
	      + symndx * 20);
    }

    // Return the global symbol count -- for objects & shared libraries only.
    unsigned int
    get_global_symbol_count() const
    {
      gold_assert(this->type() == INCREMENTAL_INPUT_OBJECT
		  || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER
		  || this->type() == INCREMENTAL_INPUT_SHARED_LIBRARY);
      return Swap32::readval(this->inputs_->p_ + this->info_offset_ + 4);
    }

    // Return the offset of the first local symbol -- for objects only.
    unsigned int
    get_local_symbol_offset() const
    {
      gold_assert(this->type() == INCREMENTAL_INPUT_OBJECT
		  || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);

      return Swap32::readval(this->inputs_->p_ + this->info_offset_ + 8);
    }

    // Return the local symbol count -- for objects only.
    unsigned int
    get_local_symbol_count() const
    {
      gold_assert(this->type() == INCREMENTAL_INPUT_OBJECT
		  || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);

      return Swap32::readval(this->inputs_->p_ + this->info_offset_ + 12);
    }

    // Return the index of the first dynamic relocation -- for objects only.
    unsigned int
    get_first_dyn_reloc() const
    {
      gold_assert(this->type() == INCREMENTAL_INPUT_OBJECT
		  || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);

      return Swap32::readval(this->inputs_->p_ + this->info_offset_ + 16);
    }

    // Return the dynamic relocation count -- for objects only.
    unsigned int
    get_dyn_reloc_count() const
    {
      gold_assert(this->type() == INCREMENTAL_INPUT_OBJECT
		  || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);

      return Swap32::readval(this->inputs_->p_ + this->info_offset_ + 20);
    }

    // Return the COMDAT group count -- for objects only.
    unsigned int
    get_comdat_group_count() const
    {
      gold_assert(this->type() == INCREMENTAL_INPUT_OBJECT
		  || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);

      return Swap32::readval(this->inputs_->p_ + this->info_offset_ + 24);
    }

    // Return the object count -- for scripts only.
    unsigned int
    get_object_count() const
    {
      gold_assert(this->type() == INCREMENTAL_INPUT_SCRIPT);
      return Swap32::readval(this->inputs_->p_ + this->info_offset_);
    }

    // Return the input file offset for object N -- for scripts only.
    unsigned int
    get_object_offset(unsigned int n) const
    {
      gold_assert(this->type() == INCREMENTAL_INPUT_SCRIPT);
      return Swap32::readval(this->inputs_->p_ + this->info_offset_
			     + 4 + n * 4);
    }

    // Return the member count -- for archives only.
    unsigned int
    get_member_count() const
    {
      gold_assert(this->type() == INCREMENTAL_INPUT_ARCHIVE);
      return Swap32::readval(this->inputs_->p_ + this->info_offset_);
    }

    // Return the unused symbol count -- for archives only.
    unsigned int
    get_unused_symbol_count() const
    {
      gold_assert(this->type() == INCREMENTAL_INPUT_ARCHIVE);
      return Swap32::readval(this->inputs_->p_ + this->info_offset_ + 4);
    }

    // Return the input file offset for archive member N -- for archives only.
    unsigned int
    get_member_offset(unsigned int n) const
    {
      gold_assert(this->type() == INCREMENTAL_INPUT_ARCHIVE);
      return Swap32::readval(this->inputs_->p_ + this->info_offset_
			     + 8 + n * 4);
    }

    // Return the Nth unused global symbol -- for archives only.
    const char*
    get_unused_symbol(unsigned int n) const
    {
      gold_assert(this->type() == INCREMENTAL_INPUT_ARCHIVE);
      unsigned int member_count = this->get_member_count();
      unsigned int offset = Swap32::readval(this->inputs_->p_
					    + this->info_offset_ + 8
					    + member_count * 4
					    + n * 4);
      return this->inputs_->get_string(offset);
    }

    // Information about an input section.
    struct Input_section_info
    {
      const char* name;
      unsigned int output_shndx;
      off_t sh_offset;
      off_t sh_size;
    };

    // Return info about the Nth input section -- for objects only.
    Input_section_info
    get_input_section(unsigned int n) const
    {
      Input_section_info info;
      const unsigned char* p = (this->inputs_->p_
				+ this->info_offset_ + 28
				+ n * input_section_entry_size);
      unsigned int name_offset = Swap32::readval(p);
      info.name = this->inputs_->get_string(name_offset);
      info.output_shndx = Swap32::readval(p + 4);
      info.sh_offset = Swap::readval(p + 8);
      info.sh_size = Swap::readval(p + 8 + size / 8);
      return info;
    }

    // Return info about the Nth global symbol -- for objects only.
    Incremental_global_symbol_reader<big_endian>
    get_global_symbol_reader(unsigned int n) const
    {
      gold_assert(this->type() == INCREMENTAL_INPUT_OBJECT
		  || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);
      unsigned int section_count = this->get_input_section_count();
      const unsigned char* p = (this->inputs_->p_
				+ this->info_offset_ + 28
				+ section_count * input_section_entry_size
				+ n * 20);
      return Incremental_global_symbol_reader<big_endian>(p);
    }

    // Return the signature of the Nth comdat group -- for objects only.
    const char*
    get_comdat_group_signature(unsigned int n) const
    {
      unsigned int section_count = this->get_input_section_count();
      unsigned int symbol_count = this->get_global_symbol_count();
      const unsigned char* p = (this->inputs_->p_
				+ this->info_offset_ + 28
				+ section_count * input_section_entry_size
				+ symbol_count * 20
				+ n * 4);
      unsigned int name_offset = Swap32::readval(p);
      return this->inputs_->get_string(name_offset);
    }

    // Return the output symbol index for the Nth global symbol -- for shared
    // libraries only.  Sets *IS_DEF to TRUE if the symbol is defined in this
    // input file.  Sets *IS_COPY to TRUE if the symbol was copied from this
    // input file with a COPY relocation.
    unsigned int
    get_output_symbol_index(unsigned int n, bool* is_def, bool* is_copy)
    {
      gold_assert(this->type() == INCREMENTAL_INPUT_SHARED_LIBRARY);
      const unsigned char* p = (this->inputs_->p_
				+ this->info_offset_ + 8
				+ n * 4);
      unsigned int output_symndx = Swap32::readval(p);
      unsigned int flags = output_symndx >> INCREMENTAL_SHLIB_SYM_FLAGS_SHIFT;
      output_symndx &= ((1U << INCREMENTAL_SHLIB_SYM_FLAGS_SHIFT) - 1);
      switch (flags)
	{
	  case INCREMENTAL_SHLIB_SYM_DEF:
	    *is_def = true;
	    *is_copy = false;
	    break;
	  case INCREMENTAL_SHLIB_SYM_COPY:
	    *is_def = true;
	    *is_copy = true;
	    break;
	  default:
	    *is_def = false;
	    *is_copy = false;
	}
      return output_symndx;
    }

   private:
    // Size of an input section entry.
    static const unsigned int input_section_entry_size = 8 + 2 * size / 8;
    // The reader instance for the containing section.
    const Incremental_inputs_reader* inputs_;
    // The flags, including the type of input file.
    unsigned int flags_;
    // Section offset to the input file entry.
    unsigned int offset_;
    // Section offset to the supplemental info for the input file.
    unsigned int info_offset_;
  };

  // Return the offset of an input file entry given its index N.
  unsigned int
  input_file_offset(unsigned int n) const
  {
    gold_assert(n < this->input_file_count_);
    return 16 + n * 24;
  }

  // Return the index of an input file entry given its OFFSET.
  unsigned int
  input_file_index(unsigned int offset) const
  {
    int n = (offset - 16) / 24;
    gold_assert(input_file_offset(n) == offset);
    return n;
  }

  // Return a reader for the Nth input file entry.
  Incremental_input_entry_reader
  input_file(unsigned int n) const
  { return Incremental_input_entry_reader(this, this->input_file_offset(n)); }

  // Return a reader for the input file entry at OFFSET.
  Incremental_input_entry_reader
  input_file_at_offset(unsigned int offset) const
  {
    gold_assert(offset < 16 + this->input_file_count_ * 24);
    return Incremental_input_entry_reader(this, offset);
  }

  // Return a reader for the global symbol info at OFFSET.
  Incremental_global_symbol_reader<big_endian>
  global_symbol_reader_at_offset(unsigned int offset) const
  {
    const unsigned char* p = this->p_ + offset;
    return Incremental_global_symbol_reader<big_endian>(p);
  }

 private:
  // Lookup a string in the ELF string table.
  const char* get_string(unsigned int offset) const
  {
    const char* s;
    if (this->strtab_.get_c_string(offset, &s))
      return s;
    return NULL;
  }

  // Base address of the .gnu_incremental_inputs section.
  const unsigned char* p_;
  // The associated ELF string table.
  elfcpp::Elf_strtab strtab_;
  // The number of input file entries in this section.
  unsigned int input_file_count_;
};

// Reader class for the .gnu_incremental_symtab section.

template<bool big_endian>
class Incremental_symtab_reader
{
 public:
  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
  { 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.

template<int size, bool big_endian>
class Incremental_relocs_reader
{
 private:
  // Size of each field.
  static const unsigned int field_size = size / 8;

 public:
  typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
  typedef typename elfcpp::Elf_types<size>::Elf_Swxword Addend;

  // Size of each entry.
  static const unsigned int reloc_size = 8 + 2 * field_size;

  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
  { return elfcpp::Swap<32, big_endian>::readval(this->p_ + off); }

  // Return the output section index for relocation entry at offset OFF.
  unsigned int
  get_r_shndx(unsigned int off) const
  { return elfcpp::Swap<32, big_endian>::readval(this->p_ + off + 4); }

  // Return the output section offset for relocation entry at offset OFF.
  Address
  get_r_offset(unsigned int off) const
  { return elfcpp::Swap<size, big_endian>::readval(this->p_ + off + 8); }

  // Return the addend for relocation entry at offset OFF.
  Addend
  get_r_addend(unsigned int off) const
  {
    return elfcpp::Swap<size, big_endian>::readval(this->p_ + off + 8
						   + this->field_size);
  }

  // Return a pointer to the relocation entry at offset OFF.
  const unsigned char*
  data(unsigned int off) const
  { return this->p_ + off; }

 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.

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);
    this->got_desc_p_ = p + 8 + ((this->got_count_ + 3) & ~3);
    this->plt_desc_p_ = this->got_desc_p_ + this->got_count_ * 8;
  }

  // Return the GOT entry count.
  unsigned int
  get_got_entry_count() const
  {
    return this->got_count_;
  }

  // Return the PLT entry count.
  unsigned int
  get_plt_entry_count() const
  {
    return elfcpp::Swap<32, big_endian>::readval(this->p_ + 4);
  }

  // Return the GOT type for GOT entry N.
  unsigned int
  get_got_type(unsigned int n)
  {
    return this->p_[8 + n];
  }

  // Return the symbol index for GOT entry N.
  unsigned int
  get_got_symndx(unsigned int n)
  {
    return elfcpp::Swap<32, big_endian>::readval(this->got_desc_p_ + n * 8);
  }

  // Return the input file index for GOT entry N.
  unsigned int
  get_got_input_index(unsigned int n)
  {
    return elfcpp::Swap<32, big_endian>::readval(this->got_desc_p_ + n * 8 + 4);
  }

  // Return the PLT descriptor for PLT entry N.
  unsigned int
  get_plt_desc(unsigned int n)
  {
    return elfcpp::Swap<32, big_endian>::readval(this->plt_desc_p_ + n * 4);
  }

 private:
  // Base address of the .gnu_incremental_got_plt section.
  const unsigned char* p_;
  // GOT entry count.
  unsigned int got_count_;
  // Base address of the GOT descriptor array.
  const unsigned char* got_desc_p_;
  // Base address of the PLT descriptor array.
  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)
    : input_args_map_(), library_map_(), script_map_(),
      output_(output), target_(target)
  { }

  virtual
  ~Incremental_binary()
  { }

  // Check the .gnu_incremental_inputs section to see whether an incremental
  // build is possible.
  bool
  check_inputs(const Command_line& cmdline,
	       Incremental_inputs* incremental_inputs)
  { return this->do_check_inputs(cmdline, incremental_inputs); }

  // Report an error.
  void
  error(const char* format, ...) const ATTRIBUTE_PRINTF_2;

  // Proxy 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(); }

    unsigned int
    arg_serial() const
    { return this->do_arg_serial(); }

    unsigned int
    get_unused_symbol_count() const
    { return this->do_get_unused_symbol_count(); }

    const char*
    get_unused_symbol(unsigned int n) const
    { return this->do_get_unused_symbol(n); }

   protected:
    virtual const char*
    do_filename() const = 0;

    virtual Timespec
    do_get_mtime() const = 0;

    virtual Incremental_input_type
    do_type() const = 0;

    virtual unsigned int
    do_arg_serial() const = 0;

    virtual unsigned int
    do_get_unused_symbol_count() const = 0;

    virtual const char*
    do_get_unused_symbol(unsigned int n) const = 0;
  };

  // Return the number of input files.
  unsigned int
  input_file_count() const
  { return this->do_input_file_count(); }

  // Return an Input_reader for input file N.
  const Input_reader*
  get_input_reader(unsigned int n) const
  { return this->do_get_input_reader(n); }

  // Return TRUE if the input file N has changed since the last link.
  bool
  file_has_changed(unsigned int n) const
  { return this->do_file_has_changed(n); }

  // Return the Input_argument for input file N.  Returns NULL if
  // the Input_argument is not available.
  const Input_argument*
  get_input_argument(unsigned int n) const
  {
    const Input_reader* input_file = this->do_get_input_reader(n);
    unsigned int arg_serial = input_file->arg_serial();
    if (arg_serial == 0 || arg_serial > this->input_args_map_.size())
      return NULL;
    return this->input_args_map_[arg_serial - 1];
  }

  // Return an Incremental_library for the given input file.
  Incremental_library*
  get_library(unsigned int n) const
  { return this->library_map_[n]; }

  // Return a Script_info for the given input file.
  Script_info*
  get_script_info(unsigned int n) const
  { return this->script_map_[n]; }

  // Initialize the layout of the output file based on the existing
  // output file.
  void
  init_layout(Layout* layout)
  { this->do_init_layout(layout); }

  // Mark regions of the input file that must be kept unchanged.
  void
  reserve_layout(unsigned int input_file_index)
  { this->do_reserve_layout(input_file_index); }

  // Process the GOT and PLT entries from the existing output file.
  void
  process_got_plt(Symbol_table* symtab, Layout* layout)
  { this->do_process_got_plt(symtab, layout); }

  // Emit COPY relocations from the existing output file.
  void
  emit_copy_relocs(Symbol_table* symtab)
  { this->do_emit_copy_relocs(symtab); }

  // Apply incremental relocations for symbols whose values have changed.
  void
  apply_incremental_relocs(const Symbol_table* symtab, Layout* layout,
			   Output_file* of)
  { this->do_apply_incremental_relocs(symtab, layout, of); }

  // 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)); }

  // Return the Output_file.
  Output_file*
  output_file()
  { return this->output_; }

 protected:
  // Check the .gnu_incremental_inputs section to see whether an incremental
  // build is possible.
  virtual bool
  do_check_inputs(const Command_line& cmdline,
		  Incremental_inputs* incremental_inputs) = 0;

  // Return TRUE if input file N has changed since the last incremental link.
  virtual bool
  do_file_has_changed(unsigned int n) const = 0;

  // Initialize the layout of the output file based on the existing
  // output file.
  virtual void
  do_init_layout(Layout* layout) = 0;

  // Mark regions of the input file that must be kept unchanged.
  virtual void
  do_reserve_layout(unsigned int input_file_index) = 0;

  // Process the GOT and PLT entries from the existing output file.
  virtual void
  do_process_got_plt(Symbol_table* symtab, Layout* layout) = 0;

  // Emit COPY relocations from the existing output file.
  virtual void
  do_emit_copy_relocs(Symbol_table* symtab) = 0;

  // Apply incremental relocations for symbols whose values have changed.
  virtual void
  do_apply_incremental_relocs(const Symbol_table*, Layout*, Output_file*) = 0;

  virtual unsigned int
  do_input_file_count() const = 0;

  virtual const Input_reader*
  do_get_input_reader(unsigned int) const = 0;

  // Map from input file index to Input_argument.
  std::vector<const Input_argument*> input_args_map_;
  // Map from an input file index to an Incremental_library.
  std::vector<Incremental_library*> library_map_;
  // Map from an input file index to a Script_info.
  std::vector<Script_info*> script_map_;

 private:
  // Edited output file object.
  Output_file* output_;
  // Target of the output file.
  Target* target_;
};

template<int size, bool big_endian>
class Sized_relobj_incr;

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),
      input_objects_(), section_map_(), symbol_map_(), copy_relocs_(),
      main_symtab_loc_(), main_strtab_loc_(), has_incremental_info_(false),
      inputs_reader_(), symtab_reader_(), relocs_reader_(), got_plt_reader_(),
      input_entry_readers_()
  { this->setup_readers(); }

  // Returns TRUE if the file contains incremental info.
  bool
  has_incremental_info() const
  { return this->has_incremental_info_; }

  // Record a pointer to the object for input file N.
  void
  set_input_object(unsigned int n,
		   Sized_relobj_incr<size, big_endian>* obj)
  { this->input_objects_[n] = obj; }

  // Return a pointer to the object for input file N.
  Sized_relobj_incr<size, big_endian>*
  input_object(unsigned int n) const
  {
    gold_assert(n < this->input_objects_.size());
    return this->input_objects_[n];
  }

  // Return the Output_section for section index SHNDX.
  Output_section*
  output_section(unsigned int shndx)
  { return this->section_map_[shndx]; }

  // Map a symbol table entry from the base file to the output symbol table.
  // SYMNDX is relative to the first forced-local or global symbol in the
  // input file symbol table.
  void
  add_global_symbol(unsigned int symndx, Symbol* gsym)
  { this->symbol_map_[symndx] = gsym; }

  // Map a symbol table entry from the base file to the output symbol table.
  // SYMNDX is relative to the first forced-local or global symbol in the
  // input file symbol table.
  Symbol*
  global_symbol(unsigned int symndx) const
  { return this->symbol_map_[symndx]; }

  // Add a COPY relocation for a global symbol.
  void
  add_copy_reloc(Symbol* gsym, Output_section* os, off_t offset)
  { this->copy_relocs_.push_back(Copy_reloc(gsym, os, offset)); }

  // Readers for the incremental info sections.

  const Incremental_inputs_reader<size, big_endian>&
  inputs_reader() const
  { return this->inputs_reader_; }

  const Incremental_symtab_reader<big_endian>&
  symtab_reader() const
  { return this->symtab_reader_; }

  const Incremental_relocs_reader<size, big_endian>&
  relocs_reader() const
  { return this->relocs_reader_; }

  const Incremental_got_plt_reader<big_endian>&
  got_plt_reader() const
  { return this->got_plt_reader_; }

  void
  get_symtab_view(View* symtab_view, unsigned int* sym_count,
		  elfcpp::Elf_strtab* strtab);

 protected:
  typedef Incremental_inputs_reader<size, big_endian> Inputs_reader;
  typedef typename Inputs_reader::Incremental_input_entry_reader
      Input_entry_reader;

  virtual bool
  do_check_inputs(const Command_line& cmdline,
		  Incremental_inputs* incremental_inputs);

  // Return TRUE if input file N has changed since the last incremental link.
  virtual bool
  do_file_has_changed(unsigned int n) const;

  // Initialize the layout of the output file based on the existing
  // output file.
  virtual void
  do_init_layout(Layout* layout);

  // Mark regions of the input file that must be kept unchanged.
  virtual void
  do_reserve_layout(unsigned int input_file_index);

  // Process the GOT and PLT entries from the existing output file.
  virtual void
  do_process_got_plt(Symbol_table* symtab, Layout* layout);

  // Emit COPY relocations from the existing output file.
  virtual void
  do_emit_copy_relocs(Symbol_table* symtab);

  // Apply incremental relocations for symbols whose values have changed.
  virtual void
  do_apply_incremental_relocs(const Symbol_table* symtab, Layout* layout,
			      Output_file* of);

  // Proxy class for a sized Incremental_input_entry_reader.

  class Sized_input_reader : public Input_reader
  {
   public:
    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(); }

    unsigned int
    do_arg_serial() const
    { return this->reader_.arg_serial(); }

    unsigned int
    do_get_unused_symbol_count() const
    { return this->reader_.get_unused_symbol_count(); }

    const char*
    do_get_unused_symbol(unsigned int n) const
    { return this->reader_.get_unused_symbol(n); }

    Input_entry_reader reader_;
  };

  virtual unsigned int
  do_input_file_count() const
  { return this->inputs_reader_.input_file_count(); }

  virtual const Input_reader*
  do_get_input_reader(unsigned int n) const
  {
    gold_assert(n < this->input_entry_readers_.size());
    return &this->input_entry_readers_[n];
  }

 private:
  // List of symbols that need COPY relocations.
  struct Copy_reloc
  {
    Copy_reloc(Symbol* sym, Output_section* os, off_t off)
      : symbol(sym), output_section(os), offset(off)
    { }

    // The global symbol to copy.
    Symbol* symbol;
    // The output section into which the symbol was copied.
    Output_section* output_section;
    // The offset within that output section.
    off_t offset;
  };
  typedef std::vector<Copy_reloc> Copy_relocs;

  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_;

  // Vector of pointers to the input objects for the unchanged files.
  // For replaced files, the corresponding pointer is NULL.
  std::vector<Sized_relobj_incr<size, big_endian>*> input_objects_;

  // Map section index to an Output_section in the updated layout.
  std::vector<Output_section*> section_map_;

  // Map global symbols from the input file to the symbol table.
  std::vector<Symbol*> symbol_map_;

  // List of symbols that need COPY relocations.
  Copy_relocs copy_relocs_;

  // Locations of the main symbol table and symbol string table.
  Location main_symtab_loc_;
  Location main_strtab_loc_;

  // 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_;
  std::vector<Sized_input_reader> input_entry_readers_;
};

// An incremental Relobj.  This class represents a relocatable object
// that has not changed since the last incremental link, and whose contents
// can be used directly from the base file.

template<int size, bool big_endian>
class Sized_relobj_incr : public Sized_relobj<size, big_endian>
{
 public:
  typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
  typedef typename Sized_relobj<size, big_endian>::Symbols Symbols;

  Sized_relobj_incr(const std::string& name,
		    Sized_incremental_binary<size, big_endian>* ibase,
		    unsigned int input_file_index);

 private:
  // For convenience.
  typedef Sized_relobj_incr<size, big_endian> This;
  static const int sym_size = elfcpp::Elf_sizes<size>::sym_size;

  typedef typename Sized_relobj<size, big_endian>::Output_sections
      Output_sections;
  typedef Incremental_inputs_reader<size, big_endian> Inputs_reader;
  typedef typename Inputs_reader::Incremental_input_entry_reader
      Input_entry_reader;

  // A local symbol.
  struct Local_symbol
  {
    Local_symbol(const char* name_, Address value_, unsigned int size_,
		 unsigned int shndx_, unsigned int type_,
		 bool needs_dynsym_entry_)
      : st_value(value_), name(name_), st_size(size_), st_shndx(shndx_),
	st_type(type_), output_dynsym_index(0),
	needs_dynsym_entry(needs_dynsym_entry_)
    { }
    // The symbol value.
    Address st_value;
    // The symbol name.  This points to the stringpool entry.
    const char* name;
    // The symbol size.
    unsigned int st_size;
    // The output section index.
    unsigned int st_shndx : 28;
    // The symbol type.
    unsigned int st_type : 4;
    // The index of the symbol in the output dynamic symbol table.
    unsigned int output_dynsym_index : 31;
    // TRUE if the symbol needs to appear in the dynamic symbol table.
    unsigned int needs_dynsym_entry : 1;
  };

  // Return TRUE if this is an incremental (unchanged) input file.
  bool
  do_is_incremental() const
  { return true; }

  // Return the last modified time of the file.
  Timespec
  do_get_mtime()
  { return this->input_reader_.get_mtime(); }

  // Read the symbols.
  void
  do_read_symbols(Read_symbols_data*);

  // Lay out the input sections.
  void
  do_layout(Symbol_table*, Layout*, Read_symbols_data*);

  // Layout sections whose layout was deferred while waiting for
  // input files from a plugin.
  void
  do_layout_deferred_sections(Layout*);

  // Add the symbols to the symbol table.
  void
  do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*);

  Archive::Should_include
  do_should_include_member(Symbol_table* symtab, Layout*, Read_symbols_data*,
                           std::string* why);

  // Iterate over global symbols, calling a visitor class V for each.
  void
  do_for_all_global_symbols(Read_symbols_data* sd,
			    Library_base::Symbol_visitor_base* v);

  // Get the size of a section.
  uint64_t
  do_section_size(unsigned int shndx);

  // Get the name of a section.
  std::string
  do_section_name(unsigned int shndx);

  // Return a view of the contents of a section.
  Object::Location
  do_section_contents(unsigned int shndx);

  // Return section flags.
  uint64_t
  do_section_flags(unsigned int shndx);

  // Return section entsize.
  uint64_t
  do_section_entsize(unsigned int shndx);

  // Return section address.
  uint64_t
  do_section_address(unsigned int shndx);

  // Return section type.
  unsigned int
  do_section_type(unsigned int shndx);

  // Return the section link field.
  unsigned int
  do_section_link(unsigned int shndx);

  // Return the section link field.
  unsigned int
  do_section_info(unsigned int shndx);

  // Return the section alignment.
  uint64_t
  do_section_addralign(unsigned int shndx);

  // Return the Xindex structure to use.
  Xindex*
  do_initialize_xindex();

  // Get symbol counts.
  void
  do_get_global_symbol_counts(const Symbol_table*, size_t*, size_t*) const;

  // Get global symbols.
  const Symbols*
  do_get_global_symbols() const
  { return &this->symbols_; }

  // Return the number of local symbols.
  unsigned int
  do_local_symbol_count() const
  { return this->local_symbol_count_; }

  // Return the number of local symbols in the output symbol table.
  unsigned int
  do_output_local_symbol_count() const
  { return this->local_symbol_count_; }

  // Return the file offset for local symbols in the output symbol table.
  off_t
  do_local_symbol_offset() const
  { return this->local_symbol_offset_; }

  // Read the relocs.
  void
  do_read_relocs(Read_relocs_data*);

  // Process the relocs to find list of referenced sections. Used only
  // during garbage collection.
  void
  do_gc_process_relocs(Symbol_table*, Layout*, Read_relocs_data*);

  // Scan the relocs and adjust the symbol table.
  void
  do_scan_relocs(Symbol_table*, Layout*, Read_relocs_data*);

  // Count the local symbols.
  void
  do_count_local_symbols(Stringpool_template<char>*,
			 Stringpool_template<char>*);

  // Finalize the local symbols.
  unsigned int
  do_finalize_local_symbols(unsigned int, off_t, Symbol_table*);

  // Set the offset where local dynamic symbol information will be stored.
  unsigned int
  do_set_local_dynsym_indexes(unsigned int);

  // Set the offset where local dynamic symbol information will be stored.
  unsigned int
  do_set_local_dynsym_offset(off_t);

  // Relocate the input sections and write out the local symbols.
  void
  do_relocate(const Symbol_table* symtab, const Layout*, Output_file* of);

  // Set the offset of a section.
  void
  do_set_section_offset(unsigned int shndx, uint64_t off);

  // The Incremental_binary base file.
  Sized_incremental_binary<size, big_endian>* ibase_;
  // The index of the object in the input file list.
  unsigned int input_file_index_;
  // The reader for the input file.
  Input_entry_reader input_reader_;
  // The number of local symbols.
  unsigned int local_symbol_count_;
  // The number of local symbols which go into the output file's dynamic
  // symbol table.
  unsigned int output_local_dynsym_count_;
  // This starting symbol index in the output symbol table.
  unsigned int local_symbol_index_;
  // The file offset for local symbols in the output symbol table.
  unsigned int local_symbol_offset_;
  // The file offset for local symbols in the output symbol table.
  unsigned int local_dynsym_offset_;
  // The entries in the symbol table for the external symbols.
  Symbols symbols_;
  // The offset of the first incremental relocation for this object.
  unsigned int incr_reloc_offset_;
  // The number of incremental relocations for this object.
  unsigned int incr_reloc_count_;
  // The index of the first incremental relocation for this object in the
  // updated output file.
  unsigned int incr_reloc_output_index_;
  // A copy of the incremental relocations from this object.
  unsigned char* incr_relocs_;
  // The local symbols.
  std::vector<Local_symbol> local_symbols_;
};

// An incremental Dynobj.  This class represents a shared object that has
// not changed since the last incremental link, and whose contents can be
// used directly from the base file.

template<int size, bool big_endian>
class Sized_incr_dynobj : public Dynobj
{
 public:
  typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;

  static const Address invalid_address = static_cast<Address>(0) - 1;

  Sized_incr_dynobj(const std::string& name,
		    Sized_incremental_binary<size, big_endian>* ibase,
		    unsigned int input_file_index);

 private:
  typedef Incremental_inputs_reader<size, big_endian> Inputs_reader;
  typedef typename Inputs_reader::Incremental_input_entry_reader
      Input_entry_reader;

  // Return TRUE if this is an incremental (unchanged) input file.
  bool
  do_is_incremental() const
  { return true; }

  // Return the last modified time of the file.
  Timespec
  do_get_mtime()
  { return this->input_reader_.get_mtime(); }

  // Read the symbols.
  void
  do_read_symbols(Read_symbols_data*);

  // Lay out the input sections.
  void
  do_layout(Symbol_table*, Layout*, Read_symbols_data*);

  // Add the symbols to the symbol table.
  void
  do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*);

  Archive::Should_include
  do_should_include_member(Symbol_table* symtab, Layout*, Read_symbols_data*,
                           std::string* why);

  // Iterate over global symbols, calling a visitor class V for each.
  void
  do_for_all_global_symbols(Read_symbols_data* sd,
			    Library_base::Symbol_visitor_base* v);

  // Iterate over local symbols, calling a visitor class V for each GOT offset
  // associated with a local symbol.
  void
  do_for_all_local_got_entries(Got_offset_list::Visitor* v) const;

  // Get the size of a section.
  uint64_t
  do_section_size(unsigned int shndx);

  // Get the name of a section.
  std::string
  do_section_name(unsigned int shndx);

  // Return a view of the contents of a section.
  Object::Location
  do_section_contents(unsigned int shndx);

  // Return section flags.
  uint64_t
  do_section_flags(unsigned int shndx);

  // Return section entsize.
  uint64_t
  do_section_entsize(unsigned int shndx);

  // Return section address.
  uint64_t
  do_section_address(unsigned int shndx);

  // Return section type.
  unsigned int
  do_section_type(unsigned int shndx);

  // Return the section link field.
  unsigned int
  do_section_link(unsigned int shndx);

  // Return the section link field.
  unsigned int
  do_section_info(unsigned int shndx);

  // Return the section alignment.
  uint64_t
  do_section_addralign(unsigned int shndx);

  // Return the Xindex structure to use.
  Xindex*
  do_initialize_xindex();

  // Get symbol counts.
  void
  do_get_global_symbol_counts(const Symbol_table*, size_t*, size_t*) const;

  // Get global symbols.
  const Symbols*
  do_get_global_symbols() const
  { return &this->symbols_; }

  // The Incremental_binary base file.
  Sized_incremental_binary<size, big_endian>* ibase_;
  // The index of the object in the input file list.
  unsigned int input_file_index_;
  // The reader for the input file.
  Input_entry_reader input_reader_;
  // The entries in the symbol table for the external symbols.
  Symbols symbols_;
};

// Allocate an incremental object of the appropriate size and endianness.
extern Object*
make_sized_incremental_object(
    Incremental_binary* base,
    unsigned int input_file_index,
    Incremental_input_type input_type,
    const Incremental_binary::Input_reader* input_reader);

// This class represents an Archive library (or --start-lib/--end-lib group)
// that has not changed since the last incremental link.  Its contents come
// from the incremental inputs entry in the base file.

class Incremental_library : public Library_base
{
 public:
  Incremental_library(const char* filename, unsigned int input_file_index,
		      const Incremental_binary::Input_reader* input_reader)
    : Library_base(NULL), filename_(filename),
      input_file_index_(input_file_index), input_reader_(input_reader),
      unused_symbols_(), is_reported_(false)
  { }

  // Return the input file index.
  unsigned int
  input_file_index() const
  { return this->input_file_index_; }

  // Return the serial number of the input file.
  unsigned int
  arg_serial() const
  { return this->input_reader_->arg_serial(); }

  // Copy the unused symbols from the incremental input info.
  // We need to do this because we may be overwriting the incremental
  // input info in the base file before we write the new incremental
  // info.
  void
  copy_unused_symbols();

  // Return FALSE on the first call to indicate that the library needs
  // to be recorded; return TRUE subsequently.
  bool
  is_reported()
  {
    bool was_reported = this->is_reported_;
    is_reported_ = true;
    return was_reported;
  }

 private:
  typedef std::vector<std::string> Symbol_list;

  // The file name.
  const std::string&
  do_filename() const
  { return this->filename_; }

  // Return the modification time of the archive file.
  Timespec
  do_get_mtime()
  { return this->input_reader_->get_mtime(); }

  // Iterator for unused global symbols in the library.
  void
  do_for_all_unused_symbols(Symbol_visitor_base* v) const;

  // The name of the library.
  std::string filename_;
  // The input file index of this library.
  unsigned int input_file_index_;
  // A reader for the incremental input information.
  const Incremental_binary::Input_reader* input_reader_;
  // List of unused symbols defined in this library.
  Symbol_list unused_symbols_;
  // TRUE when this library has been reported to the new incremental info.
  bool is_reported_;
};

} // End namespace gold.

#endif // !defined(GOLD_INCREMENTAL_H)
