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