// merge.cc -- handle section merging 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 <cstdlib>
#include <algorithm>

#include "merge.h"
#include "compressed_output.h"

namespace gold
{

// Class Object_merge_map.

// Destructor.

Object_merge_map::~Object_merge_map()
{
  for (Section_merge_maps::iterator p = this->section_merge_maps_.begin();
       p != this->section_merge_maps_.end();
       ++p)
    delete p->second;
}

// Get the Input_merge_map to use for an input section, or NULL.

Object_merge_map::Input_merge_map*
Object_merge_map::get_input_merge_map(unsigned int shndx)
{
  gold_assert(shndx != -1U);
  if (shndx == this->first_shnum_)
    return &this->first_map_;
  if (shndx == this->second_shnum_)
    return &this->second_map_;
  Section_merge_maps::const_iterator p = this->section_merge_maps_.find(shndx);
  if (p != this->section_merge_maps_.end())
    return p->second;
  return NULL;
}

// Get or create the Input_merge_map to use for an input section.

Object_merge_map::Input_merge_map*
Object_merge_map::get_or_make_input_merge_map(const Merge_map* merge_map,
					      unsigned int shndx)
{
  Input_merge_map* map = this->get_input_merge_map(shndx);
  if (map != NULL)
    {
      // For a given input section in a given object, every mapping
      // must be done with the same Merge_map.
      gold_assert(map->merge_map == merge_map);
      return map;
    }

  // We need to create a new entry.
  if (this->first_shnum_ == -1U)
    {
      this->first_shnum_ = shndx;
      this->first_map_.merge_map = merge_map;
      return &this->first_map_;
    }
  if (this->second_shnum_ == -1U)
    {
      this->second_shnum_ = shndx;
      this->second_map_.merge_map = merge_map;
      return &this->second_map_;
    }

  Input_merge_map* new_map = new Input_merge_map;
  new_map->merge_map = merge_map;
  this->section_merge_maps_[shndx] = new_map;
  return new_map;
}

// Add a mapping.

void
Object_merge_map::add_mapping(const Merge_map* merge_map, unsigned int shndx,
			      section_offset_type input_offset,
			      section_size_type length,
			      section_offset_type output_offset)
{
  Input_merge_map* map = this->get_or_make_input_merge_map(merge_map, shndx);

  // Try to merge the new entry in the last one we saw.
  if (!map->entries.empty())
    {
      Input_merge_entry& entry(map->entries.back());

      // Use section_size_type to avoid signed/unsigned warnings.
      section_size_type input_offset_u = input_offset;
      section_size_type output_offset_u = output_offset;

      // If this entry is not in order, we need to sort the vector
      // before looking anything up.
      if (input_offset_u < entry.input_offset + entry.length)
	{
	  gold_assert(input_offset < entry.input_offset);
	  gold_assert(input_offset_u + length
		      <= static_cast<section_size_type>(entry.input_offset));
	  map->sorted = false;
	}
      else if (entry.input_offset + entry.length == input_offset_u
	       && (output_offset == -1
		   ? entry.output_offset == -1
		   : entry.output_offset + entry.length == output_offset_u))
	{
	  entry.length += length;
	  return;
	}
    }

  Input_merge_entry entry;
  entry.input_offset = input_offset;
  entry.length = length;
  entry.output_offset = output_offset;
  map->entries.push_back(entry);
}

// Get the output offset for an input address.

bool
Object_merge_map::get_output_offset(const Merge_map* merge_map,
				    unsigned int shndx,
				    section_offset_type input_offset,
				    section_offset_type* output_offset)
{
  Input_merge_map* map = this->get_input_merge_map(shndx);
  if (map == NULL
      || (merge_map != NULL && map->merge_map != merge_map))
    return false;

  if (!map->sorted)
    {
      std::sort(map->entries.begin(), map->entries.end(),
		Input_merge_compare());
      map->sorted = true;
    }

  Input_merge_entry entry;
  entry.input_offset = input_offset;
  std::vector<Input_merge_entry>::const_iterator p =
    std::lower_bound(map->entries.begin(), map->entries.end(),
		     entry, Input_merge_compare());
  if (p == map->entries.end() || p->input_offset > input_offset)
    {
      if (p == map->entries.begin())
	return false;
      --p;
      gold_assert(p->input_offset <= input_offset);
    }

  if (input_offset - p->input_offset
      >= static_cast<section_offset_type>(p->length))
    return false;

  *output_offset = p->output_offset;
  if (*output_offset != -1)
    *output_offset += (input_offset - p->input_offset);
  return true;
}

// Return whether this is the merge map for section SHNDX.

inline bool
Object_merge_map::is_merge_section_for(const Merge_map* merge_map,
				       unsigned int shndx)
{
  Input_merge_map* map = this->get_input_merge_map(shndx);
  return map != NULL && map->merge_map == merge_map;
}

// Initialize a mapping from input offsets to output addresses.

template<int size>
void
Object_merge_map::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>* initialize_map)
{
  Input_merge_map* map = this->get_input_merge_map(shndx);
  gold_assert(map != NULL);

  gold_assert(initialize_map->empty());
  // We know how many entries we are going to add.
  // reserve_unordered_map takes an expected count of buckets, not a
  // count of elements, so double it to try to reduce collisions.
  reserve_unordered_map(initialize_map, map->entries.size() * 2);

  for (Input_merge_map::Entries::const_iterator p = map->entries.begin();
       p != map->entries.end();
       ++p)
    {
      section_offset_type output_offset = p->output_offset;
      if (output_offset != -1)
	output_offset += starting_address;
      else
	{
	  // If we see a relocation against an address we have chosen
	  // to discard, we relocate to zero.  FIXME: We could also
	  // issue a warning in this case; that would require
	  // reporting this somehow and checking it in the routines in
	  // reloc.h.
	  output_offset = 0;
	}
      initialize_map->insert(std::make_pair(p->input_offset, output_offset));
    }
}

