Coverage Report

Created: 2023-06-29 07:03

/src/binutils-gdb/bfd/coff-aarch64.c
Line
Count
Source (jump to first uncovered line)
1
/* BFD back-end for AArch64 COFF files.
2
   Copyright (C) 2021-2023 Free Software Foundation, Inc.
3
4
   This file is part of BFD, the Binary File Descriptor library.
5
6
   This program is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3 of the License, or
9
   (at your option) any later version.
10
11
   This program is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
16
   You should have received a copy of the GNU General Public License
17
   along with this program; if not, write to the Free Software
18
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19
   MA 02110-1301, USA.  */
20
21
22
#ifndef COFF_WITH_peAArch64
23
#define COFF_WITH_peAArch64
24
#endif
25
26
/* Note we have to make sure not to include headers twice.
27
   Not all headers are wrapped in #ifdef guards, so we define
28
   PEI_HEADERS to prevent double including here.  */
29
#ifndef PEI_HEADERS
30
#include "sysdep.h"
31
#include "bfd.h"
32
#include "libbfd.h"
33
#include "coff/aarch64.h"
34
#include "coff/internal.h"
35
#include "coff/pe.h"
36
#include "libcoff.h"
37
#include "libiberty.h"
38
#endif
39
40
#include "libcoff.h"
41
42
/* For these howto special functions,
43
   output_bfd == NULL => final link, or objdump -W and other calls to
44
   bfd_simple_get_relocated_section_contents
45
   output_bfd != NULL && output_bfd != abfd => ld -r
46
   output_bfd != NULL && output_bfd == abfd => gas.
47
   FIXME: ld -r is punted to bfd_perform_relocation.  This won't be
48
   correct for cases where the addend needs to be adjusted, eg. for
49
   relocations against section symbols, and the field is split because
50
   bfd_perform_relocation can't write addends to split relocation fields.  */
51
52
static bfd_reloc_status_type
53
coff_aarch64_rel21_reloc (bfd *abfd,
54
        arelent *reloc_entry,
55
        asymbol *symbol,
56
        void *data,
57
        asection *input_section,
58
        bfd *output_bfd,
59
        char **error_message ATTRIBUTE_UNUSED)
60
0
{
61
0
  if (output_bfd != NULL && output_bfd != abfd)
62
0
    return bfd_reloc_continue;
63
64
0
  if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
65
0
          input_section, reloc_entry->address))
66
0
    return bfd_reloc_outofrange;
67
68
0
  uint32_t op = bfd_getl32 (data + reloc_entry->address);
69
0
  bfd_vma relocation = reloc_entry->addend;
70
0
  bfd_reloc_status_type ret = bfd_reloc_ok;
71
0
  if (output_bfd == NULL)
72
0
    {
73
0
      if (bfd_is_und_section (symbol->section))
74
0
  {
75
0
    if ((symbol->flags & BSF_WEAK) == 0)
76
0
      ret = bfd_reloc_undefined;
77
0
  }
78
0
      else if (!bfd_is_com_section (symbol->section))
79
0
  relocation += (symbol->value
80
0
           + symbol->section->output_offset
81
0
           + symbol->section->output_section->vma);
82
0
      bfd_vma addend = ((op >> 3) & 0x1ffffc) | ((op >> 29) & 0x3);
83
0
      addend = (addend ^ 0x100000) - 0x100000;
84
0
      relocation += addend;
85
0
      relocation -= (reloc_entry->address
86
0
         + input_section->output_offset
87
0
         + input_section->output_section->vma);
88
0
      relocation = (bfd_signed_vma) relocation >> reloc_entry->howto->rightshift;
89
0
    }
90
0
  if (relocation + 0x100000 > 0x1fffff)
91
0
    ret = bfd_reloc_overflow;
92
93
0
  op &= 0x9f00001f;
94
0
  op |= (relocation & 0x1ffffc) << 3;
95
0
  op |= (relocation & 0x3) << 29;
96
97
0
  bfd_putl32 (op, data + reloc_entry->address);
98
99
0
  return ret;
100
0
}
Unexecuted instantiation: pei-aarch64.c:coff_aarch64_rel21_reloc
Unexecuted instantiation: pe-aarch64.c:coff_aarch64_rel21_reloc
101
102
static bfd_reloc_status_type
103
coff_aarch64_po12l_reloc (bfd *abfd,
104
        arelent *reloc_entry,
105
        asymbol *symbol ATTRIBUTE_UNUSED,
106
        void *data,
107
        asection *input_section,
108
        bfd *output_bfd,
109
        char **error_message ATTRIBUTE_UNUSED)
110
0
{
111
0
  if (output_bfd != NULL && output_bfd != abfd)
112
0
    return bfd_reloc_continue;
113
114
0
  if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
115
0
          input_section, reloc_entry->address))
116
0
    return bfd_reloc_outofrange;
117
118
0
  uint32_t op = bfd_getl32 (data + reloc_entry->address);
119
0
  bfd_vma relocation = reloc_entry->addend & 0xfff;
120
0
  int shift;
121
122
0
  if ((op & 0xff800000) == 0x3d800000)
123
0
    {
124
      /* LDR / STR with q register */
125
0
      shift = 4;
126
0
    }
127
0
  else
128
0
    {
129
      /* top two bits represent how much addend should be shifted */
130
0
      shift = op >> 30;
131
0
    }
