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@google.com> and Jing Yu <jingyu@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