// reloc.cc -- relocate input files for gold.

// Copyright 2006, 2007, 2008, 2009, 2010, 2011 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 <algorithm>

#include "workqueue.h"
#include "layout.h"
#include "symtab.h"
#include "output.h"
#include "merge.h"
#include "object.h"
#include "target-reloc.h"
#include "reloc.h"
#include "icf.h"
#include "compressed_output.h"
#include "incremental.h"

namespace gold
{

// Read_relocs methods.

// These tasks just read the relocation information from the file.
// After reading it, the start another task to process the
// information.  These tasks requires access to the file.

Task_token*
Read_relocs::is_runnable()
{
  return this->object_->is_locked() ? this->object_->token() : NULL;
}

// Lock the file.

void
Read_relocs::locks(Task_locker* tl)
{
  Task_token* token = this->object_->token();
  if (token != NULL)
    tl->add(this, token);
}

// Read the relocations and then start a Scan_relocs_task.

void
Read_relocs::run(Workqueue* workqueue)
{
  Read_relocs_data* rd = new Read_relocs_data;
  this->object_->read_relocs(rd);
  this->object_->set_relocs_data(rd);
  this->object_->release();

  // If garbage collection or identical comdat folding is desired, we  
  // process the relocs first before scanning them.  Scanning of relocs is
  // done only after garbage or identical sections is identified.
  if (parameters->options().gc_sections()
      || parameters->options().icf_enabled())
    {
      workqueue->queue_next(new Gc_process_relocs(this->symtab_,
                                                  this->layout_, 
                                                  this->object_, rd,
                                                  this->this_blocker_,
						  this->next_blocker_));
    }
  else
    {
      workqueue->queue_next(new Scan_relocs(this->symtab_, this->layout_,
					    this->object_, rd,
                                            this->this_blocker_,
					    this->next_blocker_));
    }
}

// Return a debugging name for the task.

std::string
Read_relocs::get_name() const
{
  return "Read_relocs " + this->object_->name();
}

// Gc_process_relocs methods.

Gc_process_relocs::~Gc_process_relocs()
{
  if (this->this_blocker_ != NULL)
    delete this->this_blocker_;
}

// These tasks process the relocations read by Read_relocs and
// determine which sections are referenced and which are garbage.
// This task is done only when --gc-sections is used.  This is blocked
// by THIS_BLOCKER_.  It unblocks NEXT_BLOCKER_.

Task_token*
Gc_process_relocs::is_runnable()
{
  if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
    return this->this_blocker_;
  if (this->object_->is_locked())
    return this->object_->token();
  return NULL;
}

void
Gc_process_relocs::locks(Task_locker* tl)
{
  tl->add(this, this->object_->token());
  tl->add(this, this->next_blocker_);
}

void
Gc_process_relocs::run(Workqueue*)
{
  this->object_->gc_process_relocs(this->symtab_, this->layout_, this->rd_);
  this->object_->release();
}

// Return a debugging name for the task.

std::string
Gc_process_relocs::get_name() const
{
  return "Gc_process_relocs " + this->object_->name();
}

// Scan_relocs methods.

Scan_relocs::~Scan_relocs()
{
  if (this->this_blocker_ != NULL)
    delete this->this_blocker_;
}

// These tasks scan the relocations read by Read_relocs and mark up
// the symbol table to indicate which relocations are required.  We
// use a lock on the symbol table to keep them from interfering with
// each other.

Task_token*
Scan_relocs::is_runnable()
{
  if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
    return this->this_blocker_;
  if (this->object_->is_locked())
    return this->object_->token();
  return NULL;
}

// Return the locks we hold: one on the file, one on the symbol table
// and one blocker.

void
Scan_relocs::locks(Task_locker* tl)
{
  Task_token* token = this->object_->token();
  if (token != NULL)
    tl->add(this, token);
  tl->add(this, this->next_blocker_);
}

// Scan the relocs.

void
Scan_relocs::run(Workqueue*)
{
  this->object_->scan_relocs(this->symtab_, this->layout_, this->rd_);
  delete this->rd_;
  this->rd_ = NULL;
  this->object_->release();
}

// Return a debugging name for the task.

std::string
Scan_relocs::get_name() const
{
  return "Scan_relocs " + this->object_->name();
}

// Relocate_task methods.

// We may have to wait for the output sections to be written.

Task_token*
Relocate_task::is_runnable()
{
  if (this->object_->relocs_must_follow_section_writes()
      && this->output_sections_blocker_->is_blocked())
    return this->output_sections_blocker_;

  if (this->object_->is_locked())
    return this->object_->token();

  return NULL;
}

// We want to lock the file while we run.  We want to unblock
// INPUT_SECTIONS_BLOCKER and FINAL_BLOCKER when we are done.
// INPUT_SECTIONS_BLOCKER may be NULL.

void
Relocate_task::locks(Task_locker* tl)
{
  if (this->input_sections_blocker_ != NULL)
    tl->add(this, this->input_sections_blocker_);
  tl->add(this, this->final_blocker_);
  Task_token* token = this->object_->token();
  if (token != NULL)
    tl->add(this, token);
}

// Run the task.

void
Relocate_task::run(Workqueue*)
{
  this->object_->relocate(this->symtab_, this->layout_, this->of_);

  // This is normally the last thing we will do with an object, so
  // uncache all views.
  this->object_->clear_view_cache_marks();

  this->object_->release();
}

// Return a debugging name for the task.

std::string
Relocate_task::get_name() const
{
  return "Relocate_task " + this->object_->name();
}

// Read the relocs and local symbols from the object file and store
// the information in RD.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
{
  rd->relocs.clear();

  unsigned int shnum = this->shnum();
  if (shnum == 0)
    return;

  rd->relocs.reserve(shnum / 2);

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

  const unsigned char* pshdrs = this->get_view(this->elf_file_.shoff(),
					       shnum * This::shdr_size,
					       true, true);
  // Skip the first, dummy, section.
  const unsigned char* ps = pshdrs + This::shdr_size;
  for (unsigned int i = 1; i < shnum; ++i, ps += This::shdr_size)
    {
      typename This::Shdr shdr(ps);

      unsigned int sh_type = shdr.get_sh_type();
      if (sh_type != elfcpp::SHT_REL && sh_type != elfcpp::SHT_RELA)
	continue;

      unsigned int shndx = this->adjust_shndx(shdr.get_sh_info());
      if (shndx >= shnum)
	{
	  this->error(_("relocation section %u has bad info %u"),
		      i, shndx);
	  continue;
	}

      Output_section* os = out_sections[shndx];
      if (os == NULL)
	continue;

      // We are scanning relocations in order to fill out the GOT and
      // PLT sections.  Relocations for sections which are not
      // allocated (typically debugging sections) should not add new
      // GOT and PLT entries.  So we skip them unless this is a
      // relocatable link or we need to emit relocations.  FIXME: What
      // should we do if a linker script maps a section with SHF_ALLOC
      // clear to a section with SHF_ALLOC set?
      typename This::Shdr secshdr(pshdrs + shndx * This::shdr_size);
      bool is_section_allocated = ((secshdr.get_sh_flags() & elfcpp::SHF_ALLOC)
				   != 0);
      if (!is_section_allocated
	  && !parameters->options().relocatable()
	  && !parameters->options().emit_relocs()
	  && !parameters->incremental())
	continue;

      if (this->adjust_shndx(shdr.get_sh_link()) != this->symtab_shndx_)
	{
	  this->error(_("relocation section %u uses unexpected "
			"symbol table %u"),
		      i, this->adjust_shndx(shdr.get_sh_link()));
	  continue;
	}

      off_t sh_size = shdr.get_sh_size();

      if (sh_size == 0)
	continue;

      unsigned int reloc_size;
      if (sh_type == elfcpp::SHT_REL)
	reloc_size = elfcpp::Elf_sizes<size>::rel_size;
      else
	reloc_size = elfcpp::Elf_sizes<size>::rela_size;
      if (reloc_size != shdr.get_sh_entsize())
	{
	  this->error(_("unexpected entsize for reloc section %u: %lu != %u"),
		      i, static_cast<unsigned long>(shdr.get_sh_entsize()),
		      reloc_size);
	  continue;
	}

      size_t reloc_count = sh_size / reloc_size;
      if (static_cast<off_t>(reloc_count * reloc_size) != sh_size)
	{
	  this->error(_("reloc section %u size %lu uneven"),
		      i, static_cast<unsigned long>(sh_size));
	  continue;
	}

      rd->relocs.push_back(Section_relocs());
      Section_relocs& sr(rd->relocs.back());
      sr.reloc_shndx = i;
      sr.data_shndx = shndx;
      sr.contents = this->get_lasting_view(shdr.get_sh_offset(), sh_size,
					   true, true);
      sr.sh_type = sh_type;
      sr.reloc_count = reloc_count;
      sr.output_section = os;
      sr.needs_special_offset_handling = out_offsets[shndx] == invalid_address;
      sr.is_data_section_allocated = is_section_allocated;
    }

  // Read the local symbols.
  gold_assert(this->symtab_shndx_ != -1U);
  if (this->symtab_shndx_ == 0 || this->local_symbol_count_ == 0)
    rd->local_symbols = NULL;
  else
    {
      typename This::Shdr symtabshdr(pshdrs
				     + this->symtab_shndx_ * This::shdr_size);
      gold_assert(symtabshdr.get_sh_type() == elfcpp::SHT_SYMTAB);
      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;
      rd->local_symbols = this->get_lasting_view(symtabshdr.get_sh_offset(),
						 locsize, true, true);
    }
}

// Process the relocs to generate mappings from source sections to referenced
// sections.  This is used during garbage collection to determine garbage
// sections.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::do_gc_process_relocs(Symbol_table* symtab,
							  Layout* layout,
							  Read_relocs_data* rd)
{  
  Sized_target<size, big_endian>* target =
    parameters->sized_target<size, big_endian>();

  const unsigned char* local_symbols;
  if (rd->local_symbols == NULL)
    local_symbols = NULL;
  else
    local_symbols = rd->local_symbols->data();

  for (Read_relocs_data::Relocs_list::iterator p = rd->relocs.begin();
       p != rd->relocs.end();
       ++p)
    {
      if (!parameters->options().relocatable())
	  {
	    // As noted above, when not generating an object file, we
	    // only scan allocated sections.  We may see a non-allocated
	    // section here if we are emitting relocs.
	    if (p->is_data_section_allocated)
              target->gc_process_relocs(symtab, layout, this, 
                                        p->data_shndx, p->sh_type, 
                                        p->contents->data(), p->reloc_count, 
                                        p->output_section,
                                        p->needs_special_offset_handling,
                                        this->local_symbol_count_, 
                                        local_symbols);
        }
    }
}


