1/* IA-64 support for 64-bit ELF
2   Copyright (C) 1998-2017 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.  */
67static bfd_reloc_status_type
68ia64_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.  */
92static 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
192static 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
196reloc_howto_type *
197ia64_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
219reloc_howto_type*
220ia64_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
328reloc_howto_type *
329ia64_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
379bfd_boolean
380ia64_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
482void
483ia64_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
514void
515ia64_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
544bfd_reloc_status_type
545ia64_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