// archive.h -- archive support for gold      -*- C++ -*-

// Copyright (C) 2006-2015 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_ARCHIVE_H
#define GOLD_ARCHIVE_H

#include <string>
#include <vector>

#include "fileread.h"
#include "workqueue.h"

namespace gold
{

class Task;
class Input_argument;
class Input_file;
class Input_objects;
class Input_group;
class Layout;
class Symbol_table;
class Object;
struct Read_symbols_data;
class Input_file_lib;
class Incremental_archive_entry;

// An entry in the archive map of offsets to members.
struct Archive_member
{
  Archive_member()
      : obj_(NULL), sd_(NULL), arg_serial_(0)
  { }
  Archive_member(Object* obj, Read_symbols_data* sd)
      : obj_(obj), sd_(sd), arg_serial_(0)
  { }
  // The object file.
  Object* obj_;
  // The data to pass from read_symbols() to add_symbols().
  Read_symbols_data* sd_;
  // The serial number of the file in the argument list.
  unsigned int arg_serial_;
};

// This class serves as a base class for Archive and Lib_group objects.

class Library_base
{
 public:
  Library_base(Task* task)
    : task_(task), incremental_info_(NULL)
  { }

  virtual
  ~Library_base()
  { }

  // The file name.
  const std::string&
  filename() const
  { return this->do_filename(); }

  // The modification time of the archive file.
  Timespec
  get_mtime()
  { return this->do_get_mtime(); }

  // When we see a symbol in an archive we might decide to include the member,
  // not include the member or be undecided. This enum represents these
  // possibilities.

  enum Should_include
  {
    SHOULD_INCLUDE_NO,
    SHOULD_INCLUDE_YES,
    SHOULD_INCLUDE_UNKNOWN
  };

  static Should_include
  should_include_member(Symbol_table* symtab, Layout*, const char* sym_name,
                        Symbol** symp, std::string* why, char** tmpbufp,
                        size_t* tmpbuflen);

  // Store a pointer to the incremental link info for the library.
  void
  set_incremental_info(Incremental_archive_entry* info)
  { this->incremental_info_ = info; }

  // Return the pointer to the incremental link info for the library.
  Incremental_archive_entry*
  incremental_info() const
  { return this->incremental_info_; }

  // Abstract base class for processing unused symbols.
  class Symbol_visitor_base
  {
   public:
    Symbol_visitor_base()
    { }

    virtual
    ~Symbol_visitor_base()
    { }

    // This function will be called for each unused global
    // symbol in a library, with a pointer to the symbol name.
    virtual void
    visit(const char* /* name */) = 0;
  };

  // Iterator for unused global symbols in the library.
  // Calls v->visit() for each global symbol defined
  // in each unused library member, passing a pointer to
  // the symbol name.
  void
  for_all_unused_symbols(Symbol_visitor_base* v) const
  { this->do_for_all_unused_symbols(v); }

 protected:
  // The task reading this archive.
  Task *task_;

 private:
  // The file name.
  virtual const std::string&
  do_filename() const = 0;

  // Return the modification time of the archive file.
  virtual Timespec
  do_get_mtime() = 0;

  // Iterator for unused global symbols in the library.
  virtual void
  do_for_all_unused_symbols(Symbol_visitor_base* v) const = 0;

  // The incremental link information for this archive.
  Incremental_archive_entry* incremental_info_;
};

// This class represents an archive--generally a libNAME.a file.
// Archives have a symbol table and a list of objects.

class Archive : public Library_base
{
 public:
  Archive(const std::string& name, Input_file* input_file,
          bool is_thin_archive, Dirsearch* dirpath, Task* task);

  // The length of the magic string at the start of an archive.
  static const int sarmag = 8;

  // The magic string at the start of an archive.
  static const char armag[sarmag];
  static const char armagt[sarmag];

  // The string expected at the end of an archive member header.
  static const char arfmag[2];

  // The name of the object.  This is the name used on the command
  // line; e.g., if "-lgcc" is on the command line, this will be
  // "gcc".
  const std::string&
  name() const
  { return this->name_; }

  // The input file.
  const Input_file*
  input_file() const
  { return this->input_file_; }

  // Set up the archive: read the symbol map.
  void
  setup();

  // Get a reference to the underlying file.
  File_read&
  file()
  { return this->input_file_->file(); }

  const File_read&
  file() const
  { return this->input_file_->file(); }

  // Lock the underlying file.
  void
  lock(const Task* t)
  { this->input_file_->file().lock(t); }

  // Unlock the underlying file.
  void
  unlock(const Task* t)
  { this->input_file_->file().unlock(t); }

  // Return whether the underlying file is locked.
  bool
  is_locked() const
  { return this->input_file_->file().is_locked(); }

