xref: /dflybsd-src/contrib/binutils-2.27/gold/arm-reloc-property.h (revision e656dc90e3d65d744d534af2f5ea88cf8101ebcf)
1*a9fa9459Szrj // arm-reloc-property.h -- ARM relocation properties   -*- C++ -*-
2*a9fa9459Szrj 
3*a9fa9459Szrj // Copyright (C) 2010-2016 Free Software Foundation, Inc.
4*a9fa9459Szrj // Written by Doug Kwan <dougkwan@google.com>.
5*a9fa9459Szrj 
6*a9fa9459Szrj // This file is part of gold.
7*a9fa9459Szrj 
8*a9fa9459Szrj // This program is free software; you can redistribute it and/or modify
9*a9fa9459Szrj // it under the terms of the GNU General Public License as published by
10*a9fa9459Szrj // the Free Software Foundation; either version 3 of the License, or
11*a9fa9459Szrj // (at your option) any later version.
12*a9fa9459Szrj 
13*a9fa9459Szrj // This program is distributed in the hope that it will be useful,
14*a9fa9459Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of
15*a9fa9459Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*a9fa9459Szrj // GNU General Public License for more details.
17*a9fa9459Szrj 
18*a9fa9459Szrj // You should have received a copy of the GNU General Public License
19*a9fa9459Szrj // along with this program; if not, write to the Free Software
20*a9fa9459Szrj // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21*a9fa9459Szrj // MA 02110-1301, USA.
22*a9fa9459Szrj 
23*a9fa9459Szrj #ifndef GOLD_ARM_RELOC_PROPERTY_H
24*a9fa9459Szrj #define GOLD_ARM_RELOC_PROPERTY_H
25*a9fa9459Szrj 
26*a9fa9459Szrj namespace gold
27*a9fa9459Szrj {
28*a9fa9459Szrj // The Arm_reloc_property class is to store information about a particular
29*a9fa9459Szrj // relocation code.
30*a9fa9459Szrj 
31*a9fa9459Szrj class Arm_reloc_property
32*a9fa9459Szrj {
33*a9fa9459Szrj  public:
34*a9fa9459Szrj   // Types of relocation codes.
35*a9fa9459Szrj   enum Reloc_type {
36*a9fa9459Szrj     RT_NONE,		// No relocation type.
37*a9fa9459Szrj     RT_STATIC,	// Relocations processed by static linkers.
38*a9fa9459Szrj     RT_DYNAMIC,	// Relocations processed by dynamic linkers.
39*a9fa9459Szrj     RT_PRIVATE,	// Private relocations, not supported by gold.
40*a9fa9459Szrj     RT_OBSOLETE	// Obsolete relocations that should not be used.
41*a9fa9459Szrj   };
42*a9fa9459Szrj 
43*a9fa9459Szrj   // Classes of relocation codes.
44*a9fa9459Szrj   enum Reloc_class {
45*a9fa9459Szrj     RC_NONE,	// No relocation class.
46*a9fa9459Szrj     RC_DATA,	// Data relocation.
47*a9fa9459Szrj     RC_ARM,	// ARM instruction relocation.
48*a9fa9459Szrj     RC_THM16,	// 16-bit THUMB instruction relocation.
49*a9fa9459Szrj     RC_THM32,	// 32-bit THUMB instruction relocation.
50*a9fa9459Szrj     RC_MISC	// Miscellaneous class.
51*a9fa9459Szrj   };
52*a9fa9459Szrj 
53*a9fa9459Szrj   // Types of bases of relative addressing relocation codes.
54*a9fa9459Szrj   enum Relative_address_base {
55*a9fa9459Szrj     RAB_NONE,		// Relocation is not relative addressing
56*a9fa9459Szrj     RAB_B_S,		// Address origin of output segment of defining symbol.
57*a9fa9459Szrj     RAB_DELTA_B_S,	// Change of address origin.
58*a9fa9459Szrj     RAB_GOT_ORG,	// Origin of GOT.
59*a9fa9459Szrj     RAB_P,		// Address of the place being relocated.
60*a9fa9459Szrj     RAB_Pa,		// Adjusted address (P & 0xfffffffc).
61*a9fa9459Szrj     RAB_TLS,		// Thread local storage.
62*a9fa9459Szrj     RAB_tp		// Thread pointer.
63*a9fa9459Szrj   };
64*a9fa9459Szrj 
65*a9fa9459Szrj   // Relocation code represented by this.
66*a9fa9459Szrj   unsigned int
code()67*a9fa9459Szrj   code() const
68*a9fa9459Szrj   { return this->code_; }
69*a9fa9459Szrj 
70*a9fa9459Szrj   // Name of the relocation code.
71*a9fa9459Szrj   const std::string&
name()72*a9fa9459Szrj   name() const
73*a9fa9459Szrj   { return this->name_; }
74*a9fa9459Szrj 
75*a9fa9459Szrj   // Type of relocation code.
76*a9fa9459Szrj   Reloc_type
reloc_type()77*a9fa9459Szrj   reloc_type() const
78*a9fa9459Szrj   { return this->reloc_type_; }
79*a9fa9459Szrj 
80*a9fa9459Szrj   // Whether this code is deprecated.
81*a9fa9459Szrj   bool
is_deprecated()82*a9fa9459Szrj   is_deprecated() const
83*a9fa9459Szrj   { return this->is_deprecated_; }
84*a9fa9459Szrj 
85*a9fa9459Szrj   // Class of relocation code.
86*a9fa9459Szrj   Reloc_class
reloc_class()87*a9fa9459Szrj   reloc_class() const
88*a9fa9459Szrj   { return this->reloc_class_; }
89*a9fa9459Szrj 
90*a9fa9459Szrj   // Whether this code is implemented in gold.
91*a9fa9459Szrj   bool
is_implemented()92*a9fa9459Szrj   is_implemented() const
93*a9fa9459Szrj   { return this->is_implemented_; }
94*a9fa9459Szrj 
95*a9fa9459Szrj   // If code is a group relocation code, return the group number, otherwise -1.
96*a9fa9459Szrj   int
group_index()97*a9fa9459Szrj   group_index() const
98*a9fa9459Szrj   { return this->group_index_; }
99*a9fa9459Szrj 
100*a9fa9459Szrj   // Whether relocation checks for overflow.
101*a9fa9459Szrj   bool
checks_overflow()102*a9fa9459Szrj   checks_overflow() const
103*a9fa9459Szrj   { return this->checks_overflow_; }
104*a9fa9459Szrj 
105*a9fa9459Szrj   // Return size of relocation.
106*a9fa9459Szrj   size_t
size()107*a9fa9459Szrj   size() const
108*a9fa9459Szrj   { return this->size_; }
109*a9fa9459Szrj 
110*a9fa9459Szrj   // Return alignment of relocation.
111*a9fa9459Szrj   size_t
align()112*a9fa9459Szrj   align() const
113*a9fa9459Szrj   { return this->align_; }
114*a9fa9459Szrj 
115*a9fa9459Szrj   // Whether relocation use a GOT entry.
116*a9fa9459Szrj   bool
uses_got_entry()117*a9fa9459Szrj   uses_got_entry() const
118*a9fa9459Szrj   { return this->uses_got_entry_; }
119*a9fa9459Szrj 
120*a9fa9459Szrj   // Whether relocation use a GOT origin.
121*a9fa9459Szrj   bool
uses_got_origin()122*a9fa9459Szrj   uses_got_origin() const
123*a9fa9459Szrj   { return this->uses_got_origin_; }
124*a9fa9459Szrj 
125*a9fa9459Szrj   // Whether relocation uses the Thumb-bit in a symbol address.
126*a9fa9459Szrj   bool
uses_thumb_bit()127*a9fa9459Szrj   uses_thumb_bit() const
128*a9fa9459Szrj   { return this->uses_thumb_bit_; }
129*a9fa9459Szrj 
130*a9fa9459Szrj   // Whether relocation uses the symbol base.
131*a9fa9459Szrj   bool
uses_symbol_base()132*a9fa9459Szrj   uses_symbol_base() const
133*a9fa9459Szrj   { return this->uses_symbol_base_; }
134*a9fa9459Szrj 
135*a9fa9459Szrj   // Whether relocation uses the symbol.
136*a9fa9459Szrj   bool
uses_symbol()137*a9fa9459Szrj   uses_symbol() const
138*a9fa9459Szrj   { return this->uses_symbol_; }
139*a9fa9459Szrj 
140*a9fa9459Szrj   // Return the type of relative address base or RAB_NONE if this
141*a9fa9459Szrj   // is not a relative addressing relocation.
142*a9fa9459Szrj   Relative_address_base
relative_address_base()143*a9fa9459Szrj   relative_address_base() const
144*a9fa9459Szrj   { return this->relative_address_base_; }
145*a9fa9459Szrj 
146*a9fa9459Szrj  protected:
147*a9fa9459Szrj   // These are protected.  We only allow Arm_reloc_property_table to
148*a9fa9459Szrj   // manage Arm_reloc_property.
149*a9fa9459Szrj   Arm_reloc_property(unsigned int code, const char* name, Reloc_type rtype,
150*a9fa9459Szrj 		     bool is_deprecated, Reloc_class rclass,
151*a9fa9459Szrj 		     const std::string& operation, bool is_implemented,
152*a9fa9459Szrj 		     int group_index, bool checks_overflow);
153*a9fa9459Szrj 
154*a9fa9459Szrj   friend class Arm_reloc_property_table;
155*a9fa9459Szrj 
156*a9fa9459Szrj  private:
157*a9fa9459Szrj   // Copying is not allowed.
158*a9fa9459Szrj   Arm_reloc_property(const Arm_reloc_property&);
159*a9fa9459Szrj   Arm_reloc_property& operator=(const Arm_reloc_property&);
160*a9fa9459Szrj 
161*a9fa9459Szrj   // The Tree_node class is used to represent parsed relocation operations.
162*a9fa9459Szrj   // We look at Trees to extract information about relocation operations.
163*a9fa9459Szrj   class Tree_node
164*a9fa9459Szrj   {
165*a9fa9459Szrj    public:
166*a9fa9459Szrj     typedef std::vector<Tree_node*> Tree_node_vector;
167*a9fa9459Szrj 
168*a9fa9459Szrj     // Construct a leaf node.
Tree_node(const char * name)169*a9fa9459Szrj     Tree_node(const char* name)
170*a9fa9459Szrj       : is_leaf_(true), name_(name), children_()
171*a9fa9459Szrj     { }
172*a9fa9459Szrj 
173*a9fa9459Szrj     // Construct an internal node.  A node owns all its children and is
174*a9fa9459Szrj     // responsible for releasing them at its own destruction.
Tree_node(Tree_node_vector::const_iterator begin,Tree_node_vector::const_iterator end)175*a9fa9459Szrj     Tree_node(Tree_node_vector::const_iterator begin,
176*a9fa9459Szrj 	      Tree_node_vector::const_iterator end)
177*a9fa9459Szrj       : is_leaf_(false), name_(), children_()
178*a9fa9459Szrj     {
179*a9fa9459Szrj       for (Tree_node_vector::const_iterator p = begin; p != end; ++p)
180*a9fa9459Szrj 	this->children_.push_back(*p);
181*a9fa9459Szrj     }
182*a9fa9459Szrj 
~Tree_node()183*a9fa9459Szrj     ~Tree_node()
184*a9fa9459Szrj     {
185*a9fa9459Szrj       for(size_t i = 0; i <this->children_.size(); ++i)
186*a9fa9459Szrj 	delete this->children_[i];
187*a9fa9459Szrj     }
188*a9fa9459Szrj 
189*a9fa9459Szrj     // Whether this is a leaf node.
190*a9fa9459Szrj     bool
is_leaf()191*a9fa9459Szrj     is_leaf() const
192*a9fa9459Szrj     { return this->is_leaf_; }
193*a9fa9459Szrj 
194*a9fa9459Szrj     // Return name of this.  This is only valid for a leaf node.
195*a9fa9459Szrj     const std::string&
name()196*a9fa9459Szrj     name() const
197*a9fa9459Szrj     {
198*a9fa9459Szrj       gold_assert(this->is_leaf_);
199*a9fa9459Szrj       return this->name_;
200*a9fa9459Szrj     }
201*a9fa9459Szrj 
202*a9fa9459Szrj     // Return the number of children.  This is only valid for a non-leaf node.
203*a9fa9459Szrj     size_t
number_of_children()204*a9fa9459Szrj     number_of_children() const
205*a9fa9459Szrj     {
206*a9fa9459Szrj       gold_assert(!this->is_leaf_);
207*a9fa9459Szrj       return this->children_.size();
208*a9fa9459Szrj     }
209*a9fa9459Szrj 
210*a9fa9459Szrj     // Return the i-th child of this.  This is only valid for a non-leaf node.
211*a9fa9459Szrj     Tree_node*
child(size_t i)212*a9fa9459Szrj     child(size_t i) const
213*a9fa9459Szrj     {
214*a9fa9459Szrj       gold_assert(!this->is_leaf_ && i < this->children_.size());
215*a9fa9459Szrj       return this->children_[i];
216*a9fa9459Szrj     }
217*a9fa9459Szrj 
218*a9fa9459Szrj     // Parse an S-expression string and build a tree and return the root node.
219*a9fa9459Szrj     // Caller is responsible for releasing tree after use.
220*a9fa9459Szrj     static Tree_node*
221*a9fa9459Szrj     make_tree(const std::string&);
222*a9fa9459Szrj 
223*a9fa9459Szrj     // Convert a tree back to an S-expression string.
224*a9fa9459Szrj     std::string
s_expression()225*a9fa9459Szrj     s_expression() const
226*a9fa9459Szrj     {
227*a9fa9459Szrj       if (this->is_leaf_)
228*a9fa9459Szrj 	return this->name_;
229*a9fa9459Szrj 
230*a9fa9459Szrj       // Concatenate S-expressions of children. Enclose them with
231*a9fa9459Szrj       // a pair of parentheses and use space as token delimiters.
232*a9fa9459Szrj       std::string s("(");
233*a9fa9459Szrj       for(size_t i = 0; i <this->children_.size(); ++i)
234*a9fa9459Szrj 	s = s + " " + this->children_[i]->s_expression();
235*a9fa9459Szrj       return s + " )";
236*a9fa9459Szrj     }
237*a9fa9459Szrj 
238*a9fa9459Szrj    private:
239*a9fa9459Szrj     // Whether this is a leaf node.
240*a9fa9459Szrj     bool is_leaf_;
241*a9fa9459Szrj     // Name of this if this is a leaf node.
242*a9fa9459Szrj     std::string name_;
243*a9fa9459Szrj     // Children of this if this a non-leaf node.
244*a9fa9459Szrj     Tree_node_vector children_;
245*a9fa9459Szrj   };
246*a9fa9459Szrj 
247*a9fa9459Szrj   // Relocation code.
248*a9fa9459Szrj   unsigned int code_;
249*a9fa9459Szrj   // Relocation name.
250*a9fa9459Szrj   std::string name_;
251*a9fa9459Szrj   // Type of relocation.
252*a9fa9459Szrj   Reloc_type reloc_type_;
253*a9fa9459Szrj   // Class of relocation.
254*a9fa9459Szrj   Reloc_class reloc_class_;
255*a9fa9459Szrj   // Group index (0, 1, or 2) if this is a group relocation or -1 otherwise.
256*a9fa9459Szrj   int group_index_;
257*a9fa9459Szrj   // Size of relocation.
258*a9fa9459Szrj   size_t size_;
259*a9fa9459Szrj   // Alignment of relocation.
260*a9fa9459Szrj   size_t align_;
261*a9fa9459Szrj   // Relative address base.
262*a9fa9459Szrj   Relative_address_base relative_address_base_;
263*a9fa9459Szrj   // Whether this is deprecated.
264*a9fa9459Szrj   bool is_deprecated_ : 1;
265*a9fa9459Szrj   // Whether this is implemented in gold.
266*a9fa9459Szrj   bool is_implemented_ : 1;
267*a9fa9459Szrj   // Whether this checks overflow.
268*a9fa9459Szrj   bool checks_overflow_ : 1;
269*a9fa9459Szrj   // Whether this uses a GOT entry.
270*a9fa9459Szrj   bool uses_got_entry_ : 1;
271*a9fa9459Szrj   // Whether this uses a GOT origin.
272*a9fa9459Szrj   bool uses_got_origin_ : 1;
273*a9fa9459Szrj   // Whether this uses a PLT entry.
274*a9fa9459Szrj   bool uses_plt_entry_ : 1;
275*a9fa9459Szrj   // Whether this uses the THUMB bit in symbol address.
276*a9fa9459Szrj   bool uses_thumb_bit_ : 1;
277*a9fa9459Szrj   // Whether this uses the symbol base.
278*a9fa9459Szrj   bool uses_symbol_base_ : 1;
279*a9fa9459Szrj   // Whether this uses an addend.
280*a9fa9459Szrj   bool uses_addend_ : 1;
281*a9fa9459Szrj   // Whether this uses the symbol.
282*a9fa9459Szrj   bool uses_symbol_ : 1;
283*a9fa9459Szrj };
284*a9fa9459Szrj 
285*a9fa9459Szrj // Arm_reloc_property_table.  This table is used for looking up properties
286*a9fa9459Szrj // of relocation types.  The table entries are initialized using information
287*a9fa9459Szrj // from arm-reloc.def.
288*a9fa9459Szrj 
289*a9fa9459Szrj class Arm_reloc_property_table
290*a9fa9459Szrj {
291*a9fa9459Szrj  public:
292*a9fa9459Szrj   Arm_reloc_property_table();
293*a9fa9459Szrj 
294*a9fa9459Szrj   // Return an Arm_reloc_property object for CODE if it is a valid relocation
295*a9fa9459Szrj   // code or NULL otherwise.
296*a9fa9459Szrj   const Arm_reloc_property*
get_reloc_property(unsigned int code)297*a9fa9459Szrj   get_reloc_property(unsigned int code) const
298*a9fa9459Szrj   {
299*a9fa9459Szrj     gold_assert(code < Property_table_size);
300*a9fa9459Szrj     return this->table_[code];
301*a9fa9459Szrj   }
302*a9fa9459Szrj 
303*a9fa9459Szrj   // Like get_reloc_property but only return non-NULL if relocation code is
304*a9fa9459Szrj   // static and implemented.
305*a9fa9459Szrj   const Arm_reloc_property*
get_implemented_static_reloc_property(unsigned int code)306*a9fa9459Szrj   get_implemented_static_reloc_property(unsigned int code) const
307*a9fa9459Szrj   {
308*a9fa9459Szrj     gold_assert(code < Property_table_size);
309*a9fa9459Szrj     const Arm_reloc_property* arp = this->table_[code];
310*a9fa9459Szrj     return ((arp != NULL
311*a9fa9459Szrj 	     && (arp->reloc_type() == Arm_reloc_property::RT_STATIC)
312*a9fa9459Szrj 	     && arp->is_implemented())
313*a9fa9459Szrj 	    ? arp
314*a9fa9459Szrj 	    : NULL);
315*a9fa9459Szrj   }
316*a9fa9459Szrj 
317*a9fa9459Szrj   // Return a string describing the relocation code that is not
318*a9fa9459Szrj   // an implemented static reloc code.
319*a9fa9459Szrj   std::string
320*a9fa9459Szrj   reloc_name_in_error_message(unsigned int code);
321*a9fa9459Szrj 
322*a9fa9459Szrj  private:
323*a9fa9459Szrj   // Copying is not allowed.
324*a9fa9459Szrj   Arm_reloc_property_table(const Arm_reloc_property_table&);
325*a9fa9459Szrj   Arm_reloc_property_table& operator=(const Arm_reloc_property_table&);
326*a9fa9459Szrj 
327*a9fa9459Szrj   // The Parse_expression class is used to convert relocation operations in
328*a9fa9459Szrj   // arm-reloc.def into S-expression strings, which are parsed again to
329*a9fa9459Szrj   // build actual expression trees.  We do not build the expression trees
330*a9fa9459Szrj   // directly because the parser for operations in arm-reloc.def is simpler
331*a9fa9459Szrj   // this way.  Conversion from S-expressions to trees is simple.
332*a9fa9459Szrj   class Parse_expression
333*a9fa9459Szrj   {
334*a9fa9459Szrj    public:
335*a9fa9459Szrj     // Construction a Parse_expression with an S-expression string.
Parse_expression(const std::string & s_expression)336*a9fa9459Szrj     Parse_expression(const std::string& s_expression)
337*a9fa9459Szrj       : s_expression_(s_expression)
338*a9fa9459Szrj     { }
339*a9fa9459Szrj 
340*a9fa9459Szrj     // Value of this expression as an S-expression string.
341*a9fa9459Szrj     const std::string&
s_expression()342*a9fa9459Szrj     s_expression() const
343*a9fa9459Szrj     { return this->s_expression_; }
344*a9fa9459Szrj 
345*a9fa9459Szrj     // We want to overload operators used in relocation operations so
346*a9fa9459Szrj     // that we can execute operations in arm-reloc.def to generate
347*a9fa9459Szrj     // S-expressions directly.
348*a9fa9459Szrj #define DEF_OPERATOR_OVERLOAD(op) \
349*a9fa9459Szrj     Parse_expression \
350*a9fa9459Szrj     operator op (const Parse_expression& e) \
351*a9fa9459Szrj     { \
352*a9fa9459Szrj       return Parse_expression("( " #op " " + this->s_expression_ + " " + \
353*a9fa9459Szrj 			      e.s_expression_ + " )"); \
354*a9fa9459Szrj     }
355*a9fa9459Szrj 
356*a9fa9459Szrj     // Operator appearing in relocation operations in arm-reloc.def.
357*a9fa9459Szrj     DEF_OPERATOR_OVERLOAD(+)
358*a9fa9459Szrj     DEF_OPERATOR_OVERLOAD(-)
359*a9fa9459Szrj     DEF_OPERATOR_OVERLOAD(|)
360*a9fa9459Szrj 
361*a9fa9459Szrj    private:
362*a9fa9459Szrj     // This represented as an S-expression string.
363*a9fa9459Szrj     std::string s_expression_;
364*a9fa9459Szrj   };
365*a9fa9459Szrj 
366*a9fa9459Szrj #define DEF_RELOC_FUNC(name) \
367*a9fa9459Szrj   static Parse_expression \
368*a9fa9459Szrj   (name)(const Parse_expression& arg) \
369*a9fa9459Szrj   { return Parse_expression("( " #name " " + arg.s_expression() + " )"); }
370*a9fa9459Szrj 
371*a9fa9459Szrj   // Functions appearing in relocation operations in arm-reloc.def.
372*a9fa9459Szrj   DEF_RELOC_FUNC(B)
373*a9fa9459Szrj   DEF_RELOC_FUNC(DELTA_B)
374*a9fa9459Szrj   DEF_RELOC_FUNC(GOT)
375*a9fa9459Szrj   DEF_RELOC_FUNC(Module)
376*a9fa9459Szrj   DEF_RELOC_FUNC(PLT)
377*a9fa9459Szrj 
378*a9fa9459Szrj   static const unsigned int Property_table_size = 256;
379*a9fa9459Szrj 
380*a9fa9459Szrj   // The property table.
381*a9fa9459Szrj   Arm_reloc_property* table_[Property_table_size];
382*a9fa9459Szrj };
383*a9fa9459Szrj 
384*a9fa9459Szrj } // End namespace gold.
385*a9fa9459Szrj 
386*a9fa9459Szrj #endif // !defined(GOLD_ARM_RELOC_PROPERTY_H)
387