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