1// aarch64-reloc-property.cc -- AArch64 relocation properties -*- C++ -*- 2 3// Copyright (C) 2014-2017 Free Software Foundation, Inc. 4// Written by Han Shen <shenhan@google.com> and Jing Yu <jingyu@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 32namespace gold 33{ 34 35template<int L, int U> 36bool 37rvalue_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 58template<> 59bool 60rvalue_checkup<0, 0>(int64_t) { return true; } 61 62namespace 63{ 64 65template<int L, int U> 66class Rvalue_bit_select_impl 67{ 68public: 69 static uint64_t 70 calc(uint64_t x) 71 { 72 return (x & ((1ULL << (U+1)) - 1)) >> L; 73 } 74}; 75 76template<int L> 77class Rvalue_bit_select_impl<L, 63> 78{ 79public: 80 static uint64_t 81 calc(uint64_t x) 82 { 83 return x >> L; 84 } 85}; 86 87// By our convention, L=U=0 means that the whole value should be retrieved. 88template<> 89class Rvalue_bit_select_impl<0, 0> 90{ 91public: 92 static uint64_t 93 calc(uint64_t x) 94 { 95 return x; 96 } 97}; 98 99} // End anonymous namespace. 100 101template<int L, int U> 102uint64_t 103rvalue_bit_select(uint64_t x) 104{ 105 return Rvalue_bit_select_impl<L, U>::calc(x); 106} 107 108AArch64_reloc_property::AArch64_reloc_property( 109 unsigned int code, 110 const char* name, 111 Reloc_type rtype, 112 Reloc_class rclass, 113 bool is_implemented, 114 int group_index, 115 int reference_flags, 116 Reloc_inst reloc_inst, 117 rvalue_checkup_func_p rvalue_checkup_func, 118 rvalue_bit_select_func rvalue_bit_select) 119 : code_(code), name_(name), reloc_type_(rtype), reloc_class_(rclass), 120 group_index_(group_index), 121 is_implemented_(is_implemented), 122 reference_flags_(reference_flags), 123 reloc_inst_(reloc_inst), 124 rvalue_checkup_func_(rvalue_checkup_func), 125 rvalue_bit_select_func_(rvalue_bit_select) 126{} 127 128AArch64_reloc_property_table::AArch64_reloc_property_table() 129{ 130 const bool Y(true), N(false); 131 for (unsigned int i = 0; i < Property_table_size; ++i) 132 table_[i] = NULL; 133 134#define RL_CHECK_ALIGN2 (1 << 16) 135#define RL_CHECK_ALIGN4 (3 << 16) 136#define RL_CHECK_ALIGN8 (7 << 16) 137#define RL_CHECK_ALIGN16 (15 << 16) 138 139#undef ARD 140#define ARD(rname, type, class, is_implemented, group_index, LB, UB, BSL, BSH, RFLAGS, inst) \ 141 do \ 142 { \ 143 int tidx = code_to_array_index(elfcpp::R_AARCH64_##rname); \ 144 AArch64_reloc_property * p = new AArch64_reloc_property( \ 145 elfcpp::R_AARCH64_##rname, "R_AARCH64_" #rname, \ 146 AArch64_reloc_property::RT_##type, \ 147 AArch64_reloc_property::RC_##class, \ 148 is_implemented, \ 149 group_index, \ 150 (RFLAGS), \ 151 AArch64_reloc_property::INST_##inst, \ 152 rvalue_checkup<LB,UB>, \ 153 rvalue_bit_select<BSL,BSH>); \ 154 table_[tidx] = p; \ 155 } \ 156 while (0); 157#include"aarch64-reloc.def" 158#undef ARD 159} 160 161// Return a string describing a relocation code that fails to get a 162// relocation property in get_implemented_static_reloc_property(). 163 164std::string 165AArch64_reloc_property_table::reloc_name_in_error_message(unsigned int code) 166{ 167 int tidx = code_to_array_index(code); 168 const AArch64_reloc_property* arp = this->table_[tidx]; 169 170 if (arp == NULL) 171 { 172 char buffer[100]; 173 sprintf(buffer, _("invalid reloc %u"), code); 174 return std::string(buffer); 175 } 176 177 // gold only implements static relocation codes. 178 AArch64_reloc_property::Reloc_type reloc_type = arp->reloc_type(); 179 gold_assert(reloc_type == AArch64_reloc_property::RT_STATIC 180 || !arp->is_implemented()); 181 182 const char* prefix = NULL; 183 switch (reloc_type) 184 { 185 case AArch64_reloc_property::RT_STATIC: 186 prefix = arp->is_implemented() ? _("reloc ") : _("unimplemented reloc "); 187 break; 188 case AArch64_reloc_property::RT_DYNAMIC: 189 prefix = _("dynamic reloc "); 190 break; 191 default: 192 gold_unreachable(); 193 } 194 return std::string(prefix) + arp->name(); 195} 196 197} 198