// object.h -- support for an object file for linking in gold  -*- C++ -*-

// Copyright (C) 2006-2018 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@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_OBJECT_H
#define GOLD_OBJECT_H

#include <string>
#include <vector>

#include "elfcpp.h"
#include "elfcpp_file.h"
#include "fileread.h"
#include "target.h"
#include "archive.h"

namespace gold
{

class General_options;
class Task;
class Cref;
class Layout;
class Kept_section;
class Output_data;
class Output_section;
class Output_section_data;
class Output_file;
class Output_symtab_xindex;
class Pluginobj;
class Dynobj;
class Object_merge_map;
class Relocatable_relocs;
struct Symbols_data;

template<typename Stringpool_char>
class Stringpool_template;

// Data to pass from read_symbols() to add_symbols().

struct Read_symbols_data
{
  Read_symbols_data()
    : section_headers(NULL), section_names(NULL), symbols(NULL),
      symbol_names(NULL), versym(NULL), verdef(NULL), verneed(NULL)
  { }

  ~Read_symbols_data();

  // Section headers.
  File_view* section_headers;
  // Section names.
  File_view* section_names;
  // Size of section name data in bytes.
  section_size_type section_names_size;
  // Symbol data.
  File_view* symbols;
  // Size of symbol data in bytes.
  section_size_type symbols_size;
  // Offset of external symbols within symbol data.  This structure
  // sometimes contains only external symbols, in which case this will
  // be zero.  Sometimes it contains all symbols.
  section_offset_type external_symbols_offset;
  // Symbol names.
  File_view* symbol_names;
  // Size of symbol name data in bytes.
  section_size_type symbol_names_size;

  // Version information.  This is only used on dynamic objects.
  // Version symbol data (from SHT_GNU_versym section).
  File_view* versym;
  section_size_type versym_size;
  // Version definition data (from SHT_GNU_verdef section).
  File_view* verdef;
  section_size_type verdef_size;
  unsigned int verdef_info;
  // Needed version data  (from SHT_GNU_verneed section).
  File_view* verneed;
  section_size_type verneed_size;
  unsigned int verneed_info;
};

// Information used to print error messages.

struct Symbol_location_info
{
  std::string source_file;
  std::string enclosing_symbol_name;
  elfcpp::STT enclosing_symbol_type;
};

// Data about a single relocation section.  This is read in
// read_relocs and processed in scan_relocs.

struct Section_relocs
{
  Section_relocs()
    : contents(NULL)
  { }

  ~Section_relocs()
  { delete this->contents; }

  // Index of reloc section.
  unsigned int reloc_shndx;
  // Index of section that relocs apply to.
  unsigned int data_shndx;
  // Contents of reloc section.
  File_view* contents;
  // Reloc section type.
  unsigned int sh_type;
  // Number of reloc entries.
  size_t reloc_count;
  // Output section.
  Output_section* output_section;
  // Whether this section has special handling for offsets.
  bool needs_special_offset_handling;
  // Whether the data section is allocated (has the SHF_ALLOC flag set).
  bool is_data_section_allocated;
};

// Relocations in an object file.  This is read in read_relocs and
// processed in scan_relocs.

struct Read_relocs_data
{
  Read_relocs_data()
    : local_symbols(NULL)
  { }

  ~Read_relocs_data()
  { delete this->local_symbols; }

  typedef std::vector<Section_relocs> Relocs_list;
  // The relocations.
  Relocs_list relocs;
  // The local symbols.
  File_view* local_symbols;
};

// The Xindex class manages section indexes for objects with more than
// 0xff00 sections.

class Xindex
{
 public:
  Xindex(int large_shndx_offset)
    : large_shndx_offset_(large_shndx_offset), symtab_xindex_()
  { }

  // Initialize the symtab_xindex_ array, given the object and the
  // section index of the symbol table to use.
  template<int size, bool big_endian>
  void
  initialize_symtab_xindex(Object*, unsigned int symtab_shndx);

  // Read in the symtab_xindex_ array, given its section index.
  // PSHDRS may optionally point to the section headers.
  template<int size, bool big_endian>
  void
  read_symtab_xindex(Object*, unsigned int xindex_shndx,
		     const unsigned char* pshdrs);

  // Symbol SYMNDX in OBJECT has a section of SHN_XINDEX; return the
  // real section index.
  unsigned int
  sym_xindex_to_shndx(Object* object, unsigned int symndx);

 private:
  // The type of the array giving the real section index for symbols
  // whose st_shndx field holds SHN_XINDEX.
  typedef std::vector<unsigned int> Symtab_xindex;

  // Adjust a section index if necessary.  This should only be called
  // for ordinary section indexes.
  unsigned int
  adjust_shndx(unsigned int shndx)
  {
    if (shndx >= elfcpp::SHN_LORESERVE)
      shndx += this->large_shndx_offset_;
    return shndx;
  }

  // Adjust to apply to large section indexes.
  int large_shndx_offset_;
  // The data from the SHT_SYMTAB_SHNDX section.
  Symtab_xindex symtab_xindex_;
};

// A GOT offset list.  A symbol may have more than one GOT offset
// (e.g., when mixing modules compiled with two different TLS models),
// but will usually have at most one.  GOT_TYPE identifies the type of
// GOT entry; its values are specific to each target.

class Got_offset_list
{
 public:
  Got_offset_list()
    : got_type_(-1U), got_offset_(0), got_next_(NULL)
  { }

  Got_offset_list(unsigned int got_type, unsigned int got_offset)
    : got_type_(got_type), got_offset_(got_offset), got_next_(NULL)
  { }

  ~Got_offset_list()
  {
    if (this->got_next_ != NULL)
      {
        delete this->got_next_;
        this->got_next_ = NULL;
      }
  }

  // Initialize the fields to their default values.
  void
  init()
  {
    this->got_type_ = -1U;
    this->got_offset_ = 0;
    this->got_next_ = NULL;
  }

  // Set the offset for the GOT entry of type GOT_TYPE.
  void
  set_offset(unsigned int got_type, unsigned int got_offset)
  {
    if (this->got_type_ == -1U)
      {
        this->got_type_ = got_type;
        this->got_offset_ = got_offset;
      }
    else
      {
        for (Got_offset_list* g = this; g != NULL; g = g->got_next_)
          {
            if (g->got_type_ == got_type)
              {
                g->got_offset_ = got_offset;
                return;
              }
          }
        Got_offset_list* g = new Got_offset_list(got_type, got_offset);
        g->got_next_ = this->got_next_;
        this->got_next_ = g;
      }
  }

  // Return the offset for a GOT entry of type GOT_TYPE.
  unsigned int
  get_offset(unsigned int got_type) const
  {
    for (const Got_offset_list* g = this; g != NULL; g = g->got_next_)
      {
        if (g->got_type_ == got_type)
          return g->got_offset_;
      }
    return -1U;
  }

  // Return a pointer to the list, or NULL if the list is empty.
  const Got_offset_list*
  get_list() const
  {
    if (this->got_type_ == -1U)
      return NULL;
    return this;
  }

  // Abstract visitor class for iterating over GOT offsets.
  class Visitor
  {
   public:
    Visitor()
    { }

    virtual
    ~Visitor()
    { }

    virtual void
    visit(unsigned int, unsigned int) = 0;
  };

  // Loop over all GOT offset entries, calling a visitor class V for each.
  void
  for_all_got_offsets(Visitor* v) const
  {
    if (this->got_type_ == -1U)
      return;
    for (const Got_offset_list* g = this; g != NULL; g = g->got_next_)
      v->visit(g->got_type_, g->got_offset_);
  }

 private:
  unsigned int got_type_;
  unsigned int got_offset_;
  Got_offset_list* got_next_;
};

// The Local_got_entry_key used to index the GOT offsets for local
// non-TLS symbols, and tp-relative offsets for TLS symbols.

class Local_got_entry_key
{
 public:
  Local_got_entry_key(unsigned int symndx, uint64_t addend)
    : symndx_(symndx), addend_(addend)
  {}

  // Whether this equals to another Local_got_entry_key.
  bool
  eq(const Local_got_entry_key& key) const
  {
    return (this->symndx_ == key.symndx_ && this->addend_ == key.addend_);
  }

  // Compute a hash value for this using 64-bit FNV-1a hash.
  size_t
  hash_value() const
  {
    uint64_t h = 14695981039346656037ULL; // FNV offset basis.
    uint64_t prime = 1099511628211ULL;
    h = (h ^ static_cast<uint64_t>(this->symndx_)) * prime;
    h = (h ^ static_cast<uint64_t>(this->addend_)) * prime;
    return h;
  }

  // Functors for associative containers.
  struct equal_to
  {
    bool
    operator()(const Local_got_entry_key& key1,
               const Local_got_entry_key& key2) const
    { return key1.eq(key2); }
  };

  struct hash
  {
    size_t
    operator()(const Local_got_entry_key& key) const
    { return key.hash_value(); }
  };

 private:
  // The local symbol index.
  unsigned int symndx_;
  // The addend.
  uint64_t addend_;
};

// Type for mapping section index to uncompressed size and contents.

struct Compressed_section_info
{
  section_size_type size;
  elfcpp::Elf_Xword flag;
  uint64_t addralign;
  const unsigned char* contents;
};
typedef std::map<unsigned int, Compressed_section_info> Compressed_section_map;

template<int size, bool big_endian>
Compressed_section_map*
build_compressed_section_map(const unsigned char* pshdrs, unsigned int shnum,
			     const char* names, section_size_type names_size,
			     Object* obj, bool decompress_if_needed);

// Object is an abstract base class which represents either a 32-bit
// or a 64-bit input object.  This can be a regular object file
// (ET_REL) or a shared object (ET_DYN).

class Object
{
 public:
  typedef std::vector<Symbol*> Symbols;

  // NAME is the name of the object as we would report it to the user
  // (e.g., libfoo.a(bar.o) if this is in an archive.  INPUT_FILE is
  // used to read the file.  OFFSET is the offset within the input
  // file--0 for a .o or .so file, something else for a .a file.
  Object(const std::string& name, Input_file* input_file, bool is_dynamic,
	 off_t offset = 0)
    : name_(name), input_file_(input_file), offset_(offset), shnum_(-1U),
      is_dynamic_(is_dynamic), is_needed_(false), uses_split_stack_(false),
      has_no_split_stack_(false), no_export_(false),
      is_in_system_directory_(false), as_needed_(false), xindex_(NULL),
      compressed_sections_(NULL)
  {
    if (input_file != NULL)
      {
	input_file->file().add_object();
	this->is_in_system_directory_ = input_file->is_in_system_directory();
	this->as_needed_ = input_file->options().as_needed();
      }
  }

  virtual ~Object()
  {
    if (this->input_file_ != NULL)
      this->input_file_->file().remove_object();
  }

  // Return the name of the object as we would report it to the user.
  const std::string&
  name() const
  { return this->name_; }

  // Get the offset into the file.
  off_t
  offset() const
  { return this->offset_; }