// Scan the relocs and adjust the symbol table.  This looks for
// relocations which require GOT/PLT/COPY relocations.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::do_scan_relocs(Symbol_table* symtab,
					       Layout* layout,
					       Read_relocs_data* rd)
{
  Sized_target<size, big_endian>* target =
    parameters->sized_target<size, big_endian>();

  const unsigned char* local_symbols;
  if (rd->local_symbols == NULL)
    local_symbols = NULL;
  else
    local_symbols = rd->local_symbols->data();

  // For incremental links, allocate the counters for incremental relocations.
  if (layout->incremental_inputs() != NULL)
    this->allocate_incremental_reloc_counts();

  for (Read_relocs_data::Relocs_list::iterator p = rd->relocs.begin();
       p != rd->relocs.end();
       ++p)
    {
      // When garbage collection is on, unreferenced sections are not included
      // in the link that would have been included normally. This is known only
      // after Read_relocs hence this check has to be done again.
      if (parameters->options().gc_sections()
	  || parameters->options().icf_enabled())
        {
          if (p->output_section == NULL)
            continue;
        }
      if (!parameters->options().relocatable())
	{
	  // As noted above, when not generating an object file, we
	  // only scan allocated sections.  We may see a non-allocated
	  // section here if we are emitting relocs.
	  if (p->is_data_section_allocated)
	    target->scan_relocs(symtab, layout, this, p->data_shndx,
				p->sh_type, p->contents->data(),
				p->reloc_count, p->output_section,
				p->needs_special_offset_handling,
				this->local_symbol_count_,
				local_symbols);
	  if (parameters->options().emit_relocs())
	    this->emit_relocs_scan(symtab, layout, local_symbols, p);
	  if (layout->incremental_inputs() != NULL)
	    this->incremental_relocs_scan(p);
	}
      else
	{
	  Relocatable_relocs* rr = this->relocatable_relocs(p->reloc_shndx);
	  gold_assert(rr != NULL);
	  rr->set_reloc_count(p->reloc_count);
	  target->scan_relocatable_relocs(symtab, layout, this,
					  p->data_shndx, p->sh_type,
					  p->contents->data(),
					  p->reloc_count,
					  p->output_section,
					  p->needs_special_offset_handling,
					  this->local_symbol_count_,
					  local_symbols,
					  rr);
	}

      delete p->contents;
      p->contents = NULL;
    }

  // For incremental links, finalize the allocation of relocations.
  if (layout->incremental_inputs() != NULL)
    this->finalize_incremental_relocs(layout, true);

  if (rd->local_symbols != NULL)
    {
      delete rd->local_symbols;
      rd->local_symbols = NULL;
    }
}

// This is a strategy class we use when scanning for --emit-relocs.

template<int sh_type>
class Emit_relocs_strategy
{
 public:
  // A local non-section symbol.
  inline Relocatable_relocs::Reloc_strategy
  local_non_section_strategy(unsigned int, Relobj*, unsigned int)
  { return Relocatable_relocs::RELOC_COPY; }

