// readsyms.cc -- read input file symbols for gold

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

#include "gold.h"

#include <cstring>

#include "elfcpp.h"
#include "options.h"
#include "dirsearch.h"
#include "symtab.h"
#include "object.h"
#include "archive.h"
#include "script.h"
#include "readsyms.h"
#include "plugin.h"
#include "layout.h"
#include "incremental.h"

namespace gold
{

// If we fail to open the object, then we won't create an Add_symbols
// task.  However, we still need to unblock the token, or else the
// link won't proceed to generate more error messages.  We can only
// unblock tokens when the workqueue lock is held, so we need a dummy
// task to do that.  The dummy task has to maintain the right sequence
// of blocks, so we need both this_blocker and next_blocker.

class Unblock_token : public Task
{
 public:
  Unblock_token(Task_token* this_blocker, Task_token* next_blocker)
    : this_blocker_(this_blocker), next_blocker_(next_blocker)
  { }

  ~Unblock_token()
  {
    if (this->this_blocker_ != NULL)
      delete this->this_blocker_;
  }

  Task_token*
  is_runnable()
  {
    if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
      return this->this_blocker_;
    return NULL;
  }

  void
  locks(Task_locker* tl)
  { tl->add(this, this->next_blocker_); }

  void
  run(Workqueue*)
  { }

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

