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

// Copyright 2009, 2010, 2011, 2012 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:
  // Size of the .gnu_incremental_inputs header.
  // (3 x 4-byte fields, plus 4 bytes padding.)
  static const unsigned int header_size = 16;
  // Size of an input file entry.
  // (2 x 4-byte fields, 1 x 12-byte field, 2 x 2-byte fields.)
  static const unsigned int input_entry_size = 24;
  // Size of the first part of the supplemental info block for
  // relocatable objects and archive members.
  // (7 x 4-byte fields, plus 4 bytes padding.)
  static const unsigned int object_info_size = 32;
  // Size of an input section entry.
  // (2 x 4-byte fields, 2 x address-sized fields.)
  static const unsigned int input_section_entry_size = 8 + 2 * size / 8;
  // Size of a global symbol entry in the supplemental info block.
  // (5 x 4-byte fields.)
  static const unsigned int global_sym_entry_size = 20;

  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
  {
   private:
    static const unsigned int object_info_size =
	Incremental_inputs_reader<size, big_endian>::object_info_size;
    static const unsigned int input_section_entry_size =
	Incremental_inputs_reader<size, big_endian>::input_section_entry_size;
    static const unsigned int global_sym_entry_size =
	Incremental_inputs_reader<size, big_endian>::global_sym_entry_size;

   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_
	      + this->object_info_size
	      + section_count * this->input_section_entry_size
	      + symndx * this->global_sym_entry_size);
    }

    // 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_
				+ this->object_info_size
				+ n * this->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_
				+ this->object_info_size
				+ section_count * this->input_section_entry_size
				+ n * this->global_sym_entry_size);
      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_
				+ this->object_info_size
				+ section_count * this->input_section_entry_size
				+ symbol_count * this->global_sym_entry_size
				+ 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:
    // 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 this->header_size + n * this->input_entry_size;
  }

  // Return the index of an input file entry given its OFFSET.
  unsigned int
  input_file_index(unsigned int offset) const
  {
    int n = ((offset - this->header_size) / this->input_entry_size);
    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 < (this->header_size
			  + this->input_file_count_ * this->input_entry_size));
    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.
  const unsigned char*
  do_section_contents(unsigned int shndx, section_size_type* plen,
		      bool cache);

  // 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 value of a local symbol.
  uint64_t
  do_local_symbol_value(unsigned int, uint64_t) const
  { gold_unreachable(); }

  unsigned int
  do_local_plt_offset(unsigned int) const
  { gold_unreachable(); }

  bool
  do_local_is_tls(unsigned int) const
  { gold_unreachable(); }

  // 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_;
  // Number of symbols defined in object file itself.
  size_t defined_count_;
  // 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.
  const unsigned char*
  do_section_contents(unsigned int shndx, section_size_type* plen,
		      bool cache);

  // 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_;
  // Number of symbols defined in object file itself.
  size_t defined_count_;
};

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