(root)/
binutils-2.41/
gold/
readsyms.h
       1  // readsyms.h -- read input file symbols for gold   -*- C++ -*-
       2  
       3  // Copyright (C) 2006-2023 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)