aboutsummaryrefslogtreecommitdiff
path: root/gold/aarch64-reloc-property.h
blob: a8431698a1b5569b79968679864c27ffffd30194 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
// aarch64-reloc-property.h -- AArch64 relocation properties   -*- C++ -*-

// Copyright (C) 2014-2015 Free Software Foundation, Inc.
// Written by Han Shen <shenhan@google.com> and Jing Yu <jingyu@google.com>.

// This file is part of gold.

// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
// MA 02110-1301, USA.

#ifndef GOLD_AARCH64_RELOC_PROPERTY_H
#define GOLD_AARCH64_RELOC_PROPERTY_H

#include<vector>
#include<string>

#include"aarch64.h"

namespace gold
{
// The AArch64_reloc_property class is to store information about a particular
// relocation code.

class AArch64_reloc_property
{
 public:
  // Types of relocation codes.
  enum Reloc_type {
    RT_NONE,		// No relocation type.
    RT_STATIC,		// Relocations processed by static linkers.
    RT_DYNAMIC,	// Relocations processed by dynamic linkers.
  };

  // Classes of relocation codes.
  enum Reloc_class {
    RC_NONE,		// No relocation class.
    RC_DATA,		// Data relocation.
    RC_AARCH64,		// Static AArch64 relocations
    RC_CFLOW,		// Control flow
    RC_TLS,		// Thread local storage
    RC_DYNAMIC,		// Dynamic relocation
  };

  // Instructions that are associated with relocations.
  enum Reloc_inst {
    INST_DATA = 0,
    INST_MOVW = 1,	// movz, movk, movn
    INST_LD = 2,	// ld literal
    INST_ADR = 3,	// adr
    INST_ADRP = 4,	// adrp
    INST_ADD = 5,	// add
    INST_LDST = 6,	// ld/st
    INST_TBZNZ = 7,	// tbz/tbnz
    INST_CONDB = 8,	// B.cond
    INST_B = 9,		// b  [25:0]
    INST_CALL = 10,	// bl [25:0]
    INST_NUM = 11,	// total number of entries in the table
  };

  // Types of bases of relative addressing relocation codes.
  // enum Relative_address_base {
  //   RAB_NONE,		// Relocation is not relative addressing
  // };

  typedef bool (*rvalue_checkup_func_p)(int64_t);
  typedef uint64_t (*rvalue_bit_select_func)(uint64_t);

  // Relocation code represented by this.
  unsigned int
  code() const
  { return this->code_; }

  // Name of the relocation code.
  const std::string&
  name() const
  { return this->name_; }

  // Type of relocation code.
  Reloc_type
  reloc_type() const
  { return this->reloc_type_; }

  // Class of relocation code.
  Reloc_class
  reloc_class() const
  { return this->reloc_class_; }

  // Whether this code is implemented in gold.
  bool
  is_implemented() const
  { return this->is_implemented_; }

  // If code is a group relocation code, return the group number, otherwise -1.
  int
  group_index() const
  { return this->group_index_; }

  // Return alignment of relocation.
  size_t
  align() const
  { return this->align_; }

  int
  reference_flags() const
  { return this->reference_flags_; }

  // Instruction associated with this relocation.
  Reloc_inst
  reloc_inst() const
  { return this->reloc_inst_; }

  // Check overflow of x
  bool checkup_x_value(int64_t x) const
  { return this->rvalue_checkup_func_(x); }

  // Return portions of x as is defined in aarch64-reloc.def.
  uint64_t select_x_value(uint64_t x) const
  { return this->rvalue_bit_select_func_(x); }

 protected:
  // These are protected.  We only allow AArch64_reloc_property_table to
  // manage AArch64_reloc_property.
  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);

  friend class AArch64_reloc_property_table;

 private:
  // Copying is not allowed.
  AArch64_reloc_property(const AArch64_reloc_property&);
  AArch64_reloc_property& operator=(const AArch64_reloc_property&);

  // Relocation code.
  const unsigned int code_;
  // Relocation name.
  const std::string name_;
  // Type of relocation.
  Reloc_type reloc_type_;
  // Class of relocation.
  Reloc_class reloc_class_;
  // Group index (0, 1, or 2) if this is a group relocation or -1 otherwise.
  int group_index_;
  // Size of relocation.
  size_t size_;
  // Alignment of relocation.
  size_t align_;
  // Relative address base.
  // Relative_address_base relative_address_base_;
  // Whether this is deprecated.
  bool is_deprecated_ : 1;
  // Whether this is implemented in gold.
  bool is_implemented_ : 1;
  // Whether this checks overflow.
  bool checks_overflow_ : 1;
  const int reference_flags_;
  // Instruction associated with relocation.
  Reloc_inst reloc_inst_;
  rvalue_checkup_func_p rvalue_checkup_func_;
  rvalue_bit_select_func rvalue_bit_select_func_;
};

class AArch64_reloc_property_table
{
 public:
  AArch64_reloc_property_table();

  const AArch64_reloc_property*
  get_reloc_property(unsigned int code) const
  {
    unsigned int idx = code_to_array_index(code);
    return this->table_[idx];
  }

  // Like get_reloc_property but only return non-NULL if relocation code is
  // static and implemented.
  const AArch64_reloc_property*
  get_implemented_static_reloc_property(unsigned int code) const
  {
    unsigned int idx = code_to_array_index(code);
    const AArch64_reloc_property* arp = this->table_[idx];
    return ((arp != NULL
	     && (arp->reloc_type() == AArch64_reloc_property::RT_STATIC)
	     && arp->is_implemented())
	    ? arp
	    : NULL);
  }

  // Return a string describing the relocation code that is not
  // an implemented static reloc code.
  std::string
  reloc_name_in_error_message(unsigned int code);

 private:
  // Copying is not allowed.
  AArch64_reloc_property_table(const AArch64_reloc_property_table&);
  AArch64_reloc_property_table& operator=(const AArch64_reloc_property_table&);

  // Map aarch64 rtypes into range(0,300) as following
  //   256 ~ 313 -> 0 ~ 57
  //   512 ~ 573 -> 128 ~ 189
  int
  code_to_array_index(unsigned int code) const
  {
    if (code == 0) return 0;
    if (!((code >= elfcpp::R_AARCH64_ABS64 &&
	   code <= elfcpp::R_AARCH64_LD64_GOTPAGE_LO15)
	  || (code >= elfcpp::R_AARCH64_TLSGD_ADR_PREL21 &&
	      code <= elfcpp::R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC)))
      {
	gold_error(_("Invalid/unrecognized reloc reloc %d."), code);
      }
    unsigned int rv = -1;
    if (code & (1 << 9))
      rv = 128 + code - 512;  // 512 - 573
    else if (code & (1 << 8))
      rv = code - 256;  // 256 - 313
    gold_assert(rv <= Property_table_size);
    return rv;
  }

  static const unsigned int Property_table_size = 300;
  AArch64_reloc_property* table_[Property_table_size];
};  // End of class AArch64_reloc_property_table

} // End namespace gold.

#endif // !defined(GOLD_AARCH64_RELOC_PROPERTY_H)