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