  // Return whether this is a dynamic object.
  bool
  is_dynamic() const
  { return this->is_dynamic_; }

  // Return the word size of the object file.
  virtual int elfsize() const = 0;

  // Return TRUE if this is a big-endian object file.
  virtual bool is_big_endian() const = 0;

  // Return whether this object is needed--true if it is a dynamic
  // object which defines some symbol referenced by a regular object.
  // We keep the flag here rather than in Dynobj for convenience when
  // setting it.
  bool
  is_needed() const
  { return this->is_needed_; }

  // Record that this object is needed.
  void
  set_is_needed()
  { this->is_needed_ = true; }

  // Return whether this object was compiled with -fsplit-stack.
  bool
  uses_split_stack() const
  { return this->uses_split_stack_; }

  // Return whether this object contains any functions compiled with
  // the no_split_stack attribute.
  bool
  has_no_split_stack() const
  { return this->has_no_split_stack_; }

  // Returns NULL for Objects that are not dynamic objects.  This method
  // is overridden in the Dynobj class.
  Dynobj*
  dynobj()
  { return this->do_dynobj(); }

  // Returns NULL for Objects that are not plugin objects.  This method
  // is overridden in the Pluginobj class.
  Pluginobj*
  pluginobj()
  { return this->do_pluginobj(); }

  // Get the file.  We pass on const-ness.
  Input_file*
  input_file()
  {
    gold_assert(this->input_file_ != NULL);
    return this->input_file_;
  }

  const Input_file*
  input_file() const
  {
    gold_assert(this->input_file_ != NULL);
    return this->input_file_;
  }

  // Lock the underlying file.
  void
  lock(const Task* t)
  {
    if (this->input_file_ != NULL)
      this->input_file_->file().lock(t);
  }

  // Unlock the underlying file.
  void
  unlock(const Task* t)
  {
    if (this->input_file_ != NULL)
      this->input_file()->file().unlock(t);
  }

  // Return whether the underlying file is locked.
  bool
  is_locked() const
  { return this->input_file_ != NULL && this->input_file_->file().is_locked(); }

  // Return the token, so that the task can be queued.
  Task_token*
  token()
  {
    if (this->input_file_ == NULL)
      return NULL;
    return this->input_file()->file().token();
  }

  // Release the underlying file.
  void
  release()
  {
    if (this->input_file_ != NULL)
      this->input_file()->file().release();
  }

  // Return whether we should just read symbols from this file.
  bool
  just_symbols() const
  { return this->input_file()->just_symbols(); }

  // Return whether this is an incremental object.
  bool
  is_incremental() const
  { return this->do_is_incremental(); }

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

  // Get the number of sections.
  unsigned int
  shnum() const
  { return this->shnum_; }

  // Return a view of the contents of a section.  Set *PLEN to the
  // size.  CACHE is a hint as in File_read::get_view.
  const unsigned char*
  section_contents(unsigned int shndx, section_size_type* plen, bool cache);

  // Adjust a symbol's section index as needed.  SYMNDX is the index
  // of the symbol and SHNDX is the symbol's section from
  // get_st_shndx.  This returns the section index.  It sets
  // *IS_ORDINARY to indicate whether this is a normal section index,
  // rather than a special code between SHN_LORESERVE and
  // SHN_HIRESERVE.
  unsigned int
  adjust_sym_shndx(unsigned int symndx, unsigned int shndx, bool* is_ordinary)
  {
    if (shndx < elfcpp::SHN_LORESERVE)
      *is_ordinary = true;
    else if (shndx == elfcpp::SHN_XINDEX)
      {
	if (this->xindex_ == NULL)
	  this->xindex_ = this->do_initialize_xindex();
	shndx = this->xindex_->sym_xindex_to_shndx(this, symndx);
	*is_ordinary = true;
      }
    else
      *is_ordinary = false;
    return shndx;
  }

  // Return the size of a section given a section index.
  uint64_t
  section_size(unsigned int shndx)
  { return this->do_section_size(shndx); }

  // Return the name of a section given a section index.
  std::string
  section_name(unsigned int shndx) const
  { return this->do_section_name(shndx); }

  // Return the section flags given a section index.
  uint64_t
  section_flags(unsigned int shndx)
  { return this->do_section_flags(shndx); }

  // Return the section entsize given a section index.
  uint64_t
  section_entsize(unsigned int shndx)
  { return this->do_section_entsize(shndx); }

  // Return the section address given a section index.
  uint64_t
  section_address(unsigned int shndx)
  { return this->do_section_address(shndx); }

  // Return the section type given a section index.
  unsigned int
  section_type(unsigned int shndx)
  { return this->do_section_type(shndx); }

  // Return the section link field given a section index.
  unsigned int
  section_link(unsigned int shndx)
  { return this->do_section_link(shndx); }

  // Return the section info field given a section index.
  unsigned int
  section_info(unsigned int shndx)
  { return this->do_section_info(shndx); }

  // Return the required section alignment given a section index.
  uint64_t
  section_addralign(unsigned int shndx)
  { return this->do_section_addralign(shndx); }

  // Return the output section given a section index.
  Output_section*
  output_section(unsigned int shndx) const
  { return this->do_output_section(shndx); }

  // Given a section index, return its address.
  // The return value will be -1U if the section is specially mapped,
  // such as a merge section.
  uint64_t
  output_section_address(unsigned int shndx)
  { return this->do_output_section_address(shndx); }

  // Given a section index, return the offset in the Output_section.
  // The return value will be -1U if the section is specially mapped,
  // such as a merge section.
  uint64_t
  output_section_offset(unsigned int shndx) const
  { return this->do_output_section_offset(shndx); }

  // Read the symbol information.
  void
  read_symbols(Read_symbols_data* sd)
  { return this->do_read_symbols(sd); }

  // Pass sections which should be included in the link to the Layout
  // object, and record where the sections go in the output file.
  void
  layout(Symbol_table* symtab, Layout* layout, Read_symbols_data* sd)
  { this->do_layout(symtab, layout, sd); }

  // Add symbol information to the global symbol table.
  void
  add_symbols(Symbol_table* symtab, Read_symbols_data* sd, Layout *layout)
  { this->do_add_symbols(symtab, sd, layout); }

  // Add symbol information to the global symbol table.
  Archive::Should_include
  should_include_member(Symbol_table* symtab, Layout* layout,
			Read_symbols_data* sd, std::string* why)
  { return this->do_should_include_member(symtab, layout, sd, why); }

  // Iterate over global symbols, calling a visitor class V for each.
  void
  for_all_global_symbols(Read_symbols_data* sd,
			 Library_base::Symbol_visitor_base* v)
  { return this->do_for_all_global_symbols(sd, v); }

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

  // Functions and types for the elfcpp::Elf_file interface.  This
  // permit us to use Object 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 get_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->get_view(file_offset, data_size, true, true)); }

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

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

  // Get a View given a Location.
  View view(Location loc)
  { return View(this->get_view(loc.file_offset, loc.data_size, true, true)); }

  // Get a view into the underlying file.
  const unsigned char*
  get_view(off_t start, section_size_type size, bool aligned, bool cache)
  {
    return this->input_file()->file().get_view(this->offset_, start, size,
					       aligned, cache);
  }

  // Get a lasting view into the underlying file.
  File_view*
  get_lasting_view(off_t start, section_size_type size, bool aligned,
		   bool cache)
  {
    return this->input_file()->file().get_lasting_view(this->offset_, start,
						       size, aligned, cache);
  }

  // Read data from the underlying file.
  void
  read(off_t start, section_size_type size, void* p)
  { this->input_file()->file().read(start + this->offset_, size, p); }

  // Read multiple data from the underlying file.
  void
  read_multiple(const File_read::Read_multiple& rm)
  { this->input_file()->file().read_multiple(this->offset_, rm); }

  // Stop caching views in the underlying file.
  void
  clear_view_cache_marks()
  {
    if (this->input_file_ != NULL)
      this->input_file_->file().clear_view_cache_marks();
  }

  // Get the number of global symbols defined by this object, and the
  // number of the symbols whose final definition came from this
  // object.
  void
  get_global_symbol_counts(const Symbol_table* symtab, size_t* defined,
			   size_t* used) const
  { this->do_get_global_symbol_counts(symtab, defined, used); }

  // Get the symbols defined in this object.
  const Symbols*
  get_global_symbols() const
  { return this->do_get_global_symbols(); }

  // Set flag that this object was found in a system directory.
  void
  set_is_in_system_directory()
  { this->is_in_system_directory_ = true; }

  // Return whether this object was found in a system directory.
  bool
  is_in_system_directory() const
  { return this->is_in_system_directory_; }

  // Set flag that this object was linked with --as-needed.
  void
  set_as_needed()
  { this->as_needed_ = true; }

  // Clear flag that this object was linked with --as-needed.
  void
  clear_as_needed()
  { this->as_needed_ = false; }

  // Return whether this object was linked with --as-needed.
  bool
  as_needed() const
  { return this->as_needed_; }

  // Return whether we found this object by searching a directory.
  bool
  searched_for() const
  { return this->input_file()->will_search_for(); }

  bool
  no_export() const
  { return this->no_export_; }

  void
  set_no_export(bool value)
  { this->no_export_ = value; }

  bool
  section_is_compressed(unsigned int shndx,
			section_size_type* uncompressed_size,
			elfcpp::Elf_Xword* palign = NULL) const
  {
    if (this->compressed_sections_ == NULL)
      return false;
    Compressed_section_map::const_iterator p =
        this->compressed_sections_->find(shndx);
    if (p != this->compressed_sections_->end())
      {
	if (uncompressed_size != NULL)
	  *uncompressed_size = p->second.size;
	if (palign != NULL)
	  *palign = p->second.addralign;
	return true;
      }
    return false;
  }

  // Return a view of the decompressed contents of a section.  Set *PLEN
  // to the size.  Set *IS_NEW to true if the contents need to be freed
  // by the caller.
  const unsigned char*
  decompressed_section_contents(unsigned int shndx, section_size_type* plen,
				bool* is_cached, uint64_t* palign = NULL);

  // Discard any buffers of decompressed sections.  This is done
  // at the end of the Add_symbols task.
  void
  discard_decompressed_sections();

  // Return the index of the first incremental relocation for symbol SYMNDX.
  unsigned int
  get_incremental_reloc_base(unsigned int symndx) const
  { return this->do_get_incremental_reloc_base(symndx); }

  // Return the number of incremental relocations for symbol SYMNDX.
  unsigned int
  get_incremental_reloc_count(unsigned int symndx) const
  { return this->do_get_incremental_reloc_count(symndx); }

  // Return the output view for section SHNDX.
  unsigned char*
  get_output_view(unsigned int shndx, section_size_type* plen) const
  { return this->do_get_output_view(shndx, plen); }

 protected:
  // Returns NULL for Objects that are not dynamic objects.  This method
  // is overridden in the Dynobj class.
  virtual Dynobj*
  do_dynobj()
  { return NULL; }

  // Returns NULL for Objects that are not plugin objects.  This method
  // is overridden in the Pluginobj class.
  virtual Pluginobj*
  do_pluginobj()
  { return NULL; }

