Home | History | Annotate | Download | only in gold
      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