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