  // Return TRUE if this is an incremental (unchanged) input file.
  // We return FALSE by default; the incremental object classes
  // override this method.
  virtual bool
  do_is_incremental() const
  { return false; }

  // Return the last modified time of the file.  This method may be
  // overridden for subclasses that don't use an actual file (e.g.,
  // Incremental objects).
  virtual Timespec
  do_get_mtime()
  { return this->input_file()->file().get_mtime(); }

  // Read the symbols--implemented by child class.
  virtual void
  do_read_symbols(Read_symbols_data*) = 0;

  // Lay out sections--implemented by child class.
  virtual void
  do_layout(Symbol_table*, Layout*, Read_symbols_data*) = 0;

  // Add symbol information to the global symbol table--implemented by
  // child class.
  virtual void
  do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*) = 0;

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

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

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

  // Return the location of the contents of a section.  Implemented by
  // child class.
  virtual const unsigned char*
  do_section_contents(unsigned int shndx, section_size_type* plen,
		      bool cache) = 0;

  // Get the size of a section--implemented by child class.
  virtual uint64_t
  do_section_size(unsigned int shndx) = 0;

  // Get the name of a section--implemented by child class.
  virtual std::string
  do_section_name(unsigned int shndx) const = 0;

  // Get section flags--implemented by child class.
  virtual uint64_t
  do_section_flags(unsigned int shndx) = 0;

  // Get section entsize--implemented by child class.
  virtual uint64_t
  do_section_entsize(unsigned int shndx) = 0;

  // Get section address--implemented by child class.
  virtual uint64_t
  do_section_address(unsigned int shndx) = 0;

  // Get section type--implemented by child class.
  virtual unsigned int
  do_section_type(unsigned int shndx) = 0;

  // Get section link field--implemented by child class.
  virtual unsigned int
  do_section_link(unsigned int shndx) = 0;

  // Get section info field--implemented by child class.
  virtual unsigned int
  do_section_info(unsigned int shndx) = 0;

  // Get section alignment--implemented by child class.
  virtual uint64_t
  do_section_addralign(unsigned int shndx) = 0;

  // Return the output section given a section index--implemented
  // by child class.
  virtual Output_section*
  do_output_section(unsigned int) const
  { gold_unreachable(); }

  // Get the address of a section--implemented by child class.
  virtual uint64_t
  do_output_section_address(unsigned int)
  { gold_unreachable(); }

  // Get the offset of a section--implemented by child class.
  virtual uint64_t
  do_output_section_offset(unsigned int) const
  { gold_unreachable(); }

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

  // Implement get_global_symbol_counts--implemented by child class.
  virtual void
  do_get_global_symbol_counts(const Symbol_table*, size_t*, size_t*) const = 0;

  virtual const Symbols*
  do_get_global_symbols() const = 0;

  // Set the number of sections.
  void
  set_shnum(int shnum)
  { this->shnum_ = shnum; }

  // Functions used by both Sized_relobj_file and Sized_dynobj.

  // Read the section data into a Read_symbols_data object.
  template<int size, bool big_endian>
  void
  read_section_data(elfcpp::Elf_file<size, big_endian, Object>*,
		    Read_symbols_data*);

  // Find the section header with the given NAME.  If HDR is non-NULL
  // then it is a section header returned from a previous call to this
  // function and the next section header with the same name will be
  // returned.
  template<int size, bool big_endian>
  const unsigned char*
  find_shdr(const unsigned char* pshdrs, const char* name,
	    const char* names, section_size_type names_size,
	    const unsigned char* hdr) const;

  // Let the child class initialize the xindex object directly.
  void
  set_xindex(Xindex* xindex)
  {
    gold_assert(this->xindex_ == NULL);
    this->xindex_ = xindex;
  }

  // If NAME is the name of a special .gnu.warning section, arrange
  // for the warning to be issued.  SHNDX is the section index.
  // Return whether it is a warning section.
  bool
  handle_gnu_warning_section(const char* name, unsigned int shndx,
			     Symbol_table*);

  // If NAME is the name of the special section which indicates that
  // this object was compiled with -fsplit-stack, mark it accordingly,
  // and return true.  Otherwise return false.
  bool
  handle_split_stack_section(const char* name);

  // Discard any buffers of decompressed sections.  This is done
  // at the end of the Add_symbols task.
  virtual void
  do_discard_decompressed_sections()
  { }

  // Return the index of the first incremental relocation for symbol SYMNDX--
  // implemented by child class.
  virtual unsigned int
  do_get_incremental_reloc_base(unsigned int) const
  { gold_unreachable(); }

  // Return the number of incremental relocations for symbol SYMNDX--
  // implemented by child class.
  virtual unsigned int
  do_get_incremental_reloc_count(unsigned int) const
  { gold_unreachable(); }

  // Return the output view for a section.
  virtual unsigned char*
  do_get_output_view(unsigned int, section_size_type*) const
  { gold_unreachable(); }

  void
  set_compressed_sections(Compressed_section_map* compressed_sections)
  { this->compressed_sections_ = compressed_sections; }

  Compressed_section_map*
  compressed_sections()
  { return this->compressed_sections_; }

 private:
  // This class may not be copied.
  Object(const Object&);
  Object& operator=(const Object&);

  // Name of object as printed to user.
  std::string name_;
  // For reading the file.
  Input_file* input_file_;
  // Offset within the file--0 for an object file, non-0 for an
  // archive.
  off_t offset_;
  // Number of input sections.
  unsigned int shnum_;
  // Whether this is a dynamic object.
  bool is_dynamic_ : 1;
  // Whether this object is needed.  This is only set for dynamic
  // objects, and means that the object defined a symbol which was
  // used by a reference from a regular object.
  bool is_needed_ : 1;
  // Whether this object was compiled with -fsplit-stack.
  bool uses_split_stack_ : 1;
  // Whether this object contains any functions compiled with the
  // no_split_stack attribute.
  bool has_no_split_stack_ : 1;
  // True if exclude this object from automatic symbol export.
  // This is used only for archive objects.
  bool no_export_ : 1;
  // True if the object was found in a system directory.
  bool is_in_system_directory_ : 1;
  // True if the object was linked with --as-needed.
  bool as_needed_ : 1;
  // Many sections for objects with more than SHN_LORESERVE sections.
  Xindex* xindex_;
  // For compressed debug sections, map section index to uncompressed size
  // and contents.
  Compressed_section_map* compressed_sections_;
};

// A regular object (ET_REL).  This is an abstract base class itself.
// The implementation is the template class Sized_relobj_file.

class Relobj : public Object
{
 public:
  Relobj(const std::string& name, Input_file* input_file, off_t offset = 0)
    : Object(name, input_file, false, offset),
      output_sections_(),
      map_to_relocatable_relocs_(NULL),
      object_merge_map_(NULL),
      relocs_must_follow_section_writes_(false),
      sd_(NULL),
      reloc_counts_(NULL),
      reloc_bases_(NULL),
      first_dyn_reloc_(0),
      dyn_reloc_count_(0)
  { }

  // During garbage collection, the Read_symbols_data pass for 
  // each object is stored as layout needs to be done after 
  // reloc processing.
  Symbols_data* 
  get_symbols_data()
  { return this->sd_; }

  // Decides which section names have to be included in the worklist
  // as roots.
  bool
  is_section_name_included(const char* name);
 
  void
  copy_symbols_data(Symbols_data* gc_sd, Read_symbols_data* sd,
                    unsigned int section_header_size);

  void
  set_symbols_data(Symbols_data* sd)
  { this->sd_ = sd; }

  // During garbage collection, the Read_relocs pass for all objects 
  // is done before scanning the relocs.  In that case, this->rd_ is
  // used to store the information from Read_relocs for each object.
  // This data is also used to compute the list of relevant sections.
  Read_relocs_data*
  get_relocs_data()
  { return this->rd_; }

  void
  set_relocs_data(Read_relocs_data* rd)
  { this->rd_ = rd; }

  virtual bool
  is_output_section_offset_invalid(unsigned int shndx) const = 0;

  // Read the relocs.
  void
  read_relocs(Read_relocs_data* rd)
  { return this->do_read_relocs(rd); }

  // Process the relocs, during garbage collection only.
  void
  gc_process_relocs(Symbol_table* symtab, Layout* layout, Read_relocs_data* rd)
  { return this->do_gc_process_relocs(symtab, layout, rd); }

  // Scan the relocs and adjust the symbol table.
  void
  scan_relocs(Symbol_table* symtab, Layout* layout, Read_relocs_data* rd)
  { return this->do_scan_relocs(symtab, layout, rd); }

  // Return the value of the local symbol whose index is SYMNDX, plus
  // ADDEND.  ADDEND is passed in so that we can correctly handle the
  // section symbol for a merge section.
  uint64_t
  local_symbol_value(unsigned int symndx, uint64_t addend) const
  { return this->do_local_symbol_value(symndx, addend); }

  // Return the PLT offset for a local symbol.  It is an error to call
  // this if it doesn't have one.
  unsigned int
  local_plt_offset(unsigned int symndx) const
  { return this->do_local_plt_offset(symndx); }

  // Return whether the local symbol SYMNDX has a GOT offset of type
  // GOT_TYPE.
  bool
  local_has_got_offset(unsigned int symndx, unsigned int got_type) const
  { return this->do_local_has_got_offset(symndx, got_type, 0); }

  // Return whether the local symbol SYMNDX plus ADDEND has a GOT offset
  // of type GOT_TYPE.
  bool
  local_has_got_offset(unsigned int symndx, unsigned int got_type,
		       uint64_t addend) const
  { return this->do_local_has_got_offset(symndx, got_type, addend); }

  // Return the GOT offset of type GOT_TYPE of the local symbol
  // SYMNDX.  It is an error to call this if the symbol does not have
  // a GOT offset of the specified type.
  unsigned int
  local_got_offset(unsigned int symndx, unsigned int got_type) const
  { return this->do_local_got_offset(symndx, got_type, 0); }

  // Return the GOT offset of type GOT_TYPE of the local symbol
  // SYMNDX plus ADDEND.  It is an error to call this if the symbol
  // does not have a GOT offset of the specified type.
  unsigned int
  local_got_offset(unsigned int symndx, unsigned int got_type,
		       uint64_t addend) const
  { return this->do_local_got_offset(symndx, got_type, addend); }

  // Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX
  // to GOT_OFFSET.
  void
  set_local_got_offset(unsigned int symndx, unsigned int got_type,
		       unsigned int got_offset)
  { this->do_set_local_got_offset(symndx, got_type, got_offset, 0); }

  // Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX
  // plus ADDEND to GOT_OFFSET.
  void
  set_local_got_offset(unsigned int symndx, unsigned int got_type,
		       unsigned int got_offset, uint64_t addend)
  { this->do_set_local_got_offset(symndx, got_type, got_offset, addend); }

  // Return whether the local symbol SYMNDX is a TLS symbol.
  bool
  local_is_tls(unsigned int symndx) const
  { return this->do_local_is_tls(symndx); }

