2010-02-03 Doug Kwan <dougkwan@google.com>
[external/binutils.git] / 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 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
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
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)