// object.cc -- support for an object file for linking in gold

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

#include "gold.h"

#include <cerrno>
#include <cstring>
#include <cstdarg>
#include "demangle.h"
#include "libiberty.h"

#include "gc.h"
#include "target-select.h"
#include "dwarf_reader.h"
#include "layout.h"
#include "output.h"
#include "symtab.h"
#include "cref.h"
#include "reloc.h"
#include "object.h"
#include "dynobj.h"
#include "plugin.h"
#include "compressed_output.h"
#include "incremental.h"
#include "merge.h"

namespace gold
{

// Struct Read_symbols_data.

// Destroy any remaining File_view objects and buffers of decompressed
// sections.

Read_symbols_data::~Read_symbols_data()
{
  if (this->section_headers != NULL)
    delete this->section_headers;
  if (this->section_names != NULL)
    delete this->section_names;
  if (this->symbols != NULL)
    delete this->symbols;
  if (this->symbol_names != NULL)
    delete this->symbol_names;
  if (this->versym != NULL)
    delete this->versym;
  if (this->verdef != NULL)
    delete this->verdef;
  if (this->verneed != NULL)
    delete this->verneed;
}

// Class Xindex.

// Initialize the symtab_xindex_ array.  Find the SHT_SYMTAB_SHNDX
// section and read it in.  SYMTAB_SHNDX is the index of the symbol
// table we care about.

template<int size, bool big_endian>
void
Xindex::initialize_symtab_xindex(Object* object, unsigned int symtab_shndx)
{
  if (!this->symtab_xindex_.empty())
    return;

  gold_assert(symtab_shndx != 0);

  // Look through the sections in reverse order, on the theory that it
  // is more likely to be near the end than the beginning.
  unsigned int i = object->shnum();
  while (i > 0)
    {
      --i;
      if (object->section_type(i) == elfcpp::SHT_SYMTAB_SHNDX
	  && this->adjust_shndx(object->section_link(i)) == symtab_shndx)
	{
	  this->read_symtab_xindex<size, big_endian>(object, i, NULL);
	  return;
	}
    }

  object->error(_("missing SHT_SYMTAB_SHNDX section"));
}

// Read in the symtab_xindex_ array, given the section index of the
// SHT_SYMTAB_SHNDX section.  If PSHDRS is not NULL, it points at the
// section headers.

template<int size, bool big_endian>
void
Xindex::read_symtab_xindex(Object* object, unsigned int xindex_shndx,
			   const unsigned char* pshdrs)
{
  section_size_type bytecount;
  const unsigned char* contents;
  if (pshdrs == NULL)
    contents = object->section_contents(xindex_shndx, &bytecount, false);
  else
    {
      const unsigned char* p = (pshdrs
				+ (xindex_shndx
				   * elfcpp::Elf_sizes<size>::shdr_size));
      typename elfcpp::Shdr<size, big_endian> shdr(p);
      bytecount = convert_to_section_size_type(shdr.get_sh_size());
      contents = object->get_view(shdr.get_sh_offset(), bytecount, true, false);
    }

  gold_assert(this->symtab_xindex_.empty());
  this->symtab_xindex_.reserve(bytecount / 4);
  for (section_size_type i = 0; i < bytecount; i += 4)
    {
      unsigned int shndx = elfcpp::Swap<32, big_endian>::readval(contents + i);
      // We preadjust the section indexes we save.
      this->symtab_xindex_.push_back(this->adjust_shndx(shndx));
    }
}

// Symbol symndx has a section of SHN_XINDEX; return the real section
// index.

unsigned int
Xindex::sym_xindex_to_shndx(Object* object, unsigned int symndx)
{
  if (symndx >= this->symtab_xindex_.size())
    {
      object->error(_("symbol %u out of range for SHT_SYMTAB_SHNDX section"),
		    symndx);
      return elfcpp::SHN_UNDEF;
    }
  unsigned int shndx = this->symtab_xindex_[symndx];
  if (shndx < elfcpp::SHN_LORESERVE || shndx >= object->shnum())
    {
      object->error(_("extended index for symbol %u out of range: %u"),
		    symndx, shndx);
      return elfcpp::SHN_UNDEF;
    }
  return shndx;
}

// Class Object.

// Report an error for this object file.  This is used by the
// elfcpp::Elf_file interface, and also called by the Object code
// itself.

void
Object::error(const char* format, ...) const
{
  va_list args;
  va_start(args, format);
  char* buf = NULL;
  if (vasprintf(&buf, format, args) < 0)
    gold_nomem();
  va_end(args);
  gold_error(_("%s: %s"), this->name().c_str(), buf);
  free(buf);
}

// Return a view of the contents of a section.

const unsigned char*
Object::section_contents(unsigned int shndx, section_size_type* plen,
			 bool cache)
{ return this->do_section_contents(shndx, plen, cache); }

// Read the section data into SD.  This is code common to Sized_relobj_file
// and Sized_dynobj, so we put it into Object.

template<int size, bool big_endian>
void
Object::read_section_data(elfcpp::Elf_file<size, big_endian, Object>* elf_file,
			  Read_symbols_data* sd)
{
  const int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;

  // Read the section headers.
  const off_t shoff = elf_file->shoff();
  const unsigned int shnum = this->shnum();
  sd->section_headers = this->get_lasting_view(shoff, shnum * shdr_size,
					       true, true);

  // Read the section names.
  const unsigned char* pshdrs = sd->section_headers->data();
  const unsigned char* pshdrnames = pshdrs + elf_file->shstrndx() * shdr_size;
  typename elfcpp::Shdr<size, big_endian> shdrnames(pshdrnames);

  if (shdrnames.get_sh_type() != elfcpp::SHT_STRTAB)
    this->error(_("section name section has wrong type: %u"),
		static_cast<unsigned int>(shdrnames.get_sh_type()));

  sd->section_names_size =
    convert_to_section_size_type(shdrnames.get_sh_size());
  sd->section_names = this->get_lasting_view(shdrnames.get_sh_offset(),
					     sd->section_names_size, false,
					     false);
}

// 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
Object::handle_gnu_warning_section(const char* name, unsigned int shndx,
				   Symbol_table* symtab)
{
  const char warn_prefix[] = ".gnu.warning.";
  const int warn_prefix_len = sizeof warn_prefix - 1;
  if (strncmp(name, warn_prefix, warn_prefix_len) == 0)
    {
      // Read the section contents to get the warning text.  It would
      // be nicer if we only did this if we have to actually issue a
      // warning.  Unfortunately, warnings are issued as we relocate
      // sections.  That means that we can not lock the object then,
      // as we might try to issue the same warning multiple times
      // simultaneously.
      section_size_type len;
      const unsigned char* contents = this->section_contents(shndx, &len,
							     false);
      if (len == 0)
	{
	  const char* warning = name + warn_prefix_len;
	  contents = reinterpret_cast<const unsigned char*>(warning);
	  len = strlen(warning);
	}
      std::string warning(reinterpret_cast<const char*>(contents), len);
      symtab->add_warning(name + warn_prefix_len, this, warning);
      return true;
    }
  return false;
}

// If NAME is the name of the special section which indicates that
// this object was compiled with -fsplit-stack, mark it accordingly.

bool
Object::handle_split_stack_section(const char* name)
{
  if (strcmp(name, ".note.GNU-split-stack") == 0)
    {
      this->uses_split_stack_ = true;
      return true;
    }
  if (strcmp(name, ".note.GNU-no-split-stack") == 0)
    {
      this->has_no_split_stack_ = true;
      return true;
    }
  return false;
}

// Class Relobj

template<int size>
void
Relobj::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_addresses) const {
  Object_merge_map *map = this->object_merge_map_;
  map->initialize_input_to_output_map<size>(shndx, starting_address,
					    output_addresses);
}

void
Relobj::add_merge_mapping(Output_section_data *output_data,
                          unsigned int shndx, section_offset_type offset,
                          section_size_type length,
                          section_offset_type output_offset) {
  Object_merge_map* object_merge_map = this->get_or_create_merge_map();
  object_merge_map->add_mapping(output_data, shndx, offset, length, output_offset);
}

bool
Relobj::merge_output_offset(unsigned int shndx, section_offset_type offset,
                            section_offset_type *poutput) const {
  Object_merge_map* object_merge_map = this->object_merge_map_;
  if (object_merge_map == NULL)
    return false;
  return object_merge_map->get_output_offset(shndx, offset, poutput);
}

const Output_section_data*
Relobj::find_merge_section(unsigned int shndx) const {
  Object_merge_map* object_merge_map = this->object_merge_map_;
  if (object_merge_map == NULL)
    return NULL;
  return object_merge_map->find_merge_section(shndx);
}

// To copy the symbols data read from the file to a local data structure.
// This function is called from do_layout only while doing garbage
// collection.

void
Relobj::copy_symbols_data(Symbols_data* gc_sd, Read_symbols_data* sd,
			  unsigned int section_header_size)
{
  gc_sd->section_headers_data =
	 new unsigned char[(section_header_size)];
  memcpy(gc_sd->section_headers_data, sd->section_headers->data(),
	 section_header_size);
  gc_sd->section_names_data =
	 new unsigned char[sd->section_names_size];
  memcpy(gc_sd->section_names_data, sd->section_names->data(),
	 sd->section_names_size);
  gc_sd->section_names_size = sd->section_names_size;
  if (sd->symbols != NULL)
    {
      gc_sd->symbols_data =
	     new unsigned char[sd->symbols_size];
      memcpy(gc_sd->symbols_data, sd->symbols->data(),
	    sd->symbols_size);
    }
  else
    {
      gc_sd->symbols_data = NULL;
    }
  gc_sd->symbols_size = sd->symbols_size;
  gc_sd->external_symbols_offset = sd->external_symbols_offset;
  if (sd->symbol_names != NULL)
    {
      gc_sd->symbol_names_data =
	     new unsigned char[sd->symbol_names_size];
      memcpy(gc_sd->symbol_names_data, sd->symbol_names->data(),
	    sd->symbol_names_size);
    }
  else
    {
      gc_sd->symbol_names_data = NULL;
    }
  gc_sd->symbol_names_size = sd->symbol_names_size;
}

// This function determines if a particular section name must be included
// in the link.  This is used during garbage collection to determine the
// roots of the worklist.

bool
Relobj::is_section_name_included(const char* name)
{
  if (is_prefix_of(".ctors", name)
      || is_prefix_of(".dtors", name)
      || is_prefix_of(".note", name)
      || is_prefix_of(".init", name)
      || is_prefix_of(".fini", name)
      || is_prefix_of(".gcc_except_table", name)
      || is_prefix_of(".jcr", name)
      || is_prefix_of(".preinit_array", name)
      || (is_prefix_of(".text", name)
	  && strstr(name, "personality"))
      || (is_prefix_of(".data", name)
	  && strstr(name, "personality"))
      || (is_prefix_of(".sdata", name)
	  && strstr(name, "personality"))
      || (is_prefix_of(".gnu.linkonce.d", name)
	  && strstr(name, "personality"))
      || (is_prefix_of(".rodata", name)
	  && strstr(name, "nptl_version")))
    {
      return true;
    }
  return false;
}

// Finalize the incremental relocation information.  Allocates a block
// of relocation entries for each symbol, and sets the reloc_bases_
// array to point to the first entry in each block.  If CLEAR_COUNTS
// is TRUE, also clear the per-symbol relocation counters.

void
Relobj::finalize_incremental_relocs(Layout* layout, bool clear_counts)
{
  unsigned int nsyms = this->get_global_symbols()->size();
  this->reloc_bases_ = new unsigned int[nsyms];

  gold_assert(this->reloc_bases_ != NULL);
  gold_assert(layout->incremental_inputs() != NULL);

  unsigned int rindex = layout->incremental_inputs()->get_reloc_count();
  for (unsigned int i = 0; i < nsyms; ++i)
    {
      this->reloc_bases_[i] = rindex;
      rindex += this->reloc_counts_[i];
      if (clear_counts)
	this->reloc_counts_[i] = 0;
    }
  layout->incremental_inputs()->set_reloc_count(rindex);
}

Object_merge_map*
Relobj::get_or_create_merge_map()
{
  if (!this->object_merge_map_)
    this->object_merge_map_ = new Object_merge_map();
  return this->object_merge_map_;
}

// Class Sized_relobj.

// Iterate over local symbols, calling a visitor class V for each GOT offset
// associated with a local symbol.

template<int size, bool big_endian>
void
Sized_relobj<size, big_endian>::do_for_all_local_got_entries(
    Got_offset_list::Visitor* v) const
{
  unsigned int nsyms = this->local_symbol_count();
  for (unsigned int i = 0; i < nsyms; i++)
    {
      Local_got_entry_key key(i, 0);
      Local_got_offsets::const_iterator p = this->local_got_offsets_.find(key);
      if (p != this->local_got_offsets_.end())
	{
	  const Got_offset_list* got_offsets = p->second;
	  got_offsets->for_all_got_offsets(v);
	}
    }
}

// Get the address of an output section.

template<int size, bool big_endian>
uint64_t
Sized_relobj<size, big_endian>::do_output_section_address(
    unsigned int shndx)
{
  // If the input file is linked as --just-symbols, the output
  // section address is the input section address.
  if (this->just_symbols())
    return this->section_address(shndx);

  const Output_section* os = this->do_output_section(shndx);
  gold_assert(os != NULL);
  return os->address();
}

// Class Sized_relobj_file.

template<int size, bool big_endian>
Sized_relobj_file<size, big_endian>::Sized_relobj_file(
    const std::string& name,
    Input_file* input_file,
    off_t offset,
    const elfcpp::Ehdr<size, big_endian>& ehdr)
  : Sized_relobj<size, big_endian>(name, input_file, offset),
    elf_file_(this, ehdr),
    symtab_shndx_(-1U),
    local_symbol_count_(0),
    output_local_symbol_count_(0),
    output_local_dynsym_count_(0),
    symbols_(),
    defined_count_(0),
    local_symbol_offset_(0),
    local_dynsym_offset_(0),
    local_values_(),
    local_plt_offsets_(),
    kept_comdat_sections_(),
    has_eh_frame_(false),
    is_deferred_layout_(false),
    deferred_layout_(),
    deferred_layout_relocs_(),
    output_views_(NULL)
{
  this->e_type_ = ehdr.get_e_type();
}