  // The number of local symbols in the input symbol table.
  virtual unsigned int
  local_symbol_count() const
  { return this->do_local_symbol_count(); }

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

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

  // Initial local symbol processing: count the number of local symbols
  // in the output symbol table and dynamic symbol table; add local symbol
  // names to *POOL and *DYNPOOL.
  void
  count_local_symbols(Stringpool_template<char>* pool,
                      Stringpool_template<char>* dynpool)
  { return this->do_count_local_symbols(pool, dynpool); }

  // Set the values of the local symbols, set the output symbol table
  // indexes for the local variables, and set the offset where local
  // symbol information will be stored. Returns the new local symbol index.
  unsigned int
  finalize_local_symbols(unsigned int index, off_t off, Symbol_table* symtab)
  { return this->do_finalize_local_symbols(index, off, symtab); }

  // Set the output dynamic symbol table indexes for the local variables.
  unsigned int
  set_local_dynsym_indexes(unsigned int index)
  { return this->do_set_local_dynsym_indexes(index); }

  // Set the offset where local dynamic symbol information will be stored.
  unsigned int
  set_local_dynsym_offset(off_t off)
  { return this->do_set_local_dynsym_offset(off); }

  // Record a dynamic relocation against an input section from this object.
  void
  add_dyn_reloc(unsigned int index)
  {
    if (this->dyn_reloc_count_ == 0)
      this->first_dyn_reloc_ = index;
    ++this->dyn_reloc_count_;
  }

  // Return the index of the first dynamic relocation.
  unsigned int
  first_dyn_reloc() const
  { return this->first_dyn_reloc_; }

  // Return the count of dynamic relocations.
  unsigned int
  dyn_reloc_count() const
  { return this->dyn_reloc_count_; }

  // Relocate the input sections and write out the local symbols.
  void
  relocate(const Symbol_table* symtab, const Layout* layout, Output_file* of)
  { return this->do_relocate(symtab, layout, of); }

  // Return whether an input section is being included in the link.
  bool
  is_section_included(unsigned int shndx) const
  {
    gold_assert(shndx < this->output_sections_.size());
    return this->output_sections_[shndx] != NULL;
  }

  // The output section of the input section with index SHNDX.
  // This is only used currently to remove a section from the link in
  // relaxation.
  void
  set_output_section(unsigned int shndx, Output_section* os)
  {
    gold_assert(shndx < this->output_sections_.size());
    this->output_sections_[shndx] = os;
  }
  
  // Set the offset of an input section within its output section.
  void
  set_section_offset(unsigned int shndx, uint64_t off)
  { this->do_set_section_offset(shndx, off); }

  // Return true if we need to wait for output sections to be written
  // before we can apply relocations.  This is true if the object has
  // any relocations for sections which require special handling, such
  // as the exception frame section.
  bool
  relocs_must_follow_section_writes() const
  { return this->relocs_must_follow_section_writes_; }

  Object_merge_map*
  get_or_create_merge_map();

  template<int size>
  void
  initialize_input_to_output_map(unsigned int shndx,
      typename elfcpp::Elf_types<size>::Elf_Addr starting_address,
      Unordered_map<section_offset_type,
	    typename elfcpp::Elf_types<size>::Elf_Addr>* output_address) const;

  void
  add_merge_mapping(Output_section_data *output_data,
                    unsigned int shndx, section_offset_type offset,
                    section_size_type length,
                    section_offset_type output_offset);

  bool
  merge_output_offset(unsigned int shndx, section_offset_type offset,
                      section_offset_type *poutput) const;

  const Output_section_data*
  find_merge_section(unsigned int shndx) const;

  // Record the relocatable reloc info for an input reloc section.
  void
  set_relocatable_relocs(unsigned int reloc_shndx, Relocatable_relocs* rr)
  {
    gold_assert(reloc_shndx < this->shnum());
    (*this->map_to_relocatable_relocs_)[reloc_shndx] = rr;
  }

  // Get the relocatable reloc info for an input reloc section.
  Relocatable_relocs*
  relocatable_relocs(unsigned int reloc_shndx)
  {
    gold_assert(reloc_shndx < this->shnum());
    return (*this->map_to_relocatable_relocs_)[reloc_shndx];
  }

  // Layout sections whose layout was deferred while waiting for
  // input files from a plugin.
  void
  layout_deferred_sections(Layout* layout)
  { this->do_layout_deferred_sections(layout); }

  // Return the index of the first incremental relocation for symbol SYMNDX.
  virtual unsigned int
  do_get_incremental_reloc_base(unsigned int symndx) const
  { return this->reloc_bases_[symndx]; }

  // Return the number of incremental relocations for symbol SYMNDX.
  virtual unsigned int
  do_get_incremental_reloc_count(unsigned int symndx) const
  { return this->reloc_counts_[symndx]; }

  // Return the word size of the object file.
  int
  elfsize() const
  { return this->do_elfsize(); }

  // Return TRUE if this is a big-endian object file.
  bool
  is_big_endian() const
  { return this->do_is_big_endian(); }

 protected:
  // The output section to be used for each input section, indexed by
  // the input section number.  The output section is NULL if the
  // input section is to be discarded.
  typedef std::vector<Output_section*> Output_sections;

  // Read the relocs--implemented by child class.
  virtual void
  do_read_relocs(Read_relocs_data*) = 0;

  // Process the relocs--implemented by child class.
  virtual void
  do_gc_process_relocs(Symbol_table*, Layout*, Read_relocs_data*) = 0;

  // Scan the relocs--implemented by child class.
  virtual void
  do_scan_relocs(Symbol_table*, Layout*, Read_relocs_data*) = 0;

  // Return the value of a local symbol.
  virtual uint64_t
  do_local_symbol_value(unsigned int symndx, uint64_t addend) const = 0;

  // Return the PLT offset of a local symbol.
  virtual unsigned int
  do_local_plt_offset(unsigned int symndx) const = 0;

  // Return whether a local symbol plus addend has a GOT offset
  // of a given type.
  virtual bool
  do_local_has_got_offset(unsigned int symndx,
			  unsigned int got_type, uint64_t addend) const = 0;

  // Return the GOT offset of a given type of a local symbol plus addend.
  virtual unsigned int
  do_local_got_offset(unsigned int symndx, unsigned int got_type,
		      uint64_t addend) const = 0;

  // Set the GOT offset with a given type for a local symbol plus addend.
  virtual void
  do_set_local_got_offset(unsigned int symndx, unsigned int got_type,
			  unsigned int got_offset, uint64_t addend) = 0;

  // Return whether local symbol SYMNDX is a TLS symbol.
  virtual bool
  do_local_is_tls(unsigned int symndx) const = 0;

  // Return the number of local symbols--implemented by child class.
  virtual unsigned int
  do_local_symbol_count() const = 0;

  // Return the number of output local symbols--implemented by child class.
  virtual unsigned int
  do_output_local_symbol_count() const = 0;

  // Return the file offset for local symbols--implemented by child class.
  virtual off_t
  do_local_symbol_offset() const = 0;

  // Count local symbols--implemented by child class.
  virtual void
  do_count_local_symbols(Stringpool_template<char>*,
			 Stringpool_template<char>*) = 0;

  // Finalize the local symbols.  Set the output symbol table indexes
  // for the local variables, and set the offset where local symbol
  // information will be stored.
  virtual unsigned int
  do_finalize_local_symbols(unsigned int, off_t, Symbol_table*) = 0;

  // Set the output dynamic symbol table indexes for the local variables.
  virtual unsigned int
  do_set_local_dynsym_indexes(unsigned int) = 0;

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

  // Relocate the input sections and write out the local
  // symbols--implemented by child class.
  virtual void
  do_relocate(const Symbol_table* symtab, const Layout*, Output_file* of) = 0;

  // Set the offset of a section--implemented by child class.
  virtual void
  do_set_section_offset(unsigned int shndx, uint64_t off) = 0;

  // Layout sections whose layout was deferred while waiting for
  // input files from a plugin--implemented by child class.
  virtual void
  do_layout_deferred_sections(Layout*) = 0;

  // Given a section index, return the corresponding Output_section.
  // The return value will be NULL if the section is not included in
  // the link.
  Output_section*
  do_output_section(unsigned int shndx) const
  {
    gold_assert(shndx < this->output_sections_.size());
    return this->output_sections_[shndx];
  }

  // Return the vector mapping input sections to output sections.
  Output_sections&
  output_sections()
  { return this->output_sections_; }

  const Output_sections&
  output_sections() const
  { return this->output_sections_; }

  // Set the size of the relocatable relocs array.
  void
  size_relocatable_relocs()
  {
    this->map_to_relocatable_relocs_ =
      new std::vector<Relocatable_relocs*>(this->shnum());
  }

  // Record that we must wait for the output sections to be written
  // before applying relocations.
  void
  set_relocs_must_follow_section_writes()
  { this->relocs_must_follow_section_writes_ = true; }

  // Allocate the array for counting incremental relocations.
  void
  allocate_incremental_reloc_counts()
  {
    unsigned int nsyms = this->do_get_global_symbols()->size();
    this->reloc_counts_ = new unsigned int[nsyms];
    gold_assert(this->reloc_counts_ != NULL);
    memset(this->reloc_counts_, 0, nsyms * sizeof(unsigned int));
  }

  // Record a relocation in this object referencing global symbol SYMNDX.
  // Used for tracking incremental link information.
  void
  count_incremental_reloc(unsigned int symndx)
  {
    unsigned int nsyms = this->do_get_global_symbols()->size();
    gold_assert(symndx < nsyms);
    gold_assert(this->reloc_counts_ != NULL);
    ++this->reloc_counts_[symndx];
  }

  // Finalize the incremental relocation information.
  void
  finalize_incremental_relocs(Layout* layout, bool clear_counts);

  // Return the index of the next relocation to be written for global symbol
  // SYMNDX.  Only valid after finalize_incremental_relocs() has been called.
  unsigned int
  next_incremental_reloc_index(unsigned int symndx)
  {
    unsigned int nsyms = this->do_get_global_symbols()->size();

    gold_assert(this->reloc_counts_ != NULL);
    gold_assert(this->reloc_bases_ != NULL);
    gold_assert(symndx < nsyms);

    unsigned int counter = this->reloc_counts_[symndx]++;
    return this->reloc_bases_[symndx] + counter;
  }

  // Return the word size of the object file--
  // implemented by child class.
  virtual int
  do_elfsize() const = 0;

  // Return TRUE if this is a big-endian object file--
  // implemented by child class.
  virtual bool
  do_is_big_endian() const = 0;