  // A local section symbol.
  inline Relocatable_relocs::Reloc_strategy
  local_section_strategy(unsigned int, Relobj*)
  {
    if (sh_type == elfcpp::SHT_RELA)
      return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA;
    else
      {
	// The addend is stored in the section contents.  Since this
	// is not a relocatable link, we are going to apply the
	// relocation contents to the section as usual.  This means
	// that we have no way to record the original addend.  If the
	// original addend is not zero, there is basically no way for
	// the user to handle this correctly.  Caveat emptor.
	return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_0;
      }
  }

  // A global symbol.
  inline Relocatable_relocs::Reloc_strategy
  global_strategy(unsigned int, Relobj*, unsigned int)
  { return Relocatable_relocs::RELOC_COPY; }
};

// Scan the input relocations for --emit-relocs.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::emit_relocs_scan(
    Symbol_table* symtab,
    Layout* layout,
    const unsigned char* plocal_syms,
    const Read_relocs_data::Relocs_list::iterator& p)
{
  Relocatable_relocs* rr = this->relocatable_relocs(p->reloc_shndx);
  gold_assert(rr != NULL);
  rr->set_reloc_count(p->reloc_count);

  if (p->sh_type == elfcpp::SHT_REL)
    this->emit_relocs_scan_reltype<elfcpp::SHT_REL>(symtab, layout,
						    plocal_syms, p, rr);
  else
    {
      gold_assert(p->sh_type == elfcpp::SHT_RELA);
      this->emit_relocs_scan_reltype<elfcpp::SHT_RELA>(symtab, layout,
						       plocal_syms, p, rr);
    }
}

// Scan the input relocation for --emit-relocs, templatized on the
// type of the relocation section.

template<int size, bool big_endian>
template<int sh_type>
void
Sized_relobj_file<size, big_endian>::emit_relocs_scan_reltype(
    Symbol_table* symtab,
    Layout* layout,
    const unsigned char* plocal_syms,
    const Read_relocs_data::Relocs_list::iterator& p,
    Relocatable_relocs* rr)
{
  scan_relocatable_relocs<size, big_endian, sh_type,
			  Emit_relocs_strategy<sh_type> >(
    symtab,
    layout,
    this,
    p->data_shndx,
    p->contents->data(),
    p->reloc_count,
    p->output_section,
    p->needs_special_offset_handling,
    this->local_symbol_count_,
    plocal_syms,
    rr);
}

// Scan the input relocations for --incremental.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::incremental_relocs_scan(
    const Read_relocs_data::Relocs_list::iterator& p)
{
  if (p->sh_type == elfcpp::SHT_REL)
    this->incremental_relocs_scan_reltype<elfcpp::SHT_REL>(p);
  else
    {
      gold_assert(p->sh_type == elfcpp::SHT_RELA);
      this->incremental_relocs_scan_reltype<elfcpp::SHT_RELA>(p);
    }
}

// Scan the input relocation for --incremental, templatized on the
// type of the relocation section.

template<int size, bool big_endian>
template<int sh_type>
void
Sized_relobj_file<size, big_endian>::incremental_relocs_scan_reltype(
    const Read_relocs_data::Relocs_list::iterator& p)
{
  typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
  const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size;
  const unsigned char* prelocs = p->contents->data();
  size_t reloc_count = p->reloc_count;

  for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
    {
      Reltype reloc(prelocs);

      if (p->needs_special_offset_handling
	  && !p->output_section->is_input_address_mapped(this, p->data_shndx,
						         reloc.get_r_offset()))
	continue;

      typename elfcpp::Elf_types<size>::Elf_WXword r_info =
	  reloc.get_r_info();
      const unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);

      if (r_sym >= this->local_symbol_count_)
	this->count_incremental_reloc(r_sym - this->local_symbol_count_);
    }
}

// Relocate the input sections and write out the local symbols.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::do_relocate(const Symbol_table* symtab,
						 const Layout* layout,
						 Output_file* of)
{
  unsigned int shnum = this->shnum();

  // Read the section headers.
  const unsigned char* pshdrs = this->get_view(this->elf_file_.shoff(),
					       shnum * This::shdr_size,
					       true, true);

  Views views;
  views.resize(shnum);

  // Make two passes over the sections.  The first one copies the
  // section data to the output file.  The second one applies
  // relocations.

  this->write_sections(layout, pshdrs, of, &views);

  // To speed up relocations, we set up hash tables for fast lookup of
  // input offsets to output addresses.
  this->initialize_input_to_output_maps();

  // Apply relocations.

  this->relocate_sections(symtab, layout, pshdrs, of, &views);

  // After we've done the relocations, we release the hash tables,
  // since we no longer need them.
  this->free_input_to_output_maps();

  // Write out the accumulated views.
  for (unsigned int i = 1; i < shnum; ++i)
    {
      if (views[i].view != NULL)
	{
	  if (views[i].is_ctors_reverse_view)
	    this->reverse_words(views[i].view, views[i].view_size);
	  if (!views[i].is_postprocessing_view)
	    {
	      if (views[i].is_input_output_view)
		of->write_input_output_view(views[i].offset,
					    views[i].view_size,
					    views[i].view);
	      else
		of->write_output_view(views[i].offset, views[i].view_size,
				      views[i].view);
	    }
	}
    }

  // Write out the local symbols.
  this->write_local_symbols(of, layout->sympool(), layout->dynpool(),
			    layout->symtab_xindex(), layout->dynsym_xindex(),
			    layout->symtab_section_offset());
}

// Sort a Read_multiple vector by file offset.
struct Read_multiple_compare
{
  inline bool
  operator()(const File_read::Read_multiple_entry& rme1,
	     const File_read::Read_multiple_entry& rme2) const
  { return rme1.file_offset < rme2.file_offset; }
};

