1 // arm-reloc-property.h -- ARM relocation properties -*- C++ -*- 2 3 // Copyright (C) 2010-2014 Free Software Foundation, Inc. 4 // Written by Doug Kwan <dougkwan (at) 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) 387