template<int size, bool big_endian>
Sized_relobj_file<size, big_endian>::~Sized_relobj_file()
{
}

// Set up an object file based on the file header.  This sets up the
// section information.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::do_setup()
{
  const unsigned int shnum = this->elf_file_.shnum();
  this->set_shnum(shnum);
}

// Find the SHT_SYMTAB section, given the section headers.  The ELF
// standard says that maybe in the future there can be more than one
// SHT_SYMTAB section.  Until somebody figures out how that could
// work, we assume there is only one.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::find_symtab(const unsigned char* pshdrs)
{
  const unsigned int shnum = this->shnum();
  this->symtab_shndx_ = 0;
  if (shnum > 0)
    {
      // Look through the sections in reverse order, since gas tends
      // to put the symbol table at the end.
      const unsigned char* p = pshdrs + shnum * This::shdr_size;
      unsigned int i = shnum;
      unsigned int xindex_shndx = 0;
      unsigned int xindex_link = 0;
      while (i > 0)
	{
	  --i;
	  p -= This::shdr_size;
	  typename This::Shdr shdr(p);
	  if (shdr.get_sh_type() == elfcpp::SHT_SYMTAB)
	    {
	      this->symtab_shndx_ = i;
	      if (xindex_shndx > 0 && xindex_link == i)
		{
		  Xindex* xindex =
		    new Xindex(this->elf_file_.large_shndx_offset());
		  xindex->read_symtab_xindex<size, big_endian>(this,
							       xindex_shndx,
							       pshdrs);
		  this->set_xindex(xindex);
		}
	      break;
	    }

	  // Try to pick up the SHT_SYMTAB_SHNDX section, if there is
	  // one.  This will work if it follows the SHT_SYMTAB
	  // section.
	  if (shdr.get_sh_type() == elfcpp::SHT_SYMTAB_SHNDX)
	    {
	      xindex_shndx = i;
	      xindex_link = this->adjust_shndx(shdr.get_sh_link());
	    }
	}
    }
}

// Return the Xindex structure to use for object with lots of
// sections.

template<int size, bool big_endian>
Xindex*
Sized_relobj_file<size, big_endian>::do_initialize_xindex()
{
  gold_assert(this->symtab_shndx_ != -1U);
  Xindex* xindex = new Xindex(this->elf_file_.large_shndx_offset());
  xindex->initialize_symtab_xindex<size, big_endian>(this, this->symtab_shndx_);
  return xindex;
}

// Return whether SHDR has the right type and flags to be a GNU
// .eh_frame section.

template<int size, bool big_endian>
bool
Sized_relobj_file<size, big_endian>::check_eh_frame_flags(
    const elfcpp::Shdr<size, big_endian>* shdr) const
{
  elfcpp::Elf_Word sh_type = shdr->get_sh_type();
  return ((sh_type == elfcpp::SHT_PROGBITS
	   || sh_type == parameters->target().unwind_section_type())
	  && (shdr->get_sh_flags() & elfcpp::SHF_ALLOC) != 0);
}

// Find the section header with the given name.

template<int size, bool big_endian>
const unsigned char*
Object::find_shdr(
    const unsigned char* pshdrs,
    const char* name,
    const char* names,
    section_size_type names_size,
    const unsigned char* hdr) const
{
  const int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
  const unsigned int shnum = this->shnum();
  const unsigned char* hdr_end = pshdrs + shdr_size * shnum;
  size_t sh_name = 0;

  while (1)
    {
      if (hdr)
	{
	  // We found HDR last time we were called, continue looking.
	  typename elfcpp::Shdr<size, big_endian> shdr(hdr);
	  sh_name = shdr.get_sh_name();
	}
      else
	{
	  // Look for the next occurrence of NAME in NAMES.
	  // The fact that .shstrtab produced by current GNU tools is
	  // string merged means we shouldn't have both .not.foo and
	  // .foo in .shstrtab, and multiple .foo sections should all
	  // have the same sh_name.  However, this is not guaranteed
	  // by the ELF spec and not all ELF object file producers may
	  // be so clever.
	  size_t len = strlen(name) + 1;
	  const char *p = sh_name ? names + sh_name + len : names;
	  p = reinterpret_cast<const char*>(memmem(p, names_size - (p - names),
						   name, len));
	  if (p == NULL)
	    return NULL;
	  sh_name = p - names;
	  hdr = pshdrs;
	  if (sh_name == 0)
	    return hdr;
	}

      hdr += shdr_size;
      while (hdr < hdr_end)
	{
	  typename elfcpp::Shdr<size, big_endian> shdr(hdr);
	  if (shdr.get_sh_name() == sh_name)
	    return hdr;
	  hdr += shdr_size;
	}
      hdr = NULL;
      if (sh_name == 0)
	return hdr;
    }
}

// Return whether there is a GNU .eh_frame section, given the section
// headers and the section names.

template<int size, bool big_endian>
bool
Sized_relobj_file<size, big_endian>::find_eh_frame(
    const unsigned char* pshdrs,
    const char* names,
    section_size_type names_size) const
{
  const unsigned char* s = NULL;

  while (1)
    {
      s = this->template find_shdr<size, big_endian>(pshdrs, ".eh_frame",
						     names, names_size, s);
      if (s == NULL)
	return false;

      typename This::Shdr shdr(s);
      if (this->check_eh_frame_flags(&shdr))
	return true;
    }
}

// Return TRUE if this is a section whose contents will be needed in the
// Add_symbols task.  This function is only called for sections that have
// already passed the test in is_compressed_debug_section() and the debug
// section name prefix, ".debug"/".zdebug", has been skipped.

static bool
need_decompressed_section(const char* name)
{
  if (*name++ != '_')
    return false;

#ifdef ENABLE_THREADS
  // Decompressing these sections now will help only if we're
  // multithreaded.
  if (parameters->options().threads())
    {
      // We will need .zdebug_str if this is not an incremental link
      // (i.e., we are processing string merge sections) or if we need
      // to build a gdb index.
      if ((!parameters->incremental() || parameters->options().gdb_index())
	  && strcmp(name, "str") == 0)
	return true;

      // We will need these other sections when building a gdb index.
      if (parameters->options().gdb_index()
	  && (strcmp(name, "info") == 0
	      || strcmp(name, "types") == 0
	      || strcmp(name, "pubnames") == 0
	      || strcmp(name, "pubtypes") == 0
	      || strcmp(name, "ranges") == 0
	      || strcmp(name, "abbrev") == 0))
	return true;
    }
#endif

  // Even when single-threaded, we will need .zdebug_str if this is
  // not an incremental link and we are building a gdb index.
  // Otherwise, we would decompress the section twice: once for
  // string merge processing, and once for building the gdb index.
  if (!parameters->incremental()
      && parameters->options().gdb_index()
      && strcmp(name, "str") == 0)
    return true;

  return false;
}

