1*1424dfb3Schristos // aarch64-reloc-property.cc -- AArch64 relocation properties   -*- C++ -*-
2*1424dfb3Schristos 
3*1424dfb3Schristos // Copyright (C) 2014-2020 Free Software Foundation, Inc.
4*1424dfb3Schristos // Written by Han Shen <shenhan@google.com> and Jing Yu <jingyu@google.com>.
5*1424dfb3Schristos 
6*1424dfb3Schristos // This file is part of gold.
7*1424dfb3Schristos 
8*1424dfb3Schristos // This program is free software; you can redistribute it and/or modify
9*1424dfb3Schristos // it under the terms of the GNU General Public License as published by
10*1424dfb3Schristos // the Free Software Foundation; either version 3 of the License, or
11*1424dfb3Schristos // (at your option) any later version.
12*1424dfb3Schristos 
13*1424dfb3Schristos // This program is distributed in the hope that it will be useful,
14*1424dfb3Schristos // but WITHOUT ANY WARRANTY; without even the implied warranty of
15*1424dfb3Schristos // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*1424dfb3Schristos // GNU General Public License for more details.
17*1424dfb3Schristos 
18*1424dfb3Schristos // You should have received a copy of the GNU General Public License
19*1424dfb3Schristos // along with this program; if not, write to the Free Software
20*1424dfb3Schristos // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21*1424dfb3Schristos // MA 02110-1301, USA.
22*1424dfb3Schristos 
23*1424dfb3Schristos #include "gold.h"
24*1424dfb3Schristos 
25*1424dfb3Schristos #include "aarch64-reloc-property.h"
26*1424dfb3Schristos #include "aarch64.h"
27*1424dfb3Schristos 
28*1424dfb3Schristos #include "symtab.h"
29*1424dfb3Schristos 
30*1424dfb3Schristos #include<stdio.h>
31*1424dfb3Schristos 
32*1424dfb3Schristos namespace gold
33*1424dfb3Schristos {
34*1424dfb3Schristos 
35*1424dfb3Schristos template<int L, int U>
36*1424dfb3Schristos bool
rvalue_checkup(int64_t x)37*1424dfb3Schristos rvalue_checkup(int64_t x)
38*1424dfb3Schristos {
39*1424dfb3Schristos   // We save the extra_alignment_requirement bits on [31:16] of U.
40*1424dfb3Schristos   // "extra_alignment_requirement" could be 0, 1, 3, 7 and 15.
41*1424dfb3Schristos   unsigned short extra_alignment_requirement = (U & 0xFFFF0000) >> 16;
42*1424dfb3Schristos   // [15:0] of U indicates the upper bound check.
43*1424dfb3Schristos   int64_t u = U & 0x0000FFFF;
44*1424dfb3Schristos   if (u == 0)
45*1424dfb3Schristos     {
46*1424dfb3Schristos       // No requirement to check overflow.
47*1424dfb3Schristos       gold_assert(L == 0);
48*1424dfb3Schristos       return (x & extra_alignment_requirement) == 0;
49*1424dfb3Schristos     }
50*1424dfb3Schristos 
51*1424dfb3Schristos   // Check both overflow and alignment if needed.
52*1424dfb3Schristos   int64_t low_bound = -(L == 0 ? 0 : ((int64_t)1 << L));
53*1424dfb3Schristos   int64_t up_bound = ((int64_t)1 << u);
54*1424dfb3Schristos   return ((low_bound <= x && x < up_bound)
55*1424dfb3Schristos 	  && ((x & extra_alignment_requirement) == 0));
56*1424dfb3Schristos }
57*1424dfb3Schristos 
58*1424dfb3Schristos template<>
59*1424dfb3Schristos bool
rvalue_checkup(int64_t)60*1424dfb3Schristos rvalue_checkup<0, 0>(int64_t) { return true; }
61*1424dfb3Schristos 
62*1424dfb3Schristos namespace
63*1424dfb3Schristos {
64*1424dfb3Schristos 
65*1424dfb3Schristos template<int L, int U>
66*1424dfb3Schristos class Rvalue_bit_select_impl
67*1424dfb3Schristos {
68*1424dfb3Schristos public:
69*1424dfb3Schristos   static uint64_t
calc(uint64_t x)70*1424dfb3Schristos   calc(uint64_t x)
71*1424dfb3Schristos   {
72*1424dfb3Schristos     return (x & ((1ULL << (U+1)) - 1)) >> L;
73*1424dfb3Schristos   }
74*1424dfb3Schristos };
75*1424dfb3Schristos 
76*1424dfb3Schristos template<int L>
77*1424dfb3Schristos class Rvalue_bit_select_impl<L, 63>
78*1424dfb3Schristos {
79*1424dfb3Schristos public:
80*1424dfb3Schristos   static uint64_t
calc(uint64_t x)81*1424dfb3Schristos   calc(uint64_t x)
82*1424dfb3Schristos   {
83*1424dfb3Schristos     return x >> L;
84*1424dfb3Schristos   }
85*1424dfb3Schristos };
86*1424dfb3Schristos 
87*1424dfb3Schristos // By our convention, L=U=0 means that the whole value should be retrieved.
88*1424dfb3Schristos template<>
89*1424dfb3Schristos class Rvalue_bit_select_impl<0, 0>
90*1424dfb3Schristos {
91*1424dfb3Schristos public:
92*1424dfb3Schristos   static uint64_t
calc(uint64_t x)93*1424dfb3Schristos   calc(uint64_t x)
94*1424dfb3Schristos   {
95*1424dfb3Schristos     return x;
96*1424dfb3Schristos   }
97*1424dfb3Schristos };
98*1424dfb3Schristos 
99*1424dfb3Schristos } // End anonymous namespace.
100*1424dfb3Schristos 
101*1424dfb3Schristos template<int L, int U>
102*1424dfb3Schristos uint64_t
rvalue_bit_select(uint64_t x)103*1424dfb3Schristos rvalue_bit_select(uint64_t x)
104*1424dfb3Schristos {
105*1424dfb3Schristos   return Rvalue_bit_select_impl<L, U>::calc(x);
106*1424dfb3Schristos }
107*1424dfb3Schristos 
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)108*1424dfb3Schristos AArch64_reloc_property::AArch64_reloc_property(
109*1424dfb3Schristos     unsigned int code,
110*1424dfb3Schristos     const char* name,
111*1424dfb3Schristos     Reloc_type rtype,
112*1424dfb3Schristos     Reloc_class rclass,
113*1424dfb3Schristos     bool is_implemented,
114*1424dfb3Schristos     int group_index,
115*1424dfb3Schristos     int reference_flags,
116*1424dfb3Schristos     Reloc_inst reloc_inst,
117*1424dfb3Schristos     rvalue_checkup_func_p rvalue_checkup_func,
118*1424dfb3Schristos     rvalue_bit_select_func rvalue_bit_select)
119*1424dfb3Schristos   : code_(code), name_(name), reloc_type_(rtype), reloc_class_(rclass),
120*1424dfb3Schristos     group_index_(group_index),
121*1424dfb3Schristos     is_implemented_(is_implemented),
122*1424dfb3Schristos     reference_flags_(reference_flags),
123*1424dfb3Schristos     reloc_inst_(reloc_inst),
124*1424dfb3Schristos     rvalue_checkup_func_(rvalue_checkup_func),
125*1424dfb3Schristos     rvalue_bit_select_func_(rvalue_bit_select)
126*1424dfb3Schristos {}
127*1424dfb3Schristos 
AArch64_reloc_property_table()128*1424dfb3Schristos AArch64_reloc_property_table::AArch64_reloc_property_table()
129*1424dfb3Schristos {
130*1424dfb3Schristos   const bool Y(true), N(false);
131*1424dfb3Schristos   for (unsigned int i = 0; i < Property_table_size; ++i)
132*1424dfb3Schristos     table_[i] = NULL;
133*1424dfb3Schristos 
134*1424dfb3Schristos #define RL_CHECK_ALIGN2   (1  << 16)
135*1424dfb3Schristos #define RL_CHECK_ALIGN4   (3  << 16)
136*1424dfb3Schristos #define RL_CHECK_ALIGN8   (7  << 16)
137*1424dfb3Schristos #define RL_CHECK_ALIGN16  (15 << 16)
138*1424dfb3Schristos 
139*1424dfb3Schristos #undef ARD
140*1424dfb3Schristos #define ARD(rname, type, class, is_implemented, group_index, LB, UB, BSL, BSH, RFLAGS, inst) \
141*1424dfb3Schristos     do \
142*1424dfb3Schristos       { \
143*1424dfb3Schristos 	int tidx = code_to_array_index(elfcpp::R_AARCH64_##rname); \
144*1424dfb3Schristos 	AArch64_reloc_property * p = new AArch64_reloc_property( \
145*1424dfb3Schristos 	  elfcpp::R_AARCH64_##rname, "R_AARCH64_" #rname, \
146*1424dfb3Schristos 	  AArch64_reloc_property::RT_##type, \
147*1424dfb3Schristos 	  AArch64_reloc_property::RC_##class, \
148*1424dfb3Schristos 	  is_implemented, \
149*1424dfb3Schristos 	  group_index, \
150*1424dfb3Schristos 	  (RFLAGS), \
151*1424dfb3Schristos 	  AArch64_reloc_property::INST_##inst,	\
152*1424dfb3Schristos 	  rvalue_checkup<LB,UB>,    \
153*1424dfb3Schristos 	  rvalue_bit_select<BSL,BSH>);		\
154*1424dfb3Schristos 	table_[tidx] = p; \
155*1424dfb3Schristos       } \
156*1424dfb3Schristos     while (0);
157*1424dfb3Schristos #include"aarch64-reloc.def"
158*1424dfb3Schristos #undef ARD
159*1424dfb3Schristos }
160*1424dfb3Schristos 
161*1424dfb3Schristos // Return a string describing a relocation code that fails to get a
162*1424dfb3Schristos // relocation property in get_implemented_static_reloc_property().
163*1424dfb3Schristos 
164*1424dfb3Schristos std::string
reloc_name_in_error_message(unsigned int code)165*1424dfb3Schristos AArch64_reloc_property_table::reloc_name_in_error_message(unsigned int code)
166*1424dfb3Schristos {
167*1424dfb3Schristos   int tidx = code_to_array_index(code);
168*1424dfb3Schristos   const AArch64_reloc_property* arp = this->table_[tidx];
169*1424dfb3Schristos 
170*1424dfb3Schristos   if (arp == NULL)
171*1424dfb3Schristos     {
172*1424dfb3Schristos       char buffer[100];
173*1424dfb3Schristos       sprintf(buffer, _("invalid reloc %u"), code);
174*1424dfb3Schristos       return std::string(buffer);
175*1424dfb3Schristos     }
176*1424dfb3Schristos 
177*1424dfb3Schristos   // gold only implements static relocation codes.
178*1424dfb3Schristos   AArch64_reloc_property::Reloc_type reloc_type = arp->reloc_type();
179*1424dfb3Schristos   gold_assert(reloc_type == AArch64_reloc_property::RT_STATIC
180*1424dfb3Schristos 	      || !arp->is_implemented());
181*1424dfb3Schristos 
182*1424dfb3Schristos   const char* prefix = NULL;
183*1424dfb3Schristos   switch (reloc_type)
184*1424dfb3Schristos     {
185*1424dfb3Schristos     case AArch64_reloc_property::RT_STATIC:
186*1424dfb3Schristos       prefix = arp->is_implemented() ? _("reloc ") : _("unimplemented reloc ");
187*1424dfb3Schristos       break;
188*1424dfb3Schristos     case AArch64_reloc_property::RT_DYNAMIC:
189*1424dfb3Schristos       prefix = _("dynamic reloc ");
190*1424dfb3Schristos       break;
191*1424dfb3Schristos     default:
192*1424dfb3Schristos       gold_unreachable();
193*1424dfb3Schristos     }
194*1424dfb3Schristos   return std::string(prefix) + arp->name();
195*1424dfb3Schristos }
196*1424dfb3Schristos 
197*1424dfb3Schristos }
198