Home | History | Annotate | Download | only in gold
      1 // aarch64-reloc-property.h -- AArch64 relocation properties   -*- C++ -*-
      2 
      3 // Copyright (C) 2014-2016 Free Software Foundation, Inc.
      4 // Written by Han Shen <shenhan (at) google.com> and Jing Yu <jingyu (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_AARCH64_RELOC_PROPERTY_H
     24 #define GOLD_AARCH64_RELOC_PROPERTY_H
     25 
     26 #include<vector>
     27 #include<string>
     28 
     29 #include"aarch64.h"
     30 
     31 namespace gold
     32 {
     33 // The AArch64_reloc_property class is to store information about a particular
     34 // relocation code.
     35 
     36 class AArch64_reloc_property
     37 {
     38  public:
     39   // Types of relocation codes.
     40   enum Reloc_type {
     41     RT_NONE,		// No relocation type.
     42     RT_STATIC,		// Relocations processed by static linkers.
     43     RT_DYNAMIC,	// Relocations processed by dynamic linkers.
     44   };
     45 
     46   // Classes of relocation codes.
     47   enum Reloc_class {
     48     RC_NONE,		// No relocation class.
     49     RC_DATA,		// Data relocation.
     50     RC_AARCH64,		// Static AArch64 relocations
     51     RC_CFLOW,		// Control flow
     52     RC_TLS,		// Thread local storage
     53     RC_DYNAMIC,		// Dynamic relocation
     54   };
     55 
     56   // Instructions that are associated with relocations.
     57   enum Reloc_inst {
     58     INST_DATA = 0,
     59     INST_MOVW = 1,	// movz, movk, movn
     60     INST_LD = 2,	// ld literal
     61     INST_ADR = 3,	// adr
     62     INST_ADRP = 4,	// adrp
     63     INST_ADD = 5,	// add
     64     INST_LDST = 6,	// ld/st
     65     INST_TBZNZ = 7,	// tbz/tbnz
     66     INST_CONDB = 8,	// B.cond
     67     INST_B = 9,		// b  [25:0]
     68     INST_CALL = 10,	// bl [25:0]
     69     INST_NUM = 11,	// total number of entries in the table
     70   };
     71 
     72   // Types of bases of relative addressing relocation codes.
     73   // enum Relative_address_base {
     74   //   RAB_NONE,		// Relocation is not relative addressing
     75   // };
     76 
     77   typedef bool (*rvalue_checkup_func_p)(int64_t);
     78   typedef uint64_t (*rvalue_bit_select_func)(uint64_t);
     79 
     80   // Relocation code represented by this.
     81   unsigned int
     82   code() const
     83   { return this->code_; }
     84 
     85   // Name of the relocation code.
     86   const std::string&
     87   name() const
     88   { return this->name_; }
     89 
     90   // Type of relocation code.
     91   Reloc_type
     92   reloc_type() const
     93   { return this->reloc_type_; }
     94 
     95   // Class of relocation code.
     96   Reloc_class
     97   reloc_class() const
     98   { return this->reloc_class_; }
     99 
    100   // Whether this code is implemented in gold.
    101   bool
    102   is_implemented() const
    103   { return this->is_implemented_; }
    104 
    105   // If code is a group relocation code, return the group number, otherwise -1.
    106   int
    107   group_index() const
    108   { return this->group_index_; }
    109 
    110   // Return alignment of relocation.
    111   size_t
    112   align() const
    113   { return this->align_; }
    114 
    115   int
    116   reference_flags() const
    117   { return this->reference_flags_; }
    118 
    119   // Instruction associated with this relocation.
    120   Reloc_inst
    121   reloc_inst() const
    122   { return this->reloc_inst_; }
    123 
    124   // Check overflow of x
    125   bool checkup_x_value(int64_t x) const
    126   { return this->rvalue_checkup_func_(x); }
    127 
    128   // Return portions of x as is defined in aarch64-reloc.def.
    129   uint64_t select_x_value(uint64_t x) const
    130   { return this->rvalue_bit_select_func_(x); }
    131 
    132  protected:
    133   // These are protected.  We only allow AArch64_reloc_property_table to
    134   // manage AArch64_reloc_property.
    135   AArch64_reloc_property(unsigned int code, const char* name, Reloc_type rtype,
    136 			 Reloc_class rclass,
    137 			 bool is_implemented,
    138 			 int group_index,
    139 			 int reference_flags,
    140 			 Reloc_inst reloc_inst,
    141 			 rvalue_checkup_func_p rvalue_checkup_func,
    142 			 rvalue_bit_select_func rvalue_bit_select);
    143 
    144   friend class AArch64_reloc_property_table;
    145 
    146  private:
    147   // Copying is not allowed.
    148   AArch64_reloc_property(const AArch64_reloc_property&);
    149   AArch64_reloc_property& operator=(const AArch64_reloc_property&);
    150 
    151   // Relocation code.
    152   const unsigned int code_;
    153   // Relocation name.
    154   const std::string name_;
    155   // Type of relocation.
    156   Reloc_type reloc_type_;
    157   // Class of relocation.
    158   Reloc_class reloc_class_;
    159   // Group index (0, 1, or 2) if this is a group relocation or -1 otherwise.
    160   int group_index_;
    161   // Size of relocation.
    162   size_t size_;
    163   // Alignment of relocation.
    164   size_t align_;
    165   // Relative address base.
    166   // Relative_address_base relative_address_base_;
    167   // Whether this is deprecated.
    168   bool is_deprecated_ : 1;
    169   // Whether this is implemented in gold.
    170   bool is_implemented_ : 1;
    171   // Whether this checks overflow.
    172   bool checks_overflow_ : 1;
    173   const int reference_flags_;
    174   // Instruction associated with relocation.
    175   Reloc_inst reloc_inst_;
    176   rvalue_checkup_func_p rvalue_checkup_func_;
    177   rvalue_bit_select_func rvalue_bit_select_func_;
    178 };
    179 
    180 class AArch64_reloc_property_table
    181 {
    182  public:
    183   AArch64_reloc_property_table();
    184 
    185   const AArch64_reloc_property*
    186   get_reloc_property(unsigned int code) const
    187   {
    188     unsigned int idx = code_to_array_index(code);
    189     return this->table_[idx];
    190   }
    191 
    192   // Like get_reloc_property but only return non-NULL if relocation code is
    193   // static and implemented.
    194   const AArch64_reloc_property*
    195   get_implemented_static_reloc_property(unsigned int code) const
    196   {
    197     unsigned int idx = code_to_array_index(code);
    198     const AArch64_reloc_property* arp = this->table_[idx];
    199     return ((arp != NULL
    200 	     && (arp->reloc_type() == AArch64_reloc_property::RT_STATIC)
    201 	     && arp->is_implemented())
    202 	    ? arp
    203 	    : NULL);
    204   }
    205 
    206   // Return a string describing the relocation code that is not
    207   // an implemented static reloc code.
    208   std::string
    209   reloc_name_in_error_message(unsigned int code);
    210 
    211  private:
    212   // Copying is not allowed.
    213   AArch64_reloc_property_table(const AArch64_reloc_property_table&);
    214   AArch64_reloc_property_table& operator=(const AArch64_reloc_property_table&);
    215 
    216   // Map aarch64 rtypes into range(0,300) as following
    217   //   256 ~ 313 -> 0 ~ 57
    218   //   512 ~ 573 -> 128 ~ 189
    219   int
    220   code_to_array_index(unsigned int code) const
    221   {
    222     if (code == 0) return 0;
    223     if (!((code >= elfcpp::R_AARCH64_ABS64 &&
    224 	   code <= elfcpp::R_AARCH64_LD64_GOTPAGE_LO15)
    225 	  || (code >= elfcpp::R_AARCH64_TLSGD_ADR_PREL21 &&
    226 	      code <= elfcpp::R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC)))
    227       {
    228 	gold_error(_("Invalid/unrecognized reloc reloc %d."), code);
    229       }
    230     unsigned int rv = -1;
    231     if (code & (1 << 9))
    232       rv = 128 + code - 512;  // 512 - 573
    233     else if (code & (1 << 8))
    234       rv = code - 256;  // 256 - 313
    235     gold_assert(rv <= Property_table_size);
    236     return rv;
    237   }
    238 
    239   static const unsigned int Property_table_size = 300;
    240   AArch64_reloc_property* table_[Property_table_size];
    241 };  // End of class AArch64_reloc_property_table
    242 
    243 } // End namespace gold.
    244 
    245 #endif // !defined(GOLD_AARCH64_RELOC_PROPERTY_H)
    246