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