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

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

#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 than collecting statistics, 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, this->this_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();

	  // 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;
	}
    }

  Object* elf_obj = NULL;
  bool unconfigured;
  bool* punconfigured = NULL;
  if (is_elf)
    {
      // This is an ELF object.

      unconfigured = false;
      punconfigured = (input_file->will_search_for()
		       ? &unconfigured
		       : NULL);
      elf_obj = make_elf_object(input_file->filename(),
				input_file, 0, ehdr, read_size,
				punconfigured);
    }

  if (parameters->options().has_plugins())
    {
      Pluginobj* obj = parameters->options().plugins()->claim_file(input_file,
                                                                   0, filesize,
								   elf_obj);
      if (obj != NULL)
        {
	  // Delete the elf_obj, this file has been claimed.
	  if (elf_obj != NULL)
	    delete elf_obj;

          // 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,
						NULL,
                                                this->this_blocker_,
                                                this->next_blocker_));
          return true;
        }
    }

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

      if (elf_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;
      elf_obj->read_symbols(sd);

      // 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_ = elf_obj;
          this->member_->arg_serial_ =
              this->input_argument_->file().arg_serial();
          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_,
					    elf_obj,
					    NULL,
					    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_);
  Task_token* token = this->object_->token();
  if (token != NULL)
    tl->add(this, 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_))
    {
      gold_assert(this->sd_ != NULL);
      delete this->sd_;
      this->sd_ = NULL;
      this->object_->release();
      delete this->object_;
    }
  else
    {
      Incremental_inputs* incremental_inputs =
          this->layout_->incremental_inputs();
      if (incremental_inputs != NULL)
	{
          if (this->library_ != NULL && !this->library_->is_reported())
            {
              Incremental_binary* ibase = this->layout_->incremental_base();
              gold_assert(ibase != NULL);
              unsigned int lib_serial = this->library_->arg_serial();
              unsigned int lib_index = this->library_->input_file_index();
	      Script_info* lib_script_info = ibase->get_script_info(lib_index);
	      incremental_inputs->report_archive_begin(this->library_,
						       lib_serial,
						       lib_script_info);
	    }
	  unsigned int arg_serial = this->input_argument_->file().arg_serial();
	  Script_info* script_info = this->input_argument_->script_info();
	  incremental_inputs->report_object(this->object_, arg_serial,
					    this->library_, script_info);
	}
      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 Read_member.

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

// Return whether a Read_member task is runnable.

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

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

// Run a Read_member task.

void
Read_member::run(Workqueue*)
{
  // This task doesn't need to do anything for now.  The Read_symbols task
  // that is queued for the archive library will cause the archive to be
  // processed from scratch.
}

// Class Check_script.

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

// Return whether a Check_script task is runnable.

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

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

// Run a Check_script task.

void
Check_script::run(Workqueue*)
{
  Incremental_inputs* incremental_inputs = this->layout_->incremental_inputs();
  gold_assert(incremental_inputs != NULL);
  unsigned int arg_serial = this->input_reader_->arg_serial();
  Script_info* script_info =
      this->ibase_->get_script_info(this->input_file_index_);
  Timespec mtime = this->input_reader_->get_mtime();
  incremental_inputs->report_script(script_info, arg_serial, mtime);
}

// Class Check_library.

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

// Return whether a Check_library task is runnable.

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

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

// Run a Check_library task.

void
Check_library::run(Workqueue*)
{
  Incremental_inputs* incremental_inputs = this->layout_->incremental_inputs();
  gold_assert(incremental_inputs != NULL);
  Incremental_library* lib = this->ibase_->get_library(this->input_file_index_);
  gold_assert(lib != NULL);
  lib->copy_unused_symbols();
  // FIXME: Check that unused symbols remain unused.
  if (!lib->is_reported())
    {
      unsigned int lib_serial = lib->arg_serial();
      unsigned int lib_index = lib->input_file_index();
      Script_info* script_info = this->ibase_->get_script_info(lib_index);
      incremental_inputs->report_archive_begin(lib, lib_serial, script_info);
    }
  incremental_inputs->report_archive_end(lib);
}

// Class Input_group.

// When we delete an Input_group we can delete the archive
// information.

Input_group::~Input_group()
{
  for (Input_group::const_iterator p = this->begin();
       p != this->end();
       ++p)
    delete *p;
}

// 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_);
	}
    }

  // Now that we're done with the archives, record the incremental
  // layout information.
  for (Input_group::const_iterator p = this->input_group_->begin();
       p != this->input_group_->end();
       ++p)
    {
      // For an incremental link, finish recording the layout information.
      Incremental_inputs* incremental_inputs =
          this->layout_->incremental_inputs();
      if (incremental_inputs != NULL)
	incremental_inputs->report_archive_end(*p);
    }

  if (parameters->options().has_plugins())
    parameters->options().plugins()->save_input_group(this->input_group_);
  else
    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.
