gdb/gdbserver
[deliverable/binutils-gdb.git] / bfd / elfxx-ia64.c
1 /* IA-64 support for 64-bit ELF
2 Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
3 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
4 Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
5
6 This file is part of BFD, the Binary File Descriptor library.
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 "sysdep.h"
24 #include "bfd.h"
25 #include "libbfd.h"
26 #include "elf-bfd.h"
27 #include "opcode/ia64.h"
28 #include "elf/ia64.h"
29 #include "objalloc.h"
30 #include "hashtab.h"
31 #include "bfd_stdint.h"
32 #include "elfxx-ia64.h"
33
34 /* THE RULES for all the stuff the linker creates --
35
36 GOT Entries created in response to LTOFF or LTOFF_FPTR
37 relocations. Dynamic relocs created for dynamic
38 symbols in an application; REL relocs for locals
39 in a shared library.
40
41 FPTR The canonical function descriptor. Created for local
42 symbols in applications. Descriptors for dynamic symbols
43 and local symbols in shared libraries are created by
44 ld.so. Thus there are no dynamic relocs against these
45 objects. The FPTR relocs for such _are_ passed through
46 to the dynamic relocation tables.
47
48 FULL_PLT Created for a PCREL21B relocation against a dynamic symbol.
49 Requires the creation of a PLTOFF entry. This does not
50 require any dynamic relocations.
51
52 PLTOFF Created by PLTOFF relocations. For local symbols, this
53 is an alternate function descriptor, and in shared libraries
54 requires two REL relocations. Note that this cannot be
55 transformed into an FPTR relocation, since it must be in
56 range of the GP. For dynamic symbols, this is a function
57 descriptor for a MIN_PLT entry, and requires one IPLT reloc.
58
59 MIN_PLT Created by PLTOFF entries against dynamic symbols. This
60 does not require dynamic relocations. */
61
62 /* ia64-specific relocation. */
63
64 #define NELEMS(a) ((int) (sizeof (a) / sizeof ((a)[0])))
65
66 /* Perform a relocation. Not much to do here as all the hard work is
67 done in elfNN_ia64_final_link_relocate. */
68 static bfd_reloc_status_type
69 ia64_elf_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc,
70 asymbol *sym ATTRIBUTE_UNUSED,
71 PTR data ATTRIBUTE_UNUSED, asection *input_section,
72 bfd *output_bfd, char **error_message)
73 {
74 if (output_bfd)
75 {
76 reloc->address += input_section->output_offset;
77 return bfd_reloc_ok;
78 }
79
80 if (input_section->flags & SEC_DEBUGGING)
81 return bfd_reloc_continue;
82
83 *error_message = "Unsupported call to ia64_elf_reloc";
84 return bfd_reloc_notsupported;
85 }
86
87 #define IA64_HOWTO(TYPE, NAME, SIZE, PCREL, IN) \
88 HOWTO (TYPE, 0, SIZE, 0, PCREL, 0, complain_overflow_signed, \
89 ia64_elf_reloc, NAME, FALSE, 0, -1, IN)
90
91 /* This table has to be sorted according to increasing number of the
92 TYPE field. */
93 static reloc_howto_type ia64_howto_table[] =
94 {
95 IA64_HOWTO (R_IA64_NONE, "NONE", 0, FALSE, TRUE),
96
97 IA64_HOWTO (R_IA64_IMM14, "IMM14", 0, FALSE, TRUE),
98 IA64_HOWTO (R_IA64_IMM22, "IMM22", 0, FALSE, TRUE),
99 IA64_HOWTO (R_IA64_IMM64, "IMM64", 0, FALSE, TRUE),
100 IA64_HOWTO (R_IA64_DIR32MSB, "DIR32MSB", 2, FALSE, TRUE),
101 IA64_HOWTO (R_IA64_DIR32LSB, "DIR32LSB", 2, FALSE, TRUE),
102 IA64_HOWTO (R_IA64_DIR64MSB, "DIR64MSB", 4, FALSE, TRUE),
103 IA64_HOWTO (R_IA64_DIR64LSB, "DIR64LSB", 4, FALSE, TRUE),
104
105 IA64_HOWTO (R_IA64_GPREL22, "GPREL22", 0, FALSE, TRUE),
106 IA64_HOWTO (R_IA64_GPREL64I, "GPREL64I", 0, FALSE, TRUE),
107 IA64_HOWTO (R_IA64_GPREL32MSB, "GPREL32MSB", 2, FALSE, TRUE),
108 IA64_HOWTO (R_IA64_GPREL32LSB, "GPREL32LSB", 2, FALSE, TRUE),
109 IA64_HOWTO (R_IA64_GPREL64MSB, "GPREL64MSB", 4, FALSE, TRUE),
110 IA64_HOWTO (R_IA64_GPREL64LSB, "GPREL64LSB", 4, FALSE, TRUE),
111
112 IA64_HOWTO (R_IA64_LTOFF22, "LTOFF22", 0, FALSE, TRUE),
113 IA64_HOWTO (R_IA64_LTOFF64I, "LTOFF64I", 0, FALSE, TRUE),
114
115 IA64_HOWTO (R_IA64_PLTOFF22, "PLTOFF22", 0, FALSE, TRUE),
116 IA64_HOWTO (R_IA64_PLTOFF64I, "PLTOFF64I", 0, FALSE, TRUE),
117 IA64_HOWTO (R_IA64_PLTOFF64MSB, "PLTOFF64MSB", 4, FALSE, TRUE),
118 IA64_HOWTO (R_IA64_PLTOFF64LSB, "PLTOFF64LSB", 4, FALSE, TRUE),
119
120 IA64_HOWTO (R_IA64_FPTR64I, "FPTR64I", 0, FALSE, TRUE),
121 IA64_HOWTO (R_IA64_FPTR32MSB, "FPTR32MSB", 2, FALSE, TRUE),
122 IA64_HOWTO (R_IA64_FPTR32LSB, "FPTR32LSB", 2, FALSE, TRUE),
123 IA64_HOWTO (R_IA64_FPTR64MSB, "FPTR64MSB", 4, FALSE, TRUE),
124 IA64_HOWTO (R_IA64_FPTR64LSB, "FPTR64LSB", 4, FALSE, TRUE),
125
126 IA64_HOWTO (R_IA64_PCREL60B, "PCREL60B", 0, TRUE, TRUE),
127 IA64_HOWTO (R_IA64_PCREL21B, "PCREL21B", 0, TRUE, TRUE),
128 IA64_HOWTO (R_IA64_PCREL21M, "PCREL21M", 0, TRUE, TRUE),
129 IA64_HOWTO (R_IA64_PCREL21F, "PCREL21F", 0, TRUE, TRUE),
130 IA64_HOWTO (R_IA64_PCREL32MSB, "PCREL32MSB", 2, TRUE, TRUE),
131 IA64_HOWTO (R_IA64_PCREL32LSB, "PCREL32LSB", 2, TRUE, TRUE),
132 IA64_HOWTO (R_IA64_PCREL64MSB, "PCREL64MSB", 4, TRUE, TRUE),
133 IA64_HOWTO (R_IA64_PCREL64LSB, "PCREL64LSB", 4, TRUE, TRUE),
134
135 IA64_HOWTO (R_IA64_LTOFF_FPTR22, "LTOFF_FPTR22", 0, FALSE, TRUE),
136 IA64_HOWTO (R_IA64_LTOFF_FPTR64I, "LTOFF_FPTR64I", 0, FALSE, TRUE),
137 IA64_HOWTO (R_IA64_LTOFF_FPTR32MSB, "LTOFF_FPTR32MSB", 2, FALSE, TRUE),
138 IA64_HOWTO (R_IA64_LTOFF_FPTR32LSB, "LTOFF_FPTR32LSB", 2, FALSE, TRUE),
139 IA64_HOWTO (R_IA64_LTOFF_FPTR64MSB, "LTOFF_FPTR64MSB", 4, FALSE, TRUE),
140 IA64_HOWTO (R_IA64_LTOFF_FPTR64LSB, "LTOFF_FPTR64LSB", 4, FALSE, TRUE),
141
142 IA64_HOWTO (R_IA64_SEGREL32MSB, "SEGREL32MSB", 2, FALSE, TRUE),
143 IA64_HOWTO (R_IA64_SEGREL32LSB, "SEGREL32LSB", 2, FALSE, TRUE),
144 IA64_HOWTO (R_IA64_SEGREL64MSB, "SEGREL64MSB", 4, FALSE, TRUE),
145 IA64_HOWTO (R_IA64_SEGREL64LSB, "SEGREL64LSB", 4, FALSE, TRUE),
146
147 IA64_HOWTO (R_IA64_SECREL32MSB, "SECREL32MSB", 2, FALSE, TRUE),
148 IA64_HOWTO (R_IA64_SECREL32LSB, "SECREL32LSB", 2, FALSE, TRUE),
149 IA64_HOWTO (R_IA64_SECREL64MSB, "SECREL64MSB", 4, FALSE, TRUE),
150 IA64_HOWTO (R_IA64_SECREL64LSB, "SECREL64LSB", 4, FALSE, TRUE),
151
152 IA64_HOWTO (R_IA64_REL32MSB, "REL32MSB", 2, FALSE, TRUE),
153 IA64_HOWTO (R_IA64_REL32LSB, "REL32LSB", 2, FALSE, TRUE),
154 IA64_HOWTO (R_IA64_REL64MSB, "REL64MSB", 4, FALSE, TRUE),
155 IA64_HOWTO (R_IA64_REL64LSB, "REL64LSB", 4, FALSE, TRUE),
156
157 IA64_HOWTO (R_IA64_LTV32MSB, "LTV32MSB", 2, FALSE, TRUE),
158 IA64_HOWTO (R_IA64_LTV32LSB, "LTV32LSB", 2, FALSE, TRUE),
159 IA64_HOWTO (R_IA64_LTV64MSB, "LTV64MSB", 4, FALSE, TRUE),
160 IA64_HOWTO (R_IA64_LTV64LSB, "LTV64LSB", 4, FALSE, TRUE),
161
162 IA64_HOWTO (R_IA64_PCREL21BI, "PCREL21BI", 0, TRUE, TRUE),
163 IA64_HOWTO (R_IA64_PCREL22, "PCREL22", 0, TRUE, TRUE),
164 IA64_HOWTO (R_IA64_PCREL64I, "PCREL64I", 0, TRUE, TRUE),
165
166 IA64_HOWTO (R_IA64_IPLTMSB, "IPLTMSB", 4, FALSE, TRUE),
167 IA64_HOWTO (R_IA64_IPLTLSB, "IPLTLSB", 4, FALSE, TRUE),
168 IA64_HOWTO (R_IA64_COPY, "COPY", 4, FALSE, TRUE),
169 IA64_HOWTO (R_IA64_LTOFF22X, "LTOFF22X", 0, FALSE, TRUE),
170 IA64_HOWTO (R_IA64_LDXMOV, "LDXMOV", 0, FALSE, TRUE),
171
172 IA64_HOWTO (R_IA64_TPREL14, "TPREL14", 0, FALSE, FALSE),
173 IA64_HOWTO (R_IA64_TPREL22, "TPREL22", 0, FALSE, FALSE),
174 IA64_HOWTO (R_IA64_TPREL64I, "TPREL64I", 0, FALSE, FALSE),
175 IA64_HOWTO (R_IA64_TPREL64MSB, "TPREL64MSB", 4, FALSE, FALSE),
176 IA64_HOWTO (R_IA64_TPREL64LSB, "TPREL64LSB", 4, FALSE, FALSE),
177 IA64_HOWTO (R_IA64_LTOFF_TPREL22, "LTOFF_TPREL22", 0, FALSE, FALSE),
178
179 IA64_HOWTO (R_IA64_DTPMOD64MSB, "DTPMOD64MSB", 4, FALSE, FALSE),
180 IA64_HOWTO (R_IA64_DTPMOD64LSB, "DTPMOD64LSB", 4, FALSE, FALSE),
181 IA64_HOWTO (R_IA64_LTOFF_DTPMOD22, "LTOFF_DTPMOD22", 0, FALSE, FALSE),
182
183 IA64_HOWTO (R_IA64_DTPREL14, "DTPREL14", 0, FALSE, FALSE),
184 IA64_HOWTO (R_IA64_DTPREL22, "DTPREL22", 0, FALSE, FALSE),
185 IA64_HOWTO (R_IA64_DTPREL64I, "DTPREL64I", 0, FALSE, FALSE),
186 IA64_HOWTO (R_IA64_DTPREL32MSB, "DTPREL32MSB", 2, FALSE, FALSE),
187 IA64_HOWTO (R_IA64_DTPREL32LSB, "DTPREL32LSB", 2, FALSE, FALSE),
188 IA64_HOWTO (R_IA64_DTPREL64MSB, "DTPREL64MSB", 4, FALSE, FALSE),
189 IA64_HOWTO (R_IA64_DTPREL64LSB, "DTPREL64LSB", 4, FALSE, FALSE),
190 IA64_HOWTO (R_IA64_LTOFF_DTPREL22, "LTOFF_DTPREL22", 0, FALSE, FALSE),
191 };
192
193 static unsigned char elf_code_to_howto_index[R_IA64_MAX_RELOC_CODE + 1];
194
195 /* Given a BFD reloc type, return the matching HOWTO structure. */
196
197 reloc_howto_type *
198 ia64_elf_lookup_howto (unsigned int rtype)
199 {
200 static int inited = 0;
201 int i;
202
203 if (!inited)
204 {
205 inited = 1;
206
207 memset (elf_code_to_howto_index, 0xff, sizeof (elf_code_to_howto_index));
208 for (i = 0; i < NELEMS (ia64_howto_table); ++i)
209 elf_code_to_howto_index[ia64_howto_table[i].type] = i;
210 }
211
212 if (rtype > R_IA64_MAX_RELOC_CODE)
213 return 0;
214 i = elf_code_to_howto_index[rtype];
215 if (i >= NELEMS (ia64_howto_table))
216 return 0;
217 return ia64_howto_table + i;
218 }
219
220 reloc_howto_type*
221 ia64_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
222 bfd_reloc_code_real_type bfd_code)
223 {
224 unsigned int rtype;
225
226 switch (bfd_code)
227 {
228 case BFD_RELOC_NONE: rtype = R_IA64_NONE; break;
229
230 case BFD_RELOC_IA64_IMM14: rtype = R_IA64_IMM14; break;
231 case BFD_RELOC_IA64_IMM22: rtype = R_IA64_IMM22; break;
232 case BFD_RELOC_IA64_IMM64: rtype = R_IA64_IMM64; break;
233
234 case BFD_RELOC_IA64_DIR32MSB: rtype = R_IA64_DIR32MSB; break;
235 case BFD_RELOC_IA64_DIR32LSB: rtype = R_IA64_DIR32LSB; break;
236 case BFD_RELOC_IA64_DIR64MSB: rtype = R_IA64_DIR64MSB; break;
237 case BFD_RELOC_IA64_DIR64LSB: rtype = R_IA64_DIR64LSB; break;
238
239 case BFD_RELOC_IA64_GPREL22: rtype = R_IA64_GPREL22; break;
240 case BFD_RELOC_IA64_GPREL64I: rtype = R_IA64_GPREL64I; break;
241 case BFD_RELOC_IA64_GPREL32MSB: rtype = R_IA64_GPREL32MSB; break;
242 case BFD_RELOC_IA64_GPREL32LSB: rtype = R_IA64_GPREL32LSB; break;
243 case BFD_RELOC_IA64_GPREL64MSB: rtype = R_IA64_GPREL64MSB; break;
244 case BFD_RELOC_IA64_GPREL64LSB: rtype = R_IA64_GPREL64LSB; break;
245
246 case BFD_RELOC_IA64_LTOFF22: rtype = R_IA64_LTOFF22; break;
247 case BFD_RELOC_IA64_LTOFF64I: rtype = R_IA64_LTOFF64I; break;
248
249 case BFD_RELOC_IA64_PLTOFF22: rtype = R_IA64_PLTOFF22; break;
250 case BFD_RELOC_IA64_PLTOFF64I: rtype = R_IA64_PLTOFF64I; break;
251 case BFD_RELOC_IA64_PLTOFF64MSB: rtype = R_IA64_PLTOFF64MSB; break;
252 case BFD_RELOC_IA64_PLTOFF64LSB: rtype = R_IA64_PLTOFF64LSB; break;
253 case BFD_RELOC_IA64_FPTR64I: rtype = R_IA64_FPTR64I; break;
254 case BFD_RELOC_IA64_FPTR32MSB: rtype = R_IA64_FPTR32MSB; break;
255 case BFD_RELOC_IA64_FPTR32LSB: rtype = R_IA64_FPTR32LSB; break;
256 case BFD_RELOC_IA64_FPTR64MSB: rtype = R_IA64_FPTR64MSB; break;
257 case BFD_RELOC_IA64_FPTR64LSB: rtype = R_IA64_FPTR64LSB; break;
258
259 case BFD_RELOC_IA64_PCREL21B: rtype = R_IA64_PCREL21B; break;
260 case BFD_RELOC_IA64_PCREL21BI: rtype = R_IA64_PCREL21BI; break;
261 case BFD_RELOC_IA64_PCREL21M: rtype = R_IA64_PCREL21M; break;
262 case BFD_RELOC_IA64_PCREL21F: rtype = R_IA64_PCREL21F; break;
263 case BFD_RELOC_IA64_PCREL22: rtype = R_IA64_PCREL22; break;
264 case BFD_RELOC_IA64_PCREL60B: rtype = R_IA64_PCREL60B; break;
265 case BFD_RELOC_IA64_PCREL64I: rtype = R_IA64_PCREL64I; break;
266 case BFD_RELOC_IA64_PCREL32MSB: rtype = R_IA64_PCREL32MSB; break;
267 case BFD_RELOC_IA64_PCREL32LSB: rtype = R_IA64_PCREL32LSB; break;
268 case BFD_RELOC_IA64_PCREL64MSB: rtype = R_IA64_PCREL64MSB; break;
269 case BFD_RELOC_IA64_PCREL64LSB: rtype = R_IA64_PCREL64LSB; break;
270
271 case BFD_RELOC_IA64_LTOFF_FPTR22: rtype = R_IA64_LTOFF_FPTR22; break;
272 case BFD_RELOC_IA64_LTOFF_FPTR64I: rtype = R_IA64_LTOFF_FPTR64I; break;
273 case BFD_RELOC_IA64_LTOFF_FPTR32MSB: rtype = R_IA64_LTOFF_FPTR32MSB; break;
274 case BFD_RELOC_IA64_LTOFF_FPTR32LSB: rtype = R_IA64_LTOFF_FPTR32LSB; break;
275 case BFD_RELOC_IA64_LTOFF_FPTR64MSB: rtype = R_IA64_LTOFF_FPTR64MSB; break;
276 case BFD_RELOC_IA64_LTOFF_FPTR64LSB: rtype = R_IA64_LTOFF_FPTR64LSB; break;
277
278 case BFD_RELOC_IA64_SEGREL32MSB: rtype = R_IA64_SEGREL32MSB; break;
279 case BFD_RELOC_IA64_SEGREL32LSB: rtype = R_IA64_SEGREL32LSB; break;
280 case BFD_RELOC_IA64_SEGREL64MSB: rtype = R_IA64_SEGREL64MSB; break;
281 case BFD_RELOC_IA64_SEGREL64LSB: rtype = R_IA64_SEGREL64LSB; break;
282
283 case BFD_RELOC_IA64_SECREL32MSB: rtype = R_IA64_SECREL32MSB; break;
284 case BFD_RELOC_IA64_SECREL32LSB: rtype = R_IA64_SECREL32LSB; break;
285 case BFD_RELOC_IA64_SECREL64MSB: rtype = R_IA64_SECREL64MSB; break;
286 case BFD_RELOC_IA64_SECREL64LSB: rtype = R_IA64_SECREL64LSB; break;
287
288 case BFD_RELOC_IA64_REL32MSB: rtype = R_IA64_REL32MSB; break;
289 case BFD_RELOC_IA64_REL32LSB: rtype = R_IA64_REL32LSB; break;
290 case BFD_RELOC_IA64_REL64MSB: rtype = R_IA64_REL64MSB; break;
291 case BFD_RELOC_IA64_REL64LSB: rtype = R_IA64_REL64LSB; break;
292
293 case BFD_RELOC_IA64_LTV32MSB: rtype = R_IA64_LTV32MSB; break;
294 case BFD_RELOC_IA64_LTV32LSB: rtype = R_IA64_LTV32LSB; break;
295 case BFD_RELOC_IA64_LTV64MSB: rtype = R_IA64_LTV64MSB; break;
296 case BFD_RELOC_IA64_LTV64LSB: rtype = R_IA64_LTV64LSB; break;
297
298 case BFD_RELOC_IA64_IPLTMSB: rtype = R_IA64_IPLTMSB; break;
299 case BFD_RELOC_IA64_IPLTLSB: rtype = R_IA64_IPLTLSB; break;
300 case BFD_RELOC_IA64_COPY: rtype = R_IA64_COPY; break;
301 case BFD_RELOC_IA64_LTOFF22X: rtype = R_IA64_LTOFF22X; break;
302 case BFD_RELOC_IA64_LDXMOV: rtype = R_IA64_LDXMOV; break;
303
304 case BFD_RELOC_IA64_TPREL14: rtype = R_IA64_TPREL14; break;
305 case BFD_RELOC_IA64_TPREL22: rtype = R_IA64_TPREL22; break;
306 case BFD_RELOC_IA64_TPREL64I: rtype = R_IA64_TPREL64I; break;
307 case BFD_RELOC_IA64_TPREL64MSB: rtype = R_IA64_TPREL64MSB; break;
308 case BFD_RELOC_IA64_TPREL64LSB: rtype = R_IA64_TPREL64LSB; break;
309 case BFD_RELOC_IA64_LTOFF_TPREL22: rtype = R_IA64_LTOFF_TPREL22; break;
310
311 case BFD_RELOC_IA64_DTPMOD64MSB: rtype = R_IA64_DTPMOD64MSB; break;
312 case BFD_RELOC_IA64_DTPMOD64LSB: rtype = R_IA64_DTPMOD64LSB; break;
313 case BFD_RELOC_IA64_LTOFF_DTPMOD22: rtype = R_IA64_LTOFF_DTPMOD22; break;
314
315 case BFD_RELOC_IA64_DTPREL14: rtype = R_IA64_DTPREL14; break;
316 case BFD_RELOC_IA64_DTPREL22: rtype = R_IA64_DTPREL22; break;
317 case BFD_RELOC_IA64_DTPREL64I: rtype = R_IA64_DTPREL64I; break;
318 case BFD_RELOC_IA64_DTPREL32MSB: rtype = R_IA64_DTPREL32MSB; break;
319 case BFD_RELOC_IA64_DTPREL32LSB: rtype = R_IA64_DTPREL32LSB; break;
320 case BFD_RELOC_IA64_DTPREL64MSB: rtype = R_IA64_DTPREL64MSB; break;
321 case BFD_RELOC_IA64_DTPREL64LSB: rtype = R_IA64_DTPREL64LSB; break;
322 case BFD_RELOC_IA64_LTOFF_DTPREL22: rtype = R_IA64_LTOFF_DTPREL22; break;
323
324 default: return 0;
325 }
326 return ia64_elf_lookup_howto (rtype);
327 }
328
329 reloc_howto_type *
330 ia64_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
331 const char *r_name)
332 {
333 unsigned int i;
334
335 for (i = 0;
336 i < sizeof (ia64_howto_table) / sizeof (ia64_howto_table[0]);
337 i++)
338 if (ia64_howto_table[i].name != NULL
339 && strcasecmp (ia64_howto_table[i].name, r_name) == 0)
340 return &ia64_howto_table[i];
341
342 return NULL;
343 }
344
345 #define BTYPE_SHIFT 6
346 #define Y_SHIFT 26
347 #define X6_SHIFT 27
348 #define X4_SHIFT 27
349 #define X3_SHIFT 33
350 #define X2_SHIFT 31
351 #define X_SHIFT 33
352 #define OPCODE_SHIFT 37
353
354 #define OPCODE_BITS (0xfLL << OPCODE_SHIFT)
355 #define X6_BITS (0x3fLL << X6_SHIFT)
356 #define X4_BITS (0xfLL << X4_SHIFT)
357 #define X3_BITS (0x7LL << X3_SHIFT)
358 #define X2_BITS (0x3LL << X2_SHIFT)
359 #define X_BITS (0x1LL << X_SHIFT)
360 #define Y_BITS (0x1LL << Y_SHIFT)
361 #define BTYPE_BITS (0x7LL << BTYPE_SHIFT)
362 #define PREDICATE_BITS (0x3fLL)
363
364 #define IS_NOP_B(i) \
365 (((i) & (OPCODE_BITS | X6_BITS)) == (2LL << OPCODE_SHIFT))
366 #define IS_NOP_F(i) \
367 (((i) & (OPCODE_BITS | X_BITS | X6_BITS | Y_BITS)) \
368 == (0x1LL << X6_SHIFT))
369 #define IS_NOP_I(i) \
370 (((i) & (OPCODE_BITS | X3_BITS | X6_BITS | Y_BITS)) \
371 == (0x1LL << X6_SHIFT))
372 #define IS_NOP_M(i) \
373 (((i) & (OPCODE_BITS | X3_BITS | X2_BITS | X4_BITS | Y_BITS)) \
374 == (0x1LL << X4_SHIFT))
375 #define IS_BR_COND(i) \
376 (((i) & (OPCODE_BITS | BTYPE_BITS)) == (0x4LL << OPCODE_SHIFT))
377 #define IS_BR_CALL(i) \
378 (((i) & OPCODE_BITS) == (0x5LL << OPCODE_SHIFT))
379
380 bfd_boolean
381 ia64_elf_relax_br (bfd_byte *contents, bfd_vma off)
382 {
383 unsigned int template_val, mlx;
384 bfd_vma t0, t1, s0, s1, s2, br_code;
385 long br_slot;
386 bfd_byte *hit_addr;
387
388 hit_addr = (bfd_byte *) (contents + off);
389 br_slot = (intptr_t) hit_addr & 0x3;
390 hit_addr -= br_slot;
391 t0 = bfd_getl64 (hit_addr + 0);
392 t1 = bfd_getl64 (hit_addr + 8);
393
394 /* Check if we can turn br into brl. A label is always at the start
395 of the bundle. Even if there are predicates on NOPs, we still
396 perform this optimization. */
397 template_val = t0 & 0x1e;
398 s0 = (t0 >> 5) & 0x1ffffffffffLL;
399 s1 = ((t0 >> 46) | (t1 << 18)) & 0x1ffffffffffLL;
400 s2 = (t1 >> 23) & 0x1ffffffffffLL;
401 switch (br_slot)
402 {
403 case 0:
404 /* Check if slot 1 and slot 2 are NOPs. Possible template is
405 BBB. We only need to check nop.b. */
406 if (!(IS_NOP_B (s1) && IS_NOP_B (s2)))
407 return FALSE;
408 br_code = s0;
409 break;
410 case 1:
411 /* Check if slot 2 is NOP. Possible templates are MBB and BBB.
412 For BBB, slot 0 also has to be nop.b. */
413 if (!((template_val == 0x12 /* MBB */
414 && IS_NOP_B (s2))
415 || (template_val == 0x16 /* BBB */
416 && IS_NOP_B (s0)
417 && IS_NOP_B (s2))))
418 return FALSE;
419 br_code = s1;
420 break;
421 case 2:
422 /* Check if slot 1 is NOP. Possible templates are MIB, MBB, BBB,
423 MMB and MFB. For BBB, slot 0 also has to be nop.b. */
424 if (!((template_val == 0x10 /* MIB */
425 && IS_NOP_I (s1))
426 || (template_val == 0x12 /* MBB */
427 && IS_NOP_B (s1))
428 || (template_val == 0x16 /* BBB */
429 && IS_NOP_B (s0)
430 && IS_NOP_B (s1))
431 || (template_val == 0x18 /* MMB */
432 && IS_NOP_M (s1))
433 || (template_val == 0x1c /* MFB */
434 && IS_NOP_F (s1))))
435 return FALSE;
436 br_code = s2;
437 break;
438 default:
439 /* It should never happen. */
440 abort ();
441 }
442
443 /* We can turn br.cond/br.call into brl.cond/brl.call. */
444 if (!(IS_BR_COND (br_code) || IS_BR_CALL (br_code)))
445 return FALSE;
446
447 /* Turn br into brl by setting bit 40. */
448 br_code |= 0x1LL << 40;
449
450 /* Turn the old bundle into a MLX bundle with the same stop-bit
451 variety. */
452 if (t0 & 0x1)
453 mlx = 0x5;
454 else
455 mlx = 0x4;
456
457 if (template_val == 0x16)
458 {
459 /* For BBB, we need to put nop.m in slot 0. We keep the original
460 predicate only if slot 0 isn't br. */
461 if (br_slot == 0)
462 t0 = 0LL;
463 else
464 t0 &= PREDICATE_BITS << 5;
465 t0 |= 0x1LL << (X4_SHIFT + 5);
466 }
467 else
468 {
469 /* Keep the original instruction in slot 0. */
470 t0 &= 0x1ffffffffffLL << 5;
471 }
472
473 t0 |= mlx;
474
475 /* Put brl in slot 1. */
476 t1 = br_code << 23;
477
478 bfd_putl64 (t0, hit_addr);
479 bfd_putl64 (t1, hit_addr + 8);
480 return TRUE;
481 }
482
483 void
484 ia64_elf_relax_brl (bfd_byte *contents, bfd_vma off)
485 {
486 int template_val;
487 bfd_byte *hit_addr;
488 bfd_vma t0, t1, i0, i1, i2;
489
490 hit_addr = (bfd_byte *) (contents + off);
491 hit_addr -= (intptr_t) hit_addr & 0x3;
492 t0 = bfd_getl64 (hit_addr);
493 t1 = bfd_getl64 (hit_addr + 8);
494
495 /* Keep the instruction in slot 0. */
496 i0 = (t0 >> 5) & 0x1ffffffffffLL;
497 /* Use nop.b for slot 1. */
498 i1 = 0x4000000000LL;
499 /* For slot 2, turn brl into br by masking out bit 40. */
500 i2 = (t1 >> 23) & 0x0ffffffffffLL;
501
502 /* Turn a MLX bundle into a MBB bundle with the same stop-bit
503 variety. */
504 if (t0 & 0x1)
505 template_val = 0x13;
506 else
507 template_val = 0x12;
508 t0 = (i1 << 46) | (i0 << 5) | template_val;
509 t1 = (i2 << 23) | (i1 >> 18);
510
511 bfd_putl64 (t0, hit_addr);
512 bfd_putl64 (t1, hit_addr + 8);
513 }
514
515 void
516 ia64_elf_relax_ldxmov (bfd_byte *contents, bfd_vma off)
517 {
518 int shift, r1, r3;
519 bfd_vma dword, insn;
520
521 switch ((int)off & 0x3)
522 {
523 case 0: shift = 5; break;
524 case 1: shift = 14; off += 3; break;
525 case 2: shift = 23; off += 6; break;
526 default:
527 abort ();
528 }
529
530 dword = bfd_getl64 (contents + off);
531 insn = (dword >> shift) & 0x1ffffffffffLL;
532
533 r1 = (insn >> 6) & 127;
534 r3 = (insn >> 20) & 127;
535 if (r1 == r3)
536 insn = 0x8000000; /* nop */
537 else
538 insn = (insn & 0x7f01fff) | 0x10800000000LL; /* (qp) mov r1 = r3 */
539
540 dword &= ~(0x1ffffffffffLL << shift);
541 dword |= (insn << shift);
542 bfd_putl64 (dword, contents + off);
543 }
544 \f
545 bfd_reloc_status_type
546 ia64_elf_install_value (bfd_byte *hit_addr, bfd_vma v, unsigned int r_type)
547 {
548 const struct ia64_operand *op;
549 int bigendian = 0, shift = 0;
550 bfd_vma t0, t1, dword;
551 ia64_insn insn;
552 enum ia64_opnd opnd;
553 const char *err;
554 size_t size = 8;
555 #ifdef BFD_HOST_U_64_BIT
556 BFD_HOST_U_64_BIT val = (BFD_HOST_U_64_BIT) v;
557 #else
558 bfd_vma val = v;
559 #endif
560
561 opnd = IA64_OPND_NIL;
562 switch (r_type)
563 {
564 case R_IA64_NONE:
565 case R_IA64_LDXMOV:
566 return bfd_reloc_ok;
567
568 /* Instruction relocations. */
569
570 case R_IA64_IMM14:
571 case R_IA64_TPREL14:
572 case R_IA64_DTPREL14:
573 opnd = IA64_OPND_IMM14;
574 break;
575
576 case R_IA64_PCREL21F: opnd = IA64_OPND_TGT25; break;
577 case R_IA64_PCREL21M: opnd = IA64_OPND_TGT25b; break;
578 case R_IA64_PCREL60B: opnd = IA64_OPND_TGT64; break;
579 case R_IA64_PCREL21B:
580 case R_IA64_PCREL21BI:
581 opnd = IA64_OPND_TGT25c;
582 break;
583
584 case R_IA64_IMM22:
585 case R_IA64_GPREL22:
586 case R_IA64_LTOFF22:
587 case R_IA64_LTOFF22X:
588 case R_IA64_PLTOFF22:
589 case R_IA64_PCREL22:
590 case R_IA64_LTOFF_FPTR22:
591 case R_IA64_TPREL22:
592 case R_IA64_DTPREL22:
593 case R_IA64_LTOFF_TPREL22:
594 case R_IA64_LTOFF_DTPMOD22:
595 case R_IA64_LTOFF_DTPREL22:
596 opnd = IA64_OPND_IMM22;
597 break;
598
599 case R_IA64_IMM64:
600 case R_IA64_GPREL64I:
601 case R_IA64_LTOFF64I:
602 case R_IA64_PLTOFF64I:
603 case R_IA64_PCREL64I:
604 case R_IA64_FPTR64I:
605 case R_IA64_LTOFF_FPTR64I:
606 case R_IA64_TPREL64I:
607 case R_IA64_DTPREL64I:
608 opnd = IA64_OPND_IMMU64;
609 break;
610
611 /* Data relocations. */
612
613 case R_IA64_DIR32MSB:
614 case R_IA64_GPREL32MSB:
615 case R_IA64_FPTR32MSB:
616 case R_IA64_PCREL32MSB:
617 case R_IA64_LTOFF_FPTR32MSB:
618 case R_IA64_SEGREL32MSB:
619 case R_IA64_SECREL32MSB:
620 case R_IA64_LTV32MSB:
621 case R_IA64_DTPREL32MSB:
622 size = 4; bigendian = 1;
623 break;
624
625 case R_IA64_DIR32LSB:
626 case R_IA64_GPREL32LSB:
627 case R_IA64_FPTR32LSB:
628 case R_IA64_PCREL32LSB:
629 case R_IA64_LTOFF_FPTR32LSB:
630 case R_IA64_SEGREL32LSB:
631 case R_IA64_SECREL32LSB:
632 case R_IA64_LTV32LSB:
633 case R_IA64_DTPREL32LSB:
634 size = 4; bigendian = 0;
635 break;
636
637 case R_IA64_DIR64MSB:
638 case R_IA64_GPREL64MSB:
639 case R_IA64_PLTOFF64MSB:
640 case R_IA64_FPTR64MSB:
641 case R_IA64_PCREL64MSB:
642 case R_IA64_LTOFF_FPTR64MSB:
643 case R_IA64_SEGREL64MSB:
644 case R_IA64_SECREL64MSB:
645 case R_IA64_LTV64MSB:
646 case R_IA64_TPREL64MSB:
647 case R_IA64_DTPMOD64MSB:
648 case R_IA64_DTPREL64MSB:
649 size = 8; bigendian = 1;
650 break;
651
652 case R_IA64_DIR64LSB:
653 case R_IA64_GPREL64LSB:
654 case R_IA64_PLTOFF64LSB:
655 case R_IA64_FPTR64LSB:
656 case R_IA64_PCREL64LSB:
657 case R_IA64_LTOFF_FPTR64LSB:
658 case R_IA64_SEGREL64LSB:
659 case R_IA64_SECREL64LSB:
660 case R_IA64_LTV64LSB:
661 case R_IA64_TPREL64LSB:
662 case R_IA64_DTPMOD64LSB:
663 case R_IA64_DTPREL64LSB:
664 size = 8; bigendian = 0;
665 break;
666
667 /* Unsupported / Dynamic relocations. */
668 default:
669 return bfd_reloc_notsupported;
670 }
671
672 switch (opnd)
673 {
674 case IA64_OPND_IMMU64:
675 hit_addr -= (intptr_t) hit_addr & 0x3;
676 t0 = bfd_getl64 (hit_addr);
677 t1 = bfd_getl64 (hit_addr + 8);
678
679 /* tmpl/s: bits 0.. 5 in t0
680 slot 0: bits 5..45 in t0
681 slot 1: bits 46..63 in t0, bits 0..22 in t1
682 slot 2: bits 23..63 in t1 */
683
684 /* First, clear the bits that form the 64 bit constant. */
685 t0 &= ~(0x3ffffLL << 46);
686 t1 &= ~(0x7fffffLL
687 | (( (0x07fLL << 13) | (0x1ffLL << 27)
688 | (0x01fLL << 22) | (0x001LL << 21)
689 | (0x001LL << 36)) << 23));
690
691 t0 |= ((val >> 22) & 0x03ffffLL) << 46; /* 18 lsbs of imm41 */
692 t1 |= ((val >> 40) & 0x7fffffLL) << 0; /* 23 msbs of imm41 */
693 t1 |= ( (((val >> 0) & 0x07f) << 13) /* imm7b */
694 | (((val >> 7) & 0x1ff) << 27) /* imm9d */
695 | (((val >> 16) & 0x01f) << 22) /* imm5c */
696 | (((val >> 21) & 0x001) << 21) /* ic */
697 | (((val >> 63) & 0x001) << 36)) << 23; /* i */
698
699 bfd_putl64 (t0, hit_addr);
700 bfd_putl64 (t1, hit_addr + 8);
701 break;
702
703 case IA64_OPND_TGT64:
704 hit_addr -= (intptr_t) hit_addr & 0x3;
705 t0 = bfd_getl64 (hit_addr);
706 t1 = bfd_getl64 (hit_addr + 8);
707
708 /* tmpl/s: bits 0.. 5 in t0
709 slot 0: bits 5..45 in t0
710 slot 1: bits 46..63 in t0, bits 0..22 in t1
711 slot 2: bits 23..63 in t1 */
712
713 /* First, clear the bits that form the 64 bit constant. */
714 t0 &= ~(0x3ffffLL << 46);
715 t1 &= ~(0x7fffffLL
716 | ((1LL << 36 | 0xfffffLL << 13) << 23));
717
718 val >>= 4;
719 t0 |= ((val >> 20) & 0xffffLL) << 2 << 46; /* 16 lsbs of imm39 */
720 t1 |= ((val >> 36) & 0x7fffffLL) << 0; /* 23 msbs of imm39 */
721 t1 |= ((((val >> 0) & 0xfffffLL) << 13) /* imm20b */
722 | (((val >> 59) & 0x1LL) << 36)) << 23; /* i */
723
724 bfd_putl64 (t0, hit_addr);
725 bfd_putl64 (t1, hit_addr + 8);
726 break;
727
728 default:
729 switch ((intptr_t) hit_addr & 0x3)
730 {
731 case 0: shift = 5; break;
732 case 1: shift = 14; hit_addr += 3; break;
733 case 2: shift = 23; hit_addr += 6; break;
734 case 3: return bfd_reloc_notsupported; /* shouldn't happen... */
735 }
736 dword = bfd_getl64 (hit_addr);
737 insn = (dword >> shift) & 0x1ffffffffffLL;
738
739 op = elf64_ia64_operands + opnd;
740 err = (*op->insert) (op, val, &insn);
741 if (err)
742 return bfd_reloc_overflow;
743
744 dword &= ~(0x1ffffffffffLL << shift);
745 dword |= (insn << shift);
746 bfd_putl64 (dword, hit_addr);
747 break;
748
749 case IA64_OPND_NIL:
750 /* A data relocation. */
751 if (bigendian)
752 if (size == 4)
753 bfd_putb32 (val, hit_addr);
754 else
755 bfd_putb64 (val, hit_addr);
756 else
757 if (size == 4)
758 bfd_putl32 (val, hit_addr);
759 else
760 bfd_putl64 (val, hit_addr);
761 break;
762 }
763
764 return bfd_reloc_ok;
765 }
This page took 0.04705 seconds and 4 git commands to generate.