Home | History | Annotate | Download | only in gold
      1 // arm-reloc-property.h -- ARM relocation properties   -*- C++ -*-
      2 
      3 // Copyright (C) 2010-2016 Free Software Foundation, Inc.
      4 // Written by Doug Kwan <dougkwan (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_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)
    387