// dynobj.h -- dynamic object support for gold   -*- C++ -*-

// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.

// This file is part of gold.

// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
// MA 02110-1301, USA.

#ifndef GOLD_DYNOBJ_H
#define GOLD_DYNOBJ_H

#include <vector>

#include "stringpool.h"
#include "object.h"

namespace gold
{

class Version_script_info;

// A dynamic object (ET_DYN).  This is an abstract base class itself.
// The implementations is the template class Sized_dynobj.

class Dynobj : public Object
{
 public:
  // We keep a list of all the DT_NEEDED entries we find.
  typedef std::vector<std::string> Needed;

  Dynobj(const std::string& name, Input_file* input_file, off_t offset = 0);

  // Return the name to use in a DT_NEEDED entry for this object.
  const char*
  soname() const
  { return this->soname_.c_str(); }

  // Return the list of DT_NEEDED strings.
  const Needed&
  needed() const
  { return this->needed_; }

  // Return whether this dynamic object has any DT_NEEDED entries
  // which were not seen during the link.
  bool
  has_unknown_needed_entries() const
  {
    gold_assert(this->unknown_needed_ != UNKNOWN_NEEDED_UNSET);
    return this->unknown_needed_ == UNKNOWN_NEEDED_TRUE;
  }

  // Set whether this dynamic object has any DT_NEEDED entries which
  // were not seen during the link.
  void
  set_has_unknown_needed_entries(bool set)
  {
    gold_assert(this->unknown_needed_ == UNKNOWN_NEEDED_UNSET);
    this->unknown_needed_ = set ? UNKNOWN_NEEDED_TRUE : UNKNOWN_NEEDED_FALSE;
  }

  // Compute the ELF hash code for a string.
  static uint32_t
  elf_hash(const char*);

  // Create a standard ELF hash table, setting *PPHASH and *PHASHLEN.
  // DYNSYMS is the global dynamic symbols.  LOCAL_DYNSYM_COUNT is the
  // number of local dynamic symbols, which is the index of the first
  // dynamic gobal symbol.
  static void
  create_elf_hash_table(const std::vector<Symbol*>& dynsyms,
			unsigned int local_dynsym_count,
			unsigned char** pphash,
			unsigned int* phashlen);

  // Create a GNU hash table, setting *PPHASH and *PHASHLEN.  DYNSYMS
  // is the global dynamic symbols.  LOCAL_DYNSYM_COUNT is the number
  // of local dynamic symbols, which is the index of the first dynamic
  // gobal symbol.
  static void
  create_gnu_hash_table(const std::vector<Symbol*>& dynsyms,
			unsigned int local_dynsym_count,
			unsigned char** pphash, unsigned int* phashlen);

 protected:
  // Set the DT_SONAME string.
  void
  set_soname_string(const char* s)
  { this->soname_.assign(s); }

  // Add an entry to the list of DT_NEEDED strings.
  void
  add_needed(const char* s)
  { this->needed_.push_back(std::string(s)); }

 private:
  // Compute the GNU hash code for a string.
  static uint32_t
  gnu_hash(const char*);

  // Compute the number of hash buckets to use.
  static unsigned int
  compute_bucket_count(const std::vector<uint32_t>& hashcodes,
		       bool for_gnu_hash_table);

  // Sized version of create_elf_hash_table.
  template<bool big_endian>
  static void
  sized_create_elf_hash_table(const std::vector<uint32_t>& bucket,
			      const std::vector<uint32_t>& chain,
			      unsigned char* phash,
			      unsigned int hashlen);

  // Sized version of create_gnu_hash_table.
  template<int size, bool big_endian>
  static void
  sized_create_gnu_hash_table(const std::vector<Symbol*>& hashed_dynsyms,
			      const std::vector<uint32_t>& dynsym_hashvals,
			      unsigned int unhashed_dynsym_count,
			      unsigned char** pphash,
			      unsigned int* phashlen);

