Home | History | Annotate | Download | only in gold
      1 // readsyms.cc -- read input file symbols for gold
      2 
      3 // Copyright (C) 2006-2016 Free Software Foundation, Inc.
      4 // Written by Ian Lance Taylor <iant (at) google.com>.
      5 
      6 // This file is part of gold.
      7 
      8 // This program is free software; you can redistribute it and/or modify
      9 // it under the terms of the GNU General Public License as published by
     10 // the Free Software Foundation; either version 3 of the License, or
     11 // (at your option) any later version.
     12 
     13 // This program is distributed in the hope that it will be useful,
     14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16 // GNU General Public License for more details.
     17 
     18 // You should have received a copy of the GNU General Public License
     19 // along with this program; if not, write to the Free Software
     20 // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     21 // MA 02110-1301, USA.
     22 
     23 #include "gold.h"
     24 
     25 #include <cstring>
     26 
     27 #include "elfcpp.h"
     28 #include "options.h"
     29 #include "dirsearch.h"
     30 #include "symtab.h"
     31 #include "object.h"
     32 #include "archive.h"
     33 #include "script.h"
     34 #include "readsyms.h"
     35 #include "plugin.h"
     36 #include "layout.h"
     37 #include "incremental.h"
     38 
     39 namespace gold
     40 {
     41 
     42 // If we fail to open the object, then we won't create an Add_symbols
     43 // task.  However, we still need to unblock the token, or else the
     44 // link won't proceed to generate more error messages.  We can only
     45 // unblock tokens when the workqueue lock is held, so we need a dummy
     46 // task to do that.  The dummy task has to maintain the right sequence
     47 // of blocks, so we need both this_blocker and next_blocker.
     48 
     49 class Unblock_token : public Task
     50 {
     51  public:
     52   Unblock_token(Task_token* this_blocker, Task_token* next_blocker)
     53     : this_blocker_(this_blocker), next_blocker_(next_blocker)
     54   { }
     55 
     56   ~Unblock_token()
     57   {
     58     if (this->this_blocker_ != NULL)
     59       delete this->this_blocker_;
     60   }
     61 
     62   Task_token*
     63   is_runnable()
     64   {
     65     if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
     66       return this->this_blocker_;
     67     return NULL;
     68   }
     69 
     70   void
     71   locks(Task_locker* tl)
     72   { tl->add(this, this->next_blocker_); }
     73 
     74   void
     75   run(Workqueue*)
     76   { }
     77 
     78   std::string
     79   get_name() const
     80   { return "Unblock_token"; }
     81 
     82  private:
     83   Task_token* this_blocker_;
     84   Task_token* next_blocker_;
     85 };
     86 
     87 // Class read_symbols.
     88 
     89 Read_symbols::~Read_symbols()
     90 {
     91   // The this_blocker_ and next_blocker_ pointers are passed on to the
     92   // Add_symbols task.
     93 }
     94 
     95 // If appropriate, issue a warning about skipping an incompatible
     96 // file.
     97 
     98 void
     99 Read_symbols::incompatible_warning(const Input_argument* input_argument,
    100 				   const Input_file* input_file)
    101 {
    102   if (parameters->options().warn_search_mismatch())
    103     gold_warning("skipping incompatible %s while searching for %s",
    104 		 input_file->filename().c_str(),
    105 		 input_argument->file().name());
    106 }
    107 
    108 // Requeue a Read_symbols task to search for the next object with the
    109 // same name.
    110 
    111 void
    112 Read_symbols::requeue(Workqueue* workqueue, Input_objects* input_objects,
    113 		      Symbol_table* symtab, Layout* layout, Dirsearch* dirpath,
    114 		      int dirindex, Mapfile* mapfile,
    115 		      const Input_argument* input_argument,
    116 		      Input_group* input_group, Task_token* next_blocker)
    117 {
    118   // Bump the directory search index.
    119   ++dirindex;
    120 
    121   // We don't need to worry about this_blocker, since we already
    122   // reached it.  However, we are removing the blocker on next_blocker
    123   // because the calling task is completing.  So we need to add a new
    124   // blocker.  Since next_blocker may be shared by several tasks, we
    125   // need to increment the count with the workqueue lock held.
    126   workqueue->add_blocker(next_blocker);
    127 
    128   workqueue->queue(new Read_symbols(input_objects, symtab, layout, dirpath,
    129 				    dirindex, mapfile, input_argument,
    130 				    input_group, NULL, NULL, next_blocker));
    131 }
    132 
    133 // Return whether a Read_symbols task is runnable.  We can read an
    134 // ordinary input file immediately.  For an archive specified using
    135 // -l, we have to wait until the search path is complete.
    136 
    137 Task_token*
    138 Read_symbols::is_runnable()
    139 {
    140   if (this->input_argument_->is_file()
    141       && this->input_argument_->file().may_need_search()
    142       && this->dirpath_->token()->is_blocked())
    143     return this->dirpath_->token();
    144 
    145   return NULL;
    146 }
    147 
    148 // Return a Task_locker for a Read_symbols task.  We don't need any
    149 // locks here.
    150 
    151 void
    152 Read_symbols::locks(Task_locker* tl)
    153 {
    154   if (this->member_ != NULL)
    155     tl->add(this, this->next_blocker_);
    156 }
    157 
    158 // Run a Read_symbols task.
    159 
    160 void
    161 Read_symbols::run(Workqueue* workqueue)
    162 {
    163   // If we didn't queue a new task, then we need to explicitly unblock
    164   // the token. If the object is a member of a lib group, however,
    165   // the token was already added to the list of locks for the task,
    166   // and it will be unblocked automatically at the end of the task.
    167   if (!this->do_read_symbols(workqueue) && this->member_ == NULL)
    168     workqueue->queue_soon(new Unblock_token(this->this_blocker_,
    169 					    this->next_blocker_));
    170 }
    171 
    172 // Handle a whole lib group. Other than collecting statistics, this just
    173 // mimics what we do for regular object files in the command line.
    174 
    175 bool
    176 Read_symbols::do_whole_lib_group(Workqueue* workqueue)
    177 {
    178   const Input_file_lib* lib_group = this->input_argument_->lib();
    179 
    180   ++Lib_group::total_lib_groups;
    181 
    182   Task_token* this_blocker = this->this_blocker_;
    183   for (Input_file_lib::const_iterator i = lib_group->begin();
    184        i != lib_group->end();
    185        ++i)
    186     {
    187       ++Lib_group::total_members;
    188       ++Lib_group::total_members_loaded;
    189 
    190       const Input_argument* arg = &*i;
    191 
    192       Task_token* next_blocker;
    193       if (i != lib_group->end() - 1)
    194         {
    195           next_blocker = new Task_token(true);
    196           next_blocker->add_blocker();
    197         }
    198       else
    199         next_blocker = this->next_blocker_;
    200 
    201       workqueue->queue_soon(new Read_symbols(this->input_objects_,
    202 					     this->symtab_, this->layout_,
    203 					     this->dirpath_, this->dirindex_,
    204 					     this->mapfile_, arg, NULL,
    205 					     NULL, this_blocker, next_blocker));
    206       this_blocker = next_blocker;
    207     }
    208 
    209   return true;
    210 }
    211 
    212 // Handle a lib group. We set Read_symbols Tasks as usual, but have them
    213 // just record the symbol data instead of adding the objects.  We also start
    214 // a Add_lib_group_symbols Task which runs after we've read all the symbols.
    215 // In that task we process the members in a loop until we are done.
    216 
    217 bool
    218 Read_symbols::do_lib_group(Workqueue* workqueue)
    219 {
    220   const Input_file_lib* lib_group = this->input_argument_->lib();
    221 
    222   if (lib_group->options().whole_archive())
    223     return this->do_whole_lib_group(workqueue);
    224 
    225   Lib_group* lib = new Lib_group(lib_group, this);
    226 
    227   Add_lib_group_symbols* add_lib_group_symbols =
    228     new Add_lib_group_symbols(this->symtab_, this->layout_,
    229 			      this->input_objects_,
    230 			      lib, this->next_blocker_);
    231 
    232 
    233   Task_token* next_blocker = new Task_token(true);
    234   int j = 0;
    235   for (Input_file_lib::const_iterator i = lib_group->begin();
    236        i != lib_group->end();
    237        ++i, ++j)
    238     {
    239       const Input_argument* arg = &*i;
    240       Archive_member* m = lib->get_member(j);
    241 
    242       next_blocker->add_blocker();
    243 
    244       // Since this Read_symbols will not create an Add_symbols,
    245       // just pass NULL as this_blocker.
    246       workqueue->queue_soon(new Read_symbols(this->input_objects_,
    247 					     this->symtab_, this->layout_,
    248 					     this->dirpath_, this->dirindex_,
    249 					     this->mapfile_, arg, NULL,
    250 					     m, NULL, next_blocker));
    251     }
    252 
    253   add_lib_group_symbols->set_blocker(next_blocker, this->this_blocker_);
    254   workqueue->queue_soon(add_lib_group_symbols);
    255 
    256   return true;
    257 }
    258 
    259 // Open the file and read the symbols.  Return true if a new task was
    260 // queued, false if that could not happen due to some error.
    261 
    262 bool
    263 Read_symbols::do_read_symbols(Workqueue* workqueue)
    264 {
    265   if (this->input_argument_->is_group())
    266     {
    267       gold_assert(this->input_group_ == NULL);
    268       this->do_group(workqueue);
    269       return true;
    270     }
    271 
    272   if (this->input_argument_->is_lib())
    273     return this->do_lib_group(workqueue);
    274 
    275   Input_file* input_file = new Input_file(&this->input_argument_->file());
    276   if (!input_file->open(*this->dirpath_, this, &this->dirindex_))
    277     return false;
    278 
    279   // Read enough of the file to pick up the entire ELF header.
    280 
    281   off_t filesize = input_file->file().filesize();
    282 
    283   if (filesize == 0)
    284     {
    285       gold_error(_("%s: file is empty"),
    286 		 input_file->file().filename().c_str());
    287       return false;
    288     }
    289 
    290   const unsigned char* ehdr;
    291   int read_size;
    292   bool is_elf = is_elf_object(input_file, 0, &ehdr, &read_size);
    293 
    294   if (read_size >= Archive::sarmag)
    295     {
    296       bool is_thin_archive
    297           = memcmp(ehdr, Archive::armagt, Archive::sarmag) == 0;
    298       if (is_thin_archive
    299           || memcmp(ehdr, Archive::armag, Archive::sarmag) == 0)
    300 	{
    301 	  // This is an archive.
    302 	  Archive* arch = new Archive(this->input_argument_->file().name(),
    303 				      input_file, is_thin_archive,
    304 				      this->dirpath_, this);
    305 	  arch->setup();
    306 
    307 	  // Unlock the archive so it can be used in the next task.
    308 	  arch->unlock(this);
    309 
    310 	  workqueue->queue_next(new Add_archive_symbols(this->symtab_,
    311 							this->layout_,
    312 							this->input_objects_,
    313 							this->dirpath_,
    314 							this->dirindex_,
    315 							this->mapfile_,
    316 							this->input_argument_,
    317 							arch,
    318 							this->input_group_,
    319 							this->this_blocker_,
    320 							this->next_blocker_));
    321 	  return true;
    322 	}
    323     }
    324 
    325   Object* elf_obj = NULL;
    326   bool unconfigured;
    327   bool* punconfigured = NULL;
    328   if (is_elf)
    329     {
    330       // This is an ELF object.
    331 
    332       unconfigured = false;
    333       punconfigured = (input_file->will_search_for()
    334 		       ? &unconfigured
    335 		       : NULL);
    336       elf_obj = make_elf_object(input_file->filename(),
    337 				input_file, 0, ehdr, read_size,
    338 				punconfigured);
    339     }
    340 
    341   if (parameters->options().has_plugins())
    342     {
    343       Pluginobj* obj = parameters->options().plugins()->claim_file(input_file,
    344                                                                    0, filesize,
    345 								   elf_obj);
    346       if (obj != NULL)
    347         {
    348 	  // Delete the elf_obj, this file has been claimed.
    349 	  if (elf_obj != NULL)
    350 	    delete elf_obj;
    351 
    352           // The input file was claimed by a plugin, and its symbols
    353           // have been provided by the plugin.
    354 
    355           // We are done with the file at this point, so unlock it.
    356           obj->unlock(this);
    357 
    358           if (this->member_ != NULL)
    359 	    {
    360 	      this->member_->sd_ = NULL;
    361 	      this->member_->obj_ = obj;
    362 	      return true;
    363 	    }
    364 
    365           workqueue->queue_next(new Add_symbols(this->input_objects_,
    366                                                 this->symtab_,
    367                                                 this->layout_,
    368 						this->dirpath_,
    369 						this->dirindex_,
    370 						this->mapfile_,
    371 						this->input_argument_,
    372                                                 obj,
    373                                                 NULL,
    374 						NULL,
    375                                                 this->this_blocker_,
    376                                                 this->next_blocker_));
    377           return true;
    378         }
    379     }
    380 
    381   if (is_elf)
    382     {
    383       // This is an ELF object.
    384 
    385       if (elf_obj == NULL)
    386 	{
    387 	  if (unconfigured)
    388 	    {
    389 	      Read_symbols::incompatible_warning(this->input_argument_,
    390 						 input_file);
    391 	      input_file->file().release();
    392 	      input_file->file().unlock(this);
    393 	      delete input_file;
    394 	      ++this->dirindex_;
    395 	      return this->do_read_symbols(workqueue);
    396 	    }
    397 	  return false;
    398 	}
    399 
    400       Read_symbols_data* sd = new Read_symbols_data;
    401       elf_obj->read_symbols(sd);
    402 
    403       // Opening the file locked it, so now we need to unlock it.  We
    404       // need to unlock it before queuing the Add_symbols task,
    405       // because the workqueue doesn't know about our lock on the
    406       // file.  If we queue the Add_symbols task first, it will be
    407       // stuck on the end of the file lock, but since the workqueue
    408       // doesn't know about that lock, it will never release the
    409       // Add_symbols task.
    410 
    411       input_file->file().unlock(this);
    412 
    413       if (this->member_ != NULL)
    414         {
    415           this->member_->sd_ = sd;
    416           this->member_->obj_ = elf_obj;
    417           this->member_->arg_serial_ =
    418               this->input_argument_->file().arg_serial();
    419           return true;
    420         }
    421 
    422       // We use queue_next because everything is cached for this
    423       // task to run right away if possible.
    424 
    425       workqueue->queue_next(new Add_symbols(this->input_objects_,
    426 					    this->symtab_, this->layout_,
    427 					    this->dirpath_,
    428 					    this->dirindex_,
    429 					    this->mapfile_,
    430 					    this->input_argument_,
    431 					    elf_obj,
    432 					    NULL,
    433 					    sd,
    434 					    this->this_blocker_,
    435 					    this->next_blocker_));
    436 
    437       return true;
    438     }
    439 
    440   // Queue up a task to try to parse this file as a script.  We use a
    441   // separate task so that the script will be read in order with other
    442   // objects named on the command line.  Also so that we don't try to
    443   // read multiple scripts simultaneously, which could lead to
    444   // unpredictable changes to the General_options structure.
    445 
    446   workqueue->queue_soon(new Read_script(this->symtab_,
    447 					this->layout_,
    448 					this->dirpath_,
    449 					this->dirindex_,
    450 					this->input_objects_,
    451 					this->mapfile_,
    452 					this->input_group_,
    453 					this->input_argument_,
    454 					input_file,
    455 					this->this_blocker_,
    456 					this->next_blocker_));
    457   return true;
    458 }
    459 
    460 // Handle a group.  We need to walk through the arguments over and
    461 // over until we don't see any new undefined symbols.  We do this by
    462 // setting off Read_symbols Tasks as usual, but recording the archive
    463 // entries instead of deleting them.  We also start a Finish_group
    464 // Task which runs after we've read all the symbols.  In that task we
    465 // process the archives in a loop until we are done.
    466 
    467 void
    468 Read_symbols::do_group(Workqueue* workqueue)
    469 {
    470   Input_group* input_group = new Input_group();
    471 
    472   const Input_file_group* group = this->input_argument_->group();
    473   Task_token* this_blocker = this->this_blocker_;
    474 
    475   Finish_group* finish_group = new Finish_group(this->input_objects_,
    476 						this->symtab_,
    477 						this->layout_,
    478 						this->mapfile_,
    479 						input_group,
    480 						this->next_blocker_);
    481 
    482   Task_token* next_blocker = new Task_token(true);
    483   next_blocker->add_blocker();
    484   workqueue->queue_soon(new Start_group(this->symtab_, finish_group,
    485 					this_blocker, next_blocker));
    486   this_blocker = next_blocker;
    487 
    488   for (Input_file_group::const_iterator p = group->begin();
    489        p != group->end();
    490        ++p)
    491     {
    492       const Input_argument* arg = &*p;
    493       gold_assert(arg->is_file());
    494 
    495       next_blocker = new Task_token(true);
    496       next_blocker->add_blocker();
    497       workqueue->queue_soon(new Read_symbols(this->input_objects_,
    498 					     this->symtab_, this->layout_,
    499 					     this->dirpath_, this->dirindex_,
    500 					     this->mapfile_, arg, input_group,
    501 					     NULL, this_blocker, next_blocker));
    502       this_blocker = next_blocker;
    503     }
    504 
    505   finish_group->set_blocker(this_blocker);
    506 
    507   workqueue->queue_soon(finish_group);
    508 }
    509 
    510 // Return a debugging name for a Read_symbols task.
    511 
    512 std::string
    513 Read_symbols::get_name() const
    514 {
    515   if (this->input_argument_->is_group())
    516     {
    517       std::string ret("Read_symbols group (");
    518       bool add_space = false;
    519       const Input_file_group* group = this->input_argument_->group();
    520       for (Input_file_group::const_iterator p = group->begin();
    521            p != group->end();
    522            ++p)
    523       {
    524         if (add_space)
    525           ret += ' ';
    526         ret += p->file().name();
    527         add_space = true;
    528       }
    529       return ret + ')';
    530     }
    531   else if (this->input_argument_->is_lib())
    532     {
    533       std::string ret("Read_symbols lib (");
    534       bool add_space = false;
    535       const Input_file_lib* lib = this->input_argument_->lib();
    536       for (Input_file_lib::const_iterator p = lib->begin();
    537            p != lib->end();
    538            ++p)
    539       {
    540         if (add_space)
    541           ret += ' ';
    542         ret += p->file().name();
    543         add_space = true;
    544       }
    545       return ret + ')';
    546     }
    547   else
    548     {
    549       std::string ret("Read_symbols ");
    550       if (this->input_argument_->file().is_lib())
    551 	ret += "-l";
    552       else if (this->input_argument_->file().is_searched_file())
    553 	ret += "-l:";
    554       ret += this->input_argument_->file().name();
    555       return ret;
    556     }
    557 }
    558 
    559 // Class Add_symbols.
    560 
    561 Add_symbols::~Add_symbols()
    562 {
    563   if (this->this_blocker_ != NULL)
    564     delete this->this_blocker_;
    565   // next_blocker_ is deleted by the task associated with the next
    566   // input file.
    567 }
    568 
    569 // We are blocked by this_blocker_.  We block next_blocker_.  We also
    570 // lock the file.
    571 
    572 Task_token*
    573 Add_symbols::is_runnable()
    574 {
    575   if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
    576     return this->this_blocker_;
    577   if (this->object_->is_locked())
    578     return this->object_->token();
    579   return NULL;
    580 }
    581 
    582 void
    583 Add_symbols::locks(Task_locker* tl)
    584 {
    585   tl->add(this, this->next_blocker_);
    586   Task_token* token = this->object_->token();
    587   if (token != NULL)
    588     tl->add(this, token);
    589 }
    590 
    591 // Add the symbols in the object to the symbol table.
    592 
    593 void
    594 Add_symbols::run(Workqueue*)
    595 {
    596   Pluginobj* pluginobj = this->object_->pluginobj();
    597   if (pluginobj != NULL)
    598     {
    599       this->object_->add_symbols(this->symtab_, this->sd_, this->layout_);
    600       return;
    601     }
    602 
    603   if (!this->input_objects_->add_object(this->object_))
    604     {
    605       this->object_->discard_decompressed_sections();
    606       gold_assert(this->sd_ != NULL);
    607       delete this->sd_;
    608       this->sd_ = NULL;
    609       this->object_->release();
    610       delete this->object_;
    611     }
    612   else
    613     {
    614       Incremental_inputs* incremental_inputs =
    615           this->layout_->incremental_inputs();
    616       if (incremental_inputs != NULL)
    617 	{
    618           if (this->library_ != NULL && !this->library_->is_reported())
    619             {
    620               Incremental_binary* ibase = this->layout_->incremental_base();
    621               gold_assert(ibase != NULL);
    622               unsigned int lib_serial = this->library_->arg_serial();
    623               unsigned int lib_index = this->library_->input_file_index();
    624 	      Script_info* lib_script_info = ibase->get_script_info(lib_index);
    625 	      incremental_inputs->report_archive_begin(this->library_,
    626 						       lib_serial,
    627 						       lib_script_info);
    628 	    }
    629 	  unsigned int arg_serial = this->input_argument_->file().arg_serial();
    630 	  Script_info* script_info = this->input_argument_->script_info();
    631 	  incremental_inputs->report_object(this->object_, arg_serial,
    632 					    this->library_, script_info);
    633 	}
    634       this->object_->layout(this->symtab_, this->layout_, this->sd_);
    635       this->object_->add_symbols(this->symtab_, this->sd_, this->layout_);
    636       this->object_->discard_decompressed_sections();
    637       delete this->sd_;
    638       this->sd_ = NULL;
    639       this->object_->release();
    640     }
    641 }
    642 
    643 // Class Read_member.
    644 
    645 Read_member::~Read_member()
    646 {
    647   if (this->this_blocker_ != NULL)
    648     delete this->this_blocker_;
    649   // next_blocker_ is deleted by the task associated with the next
    650   // input file.
    651 }
    652 
    653 // Return whether a Read_member task is runnable.
    654 
    655 Task_token*
    656 Read_member::is_runnable()
    657 {
    658   if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
    659     return this->this_blocker_;
    660   return NULL;
    661 }
    662 
    663 void
    664 Read_member::locks(Task_locker* tl)
    665 {
    666   tl->add(this, this->next_blocker_);
    667 }
    668 
    669 // Run a Read_member task.
    670 
    671 void
    672 Read_member::run(Workqueue*)
    673 {
    674   // This task doesn't need to do anything for now.  The Read_symbols task
    675   // that is queued for the archive library will cause the archive to be
    676   // processed from scratch.
    677 }
    678 
    679 // Class Check_script.
    680 
    681 Check_script::~Check_script()
    682 {
    683   if (this->this_blocker_ != NULL)
    684     delete this->this_blocker_;
    685   // next_blocker_ is deleted by the task associated with the next
    686   // input file.
    687 }
    688 
    689 // Return whether a Check_script task is runnable.
    690 
    691 Task_token*
    692 Check_script::is_runnable()
    693 {
    694   if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
    695     return this->this_blocker_;
    696   return NULL;
    697 }
    698 
    699 void
    700 Check_script::locks(Task_locker* tl)
    701 {
    702   tl->add(this, this->next_blocker_);
    703 }
    704 
    705 // Run a Check_script task.
    706 
    707 void
    708 Check_script::run(Workqueue*)
    709 {
    710   Incremental_inputs* incremental_inputs = this->layout_->incremental_inputs();
    711   gold_assert(incremental_inputs != NULL);
    712   unsigned int arg_serial = this->input_reader_->arg_serial();
    713   Script_info* script_info =
    714       this->ibase_->get_script_info(this->input_file_index_);
    715   Timespec mtime = this->input_reader_->get_mtime();
    716   incremental_inputs->report_script(script_info, arg_serial, mtime);
    717 }
    718 
    719 // Class Check_library.
    720 
    721 Check_library::~Check_library()
    722 {
    723   if (this->this_blocker_ != NULL)
    724     delete this->this_blocker_;
    725   // next_blocker_ is deleted by the task associated with the next
    726   // input file.
    727 }
    728 
    729 // Return whether a Check_library task is runnable.
    730 
    731 Task_token*
    732 Check_library::is_runnable()
    733 {
    734   if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
    735     return this->this_blocker_;
    736   return NULL;
    737 }
    738 
    739 void
    740 Check_library::locks(Task_locker* tl)
    741 {
    742   tl->add(this, this->next_blocker_);
    743 }
    744 
    745 // Run a Check_library task.
    746 
    747 void
    748 Check_library::run(Workqueue*)
    749 {
    750   Incremental_inputs* incremental_inputs = this->layout_->incremental_inputs();
    751   gold_assert(incremental_inputs != NULL);
    752   Incremental_library* lib = this->ibase_->get_library(this->input_file_index_);
    753   gold_assert(lib != NULL);
    754   lib->copy_unused_symbols();
    755   // FIXME: Check that unused symbols remain unused.
    756   if (!lib->is_reported())
    757     {
    758       unsigned int lib_serial = lib->arg_serial();
    759       unsigned int lib_index = lib->input_file_index();
    760       Script_info* script_info = this->ibase_->get_script_info(lib_index);
    761       incremental_inputs->report_archive_begin(lib, lib_serial, script_info);
    762     }
    763   incremental_inputs->report_archive_end(lib);
    764 }
    765 
    766 // Class Input_group.
    767 
    768 // When we delete an Input_group we can delete the archive
    769 // information.
    770 
    771 Input_group::~Input_group()
    772 {
    773   for (Input_group::const_iterator p = this->begin();
    774        p != this->end();
    775        ++p)
    776     delete *p;
    777 }
    778 
    779 // Class Start_group.
    780 
    781 Start_group::~Start_group()
    782 {
    783   if (this->this_blocker_ != NULL)
    784     delete this->this_blocker_;
    785   // next_blocker_ is deleted by the task associated with the first
    786   // file in the group.
    787 }
    788 
    789 // We need to wait for THIS_BLOCKER_ and unblock NEXT_BLOCKER_.
    790 
    791 Task_token*
    792 Start_group::is_runnable()
    793 {
    794   if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
    795     return this->this_blocker_;
    796   return NULL;
    797 }
    798 
    799 void
    800 Start_group::locks(Task_locker* tl)
    801 {
    802   tl->add(this, this->next_blocker_);
    803 }
    804 
    805 // Store the number of undefined symbols we see now.
    806 
    807 void
    808 Start_group::run(Workqueue*)
    809 {
    810   this->finish_group_->set_saw_undefined(this->symtab_->saw_undefined());
    811 }
    812 
    813 // Class Finish_group.
    814 
    815 Finish_group::~Finish_group()
    816 {
    817   if (this->this_blocker_ != NULL)
    818     delete this->this_blocker_;
    819   // next_blocker_ is deleted by the task associated with the next
    820   // input file following the group.
    821 }
    822 
    823 // We need to wait for THIS_BLOCKER_ and unblock NEXT_BLOCKER_.
    824 
    825 Task_token*
    826 Finish_group::is_runnable()
    827 {
    828   if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
    829     return this->this_blocker_;
    830   return NULL;
    831 }
    832 
    833 void
    834 Finish_group::locks(Task_locker* tl)
    835 {
    836   tl->add(this, this->next_blocker_);
    837 }
    838 
    839 // Loop over the archives until there are no new undefined symbols.
    840 
    841 void
    842 Finish_group::run(Workqueue*)
    843 {
    844   size_t saw_undefined = this->saw_undefined_;
    845   while (saw_undefined != this->symtab_->saw_undefined())
    846     {
    847       saw_undefined = this->symtab_->saw_undefined();
    848 
    849       for (Input_group::const_iterator p = this->input_group_->begin();
    850 	   p != this->input_group_->end();
    851 	   ++p)
    852 	{
    853 	  Task_lock_obj<Archive> tl(this, *p);
    854 
    855 	  (*p)->add_symbols(this->symtab_, this->layout_,
    856 			    this->input_objects_, this->mapfile_);
    857 	}
    858     }
    859 
    860   // Now that we're done with the archives, record the incremental
    861   // layout information.
    862   for (Input_group::const_iterator p = this->input_group_->begin();
    863        p != this->input_group_->end();
    864        ++p)
    865     {
    866       // For an incremental link, finish recording the layout information.
    867       Incremental_inputs* incremental_inputs =
    868           this->layout_->incremental_inputs();
    869       if (incremental_inputs != NULL)
    870 	incremental_inputs->report_archive_end(*p);
    871     }
    872 
    873   if (parameters->options().has_plugins())
    874     parameters->options().plugins()->save_input_group(this->input_group_);
    875   else
    876     delete this->input_group_;
    877 }
    878 
    879 // Class Read_script
    880 
    881 Read_script::~Read_script()
    882 {
    883   if (this->this_blocker_ != NULL)
    884     delete this->this_blocker_;
    885   // next_blocker_ is deleted by the task associated with the next
    886   // input file.
    887 }
    888 
    889 // We are blocked by this_blocker_.
    890 
    891 Task_token*
    892 Read_script::is_runnable()
    893 {
    894   if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
    895     return this->this_blocker_;
    896   return NULL;
    897 }
    898 
    899 // We don't unlock next_blocker_ here.  If the script names any input
    900 // files, then the last file will be responsible for unlocking it.
    901 
    902 void
    903 Read_script::locks(Task_locker*)
    904 {
    905 }
    906 
    907 // Read the script, if it is a script.
    908 
    909 void
    910 Read_script::run(Workqueue* workqueue)
    911 {
    912   bool used_next_blocker;
    913   if (!read_input_script(workqueue, this->symtab_, this->layout_,
    914 			 this->dirpath_, this->dirindex_, this->input_objects_,
    915 			 this->mapfile_, this->input_group_,
    916 			 this->input_argument_, this->input_file_,
    917 			 this->next_blocker_, &used_next_blocker))
    918     {
    919       // Here we have to handle any other input file types we need.
    920       gold_error(_("%s: not an object or archive"),
    921 		 this->input_file_->file().filename().c_str());
    922     }
    923 
    924   if (!used_next_blocker)
    925     {
    926       // Queue up a task to unlock next_blocker.  We can't just unlock
    927       // it here, as we don't hold the workqueue lock.
    928       workqueue->queue_soon(new Unblock_token(NULL, this->next_blocker_));
    929     }
    930 }
    931 
    932 // Return a debugging name for a Read_script task.
    933 
    934 std::string
    935 Read_script::get_name() const
    936 {
    937   std::string ret("Read_script ");
    938   if (this->input_argument_->file().is_lib())
    939     ret += "-l";
    940   else if (this->input_argument_->file().is_searched_file())
    941     ret += "-l:";
    942   ret += this->input_argument_->file().name();
    943   return ret;
    944 }
    945 
    946 } // End namespace gold.
    947