// Write section data to the output file.  PSHDRS points to the
// section headers.  Record the views in *PVIEWS for use when
// relocating.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::write_sections(const Layout* layout,
						    const unsigned char* pshdrs,
						    Output_file* of,
						    Views* pviews)
{
  unsigned int shnum = this->shnum();
  const Output_sections& out_sections(this->output_sections());
  const std::vector<Address>& out_offsets(this->section_offsets());

  File_read::Read_multiple rm;
  bool is_sorted = true;

  const unsigned char* p = pshdrs + This::shdr_size;
  for (unsigned int i = 1; i < shnum; ++i, p += This::shdr_size)
    {
      View_size* pvs = &(*pviews)[i];

      pvs->view = NULL;

      const Output_section* os = out_sections[i];
      if (os == NULL)
	continue;
      Address output_offset = out_offsets[i];

      typename This::Shdr shdr(p);

      if (shdr.get_sh_type() == elfcpp::SHT_NOBITS)
	continue;

      if ((parameters->options().relocatable()
	   || parameters->options().emit_relocs())
	  && (shdr.get_sh_type() == elfcpp::SHT_REL
	      || shdr.get_sh_type() == elfcpp::SHT_RELA)
	  && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
	{
	  // This is a reloc section in a relocatable link or when
	  // emitting relocs.  We don't need to read the input file.
	  // The size and file offset are stored in the
	  // Relocatable_relocs structure.
	  Relocatable_relocs* rr = this->relocatable_relocs(i);
	  gold_assert(rr != NULL);
	  Output_data* posd = rr->output_data();
	  gold_assert(posd != NULL);

	  pvs->offset = posd->offset();
	  pvs->view_size = posd->data_size();
	  pvs->view = of->get_output_view(pvs->offset, pvs->view_size);
	  pvs->address = posd->address();
	  pvs->is_input_output_view = false;
	  pvs->is_postprocessing_view = false;
	  pvs->is_ctors_reverse_view = false;

	  continue;
	}

      // In the normal case, this input section is simply mapped to
      // the output section at offset OUTPUT_OFFSET.

      // However, if OUTPUT_OFFSET == INVALID_ADDRESS, then input data is
      // handled specially--e.g., a .eh_frame section.  The relocation
      // routines need to check for each reloc where it should be
      // applied.  For this case, we need an input/output view for the
      // entire contents of the section in the output file.  We don't
      // want to copy the contents of the input section to the output
      // section; the output section contents were already written,
      // and we waited for them in Relocate_task::is_runnable because
      // relocs_must_follow_section_writes is set for the object.

      // Regardless of which of the above cases is true, we have to
      // check requires_postprocessing of the output section.  If that
      // is false, then we work with views of the output file
      // directly.  If it is true, then we work with a separate
      // buffer, and the output section is responsible for writing the
      // final data to the output file.

      off_t output_section_offset;
      Address output_section_size;
      if (!os->requires_postprocessing())
	{
	  output_section_offset = os->offset();
	  output_section_size = convert_types<Address, off_t>(os->data_size());
	}
      else
	{
	  output_section_offset = 0;
	  output_section_size =
              convert_types<Address, off_t>(os->postprocessing_buffer_size());
	}

      off_t view_start;
      section_size_type view_size;
      bool must_decompress = false;
      if (output_offset != invalid_address)
	{
	  view_start = output_section_offset + output_offset;
	  view_size = convert_to_section_size_type(shdr.get_sh_size());
	  section_size_type uncompressed_size;
	  if (this->section_is_compressed(i, &uncompressed_size))
	    {
	      view_size = uncompressed_size;
	      must_decompress = true;
	    }
	}
      else
	{
	  view_start = output_section_offset;
	  view_size = convert_to_section_size_type(output_section_size);
	}

      if (view_size == 0)
	continue;

      gold_assert(output_offset == invalid_address
		  || output_offset + view_size <= output_section_size);

      unsigned char* view;
      if (os->requires_postprocessing())
	{
	  unsigned char* buffer = os->postprocessing_buffer();
	  view = buffer + view_start;
	  if (output_offset != invalid_address && !must_decompress)
	    {
	      off_t sh_offset = shdr.get_sh_offset();
	      if (!rm.empty() && rm.back().file_offset > sh_offset)
		is_sorted = false;
	      rm.push_back(File_read::Read_multiple_entry(sh_offset,
							  view_size, view));
	    }
	}
      else
	{
	  if (output_offset == invalid_address)
	    view = of->get_input_output_view(view_start, view_size);
	  else
	    {
	      view = of->get_output_view(view_start, view_size);
	      if (!must_decompress)
		{
		  off_t sh_offset = shdr.get_sh_offset();
		  if (!rm.empty() && rm.back().file_offset > sh_offset)
		    is_sorted = false;
		  rm.push_back(File_read::Read_multiple_entry(sh_offset,
							      view_size, view));
		}
	    }
	}

      if (must_decompress)
        {
	  // Read and decompress the section.
          section_size_type len;
	  const unsigned char* p = this->section_contents(i, &len, false);
	  if (!decompress_input_section(p, len, view, view_size))
	    this->error(_("could not decompress section %s"),
			this->section_name(i).c_str());
        }

      pvs->view = view;
      pvs->address = os->address();
      if (output_offset != invalid_address)
	pvs->address += output_offset;
      pvs->offset = view_start;
      pvs->view_size = view_size;
      pvs->is_input_output_view = output_offset == invalid_address;
      pvs->is_postprocessing_view = os->requires_postprocessing();
      pvs->is_ctors_reverse_view =
	(!parameters->options().relocatable()
	 && view_size > size / 8
	 && (strcmp(os->name(), ".init_array") == 0
	     || strcmp(os->name(), ".fini_array") == 0)
	 && layout->is_ctors_in_init_array(this, i));
    }

  // Actually read the data.
  if (!rm.empty())
    {
      if (!is_sorted)
	std::sort(rm.begin(), rm.end(), Read_multiple_compare());
      this->read_multiple(rm);
    }
}

// Relocate section data.  VIEWS points to the section data as views
// in the output file.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::do_relocate_sections(
    const Symbol_table* symtab,
    const Layout* layout,
    const unsigned char* pshdrs,
    Output_file* of,
    Views* pviews)
{
  unsigned int shnum = this->shnum();
  Sized_target<size, big_endian>* target =
    parameters->sized_target<size, big_endian>();

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

  Relocate_info<size, big_endian> relinfo;
  relinfo.symtab = symtab;
  relinfo.layout = layout;
  relinfo.object = this;

  const unsigned char* p = pshdrs + This::shdr_size;
  for (unsigned int i = 1; i < shnum; ++i, p += This::shdr_size)
    {
      typename This::Shdr shdr(p);

      unsigned int sh_type = shdr.get_sh_type();
      if (sh_type != elfcpp::SHT_REL && sh_type != elfcpp::SHT_RELA)
	continue;

      off_t sh_size = shdr.get_sh_size();
      if (sh_size == 0)
	continue;

      unsigned int index = this->adjust_shndx(shdr.get_sh_info());
      if (index >= this->shnum())
	{
	  this->error(_("relocation section %u has bad info %u"),
		      i, index);
	  continue;
	}

      Output_section* os = out_sections[index];
      if (os == NULL)
	{
	  // This relocation section is against a section which we
	  // discarded.
	  continue;
	}
      Address output_offset = out_offsets[index];

      gold_assert((*pviews)[index].view != NULL);
      if (parameters->options().relocatable())
	gold_assert((*pviews)[i].view != NULL);

      if (this->adjust_shndx(shdr.get_sh_link()) != this->symtab_shndx_)
	{
	  gold_error(_("relocation section %u uses unexpected "
		       "symbol table %u"),
		     i, this->adjust_shndx(shdr.get_sh_link()));
	  continue;
	}

      const unsigned char* prelocs = this->get_view(shdr.get_sh_offset(),
						    sh_size, true, false);

      unsigned int reloc_size;
      if (sh_type == elfcpp::SHT_REL)
	reloc_size = elfcpp::Elf_sizes<size>::rel_size;
      else
	reloc_size = elfcpp::Elf_sizes<size>::rela_size;

      if (reloc_size != shdr.get_sh_entsize())
	{
	  gold_error(_("unexpected entsize for reloc section %u: %lu != %u"),
		     i, static_cast<unsigned long>(shdr.get_sh_entsize()),
		     reloc_size);
	  continue;
	}

      size_t reloc_count = sh_size / reloc_size;
      if (static_cast<off_t>(reloc_count * reloc_size) != sh_size)
	{
	  gold_error(_("reloc section %u size %lu uneven"),
		     i, static_cast<unsigned long>(sh_size));
	  continue;
	}

      gold_assert(output_offset != invalid_address
		  || this->relocs_must_follow_section_writes());

      relinfo.reloc_shndx = i;
      relinfo.reloc_shdr = p;
      relinfo.data_shndx = index;
      relinfo.data_shdr = pshdrs + index * This::shdr_size;
      unsigned char* view = (*pviews)[index].view;
      Address address = (*pviews)[index].address;
      section_size_type view_size = (*pviews)[index].view_size;

      Reloc_symbol_changes* reloc_map = NULL;
      if (this->uses_split_stack() && output_offset != invalid_address)
	{
	  typename This::Shdr data_shdr(pshdrs + index * This::shdr_size);
	  if ((data_shdr.get_sh_flags() & elfcpp::SHF_EXECINSTR) != 0)
	    this->split_stack_adjust(symtab, pshdrs, sh_type, index,
				     prelocs, reloc_count, view, view_size,
				     &reloc_map);
	}

      if (!parameters->options().relocatable())
	{
	  target->relocate_section(&relinfo, sh_type, prelocs, reloc_count, os,
				   output_offset == invalid_address,
				   view, address, view_size, reloc_map);
	  if (parameters->options().emit_relocs())
	    this->emit_relocs(&relinfo, i, sh_type, prelocs, reloc_count,
			      os, output_offset, view, address, view_size,
			      (*pviews)[i].view, (*pviews)[i].view_size);
	  if (parameters->incremental())
	    this->incremental_relocs_write(&relinfo, sh_type, prelocs,
					   reloc_count, os, output_offset, of);
	}
      else
	{
	  Relocatable_relocs* rr = this->relocatable_relocs(i);
	  target->relocate_for_relocatable(&relinfo, sh_type, prelocs,
					   reloc_count, os, output_offset, rr,
					   view, address, view_size,
					   (*pviews)[i].view,
					   (*pviews)[i].view_size);
	}
    }
}

