Commit | Line | Data |
---|---|---|
9363c7c3 JY |
1 | // aarch64-reloc-property.h -- AArch64 relocation properties -*- C++ -*- |
2 | ||
82704155 | 3 | // Copyright (C) 2014-2019 Free Software Foundation, Inc. |
9363c7c3 JY |
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 | ||
31 | namespace gold | |
32 | { | |
33 | // The AArch64_reloc_property class is to store information about a particular | |
34 | // relocation code. | |
35 | ||
36 | class 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 | ||
180 | class 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) |