  // Return the token, so that the task can be queued.
  Task_token*
  token()
  { return this->input_file_->file().token(); }

  // Release the underlying file.
  void
  release()
  { this->input_file_->file().release(); }

  // Clear uncached views in the underlying file.
  void
  clear_uncached_views()
  { this->input_file_->file().clear_uncached_views(); }

  // Whether this is a thin archive.
  bool
  is_thin_archive() const
  { return this->is_thin_archive_; }

  // Unlock any nested archives.
  void
  unlock_nested_archives();

  // Select members from the archive as needed and add them to the
  // link.
  bool
  add_symbols(Symbol_table*, Layout*, Input_objects*, Mapfile*);

  // Return whether the archive defines the symbol.
  bool
  defines_symbol(Symbol*) const;

  // Dump statistical information to stderr.
  static void
  print_stats();

  // Return the number of members in the archive.
  size_t
  count_members();

  // Return the no-export flag.
  bool
  no_export()
  { return this->no_export_; }

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

  // The file name.
  const std::string&
  do_filename() const
  { return this->input_file_->filename(); }

  // The modification time of the archive file.
  Timespec
  do_get_mtime()
  { return this->file().get_mtime(); }

  struct Archive_header;

  // Total number of archives seen.
  static unsigned int total_archives;
  // Total number of archive members seen.
  static unsigned int total_members;
  // Number of archive members loaded.
  static unsigned int total_members_loaded;

  // Get a view into the underlying file.
  const unsigned char*
  get_view(off_t start, section_size_type size, bool aligned, bool cache)
  { return this->input_file_->file().get_view(0, start, size, aligned, cache); }

  // Read the archive symbol map.
  void
  read_armap(off_t start, section_size_type size);

  // Read an archive member header at OFF.  CACHE is whether to cache
  // the file view.  Return the size of the member, and set *PNAME to
  // the name.
  off_t
  read_header(off_t off, bool cache, std::string* pname, off_t* nested_off);

  // Interpret an archive header HDR at OFF.  Return the size of the
  // member, and set *PNAME to the name.
  off_t
  interpret_header(const Archive_header* hdr, off_t off, std::string* pname,
                   off_t* nested_off) const;

  // Get the file and offset for an archive member, which may be an
  // external member of a thin archive.  Set *INPUT_FILE to the
  // file containing the actual member, *MEMOFF to the offset
  // within that file (0 if not a nested archive), and *MEMBER_NAME
  // to the name of the archive member.  Return TRUE on success.
  bool
  get_file_and_offset(off_t off, Input_file** input_file, off_t* memoff,
                      off_t* memsize, std::string* member_name);

  // Return an ELF object for the member at offset OFF.
  Object*
  get_elf_object_for_member(off_t off, bool*);

  // Read the symbols from all the archive members in the link.
  void
  read_all_symbols();

  // Read the symbols from an archive member in the link.  OFF is the file
  // offset of the member header.
  void
  read_symbols(off_t off);

  // Include all the archive members in the link.
  bool
  include_all_members(Symbol_table*, Layout*, Input_objects*, Mapfile*);

  // Include an archive member in the link.
  bool
  include_member(Symbol_table*, Layout*, Input_objects*, off_t off,
		 Mapfile*, Symbol*, const char* why);

  // Return whether we found this archive by searching a directory.
  bool
  searched_for() const
  { return this->input_file_->will_search_for(); }

  // Iterate over archive members.
  class const_iterator;

  const_iterator
  begin();

  const_iterator
  end();

  friend class const_iterator;

  // Iterator for unused global symbols in the library.
  void
  do_for_all_unused_symbols(Symbol_visitor_base* v) const;

  // An entry in the archive map of symbols to object files.
  struct Armap_entry
  {
    // The offset to the symbol name in armap_names_.
    off_t name_offset;
    // The file offset to the object in the archive.
    off_t file_offset;
  };

  // A simple hash code for off_t values.
  class Seen_hash
  {
   public:
    size_t operator()(off_t val) const
    { return static_cast<size_t>(val); }
  };

  // For keeping track of open nested archives in a thin archive file.
  typedef Unordered_map<std::string, Archive*> Nested_archive_table;