// Emit the relocs for --emit-relocs.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::emit_relocs(
    const Relocate_info<size, big_endian>* relinfo,
    unsigned int i,
    unsigned int sh_type,
    const unsigned char* prelocs,
    size_t reloc_count,
    Output_section* output_section,
    typename elfcpp::Elf_types<size>::Elf_Addr offset_in_output_section,
    unsigned char* view,
    typename elfcpp::Elf_types<size>::Elf_Addr address,
    section_size_type view_size,
    unsigned char* reloc_view,
    section_size_type reloc_view_size)
{
  if (sh_type == elfcpp::SHT_REL)
    this->emit_relocs_reltype<elfcpp::SHT_REL>(relinfo, i, prelocs,
					       reloc_count, output_section,
					       offset_in_output_section,
					       view, address, view_size,
					       reloc_view, reloc_view_size);
  else
    {
      gold_assert(sh_type == elfcpp::SHT_RELA);
      this->emit_relocs_reltype<elfcpp::SHT_RELA>(relinfo, i, prelocs,
						  reloc_count, output_section,
						  offset_in_output_section,
						  view, address, view_size,
						  reloc_view, reloc_view_size);
    }
}

// Emit the relocs for --emit-relocs, templatized on the type of the
// relocation section.

template<int size, bool big_endian>
template<int sh_type>
void
Sized_relobj_file<size, big_endian>::emit_relocs_reltype(
    const Relocate_info<size, big_endian>* relinfo,
    unsigned int i,
    const unsigned char* prelocs,
    size_t reloc_count,
    Output_section* output_section,
    typename elfcpp::Elf_types<size>::Elf_Addr offset_in_output_section,
    unsigned char* view,
    typename elfcpp::Elf_types<size>::Elf_Addr address,
    section_size_type view_size,
    unsigned char* reloc_view,
    section_size_type reloc_view_size)
{
  const Relocatable_relocs* rr = this->relocatable_relocs(i);
  relocate_for_relocatable<size, big_endian, sh_type>(
    relinfo,
    prelocs,
    reloc_count,
    output_section,
    offset_in_output_section,
    rr,
    view,
    address,
    view_size,
    reloc_view,
    reloc_view_size);
}

// Write the incremental relocs.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::incremental_relocs_write(
    const Relocate_info<size, big_endian>* relinfo,
    unsigned int sh_type,
    const unsigned char* prelocs,
    size_t reloc_count,
    Output_section* output_section,
    Address output_offset,
    Output_file* of)
{
  if (sh_type == elfcpp::SHT_REL)
    this->incremental_relocs_write_reltype<elfcpp::SHT_REL>(
	relinfo,
	prelocs,
	reloc_count,
	output_section,
	output_offset,
	of);
  else
    {
      gold_assert(sh_type == elfcpp::SHT_RELA);
      this->incremental_relocs_write_reltype<elfcpp::SHT_RELA>(
	  relinfo,
	  prelocs,
	  reloc_count,
	  output_section,
	  output_offset,
	  of);
    }
}

// Write the incremental relocs, templatized on the type of the
// relocation section.

template<int size, bool big_endian>
template<int sh_type>
void
Sized_relobj_file<size, big_endian>::incremental_relocs_write_reltype(
    const Relocate_info<size, big_endian>* relinfo,
    const unsigned char* prelocs,
    size_t reloc_count,
    Output_section* output_section,
    Address output_offset,
    Output_file* of)
{
  typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reloc;
  const unsigned int reloc_size =
      Reloc_types<sh_type, size, big_endian>::reloc_size;
  const unsigned int sizeof_addr = size / 8;
  const unsigned int incr_reloc_size =
      Incremental_relocs_reader<size, big_endian>::reloc_size;

  unsigned int out_shndx = output_section->out_shndx();

  // Get a view for the .gnu_incremental_relocs section.

  Incremental_inputs* inputs = relinfo->layout->incremental_inputs();
  gold_assert(inputs != NULL);
  const off_t relocs_off = inputs->relocs_section()->offset();
  const off_t relocs_size = inputs->relocs_section()->data_size();
  unsigned char* const view = of->get_output_view(relocs_off, relocs_size);

  for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
    {
      Reloc reloc(prelocs);

      typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info();
      const unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
      const unsigned int r_type = elfcpp::elf_r_type<size>(r_info);

      if (r_sym < this->local_symbol_count_)
        continue;

      // Get the new offset--the location in the output section where
      // this relocation should be applied.

      Address offset = reloc.get_r_offset();
      if (output_offset != invalid_address)
	offset += output_offset;
      else
	{
          section_offset_type sot_offset =
              convert_types<section_offset_type, Address>(offset);
	  section_offset_type new_sot_offset =
	      output_section->output_offset(relinfo->object,
					    relinfo->data_shndx,
					    sot_offset);
	  gold_assert(new_sot_offset != -1);
	  offset += new_sot_offset;
	}

      // Get the addend.
      typename elfcpp::Elf_types<size>::Elf_Swxword addend;
      if (sh_type == elfcpp::SHT_RELA)
	addend =
	    Reloc_types<sh_type, size, big_endian>::get_reloc_addend(&reloc);
      else
        {
          // FIXME: Get the addend for SHT_REL.
          addend = 0;
        }

      // Get the index of the output relocation.

      unsigned int reloc_index =
          this->next_incremental_reloc_index(r_sym - this->local_symbol_count_);

      // Write the relocation.

      unsigned char* pov = view + reloc_index * incr_reloc_size;
      elfcpp::Swap<32, big_endian>::writeval(pov, r_type);
      elfcpp::Swap<32, big_endian>::writeval(pov + 4, out_shndx);
      elfcpp::Swap<size, big_endian>::writeval(pov + 8, offset);
      elfcpp::Swap<size, big_endian>::writeval(pov + 8 + sizeof_addr, addend);
      of->write_output_view(pov - view, incr_reloc_size, view);
    }
}