// Class Merge_map.

// Add a mapping for the bytes from OFFSET to OFFSET + LENGTH in input
// section SHNDX in object OBJECT to an OUTPUT_OFFSET in merged data
// in an output section.

void
Merge_map::add_mapping(Relobj* object, unsigned int shndx,
		       section_offset_type offset, section_size_type length,
		       section_offset_type output_offset)
{
  gold_assert(object != NULL);
  Object_merge_map* object_merge_map = object->merge_map();
  if (object_merge_map == NULL)
    {
      object_merge_map = new Object_merge_map();
      object->set_merge_map(object_merge_map);
    }

  object_merge_map->add_mapping(this, shndx, offset, length, output_offset);
}

// Return the output offset for an input address.  The input address
// is at offset OFFSET in section SHNDX in OBJECT.  This sets
// *OUTPUT_OFFSET to the offset in the merged data in the output
// section.  This returns true if the mapping is known, false
// otherwise.

bool
Merge_map::get_output_offset(const Relobj* object, unsigned int shndx,
			     section_offset_type offset,
			     section_offset_type* output_offset) const
{
  Object_merge_map* object_merge_map = object->merge_map();
  if (object_merge_map == NULL)
    return false;
  return object_merge_map->get_output_offset(this, shndx, offset,
					     output_offset);
}

// Return whether this is the merge section for SHNDX in OBJECT.

bool
Merge_map::is_merge_section_for(const Relobj* object, unsigned int shndx) const
{
  Object_merge_map* object_merge_map = object->merge_map();
  if (object_merge_map == NULL)
    return false;
  return object_merge_map->is_merge_section_for(this, shndx);
}

// Class Output_merge_base.

// Return the output offset for an input offset.  The input address is
// at offset OFFSET in section SHNDX in OBJECT.  If we know the
// offset, set *POUTPUT and return true.  Otherwise return false.

bool
Output_merge_base::do_output_offset(const Relobj* object,
				    unsigned int shndx,
				    section_offset_type offset,
				    section_offset_type* poutput) const
{
  return this->merge_map_.get_output_offset(object, shndx, offset, poutput);
}

// Return whether this is the merge section for SHNDX in OBJECT.