132
133
0
  bfd_reloc_status_type ret = bfd_reloc_ok;
134
0
  if (output_bfd == NULL)
135
0
    {
136
0
      if (bfd_is_und_section (symbol->section))
137
0
  {
138
0
    if ((symbol->flags & BSF_WEAK) == 0)
139
0
      ret = bfd_reloc_undefined;
140
0
  }
141
0
      else if (!bfd_is_com_section (symbol->section))
142
0
  relocation += (symbol->value
143
0
           + symbol->section->output_offset
144
0
           + symbol->section->output_section->vma);
145
0
      bfd_vma addend = (op >> 10) & 0xfff;
146
0
      addend <<= shift;
147
0
      relocation += addend;
148
0
    }
149
150
0
  if (relocation & ((1 << shift) - 1))
151
0
    ret = bfd_reloc_overflow;
152
153
0
  op &= 0xffc003ff;
154
0
  op |= (relocation >> shift << 10) & 0x3ffc00;
155
156
0
  bfd_putl32 (op, data + reloc_entry->address);
157
158
0
  return ret;
159
0
}
Unexecuted instantiation: pei-aarch64.c:coff_aarch64_po12l_reloc
Unexecuted instantiation: pe-aarch64.c:coff_aarch64_po12l_reloc
160
161
static bfd_reloc_status_type
162
coff_aarch64_addr32nb_reloc (bfd *abfd,
163
           arelent *reloc_entry,
164
           asymbol *symbol ATTRIBUTE_UNUSED,
165
           void *data,
166
           asection *input_section,
167
           bfd *output_bfd,
168
           char **error_message)
169
0
{
170
0
  if (output_bfd != NULL && output_bfd != abfd)
171
0
    return bfd_reloc_continue;
172
173
0
  if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
174
0
          input_section, reloc_entry->address))
175
0
    return bfd_reloc_outofrange;
176
177
0
  bfd_vma relocation = reloc_entry->addend;
178
0
  bfd_reloc_status_type ret = bfd_reloc_ok;
179
0
  if (output_bfd == NULL)
180
0
    {
181
0
      if (bfd_is_und_section (symbol->section))
182
0
  {
183
0
    if ((symbol->flags & BSF_WEAK) == 0)
184
0
      ret = bfd_reloc_undefined;
185
0
  }
186
0
      else if (!bfd_is_com_section (symbol->section))
187
0
  relocation += (symbol->value
188
0
           + symbol->section->output_offset
189
0
           + symbol->section->output_section->vma);
190
0
      bfd_vma addend = bfd_getl_signed_32 (data + reloc_entry->address);
191
0
      relocation += addend;
192
0
      bfd *obfd = input_section->output_section->owner;
193
0
      if (bfd_get_flavour (obfd) == bfd_target_coff_flavour
194
0
    && obj_pe (obfd))
195
0
  relocation -= pe_data (obfd)->pe_opthdr.ImageBase;
196
0
      else
197
0
  {
198
0
    *error_message = "unsupported";
199
0
    return bfd_reloc_dangerous;
200
0
  }
201
0
    }
202
203
0
  if (relocation + 0x80000000 > 0xffffffff)
204
0
    ret = bfd_reloc_overflow;
205
206
0
  bfd_putl32 (relocation, data + reloc_entry->address);
207
208
0
  return ret;
209
0
}
Unexecuted instantiation: pei-aarch64.c:coff_aarch64_addr32nb_reloc
Unexecuted instantiation: pe-aarch64.c:coff_aarch64_addr32nb_reloc
210
211
static bfd_reloc_status_type
212
coff_aarch64_secrel_reloc (bfd *abfd,
213
         arelent *reloc_entry,
214
         asymbol *symbol ATTRIBUTE_UNUSED,
215
         void *data,
216
         asection *input_section,
217
         bfd *output_bfd,
218
         char **error_message ATTRIBUTE_UNUSED)
219
0
{
220
0
  if (output_bfd != NULL && output_bfd != abfd)
221
0
    return bfd_reloc_continue;
222
223
0
  if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
224
0
          input_section, reloc_entry->address))
225
0
    return bfd_reloc_outofrange;
226
227
0
  bfd_vma relocation = reloc_entry->addend;
228
0
  bfd_reloc_status_type ret = bfd_reloc_ok;
229
0
  if (output_bfd == NULL)
230
0
    {
231
0
      if (bfd_is_und_section (symbol->section))
232
0
  {
233
0
    if ((symbol->flags & BSF_WEAK) == 0)
234
0
      ret = bfd_reloc_undefined;
235
0
  }
236
0
      else if (!bfd_is_com_section (symbol->section))
237
0
  relocation += (symbol->value
238
0
           + symbol->section->output_offset);
239
0
      bfd_vma addend = bfd_getl_signed_32 (data + reloc_entry->address);
240
0
      relocation += addend;
241
0
    }
242
0
  if (relocation > 0xffffffff)
243
0
    ret = bfd_reloc_overflow;
244
245
0
  bfd_putl32 (relocation, data + reloc_entry->address);
246
247
0
  return ret;