// Build a table for any compressed debug sections, mapping each section index
// to the uncompressed size and (if needed) the decompressed contents.

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)
{
  Compressed_section_map* uncompressed_map = new Compressed_section_map();
  const unsigned int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
  const unsigned char* p = pshdrs + shdr_size;

  for (unsigned int i = 1; i < shnum; ++i, p += shdr_size)
    {
      typename elfcpp::Shdr<size, big_endian> shdr(p);
      if (shdr.get_sh_type() == elfcpp::SHT_PROGBITS
	  && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
	{
	  if (shdr.get_sh_name() >= names_size)
	    {
	      obj->error(_("bad section name offset for section %u: %lu"),
			 i, static_cast<unsigned long>(shdr.get_sh_name()));
	      continue;
	    }

	  const char* name = names + shdr.get_sh_name();
	  bool is_compressed = ((shdr.get_sh_flags()
				 & elfcpp::SHF_COMPRESSED) != 0);
	  bool is_zcompressed = (!is_compressed
				 && is_compressed_debug_section(name));

	  if (is_zcompressed || is_compressed)
	    {
	      section_size_type len;
	      const unsigned char* contents =
		  obj->section_contents(i, &len, false);
	      uint64_t uncompressed_size;
	      if (is_zcompressed)
		{
		  // Skip over the ".zdebug" prefix.
		  name += 7;
		  uncompressed_size = get_uncompressed_size(contents, len);
		}
	      else
		{
		  // Skip over the ".debug" prefix.
		  name += 6;
		  elfcpp::Chdr<size, big_endian> chdr(contents);
		  uncompressed_size = chdr.get_ch_size();
		}
	      Compressed_section_info info;
	      info.size = convert_to_section_size_type(uncompressed_size);
	      info.flag = shdr.get_sh_flags();
	      info.contents = NULL;
	      if (uncompressed_size != -1ULL)
		{
		  unsigned char* uncompressed_data = NULL;
		  if (decompress_if_needed && need_decompressed_section(name))
		    {
		      uncompressed_data = new unsigned char[uncompressed_size];
		      if (decompress_input_section(contents, len,
						   uncompressed_data,
						   uncompressed_size,
						   size, big_endian,
						   shdr.get_sh_flags()))
			info.contents = uncompressed_data;
		      else
			delete[] uncompressed_data;
		    }
		  (*uncompressed_map)[i] = info;
		}
	    }
	}
    }
  return uncompressed_map;
}

// Stash away info for a number of special sections.
// Return true if any of the sections found require local symbols to be read.

template<int size, bool big_endian>
bool
Sized_relobj_file<size, big_endian>::do_find_special_sections(
    Read_symbols_data* sd)
{
  const unsigned char* const pshdrs = sd->section_headers->data();
  const unsigned char* namesu = sd->section_names->data();
  const char* names = reinterpret_cast<const char*>(namesu);

  if (this->find_eh_frame(pshdrs, names, sd->section_names_size))
    this->has_eh_frame_ = true;

  Compressed_section_map* compressed_sections =
    build_compressed_section_map<size, big_endian>(
      pshdrs, this->shnum(), names, sd->section_names_size, this, true);
  if (compressed_sections != NULL)
    this->set_compressed_sections(compressed_sections);

  return (this->has_eh_frame_
	  || (!parameters->options().relocatable()
	      && parameters->options().gdb_index()
	      && (memmem(names, sd->section_names_size, "debug_info", 11) != NULL
		  || memmem(names, sd->section_names_size,
			    "debug_types", 12) != NULL)));
}

// Read the sections and symbols from an object file.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
{
  this->base_read_symbols(sd);
}

// Read the sections and symbols from an object file.  This is common
// code for all target-specific overrides of do_read_symbols().

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::base_read_symbols(Read_symbols_data* sd)
{
  this->read_section_data(&this->elf_file_, sd);

  const unsigned char* const pshdrs = sd->section_headers->data();

  this->find_symtab(pshdrs);

  bool need_local_symbols = this->do_find_special_sections(sd);

  sd->symbols = NULL;
  sd->symbols_size = 0;
  sd->external_symbols_offset = 0;
  sd->symbol_names = NULL;
  sd->symbol_names_size = 0;

  if (this->symtab_shndx_ == 0)
    {
      // No symbol table.  Weird but legal.
      return;
    }

  // Get the symbol table section header.
  typename This::Shdr symtabshdr(pshdrs
				 + this->symtab_shndx_ * This::shdr_size);
  gold_assert(symtabshdr.get_sh_type() == elfcpp::SHT_SYMTAB);

  // If this object has a .eh_frame section, or if building a .gdb_index
  // section and there is debug info, we need all the symbols.
  // Otherwise we only need the external symbols.  While it would be
  // simpler to just always read all the symbols, I've seen object
  // files with well over 2000 local symbols, which for a 64-bit
  // object file format is over 5 pages that we don't need to read
  // now.

  const int sym_size = This::sym_size;
  const unsigned int loccount = symtabshdr.get_sh_info();
  this->local_symbol_count_ = loccount;
  this->local_values_.resize(loccount);
  section_offset_type locsize = loccount * sym_size;
  off_t dataoff = symtabshdr.get_sh_offset();
  section_size_type datasize =
    convert_to_section_size_type(symtabshdr.get_sh_size());
  off_t extoff = dataoff + locsize;
  section_size_type extsize = datasize - locsize;

  off_t readoff = need_local_symbols ? dataoff : extoff;
  section_size_type readsize = need_local_symbols ? datasize : extsize;

  if (readsize == 0)
    {
      // No external symbols.  Also weird but also legal.
      return;
    }

  File_view* fvsymtab = this->get_lasting_view(readoff, readsize, true, false);

  // Read the section header for the symbol names.
  unsigned int strtab_shndx = this->adjust_shndx(symtabshdr.get_sh_link());
  if (strtab_shndx >= this->shnum())
    {
      this->error(_("invalid symbol table name index: %u"), strtab_shndx);
      return;
    }
  typename This::Shdr strtabshdr(pshdrs + strtab_shndx * This::shdr_size);
  if (strtabshdr.get_sh_type() != elfcpp::SHT_STRTAB)
    {
      this->error(_("symbol table name section has wrong type: %u"),
		  static_cast<unsigned int>(strtabshdr.get_sh_type()));
      return;
    }

  // Read the symbol names.
  File_view* fvstrtab = this->get_lasting_view(strtabshdr.get_sh_offset(),
					       strtabshdr.get_sh_size(),
					       false, true);

  sd->symbols = fvsymtab;
  sd->symbols_size = readsize;
  sd->external_symbols_offset = need_local_symbols ? locsize : 0;
  sd->symbol_names = fvstrtab;
  sd->symbol_names_size =
    convert_to_section_size_type(strtabshdr.get_sh_size());
}

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

template<int size, bool big_endian>
unsigned int
Sized_relobj_file<size, big_endian>::symbol_section_and_value(unsigned int sym,
							      Address* value,
							      bool* is_ordinary)
{
  section_size_type symbols_size;
  const unsigned char* symbols = this->section_contents(this->symtab_shndx_,
							&symbols_size,
							false);

  const size_t count = symbols_size / This::sym_size;
  gold_assert(sym < count);

  elfcpp::Sym<size, big_endian> elfsym(symbols + sym * This::sym_size);
  *value = elfsym.get_st_value();

  return this->adjust_sym_shndx(sym, elfsym.get_st_shndx(), is_ordinary);
}

// Return whether to include a section group in the link.  LAYOUT is
// used to keep track of which section groups we have already seen.
// INDEX is the index of the section group and SHDR is the section
// header.  If we do not want to include this group, we set bits in
// OMIT for each section which should be discarded.

template<int size, bool big_endian>
bool
Sized_relobj_file<size, big_endian>::include_section_group(
    Symbol_table* symtab,
    Layout* layout,
    unsigned int index,
    const char* name,
    const unsigned char* shdrs,
    const char* section_names,
    section_size_type section_names_size,
    std::vector<bool>* omit)
{
  // Read the section contents.
  typename This::Shdr shdr(shdrs + index * This::shdr_size);
  const unsigned char* pcon = this->get_view(shdr.get_sh_offset(),
					     shdr.get_sh_size(), true, false);
  const elfcpp::Elf_Word* pword =
    reinterpret_cast<const elfcpp::Elf_Word*>(pcon);

  // The first word contains flags.  We only care about COMDAT section
  // groups.  Other section groups are always included in the link
  // just like ordinary sections.
  elfcpp::Elf_Word flags = elfcpp::Swap<32, big_endian>::readval(pword);

  // Look up the group signature, which is the name of a symbol.  ELF
  // uses a symbol name because some group signatures are long, and
  // the name is generally already in the symbol table, so it makes
  // sense to put the long string just once in .strtab rather than in
  // both .strtab and .shstrtab.

  // Get the appropriate symbol table header (this will normally be
  // the single SHT_SYMTAB section, but in principle it need not be).
  const unsigned int link = this->adjust_shndx(shdr.get_sh_link());
  typename This::Shdr symshdr(this, this->elf_file_.section_header(link));

  // Read the symbol table entry.
  unsigned int symndx = shdr.get_sh_info();
  if (symndx >= symshdr.get_sh_size() / This::sym_size)
    {
      this->error(_("section group %u info %u out of range"),
		  index, symndx);
      return false;
    }
  off_t symoff = symshdr.get_sh_offset() + symndx * This::sym_size;
  const unsigned char* psym = this->get_view(symoff, This::sym_size, true,
					     false);
  elfcpp::Sym<size, big_endian> sym(psym);

  // Read the symbol table names.
  section_size_type symnamelen;
  const unsigned char* psymnamesu;
  psymnamesu = this->section_contents(this->adjust_shndx(symshdr.get_sh_link()),
				      &symnamelen, true);
  const char* psymnames = reinterpret_cast<const char*>(psymnamesu);

  // Get the section group signature.
  if (sym.get_st_name() >= symnamelen)
    {
      this->error(_("symbol %u name offset %u out of range"),
		  symndx, sym.get_st_name());
      return false;
    }

  std::string signature(psymnames + sym.get_st_name());

  // It seems that some versions of gas will create a section group
  // associated with a section symbol, and then fail to give a name to
  // the section symbol.  In such a case, use the name of the section.
  if (signature[0] == '\0' && sym.get_st_type() == elfcpp::STT_SECTION)
    {
      bool is_ordinary;
      unsigned int sym_shndx = this->adjust_sym_shndx(symndx,
						      sym.get_st_shndx(),
						      &is_ordinary);
      if (!is_ordinary || sym_shndx >= this->shnum())
	{
	  this->error(_("symbol %u invalid section index %u"),
		      symndx, sym_shndx);
	  return false;
	}
      typename This::Shdr member_shdr(shdrs + sym_shndx * This::shdr_size);
      if (member_shdr.get_sh_name() < section_names_size)
	signature = section_names + member_shdr.get_sh_name();
    }

  // Record this section group in the layout, and see whether we've already
  // seen one with the same signature.
  bool include_group;
  bool is_comdat;
  Kept_section* kept_section = NULL;

  if ((flags & elfcpp::GRP_COMDAT) == 0)
    {
      include_group = true;
      is_comdat = false;
    }
  else
    {
      include_group = layout->find_or_add_kept_section(signature,
						       this, index, true,
						       true, &kept_section);
      is_comdat = true;
    }

  if (is_comdat && include_group)
    {
      Incremental_inputs* incremental_inputs = layout->incremental_inputs();
      if (incremental_inputs != NULL)
	incremental_inputs->report_comdat_group(this, signature.c_str());
    }

  size_t count = shdr.get_sh_size() / sizeof(elfcpp::Elf_Word);

  std::vector<unsigned int> shndxes;
  bool relocate_group = include_group && parameters->options().relocatable();
  if (relocate_group)
    shndxes.reserve(count - 1);

  for (size_t i = 1; i < count; ++i)
    {
      elfcpp::Elf_Word shndx =
	this->adjust_shndx(elfcpp::Swap<32, big_endian>::readval(pword + i));

      if (relocate_group)
	shndxes.push_back(shndx);

      if (shndx >= this->shnum())
	{
	  this->error(_("section %u in section group %u out of range"),
		      shndx, index);
	  continue;
	}

      // Check for an earlier section number, since we're going to get
      // it wrong--we may have already decided to include the section.
      if (shndx < index)
	this->error(_("invalid section group %u refers to earlier section %u"),
		    index, shndx);

      // Get the name of the member section.
      typename This::Shdr member_shdr(shdrs + shndx * This::shdr_size);
      if (member_shdr.get_sh_name() >= section_names_size)
	{
	  // This is an error, but it will be diagnosed eventually
	  // in do_layout, so we don't need to do anything here but
	  // ignore it.
	  continue;
	}
      std::string mname(section_names + member_shdr.get_sh_name());

      if (include_group)
	{
	  if (is_comdat)
	    kept_section->add_comdat_section(mname, shndx,
					     member_shdr.get_sh_size());
	}
      else
	{
	  (*omit)[shndx] = true;

	  // Store a mapping from this section to the Kept_section
	  // information for the group.  This mapping is used for
	  // relocation processing and diagnostics.
	  // If the kept section is a linkonce section, we don't
	  // bother with it unless the comdat group contains just
	  // a single section, making it easy to match up.
	  if (is_comdat
	      && (kept_section->is_comdat() || count == 2))
	    this->set_kept_comdat_section(shndx, true, symndx,
					  member_shdr.get_sh_size(),
					  kept_section);
	}
    }

  if (relocate_group)
    layout->layout_group(symtab, this, index, name, signature.c_str(),
			 shdr, flags, &shndxes);

  return include_group;
}

// Whether to include a linkonce section in the link.  NAME is the
// name of the section and SHDR is the section header.

// Linkonce sections are a GNU extension implemented in the original
// GNU linker before section groups were defined.  The semantics are
// that we only include one linkonce section with a given name.  The
// name of a linkonce section is normally .gnu.linkonce.T.SYMNAME,
// where T is the type of section and SYMNAME is the name of a symbol.
// In an attempt to make linkonce sections interact well with section
// groups, we try to identify SYMNAME and use it like a section group
// signature.  We want to block section groups with that signature,
// but not other linkonce sections with that signature.  We also use
// the full name of the linkonce section as a normal section group
// signature.

template<int size, bool big_endian>
bool
Sized_relobj_file<size, big_endian>::include_linkonce_section(
    Layout* layout,
    unsigned int index,
    const char* name,
    const elfcpp::Shdr<size, big_endian>& shdr)
{
  typename elfcpp::Elf_types<size>::Elf_WXword sh_size = shdr.get_sh_size();
  // In general the symbol name we want will be the string following
  // the last '.'.  However, we have to handle the case of
  // .gnu.linkonce.t.__i686.get_pc_thunk.bx, which was generated by
  // some versions of gcc.  So we use a heuristic: if the name starts
  // with ".gnu.linkonce.t.", we use everything after that.  Otherwise
  // we look for the last '.'.  We can't always simply skip
  // ".gnu.linkonce.X", because we have to deal with cases like
  // ".gnu.linkonce.d.rel.ro.local".
  const char* const linkonce_t = ".gnu.linkonce.t.";
  const char* symname;
  if (strncmp(name, linkonce_t, strlen(linkonce_t)) == 0)
    symname = name + strlen(linkonce_t);
  else
    symname = strrchr(name, '.') + 1;
  std::string sig1(symname);
  std::string sig2(name);
  Kept_section* kept1;
  Kept_section* kept2;
  bool include1 = layout->find_or_add_kept_section(sig1, this, index, false,
						   false, &kept1);
  bool include2 = layout->find_or_add_kept_section(sig2, this, index, false,
						   true, &kept2);

  if (!include2)
    {
      // We are not including this section because we already saw the
      // name of the section as a signature.  This normally implies
      // that the kept section is another linkonce section.  If it is
      // the same size, record it as the section which corresponds to
      // this one.
      if (kept2->object() != NULL && !kept2->is_comdat())
	this->set_kept_comdat_section(index, false, 0, sh_size, kept2);
    }
  else if (!include1)
    {
      // The section is being discarded on the basis of its symbol
      // name.  This means that the corresponding kept section was
      // part of a comdat group, and it will be difficult to identify
      // the specific section within that group that corresponds to
      // this linkonce section.  We'll handle the simple case where
      // the group has only one member section.  Otherwise, it's not
      // worth the effort.
      if (kept1->object() != NULL && kept1->is_comdat())
	this->set_kept_comdat_section(index, false, 0, sh_size, kept1);
    }
  else
    {
      kept1->set_linkonce_size(sh_size);
      kept2->set_linkonce_size(sh_size);
    }

  return include1 && include2;
}

// Layout an input section.

template<int size, bool big_endian>
inline void
Sized_relobj_file<size, big_endian>::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)
{
  off_t offset;
  Output_section* os = layout->layout(this, shndx, name, shdr, sh_type,
				      reloc_shndx, reloc_type, &offset);

  this->output_sections()[shndx] = os;
  if (offset == -1)
    this->section_offsets()[shndx] = invalid_address;
  else
    this->section_offsets()[shndx] = convert_types<Address, off_t>(offset);

  // If this section requires special handling, and if there are
  // relocs that apply to it, then we must do the special handling
  // before we apply the relocs.
  if (offset == -1 && reloc_shndx != 0)
    this->set_relocs_must_follow_section_writes();
}

// Layout an input .eh_frame section.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::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& shdr,
    unsigned int reloc_shndx,
    unsigned int reloc_type)
{
  gold_assert(this->has_eh_frame_);

  off_t offset;
  Output_section* os = layout->layout_eh_frame(this,
					       symbols_data,
					       symbols_size,
					       symbol_names_data,
					       symbol_names_size,
					       shndx,
					       shdr,
					       reloc_shndx,
					       reloc_type,
					       &offset);
  this->output_sections()[shndx] = os;
  if (os == NULL || offset == -1)
    this->section_offsets()[shndx] = invalid_address;
  else
    this->section_offsets()[shndx] = convert_types<Address, off_t>(offset);

  // If this section requires special handling, and if there are
  // relocs that aply to it, then we must do the special handling
  // before we apply the relocs.
  if (os != NULL && offset == -1 && reloc_shndx != 0)
    this->set_relocs_must_follow_section_writes();
}

// Layout an input .note.gnu.property section.

// This note section has an *extremely* non-standard layout.
// The gABI spec says that ELF-64 files should have 8-byte fields and
// 8-byte alignment in the note section, but the Gnu tools generally
// use 4-byte fields and 4-byte alignment (see the comment for
// Layout::create_note).  This section uses 4-byte fields (i.e.,
// namesz, descsz, and type are always 4 bytes), the name field is
// padded to a multiple of 4 bytes, but the desc field is padded
// to a multiple of 4 or 8 bytes, depending on the ELF class.
// The individual properties within the desc field always use
// 4-byte pr_type and pr_datasz fields, but pr_data is padded to
// a multiple of 4 or 8 bytes, depending on the ELF class.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::layout_gnu_property_section(
    Layout* layout,
    unsigned int shndx)
{
  section_size_type contents_len;
  const unsigned char* pcontents = this->section_contents(shndx,
							  &contents_len,
							  false);
  const unsigned char* pcontents_end = pcontents + contents_len;

  // Loop over all the notes in this section.
  while (pcontents < pcontents_end)
    {
      if (pcontents + 16 > pcontents_end)
	{
	  gold_warning(_("%s: corrupt .note.gnu.property section "
			 "(note too short)"),
		       this->name().c_str());
	  return;
	}

      size_t namesz = elfcpp::Swap<32, big_endian>::readval(pcontents);
      size_t descsz = elfcpp::Swap<32, big_endian>::readval(pcontents + 4);
      unsigned int ntype = elfcpp::Swap<32, big_endian>::readval(pcontents + 8);
      const unsigned char* pname = pcontents + 12;

      if (namesz != 4 || strcmp(reinterpret_cast<const char*>(pname), "GNU") != 0)
	{
	  gold_warning(_("%s: corrupt .note.gnu.property section "
			 "(name is not 'GNU')"),
		       this->name().c_str());
	  return;
	}

      if (ntype != elfcpp::NT_GNU_PROPERTY_TYPE_0)
	{
	  gold_warning(_("%s: unsupported note type %d "
			 "in .note.gnu.property section"),
		       this->name().c_str(), ntype);
	  return;
	}

      size_t aligned_namesz = align_address(namesz, 4);
      const unsigned char* pdesc = pname + aligned_namesz;

      if (pdesc + descsz > pcontents + contents_len)
	{
	  gold_warning(_("%s: corrupt .note.gnu.property section"),
		       this->name().c_str());
	  return;
	}

      const unsigned char* pprop = pdesc;

      // Loop over the program properties in this note.
      while (pprop < pdesc + descsz)
	{
	  if (pprop + 8 > pdesc + descsz)
	    {
	      gold_warning(_("%s: corrupt .note.gnu.property section"),
			   this->name().c_str());
	      return;
	    }
	  unsigned int pr_type = elfcpp::Swap<32, big_endian>::readval(pprop);
	  size_t pr_datasz = elfcpp::Swap<32, big_endian>::readval(pprop + 4);
	  pprop += 8;
	  if (pprop + pr_datasz > pdesc + descsz)
	    {
	      gold_warning(_("%s: corrupt .note.gnu.property section"),
			   this->name().c_str());
	      return;
	    }
	  layout->layout_gnu_property(ntype, pr_type, pr_datasz, pprop, this);
	  pprop += align_address(pr_datasz, size / 8);
	}

      pcontents = pdesc + align_address(descsz, size / 8);
    }
}

