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