Coverage Report

Created: 2025-06-24 06:45

/src/binutils-gdb/bfd/elfxx-ia64.c
Line
Count
Source (jump to first uncovered line)
1
/* IA-64 support for 64-bit ELF
2
   Copyright (C) 1998-2025 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
3.01k
#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
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
8
{
72
8
  if (output_bfd)
73
0
    {
74
0
      reloc->address += input_section->output_offset;
75
0
      return bfd_reloc_ok;
76
0
    }
77
78
8
  if (input_section->flags & SEC_DEBUGGING)
79
7
    return bfd_reloc_continue;
80
81
1
  *error_message = "Unsupported call to ia64_elf_reloc";
82
1
  return bfd_reloc_notsupported;
83
8
}
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 *
196
ia64_elf_lookup_howto (unsigned int rtype)
197
2.70k
{
198
2.70k
  static bool inited = false;
199
2.70k
  int i;
200
201
2.70k
  if (!inited)
202
4
    {
203
4
      inited = true;
204
205
4
      memset (elf_code_to_howto_index, 0xff, sizeof (elf_code_to_howto_index));
206
324
      for (i = 0; i < NELEMS (ia64_howto_table); ++i)
207
320
  elf_code_to_howto_index[ia64_howto_table[i].type] = i;
208
4
    }
209
210
2.70k
  if (rtype > R_IA64_MAX_RELOC_CODE)
211
17
    return NULL;
212
2.68k
  i = elf_code_to_howto_index[rtype];
213
2.68k
  if (i >= NELEMS (ia64_howto_table))
214
100
    return NULL;
215
2.58k
  return ia64_howto_table + i;
216
2.68k
}
217
218
reloc_howto_type *
219
ia64_elf_reloc_type_lookup (bfd *abfd,
220
          bfd_reloc_code_real_type bfd_code)
221
0
{
222
0
  unsigned int rtype;
223
224
0
  switch (bfd_code)
225
0
    {
226
0
    case BFD_RELOC_NONE:    rtype = R_IA64_NONE; break;
227
228
0
    case BFD_RELOC_IA64_IMM14:    rtype = R_IA64_IMM14; break;
229
0
    case BFD_RELOC_IA64_IMM22:    rtype = R_IA64_IMM22; break;
230
0
    case BFD_RELOC_IA64_IMM64:    rtype = R_IA64_IMM64; break;
231
232
0
    case BFD_RELOC_IA64_DIR32MSB: rtype = R_IA64_DIR32MSB; break;
233
0
    case BFD_RELOC_IA64_DIR32LSB: rtype = R_IA64_DIR32LSB; break;
234
0
    case BFD_RELOC_IA64_DIR64MSB: rtype = R_IA64_DIR64MSB; break;
235
0
    case BFD_RELOC_IA64_DIR64LSB: rtype = R_IA64_DIR64LSB; break;
236
237
0
    case BFD_RELOC_IA64_GPREL22:  rtype = R_IA64_GPREL22; break;
238
0
    case BFD_RELOC_IA64_GPREL64I: rtype = R_IA64_GPREL64I; break;
239
0
    case BFD_RELOC_IA64_GPREL32MSB: rtype = R_IA64_GPREL32MSB; break;
240
0
    case BFD_RELOC_IA64_GPREL32LSB: rtype = R_IA64_GPREL32LSB; break;
241
0
    case BFD_RELOC_IA64_GPREL64MSB: rtype = R_IA64_GPREL64MSB; break;
242
0
    case BFD_RELOC_IA64_GPREL64LSB: rtype = R_IA64_GPREL64LSB; break;
243
244
0
    case BFD_RELOC_IA64_LTOFF22:  rtype = R_IA64_LTOFF22; break;
245
0
    case BFD_RELOC_IA64_LTOFF64I: rtype = R_IA64_LTOFF64I; break;
246
247
0
    case BFD_RELOC_IA64_PLTOFF22: rtype = R_IA64_PLTOFF22; break;
248
0
    case BFD_RELOC_IA64_PLTOFF64I:  rtype = R_IA64_PLTOFF64I; break;
249
0
    case BFD_RELOC_IA64_PLTOFF64MSB:  rtype = R_IA64_PLTOFF64MSB; break;
250
0
    case BFD_RELOC_IA64_PLTOFF64LSB:  rtype = R_IA64_PLTOFF64LSB; break;
251
0
    case BFD_RELOC_IA64_FPTR64I:  rtype = R_IA64_FPTR64I; break;
252
0
    case BFD_RELOC_IA64_FPTR32MSB:  rtype = R_IA64_FPTR32MSB; break;
253
0
    case BFD_RELOC_IA64_FPTR32LSB:  rtype = R_IA64_FPTR32LSB; break;
254
0
    case BFD_RELOC_IA64_FPTR64MSB:  rtype = R_IA64_FPTR64MSB; break;
255
0
    case BFD_RELOC_IA64_FPTR64LSB:  rtype = R_IA64_FPTR64LSB; break;
256
257
0
    case BFD_RELOC_IA64_PCREL21B: rtype = R_IA64_PCREL21B; break;
258
0
    case BFD_RELOC_IA64_PCREL21BI:  rtype = R_IA64_PCREL21BI; break;
259
0
    case BFD_RELOC_IA64_PCREL21M: rtype = R_IA64_PCREL21M; break;
260
0
    case BFD_RELOC_IA64_PCREL21F: rtype = R_IA64_PCREL21F; break;
261
0
    case BFD_RELOC_IA64_PCREL22:  rtype = R_IA64_PCREL22; break;
262
0
    case BFD_RELOC_IA64_PCREL60B: rtype = R_IA64_PCREL60B; break;
263
0
    case BFD_RELOC_IA64_PCREL64I: rtype = R_IA64_PCREL64I; break;
264
0
    case BFD_RELOC_IA64_PCREL32MSB: rtype = R_IA64_PCREL32MSB; break;
265
0
    case BFD_RELOC_IA64_PCREL32LSB: rtype = R_IA64_PCREL32LSB; break;
266
0
    case BFD_RELOC_IA64_PCREL64MSB: rtype = R_IA64_PCREL64MSB; break;
267
0
    case BFD_RELOC_IA64_PCREL64LSB: rtype = R_IA64_PCREL64LSB; break;
268
269
0
    case BFD_RELOC_IA64_LTOFF_FPTR22: rtype = R_IA64_LTOFF_FPTR22; break;
270
0
    case BFD_RELOC_IA64_LTOFF_FPTR64I:  rtype = R_IA64_LTOFF_FPTR64I; break;
271
0
    case BFD_RELOC_IA64_LTOFF_FPTR32MSB: rtype = R_IA64_LTOFF_FPTR32MSB; break;
272
0
    case BFD_RELOC_IA64_LTOFF_FPTR32LSB: rtype = R_IA64_LTOFF_FPTR32LSB; break;
273
0
    case BFD_RELOC_IA64_LTOFF_FPTR64MSB: rtype = R_IA64_LTOFF_FPTR64MSB; break;
274
0
    case BFD_RELOC_IA64_LTOFF_FPTR64LSB: rtype = R_IA64_LTOFF_FPTR64LSB; break;
275
276
0
    case BFD_RELOC_IA64_SEGREL32MSB:  rtype = R_IA64_SEGREL32MSB; break;
277
0
    case BFD_RELOC_IA64_SEGREL32LSB:  rtype = R_IA64_SEGREL32LSB; break;
278
0
    case BFD_RELOC_IA64_SEGREL64MSB:  rtype = R_IA64_SEGREL64MSB; break;
279
0
    case BFD_RELOC_IA64_SEGREL64LSB:  rtype = R_IA64_SEGREL64LSB; break;
280
281
0
    case BFD_RELOC_IA64_SECREL32MSB:  rtype = R_IA64_SECREL32MSB; break;
282
0
    case BFD_RELOC_IA64_SECREL32LSB:  rtype = R_IA64_SECREL32LSB; break;
283
0
    case BFD_RELOC_IA64_SECREL64MSB:  rtype = R_IA64_SECREL64MSB; break;
284
0
    case BFD_RELOC_IA64_SECREL64LSB:  rtype = R_IA64_SECREL64LSB; break;
285
286
0
    case BFD_RELOC_IA64_REL32MSB: rtype = R_IA64_REL32MSB; break;
287
0
    case BFD_RELOC_IA64_REL32LSB: rtype = R_IA64_REL32LSB; break;
288
0
    case BFD_RELOC_IA64_REL64MSB: rtype = R_IA64_REL64MSB; break;
289
0
    case BFD_RELOC_IA64_REL64LSB: rtype = R_IA64_REL64LSB; break;
290
291
0
    case BFD_RELOC_IA64_LTV32MSB: rtype = R_IA64_LTV32MSB; break;
292
0
    case BFD_RELOC_IA64_LTV32LSB: rtype = R_IA64_LTV32LSB; break;
293
0
    case BFD_RELOC_IA64_LTV64MSB: rtype = R_IA64_LTV64MSB; break;
294
0
    case BFD_RELOC_IA64_LTV64LSB: rtype = R_IA64_LTV64LSB; break;
295
296
0
    case BFD_RELOC_IA64_IPLTMSB:  rtype = R_IA64_IPLTMSB; break;
297
0
    case BFD_RELOC_IA64_IPLTLSB:  rtype = R_IA64_IPLTLSB; break;
298
0
    case BFD_RELOC_IA64_COPY:   rtype = R_IA64_COPY; break;
299
0
    case BFD_RELOC_IA64_LTOFF22X: rtype = R_IA64_LTOFF22X; break;
300
0
    case BFD_RELOC_IA64_LDXMOV:   rtype = R_IA64_LDXMOV; break;
301
302
0
    case BFD_RELOC_IA64_TPREL14:  rtype = R_IA64_TPREL14; break;
303
0
    case BFD_RELOC_IA64_TPREL22:  rtype = R_IA64_TPREL22; break;
304
0
    case BFD_RELOC_IA64_TPREL64I: rtype = R_IA64_TPREL64I; break;
305
0
    case BFD_RELOC_IA64_TPREL64MSB: rtype = R_IA64_TPREL64MSB; break;
306
0
    case BFD_RELOC_IA64_TPREL64LSB: rtype = R_IA64_TPREL64LSB; break;
307
0
    case BFD_RELOC_IA64_LTOFF_TPREL22:  rtype = R_IA64_LTOFF_TPREL22; break;
308
309
0
    case BFD_RELOC_IA64_DTPMOD64MSB:  rtype = R_IA64_DTPMOD64MSB; break;
310
0
    case BFD_RELOC_IA64_DTPMOD64LSB:  rtype = R_IA64_DTPMOD64LSB; break;
311
0
    case BFD_RELOC_IA64_LTOFF_DTPMOD22: rtype = R_IA64_LTOFF_DTPMOD22; break;
312
313
0
    case BFD_RELOC_IA64_DTPREL14: rtype = R_IA64_DTPREL14; break;
314
0
    case BFD_RELOC_IA64_DTPREL22: rtype = R_IA64_DTPREL22; break;
315
0
    case BFD_RELOC_IA64_DTPREL64I:  rtype = R_IA64_DTPREL64I; break;
316
0
    case BFD_RELOC_IA64_DTPREL32MSB:  rtype = R_IA64_DTPREL32MSB; break;
317
0
    case BFD_RELOC_IA64_DTPREL32LSB:  rtype = R_IA64_DTPREL32LSB; break;
318
0
    case BFD_RELOC_IA64_DTPREL64MSB:  rtype = R_IA64_DTPREL64MSB; break;
319
0
    case BFD_RELOC_IA64_DTPREL64LSB:  rtype = R_IA64_DTPREL64LSB; break;
320
0
    case BFD_RELOC_IA64_LTOFF_DTPREL22: rtype = R_IA64_LTOFF_DTPREL22; break;
321
322
0
    default:
323
      /* xgettext:c-format */