// Lay out the input sections.  We walk through the sections and check
// whether they should be included in the link.  If they should, we
// pass them to the Layout object, which will return an output section
// and an offset.
// This function is called twice sometimes, two passes, when mapping
// of input sections to output sections must be delayed.
// This is true for the following :
// * Garbage collection (--gc-sections): Some input sections will be
// discarded and hence the assignment must wait until the second pass.
// In the first pass,  it is for setting up some sections as roots to
// a work-list for --gc-sections and to do comdat processing.
// * Identical Code Folding (--icf=<safe,all>): Some input sections
// will be folded and hence the assignment must wait.
// * Using plugins to map some sections to unique segments: Mapping
// some sections to unique segments requires mapping them to unique
// output sections too.  This can be done via plugins now and this
// information is not available in the first pass.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
					       Layout* layout,
					       Read_symbols_data* sd)
{
  const unsigned int unwind_section_type =
      parameters->target().unwind_section_type();
  const unsigned int shnum = this->shnum();

  /* Should this function be called twice?  */
  bool is_two_pass = (parameters->options().gc_sections()
		      || parameters->options().icf_enabled()
		      || layout->is_unique_segment_for_sections_specified());

  /* Only one of is_pass_one and is_pass_two is true.  Both are false when
     a two-pass approach is not needed.  */
  bool is_pass_one = false;
  bool is_pass_two = false;

  Symbols_data* gc_sd = NULL;

  /* Check if do_layout needs to be two-pass.  If so, find out which pass
     should happen.  In the first pass, the data in sd is saved to be used
     later in the second pass.  */
  if (is_two_pass)
    {
      gc_sd = this->get_symbols_data();
      if (gc_sd == NULL)
	{
	  gold_assert(sd != NULL);
	  is_pass_one = true;
	}
      else
	{
	  if (parameters->options().gc_sections())
	    gold_assert(symtab->gc()->is_worklist_ready());
	  if (parameters->options().icf_enabled())
	    gold_assert(symtab->icf()->is_icf_ready()); 
	  is_pass_two = true;
	}
    }
    
  if (shnum == 0)
    return;

  if (is_pass_one)
    {
      // During garbage collection save the symbols data to use it when
      // re-entering this function.
      gc_sd = new Symbols_data;
      this->copy_symbols_data(gc_sd, sd, This::shdr_size * shnum);
      this->set_symbols_data(gc_sd);
    }

  const unsigned char* section_headers_data = NULL;
  section_size_type section_names_size;
  const unsigned char* symbols_data = NULL;
  section_size_type symbols_size;
  const unsigned char* symbol_names_data = NULL;
  section_size_type symbol_names_size;

  if (is_two_pass)
    {
      section_headers_data = gc_sd->section_headers_data;
      section_names_size = gc_sd->section_names_size;
      symbols_data = gc_sd->symbols_data;
      symbols_size = gc_sd->symbols_size;
      symbol_names_data = gc_sd->symbol_names_data;
      symbol_names_size = gc_sd->symbol_names_size;
    }
  else
    {
      section_headers_data = sd->section_headers->data();
      section_names_size = sd->section_names_size;
      if (sd->symbols != NULL)
	symbols_data = sd->symbols->data();
      symbols_size = sd->symbols_size;
      if (sd->symbol_names != NULL)
	symbol_names_data = sd->symbol_names->data();
      symbol_names_size = sd->symbol_names_size;
    }

  // Get the section headers.
  const unsigned char* shdrs = section_headers_data;
  const unsigned char* pshdrs;

  // Get the section names.
  const unsigned char* pnamesu = (is_two_pass
				  ? gc_sd->section_names_data
				  : sd->section_names->data());

  const char* pnames = reinterpret_cast<const char*>(pnamesu);

  // If any input files have been claimed by plugins, we need to defer
  // actual layout until the replacement files have arrived.
  const bool should_defer_layout =
      (parameters->options().has_plugins()
       && parameters->options().plugins()->should_defer_layout());
  unsigned int num_sections_to_defer = 0;

  // For each section, record the index of the reloc section if any.
  // Use 0 to mean that there is no reloc section, -1U to mean that
  // there is more than one.
  std::vector<unsigned int> reloc_shndx(shnum, 0);
  std::vector<unsigned int> reloc_type(shnum, elfcpp::SHT_NULL);
  // Skip the first, dummy, section.
  pshdrs = shdrs + This::shdr_size;
  for (unsigned int i = 1; i < shnum; ++i, pshdrs += This::shdr_size)
    {
      typename This::Shdr shdr(pshdrs);

      // Count the number of sections whose layout will be deferred.
      if (should_defer_layout && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC))
	++num_sections_to_defer;

      unsigned int sh_type = shdr.get_sh_type();
      if (sh_type == elfcpp::SHT_REL || sh_type == elfcpp::SHT_RELA)
	{
	  unsigned int target_shndx = this->adjust_shndx(shdr.get_sh_info());
	  if (target_shndx == 0 || target_shndx >= shnum)
	    {
	      this->error(_("relocation section %u has bad info %u"),
			  i, target_shndx);
	      continue;
	    }

	  if (reloc_shndx[target_shndx] != 0)
	    reloc_shndx[target_shndx] = -1U;
	  else
	    {
	      reloc_shndx[target_shndx] = i;
	      reloc_type[target_shndx] = sh_type;
	    }
	}
    }

  Output_sections& out_sections(this->output_sections());
  std::vector<Address>& out_section_offsets(this->section_offsets());

  if (!is_pass_two)
    {
      out_sections.resize(shnum);
      out_section_offsets.resize(shnum);
    }

  // If we are only linking for symbols, then there is nothing else to
  // do here.
  if (this->input_file()->just_symbols())
    {
      if (!is_pass_two)
	{
	  delete sd->section_headers;
	  sd->section_headers = NULL;
	  delete sd->section_names;
	  sd->section_names = NULL;
	}
      return;
    }

  if (num_sections_to_defer > 0)
    {
      parameters->options().plugins()->add_deferred_layout_object(this);
      this->deferred_layout_.reserve(num_sections_to_defer);
      this->is_deferred_layout_ = true;
    }

  // Whether we've seen a .note.GNU-stack section.
  bool seen_gnu_stack = false;
  // The flags of a .note.GNU-stack section.
  uint64_t gnu_stack_flags = 0;

  // Keep track of which sections to omit.
  std::vector<bool> omit(shnum, false);

  // Keep track of reloc sections when emitting relocations.
  const bool relocatable = parameters->options().relocatable();
  const bool emit_relocs = (relocatable
			    || parameters->options().emit_relocs());
  std::vector<unsigned int> reloc_sections;

  // Keep track of .eh_frame sections.
  std::vector<unsigned int> eh_frame_sections;

  // Keep track of .debug_info and .debug_types sections.
  std::vector<unsigned int> debug_info_sections;
  std::vector<unsigned int> debug_types_sections;

  // Skip the first, dummy, section.
  pshdrs = shdrs + This::shdr_size;
  for (unsigned int i = 1; i < shnum; ++i, pshdrs += This::shdr_size)
    {
      typename This::Shdr shdr(pshdrs);
      const unsigned int sh_name = shdr.get_sh_name();
      unsigned int sh_type = shdr.get_sh_type();

      if (sh_name >= section_names_size)
	{
	  this->error(_("bad section name offset for section %u: %lu"),
		      i, static_cast<unsigned long>(sh_name));
	  return;
	}

      const char* name = pnames + sh_name;

      if (!is_pass_two)
	{
	  if (this->handle_gnu_warning_section(name, i, symtab))
	    {
	      if (!relocatable && !parameters->options().shared())
		omit[i] = true;
	    }

	  // The .note.GNU-stack section is special.  It gives the
	  // protection flags that this object file requires for the stack
	  // in memory.
	  if (strcmp(name, ".note.GNU-stack") == 0)
	    {
	      seen_gnu_stack = true;
	      gnu_stack_flags |= shdr.get_sh_flags();
	      omit[i] = true;
	    }

	  // The .note.GNU-split-stack section is also special.  It
	  // indicates that the object was compiled with
	  // -fsplit-stack.
	  if (this->handle_split_stack_section(name))
	    {
	      if (!relocatable && !parameters->options().shared())
		omit[i] = true;
	    }

	  // Skip attributes section.
	  if (parameters->target().is_attributes_section(name))
	    {
	      omit[i] = true;
	    }

	  // Handle .note.gnu.property sections.
	  if (sh_type == elfcpp::SHT_NOTE
	      && strcmp(name, ".note.gnu.property") == 0)
	    {
	      this->layout_gnu_property_section(layout, i);
	      omit[i] = true;
	    }

	  bool discard = omit[i];
	  if (!discard)
	    {
	      if (sh_type == elfcpp::SHT_GROUP)
		{
		  if (!this->include_section_group(symtab, layout, i, name,
						   shdrs, pnames,
						   section_names_size,
						   &omit))
		    discard = true;
		}
	      else if ((shdr.get_sh_flags() & elfcpp::SHF_GROUP) == 0
		       && Layout::is_linkonce(name))
		{
		  if (!this->include_linkonce_section(layout, i, name, shdr))
		    discard = true;
		}
	    }

	  // Add the section to the incremental inputs layout.
	  Incremental_inputs* incremental_inputs = layout->incremental_inputs();
	  if (incremental_inputs != NULL
	      && !discard
	      && can_incremental_update(sh_type))
	    {
	      off_t sh_size = shdr.get_sh_size();
	      section_size_type uncompressed_size;
	      if (this->section_is_compressed(i, &uncompressed_size))
		sh_size = uncompressed_size;
	      incremental_inputs->report_input_section(this, i, name, sh_size);
	    }

	  if (discard)
	    {
	      // Do not include this section in the link.
	      out_sections[i] = NULL;
	      out_section_offsets[i] = invalid_address;
	      continue;
	    }
	}

      if (is_pass_one && parameters->options().gc_sections())
	{
	  if (this->is_section_name_included(name)
	      || layout->keep_input_section (this, name)
	      || sh_type == elfcpp::SHT_INIT_ARRAY
	      || sh_type == elfcpp::SHT_FINI_ARRAY)
	    {
	      symtab->gc()->worklist().push_back(Section_id(this, i));
	    }
	  // If the section name XXX can be represented as a C identifier
	  // it cannot be discarded if there are references to
	  // __start_XXX and __stop_XXX symbols.  These need to be
	  // specially handled.
	  if (is_cident(name))
	    {
	      symtab->gc()->add_cident_section(name, Section_id(this, i));
	    }
	}

      // When doing a relocatable link we are going to copy input
      // reloc sections into the output.  We only want to copy the
      // ones associated with sections which are not being discarded.
      // However, we don't know that yet for all sections.  So save
      // reloc sections and process them later. Garbage collection is
      // not triggered when relocatable code is desired.
      if (emit_relocs
	  && (sh_type == elfcpp::SHT_REL
	      || sh_type == elfcpp::SHT_RELA))
	{
	  reloc_sections.push_back(i);
	  continue;
	}

      if (relocatable && sh_type == elfcpp::SHT_GROUP)
	continue;

      // The .eh_frame section is special.  It holds exception frame
      // information that we need to read in order to generate the
      // exception frame header.  We process these after all the other
      // sections so that the exception frame reader can reliably
      // determine which sections are being discarded, and discard the
      // corresponding information.
      if (this->check_eh_frame_flags(&shdr)
	  && strcmp(name, ".eh_frame") == 0)
	{
	  // If the target has a special unwind section type, let's
	  // canonicalize it here.
	  sh_type = unwind_section_type;
	  if (!relocatable)
	    {
	      if (is_pass_one)
		{
		  if (this->is_deferred_layout())
		    out_sections[i] = reinterpret_cast<Output_section*>(2);
		  else
		    out_sections[i] = reinterpret_cast<Output_section*>(1);
		  out_section_offsets[i] = invalid_address;
		}
	      else if (this->is_deferred_layout())
		this->deferred_layout_.push_back(
		    Deferred_layout(i, name, sh_type, pshdrs,
				    reloc_shndx[i], reloc_type[i]));
	      else
		eh_frame_sections.push_back(i);
	      continue;
	    }
	}

      if (is_pass_two && parameters->options().gc_sections())
	{
	  // This is executed during the second pass of garbage
	  // collection. do_layout has been called before and some
	  // sections have been already discarded. Simply ignore
	  // such sections this time around.
	  if (out_sections[i] == NULL)
	    {
	      gold_assert(out_section_offsets[i] == invalid_address);
	      continue;
	    }
	  if (((shdr.get_sh_flags() & elfcpp::SHF_ALLOC) != 0)
	      && symtab->gc()->is_section_garbage(this, i))
	      {
		if (parameters->options().print_gc_sections())
		  gold_info(_("%s: removing unused section from '%s'"
			      " in file '%s'"),
			    program_name, this->section_name(i).c_str(),
			    this->name().c_str());
		out_sections[i] = NULL;
		out_section_offsets[i] = invalid_address;
		continue;
	      }
	}

      if (is_pass_two && parameters->options().icf_enabled())
	{
	  if (out_sections[i] == NULL)
	    {
	      gold_assert(out_section_offsets[i] == invalid_address);
	      continue;
	    }
	  if (((shdr.get_sh_flags() & elfcpp::SHF_ALLOC) != 0)
	      && symtab->icf()->is_section_folded(this, i))
	      {
		if (parameters->options().print_icf_sections())
		  {
		    Section_id folded =
				symtab->icf()->get_folded_section(this, i);
		    Relobj* folded_obj =
				reinterpret_cast<Relobj*>(folded.first);
		    gold_info(_("%s: ICF folding section '%s' in file '%s' "
				"into '%s' in file '%s'"),
			      program_name, this->section_name(i).c_str(),
			      this->name().c_str(),
			      folded_obj->section_name(folded.second).c_str(),
			      folded_obj->name().c_str());
		  }
		out_sections[i] = NULL;
		out_section_offsets[i] = invalid_address;
		continue;
	      }
	}

      // Defer layout here if input files are claimed by plugins.  When gc
      // is turned on this function is called twice; we only want to do this
      // on the first pass.
      if (!is_pass_two
          && this->is_deferred_layout()
          && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC))
	{
	  this->deferred_layout_.push_back(Deferred_layout(i, name, sh_type,
							   pshdrs,
							   reloc_shndx[i],
							   reloc_type[i]));
	  // Put dummy values here; real values will be supplied by
	  // do_layout_deferred_sections.
	  out_sections[i] = reinterpret_cast<Output_section*>(2);
	  out_section_offsets[i] = invalid_address;
	  continue;
	}

      // During gc_pass_two if a section that was previously deferred is
      // found, do not layout the section as layout_deferred_sections will
      // do it later from gold.cc.
      if (is_pass_two
	  && (out_sections[i] == reinterpret_cast<Output_section*>(2)))
	continue;

      if (is_pass_one)
	{
	  // This is during garbage collection. The out_sections are
	  // assigned in the second call to this function.
	  out_sections[i] = reinterpret_cast<Output_section*>(1);
	  out_section_offsets[i] = invalid_address;
	}
      else
	{
	  // When garbage collection is switched on the actual layout
	  // only happens in the second call.
	  this->layout_section(layout, i, name, shdr, sh_type, reloc_shndx[i],
			       reloc_type[i]);

	  // When generating a .gdb_index section, we do additional
	  // processing of .debug_info and .debug_types sections after all
	  // the other sections for the same reason as above.
	  if (!relocatable
	      && parameters->options().gdb_index()
	      && !(shdr.get_sh_flags() & elfcpp::SHF_ALLOC))
	    {
	      if (strcmp(name, ".debug_info") == 0
		  || strcmp(name, ".zdebug_info") == 0)
		debug_info_sections.push_back(i);
	      else if (strcmp(name, ".debug_types") == 0
		       || strcmp(name, ".zdebug_types") == 0)
		debug_types_sections.push_back(i);
	    }
	}
    }

  if (!is_pass_two)
    {
      layout->merge_gnu_properties(this);
      layout->layout_gnu_stack(seen_gnu_stack, gnu_stack_flags, this);
    }

  // Handle the .eh_frame sections after the other sections.
  gold_assert(!is_pass_one || eh_frame_sections.empty());
  for (std::vector<unsigned int>::const_iterator p = eh_frame_sections.begin();
       p != eh_frame_sections.end();
       ++p)
    {
      unsigned int i = *p;
      const unsigned char* pshdr;
      pshdr = section_headers_data + i * This::shdr_size;
      typename This::Shdr shdr(pshdr);

      this->layout_eh_frame_section(layout,
				    symbols_data,
				    symbols_size,
				    symbol_names_data,
				    symbol_names_size,
				    i,
				    shdr,
				    reloc_shndx[i],
				    reloc_type[i]);
    }

  // When doing a relocatable link handle the reloc sections at the
  // end.  Garbage collection  and Identical Code Folding is not
  // turned on for relocatable code.
  if (emit_relocs)
    this->size_relocatable_relocs();

  gold_assert(!is_two_pass || reloc_sections.empty());

  for (std::vector<unsigned int>::const_iterator p = reloc_sections.begin();
       p != reloc_sections.end();
       ++p)
    {
      unsigned int i = *p;
      const unsigned char* pshdr;
      pshdr = section_headers_data + i * This::shdr_size;
      typename This::Shdr shdr(pshdr);

      unsigned int data_shndx = this->adjust_shndx(shdr.get_sh_info());
      if (data_shndx >= shnum)
	{
	  // We already warned about this above.
	  continue;
	}

      Output_section* data_section = out_sections[data_shndx];
      if (data_section == reinterpret_cast<Output_section*>(2))
	{
	  if (is_pass_two)
	    continue;
	  // The layout for the data section was deferred, so we need
	  // to defer the relocation section, too.
	  const char* name = pnames + shdr.get_sh_name();
	  this->deferred_layout_relocs_.push_back(
	      Deferred_layout(i, name, shdr.get_sh_type(), pshdr, 0,
			      elfcpp::SHT_NULL));
	  out_sections[i] = reinterpret_cast<Output_section*>(2);
	  out_section_offsets[i] = invalid_address;
	  continue;
	}
      if (data_section == NULL)
	{
	  out_sections[i] = NULL;
	  out_section_offsets[i] = invalid_address;
	  continue;
	}

      Relocatable_relocs* rr = new Relocatable_relocs();
      this->set_relocatable_relocs(i, rr);

      Output_section* os = layout->layout_reloc(this, i, shdr, data_section,
						rr);
      out_sections[i] = os;
      out_section_offsets[i] = invalid_address;
    }

  // When building a .gdb_index section, scan the .debug_info and
  // .debug_types sections.
  gold_assert(!is_pass_one
	      || (debug_info_sections.empty() && debug_types_sections.empty()));
  for (std::vector<unsigned int>::const_iterator p
	   = debug_info_sections.begin();
       p != debug_info_sections.end();
       ++p)
    {
      unsigned int i = *p;
      layout->add_to_gdb_index(false, this, symbols_data, symbols_size,
			       i, reloc_shndx[i], reloc_type[i]);
    }
  for (std::vector<unsigned int>::const_iterator p
	   = debug_types_sections.begin();
       p != debug_types_sections.end();
       ++p)
    {
      unsigned int i = *p;
      layout->add_to_gdb_index(true, this, symbols_data, symbols_size,
			       i, reloc_shndx[i], reloc_type[i]);
    }

  if (is_pass_two)
    {
      delete[] gc_sd->section_headers_data;
      delete[] gc_sd->section_names_data;
      delete[] gc_sd->symbols_data;
      delete[] gc_sd->symbol_names_data;
      this->set_symbols_data(NULL);
    }
  else
    {
      delete sd->section_headers;
      sd->section_headers = NULL;
      delete sd->section_names;
      sd->section_names = NULL;
    }
}