bool
Output_merge_base::do_is_merge_section_for(const Relobj* object,
					   unsigned int shndx) const
{
  return this->merge_map_.is_merge_section_for(object, shndx);
}

// Record a merged input section for script processing.

void
Output_merge_base::record_input_section(Relobj* relobj, unsigned int shndx)
{
  gold_assert(this->keeps_input_sections_ && relobj != NULL);
  // If this is the first input section, record it.  We need do this because
  // this->input_sections_ is unordered.
  if (this->first_relobj_ == NULL)
    {
      this->first_relobj_ = relobj;
      this->first_shndx_ = shndx;
    }

  std::pair<Input_sections::iterator, bool> result =
    this->input_sections_.insert(Section_id(relobj, shndx));
  // We should insert a merge section once only.
  gold_assert(result.second);
}

// Class Output_merge_data.

// Compute the hash code for a fixed-size constant.

size_t
Output_merge_data::Merge_data_hash::operator()(Merge_data_key k) const
{
  const unsigned char* p = this->pomd_->constant(k);
  section_size_type entsize =
    convert_to_section_size_type(this->pomd_->entsize());

  // Fowler/Noll/Vo (FNV) hash (type FNV-1a).
  if (sizeof(size_t) == 8)
    {
      size_t result = static_cast<size_t>(14695981039346656037ULL);
      for (section_size_type i = 0; i < entsize; ++i)
	{
	  result &= (size_t) *p++;
	  result *= 1099511628211ULL;
	}
      return result;
    }
  else
    {
      size_t result = 2166136261UL;
      for (section_size_type i = 0; i < entsize; ++i)
	{
	  result ^= (size_t) *p++;
	  result *= 16777619UL;
	}
      return result;
    }
}

// Return whether one hash table key equals another.

bool
Output_merge_data::Merge_data_eq::operator()(Merge_data_key k1,
					     Merge_data_key k2) const
{
  const unsigned char* p1 = this->pomd_->constant(k1);
  const unsigned char* p2 = this->pomd_->constant(k2);
  return memcmp(p1, p2, this->pomd_->entsize()) == 0;
}

// Add a constant to the end of the section contents.

void
Output_merge_data::add_constant(const unsigned char* p)
{
  section_size_type entsize = convert_to_section_size_type(this->entsize());
  section_size_type addralign =
    convert_to_section_size_type(this->addralign());
  section_size_type addsize = std::max(entsize, addralign);
  if (this->len_ + addsize > this->alc_)
    {
      if (this->alc_ == 0)
	this->alc_ = 128 * addsize;
      else
	this->alc_ *= 2;
      this->p_ = static_cast<unsigned char*>(realloc(this->p_, this->alc_));
      if (this->p_ == NULL)
	gold_nomem();
    }

  memcpy(this->p_ + this->len_, p, entsize);
  if (addsize > entsize)
    memset(this->p_ + this->len_ + entsize, 0, addsize - entsize);
  this->len_ += addsize;
}

// Add the input section SHNDX in OBJECT to a merged output section
// which holds fixed length constants.  Return whether we were able to
// handle the section; if not, it will be linked as usual without
// constant merging.

bool
Output_merge_data::do_add_input_section(Relobj* object, unsigned int shndx)
{
  section_size_type len;
  bool is_new;
  const unsigned char* p = object->decompressed_section_contents(shndx, &len,
								 &is_new);

  section_size_type entsize = convert_to_section_size_type(this->entsize());

  if (len % entsize != 0)
    {
      if (is_new)
	delete[] p;
      return false;
    }

  this->input_count_ += len / entsize;

  for (section_size_type i = 0; i < len; i += entsize, p += entsize)
    {
      // Add the constant to the section contents.  If we find that it
      // is already in the hash table, we will remove it again.
      Merge_data_key k = this->len_;
      this->add_constant(p);

      std::pair<Merge_data_hashtable::iterator, bool> ins =
	this->hashtable_.insert(k);

      if (!ins.second)
	{
	  // Key was already present.  Remove the copy we just added.
	  this->len_ -= entsize;
	  k = *ins.first;
	}

      // Record the offset of this constant in the output section.
      this->add_mapping(object, shndx, i, entsize, k);
    }

  // For script processing, we keep the input sections.
  if (this->keeps_input_sections())
    record_input_section(object, shndx);

  if (is_new)
    delete[] p;

  return true;
}

