Automatic date update in version.in
[binutils-gdb.git] / bfd / coff-aarch64.c
blob06c22fc58fa26d5c2b4fe2cc5adc75a34d46c9d3
1 /* BFD back-end for AArch64 COFF files.
2 Copyright (C) 2021-2024 Free Software Foundation, Inc.
4 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
22 #ifndef COFF_WITH_peAArch64
23 #define COFF_WITH_peAArch64
24 #endif
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"
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. */
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)
54 if (output_bfd != NULL && output_bfd != abfd)
55 return bfd_reloc_continue;
57 if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
58 input_section, reloc_entry->address))
59 return bfd_reloc_outofrange;
61 uint32_t op = bfd_getl32 (data + reloc_entry->address);
62 bfd_vma relocation = reloc_entry->addend;
63 bfd_reloc_status_type ret = bfd_reloc_ok;
64 if (output_bfd == NULL)
66 if (bfd_is_und_section (symbol->section))
68 if ((symbol->flags & BSF_WEAK) == 0)
69 ret = bfd_reloc_undefined;
71 else if (!bfd_is_com_section (symbol->section))
72 relocation += (symbol->value
73 + symbol->section->output_offset
74 + symbol->section->output_section->vma);
75 bfd_vma addend = ((op >> 3) & 0x1ffffc) | ((op >> 29) & 0x3);
76 addend = (addend ^ 0x100000) - 0x100000;
77 relocation += addend;
78 relocation -= (reloc_entry->address
79 + input_section->output_offset
80 + input_section->output_section->vma);
81 relocation = (bfd_signed_vma) relocation >> reloc_entry->howto->rightshift;
83 if (relocation + 0x100000 > 0x1fffff)
84 ret = bfd_reloc_overflow;
86 op &= 0x9f00001f;
87 op |= (relocation & 0x1ffffc) << 3;
88 op |= (relocation & 0x3) << 29;
90 bfd_putl32 (op, data + reloc_entry->address);
92 return ret;
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)
104 if (output_bfd != NULL && output_bfd != abfd)
105 return bfd_reloc_continue;
107 if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
108 input_section, reloc_entry->address))
109 return bfd_reloc_outofrange;
111 uint32_t op = bfd_getl32 (data + reloc_entry->address);
112 bfd_vma relocation = reloc_entry->addend & 0xfff;
113 int shift;
115 if ((op & 0xff800000) == 0x3d800000)
117 /* LDR / STR with q register */
118 shift = 4;
120 else
122 /* top two bits represent how much addend should be shifted */
123 shift = op >> 30;
126 bfd_reloc_status_type ret = bfd_reloc_ok;
127 if (output_bfd == NULL)
129 if (bfd_is_und_section (symbol->section))
131 if ((symbol->flags & BSF_WEAK) == 0)
132 ret = bfd_reloc_undefined;
134 else if (!bfd_is_com_section (symbol->section))
135 relocation += (symbol->value
136 + symbol->section->output_offset
137 + symbol->section->output_section->vma);
138 bfd_vma addend = (op >> 10) & 0xfff;
139 addend <<= shift;
140 relocation += addend;
143 if (relocation & ((1 << shift) - 1))
144 ret = bfd_reloc_overflow;
146 op &= 0xffc003ff;
147 op |= (relocation >> shift << 10) & 0x3ffc00;
149 bfd_putl32 (op, data + reloc_entry->address);
151 return ret;
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)
163 if (output_bfd != NULL && output_bfd != abfd)
164 return bfd_reloc_continue;
166 if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
167 input_section, reloc_entry->address))
168 return bfd_reloc_outofrange;
170 bfd_vma relocation = reloc_entry->addend;
171 bfd_reloc_status_type ret = bfd_reloc_ok;
172 if (output_bfd == NULL)
174 if (bfd_is_und_section (symbol->section))
176 if ((symbol->flags & BSF_WEAK) == 0)
177 ret = bfd_reloc_undefined;
179 else if (!bfd_is_com_section (symbol->section))
180 relocation += (symbol->value
181 + symbol->section->output_offset
182 + symbol->section->output_section->vma);
183 bfd_vma addend = bfd_getl_signed_32 (data + reloc_entry->address);
184 relocation += addend;
185 bfd *obfd = input_section->output_section->owner;
186 if (bfd_get_flavour (obfd) == bfd_target_coff_flavour
187 && obj_pe (obfd))
188 relocation -= pe_data (obfd)->pe_opthdr.ImageBase;
189 else
191 *error_message = "unsupported";
192 return bfd_reloc_dangerous;
196 if (relocation + 0x80000000 > 0xffffffff)
197 ret = bfd_reloc_overflow;
199 bfd_putl32 (relocation, data + reloc_entry->address);
201 return ret;
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)
213 if (output_bfd != NULL && output_bfd != abfd)
214 return bfd_reloc_continue;
216 if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
217 input_section, reloc_entry->address))
218 return bfd_reloc_outofrange;
220 bfd_vma relocation = reloc_entry->addend;
221 bfd_reloc_status_type ret = bfd_reloc_ok;
222 if (output_bfd == NULL)
224 if (bfd_is_und_section (symbol->section))
226 if ((symbol->flags & BSF_WEAK) == 0)
227 ret = bfd_reloc_undefined;
229 else if (!bfd_is_com_section (symbol->section))
230 relocation += (symbol->value
231 + symbol->section->output_offset);
232 bfd_vma addend = bfd_getl_signed_32 (data + reloc_entry->address);
233 relocation += addend;
235 if (relocation > 0xffffffff)
236 ret = bfd_reloc_overflow;
238 bfd_putl32 (relocation, data + reloc_entry->address);
240 return ret;
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)
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);
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));
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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
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 cache_ptr->addend = 0;
330 #ifndef NUM_ELEM
331 #define NUM_ELEM(a) ((sizeof (a)) / sizeof ((a)[0]))
332 #endif
334 #define NUM_RELOCS NUM_ELEM (arm64_howto_table)
336 #define coff_bfd_reloc_type_lookup coff_aarch64_reloc_type_lookup
337 #define coff_bfd_reloc_name_lookup coff_aarch64_reloc_name_lookup
339 static reloc_howto_type *
340 coff_aarch64_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code)
342 switch (code)
344 case BFD_RELOC_64:
345 return &arm64_reloc_howto_64;
346 case BFD_RELOC_32:
347 return &arm64_reloc_howto_32;
348 case BFD_RELOC_32_PCREL:
349 return &arm64_reloc_howto_32_pcrel;
350 case BFD_RELOC_AARCH64_CALL26:
351 case BFD_RELOC_AARCH64_JUMP26:
352 return &arm64_reloc_howto_branch26;
353 case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
354 case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL:
355 case BFD_RELOC_AARCH64_ADR_GOT_PAGE:
356 return &arm64_reloc_howto_page21;
357 case BFD_RELOC_AARCH64_TSTBR14:
358 return &arm64_reloc_howto_branch14;
359 case BFD_RELOC_AARCH64_ADR_LO21_PCREL:
360 return &arm64_reloc_howto_lo21;
361 case BFD_RELOC_AARCH64_ADD_LO12:
362 return &arm64_reloc_howto_pgoff12a;
363 case BFD_RELOC_AARCH64_LDST8_LO12:
364 case BFD_RELOC_AARCH64_LDST16_LO12:
365 case BFD_RELOC_AARCH64_LDST32_LO12:
366 case BFD_RELOC_AARCH64_LDST64_LO12:
367 case BFD_RELOC_AARCH64_LDST128_LO12:
368 case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC:
369 return &arm64_reloc_howto_pgoff12l;
370 case BFD_RELOC_AARCH64_BRANCH19:
371 return &arm64_reloc_howto_branch19;
372 case BFD_RELOC_RVA:
373 return &arm64_reloc_howto_32nb;
374 case BFD_RELOC_32_SECREL:
375 return &arm64_reloc_howto_secrel;
376 case BFD_RELOC_16_SECIDX:
377 return &arm64_reloc_howto_secidx;
378 default:
379 BFD_FAIL ();
380 return NULL;
383 return NULL;
386 static reloc_howto_type *
387 coff_aarch64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
388 const char *r_name)
390 unsigned int i;
392 for (i = 0; i < NUM_RELOCS; i++)
393 if (arm64_howto_table[i]->name != NULL
394 && strcasecmp (arm64_howto_table[i]->name, r_name) == 0)
395 return arm64_howto_table[i];
397 return NULL;
400 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 2
401 #define COFF_PAGE_SIZE 0x1000
403 static reloc_howto_type *
404 coff_aarch64_rtype_lookup (unsigned int code)
406 switch (code)
408 case IMAGE_REL_ARM64_ABSOLUTE:
409 return &arm64_reloc_howto_abs;
410 case IMAGE_REL_ARM64_ADDR64:
411 return &arm64_reloc_howto_64;
412 case IMAGE_REL_ARM64_ADDR32:
413 return &arm64_reloc_howto_32;
414 case IMAGE_REL_ARM64_REL32:
415 return &arm64_reloc_howto_32_pcrel;
416 case IMAGE_REL_ARM64_BRANCH26:
417 return &arm64_reloc_howto_branch26;
418 case IMAGE_REL_ARM64_PAGEBASE_REL21:
419 return &arm64_reloc_howto_page21;
420 case IMAGE_REL_ARM64_REL21:
421 return &arm64_reloc_howto_lo21;
422 case IMAGE_REL_ARM64_PAGEOFFSET_12L:
423 return &arm64_reloc_howto_pgoff12l;
424 case IMAGE_REL_ARM64_BRANCH19:
425 return &arm64_reloc_howto_branch19;
426 case IMAGE_REL_ARM64_BRANCH14:
427 return &arm64_reloc_howto_branch14;
428 case IMAGE_REL_ARM64_PAGEOFFSET_12A:
429 return &arm64_reloc_howto_pgoff12a;
430 case IMAGE_REL_ARM64_ADDR32NB:
431 return &arm64_reloc_howto_32nb;
432 case IMAGE_REL_ARM64_SECREL:
433 return &arm64_reloc_howto_secrel;
434 case IMAGE_REL_ARM64_SECTION:
435 return &arm64_reloc_howto_secidx;
436 default:
437 return NULL;
440 return NULL;
443 #define RTYPE2HOWTO(cache_ptr, dst) \
444 ((cache_ptr)->howto = coff_aarch64_rtype_lookup((dst)->r_type))
446 static reloc_howto_type *
447 coff_aarch64_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
448 asection *sec ATTRIBUTE_UNUSED,
449 struct internal_reloc *rel,
450 struct coff_link_hash_entry *h ATTRIBUTE_UNUSED,
451 struct internal_syment *sym ATTRIBUTE_UNUSED,
452 bfd_vma *addendp)
454 reloc_howto_type *howto = coff_aarch64_rtype_lookup (rel->r_type);
456 /* Cancel out code in _bfd_coff_generic_relocate_section. */
457 *addendp = 0;
459 return howto;
462 #define coff_rtype_to_howto coff_aarch64_rtype_to_howto
464 #define SELECT_RELOC(x,howto) { (x).r_type = (howto)->type; }
466 #ifndef bfd_pe_print_pdata
467 #define bfd_pe_print_pdata NULL
468 #endif
470 #ifdef COFF_WITH_PE
471 /* Return TRUE if this relocation should
472 appear in the output .reloc section. */
474 static bool
475 in_reloc_p (bfd * abfd ATTRIBUTE_UNUSED,
476 reloc_howto_type * howto)
478 return !howto->pc_relative;
480 #endif
482 static bool
483 coff_pe_aarch64_relocate_section (bfd *output_bfd,
484 struct bfd_link_info *info,
485 bfd *input_bfd,
486 asection *input_section,
487 bfd_byte *contents,
488 struct internal_reloc *relocs,
489 struct internal_syment *syms,
490 asection **sections)
492 struct internal_reloc *rel;
493 struct internal_reloc *relend;
495 if (bfd_link_relocatable (info))
496 return true;
498 rel = relocs;
499 relend = rel + input_section->reloc_count;
501 /* The addend for a relocation is stored in the immediate bits of each
502 opcode. So for each relocation, we need to extract the immediate value,
503 use this to calculate what it should be for the symbol, and rewrite the
504 opcode into the section stream. */
506 for (; rel < relend; rel++)
508 long symndx;
509 struct coff_link_hash_entry *h;
510 bfd_vma sym_value;
511 asection *sec = NULL;
512 uint64_t dest_vma;
514 /* skip trivial relocations */
515 if (rel->r_type == IMAGE_REL_ARM64_ADDR32
516 || rel->r_type == IMAGE_REL_ARM64_ADDR64
517 || rel->r_type == IMAGE_REL_ARM64_ABSOLUTE)
518 continue;
520 symndx = rel->r_symndx;
521 sym_value = syms[symndx].n_value;
523 h = obj_coff_sym_hashes (input_bfd)[symndx];
525 if (h && h->root.type == bfd_link_hash_defined)
527 sec = h->root.u.def.section;
528 sym_value = h->root.u.def.value;
530 else
532 sec = sections[symndx];
535 if (!sec)
536 continue;
538 if (bfd_is_und_section (sec))
539 continue;
541 if (discarded_section (sec))
542 continue;
544 dest_vma = sec->output_section->vma + sec->output_offset + sym_value;
546 if (symndx < 0
547 || (unsigned long) symndx >= obj_raw_syment_count (input_bfd))
548 continue;
550 /* All the relocs handled below operate on 4 bytes. */
551 if (input_section->size < rel->r_vaddr
552 || input_section->size - rel->r_vaddr < 4)
554 _bfd_error_handler
555 /* xgettext: c-format */
556 (_("%pB: bad reloc address %#" PRIx64 " in section `%pA'"),
557 input_bfd, (uint64_t) rel->r_vaddr, input_section);
558 continue;
561 switch (rel->r_type)
563 case IMAGE_REL_ARM64_ADDR32NB:
565 uint64_t val;
566 int32_t addend;
568 addend = bfd_getl32 (contents + rel->r_vaddr);
570 dest_vma += addend;
572 val = dest_vma;
573 val -= pe_data (output_bfd)->pe_opthdr.ImageBase;
575 if (val > 0xffffffff)
576 (*info->callbacks->reloc_overflow)
577 (info, h ? &h->root : NULL, syms[symndx]._n._n_name,
578 "IMAGE_REL_ARM64_ADDR32NB", addend, input_bfd,
579 input_section, rel->r_vaddr - input_section->vma);
581 bfd_putl32 (val, contents + rel->r_vaddr);
582 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
584 break;
587 case IMAGE_REL_ARM64_BRANCH26:
589 uint64_t cur_vma;
590 uint32_t opcode;
591 int64_t addend, val;
593 opcode = bfd_getl32 (contents + rel->r_vaddr);
595 addend = (opcode & 0x3ffffff) << 2;
597 if (addend & 0x8000000)
598 addend |= 0xfffffffff0000000;
600 dest_vma += addend;
601 cur_vma = input_section->output_section->vma
602 + input_section->output_offset
603 + rel->r_vaddr;
605 val = (dest_vma >> 2) - (cur_vma >> 2);
607 if (val > 0x1ffffff || val < -0x2000000)
608 (*info->callbacks->reloc_overflow)
609 (info, h ? &h->root : NULL, syms[symndx]._n._n_name,
610 "IMAGE_REL_ARM64_BRANCH26", addend, input_bfd,
611 input_section, rel->r_vaddr - input_section->vma);
613 opcode &= 0xfc000000;
614 opcode |= val & 0x3ffffff;
616 bfd_putl32 (opcode, contents + rel->r_vaddr);
617 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
619 break;
622 case IMAGE_REL_ARM64_BRANCH19:
624 uint64_t cur_vma;
625 uint32_t opcode;
626 int64_t addend, val;
628 opcode = bfd_getl32 (contents + rel->r_vaddr);
630 addend = (opcode & 0xffffe0) >> 3;
632 if (addend & 0x100000)
633 addend |= 0xffffffffffe00000;
635 dest_vma += addend;
636 cur_vma = input_section->output_section->vma
637 + input_section->output_offset
638 + rel->r_vaddr;
640 val = (dest_vma >> 2) - (cur_vma >> 2);
642 if (val > 0x3ffff || val < -0x40000)
643 (*info->callbacks->reloc_overflow)
644 (info, h ? &h->root : NULL, syms[symndx]._n._n_name,
645 "IMAGE_REL_ARM64_BRANCH19", addend, input_bfd,
646 input_section, rel->r_vaddr - input_section->vma);
648 opcode &= 0xff00001f;
649 opcode |= (val & 0x7ffff) << 5;
651 bfd_putl32 (opcode, contents + rel->r_vaddr);
652 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
654 break;
657 case IMAGE_REL_ARM64_BRANCH14:
659 uint64_t cur_vma;
660 uint32_t opcode;
661 int64_t addend, val;
663 opcode = bfd_getl32 (contents + rel->r_vaddr);
665 addend = (opcode & 0x7ffe0) >> 3;
667 if (addend & 0x8000)
668 addend |= 0xffffffffffff0000;
670 dest_vma += addend;
671 cur_vma = input_section->output_section->vma
672 + input_section->output_offset
673 + rel->r_vaddr;
675 val = (dest_vma >> 2) - (cur_vma >> 2);
677 if (val > 0x1fff || val < -0x2000)
678 (*info->callbacks->reloc_overflow)
679 (info, h ? &h->root : NULL, syms[symndx]._n._n_name,
680 "IMAGE_REL_ARM64_BRANCH14", addend, input_bfd,
681 input_section, rel->r_vaddr - input_section->vma);
683 opcode &= 0xfff8001f;
684 opcode |= (val & 0x3fff) << 5;
686 bfd_putl32 (opcode, contents + rel->r_vaddr);
687 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
689 break;
692 case IMAGE_REL_ARM64_PAGEBASE_REL21:
694 uint64_t cur_vma;
695 uint32_t opcode;
696 int64_t addend, val;
698 opcode = bfd_getl32 (contents + rel->r_vaddr);
700 addend = ((opcode & 0xffffe0) >> 3)
701 | ((opcode & 0x60000000) >> 29);
703 if (addend & 0x100000)
704 addend |= 0xffffffffffe00000;
706 dest_vma += addend;
707 cur_vma = input_section->output_section->vma
708 + input_section->output_offset
709 + rel->r_vaddr;
711 val = (dest_vma >> 12) - (cur_vma >> 12);
713 if (val > 0xfffff || val < -0x100000)
714 (*info->callbacks->reloc_overflow)
715 (info, h ? &h->root : NULL, syms[symndx]._n._n_name,
716 "IMAGE_REL_ARM64_PAGEBASE_REL21", addend, input_bfd,
717 input_section, rel->r_vaddr - input_section->vma);
719 opcode &= 0x9f00001f;
720 opcode |= (val & 0x3) << 29;
721 opcode |= (val & 0x1ffffc) << 3;
723 bfd_putl32 (opcode, contents + rel->r_vaddr);
724 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
726 break;
729 case IMAGE_REL_ARM64_REL21:
731 uint64_t cur_vma;
732 uint32_t opcode;
733 int64_t addend, val;
735 opcode = bfd_getl32 (contents + rel->r_vaddr);
737 addend = ((opcode & 0xffffe0) >> 3)
738 | ((opcode & 0x60000000) >> 29);
740 if (addend & 0x100000)
741 addend |= 0xffffffffffe00000;
743 dest_vma += addend;
744 cur_vma = input_section->output_section->vma
745 + input_section->output_offset
746 + rel->r_vaddr;
748 val = dest_vma - cur_vma;
750 if (val > 0xfffff || val < -0x100000)
751 (*info->callbacks->reloc_overflow)
752 (info, h ? &h->root : NULL, syms[symndx]._n._n_name,
753 "IMAGE_REL_ARM64_REL21", addend, input_bfd,
754 input_section, rel->r_vaddr - input_section->vma);
756 opcode &= 0x9f00001f;
757 opcode |= (val & 0x3) << 29;
758 opcode |= (val & 0x1ffffc) << 3;
760 bfd_putl32 (opcode, contents + rel->r_vaddr);
761 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
763 break;
766 case IMAGE_REL_ARM64_REL32:
768 uint64_t cur_vma;
769 int64_t addend, val;
771 addend = bfd_getl32 (contents + rel->r_vaddr);
773 if (addend & 0x80000000)
774 addend |= 0xffffffff00000000;
776 dest_vma += addend;
777 cur_vma = input_section->output_section->vma
778 + input_section->output_offset
779 + rel->r_vaddr;
781 val = dest_vma - cur_vma;
783 if (val > 0xffffffff || val < -0x100000000)
784 (*info->callbacks->reloc_overflow)
785 (info, h ? &h->root : NULL, syms[symndx]._n._n_name,
786 "IMAGE_REL_ARM64_REL32", addend, input_bfd,
787 input_section, rel->r_vaddr - input_section->vma);
789 bfd_putl32 (val, contents + rel->r_vaddr);
790 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
792 break;
795 case IMAGE_REL_ARM64_PAGEOFFSET_12L:
797 uint32_t opcode, val;
798 uint8_t shift;
799 int32_t addend;
801 opcode = bfd_getl32 (contents + rel->r_vaddr);
803 addend = (opcode & 0x3ffc00) >> 10;
805 if ((opcode & 0xff800000) == 0x3d800000)
807 /* LDR / STR with q register */
808 shift = 4;
810 else
812 /* top two bits represent how much addend should be shifted */
813 shift = opcode >> 30;
816 addend <<= shift;
818 dest_vma += addend;
820 /* only interested in bottom 12 bits */
821 val = dest_vma & 0xfff;
823 if (val & ((1 << shift) - 1))
824 (*info->callbacks->reloc_overflow)
825 (info, h ? &h->root : NULL, syms[symndx]._n._n_name,
826 "IMAGE_REL_ARM64_PAGEOFFSET_12L", addend, input_bfd,
827 input_section, rel->r_vaddr - input_section->vma);
829 val >>= shift;
831 opcode &= 0xffc003ff;
832 opcode |= val << 10;
834 bfd_putl32 (opcode, contents + rel->r_vaddr);
835 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
837 break;
840 case IMAGE_REL_ARM64_PAGEOFFSET_12A:
842 uint32_t opcode, val;
843 int32_t addend;
845 opcode = bfd_getl32 (contents + rel->r_vaddr);
847 addend = (opcode & 0x3ffc00) >> 10;
849 dest_vma += addend;
851 /* only interested in bottom 12 bits */
852 val = dest_vma & 0xfff;
854 opcode &= 0xffc003ff;
855 opcode |= val << 10;
857 bfd_putl32 (opcode, contents + rel->r_vaddr);
858 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
860 break;
863 case IMAGE_REL_ARM64_SECREL:
865 uint64_t val;
866 int32_t addend;
868 addend = bfd_getl32 (contents + rel->r_vaddr);
870 val = sec->output_offset + sym_value + addend;
872 if (val > 0xffffffff)
873 (*info->callbacks->reloc_overflow)
874 (info, h ? &h->root : NULL, syms[symndx]._n._n_name,
875 "IMAGE_REL_ARM64_SECREL", addend, input_bfd,
876 input_section, rel->r_vaddr - input_section->vma);
878 bfd_putl32 (val, contents + rel->r_vaddr);
879 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
881 break;
884 case IMAGE_REL_ARM64_SECTION:
886 uint16_t idx = 0, i = 1;
887 asection *s;
889 s = output_bfd->sections;
890 while (s)
892 if (s == sec->output_section)
894 idx = i;
895 break;
898 i++;
899 s = s->next;
903 bfd_putl16 (idx, contents + rel->r_vaddr);
904 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
906 break;
909 default:
910 info->callbacks->einfo (_("%F%P: Unhandled relocation type %u\n"),
911 rel->r_type);
912 BFD_FAIL ();
913 return false;
917 return _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
918 input_section, contents,
919 relocs, syms, sections);
922 #define coff_relocate_section coff_pe_aarch64_relocate_section
924 #include "coffcode.h"
926 /* Prevent assertion in md_apply_fix by forcing use_rela_p on for new
927 sections. */
928 static bool
929 coff_aarch64_new_section_hook (bfd *abfd, asection *section)
931 if (!coff_new_section_hook (abfd, section))
932 return false;
934 section->use_rela_p = 1;
936 return true;
939 #define coff_aarch64_close_and_cleanup coff_close_and_cleanup
940 #define coff_aarch64_bfd_free_cached_info coff_bfd_free_cached_info
941 #define coff_aarch64_get_section_contents coff_get_section_contents
942 #define coff_aarch64_get_section_contents_in_window coff_get_section_contents_in_window
944 /* Target vectors. */
945 const bfd_target
946 #ifdef TARGET_SYM
947 TARGET_SYM =
948 #else
949 # error "target symbol name not specified"
950 #endif
952 #ifdef TARGET_NAME
953 TARGET_NAME,
954 #else
955 # error "target name not specified"
956 #endif
957 bfd_target_coff_flavour,
958 BFD_ENDIAN_LITTLE, /* Data byte order is little. */
959 BFD_ENDIAN_LITTLE, /* Header byte order is little. */
961 (HAS_RELOC | EXEC_P /* Object flags. */
962 | HAS_LINENO | HAS_DEBUG
963 | HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS),
965 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* Section flags. */
966 #if defined(COFF_WITH_PE)
967 | SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_READONLY | SEC_DEBUGGING
968 #endif
969 | SEC_CODE | SEC_DATA | SEC_EXCLUDE ),
971 #ifdef TARGET_UNDERSCORE
972 TARGET_UNDERSCORE, /* Leading underscore. */
973 #else
974 0, /* Leading underscore. */
975 #endif
976 '/', /* Ar_pad_char. */
977 15, /* Ar_max_namelen. */
978 0, /* match priority. */
979 TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */
981 /* Data conversion functions. */
982 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
983 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
984 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data. */
985 /* Header conversion functions. */
986 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
987 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
988 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Hdrs. */
990 /* Note that we allow an object file to be treated as a core file as well. */
991 { /* bfd_check_format. */
992 _bfd_dummy_target,
993 coff_object_p,
994 bfd_generic_archive_p,
995 coff_object_p
997 { /* bfd_set_format. */
998 _bfd_bool_bfd_false_error,
999 coff_mkobject,
1000 _bfd_generic_mkarchive,
1001 _bfd_bool_bfd_false_error
1003 { /* bfd_write_contents. */
1004 _bfd_bool_bfd_false_error,
1005 coff_write_object_contents,
1006 _bfd_write_archive_contents,
1007 _bfd_bool_bfd_false_error
1010 BFD_JUMP_TABLE_GENERIC (coff_aarch64),
1011 BFD_JUMP_TABLE_COPY (coff),
1012 BFD_JUMP_TABLE_CORE (_bfd_nocore),
1013 BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
1014 BFD_JUMP_TABLE_SYMBOLS (coff),
1015 BFD_JUMP_TABLE_RELOCS (coff),
1016 BFD_JUMP_TABLE_WRITE (coff),
1017 BFD_JUMP_TABLE_LINK (coff),
1018 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1020 NULL,
1022 COFF_SWAP_TABLE