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
29 #include "coff/aarch64.h"
30 #include "coff/internal.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
,
50 asection
*input_section
,
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;
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
;
87 op
|= (relocation
& 0x1ffffc) << 3;
88 op
|= (relocation
& 0x3) << 29;
90 bfd_putl32 (op
, data
+ reloc_entry
->address
);
95 static bfd_reloc_status_type
96 coff_aarch64_po12l_reloc (bfd
*abfd
,
98 asymbol
*symbol ATTRIBUTE_UNUSED
,
100 asection
*input_section
,
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;
115 if ((op
& 0xff800000) == 0x3d800000)
117 /* LDR / STR with q register */
122 /* top two bits represent how much addend should be shifted */
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;
140 relocation
+= addend
;
143 if (relocation
& ((1 << shift
) - 1))
144 ret
= bfd_reloc_overflow
;
147 op
|= (relocation
>> shift
<< 10) & 0x3ffc00;
149 bfd_putl32 (op
, data
+ reloc_entry
->address
);
154 static bfd_reloc_status_type
155 coff_aarch64_addr32nb_reloc (bfd
*abfd
,
156 arelent
*reloc_entry
,
157 asymbol
*symbol ATTRIBUTE_UNUSED
,
159 asection
*input_section
,
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
188 relocation
-= pe_data (obfd
)->pe_opthdr
.ImageBase
;
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
);
204 static bfd_reloc_status_type
205 coff_aarch64_secrel_reloc (bfd
*abfd
,
206 arelent
*reloc_entry
,
207 asymbol
*symbol ATTRIBUTE_UNUSED
,
209 asection
*input_section
,
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
);
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;
331 #define NUM_ELEM(a) ((sizeof (a)) / sizeof ((a)[0]))
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
)
345 return &arm64_reloc_howto_64
;
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
;
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
;
384 static reloc_howto_type
*
385 coff_aarch64_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
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
];
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
)
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
;
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
,
452 reloc_howto_type
*howto
= coff_aarch64_rtype_lookup (rel
->r_type
);
454 /* Cancel out code in _bfd_coff_generic_relocate_section. */
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
469 /* Return TRUE if this relocation should
470 appear in the output .reloc section. */
473 in_reloc_p (bfd
* abfd ATTRIBUTE_UNUSED
,
474 reloc_howto_type
* howto
)
476 return !howto
->pc_relative
;
481 coff_pe_aarch64_relocate_section (bfd
*output_bfd
,
482 struct bfd_link_info
*info
,
484 asection
*input_section
,
486 struct internal_reloc
*relocs
,
487 struct internal_syment
*syms
,
490 struct internal_reloc
*rel
;
491 struct internal_reloc
*relend
;
493 if (bfd_link_relocatable (info
))
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
++)
507 struct coff_link_hash_entry
*h
;
509 asection
*sec
= NULL
;
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
)
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
;
530 sec
= sections
[symndx
];
536 if (bfd_is_und_section (sec
))
539 if (discarded_section (sec
))
542 dest_vma
= sec
->output_section
->vma
+ sec
->output_offset
+ sym_value
;
545 || (unsigned long) symndx
>= obj_raw_syment_count (input_bfd
))
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)
553 /* xgettext: c-format */
554 (_("%pB: bad reloc address %#" PRIx64
" in section `%pA'"),
555 input_bfd
, (uint64_t) rel
->r_vaddr
, input_section
);
561 case IMAGE_REL_ARM64_ADDR32NB
:
566 addend
= bfd_getl32 (contents
+ rel
->r_vaddr
);
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
;
585 case IMAGE_REL_ARM64_BRANCH26
:
591 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
593 addend
= (opcode
& 0x3ffffff) << 2;
595 if (addend
& 0x8000000)
596 addend
|= 0xfffffffff0000000;
599 cur_vma
= input_section
->output_section
->vma
600 + input_section
->output_offset
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
;
620 case IMAGE_REL_ARM64_BRANCH19
:
626 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
628 addend
= (opcode
& 0xffffe0) >> 3;
630 if (addend
& 0x100000)
631 addend
|= 0xffffffffffe00000;
634 cur_vma
= input_section
->output_section
->vma
635 + input_section
->output_offset
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
;
655 case IMAGE_REL_ARM64_BRANCH14
:
661 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
663 addend
= (opcode
& 0x7ffe0) >> 3;
666 addend
|= 0xffffffffffff0000;
669 cur_vma
= input_section
->output_section
->vma
670 + input_section
->output_offset
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
;
690 case IMAGE_REL_ARM64_PAGEBASE_REL21
:
696 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
698 addend
= ((opcode
& 0xffffe0) >> 3)
699 | ((opcode
& 0x60000000) >> 29);
701 if (addend
& 0x100000)
702 addend
|= 0xffffffffffe00000;
705 cur_vma
= input_section
->output_section
->vma
706 + input_section
->output_offset
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
;
727 case IMAGE_REL_ARM64_REL21
:
733 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
735 addend
= ((opcode
& 0xffffe0) >> 3)
736 | ((opcode
& 0x60000000) >> 29);
738 if (addend
& 0x100000)
739 addend
|= 0xffffffffffe00000;
742 cur_vma
= input_section
->output_section
->vma
743 + input_section
->output_offset
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
;
764 case IMAGE_REL_ARM64_PAGEOFFSET_12L
:
766 uint32_t opcode
, val
;
770 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
772 addend
= (opcode
& 0x3ffc00) >> 10;
774 if ((opcode
& 0xff800000) == 0x3d800000)
776 /* LDR / STR with q register */
781 /* top two bits represent how much addend should be shifted */
782 shift
= opcode
>> 30;
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
);
800 opcode
&= 0xffc003ff;
803 bfd_putl32 (opcode
, contents
+ rel
->r_vaddr
);
804 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
809 case IMAGE_REL_ARM64_PAGEOFFSET_12A
:
811 uint32_t opcode
, val
;
814 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
816 addend
= (opcode
& 0x3ffc00) >> 10;
820 /* only interested in bottom 12 bits */
821 val
= dest_vma
& 0xfff;
823 opcode
&= 0xffc003ff;
826 bfd_putl32 (opcode
, contents
+ rel
->r_vaddr
);
827 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
832 case IMAGE_REL_ARM64_SECREL
:
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
;
853 case IMAGE_REL_ARM64_SECTION
:
855 uint16_t idx
= 0, i
= 1;
858 s
= output_bfd
->sections
;
861 if (s
== sec
->output_section
)
872 bfd_putl16 (idx
, contents
+ rel
->r_vaddr
);
873 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
879 info
->callbacks
->einfo (_("%F%P: Unhandled relocation type %u\n"),
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
898 coff_aarch64_new_section_hook (bfd
*abfd
, asection
*section
)
900 if (!coff_new_section_hook (abfd
, section
))
903 section
->use_rela_p
= 1;
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. */
918 # error "target symbol name not specified"
924 # error "target name not specified"
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
938 | SEC_CODE
| SEC_DATA
| SEC_EXCLUDE
),
940 #ifdef TARGET_UNDERSCORE
941 TARGET_UNDERSCORE
, /* Leading underscore. */
943 0, /* Leading underscore. */
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. */
963 bfd_generic_archive_p
,
966 { /* bfd_set_format. */
967 _bfd_bool_bfd_false_error
,
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
),