// Create merge hash tables for the local symbols.  These are used to
// speed up relocations.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::initialize_input_to_output_maps()
{
  const unsigned int loccount = this->local_symbol_count_;
  for (unsigned int i = 1; i < loccount; ++i)
    {
      Symbol_value<size>& lv(this->local_values_[i]);
      lv.initialize_input_to_output_map(this);
    }
}

// Free merge hash tables for the local symbols.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::free_input_to_output_maps()
{
  const unsigned int loccount = this->local_symbol_count_;
  for (unsigned int i = 1; i < loccount; ++i)
    {
      Symbol_value<size>& lv(this->local_values_[i]);
      lv.free_input_to_output_map();
    }
}

// If an object was compiled with -fsplit-stack, this is called to
// check whether any relocations refer to functions defined in objects
// which were not compiled with -fsplit-stack.  If they were, then we
// need to apply some target-specific adjustments to request
// additional stack space.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::split_stack_adjust(
    const Symbol_table* symtab,
    const unsigned char* pshdrs,
    unsigned int sh_type,
    unsigned int shndx,
    const unsigned char* prelocs,
    size_t reloc_count,
    unsigned char* view,
    section_size_type view_size,
    Reloc_symbol_changes** reloc_map)
{
  if (sh_type == elfcpp::SHT_REL)
    this->split_stack_adjust_reltype<elfcpp::SHT_REL>(symtab, pshdrs, shndx,
						      prelocs, reloc_count,
						      view, view_size,
						      reloc_map);
  else
    {
      gold_assert(sh_type == elfcpp::SHT_RELA);
      this->split_stack_adjust_reltype<elfcpp::SHT_RELA>(symtab, pshdrs, shndx,
							 prelocs, reloc_count,
							 view, view_size,
							 reloc_map);
    }
}

// Adjust for -fsplit-stack, templatized on the type of the relocation
// section.

template<int size, bool big_endian>
template<int sh_type>
void
Sized_relobj_file<size, big_endian>::split_stack_adjust_reltype(
    const Symbol_table* symtab,
    const unsigned char* pshdrs,
    unsigned int shndx,
    const unsigned char* prelocs,
    size_t reloc_count,
    unsigned char* view,
    section_size_type view_size,
    Reloc_symbol_changes** reloc_map)
{
  typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
  const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size;

  size_t local_count = this->local_symbol_count();

  std::vector<section_offset_type> non_split_refs;

  const unsigned char* pr = prelocs;
  for (size_t i = 0; i < reloc_count; ++i, pr += reloc_size)
    {
      Reltype reloc(pr);

      typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info();
      unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
      if (r_sym < local_count)
	continue;

      const Symbol* gsym = this->global_symbol(r_sym);
      gold_assert(gsym != NULL);
      if (gsym->is_forwarder())
	gsym = symtab->resolve_forwards(gsym);

      // See if this relocation refers to a function defined in an
      // object compiled without -fsplit-stack.  Note that we don't
      // care about the type of relocation--this means that in some
      // cases we will ask for a large stack unnecessarily, but this
      // is not fatal.  FIXME: Some targets have symbols which are
      // functions but are not type STT_FUNC, e.g., STT_ARM_TFUNC.
      if (!gsym->is_undefined()
	  && gsym->source() == Symbol::FROM_OBJECT
	  && !gsym->object()->uses_split_stack())
	{
	  unsigned int r_type = elfcpp::elf_r_type<size>(reloc.get_r_info());
	  if (parameters->target().is_call_to_non_split(gsym, r_type))
	    {
	      section_offset_type offset =
		convert_to_section_size_type(reloc.get_r_offset());
	      non_split_refs.push_back(offset);
	    }
	}
    }

  if (non_split_refs.empty())
    return;

  // At this point, every entry in NON_SPLIT_REFS indicates a
  // relocation which refers to a function in an object compiled
  // without -fsplit-stack.  We now have to convert that list into a
  // set of offsets to functions.  First, we find all the functions.

  Function_offsets function_offsets;
  this->find_functions(pshdrs, shndx, &function_offsets);
  if (function_offsets.empty())
    return;

  // Now get a list of the function with references to non split-stack
  // code.

  Function_offsets calls_non_split;
  for (std::vector<section_offset_type>::const_iterator p
	 = non_split_refs.begin();
       p != non_split_refs.end();
       ++p)
    {
      Function_offsets::const_iterator low = function_offsets.lower_bound(*p);
      if (low == function_offsets.end())
	--low;
      else if (low->first == *p)
	;
      else if (low == function_offsets.begin())
	continue;
      else
	--low;

      calls_non_split.insert(*low);
    }
  if (calls_non_split.empty())
    return;

  // Now we have a set of functions to adjust.  The adjustments are
  // target specific.  Besides changing the output section view
  // however, it likes, the target may request a relocation change
  // from one global symbol name to another.

  for (Function_offsets::const_iterator p = calls_non_split.begin();
       p != calls_non_split.end();
       ++p)
    {
      std::string from;
      std::string to;
      parameters->target().calls_non_split(this, shndx, p->first, p->second,
					   view, view_size, &from, &to);
      if (!from.empty())
	{
	  gold_assert(!to.empty());
	  Symbol* tosym = NULL;

	  // Find relocations in the relevant function which are for
	  // FROM.
	  pr = prelocs;
	  for (size_t i = 0; i < reloc_count; ++i, pr += reloc_size)
	    {
	      Reltype reloc(pr);

	      typename elfcpp::Elf_types<size>::Elf_WXword r_info =
		reloc.get_r_info();
	      unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
	      if (r_sym < local_count)
		continue;

	      section_offset_type offset =
		convert_to_section_size_type(reloc.get_r_offset());
	      if (offset < p->first
		  || (offset
		      >= (p->first
			  + static_cast<section_offset_type>(p->second))))
		continue;

	      const Symbol* gsym = this->global_symbol(r_sym);
	      if (from == gsym->name())
		{
		  if (tosym == NULL)
		    {
		      tosym = symtab->lookup(to.c_str());
		      if (tosym == NULL)
			{
			  this->error(_("could not convert call "
					"to '%s' to '%s'"),
				      from.c_str(), to.c_str());
			  break;
			}
		    }

		  if (*reloc_map == NULL)
		    *reloc_map = new Reloc_symbol_changes(reloc_count);
		  (*reloc_map)->set(i, tosym);
		}
	    }
	}
    }
}