248
0
}
Unexecuted instantiation: pei-aarch64.c:coff_aarch64_secrel_reloc
Unexecuted instantiation: pe-aarch64.c:coff_aarch64_secrel_reloc
249
250
#define coff_aarch64_NULL NULL
251
#undef HOWTO_INSTALL_ADDEND
252
#define HOWTO_INSTALL_ADDEND 1
253
#define HOW(type, right, size, bits, pcrel, left, ovf, func, mask) \
254
  HOWTO (type, right, size, bits, pcrel, left, complain_overflow_##ovf, \
255
   coff_aarch64_##func, #type, true, mask, mask, false)
256
257
static const reloc_howto_type arm64_reloc_howto_abs
258
= HOW (IMAGE_REL_ARM64_ABSOLUTE,
259
       0, 0, 0, false, 0, dont, NULL, 0);
260
261
static const reloc_howto_type arm64_reloc_howto_64
262
= HOW (IMAGE_REL_ARM64_ADDR64,
263
       0, 8, 64, false, 0, dont, NULL, UINT64_C (-1));
264
265
static const reloc_howto_type arm64_reloc_howto_32
266
= HOW (IMAGE_REL_ARM64_ADDR32,
267
       0, 4, 32, false, 0, signed, NULL, 0xffffffff);
268
269
static const reloc_howto_type arm64_reloc_howto_32_pcrel
270
= HOW (IMAGE_REL_ARM64_REL32,
271
       0, 4, 32, true, 0, signed, NULL, 0xffffffff);
272
273
static const reloc_howto_type arm64_reloc_howto_branch26
274
= HOW (IMAGE_REL_ARM64_BRANCH26,
275
       2, 4, 26, true, 0, signed, NULL, 0x3ffffff);
276
277
static const reloc_howto_type arm64_reloc_howto_page21
278
= HOW (IMAGE_REL_ARM64_PAGEBASE_REL21,
279
       12, 4, 21, true, 0, signed, rel21_reloc, 0x1fffff);
280
281
static const reloc_howto_type arm64_reloc_howto_lo21
282
= HOW (IMAGE_REL_ARM64_REL21,
283
       0, 4, 21, true, 0, signed, rel21_reloc, 0x1fffff);
284
285
static const reloc_howto_type arm64_reloc_howto_pgoff12l
286
= HOW (IMAGE_REL_ARM64_PAGEOFFSET_12L,
287
       0, 4, 12, true, 10, signed, po12l_reloc, 0x3ffc00);
288
289
static const reloc_howto_type arm64_reloc_howto_branch19
290
= HOW (IMAGE_REL_ARM64_BRANCH19,
291
       2, 4, 19, true, 5, signed, NULL, 0xffffe0);
292
293
static const reloc_howto_type arm64_reloc_howto_branch14
294
= HOW (IMAGE_REL_ARM64_BRANCH14,
295
       2, 4, 14, true, 5, signed, NULL, 0x7ffe0);
296
297
static const reloc_howto_type arm64_reloc_howto_pgoff12a
298
= HOW (IMAGE_REL_ARM64_PAGEOFFSET_12A,
299
       0, 4, 12, true, 10, dont, NULL, 0x3ffc00);
300
301
static const reloc_howto_type arm64_reloc_howto_32nb
302
= HOW (IMAGE_REL_ARM64_ADDR32NB,
303
       0, 4, 32, false, 0, signed, addr32nb_reloc, 0xffffffff);
304
305
static const reloc_howto_type arm64_reloc_howto_secrel
306
= HOW (IMAGE_REL_ARM64_SECREL,
307
       0, 4, 32, false, 0, dont, secrel_reloc, 0xffffffff);
308
309
static const reloc_howto_type arm64_reloc_howto_secidx
310
= HOW (IMAGE_REL_ARM64_SECTION,
311
       0, 2, 16, false, 0, dont, NULL, 0xffff);
312
313
static const reloc_howto_type* const arm64_howto_table[] = {
314
     &arm64_reloc_howto_abs,
315
     &arm64_reloc_howto_64,
316
     &arm64_reloc_howto_32,
317
     &arm64_reloc_howto_32_pcrel,
318
     &arm64_reloc_howto_branch26,
319
     &arm64_reloc_howto_page21,
320
     &arm64_reloc_howto_lo21,
321
     &arm64_reloc_howto_pgoff12l,
322
     &arm64_reloc_howto_branch19,
323
     &arm64_reloc_howto_branch14,
324
     &arm64_reloc_howto_pgoff12a,
325
     &arm64_reloc_howto_32nb,
326
     &arm64_reloc_howto_secrel,
327
     &arm64_reloc_howto_secidx
328
};
329
330
/* No adjustment to addends should be needed.  The actual relocation
331
   addend is in the section contents.  Unfortunately this means actual
332
   addends are not shown by objdump -r, but that's true for most
333
   COFF/PE targets where arelent.addend is an adjustment.  */
334
#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)    \
335
0
  cache_ptr->addend = 0;
336
337
#ifndef NUM_ELEM
338
0
#define NUM_ELEM(a) ((sizeof (a)) / sizeof ((a)[0]))
339
#endif
340
341
0
#define NUM_RELOCS NUM_ELEM (arm64_howto_table)
342
343
#define coff_bfd_reloc_type_lookup    coff_aarch64_reloc_type_lookup
344
#define coff_bfd_reloc_name_lookup    coff_aarch64_reloc_name_lookup
345
346
static reloc_howto_type *
347
coff_aarch64_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code)
348
0
{
349
0
  switch (code)
350
0
  {
351
0
  case BFD_RELOC_64:
352
0
    return &arm64_reloc_howto_64;
353
0
  case BFD_RELOC_32:
354
0
    return &arm64_reloc_howto_32;
355
0
  case BFD_RELOC_32_PCREL:
356
0
    return &arm64_reloc_howto_32_pcrel;
357
0
  case BFD_RELOC_AARCH64_CALL26:
358
0
  case BFD_RELOC_AARCH64_JUMP26:
359
0
    return &arm64_reloc_howto_branch26;
360
0
  case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
361
0
  case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL:
362
0
    return &arm64_reloc_howto_page21;
363
0
  case BFD_RELOC_AARCH64_TSTBR14:
364
0
    return &arm64_reloc_howto_branch14;
365
0
  case BFD_RELOC_AARCH64_ADR_LO21_PCREL:
366
0
    return &arm64_reloc_howto_lo21;
367
0
  case BFD_RELOC_AARCH64_ADD_LO12:
368
0
    return &arm64_reloc_howto_pgoff12a;
369
0
  case BFD_RELOC_AARCH64_LDST8_LO12:
370
0
  case BFD_RELOC_AARCH64_LDST16_LO12:
371
0
  case BFD_RELOC_AARCH64_LDST32_LO12:
372
0
  case BFD_RELOC_AARCH64_LDST64_LO12:
373
0
  case BFD_RELOC_AARCH64_LDST128_LO12:
374
0
    return &arm64_reloc_howto_pgoff12l;
375
0
  case BFD_RELOC_AARCH64_BRANCH19:
376
0
    return &arm64_reloc_howto_branch19;
377
0
  case BFD_RELOC_RVA:
378
0
    return &arm64_reloc_howto_32nb;
379
0
  case BFD_RELOC_32_SECREL:
380
0
    return &arm64_reloc_howto_secrel;
381
0
  case BFD_RELOC_16_SECIDX:
382
0
    return &arm64_reloc_howto_secidx;
383
0
  default:
384
0
    BFD_FAIL ();
385
0
    return NULL;
386
0
  }
387
388
0
  return NULL;
389
0
}
Unexecuted instantiation: pei-aarch64.c:coff_aarch64_reloc_type_lookup
Unexecuted instantiation: pe-aarch64.c:coff_aarch64_reloc_type_lookup
390
391
static reloc_howto_type *
392
coff_aarch64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
393
          const char *r_name)
