Fix memory leak in RiscV assembler.
[binutils-gdb.git] / bfd / coff-aarch64.c
blob60e231343440bb73231bf00d62439faf61cef219
1 /* BFD back-end for AArch64 COFF files.
2 Copyright (C) 2021-2023 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 return &arm64_reloc_howto_page21;
356 case BFD_RELOC_AARCH64_TSTBR14:
357 return &arm64_reloc_howto_branch14;
358 case BFD_RELOC_AARCH64_ADR_LO21_PCREL:
359 return &arm64_reloc_howto_lo21;
360 case BFD_RELOC_AARCH64_ADD_LO12:
361 return &arm64_reloc_howto_pgoff12a;
362 case BFD_RELOC_AARCH64_LDST8_LO12:
363 case BFD_RELOC_AARCH64_LDST16_LO12:
364 case BFD_RELOC_AARCH64_LDST32_LO12:
365 case BFD_RELOC_AARCH64_LDST64_LO12:
366 case BFD_RELOC_AARCH64_LDST128_LO12:
367 return &arm64_reloc_howto_pgoff12l;
368 case BFD_RELOC_AARCH64_BRANCH19:
369 return &arm64_reloc_howto_branch19;
370 case BFD_RELOC_RVA:
371 return &arm64_reloc_howto_32nb;
372 case BFD_RELOC_32_SECREL:
373 return &arm64_reloc_howto_secrel;
374 case BFD_RELOC_16_SECIDX:
375 return &arm64_reloc_howto_secidx;
376 default:
377 BFD_FAIL ();
378 return NULL;
381 return NULL;
384 static reloc_howto_type *
385 coff_aarch64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
386 const char *r_name)
388 unsigned int i;
390 for (i = 0; i < NUM_RELOCS; i++)
391 if (arm64_howto_table[i]->name != NULL
392 && strcasecmp (arm64_howto_table[i]->name, r_name) == 0)
393 return arm64_howto_table[i];
395 return NULL;
398 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 2
399 #define COFF_PAGE_SIZE 0x1000
401 static reloc_howto_type *
402 coff_aarch64_rtype_lookup (unsigned int code)
404 switch (code)
406 case IMAGE_REL_ARM64_ABSOLUTE:
407 return &arm64_reloc_howto_abs;
408 case IMAGE_REL_ARM64_ADDR64:
409 return &arm64_reloc_howto_64;
410 case IMAGE_REL_ARM64_ADDR32:
411 return &arm64_reloc_howto_32;
412 case IMAGE_REL_ARM64_REL32:
413 return &arm64_reloc_howto_32_pcrel;
414 case IMAGE_REL_ARM64_BRANCH26:
415 return &arm64_reloc_howto_branch26;
416 case IMAGE_REL_ARM64_PAGEBASE_REL21:
417 return &arm64_reloc_howto_page21;
418 case IMAGE_REL_ARM64_REL21:
419 return &arm64_reloc_howto_lo21;
420 case IMAGE_REL_ARM64_PAGEOFFSET_12L:
421 return &arm64_reloc_howto_pgoff12l;
422 case IMAGE_REL_ARM64_BRANCH19:
423 return &arm64_reloc_howto_branch19;
424 case IMAGE_REL_ARM64_BRANCH14:
425 return &arm64_reloc_howto_branch14;
426 case IMAGE_REL_ARM64_PAGEOFFSET_12A:
427 return &arm64_reloc_howto_pgoff12a;
428 case IMAGE_REL_ARM64_ADDR32NB:
429 return &arm64_reloc_howto_32nb;
430 case IMAGE_REL_ARM64_SECREL:
431 return &arm64_reloc_howto_secrel;
432 case IMAGE_REL_ARM64_SECTION:
433 return &arm64_reloc_howto_secidx;
434 default:
435 return NULL;
438 return NULL;
441 #define RTYPE2HOWTO(cache_ptr, dst) \
442 ((cache_ptr)->howto = coff_aarch64_rtype_lookup((dst)->r_type))
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)
452 reloc_howto_type *howto = coff_aarch64_rtype_lookup (rel->r_type);
454 /* Cancel out code in _bfd_coff_generic_relocate_section. */
455 *addendp = 0;
457 return howto;
460 #define coff_rtype_to_howto coff_aarch64_rtype_to_howto
462 #define SELECT_RELOC(x,howto) { (x).r_type = (howto)->type; }
464 #ifndef bfd_pe_print_pdata
465 #define bfd_pe_print_pdata NULL
466 #endif
468 #ifdef COFF_WITH_PE
469 /* Return TRUE if this relocation should
470 appear in the output .reloc section. */
472 static bool
473 in_reloc_p (bfd * abfd ATTRIBUTE_UNUSED,
474 reloc_howto_type * howto)
476 return !howto->pc_relative;
478 #endif
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)
490 struct internal_reloc *rel;
491 struct internal_reloc *relend;
493 if (bfd_link_relocatable (info))
494 return true;
496 rel = relocs;
497 relend = rel + input_section->reloc_count;
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. */
504 for (; rel < relend; rel++)
506 long symndx;
507 struct coff_link_hash_entry *h;
508 bfd_vma sym_value;
509 asection *sec = NULL;
510 uint64_t dest_vma;
512 /* skip trivial relocations */
513 if (rel->r_type == IMAGE_REL_ARM64_ADDR32
514 || rel->r_type == IMAGE_REL_ARM64_ADDR64
515 || rel->r_type == IMAGE_REL_ARM64_ABSOLUTE)
516 continue;
518 symndx = rel->r_symndx;
519 sym_value = syms[symndx].n_value;
521 h = obj_coff_sym_hashes (input_bfd)[symndx];
523 if (h && h->root.type == bfd_link_hash_defined)
525 sec = h->root.u.def.section;
526 sym_value = h->root.u.def.value;
528 else
530 sec = sections[symndx];
533 if (!sec)
534 continue;
536 if (bfd_is_und_section (sec))
537 continue;
539 if (discarded_section (sec))
540 continue;
542 dest_vma = sec->output_section->vma + sec->output_offset + sym_value;
544 if (symndx < 0
545 || (unsigned long) symndx >= obj_raw_syment_count (input_bfd))
546 continue;
548 /* All the relocs handled below operate on 4 bytes. */
549 if (input_section->size < rel->r_vaddr
550 || input_section->size - rel->r_vaddr < 4)
552 _bfd_error_handler
553 /* xgettext: c-format */
554 (_("%pB: bad reloc address %#" PRIx64 " in section `%pA'"),
555 input_bfd, (uint64_t) rel->r_vaddr, input_section);
556 continue;
559 switch (rel->r_type)
561 case IMAGE_REL_ARM64_ADDR32NB:
563 uint64_t val;
564 int32_t addend;
566 addend = bfd_getl32 (contents + rel->r_vaddr);
568 dest_vma += addend;
570 val = dest_vma;
571 val -= pe_data (output_bfd)->pe_opthdr.ImageBase;
573 if (val > 0xffffffff)
574 (*info->callbacks->reloc_overflow)
575 (info, h ? &h->root : NULL, syms[symndx]._n._n_name,
576 "IMAGE_REL_ARM64_ADDR32NB", addend, input_bfd,
577 input_section, rel->r_vaddr - input_section->vma);
579 bfd_putl32 (val, contents + rel->r_vaddr);
580 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
582 break;
585 case IMAGE_REL_ARM64_BRANCH26:
587 uint64_t cur_vma;
588 uint32_t opcode;
589 int64_t addend, val;
591 opcode = bfd_getl32 (contents + rel->r_vaddr);
593 addend = (opcode & 0x3ffffff) << 2;
595 if (addend & 0x8000000)
596 addend |= 0xfffffffff0000000;
598 dest_vma += addend;
599 cur_vma = input_section->output_section->vma
600 + input_section->output_offset
601 + rel->r_vaddr;
603 val = (dest_vma >> 2) - (cur_vma >> 2);
605 if (val > 0x1ffffff || val < -0x2000000)
606 (*info->callbacks->reloc_overflow)
607 (info, h ? &h->root : NULL, syms[symndx]._n._n_name,
608 "IMAGE_REL_ARM64_BRANCH26", addend, input_bfd,
609 input_section, rel->r_vaddr - input_section->vma);
611 opcode &= 0xfc000000;
612 opcode |= val & 0x3ffffff;
614 bfd_putl32 (opcode, contents + rel->r_vaddr);
615 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
617 break;
620 case IMAGE_REL_ARM64_BRANCH19:
622 uint64_t cur_vma;
623 uint32_t opcode;
624 int64_t addend, val;
626 opcode = bfd_getl32 (contents + rel->r_vaddr);
628 addend = (opcode & 0xffffe0) >> 3;
630 if (addend & 0x100000)
631 addend |= 0xffffffffffe00000;
633 dest_vma += addend;
634 cur_vma = input_section->output_section->vma
635 + input_section->output_offset
636 + rel->r_vaddr;
638 val = (dest_vma >> 2) - (cur_vma >> 2);
640 if (val > 0x3ffff || val < -0x40000)
641 (*info->callbacks->reloc_overflow)
642 (info, h ? &h->root : NULL, syms[symndx]._n._n_name,
643 "IMAGE_REL_ARM64_BRANCH19", addend, input_bfd,
644 input_section, rel->r_vaddr - input_section->vma);
646 opcode &= 0xff00001f;
647 opcode |= (val & 0x7ffff) << 5;
649 bfd_putl32 (opcode, contents + rel->r_vaddr);
650 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
652 break;
655 case IMAGE_REL_ARM64_BRANCH14:
657 uint64_t cur_vma;
658 uint32_t opcode;
659 int64_t addend, val;
661 opcode = bfd_getl32 (contents + rel->r_vaddr);
663 addend = (opcode & 0x7ffe0) >> 3;
665 if (addend & 0x8000)
666 addend |= 0xffffffffffff0000;
668 dest_vma += addend;
669 cur_vma = input_section->output_section->vma
670 + input_section->output_offset
671 + rel->r_vaddr;
673 val = (dest_vma >> 2) - (cur_vma >> 2);
675 if (val > 0x1fff || val < -0x2000)
676 (*info->callbacks->reloc_overflow)
677 (info, h ? &h->root : NULL, syms[symndx]._n._n_name,
678 "IMAGE_REL_ARM64_BRANCH14", addend, input_bfd,
679 input_section, rel->r_vaddr - input_section->vma);
681 opcode &= 0xfff8001f;
682 opcode |= (val & 0x3fff) << 5;
684 bfd_putl32 (opcode, contents + rel->r_vaddr);
685 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
687 break;
690 case IMAGE_REL_ARM64_PAGEBASE_REL21:
692 uint64_t cur_vma;
693 uint32_t opcode;
694 int64_t addend, val;
696 opcode = bfd_getl32 (contents + rel->r_vaddr);
698 addend = ((opcode & 0xffffe0) >> 3)
699 | ((opcode & 0x60000000) >> 29);
701 if (addend & 0x100000)
702 addend |= 0xffffffffffe00000;
704 dest_vma += addend;
705 cur_vma = input_section->output_section->vma
706 + input_section->output_offset
707 + rel->r_vaddr;
709 val = (dest_vma >> 12) - (cur_vma >> 12);
711 if (val > 0xfffff || val < -0x100000)
712 (*info->callbacks->reloc_overflow)
713 (info, h ? &h->root : NULL, syms[symndx]._n._n_name,
714 "IMAGE_REL_ARM64_PAGEBASE_REL21", addend, input_bfd,
715 input_section, rel->r_vaddr - input_section->vma);
717 opcode &= 0x9f00001f;
718 opcode |= (val & 0x3) << 29;
719 opcode |= (val & 0x1ffffc) << 3;
721 bfd_putl32 (opcode, contents + rel->r_vaddr);
722 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
724 break;
727 case IMAGE_REL_ARM64_REL21:
729 uint64_t cur_vma;
730 uint32_t opcode;
731 int64_t addend, val;
733 opcode = bfd_getl32 (contents + rel->r_vaddr);
735 addend = ((opcode & 0xffffe0) >> 3)
736 | ((opcode & 0x60000000) >> 29);
738 if (addend & 0x100000)
739 addend |= 0xffffffffffe00000;
741 dest_vma += addend;
742 cur_vma = input_section->output_section->vma
743 + input_section->output_offset
744 + rel->r_vaddr;
746 val = dest_vma - cur_vma;
748 if (val > 0xfffff || val < -0x100000)
749 (*info->callbacks->reloc_overflow)
750 (info, h ? &h->root : NULL, syms[symndx]._n._n_name,
751 "IMAGE_REL_ARM64_REL21", addend, input_bfd,
752 input_section, rel->r_vaddr - input_section->vma);
754 opcode &= 0x9f00001f;
755 opcode |= (val & 0x3) << 29;
756 opcode |= (val & 0x1ffffc) << 3;
758 bfd_putl32 (opcode, contents + rel->r_vaddr);
759 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
761 break;
764 case IMAGE_REL_ARM64_PAGEOFFSET_12L:
766 uint32_t opcode, val;
767 uint8_t shift;
768 int32_t addend;
770 opcode = bfd_getl32 (contents + rel->r_vaddr);
772 addend = (opcode & 0x3ffc00) >> 10;
774 if ((opcode & 0xff800000) == 0x3d800000)
776 /* LDR / STR with q register */
777 shift = 4;
779 else
781 /* top two bits represent how much addend should be shifted */
782 shift = opcode >> 30;
785 addend <<= shift;
787 dest_vma += addend;
789 /* only interested in bottom 12 bits */
790 val = dest_vma & 0xfff;
792 if (val & ((1 << shift) - 1))
793 (*info->callbacks->reloc_overflow)
794 (info, h ? &h->root : NULL, syms[symndx]._n._n_name,
795 "IMAGE_REL_ARM64_PAGEOFFSET_12L", addend, input_bfd,
796 input_section, rel->r_vaddr - input_section->vma);
798 val >>= shift;
800 opcode &= 0xffc003ff;
801 opcode |= val << 10;
803 bfd_putl32 (opcode, contents + rel->r_vaddr);
804 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
806 break;
809 case IMAGE_REL_ARM64_PAGEOFFSET_12A:
811 uint32_t opcode, val;
812 int32_t addend;
814 opcode = bfd_getl32 (contents + rel->r_vaddr);
816 addend = (opcode & 0x3ffc00) >> 10;
818 dest_vma += addend;
820 /* only interested in bottom 12 bits */
821 val = dest_vma & 0xfff;
823 opcode &= 0xffc003ff;
824 opcode |= val << 10;
826 bfd_putl32 (opcode, contents + rel->r_vaddr);
827 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
829 break;
832 case IMAGE_REL_ARM64_SECREL:
834 uint64_t val;
835 int32_t addend;
837 addend = bfd_getl32 (contents + rel->r_vaddr);
839 val = sec->output_offset + sym_value + addend;
841 if (val > 0xffffffff)
842 (*info->callbacks->reloc_overflow)
843 (info, h ? &h->root : NULL, syms[symndx]._n._n_name,
844 "IMAGE_REL_ARM64_SECREL", addend, input_bfd,
845 input_section, rel->r_vaddr - input_section->vma);
847 bfd_putl32 (val, contents + rel->r_vaddr);
848 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
850 break;
853 case IMAGE_REL_ARM64_SECTION:
855 uint16_t idx = 0, i = 1;
856 asection *s;
858 s = output_bfd->sections;
859 while (s)
861 if (s == sec->output_section)
863 idx = i;
864 break;
867 i++;
868 s = s->next;
872 bfd_putl16 (idx, contents + rel->r_vaddr);
873 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
875 break;
878 default:
879 info->callbacks->einfo (_("%F%P: Unhandled relocation type %u\n"),
880 rel->r_type);
881 BFD_FAIL ();
882 return false;
886 return _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
887 input_section, contents,
888 relocs, syms, sections);
891 #define coff_relocate_section coff_pe_aarch64_relocate_section
893 #include "coffcode.h"
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)
900 if (!coff_new_section_hook (abfd, section))
901 return false;
903 section->use_rela_p = 1;
905 return true;
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
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
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. */
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),
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 ),
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. */
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. */
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
966 { /* bfd_set_format. */
967 _bfd_bool_bfd_false_error,
968 coff_mkobject,
969 _bfd_generic_mkarchive,
970 _bfd_bool_bfd_false_error
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
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),
989 NULL,
991 COFF_SWAP_TABLE