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

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

#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:
  // Return a pointer to this object.
  virtual Dynobj*
  do_dynobj()
  { return this; }

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

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

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

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

  // Return section flags.
  uint64_t
  do_section_flags(unsigned int shndx)
  { return 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(Stringpool*, 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 libraries and is cleared when the base version is defined.
  bool needs_base_version_;
};

} // End namespace gold.

#endif // !defined(GOLD_DYNOBJ_H)