394
0
{
395
0
  unsigned int i;
396
397
0
  for (i = 0; i < NUM_RELOCS; i++)
398
0
    if (arm64_howto_table[i]->name != NULL
399
0
      && strcasecmp (arm64_howto_table[i]->name, r_name) == 0)
400
0
      return arm64_howto_table[i];
401
402
0
  return NULL;
403
0
}
Unexecuted instantiation: pei-aarch64.c:coff_aarch64_reloc_name_lookup
Unexecuted instantiation: pe-aarch64.c:coff_aarch64_reloc_name_lookup
404
405
0
#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER  2
406
0
#define COFF_PAGE_SIZE            0x1000
407
408
static reloc_howto_type *
409
coff_aarch64_rtype_lookup (unsigned int code)
410
0
{
411
0
  switch (code)
412
0
  {
413
0
    case IMAGE_REL_ARM64_ABSOLUTE:
414
0
      return &arm64_reloc_howto_abs;
415
0
    case IMAGE_REL_ARM64_ADDR64:
416
0
      return &arm64_reloc_howto_64;
417
0
    case IMAGE_REL_ARM64_ADDR32:
418
0
      return &arm64_reloc_howto_32;
419
0
    case IMAGE_REL_ARM64_REL32:
420
0
      return &arm64_reloc_howto_32_pcrel;
421
0
    case IMAGE_REL_ARM64_BRANCH26:
422
0
      return &arm64_reloc_howto_branch26;
423
0
    case IMAGE_REL_ARM64_PAGEBASE_REL21:
424
0
      return &arm64_reloc_howto_page21;
425
0
    case IMAGE_REL_ARM64_REL21:
426
0
      return &arm64_reloc_howto_lo21;
427
0
    case IMAGE_REL_ARM64_PAGEOFFSET_12L:
428
0
      return &arm64_reloc_howto_pgoff12l;
429
0
    case IMAGE_REL_ARM64_BRANCH19:
430
0
      return &arm64_reloc_howto_branch19;
431
0
    case IMAGE_REL_ARM64_BRANCH14:
432
0
      return &arm64_reloc_howto_branch14;
433
0
    case IMAGE_REL_ARM64_PAGEOFFSET_12A:
434
0
      return &arm64_reloc_howto_pgoff12a;
435
0
    case IMAGE_REL_ARM64_ADDR32NB:
436
0
      return &arm64_reloc_howto_32nb;
437
0
    case IMAGE_REL_ARM64_SECREL:
438
0
      return &arm64_reloc_howto_secrel;
439
0
    case IMAGE_REL_ARM64_SECTION:
440
0
      return &arm64_reloc_howto_secidx;
441
0
    default:
442
0
      return NULL;
443
0
  }
444
445
0
  return NULL;
446
0
}
Unexecuted instantiation: pei-aarch64.c:coff_aarch64_rtype_lookup
Unexecuted instantiation: pe-aarch64.c:coff_aarch64_rtype_lookup
447
448
#define RTYPE2HOWTO(cache_ptr, dst)         \
449
0
  ((cache_ptr)->howto = coff_aarch64_rtype_lookup((dst)->r_type))
