(root)/
binutils-2.41/
gold/
arm-reloc-property.h
       1  // arm-reloc-property.h -- ARM relocation properties   -*- C++ -*-
       2  
       3  // Copyright (C) 2010-2023 Free Software Foundation, Inc.
       4  // Written by Doug Kwan <dougkwan@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_ARM_RELOC_PROPERTY_H
      24  #define GOLD_ARM_RELOC_PROPERTY_H
      25  
      26  namespace gold
      27  {
      28  // The Arm_reloc_property class is to store information about a particular
      29  // relocation code.
      30  
      31  class Arm_reloc_property
      32  {
      33   public:
      34    // Types of relocation codes.
      35    enum Reloc_type {
      36      RT_NONE,		// No relocation type.
      37      RT_STATIC,	// Relocations processed by static linkers.
      38      RT_DYNAMIC,	// Relocations processed by dynamic linkers.
      39      RT_PRIVATE,	// Private relocations, not supported by gold.
      40      RT_OBSOLETE	// Obsolete relocations that should not be used.
      41    };
      42  
      43    // Classes of relocation codes.
      44    enum Reloc_class {
      45      RC_NONE,	// No relocation class.
      46      RC_DATA,	// Data relocation.
      47      RC_ARM,	// ARM instruction relocation.
      48      RC_THM16,	// 16-bit THUMB instruction relocation.
      49      RC_THM32,	// 32-bit THUMB instruction relocation.
      50      RC_MISC	// Miscellaneous class.
      51    };
      52  
      53    // Types of bases of relative addressing relocation codes.
      54    enum Relative_address_base {
      55      RAB_NONE,		// Relocation is not relative addressing
      56      RAB_B_S,		// Address origin of output segment of defining symbol.
      57      RAB_DELTA_B_S,	// Change of address origin.
      58      RAB_GOT_ORG,	// Origin of GOT.
      59      RAB_P,		// Address of the place being relocated.
      60      RAB_Pa,		// Adjusted address (P & 0xfffffffc).
      61      RAB_TLS,		// Thread local storage.
      62      RAB_tp		// Thread pointer.
      63    };
      64  
      65    // Relocation code represented by this.
      66    unsigned int
      67    code() const
      68    { return this->code_; }
      69  
      70    // Name of the relocation code.
      71    const std::string&
      72    name() const
      73    { return this->name_; }
      74    
      75    // Type of relocation code.
      76    Reloc_type
      77    reloc_type() const
      78    { return this->reloc_type_; }
      79  
      80    // Whether this code is deprecated.
      81    bool
      82    is_deprecated() const
      83    { return this->is_deprecated_; }
      84  
      85    // Class of relocation code.
      86    Reloc_class
      87    reloc_class() const
      88    { return this->reloc_class_; }
      89  
      90    // Whether this code is implemented in gold.
      91    bool
      92    is_implemented() const
      93    { return this->is_implemented_; }
      94  
      95    // If code is a group relocation code, return the group number, otherwise -1.
      96    int
      97    group_index() const
      98    { return this->group_index_; }
      99  
     100    // Whether relocation checks for overflow.
     101    bool
     102    checks_overflow() const
     103    { return this->checks_overflow_; }
     104  
     105    // Return size of relocation.
     106    size_t
     107    size() const
     108    { return this->size_; }
     109  
     110    // Return alignment of relocation.
     111    size_t
     112    align() const
     113    { return this->align_; }
     114  
     115    // Whether relocation use a GOT entry.
     116    bool
     117    uses_got_entry() const
     118    { return this->uses_got_entry_; }
     119  
     120    // Whether relocation use a GOT origin.
     121    bool
     122    uses_got_origin() const
     123    { return this->uses_got_origin_; }
     124    
     125    // Whether relocation uses the Thumb-bit in a symbol address.
     126    bool
     127    uses_thumb_bit() const
     128    { return this->uses_thumb_bit_; }
     129  
     130    // Whether relocation uses the symbol base.
     131    bool
     132    uses_symbol_base() const
     133    { return this->uses_symbol_base_; }
     134  
     135    // Whether relocation uses the symbol.
     136    bool
     137    uses_symbol() const
     138    { return this->uses_symbol_; }
     139  
     140    // Return the type of relative address base or RAB_NONE if this
     141    // is not a relative addressing relocation.
     142    Relative_address_base
     143    relative_address_base() const
     144    { return this->relative_address_base_; } 
     145  
     146   protected:
     147    // These are protected.  We only allow Arm_reloc_property_table to
     148    // manage Arm_reloc_property. 
     149    Arm_reloc_property(unsigned int code, const char* name, Reloc_type rtype,
     150  		     bool is_deprecated, Reloc_class rclass,
     151  		     const std::string& operation, bool is_implemented,
     152  		     int group_index, bool checks_overflow);
     153  
     154    friend class Arm_reloc_property_table;
     155    
     156   private:
     157    // Copying is not allowed.
     158    Arm_reloc_property(const Arm_reloc_property&);
     159    Arm_reloc_property& operator=(const Arm_reloc_property&);
     160  
     161    // The Tree_node class is used to represent parsed relocation operations. 
     162    // We look at Trees to extract information about relocation operations.
     163    class Tree_node
     164    {
     165     public:
     166      typedef std::vector<Tree_node*> Tree_node_vector;
     167  
     168      // Construct a leaf node.
     169      Tree_node(const char* name)
     170        : is_leaf_(true), name_(name), children_()
     171      { }
     172  
     173      // Construct an internal node.  A node owns all its children and is
     174      // responsible for releasing them at its own destruction.
     175      Tree_node(Tree_node_vector::const_iterator begin,
     176  	      Tree_node_vector::const_iterator end)
     177        : is_leaf_(false), name_(), children_()
     178      {
     179        for (Tree_node_vector::const_iterator p = begin; p != end; ++p)
     180  	this->children_.push_back(*p);
     181      }
     182  
     183      ~Tree_node()
     184      {
     185        for(size_t i = 0; i <this->children_.size(); ++i)
     186  	delete this->children_[i];
     187      }
     188  
     189      // Whether this is a leaf node.
     190      bool
     191      is_leaf() const
     192      { return this->is_leaf_; }
     193  
     194      // Return name of this.  This is only valid for a leaf node.
     195      const std::string&
     196      name() const
     197      {
     198        gold_assert(this->is_leaf_);
     199        return this->name_;
     200      }
     201  
     202      // Return the number of children.  This is only valid for a non-leaf node.
     203      size_t
     204      number_of_children() const
     205      {
     206        gold_assert(!this->is_leaf_);
     207        return this->children_.size();
     208      }
     209  
     210      // Return the i-th child of this.  This is only valid for a non-leaf node.
     211      Tree_node*
     212      child(size_t i) const
     213      {
     214        gold_assert(!this->is_leaf_ && i < this->children_.size());
     215        return this->children_[i];
     216      }
     217  
     218      // Parse an S-expression string and build a tree and return the root node.
     219      // Caller is responsible for releasing tree after use.
     220      static Tree_node*
     221      make_tree(const std::string&);
     222  
     223      // Convert a tree back to an S-expression string.
     224      std::string
     225      s_expression() const
     226      {
     227        if (this->is_leaf_)
     228  	return this->name_;
     229  
     230        // Concatenate S-expressions of children. Enclose them with
     231        // a pair of parentheses and use space as token delimiters.
     232        std::string s("(");
     233        for(size_t i = 0; i <this->children_.size(); ++i)
     234  	s = s + " " + this->children_[i]->s_expression();
     235        return s + " )";
     236      }
     237  
     238     private:
     239      // Whether this is a leaf node.
     240      bool is_leaf_;
     241      // Name of this if this is a leaf node.
     242      std::string name_;
     243      // Children of this if this a non-leaf node.
     244      Tree_node_vector children_;
     245    };
     246  
     247    // Relocation code.
     248    unsigned int code_;
     249    // Relocation name.
     250    std::string name_;
     251    // Type of relocation.
     252    Reloc_type reloc_type_;
     253    // Class of relocation.
     254    Reloc_class reloc_class_;
     255    // Group index (0, 1, or 2) if this is a group relocation or -1 otherwise.
     256    int group_index_; 
     257    // Size of relocation.
     258    size_t size_;
     259    // Alignment of relocation.
     260    size_t align_;
     261    // Relative address base.
     262    Relative_address_base relative_address_base_;
     263    // Whether this is deprecated.
     264    bool is_deprecated_ : 1;
     265    // Whether this is implemented in gold.
     266    bool is_implemented_ : 1;
     267    // Whether this checks overflow.
     268    bool checks_overflow_ : 1;
     269    // Whether this uses a GOT entry.
     270    bool uses_got_entry_ : 1;
     271    // Whether this uses a GOT origin.
     272    bool uses_got_origin_ : 1;
     273    // Whether this uses a PLT entry.
     274    bool uses_plt_entry_ : 1;
     275    // Whether this uses the THUMB bit in symbol address.
     276    bool uses_thumb_bit_ : 1;
     277    // Whether this uses the symbol base.
     278    bool uses_symbol_base_ : 1;
     279    // Whether this uses an addend.
     280    bool uses_addend_ : 1;
     281    // Whether this uses the symbol.
     282    bool uses_symbol_ : 1;
     283  };
     284  
     285  // Arm_reloc_property_table.  This table is used for looking up properties
     286  // of relocation types.  The table entries are initialized using information
     287  // from arm-reloc.def.
     288  
     289  class Arm_reloc_property_table
     290  {
     291   public:
     292    Arm_reloc_property_table();
     293  
     294    // Return an Arm_reloc_property object for CODE if it is a valid relocation
     295    // code or NULL otherwise.
     296    const Arm_reloc_property*
     297    get_reloc_property(unsigned int code) const
     298    {
     299      gold_assert(code < Property_table_size);
     300      return this->table_[code];
     301    }
     302  
     303    // Like get_reloc_property but only return non-NULL if relocation code is
     304    // static and implemented.
     305    const Arm_reloc_property*
     306    get_implemented_static_reloc_property(unsigned int code) const
     307    {
     308      gold_assert(code < Property_table_size);
     309      const Arm_reloc_property* arp = this->table_[code];
     310      return ((arp != NULL
     311  	     && (arp->reloc_type() == Arm_reloc_property::RT_STATIC)
     312  	     && arp->is_implemented())
     313  	    ? arp
     314  	    : NULL);
     315    }
     316    
     317    // Return a string describing the relocation code that is not
     318    // an implemented static reloc code.
     319    std::string
     320    reloc_name_in_error_message(unsigned int code);
     321  
     322   private:
     323    // Copying is not allowed.
     324    Arm_reloc_property_table(const Arm_reloc_property_table&);
     325    Arm_reloc_property_table& operator=(const Arm_reloc_property_table&);
     326  
     327    // The Parse_expression class is used to convert relocation operations in
     328    // arm-reloc.def into S-expression strings, which are parsed again to
     329    // build actual expression trees.  We do not build the expression trees
     330    // directly because the parser for operations in arm-reloc.def is simpler
     331    // this way.  Conversion from S-expressions to trees is simple.
     332    class Parse_expression
     333    {
     334     public:
     335      // Construction a Parse_expression with an S-expression string.
     336      Parse_expression(const std::string& s_expression)
     337        : s_expression_(s_expression)
     338      { }
     339  
     340      // Value of this expression as an S-expression string.
     341      const std::string&
     342      s_expression() const
     343      { return this->s_expression_; }
     344  
     345      // We want to overload operators used in relocation operations so
     346      // that we can execute operations in arm-reloc.def to generate
     347      // S-expressions directly.
     348  #define DEF_OPERATOR_OVERLOAD(op) \
     349      Parse_expression \
     350      operator op (const Parse_expression& e) \
     351      { \
     352        return Parse_expression("( " #op " " + this->s_expression_ + " " + \
     353  			      e.s_expression_ + " )"); \
     354      }
     355  
     356      // Operator appearing in relocation operations in arm-reloc.def.
     357      DEF_OPERATOR_OVERLOAD(+)
     358      DEF_OPERATOR_OVERLOAD(-)
     359      DEF_OPERATOR_OVERLOAD(|)
     360      
     361     private:
     362      // This represented as an S-expression string.
     363      std::string s_expression_;
     364    };
     365  
     366  #define DEF_RELOC_FUNC(name) \
     367    static Parse_expression \
     368    (name)(const Parse_expression& arg) \
     369    { return Parse_expression("( " #name " " + arg.s_expression() + " )"); }
     370  
     371    // Functions appearing in relocation operations in arm-reloc.def.
     372    DEF_RELOC_FUNC(B)
     373    DEF_RELOC_FUNC(DELTA_B)
     374    DEF_RELOC_FUNC(GOT)
     375    DEF_RELOC_FUNC(Module)
     376    DEF_RELOC_FUNC(PLT)
     377  
     378    static const unsigned int Property_table_size = 256;
     379  
     380    // The property table.
     381    Arm_reloc_property* table_[Property_table_size];
     382  };
     383  
     384  } // End namespace gold.
     385  
     386  #endif // !defined(GOLD_ARM_RELOC_PROPERTY_H)