diff options
Diffstat (limited to 'gold/arm-reloc-property.h')
-rw-r--r-- | gold/arm-reloc-property.h | 360 |
1 files changed, 360 insertions, 0 deletions
diff --git a/gold/arm-reloc-property.h b/gold/arm-reloc-property.h new file mode 100644 index 0000000..2d88211 --- /dev/null +++ b/gold/arm-reloc-property.h @@ -0,0 +1,360 @@ +// arm-reloc-property.h -- ARM relocation properties -*- C++ -*- + +// Copyright 2010 Free Software Foundation, Inc. +// Written by Doug Kwan <dougkwan@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +#ifndef GOLD_ARM_RELOC_PROPERTY_H +#define GOLD_ARM_RELOC_PROPERTY_H + +namespace gold +{ +// The Arm_reloc_property class is to store information about a paticular +// relocation code. + +class Arm_reloc_property +{ + public: + // Types of relocation codes. + enum Reloc_type { + RT_NONE, // No relocation type. + RT_STATIC, // Relocations processed by static linkers. + RT_DYNAMIC, // Relocations processed by dynamic linkers. + RT_PRIVATE, // Private relocations, not supported by gold. + RT_OBSOLETE // Obsolete relocations that should not be used. + }; + + // Classes of relocation codes. + enum Reloc_class { + RC_NONE, // No relocation class. + RC_DATA, // Data relocation. + RC_ARM, // ARM instruction relocation. + RC_THM16, // 16-bit THUMB instruction relocation. + RC_THM32, // 32-bit THUMB instruction relocation. + RC_MISC // Miscellaneous class. + }; + + // Types of bases of relative addressing relocation codes. + enum Relative_address_base { + RAB_NONE, // Relocation is not relative addressing + RAB_B_S, // Address origin of output segment of defining symbol. + RAB_DELTA_B_S, // Change of address origin. + RAB_GOT_ORG, // Origin of GOT. + RAB_P, // Address of the place being relocated. + RAB_Pa, // Adjusted address (P & 0xfffffffc). + RAB_TLS, // Thread local storage. + RAB_tp // Thread pointer. + }; + + // Relocation code represented by this. + unsigned int + code() const + { return this->code_; } + + // Name of the relocation code. + const std::string& + name() const + { return this->name_; } + + // Type of relocation code. + Reloc_type + reloc_type() const + { return this->reloc_type_; } + + // Whether this code is deprecated. + bool + is_deprecated() const + { return this->is_deprecated_; } + + // Class of relocation code. + Reloc_class + reloc_class() const + { return this->reloc_class_; } + + // Whether this code is implemented in gold. + bool + is_implemented() const + { return this->is_implemented_; } + + // If code is a group relocation code, return the group number, otherwise -1. + int + group_index() const + { return this->group_index_; } + + // Whether relocation checks for overflow. + bool + checks_overflow() const + { return this->checks_overflow_; } + + // Return size of relocation. + size_t + size() const + { return this->size_; } + + // Return alignment of relocation. + size_t + align() const + { return this->align_; } + + // Whether relocation use a GOT entry. + bool + uses_got_entry() const + { return this->uses_got_entry_; } + + // Whether relocation use a GOT origin. + bool + uses_got_origin() const + { return this->uses_got_origin_; } + + // Whether relocation uses the Thumb-bit in a symbol address. + bool + uses_thumb_bit() const + { return this->uses_thumb_bit_; } + + // Whether relocation uses the symbol base. + bool + uses_symbol_base() const + { return this->uses_symbol_base_; } + + // Return the type of relative address base or RAB_NONE if this + // is not a relative addressing relocation. + Relative_address_base + relative_address_base() const + { return this->relative_address_base_; } + + protected: + // These are protected. We only allow Arm_reloc_property_table to + // manage Arm_reloc_property. + Arm_reloc_property(unsigned int code, const char* name, Reloc_type rtype, + bool is_deprecated, Reloc_class rclass, + const std::string& operation, bool is_implemented, + int group_index, bool checks_overflow); + + friend class Arm_reloc_property_table; + + private: + // Copying is not allowed. + Arm_reloc_property(const Arm_reloc_property&); + Arm_reloc_property& operator=(const Arm_reloc_property&); + + // The Tree_node class is used to represent parsed relocation operations. + // We look at Trees to extract information about relocation operations. + class Tree_node + { + public: + typedef std::vector<Tree_node*> Tree_node_vector; + + // Construct a leaf node. + Tree_node(const char* name) + : is_leaf_(true), name_(name), children_() + { } + + // Construct an internal node. A node owns all its children and is + // responsible for releasing them at its own destruction. + Tree_node(Tree_node_vector::const_iterator begin, + Tree_node_vector::const_iterator end) + : is_leaf_(false), name_(), children_() + { + for (Tree_node_vector::const_iterator p = begin; p != end; ++p) + this->children_.push_back(*p); + } + + ~Tree_node() + { + for(size_t i = 0; i <this->children_.size(); ++i) + delete this->children_[i]; + } + + // Whether this is a leaf node. + bool + is_leaf() const + { return this->is_leaf_; } + + // Return name of this. This is only valid for a leaf node. + const std::string& + name() const + { + gold_assert(this->is_leaf_); + return this->name_; + } + + // Return the number of children. This is only valid for a non-leaf node. + size_t + number_of_children() const + { + gold_assert(!this->is_leaf_); + return this->children_.size(); + } + + // Return the i-th child of this. This is only valid for a non-leaf node. + Tree_node* + child(size_t i) const + { + gold_assert(!this->is_leaf_ && i < this->children_.size()); + return this->children_[i]; + } + + // Parse an S-expression string and build a tree and return the root node. + // Caller is responsible for releasing tree after use. + static Tree_node* + make_tree(const std::string&); + + // Convert a tree back to an S-expression string. + std::string + s_expression() const + { + if (this->is_leaf_) + return this->name_; + + // Concatenate S-expressions of children. Enclose them with + // a pair of parentheses and use space as token delimiters. + std::string s("("); + for(size_t i = 0; i <this->children_.size(); ++i) + s = s + " " + this->children_[i]->s_expression(); + return s + " )"; + } + + private: + // Whether this is a leaf node. + bool is_leaf_; + // Name of this if this is a leaf node. + std::string name_; + // Children of this if this a non-leaf node. + Tree_node_vector children_; + }; + + // Relocation code. + unsigned int code_; + // Relocation name. + std::string name_; + // Type of relocation. + Reloc_type reloc_type_; + // Class of relocation. + Reloc_class reloc_class_; + // Group index (0, 1, or 2) if this is a group relocation or -1 otherwise. + int group_index_; + // Size of relocation. + size_t size_; + // Alignment of relocation. + size_t align_; + // Relative address base. + Relative_address_base relative_address_base_; + // Whether this is deprecated. + bool is_deprecated_ : 1; + // Whether this is implemented in gold. + bool is_implemented_ : 1; + // Whether this checks overflow. + bool checks_overflow_ : 1; + // Whether this uses a GOT entry. + bool uses_got_entry_ : 1; + // Whether this uses a GOT origin. + bool uses_got_origin_ : 1; + // Whether this uses a PLT entry. + bool uses_plt_entry_ : 1; + // Whether this uses the THUMB bit in symbol address. + bool uses_thumb_bit_ : 1; + // Whether this uses the symbol base. + bool uses_symbol_base_ : 1; + // Whether this uses an addend. + bool uses_addend_ : 1; +}; + +// Arm_reloc_property_table. This table is used for looking up propeties +// of relocationt types. The table entries are initialized using information +// from arm-reloc.def. + +class Arm_reloc_property_table +{ + public: + Arm_reloc_property_table(); + + // Return an Arm_reloc_property object for CODE if it is a valid relocation + // code or NULL otherwise. + const Arm_reloc_property* + get_reloc_property(unsigned int code) const + { + gold_assert(code < Property_table_size); + return this->table_[code]; + } + + private: + // Copying is not allowed. + Arm_reloc_property_table(const Arm_reloc_property_table&); + Arm_reloc_property_table& operator=(const Arm_reloc_property_table&); + + // The Parse_expression class is used to convert relocation operations in + // arm-reloc.def into S-expression strings, which are parsed again to + // build actual expression trees. We do not build the expression trees + // directly because the parser for operations in arm-reloc.def is simpler + // this way. Coversion from S-expressions to trees is simple. + class Parse_expression + { + public: + // Construction a Parse_expression with an S-expression string. + Parse_expression(const std::string& s_expression) + : s_expression_(s_expression) + { } + + // Value of this expression as an S-expression string. + const std::string& + s_expression() const + { return this->s_expression_; } + + // We want to overload operators used in relocation operations so + // that we can execute operations in arm-reloc.def to generate + // S-expressions directly. +#define DEF_OPERATOR_OVERLOAD(op) \ + Parse_expression \ + operator op (const Parse_expression& e) \ + { \ + return Parse_expression("( " #op " " + this->s_expression_ + " " + \ + e.s_expression_ + " )"); \ + } + + // Operator appearing in relocation operations in arm-reloc.def. + DEF_OPERATOR_OVERLOAD(+) + DEF_OPERATOR_OVERLOAD(-) + DEF_OPERATOR_OVERLOAD(|) + + private: + // This represented as an S-expression string. + std::string s_expression_; + }; + +#define DEF_RELOC_FUNC(name) \ + static Parse_expression \ + (name)(const Parse_expression& arg) \ + { return Parse_expression("( " #name " " + arg.s_expression() + " )"); } + + // Functions appearing in relocation operations in arm-reloc.def. + DEF_RELOC_FUNC(B) + DEF_RELOC_FUNC(DELTA_B) + DEF_RELOC_FUNC(GOT) + DEF_RELOC_FUNC(Module) + DEF_RELOC_FUNC(PLT) + + static const unsigned int Property_table_size = 256; + + // The property table. + Arm_reloc_property* table_[Property_table_size]; +}; + +} // End namespace gold. + +#endif // !defined(GOLD_ARM_RELOC_PROPERTY_H) |