324
0
      _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
325
0
        abfd, (int) bfd_code);
326
0
      bfd_set_error (bfd_error_bad_value);
327
0
      return NULL;
328
0
    }
329
0
  return ia64_elf_lookup_howto (rtype);
330
0
}
331
332
reloc_howto_type *
333
ia64_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
334
          const char *r_name)
335
0
{
336
0
  unsigned int i;
337
338
0
  for (i = 0;
339
0
       i < sizeof (ia64_howto_table) / sizeof (ia64_howto_table[0]);
340
0
       i++)
341
0
    if (ia64_howto_table[i].name != NULL
342
0
  && strcasecmp (ia64_howto_table[i].name, r_name) == 0)
343
0
      return &ia64_howto_table[i];
344
345
0
  return NULL;
346
0
}
347
348
0
#define BTYPE_SHIFT 6
349
0
#define Y_SHIFT   26
350
0
#define X6_SHIFT  27
351
0
#define X4_SHIFT  27
352
0
#define X3_SHIFT  33
353
0
#define X2_SHIFT  31
354
0
#define X_SHIFT   33
355
0
#define OPCODE_SHIFT  37
356
357
0
#define OPCODE_BITS (0xfLL << OPCODE_SHIFT)
358
0
#define X6_BITS   (0x3fLL << X6_SHIFT)
359
0
#define X4_BITS   (0xfLL << X4_SHIFT)
360
0
#define X3_BITS   (0x7LL << X3_SHIFT)
361
0
#define X2_BITS   (0x3LL << X2_SHIFT)
362
0
#define X_BITS    (0x1LL << X_SHIFT)
363
0
#define Y_BITS    (0x1LL << Y_SHIFT)
364
0
#define BTYPE_BITS  (0x7LL << BTYPE_SHIFT)
365
0
#define PREDICATE_BITS  (0x3fLL)
366
367
#define IS_NOP_B(i) \
368
0
  (((i) & (OPCODE_BITS | X6_BITS)) == (2LL << OPCODE_SHIFT))
