]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - bfd/coff-aarch64.c
Fix the BFD library's find_nearest_line feature to produce consistent results.
[thirdparty/binutils-gdb.git] / bfd / coff-aarch64.c
1 /* BFD back-end for AArch64 COFF files.
2 Copyright (C) 2021-2023 Free Software Foundation, Inc.
3
4 This file is part of BFD, the Binary File Descriptor library.
5
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.
10
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.
15
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. */
20
21
22 #ifndef COFF_WITH_peAArch64
23 #define COFF_WITH_peAArch64
24 #endif
25
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. */
29 #ifndef PEI_HEADERS
30 #include "sysdep.h"
31 #include "bfd.h"
32 #include "libbfd.h"
33 #include "coff/aarch64.h"
34 #include "coff/internal.h"
35 #include "coff/pe.h"
36 #include "libcoff.h"
37 #include "libiberty.h"
38 #endif
39
40 #include "libcoff.h"
41
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. */
51
52 static bfd_reloc_status_type
53 coff_aarch64_rel21_reloc (bfd *abfd,
54 arelent *reloc_entry,
55 asymbol *symbol,
56 void *data,
57 asection *input_section,
58 bfd *output_bfd,
59 char **error_message ATTRIBUTE_UNUSED)
60 {
61 if (output_bfd != NULL && output_bfd != abfd)
62 return bfd_reloc_continue;
63
64 if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
65 input_section, reloc_entry->address))
66 return bfd_reloc_outofrange;
67
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)
72 {
73 if (bfd_is_und_section (symbol->section))
74 {
75 if ((symbol->flags & BSF_WEAK) == 0)
76 ret = bfd_reloc_undefined;
77 }
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;
84 relocation += addend;
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;
89 }
90 if (relocation + 0x100000 > 0x1fffff)
91 ret = bfd_reloc_overflow;
92
93 op &= 0x9f00001f;
94 op |= (relocation & 0x1ffffc) << 3;
95 op |= (relocation & 0x3) << 29;
96
97 bfd_putl32 (op, data + reloc_entry->address);
98
99 return ret;
100 }
101
102 static bfd_reloc_status_type
103 coff_aarch64_po12l_reloc (bfd *abfd,
104 arelent *reloc_entry,
105 asymbol *symbol ATTRIBUTE_UNUSED,
106 void *data,
107 asection *input_section,
108 bfd *output_bfd,
109 char **error_message ATTRIBUTE_UNUSED)
110 {
111 if (output_bfd != NULL && output_bfd != abfd)
112 return bfd_reloc_continue;
113
114 if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
115 input_section, reloc_entry->address))
116 return bfd_reloc_outofrange;
117
118 uint32_t op = bfd_getl32 (data + reloc_entry->address);
119 bfd_vma relocation = reloc_entry->addend & 0xfff;
120 int shift;
121
122 if ((op & 0xff800000) == 0x3d800000)
123 {
124 /* LDR / STR with q register */
125 shift = 4;
126 }
127 else
128 {
129 /* top two bits represent how much addend should be shifted */
130 shift = op >> 30;
131 }
132
133 bfd_reloc_status_type ret = bfd_reloc_ok;
134 if (output_bfd == NULL)
135 {
136 if (bfd_is_und_section (symbol->section))
137 {
138 if ((symbol->flags & BSF_WEAK) == 0)
139 ret = bfd_reloc_undefined;
140 }
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;
146 addend <<= shift;
147 relocation += addend;
148 }
149
150 if (relocation & ((1 << shift) - 1))
151 ret = bfd_reloc_overflow;
152
153 op &= 0xffc003ff;
154 op |= (relocation >> shift << 10) & 0x3ffc00;
155
156 bfd_putl32 (op, data + reloc_entry->address);
157
158 return ret;
159 }
160
161 static bfd_reloc_status_type
162 coff_aarch64_addr32nb_reloc (bfd *abfd,
163 arelent *reloc_entry,
164 asymbol *symbol ATTRIBUTE_UNUSED,
165 void *data,
166 asection *input_section,
167 bfd *output_bfd,
168 char **error_message)
169 {
170 if (output_bfd != NULL && output_bfd != abfd)
171 return bfd_reloc_continue;
172
173 if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
174 input_section, reloc_entry->address))
175 return bfd_reloc_outofrange;
176
177 bfd_vma relocation = reloc_entry->addend;
178 bfd_reloc_status_type ret = bfd_reloc_ok;
179 if (output_bfd == NULL)
180 {
181 if (bfd_is_und_section (symbol->section))
182 {
183 if ((symbol->flags & BSF_WEAK) == 0)
184 ret = bfd_reloc_undefined;
185 }
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
194 && obj_pe (obfd))
195 relocation -= pe_data (obfd)->pe_opthdr.ImageBase;
196 else
197 {
198 *error_message = "unsupported";
199 return bfd_reloc_dangerous;
200 }
201 }
202
203 if (relocation + 0x80000000 > 0xffffffff)
204 ret = bfd_reloc_overflow;
205
206 bfd_putl32 (relocation, data + reloc_entry->address);
207
208 return ret;
209 }
210
211 static bfd_reloc_status_type
212 coff_aarch64_secrel_reloc (bfd *abfd,
213 arelent *reloc_entry,
214 asymbol *symbol ATTRIBUTE_UNUSED,
215 void *data,
216 asection *input_section,
217 bfd *output_bfd,
218 char **error_message ATTRIBUTE_UNUSED)
219 {
220 if (output_bfd != NULL && output_bfd != abfd)
221 return bfd_reloc_continue;
222
223 if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
224 input_section, reloc_entry->address))
225 return bfd_reloc_outofrange;
226
227 bfd_vma relocation = reloc_entry->addend;
228 bfd_reloc_status_type ret = bfd_reloc_ok;
229 if (output_bfd == NULL)
230 {
231 if (bfd_is_und_section (symbol->section))
232 {
233 if ((symbol->flags & BSF_WEAK) == 0)
234 ret = bfd_reloc_undefined;
235 }
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;
241 }
242 if (relocation > 0xffffffff)
243 ret = bfd_reloc_overflow;
244
245 bfd_putl32 (relocation, data + reloc_entry->address);
246
247 return ret;
248 }
249
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)
256
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);
260
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));
264
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);
268
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);
272
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);
276
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);
280
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);
284
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);
288
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);
292
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);
296
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);
300
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);
304
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);
308
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);
312
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
328 };
329
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;
336
337 #ifndef NUM_ELEM
338 #define NUM_ELEM(a) ((sizeof (a)) / sizeof ((a)[0]))
339 #endif
340
341 #define NUM_RELOCS NUM_ELEM (arm64_howto_table)
342
343 #define coff_bfd_reloc_type_lookup coff_aarch64_reloc_type_lookup
344 #define coff_bfd_reloc_name_lookup coff_aarch64_reloc_name_lookup
345
346 static reloc_howto_type *
347 coff_aarch64_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code)
348 {
349 switch (code)
350 {
351 case BFD_RELOC_64:
352 return &arm64_reloc_howto_64;
353 case BFD_RELOC_32:
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;
377 case BFD_RELOC_RVA:
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;
383 default:
384 BFD_FAIL ();
385 return NULL;
386 }
387
388 return NULL;
389 }
390
391 static reloc_howto_type *
392 coff_aarch64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
393 const char *r_name)
394 {
395 unsigned int i;
396
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];
401
402 return NULL;
403 }
404
405 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 2
406 #define COFF_PAGE_SIZE 0x1000
407
408 static reloc_howto_type *
409 coff_aarch64_rtype_lookup (unsigned int code)
410 {
411 switch (code)
412 {
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;
441 default:
442 return NULL;
443 }
444
445 return NULL;
446 }
447
448 #define RTYPE2HOWTO(cache_ptr, dst) \
449 ((cache_ptr)->howto = coff_aarch64_rtype_lookup((dst)->r_type))
450
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,
457 bfd_vma *addendp)
458 {
459 reloc_howto_type *howto = coff_aarch64_rtype_lookup (rel->r_type);
460
461 /* Cancel out code in _bfd_coff_generic_relocate_section. */
462 *addendp = 0;
463
464 return howto;
465 }
466
467 #define coff_rtype_to_howto coff_aarch64_rtype_to_howto
468
469 #define SELECT_RELOC(x,howto) { (x).r_type = (howto)->type; }
470
471 #ifndef bfd_pe_print_pdata
472 #define bfd_pe_print_pdata NULL
473 #endif
474
475 #ifdef COFF_WITH_PE
476 /* Return TRUE if this relocation should
477 appear in the output .reloc section. */
478
479 static bool
480 in_reloc_p (bfd * abfd ATTRIBUTE_UNUSED,
481 reloc_howto_type * howto)
482 {
483 return !howto->pc_relative;
484 }
485 #endif
486
487 static bool
488 coff_pe_aarch64_relocate_section (bfd *output_bfd,
489 struct bfd_link_info *info,
490 bfd *input_bfd,
491 asection *input_section,
492 bfd_byte *contents,
493 struct internal_reloc *relocs,
494 struct internal_syment *syms,
495 asection **sections)
496 {
497 struct internal_reloc *rel;
498 struct internal_reloc *relend;
499
500 if (bfd_link_relocatable (info))
501 return true;
502
503 rel = relocs;
504 relend = rel + input_section->reloc_count;
505
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. */
510
511 for (; rel < relend; rel++)
512 {
513 long symndx;
514 struct coff_link_hash_entry *h;
515 bfd_vma sym_value;
516 asection *sec = NULL;
517 uint64_t dest_vma;
518
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)
523 continue;
524
525 symndx = rel->r_symndx;
526 sym_value = syms[symndx].n_value;
527
528 h = obj_coff_sym_hashes (input_bfd)[symndx];
529
530 if (h && h->root.type == bfd_link_hash_defined)
531 {
532 sec = h->root.u.def.section;
533 sym_value = h->root.u.def.value;
534 }
535 else
536 {
537 sec = sections[symndx];
538 }
539
540 if (!sec)
541 continue;
542
543 if (bfd_is_und_section (sec))
544 continue;
545
546 if (discarded_section (sec))
547 continue;
548
549 dest_vma = sec->output_section->vma + sec->output_offset + sym_value;
550
551 if (symndx < 0
552 || (unsigned long) symndx >= obj_raw_syment_count (input_bfd))
553 continue;
554
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)
558 {
559 _bfd_error_handler
560 /* xgettext: c-format */
561 (_("%pB: bad reloc address %#" PRIx64 " in section `%pA'"),
562 input_bfd, (uint64_t) rel->r_vaddr, input_section);
563 continue;
564 }
565
566 switch (rel->r_type)
567 {
568 case IMAGE_REL_ARM64_ADDR32NB:
569 {
570 uint64_t val;
571 int32_t addend;
572
573 addend = bfd_getl32 (contents + rel->r_vaddr);
574
575 dest_vma += addend;
576
577 val = dest_vma;
578 val -= pe_data (output_bfd)->pe_opthdr.ImageBase;
579
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);
585
586 bfd_putl32 (val, contents + rel->r_vaddr);
587 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
588
589 break;
590 }
591
592 case IMAGE_REL_ARM64_BRANCH26:
593 {
594 uint64_t cur_vma;
595 uint32_t opcode;
596 int64_t addend, val;
597
598 opcode = bfd_getl32 (contents + rel->r_vaddr);
599
600 addend = (opcode & 0x3ffffff) << 2;
601
602 if (addend & 0x8000000)
603 addend |= 0xfffffffff0000000;
604
605 dest_vma += addend;
606 cur_vma = input_section->output_section->vma
607 + input_section->output_offset
608 + rel->r_vaddr;
609
610 val = (dest_vma >> 2) - (cur_vma >> 2);
611
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);
617
618 opcode &= 0xfc000000;
619 opcode |= val & 0x3ffffff;
620
621 bfd_putl32 (opcode, contents + rel->r_vaddr);
622 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
623
624 break;
625 }
626
627 case IMAGE_REL_ARM64_BRANCH19:
628 {
629 uint64_t cur_vma;
630 uint32_t opcode;
631 int64_t addend, val;
632
633 opcode = bfd_getl32 (contents + rel->r_vaddr);
634
635 addend = (opcode & 0xffffe0) >> 3;
636
637 if (addend & 0x100000)
638 addend |= 0xffffffffffe00000;
639
640 dest_vma += addend;
641 cur_vma = input_section->output_section->vma
642 + input_section->output_offset
643 + rel->r_vaddr;
644
645 val = (dest_vma >> 2) - (cur_vma >> 2);
646
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);
652
653 opcode &= 0xff00001f;
654 opcode |= (val & 0x7ffff) << 5;
655
656 bfd_putl32 (opcode, contents + rel->r_vaddr);
657 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
658
659 break;
660 }
661
662 case IMAGE_REL_ARM64_BRANCH14:
663 {
664 uint64_t cur_vma;
665 uint32_t opcode;
666 int64_t addend, val;
667
668 opcode = bfd_getl32 (contents + rel->r_vaddr);
669
670 addend = (opcode & 0x7ffe0) >> 3;
671
672 if (addend & 0x8000)
673 addend |= 0xffffffffffff0000;
674
675 dest_vma += addend;
676 cur_vma = input_section->output_section->vma
677 + input_section->output_offset
678 + rel->r_vaddr;
679
680 val = (dest_vma >> 2) - (cur_vma >> 2);
681
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);
687
688 opcode &= 0xfff8001f;
689 opcode |= (val & 0x3fff) << 5;
690
691 bfd_putl32 (opcode, contents + rel->r_vaddr);
692 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
693
694 break;
695 }
696
697 case IMAGE_REL_ARM64_PAGEBASE_REL21:
698 {
699 uint64_t cur_vma;
700 uint32_t opcode;
701 int64_t addend, val;
702
703 opcode = bfd_getl32 (contents + rel->r_vaddr);
704
705 addend = ((opcode & 0xffffe0) >> 3)
706 | ((opcode & 0x60000000) >> 29);
707
708 if (addend & 0x100000)
709 addend |= 0xffffffffffe00000;
710
711 dest_vma += addend;
712 cur_vma = input_section->output_section->vma
713 + input_section->output_offset
714 + rel->r_vaddr;
715
716 val = (dest_vma >> 12) - (cur_vma >> 12);
717
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);
723
724 opcode &= 0x9f00001f;
725 opcode |= (val & 0x3) << 29;
726 opcode |= (val & 0x1ffffc) << 3;
727
728 bfd_putl32 (opcode, contents + rel->r_vaddr);
729 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
730
731 break;
732 }
733
734 case IMAGE_REL_ARM64_REL21:
735 {
736 uint64_t cur_vma;
737 uint32_t opcode;
738 int64_t addend, val;
739
740 opcode = bfd_getl32 (contents + rel->r_vaddr);
741
742 addend = ((opcode & 0xffffe0) >> 3)
743 | ((opcode & 0x60000000) >> 29);
744
745 if (addend & 0x100000)
746 addend |= 0xffffffffffe00000;
747
748 dest_vma += addend;
749 cur_vma = input_section->output_section->vma
750 + input_section->output_offset
751 + rel->r_vaddr;
752
753 val = dest_vma - cur_vma;
754
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);
760
761 opcode &= 0x9f00001f;
762 opcode |= (val & 0x3) << 29;
763 opcode |= (val & 0x1ffffc) << 3;
764
765 bfd_putl32 (opcode, contents + rel->r_vaddr);
766 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
767
768 break;
769 }
770
771 case IMAGE_REL_ARM64_PAGEOFFSET_12L:
772 {
773 uint32_t opcode, val;
774 uint8_t shift;
775 int32_t addend;
776
777 opcode = bfd_getl32 (contents + rel->r_vaddr);
778
779 addend = (opcode & 0x3ffc00) >> 10;
780
781 if ((opcode & 0xff800000) == 0x3d800000)
782 {
783 /* LDR / STR with q register */
784 shift = 4;
785 }
786 else
787 {
788 /* top two bits represent how much addend should be shifted */
789 shift = opcode >> 30;
790 }
791
792 addend <<= shift;
793
794 dest_vma += addend;
795
796 /* only interested in bottom 12 bits */
797 val = dest_vma & 0xfff;
798
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);
804
805 val >>= shift;
806
807 opcode &= 0xffc003ff;
808 opcode |= val << 10;
809
810 bfd_putl32 (opcode, contents + rel->r_vaddr);
811 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
812
813 break;
814 }
815
816 case IMAGE_REL_ARM64_PAGEOFFSET_12A:
817 {
818 uint32_t opcode, val;
819 int32_t addend;
820
821 opcode = bfd_getl32 (contents + rel->r_vaddr);
822
823 addend = (opcode & 0x3ffc00) >> 10;
824
825 dest_vma += addend;
826
827 /* only interested in bottom 12 bits */
828 val = dest_vma & 0xfff;
829
830 opcode &= 0xffc003ff;
831 opcode |= val << 10;
832
833 bfd_putl32 (opcode, contents + rel->r_vaddr);
834 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
835
836 break;
837 }
838
839 case IMAGE_REL_ARM64_SECREL:
840 {
841 uint64_t val;
842 int32_t addend;
843
844 addend = bfd_getl32 (contents + rel->r_vaddr);
845
846 val = sec->output_offset + sym_value + addend;
847
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);
853
854 bfd_putl32 (val, contents + rel->r_vaddr);
855 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
856
857 break;
858 }
859
860 case IMAGE_REL_ARM64_SECTION:
861 {
862 uint16_t idx = 0, i = 1;
863 asection *s;
864
865 s = output_bfd->sections;
866 while (s)
867 {
868 if (s == sec->output_section)
869 {
870 idx = i;
871 break;
872 }
873
874 i++;
875 s = s->next;
876 }
877
878
879 bfd_putl16 (idx, contents + rel->r_vaddr);
880 rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
881
882 break;
883 }
884
885 default:
886 info->callbacks->einfo (_("%F%P: Unhandled relocation type %u\n"),
887 rel->r_type);
888 BFD_FAIL ();
889 return false;
890 }
891 }
892
893 return _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
894 input_section, contents,
895 relocs, syms, sections);
896 }
897
898 #define coff_relocate_section coff_pe_aarch64_relocate_section
899
900 #include "coffcode.h"
901
902 /* Prevent assertion in md_apply_fix by forcing use_rela_p on for new
903 sections. */
904 static bool
905 coff_aarch64_new_section_hook (bfd *abfd, asection *section)
906 {
907 if (!coff_new_section_hook (abfd, section))
908 return false;
909
910 section->use_rela_p = 1;
911
912 return true;
913 }
914
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
919
920 /* Target vectors. */
921 const bfd_target
922 #ifdef TARGET_SYM
923 TARGET_SYM =
924 #else
925 # error "target symbol name not specified"
926 #endif
927 {
928 #ifdef TARGET_NAME
929 TARGET_NAME,
930 #else
931 # error "target name not specified"
932 #endif
933 bfd_target_coff_flavour,
934 BFD_ENDIAN_LITTLE, /* Data byte order is little. */
935 BFD_ENDIAN_LITTLE, /* Header byte order is little. */
936
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),
940
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
944 #endif
945 | SEC_CODE | SEC_DATA | SEC_EXCLUDE ),
946
947 #ifdef TARGET_UNDERSCORE
948 TARGET_UNDERSCORE, /* Leading underscore. */
949 #else
950 0, /* Leading underscore. */
951 #endif
952 '/', /* Ar_pad_char. */
953 15, /* Ar_max_namelen. */
954 0, /* match priority. */
955 TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */
956
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. */
965
966 /* Note that we allow an object file to be treated as a core file as well. */
967 { /* bfd_check_format. */
968 _bfd_dummy_target,
969 coff_object_p,
970 bfd_generic_archive_p,
971 coff_object_p
972 },
973 { /* bfd_set_format. */
974 _bfd_bool_bfd_false_error,
975 coff_mkobject,
976 _bfd_generic_mkarchive,
977 _bfd_bool_bfd_false_error
978 },
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
984 },
985
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),
995
996 NULL,
997
998 COFF_SWAP_TABLE
999 };