(root)/
binutils-2.41/
gold/
target-select.h
       1  // target-select.h -- select a target for an object file  -*- 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_TARGET_SELECT_H
      24  #define GOLD_TARGET_SELECT_H
      25  
      26  #include <vector>
      27  
      28  #include "gold-threads.h"
      29  
      30  namespace gold
      31  {
      32  
      33  class Input_file;
      34  class Target;
      35  class Target_selector;
      36  
      37  // Used to set the target only once.
      38  
      39  class Set_target_once : public Once
      40  {
      41   public:
      42    Set_target_once(Target_selector* target_selector)
      43      : target_selector_(target_selector)
      44    { }
      45  
      46   protected:
      47    void
      48    do_run_once(void*);
      49  
      50   private:
      51    Target_selector* target_selector_;
      52  };
      53  
      54  // We want to avoid a master list of targets, which implies using a
      55  // global constructor.  And we also want the program to start up as
      56  // quickly as possible, which implies avoiding global constructors.
      57  // We compromise on a very simple global constructor.  We use a target
      58  // selector, which specifies an ELF machine number and a recognition
      59  // function.  We use global constructors to build a linked list of
      60  // target selectors--a simple pointer list, not a std::list.
      61  
      62  class Target_selector
      63  {
      64   public:
      65    // Create a target selector for a specific machine number, size (32
      66    // or 64), and endianness.  The machine number can be EM_NONE to
      67    // test for any machine number.  BFD_NAME is the name of the target
      68    // used by the GNU linker, for backward compatibility; it may be
      69    // NULL.  EMULATION is the name of the emulation used by the GNU
      70    // linker; it is similar to BFD_NAME.
      71    Target_selector(int machine, int size, bool is_big_endian,
      72  		  const char* bfd_name, const char* emulation);
      73  
      74    virtual ~Target_selector()
      75    { }
      76  
      77    // If we can handle this target, return a pointer to a target
      78    // structure.  The size and endianness are known.
      79    Target*
      80    recognize(Input_file* input_file, off_t offset,
      81  	    int machine, int osabi, int abiversion)
      82    { return this->do_recognize(input_file, offset, machine, osabi, abiversion); }
      83  
      84    // If NAME matches the target, return a pointer to a target
      85    // structure.
      86    Target*
      87    recognize_by_bfd_name(const char* name)
      88    { return this->do_recognize_by_bfd_name(name); }
      89  
      90    // Push all supported BFD names onto the vector.  This is only used
      91    // for help output.
      92    void
      93    supported_bfd_names(std::vector<const char*>* names)
      94    { this->do_supported_bfd_names(names); }
      95  
      96    // If NAME matches the target emulation, return a pointer to a
      97    // target structure.
      98    Target*
      99    recognize_by_emulation(const char* name)
     100    { return this->do_recognize_by_emulation(name); }
     101  
     102    // Push all supported emulations onto the vector.  This is only used
     103    // for help output.
     104    void
     105    supported_emulations(std::vector<const char*>* names)
     106    { this->do_supported_emulations(names); }
     107  
     108    // Return the next Target_selector in the linked list.
     109    Target_selector*
     110    next() const
     111    { return this->next_; }
     112  
     113    // Return the machine number this selector is looking for.  This can
     114    // be EM_NONE to match any machine number, in which case the
     115    // do_recognize hook will be responsible for matching the machine
     116    // number.
     117    int
     118    machine() const
     119    { return this->machine_; }
     120  
     121    // Return the size this is looking for (32 or 64).
     122    int
     123    get_size() const
     124    { return this->size_; }
     125  
     126    // Return the endianness this is looking for.
     127    bool
     128    is_big_endian() const
     129    { return this->is_big_endian_; }
     130  
     131    // Return the BFD name.  This may return NULL, in which case the
     132    // do_recognize_by_bfd_name hook will be responsible for matching
     133    // the BFD name.
     134    const char*
     135    bfd_name() const
     136    { return this->bfd_name_; }
     137  
     138    // Return the emulation.  This may return NULL, in which case the
     139    // do_recognize_by_emulation hook will be responsible for matching
     140    // the emulation.
     141    const char*
     142    emulation() const
     143    { return this->emulation_; }
     144  
     145    // The reverse mapping, for --print-output-format: if we
     146    // instantiated TARGET, return our BFD_NAME.  If we did not
     147    // instantiate it, return NULL.
     148    const char*
     149    target_bfd_name(const Target* target)
     150    { return this->do_target_bfd_name(target); }
     151  
     152   protected:
     153    // Return an instance of the real target.  This must be implemented
     154    // by the child class.
     155    virtual Target*
     156    do_instantiate_target() = 0;
     157  
     158    // Recognize an object file given a machine code, OSABI code, and
     159    // ELF version value.  When this is called we already know that they
     160    // match the machine_, size_, and is_big_endian_ fields.  The child
     161    // class may implement a different version of this to do additional
     162    // checks, or to check for multiple machine codes if the machine_
     163    // field is EM_NONE.
     164    virtual Target*
     165    do_recognize(Input_file*, off_t, int, int, int)
     166    { return this->instantiate_target(); }
     167  
     168    // Recognize a target by name.  When this is called we already know
     169    // that the name matches (or that the bfd_name_ field is NULL).  The
     170    // child class may implement a different version of this to
     171    // recognize more than one name.
     172    virtual Target*
     173    do_recognize_by_bfd_name(const char*)
     174    { return this->instantiate_target(); }
     175  
     176    // Return a list of supported BFD names.  The child class may
     177    // implement a different version of this to handle more than one
     178    // name.
     179    virtual void
     180    do_supported_bfd_names(std::vector<const char*>* names)
     181    {
     182      gold_assert(this->bfd_name_ != NULL);
     183      names->push_back(this->bfd_name_);
     184    }
     185  
     186    // Recognize a target by emulation.  When this is called we already
     187    // know that the name matches (or that the emulation_ field is
     188    // NULL).  The child class may implement a different version of this
     189    // to recognize more than one emulation.
     190    virtual Target*
     191    do_recognize_by_emulation(const char*)
     192    { return this->instantiate_target(); }
     193  
     194    // Return a list of supported emulations.  The child class may
     195    // implement a different version of this to handle more than one
     196    // emulation.
     197    virtual void
     198    do_supported_emulations(std::vector<const char*>* emulations)
     199    {
     200      gold_assert(this->emulation_ != NULL);
     201      emulations->push_back(this->emulation_);
     202    }
     203  
     204    // Map from target to BFD name.
     205    virtual const char*
     206    do_target_bfd_name(const Target*);
     207  
     208    // Instantiate the target and return it.
     209    Target*
     210    instantiate_target();
     211  
     212    // Return whether TARGET is the target we instantiated.
     213    bool
     214    is_our_target(const Target* target)
     215    { return target == this->instantiated_target_; }
     216  
     217   private:
     218    // Set the target.
     219    void
     220    set_target();
     221  
     222    friend class Set_target_once;
     223  
     224    // ELF machine code.
     225    const int machine_;
     226    // Target size--32 or 64.
     227    const int size_;
     228    // Whether the target is big endian.
     229    const bool is_big_endian_;
     230    // BFD name of target, for compatibility.
     231    const char* const bfd_name_;
     232    // GNU linker emulation for this target, for compatibility.
     233    const char* const emulation_;
     234    // Next entry in list built at global constructor time.
     235    Target_selector* next_;
     236    // The singleton Target structure--this points to an instance of the
     237    // real implementation.
     238    Target* instantiated_target_;
     239    // Used to set the target only once.
     240    Set_target_once set_target_once_;
     241  };
     242  
     243  // Select the target for an ELF file.
     244  
     245  extern Target*
     246  select_target(Input_file*, off_t,
     247  	      int machine, int size, bool big_endian, int osabi,
     248  	      int abiversion);
     249  
     250  // Select a target using a BFD name.
     251  
     252  extern Target*
     253  select_target_by_bfd_name(const char* name);
     254  
     255  // Select a target using a GNU linker emulation.
     256  
     257  extern Target*
     258  select_target_by_emulation(const char* name);
     259  
     260  // Fill in a vector with the list of supported targets.  This returns
     261  // a list of BFD names.
     262  
     263  extern void
     264  supported_target_names(std::vector<const char*>*);
     265  
     266  // Fill in a vector with the list of supported emulations.
     267  
     268  extern void
     269  supported_emulation_names(std::vector<const char*>*);
     270  
     271  // Print the output format, for the --print-output-format option.
     272  
     273  extern void
     274  print_output_format();
     275  
     276  } // End namespace gold.
     277  
     278  #endif // !defined(GOLD_TARGET_SELECT_H)