// Find all the function in this object defined in section SHNDX.
// Store their offsets in the section in FUNCTION_OFFSETS.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::find_functions(
    const unsigned char* pshdrs,
    unsigned int shndx,
    Sized_relobj_file<size, big_endian>::Function_offsets* function_offsets)
{
  // We need to read the symbols to find the functions.  If we wanted
  // to, we could cache reading the symbols across all sections in the
  // object.
  const unsigned int symtab_shndx = this->symtab_shndx_;
  typename This::Shdr symtabshdr(pshdrs + symtab_shndx * This::shdr_size);
  gold_assert(symtabshdr.get_sh_type() == elfcpp::SHT_SYMTAB);

  typename elfcpp::Elf_types<size>::Elf_WXword sh_size =
    symtabshdr.get_sh_size();
  const unsigned char* psyms = this->get_view(symtabshdr.get_sh_offset(),
					      sh_size, true, true);

  const int sym_size = This::sym_size;
  const unsigned int symcount = sh_size / sym_size;
  for (unsigned int i = 0; i < symcount; ++i, psyms += sym_size)
    {
      typename elfcpp::Sym<size, big_endian> isym(psyms);

      // FIXME: Some targets can have functions which do not have type
      // STT_FUNC, e.g., STT_ARM_TFUNC.
      if (isym.get_st_type() != elfcpp::STT_FUNC
	  || isym.get_st_size() == 0)
	continue;

      bool is_ordinary;
      unsigned int sym_shndx = this->adjust_sym_shndx(i, isym.get_st_shndx(),
						      &is_ordinary);
      if (!is_ordinary || sym_shndx != shndx)
	continue;

      section_offset_type value =
	convert_to_section_size_type(isym.get_st_value());
      section_size_type fnsize =
	convert_to_section_size_type(isym.get_st_size());

      (*function_offsets)[value] = fnsize;
    }
}

// Reverse the words in a section.  Used for .ctors sections mapped to
// .init_array sections.  See ctors_sections_in_init_array in
// layout.cc.

template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::reverse_words(unsigned char* view,
						   section_size_type view_size)
{
  typedef typename elfcpp::Swap<size, big_endian>::Valtype Valtype;
  Valtype* vview = reinterpret_cast<Valtype*>(view);
  section_size_type vview_size = view_size / (size / 8);
  for (section_size_type i = 0; i < vview_size / 2; ++i)
    {
      Valtype tmp = vview[i];
      vview[i] = vview[vview_size - 1 - i];
      vview[vview_size - 1 - i] = tmp;
    }
}

// Class Merged_symbol_value.

template<int size>
void
Merged_symbol_value<size>::initialize_input_to_output_map(
    const Relobj* object,
    unsigned int input_shndx)
{
  Object_merge_map* map = object->merge_map();
  map->initialize_input_to_output_map<size>(input_shndx,
					    this->output_start_address_,
					    &this->output_addresses_);
}

// Get the output value corresponding to an input offset if we
// couldn't find it in the hash table.

template<int size>
typename elfcpp::Elf_types<size>::Elf_Addr
Merged_symbol_value<size>::value_from_output_section(
    const Relobj* object,
    unsigned int input_shndx,
    typename elfcpp::Elf_types<size>::Elf_Addr input_offset) const
{
  section_offset_type output_offset;
  bool found = object->merge_map()->get_output_offset(NULL, input_shndx,
						      input_offset,
						      &output_offset);

  // If this assertion fails, it means that some relocation was
  // against a portion of an input merge section which we didn't map
  // to the output file and we didn't explicitly discard.  We should
  // always map all portions of input merge sections.
  gold_assert(found);

  if (output_offset == -1)
    return 0;
  else
    return this->output_start_address_ + output_offset;
}

// Track_relocs methods.

// Initialize the class to track the relocs.  This gets the object,
// the reloc section index, and the type of the relocs.  This returns
// false if something goes wrong.

template<int size, bool big_endian>
bool
Track_relocs<size, big_endian>::initialize(
    Object* object,
    unsigned int reloc_shndx,
    unsigned int reloc_type)
{
  // If RELOC_SHNDX is -1U, it means there is more than one reloc
  // section for the .eh_frame section.  We can't handle that case.
  if (reloc_shndx == -1U)
    return false;

  // If RELOC_SHNDX is 0, there is no reloc section.
  if (reloc_shndx == 0)
    return true;

  // Get the contents of the reloc section.
  this->prelocs_ = object->section_contents(reloc_shndx, &this->len_, false);

  if (reloc_type == elfcpp::SHT_REL)
    this->reloc_size_ = elfcpp::Elf_sizes<size>::rel_size;
  else if (reloc_type == elfcpp::SHT_RELA)
    this->reloc_size_ = elfcpp::Elf_sizes<size>::rela_size;
  else
    gold_unreachable();

  if (this->len_ % this->reloc_size_ != 0)
    {
      object->error(_("reloc section size %zu is not a multiple of "
		      "reloc size %d\n"),
		    static_cast<size_t>(this->len_),
		    this->reloc_size_);
      return false;
    }

  return true;
}

// Return the offset of the next reloc, or -1 if there isn't one.

template<int size, bool big_endian>
off_t
Track_relocs<size, big_endian>::next_offset() const
{
  if (this->pos_ >= this->len_)
    return -1;

  // Rel and Rela start out the same, so we can always use Rel to find
  // the r_offset value.
  elfcpp::Rel<size, big_endian> rel(this->prelocs_ + this->pos_);
  return rel.get_r_offset();
}

// Return the index of the symbol referenced by the next reloc, or -1U
// if there aren't any more relocs.

template<int size, bool big_endian>
unsigned int
Track_relocs<size, big_endian>::next_symndx() const
{
  if (this->pos_ >= this->len_)
    return -1U;

  // Rel and Rela start out the same, so we can use Rel to find the
  // symbol index.
  elfcpp::Rel<size, big_endian> rel(this->prelocs_ + this->pos_);
  return elfcpp::elf_r_sym<size>(rel.get_r_info());
}

// Return the addend of the next reloc, or 0 if there isn't one.

