// plugin.h -- plugin manager for gold      -*- C++ -*-

// Copyright 2008, 2009 Free Software Foundation, Inc.
// Written by Cary Coutant <ccoutant@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_PLUGIN_H
#define GOLD_PLUGIN_H

#include <list>
#include <string>

#include "object.h"
#include "plugin-api.h"
#include "workqueue.h"

namespace gold
{

class General_options;
class Input_file;
class Input_objects;
class Symbol_table;
class Layout;
class Dirsearch;
class Mapfile;
class Task_token;
class Pluginobj;

// This class represents a single plugin library.

class Plugin
{
 public:
  Plugin(const char* filename)
    : handle_(NULL),
      filename_(filename),
      args_(),
      claim_file_handler_(NULL),
      all_symbols_read_handler_(NULL),
      cleanup_handler_(NULL)      
  { }

  ~Plugin()
  { }

  // Load the library and call its entry point.
  void
  load();

  // Call the claim-file handler.
  bool
  claim_file(struct ld_plugin_input_file *plugin_input_file);

  // Call the all-symbols-read handler.
  void
  all_symbols_read();

  // Call the cleanup handler.
  void
  cleanup();

  // Register a claim-file handler.
  void
  set_claim_file_handler(ld_plugin_claim_file_handler handler)
  { this->claim_file_handler_ = handler; }

  // Register an all-symbols-read handler.
  void
  set_all_symbols_read_handler(ld_plugin_all_symbols_read_handler handler)
  { this->all_symbols_read_handler_ = handler; }

  // Register a claim-file handler.
  void
  set_cleanup_handler(ld_plugin_cleanup_handler handler)
  { this->cleanup_handler_ = handler; }

  // Add an argument
  void
  add_option(const char *arg)
  {
    this->args_.push_back(arg);
  }

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

  // The shared library handle returned by dlopen.
  void* handle_;
  // The argument string given to --plugin.
  std::string filename_;
  // The list of argument string given to --plugin-opt.
  std::vector<std::string> args_;
  // The plugin's event handlers.
  ld_plugin_claim_file_handler claim_file_handler_;
  ld_plugin_all_symbols_read_handler all_symbols_read_handler_;
  ld_plugin_cleanup_handler cleanup_handler_;
};

// A manager class for plugins.

class Plugin_manager
{
 public:
  Plugin_manager(const General_options& options)
    : plugins_(), objects_(), deferred_layout_objects_(), input_file_(NULL),
      plugin_input_file_(), in_replacement_phase_(false), cleanup_done_(false),
      options_(options), workqueue_(NULL), task_(NULL), input_objects_(NULL),
      symtab_(NULL), layout_(NULL), dirpath_(NULL), mapfile_(NULL),
      this_blocker_(NULL)
  { this->current_ = plugins_.end(); }

  ~Plugin_manager();

  // Add a plugin library.
  void
  add_plugin(const char* filename)
  { this->plugins_.push_back(new Plugin(filename)); }

  // Add an argument to the current plugin.
  void
  add_plugin_option(const char* opt)
  {
    Plugin* last = this->plugins_.back();
    last->add_option(opt);
  }

  // Load all plugin libraries.
  void
  load_plugins();

  // Call the plugin claim-file handlers in turn to see if any claim the file.
  Pluginobj*
  claim_file(Input_file *input_file, off_t offset, off_t filesize);

  // Call the all-symbols-read handlers.
  void
  all_symbols_read(Workqueue* workqueue, Task* task,
                   Input_objects* input_objects, Symbol_table* symtab,
                   Layout* layout, Dirsearch* dirpath, Mapfile* mapfile,
                   Task_token** last_blocker);

  // Run deferred layout.
  void
  layout_deferred_objects();

  // Call the cleanup handlers.
  void
  cleanup();

  // Register a claim-file handler.
  void
  set_claim_file_handler(ld_plugin_claim_file_handler handler)
  {
    gold_assert(this->current_ != plugins_.end());
    (*this->current_)->set_claim_file_handler(handler);
  }

  // Register an all-symbols-read handler.
  void
  set_all_symbols_read_handler(ld_plugin_all_symbols_read_handler handler)
  {
    gold_assert(this->current_ != plugins_.end());
    (*this->current_)->set_all_symbols_read_handler(handler);
  }

  // Register a claim-file handler.
  void
  set_cleanup_handler(ld_plugin_cleanup_handler handler)
  {
    gold_assert(this->current_ != plugins_.end());
    (*this->current_)->set_cleanup_handler(handler);
  }

  // Make a new Pluginobj object.  This is called when the plugin calls
  // the add_symbols API.
  Pluginobj*
  make_plugin_object(unsigned int handle);

  // Return the Pluginobj associated with the given HANDLE.
  Pluginobj*
  object(unsigned int handle) const
  {
    if (handle >= this->objects_.size())
      return NULL;
    return this->objects_[handle];
  }

  // Return TRUE if any input files have been claimed by a plugin
  // and we are still in the initial input phase.
  bool
  should_defer_layout() const
  { return !this->objects_.empty() && !this->in_replacement_phase_; }

  // Add a regular object to the deferred layout list.  These are
  // objects whose layout has been deferred until after the
  // replacement files have arrived.
  void
  add_deferred_layout_object(Relobj* obj)
  { this->deferred_layout_objects_.push_back(obj); }

  // Get input file information with an open (possibly re-opened)
  // file descriptor.
  ld_plugin_status
  get_input_file(unsigned int handle, struct ld_plugin_input_file *file);

  // Release an input file.
  ld_plugin_status
  release_input_file(unsigned int handle);

  // Add a new input file.
  ld_plugin_status
  add_input_file(char *pathname);

