Commit | Line | Data |
---|---|---|
0d31c79d DK |
1 | // arm-reloc-property.h -- ARM relocation properties -*- C++ -*- |
2 | ||
3 | // Copyright 2010 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 | { | |
9b547ce6 | 28 | // The Arm_reloc_property class is to store information about a particular |
0d31c79d DK |
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 | ||
b2286c10 DK |
135 | // Whether relocation uses the symbol. |
136 | bool | |
137 | uses_symbol() const | |
138 | { return this->uses_symbol_; } | |
139 | ||
0d31c79d DK |
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; | |
b2286c10 DK |
281 | // Whether this uses the symbol. |
282 | bool uses_symbol_ : 1; | |
0d31c79d DK |
283 | }; |
284 | ||
9b547ce6 RW |
285 | // Arm_reloc_property_table. This table is used for looking up properties |
286 | // of relocation types. The table entries are initialized using information | |
0d31c79d DK |
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 | ||
5c57f1be DK |
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 | ||
9b547ce6 | 317 | // Return a string describing the relocation code that is not |
5c57f1be DK |
318 | // an implemented static reloc code. |
319 | std::string | |
320 | reloc_name_in_error_message(unsigned int code); | |
321 | ||
0d31c79d DK |
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 | |
9b547ce6 | 331 | // this way. Conversion from S-expressions to trees is simple. |
0d31c79d DK |
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) |