1 // aarch64-reloc-property.cc -- AArch64 relocation properties -*- C++ -*- 2 3 // Copyright (C) 2014 Free Software Foundation, Inc. 4 // Written by Han Shen <shenhan (at) google.com> and Jing Yu <jingyu (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 #include "gold.h" 24 25 #include "aarch64-reloc-property.h" 26 #include "aarch64.h" 27 28 #include "symtab.h" 29 30 #include<stdio.h> 31 32 namespace gold 33 { 34 35 template<int L, int U> 36 bool 37 rvalue_checkup(int64_t x) 38 { 39 // We save the extra_alignment_requirement bits on [31:16] of U. 40 // "extra_alignment_requirement" could be 0, 1, 3, 7 and 15. 41 unsigned short extra_alignment_requirement = (U & 0xFFFF0000) >> 16; 42 // [15:0] of U indicates the upper bound check. 43 int64_t u = U & 0x0000FFFF; 44 if (u == 0) 45 { 46 // No requirement to check overflow. 47 gold_assert(L == 0); 48 return (x & extra_alignment_requirement) == 0; 49 } 50 51 // Check both overflow and alignment if needed. 52 int64_t low_bound = -(L == 0 ? 0 : ((int64_t)1 << L)); 53 int64_t up_bound = ((int64_t)1 << u); 54 return ((low_bound <= x && x < up_bound) 55 && ((x & extra_alignment_requirement) == 0)); 56 } 57 58 template<> 59 bool 60 rvalue_checkup<0, 0>(int64_t) { return true; } 61 62 template<int L, int U> 63 uint64_t 64 rvalue_bit_select(uint64_t x) 65 { 66 if (U == 63) return x >> L; 67 return (x & (((uint64_t)1 << (U+1)) - 1)) >> L; 68 } 69 70 template<> 71 uint64_t 72 rvalue_bit_select<0, 0>(uint64_t x) { return x; } 73 74 AArch64_reloc_property::AArch64_reloc_property( 75 unsigned int code, 76 const char* name, 77 Reloc_type rtype, 78 Reloc_class rclass, 79 bool is_implemented, 80 int group_index, 81 int reference_flags, 82 Reloc_inst reloc_inst, 83 rvalue_checkup_func_p rvalue_checkup_func, 84 rvalue_bit_select_func rvalue_bit_select) 85 : code_(code), name_(name), reloc_type_(rtype), reloc_class_(rclass), 86 group_index_(group_index), 87 is_implemented_(is_implemented), 88 reference_flags_(reference_flags), 89 reloc_inst_(reloc_inst), 90 rvalue_checkup_func_(rvalue_checkup_func), 91 rvalue_bit_select_func_(rvalue_bit_select) 92 {} 93 94 AArch64_reloc_property_table::AArch64_reloc_property_table() 95 { 96 const bool Y(true), N(false); 97 for (unsigned int i = 0; i < Property_table_size; ++i) 98 table_[i] = NULL; 99 100 #define RL_CHECK_ALIGN2 (1 << 16) 101 #define RL_CHECK_ALIGN4 (3 << 16) 102 #define RL_CHECK_ALIGN8 (7 << 16) 103 #define RL_CHECK_ALIGN16 (15 << 16) 104 105 #undef ARD 106 #define ARD(rname, type, class, is_implemented, group_index, LB, UB, BSL, BSH, RFLAGS, inst) \ 107 do \ 108 { \ 109 int tidx = code_to_array_index(elfcpp::R_AARCH64_##rname); \ 110 AArch64_reloc_property * p = new AArch64_reloc_property( \ 111 elfcpp::R_AARCH64_##rname, "R_AARCH64_" #rname, \ 112 AArch64_reloc_property::RT_##type, \ 113 AArch64_reloc_property::RC_##class, \ 114 is_implemented, \ 115 group_index, \ 116 (RFLAGS), \ 117 AArch64_reloc_property::INST_##inst, \ 118 rvalue_checkup<LB,UB>, \ 119 rvalue_bit_select<BSL,BSH>); \ 120 table_[tidx] = p; \ 121 } \ 122 while (0); 123 #include"aarch64-reloc.def" 124 #undef ARD 125 } 126 127 // Return a string describing a relocation code that fails to get a 128 // relocation property in get_implemented_static_reloc_property(). 129 130 std::string 131 AArch64_reloc_property_table::reloc_name_in_error_message(unsigned int code) 132 { 133 int tidx = code_to_array_index(code); 134 const AArch64_reloc_property* arp = this->table_[tidx]; 135 136 if (arp == NULL) 137 { 138 char buffer[100]; 139 sprintf(buffer, _("invalid reloc %u"), code); 140 return std::string(buffer); 141 } 142 143 // gold only implements static relocation codes. 144 AArch64_reloc_property::Reloc_type reloc_type = arp->reloc_type(); 145 gold_assert(reloc_type == AArch64_reloc_property::RT_STATIC 146 || !arp->is_implemented()); 147 148 const char* prefix = NULL; 149 switch (reloc_type) 150 { 151 case AArch64_reloc_property::RT_STATIC: 152 prefix = arp->is_implemented() ? _("reloc ") : _("unimplemented reloc "); 153 break; 154 case AArch64_reloc_property::RT_DYNAMIC: 155 prefix = _("dynamic reloc "); 156 break; 157 default: 158 gold_unreachable(); 159 } 160 return std::string(prefix) + arp->name(); 161 } 162 163 } 164