  // Name of object as printed to user.
  std::string name_;
  // For reading the file.
  Input_file* input_file_;
  // The archive map.
  std::vector<Armap_entry> armap_;
  // The names in the archive map.
  std::string armap_names_;
  // The extended name table.
  std::string extended_names_;
  // Track which symbols in the archive map are for elements which are
  // defined or which have already been included in the link.
  std::vector<bool> armap_checked_;
  // Track which elements have been included by offset.
  Unordered_set<off_t, Seen_hash> seen_offsets_;
  // Table of objects whose symbols have been pre-read.
  std::map<off_t, Archive_member> members_;
  // True if this is a thin archive.
  const bool is_thin_archive_;
  // True if we have included at least one object from this archive.
  bool included_member_;
  // Table of nested archives, indexed by filename.
  Nested_archive_table nested_archives_;
  // The directory search path.
  Dirsearch* dirpath_;
  // Number of members in this archive;
  unsigned int num_members_;
  // True if we exclude this library archive from automatic export.
  bool no_export_;
  // True if this library has been included as a --whole-archive.
  bool included_all_members_;
};

// This class is used to read an archive and pick out the desired
// elements and add them to the link.

class Add_archive_symbols : public Task
{
 public:
  Add_archive_symbols(Symbol_table* symtab, Layout* layout,
		      Input_objects* input_objects, Dirsearch* dirpath,
		      int dirindex, Mapfile* mapfile,
		      const Input_argument* input_argument,
		      Archive* archive, Input_group* input_group,
		      Task_token* this_blocker,
		      Task_token* next_blocker)
    : symtab_(symtab), layout_(layout), input_objects_(input_objects),
      dirpath_(dirpath), dirindex_(dirindex), mapfile_(mapfile),
      input_argument_(input_argument), archive_(archive),
      input_group_(input_group), this_blocker_(this_blocker),
      next_blocker_(next_blocker)
  { }

  ~Add_archive_symbols();

  // The standard Task methods.

  Task_token*
  is_runnable();

  void
  locks(Task_locker*);

  void
  run(Workqueue*);

  std::string
  get_name() const
  {
    if (this->archive_ == NULL)
      return "Add_archive_symbols";
    return "Add_archive_symbols " + this->archive_->file().filename();
  }

 private:
  Symbol_table* symtab_;
  Layout* layout_;
  Input_objects* input_objects_;
  Dirsearch* dirpath_;
  int dirindex_;
  Mapfile* mapfile_;
  const Input_argument* input_argument_;
  Archive* archive_;
  Input_group* input_group_;
  Task_token* this_blocker_;
  Task_token* next_blocker_;
};

// This class represents the files surrounded by a --start-lib ... --end-lib.

class Lib_group : public Library_base
{
 public:
  Lib_group(const Input_file_lib* lib, Task* task);

  // Select members from the lib group as needed and add them to the link.
  void
  add_symbols(Symbol_table*, Layout*, Input_objects*);

  // Include a member of the lib group in the link.
  void
  include_member(Symbol_table*, Layout*, Input_objects*, const Archive_member&);

  Archive_member*
  get_member(int i)
  {
    return &this->members_[i];
  }

  // Total number of archives seen.
  static unsigned int total_lib_groups;
  // Total number of archive members seen.
  static unsigned int total_members;
  // Number of archive members loaded.
  static unsigned int total_members_loaded;

  // Dump statistical information to stderr.
  static void
  print_stats();

 private:
  // The file name.
  const std::string&
  do_filename() const;

  // A Lib_group does not have a modification time, since there is no
  // real library file.
  Timespec
  do_get_mtime()
  { return Timespec(0, 0); }

  // Iterator for unused global symbols in the library.
  void
  do_for_all_unused_symbols(Symbol_visitor_base*) const;

  // Table of the objects in the group.
  std::vector<Archive_member> members_;
};

// This class is used to pick out the desired elements and add them to the link.

class Add_lib_group_symbols : public Task
{
 public:
  Add_lib_group_symbols(Symbol_table* symtab, Layout* layout,
                        Input_objects* input_objects,
                        Lib_group* lib, Task_token* next_blocker)
      : symtab_(symtab), layout_(layout), input_objects_(input_objects),
        lib_(lib), readsyms_blocker_(NULL), this_blocker_(NULL),
        next_blocker_(next_blocker)
  { }

  ~Add_lib_group_symbols();

  // The standard Task methods.

  Task_token*
  is_runnable();

  void
  locks(Task_locker*);

  void
  run(Workqueue*);

  // Set the blocker to use for this task.
  void
  set_blocker(Task_token* readsyms_blocker, Task_token* this_blocker)
  {
    gold_assert(this->readsyms_blocker_ == NULL && this->this_blocker_ == NULL);
    this->readsyms_blocker_ = readsyms_blocker;
    this->this_blocker_ = this_blocker;
  }

  std::string
  get_name() const
  {
    return "Add_lib_group_symbols";
  }

 private:
  Symbol_table* symtab_;
  Layout* layout_;
  Input_objects* input_objects_;
  Lib_group* lib_;
  Task_token* readsyms_blocker_;
  Task_token* this_blocker_;
  Task_token* next_blocker_;
};

} // End namespace gold.

#endif // !defined(GOLD_ARCHIVE_H)