template<int size, bool big_endian>
uint64_t
Track_relocs<size, big_endian>::next_addend() const
{
  if (this->pos_ >= this->len_)
    return 0;
  if (this->reloc_size_ == elfcpp::Elf_sizes<size>::rel_size)
    return 0;
  elfcpp::Rela<size, big_endian> rela(this->prelocs_ + this->pos_);
  return rela.get_r_addend();
}

// Advance to the next reloc whose r_offset is greater than or equal
// to OFFSET.  Return the number of relocs we skip.

template<int size, bool big_endian>
int
Track_relocs<size, big_endian>::advance(off_t offset)
{
  int ret = 0;
  while (this->pos_ < this->len_)
    {
      // Rel and Rela start out the same, so we can always use Rel to
      // find the r_offset value.
      elfcpp::Rel<size, big_endian> rel(this->prelocs_ + this->pos_);
      if (static_cast<off_t>(rel.get_r_offset()) >= offset)
	break;
      ++ret;
      this->pos_ += this->reloc_size_;
    }
  return ret;
}

// Instantiate the templates we need.

#ifdef HAVE_TARGET_32_LITTLE
template
void
Sized_relobj_file<32, false>::do_read_relocs(Read_relocs_data* rd);
#endif

#ifdef HAVE_TARGET_32_BIG
template
void
Sized_relobj_file<32, true>::do_read_relocs(Read_relocs_data* rd);
#endif

#ifdef HAVE_TARGET_64_LITTLE
template
void
Sized_relobj_file<64, false>::do_read_relocs(Read_relocs_data* rd);
#endif

#ifdef HAVE_TARGET_64_BIG
template
void
Sized_relobj_file<64, true>::do_read_relocs(Read_relocs_data* rd);
#endif

#ifdef HAVE_TARGET_32_LITTLE
template
void
Sized_relobj_file<32, false>::do_gc_process_relocs(Symbol_table* symtab,
						   Layout* layout,
						   Read_relocs_data* rd);
#endif

#ifdef HAVE_TARGET_32_BIG
template
void
Sized_relobj_file<32, true>::do_gc_process_relocs(Symbol_table* symtab,
						  Layout* layout,
						  Read_relocs_data* rd);
#endif

#ifdef HAVE_TARGET_64_LITTLE
template
void
Sized_relobj_file<64, false>::do_gc_process_relocs(Symbol_table* symtab,
						   Layout* layout,
						   Read_relocs_data* rd);
#endif

#ifdef HAVE_TARGET_64_BIG
template
void
Sized_relobj_file<64, true>::do_gc_process_relocs(Symbol_table* symtab,
						  Layout* layout,
						  Read_relocs_data* rd);
#endif

#ifdef HAVE_TARGET_32_LITTLE
template
void
Sized_relobj_file<32, false>::do_scan_relocs(Symbol_table* symtab,
					     Layout* layout,
					     Read_relocs_data* rd);
#endif

#ifdef HAVE_TARGET_32_BIG
template
void
Sized_relobj_file<32, true>::do_scan_relocs(Symbol_table* symtab,
					    Layout* layout,
					    Read_relocs_data* rd);
#endif

#ifdef HAVE_TARGET_64_LITTLE
template
void
Sized_relobj_file<64, false>::do_scan_relocs(Symbol_table* symtab,
					     Layout* layout,
					     Read_relocs_data* rd);
#endif

#ifdef HAVE_TARGET_64_BIG
template
void
Sized_relobj_file<64, true>::do_scan_relocs(Symbol_table* symtab,
					    Layout* layout,
					    Read_relocs_data* rd);
#endif

#ifdef HAVE_TARGET_32_LITTLE
template
void
Sized_relobj_file<32, false>::do_relocate(const Symbol_table* symtab,
					  const Layout* layout,
					  Output_file* of);
#endif

#ifdef HAVE_TARGET_32_BIG
template
void
Sized_relobj_file<32, true>::do_relocate(const Symbol_table* symtab,
					 const Layout* layout,
					 Output_file* of);
#endif

#ifdef HAVE_TARGET_64_LITTLE
template
void
Sized_relobj_file<64, false>::do_relocate(const Symbol_table* symtab,
					  const Layout* layout,
					  Output_file* of);
#endif

#ifdef HAVE_TARGET_64_BIG
template
void
Sized_relobj_file<64, true>::do_relocate(const Symbol_table* symtab,
					 const Layout* layout,
					 Output_file* of);
#endif

#ifdef HAVE_TARGET_32_LITTLE
template
void
Sized_relobj_file<32, false>::do_relocate_sections(
    const Symbol_table* symtab,
    const Layout* layout,
    const unsigned char* pshdrs,
    Output_file* of,
    Views* pviews);
#endif

#ifdef HAVE_TARGET_32_BIG
template
void
Sized_relobj_file<32, true>::do_relocate_sections(
    const Symbol_table* symtab,
    const Layout* layout,
    const unsigned char* pshdrs,
    Output_file* of,
    Views* pviews);
#endif

#ifdef HAVE_TARGET_64_LITTLE
template
void
Sized_relobj_file<64, false>::do_relocate_sections(
    const Symbol_table* symtab,
    const Layout* layout,
    const unsigned char* pshdrs,
    Output_file* of,
    Views* pviews);
#endif

#ifdef HAVE_TARGET_64_BIG
template
void
Sized_relobj_file<64, true>::do_relocate_sections(
    const Symbol_table* symtab,
    const Layout* layout,
    const unsigned char* pshdrs,
    Output_file* of,
    Views* pviews);
#endif

#ifdef HAVE_TARGET_32_LITTLE
template
void
Sized_relobj_file<32, false>::initialize_input_to_output_maps();

template
void
Sized_relobj_file<32, false>::free_input_to_output_maps();
#endif

#ifdef HAVE_TARGET_32_BIG
template
void
Sized_relobj_file<32, true>::initialize_input_to_output_maps();

template
void
Sized_relobj_file<32, true>::free_input_to_output_maps();
#endif

#ifdef HAVE_TARGET_64_LITTLE
template
void
Sized_relobj_file<64, false>::initialize_input_to_output_maps();

template
void
Sized_relobj_file<64, false>::free_input_to_output_maps();
#endif

#ifdef HAVE_TARGET_64_BIG
template
void
Sized_relobj_file<64, true>::initialize_input_to_output_maps();

template
void
Sized_relobj_file<64, true>::free_input_to_output_maps();
#endif

#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
template
class Merged_symbol_value<32>;
#endif

#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
template
class Merged_symbol_value<64>;
#endif

#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
template
class Symbol_value<32>;
#endif

#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
template
class Symbol_value<64>;
#endif

#ifdef HAVE_TARGET_32_LITTLE
template
class Track_relocs<32, false>;
#endif

#ifdef HAVE_TARGET_32_BIG
template
class Track_relocs<32, true>;
#endif

#ifdef HAVE_TARGET_64_LITTLE
template
class Track_relocs<64, false>;
#endif

#ifdef HAVE_TARGET_64_BIG
template
class Track_relocs<64, true>;
#endif

} // End namespace gold.
