xref: /netbsd-src/external/gpl3/binutils.old/dist/bfd/elfxx-ia64.c (revision fdd524d4ccd2bb0c6f67401e938dabf773eb0372)
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 
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 }
766