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
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. */
33 #include "coff/aarch64.h"
34 #include "coff/internal.h"
37 #include "libiberty.h"
42 static bfd_reloc_status_type
43 coff_aarch64_addr64_reloc (bfd
*abfd ATTRIBUTE_UNUSED
,
45 asymbol
*symbol ATTRIBUTE_UNUSED
,
47 asection
*input_section ATTRIBUTE_UNUSED
,
48 bfd
*output_bfd ATTRIBUTE_UNUSED
,
49 char **error_message ATTRIBUTE_UNUSED
)
51 uint64_t val
= reloc_entry
->addend
;
53 bfd_putl64 (val
, data
+ reloc_entry
->address
);
58 static bfd_reloc_status_type
59 coff_aarch64_addr32_reloc (bfd
*abfd ATTRIBUTE_UNUSED
,
61 asymbol
*symbol ATTRIBUTE_UNUSED
,
63 asection
*input_section ATTRIBUTE_UNUSED
,
64 bfd
*output_bfd ATTRIBUTE_UNUSED
,
65 char **error_message ATTRIBUTE_UNUSED
)
69 if ((int64_t) reloc_entry
->addend
> 0x7fffffff
70 || (int64_t) reloc_entry
->addend
< -0x7fffffff)
71 return bfd_reloc_overflow
;
73 val
= reloc_entry
->addend
;
75 bfd_putl32 ((uint32_t) val
, data
+ reloc_entry
->address
);
80 static bfd_reloc_status_type
81 coff_aarch64_branch26_reloc (bfd
*abfd ATTRIBUTE_UNUSED
,
83 asymbol
*symbol ATTRIBUTE_UNUSED
,
85 asection
*input_section ATTRIBUTE_UNUSED
,
86 bfd
*output_bfd ATTRIBUTE_UNUSED
,
87 char **error_message ATTRIBUTE_UNUSED
)
92 op
= bfd_getl32 (data
+ reloc_entry
->address
);
93 param
= reloc_entry
->addend
;
95 if (param
> 0x7ffffff || param
< -0x8000000)
96 return bfd_reloc_overflow
;
99 op
|= (param
>> 2) & 0x3ffffff;
101 bfd_putl32 (op
, data
+ reloc_entry
->address
);
106 static bfd_reloc_status_type
107 coff_aarch64_rel21_reloc (bfd
*abfd ATTRIBUTE_UNUSED
,
108 arelent
*reloc_entry
,
109 asymbol
*symbol ATTRIBUTE_UNUSED
,
111 asection
*input_section ATTRIBUTE_UNUSED
,
112 bfd
*output_bfd ATTRIBUTE_UNUSED
,
113 char **error_message ATTRIBUTE_UNUSED
)
118 op
= bfd_getl32 (data
+ reloc_entry
->address
);
119 param
= reloc_entry
->addend
;
121 if (param
> 0xfffff || param
< -0x100000)
122 return bfd_reloc_overflow
;
125 op
|= (param
& 0x1ffffc) << 3;
126 op
|= (param
& 0x3) << 29;
128 bfd_putl32 (op
, data
+ reloc_entry
->address
);
133 static bfd_reloc_status_type
134 coff_aarch64_po12l_reloc (bfd
*abfd ATTRIBUTE_UNUSED
,
135 arelent
*reloc_entry
,
136 asymbol
*symbol ATTRIBUTE_UNUSED
,
138 asection
*input_section ATTRIBUTE_UNUSED
,
139 bfd
*output_bfd ATTRIBUTE_UNUSED
,
140 char **error_message ATTRIBUTE_UNUSED
)
146 op
= bfd_getl32 (data
+ reloc_entry
->address
);
147 param
= reloc_entry
->addend
& 0xfff;
149 if ((op
& 0xff800000) == 0x3d800000)
151 /* LDR / STR with q register */
156 /* top two bits represent how much addend should be shifted */
160 if (param
& ((1 << shift
) - 1))
161 return bfd_reloc_overflow
;
168 bfd_putl32 (op
, data
+ reloc_entry
->address
);
173 static bfd_reloc_status_type
174 coff_aarch64_branch19_reloc (bfd
*abfd ATTRIBUTE_UNUSED
,
175 arelent
*reloc_entry
,
176 asymbol
*symbol ATTRIBUTE_UNUSED
,
178 asection
*input_section ATTRIBUTE_UNUSED
,
179 bfd
*output_bfd ATTRIBUTE_UNUSED
,
180 char **error_message ATTRIBUTE_UNUSED
)
185 op
= bfd_getl32 (data
+ reloc_entry
->address
);
186 param
= reloc_entry
->addend
;
188 if (param
> 0xfffff || param
< -0x100000)
189 return bfd_reloc_overflow
;
192 op
|= ((param
>> 2) & 0x7ffff) << 5;
194 bfd_putl32 (op
, data
+ reloc_entry
->address
);
199 static bfd_reloc_status_type
200 coff_aarch64_branch14_reloc (bfd
*abfd ATTRIBUTE_UNUSED
,
201 arelent
*reloc_entry
,
202 asymbol
*symbol ATTRIBUTE_UNUSED
,
204 asection
*input_section ATTRIBUTE_UNUSED
,
205 bfd
*output_bfd ATTRIBUTE_UNUSED
,
206 char **error_message ATTRIBUTE_UNUSED
)
211 op
= bfd_getl32 (data
+ reloc_entry
->address
);
212 param
= reloc_entry
->addend
;
214 if (param
> 0x7fff || param
< -0x8000)
215 return bfd_reloc_overflow
;
218 op
|= ((param
>> 2) & 0x3fff) << 5;
220 bfd_putl32 (op
, data
+ reloc_entry
->address
);
225 static bfd_reloc_status_type
226 coff_aarch64_po12a_reloc (bfd
*abfd ATTRIBUTE_UNUSED
,
227 arelent
*reloc_entry
,
228 asymbol
*symbol ATTRIBUTE_UNUSED
,
230 asection
*input_section ATTRIBUTE_UNUSED
,
231 bfd
*output_bfd ATTRIBUTE_UNUSED
,
232 char **error_message ATTRIBUTE_UNUSED
)
237 op
= bfd_getl32 (data
+ reloc_entry
->address
);
238 param
= reloc_entry
->addend
;
241 op
|= (param
& 0xfff) << 10;
243 bfd_putl32 (op
, data
+ reloc_entry
->address
);
248 static bfd_reloc_status_type
249 coff_aarch64_addr32nb_reloc (bfd
*abfd ATTRIBUTE_UNUSED
,
250 arelent
*reloc_entry
,
251 asymbol
*symbol ATTRIBUTE_UNUSED
,
253 asection
*input_section ATTRIBUTE_UNUSED
,
254 bfd
*output_bfd ATTRIBUTE_UNUSED
,
255 char **error_message ATTRIBUTE_UNUSED
)
259 if ((int64_t) reloc_entry
->addend
> 0x7fffffff
260 || (int64_t) reloc_entry
->addend
< -0x7fffffff)
261 return bfd_reloc_overflow
;
263 val
= reloc_entry
->addend
;
265 bfd_putl32 ((uint32_t) val
, data
+ reloc_entry
->address
);
270 static bfd_reloc_status_type
271 coff_aarch64_secrel_reloc (bfd
*abfd ATTRIBUTE_UNUSED
,
272 arelent
*reloc_entry
,
273 asymbol
*symbol ATTRIBUTE_UNUSED
,
275 asection
*input_section ATTRIBUTE_UNUSED
,
276 bfd
*output_bfd ATTRIBUTE_UNUSED
,
277 char **error_message ATTRIBUTE_UNUSED
)
279 bfd_putl32 (reloc_entry
->addend
, data
+ reloc_entry
->address
);
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)
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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
358 #define NUM_ELEM(a) ((sizeof (a)) / sizeof ((a)[0]))
361 #define NUM_RELOCS NUM_ELEM (arm64_howto_table)
363 #define coff_bfd_reloc_type_lookup coff_aarch64_reloc_type_lookup
364 #define coff_bfd_reloc_name_lookup coff_aarch64_reloc_name_lookup
366 static reloc_howto_type
*
367 coff_aarch64_reloc_type_lookup (bfd
* abfd ATTRIBUTE_UNUSED
, bfd_reloc_code_real_type code
)
372 return &arm64_reloc_howto_64
;
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
;
398 return &arm64_reloc_howto_32nb
;
399 case BFD_RELOC_32_SECREL
:
400 return &arm64_reloc_howto_secrel
;
409 static reloc_howto_type
*
410 coff_aarch64_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
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
];
423 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 2
424 #define COFF_PAGE_SIZE 0x1000
426 static reloc_howto_type
*
427 coff_aarch64_rtype_lookup (unsigned int code
)
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
;
465 #define RTYPE2HOWTO(cache_ptr, dst) \
466 ((cache_ptr)->howto = coff_aarch64_rtype_lookup((dst)->r_type))
468 #define SELECT_RELOC(x,howto) { (x).r_type = (howto)->type; }
470 #ifndef bfd_pe_print_pdata
471 #define bfd_pe_print_pdata NULL
475 /* Return TRUE if this relocation should
476 appear in the output .reloc section. */
479 in_reloc_p (bfd
* abfd ATTRIBUTE_UNUSED
,
480 reloc_howto_type
* howto
)
482 return !howto
->pc_relative
;
487 coff_pe_aarch64_relocate_section (bfd
*output_bfd
,
488 struct bfd_link_info
*info
,
490 asection
*input_section
,
492 struct internal_reloc
*relocs
,
493 struct internal_syment
*syms
,
496 struct internal_reloc
*rel
;
497 struct internal_reloc
*relend
;
499 if (bfd_link_relocatable (info
))
503 relend
= rel
+ input_section
->reloc_count
;
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. */
510 for (; rel
< relend
; rel
++)
513 struct coff_link_hash_entry
*h
;
515 asection
*sec
= NULL
;
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
)
524 symndx
= rel
->r_symndx
;
525 sym_value
= syms
[symndx
].n_value
;
527 h
= obj_coff_sym_hashes (input_bfd
)[symndx
];
529 if (h
&& h
->root
.type
== bfd_link_hash_defined
)
531 sec
= h
->root
.u
.def
.section
;
532 sym_value
= h
->root
.u
.def
.value
;
536 sec
= sections
[symndx
];
542 if (bfd_is_und_section (sec
))
545 if (discarded_section (sec
))
548 dest_vma
= sec
->output_section
->vma
+ sec
->output_offset
+ sym_value
;
551 || (unsigned long) symndx
>= obj_raw_syment_count (input_bfd
))
556 case IMAGE_REL_ARM64_ADDR32NB
:
561 addend
= bfd_getl32 (contents
+ rel
->r_vaddr
);
566 val
-= pe_data (output_bfd
)->pe_opthdr
.ImageBase
;
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
);
574 bfd_putl32 (val
, contents
+ rel
->r_vaddr
);
575 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
580 case IMAGE_REL_ARM64_BRANCH26
:
586 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
588 addend
= (opcode
& 0x3ffffff) << 2;
590 if (addend
& 0x8000000)
591 addend
|= 0xfffffffff0000000;
594 cur_vma
= input_section
->output_section
->vma
595 + input_section
->output_offset
598 val
= (dest_vma
>> 2) - (cur_vma
>> 2);
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
);
606 opcode
&= 0xfc000000;
607 opcode
|= val
& 0x3ffffff;
609 bfd_putl32 (opcode
, contents
+ rel
->r_vaddr
);
610 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
615 case IMAGE_REL_ARM64_BRANCH19
:
621 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
623 addend
= (opcode
& 0xffffe0) >> 3;
625 if (addend
& 0x100000)
626 addend
|= 0xffffffffffe00000;
629 cur_vma
= input_section
->output_section
->vma
630 + input_section
->output_offset
633 val
= (dest_vma
>> 2) - (cur_vma
>> 2);
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
);
641 opcode
&= 0xff00001f;
642 opcode
|= (val
& 0x7ffff) << 5;
644 bfd_putl32 (opcode
, contents
+ rel
->r_vaddr
);
645 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
650 case IMAGE_REL_ARM64_BRANCH14
:
656 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
658 addend
= (opcode
& 0x7ffe0) >> 3;
661 addend
|= 0xffffffffffff0000;
664 cur_vma
= input_section
->output_section
->vma
665 + input_section
->output_offset
668 val
= (dest_vma
>> 2) - (cur_vma
>> 2);
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
);
676 opcode
&= 0xfff8001f;
677 opcode
|= (val
& 0x3fff) << 5;
679 bfd_putl32 (opcode
, contents
+ rel
->r_vaddr
);
680 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
685 case IMAGE_REL_ARM64_PAGEBASE_REL21
:
691 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
693 addend
= ((opcode
& 0xffffe0) >> 3)
694 | ((opcode
& 0x60000000) >> 29);
696 if (addend
& 0x100000)
697 addend
|= 0xffffffffffe00000;
700 cur_vma
= input_section
->output_section
->vma
701 + input_section
->output_offset
704 val
= (dest_vma
>> 12) - (cur_vma
>> 12);
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
);
712 opcode
&= 0x9f00001f;
713 opcode
|= (val
& 0x3) << 29;
714 opcode
|= (val
& 0x1ffffc) << 3;
716 bfd_putl32 (opcode
, contents
+ rel
->r_vaddr
);
717 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
722 case IMAGE_REL_ARM64_REL21
:
728 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
730 addend
= ((opcode
& 0xffffe0) >> 3)
731 | ((opcode
& 0x60000000) >> 29);
733 if (addend
& 0x100000)
734 addend
|= 0xffffffffffe00000;
737 cur_vma
= input_section
->output_section
->vma
738 + input_section
->output_offset
741 val
= dest_vma
- cur_vma
;
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
);
749 opcode
&= 0x9f00001f;
750 opcode
|= (val
& 0x3) << 29;
751 opcode
|= (val
& 0x1ffffc) << 3;
753 bfd_putl32 (opcode
, contents
+ rel
->r_vaddr
);
754 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
759 case IMAGE_REL_ARM64_PAGEOFFSET_12L
:
761 uint32_t opcode
, val
;
765 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
767 addend
= (opcode
& 0x3ffc00) >> 10;
769 if ((opcode
& 0xff800000) == 0x3d800000)
771 /* LDR / STR with q register */
776 /* top two bits represent how much addend should be shifted */
777 shift
= opcode
>> 30;
784 /* only interested in bottom 12 bits */
785 val
= dest_vma
& 0xfff;
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
);
795 opcode
&= 0xffc003ff;
798 bfd_putl32 (opcode
, contents
+ rel
->r_vaddr
);
799 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
804 case IMAGE_REL_ARM64_PAGEOFFSET_12A
:
806 uint32_t opcode
, val
;
809 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
811 addend
= (opcode
& 0x3ffc00) >> 10;
815 /* only interested in bottom 12 bits */
816 val
= dest_vma
& 0xfff;
818 opcode
&= 0xffc003ff;
821 bfd_putl32 (opcode
, contents
+ rel
->r_vaddr
);
822 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
827 case IMAGE_REL_ARM64_SECREL
:
832 addend
= bfd_getl32 (contents
+ rel
->r_vaddr
);
834 val
= sec
->output_offset
+ sym_value
+ addend
;
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
);
842 bfd_putl32 (val
, contents
+ rel
->r_vaddr
);
843 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
849 info
->callbacks
->einfo (_("%F%P: Unhandled relocation type %u\n"),
856 return _bfd_coff_generic_relocate_section (output_bfd
, info
, input_bfd
,
857 input_section
, contents
,
858 relocs
, syms
, sections
);
861 #define coff_relocate_section coff_pe_aarch64_relocate_section
863 #include "coffcode.h"
865 /* Prevent assertion in md_apply_fix by forcing use_rela_p on for new
868 coff_aarch64_new_section_hook (bfd
*abfd
, asection
*section
)
870 if (!coff_new_section_hook (abfd
, section
))
873 section
->use_rela_p
= 1;
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
883 /* Target vectors. */
888 # error "target symbol name not specified"
894 # error "target name not specified"
896 bfd_target_coff_flavour
,
897 BFD_ENDIAN_LITTLE
, /* Data byte order is little. */
898 BFD_ENDIAN_LITTLE
, /* Header byte order is little. */
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
),
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
908 | SEC_CODE
| SEC_DATA
| SEC_EXCLUDE
),
910 #ifdef TARGET_UNDERSCORE
911 TARGET_UNDERSCORE
, /* Leading underscore. */
913 0, /* Leading underscore. */
915 '/', /* Ar_pad_char. */
916 15, /* Ar_max_namelen. */
917 0, /* match priority. */
918 TARGET_KEEP_UNUSED_SECTION_SYMBOLS
, /* keep unused section symbols. */
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. */
929 /* Note that we allow an object file to be treated as a core file as well. */
930 { /* bfd_check_format. */
933 bfd_generic_archive_p
,
936 { /* bfd_set_format. */
937 _bfd_bool_bfd_false_error
,
939 _bfd_generic_mkarchive
,
940 _bfd_bool_bfd_false_error
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
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
),