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

// Copyright (C) 2006-2019 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];

  // Name of 64-bit symbol table member.
  static const char sym64name[7];

  // 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.
  template<int mapsize>
  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)
