xref: /netbsd-src/external/gpl3/binutils/dist/bfd/elfxx-ia64.c (revision f3cfa6f6ce31685c6c4a758bc430e69eb99f50a4)
1 /* IA-64 support for 64-bit ELF
2    Copyright (C) 1998-2018 Free Software Foundation, Inc.
3    Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4 
5    This file is part of BFD, the Binary File Descriptor library.
6 
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
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
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.
16 
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
19    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20    MA 02110-1301, USA.  */
21 
22 #include "sysdep.h"
23 #include "bfd.h"
24 #include "libbfd.h"
25 #include "elf-bfd.h"
26 #include "opcode/ia64.h"
27 #include "elf/ia64.h"
28 #include "objalloc.h"
29 #include "hashtab.h"
30 #include "bfd_stdint.h"
31 #include "elfxx-ia64.h"
32 
33 /* THE RULES for all the stuff the linker creates --
34 
35   GOT		Entries created in response to LTOFF or LTOFF_FPTR
36 		relocations.  Dynamic relocs created for dynamic
37 		symbols in an application; REL relocs for locals
38 		in a shared library.
39 
40   FPTR		The canonical function descriptor.  Created for local
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.
46 
47   FULL_PLT	Created for a PCREL21B relocation against a dynamic symbol.
48 		Requires the creation of a PLTOFF entry.  This does not
49 		require any dynamic relocations.
50 
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.
57 
58   MIN_PLT	Created by PLTOFF entries against dynamic symbols.  This
59 		does not require dynamic relocations.  */
60 
61 /* ia64-specific relocation.  */
62 
63 #define NELEMS(a)	((int) (sizeof (a) / sizeof ((a)[0])))
64 
65 /* Perform a relocation.  Not much to do here as all the hard work is
66    done in elfNN_ia64_final_link_relocate.  */
67 static bfd_reloc_status_type
68 ia64_elf_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc,
69 		asymbol *sym ATTRIBUTE_UNUSED,
70 		PTR data ATTRIBUTE_UNUSED, asection *input_section,
71 		bfd *output_bfd, char **error_message)
72 {
73   if (output_bfd)
74     {
75       reloc->address += input_section->output_offset;
76       return bfd_reloc_ok;
77     }
78 
79   if (input_section->flags & SEC_DEBUGGING)
80     return bfd_reloc_continue;
81 
82   *error_message = "Unsupported call to ia64_elf_reloc";
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,	\
88 	 ia64_elf_reloc, NAME, FALSE, 0, -1, IN)
89 
90 /* This table has to be sorted according to increasing number of the
91    TYPE field.  */
92 static reloc_howto_type ia64_howto_table[] =
93   {
94     IA64_HOWTO (R_IA64_NONE,	    "NONE",	   3, FALSE, TRUE),
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),
174     IA64_HOWTO (R_IA64_TPREL64MSB,  "TPREL64MSB",  4, FALSE, FALSE),
175     IA64_HOWTO (R_IA64_TPREL64LSB,  "TPREL64LSB",  4, FALSE, FALSE),
176     IA64_HOWTO (R_IA64_LTOFF_TPREL22, "LTOFF_TPREL22",  0, FALSE, FALSE),
177 
178     IA64_HOWTO (R_IA64_DTPMOD64MSB, "DTPMOD64MSB",  4, FALSE, FALSE),
179     IA64_HOWTO (R_IA64_DTPMOD64LSB, "DTPMOD64LSB",  4, FALSE, FALSE),
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),
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),
189     IA64_HOWTO (R_IA64_LTOFF_DTPREL22, "LTOFF_DTPREL22", 0, FALSE, FALSE),
190   };
191 
192 static 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 
196 reloc_howto_type *
197 ia64_elf_lookup_howto (unsigned int rtype)
198 {
199   static bfd_boolean inited = FALSE;
200   int i;
201 
202   if (!inited)
203     {
204       inited = TRUE;
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 
211   if (rtype > R_IA64_MAX_RELOC_CODE)
212     return NULL;
213   i = elf_code_to_howto_index[rtype];
214   if (i >= NELEMS (ia64_howto_table))
215     return NULL;
216   return ia64_howto_table + i;
217 }
218 
219 reloc_howto_type *
220 ia64_elf_reloc_type_lookup (bfd *abfd,
221 			    bfd_reloc_code_real_type bfd_code)
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;
259     case BFD_RELOC_IA64_PCREL21BI:	rtype = R_IA64_PCREL21BI; break;
260     case BFD_RELOC_IA64_PCREL21M:	rtype = R_IA64_PCREL21M; break;
261     case BFD_RELOC_IA64_PCREL21F:	rtype = R_IA64_PCREL21F; break;
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;
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;
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;
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 
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;
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 
303     case BFD_RELOC_IA64_TPREL14:	rtype = R_IA64_TPREL14; break;
304     case BFD_RELOC_IA64_TPREL22:	rtype = R_IA64_TPREL22; break;
305     case BFD_RELOC_IA64_TPREL64I:	rtype = R_IA64_TPREL64I; break;
306     case BFD_RELOC_IA64_TPREL64MSB:	rtype = R_IA64_TPREL64MSB; break;
307     case BFD_RELOC_IA64_TPREL64LSB:	rtype = R_IA64_TPREL64LSB; break;
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;
322 
323     default:
324       /* xgettext:c-format */
325       _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
326 			  abfd, (int) bfd_code);
327       bfd_set_error (bfd_error_bad_value);
328       return NULL;
329     }
330   return ia64_elf_lookup_howto (rtype);
331 }
332 
333 reloc_howto_type *
334 ia64_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
335 			    const char *r_name)
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 
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 
384 bfd_boolean
385 ia64_elf_relax_br (bfd_byte *contents, bfd_vma off)
386 {
387   unsigned int template_val, mlx;
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);
393   br_slot = (intptr_t) hit_addr & 0x3;
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.  */
401   template_val = t0 & 0x1e;
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
409 	 BBB.  We only need to check nop.b.  */
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.  */
417       if (!((template_val == 0x12				/* MBB */
418 	     && IS_NOP_B (s2))
419 	    || (template_val == 0x16			/* BBB */
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.  */
428       if (!((template_val == 0x10				/* MIB */
429 	     && IS_NOP_I (s1))
430 	    || (template_val == 0x12			/* MBB */
431 		&& IS_NOP_B (s1))
432 	    || (template_val == 0x16			/* BBB */
433 		&& IS_NOP_B (s0)
434 		&& IS_NOP_B (s1))
435 	    || (template_val == 0x18			/* MMB */
436 		&& IS_NOP_M (s1))
437 	    || (template_val == 0x1c			/* MFB */
438 		&& IS_NOP_F (s1))))
439 	return FALSE;
440       br_code = s2;
441       break;
442     default:
443       /* It should never happen.  */
444       abort ();
445     }
446 
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 
461   if (template_val == 0x16)
462     {
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;
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 
487 void
488 ia64_elf_relax_brl (bfd_byte *contents, bfd_vma off)
489 {
490   int template_val;
491   bfd_byte *hit_addr;
492   bfd_vma t0, t1, i0, i1, i2;
493 
494   hit_addr = (bfd_byte *) (contents + off);
495   hit_addr -= (intptr_t) hit_addr & 0x3;
496   t0 = bfd_getl64 (hit_addr);
497   t1 = bfd_getl64 (hit_addr + 8);
498 
499   /* Keep the instruction in slot 0. */
500   i0 = (t0 >> 5) & 0x1ffffffffffLL;
501   /* Use nop.b for slot 1. */
502   i1 = 0x4000000000LL;
503   /* For slot 2, turn brl into br by masking out bit 40.  */
504   i2 = (t1 >> 23) & 0x0ffffffffffLL;
505 
506   /* Turn a MLX bundle into a MBB bundle with the same stop-bit
507      variety.  */
508   if (t0 & 0x1)
509     template_val = 0x13;
510   else
511     template_val = 0x12;
512   t0 = (i1 << 46) | (i0 << 5) | template_val;
513   t1 = (i2 << 23) | (i1 >> 18);
514 
515   bfd_putl64 (t0, hit_addr);
516   bfd_putl64 (t1, hit_addr + 8);
517 }
518 
519 void
520 ia64_elf_relax_ldxmov (bfd_byte *contents, bfd_vma off)
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;
530     default:
531       abort ();
532     }
533 
534   dword = bfd_getl64 (contents + off);
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);
546   bfd_putl64 (dword, contents + off);
547 }
548 
549 bfd_reloc_status_type
550 ia64_elf_install_value (bfd_byte *hit_addr, bfd_vma v, unsigned int r_type)
551 {
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
564 
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;
571 
572       /* Instruction relocations.  */
573 
574     case R_IA64_IMM14:
575     case R_IA64_TPREL14:
576     case R_IA64_DTPREL14:
577       opnd = IA64_OPND_IMM14;
578       break;
579 
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;
586       break;
587 
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;
602 
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;
614 
615       /* Data relocations.  */
616 
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;
628 
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;
639       break;
640 
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;
655 
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;
669       break;
670 
671       /* Unsupported / Dynamic relocations.  */
672     default:
673       return bfd_reloc_notsupported;
674     }
675 
676   switch (opnd)
677     {
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);
682 
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 */
687 
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));
694 
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 */
702 
703       bfd_putl64 (t0, hit_addr);
704       bfd_putl64 (t1, hit_addr + 8);
705       break;
706 
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);
711 
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 */
716 
717       /* First, clear the bits that form the 64 bit constant.  */
718       t0 &= ~(0x3ffffLL << 46);
719       t1 &= ~(0x7fffffLL
720 	      | ((1LL << 36 | 0xfffffLL << 13) << 23));
721 
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 */
727 
728       bfd_putl64 (t0, hit_addr);
729       bfd_putl64 (t1, hit_addr + 8);
730       break;
731 
732     default:
733       switch ((intptr_t) hit_addr & 0x3)
734 	{
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...  */
739 	}
740       dword = bfd_getl64 (hit_addr);
741       insn = (dword >> shift) & 0x1ffffffffffLL;
742 
743       op = elf64_ia64_operands + opnd;
744       err = (*op->insert) (op, val, &insn);
745       if (err)
746 	return bfd_reloc_overflow;
747 
748       dword &= ~(0x1ffffffffffLL << shift);
749       dword |= (insn << shift);
750       bfd_putl64 (dword, hit_addr);
751       break;
752 
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;
766     }
767 
768   return bfd_reloc_ok;
769 }
770