// Layout sections whose layout was deferred while waiting for
// input files from a plugin.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::do_layout_deferred_sections(Layout* layout)
{
  typename std::vector<Deferred_layout>::iterator deferred;

  for (deferred = this->deferred_layout_.begin();
       deferred != this->deferred_layout_.end();
       ++deferred)
    {
      typename This::Shdr shdr(deferred->shdr_data_);

      if (!parameters->options().relocatable()
	  && deferred->name_ == ".eh_frame"
	  && this->check_eh_frame_flags(&shdr))
	{
	  // Checking is_section_included is not reliable for
	  // .eh_frame sections, because they do not have an output
	  // section.  This is not a problem normally because we call
	  // layout_eh_frame_section unconditionally, but when
	  // deferring sections that is not true.  We don't want to
	  // keep all .eh_frame sections because that will cause us to
	  // keep all sections that they refer to, which is the wrong
	  // way around.  Instead, the eh_frame code will discard
	  // .eh_frame sections that refer to discarded sections.

	  // Reading the symbols again here may be slow.
	  Read_symbols_data sd;
	  this->base_read_symbols(&sd);
	  this->layout_eh_frame_section(layout,
					sd.symbols->data(),
					sd.symbols_size,
					sd.symbol_names->data(),
					sd.symbol_names_size,
					deferred->shndx_,
					shdr,
					deferred->reloc_shndx_,
					deferred->reloc_type_);
	  continue;
	}

      // If the section is not included, it is because the garbage collector
      // decided it is not needed.  Avoid reverting that decision.
      if (!this->is_section_included(deferred->shndx_))
	continue;

      this->layout_section(layout, deferred->shndx_, deferred->name_.c_str(),
			   shdr, shdr.get_sh_type(), deferred->reloc_shndx_,
			   deferred->reloc_type_);
    }

  this->deferred_layout_.clear();

  // Now handle the deferred relocation sections.

  Output_sections& out_sections(this->output_sections());
  std::vector<Address>& out_section_offsets(this->section_offsets());

  for (deferred = this->deferred_layout_relocs_.begin();
       deferred != this->deferred_layout_relocs_.end();
       ++deferred)
    {
      unsigned int shndx = deferred->shndx_;
      typename This::Shdr shdr(deferred->shdr_data_);
      unsigned int data_shndx = this->adjust_shndx(shdr.get_sh_info());

      Output_section* data_section = out_sections[data_shndx];
      if (data_section == NULL)
	{
	  out_sections[shndx] = NULL;
	  out_section_offsets[shndx] = invalid_address;
	  continue;
	}

      Relocatable_relocs* rr = new Relocatable_relocs();
      this->set_relocatable_relocs(shndx, rr);

      Output_section* os = layout->layout_reloc(this, shndx, shdr,
						data_section, rr);
      out_sections[shndx] = os;
      out_section_offsets[shndx] = invalid_address;
    }
}

// Add the symbols to the symbol table.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::do_add_symbols(Symbol_table* symtab,
						    Read_symbols_data* sd,
						    Layout*)
{
  if (sd->symbols == NULL)
    {
      gold_assert(sd->symbol_names == NULL);
      return;
    }

  const int sym_size = This::sym_size;
  size_t symcount = ((sd->symbols_size - sd->external_symbols_offset)
		     / sym_size);
  if (symcount * sym_size != sd->symbols_size - sd->external_symbols_offset)
    {
      this->error(_("size of symbols is not multiple of symbol size"));
      return;
    }

  this->symbols_.resize(symcount);

  const char* sym_names =
    reinterpret_cast<const char*>(sd->symbol_names->data());
  symtab->add_from_relobj(this,
			  sd->symbols->data() + sd->external_symbols_offset,
			  symcount, this->local_symbol_count_,
			  sym_names, sd->symbol_names_size,
			  &this->symbols_,
			  &this->defined_count_);

  delete sd->symbols;
  sd->symbols = NULL;
  delete sd->symbol_names;
  sd->symbol_names = NULL;
}

// Find out if this object, that is a member of a lib group, should be included
// in the link. We check every symbol defined by this object. If the symbol
// table has a strong undefined reference to that symbol, we have to include
// the object.

template<int size, bool big_endian>
Archive::Should_include
Sized_relobj_file<size, big_endian>::do_should_include_member(
    Symbol_table* symtab,
    Layout* layout,
    Read_symbols_data* sd,
    std::string* why)
{
  char* tmpbuf = NULL;
  size_t tmpbuflen = 0;
  const char* sym_names =
      reinterpret_cast<const char*>(sd->symbol_names->data());
  const unsigned char* syms =
      sd->symbols->data() + sd->external_symbols_offset;
  const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
  size_t symcount = ((sd->symbols_size - sd->external_symbols_offset)
			 / sym_size);

  const unsigned char* p = syms;

  for (size_t i = 0; i < symcount; ++i, p += sym_size)
    {
      elfcpp::Sym<size, big_endian> sym(p);
      unsigned int st_shndx = sym.get_st_shndx();
      if (st_shndx == elfcpp::SHN_UNDEF)
	continue;

      unsigned int st_name = sym.get_st_name();
      const char* name = sym_names + st_name;
      Symbol* symbol;
      Archive::Should_include t = Archive::should_include_member(symtab,
								 layout,
								 name,
								 &symbol, why,
								 &tmpbuf,
								 &tmpbuflen);
      if (t == Archive::SHOULD_INCLUDE_YES)
	{
	  if (tmpbuf != NULL)
	    free(tmpbuf);
	  return t;
	}
    }
  if (tmpbuf != NULL)
    free(tmpbuf);
  return Archive::SHOULD_INCLUDE_UNKNOWN;
}

// Iterate over global defined symbols, calling a visitor class V for each.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::do_for_all_global_symbols(
    Read_symbols_data* sd,
    Library_base::Symbol_visitor_base* v)
{
  const char* sym_names =
      reinterpret_cast<const char*>(sd->symbol_names->data());
  const unsigned char* syms =
      sd->symbols->data() + sd->external_symbols_offset;
  const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
  size_t symcount = ((sd->symbols_size - sd->external_symbols_offset)
		     / sym_size);
  const unsigned char* p = syms;

  for (size_t i = 0; i < symcount; ++i, p += sym_size)
    {
      elfcpp::Sym<size, big_endian> sym(p);
      if (sym.get_st_shndx() != elfcpp::SHN_UNDEF)
	v->visit(sym_names + sym.get_st_name());
    }
}

// Return whether the local symbol SYMNDX has a PLT offset.

template<int size, bool big_endian>
bool
Sized_relobj_file<size, big_endian>::local_has_plt_offset(
    unsigned int symndx) const
{
  typename Local_plt_offsets::const_iterator p =
    this->local_plt_offsets_.find(symndx);
  return p != this->local_plt_offsets_.end();
}

// Get the PLT offset of a local symbol.

template<int size, bool big_endian>
unsigned int
Sized_relobj_file<size, big_endian>::do_local_plt_offset(
    unsigned int symndx) const
{
  typename Local_plt_offsets::const_iterator p =
    this->local_plt_offsets_.find(symndx);
  gold_assert(p != this->local_plt_offsets_.end());
  return p->second;
}

// Set the PLT offset of a local symbol.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::set_local_plt_offset(
    unsigned int symndx, unsigned int plt_offset)
{
  std::pair<typename Local_plt_offsets::iterator, bool> ins =
    this->local_plt_offsets_.insert(std::make_pair(symndx, plt_offset));
  gold_assert(ins.second);
}