  // Values for the has_unknown_needed_entries_ field.
  enum Unknown_needed
  {
    UNKNOWN_NEEDED_UNSET,
    UNKNOWN_NEEDED_TRUE,
    UNKNOWN_NEEDED_FALSE
  };

  // The DT_SONAME name, if any.
  std::string soname_;
  // The list of DT_NEEDED entries.
  Needed needed_;
  // Whether this dynamic object has any DT_NEEDED entries not seen
  // during the link.
  Unknown_needed unknown_needed_;
};

// A dynamic object, size and endian specific version.

template<int size, bool big_endian>
class Sized_dynobj : public Dynobj
{
 public:
  typedef typename Sized_relobj<size, big_endian>::Symbols Symbols;

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

  // Set up the object file based on TARGET.
  void
  setup();

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

  // Lay out the input sections.
  void
  do_layout(Symbol_table*, Layout*, Read_symbols_data*);

  // Add the symbols to the symbol table.
  void
  do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*);

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

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

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

  // Return a view of the contents of a section.  Set *PLEN to the
  // size.
  Object::Location
  do_section_contents(unsigned int shndx)
  { return this->elf_file_.section_contents(shndx); }

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

  // Not used for dynobj.
  uint64_t
  do_section_entsize(unsigned int )
  { gold_unreachable(); }

  // Return section address.
  uint64_t
  do_section_address(unsigned int shndx)
  { return this->elf_file_.section_addr(shndx); }

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

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

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

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

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

  // Get symbol counts.
  void
  do_get_global_symbol_counts(const Symbol_table*, size_t*, size_t*) const;

  // Get the global symbols.
  const Symbols*
  do_get_global_symbols() const
  { return this->symbols_; }

 private:
  // For convenience.
  typedef Sized_dynobj<size, big_endian> This;
  static const int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
  static const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
  static const int dyn_size = elfcpp::Elf_sizes<size>::dyn_size;
  typedef elfcpp::Shdr<size, big_endian> Shdr;
  typedef elfcpp::Dyn<size, big_endian> Dyn;

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

  // Find the dynamic symbol table and the version sections, given the
  // section headers.
  void
  find_dynsym_sections(const unsigned char* pshdrs,
		       unsigned int* pversym_shndx,
		       unsigned int* pverdef_shndx,
		       unsigned int* pverneed_shndx,
		       unsigned int* pdynamic_shndx);

  // Read the dynamic symbol section SHNDX.
  void
  read_dynsym_section(const unsigned char* pshdrs, unsigned int shndx,
		      elfcpp::SHT type, unsigned int link,
		      File_view** view, section_size_type* view_size,
		      unsigned int* view_info);

  // Read the dynamic tags.
  void
  read_dynamic(const unsigned char* pshdrs, unsigned int dynamic_shndx,
	       unsigned int strtab_shndx, const unsigned char* strtabu,
	       off_t strtab_size);

  // Mapping from version number to version name.
  typedef std::vector<const char*> Version_map;

  // Create the version map.
  void
  make_version_map(Read_symbols_data* sd, Version_map*) const;

  // Add version definitions to the version map.
  void
  make_verdef_map(Read_symbols_data* sd, Version_map*) const;

  // Add version references to the version map.
  void
  make_verneed_map(Read_symbols_data* sd, Version_map*) const;

  // Add an entry to the version map.
  void
  set_version_map(Version_map*, unsigned int ndx, const char* name) const;

  // General access to the ELF file.
  elfcpp::Elf_file<size, big_endian, Object> elf_file_;
  // The section index of the dynamic symbol table.
  unsigned int dynsym_shndx_;
  // The entries in the symbol table for the symbols.  We only keep
  // this if we need it to print symbol information.
  Symbols* symbols_;
  // Number of defined symbols.
  size_t defined_count_;
};

// A base class for Verdef and Verneed_version which just handles the
// version index which will be stored in the SHT_GNU_versym section.

