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