Home | History | Annotate | Download | only in gold
      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 (at) 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)
    492