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 /* For these howto special functions,
43 output_bfd == NULL => final link, or objdump -W and other calls to
44 bfd_simple_get_relocated_section_contents
45 output_bfd != NULL && output_bfd != abfd => ld -r
46 output_bfd != NULL && output_bfd == abfd => gas.
47 FIXME: ld -r is punted to bfd_perform_relocation. This won't be
48 correct for cases where the addend needs to be adjusted, eg. for
49 relocations against section symbols, and the field is split because
50 bfd_perform_relocation can't write addends to split relocation fields. */
52 static bfd_reloc_status_type
53 coff_aarch64_rel21_reloc (bfd
*abfd
,
57 asection
*input_section
,
59 char **error_message ATTRIBUTE_UNUSED
)
61 if (output_bfd
!= NULL
&& output_bfd
!= abfd
)
62 return bfd_reloc_continue
;
64 if (!bfd_reloc_offset_in_range (reloc_entry
->howto
, abfd
,
65 input_section
, reloc_entry
->address
))
66 return bfd_reloc_outofrange
;
68 uint32_t op
= bfd_getl32 (data
+ reloc_entry
->address
);
69 bfd_vma relocation
= reloc_entry
->addend
;
70 bfd_reloc_status_type ret
= bfd_reloc_ok
;
71 if (output_bfd
== NULL
)
73 if (bfd_is_und_section (symbol
->section
))
75 if ((symbol
->flags
& BSF_WEAK
) == 0)
76 ret
= bfd_reloc_undefined
;
78 else if (!bfd_is_com_section (symbol
->section
))
79 relocation
+= (symbol
->value
80 + symbol
->section
->output_offset
81 + symbol
->section
->output_section
->vma
);
82 bfd_vma addend
= ((op
>> 3) & 0x1ffffc) | ((op
>> 29) & 0x3);
83 addend
= (addend
^ 0x100000) - 0x100000;
85 relocation
-= (reloc_entry
->address
86 + input_section
->output_offset
87 + input_section
->output_section
->vma
);
88 relocation
= (bfd_signed_vma
) relocation
>> reloc_entry
->howto
->rightshift
;
90 if (relocation
+ 0x100000 > 0x1fffff)
91 ret
= bfd_reloc_overflow
;
94 op
|= (relocation
& 0x1ffffc) << 3;
95 op
|= (relocation
& 0x3) << 29;
97 bfd_putl32 (op
, data
+ reloc_entry
->address
);
102 static bfd_reloc_status_type
103 coff_aarch64_po12l_reloc (bfd
*abfd
,
104 arelent
*reloc_entry
,
105 asymbol
*symbol ATTRIBUTE_UNUSED
,
107 asection
*input_section
,
109 char **error_message ATTRIBUTE_UNUSED
)
111 if (output_bfd
!= NULL
&& output_bfd
!= abfd
)
112 return bfd_reloc_continue
;
114 if (!bfd_reloc_offset_in_range (reloc_entry
->howto
, abfd
,
115 input_section
, reloc_entry
->address
))
116 return bfd_reloc_outofrange
;
118 uint32_t op
= bfd_getl32 (data
+ reloc_entry
->address
);
119 bfd_vma relocation
= reloc_entry
->addend
& 0xfff;
122 if ((op
& 0xff800000) == 0x3d800000)
124 /* LDR / STR with q register */
129 /* top two bits represent how much addend should be shifted */
133 bfd_reloc_status_type ret
= bfd_reloc_ok
;
134 if (output_bfd
== NULL
)
136 if (bfd_is_und_section (symbol
->section
))
138 if ((symbol
->flags
& BSF_WEAK
) == 0)
139 ret
= bfd_reloc_undefined
;
141 else if (!bfd_is_com_section (symbol
->section
))
142 relocation
+= (symbol
->value
143 + symbol
->section
->output_offset
144 + symbol
->section
->output_section
->vma
);
145 bfd_vma addend
= (op
>> 10) & 0xfff;
147 relocation
+= addend
;
150 if (relocation
& ((1 << shift
) - 1))
151 ret
= bfd_reloc_overflow
;
154 op
|= (relocation
>> shift
<< 10) & 0x3ffc00;
156 bfd_putl32 (op
, data
+ reloc_entry
->address
);
161 static bfd_reloc_status_type
162 coff_aarch64_addr32nb_reloc (bfd
*abfd
,
163 arelent
*reloc_entry
,
164 asymbol
*symbol ATTRIBUTE_UNUSED
,
166 asection
*input_section
,
168 char **error_message
)
170 if (output_bfd
!= NULL
&& output_bfd
!= abfd
)
171 return bfd_reloc_continue
;
173 if (!bfd_reloc_offset_in_range (reloc_entry
->howto
, abfd
,
174 input_section
, reloc_entry
->address
))
175 return bfd_reloc_outofrange
;
177 bfd_vma relocation
= reloc_entry
->addend
;
178 bfd_reloc_status_type ret
= bfd_reloc_ok
;
179 if (output_bfd
== NULL
)
181 if (bfd_is_und_section (symbol
->section
))
183 if ((symbol
->flags
& BSF_WEAK
) == 0)
184 ret
= bfd_reloc_undefined
;
186 else if (!bfd_is_com_section (symbol
->section
))
187 relocation
+= (symbol
->value
188 + symbol
->section
->output_offset
189 + symbol
->section
->output_section
->vma
);
190 bfd_vma addend
= bfd_getl_signed_32 (data
+ reloc_entry
->address
);
191 relocation
+= addend
;
192 bfd
*obfd
= input_section
->output_section
->owner
;
193 if (bfd_get_flavour (obfd
) == bfd_target_coff_flavour
195 relocation
-= pe_data (obfd
)->pe_opthdr
.ImageBase
;
198 *error_message
= "unsupported";
199 return bfd_reloc_dangerous
;
203 if (relocation
+ 0x80000000 > 0xffffffff)
204 ret
= bfd_reloc_overflow
;
206 bfd_putl32 (relocation
, data
+ reloc_entry
->address
);
211 static bfd_reloc_status_type
212 coff_aarch64_secrel_reloc (bfd
*abfd
,
213 arelent
*reloc_entry
,
214 asymbol
*symbol ATTRIBUTE_UNUSED
,
216 asection
*input_section
,
218 char **error_message ATTRIBUTE_UNUSED
)
220 if (output_bfd
!= NULL
&& output_bfd
!= abfd
)
221 return bfd_reloc_continue
;
223 if (!bfd_reloc_offset_in_range (reloc_entry
->howto
, abfd
,
224 input_section
, reloc_entry
->address
))
225 return bfd_reloc_outofrange
;
227 bfd_vma relocation
= reloc_entry
->addend
;
228 bfd_reloc_status_type ret
= bfd_reloc_ok
;
229 if (output_bfd
== NULL
)
231 if (bfd_is_und_section (symbol
->section
))
233 if ((symbol
->flags
& BSF_WEAK
) == 0)
234 ret
= bfd_reloc_undefined
;
236 else if (!bfd_is_com_section (symbol
->section
))
237 relocation
+= (symbol
->value
238 + symbol
->section
->output_offset
);
239 bfd_vma addend
= bfd_getl_signed_32 (data
+ reloc_entry
->address
);
240 relocation
+= addend
;
242 if (relocation
> 0xffffffff)
243 ret
= bfd_reloc_overflow
;
245 bfd_putl32 (relocation
, data
+ reloc_entry
->address
);
250 #define coff_aarch64_NULL NULL
251 #undef HOWTO_INSTALL_ADDEND
252 #define HOWTO_INSTALL_ADDEND 1
253 #define HOW(type, right, size, bits, pcrel, left, ovf, func, mask) \
254 HOWTO (type, right, size, bits, pcrel, left, complain_overflow_##ovf, \
255 coff_aarch64_##func, #type, true, mask, mask, false)
257 static const reloc_howto_type arm64_reloc_howto_abs
258 = HOW (IMAGE_REL_ARM64_ABSOLUTE
,
259 0, 0, 0, false, 0, dont
, NULL
, 0);
261 static const reloc_howto_type arm64_reloc_howto_64
262 = HOW (IMAGE_REL_ARM64_ADDR64
,
263 0, 8, 64, false, 0, dont
, NULL
, UINT64_C (-1));
265 static const reloc_howto_type arm64_reloc_howto_32
266 = HOW (IMAGE_REL_ARM64_ADDR32
,
267 0, 4, 32, false, 0, signed, NULL
, 0xffffffff);
269 static const reloc_howto_type arm64_reloc_howto_32_pcrel
270 = HOW (IMAGE_REL_ARM64_REL32
,
271 0, 4, 32, true, 0, signed, NULL
, 0xffffffff);
273 static const reloc_howto_type arm64_reloc_howto_branch26
274 = HOW (IMAGE_REL_ARM64_BRANCH26
,
275 2, 4, 26, true, 0, signed, NULL
, 0x3ffffff);
277 static const reloc_howto_type arm64_reloc_howto_page21
278 = HOW (IMAGE_REL_ARM64_PAGEBASE_REL21
,
279 12, 4, 21, true, 0, signed, rel21_reloc
, 0x1fffff);
281 static const reloc_howto_type arm64_reloc_howto_lo21
282 = HOW (IMAGE_REL_ARM64_REL21
,
283 0, 4, 21, true, 0, signed, rel21_reloc
, 0x1fffff);
285 static const reloc_howto_type arm64_reloc_howto_pgoff12l
286 = HOW (IMAGE_REL_ARM64_PAGEOFFSET_12L
,
287 0, 4, 12, true, 10, signed, po12l_reloc
, 0x3ffc00);
289 static const reloc_howto_type arm64_reloc_howto_branch19
290 = HOW (IMAGE_REL_ARM64_BRANCH19
,
291 2, 4, 19, true, 5, signed, NULL
, 0xffffe0);
293 static const reloc_howto_type arm64_reloc_howto_branch14
294 = HOW (IMAGE_REL_ARM64_BRANCH14
,
295 2, 4, 14, true, 5, signed, NULL
, 0x7ffe0);
297 static const reloc_howto_type arm64_reloc_howto_pgoff12a
298 = HOW (IMAGE_REL_ARM64_PAGEOFFSET_12A
,
299 0, 4, 12, true, 10, dont
, NULL
, 0x3ffc00);
301 static const reloc_howto_type arm64_reloc_howto_32nb
302 = HOW (IMAGE_REL_ARM64_ADDR32NB
,
303 0, 4, 32, false, 0, signed, addr32nb_reloc
, 0xffffffff);
305 static const reloc_howto_type arm64_reloc_howto_secrel
306 = HOW (IMAGE_REL_ARM64_SECREL
,
307 0, 4, 32, false, 0, dont
, secrel_reloc
, 0xffffffff);
309 static const reloc_howto_type arm64_reloc_howto_secidx
310 = HOW (IMAGE_REL_ARM64_SECTION
,
311 0, 2, 16, false, 0, dont
, NULL
, 0xffff);
313 static const reloc_howto_type
* const arm64_howto_table
[] = {
314 &arm64_reloc_howto_abs
,
315 &arm64_reloc_howto_64
,
316 &arm64_reloc_howto_32
,
317 &arm64_reloc_howto_32_pcrel
,
318 &arm64_reloc_howto_branch26
,
319 &arm64_reloc_howto_page21
,
320 &arm64_reloc_howto_lo21
,
321 &arm64_reloc_howto_pgoff12l
,
322 &arm64_reloc_howto_branch19
,
323 &arm64_reloc_howto_branch14
,
324 &arm64_reloc_howto_pgoff12a
,
325 &arm64_reloc_howto_32nb
,
326 &arm64_reloc_howto_secrel
,
327 &arm64_reloc_howto_secidx
330 /* No adjustment to addends should be needed. The actual relocation
331 addend is in the section contents. Unfortunately this means actual
332 addends are not shown by objdump -r, but that's true for most
333 COFF/PE targets where arelent.addend is an adjustment. */
334 #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
335 cache_ptr->addend = 0;
338 #define NUM_ELEM(a) ((sizeof (a)) / sizeof ((a)[0]))
341 #define NUM_RELOCS NUM_ELEM (arm64_howto_table)
343 #define coff_bfd_reloc_type_lookup coff_aarch64_reloc_type_lookup
344 #define coff_bfd_reloc_name_lookup coff_aarch64_reloc_name_lookup
346 static reloc_howto_type
*
347 coff_aarch64_reloc_type_lookup (bfd
* abfd ATTRIBUTE_UNUSED
, bfd_reloc_code_real_type code
)
352 return &arm64_reloc_howto_64
;
354 return &arm64_reloc_howto_32
;
355 case BFD_RELOC_32_PCREL
:
356 return &arm64_reloc_howto_32_pcrel
;
357 case BFD_RELOC_AARCH64_CALL26
:
358 case BFD_RELOC_AARCH64_JUMP26
:
359 return &arm64_reloc_howto_branch26
;
360 case BFD_RELOC_AARCH64_ADR_HI21_PCREL
:
361 case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL
:
362 return &arm64_reloc_howto_page21
;
363 case BFD_RELOC_AARCH64_TSTBR14
:
364 return &arm64_reloc_howto_branch14
;
365 case BFD_RELOC_AARCH64_ADR_LO21_PCREL
:
366 return &arm64_reloc_howto_lo21
;
367 case BFD_RELOC_AARCH64_ADD_LO12
:
368 return &arm64_reloc_howto_pgoff12a
;
369 case BFD_RELOC_AARCH64_LDST8_LO12
:
370 case BFD_RELOC_AARCH64_LDST16_LO12
:
371 case BFD_RELOC_AARCH64_LDST32_LO12
:
372 case BFD_RELOC_AARCH64_LDST64_LO12
:
373 case BFD_RELOC_AARCH64_LDST128_LO12
:
374 return &arm64_reloc_howto_pgoff12l
;
375 case BFD_RELOC_AARCH64_BRANCH19
:
376 return &arm64_reloc_howto_branch19
;
378 return &arm64_reloc_howto_32nb
;
379 case BFD_RELOC_32_SECREL
:
380 return &arm64_reloc_howto_secrel
;
381 case BFD_RELOC_16_SECIDX
:
382 return &arm64_reloc_howto_secidx
;
391 static reloc_howto_type
*
392 coff_aarch64_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
397 for (i
= 0; i
< NUM_RELOCS
; i
++)
398 if (arm64_howto_table
[i
]->name
!= NULL
399 && strcasecmp (arm64_howto_table
[i
]->name
, r_name
) == 0)
400 return arm64_howto_table
[i
];
405 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 2
406 #define COFF_PAGE_SIZE 0x1000
408 static reloc_howto_type
*
409 coff_aarch64_rtype_lookup (unsigned int code
)
413 case IMAGE_REL_ARM64_ABSOLUTE
:
414 return &arm64_reloc_howto_abs
;
415 case IMAGE_REL_ARM64_ADDR64
:
416 return &arm64_reloc_howto_64
;
417 case IMAGE_REL_ARM64_ADDR32
:
418 return &arm64_reloc_howto_32
;
419 case IMAGE_REL_ARM64_REL32
:
420 return &arm64_reloc_howto_32_pcrel
;
421 case IMAGE_REL_ARM64_BRANCH26
:
422 return &arm64_reloc_howto_branch26
;
423 case IMAGE_REL_ARM64_PAGEBASE_REL21
:
424 return &arm64_reloc_howto_page21
;
425 case IMAGE_REL_ARM64_REL21
:
426 return &arm64_reloc_howto_lo21
;
427 case IMAGE_REL_ARM64_PAGEOFFSET_12L
:
428 return &arm64_reloc_howto_pgoff12l
;
429 case IMAGE_REL_ARM64_BRANCH19
:
430 return &arm64_reloc_howto_branch19
;
431 case IMAGE_REL_ARM64_BRANCH14
:
432 return &arm64_reloc_howto_branch14
;
433 case IMAGE_REL_ARM64_PAGEOFFSET_12A
:
434 return &arm64_reloc_howto_pgoff12a
;
435 case IMAGE_REL_ARM64_ADDR32NB
:
436 return &arm64_reloc_howto_32nb
;
437 case IMAGE_REL_ARM64_SECREL
:
438 return &arm64_reloc_howto_secrel
;
439 case IMAGE_REL_ARM64_SECTION
:
440 return &arm64_reloc_howto_secidx
;
448 #define RTYPE2HOWTO(cache_ptr, dst) \
449 ((cache_ptr)->howto = coff_aarch64_rtype_lookup((dst)->r_type))
451 static reloc_howto_type
*
452 coff_aarch64_rtype_to_howto (bfd
*abfd ATTRIBUTE_UNUSED
,
453 asection
*sec ATTRIBUTE_UNUSED
,
454 struct internal_reloc
*rel
,
455 struct coff_link_hash_entry
*h ATTRIBUTE_UNUSED
,
456 struct internal_syment
*sym ATTRIBUTE_UNUSED
,
459 reloc_howto_type
*howto
= coff_aarch64_rtype_lookup (rel
->r_type
);
461 /* Cancel out code in _bfd_coff_generic_relocate_section. */
467 #define coff_rtype_to_howto coff_aarch64_rtype_to_howto
469 #define SELECT_RELOC(x,howto) { (x).r_type = (howto)->type; }
471 #ifndef bfd_pe_print_pdata
472 #define bfd_pe_print_pdata NULL
476 /* Return TRUE if this relocation should
477 appear in the output .reloc section. */
480 in_reloc_p (bfd
* abfd ATTRIBUTE_UNUSED
,
481 reloc_howto_type
* howto
)
483 return !howto
->pc_relative
;
488 coff_pe_aarch64_relocate_section (bfd
*output_bfd
,
489 struct bfd_link_info
*info
,
491 asection
*input_section
,
493 struct internal_reloc
*relocs
,
494 struct internal_syment
*syms
,
497 struct internal_reloc
*rel
;
498 struct internal_reloc
*relend
;
500 if (bfd_link_relocatable (info
))
504 relend
= rel
+ input_section
->reloc_count
;
506 /* The addend for a relocation is stored in the immediate bits of each
507 opcode. So for each relocation, we need to extract the immediate value,
508 use this to calculate what it should be for the symbol, and rewrite the
509 opcode into the section stream. */
511 for (; rel
< relend
; rel
++)
514 struct coff_link_hash_entry
*h
;
516 asection
*sec
= NULL
;
519 /* skip trivial relocations */
520 if (rel
->r_type
== IMAGE_REL_ARM64_ADDR32
521 || rel
->r_type
== IMAGE_REL_ARM64_ADDR64
522 || rel
->r_type
== IMAGE_REL_ARM64_ABSOLUTE
)
525 symndx
= rel
->r_symndx
;
526 sym_value
= syms
[symndx
].n_value
;
528 h
= obj_coff_sym_hashes (input_bfd
)[symndx
];
530 if (h
&& h
->root
.type
== bfd_link_hash_defined
)
532 sec
= h
->root
.u
.def
.section
;
533 sym_value
= h
->root
.u
.def
.value
;
537 sec
= sections
[symndx
];
543 if (bfd_is_und_section (sec
))
546 if (discarded_section (sec
))
549 dest_vma
= sec
->output_section
->vma
+ sec
->output_offset
+ sym_value
;
552 || (unsigned long) symndx
>= obj_raw_syment_count (input_bfd
))
555 /* All the relocs handled below operate on 4 bytes. */
556 if (input_section
->size
< rel
->r_vaddr
557 || input_section
->size
- rel
->r_vaddr
< 4)
560 /* xgettext: c-format */
561 (_("%pB: bad reloc address %#" PRIx64
" in section `%pA'"),
562 input_bfd
, (uint64_t) rel
->r_vaddr
, input_section
);
568 case IMAGE_REL_ARM64_ADDR32NB
:
573 addend
= bfd_getl32 (contents
+ rel
->r_vaddr
);
578 val
-= pe_data (output_bfd
)->pe_opthdr
.ImageBase
;
580 if (val
> 0xffffffff)
581 (*info
->callbacks
->reloc_overflow
)
582 (info
, h
? &h
->root
: NULL
, syms
[symndx
]._n
._n_name
,
583 "IMAGE_REL_ARM64_ADDR32NB", addend
, input_bfd
,
584 input_section
, rel
->r_vaddr
- input_section
->vma
);
586 bfd_putl32 (val
, contents
+ rel
->r_vaddr
);
587 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
592 case IMAGE_REL_ARM64_BRANCH26
:
598 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
600 addend
= (opcode
& 0x3ffffff) << 2;
602 if (addend
& 0x8000000)
603 addend
|= 0xfffffffff0000000;
606 cur_vma
= input_section
->output_section
->vma
607 + input_section
->output_offset
610 val
= (dest_vma
>> 2) - (cur_vma
>> 2);
612 if (val
> 0x1ffffff || val
< -0x2000000)
613 (*info
->callbacks
->reloc_overflow
)
614 (info
, h
? &h
->root
: NULL
, syms
[symndx
]._n
._n_name
,
615 "IMAGE_REL_ARM64_BRANCH26", addend
, input_bfd
,
616 input_section
, rel
->r_vaddr
- input_section
->vma
);
618 opcode
&= 0xfc000000;
619 opcode
|= val
& 0x3ffffff;
621 bfd_putl32 (opcode
, contents
+ rel
->r_vaddr
);
622 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
627 case IMAGE_REL_ARM64_BRANCH19
:
633 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
635 addend
= (opcode
& 0xffffe0) >> 3;
637 if (addend
& 0x100000)
638 addend
|= 0xffffffffffe00000;
641 cur_vma
= input_section
->output_section
->vma
642 + input_section
->output_offset
645 val
= (dest_vma
>> 2) - (cur_vma
>> 2);
647 if (val
> 0x3ffff || val
< -0x40000)
648 (*info
->callbacks
->reloc_overflow
)
649 (info
, h
? &h
->root
: NULL
, syms
[symndx
]._n
._n_name
,
650 "IMAGE_REL_ARM64_BRANCH19", addend
, input_bfd
,
651 input_section
, rel
->r_vaddr
- input_section
->vma
);
653 opcode
&= 0xff00001f;
654 opcode
|= (val
& 0x7ffff) << 5;
656 bfd_putl32 (opcode
, contents
+ rel
->r_vaddr
);
657 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
662 case IMAGE_REL_ARM64_BRANCH14
:
668 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
670 addend
= (opcode
& 0x7ffe0) >> 3;
673 addend
|= 0xffffffffffff0000;
676 cur_vma
= input_section
->output_section
->vma
677 + input_section
->output_offset
680 val
= (dest_vma
>> 2) - (cur_vma
>> 2);
682 if (val
> 0x1fff || val
< -0x2000)
683 (*info
->callbacks
->reloc_overflow
)
684 (info
, h
? &h
->root
: NULL
, syms
[symndx
]._n
._n_name
,
685 "IMAGE_REL_ARM64_BRANCH14", addend
, input_bfd
,
686 input_section
, rel
->r_vaddr
- input_section
->vma
);
688 opcode
&= 0xfff8001f;
689 opcode
|= (val
& 0x3fff) << 5;
691 bfd_putl32 (opcode
, contents
+ rel
->r_vaddr
);
692 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
697 case IMAGE_REL_ARM64_PAGEBASE_REL21
:
703 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
705 addend
= ((opcode
& 0xffffe0) >> 3)
706 | ((opcode
& 0x60000000) >> 29);
708 if (addend
& 0x100000)
709 addend
|= 0xffffffffffe00000;
712 cur_vma
= input_section
->output_section
->vma
713 + input_section
->output_offset
716 val
= (dest_vma
>> 12) - (cur_vma
>> 12);
718 if (val
> 0xfffff || val
< -0x100000)
719 (*info
->callbacks
->reloc_overflow
)
720 (info
, h
? &h
->root
: NULL
, syms
[symndx
]._n
._n_name
,
721 "IMAGE_REL_ARM64_PAGEBASE_REL21", addend
, input_bfd
,
722 input_section
, rel
->r_vaddr
- input_section
->vma
);
724 opcode
&= 0x9f00001f;
725 opcode
|= (val
& 0x3) << 29;
726 opcode
|= (val
& 0x1ffffc) << 3;
728 bfd_putl32 (opcode
, contents
+ rel
->r_vaddr
);
729 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
734 case IMAGE_REL_ARM64_REL21
:
740 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
742 addend
= ((opcode
& 0xffffe0) >> 3)
743 | ((opcode
& 0x60000000) >> 29);
745 if (addend
& 0x100000)
746 addend
|= 0xffffffffffe00000;
749 cur_vma
= input_section
->output_section
->vma
750 + input_section
->output_offset
753 val
= dest_vma
- cur_vma
;
755 if (val
> 0xfffff || val
< -0x100000)
756 (*info
->callbacks
->reloc_overflow
)
757 (info
, h
? &h
->root
: NULL
, syms
[symndx
]._n
._n_name
,
758 "IMAGE_REL_ARM64_REL21", addend
, input_bfd
,
759 input_section
, rel
->r_vaddr
- input_section
->vma
);
761 opcode
&= 0x9f00001f;
762 opcode
|= (val
& 0x3) << 29;
763 opcode
|= (val
& 0x1ffffc) << 3;
765 bfd_putl32 (opcode
, contents
+ rel
->r_vaddr
);
766 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
771 case IMAGE_REL_ARM64_PAGEOFFSET_12L
:
773 uint32_t opcode
, val
;
777 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
779 addend
= (opcode
& 0x3ffc00) >> 10;
781 if ((opcode
& 0xff800000) == 0x3d800000)
783 /* LDR / STR with q register */
788 /* top two bits represent how much addend should be shifted */
789 shift
= opcode
>> 30;
796 /* only interested in bottom 12 bits */
797 val
= dest_vma
& 0xfff;
799 if (val
& ((1 << shift
) - 1))
800 (*info
->callbacks
->reloc_overflow
)
801 (info
, h
? &h
->root
: NULL
, syms
[symndx
]._n
._n_name
,
802 "IMAGE_REL_ARM64_PAGEOFFSET_12L", addend
, input_bfd
,
803 input_section
, rel
->r_vaddr
- input_section
->vma
);
807 opcode
&= 0xffc003ff;
810 bfd_putl32 (opcode
, contents
+ rel
->r_vaddr
);
811 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
816 case IMAGE_REL_ARM64_PAGEOFFSET_12A
:
818 uint32_t opcode
, val
;
821 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
823 addend
= (opcode
& 0x3ffc00) >> 10;
827 /* only interested in bottom 12 bits */
828 val
= dest_vma
& 0xfff;
830 opcode
&= 0xffc003ff;
833 bfd_putl32 (opcode
, contents
+ rel
->r_vaddr
);
834 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
839 case IMAGE_REL_ARM64_SECREL
:
844 addend
= bfd_getl32 (contents
+ rel
->r_vaddr
);
846 val
= sec
->output_offset
+ sym_value
+ addend
;
848 if (val
> 0xffffffff)
849 (*info
->callbacks
->reloc_overflow
)
850 (info
, h
? &h
->root
: NULL
, syms
[symndx
]._n
._n_name
,
851 "IMAGE_REL_ARM64_SECREL", addend
, input_bfd
,
852 input_section
, rel
->r_vaddr
- input_section
->vma
);
854 bfd_putl32 (val
, contents
+ rel
->r_vaddr
);
855 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
860 case IMAGE_REL_ARM64_SECTION
:
862 uint16_t idx
= 0, i
= 1;
865 s
= output_bfd
->sections
;
868 if (s
== sec
->output_section
)
879 bfd_putl16 (idx
, contents
+ rel
->r_vaddr
);
880 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
886 info
->callbacks
->einfo (_("%F%P: Unhandled relocation type %u\n"),
893 return _bfd_coff_generic_relocate_section (output_bfd
, info
, input_bfd
,
894 input_section
, contents
,
895 relocs
, syms
, sections
);
898 #define coff_relocate_section coff_pe_aarch64_relocate_section
900 #include "coffcode.h"
902 /* Prevent assertion in md_apply_fix by forcing use_rela_p on for new
905 coff_aarch64_new_section_hook (bfd
*abfd
, asection
*section
)
907 if (!coff_new_section_hook (abfd
, section
))
910 section
->use_rela_p
= 1;
915 #define coff_aarch64_close_and_cleanup coff_close_and_cleanup
916 #define coff_aarch64_bfd_free_cached_info coff_bfd_free_cached_info
917 #define coff_aarch64_get_section_contents coff_get_section_contents
918 #define coff_aarch64_get_section_contents_in_window coff_get_section_contents_in_window
920 /* Target vectors. */
925 # error "target symbol name not specified"
931 # error "target name not specified"
933 bfd_target_coff_flavour
,
934 BFD_ENDIAN_LITTLE
, /* Data byte order is little. */
935 BFD_ENDIAN_LITTLE
, /* Header byte order is little. */
937 (HAS_RELOC
| EXEC_P
/* Object flags. */
938 | HAS_LINENO
| HAS_DEBUG
939 | HAS_SYMS
| HAS_LOCALS
| WP_TEXT
| D_PAGED
| BFD_COMPRESS
| BFD_DECOMPRESS
),
941 (SEC_HAS_CONTENTS
| SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
/* Section flags. */
942 #if defined(COFF_WITH_PE)
943 | SEC_LINK_ONCE
| SEC_LINK_DUPLICATES
| SEC_READONLY
| SEC_DEBUGGING
945 | SEC_CODE
| SEC_DATA
| SEC_EXCLUDE
),
947 #ifdef TARGET_UNDERSCORE
948 TARGET_UNDERSCORE
, /* Leading underscore. */
950 0, /* Leading underscore. */
952 '/', /* Ar_pad_char. */
953 15, /* Ar_max_namelen. */
954 0, /* match priority. */
955 TARGET_KEEP_UNUSED_SECTION_SYMBOLS
, /* keep unused section symbols. */
957 /* Data conversion functions. */
958 bfd_getl64
, bfd_getl_signed_64
, bfd_putl64
,
959 bfd_getl32
, bfd_getl_signed_32
, bfd_putl32
,
960 bfd_getl16
, bfd_getl_signed_16
, bfd_putl16
, /* Data. */
961 /* Header conversion functions. */
962 bfd_getl64
, bfd_getl_signed_64
, bfd_putl64
,
963 bfd_getl32
, bfd_getl_signed_32
, bfd_putl32
,
964 bfd_getl16
, bfd_getl_signed_16
, bfd_putl16
, /* Hdrs. */
966 /* Note that we allow an object file to be treated as a core file as well. */
967 { /* bfd_check_format. */
970 bfd_generic_archive_p
,
973 { /* bfd_set_format. */
974 _bfd_bool_bfd_false_error
,
976 _bfd_generic_mkarchive
,
977 _bfd_bool_bfd_false_error
979 { /* bfd_write_contents. */
980 _bfd_bool_bfd_false_error
,
981 coff_write_object_contents
,
982 _bfd_write_archive_contents
,
983 _bfd_bool_bfd_false_error
986 BFD_JUMP_TABLE_GENERIC (coff_aarch64
),
987 BFD_JUMP_TABLE_COPY (coff
),
988 BFD_JUMP_TABLE_CORE (_bfd_nocore
),
989 BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff
),
990 BFD_JUMP_TABLE_SYMBOLS (coff
),
991 BFD_JUMP_TABLE_RELOCS (coff
),
992 BFD_JUMP_TABLE_WRITE (coff
),
993 BFD_JUMP_TABLE_LINK (coff
),
994 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic
),