Coverage Report

Created: 2023-08-28 06:23

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