450
451
static reloc_howto_type *
452
coff_aarch64_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
453
           asection *sec ATTRIBUTE_UNUSED,
454
           struct internal_reloc *rel,
455
           struct coff_link_hash_entry *h ATTRIBUTE_UNUSED,
456
           struct internal_syment *sym ATTRIBUTE_UNUSED,
457
           bfd_vma *addendp)
458
0
{
459
0
  reloc_howto_type *howto = coff_aarch64_rtype_lookup (rel->r_type);
460
461
  /* Cancel out code in _bfd_coff_generic_relocate_section.  */
462
0
  *addendp = 0;
463
464
0
  return howto;
465
0
}
Unexecuted instantiation: pei-aarch64.c:coff_aarch64_rtype_to_howto
Unexecuted instantiation: pe-aarch64.c:coff_aarch64_rtype_to_howto
466
467
#define coff_rtype_to_howto coff_aarch64_rtype_to_howto
468
469
0
#define SELECT_RELOC(x,howto) { (x).r_type = (howto)->type; }
470
471
#ifndef bfd_pe_print_pdata
472
#define bfd_pe_print_pdata      NULL
473
#endif
474
475
#ifdef COFF_WITH_PE
476
/* Return TRUE if this relocation should
477
   appear in the output .reloc section.  */
478
479
static bool
480
in_reloc_p (bfd * abfd ATTRIBUTE_UNUSED,
481
            reloc_howto_type * howto)
482
0
{
483
0
  return !howto->pc_relative;
484
0
}
Unexecuted instantiation: pei-aarch64.c:in_reloc_p
Unexecuted instantiation: pe-aarch64.c:in_reloc_p
485
#endif
486
487
static bool
488
coff_pe_aarch64_relocate_section (bfd *output_bfd,
489
          struct bfd_link_info *info,
490
          bfd *input_bfd,
491
          asection *input_section,
492
          bfd_byte *contents,
493
          struct internal_reloc *relocs,
494
          struct internal_syment *syms,
495
          asection **sections)
