2013-04-29 Alexander Ivchenko <alexander.ivchenko@intel.com>
[external/binutils.git] / gold / readsyms.h
1 // readsyms.h -- read input file symbols for gold   -*- C++ -*-
2
3 // Copyright 2006, 2007, 2008, 2009, 2010, 2011 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.
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.
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       dirpath_(dirpath), dirindex_(dirindex), mapfile_(mapfile),
147       input_argument_(input_argument), object_(object), library_(library),
148       sd_(sd), this_blocker_(this_blocker), next_blocker_(next_blocker)
149   { }
150
151   ~Add_symbols();
152
153   // The standard Task methods.
154
155   Task_token*
156   is_runnable();
157
158   void
159   locks(Task_locker*);
160
161   void
162   run(Workqueue*);
163
164   std::string
165   get_name() const
166   { return "Add_symbols " + this->object_->name(); }
167
168 private:
169   Input_objects* input_objects_;
170   Symbol_table* symtab_;
171   Layout* layout_;
172   Dirsearch* dirpath_;
173   int dirindex_;
174   Mapfile* mapfile_;
175   const Input_argument* input_argument_;
176   Object* object_;
177   Incremental_library* library_;
178   Read_symbols_data* sd_;
179   Task_token* this_blocker_;
180   Task_token* next_blocker_;
181 };
182
183 // This Task is responsible for reading the symbols from an archive
184 // member that has changed since the last incremental link.
185
186 class Read_member : public Task
187 {
188  public:
189   // INPUT is the file to read.  INPUT_GROUP is not NULL if we are in
190   // the middle of an input group.  THIS_BLOCKER is used to prevent
191   // the associated Add_symbols task from running before the previous
192   // one has completed; it will be NULL for the first task.
193   // NEXT_BLOCKER is used to block the next input file from adding
194   // symbols.
195   Read_member(Input_objects* input_objects, Symbol_table* symtab,
196               Layout* layout, Mapfile* mapfile,
197               const Incremental_binary::Input_reader* input_reader,
198               Task_token* this_blocker, Task_token* next_blocker)
199     : input_objects_(input_objects), symtab_(symtab), layout_(layout),
200       mapfile_(mapfile), input_reader_(input_reader),
201       this_blocker_(this_blocker), next_blocker_(next_blocker)
202   { }
203
204   ~Read_member();
205
206   // The standard Task methods.
207
208   Task_token*
209   is_runnable();
210
211   void
212   locks(Task_locker*);
213
214   void
215   run(Workqueue*);
216
217   std::string
218   get_name() const
219   {
220     return (std::string("Read_member ") + this->input_reader_->filename());
221   }
222
223  private:
224   Input_objects* input_objects_;
225   Symbol_table* symtab_;
226   Layout* layout_;
227   Mapfile* mapfile_;
228   const Incremental_binary::Input_reader* input_reader_;
229   Task_token* this_blocker_;
230   Task_token* next_blocker_;
231 };
232
233 // This Task is responsible for processing an input script file that has
234 // not changed since the last incremental link.
235
236 class Check_script : public Task
237 {
238  public:
239   Check_script(Layout* layout, Incremental_binary* ibase,
240                unsigned int input_file_index,
241                const Incremental_binary::Input_reader* input_reader,
242                Task_token* this_blocker, Task_token* next_blocker)
243     : layout_(layout), ibase_(ibase), input_file_index_(input_file_index),
244       input_reader_(input_reader), this_blocker_(this_blocker),
245       next_blocker_(next_blocker)
246   {
247     this->filename_ = std::string(this->input_reader_->filename());
248   }
249
250   ~Check_script();
251
252   // The standard Task methods.
253
254   Task_token*
255   is_runnable();
256
257   void
258   locks(Task_locker*);
259
260   void
261   run(Workqueue*);
262
263   std::string
264   get_name() const
265   {
266     return (std::string("Check_script ") + this->input_reader_->filename());
267   }
268
269  private:
270   std::string filename_;
271   Layout* layout_;
272   Incremental_binary* ibase_;
273   unsigned int input_file_index_;
274   const Incremental_binary::Input_reader* input_reader_;
275   Task_token* this_blocker_;
276   Task_token* next_blocker_;
277 };
278
279 // This Task is responsible for processing an archive library that has
280 // not changed since the last incremental link.
281
282 class Check_library : public Task
283 {
284  public:
285   Check_library(Symbol_table* symtab, Layout* layout,
286                 Incremental_binary* ibase,
287                 unsigned int input_file_index,
288                 const Incremental_binary::Input_reader* input_reader,
289                 Task_token* this_blocker, Task_token* next_blocker)
290     : layout_(layout), symtab_(symtab), ibase_(ibase),
291       input_file_index_(input_file_index), input_reader_(input_reader),
292       this_blocker_(this_blocker), next_blocker_(next_blocker)
293   { }
294
295   ~Check_library();
296
297   // The standard Task methods.
298
299   Task_token*
300   is_runnable();
301
302   void
303   locks(Task_locker*);
304
305   void
306   run(Workqueue*);
307
308   std::string
309   get_name() const
310   {
311     return (std::string("Check_library ") + this->input_reader_->filename());
312   }
313
314  private:
315   Layout* layout_;
316   Symbol_table* symtab_;
317   Incremental_binary* ibase_;
318   unsigned int input_file_index_;
319   const Incremental_binary::Input_reader* input_reader_;
320   Task_token* this_blocker_;
321   Task_token* next_blocker_;
322 };
323
324 // This class is used to track the archives in a group.
325
326 class Input_group
327 {
328  public:
329   typedef std::vector<Archive*> Archives;
330   typedef Archives::const_iterator const_iterator;
331
332   Input_group()
333     : archives_()
334   { }
335
336   ~Input_group();
337
338   // Add an archive to the group.
339   void
340   add_archive(Archive* arch)
341   { this->archives_.push_back(arch); }
342
343   // Loop over the archives in the group.
344
345   const_iterator
346   begin() const
347   { return this->archives_.begin(); }
348
349   const_iterator
350   end() const
351   { return this->archives_.end(); }
352
353  private:
354   Archives archives_;
355 };
356
357 // This class starts the handling of a group.  It exists only to pick
358 // up the number of undefined symbols at that point, so that we only
359 // run back through the group if we saw a new undefined symbol.
360
361 class Start_group : public Task
362 {
363  public:
364   Start_group(Symbol_table* symtab, Finish_group* finish_group,
365               Task_token* this_blocker, Task_token* next_blocker)
366     : symtab_(symtab), finish_group_(finish_group),
367       this_blocker_(this_blocker), next_blocker_(next_blocker)
368   { }
369
370   ~Start_group();
371
372   // The standard Task methods.
373
374   Task_token*
375   is_runnable();
376
377   void
378   locks(Task_locker*);
379
380   void
381   run(Workqueue*);
382
383   std::string
384   get_name() const
385   { return "Start_group"; }
386
387  private:
388   Symbol_table* symtab_;
389   Finish_group* finish_group_;
390   Task_token* this_blocker_;
391   Task_token* next_blocker_;
392 };
393
394 // This class is used to finish up handling a group.  It is just a
395 // closure.
396
397 class Finish_group : public Task
398 {
399  public:
400   Finish_group(Input_objects* input_objects, Symbol_table* symtab,
401                Layout* layout, Mapfile* mapfile, Input_group* input_group,
402                Task_token* next_blocker)
403     : input_objects_(input_objects), symtab_(symtab),
404       layout_(layout), mapfile_(mapfile), input_group_(input_group),
405       saw_undefined_(0), this_blocker_(NULL), next_blocker_(next_blocker)
406   { }
407
408   ~Finish_group();
409
410   // Set the number of undefined symbols when we start processing the
411   // group.  This is called by the Start_group task.
412   void
413   set_saw_undefined(size_t saw_undefined)
414   { this->saw_undefined_ = saw_undefined; }
415
416   // Set the blocker to use for this task.
417   void
418   set_blocker(Task_token* this_blocker)
419   {
420     gold_assert(this->this_blocker_ == NULL);
421     this->this_blocker_ = this_blocker;
422   }
423
424   // The standard Task methods.
425
426   Task_token*
427   is_runnable();
428
429   void
430   locks(Task_locker*);
431
432   void
433   run(Workqueue*);
434
435   std::string
436   get_name() const
437   { return "Finish_group"; }
438
439  private:
440   Input_objects* input_objects_;
441   Symbol_table* symtab_;
442   Layout* layout_;
443   Mapfile* mapfile_;
444   Input_group* input_group_;
445   size_t saw_undefined_;
446   Task_token* this_blocker_;
447   Task_token* next_blocker_;
448 };
449
450 // This class is used to read a file which was not recognized as an
451 // object or archive.  It tries to read it as a linker script, using
452 // the tokens to serialize with the calls to Add_symbols.
453
454 class Read_script : public Task
455 {
456  public:
457   Read_script(Symbol_table* symtab, Layout* layout, Dirsearch* dirpath,
458               int dirindex, Input_objects* input_objects, Mapfile* mapfile,
459               Input_group* input_group, const Input_argument* input_argument,
460               Input_file* input_file, Task_token* this_blocker,
461               Task_token* next_blocker)
462     : symtab_(symtab), layout_(layout), dirpath_(dirpath), dirindex_(dirindex),
463       input_objects_(input_objects), mapfile_(mapfile),
464       input_group_(input_group), input_argument_(input_argument),
465       input_file_(input_file), this_blocker_(this_blocker),
466       next_blocker_(next_blocker)
467   { }
468
469   ~Read_script();
470
471   // The standard Task methods.
472
473   Task_token*
474   is_runnable();
475
476   void
477   locks(Task_locker*);
478
479   void
480   run(Workqueue*);
481
482   std::string
483   get_name() const;
484
485  private:
486   Symbol_table* symtab_;
487   Layout* layout_;
488   Dirsearch* dirpath_;
489   int dirindex_;
490   Input_objects* input_objects_;
491   Mapfile* mapfile_;
492   Input_group* input_group_;
493   const Input_argument* input_argument_;
494   Input_file* input_file_;
495   Task_token* this_blocker_;
496   Task_token* next_blocker_;
497 };
498
499 } // end namespace gold
500
501 #endif // !defined(GOLD_READSYMS_H)