369
#define IS_NOP_F(i) \
370
0
  (((i) & (OPCODE_BITS | X_BITS | X6_BITS | Y_BITS)) \
371
0
   == (0x1LL << X6_SHIFT))
372
#define IS_NOP_I(i) \
373
0
  (((i) & (OPCODE_BITS | X3_BITS | X6_BITS | Y_BITS)) \
374
0
   == (0x1LL << X6_SHIFT))
375
#define IS_NOP_M(i) \
376
0
  (((i) & (OPCODE_BITS | X3_BITS | X2_BITS | X4_BITS | Y_BITS)) \
377
0
   == (0x1LL << X4_SHIFT))
378
#define IS_BR_COND(i) \
379
0
  (((i) & (OPCODE_BITS | BTYPE_BITS)) == (0x4LL << OPCODE_SHIFT))
380
#define IS_BR_CALL(i) \
381
0
  (((i) & OPCODE_BITS) == (0x5LL << OPCODE_SHIFT))
382
383
bool
384
ia64_elf_relax_br (bfd_byte *contents, bfd_vma off)
385
0
{
386
0
  unsigned int template_val, mlx;
387
0
  bfd_vma t0, t1, s0, s1, s2, br_code;
388
0
  long br_slot;
389
0
  bfd_byte *hit_addr;
390
391
0
  hit_addr = (bfd_byte *) (contents + off);
392
0
  br_slot = (intptr_t) hit_addr & 0x3;
393
0
  hit_addr -= br_slot;
394
0
  t0 = bfd_getl64 (hit_addr + 0);
395
0
  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
0
  template_val = t0 & 0x1e;
401
0
  s0 = (t0 >> 5) & 0x1ffffffffffLL;
402
0
  s1 = ((t0 >> 46) | (t1 << 18)) & 0x1ffffffffffLL;
403
0
  s2 = (t1 >> 23) & 0x1ffffffffffLL;
404
0
  switch (br_slot)
405
0
    {
406
0
    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
0
      if (!(IS_NOP_B (s1) && IS_NOP_B (s2)))
410
0
  return false;
411
0
      br_code = s0;
412
0
      break;
413
0
    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
0
      if (!((template_val == 0x12        /* MBB */
417
0
       && IS_NOP_B (s2))
418
0
      || (template_val == 0x16      /* BBB */
419
0
    && IS_NOP_B (s0)
420
0
    && IS_NOP_B (s2))))
421
0
  return false;
422
0
      br_code = s1;
423
0
      break;
424
0
    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
0
      if (!((template_val == 0x10        /* MIB */
428
0
       && IS_NOP_I (s1))
429
0
      || (template_val == 0x12      /* MBB */
430
0
    && IS_NOP_B (s1))
431
0
      || (template_val == 0x16      /* BBB */
432
0
    && IS_NOP_B (s0)
433
0
    && IS_NOP_B (s1))
434
0
      || (template_val == 0x18      /* MMB */
435
0
    && IS_NOP_M (s1))
436
0
      || (template_val == 0x1c      /* MFB */
437
0
    && IS_NOP_F (s1))))
438
0
  return false;
439
0
      br_code = s2;
440
0
      break;
441
0
    default:
442
      /* It should never happen.  */
443
0
      abort ();
444
0
    }
445
446
  /* We can turn br.cond/br.call into brl.cond/brl.call.  */
447
0
  if (!(IS_BR_COND (br_code) || IS_BR_CALL (br_code)))
448
0
    return false;
449
450
  /* Turn br into brl by setting bit 40.  */
451
0
  br_code |= 0x1LL << 40;
452
453
  /* Turn the old bundle into a MLX bundle with the same stop-bit
454
     variety.  */
455
0
  if (t0 & 0x1)
456
0
    mlx = 0x5;
457
0
  else
458
0
    mlx = 0x4;
459
460
0
  if (template_val == 0x16)
461
0
    {
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
0
      if (br_slot == 0)
465
0
  t0 = 0LL;
466
0
      else
467
0
  t0 &= PREDICATE_BITS << 5;
468
0
      t0 |= 0x1LL << (X4_SHIFT + 5);
469
0
    }
470
0
  else
471
0
    {
472
      /* Keep the original instruction in slot 0.  */
473
0
      t0 &= 0x1ffffffffffLL << 5;
474
0
    }
475
476
0
  t0 |= mlx;
477
478
  /* Put brl in slot 1.  */
479
0
  t1 = br_code << 23;
480
481
0
  bfd_putl64 (t0, hit_addr);
482
0
  bfd_putl64 (t1, hit_addr + 8);
483
0
  return true;
484
0
}
485
486
void
487
ia64_elf_relax_brl (bfd_byte *contents, bfd_vma off)
488
0
{
489
0
  int template_val;
490
0
  bfd_byte *hit_addr;
491
0
  bfd_vma t0, t1, i0, i1, i2;
492
493
0
  hit_addr = (bfd_byte *) (contents + off);
494
0
  hit_addr -= (intptr_t) hit_addr & 0x3;
495
0
  t0 = bfd_getl64 (hit_addr);
496
0
  t1 = bfd_getl64 (hit_addr + 8);
497
498
  /* Keep the instruction in slot 0. */
499
0
  i0 = (t0 >> 5) & 0x1ffffffffffLL;
500
  /* Use nop.b for slot 1. */
501
0
  i1 = 0x4000000000LL;
502
  /* For slot 2, turn brl into br by masking out bit 40.  */
503
0
  i2 = (t1 >> 23) & 0x0ffffffffffLL;
504
505
  /* Turn a MLX bundle into a MBB bundle with the same stop-bit
506
     variety.  */
507
0
  if (t0 & 0x1)
508
0
    template_val = 0x13;
509
0
  else
510
0
    template_val = 0x12;
511
0
  t0 = (i1 << 46) | (i0 << 5) | template_val;
512
0
  t1 = (i2 << 23) | (i1 >> 18);
513
514
0
  bfd_putl64 (t0, hit_addr);
515
0
  bfd_putl64 (t1, hit_addr + 8);
516
0
}
517
518
void
519
ia64_elf_relax_ldxmov (bfd_byte *contents, bfd_vma off)
520
0
{
521
0
  int shift, r1, r3;
522
0
  bfd_vma dword, insn;
523
524
0
  switch ((int)off & 0x3)
525
0
    {
526
0
    case 0: shift =  5; break;
527
0
    case 1: shift = 14; off += 3; break;
528
0
    case 2: shift = 23; off += 6; break;
529
0
    default:
530
0
      abort ();
531
0
    }
532
533
0
  dword = bfd_getl64 (contents + off);
534
0
  insn = (dword >> shift) & 0x1ffffffffffLL;
535
536
0
  r1 = (insn >> 6) & 127;
537
0
  r3 = (insn >> 20) & 127;
538
0
  if (r1 == r3)
539
0
    insn = 0x8000000;          /* nop */
540
0
  else
541
0
    insn = (insn & 0x7f01fff) | 0x10800000000LL;   /* (qp) mov r1 = r3 */
542
543
0
  dword &= ~(0x1ffffffffffLL << shift);
544
0
  dword |= (insn << shift);
545
0
  bfd_putl64 (dword, contents + off);
546
0
}
547

