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 | { | |
28 | // The Arm_reloc_property class is to store information about a paticular | |
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 | // Return the type of relative address base or RAB_NONE if this | |
136 | // is not a relative addressing relocation. | |
137 | Relative_address_base | |
138 | relative_address_base() const | |
139 | { return this->relative_address_base_; } | |
140 | ||
141 | protected: | |
142 | // These are protected. We only allow Arm_reloc_property_table to | |
143 | // manage Arm_reloc_property. | |
144 | Arm_reloc_property(unsigned int code, const char* name, Reloc_type rtype, | |
145 | bool is_deprecated, Reloc_class rclass, | |
146 | const std::string& operation, bool is_implemented, | |
147 | int group_index, bool checks_overflow); | |
148 | ||
149 | friend class Arm_reloc_property_table; | |
150 | ||
151 | private: | |
152 | // Copying is not allowed. | |
153 | Arm_reloc_property(const Arm_reloc_property&); | |
154 | Arm_reloc_property& operator=(const Arm_reloc_property&); | |
155 | ||
156 | // The Tree_node class is used to represent parsed relocation operations. | |
157 | // We look at Trees to extract information about relocation operations. | |
158 | class Tree_node | |
159 | { | |
160 | public: | |
161 | typedef std::vector<Tree_node*> Tree_node_vector; | |
162 | ||
163 | // Construct a leaf node. | |
164 | Tree_node(const char* name) | |
165 | : is_leaf_(true), name_(name), children_() | |
166 | { } | |
167 | ||
168 | // Construct an internal node. A node owns all its children and is | |
169 | // responsible for releasing them at its own destruction. | |
170 | Tree_node(Tree_node_vector::const_iterator begin, | |
171 | Tree_node_vector::const_iterator end) | |
172 | : is_leaf_(false), name_(), children_() | |
173 | { | |
174 | for (Tree_node_vector::const_iterator p = begin; p != end; ++p) | |
175 | this->children_.push_back(*p); | |
176 | } | |
177 | ||
178 | ~Tree_node() | |
179 | { | |
180 | for(size_t i = 0; i <this->children_.size(); ++i) | |
181 | delete this->children_[i]; | |
182 | } | |
183 | ||
184 | // Whether this is a leaf node. | |
185 | bool | |
186 | is_leaf() const | |
187 | { return this->is_leaf_; } | |
188 | ||
189 | // Return name of this. This is only valid for a leaf node. | |
190 | const std::string& | |
191 | name() const | |
192 | { | |
193 | gold_assert(this->is_leaf_); | |
194 | return this->name_; | |
195 | } | |
196 | ||
197 | // Return the number of children. This is only valid for a non-leaf node. | |
198 | size_t | |
199 | number_of_children() const | |
200 | { | |
201 | gold_assert(!this->is_leaf_); | |
202 | return this->children_.size(); | |
203 | } | |
204 | ||
205 | // Return the i-th child of this. This is only valid for a non-leaf node. | |
206 | Tree_node* | |
207 | child(size_t i) const | |
208 | { | |
209 | gold_assert(!this->is_leaf_ && i < this->children_.size()); | |
210 | return this->children_[i]; | |
211 | } | |
212 | ||
213 | // Parse an S-expression string and build a tree and return the root node. | |
214 | // Caller is responsible for releasing tree after use. | |
215 | static Tree_node* | |
216 | make_tree(const std::string&); | |
217 | ||
218 | // Convert a tree back to an S-expression string. | |
219 | std::string | |
220 | s_expression() const | |
221 | { | |
222 | if (this->is_leaf_) | |
223 | return this->name_; | |
224 | ||
225 | // Concatenate S-expressions of children. Enclose them with | |
226 | // a pair of parentheses and use space as token delimiters. | |
227 | std::string s("("); | |
228 | for(size_t i = 0; i <this->children_.size(); ++i) | |
229 | s = s + " " + this->children_[i]->s_expression(); | |
230 | return s + " )"; | |
231 | } | |
232 | ||
233 | private: | |
234 | // Whether this is a leaf node. | |
235 | bool is_leaf_; | |
236 | // Name of this if this is a leaf node. | |
237 | std::string name_; | |
238 | // Children of this if this a non-leaf node. | |
239 | Tree_node_vector children_; | |
240 | }; | |
241 | ||
242 | // Relocation code. | |
243 | unsigned int code_; | |
244 | // Relocation name. | |
245 | std::string name_; | |
246 | // Type of relocation. | |
247 | Reloc_type reloc_type_; | |
248 | // Class of relocation. | |
249 | Reloc_class reloc_class_; | |
250 | // Group index (0, 1, or 2) if this is a group relocation or -1 otherwise. | |
251 | int group_index_; | |
252 | // Size of relocation. | |
253 | size_t size_; | |
254 | // Alignment of relocation. | |
255 | size_t align_; | |
256 | // Relative address base. | |
257 | Relative_address_base relative_address_base_; | |
258 | // Whether this is deprecated. | |
259 | bool is_deprecated_ : 1; | |
260 | // Whether this is implemented in gold. | |
261 | bool is_implemented_ : 1; | |
262 | // Whether this checks overflow. | |
263 | bool checks_overflow_ : 1; | |
264 | // Whether this uses a GOT entry. | |
265 | bool uses_got_entry_ : 1; | |
266 | // Whether this uses a GOT origin. | |
267 | bool uses_got_origin_ : 1; | |
268 | // Whether this uses a PLT entry. | |
269 | bool uses_plt_entry_ : 1; | |
270 | // Whether this uses the THUMB bit in symbol address. | |
271 | bool uses_thumb_bit_ : 1; | |
272 | // Whether this uses the symbol base. | |
273 | bool uses_symbol_base_ : 1; | |
274 | // Whether this uses an addend. | |
275 | bool uses_addend_ : 1; | |
276 | }; | |
277 | ||
278 | // Arm_reloc_property_table. This table is used for looking up propeties | |
279 | // of relocationt types. The table entries are initialized using information | |
280 | // from arm-reloc.def. | |
281 | ||
282 | class Arm_reloc_property_table | |
283 | { | |
284 | public: | |
285 | Arm_reloc_property_table(); | |
286 | ||
287 | // Return an Arm_reloc_property object for CODE if it is a valid relocation | |
288 | // code or NULL otherwise. | |
289 | const Arm_reloc_property* | |
290 | get_reloc_property(unsigned int code) const | |
291 | { | |
292 | gold_assert(code < Property_table_size); | |
293 | return this->table_[code]; | |
294 | } | |
295 | ||
5c57f1be DK |
296 | // Like get_reloc_property but only return non-NULL if relocation code is |
297 | // static and implemented. | |
298 | const Arm_reloc_property* | |
299 | get_implemented_static_reloc_property(unsigned int code) const | |
300 | { | |
301 | gold_assert(code < Property_table_size); | |
302 | const Arm_reloc_property* arp = this->table_[code]; | |
303 | return ((arp != NULL | |
304 | && (arp->reloc_type() == Arm_reloc_property::RT_STATIC) | |
305 | && arp->is_implemented()) | |
306 | ? arp | |
307 | : NULL); | |
308 | } | |
309 | ||
310 | // Return a string describing the a relocation code that is not | |
311 | // an implemented static reloc code. | |
312 | std::string | |
313 | reloc_name_in_error_message(unsigned int code); | |
314 | ||
0d31c79d DK |
315 | private: |
316 | // Copying is not allowed. | |
317 | Arm_reloc_property_table(const Arm_reloc_property_table&); | |
318 | Arm_reloc_property_table& operator=(const Arm_reloc_property_table&); | |
319 | ||
320 | // The Parse_expression class is used to convert relocation operations in | |
321 | // arm-reloc.def into S-expression strings, which are parsed again to | |
322 | // build actual expression trees. We do not build the expression trees | |
323 | // directly because the parser for operations in arm-reloc.def is simpler | |
324 | // this way. Coversion from S-expressions to trees is simple. | |
325 | class Parse_expression | |
326 | { | |
327 | public: | |
328 | // Construction a Parse_expression with an S-expression string. | |
329 | Parse_expression(const std::string& s_expression) | |
330 | : s_expression_(s_expression) | |
331 | { } | |
332 | ||
333 | // Value of this expression as an S-expression string. | |
334 | const std::string& | |
335 | s_expression() const | |
336 | { return this->s_expression_; } | |
337 | ||
338 | // We want to overload operators used in relocation operations so | |
339 | // that we can execute operations in arm-reloc.def to generate | |
340 | // S-expressions directly. | |
341 | #define DEF_OPERATOR_OVERLOAD(op) \ | |
342 | Parse_expression \ | |
343 | operator op (const Parse_expression& e) \ | |
344 | { \ | |
345 | return Parse_expression("( " #op " " + this->s_expression_ + " " + \ | |
346 | e.s_expression_ + " )"); \ | |
347 | } | |
348 | ||
349 | // Operator appearing in relocation operations in arm-reloc.def. | |
350 | DEF_OPERATOR_OVERLOAD(+) | |
351 | DEF_OPERATOR_OVERLOAD(-) | |
352 | DEF_OPERATOR_OVERLOAD(|) | |
353 | ||
354 | private: | |
355 | // This represented as an S-expression string. | |
356 | std::string s_expression_; | |
357 | }; | |
358 | ||
359 | #define DEF_RELOC_FUNC(name) \ | |
360 | static Parse_expression \ | |
361 | (name)(const Parse_expression& arg) \ | |
362 | { return Parse_expression("( " #name " " + arg.s_expression() + " )"); } | |
363 | ||
364 | // Functions appearing in relocation operations in arm-reloc.def. | |
365 | DEF_RELOC_FUNC(B) | |
366 | DEF_RELOC_FUNC(DELTA_B) | |
367 | DEF_RELOC_FUNC(GOT) | |
368 | DEF_RELOC_FUNC(Module) | |
369 | DEF_RELOC_FUNC(PLT) | |
370 | ||
371 | static const unsigned int Property_table_size = 256; | |
372 | ||
373 | // The property table. | |
374 | Arm_reloc_property* table_[Property_table_size]; | |
375 | }; | |
376 | ||
377 | } // End namespace gold. | |
378 | ||
379 | #endif // !defined(GOLD_ARM_RELOC_PROPERTY_H) |