*** empty log message ***
[deliverable/binutils-gdb.git] / bfd / elfxx-ia64.c
CommitLineData
800eeca4 1/* IA-64 support for 64-bit ELF
01e1a5bc 2 Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
e57278ef 3 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
800eeca4
JW
4 Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
5
5e8d7549 6 This file is part of BFD, the Binary File Descriptor library.
800eeca4 7
5e8d7549
NC
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
cd123cb7 10 the Free Software Foundation; either version 3 of the License, or
5e8d7549 11 (at your option) any later version.
800eeca4 12
5e8d7549
NC
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.
800eeca4 17
5e8d7549
NC
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
cd123cb7
NC
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
800eeca4 22
800eeca4 23#include "sysdep.h"
3db64b00 24#include "bfd.h"
800eeca4
JW
25#include "libbfd.h"
26#include "elf-bfd.h"
27#include "opcode/ia64.h"
28#include "elf/ia64.h"
0aa92b58
JJ
29#include "objalloc.h"
30#include "hashtab.h"
6f8027ae 31#include "bfd_stdint.h"
cbe79dfe 32#include "elfxx-ia64.h"
5a260b66 33
5e8d7549 34/* THE RULES for all the stuff the linker creates --
b34976b6 35
5e8d7549
NC
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.
b34976b6 40
5e8d7549
NC
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.
b34976b6 47
5e8d7549
NC
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.
b34976b6 51
5e8d7549
NC
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.
b34976b6 58
5e8d7549 59 MIN_PLT Created by PLTOFF entries against dynamic symbols. This
4cc11e76 60 does not require dynamic relocations. */
800eeca4 61
cbe79dfe 62/* ia64-specific relocation. */
7256a114 63
800eeca4
JW
64#define NELEMS(a) ((int) (sizeof (a) / sizeof ((a)[0])))
65
800eeca4 66/* Perform a relocation. Not much to do here as all the hard work is
bbe66d08 67 done in elfNN_ia64_final_link_relocate. */
800eeca4 68static bfd_reloc_status_type
cbe79dfe
TG
69ia64_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)
800eeca4
JW
73{
74 if (output_bfd)
75 {
76 reloc->address += input_section->output_offset;
77 return bfd_reloc_ok;
78 }
6e84a906
DJ
79
80 if (input_section->flags & SEC_DEBUGGING)
81 return bfd_reloc_continue;
82
cbe79dfe 83 *error_message = "Unsupported call to ia64_elf_reloc";
800eeca4
JW
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, \
cbe79dfe 89 ia64_elf_reloc, NAME, FALSE, 0, -1, IN)
800eeca4
JW
90
91/* This table has to be sorted according to increasing number of the
92 TYPE field. */
93static reloc_howto_type ia64_howto_table[] =
94 {
b34976b6
AM
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),
1fc0d173
JJ
175 IA64_HOWTO (R_IA64_TPREL64MSB, "TPREL64MSB", 4, FALSE, FALSE),
176 IA64_HOWTO (R_IA64_TPREL64LSB, "TPREL64LSB", 4, FALSE, FALSE),
b34976b6
AM
177 IA64_HOWTO (R_IA64_LTOFF_TPREL22, "LTOFF_TPREL22", 0, FALSE, FALSE),
178
0ca3e455
JB
179 IA64_HOWTO (R_IA64_DTPMOD64MSB, "DTPMOD64MSB", 4, FALSE, FALSE),
180 IA64_HOWTO (R_IA64_DTPMOD64LSB, "DTPMOD64LSB", 4, FALSE, FALSE),
b34976b6
AM
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),
1fc0d173
JJ
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),
b34976b6 190 IA64_HOWTO (R_IA64_LTOFF_DTPREL22, "LTOFF_DTPREL22", 0, FALSE, FALSE),
800eeca4
JW
191 };
192
193static 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
cbe79dfe
TG
197reloc_howto_type *
198ia64_elf_lookup_howto (unsigned int rtype)
800eeca4
JW
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
d0fb9a8d
JJ
212 if (rtype > R_IA64_MAX_RELOC_CODE)
213 return 0;
800eeca4
JW
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
cbe79dfe
TG
220reloc_howto_type*
221ia64_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
222 bfd_reloc_code_real_type bfd_code)
800eeca4
JW
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;
748abff6 260 case BFD_RELOC_IA64_PCREL21BI: rtype = R_IA64_PCREL21BI; break;
800eeca4
JW
261 case BFD_RELOC_IA64_PCREL21M: rtype = R_IA64_PCREL21M; break;
262 case BFD_RELOC_IA64_PCREL21F: rtype = R_IA64_PCREL21F; break;
748abff6
RH
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;
800eeca4
JW
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;
a4bd8390
JW
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;
800eeca4
JW
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
800eeca4
JW
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;
800eeca4
JW
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
13ae64f3 304 case BFD_RELOC_IA64_TPREL14: rtype = R_IA64_TPREL14; break;
800eeca4 305 case BFD_RELOC_IA64_TPREL22: rtype = R_IA64_TPREL22; break;
13ae64f3 306 case BFD_RELOC_IA64_TPREL64I: rtype = R_IA64_TPREL64I; break;
800eeca4
JW
307 case BFD_RELOC_IA64_TPREL64MSB: rtype = R_IA64_TPREL64MSB; break;
308 case BFD_RELOC_IA64_TPREL64LSB: rtype = R_IA64_TPREL64LSB; break;
13ae64f3
JJ
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;
800eeca4
JW
323
324 default: return 0;
325 }
cbe79dfe 326 return ia64_elf_lookup_howto (rtype);
800eeca4
JW
327}
328
cbe79dfe
TG
329reloc_howto_type *
330ia64_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
331 const char *r_name)
157090f7
AM
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
83b6bd86
L
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
cbe79dfe
TG
380bfd_boolean
381ia64_elf_relax_br (bfd_byte *contents, bfd_vma off)
83b6bd86 382{
d3ce72d0 383 unsigned int template_val, mlx;
83b6bd86
L
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);
d68cd58c 389 br_slot = (intptr_t) hit_addr & 0x3;
83b6bd86
L
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. */
d3ce72d0 397 template_val = t0 & 0x1e;
83b6bd86
L
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. */
d3ce72d0 413 if (!((template_val == 0x12 /* MBB */
83b6bd86 414 && IS_NOP_B (s2))
d3ce72d0 415 || (template_val == 0x16 /* BBB */
83b6bd86
L
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. */
d3ce72d0 424 if (!((template_val == 0x10 /* MIB */
83b6bd86 425 && IS_NOP_I (s1))
d3ce72d0 426 || (template_val == 0x12 /* MBB */
83b6bd86 427 && IS_NOP_B (s1))
d3ce72d0 428 || (template_val == 0x16 /* BBB */
83b6bd86
L
429 && IS_NOP_B (s0)
430 && IS_NOP_B (s1))
d3ce72d0 431 || (template_val == 0x18 /* MMB */
83b6bd86 432 && IS_NOP_M (s1))
d3ce72d0 433 || (template_val == 0x1c /* MFB */
83b6bd86
L
434 && IS_NOP_F (s1))))
435 return FALSE;
436 br_code = s2;
437 break;
438 default:
439 /* It should never happen. */
440 abort ();
441 }
9a2e389a 442
83b6bd86
L
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
d3ce72d0 457 if (template_val == 0x16)
83b6bd86 458 {
5e27d427
L
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;
83b6bd86
L
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
cbe79dfe
TG
483void
484ia64_elf_relax_brl (bfd_byte *contents, bfd_vma off)
03609792 485{
d3ce72d0 486 int template_val;
03609792 487 bfd_byte *hit_addr;
fc3ab699 488 bfd_vma t0, t1, i0, i1, i2;
03609792
L
489
490 hit_addr = (bfd_byte *) (contents + off);
d68cd58c 491 hit_addr -= (intptr_t) hit_addr & 0x3;
fc3ab699
L
492 t0 = bfd_getl64 (hit_addr);
493 t1 = bfd_getl64 (hit_addr + 8);
03609792 494
7e3102a7 495 /* Keep the instruction in slot 0. */
fc3ab699
L
496 i0 = (t0 >> 5) & 0x1ffffffffffLL;
497 /* Use nop.b for slot 1. */
498 i1 = 0x4000000000LL;
7e3102a7 499 /* For slot 2, turn brl into br by masking out bit 40. */
fc3ab699 500 i2 = (t1 >> 23) & 0x0ffffffffffLL;
7e3102a7 501
fc3ab699
L
502 /* Turn a MLX bundle into a MBB bundle with the same stop-bit
503 variety. */
504 if (t0 & 0x1)
d3ce72d0 505 template_val = 0x13;
fc3ab699 506 else
d3ce72d0
NC
507 template_val = 0x12;
508 t0 = (i1 << 46) | (i0 << 5) | template_val;
fc3ab699 509 t1 = (i2 << 23) | (i1 >> 18);
7e3102a7 510
fc3ab699
L
511 bfd_putl64 (t0, hit_addr);
512 bfd_putl64 (t1, hit_addr + 8);
03609792 513}
fbbc3759 514
cbe79dfe
TG
515void
516ia64_elf_relax_ldxmov (bfd_byte *contents, bfd_vma off)
2c4c2bc0
RH
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;
60d8b524 526 default:
2c4c2bc0
RH
527 abort ();
528 }
529
bbb268c3 530 dword = bfd_getl64 (contents + off);
2c4c2bc0
RH
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);
bbb268c3 542 bfd_putl64 (dword, contents + off);
2c4c2bc0 543}
800eeca4 544\f
cbe79dfe
TG
545bfd_reloc_status_type
546ia64_elf_install_value (bfd_byte *hit_addr, bfd_vma v, unsigned int r_type)
81545d45 547{
cbe79dfe
TG
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
d9cf1b54 560
cbe79dfe
TG
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;
81545d45 567
cbe79dfe 568 /* Instruction relocations. */
800eeca4 569
cbe79dfe
TG
570 case R_IA64_IMM14:
571 case R_IA64_TPREL14:
572 case R_IA64_DTPREL14:
573 opnd = IA64_OPND_IMM14;
800eeca4
JW
574 break;
575
cbe79dfe
TG
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;
800eeca4
JW
582 break;
583
cbe79dfe
TG
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;
800eeca4 598
cbe79dfe
TG
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;
800eeca4 610
cbe79dfe 611 /* Data relocations. */
b59dd4a5 612
cbe79dfe
TG
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;
b59dd4a5 624
cbe79dfe
TG
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;
b59dd4a5 635 break;
b59dd4a5 636
cbe79dfe
TG
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;
7256a114 651
cbe79dfe
TG
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;
01e1a5bc
NC
665 break;
666
cbe79dfe 667 /* Unsupported / Dynamic relocations. */
01e1a5bc 668 default:
cbe79dfe 669 return bfd_reloc_notsupported;
01e1a5bc 670 }
01e1a5bc 671
cbe79dfe 672 switch (opnd)
01e1a5bc 673 {
cbe79dfe
TG
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);
01e1a5bc 678
cbe79dfe
TG
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 */
01e1a5bc 683
cbe79dfe
TG
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));
01e1a5bc 690
cbe79dfe
TG
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 */
01e1a5bc 698
cbe79dfe
TG
699 bfd_putl64 (t0, hit_addr);
700 bfd_putl64 (t1, hit_addr + 8);
701 break;
01e1a5bc 702
cbe79dfe
TG
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);
01e1a5bc 707
cbe79dfe
TG
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 */
01e1a5bc 712
cbe79dfe
TG
713 /* First, clear the bits that form the 64 bit constant. */
714 t0 &= ~(0x3ffffLL << 46);
715 t1 &= ~(0x7fffffLL
716 | ((1LL << 36 | 0xfffffLL << 13) << 23));
01e1a5bc 717
cbe79dfe
TG
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 */
01e1a5bc 723
cbe79dfe
TG
724 bfd_putl64 (t0, hit_addr);
725 bfd_putl64 (t1, hit_addr + 8);
726 break;
01e1a5bc 727
cbe79dfe
TG
728 default:
729 switch ((intptr_t) hit_addr & 0x3)
01e1a5bc 730 {
cbe79dfe
TG
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... */
01e1a5bc 735 }
cbe79dfe
TG
736 dword = bfd_getl64 (hit_addr);
737 insn = (dword >> shift) & 0x1ffffffffffLL;
01e1a5bc 738
cbe79dfe
TG
739 op = elf64_ia64_operands + opnd;
740 err = (*op->insert) (op, val, &insn);
741 if (err)
742 return bfd_reloc_overflow;
01e1a5bc 743
cbe79dfe
TG
744 dword &= ~(0x1ffffffffffLL << shift);
745 dword |= (insn << shift);
746 bfd_putl64 (dword, hit_addr);
747 break;
01e1a5bc 748
cbe79dfe
TG
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;
01e1a5bc
NC
762 }
763
cbe79dfe 764 return bfd_reloc_ok;
01e1a5bc 765}
This page took 1.087982 seconds and 4 git commands to generate.