OSDN Git Service

daily update
[pf3gnuchains/pf3gnuchains4x.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 }