Merge branch 'vendor/GREP'
[dragonfly.git] / contrib / binutils-2.24 / gold / arm-reloc-property.h
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 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)