  // Return TRUE if we are in the replacement phase.
  bool
  in_replacement_phase() const
  { return this->in_replacement_phase_; }

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

  typedef std::list<Plugin*> Plugin_list;
  typedef std::vector<Pluginobj*> Object_list;
  typedef std::vector<Relobj*> Deferred_layout_list;

  // The list of plugin libraries.
  Plugin_list plugins_;
  // A pointer to the current plugin.  Used while loading plugins.
  Plugin_list::iterator current_;

  // The list of plugin objects.  The index of an item in this list
  // serves as the "handle" that we pass to the plugins.
  Object_list objects_;

  // The list of regular objects whose layout has been deferred.
  Deferred_layout_list deferred_layout_objects_;

  // The file currently up for claim by the plugins.
  Input_file* input_file_;
  struct ld_plugin_input_file plugin_input_file_;

  // TRUE after the all symbols read event; indicates that we are
  // processing replacement files whose symbols should replace the
  // placeholder symbols from the Pluginobj objects.
  bool in_replacement_phase_;

  // TRUE if the cleanup handlers have been called.
  bool cleanup_done_;

  const General_options& options_;
  Workqueue* workqueue_;
  Task* task_;
  Input_objects* input_objects_;
  Symbol_table* symtab_;
  Layout* layout_;
  Dirsearch* dirpath_;
  Mapfile* mapfile_;
  Task_token* this_blocker_;
};


// An object file claimed by a plugin.  This is an abstract base class.
// The implementation is the template class Sized_pluginobj.

class Pluginobj : public Object
{
 public:

  typedef std::vector<Symbol*> Symbols;

  Pluginobj(const std::string& name, Input_file* input_file, off_t offset,
            off_t filesize);

  // Fill in the symbol resolution status for the given plugin symbols.
  ld_plugin_status
  get_symbol_resolution_info(int nsyms, ld_plugin_symbol* syms) const;

  // Store the incoming symbols from the plugin for later processing.
  void
  store_incoming_symbols(int nsyms, const struct ld_plugin_symbol* syms)
  {
    this->nsyms_ = nsyms;
    this->syms_ = syms;
  }

  // Return TRUE if the comdat group with key COMDAT_KEY from this object
  // should be kept.
  bool
  include_comdat_group(std::string comdat_key, Layout* layout);

  // Return the filename.
  const std::string&
  filename() const
  { return this->input_file()->filename(); }

  // Return the file descriptor.
  int
  descriptor()
  { return this->input_file()->file().descriptor(); }

  // Return the size of the file or archive member.
  off_t
  filesize()
  { return this->filesize_; }

 protected:
  // Return TRUE if this is an object claimed by a plugin.
  virtual Pluginobj*
  do_pluginobj()
  { return this; }

  // The number of symbols provided by the plugin.
  int nsyms_;
  
  // The symbols provided by the plugin.
  const struct ld_plugin_symbol* syms_;

  // The entries in the symbol table for the external symbols.
  Symbols symbols_;

 private:
  // Size of the file (or archive member).
  off_t filesize_;
  // Map a comdat key symbol to a boolean indicating whether the comdat
  // group in this object with that key should be kept.
  typedef Unordered_map<std::string, bool> Comdat_map;
  Comdat_map comdat_map_;
};

// A plugin object, size-specific version.

template<int size, bool big_endian>
class Sized_pluginobj : public Pluginobj
{
 public:
  Sized_pluginobj(const std::string& name, Input_file* input_file,
                  off_t offset, off_t filesize);

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

  // Get the size of a section.
  uint64_t
  do_section_size(unsigned int shndx);

  // Get the name of a section.
  std::string
  do_section_name(unsigned int shndx);

  // Return a view of the contents of a section.
  Object::Location
  do_section_contents(unsigned int shndx);

  // Return section flags.
  uint64_t
  do_section_flags(unsigned int shndx);

  // Return section address.
  uint64_t
  do_section_address(unsigned int shndx);

  // Return section type.
  unsigned int
  do_section_type(unsigned int shndx);

  // Return the section link field.
  unsigned int
  do_section_link(unsigned int shndx);

  // Return the section link field.
  unsigned int
  do_section_info(unsigned int shndx);

  // Return the section alignment.
  uint64_t
  do_section_addralign(unsigned int 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;

  // Add placeholder symbols from a claimed file.
  ld_plugin_status
  add_symbols_from_plugin(int nsyms, const ld_plugin_symbol* syms);

 protected:

 private:
};

// This Task handles handles the "all symbols read" event hook.
// The plugin may add additional input files at this time, which must
// be queued for reading.

class Plugin_hook : public Task
{
 public:
  Plugin_hook(const General_options& options, Input_objects* input_objects,
	      Symbol_table* symtab, Layout* layout, Dirsearch* dirpath,
	      Mapfile* mapfile, Task_token* this_blocker,
	      Task_token* next_blocker)
    : options_(options), input_objects_(input_objects), symtab_(symtab),
      layout_(layout), dirpath_(dirpath), mapfile_(mapfile),
      this_blocker_(this_blocker), next_blocker_(next_blocker)
  { }

  ~Plugin_hook();

  // The standard Task methods.

  Task_token*
  is_runnable();

  void
  locks(Task_locker*);

  void
  run(Workqueue*);

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

 private:
  const General_options& options_;
  Input_objects* input_objects_;
  Symbol_table* symtab_;
  Layout* layout_;
  Dirsearch* dirpath_;
  Mapfile* mapfile_;
  Task_token* this_blocker_;
  Task_token* next_blocker_;
};

} // End namespace gold.

#endif // !defined(GOLD_PLUGIN_H)
