1 /* IA-64 support for 64-bit ELF
2    Copyright (C) 1998-2016 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
ia64_elf_reloc(bfd * abfd ATTRIBUTE_UNUSED,arelent * reloc,asymbol * sym ATTRIBUTE_UNUSED,PTR data ATTRIBUTE_UNUSED,asection * input_section,bfd * output_bfd,char ** error_message)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 *
ia64_elf_lookup_howto(unsigned int rtype)197 ia64_elf_lookup_howto (unsigned int rtype)
198 {
199   static int inited = 0;
200   int i;
201 
202   if (!inited)
203     {
204       inited = 1;
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 0;
213   i = elf_code_to_howto_index[rtype];
214   if (i >= NELEMS (ia64_howto_table))
215     return 0;
216   return ia64_howto_table + i;
217 }
218 
219 reloc_howto_type*
ia64_elf_reloc_type_lookup(bfd * abfd ATTRIBUTE_UNUSED,bfd_reloc_code_real_type bfd_code)220 ia64_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
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: return 0;
324     }
325   return ia64_elf_lookup_howto (rtype);
326 }
327 
328 reloc_howto_type *
ia64_elf_reloc_name_lookup(bfd * abfd ATTRIBUTE_UNUSED,const char * r_name)329 ia64_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
330                             const char *r_name)
331 {
332   unsigned int i;
333 
334   for (i = 0;
335        i < sizeof (ia64_howto_table) / sizeof (ia64_howto_table[0]);
336        i++)
337     if (ia64_howto_table[i].name != NULL
338 	&& strcasecmp (ia64_howto_table[i].name, r_name) == 0)
339       return &ia64_howto_table[i];
340 
341   return NULL;
342 }
343 
344 #define BTYPE_SHIFT	6
345 #define Y_SHIFT		26
346 #define X6_SHIFT	27
347 #define X4_SHIFT	27
348 #define X3_SHIFT	33
349 #define X2_SHIFT	31
350 #define X_SHIFT		33
351 #define OPCODE_SHIFT	37
352 
353 #define OPCODE_BITS	(0xfLL << OPCODE_SHIFT)
354 #define X6_BITS		(0x3fLL << X6_SHIFT)
355 #define X4_BITS		(0xfLL << X4_SHIFT)
356 #define X3_BITS		(0x7LL << X3_SHIFT)
357 #define X2_BITS		(0x3LL << X2_SHIFT)
358 #define X_BITS		(0x1LL << X_SHIFT)
359 #define Y_BITS		(0x1LL << Y_SHIFT)
360 #define BTYPE_BITS	(0x7LL << BTYPE_SHIFT)
361 #define PREDICATE_BITS	(0x3fLL)
362 
363 #define IS_NOP_B(i) \
364   (((i) & (OPCODE_BITS | X6_BITS)) == (2LL << OPCODE_SHIFT))
365 #define IS_NOP_F(i) \
366   (((i) & (OPCODE_BITS | X_BITS | X6_BITS | Y_BITS)) \
367    == (0x1LL << X6_SHIFT))
368 #define IS_NOP_I(i) \
369   (((i) & (OPCODE_BITS | X3_BITS | X6_BITS | Y_BITS)) \
370    == (0x1LL << X6_SHIFT))
371 #define IS_NOP_M(i) \
372   (((i) & (OPCODE_BITS | X3_BITS | X2_BITS | X4_BITS | Y_BITS)) \
373    == (0x1LL << X4_SHIFT))
374 #define IS_BR_COND(i) \
375   (((i) & (OPCODE_BITS | BTYPE_BITS)) == (0x4LL << OPCODE_SHIFT))
376 #define IS_BR_CALL(i) \
377   (((i) & OPCODE_BITS) == (0x5LL << OPCODE_SHIFT))
378 
379 bfd_boolean
ia64_elf_relax_br(bfd_byte * contents,bfd_vma off)380 ia64_elf_relax_br (bfd_byte *contents, bfd_vma off)
381 {
382   unsigned int template_val, mlx;
383   bfd_vma t0, t1, s0, s1, s2, br_code;
384   long br_slot;
385   bfd_byte *hit_addr;
386 
387   hit_addr = (bfd_byte *) (contents + off);
388   br_slot = (intptr_t) hit_addr & 0x3;
389   hit_addr -= br_slot;
390   t0 = bfd_getl64 (hit_addr + 0);
391   t1 = bfd_getl64 (hit_addr + 8);
392 
393   /* Check if we can turn br into brl.  A label is always at the start
394      of the bundle.  Even if there are predicates on NOPs, we still
395      perform this optimization.  */
396   template_val = t0 & 0x1e;
397   s0 = (t0 >> 5) & 0x1ffffffffffLL;
398   s1 = ((t0 >> 46) | (t1 << 18)) & 0x1ffffffffffLL;
399   s2 = (t1 >> 23) & 0x1ffffffffffLL;
400   switch (br_slot)
401     {
402     case 0:
403       /* Check if slot 1 and slot 2 are NOPs. Possible template is
404          BBB.  We only need to check nop.b.  */
405       if (!(IS_NOP_B (s1) && IS_NOP_B (s2)))
406 	return FALSE;
407       br_code = s0;
408       break;
409     case 1:
410       /* Check if slot 2 is NOP. Possible templates are MBB and BBB.
411 	 For BBB, slot 0 also has to be nop.b.  */
412       if (!((template_val == 0x12				/* MBB */
413 	     && IS_NOP_B (s2))
414 	    || (template_val == 0x16			/* BBB */
415 		&& IS_NOP_B (s0)
416 		&& IS_NOP_B (s2))))
417 	return FALSE;
418       br_code = s1;
419       break;
420     case 2:
421       /* Check if slot 1 is NOP. Possible templates are MIB, MBB, BBB,
422 	 MMB and MFB. For BBB, slot 0 also has to be nop.b.  */
423       if (!((template_val == 0x10				/* MIB */
424 	     && IS_NOP_I (s1))
425 	    || (template_val == 0x12			/* MBB */
426 		&& IS_NOP_B (s1))
427 	    || (template_val == 0x16			/* BBB */
428 		&& IS_NOP_B (s0)
429 		&& IS_NOP_B (s1))
430 	    || (template_val == 0x18			/* MMB */
431 		&& IS_NOP_M (s1))
432 	    || (template_val == 0x1c			/* MFB */
433 		&& IS_NOP_F (s1))))
434 	return FALSE;
435       br_code = s2;
436       break;
437     default:
438       /* It should never happen.  */
439       abort ();
440     }
441 
442   /* We can turn br.cond/br.call into brl.cond/brl.call.  */
443   if (!(IS_BR_COND (br_code) || IS_BR_CALL (br_code)))
444     return FALSE;
445 
446   /* Turn br into brl by setting bit 40.  */
447   br_code |= 0x1LL << 40;
448 
449   /* Turn the old bundle into a MLX bundle with the same stop-bit
450      variety.  */
451   if (t0 & 0x1)
452     mlx = 0x5;
453   else
454     mlx = 0x4;
455 
456   if (template_val == 0x16)
457     {
458       /* For BBB, we need to put nop.m in slot 0.  We keep the original
459 	 predicate only if slot 0 isn't br.  */
460       if (br_slot == 0)
461 	t0 = 0LL;
462       else
463 	t0 &= PREDICATE_BITS << 5;
464       t0 |= 0x1LL << (X4_SHIFT + 5);
465     }
466   else
467     {
468       /* Keep the original instruction in slot 0.  */
469       t0 &= 0x1ffffffffffLL << 5;
470     }
471 
472   t0 |= mlx;
473 
474   /* Put brl in slot 1.  */
475   t1 = br_code << 23;
476 
477   bfd_putl64 (t0, hit_addr);
478   bfd_putl64 (t1, hit_addr + 8);
479   return TRUE;
480 }
481 
482 void
ia64_elf_relax_brl(bfd_byte * contents,bfd_vma off)483 ia64_elf_relax_brl (bfd_byte *contents, bfd_vma off)
484 {
485   int template_val;
486   bfd_byte *hit_addr;
487   bfd_vma t0, t1, i0, i1, i2;
488 
489   hit_addr = (bfd_byte *) (contents + off);
490   hit_addr -= (intptr_t) hit_addr & 0x3;
491   t0 = bfd_getl64 (hit_addr);
492   t1 = bfd_getl64 (hit_addr + 8);
493 
494   /* Keep the instruction in slot 0. */
495   i0 = (t0 >> 5) & 0x1ffffffffffLL;
496   /* Use nop.b for slot 1. */
497   i1 = 0x4000000000LL;
498   /* For slot 2, turn brl into br by masking out bit 40.  */
499   i2 = (t1 >> 23) & 0x0ffffffffffLL;
500 
501   /* Turn a MLX bundle into a MBB bundle with the same stop-bit
502      variety.  */
503   if (t0 & 0x1)
504     template_val = 0x13;
505   else
506     template_val = 0x12;
507   t0 = (i1 << 46) | (i0 << 5) | template_val;
508   t1 = (i2 << 23) | (i1 >> 18);
509 
510   bfd_putl64 (t0, hit_addr);
511   bfd_putl64 (t1, hit_addr + 8);
512 }
513 
514 void
ia64_elf_relax_ldxmov(bfd_byte * contents,bfd_vma off)515 ia64_elf_relax_ldxmov (bfd_byte *contents, bfd_vma off)
516 {
517   int shift, r1, r3;
518   bfd_vma dword, insn;
519 
520   switch ((int)off & 0x3)
521     {
522     case 0: shift =  5; break;
523     case 1: shift = 14; off += 3; break;
524     case 2: shift = 23; off += 6; break;
525     default:
526       abort ();
527     }
528 
529   dword = bfd_getl64 (contents + off);
530   insn = (dword >> shift) & 0x1ffffffffffLL;
531 
532   r1 = (insn >> 6) & 127;
533   r3 = (insn >> 20) & 127;
534   if (r1 == r3)
535     insn = 0x8000000;				   /* nop */
536   else
537     insn = (insn & 0x7f01fff) | 0x10800000000LL;   /* (qp) mov r1 = r3 */
538 
539   dword &= ~(0x1ffffffffffLL << shift);
540   dword |= (insn << shift);
541   bfd_putl64 (dword, contents + off);
542 }
543 
544 bfd_reloc_status_type
ia64_elf_install_value(bfd_byte * hit_addr,bfd_vma v,unsigned int r_type)545 ia64_elf_install_value (bfd_byte *hit_addr, bfd_vma v, unsigned int r_type)
546 {
547   const struct ia64_operand *op;
548   int bigendian = 0, shift = 0;
549   bfd_vma t0, t1, dword;
550   ia64_insn insn;
551   enum ia64_opnd opnd;
552   const char *err;
553   size_t size = 8;
554 #ifdef BFD_HOST_U_64_BIT
555   BFD_HOST_U_64_BIT val = (BFD_HOST_U_64_BIT) v;
556 #else
557   bfd_vma val = v;
558 #endif
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 &= ~(0x3ffffLL << 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 &= ~(0x3ffffLL << 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 &= ~(0x1ffffffffffLL << 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