class Version_base
{
 public:
  Version_base()
    : index_(-1U)
  { }

  virtual
  ~Version_base()
  { }

  // Return the version index.
  unsigned int
  index() const
  {
    gold_assert(this->index_ != -1U);
    return this->index_;
  }

  // Set the version index.
  void
  set_index(unsigned int index)
  {
    gold_assert(this->index_ == -1U);
    this->index_ = index;
  }

  // Clear the weak flag in a version definition.
  virtual void
  clear_weak() = 0;

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

  // The index of the version definition or reference.
  unsigned int index_;
};

// This class handles a version being defined in the file we are
// generating.

class Verdef : public Version_base
{
 public:
  Verdef(const char* name, const std::vector<std::string>& deps,
         bool is_base, bool is_weak, bool is_info, bool is_symbol_created)
    : name_(name), deps_(deps), is_base_(is_base), is_weak_(is_weak),
      is_info_(is_info), is_symbol_created_(is_symbol_created)
  { }

  // Return the version name.
  const char*
  name() const
  { return this->name_; }

  // Return the number of dependencies.
  unsigned int
  count_dependencies() const
  { return this->deps_.size(); }

  // Add a dependency to this version.  The NAME should be
  // canonicalized in the dynamic Stringpool.
  void
  add_dependency(const char* name)
  { this->deps_.push_back(name); }

  // Return whether this definition is weak.
  bool
  is_weak() const
  { return this->is_weak_; }

  // Clear the weak flag.
  void
  clear_weak()
  { this->is_weak_ = false; }

  // Return whether this definition is informational.
  bool
  is_info() const
  { return this->is_info_; }

  // Return whether a version symbol has been created for this
  // definition.
  bool
  is_symbol_created() const
  { return this->is_symbol_created_; }

  // Write contents to buffer.
  template<int size, bool big_endian>
  unsigned char*
  write(const Stringpool*, bool is_last, unsigned char*) const;

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

  // The type of the list of version dependencies.  Each dependency
  // should be canonicalized in the dynamic Stringpool.
  typedef std::vector<std::string> Deps;

  // The name of this version.  This should be canonicalized in the
  // dynamic Stringpool.
  const char* name_;
  // A list of other versions which this version depends upon.
  Deps deps_;
  // Whether this is the base version.
  bool is_base_;
  // Whether this version is weak.
  bool is_weak_;
  // Whether this version is informational.
  bool is_info_;
  // Whether a version symbol has been created.
  bool is_symbol_created_;
};

// A referened version.  This will be associated with a filename by
// Verneed.

class Verneed_version : public Version_base
{
 public:
  Verneed_version(const char* version)
    : version_(version)
  { }

  // Return the version name.
  const char*
  version() const
  { return this->version_; }

  // Clear the weak flag.  This is invalid for a reference.
  void
  clear_weak()
  { gold_unreachable(); }

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

  const char* version_;
};

// Version references in a single dynamic object.

class Verneed
{
 public:
  Verneed(const char* filename)
    : filename_(filename), need_versions_()
  { }

  ~Verneed();

  // Return the file name.
  const char*
  filename() const
  { return this->filename_; }

  // Return the number of versions.
  unsigned int
  count_versions() const
  { return this->need_versions_.size(); }

  // Add a version name.  The name should be canonicalized in the
  // dynamic Stringpool.  If the name is already present, this does
  // nothing.
  Verneed_version*
  add_name(const char* name);

  // Set the version indexes, starting at INDEX.  Return the updated
  // INDEX.
  unsigned int
  finalize(unsigned int index);

  // Write contents to buffer.
  template<int size, bool big_endian>
  unsigned char*
  write(const Stringpool*, bool is_last, unsigned char*) const;

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

  // The type of the list of version names.  Each name should be
  // canonicalized in the dynamic Stringpool.
  typedef std::vector<Verneed_version*> Need_versions;