 private:
  // Mapping from input sections to output section.
  Output_sections output_sections_;
  // Mapping from input section index to the information recorded for
  // the relocations.  This is only used for a relocatable link.
  std::vector<Relocatable_relocs*>* map_to_relocatable_relocs_;
  // Mappings for merge sections.  This is managed by the code in the
  // Merge_map class.
  Object_merge_map* object_merge_map_;
  // Whether we need to wait for output sections to be written before
  // we can apply relocations.
  bool relocs_must_follow_section_writes_;
  // Used to store the relocs data computed by the Read_relocs pass. 
  // Used during garbage collection of unused sections.
  Read_relocs_data* rd_;
  // Used to store the symbols data computed by the Read_symbols pass.
  // Again used during garbage collection when laying out referenced
  // sections.
  gold::Symbols_data* sd_;
  // Per-symbol counts of relocations, for incremental links.
  unsigned int* reloc_counts_;
  // Per-symbol base indexes of relocations, for incremental links.
  unsigned int* reloc_bases_;
  // Index of the first dynamic relocation for this object.
  unsigned int first_dyn_reloc_;
  // Count of dynamic relocations for this object.
  unsigned int dyn_reloc_count_;
};

// This class is used to handle relocations against a section symbol
// in an SHF_MERGE section.  For such a symbol, we need to know the
// addend of the relocation before we can determine the final value.
// The addend gives us the location in the input section, and we can
// determine how it is mapped to the output section.  For a
// non-section symbol, we apply the addend to the final value of the
// symbol; that is done in finalize_local_symbols, and does not use
// this class.

template<int size>
class Merged_symbol_value
{
 public:
  typedef typename elfcpp::Elf_types<size>::Elf_Addr Value;

  // We use a hash table to map offsets in the input section to output
  // addresses.
  typedef Unordered_map<section_offset_type, Value> Output_addresses;

  Merged_symbol_value(Value input_value, Value output_start_address)
    : input_value_(input_value), output_start_address_(output_start_address),
      output_addresses_()
  { }

  // Initialize the hash table.
  void
  initialize_input_to_output_map(const Relobj*, unsigned int input_shndx);

  // Release the hash table to save space.
  void
  free_input_to_output_map()
  { this->output_addresses_.clear(); }

  // Get the output value corresponding to an addend.  The object and
  // input section index are passed in because the caller will have
  // them; otherwise we could store them here.
  Value
  value(const Relobj* object, unsigned int input_shndx, Value addend) const
  {
    // This is a relocation against a section symbol.  ADDEND is the
    // offset in the section.  The result should be the start of some
    // merge area.  If the object file wants something else, it should
    // use a regular symbol rather than a section symbol.
    // Unfortunately, PR 6658 shows a case in which the object file
    // refers to the section symbol, but uses a negative ADDEND to
    // compensate for a PC relative reloc.  We can't handle the
    // general case.  However, we can handle the special case of a
    // negative addend, by assuming that it refers to the start of the
    // section.  Of course, that means that we have to guess when
    // ADDEND is negative.  It is normal to see a 32-bit value here
    // even when the template parameter size is 64, as 64-bit object
    // file formats have 32-bit relocations.  We know this is a merge
    // section, so we know it has to fit into memory.  So we assume
    // that we won't see a value larger than a large 32-bit unsigned
    // value.  This will break objects with very very large merge
    // sections; they probably break in other ways anyhow.
    Value input_offset = this->input_value_;
    if (addend < 0xffffff00)
      {
	input_offset += addend;
	addend = 0;
      }
    typename Output_addresses::const_iterator p =
      this->output_addresses_.find(input_offset);
    if (p != this->output_addresses_.end())
      return p->second + addend;

    return (this->value_from_output_section(object, input_shndx, input_offset)
	    + addend);
  }

 private:
  // Get the output value for an input offset if we couldn't find it
  // in the hash table.
  Value
  value_from_output_section(const Relobj*, unsigned int input_shndx,
			    Value input_offset) const;

  // The value of the section symbol in the input file.  This is
  // normally zero, but could in principle be something else.
  Value input_value_;
  // The start address of this merged section in the output file.
  Value output_start_address_;
  // A hash table which maps offsets in the input section to output
  // addresses.  This only maps specific offsets, not all offsets.
  Output_addresses output_addresses_;
};

// This POD class is holds the value of a symbol.  This is used for
// local symbols, and for all symbols during relocation processing.
// For special sections, such as SHF_MERGE sections, this calls a
// function to get the final symbol value.

template<int size>
class Symbol_value
{
 public:
  typedef typename elfcpp::Elf_types<size>::Elf_Addr Value;

  Symbol_value()
    : output_symtab_index_(0), output_dynsym_index_(-1U), input_shndx_(0),
      is_ordinary_shndx_(false), is_section_symbol_(false),
      is_tls_symbol_(false), is_ifunc_symbol_(false), has_output_value_(true)
  { this->u_.value = 0; }

  ~Symbol_value()
  {
    if (!this->has_output_value_)
      delete this->u_.merged_symbol_value;
  }

  // Get the value of this symbol.  OBJECT is the object in which this
  // symbol is defined, and ADDEND is an addend to add to the value.
  template<bool big_endian>
  Value
  value(const Sized_relobj_file<size, big_endian>* object, Value addend) const
  {
    if (this->has_output_value_)
      return this->u_.value + addend;
    else
      {
	gold_assert(this->is_ordinary_shndx_);
	return this->u_.merged_symbol_value->value(object, this->input_shndx_,
						   addend);
      }
  }

  // Set the value of this symbol in the output symbol table.
  void
  set_output_value(Value value)
  { this->u_.value = value; }

  // For a section symbol in a merged section, we need more
  // information.
  void
  set_merged_symbol_value(Merged_symbol_value<size>* msv)
  {
    gold_assert(this->is_section_symbol_);
    this->has_output_value_ = false;
    this->u_.merged_symbol_value = msv;
  }

  // Initialize the input to output map for a section symbol in a
  // merged section.  We also initialize the value of a non-section
  // symbol in a merged section.
  void
  initialize_input_to_output_map(const Relobj* object)
  {
    if (!this->has_output_value_)
      {
	gold_assert(this->is_section_symbol_ && this->is_ordinary_shndx_);
	Merged_symbol_value<size>* msv = this->u_.merged_symbol_value;
	msv->initialize_input_to_output_map(object, this->input_shndx_);
      }
  }

  // Free the input to output map for a section symbol in a merged
  // section.
  void
  free_input_to_output_map()
  {
    if (!this->has_output_value_)
      this->u_.merged_symbol_value->free_input_to_output_map();
  }

  // Set the value of the symbol from the input file.  This is only
  // called by count_local_symbols, to communicate the value to
  // finalize_local_symbols.
  void
  set_input_value(Value value)
  { this->u_.value = value; }

  // Return the input value.  This is only called by
  // finalize_local_symbols and (in special cases) relocate_section.
  Value
  input_value() const
  { return this->u_.value; }

  // Return whether we have set the index in the output symbol table
  // yet.
  bool
  is_output_symtab_index_set() const
  {
    return (this->output_symtab_index_ != 0
	    && this->output_symtab_index_ != -2U);
  }

  // Return whether this symbol may be discarded from the normal
  // symbol table.
  bool
  may_be_discarded_from_output_symtab() const
  {
    gold_assert(!this->is_output_symtab_index_set());
    return this->output_symtab_index_ != -2U;
  }

  // Return whether this symbol has an entry in the output symbol
  // table.
  bool
  has_output_symtab_entry() const
  {
    gold_assert(this->is_output_symtab_index_set());
    return this->output_symtab_index_ != -1U;
  }

  // Return the index in the output symbol table.
  unsigned int
  output_symtab_index() const
  {
    gold_assert(this->is_output_symtab_index_set()
		&& this->output_symtab_index_ != -1U);
    return this->output_symtab_index_;
  }

  // Set the index in the output symbol table.
  void
  set_output_symtab_index(unsigned int i)
  {
    gold_assert(!this->is_output_symtab_index_set());
    gold_assert(i != 0 && i != -1U && i != -2U);
    this->output_symtab_index_ = i;
  }

  // Record that this symbol should not go into the output symbol
  // table.
  void
  set_no_output_symtab_entry()
  {
    gold_assert(this->output_symtab_index_ == 0);
    this->output_symtab_index_ = -1U;
  }

  // Record that this symbol must go into the output symbol table,
  // because it there is a relocation that uses it.
  void
  set_must_have_output_symtab_entry()
  {
    gold_assert(!this->is_output_symtab_index_set());
    this->output_symtab_index_ = -2U;
  }

  // Set the index in the output dynamic symbol table.
  void
  set_needs_output_dynsym_entry()
  {
    gold_assert(!this->is_section_symbol());
    this->output_dynsym_index_ = 0;
  }

  // Return whether this symbol should go into the dynamic symbol
  // table.
  bool
  needs_output_dynsym_entry() const
  {
    return this->output_dynsym_index_ != -1U;
  }

  // Return whether this symbol has an entry in the dynamic symbol
  // table.
  bool
  has_output_dynsym_entry() const
  {
    gold_assert(this->output_dynsym_index_ != 0);
    return this->output_dynsym_index_ != -1U;
  }

  // Record that this symbol should go into the dynamic symbol table.
  void
  set_output_dynsym_index(unsigned int i)
  {
    gold_assert(this->output_dynsym_index_ == 0);
    gold_assert(i != 0 && i != -1U);
    this->output_dynsym_index_ = i;
  }

  // Return the index in the output dynamic symbol table.
  unsigned int
  output_dynsym_index() const
  {
    gold_assert(this->output_dynsym_index_ != 0
                && this->output_dynsym_index_ != -1U);
    return this->output_dynsym_index_;
  }

  // Set the index of the input section in the input file.
  void
  set_input_shndx(unsigned int i, bool is_ordinary)
  {
    this->input_shndx_ = i;
    // input_shndx_ field is a bitfield, so make sure that the value
    // fits.
    gold_assert(this->input_shndx_ == i);
    this->is_ordinary_shndx_ = is_ordinary;
  }

  // Return the index of the input section in the input file.
  unsigned int
  input_shndx(bool* is_ordinary) const
  {
    *is_ordinary = this->is_ordinary_shndx_;
    return this->input_shndx_;
  }

  // Whether this is a section symbol.
  bool
  is_section_symbol() const
  { return this->is_section_symbol_; }

  // Record that this is a section symbol.
  void
  set_is_section_symbol()
  {
    gold_assert(!this->needs_output_dynsym_entry());
    this->is_section_symbol_ = true;
  }

  // Record that this is a TLS symbol.
  void
  set_is_tls_symbol()
  { this->is_tls_symbol_ = true; }

  // Return true if this is a TLS symbol.
  bool
  is_tls_symbol() const
  { return this->is_tls_symbol_; }

  // Record that this is an IFUNC symbol.
  void
  set_is_ifunc_symbol()
  { this->is_ifunc_symbol_ = true; }

  // Return true if this is an IFUNC symbol.
  bool
  is_ifunc_symbol() const
  { return this->is_ifunc_symbol_; }

  // Return true if this has output value.
  bool
  has_output_value() const
  { return this->has_output_value_; }