496
0
{
497
0
  struct internal_reloc *rel;
498
0
  struct internal_reloc *relend;
499
500
0
  if (bfd_link_relocatable (info))
501
0
    return true;
502
503
0
  rel = relocs;
504
0
  relend = rel + input_section->reloc_count;
505
506
  /* The addend for a relocation is stored in the immediate bits of each
507
     opcode.  So for each relocation, we need to extract the immediate value,
508
     use this to calculate what it should be for the symbol, and rewrite the
509
     opcode into the section stream.  */
510
511
0
  for (; rel < relend; rel++)
512
0
    {
513
0
      long symndx;
514
0
      struct coff_link_hash_entry *h;
515
0
      bfd_vma sym_value;
516
0
      asection *sec = NULL;
517
0
      uint64_t dest_vma;
518
519
      /* skip trivial relocations */
520
0
      if (rel->r_type == IMAGE_REL_ARM64_ADDR32
521
0
    || rel->r_type == IMAGE_REL_ARM64_ADDR64
522
0
    || rel->r_type == IMAGE_REL_ARM64_ABSOLUTE)
523
0
  continue;
524
525
0
      symndx = rel->r_symndx;
526
0
      sym_value = syms[symndx].n_value;
527
528
0
      h = obj_coff_sym_hashes (input_bfd)[symndx];
529
530
0
      if (h && h->root.type == bfd_link_hash_defined)
531
0
  {
532
0
    sec = h->root.u.def.section;
533
0
    sym_value = h->root.u.def.value;
534
0
  }
535
0
      else
536
0
  {
537
0
    sec = sections[symndx];
538
0
  }
539
540
0
      if (!sec)
541
0
  continue;
542
543
0
      if (bfd_is_und_section (sec))
544
0
  continue;
545
546
0
      if (discarded_section (sec))
547
0
  continue;
548
549
0
      dest_vma = sec->output_section->vma + sec->output_offset + sym_value;
550
551
0
      if (symndx < 0
552
0
    || (unsigned long) symndx >= obj_raw_syment_count (input_bfd))
553
0
  continue;
554
555
      /* All the relocs handled below operate on 4 bytes.  */
556
0
      if (input_section->size < rel->r_vaddr
557
0
    || input_section->size - rel->r_vaddr < 4)
558
0
  {
559
0
    _bfd_error_handler
560
      /* xgettext: c-format */
561
0
      (_("%pB: bad reloc address %#" PRIx64 " in section `%pA'"),
562
0
       input_bfd, (uint64_t) rel->r_vaddr, input_section);
563
0
    continue;
564
0
  }
565
566
0
      switch (rel->r_type)
567
0
  {
568
0
  case IMAGE_REL_ARM64_ADDR32NB:
569
0
    {
570
0
      uint64_t val;
571
0
      int32_t addend;
572
573
0
      addend = bfd_getl32 (contents + rel->r_vaddr);
574
575
0
      dest_vma += addend;
576
577
0
      val = dest_vma;
578
0
      val -= pe_data (output_bfd)->pe_opthdr.ImageBase;
579
580
0
      if (val > 0xffffffff)
581
0
        (*info->callbacks->reloc_overflow)
582
0
    (info, h ? &h->root : NULL, syms[symndx]._n._n_name,
583
0
    "IMAGE_REL_ARM64_ADDR32NB", addend, input_bfd,
584
0
    input_section, rel->r_vaddr - input_section->vma);
585
586
0
      bfd_putl32 (val, contents + rel->r_vaddr);
587
0
      rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
588
589
0
      break;
590
0
    }
591
592
0
  case IMAGE_REL_ARM64_BRANCH26:
593
0
    {
594
0
      uint64_t cur_vma;
595
0
      uint32_t opcode;
596
0
      int64_t addend, val;
597
598
0
      opcode = bfd_getl32 (contents + rel->r_vaddr);
599
600
0
      addend = (opcode & 0x3ffffff) << 2;
601
602
0
      if (addend & 0x8000000)
603
0
        addend |= 0xfffffffff0000000;
604
605
0
      dest_vma += addend;
606
0
      cur_vma = input_section->output_section->vma
607
0
          + input_section->output_offset
608
0
          + rel->r_vaddr;
609
610
0
      val = (dest_vma >> 2) - (cur_vma >> 2);
611
612
0
      if (val > 0x1ffffff || val < -0x2000000)
613
0
        (*info->callbacks->reloc_overflow)
614
0
    (info, h ? &h->root : NULL, syms[symndx]._n._n_name,
615
0
    "IMAGE_REL_ARM64_BRANCH26", addend, input_bfd,
616
0
    input_section, rel->r_vaddr - input_section->vma);
617
618
0
      opcode &= 0xfc000000;
619
0
      opcode |= val & 0x3ffffff;
620
621
0
      bfd_putl32 (opcode, contents + rel->r_vaddr);
622
0
      rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
623
624
0
      break;
625
0
    }
626
627
0
  case IMAGE_REL_ARM64_BRANCH19:
628
0
    {
629
0
      uint64_t cur_vma;
630
0
      uint32_t opcode;
631
0
      int64_t addend, val;
632
633
0
      opcode = bfd_getl32 (contents + rel->r_vaddr);
634
635
0
      addend = (opcode & 0xffffe0) >> 3;
636
637
0
      if (addend & 0x100000)
638
0
        addend |= 0xffffffffffe00000;
639
640
0
      dest_vma += addend;
641
0
      cur_vma = input_section->output_section->vma
642
0
          + input_section->output_offset
643
0
          + rel->r_vaddr;
644
645
0
      val = (dest_vma >> 2) - (cur_vma >> 2);
646
647
0
      if (val > 0x3ffff || val < -0x40000)
648
0
        (*info->callbacks->reloc_overflow)
649
0
    (info, h ? &h->root : NULL, syms[symndx]._n._n_name,
650
0
    "IMAGE_REL_ARM64_BRANCH19", addend, input_bfd,
651
0
    input_section, rel->r_vaddr - input_section->vma);
652
653
0
      opcode &= 0xff00001f;
654
0
      opcode |= (val & 0x7ffff) << 5;
655
656
0
      bfd_putl32 (opcode, contents + rel->r_vaddr);
657
0
      rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
658
659
0
      break;
660
0
    }
661
662
0
  case IMAGE_REL_ARM64_BRANCH14:
663
0
    {
664
0
      uint64_t cur_vma;
665
0
      uint32_t opcode;
666
0
      int64_t addend, val;
667
668
0
      opcode = bfd_getl32 (contents + rel->r_vaddr);
669
670
0
      addend = (opcode & 0x7ffe0) >> 3;
671
672
0
      if (addend & 0x8000)
673
0
        addend |= 0xffffffffffff0000;
674
675
0
      dest_vma += addend;
676
0
      cur_vma = input_section->output_section->vma
677
0
          + input_section->output_offset
678
0
          + rel->r_vaddr;
679
680
0
      val = (dest_vma >> 2) - (cur_vma >> 2);
681
682
0
      if (val > 0x1fff || val < -0x2000)
683
0
        (*info->callbacks->reloc_overflow)
684
0
    (info, h ? &h->root : NULL, syms[symndx]._n._n_name,
685
0
    "IMAGE_REL_ARM64_BRANCH14", addend, input_bfd,
686
0
    input_section, rel->r_vaddr - input_section->vma);
687
688
0
      opcode &= 0xfff8001f;
689
0
      opcode |= (val & 0x3fff) << 5;
690
691
0
      bfd_putl32 (opcode, contents + rel->r_vaddr);
692
0
      rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
693
694
0
      break;
695
0
    }
696
697
0
  case IMAGE_REL_ARM64_PAGEBASE_REL21:
698
0
    {
699
0
      uint64_t cur_vma;
700
0
      uint32_t opcode;
701
0
      int64_t addend, val;
702
703
0
      opcode = bfd_getl32 (contents + rel->r_vaddr);
704
705
0
      addend = ((opcode & 0xffffe0) >> 3)
706
0
         | ((opcode & 0x60000000) >> 29);
707
708
0
      if (addend & 0x100000)
709
0
        addend |= 0xffffffffffe00000;
710
711
0
      dest_vma += addend;
712
0
      cur_vma = input_section->output_section->vma
713
0
          + input_section->output_offset
714
0
          + rel->r_vaddr;
715
716
0
      val = (dest_vma >> 12) - (cur_vma >> 12);
717
718
0
      if (val > 0xfffff || val < -0x100000)
719
0
        (*info->callbacks->reloc_overflow)
720
0
    (info, h ? &h->root : NULL, syms[symndx]._n._n_name,
721
0
    "IMAGE_REL_ARM64_PAGEBASE_REL21", addend, input_bfd,
722
0
    input_section, rel->r_vaddr - input_section->vma);
723
724
0
      opcode &= 0x9f00001f;
725
0
      opcode |= (val & 0x3) << 29;
726
0
      opcode |= (val & 0x1ffffc) << 3;
727
728
0
      bfd_putl32 (opcode, contents + rel->r_vaddr);
729
0
      rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
730
731
0
      break;
732
0
    }
733
734
0
  case IMAGE_REL_ARM64_REL21:
735
0
    {
736
0
      uint64_t cur_vma;
737
0
      uint32_t opcode;
738
0
      int64_t addend, val;
739
740
0
      opcode = bfd_getl32 (contents + rel->r_vaddr);
741
742
0
      addend = ((opcode & 0xffffe0) >> 3)
743
0
         | ((opcode & 0x60000000) >> 29);
744
745
0
      if (addend & 0x100000)
746
0
        addend |= 0xffffffffffe00000;
747
748
0
      dest_vma += addend;
749
0
      cur_vma = input_section->output_section->vma
750
0
          + input_section->output_offset
751
0
          + rel->r_vaddr;
752
753
0
      val = dest_vma - cur_vma;
754
755
0
      if (val > 0xfffff || val < -0x100000)
756
0
        (*info->callbacks->reloc_overflow)
757
0
    (info, h ? &h->root : NULL, syms[symndx]._n._n_name,
758
0
    "IMAGE_REL_ARM64_REL21", addend, input_bfd,
759
0
    input_section, rel->r_vaddr - input_section->vma);
760
761
0
      opcode &= 0x9f00001f;
762
0
      opcode |= (val & 0x3) << 29;
763
0
      opcode |= (val & 0x1ffffc) << 3;
764
765
0
      bfd_putl32 (opcode, contents + rel->r_vaddr);
766
0
      rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
767
768
0
      break;
769
0
    }
770
771
0
  case IMAGE_REL_ARM64_PAGEOFFSET_12L:
772
0
    {
773
0
      uint32_t opcode, val;
774
0
      uint8_t shift;
775
0
      int32_t addend;
776
777
0
      opcode = bfd_getl32 (contents + rel->r_vaddr);
778
779
0
      addend = (opcode & 0x3ffc00) >> 10;
780
781
0
      if ((opcode & 0xff800000) == 0x3d800000)
782
0
        {
783
    /* LDR / STR with q register */
784
0
    shift = 4;
785
0
        }
786
0
      else
787
0
        {
788
    /* top two bits represent how much addend should be shifted */
789
0
    shift = opcode >> 30;
790
0
        }
791
792
0
      addend <<= shift;
793
794
0
      dest_vma += addend;
795
796
      /* only interested in bottom 12 bits */
797
0
      val = dest_vma & 0xfff;
798
799
0
      if (val & ((1 << shift) - 1))
800
0
        (*info->callbacks->reloc_overflow)
801
0
    (info, h ? &h->root : NULL, syms[symndx]._n._n_name,
802
0
    "IMAGE_REL_ARM64_PAGEOFFSET_12L", addend, input_bfd,
803
0
    input_section, rel->r_vaddr - input_section->vma);
804
805
0
      val >>= shift;
806
807
0
      opcode &= 0xffc003ff;
808
0
      opcode |= val << 10;
809
810
0
      bfd_putl32 (opcode, contents + rel->r_vaddr);
811
0
      rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
812
813
0
      break;
814
0
    }
815
816
0
  case IMAGE_REL_ARM64_PAGEOFFSET_12A:
817
0
    {
818
0
      uint32_t opcode, val;
819
0
      int32_t addend;
820
821
0
      opcode = bfd_getl32 (contents + rel->r_vaddr);
822
823
0
      addend = (opcode & 0x3ffc00) >> 10;
824
825
0
      dest_vma += addend;
826
827
      /* only interested in bottom 12 bits */
828
0
      val = dest_vma & 0xfff;
829
830
0
      opcode &= 0xffc003ff;
831
0
      opcode |= val << 10;
832
833
0
      bfd_putl32 (opcode, contents + rel->r_vaddr);
834
0
      rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
835
836
0
      break;
837
0
    }
838
839
0
  case IMAGE_REL_ARM64_SECREL:
840
0
    {
841
0
      uint64_t val;
842
0
      int32_t addend;
843
844
0
      addend = bfd_getl32 (contents + rel->r_vaddr);
845
846
0
      val = sec->output_offset + sym_value + addend;
847
848
0
      if (val > 0xffffffff)
849
0
        (*info->callbacks->reloc_overflow)
850
0
    (info, h ? &h->root : NULL, syms[symndx]._n._n_name,
851
0
    "IMAGE_REL_ARM64_SECREL", addend, input_bfd,
852
0
    input_section, rel->r_vaddr - input_section->vma);
853
854
0
      bfd_putl32 (val, contents + rel->r_vaddr);
855
0
      rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
856
857
0
      break;
858
0
    }
859
860
0
  case IMAGE_REL_ARM64_SECTION:
861
0
    {
862
0
      uint16_t idx = 0, i = 1;
863
0
      asection *s;
864
865
0
      s = output_bfd->sections;
866
0
      while (s)
867
0
        {
868
0
    if (s == sec->output_section)
869
0
      {
870
0
        idx = i;
871
0
        break;
872
0
      }
873
874
0
    i++;
875
0
    s = s->next;
876
0
        }
877
878
879
0
      bfd_putl16 (idx, contents + rel->r_vaddr);
880
0
      rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
881
882
0
      break;
883
0
    }
884
885
0
  default:
886
0
    info->callbacks->einfo (_("%F%P: Unhandled relocation type %u\n"),
887
0
          rel->r_type);
888
0
    BFD_FAIL ();
889
0
    return false;
890
0
  }
891
0
    }
892
893
0
  return _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
894
0
               input_section, contents,
895
0
               relocs, syms, sections);