// First pass over the local symbols.  Here we add their names to
// *POOL and *DYNPOOL, and we store the symbol value in
// THIS->LOCAL_VALUES_.  This function is always called from a
// singleton thread.  This is followed by a call to
// finalize_local_symbols.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::do_count_local_symbols(Stringpool* pool,
							    Stringpool* dynpool)
{
  gold_assert(this->symtab_shndx_ != -1U);
  if (this->symtab_shndx_ == 0)
    {
      // This object has no symbols.  Weird but legal.
      return;
    }

  // Read the symbol table section header.
  const unsigned int symtab_shndx = this->symtab_shndx_;
  typename This::Shdr symtabshdr(this,
				 this->elf_file_.section_header(symtab_shndx));
  gold_assert(symtabshdr.get_sh_type() == elfcpp::SHT_SYMTAB);

  // Read the local symbols.
  const int sym_size = This::sym_size;
  const unsigned int loccount = this->local_symbol_count_;
  gold_assert(loccount == symtabshdr.get_sh_info());
  off_t locsize = loccount * sym_size;
  const unsigned char* psyms = this->get_view(symtabshdr.get_sh_offset(),
					      locsize, true, true);

  // Read the symbol names.
  const unsigned int strtab_shndx =
    this->adjust_shndx(symtabshdr.get_sh_link());
  section_size_type strtab_size;
  const unsigned char* pnamesu = this->section_contents(strtab_shndx,
							&strtab_size,
							true);
  const char* pnames = reinterpret_cast<const char*>(pnamesu);

  // Loop over the local symbols.

  const Output_sections& out_sections(this->output_sections());
  std::vector<Address>& out_section_offsets(this->section_offsets());
  unsigned int shnum = this->shnum();
  unsigned int count = 0;
  unsigned int dyncount = 0;
  // Skip the first, dummy, symbol.
  psyms += sym_size;
  bool strip_all = parameters->options().strip_all();
  bool discard_all = parameters->options().discard_all();
  bool discard_locals = parameters->options().discard_locals();
  bool discard_sec_merge = parameters->options().discard_sec_merge();
  for (unsigned int i = 1; i < loccount; ++i, psyms += sym_size)
    {
      elfcpp::Sym<size, big_endian> sym(psyms);

      Symbol_value<size>& lv(this->local_values_[i]);

      bool is_ordinary;
      unsigned int shndx = this->adjust_sym_shndx(i, sym.get_st_shndx(),
						  &is_ordinary);
      lv.set_input_shndx(shndx, is_ordinary);

      if (sym.get_st_type() == elfcpp::STT_SECTION)
	lv.set_is_section_symbol();
      else if (sym.get_st_type() == elfcpp::STT_TLS)
	lv.set_is_tls_symbol();
      else if (sym.get_st_type() == elfcpp::STT_GNU_IFUNC)
	lv.set_is_ifunc_symbol();

      // Save the input symbol value for use in do_finalize_local_symbols().
      lv.set_input_value(sym.get_st_value());

      // Decide whether this symbol should go into the output file.

      if (is_ordinary
	  && shndx < shnum
	  && (out_sections[shndx] == NULL
	      || (out_sections[shndx]->order() == ORDER_EHFRAME
		  && out_section_offsets[shndx] == invalid_address)))
	{
	  // This is either a discarded section or an optimized .eh_frame
	  // section.
	  lv.set_no_output_symtab_entry();
	  gold_assert(!lv.needs_output_dynsym_entry());
	  continue;
	}

      if (sym.get_st_type() == elfcpp::STT_SECTION
	  || !this->adjust_local_symbol(&lv))
	{
	  lv.set_no_output_symtab_entry();
	  gold_assert(!lv.needs_output_dynsym_entry());
	  continue;
	}

      if (sym.get_st_name() >= strtab_size)
	{
	  this->error(_("local symbol %u section name out of range: %u >= %u"),
		      i, sym.get_st_name(),
		      static_cast<unsigned int>(strtab_size));
	  lv.set_no_output_symtab_entry();
	  continue;
	}

      const char* name = pnames + sym.get_st_name();

      // If needed, add the symbol to the dynamic symbol table string pool.
      if (lv.needs_output_dynsym_entry())
	{
	  dynpool->add(name, true, NULL);
	  ++dyncount;
	}

      if (strip_all
	  || (discard_all && lv.may_be_discarded_from_output_symtab()))
	{
	  lv.set_no_output_symtab_entry();
	  continue;
	}

      // By default, discard temporary local symbols in merge sections.
      // If --discard-locals option is used, discard all temporary local
      // symbols.  These symbols start with system-specific local label
      // prefixes, typically .L for ELF system.  We want to be compatible
      // with GNU ld so here we essentially use the same check in
      // bfd_is_local_label().  The code is different because we already
      // know that:
      //
      //   - the symbol is local and thus cannot have global or weak binding.
      //   - the symbol is not a section symbol.
      //   - the symbol has a name.
      //
      // We do not discard a symbol if it needs a dynamic symbol entry.
      if ((discard_locals
	   || (discard_sec_merge
	       && is_ordinary
	       && out_section_offsets[shndx] == invalid_address))
	  && sym.get_st_type() != elfcpp::STT_FILE
	  && !lv.needs_output_dynsym_entry()
	  && lv.may_be_discarded_from_output_symtab()
	  && parameters->target().is_local_label_name(name))
	{
	  lv.set_no_output_symtab_entry();
	  continue;
	}

      // Discard the local symbol if -retain_symbols_file is specified
      // and the local symbol is not in that file.
      if (!parameters->options().should_retain_symbol(name))
	{
	  lv.set_no_output_symtab_entry();
	  continue;
	}

      // Add the symbol to the symbol table string pool.
      pool->add(name, true, NULL);
      ++count;
    }

  this->output_local_symbol_count_ = count;
  this->output_local_dynsym_count_ = dyncount;
}

// Compute the final value of a local symbol.

template<int size, bool big_endian>
typename Sized_relobj_file<size, big_endian>::Compute_final_local_value_status
Sized_relobj_file<size, big_endian>::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)
{
  // We are going to overwrite *LV_OUT, if it has a merged symbol value,
  // we may have a memory leak.
  gold_assert(lv_out->has_output_value());

  bool is_ordinary;
  unsigned int shndx = lv_in->input_shndx(&is_ordinary);

  // Set the output symbol value.

  if (!is_ordinary)
    {
      if (shndx == elfcpp::SHN_ABS || Symbol::is_common_shndx(shndx))
	lv_out->set_output_value(lv_in->input_value());
      else
	{
	  this->error(_("unknown section index %u for local symbol %u"),
		      shndx, r_sym);
	  lv_out->set_output_value(0);
	  return This::CFLV_ERROR;
	}
    }
  else
    {
      if (shndx >= this->shnum())
	{
	  this->error(_("local symbol %u section index %u out of range"),
		      r_sym, shndx);
	  lv_out->set_output_value(0);
	  return This::CFLV_ERROR;
	}

      Output_section* os = out_sections[shndx];
      Address secoffset = out_offsets[shndx];
      if (symtab->is_section_folded(this, shndx))
	{
	  gold_assert(os == NULL && secoffset == invalid_address);
	  // Get the os of the section it is folded onto.
	  Section_id folded = symtab->icf()->get_folded_section(this,
								shndx);
	  gold_assert(folded.first != NULL);
	  Sized_relobj_file<size, big_endian>* folded_obj = reinterpret_cast
	    <Sized_relobj_file<size, big_endian>*>(folded.first);
	  os = folded_obj->output_section(folded.second);
	  gold_assert(os != NULL);
	  secoffset = folded_obj->get_output_section_offset(folded.second);

	  // This could be a relaxed input section.
	  if (secoffset == invalid_address)
	    {
	      const Output_relaxed_input_section* relaxed_section =
		os->find_relaxed_input_section(folded_obj, folded.second);
	      gold_assert(relaxed_section != NULL);
	      secoffset = relaxed_section->address() - os->address();
	    }
	}

      if (os == NULL)
	{
	  // This local symbol belongs to a section we are discarding.
	  // In some cases when applying relocations later, we will
	  // attempt to match it to the corresponding kept section,
	  // so we leave the input value unchanged here.
	  return This::CFLV_DISCARDED;
	}
      else if (secoffset == invalid_address)
	{
	  uint64_t start;

	  // This is a SHF_MERGE section or one which otherwise
	  // requires special handling.
	  if (os->order() == ORDER_EHFRAME)
	    {
	      // This local symbol belongs to a discarded or optimized
	      // .eh_frame section.  Just treat it like the case in which
	      // os == NULL above.
	      gold_assert(this->has_eh_frame_);
	      return This::CFLV_DISCARDED;
	    }
	  else if (!lv_in->is_section_symbol())
	    {
	      // This is not a section symbol.  We can determine
	      // the final value now.
	      uint64_t value =
		os->output_address(this, shndx, lv_in->input_value());
	      if (relocatable)
		value -= os->address();
	      lv_out->set_output_value(value);
	    }
	  else if (!os->find_starting_output_address(this, shndx, &start))
	    {
	      // This is a section symbol, but apparently not one in a
	      // merged section.  First check to see if this is a relaxed
	      // input section.  If so, use its address.  Otherwise just
	      // use the start of the output section.  This happens with
	      // relocatable links when the input object has section
	      // symbols for arbitrary non-merge sections.
	      const Output_section_data* posd =
		os->find_relaxed_input_section(this, shndx);
	      if (posd != NULL)
		{
		  uint64_t value = posd->address();
		  if (relocatable)
		    value -= os->address();
		  lv_out->set_output_value(value);
		}
	      else
		lv_out->set_output_value(os->address());
	    }
	  else
	    {
	      // We have to consider the addend to determine the
	      // value to use in a relocation.  START is the start
	      // of this input section.  If we are doing a relocatable
	      // link, use offset from start output section instead of
	      // address.
	      Address adjusted_start =
		relocatable ? start - os->address() : start;
	      Merged_symbol_value<size>* msv =
		new Merged_symbol_value<size>(lv_in->input_value(),
					      adjusted_start);
	      lv_out->set_merged_symbol_value(msv);
	    }
	}
      else if (lv_in->is_tls_symbol()
               || (lv_in->is_section_symbol()
                   && (os->flags() & elfcpp::SHF_TLS)))
	lv_out->set_output_value(os->tls_offset()
				 + secoffset
				 + lv_in->input_value());
      else
	lv_out->set_output_value((relocatable ? 0 : os->address())
				 + secoffset
				 + lv_in->input_value());
    }
  return This::CFLV_OK;
}

// Compute final local symbol value.  R_SYM is the index of a local
// symbol in symbol table.  LV points to a symbol value, which is
// expected to hold the input value and to be over-written by the
// final value.  SYMTAB points to a symbol table.  Some targets may want
// to know would-be-finalized local symbol values in relaxation.
// Hence we provide this method.  Since this method updates *LV, a
// callee should make a copy of the original local symbol value and
// use the copy instead of modifying an object's local symbols before
// everything is finalized.  The caller should also free up any allocated
// memory in the return value in *LV.
template<int size, bool big_endian>
typename Sized_relobj_file<size, big_endian>::Compute_final_local_value_status
Sized_relobj_file<size, big_endian>::compute_final_local_value(
    unsigned int r_sym,
    const Symbol_value<size>* lv_in,
    Symbol_value<size>* lv_out,
    const Symbol_table* symtab)
{
  // This is just a wrapper of compute_final_local_value_internal.
  const bool relocatable = parameters->options().relocatable();
  const Output_sections& out_sections(this->output_sections());
  const std::vector<Address>& out_offsets(this->section_offsets());
  return this->compute_final_local_value_internal(r_sym, lv_in, lv_out,
						  relocatable, out_sections,
						  out_offsets, symtab);
}

// Finalize the local symbols.  Here we set the final value in
// THIS->LOCAL_VALUES_ and set their output symbol table indexes.
// This function is always called from a singleton thread.  The actual
// output of the local symbols will occur in a separate task.

template<int size, bool big_endian>
unsigned int
Sized_relobj_file<size, big_endian>::do_finalize_local_symbols(
    unsigned int index,
    off_t off,
    Symbol_table* symtab)
{
  gold_assert(off == static_cast<off_t>(align_address(off, size >> 3)));

  const unsigned int loccount = this->local_symbol_count_;
  this->local_symbol_offset_ = off;

  const bool relocatable = parameters->options().relocatable();
  const Output_sections& out_sections(this->output_sections());
  const std::vector<Address>& out_offsets(this->section_offsets());

  for (unsigned int i = 1; i < loccount; ++i)
    {
      Symbol_value<size>* lv = &this->local_values_[i];

      Compute_final_local_value_status cflv_status =
	this->compute_final_local_value_internal(i, lv, lv, relocatable,
						 out_sections, out_offsets,
						 symtab);
      switch (cflv_status)
	{
	case CFLV_OK:
	  if (!lv->is_output_symtab_index_set())
	    {
	      lv->set_output_symtab_index(index);
	      ++index;
	    }
	  break;
	case CFLV_DISCARDED:
	case CFLV_ERROR:
	  // Do nothing.
	  break;
	default:
	  gold_unreachable();
	}
    }
  return index;
}

// Set the output dynamic symbol table indexes for the local variables.

template<int size, bool big_endian>
unsigned int
Sized_relobj_file<size, big_endian>::do_set_local_dynsym_indexes(
    unsigned int index)
{
  const unsigned int loccount = this->local_symbol_count_;
  for (unsigned int i = 1; i < loccount; ++i)
    {
      Symbol_value<size>& lv(this->local_values_[i]);
      if (lv.needs_output_dynsym_entry())
	{
	  lv.set_output_dynsym_index(index);
	  ++index;
	}
    }
  return index;
}

// Set the offset where local dynamic symbol information will be stored.
// Returns the count of local symbols contributed to the symbol table by
// this object.

template<int size, bool big_endian>
unsigned int
Sized_relobj_file<size, big_endian>::do_set_local_dynsym_offset(off_t off)
{
  gold_assert(off == static_cast<off_t>(align_address(off, size >> 3)));
  this->local_dynsym_offset_ = off;
  return this->output_local_dynsym_count_;
}

// If Symbols_data is not NULL get the section flags from here otherwise
// get it from the file.

template<int size, bool big_endian>
uint64_t
Sized_relobj_file<size, big_endian>::do_section_flags(unsigned int shndx)
{
  Symbols_data* sd = this->get_symbols_data();
  if (sd != NULL)
    {
      const unsigned char* pshdrs = sd->section_headers_data
				    + This::shdr_size * shndx;
      typename This::Shdr shdr(pshdrs);
      return shdr.get_sh_flags();
    }
  // If sd is NULL, read the section header from the file.
  return this->elf_file_.section_flags(shndx);
}