548
bfd_reloc_status_type
549
ia64_elf_install_value (bfd_byte *hit_addr, bfd_vma v, unsigned int r_type)
550
0
{
551
0
  const struct ia64_operand *op;
552
0
  int bigendian = 0, shift = 0;
553
0
  bfd_vma t0, t1, dword;
554
0
  ia64_insn insn;
555
0
  enum ia64_opnd opnd;
556
0
  const char *err;
557
0
  size_t size = 8;
558
0
  uint64_t val = v;
559
560
0
  opnd = IA64_OPND_NIL;
561
0
  switch (r_type)
562
0
    {
563
0
    case R_IA64_NONE:
564
0
    case R_IA64_LDXMOV:
565
0
      return bfd_reloc_ok;
566
567
      /* Instruction relocations.  */
568
569
0
    case R_IA64_IMM14:
570
0
    case R_IA64_TPREL14:
571
0
    case R_IA64_DTPREL14:
572
0
      opnd = IA64_OPND_IMM14;
573
0
      break;
574
575
0
    case R_IA64_PCREL21F: opnd = IA64_OPND_TGT25; break;
576
0
    case R_IA64_PCREL21M: opnd = IA64_OPND_TGT25b; break;
577
0
    case R_IA64_PCREL60B: opnd = IA64_OPND_TGT64; break;
578
0
    case R_IA64_PCREL21B:
579
0
    case R_IA64_PCREL21BI:
580
0
      opnd = IA64_OPND_TGT25c;
581
0
      break;
582
583
0
    case R_IA64_IMM22:
584
0
    case R_IA64_GPREL22:
585
0
    case R_IA64_LTOFF22:
586
0
    case R_IA64_LTOFF22X:
587
0
    case R_IA64_PLTOFF22:
588
0
    case R_IA64_PCREL22:
589
0
    case R_IA64_LTOFF_FPTR22:
590
0
    case R_IA64_TPREL22:
591
0
    case R_IA64_DTPREL22:
592
0
    case R_IA64_LTOFF_TPREL22:
593
0
    case R_IA64_LTOFF_DTPMOD22:
594
0
    case R_IA64_LTOFF_DTPREL22:
595
0
      opnd = IA64_OPND_IMM22;
596
0
      break;
597
598
0
    case R_IA64_IMM64:
599
0
    case R_IA64_GPREL64I:
600
0
    case R_IA64_LTOFF64I:
601
0
    case R_IA64_PLTOFF64I:
602
0
    case R_IA64_PCREL64I:
603
0
    case R_IA64_FPTR64I:
604
0
    case R_IA64_LTOFF_FPTR64I:
605
0
    case R_IA64_TPREL64I:
606
0
    case R_IA64_DTPREL64I:
607
0
      opnd = IA64_OPND_IMMU64;
608
0
      break;
609
610
      /* Data relocations.  */
611
612
0
    case R_IA64_DIR32MSB:
613
0
    case R_IA64_GPREL32MSB:
614
0
    case R_IA64_FPTR32MSB:
615
0
    case R_IA64_PCREL32MSB:
616
0
    case R_IA64_LTOFF_FPTR32MSB:
617
0
    case R_IA64_SEGREL32MSB:
618
0
    case R_IA64_SECREL32MSB:
619
0
    case R_IA64_LTV32MSB:
620
0
    case R_IA64_DTPREL32MSB:
621
0
      size = 4; bigendian = 1;
622
0
      break;
623
624
0
    case R_IA64_DIR32LSB:
625
0
    case R_IA64_GPREL32LSB:
626
0
    case R_IA64_FPTR32LSB:
627
0
    case R_IA64_PCREL32LSB:
628
0
    case R_IA64_LTOFF_FPTR32LSB:
629
0
    case R_IA64_SEGREL32LSB:
630
0
    case R_IA64_SECREL32LSB:
631
0
    case R_IA64_LTV32LSB:
632
0
    case R_IA64_DTPREL32LSB:
633
0
      size = 4; bigendian = 0;
634
0
      break;
635
636
0
    case R_IA64_DIR64MSB:
637
0
    case R_IA64_GPREL64MSB:
638
0
    case R_IA64_PLTOFF64MSB:
639
0
    case R_IA64_FPTR64MSB:
640
0
    case R_IA64_PCREL64MSB:
641
0
    case R_IA64_LTOFF_FPTR64MSB:
642
0
    case R_IA64_SEGREL64MSB:
643
0
    case R_IA64_SECREL64MSB:
644
0
    case R_IA64_LTV64MSB:
645
0
    case R_IA64_TPREL64MSB:
646
0
    case R_IA64_DTPMOD64MSB:
647
0
    case R_IA64_DTPREL64MSB:
648
0
      size = 8; bigendian = 1;
649
0
      break;
650
651
0
    case R_IA64_DIR64LSB:
652
0
    case R_IA64_GPREL64LSB:
653
0
    case R_IA64_PLTOFF64LSB:
654
0
    case R_IA64_FPTR64LSB:
655
0
    case R_IA64_PCREL64LSB:
656
0
    case R_IA64_LTOFF_FPTR64LSB:
657
0
    case R_IA64_SEGREL64LSB:
658
0
    case R_IA64_SECREL64LSB:
659
0
    case R_IA64_LTV64LSB:
660
0
    case R_IA64_TPREL64LSB:
661
0
    case R_IA64_DTPMOD64LSB:
662
0
    case R_IA64_DTPREL64LSB:
663
0
      size = 8; bigendian = 0;
664
0
      break;
665
666
      /* Unsupported / Dynamic relocations.  */
667
0
    default:
668
0
      return bfd_reloc_notsupported;
669
0
    }
670
671
0
  switch (opnd)
672
0
    {
673
0
    case IA64_OPND_IMMU64:
674
0
      hit_addr -= (intptr_t) hit_addr & 0x3;
675
0
      t0 = bfd_getl64 (hit_addr);
676
0
      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
0
      t0 &= ~(0x3ffffULL << 46);
685
0
      t1 &= ~(0x7fffffLL
686
0
        | ((  (0x07fLL << 13) | (0x1ffLL << 27)
687
0
        | (0x01fLL << 22) | (0x001LL << 21)
688
0
        | (0x001LL << 36)) << 23));
689
690
0
      t0 |= ((val >> 22) & 0x03ffffLL) << 46;   /* 18 lsbs of imm41 */
691
0
      t1 |= ((val >> 40) & 0x7fffffLL) <<  0;   /* 23 msbs of imm41 */
692
0
      t1 |= (  (((val >>  0) & 0x07f) << 13)    /* imm7b */
693
0
         | (((val >>  7) & 0x1ff) << 27)    /* imm9d */
694
0
         | (((val >> 16) & 0x01f) << 22)    /* imm5c */
695
0
         | (((val >> 21) & 0x001) << 21)    /* ic */
696
0
         | (((val >> 63) & 0x001) << 36)) << 23;  /* i */
697
698
0
      bfd_putl64 (t0, hit_addr);
699
0
      bfd_putl64 (t1, hit_addr + 8);
700
0
      break;
701
702
0
    case IA64_OPND_TGT64:
703
0
      hit_addr -= (intptr_t) hit_addr & 0x3;
704
0
      t0 = bfd_getl64 (hit_addr);
705
0
      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
0
      t0 &= ~(0x3ffffULL << 46);
714
0
      t1 &= ~(0x7fffffLL
715
0
        | ((1LL << 36 | 0xfffffLL << 13) << 23));
716
717
0
      val >>= 4;
718
0
      t0 |= ((val >> 20) & 0xffffLL) << 2 << 46;  /* 16 lsbs of imm39 */
719
0
      t1 |= ((val >> 36) & 0x7fffffLL) << 0;    /* 23 msbs of imm39 */
720
0
      t1 |= ((((val >> 0) & 0xfffffLL) << 13)   /* imm20b */
721
0
        | (((val >> 59) & 0x1LL) << 36)) << 23; /* i */
722
723
0
      bfd_putl64 (t0, hit_addr);
724
0
      bfd_putl64 (t1, hit_addr + 8);
725
0
      break;
726
727
0
    default:
728
0
      switch ((intptr_t) hit_addr & 0x3)
729
0
  {
730
0
  case 0: shift =  5; break;
731
0
  case 1: shift = 14; hit_addr += 3; break;
732
0
  case 2: shift = 23; hit_addr += 6; break;
733
0
  case 3: return bfd_reloc_notsupported; /* shouldn't happen...  */
734
0
  }
735
0
      dword = bfd_getl64 (hit_addr);
736
0
      insn = (dword >> shift) & 0x1ffffffffffLL;
737
738
0
      op = elf64_ia64_operands + opnd;
739
0
      err = (*op->insert) (op, val, &insn);
740
0
      if (err)
741
0
  return bfd_reloc_overflow;
742
743
0
      dword &= ~(0x1ffffffffffULL << shift);
744
0
      dword |= (insn << shift);
745
0
      bfd_putl64 (dword, hit_addr);
746
0
      break;
747
748
0
    case IA64_OPND_NIL:
749
      /* A data relocation.  */
750
0
      if (bigendian)
751
0
  if (size == 4)
752
0
    bfd_putb32 (val, hit_addr);
753
0
  else
754
0
    bfd_putb64 (val, hit_addr);
755
0
      else
756
0
  if (size == 4)
757
0
    bfd_putl32 (val, hit_addr);
758
0
  else
759
0
    bfd_putl64 (val, hit_addr);
760
0
      break;
761
0
    }
762
763
0
  return bfd_reloc_ok;
764
0
}