1// aarch64-reloc-property.h -- 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#ifndef GOLD_AARCH64_RELOC_PROPERTY_H
24#define GOLD_AARCH64_RELOC_PROPERTY_H
25
26#include<vector>
27#include<string>
28
29#include"aarch64.h"
30
31namespace gold
32{
33// The AArch64_reloc_property class is to store information about a particular
34// relocation code.
35
36class AArch64_reloc_property
37{
38 public:
39  // Types of relocation codes.
40  enum Reloc_type {
41    RT_NONE,		// No relocation type.
42    RT_STATIC,		// Relocations processed by static linkers.
43    RT_DYNAMIC,	// Relocations processed by dynamic linkers.
44  };
45
46  // Classes of relocation codes.
47  enum Reloc_class {
48    RC_NONE,		// No relocation class.
49    RC_DATA,		// Data relocation.
50    RC_AARCH64,		// Static AArch64 relocations
51    RC_CFLOW,		// Control flow
52    RC_TLS,		// Thread local storage
53    RC_DYNAMIC,		// Dynamic relocation
54  };
55
56  // Instructions that are associated with relocations.
57  enum Reloc_inst {
58    INST_DATA = 0,
59    INST_MOVW = 1,	// movz, movk, movn
60    INST_LD = 2,	// ld literal
61    INST_ADR = 3,	// adr
62    INST_ADRP = 4,	// adrp
63    INST_ADD = 5,	// add
64    INST_LDST = 6,	// ld/st
65    INST_TBZNZ = 7,	// tbz/tbnz
66    INST_CONDB = 8,	// B.cond
67    INST_B = 9,		// b  [25:0]
68    INST_CALL = 10,	// bl [25:0]
69    INST_NUM = 11,	// total number of entries in the table
70  };
71
72  // Types of bases of relative addressing relocation codes.
73  // enum Relative_address_base {
74  //   RAB_NONE,		// Relocation is not relative addressing
75  // };
76
77  typedef bool (*rvalue_checkup_func_p)(int64_t);
78  typedef uint64_t (*rvalue_bit_select_func)(uint64_t);
79
80  // Relocation code represented by this.
81  unsigned int
82  code() const
83  { return this->code_; }
84
85  // Name of the relocation code.
86  const std::string&
87  name() const
88  { return this->name_; }
89
90  // Type of relocation code.
91  Reloc_type
92  reloc_type() const
93  { return this->reloc_type_; }
94
95  // Class of relocation code.
96  Reloc_class
97  reloc_class() const
98  { return this->reloc_class_; }
99
100  // Whether this code is implemented in gold.
101  bool
102  is_implemented() const
103  { return this->is_implemented_; }
104
105  // If code is a group relocation code, return the group number, otherwise -1.
106  int
107  group_index() const
108  { return this->group_index_; }
109
110  // Return alignment of relocation.
111  size_t
112  align() const
113  { return this->align_; }
114
115  int
116  reference_flags() const
117  { return this->reference_flags_; }
118
119  // Instruction associated with this relocation.
120  Reloc_inst
121  reloc_inst() const
122  { return this->reloc_inst_; }
123
124  // Check overflow of x
125  bool checkup_x_value(int64_t x) const
126  { return this->rvalue_checkup_func_(x); }
127
128  // Return portions of x as is defined in aarch64-reloc.def.
129  uint64_t select_x_value(uint64_t x) const
130  { return this->rvalue_bit_select_func_(x); }
131
132 protected:
133  // These are protected.  We only allow AArch64_reloc_property_table to
134  // manage AArch64_reloc_property.
135  AArch64_reloc_property(unsigned int code, const char* name, Reloc_type rtype,
136			 Reloc_class rclass,
137			 bool is_implemented,
138			 int group_index,
139			 int reference_flags,
140			 Reloc_inst reloc_inst,
141			 rvalue_checkup_func_p rvalue_checkup_func,
142			 rvalue_bit_select_func rvalue_bit_select);
143
144  friend class AArch64_reloc_property_table;
145
146 private:
147  // Copying is not allowed.
148  AArch64_reloc_property(const AArch64_reloc_property&);
149  AArch64_reloc_property& operator=(const AArch64_reloc_property&);
150
151  // Relocation code.
152  const unsigned int code_;
153  // Relocation name.
154  const std::string name_;
155  // Type of relocation.
156  Reloc_type reloc_type_;
157  // Class of relocation.
158  Reloc_class reloc_class_;
159  // Group index (0, 1, or 2) if this is a group relocation or -1 otherwise.
160  int group_index_;
161  // Size of relocation.
162  size_t size_;
163  // Alignment of relocation.
164  size_t align_;
165  // Relative address base.
166  // Relative_address_base relative_address_base_;
167  // Whether this is deprecated.
168  bool is_deprecated_ : 1;
169  // Whether this is implemented in gold.
170  bool is_implemented_ : 1;
171  // Whether this checks overflow.
172  bool checks_overflow_ : 1;
173  const int reference_flags_;
174  // Instruction associated with relocation.
175  Reloc_inst reloc_inst_;
176  rvalue_checkup_func_p rvalue_checkup_func_;
177  rvalue_bit_select_func rvalue_bit_select_func_;
178};
179
180class AArch64_reloc_property_table
181{
182 public:
183  AArch64_reloc_property_table();
184
185  const AArch64_reloc_property*
186  get_reloc_property(unsigned int code) const
187  {
188    unsigned int idx = code_to_array_index(code);
189    return this->table_[idx];
190  }
191
192  // Like get_reloc_property but only return non-NULL if relocation code is
193  // static and implemented.
194  const AArch64_reloc_property*
195  get_implemented_static_reloc_property(unsigned int code) const
196  {
197    unsigned int idx = code_to_array_index(code);
198    const AArch64_reloc_property* arp = this->table_[idx];
199    return ((arp != NULL
200	     && (arp->reloc_type() == AArch64_reloc_property::RT_STATIC)
201	     && arp->is_implemented())
202	    ? arp
203	    : NULL);
204  }
205
206  // Return a string describing the relocation code that is not
207  // an implemented static reloc code.
208  std::string
209  reloc_name_in_error_message(unsigned int code);
210
211 private:
212  // Copying is not allowed.
213  AArch64_reloc_property_table(const AArch64_reloc_property_table&);
214  AArch64_reloc_property_table& operator=(const AArch64_reloc_property_table&);
215
216  // Map aarch64 rtypes into range(0,300) as following
217  //   256 ~ 313 -> 0 ~ 57
218  //   512 ~ 573 -> 128 ~ 189
219  int
220  code_to_array_index(unsigned int code) const
221  {
222    if (code == 0) return 0;
223    if (!((code >= elfcpp::R_AARCH64_ABS64 &&
224	   code <= elfcpp::R_AARCH64_LD64_GOTPAGE_LO15)
225	  || (code >= elfcpp::R_AARCH64_TLSGD_ADR_PREL21 &&
226	      code <= elfcpp::R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC)))
227      {
228	gold_error(_("Invalid/unrecognized reloc reloc %d."), code);
229      }
230    unsigned int rv = -1;
231    if (code & (1 << 9))
232      rv = 128 + code - 512;  // 512 - 573
233    else if (code & (1 << 8))
234      rv = code - 256;  // 256 - 313
235    gold_assert(rv <= Property_table_size);
236    return rv;
237  }
238
239  static const unsigned int Property_table_size = 300;
240  AArch64_reloc_property* table_[Property_table_size];
241};  // End of class AArch64_reloc_property_table
242
243} // End namespace gold.
244
245#endif // !defined(GOLD_AARCH64_RELOC_PROPERTY_H)
246