// Get the section's ent size from Symbols_data.  Called by get_section_contents
// in icf.cc

template<int size, bool big_endian>
uint64_t
Sized_relobj_file<size, big_endian>::do_section_entsize(unsigned int shndx)
{
  Symbols_data* sd = this->get_symbols_data();
  gold_assert(sd != NULL);

  const unsigned char* pshdrs = sd->section_headers_data
				+ This::shdr_size * shndx;
  typename This::Shdr shdr(pshdrs);
  return shdr.get_sh_entsize();
}

// Write out the local symbols.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::write_local_symbols(
    Output_file* of,
    const Stringpool* sympool,
    const Stringpool* dynpool,
    Output_symtab_xindex* symtab_xindex,
    Output_symtab_xindex* dynsym_xindex,
    off_t symtab_off)
{
  const bool strip_all = parameters->options().strip_all();
  if (strip_all)
    {
      if (this->output_local_dynsym_count_ == 0)
	return;
      this->output_local_symbol_count_ = 0;
    }

  gold_assert(this->symtab_shndx_ != -1U);
  if (this->symtab_shndx_ == 0)
    {
      // This object has no symbols.  Weird but legal.
      return;
    }

  // Read the symbol table section header.
  const unsigned int symtab_shndx = this->symtab_shndx_;
  typename This::Shdr symtabshdr(this,
				 this->elf_file_.section_header(symtab_shndx));
  gold_assert(symtabshdr.get_sh_type() == elfcpp::SHT_SYMTAB);
  const unsigned int loccount = this->local_symbol_count_;
  gold_assert(loccount == symtabshdr.get_sh_info());

  // Read the local symbols.
  const int sym_size = This::sym_size;
  off_t locsize = loccount * sym_size;
  const unsigned char* psyms = this->get_view(symtabshdr.get_sh_offset(),
					      locsize, true, false);

  // Read the symbol names.
  const unsigned int strtab_shndx =
    this->adjust_shndx(symtabshdr.get_sh_link());
  section_size_type strtab_size;
  const unsigned char* pnamesu = this->section_contents(strtab_shndx,
							&strtab_size,
							false);
  const char* pnames = reinterpret_cast<const char*>(pnamesu);

  // Get views into the output file for the portions of the symbol table
  // and the dynamic symbol table that we will be writing.
  off_t output_size = this->output_local_symbol_count_ * sym_size;
  unsigned char* oview = NULL;
  if (output_size > 0)
    oview = of->get_output_view(symtab_off + this->local_symbol_offset_,
				output_size);

  off_t dyn_output_size = this->output_local_dynsym_count_ * sym_size;
  unsigned char* dyn_oview = NULL;
  if (dyn_output_size > 0)
    dyn_oview = of->get_output_view(this->local_dynsym_offset_,
				    dyn_output_size);

  const Output_sections& out_sections(this->output_sections());

  gold_assert(this->local_values_.size() == loccount);

  unsigned char* ov = oview;
  unsigned char* dyn_ov = dyn_oview;
  psyms += sym_size;
  for (unsigned int i = 1; i < loccount; ++i, psyms += sym_size)
    {
      elfcpp::Sym<size, big_endian> isym(psyms);

      Symbol_value<size>& lv(this->local_values_[i]);

      bool is_ordinary;
      unsigned int st_shndx = this->adjust_sym_shndx(i, isym.get_st_shndx(),
						     &is_ordinary);
      if (is_ordinary)
	{
	  gold_assert(st_shndx < out_sections.size());
	  if (out_sections[st_shndx] == NULL)
	    continue;
	  st_shndx = out_sections[st_shndx]->out_shndx();
	  if (st_shndx >= elfcpp::SHN_LORESERVE)
	    {
	      if (lv.has_output_symtab_entry())
		symtab_xindex->add(lv.output_symtab_index(), st_shndx);
	      if (lv.has_output_dynsym_entry())
		dynsym_xindex->add(lv.output_dynsym_index(), st_shndx);
	      st_shndx = elfcpp::SHN_XINDEX;
	    }
	}

      // Write the symbol to the output symbol table.
      if (lv.has_output_symtab_entry())
	{
	  elfcpp::Sym_write<size, big_endian> osym(ov);

	  gold_assert(isym.get_st_name() < strtab_size);
	  const char* name = pnames + isym.get_st_name();
	  osym.put_st_name(sympool->get_offset(name));
	  osym.put_st_value(lv.value(this, 0));
	  osym.put_st_size(isym.get_st_size());
	  osym.put_st_info(isym.get_st_info());
	  osym.put_st_other(isym.get_st_other());
	  osym.put_st_shndx(st_shndx);

	  ov += sym_size;
	}

      // Write the symbol to the output dynamic symbol table.
      if (lv.has_output_dynsym_entry())
	{
	  gold_assert(dyn_ov < dyn_oview + dyn_output_size);
	  elfcpp::Sym_write<size, big_endian> osym(dyn_ov);

	  gold_assert(isym.get_st_name() < strtab_size);
	  const char* name = pnames + isym.get_st_name();
	  osym.put_st_name(dynpool->get_offset(name));
	  osym.put_st_value(lv.value(this, 0));
	  osym.put_st_size(isym.get_st_size());
	  osym.put_st_info(isym.get_st_info());
	  osym.put_st_other(isym.get_st_other());
	  osym.put_st_shndx(st_shndx);

	  dyn_ov += sym_size;
	}
    }


  if (output_size > 0)
    {
      gold_assert(ov - oview == output_size);
      of->write_output_view(symtab_off + this->local_symbol_offset_,
			    output_size, oview);
    }

  if (dyn_output_size > 0)
    {
      gold_assert(dyn_ov - dyn_oview == dyn_output_size);
      of->write_output_view(this->local_dynsym_offset_, dyn_output_size,
			    dyn_oview);
    }
}

// Set *INFO to symbolic information about the offset OFFSET in the
// section SHNDX.  Return true if we found something, false if we
// found nothing.

template<int size, bool big_endian>
bool
Sized_relobj_file<size, big_endian>::get_symbol_location_info(
    unsigned int shndx,
    off_t offset,
    Symbol_location_info* info)
{
  if (this->symtab_shndx_ == 0)
    return false;

  section_size_type symbols_size;
  const unsigned char* symbols = this->section_contents(this->symtab_shndx_,
							&symbols_size,
							false);

  unsigned int symbol_names_shndx =
    this->adjust_shndx(this->section_link(this->symtab_shndx_));
  section_size_type names_size;
  const unsigned char* symbol_names_u =
    this->section_contents(symbol_names_shndx, &names_size, false);
  const char* symbol_names = reinterpret_cast<const char*>(symbol_names_u);

  const int sym_size = This::sym_size;
  const size_t count = symbols_size / sym_size;

  const unsigned char* p = symbols;
  for (size_t i = 0; i < count; ++i, p += sym_size)
    {
      elfcpp::Sym<size, big_endian> sym(p);

      if (sym.get_st_type() == elfcpp::STT_FILE)
	{
	  if (sym.get_st_name() >= names_size)
	    info->source_file = "(invalid)";
	  else
	    info->source_file = symbol_names + sym.get_st_name();
	  continue;
	}

      bool is_ordinary;
      unsigned int st_shndx = this->adjust_sym_shndx(i, sym.get_st_shndx(),
						     &is_ordinary);
      if (is_ordinary
	  && st_shndx == shndx
	  && static_cast<off_t>(sym.get_st_value()) <= offset
	  && (static_cast<off_t>(sym.get_st_value() + sym.get_st_size())
	      > offset))
	{
	  info->enclosing_symbol_type = sym.get_st_type();
	  if (sym.get_st_name() > names_size)
	    info->enclosing_symbol_name = "(invalid)";
	  else
	    {
	      info->enclosing_symbol_name = symbol_names + sym.get_st_name();
	      if (parameters->options().do_demangle())
		{
		  char* demangled_name = cplus_demangle(
		      info->enclosing_symbol_name.c_str(),
		      DMGL_ANSI | DMGL_PARAMS);
		  if (demangled_name != NULL)
		    {
		      info->enclosing_symbol_name.assign(demangled_name);
		      free(demangled_name);
		    }
		}
	    }
	  return true;
	}
    }

  return false;
}

// 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.  If we can't find the kept section, return 0.

template<int size, bool big_endian>
typename Sized_relobj_file<size, big_endian>::Address
Sized_relobj_file<size, big_endian>::map_to_kept_section(
    unsigned int shndx,
    std::string& section_name,
    bool* pfound) const
{
  Kept_section* kept_section;
  bool is_comdat;
  uint64_t sh_size;
  unsigned int symndx;
  bool found = false;

  if (this->get_kept_comdat_section(shndx, &is_comdat, &symndx, &sh_size,
				    &kept_section))
    {
      Relobj* kept_object = kept_section->object();
      unsigned int kept_shndx = 0;
      if (!kept_section->is_comdat())
        {
	  // The kept section is a linkonce section.
	  if (sh_size == kept_section->linkonce_size())
	    found = true;
        }
      else
	{
	  if (is_comdat)
	    {
	      // Find the corresponding kept section.
	      // Since we're using this mapping for relocation processing,
	      // we don't want to match sections unless they have the same
	      // size.
	      uint64_t kept_size;
	      if (kept_section->find_comdat_section(section_name, &kept_shndx,
						    &kept_size))
		{
		  if (sh_size == kept_size)
		    found = true;
		}
	    }
	  else
	    {
	      uint64_t kept_size;
	      if (kept_section->find_single_comdat_section(&kept_shndx,
							   &kept_size)
		  && sh_size == kept_size)
		found = true;
	    }
	}

      if (found)
	{
	  Sized_relobj_file<size, big_endian>* kept_relobj =
	    static_cast<Sized_relobj_file<size, big_endian>*>(kept_object);
	  Output_section* os = kept_relobj->output_section(kept_shndx);
	  Address offset = kept_relobj->get_output_section_offset(kept_shndx);
	  if (os != NULL && offset != invalid_address)
	    {
	      *pfound = true;
	      return os->address() + offset;
	    }
	}
    }
  *pfound = false;
  return 0;
}

// Look for a kept section corresponding to the given discarded section,
// and return its object file.

template<int size, bool big_endian>
Relobj*
Sized_relobj_file<size, big_endian>::find_kept_section_object(
    unsigned int shndx, unsigned int *symndx_p) const
{
  Kept_section* kept_section;
  bool is_comdat;
  uint64_t sh_size;
  if (this->get_kept_comdat_section(shndx, &is_comdat, symndx_p, &sh_size,
				    &kept_section))
    return kept_section->object();
  return NULL;
}

// Return the name of symbol SYMNDX.

template<int size, bool big_endian>
const char*
Sized_relobj_file<size, big_endian>::get_symbol_name(unsigned int symndx)
{
  if (this->symtab_shndx_ == 0)
    return NULL;

  section_size_type symbols_size;
  const unsigned char* symbols = this->section_contents(this->symtab_shndx_,
							&symbols_size,
							false);

  unsigned int symbol_names_shndx =
    this->adjust_shndx(this->section_link(this->symtab_shndx_));
  section_size_type names_size;
  const unsigned char* symbol_names_u =
    this->section_contents(symbol_names_shndx, &names_size, false);
  const char* symbol_names = reinterpret_cast<const char*>(symbol_names_u);

  const unsigned char* p = symbols + symndx * This::sym_size;

  if (p >= symbols + symbols_size)
    return NULL;

  elfcpp::Sym<size, big_endian> sym(p);

  return symbol_names + sym.get_st_name();
}

// Get symbol counts.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::do_get_global_symbol_counts(
    const Symbol_table*,
    size_t* defined,
    size_t* used) const
{
  *defined = this->defined_count_;
  size_t count = 0;
  for (typename Symbols::const_iterator p = this->symbols_.begin();
       p != this->symbols_.end();
       ++p)
    if (*p != NULL
	&& (*p)->source() == Symbol::FROM_OBJECT
	&& (*p)->object() == this
	&& (*p)->is_defined())
      ++count;
  *used = count;
}

// 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*
Object::decompressed_section_contents(
    unsigned int shndx,
    section_size_type* plen,
    bool* is_new)
{
  section_size_type buffer_size;
  const unsigned char* buffer = this->do_section_contents(shndx, &buffer_size,
							  false);

  if (this->compressed_sections_ == NULL)
    {
      *plen = buffer_size;
      *is_new = false;
      return buffer;
    }

  Compressed_section_map::const_iterator p =
      this->compressed_sections_->find(shndx);
  if (p == this->compressed_sections_->end())
    {
      *plen = buffer_size;
      *is_new = false;
      return buffer;
    }

  section_size_type uncompressed_size = p->second.size;
  if (p->second.contents != NULL)
    {
      *plen = uncompressed_size;
      *is_new = false;
      return p->second.contents;
    }

  unsigned char* uncompressed_data = new unsigned char[uncompressed_size];
  if (!decompress_input_section(buffer,
				buffer_size,
				uncompressed_data,
				uncompressed_size,
				elfsize(),
				is_big_endian(),
				p->second.flag))
    this->error(_("could not decompress section %s"),
		this->do_section_name(shndx).c_str());

  // We could cache the results in p->second.contents and store
  // false in *IS_NEW, but build_compressed_section_map() would
  // have done so if it had expected it to be profitable.  If
  // we reach this point, we expect to need the contents only
  // once in this pass.
  *plen = uncompressed_size;
  *is_new = true;
  return uncompressed_data;
}

// Discard any buffers of uncompressed sections.  This is done
// at the end of the Add_symbols task.

void
Object::discard_decompressed_sections()
{
  if (this->compressed_sections_ == NULL)
    return;

  for (Compressed_section_map::iterator p = this->compressed_sections_->begin();
       p != this->compressed_sections_->end();
       ++p)
    {
      if (p->second.contents != NULL)
	{
	  delete[] p->second.contents;
	  p->second.contents = NULL;
	}
    }
}

// Input_objects methods.

// Add a regular relocatable object to the list.  Return false if this
// object should be ignored.