  // The filename of the dynamic object.  This should be
  // canonicalized in the dynamic Stringpool.
  const char* filename_;
  // The list of version names.
  Need_versions need_versions_;
};

// This class handles version definitions and references which go into
// the output file.

class Versions
{
 public:
  Versions(const Version_script_info&, Stringpool*);

  ~Versions();

  // SYM is going into the dynamic symbol table and has a version.
  // Record the appropriate version information.
  void
  record_version(const Symbol_table* symtab, Stringpool*, const Symbol* sym);

  // Set the version indexes.  DYNSYM_INDEX is the index we should use
  // for the next dynamic symbol.  We add new dynamic symbols to SYMS
  // and return an updated DYNSYM_INDEX.
  unsigned int
  finalize(Symbol_table* symtab, unsigned int dynsym_index,
	   std::vector<Symbol*>* syms);

  // Return whether there are any version definitions.
  bool
  any_defs() const
  { return !this->defs_.empty(); }

  // Return whether there are any version references.
  bool
  any_needs() const
  { return !this->needs_.empty(); }

  // Build an allocated buffer holding the contents of the symbol
  // version section (.gnu.version).
  template<int size, bool big_endian>
  void
  symbol_section_contents(const Symbol_table*, const Stringpool*,
			  unsigned int local_symcount,
			  const std::vector<Symbol*>& syms,
			  unsigned char**, unsigned int*) const;

  // Build an allocated buffer holding the contents of the version
  // definition section (.gnu.version_d).
  template<int size, bool big_endian>
  void
  def_section_contents(const Stringpool*, unsigned char**,
		       unsigned int* psize, unsigned int* pentries) const;

  // Build an allocated buffer holding the contents of the version
  // reference section (.gnu.version_r).
  template<int size, bool big_endian>
  void
  need_section_contents(const Stringpool*, unsigned char**,
			unsigned int* psize, unsigned int* pentries) const;

  const Version_script_info&
  version_script() const
  { return this->version_script_; }

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

  // The type of the list of version definitions.
  typedef std::vector<Verdef*> Defs;

  // The type of the list of version references.
  typedef std::vector<Verneed*> Needs;

  // Handle a symbol SYM defined with version VERSION.
  void
  add_def(const Symbol* sym, const char* version, Stringpool::Key);

  // Add a reference to version NAME in file FILENAME.
  void
  add_need(Stringpool*, const char* filename, const char* name,
	   Stringpool::Key);

  // Get the dynamic object to use for SYM.
  Dynobj*
  get_dynobj_for_sym(const Symbol_table*, const Symbol* sym) const;

  // Return the version index to use for SYM.
  unsigned int
  version_index(const Symbol_table*, const Stringpool*,
		const Symbol* sym) const;

  // Define the base version of a shared library.
  void
  define_base_version(Stringpool* dynpool);

  // We keep a hash table mapping canonicalized name/version pairs to
  // a version base.
  typedef std::pair<Stringpool::Key, Stringpool::Key> Key;

  struct Version_table_hash
  {
    size_t
    operator()(const Key& k) const
    { return k.first + k.second; }
  };

  struct Version_table_eq
  {
    bool
    operator()(const Key& k1, const Key& k2) const
    { return k1.first == k2.first && k1.second == k2.second; }
  };

  typedef Unordered_map<Key, Version_base*, Version_table_hash,
			Version_table_eq> Version_table;

  // The version definitions.
  Defs defs_;
  // The version references.
  Needs needs_;
  // The mapping from a canonicalized version/filename pair to a
  // version index.  The filename may be NULL.
  Version_table version_table_;
  // Whether the version indexes have been set.
  bool is_finalized_;
  // Contents of --version-script, if passed, or NULL.
  const Version_script_info& version_script_;
  // Whether we need to insert a base version.  This is only used for
  // shared libaries and is cleared when the base version is defined.
  bool needs_base_version_;
};

} // End namespace gold.

#endif // !defined(GOLD_DYNOBJ_H)