896
0
}
Unexecuted instantiation: pei-aarch64.c:coff_pe_aarch64_relocate_section
Unexecuted instantiation: pe-aarch64.c:coff_pe_aarch64_relocate_section
897
898
#define coff_relocate_section coff_pe_aarch64_relocate_section
899
900
#include "coffcode.h"
901
902
/* Prevent assertion in md_apply_fix by forcing use_rela_p on for new
903
   sections.  */
904
static bool
905
coff_aarch64_new_section_hook (bfd *abfd, asection *section)
906
0
{
907
0
  if (!coff_new_section_hook (abfd, section))
908
0
    return false;
909
910
0
  section->use_rela_p = 1;
911
912
0
  return true;
913
0
}
Unexecuted instantiation: pei-aarch64.c:coff_aarch64_new_section_hook
Unexecuted instantiation: pe-aarch64.c:coff_aarch64_new_section_hook
914
915
#define coff_aarch64_close_and_cleanup coff_close_and_cleanup
916
#define coff_aarch64_bfd_free_cached_info coff_bfd_free_cached_info
917
#define coff_aarch64_get_section_contents coff_get_section_contents
918
#define coff_aarch64_get_section_contents_in_window coff_get_section_contents_in_window
919
920
/* Target vectors.  */
921
const bfd_target
922
#ifdef TARGET_SYM
923
  TARGET_SYM =