bool
Input_objects::add_object(Object* obj)
{
  // Print the filename if the -t/--trace option is selected.
  if (parameters->options().trace())
    gold_info("%s", obj->name().c_str());

  if (!obj->is_dynamic())
    this->relobj_list_.push_back(static_cast<Relobj*>(obj));
  else
    {
      // See if this is a duplicate SONAME.
      Dynobj* dynobj = static_cast<Dynobj*>(obj);
      const char* soname = dynobj->soname();

      Unordered_map<std::string, Object*>::value_type val(soname, obj);
      std::pair<Unordered_map<std::string, Object*>::iterator, bool> ins =
	this->sonames_.insert(val);
      if (!ins.second)
	{
	  // We have already seen a dynamic object with this soname.
	  // If any instances of this object on the command line have
	  // the --no-as-needed flag, make sure the one we keep is
	  // marked so.
	  if (!obj->as_needed())
	    {
	      gold_assert(ins.first->second != NULL);
	      ins.first->second->clear_as_needed();
	    }
	  return false;
	}

      this->dynobj_list_.push_back(dynobj);
    }

  // Add this object to the cross-referencer if requested.
  if (parameters->options().user_set_print_symbol_counts()
      || parameters->options().cref())
    {
      if (this->cref_ == NULL)
	this->cref_ = new Cref();
      this->cref_->add_object(obj);
    }

  return true;
}

// For each dynamic object, record whether we've seen all of its
// explicit dependencies.

void
Input_objects::check_dynamic_dependencies() const
{
  bool issued_copy_dt_needed_error = false;
  for (Dynobj_list::const_iterator p = this->dynobj_list_.begin();
       p != this->dynobj_list_.end();
       ++p)
    {
      const Dynobj::Needed& needed((*p)->needed());
      bool found_all = true;
      Dynobj::Needed::const_iterator pneeded;
      for (pneeded = needed.begin(); pneeded != needed.end(); ++pneeded)
	{
	  if (this->sonames_.find(*pneeded) == this->sonames_.end())
	    {
	      found_all = false;
	      break;
	    }
	}
      (*p)->set_has_unknown_needed_entries(!found_all);

      // --copy-dt-needed-entries aka --add-needed is a GNU ld option
      // that gold does not support.  However, they cause no trouble
      // unless there is a DT_NEEDED entry that we don't know about;
      // warn only in that case.
      if (!found_all
	  && !issued_copy_dt_needed_error
	  && (parameters->options().copy_dt_needed_entries()
	      || parameters->options().add_needed()))
	{
	  const char* optname;
	  if (parameters->options().copy_dt_needed_entries())
	    optname = "--copy-dt-needed-entries";
	  else
	    optname = "--add-needed";
	  gold_error(_("%s is not supported but is required for %s in %s"),
		     optname, (*pneeded).c_str(), (*p)->name().c_str());
	  issued_copy_dt_needed_error = true;
	}
    }
}

// Start processing an archive.

void
Input_objects::archive_start(Archive* archive)
{
  if (parameters->options().user_set_print_symbol_counts()
      || parameters->options().cref())
    {
      if (this->cref_ == NULL)
	this->cref_ = new Cref();
      this->cref_->add_archive_start(archive);
    }
}

// Stop processing an archive.

void
Input_objects::archive_stop(Archive* archive)
{
  if (parameters->options().user_set_print_symbol_counts()
      || parameters->options().cref())
    this->cref_->add_archive_stop(archive);
}

// Print symbol counts

void
Input_objects::print_symbol_counts(const Symbol_table* symtab) const
{
  if (parameters->options().user_set_print_symbol_counts()
      && this->cref_ != NULL)
    this->cref_->print_symbol_counts(symtab);
}

// Print a cross reference table.

void
Input_objects::print_cref(const Symbol_table* symtab, FILE* f) const
{
  if (parameters->options().cref() && this->cref_ != NULL)
    this->cref_->print_cref(symtab, f);
}

// Relocate_info methods.

// Return a string describing the location of a relocation when file
// and lineno information is not available.  This is only used in
// error messages.

template<int size, bool big_endian>
std::string
Relocate_info<size, big_endian>::location(size_t, off_t offset) const
{
  Sized_dwarf_line_info<size, big_endian> line_info(this->object);
  std::string ret = line_info.addr2line(this->data_shndx, offset, NULL);
  if (!ret.empty())
    return ret;

  ret = this->object->name();

  Symbol_location_info info;
  if (this->object->get_symbol_location_info(this->data_shndx, offset, &info))
    {
      if (!info.source_file.empty())
	{
	  ret += ":";
	  ret += info.source_file;
	}
      ret += ":";
      if (info.enclosing_symbol_type == elfcpp::STT_FUNC)
	ret += _("function ");
      ret += info.enclosing_symbol_name;
      return ret;
    }

  ret += "(";
  ret += this->object->section_name(this->data_shndx);
  char buf[100];
  snprintf(buf, sizeof buf, "+0x%lx)", static_cast<long>(offset));
  ret += buf;
  return ret;
}

} // End namespace gold.

namespace
{

using namespace gold;

// Read an ELF file with the header and return the appropriate
// instance of Object.

template<int size, bool big_endian>
Object*
make_elf_sized_object(const std::string& name, Input_file* input_file,
		      off_t offset, const elfcpp::Ehdr<size, big_endian>& ehdr,
		      bool* punconfigured)
{
  Target* target = select_target(input_file, offset,
				 ehdr.get_e_machine(), size, big_endian,
				 ehdr.get_e_ident()[elfcpp::EI_OSABI],
				 ehdr.get_e_ident()[elfcpp::EI_ABIVERSION]);
  if (target == NULL)
    gold_fatal(_("%s: unsupported ELF machine number %d"),
	       name.c_str(), ehdr.get_e_machine());

  if (!parameters->target_valid())
    set_parameters_target(target);
  else if (target != &parameters->target())
    {
      if (punconfigured != NULL)
	*punconfigured = true;
      else
	gold_error(_("%s: incompatible target"), name.c_str());
      return NULL;
    }

  return target->make_elf_object<size, big_endian>(name, input_file, offset,
						   ehdr);
}

} // End anonymous namespace.

namespace gold
{

// Return whether INPUT_FILE is an ELF object.

bool
is_elf_object(Input_file* input_file, off_t offset,
	      const unsigned char** start, int* read_size)
{
  off_t filesize = input_file->file().filesize();
  int want = elfcpp::Elf_recognizer::max_header_size;
  if (filesize - offset < want)
    want = filesize - offset;

  const unsigned char* p = input_file->file().get_view(offset, 0, want,
						       true, false);
  *start = p;
  *read_size = want;

  return elfcpp::Elf_recognizer::is_elf_file(p, want);
}

// Read an ELF file and return the appropriate instance of Object.

Object*
make_elf_object(const std::string& name, Input_file* input_file, off_t offset,
		const unsigned char* p, section_offset_type bytes,
		bool* punconfigured)
{
  if (punconfigured != NULL)
    *punconfigured = false;

  std::string error;
  bool big_endian = false;
  int size = 0;
  if (!elfcpp::Elf_recognizer::is_valid_header(p, bytes, &size,
					       &big_endian, &error))
    {
      gold_error(_("%s: %s"), name.c_str(), error.c_str());
      return NULL;
    }

  if (size == 32)
    {
      if (big_endian)
	{
#ifdef HAVE_TARGET_32_BIG
	  elfcpp::Ehdr<32, true> ehdr(p);
	  return make_elf_sized_object<32, true>(name, input_file,
						 offset, ehdr, punconfigured);
#else
	  if (punconfigured != NULL)
	    *punconfigured = true;
	  else
	    gold_error(_("%s: not configured to support "
			 "32-bit big-endian object"),
		       name.c_str());
	  return NULL;
#endif
	}
      else
	{
#ifdef HAVE_TARGET_32_LITTLE
	  elfcpp::Ehdr<32, false> ehdr(p);
	  return make_elf_sized_object<32, false>(name, input_file,
						  offset, ehdr, punconfigured);
#else
	  if (punconfigured != NULL)
	    *punconfigured = true;
	  else
	    gold_error(_("%s: not configured to support "
			 "32-bit little-endian object"),
		       name.c_str());
	  return NULL;
#endif
	}
    }
  else if (size == 64)
    {
      if (big_endian)
	{
#ifdef HAVE_TARGET_64_BIG
	  elfcpp::Ehdr<64, true> ehdr(p);
	  return make_elf_sized_object<64, true>(name, input_file,
						 offset, ehdr, punconfigured);
#else
	  if (punconfigured != NULL)
	    *punconfigured = true;
	  else
	    gold_error(_("%s: not configured to support "
			 "64-bit big-endian object"),
		       name.c_str());
	  return NULL;
#endif
	}
      else
	{
#ifdef HAVE_TARGET_64_LITTLE
	  elfcpp::Ehdr<64, false> ehdr(p);
	  return make_elf_sized_object<64, false>(name, input_file,
						  offset, ehdr, punconfigured);
#else
	  if (punconfigured != NULL)
	    *punconfigured = true;
	  else
	    gold_error(_("%s: not configured to support "
			 "64-bit little-endian object"),
		       name.c_str());
	  return NULL;
#endif
	}
    }
  else
    gold_unreachable();
}

// Instantiate the templates we need.

#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
template
void
Relobj::initialize_input_to_output_map<64>(unsigned int shndx,
      elfcpp::Elf_types<64>::Elf_Addr starting_address,
      Unordered_map<section_offset_type,
      elfcpp::Elf_types<64>::Elf_Addr>* output_addresses) const;
#endif

#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
template
void
Relobj::initialize_input_to_output_map<32>(unsigned int shndx,
      elfcpp::Elf_types<32>::Elf_Addr starting_address,
      Unordered_map<section_offset_type,
      elfcpp::Elf_types<32>::Elf_Addr>* output_addresses) const;
#endif

#ifdef HAVE_TARGET_32_LITTLE
template
void
Object::read_section_data<32, false>(elfcpp::Elf_file<32, false, Object>*,
				     Read_symbols_data*);
template
const unsigned char*
Object::find_shdr<32,false>(const unsigned char*, const char*, const char*,
			    section_size_type, const unsigned char*) const;
#endif

#ifdef HAVE_TARGET_32_BIG
template
void
Object::read_section_data<32, true>(elfcpp::Elf_file<32, true, Object>*,
				    Read_symbols_data*);
template
const unsigned char*
Object::find_shdr<32,true>(const unsigned char*, const char*, const char*,
			   section_size_type, const unsigned char*) const;
#endif

#ifdef HAVE_TARGET_64_LITTLE
template
void
Object::read_section_data<64, false>(elfcpp::Elf_file<64, false, Object>*,
				     Read_symbols_data*);
template
const unsigned char*
Object::find_shdr<64,false>(const unsigned char*, const char*, const char*,
			    section_size_type, const unsigned char*) const;
#endif

#ifdef HAVE_TARGET_64_BIG
template
void
Object::read_section_data<64, true>(elfcpp::Elf_file<64, true, Object>*,
				    Read_symbols_data*);
template
const unsigned char*
Object::find_shdr<64,true>(const unsigned char*, const char*, const char*,
			   section_size_type, const unsigned char*) const;
#endif

#ifdef HAVE_TARGET_32_LITTLE
template
class Sized_relobj<32, false>;

template
class Sized_relobj_file<32, false>;
#endif

#ifdef HAVE_TARGET_32_BIG
template
class Sized_relobj<32, true>;

template
class Sized_relobj_file<32, true>;
#endif

#ifdef HAVE_TARGET_64_LITTLE
template
class Sized_relobj<64, false>;

template
class Sized_relobj_file<64, false>;
#endif

#ifdef HAVE_TARGET_64_BIG
template
class Sized_relobj<64, true>;

template
class Sized_relobj_file<64, true>;
#endif

#ifdef HAVE_TARGET_32_LITTLE
template
struct Relocate_info<32, false>;
#endif

#ifdef HAVE_TARGET_32_BIG
template
struct Relocate_info<32, true>;
#endif

#ifdef HAVE_TARGET_64_LITTLE
template
struct Relocate_info<64, false>;
#endif

#ifdef HAVE_TARGET_64_BIG
template
struct Relocate_info<64, true>;
#endif

#ifdef HAVE_TARGET_32_LITTLE
template
void
Xindex::initialize_symtab_xindex<32, false>(Object*, unsigned int);

template
void
Xindex::read_symtab_xindex<32, false>(Object*, unsigned int,
				      const unsigned char*);
#endif

#ifdef HAVE_TARGET_32_BIG
template
void
Xindex::initialize_symtab_xindex<32, true>(Object*, unsigned int);

template
void
Xindex::read_symtab_xindex<32, true>(Object*, unsigned int,
				     const unsigned char*);
#endif

#ifdef HAVE_TARGET_64_LITTLE
template
void
Xindex::initialize_symtab_xindex<64, false>(Object*, unsigned int);

template
void
Xindex::read_symtab_xindex<64, false>(Object*, unsigned int,
				      const unsigned char*);
#endif

#ifdef HAVE_TARGET_64_BIG
template
void
Xindex::initialize_symtab_xindex<64, true>(Object*, unsigned int);

template
void
Xindex::read_symtab_xindex<64, true>(Object*, unsigned int,
				     const unsigned char*);
#endif

#ifdef HAVE_TARGET_32_LITTLE
template
Compressed_section_map*
build_compressed_section_map<32, false>(const unsigned char*, unsigned int,
					const char*, section_size_type, 
					Object*, bool);
#endif

#ifdef HAVE_TARGET_32_BIG
template
Compressed_section_map*
build_compressed_section_map<32, true>(const unsigned char*, unsigned int,
					const char*, section_size_type, 
					Object*, bool);
#endif

#ifdef HAVE_TARGET_64_LITTLE
template
Compressed_section_map*
build_compressed_section_map<64, false>(const unsigned char*, unsigned int,
					const char*, section_size_type, 
					Object*, bool);
#endif

#ifdef HAVE_TARGET_64_BIG
template
Compressed_section_map*
build_compressed_section_map<64, true>(const unsigned char*, unsigned int,
					const char*, section_size_type, 
					Object*, bool);
#endif

} // End namespace gold.
