// aarch64-reloc-property.h -- AArch64 relocation properties -*- C++ -*- // Copyright (C) 2014 Free Software Foundation, Inc. // Written by Han Shen and Jing Yu . // 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_AARCH64_RELOC_PROPERTY_H #define GOLD_AARCH64_RELOC_PROPERTY_H #include #include #include"aarch64.h" namespace gold { // The AArch64_reloc_property class is to store information about a particular // relocation code. class AArch64_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. }; // Classes of relocation codes. enum Reloc_class { RC_NONE, // No relocation class. RC_DATA, // Data relocation. RC_AARCH64, // Static AArch64 relocations RC_CFLOW, // Control flow RC_TLS, // Thread local storage RC_DYNAMIC, // Dynamic relocation }; // Instructions that are associated with relocations. enum Reloc_inst { INST_DATA = 0, INST_MOVW = 1, // movz, movk, movn INST_LD = 2, // ld literal INST_ADR = 3, // adr INST_ADRP = 4, // adrp INST_ADD = 5, // add INST_LDST = 6, // ld/st INST_TBZNZ = 7, // tbz/tbnz INST_CONDB = 8, // B.cond INST_B = 9, // b [25:0] INST_CALL = 10, // bl [25:0] INST_NUM = 11, // total number of entries in the table }; // Types of bases of relative addressing relocation codes. // enum Relative_address_base { // RAB_NONE, // Relocation is not relative addressing // }; typedef bool (*rvalue_checkup_func_p)(int64_t); typedef uint64_t (*rvalue_bit_select_func)(uint64_t); // 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_; } // 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_; } // Return alignment of relocation. size_t align() const { return this->align_; } int reference_flags() const { return this->reference_flags_; } // Instruction associated with this relocation. Reloc_inst reloc_inst() const { return this->reloc_inst_; } // Check overflow of x bool checkup_x_value(int64_t x) const { return this->rvalue_checkup_func_(x); } // Return portions of x as is defined in aarch64-reloc.def. uint64_t select_x_value(uint64_t x) const { return this->rvalue_bit_select_func_(x); } protected: // These are protected. We only allow AArch64_reloc_property_table to // manage AArch64_reloc_property. AArch64_reloc_property(unsigned int code, const char* name, Reloc_type rtype, Reloc_class rclass, bool is_implemented, int group_index, int reference_flags, Reloc_inst reloc_inst, rvalue_checkup_func_p rvalue_checkup_func, rvalue_bit_select_func rvalue_bit_select); friend class AArch64_reloc_property_table; private: // Copying is not allowed. AArch64_reloc_property(const AArch64_reloc_property&); AArch64_reloc_property& operator=(const AArch64_reloc_property&); // Relocation code. const unsigned int code_; // Relocation name. const 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; const int reference_flags_; // Instruction associated with relocation. Reloc_inst reloc_inst_; rvalue_checkup_func_p rvalue_checkup_func_; rvalue_bit_select_func rvalue_bit_select_func_; }; class AArch64_reloc_property_table { public: AArch64_reloc_property_table(); const AArch64_reloc_property* get_reloc_property(unsigned int code) const { unsigned int idx = code_to_array_index(code); return this->table_[idx]; } // Like get_reloc_property but only return non-NULL if relocation code is // static and implemented. const AArch64_reloc_property* get_implemented_static_reloc_property(unsigned int code) const { unsigned int idx = code_to_array_index(code); const AArch64_reloc_property* arp = this->table_[idx]; return ((arp != NULL && (arp->reloc_type() == AArch64_reloc_property::RT_STATIC) && arp->is_implemented()) ? arp : NULL); } // Return a string describing the relocation code that is not // an implemented static reloc code. std::string reloc_name_in_error_message(unsigned int code); private: // Copying is not allowed. AArch64_reloc_property_table(const AArch64_reloc_property_table&); AArch64_reloc_property_table& operator=(const AArch64_reloc_property_table&); // Map aarch64 rtypes into range(0,300) as following // 256 ~ 313 -> 0 ~ 57 // 512 ~ 573 -> 128 ~ 189 int code_to_array_index(unsigned int code) const { if (code == 0) return 0; if (!((code >= elfcpp::R_AARCH64_ABS64 && code <= elfcpp::R_AARCH64_LD64_GOTPAGE_LO15) || (code >= elfcpp::R_AARCH64_TLSGD_ADR_PREL21 && code <= elfcpp::R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC))) { gold_error(_("Invalid/unrecognized reloc reloc %d."), code); } unsigned int rv = -1; if (code & (1 << 9)) rv = 128 + code - 512; // 512 - 573 else if (code & (1 << 8)) rv = code - 256; // 256 - 313 gold_assert(rv <= Property_table_size); return rv; } static const unsigned int Property_table_size = 300; AArch64_reloc_property* table_[Property_table_size]; }; // End of class AArch64_reloc_property_table } // End namespace gold. #endif // !defined(GOLD_AARCH64_RELOC_PROPERTY_H)