// Set the final data size in a merged output section with fixed size
// constants.

void
Output_merge_data::set_final_data_size()
{
  // Release the memory we don't need.
  this->p_ = static_cast<unsigned char*>(realloc(this->p_, this->len_));
  // An Output_merge_data object may be empty and realloc is allowed
  // to return a NULL pointer in this case.  An Output_merge_data is empty
  // if all its input sections have sizes that are not multiples of entsize.
  gold_assert(this->p_ != NULL || this->len_ == 0);
  this->set_data_size(this->len_);
}

// Write the data of a merged output section with fixed size constants
// to the file.

void
Output_merge_data::do_write(Output_file* of)
{
  of->write(this->offset(), this->p_, this->len_);
}

// Write the data to a buffer.

void
Output_merge_data::do_write_to_buffer(unsigned char* buffer)
{
  memcpy(buffer, this->p_, this->len_);
}

// Print merge stats to stderr.

void
Output_merge_data::do_print_merge_stats(const char* section_name)
{
  fprintf(stderr,
	  _("%s: %s merged constants size: %lu; input: %zu; output: %zu\n"),
	  program_name, section_name,
	  static_cast<unsigned long>(this->entsize()),
	  this->input_count_, this->hashtable_.size());
}

// Class Output_merge_string.

// Add an input section to a merged string section.

template<typename Char_type>
bool
Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
						     unsigned int shndx)
{
  section_size_type sec_len;
  bool is_new;
  const unsigned char* pdata = object->decompressed_section_contents(shndx,
								     &sec_len,
								     &is_new);

  const Char_type* p = reinterpret_cast<const Char_type*>(pdata);
  const Char_type* pend = p + sec_len / sizeof(Char_type);
  const Char_type* pend0 = pend;

  if (sec_len % sizeof(Char_type) != 0)
    {
      object->error(_("mergeable string section length not multiple of "
		      "character size"));
      if (is_new)
	delete[] pdata;
      return false;
    }

  if (pend[-1] != 0)
    {
      gold_warning(_("%s: last entry in mergeable string section '%s' "
		     "not null terminated"),
		   object->name().c_str(),
		   object->section_name(shndx).c_str());
      // Find the end of the last NULL-terminated string in the buffer.
      while (pend0 > p && pend0[-1] != 0)
	--pend0;
    }

  Merged_strings_list* merged_strings_list =
      new Merged_strings_list(object, shndx);
  this->merged_strings_lists_.push_back(merged_strings_list);
  Merged_strings& merged_strings = merged_strings_list->merged_strings;

  // Count the number of non-null strings in the section and size the list.
  size_t count = 0;
  const Char_type* pt = p;
  while (pt < pend0)
    {
      size_t len = string_length(pt);
      if (len != 0)
	++count;
      pt += len + 1;
    }
  if (pend0 < pend)
    ++count;
  merged_strings.reserve(count + 1);

  // The index I is in bytes, not characters.
  section_size_type i = 0;

  // We assume here that the beginning of the section is correctly
  // aligned, so each string within the section must retain the same
  // modulo.
  uintptr_t init_align_modulo = (reinterpret_cast<uintptr_t>(pdata)
				 & (this->addralign() - 1));
  bool has_misaligned_strings = false;

  while (p < pend0)
    {
      size_t len = string_length(p);

      // Within merge input section each string must be aligned.
      if (len != 0
	  && ((reinterpret_cast<uintptr_t>(p) & (this->addralign() - 1))
	      != init_align_modulo))
	  has_misaligned_strings = true;

      Stringpool::Key key;
      this->stringpool_.add_with_length(p, len, true, &key);

      merged_strings.push_back(Merged_string(i, key));
      p += len + 1;
      i += (len + 1) * sizeof(Char_type);
    }
  if (p < pend)
    {
      size_t len = pend - p;

      Stringpool::Key key;
      this->stringpool_.add_with_length(p, len, true, &key);

      merged_strings.push_back(Merged_string(i, key));

      i += (len + 1) * sizeof(Char_type);
    }

  // Record the last offset in the input section so that we can
  // compute the length of the last string.
  merged_strings.push_back(Merged_string(i, 0));

  this->input_count_ += count;
  this->input_size_ += i;

  if (has_misaligned_strings)
    gold_warning(_("%s: section %s contains incorrectly aligned strings;"
		   " the alignment of those strings won't be preserved"),
		 object->name().c_str(),
		 object->section_name(shndx).c_str());

  // For script processing, we keep the input sections.
  if (this->keeps_input_sections())
    record_input_section(object, shndx);

  if (is_new)
    delete[] pdata;

  return true;
}