 private:
  // The index of this local symbol in the output symbol table.  This
  // will be 0 if no value has been assigned yet, and the symbol may
  // be omitted.  This will be -1U if the symbol should not go into
  // the symbol table.  This will be -2U if the symbol must go into
  // the symbol table, but no index has been assigned yet.
  unsigned int output_symtab_index_;
  // The index of this local symbol in the dynamic symbol table.  This
  // will be -1U if the symbol should not go into the symbol table.
  unsigned int output_dynsym_index_;
  // The section index in the input file in which this symbol is
  // defined.
  unsigned int input_shndx_ : 27;
  // Whether the section index is an ordinary index, not a special
  // value.
  bool is_ordinary_shndx_ : 1;
  // Whether this is a STT_SECTION symbol.
  bool is_section_symbol_ : 1;
  // Whether this is a STT_TLS symbol.
  bool is_tls_symbol_ : 1;
  // Whether this is a STT_GNU_IFUNC symbol.
  bool is_ifunc_symbol_ : 1;
  // Whether this symbol has a value for the output file.  This is
  // normally set to true during Layout::finalize, by
  // finalize_local_symbols.  It will be false for a section symbol in
  // a merge section, as for such symbols we can not determine the
  // value to use in a relocation until we see the addend.
  bool has_output_value_ : 1;
  union
  {
    // This is used if has_output_value_ is true.  Between
    // count_local_symbols and finalize_local_symbols, this is the
    // value in the input file.  After finalize_local_symbols, it is
    // the value in the output file.
    Value value;
    // This is used if has_output_value_ is false.  It points to the
    // information we need to get the value for a merge section.
    Merged_symbol_value<size>* merged_symbol_value;
  } u_;
};

// This type is used to modify relocations for -fsplit-stack.  It is
// indexed by relocation index, and means that the relocation at that
// index should use the symbol from the vector, rather than the one
// indicated by the relocation.

class Reloc_symbol_changes
{
 public:
  Reloc_symbol_changes(size_t count)
    : vec_(count, NULL)
  { }

  void
  set(size_t i, Symbol* sym)
  { this->vec_[i] = sym; }

  const Symbol*
  operator[](size_t i) const
  { return this->vec_[i]; }

 private:
  std::vector<Symbol*> vec_;
};

// Abstract base class for a regular object file, either a real object file
// or an incremental (unchanged) object.  This is size and endian specific.

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

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

  Sized_relobj(const std::string& name, Input_file* input_file)
    : Relobj(name, input_file), local_got_offsets_(), section_offsets_()
  { }

  Sized_relobj(const std::string& name, Input_file* input_file,
		    off_t offset)
    : Relobj(name, input_file, offset), local_got_offsets_(), section_offsets_()
  { }

  ~Sized_relobj()
  { }

  // If this is a regular object, return a pointer to the Sized_relobj_file
  // object.  Otherwise, return NULL.
  virtual Sized_relobj_file<size, big_endian>*
  sized_relobj()
  { return NULL; }

  const virtual Sized_relobj_file<size, big_endian>*
  sized_relobj() const
  { return NULL; }

  // Checks if the offset of input section SHNDX within its output
  // section is invalid.
  bool
  is_output_section_offset_invalid(unsigned int shndx) const
  { return this->get_output_section_offset(shndx) == invalid_address; }

  // Get the offset of input section SHNDX within its output section.
  // This is -1 if the input section requires a special mapping, such
  // as a merge section.  The output section can be found in the
  // output_sections_ field of the parent class Relobj.
  Address
  get_output_section_offset(unsigned int shndx) const
  {
    gold_assert(shndx < this->section_offsets_.size());
    return this->section_offsets_[shndx];
  }

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

 protected:
  typedef Relobj::Output_sections Output_sections;

  // Clear the local symbol information.
  void
  clear_got_offsets()
  { this->local_got_offsets_.clear(); }

  // Return the vector of section offsets.
  std::vector<Address>&
  section_offsets()
  { return this->section_offsets_; }

  // Get the address of an output section.
  uint64_t
  do_output_section_address(unsigned int shndx);

  // Get the offset of a section.
  uint64_t
  do_output_section_offset(unsigned int shndx) const
  {
    Address off = this->get_output_section_offset(shndx);
    if (off == invalid_address)
      return -1ULL;
    return off;
  }

  // Set the offset of a section.
  void
  do_set_section_offset(unsigned int shndx, uint64_t off)
  {
    gold_assert(shndx < this->section_offsets_.size());
    this->section_offsets_[shndx] =
      (off == static_cast<uint64_t>(-1)
       ? invalid_address
       : convert_types<Address, uint64_t>(off));
  }

  // Return whether the local symbol SYMNDX plus ADDEND has a GOT offset
  // of type GOT_TYPE.
  bool
  do_local_has_got_offset(unsigned int symndx, unsigned int got_type,
			  uint64_t addend) const
  {
    Local_got_entry_key key(symndx, addend);
    Local_got_offsets::const_iterator p =
        this->local_got_offsets_.find(key);
    return (p != this->local_got_offsets_.end()
            && p->second->get_offset(got_type) != -1U);
  }

  // Return the GOT offset of type GOT_TYPE of the local symbol
  // SYMNDX plus ADDEND.
  unsigned int
  do_local_got_offset(unsigned int symndx, unsigned int got_type,
			  uint64_t addend) const
  {
    Local_got_entry_key key(symndx, addend);
    Local_got_offsets::const_iterator p =
        this->local_got_offsets_.find(key);
    gold_assert(p != this->local_got_offsets_.end());
    unsigned int off = p->second->get_offset(got_type);
    gold_assert(off != -1U);
    return off;
  }

  // Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX
  // plus ADDEND to GOT_OFFSET.
  void
  do_set_local_got_offset(unsigned int symndx, unsigned int got_type,
			  unsigned int got_offset, uint64_t addend)
  {
    Local_got_entry_key key(symndx, addend);
    Local_got_offsets::const_iterator p =
        this->local_got_offsets_.find(key);
    if (p != this->local_got_offsets_.end())
      p->second->set_offset(got_type, got_offset);
    else
      {
        Got_offset_list* g = new Got_offset_list(got_type, got_offset);
        std::pair<Local_got_offsets::iterator, bool> ins =
            this->local_got_offsets_.insert(std::make_pair(key, g));
        gold_assert(ins.second);
      }
  }

  // Return the word size of the object file.
  virtual int
  do_elfsize() const
  { return size; }

  // Return TRUE if this is a big-endian object file.
  virtual bool
  do_is_big_endian() const
  { return big_endian; }

 private:
  // The GOT offsets of local symbols. This map also stores GOT offsets
  // for tp-relative offsets for TLS symbols.
  typedef Unordered_map<Local_got_entry_key, Got_offset_list*,
                        Local_got_entry_key::hash,
                        Local_got_entry_key::equal_to> Local_got_offsets;

  // GOT offsets for local non-TLS symbols, and tp-relative offsets
  // for TLS symbols, indexed by local got entry key class.
  Local_got_offsets local_got_offsets_;
  // For each input section, the offset of the input section in its
  // output section.  This is INVALID_ADDRESS if the input section requires a
  // special mapping.
  std::vector<Address> section_offsets_;
};

// A regular object file.  This is size and endian specific.

