1 // readsyms.h -- read input file symbols for gold   -*- C++ -*-
2 
3 // Copyright (C) 2006-2016 Free Software Foundation, Inc.
4 // Written by Ian Lance Taylor <iant@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 #ifndef GOLD_READSYMS_H
24 #define GOLD_READSYMS_H
25 
26 #include <vector>
27 
28 #include "workqueue.h"
29 #include "object.h"
30 #include "incremental.h"
31 
32 namespace gold
33 {
34 
35 class Input_objects;
36 class Symbol_table;
37 class Input_group;
38 class Archive;
39 class Finish_group;
40 
41 // This Task is responsible for reading the symbols from an input
42 // file.  This also includes reading the relocations so that we can
43 // check for any that require a PLT and/or a GOT.  After the data has
44 // been read, this queues up another task to actually add the symbols
45 // to the symbol table.  The tasks are separated because the file
46 // reading can occur in parallel but adding the symbols must be done
47 // in the order of the input files.
48 
49 class Read_symbols : public Task
50 {
51  public:
52   // DIRPATH is the list of directories to search for libraries.
53   // INPUT is the file to read.  INPUT_GROUP is not NULL if we are in
54   // the middle of an input group.  THIS_BLOCKER is used to prevent
55   // the associated Add_symbols task from running before the previous
56   // one has completed; it will be NULL for the first task.
57   // NEXT_BLOCKER is used to block the next input file from adding
58   // symbols.
Read_symbols(Input_objects * input_objects,Symbol_table * symtab,Layout * layout,Dirsearch * dirpath,int dirindex,Mapfile * mapfile,const Input_argument * input_argument,Input_group * input_group,Archive_member * member,Task_token * this_blocker,Task_token * next_blocker)59   Read_symbols(Input_objects* input_objects, Symbol_table* symtab,
60 	       Layout* layout, Dirsearch* dirpath, int dirindex,
61 	       Mapfile* mapfile, const Input_argument* input_argument,
62 	       Input_group* input_group, Archive_member* member,
63                Task_token* this_blocker, Task_token* next_blocker)
64     : input_objects_(input_objects), symtab_(symtab), layout_(layout),
65       dirpath_(dirpath), dirindex_(dirindex), mapfile_(mapfile),
66       input_argument_(input_argument), input_group_(input_group),
67       member_(member), this_blocker_(this_blocker),
68       next_blocker_(next_blocker)
69   { }
70 
71   ~Read_symbols();
72 
73   // If appropriate, issue a warning about skipping an incompatible
74   // object.
75   static void
76   incompatible_warning(const Input_argument*, const Input_file*);
77 
78   // Requeue a Read_symbols task to search for the next object with
79   // the same name.
80   static void
81   requeue(Workqueue*, Input_objects*, Symbol_table*, Layout*, Dirsearch*,
82 	  int dirindex, Mapfile*, const Input_argument*, Input_group*,
83 	  Task_token* next_blocker);
84 
85   // The standard Task methods.
86 
87   Task_token*
88   is_runnable();
89 
90   void
91   locks(Task_locker*);
92 
93   void
94   run(Workqueue*);
95 
96   std::string
97   get_name() const;
98 
99  private:
100   // Handle an archive group.
101   void
102   do_group(Workqueue*);
103 
104   // Handle --start-lib ... --end-lib
105   bool
106   do_lib_group(Workqueue*);
107 
108   // Handle --whole-archive --start-lib ... --end-lib --no-whole-archive
109   bool
110   do_whole_lib_group(Workqueue*);
111 
112   // Open and identify the file.
113   bool
114   do_read_symbols(Workqueue*);
115 
116   Input_objects* input_objects_;
117   Symbol_table* symtab_;
118   Layout* layout_;
119   Dirsearch* dirpath_;
120   int dirindex_;
121   Mapfile* mapfile_;
122   const Input_argument* input_argument_;
123   Input_group* input_group_;
124   Archive_member* member_;
125   Task_token* this_blocker_;
126   Task_token* next_blocker_;
127 };
128 
129 // This Task handles adding the symbols to the symbol table.  These
130 // tasks must be run in the same order as the arguments appear on the
131 // command line.
132 
133 class Add_symbols : public Task
134 {
135  public:
136   // THIS_BLOCKER is used to prevent this task from running before the
137   // one for the previous input file.  NEXT_BLOCKER is used to prevent
138   // the next task from running.
Add_symbols(Input_objects * input_objects,Symbol_table * symtab,Layout * layout,Dirsearch *,int,Mapfile *,const Input_argument * input_argument,Object * object,Incremental_library * library,Read_symbols_data * sd,Task_token * this_blocker,Task_token * next_blocker)139   Add_symbols(Input_objects* input_objects, Symbol_table* symtab,
140 	      Layout* layout, Dirsearch* /*dirpath*/, int /*dirindex*/,
141 	      Mapfile* /*mapfile*/, const Input_argument* input_argument,
142 	      Object* object, Incremental_library* library,
143 	      Read_symbols_data* sd, Task_token* this_blocker,
144 	      Task_token* next_blocker)
145     : input_objects_(input_objects), symtab_(symtab), layout_(layout),
146       input_argument_(input_argument), object_(object), library_(library),
147       sd_(sd), this_blocker_(this_blocker), next_blocker_(next_blocker)
148   { }
149 
150   ~Add_symbols();
151 
152   // The standard Task methods.
153 
154   Task_token*
155   is_runnable();
156 
157   void
158   locks(Task_locker*);
159 
160   void
161   run(Workqueue*);
162 
163   std::string
get_name()164   get_name() const
165   { return "Add_symbols " + this->object_->name(); }
166 
167 private:
168   Input_objects* input_objects_;
169   Symbol_table* symtab_;
170   Layout* layout_;
171   const Input_argument* input_argument_;
172   Object* object_;
173   Incremental_library* library_;
174   Read_symbols_data* sd_;
175   Task_token* this_blocker_;
176   Task_token* next_blocker_;
177 };
178 
179 // This Task is responsible for reading the symbols from an archive
180 // member that has changed since the last incremental link.
181 
182 class Read_member : public Task
183 {
184  public:
185   // INPUT is the file to read.  INPUT_GROUP is not NULL if we are in
186   // the middle of an input group.  THIS_BLOCKER is used to prevent
187   // the associated Add_symbols task from running before the previous
188   // one has completed; it will be NULL for the first task.
189   // NEXT_BLOCKER is used to block the next input file from adding
190   // symbols.
Read_member(Input_objects *,Symbol_table *,Layout *,Mapfile *,const Incremental_binary::Input_reader * input_reader,Task_token * this_blocker,Task_token * next_blocker)191   Read_member(Input_objects* /*input_objects*/, Symbol_table* /*symtab*/,
192 	      Layout* /*layout*/, Mapfile* /*mapfile*/,
193 	      const Incremental_binary::Input_reader* input_reader,
194               Task_token* this_blocker, Task_token* next_blocker)
195     : input_reader_(input_reader),
196       this_blocker_(this_blocker), next_blocker_(next_blocker)
197   { }
198 
199   ~Read_member();
200 
201   // The standard Task methods.
202 
203   Task_token*
204   is_runnable();
205 
206   void
207   locks(Task_locker*);
208 
209   void
210   run(Workqueue*);
211 
212   std::string
get_name()213   get_name() const
214   {
215     return (std::string("Read_member ") + this->input_reader_->filename());
216   }
217 
218  private:
219   const Incremental_binary::Input_reader* input_reader_;
220   Task_token* this_blocker_;
221   Task_token* next_blocker_;
222 };
223 
224 // This Task is responsible for processing an input script file that has
225 // not changed since the last incremental link.
226 
227 class Check_script : public Task
228 {
229  public:
Check_script(Layout * layout,Incremental_binary * ibase,unsigned int input_file_index,const Incremental_binary::Input_reader * input_reader,Task_token * this_blocker,Task_token * next_blocker)230   Check_script(Layout* layout, Incremental_binary* ibase,
231 	       unsigned int input_file_index,
232 	       const Incremental_binary::Input_reader* input_reader,
233 	       Task_token* this_blocker, Task_token* next_blocker)
234     : layout_(layout), ibase_(ibase), input_file_index_(input_file_index),
235       input_reader_(input_reader), this_blocker_(this_blocker),
236       next_blocker_(next_blocker)
237   {
238     this->filename_ = std::string(this->input_reader_->filename());
239   }
240 
241   ~Check_script();
242 
243   // The standard Task methods.
244 
245   Task_token*
246   is_runnable();
247 
248   void
249   locks(Task_locker*);
250 
251   void
252   run(Workqueue*);
253 
254   std::string
get_name()255   get_name() const
256   {
257     return (std::string("Check_script ") + this->input_reader_->filename());
258   }
259 
260  private:
261   std::string filename_;
262   Layout* layout_;
263   Incremental_binary* ibase_;
264   unsigned int input_file_index_;
265   const Incremental_binary::Input_reader* input_reader_;
266   Task_token* this_blocker_;
267   Task_token* next_blocker_;
268 };
269 
270 // This Task is responsible for processing an archive library that has
271 // not changed since the last incremental link.
272 
273 class Check_library : public Task
274 {
275  public:
Check_library(Symbol_table *,Layout * layout,Incremental_binary * ibase,unsigned int input_file_index,const Incremental_binary::Input_reader * input_reader,Task_token * this_blocker,Task_token * next_blocker)276   Check_library(Symbol_table* /*symtab*/, Layout* layout,
277 		Incremental_binary* ibase,
278 		unsigned int input_file_index,
279 		const Incremental_binary::Input_reader* input_reader,
280 		Task_token* this_blocker, Task_token* next_blocker)
281     : layout_(layout), ibase_(ibase),
282       input_file_index_(input_file_index), input_reader_(input_reader),
283       this_blocker_(this_blocker), next_blocker_(next_blocker)
284   { }
285 
286   ~Check_library();
287 
288   // The standard Task methods.
289 
290   Task_token*
291   is_runnable();
292 
293   void
294   locks(Task_locker*);
295 
296   void
297   run(Workqueue*);
298 
299   std::string
get_name()300   get_name() const
301   {
302     return (std::string("Check_library ") + this->input_reader_->filename());
303   }
304 
305  private:
306   Layout* layout_;
307   Incremental_binary* ibase_;
308   unsigned int input_file_index_;
309   const Incremental_binary::Input_reader* input_reader_;
310   Task_token* this_blocker_;
311   Task_token* next_blocker_;
312 };
313 
314 // This class is used to track the archives in a group.
315 
316 class Input_group
317 {
318  public:
319   typedef std::vector<Archive*> Archives;
320   typedef Archives::const_iterator const_iterator;
321 
Input_group()322   Input_group()
323     : archives_()
324   { }
325 
326   ~Input_group();
327 
328   // Add an archive to the group.
329   void
add_archive(Archive * arch)330   add_archive(Archive* arch)
331   { this->archives_.push_back(arch); }
332 
333   // Loop over the archives in the group.
334 
335   const_iterator
begin()336   begin() const
337   { return this->archives_.begin(); }
338 
339   const_iterator
end()340   end() const
341   { return this->archives_.end(); }
342 
343  private:
344   Archives archives_;
345 };
346 
347 // This class starts the handling of a group.  It exists only to pick
348 // up the number of undefined symbols at that point, so that we only
349 // run back through the group if we saw a new undefined symbol.
350 
351 class Start_group : public Task
352 {
353  public:
Start_group(Symbol_table * symtab,Finish_group * finish_group,Task_token * this_blocker,Task_token * next_blocker)354   Start_group(Symbol_table* symtab, Finish_group* finish_group,
355 	      Task_token* this_blocker, Task_token* next_blocker)
356     : symtab_(symtab), finish_group_(finish_group),
357       this_blocker_(this_blocker), next_blocker_(next_blocker)
358   { }
359 
360   ~Start_group();
361 
362   // The standard Task methods.
363 
364   Task_token*
365   is_runnable();
366 
367   void
368   locks(Task_locker*);
369 
370   void
371   run(Workqueue*);
372 
373   std::string
get_name()374   get_name() const
375   { return "Start_group"; }
376 
377  private:
378   Symbol_table* symtab_;
379   Finish_group* finish_group_;
380   Task_token* this_blocker_;
381   Task_token* next_blocker_;
382 };
383 
384 // This class is used to finish up handling a group.  It is just a
385 // closure.
386 
387 class Finish_group : public Task
388 {
389  public:
Finish_group(Input_objects * input_objects,Symbol_table * symtab,Layout * layout,Mapfile * mapfile,Input_group * input_group,Task_token * next_blocker)390   Finish_group(Input_objects* input_objects, Symbol_table* symtab,
391 	       Layout* layout, Mapfile* mapfile, Input_group* input_group,
392 	       Task_token* next_blocker)
393     : input_objects_(input_objects), symtab_(symtab),
394       layout_(layout), mapfile_(mapfile), input_group_(input_group),
395       saw_undefined_(0), this_blocker_(NULL), next_blocker_(next_blocker)
396   { }
397 
398   ~Finish_group();
399 
400   // Set the number of undefined symbols when we start processing the
401   // group.  This is called by the Start_group task.
402   void
set_saw_undefined(size_t saw_undefined)403   set_saw_undefined(size_t saw_undefined)
404   { this->saw_undefined_ = saw_undefined; }
405 
406   // Set the blocker to use for this task.
407   void
set_blocker(Task_token * this_blocker)408   set_blocker(Task_token* this_blocker)
409   {
410     gold_assert(this->this_blocker_ == NULL);
411     this->this_blocker_ = this_blocker;
412   }
413 
414   // The standard Task methods.
415 
416   Task_token*
417   is_runnable();
418 
419   void
420   locks(Task_locker*);
421 
422   void
423   run(Workqueue*);
424 
425   std::string
get_name()426   get_name() const
427   { return "Finish_group"; }
428 
429  private:
430   Input_objects* input_objects_;
431   Symbol_table* symtab_;
432   Layout* layout_;
433   Mapfile* mapfile_;
434   Input_group* input_group_;
435   size_t saw_undefined_;
436   Task_token* this_blocker_;
437   Task_token* next_blocker_;
438 };
439 
440 // This class is used to read a file which was not recognized as an
441 // object or archive.  It tries to read it as a linker script, using
442 // the tokens to serialize with the calls to Add_symbols.
443 
444 class Read_script : public Task
445 {
446  public:
Read_script(Symbol_table * symtab,Layout * layout,Dirsearch * dirpath,int dirindex,Input_objects * input_objects,Mapfile * mapfile,Input_group * input_group,const Input_argument * input_argument,Input_file * input_file,Task_token * this_blocker,Task_token * next_blocker)447   Read_script(Symbol_table* symtab, Layout* layout, Dirsearch* dirpath,
448 	      int dirindex, Input_objects* input_objects, Mapfile* mapfile,
449 	      Input_group* input_group, const Input_argument* input_argument,
450 	      Input_file* input_file, Task_token* this_blocker,
451 	      Task_token* next_blocker)
452     : symtab_(symtab), layout_(layout), dirpath_(dirpath), dirindex_(dirindex),
453       input_objects_(input_objects), mapfile_(mapfile),
454       input_group_(input_group), input_argument_(input_argument),
455       input_file_(input_file), this_blocker_(this_blocker),
456       next_blocker_(next_blocker)
457   { }
458 
459   ~Read_script();
460 
461   // The standard Task methods.
462 
463   Task_token*
464   is_runnable();
465 
466   void
467   locks(Task_locker*);
468 
469   void
470   run(Workqueue*);
471 
472   std::string
473   get_name() const;
474 
475  private:
476   Symbol_table* symtab_;
477   Layout* layout_;
478   Dirsearch* dirpath_;
479   int dirindex_;
480   Input_objects* input_objects_;
481   Mapfile* mapfile_;
482   Input_group* input_group_;
483   const Input_argument* input_argument_;
484   Input_file* input_file_;
485   Task_token* this_blocker_;
486   Task_token* next_blocker_;
487 };
488 
489 } // end namespace gold
490 
491 #endif // !defined(GOLD_READSYMS_H)
492