// Finalize the mappings from the input sections to the output
// section, and return the final data size.

template<typename Char_type>
section_size_type
Output_merge_string<Char_type>::finalize_merged_data()
{
  this->stringpool_.set_string_offsets();

  for (typename Merged_strings_lists::const_iterator l =
	 this->merged_strings_lists_.begin();
       l != this->merged_strings_lists_.end();
       ++l)
    {
      section_offset_type last_input_offset = 0;
      section_offset_type last_output_offset = 0;
      for (typename Merged_strings::const_iterator p =
	     (*l)->merged_strings.begin();
	   p != (*l)->merged_strings.end();
	   ++p)
	{
	  section_size_type length = p->offset - last_input_offset;
	  if (length > 0)
	    this->add_mapping((*l)->object, (*l)->shndx, last_input_offset,
	    		      length, last_output_offset);
	  last_input_offset = p->offset;
	  if (p->stringpool_key != 0)
	    last_output_offset =
	        this->stringpool_.get_offset_from_key(p->stringpool_key);
	}
      delete *l;
    }

  // Save some memory.  This also ensures that this function will work
  // if called twice, as may happen if Layout::set_segment_offsets
  // finds a better alignment.
  this->merged_strings_lists_.clear();

  return this->stringpool_.get_strtab_size();
}

template<typename Char_type>
void
Output_merge_string<Char_type>::set_final_data_size()
{
  const off_t final_data_size = this->finalize_merged_data();
  this->set_data_size(final_data_size);
}

// Write out a merged string section.

template<typename Char_type>
void
Output_merge_string<Char_type>::do_write(Output_file* of)
{
  this->stringpool_.write(of, this->offset());
}

// Write a merged string section to a buffer.

template<typename Char_type>
void
Output_merge_string<Char_type>::do_write_to_buffer(unsigned char* buffer)
{
  this->stringpool_.write_to_buffer(buffer, this->data_size());
}

// Return the name of the types of string to use with
// do_print_merge_stats.

template<typename Char_type>
const char*
Output_merge_string<Char_type>::string_name()
{
  gold_unreachable();
  return NULL;
}

template<>
const char*
Output_merge_string<char>::string_name()
{
  return "strings";
}

template<>
const char*
Output_merge_string<uint16_t>::string_name()
{
  return "16-bit strings";
}

template<>
const char*
Output_merge_string<uint32_t>::string_name()
{
  return "32-bit strings";
}

// Print merge stats to stderr.

template<typename Char_type>
void
Output_merge_string<Char_type>::do_print_merge_stats(const char* section_name)
{
  char buf[200];
  snprintf(buf, sizeof buf, "%s merged %s", section_name, this->string_name());
  fprintf(stderr, _("%s: %s input bytes: %zu\n"),
	  program_name, buf, this->input_size_);
  fprintf(stderr, _("%s: %s input strings: %zu\n"),
	  program_name, buf, this->input_count_);
  this->stringpool_.print_stats(buf);
}

// Instantiate the templates we need.

template
class Output_merge_string<char>;

template
class Output_merge_string<uint16_t>;

template
class Output_merge_string<uint32_t>;

#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
template
void
Object_merge_map::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>*);
#endif

#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
template
void
Object_merge_map::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>*);
#endif

} // End namespace gold.
