Merge remote-tracking branch 'origin/vendor/LDNS'
[dragonfly.git] / contrib / binutils-2.25 / gold / readsyms.h
1 // readsyms.h -- read input file symbols for gold   -*- C++ -*-
2
3 // Copyright (C) 2006-2014 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       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
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.
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
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:
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
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:
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
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
322   Input_group()
323     : archives_()
324   { }
325
326   ~Input_group();
327
328   // Add an archive to the group.
329   void
330   add_archive(Archive* arch)
331   { this->archives_.push_back(arch); }
332
333   // Loop over the archives in the group.
334
335   const_iterator
336   begin() const
337   { return this->archives_.begin(); }
338
339   const_iterator
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:
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
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:
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
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
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
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:
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)