 private:
  Task_token* this_blocker_;
  Task_token* next_blocker_;
};

// Class read_symbols.

Read_symbols::~Read_symbols()
{
  // The this_blocker_ and next_blocker_ pointers are passed on to the
  // Add_symbols task.
}

// If appropriate, issue a warning about skipping an incompatible
// file.

void
Read_symbols::incompatible_warning(const Input_argument* input_argument,
				   const Input_file* input_file)
{
  if (parameters->options().warn_search_mismatch())
    gold_warning("skipping incompatible %s while searching for %s",
		 input_file->filename().c_str(),
		 input_argument->file().name());
}

// Requeue a Read_symbols task to search for the next object with the
// same name.

void
Read_symbols::requeue(Workqueue* workqueue, Input_objects* input_objects,
		      Symbol_table* symtab, Layout* layout, Dirsearch* dirpath,
		      int dirindex, Mapfile* mapfile,
		      const Input_argument* input_argument,
		      Input_group* input_group, Task_token* next_blocker)
{
  // Bump the directory search index.
  ++dirindex;

  // We don't need to worry about this_blocker, since we already
  // reached it.  However, we are removing the blocker on next_blocker
  // because the calling task is completing.  So we need to add a new
  // blocker.  Since next_blocker may be shared by several tasks, we
  // need to increment the count with the workqueue lock held.
  workqueue->add_blocker(next_blocker);

  workqueue->queue(new Read_symbols(input_objects, symtab, layout, dirpath,
				    dirindex, mapfile, input_argument,
				    input_group, NULL, NULL, next_blocker));
}

// Return whether a Read_symbols task is runnable.  We can read an
// ordinary input file immediately.  For an archive specified using
// -l, we have to wait until the search path is complete.

Task_token*
Read_symbols::is_runnable()
{
  if (this->input_argument_->is_file()
      && this->input_argument_->file().may_need_search()
      && this->dirpath_->token()->is_blocked())
    return this->dirpath_->token();

  return NULL;
}

// Return a Task_locker for a Read_symbols task.  We don't need any
// locks here.

void
Read_symbols::locks(Task_locker* tl)
{
  if (this->member_ != NULL)
    tl->add(this, this->next_blocker_);
}

// Run a Read_symbols task.

void
Read_symbols::run(Workqueue* workqueue)
{
  // If we didn't queue a new task, then we need to explicitly unblock
  // the token.
  if (!this->do_read_symbols(workqueue))
    workqueue->queue_soon(new Unblock_token(this->this_blocker_,
					    this->next_blocker_));
}

// Handle a whole lib group. Other then collecting statisticts, this just
// mimics what we do for regular object files in the command line.

bool
Read_symbols::do_whole_lib_group(Workqueue* workqueue)
{
  const Input_file_lib* lib_group = this->input_argument_->lib();

  ++Lib_group::total_lib_groups;

  Task_token* this_blocker = this->this_blocker_;
  for (Input_file_lib::const_iterator i = lib_group->begin();
       i != lib_group->end();
       ++i)
    {
      ++Lib_group::total_members;
      ++Lib_group::total_members_loaded;

      const Input_argument* arg = &*i;

      Task_token* next_blocker;
      if (i != lib_group->end() - 1)
        {
          next_blocker = new Task_token(true);
          next_blocker->add_blocker();
        }
      else
        next_blocker = this->next_blocker_;

      workqueue->queue_soon(new Read_symbols(this->input_objects_,
					     this->symtab_, this->layout_,
					     this->dirpath_, this->dirindex_,
					     this->mapfile_, arg, NULL,
					     NULL, this_blocker, next_blocker));
      this_blocker = next_blocker;
    }

  return true;
}

// Handle a lib group. We set Read_symbols Tasks as usual, but have them
// just record the symbol data instead of adding the objects.  We also start
// a Add_lib_group_symbols Task which runs after we've read all the symbols.
// In that task we process the members in a loop until we are done.

bool
Read_symbols::do_lib_group(Workqueue* workqueue)
{
  const Input_file_lib* lib_group = this->input_argument_->lib();

  if (lib_group->options().whole_archive())
    return this->do_whole_lib_group(workqueue);

  Lib_group* lib = new Lib_group(lib_group, this);

  Add_lib_group_symbols* add_lib_group_symbols =
    new Add_lib_group_symbols(this->symtab_, this->layout_,
			      this->input_objects_,
			      lib, this->next_blocker_);


  Task_token* next_blocker = new Task_token(true);
  int j = 0;
  for (Input_file_lib::const_iterator i = lib_group->begin();
       i != lib_group->end();
       ++i, ++j)
    {
      const Input_argument* arg = &*i;
      Archive_member* m = lib->get_member(j);

      next_blocker->add_blocker();

      // Since this Read_symbols will not create an Add_symbols,
      // just pass NULL as this_blocker.
      workqueue->queue_soon(new Read_symbols(this->input_objects_,
					     this->symtab_, this->layout_,
					     this->dirpath_, this->dirindex_,
					     this->mapfile_, arg, NULL,
					     m, NULL, next_blocker));
    }

  add_lib_group_symbols->set_blocker(next_blocker);
  workqueue->queue_soon(add_lib_group_symbols);

  return true;
}

// Open the file and read the symbols.  Return true if a new task was
// queued, false if that could not happen due to some error.

bool
Read_symbols::do_read_symbols(Workqueue* workqueue)
{
  if (this->input_argument_->is_group())
    {
      gold_assert(this->input_group_ == NULL);
      this->do_group(workqueue);
      return true;
    }

  if (this->input_argument_->is_lib())
    return this->do_lib_group(workqueue);

  Input_file* input_file = new Input_file(&this->input_argument_->file());
  if (!input_file->open(*this->dirpath_, this, &this->dirindex_))
    return false;

  // Read enough of the file to pick up the entire ELF header.

  off_t filesize = input_file->file().filesize();

  if (filesize == 0)
    {
      gold_error(_("%s: file is empty"),
		 input_file->file().filename().c_str());
      return false;
    }

  const unsigned char* ehdr;
  int read_size;
  bool is_elf = is_elf_object(input_file, 0, &ehdr, &read_size);

  if (read_size >= Archive::sarmag)
    {
      bool is_thin_archive
          = memcmp(ehdr, Archive::armagt, Archive::sarmag) == 0;
      if (is_thin_archive
          || memcmp(ehdr, Archive::armag, Archive::sarmag) == 0)
	{
	  // This is an archive.
	  Archive* arch = new Archive(this->input_argument_->file().name(),
				      input_file, is_thin_archive,
				      this->dirpath_, this);
	  arch->setup();

	  if (this->layout_->incremental_inputs())
	    {
	      const Input_argument* ia = this->input_argument_;
	      this->layout_->incremental_inputs()->report_archive(ia, arch);
	    }

	  // Unlock the archive so it can be used in the next task.
	  arch->unlock(this);

	  workqueue->queue_next(new Add_archive_symbols(this->symtab_,
							this->layout_,
							this->input_objects_,
							this->dirpath_,
							this->dirindex_,
							this->mapfile_,
							this->input_argument_,
							arch,
							this->input_group_,
							this->this_blocker_,
							this->next_blocker_));
	  return true;
	}
    }

  if (parameters->options().has_plugins())
    {
      Pluginobj* obj = parameters->options().plugins()->claim_file(input_file,
                                                                   0, filesize);
      if (obj != NULL)
        {
          // The input file was claimed by a plugin, and its symbols
          // have been provided by the plugin.

          // We are done with the file at this point, so unlock it.
          obj->unlock(this);

          if (this->member_ != NULL)
	    {
	      this->member_->sd_ = NULL;
	      this->member_->obj_ = obj;
	      return true;
	    }

          workqueue->queue_next(new Add_symbols(this->input_objects_,
                                                this->symtab_,
                                                this->layout_,
						this->dirpath_,
						this->dirindex_,
						this->mapfile_,
						this->input_argument_,
                                                obj,
						NULL,
                                                this->this_blocker_,
                                                this->next_blocker_));
          return true;
        }
    }

  if (is_elf)
    {
      // This is an ELF object.

      bool unconfigured = false;
      bool* punconfigured = (input_file->will_search_for()
			     ? &unconfigured
			     : NULL);
      Object* obj = make_elf_object(input_file->filename(),
				    input_file, 0, ehdr, read_size,
				    punconfigured);
      if (obj == NULL)
	{
	  if (unconfigured)
	    {
	      Read_symbols::incompatible_warning(this->input_argument_,
						 input_file);
	      input_file->file().release();
	      input_file->file().unlock(this);
	      delete input_file;
	      ++this->dirindex_;
	      return this->do_read_symbols(workqueue);
	    }
	  return false;
	}

      Read_symbols_data* sd = new Read_symbols_data;
      obj->read_symbols(sd);

      if (this->layout_->incremental_inputs())
	{
	  const Input_argument* ia = this->input_argument_;
	  this->layout_->incremental_inputs()->report_object(ia, obj);
	}

      // Opening the file locked it, so now we need to unlock it.  We
      // need to unlock it before queuing the Add_symbols task,
      // because the workqueue doesn't know about our lock on the
      // file.  If we queue the Add_symbols task first, it will be
      // stuck on the end of the file lock, but since the workqueue
      // doesn't know about that lock, it will never release the
      // Add_symbols task.

      input_file->file().unlock(this);

      if (this->member_ != NULL)
        {
          this->member_->sd_ = sd;
          this->member_->obj_ = obj;
          return true;
        }

      // We use queue_next because everything is cached for this
      // task to run right away if possible.

      workqueue->queue_next(new Add_symbols(this->input_objects_,
					    this->symtab_, this->layout_,
					    this->dirpath_,
					    this->dirindex_,
					    this->mapfile_,
					    this->input_argument_,
					    obj,
					    sd,
					    this->this_blocker_,
					    this->next_blocker_));

      return true;
    }

  // Queue up a task to try to parse this file as a script.  We use a
  // separate task so that the script will be read in order with other
  // objects named on the command line.  Also so that we don't try to
  // read multiple scripts simultaneously, which could lead to
  // unpredictable changes to the General_options structure.

  workqueue->queue_soon(new Read_script(this->symtab_,
					this->layout_,
					this->dirpath_,
					this->dirindex_,
					this->input_objects_,
					this->mapfile_,
					this->input_group_,
					this->input_argument_,
					input_file,
					this->this_blocker_,
					this->next_blocker_));
  return true;
}

// Handle a group.  We need to walk through the arguments over and
// over until we don't see any new undefined symbols.  We do this by
// setting off Read_symbols Tasks as usual, but recording the archive
// entries instead of deleting them.  We also start a Finish_group
// Task which runs after we've read all the symbols.  In that task we
// process the archives in a loop until we are done.

void
Read_symbols::do_group(Workqueue* workqueue)
{
  Input_group* input_group = new Input_group();

  const Input_file_group* group = this->input_argument_->group();
  Task_token* this_blocker = this->this_blocker_;

  Finish_group* finish_group = new Finish_group(this->input_objects_,
						this->symtab_,
						this->layout_,
						this->mapfile_,
						input_group,
						this->next_blocker_);

  Task_token* next_blocker = new Task_token(true);
  next_blocker->add_blocker();
  workqueue->queue_soon(new Start_group(this->symtab_, finish_group,
					this_blocker, next_blocker));
  this_blocker = next_blocker;

  for (Input_file_group::const_iterator p = group->begin();
       p != group->end();
       ++p)
    {
      const Input_argument* arg = &*p;
      gold_assert(arg->is_file());

      next_blocker = new Task_token(true);
      next_blocker->add_blocker();
      workqueue->queue_soon(new Read_symbols(this->input_objects_,
					     this->symtab_, this->layout_,
					     this->dirpath_, this->dirindex_,
					     this->mapfile_, arg, input_group,
					     NULL, this_blocker, next_blocker));
      this_blocker = next_blocker;
    }

  finish_group->set_blocker(this_blocker);

  workqueue->queue_soon(finish_group);
}

// Return a debugging name for a Read_symbols task.

std::string
Read_symbols::get_name() const
{
  if (this->input_argument_->is_group())
    {
      std::string ret("Read_symbols group (");
      bool add_space = false;
      const Input_file_group* group = this->input_argument_->group();
      for (Input_file_group::const_iterator p = group->begin();
           p != group->end();
           ++p)
      {
        if (add_space)
          ret += ' ';
        ret += p->file().name();
        add_space = true;
      }
      return ret + ')';
    }
  else if (this->input_argument_->is_lib())
    {
      std::string ret("Read_symbols lib (");
      bool add_space = false;
      const Input_file_lib* lib = this->input_argument_->lib();
      for (Input_file_lib::const_iterator p = lib->begin();
           p != lib->end();
           ++p)
      {
        if (add_space)
          ret += ' ';
        ret += p->file().name();
        add_space = true;
      }
      return ret + ')';
    }
  else
    {
      std::string ret("Read_symbols ");
      if (this->input_argument_->file().is_lib())
	ret += "-l";
      else if (this->input_argument_->file().is_searched_file())
	ret += "-l:";
      ret += this->input_argument_->file().name();
      return ret;
    }
}

// Class Add_symbols.

Add_symbols::~Add_symbols()
{
  if (this->this_blocker_ != NULL)
    delete this->this_blocker_;
  // next_blocker_ is deleted by the task associated with the next
  // input file.
}

// We are blocked by this_blocker_.  We block next_blocker_.  We also
// lock the file.

Task_token*
Add_symbols::is_runnable()
{
  if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
    return this->this_blocker_;
  if (this->object_->is_locked())
    return this->object_->token();
  return NULL;
}

void
Add_symbols::locks(Task_locker* tl)
{
  tl->add(this, this->next_blocker_);
  tl->add(this, this->object_->token());
}

// Add the symbols in the object to the symbol table.

void
Add_symbols::run(Workqueue*)
{
  Pluginobj* pluginobj = this->object_->pluginobj();
  if (pluginobj != NULL)
    {
      this->object_->add_symbols(this->symtab_, this->sd_, this->layout_);
      return;
    }

  if (!this->input_objects_->add_object(this->object_))
    {
      delete this->sd_;
      this->sd_ = NULL;
      this->object_->release();
      delete this->object_;
    }
  else
    {
      this->object_->layout(this->symtab_, this->layout_, this->sd_);
      this->object_->add_symbols(this->symtab_, this->sd_, this->layout_);
      delete this->sd_;
      this->sd_ = NULL;
      this->object_->release();
    }
}

// Class Start_group.

Start_group::~Start_group()
{
  if (this->this_blocker_ != NULL)
    delete this->this_blocker_;
  // next_blocker_ is deleted by the task associated with the first
  // file in the group.
}

// We need to wait for THIS_BLOCKER_ and unblock NEXT_BLOCKER_.

Task_token*
Start_group::is_runnable()
{
  if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
    return this->this_blocker_;
  return NULL;
}

void
Start_group::locks(Task_locker* tl)
{
  tl->add(this, this->next_blocker_);
}

// Store the number of undefined symbols we see now.

void
Start_group::run(Workqueue*)
{
  this->finish_group_->set_saw_undefined(this->symtab_->saw_undefined());
}

// Class Finish_group.

Finish_group::~Finish_group()
{
  if (this->this_blocker_ != NULL)
    delete this->this_blocker_;
  // next_blocker_ is deleted by the task associated with the next
  // input file following the group.
}

// We need to wait for THIS_BLOCKER_ and unblock NEXT_BLOCKER_.

Task_token*
Finish_group::is_runnable()
{
  if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
    return this->this_blocker_;
  return NULL;
}

void
Finish_group::locks(Task_locker* tl)
{
  tl->add(this, this->next_blocker_);
}

// Loop over the archives until there are no new undefined symbols.

void
Finish_group::run(Workqueue*)
{
  size_t saw_undefined = this->saw_undefined_;
  while (saw_undefined != this->symtab_->saw_undefined())
    {
      saw_undefined = this->symtab_->saw_undefined();

      for (Input_group::const_iterator p = this->input_group_->begin();
	   p != this->input_group_->end();
	   ++p)
	{
	  Task_lock_obj<Archive> tl(this, *p);

	  (*p)->add_symbols(this->symtab_, this->layout_,
			    this->input_objects_, this->mapfile_);
	}
    }

  // Delete all the archives now that we no longer need them.
  for (Input_group::const_iterator p = this->input_group_->begin();
       p != this->input_group_->end();
       ++p)
    delete *p;
  delete this->input_group_;
}

// Class Read_script

Read_script::~Read_script()
{
  if (this->this_blocker_ != NULL)
    delete this->this_blocker_;
  // next_blocker_ is deleted by the task associated with the next
  // input file.
}

// We are blocked by this_blocker_.

Task_token*
Read_script::is_runnable()
{
  if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
    return this->this_blocker_;
  return NULL;
}

// We don't unlock next_blocker_ here.  If the script names any input
// files, then the last file will be responsible for unlocking it.

void
Read_script::locks(Task_locker*)
{
}

// Read the script, if it is a script.

void
Read_script::run(Workqueue* workqueue)
{
  bool used_next_blocker;
  if (!read_input_script(workqueue, this->symtab_, this->layout_,
			 this->dirpath_, this->dirindex_, this->input_objects_,
			 this->mapfile_, this->input_group_,
			 this->input_argument_, this->input_file_,
			 this->next_blocker_, &used_next_blocker))
    {
      // Here we have to handle any other input file types we need.
      gold_error(_("%s: not an object or archive"),
		 this->input_file_->file().filename().c_str());
    }

  if (!used_next_blocker)
    {
      // Queue up a task to unlock next_blocker.  We can't just unlock
      // it here, as we don't hold the workqueue lock.
      workqueue->queue_soon(new Unblock_token(NULL, this->next_blocker_));
    }
}

// Return a debugging name for a Read_script task.

std::string
Read_script::get_name() const
{
  std::string ret("Read_script ");
  if (this->input_argument_->file().is_lib())
    ret += "-l";
  else if (this->input_argument_->file().is_searched_file())
    ret += "-l:";
  ret += this->input_argument_->file().name();
  return ret;
}

} // End namespace gold.