924
#else
925
# error "target symbol name not specified"
926
#endif
927
{
928
#ifdef TARGET_NAME
929
  TARGET_NAME,
930
#else
931
# error "target name not specified"
932
#endif
933
  bfd_target_coff_flavour,
934
  BFD_ENDIAN_LITTLE,    /* Data byte order is little.  */
935
  BFD_ENDIAN_LITTLE,    /* Header byte order is little.  */
936
937
  (HAS_RELOC | EXEC_P   /* Object flags.  */
938
   | HAS_LINENO | HAS_DEBUG
939
   | HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS),
940
941
  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* Section flags.  */
942
#if defined(COFF_WITH_PE)
943
   | SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_READONLY | SEC_DEBUGGING
944
#endif
945
   | SEC_CODE | SEC_DATA | SEC_EXCLUDE ),
946
947
#ifdef TARGET_UNDERSCORE
948
  TARGET_UNDERSCORE,    /* Leading underscore.  */
949
#else
950
  0,        /* Leading underscore.  */
951
#endif
952
  '/',        /* Ar_pad_char.  */
953
  15,       /* Ar_max_namelen.  */
954
  0,        /* match priority.  */
955
  TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
956
957
  /* Data conversion functions.  */
958
  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
959
  bfd_getl32, bfd_getl_signed_32, bfd_putl32,
960
  bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data.  */
961
  /* Header conversion functions.  */
962
  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
963
  bfd_getl32, bfd_getl_signed_32, bfd_putl32,
964
  bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Hdrs.  */
965
966
  /* Note that we allow an object file to be treated as a core file as well.  */
967
  {       /* bfd_check_format.  */
968
    _bfd_dummy_target,
969
    coff_object_p,
970
    bfd_generic_archive_p,
971
    coff_object_p
972
  },
973
  {       /* bfd_set_format.  */
974
    _bfd_bool_bfd_false_error,
975
    coff_mkobject,
976
    _bfd_generic_mkarchive,
977
    _bfd_bool_bfd_false_error
978
  },
979
  {       /* bfd_write_contents.  */
980
    _bfd_bool_bfd_false_error,
981
    coff_write_object_contents,
982
    _bfd_write_archive_contents,
983
    _bfd_bool_bfd_false_error
984
  },
985
986
  BFD_JUMP_TABLE_GENERIC (coff_aarch64),
987
  BFD_JUMP_TABLE_COPY (coff),
988
  BFD_JUMP_TABLE_CORE (_bfd_nocore),
989
  BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
990
  BFD_JUMP_TABLE_SYMBOLS (coff),
991
  BFD_JUMP_TABLE_RELOCS (coff),
992
  BFD_JUMP_TABLE_WRITE (coff),
993
  BFD_JUMP_TABLE_LINK (coff),
994
  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
995
996
  NULL,
997
998
  COFF_SWAP_TABLE
999
};