1/* IA-64 support for 64-bit ELF
2   Copyright (C) 1998-2020 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.  */
66static bfd_reloc_status_type
67ia64_elf_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc,
68		asymbol *sym ATTRIBUTE_UNUSED,
69		PTR 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.  */
91static reloc_howto_type ia64_howto_table[] =
92  {
93    IA64_HOWTO (R_IA64_NONE,	    "NONE",	   3, FALSE, TRUE),
94
95    IA64_HOWTO (R_IA64_IMM14,	    "IMM14",	   0, FALSE, TRUE),
96    IA64_HOWTO (R_IA64_IMM22,	    "IMM22",	   0, FALSE, TRUE),
97    IA64_HOWTO (R_IA64_IMM64,	    "IMM64",	   0, FALSE, TRUE),
98    IA64_HOWTO (R_IA64_DIR32MSB,    "DIR32MSB",	   2, FALSE, TRUE),
99    IA64_HOWTO (R_IA64_DIR32LSB,    "DIR32LSB",	   2, FALSE, TRUE),
100    IA64_HOWTO (R_IA64_DIR64MSB,    "DIR64MSB",	   4, FALSE, TRUE),
101    IA64_HOWTO (R_IA64_DIR64LSB,    "DIR64LSB",	   4, FALSE, TRUE),
102
103    IA64_HOWTO (R_IA64_GPREL22,	    "GPREL22",	   0, FALSE, TRUE),
104    IA64_HOWTO (R_IA64_GPREL64I,    "GPREL64I",	   0, FALSE, TRUE),
105    IA64_HOWTO (R_IA64_GPREL32MSB,  "GPREL32MSB",  2, FALSE, TRUE),
106    IA64_HOWTO (R_IA64_GPREL32LSB,  "GPREL32LSB",  2, FALSE, TRUE),
107    IA64_HOWTO (R_IA64_GPREL64MSB,  "GPREL64MSB",  4, FALSE, TRUE),
108    IA64_HOWTO (R_IA64_GPREL64LSB,  "GPREL64LSB",  4, FALSE, TRUE),
109
110    IA64_HOWTO (R_IA64_LTOFF22,	    "LTOFF22",	   0, FALSE, TRUE),
111    IA64_HOWTO (R_IA64_LTOFF64I,    "LTOFF64I",	   0, FALSE, TRUE),
112
113    IA64_HOWTO (R_IA64_PLTOFF22,    "PLTOFF22",	   0, FALSE, TRUE),
114    IA64_HOWTO (R_IA64_PLTOFF64I,   "PLTOFF64I",   0, FALSE, TRUE),
115    IA64_HOWTO (R_IA64_PLTOFF64MSB, "PLTOFF64MSB", 4, FALSE, TRUE),
116    IA64_HOWTO (R_IA64_PLTOFF64LSB, "PLTOFF64LSB", 4, FALSE, TRUE),
117
118    IA64_HOWTO (R_IA64_FPTR64I,	    "FPTR64I",	   0, FALSE, TRUE),
119    IA64_HOWTO (R_IA64_FPTR32MSB,   "FPTR32MSB",   2, FALSE, TRUE),
120    IA64_HOWTO (R_IA64_FPTR32LSB,   "FPTR32LSB",   2, FALSE, TRUE),
121    IA64_HOWTO (R_IA64_FPTR64MSB,   "FPTR64MSB",   4, FALSE, TRUE),
122    IA64_HOWTO (R_IA64_FPTR64LSB,   "FPTR64LSB",   4, FALSE, TRUE),
123
124    IA64_HOWTO (R_IA64_PCREL60B,    "PCREL60B",	   0, TRUE, TRUE),
125    IA64_HOWTO (R_IA64_PCREL21B,    "PCREL21B",	   0, TRUE, TRUE),
126    IA64_HOWTO (R_IA64_PCREL21M,    "PCREL21M",	   0, TRUE, TRUE),
127    IA64_HOWTO (R_IA64_PCREL21F,    "PCREL21F",	   0, TRUE, TRUE),
128    IA64_HOWTO (R_IA64_PCREL32MSB,  "PCREL32MSB",  2, TRUE, TRUE),
129    IA64_HOWTO (R_IA64_PCREL32LSB,  "PCREL32LSB",  2, TRUE, TRUE),
130    IA64_HOWTO (R_IA64_PCREL64MSB,  "PCREL64MSB",  4, TRUE, TRUE),
131    IA64_HOWTO (R_IA64_PCREL64LSB,  "PCREL64LSB",  4, TRUE, TRUE),
132
133    IA64_HOWTO (R_IA64_LTOFF_FPTR22, "LTOFF_FPTR22", 0, FALSE, TRUE),
134    IA64_HOWTO (R_IA64_LTOFF_FPTR64I, "LTOFF_FPTR64I", 0, FALSE, TRUE),
135    IA64_HOWTO (R_IA64_LTOFF_FPTR32MSB, "LTOFF_FPTR32MSB", 2, FALSE, TRUE),
136    IA64_HOWTO (R_IA64_LTOFF_FPTR32LSB, "LTOFF_FPTR32LSB", 2, FALSE, TRUE),
137    IA64_HOWTO (R_IA64_LTOFF_FPTR64MSB, "LTOFF_FPTR64MSB", 4, FALSE, TRUE),
138    IA64_HOWTO (R_IA64_LTOFF_FPTR64LSB, "LTOFF_FPTR64LSB", 4, FALSE, TRUE),
139
140    IA64_HOWTO (R_IA64_SEGREL32MSB, "SEGREL32MSB", 2, FALSE, TRUE),
141    IA64_HOWTO (R_IA64_SEGREL32LSB, "SEGREL32LSB", 2, FALSE, TRUE),
142    IA64_HOWTO (R_IA64_SEGREL64MSB, "SEGREL64MSB", 4, FALSE, TRUE),
143    IA64_HOWTO (R_IA64_SEGREL64LSB, "SEGREL64LSB", 4, FALSE, TRUE),
144
145    IA64_HOWTO (R_IA64_SECREL32MSB, "SECREL32MSB", 2, FALSE, TRUE),
146    IA64_HOWTO (R_IA64_SECREL32LSB, "SECREL32LSB", 2, FALSE, TRUE),
147    IA64_HOWTO (R_IA64_SECREL64MSB, "SECREL64MSB", 4, FALSE, TRUE),
148    IA64_HOWTO (R_IA64_SECREL64LSB, "SECREL64LSB", 4, FALSE, TRUE),
149
150    IA64_HOWTO (R_IA64_REL32MSB,    "REL32MSB",	   2, FALSE, TRUE),
151    IA64_HOWTO (R_IA64_REL32LSB,    "REL32LSB",	   2, FALSE, TRUE),
152    IA64_HOWTO (R_IA64_REL64MSB,    "REL64MSB",	   4, FALSE, TRUE),
153    IA64_HOWTO (R_IA64_REL64LSB,    "REL64LSB",	   4, FALSE, TRUE),
154
155    IA64_HOWTO (R_IA64_LTV32MSB,    "LTV32MSB",	   2, FALSE, TRUE),
156    IA64_HOWTO (R_IA64_LTV32LSB,    "LTV32LSB",	   2, FALSE, TRUE),
157    IA64_HOWTO (R_IA64_LTV64MSB,    "LTV64MSB",	   4, FALSE, TRUE),
158    IA64_HOWTO (R_IA64_LTV64LSB,    "LTV64LSB",	   4, FALSE, TRUE),
159
160    IA64_HOWTO (R_IA64_PCREL21BI,   "PCREL21BI",   0, TRUE, TRUE),
161    IA64_HOWTO (R_IA64_PCREL22,     "PCREL22",     0, TRUE, TRUE),
162    IA64_HOWTO (R_IA64_PCREL64I,    "PCREL64I",    0, TRUE, TRUE),
163
164    IA64_HOWTO (R_IA64_IPLTMSB,	    "IPLTMSB",	   4, FALSE, TRUE),
165    IA64_HOWTO (R_IA64_IPLTLSB,	    "IPLTLSB",	   4, FALSE, TRUE),
166    IA64_HOWTO (R_IA64_COPY,	    "COPY",	   4, FALSE, TRUE),
167    IA64_HOWTO (R_IA64_LTOFF22X,    "LTOFF22X",	   0, FALSE, TRUE),
168    IA64_HOWTO (R_IA64_LDXMOV,	    "LDXMOV",	   0, FALSE, TRUE),
169
170    IA64_HOWTO (R_IA64_TPREL14,	    "TPREL14",	   0, FALSE, FALSE),
171    IA64_HOWTO (R_IA64_TPREL22,	    "TPREL22",	   0, FALSE, FALSE),
172    IA64_HOWTO (R_IA64_TPREL64I,    "TPREL64I",	   0, FALSE, FALSE),
173    IA64_HOWTO (R_IA64_TPREL64MSB,  "TPREL64MSB",  4, FALSE, FALSE),
174    IA64_HOWTO (R_IA64_TPREL64LSB,  "TPREL64LSB",  4, FALSE, FALSE),
175    IA64_HOWTO (R_IA64_LTOFF_TPREL22, "LTOFF_TPREL22",  0, FALSE, FALSE),
176
177    IA64_HOWTO (R_IA64_DTPMOD64MSB, "DTPMOD64MSB",  4, FALSE, FALSE),
178    IA64_HOWTO (R_IA64_DTPMOD64LSB, "DTPMOD64LSB",  4, FALSE, FALSE),
179    IA64_HOWTO (R_IA64_LTOFF_DTPMOD22, "LTOFF_DTPMOD22", 0, FALSE, FALSE),
180
181    IA64_HOWTO (R_IA64_DTPREL14,    "DTPREL14",	   0, FALSE, FALSE),
182    IA64_HOWTO (R_IA64_DTPREL22,    "DTPREL22",	   0, FALSE, FALSE),
183    IA64_HOWTO (R_IA64_DTPREL64I,   "DTPREL64I",   0, FALSE, FALSE),
184    IA64_HOWTO (R_IA64_DTPREL32MSB, "DTPREL32MSB", 2, FALSE, FALSE),
185    IA64_HOWTO (R_IA64_DTPREL32LSB, "DTPREL32LSB", 2, FALSE, FALSE),
186    IA64_HOWTO (R_IA64_DTPREL64MSB, "DTPREL64MSB", 4, FALSE, FALSE),
187    IA64_HOWTO (R_IA64_DTPREL64LSB, "DTPREL64LSB", 4, FALSE, FALSE),
188    IA64_HOWTO (R_IA64_LTOFF_DTPREL22, "LTOFF_DTPREL22", 0, FALSE, FALSE),
189  };
190
191static 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
195reloc_howto_type *
196ia64_elf_lookup_howto (unsigned int rtype)
197{
198  static bfd_boolean 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
218reloc_howto_type *
219ia64_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
332reloc_howto_type *
333ia64_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
383bfd_boolean
384ia64_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
486void
487ia64_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
518void
519ia64_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
548bfd_reloc_status_type
549ia64_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#ifdef BFD_HOST_U_64_BIT
559  BFD_HOST_U_64_BIT val = (BFD_HOST_U_64_BIT) v;
560#else
561  bfd_vma val = v;
562#endif
563
564  opnd = IA64_OPND_NIL;
565  switch (r_type)
566    {
567    case R_IA64_NONE:
568    case R_IA64_LDXMOV:
569      return bfd_reloc_ok;
570
571      /* Instruction relocations.  */
572
573    case R_IA64_IMM14:
574    case R_IA64_TPREL14:
575    case R_IA64_DTPREL14:
576      opnd = IA64_OPND_IMM14;
577      break;
578
579    case R_IA64_PCREL21F:	opnd = IA64_OPND_TGT25; break;
580    case R_IA64_PCREL21M:	opnd = IA64_OPND_TGT25b; break;
581    case R_IA64_PCREL60B:	opnd = IA64_OPND_TGT64; break;
582    case R_IA64_PCREL21B:
583    case R_IA64_PCREL21BI:
584      opnd = IA64_OPND_TGT25c;
585      break;
586
587    case R_IA64_IMM22:
588    case R_IA64_GPREL22:
589    case R_IA64_LTOFF22:
590    case R_IA64_LTOFF22X:
591    case R_IA64_PLTOFF22:
592    case R_IA64_PCREL22:
593    case R_IA64_LTOFF_FPTR22:
594    case R_IA64_TPREL22:
595    case R_IA64_DTPREL22:
596    case R_IA64_LTOFF_TPREL22:
597    case R_IA64_LTOFF_DTPMOD22:
598    case R_IA64_LTOFF_DTPREL22:
599      opnd = IA64_OPND_IMM22;
600      break;
601
602    case R_IA64_IMM64:
603    case R_IA64_GPREL64I:
604    case R_IA64_LTOFF64I:
605    case R_IA64_PLTOFF64I:
606    case R_IA64_PCREL64I:
607    case R_IA64_FPTR64I:
608    case R_IA64_LTOFF_FPTR64I:
609    case R_IA64_TPREL64I:
610    case R_IA64_DTPREL64I:
611      opnd = IA64_OPND_IMMU64;
612      break;
613
614      /* Data relocations.  */
615
616    case R_IA64_DIR32MSB:
617    case R_IA64_GPREL32MSB:
618    case R_IA64_FPTR32MSB:
619    case R_IA64_PCREL32MSB:
620    case R_IA64_LTOFF_FPTR32MSB:
621    case R_IA64_SEGREL32MSB:
622    case R_IA64_SECREL32MSB:
623    case R_IA64_LTV32MSB:
624    case R_IA64_DTPREL32MSB:
625      size = 4; bigendian = 1;
626      break;
627
628    case R_IA64_DIR32LSB:
629    case R_IA64_GPREL32LSB:
630    case R_IA64_FPTR32LSB:
631    case R_IA64_PCREL32LSB:
632    case R_IA64_LTOFF_FPTR32LSB:
633    case R_IA64_SEGREL32LSB:
634    case R_IA64_SECREL32LSB:
635    case R_IA64_LTV32LSB:
636    case R_IA64_DTPREL32LSB:
637      size = 4; bigendian = 0;
638      break;
639
640    case R_IA64_DIR64MSB:
641    case R_IA64_GPREL64MSB:
642    case R_IA64_PLTOFF64MSB:
643    case R_IA64_FPTR64MSB:
644    case R_IA64_PCREL64MSB:
645    case R_IA64_LTOFF_FPTR64MSB:
646    case R_IA64_SEGREL64MSB:
647    case R_IA64_SECREL64MSB:
648    case R_IA64_LTV64MSB:
649    case R_IA64_TPREL64MSB:
650    case R_IA64_DTPMOD64MSB:
651    case R_IA64_DTPREL64MSB:
652      size = 8; bigendian = 1;
653      break;
654
655    case R_IA64_DIR64LSB:
656    case R_IA64_GPREL64LSB:
657    case R_IA64_PLTOFF64LSB:
658    case R_IA64_FPTR64LSB:
659    case R_IA64_PCREL64LSB:
660    case R_IA64_LTOFF_FPTR64LSB:
661    case R_IA64_SEGREL64LSB:
662    case R_IA64_SECREL64LSB:
663    case R_IA64_LTV64LSB:
664    case R_IA64_TPREL64LSB:
665    case R_IA64_DTPMOD64LSB:
666    case R_IA64_DTPREL64LSB:
667      size = 8; bigendian = 0;
668      break;
669
670      /* Unsupported / Dynamic relocations.  */
671    default:
672      return bfd_reloc_notsupported;
673    }
674
675  switch (opnd)
676    {
677    case IA64_OPND_IMMU64:
678      hit_addr -= (intptr_t) hit_addr & 0x3;
679      t0 = bfd_getl64 (hit_addr);
680      t1 = bfd_getl64 (hit_addr + 8);
681
682      /* tmpl/s: bits  0.. 5 in t0
683	 slot 0: bits  5..45 in t0
684	 slot 1: bits 46..63 in t0, bits 0..22 in t1
685	 slot 2: bits 23..63 in t1 */
686
687      /* First, clear the bits that form the 64 bit constant.  */
688      t0 &= ~(0x3ffffLL << 46);
689      t1 &= ~(0x7fffffLL
690	      | ((  (0x07fLL << 13) | (0x1ffLL << 27)
691		    | (0x01fLL << 22) | (0x001LL << 21)
692		    | (0x001LL << 36)) << 23));
693
694      t0 |= ((val >> 22) & 0x03ffffLL) << 46;		/* 18 lsbs of imm41 */
695      t1 |= ((val >> 40) & 0x7fffffLL) <<  0;		/* 23 msbs of imm41 */
696      t1 |= (  (((val >>  0) & 0x07f) << 13)		/* imm7b */
697	       | (((val >>  7) & 0x1ff) << 27)		/* imm9d */
698	       | (((val >> 16) & 0x01f) << 22)		/* imm5c */
699	       | (((val >> 21) & 0x001) << 21)		/* ic */
700	       | (((val >> 63) & 0x001) << 36)) << 23;	/* i */
701
702      bfd_putl64 (t0, hit_addr);
703      bfd_putl64 (t1, hit_addr + 8);
704      break;
705
706    case IA64_OPND_TGT64:
707      hit_addr -= (intptr_t) hit_addr & 0x3;
708      t0 = bfd_getl64 (hit_addr);
709      t1 = bfd_getl64 (hit_addr + 8);
710
711      /* tmpl/s: bits  0.. 5 in t0
712	 slot 0: bits  5..45 in t0
713	 slot 1: bits 46..63 in t0, bits 0..22 in t1
714	 slot 2: bits 23..63 in t1 */
715
716      /* First, clear the bits that form the 64 bit constant.  */
717      t0 &= ~(0x3ffffLL << 46);
718      t1 &= ~(0x7fffffLL
719	      | ((1LL << 36 | 0xfffffLL << 13) << 23));
720
721      val >>= 4;
722      t0 |= ((val >> 20) & 0xffffLL) << 2 << 46;	/* 16 lsbs of imm39 */
723      t1 |= ((val >> 36) & 0x7fffffLL) << 0;		/* 23 msbs of imm39 */
724      t1 |= ((((val >> 0) & 0xfffffLL) << 13)		/* imm20b */
725	      | (((val >> 59) & 0x1LL) << 36)) << 23;	/* i */
726
727      bfd_putl64 (t0, hit_addr);
728      bfd_putl64 (t1, hit_addr + 8);
729      break;
730
731    default:
732      switch ((intptr_t) hit_addr & 0x3)
733	{
734	case 0: shift =  5; break;
735	case 1: shift = 14; hit_addr += 3; break;
736	case 2: shift = 23; hit_addr += 6; break;
737	case 3: return bfd_reloc_notsupported; /* shouldn't happen...  */
738	}
739      dword = bfd_getl64 (hit_addr);
740      insn = (dword >> shift) & 0x1ffffffffffLL;
741
742      op = elf64_ia64_operands + opnd;
743      err = (*op->insert) (op, val, &insn);
744      if (err)
745	return bfd_reloc_overflow;
746
747      dword &= ~(0x1ffffffffffLL << shift);
748      dword |= (insn << shift);
749      bfd_putl64 (dword, hit_addr);
750      break;
751
752    case IA64_OPND_NIL:
753      /* A data relocation.  */
754      if (bigendian)
755	if (size == 4)
756	  bfd_putb32 (val, hit_addr);
757	else
758	  bfd_putb64 (val, hit_addr);
759      else
760	if (size == 4)
761	  bfd_putl32 (val, hit_addr);
762	else
763	  bfd_putl64 (val, hit_addr);
764      break;
765    }
766
767  return bfd_reloc_ok;
768}
769