1 /* BFD back-end for AArch64 COFF files.
2 Copyright (C) 2021-2024 Free Software Foundation, Inc.
4 This file is part of BFD, the Binary File Descriptor library.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
22 #ifndef COFF_WITH_peAArch64
23 #define COFF_WITH_peAArch64
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 case BFD_RELOC_AARCH64_ADR_GOT_PAGE
:
356 return &arm64_reloc_howto_page21
;
357 case BFD_RELOC_AARCH64_TSTBR14
:
358 return &arm64_reloc_howto_branch14
;
359 case BFD_RELOC_AARCH64_ADR_LO21_PCREL
:
360 return &arm64_reloc_howto_lo21
;
361 case BFD_RELOC_AARCH64_ADD_LO12
:
362 return &arm64_reloc_howto_pgoff12a
;
363 case BFD_RELOC_AARCH64_LDST8_LO12
:
364 case BFD_RELOC_AARCH64_LDST16_LO12
:
365 case BFD_RELOC_AARCH64_LDST32_LO12
:
366 case BFD_RELOC_AARCH64_LDST64_LO12
:
367 case BFD_RELOC_AARCH64_LDST128_LO12
:
368 case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC
:
369 return &arm64_reloc_howto_pgoff12l
;
370 case BFD_RELOC_AARCH64_BRANCH19
:
371 return &arm64_reloc_howto_branch19
;
373 return &arm64_reloc_howto_32nb
;
374 case BFD_RELOC_32_SECREL
:
375 return &arm64_reloc_howto_secrel
;
376 case BFD_RELOC_16_SECIDX
:
377 return &arm64_reloc_howto_secidx
;
386 static reloc_howto_type
*
387 coff_aarch64_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
392 for (i
= 0; i
< NUM_RELOCS
; i
++)
393 if (arm64_howto_table
[i
]->name
!= NULL
394 && strcasecmp (arm64_howto_table
[i
]->name
, r_name
) == 0)
395 return arm64_howto_table
[i
];
400 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 2
401 #define COFF_PAGE_SIZE 0x1000
403 static reloc_howto_type
*
404 coff_aarch64_rtype_lookup (unsigned int code
)
408 case IMAGE_REL_ARM64_ABSOLUTE
:
409 return &arm64_reloc_howto_abs
;
410 case IMAGE_REL_ARM64_ADDR64
:
411 return &arm64_reloc_howto_64
;
412 case IMAGE_REL_ARM64_ADDR32
:
413 return &arm64_reloc_howto_32
;
414 case IMAGE_REL_ARM64_REL32
:
415 return &arm64_reloc_howto_32_pcrel
;
416 case IMAGE_REL_ARM64_BRANCH26
:
417 return &arm64_reloc_howto_branch26
;
418 case IMAGE_REL_ARM64_PAGEBASE_REL21
:
419 return &arm64_reloc_howto_page21
;
420 case IMAGE_REL_ARM64_REL21
:
421 return &arm64_reloc_howto_lo21
;
422 case IMAGE_REL_ARM64_PAGEOFFSET_12L
:
423 return &arm64_reloc_howto_pgoff12l
;
424 case IMAGE_REL_ARM64_BRANCH19
:
425 return &arm64_reloc_howto_branch19
;
426 case IMAGE_REL_ARM64_BRANCH14
:
427 return &arm64_reloc_howto_branch14
;
428 case IMAGE_REL_ARM64_PAGEOFFSET_12A
:
429 return &arm64_reloc_howto_pgoff12a
;
430 case IMAGE_REL_ARM64_ADDR32NB
:
431 return &arm64_reloc_howto_32nb
;
432 case IMAGE_REL_ARM64_SECREL
:
433 return &arm64_reloc_howto_secrel
;
434 case IMAGE_REL_ARM64_SECTION
:
435 return &arm64_reloc_howto_secidx
;
443 #define RTYPE2HOWTO(cache_ptr, dst) \
444 ((cache_ptr)->howto = coff_aarch64_rtype_lookup((dst)->r_type))
446 static reloc_howto_type
*
447 coff_aarch64_rtype_to_howto (bfd
*abfd ATTRIBUTE_UNUSED
,
448 asection
*sec ATTRIBUTE_UNUSED
,
449 struct internal_reloc
*rel
,
450 struct coff_link_hash_entry
*h ATTRIBUTE_UNUSED
,
451 struct internal_syment
*sym ATTRIBUTE_UNUSED
,
454 reloc_howto_type
*howto
= coff_aarch64_rtype_lookup (rel
->r_type
);
456 /* Cancel out code in _bfd_coff_generic_relocate_section. */
462 #define coff_rtype_to_howto coff_aarch64_rtype_to_howto
464 #define SELECT_RELOC(x,howto) { (x).r_type = (howto)->type; }
466 #ifndef bfd_pe_print_pdata
467 #define bfd_pe_print_pdata NULL
471 /* Return TRUE if this relocation should
472 appear in the output .reloc section. */
475 in_reloc_p (bfd
* abfd ATTRIBUTE_UNUSED
,
476 reloc_howto_type
* howto
)
478 return !howto
->pc_relative
;
483 coff_pe_aarch64_relocate_section (bfd
*output_bfd
,
484 struct bfd_link_info
*info
,
486 asection
*input_section
,
488 struct internal_reloc
*relocs
,
489 struct internal_syment
*syms
,
492 struct internal_reloc
*rel
;
493 struct internal_reloc
*relend
;
495 if (bfd_link_relocatable (info
))
499 relend
= rel
+ input_section
->reloc_count
;
501 /* The addend for a relocation is stored in the immediate bits of each
502 opcode. So for each relocation, we need to extract the immediate value,
503 use this to calculate what it should be for the symbol, and rewrite the
504 opcode into the section stream. */
506 for (; rel
< relend
; rel
++)
509 struct coff_link_hash_entry
*h
;
511 asection
*sec
= NULL
;
514 /* skip trivial relocations */
515 if (rel
->r_type
== IMAGE_REL_ARM64_ADDR32
516 || rel
->r_type
== IMAGE_REL_ARM64_ADDR64
517 || rel
->r_type
== IMAGE_REL_ARM64_ABSOLUTE
)
520 symndx
= rel
->r_symndx
;
521 sym_value
= syms
[symndx
].n_value
;
523 h
= obj_coff_sym_hashes (input_bfd
)[symndx
];
525 if (h
&& h
->root
.type
== bfd_link_hash_defined
)
527 sec
= h
->root
.u
.def
.section
;
528 sym_value
= h
->root
.u
.def
.value
;
532 sec
= sections
[symndx
];
538 if (bfd_is_und_section (sec
))
541 if (discarded_section (sec
))
544 dest_vma
= sec
->output_section
->vma
+ sec
->output_offset
+ sym_value
;
547 || (unsigned long) symndx
>= obj_raw_syment_count (input_bfd
))
550 /* All the relocs handled below operate on 4 bytes. */
551 if (input_section
->size
< rel
->r_vaddr
552 || input_section
->size
- rel
->r_vaddr
< 4)
555 /* xgettext: c-format */
556 (_("%pB: bad reloc address %#" PRIx64
" in section `%pA'"),
557 input_bfd
, (uint64_t) rel
->r_vaddr
, input_section
);
563 case IMAGE_REL_ARM64_ADDR32NB
:
568 addend
= bfd_getl32 (contents
+ rel
->r_vaddr
);
573 val
-= pe_data (output_bfd
)->pe_opthdr
.ImageBase
;
575 if (val
> 0xffffffff)
576 (*info
->callbacks
->reloc_overflow
)
577 (info
, h
? &h
->root
: NULL
, syms
[symndx
]._n
._n_name
,
578 "IMAGE_REL_ARM64_ADDR32NB", addend
, input_bfd
,
579 input_section
, rel
->r_vaddr
- input_section
->vma
);
581 bfd_putl32 (val
, contents
+ rel
->r_vaddr
);
582 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
587 case IMAGE_REL_ARM64_BRANCH26
:
593 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
595 addend
= (opcode
& 0x3ffffff) << 2;
597 if (addend
& 0x8000000)
598 addend
|= 0xfffffffff0000000;
601 cur_vma
= input_section
->output_section
->vma
602 + input_section
->output_offset
605 val
= (dest_vma
>> 2) - (cur_vma
>> 2);
607 if (val
> 0x1ffffff || val
< -0x2000000)
608 (*info
->callbacks
->reloc_overflow
)
609 (info
, h
? &h
->root
: NULL
, syms
[symndx
]._n
._n_name
,
610 "IMAGE_REL_ARM64_BRANCH26", addend
, input_bfd
,
611 input_section
, rel
->r_vaddr
- input_section
->vma
);
613 opcode
&= 0xfc000000;
614 opcode
|= val
& 0x3ffffff;
616 bfd_putl32 (opcode
, contents
+ rel
->r_vaddr
);
617 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
622 case IMAGE_REL_ARM64_BRANCH19
:
628 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
630 addend
= (opcode
& 0xffffe0) >> 3;
632 if (addend
& 0x100000)
633 addend
|= 0xffffffffffe00000;
636 cur_vma
= input_section
->output_section
->vma
637 + input_section
->output_offset
640 val
= (dest_vma
>> 2) - (cur_vma
>> 2);
642 if (val
> 0x3ffff || val
< -0x40000)
643 (*info
->callbacks
->reloc_overflow
)
644 (info
, h
? &h
->root
: NULL
, syms
[symndx
]._n
._n_name
,
645 "IMAGE_REL_ARM64_BRANCH19", addend
, input_bfd
,
646 input_section
, rel
->r_vaddr
- input_section
->vma
);
648 opcode
&= 0xff00001f;
649 opcode
|= (val
& 0x7ffff) << 5;
651 bfd_putl32 (opcode
, contents
+ rel
->r_vaddr
);
652 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
657 case IMAGE_REL_ARM64_BRANCH14
:
663 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
665 addend
= (opcode
& 0x7ffe0) >> 3;
668 addend
|= 0xffffffffffff0000;
671 cur_vma
= input_section
->output_section
->vma
672 + input_section
->output_offset
675 val
= (dest_vma
>> 2) - (cur_vma
>> 2);
677 if (val
> 0x1fff || val
< -0x2000)
678 (*info
->callbacks
->reloc_overflow
)
679 (info
, h
? &h
->root
: NULL
, syms
[symndx
]._n
._n_name
,
680 "IMAGE_REL_ARM64_BRANCH14", addend
, input_bfd
,
681 input_section
, rel
->r_vaddr
- input_section
->vma
);
683 opcode
&= 0xfff8001f;
684 opcode
|= (val
& 0x3fff) << 5;
686 bfd_putl32 (opcode
, contents
+ rel
->r_vaddr
);
687 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
692 case IMAGE_REL_ARM64_PAGEBASE_REL21
:
698 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
700 addend
= ((opcode
& 0xffffe0) >> 3)
701 | ((opcode
& 0x60000000) >> 29);
703 if (addend
& 0x100000)
704 addend
|= 0xffffffffffe00000;
707 cur_vma
= input_section
->output_section
->vma
708 + input_section
->output_offset
711 val
= (dest_vma
>> 12) - (cur_vma
>> 12);
713 if (val
> 0xfffff || val
< -0x100000)
714 (*info
->callbacks
->reloc_overflow
)
715 (info
, h
? &h
->root
: NULL
, syms
[symndx
]._n
._n_name
,
716 "IMAGE_REL_ARM64_PAGEBASE_REL21", addend
, input_bfd
,
717 input_section
, rel
->r_vaddr
- input_section
->vma
);
719 opcode
&= 0x9f00001f;
720 opcode
|= (val
& 0x3) << 29;
721 opcode
|= (val
& 0x1ffffc) << 3;
723 bfd_putl32 (opcode
, contents
+ rel
->r_vaddr
);
724 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
729 case IMAGE_REL_ARM64_REL21
:
735 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
737 addend
= ((opcode
& 0xffffe0) >> 3)
738 | ((opcode
& 0x60000000) >> 29);
740 if (addend
& 0x100000)
741 addend
|= 0xffffffffffe00000;
744 cur_vma
= input_section
->output_section
->vma
745 + input_section
->output_offset
748 val
= dest_vma
- cur_vma
;
750 if (val
> 0xfffff || val
< -0x100000)
751 (*info
->callbacks
->reloc_overflow
)
752 (info
, h
? &h
->root
: NULL
, syms
[symndx
]._n
._n_name
,
753 "IMAGE_REL_ARM64_REL21", addend
, input_bfd
,
754 input_section
, rel
->r_vaddr
- input_section
->vma
);
756 opcode
&= 0x9f00001f;
757 opcode
|= (val
& 0x3) << 29;
758 opcode
|= (val
& 0x1ffffc) << 3;
760 bfd_putl32 (opcode
, contents
+ rel
->r_vaddr
);
761 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
766 case IMAGE_REL_ARM64_REL32
:
771 addend
= bfd_getl32 (contents
+ rel
->r_vaddr
);
773 if (addend
& 0x80000000)
774 addend
|= 0xffffffff00000000;
777 cur_vma
= input_section
->output_section
->vma
778 + input_section
->output_offset
781 val
= dest_vma
- cur_vma
;
783 if (val
> 0xffffffff || val
< -0x100000000)
784 (*info
->callbacks
->reloc_overflow
)
785 (info
, h
? &h
->root
: NULL
, syms
[symndx
]._n
._n_name
,
786 "IMAGE_REL_ARM64_REL32", addend
, input_bfd
,
787 input_section
, rel
->r_vaddr
- input_section
->vma
);
789 bfd_putl32 (val
, contents
+ rel
->r_vaddr
);
790 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
795 case IMAGE_REL_ARM64_PAGEOFFSET_12L
:
797 uint32_t opcode
, val
;
801 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
803 addend
= (opcode
& 0x3ffc00) >> 10;
805 if ((opcode
& 0xff800000) == 0x3d800000)
807 /* LDR / STR with q register */
812 /* top two bits represent how much addend should be shifted */
813 shift
= opcode
>> 30;
820 /* only interested in bottom 12 bits */
821 val
= dest_vma
& 0xfff;
823 if (val
& ((1 << shift
) - 1))
824 (*info
->callbacks
->reloc_overflow
)
825 (info
, h
? &h
->root
: NULL
, syms
[symndx
]._n
._n_name
,
826 "IMAGE_REL_ARM64_PAGEOFFSET_12L", addend
, input_bfd
,
827 input_section
, rel
->r_vaddr
- input_section
->vma
);
831 opcode
&= 0xffc003ff;
834 bfd_putl32 (opcode
, contents
+ rel
->r_vaddr
);
835 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
840 case IMAGE_REL_ARM64_PAGEOFFSET_12A
:
842 uint32_t opcode
, val
;
845 opcode
= bfd_getl32 (contents
+ rel
->r_vaddr
);
847 addend
= (opcode
& 0x3ffc00) >> 10;
851 /* only interested in bottom 12 bits */
852 val
= dest_vma
& 0xfff;
854 opcode
&= 0xffc003ff;
857 bfd_putl32 (opcode
, contents
+ rel
->r_vaddr
);
858 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
863 case IMAGE_REL_ARM64_SECREL
:
868 addend
= bfd_getl32 (contents
+ rel
->r_vaddr
);
870 val
= sec
->output_offset
+ sym_value
+ addend
;
872 if (val
> 0xffffffff)
873 (*info
->callbacks
->reloc_overflow
)
874 (info
, h
? &h
->root
: NULL
, syms
[symndx
]._n
._n_name
,
875 "IMAGE_REL_ARM64_SECREL", addend
, input_bfd
,
876 input_section
, rel
->r_vaddr
- input_section
->vma
);
878 bfd_putl32 (val
, contents
+ rel
->r_vaddr
);
879 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
884 case IMAGE_REL_ARM64_SECTION
:
886 uint16_t idx
= 0, i
= 1;
889 s
= output_bfd
->sections
;
892 if (s
== sec
->output_section
)
903 bfd_putl16 (idx
, contents
+ rel
->r_vaddr
);
904 rel
->r_type
= IMAGE_REL_ARM64_ABSOLUTE
;
910 info
->callbacks
->einfo (_("%F%P: Unhandled relocation type %u\n"),
917 return _bfd_coff_generic_relocate_section (output_bfd
, info
, input_bfd
,
918 input_section
, contents
,
919 relocs
, syms
, sections
);
922 #define coff_relocate_section coff_pe_aarch64_relocate_section
924 #include "coffcode.h"
926 /* Prevent assertion in md_apply_fix by forcing use_rela_p on for new
929 coff_aarch64_new_section_hook (bfd
*abfd
, asection
*section
)
931 if (!coff_new_section_hook (abfd
, section
))
934 section
->use_rela_p
= 1;
939 #define coff_aarch64_close_and_cleanup coff_close_and_cleanup
940 #define coff_aarch64_bfd_free_cached_info coff_bfd_free_cached_info
941 #define coff_aarch64_get_section_contents coff_get_section_contents
942 #define coff_aarch64_get_section_contents_in_window coff_get_section_contents_in_window
944 /* Target vectors. */
949 # error "target symbol name not specified"
955 # error "target name not specified"
957 bfd_target_coff_flavour
,
958 BFD_ENDIAN_LITTLE
, /* Data byte order is little. */
959 BFD_ENDIAN_LITTLE
, /* Header byte order is little. */
961 (HAS_RELOC
| EXEC_P
/* Object flags. */
962 | HAS_LINENO
| HAS_DEBUG
963 | HAS_SYMS
| HAS_LOCALS
| WP_TEXT
| D_PAGED
| BFD_COMPRESS
| BFD_DECOMPRESS
),
965 (SEC_HAS_CONTENTS
| SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
/* Section flags. */
966 #if defined(COFF_WITH_PE)
967 | SEC_LINK_ONCE
| SEC_LINK_DUPLICATES
| SEC_READONLY
| SEC_DEBUGGING
969 | SEC_CODE
| SEC_DATA
| SEC_EXCLUDE
),
971 #ifdef TARGET_UNDERSCORE
972 TARGET_UNDERSCORE
, /* Leading underscore. */
974 0, /* Leading underscore. */
976 '/', /* Ar_pad_char. */
977 15, /* Ar_max_namelen. */
978 0, /* match priority. */
979 TARGET_KEEP_UNUSED_SECTION_SYMBOLS
, /* keep unused section symbols. */
981 /* Data conversion functions. */
982 bfd_getl64
, bfd_getl_signed_64
, bfd_putl64
,
983 bfd_getl32
, bfd_getl_signed_32
, bfd_putl32
,
984 bfd_getl16
, bfd_getl_signed_16
, bfd_putl16
, /* Data. */
985 /* Header conversion functions. */
986 bfd_getl64
, bfd_getl_signed_64
, bfd_putl64
,
987 bfd_getl32
, bfd_getl_signed_32
, bfd_putl32
,
988 bfd_getl16
, bfd_getl_signed_16
, bfd_putl16
, /* Hdrs. */
990 /* Note that we allow an object file to be treated as a core file as well. */
991 { /* bfd_check_format. */
994 bfd_generic_archive_p
,
997 { /* bfd_set_format. */
998 _bfd_bool_bfd_false_error
,
1000 _bfd_generic_mkarchive
,
1001 _bfd_bool_bfd_false_error
1003 { /* bfd_write_contents. */
1004 _bfd_bool_bfd_false_error
,
1005 coff_write_object_contents
,
1006 _bfd_write_archive_contents
,
1007 _bfd_bool_bfd_false_error
1010 BFD_JUMP_TABLE_GENERIC (coff_aarch64
),
1011 BFD_JUMP_TABLE_COPY (coff
),
1012 BFD_JUMP_TABLE_CORE (_bfd_nocore
),
1013 BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff
),
1014 BFD_JUMP_TABLE_SYMBOLS (coff
),
1015 BFD_JUMP_TABLE_RELOCS (coff
),
1016 BFD_JUMP_TABLE_WRITE (coff
),
1017 BFD_JUMP_TABLE_LINK (coff
),
1018 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic
),