template<int size, bool big_endian>
class Sized_relobj_file : 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;
  typedef std::vector<Symbol_value<size> > Local_values;

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

  enum Compute_final_local_value_status
  {
    // No error.
    CFLV_OK,
    // An error occurred.
    CFLV_ERROR,
    // The local symbol has no output section.
    CFLV_DISCARDED
  };

  Sized_relobj_file(const std::string& name,
		    Input_file* input_file,
		    off_t offset,
		    const typename elfcpp::Ehdr<size, big_endian>&);

  ~Sized_relobj_file();

  // Set up the object file based on TARGET.
  void
  setup()
  { this->do_setup(); }

  // Return a pointer to the Sized_relobj_file object.
  Sized_relobj_file<size, big_endian>*
  sized_relobj()
  { return this; }

  const Sized_relobj_file<size, big_endian>*
  sized_relobj() const
  { return this; }

  // Return the ELF file type.
  int
  e_type() const
  { return this->e_type_; }

  // Return the number of symbols.  This is only valid after
  // Object::add_symbols has been called.
  unsigned int
  symbol_count() const
  { return this->local_symbol_count_ + this->symbols_.size(); }

  // If SYM is the index of a global symbol in the object file's
  // symbol table, return the Symbol object.  Otherwise, return NULL.
  Symbol*
  global_symbol(unsigned int sym) const
  {
    if (sym >= this->local_symbol_count_)
      {
	gold_assert(sym - this->local_symbol_count_ < this->symbols_.size());
	return this->symbols_[sym - this->local_symbol_count_];
      }
    return NULL;
  }

  // Return the section index of symbol SYM.  Set *VALUE to its value
  // in the object file.  Set *IS_ORDINARY if this is an ordinary
  // section index, not a special code between SHN_LORESERVE and
  // SHN_HIRESERVE.  Note that for a symbol which is not defined in
  // this object file, this will set *VALUE to 0 and return SHN_UNDEF;
  // it will not return the final value of the symbol in the link.
  unsigned int
  symbol_section_and_value(unsigned int sym, Address* value, bool* is_ordinary);

  // Return a pointer to the Symbol_value structure which holds the
  // value of a local symbol.
  const Symbol_value<size>*
  local_symbol(unsigned int sym) const
  {
    gold_assert(sym < this->local_values_.size());
    return &this->local_values_[sym];
  }

  // Return the index of local symbol SYM in the ordinary symbol
  // table.  A value of -1U means that the symbol is not being output.
  unsigned int
  symtab_index(unsigned int sym) const
  {
    gold_assert(sym < this->local_values_.size());
    return this->local_values_[sym].output_symtab_index();
  }

  // Return the index of local symbol SYM in the dynamic symbol
  // table.  A value of -1U means that the symbol is not being output.
  unsigned int
  dynsym_index(unsigned int sym) const
  {
    gold_assert(sym < this->local_values_.size());
    return this->local_values_[sym].output_dynsym_index();
  }

  // Return the input section index of local symbol SYM.
  unsigned int
  local_symbol_input_shndx(unsigned int sym, bool* is_ordinary) const
  {
    gold_assert(sym < this->local_values_.size());
    return this->local_values_[sym].input_shndx(is_ordinary);
  }

  // Record that local symbol SYM must be in the output symbol table.
  void
  set_must_have_output_symtab_entry(unsigned int sym)
  {
    gold_assert(sym < this->local_values_.size());
    this->local_values_[sym].set_must_have_output_symtab_entry();
  }

  // Record that local symbol SYM needs a dynamic symbol entry.
  void
  set_needs_output_dynsym_entry(unsigned int sym)
  {
    gold_assert(sym < this->local_values_.size());
    this->local_values_[sym].set_needs_output_dynsym_entry();
  }

  // Return whether the local symbol SYMNDX has a PLT offset.
  bool
  local_has_plt_offset(unsigned int symndx) const;

  // Set the PLT offset of the local symbol SYMNDX.
  void
  set_local_plt_offset(unsigned int symndx, unsigned int plt_offset);

  // Adjust this local symbol value.  Return false if the symbol
  // should be discarded from the output file.
  bool
  adjust_local_symbol(Symbol_value<size>* lv) const
  { return this->do_adjust_local_symbol(lv); }

  // Return the name of the symbol that spans the given offset in the
  // specified section in this object.  This is used only for error
  // messages and is not particularly efficient.
  bool
  get_symbol_location_info(unsigned int shndx, off_t offset,
			   Symbol_location_info* info);

  // Look for a kept section corresponding to the given discarded section,
  // and return its output address.  This is used only for relocations in
  // debugging sections.
  Address
  map_to_kept_section(unsigned int shndx, std::string& section_name,
		      bool* found) const;

  // Look for a kept section corresponding to the given discarded section,
  // and return its object file.
  Relobj*
  find_kept_section_object(unsigned int shndx, unsigned int* symndx_p) const;

  // Return the name of symbol SYMNDX.
  const char*
  get_symbol_name(unsigned int symndx);

  // Compute final local symbol value.  R_SYM is the local symbol index.
  // LV_IN points to a local symbol value containing the input value.
  // LV_OUT points to a local symbol value storing the final output value,
  // which must not be a merged symbol value since before calling this
  // method to avoid memory leak.  SYMTAB points to a symbol table.
  //
  // The method returns a status code at return.  If the return status is
  // CFLV_OK, *LV_OUT contains the final value.  If the return status is
  // CFLV_ERROR, *LV_OUT is 0.  If the return status is CFLV_DISCARDED,
  // *LV_OUT is not modified.
  Compute_final_local_value_status
  compute_final_local_value(unsigned int r_sym,
			    const Symbol_value<size>* lv_in,
			    Symbol_value<size>* lv_out,
			    const Symbol_table* symtab);

  // Return true if the layout for this object was deferred.
  bool is_deferred_layout() const
  { return this->is_deferred_layout_; }

 protected:
  typedef typename Sized_relobj<size, big_endian>::Output_sections
      Output_sections;

  // Set up.
  virtual void
  do_setup();

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

  // Read the symbols.  This is common code for all target-specific
  // overrides of do_read_symbols.
  void
  base_read_symbols(Read_symbols_data*);

  // Return the value of a local symbol.
  uint64_t
  do_local_symbol_value(unsigned int symndx, uint64_t addend) const
  {
    const Symbol_value<size>* symval = this->local_symbol(symndx);
    return symval->value(this, addend);
  }

  // Return the PLT offset for a local symbol.  It is an error to call
  // this if it doesn't have one.
  unsigned int
  do_local_plt_offset(unsigned int symndx) const;

  // Return whether local symbol SYMNDX is a TLS symbol.
  bool
  do_local_is_tls(unsigned int symndx) const
  { return this->local_symbol(symndx)->is_tls_symbol(); }

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

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

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

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

  // Get the size of a section.
  uint64_t
  do_section_size(unsigned int shndx)
  { return this->elf_file_.section_size(shndx); }

  // Get the name of a section.
  std::string
  do_section_name(unsigned int shndx) const
  { return this->elf_file_.section_name(shndx); }

  // Return the location of the contents of a section.
  const unsigned char*
  do_section_contents(unsigned int shndx, section_size_type* plen,
		      bool cache)
  {
    Object::Location loc(this->elf_file_.section_contents(shndx));
    *plen = convert_to_section_size_type(loc.data_size);
    if (*plen == 0)
      {
	static const unsigned char empty[1] = { '\0' };
	return empty;
      }
    return this->get_view(loc.file_offset, *plen, true, 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 this->elf_file_.section_addr(shndx); }

  // Return section type.
  unsigned int
  do_section_type(unsigned int shndx)
  { return this->elf_file_.section_type(shndx); }

  // Return the section link field.
  unsigned int
  do_section_link(unsigned int shndx)
  { return this->elf_file_.section_link(shndx); }

  // Return the section info field.
  unsigned int
  do_section_info(unsigned int shndx)
  { return this->elf_file_.section_info(shndx); }

  // Return the section alignment.
  uint64_t
  do_section_addralign(unsigned int shndx)
  { return this->elf_file_.section_addralign(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 the global symbols.
  const Symbols*
  do_get_global_symbols() const
  { return &this->symbols_; }

  // Adjust a section index if necessary.
  unsigned int
  adjust_shndx(unsigned int shndx)
  {
    if (shndx >= elfcpp::SHN_LORESERVE)
      shndx += this->elf_file_.large_shndx_offset();
    return shndx;
  }

  // Initialize input to output maps for section symbols in merged
  // sections.
  void
  initialize_input_to_output_maps();

  // Free the input to output maps for section symbols in merged
  // sections.
  void
  free_input_to_output_maps();

  // Return symbol table section index.
  unsigned int
  symtab_shndx() const
  { return this->symtab_shndx_; }

  // Allow a child class to access the ELF file.
  elfcpp::Elf_file<size, big_endian, Object>*
  elf_file()
  { return &this->elf_file_; }
  
  // Allow a child class to access the local values.
  Local_values*
  local_values()
  { return &this->local_values_; }

  // Views and sizes when relocating.
  struct View_size
  {
    unsigned char* view;
    typename elfcpp::Elf_types<size>::Elf_Addr address;
    off_t offset;
    section_size_type view_size;
    bool is_input_output_view;
    bool is_postprocessing_view;
    bool is_ctors_reverse_view;
  };

  typedef std::vector<View_size> Views;

  // Stash away info for a number of special sections.
  // Return true if any of the sections found require local symbols to be read.
  virtual bool
  do_find_special_sections(Read_symbols_data* sd);

  // This may be overriden by a child class.
  virtual void
  do_relocate_sections(const Symbol_table* symtab, const Layout* layout,
		       const unsigned char* pshdrs, Output_file* of,
		       Views* pviews);

  // Relocate section data for a range of sections.
  void
  relocate_section_range(const Symbol_table* symtab, const Layout* layout,
			 const unsigned char* pshdrs, Output_file* of,
			 Views* pviews, unsigned int start_shndx,
			 unsigned int end_shndx);

  // Adjust this local symbol value.  Return false if the symbol
  // should be discarded from the output file.
  virtual bool
  do_adjust_local_symbol(Symbol_value<size>*) const
  { return true; }

  // Allow a child to set output local symbol count.
  void
  set_output_local_symbol_count(unsigned int value)
  { this->output_local_symbol_count_ = value; }

  // Return the output view for a section.
  unsigned char*
  do_get_output_view(unsigned int, section_size_type*) const;

 private:
  // For convenience.
  typedef Sized_relobj_file<size, big_endian> This;
  static const int ehdr_size = elfcpp::Elf_sizes<size>::ehdr_size;
  static const int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
  static const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
  typedef elfcpp::Shdr<size, big_endian> Shdr;
  typedef elfcpp::Shdr_write<size, big_endian> Shdr_write;

  // To keep track of discarded comdat sections, we need to map a member
  // section index to the object and section index of the corresponding
  // kept section.
  struct Kept_comdat_section
  {
    Kept_comdat_section(uint64_t a_sh_size, Kept_section* a_kept_section,
			unsigned int a_symndx, bool a_is_comdat)
      : sh_size(a_sh_size), kept_section(a_kept_section),
	symndx (a_symndx), is_comdat(a_is_comdat)
    { }
    uint64_t sh_size;		// Section size
    Kept_section* kept_section;	// Kept section info
    unsigned int symndx;	// Index of key symbol
    bool is_comdat;		// True if comdat group, false if linkonce
  };
  typedef std::map<unsigned int, Kept_comdat_section>
      Kept_comdat_section_table;

  // Find the SHT_SYMTAB section, given the section headers.
  void
  find_symtab(const unsigned char* pshdrs);

  // Return whether SHDR has the right flags for a GNU style exception
  // frame section.
  bool
  check_eh_frame_flags(const elfcpp::Shdr<size, big_endian>* shdr) const;

  // Return whether there is a section named .eh_frame which might be
  // a GNU style exception frame section.
  bool
  find_eh_frame(const unsigned char* pshdrs, const char* names,
		section_size_type names_size) const;

  // Whether to include a section group in the link.
  bool
  include_section_group(Symbol_table*, Layout*, unsigned int, const char*,
			const unsigned char*, const char*, section_size_type,
			std::vector<bool>*);

  // Whether to include a linkonce section in the link.
  bool
  include_linkonce_section(Layout*, unsigned int, const char*,
			   const elfcpp::Shdr<size, big_endian>&);

  // Layout an input section.
  void
  layout_section(Layout* layout, unsigned int shndx, const char* name,
                 const typename This::Shdr& shdr, unsigned int sh_type,
                 unsigned int reloc_shndx, unsigned int reloc_type);

  // Layout an input .eh_frame section.
  void
  layout_eh_frame_section(Layout* layout, const unsigned char* symbols_data,
			  section_size_type symbols_size,
			  const unsigned char* symbol_names_data,
			  section_size_type symbol_names_size,
			  unsigned int shndx, const typename This::Shdr&,
			  unsigned int reloc_shndx, unsigned int reloc_type);

  // Layout an input .note.gnu.property section.
  void
  layout_gnu_property_section(Layout* layout, unsigned int shndx);

  // Write section data to the output file.  Record the views and
  // sizes in VIEWS for use when relocating.
  void
  write_sections(const Layout*, const unsigned char* pshdrs, Output_file*,
		 Views*);

  // Relocate the sections in the output file.
  void
  relocate_sections(const Symbol_table* symtab, const Layout* layout,
		    const unsigned char* pshdrs, Output_file* of,
		    Views* pviews)
  { this->do_relocate_sections(symtab, layout, pshdrs, of, pviews); }

  // Reverse the words in a section.  Used for .ctors sections mapped
  // to .init_array sections.
  void
  reverse_words(unsigned char*, section_size_type);

  // Scan the input relocations for --emit-relocs.
  void
  emit_relocs_scan(Symbol_table*, Layout*, const unsigned char* plocal_syms,
		   const Read_relocs_data::Relocs_list::iterator&);

  // Scan the input relocations for --emit-relocs, templatized on the
  // type of the relocation section.
  template<int sh_type>
  void
  emit_relocs_scan_reltype(Symbol_table*, Layout*,
			   const unsigned char* plocal_syms,
			   const Read_relocs_data::Relocs_list::iterator&,
			   Relocatable_relocs*);

  // Scan the input relocations for --incremental.
  void
  incremental_relocs_scan(const Read_relocs_data::Relocs_list::iterator&);

  // Scan the input relocations for --incremental, templatized on the
  // type of the relocation section.
  template<int sh_type>
  void
  incremental_relocs_scan_reltype(
      const Read_relocs_data::Relocs_list::iterator&);

  void
  incremental_relocs_write(const Relocate_info<size, big_endian>*,
			   unsigned int sh_type,
			   const unsigned char* prelocs,
			   size_t reloc_count,
			   Output_section*,
			   Address output_offset,
			   Output_file*);

  template<int sh_type>
  void
  incremental_relocs_write_reltype(const Relocate_info<size, big_endian>*,
				   const unsigned char* prelocs,
				   size_t reloc_count,
				   Output_section*,
				   Address output_offset,
				   Output_file*);

  // A type shared by split_stack_adjust_reltype and find_functions.
  typedef std::map<section_offset_type, section_size_type> Function_offsets;

  // Check for -fsplit-stack routines calling non-split-stack routines.
  void
  split_stack_adjust(const Symbol_table*, const unsigned char* pshdrs,
		     unsigned int sh_type, unsigned int shndx,
		     const unsigned char* prelocs, size_t reloc_count,
		     unsigned char* view, section_size_type view_size,
		     Reloc_symbol_changes** reloc_map,
		     const Sized_target<size, big_endian>* target);

  template<int sh_type>
  void
  split_stack_adjust_reltype(const Symbol_table*, const unsigned char* pshdrs,
			     unsigned int shndx, const unsigned char* prelocs,
			     size_t reloc_count, unsigned char* view,
			     section_size_type view_size,
			     Reloc_symbol_changes** reloc_map,
			     const Sized_target<size, big_endian>* target);

  // Find all functions in a section.
  void
  find_functions(const unsigned char* pshdrs, unsigned int shndx,
		 Function_offsets*);

  // Write out the local symbols.
  void
  write_local_symbols(Output_file*,
		      const Stringpool_template<char>*,
		      const Stringpool_template<char>*,
		      Output_symtab_xindex*,
		      Output_symtab_xindex*,
		      off_t);

  // Record a mapping from discarded section SHNDX to the corresponding
  // kept section.
  void
  set_kept_comdat_section(unsigned int shndx, bool is_comdat,
			  unsigned int symndx, uint64_t sh_size,
			  Kept_section* kept_section)
  {
    Kept_comdat_section kept(sh_size, kept_section, symndx, is_comdat);
    this->kept_comdat_sections_.insert(std::make_pair(shndx, kept));
  }

  // Find the kept section corresponding to the discarded section
  // SHNDX.  Return true if found.
  bool
  get_kept_comdat_section(unsigned int shndx, bool* is_comdat,
			  unsigned int *symndx, uint64_t* sh_size,
			  Kept_section** kept_section) const
  {
    typename Kept_comdat_section_table::const_iterator p =
      this->kept_comdat_sections_.find(shndx);
    if (p == this->kept_comdat_sections_.end())
      return false;
    *is_comdat = p->second.is_comdat;
    *symndx = p->second.symndx;
    *sh_size = p->second.sh_size;
    *kept_section = p->second.kept_section;
    return true;
  }

  // Compute final local symbol value.  R_SYM is the local symbol index.
  // LV_IN points to a local symbol value containing the input value.
  // LV_OUT points to a local symbol value storing the final output value,
  // which must not be a merged symbol value since before calling this
  // method to avoid memory leak.  RELOCATABLE indicates whether we are
  // linking a relocatable output.  OUT_SECTIONS is an array of output
  // sections.  OUT_OFFSETS is an array of offsets of the sections.  SYMTAB
  // points to a symbol table.
  //
  // The method returns a status code at return.  If the return status is
  // CFLV_OK, *LV_OUT contains the final value.  If the return status is
  // CFLV_ERROR, *LV_OUT is 0.  If the return status is CFLV_DISCARDED,
  // *LV_OUT is not modified.
  inline Compute_final_local_value_status
  compute_final_local_value_internal(unsigned int r_sym,
				     const Symbol_value<size>* lv_in,
				     Symbol_value<size>* lv_out,
				     bool relocatable,
				     const Output_sections& out_sections,
				     const std::vector<Address>& out_offsets,
				     const Symbol_table* symtab);

  // The PLT offsets of local symbols.
  typedef Unordered_map<unsigned int, unsigned int> Local_plt_offsets;

  // Saved information for sections whose layout was deferred.
  struct Deferred_layout
  {
    static const int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
    Deferred_layout(unsigned int shndx, const char* name,
                    unsigned int sh_type,
                    const unsigned char* pshdr,
                    unsigned int reloc_shndx, unsigned int reloc_type)
      : name_(name), shndx_(shndx), reloc_shndx_(reloc_shndx),
        reloc_type_(reloc_type)
    {
      typename This::Shdr_write shdr(this->shdr_data_);
      memcpy(this->shdr_data_, pshdr, shdr_size);
      shdr.put_sh_type(sh_type);
    }
    std::string name_;
    unsigned int shndx_;
    unsigned int reloc_shndx_;
    unsigned int reloc_type_;
    unsigned char shdr_data_[shdr_size];
  };

  // General access to the ELF file.
  elfcpp::Elf_file<size, big_endian, Object> elf_file_;
  // Type of ELF file (ET_REL or ET_EXEC).  ET_EXEC files are allowed
  // as input files only for the --just-symbols option.
  int e_type_;
  // Index of SHT_SYMTAB section.
  unsigned int symtab_shndx_;
  // The number of local symbols.
  unsigned int local_symbol_count_;
  // The number of local symbols which go into the output file.
  unsigned int output_local_symbol_count_;
  // The number of local symbols which go into the output file's dynamic
  // symbol table.
  unsigned int output_local_dynsym_count_;
  // The entries in the symbol table for the external symbols.
  Symbols symbols_;
  // Number of symbols defined in object file itself.
  size_t defined_count_;
  // File offset for local symbols (relative to start of symbol table).
  off_t local_symbol_offset_;
  // File offset for local dynamic symbols (absolute).
  off_t local_dynsym_offset_;
  // Values of local symbols.
  Local_values local_values_;
  // PLT offsets for local symbols.
  Local_plt_offsets local_plt_offsets_;
  // Table mapping discarded comdat sections to corresponding kept sections.
  Kept_comdat_section_table kept_comdat_sections_;
  // Whether this object has a GNU style .eh_frame section.
  bool has_eh_frame_;
  // True if the layout of this object was deferred, waiting for plugin
  // replacement files.
  bool is_deferred_layout_;
  // The list of sections whose layout was deferred.
  std::vector<Deferred_layout> deferred_layout_;
  // The list of relocation sections whose layout was deferred.
  std::vector<Deferred_layout> deferred_layout_relocs_;
  // Pointer to the list of output views; valid only during do_relocate().
  const Views* output_views_;
};

// A class to manage the list of all objects.

class Input_objects
{
 public:
  Input_objects()
    : relobj_list_(), dynobj_list_(), sonames_(), cref_(NULL)
  { }

  // The type of the list of input relocateable objects.
  typedef std::vector<Relobj*> Relobj_list;
  typedef Relobj_list::const_iterator Relobj_iterator;

  // The type of the list of input dynamic objects.
  typedef std::vector<Dynobj*> Dynobj_list;
  typedef Dynobj_list::const_iterator Dynobj_iterator;

  // Add an object to the list.  Return true if all is well, or false
  // if this object should be ignored.
  bool
  add_object(Object*);

  // Start processing an archive.
  void
  archive_start(Archive*);

  // Stop processing an archive.
  void
  archive_stop(Archive*);

  // For each dynamic object, check whether we've seen all of its
  // explicit dependencies.
  void
  check_dynamic_dependencies() const;

  // Return whether an object was found in the system library
  // directory.
  bool
  found_in_system_library_directory(const Object*) const;

  // Print symbol counts.
  void
  print_symbol_counts(const Symbol_table*) const;

  // Print a cross reference table.
  void
  print_cref(const Symbol_table*, FILE*) const;

  // Iterate over all regular objects.

  Relobj_iterator
  relobj_begin() const
  { return this->relobj_list_.begin(); }

  Relobj_iterator
  relobj_end() const
  { return this->relobj_list_.end(); }

  // Iterate over all dynamic objects.

  Dynobj_iterator
  dynobj_begin() const
  { return this->dynobj_list_.begin(); }

  Dynobj_iterator
  dynobj_end() const
  { return this->dynobj_list_.end(); }

  // Return whether we have seen any dynamic objects.
  bool
  any_dynamic() const
  { return !this->dynobj_list_.empty(); }

  // Return the number of non dynamic objects.
  int
  number_of_relobjs() const
  { return this->relobj_list_.size(); }

  // Return the number of input objects.
  int
  number_of_input_objects() const
  { return this->relobj_list_.size() + this->dynobj_list_.size(); }

 private:
  Input_objects(const Input_objects&);
  Input_objects& operator=(const Input_objects&);

  // The list of ordinary objects included in the link.
  Relobj_list relobj_list_;
  // The list of dynamic objects included in the link.
  Dynobj_list dynobj_list_;
  // SONAMEs that we have seen.
  Unordered_map<std::string, Object*> sonames_;
  // Manage cross-references if requested.
  Cref* cref_;
};

// Some of the information we pass to the relocation routines.  We
// group this together to avoid passing a dozen different arguments.

template<int size, bool big_endian>
struct Relocate_info
{
  // Symbol table.
  const Symbol_table* symtab;
  // Layout.
  const Layout* layout;
  // Object being relocated.
  Sized_relobj_file<size, big_endian>* object;
  // Section index of relocation section.
  unsigned int reloc_shndx;
  // Section header of relocation section.
  const unsigned char* reloc_shdr;
  // Info about how relocs should be handled
  Relocatable_relocs* rr;
  // Section index of section being relocated.
  unsigned int data_shndx;
  // Section header of data section.
  const unsigned char* data_shdr;

  // Return a string showing the location of a relocation.  This is
  // only used for error messages.
  std::string
  location(size_t relnum, off_t reloffset) const;
};

// This is used to represent a section in an object and is used as the
// key type for various section maps.
typedef std::pair<Relobj*, unsigned int> Section_id;

// This is similar to Section_id but is used when the section
// pointers are const.
typedef std::pair<const Relobj*, unsigned int> Const_section_id;

// The hash value is based on the address of an object in memory during
// linking.  It is okay to use this for looking up sections but never use
// this in an unordered container that we want to traverse in a repeatable
// manner.

struct Section_id_hash
{
  size_t operator()(const Section_id& loc) const
  { return reinterpret_cast<uintptr_t>(loc.first) ^ loc.second; }
};

struct Const_section_id_hash
{
  size_t operator()(const Const_section_id& loc) const
  { return reinterpret_cast<uintptr_t>(loc.first) ^ loc.second; }
};

// Return whether INPUT_FILE contains an ELF object start at file
// offset OFFSET.  This sets *START to point to a view of the start of
// the file.  It sets *READ_SIZE to the number of bytes in the view.

extern bool
is_elf_object(Input_file* input_file, off_t offset,
	      const unsigned char** start, int* read_size);

// Return an Object appropriate for the input file.  P is BYTES long,
// and holds the ELF header.  If PUNCONFIGURED is not NULL, then if
// this sees an object the linker is not configured to support, it
// sets *PUNCONFIGURED to true and returns NULL without giving an
// error message.

extern Object*
make_elf_object(const std::string& name, Input_file*,
		off_t offset, const unsigned char* p,
		section_offset_type bytes, bool* punconfigured);

} // end namespace gold

#endif // !defined(GOLD_OBJECT_H)
