xref: /netbsd-src/external/gpl3/binutils/dist/bfd/coff-aarch64.c (revision cb63e24e8d6aae7ddac1859a9015f48b1d8bd90e)
1 /* BFD back-end for AArch64 COFF files.
2    Copyright (C) 2021-2024 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 #include "sysdep.h"
27 #include "bfd.h"
28 #include "libbfd.h"
29 #include "coff/aarch64.h"
30 #include "coff/internal.h"
31 #include "coff/pe.h"
32 #include "libcoff.h"
33 #include "libiberty.h"
34 
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.  */
44 
45 static bfd_reloc_status_type
coff_aarch64_rel21_reloc(bfd * abfd,arelent * reloc_entry,asymbol * symbol,void * data,asection * input_section,bfd * output_bfd,char ** error_message ATTRIBUTE_UNUSED)46 coff_aarch64_rel21_reloc (bfd *abfd,
47 			  arelent *reloc_entry,
48 			  asymbol *symbol,
49 			  void *data,
50 			  asection *input_section,
51 			  bfd *output_bfd,
52 			  char **error_message ATTRIBUTE_UNUSED)
53 {
54   if (output_bfd != NULL && output_bfd != abfd)
55     return bfd_reloc_continue;
56 
57   if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
58 				  input_section, reloc_entry->address))
59     return bfd_reloc_outofrange;
60 
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)
65     {
66       if (bfd_is_und_section (symbol->section))
67 	{
68 	  if ((symbol->flags & BSF_WEAK) == 0)
69 	    ret = bfd_reloc_undefined;
70 	}
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;
77       relocation += addend;
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;
82     }
83   if (relocation + 0x100000 > 0x1fffff)
84     ret = bfd_reloc_overflow;
85 
86   op &= 0x9f00001f;
87   op |= (relocation & 0x1ffffc) << 3;
88   op |= (relocation & 0x3) << 29;
89 
90   bfd_putl32 (op, data + reloc_entry->address);
91 
92   return ret;
93 }
94 
95 static bfd_reloc_status_type
coff_aarch64_po12l_reloc(bfd * abfd,arelent * reloc_entry,asymbol * symbol ATTRIBUTE_UNUSED,void * data,asection * input_section,bfd * output_bfd,char ** error_message ATTRIBUTE_UNUSED)96 coff_aarch64_po12l_reloc (bfd *abfd,
97 			  arelent *reloc_entry,
98 			  asymbol *symbol ATTRIBUTE_UNUSED,
99 			  void *data,
100 			  asection *input_section,
101 			  bfd *output_bfd,
102 			  char **error_message ATTRIBUTE_UNUSED)
103 {
104   if (output_bfd != NULL && output_bfd != abfd)
105     return bfd_reloc_continue;
106 
107   if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
108 				  input_section, reloc_entry->address))
109     return bfd_reloc_outofrange;
110 
111   uint32_t op = bfd_getl32 (data + reloc_entry->address);
112   bfd_vma relocation = reloc_entry->addend & 0xfff;
113   int shift;
114 
115   if ((op & 0xff800000) == 0x3d800000)
116     {
117       /* LDR / STR with q register */
118       shift = 4;
119     }
120   else
121     {
122       /* top two bits represent how much addend should be shifted */
123       shift = op >> 30;
124     }
125 
126   bfd_reloc_status_type ret = bfd_reloc_ok;
127   if (output_bfd == NULL)
128     {
129       if (bfd_is_und_section (symbol->section))
130 	{
131 	  if ((symbol->flags & BSF_WEAK) == 0)
132 	    ret = bfd_reloc_undefined;
133 	}
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;
139       addend <<= shift;
140       relocation += addend;
141     }
142 
143   if (relocation & ((1 << shift) - 1))
144     ret = bfd_reloc_overflow;
145 
146   op &= 0xffc003ff;
147   op |= (relocation >> shift << 10) & 0x3ffc00;
148 
149   bfd_putl32 (op, data + reloc_entry->address);
150 
151   return ret;
152 }
153 
154 static bfd_reloc_status_type
coff_aarch64_addr32nb_reloc(bfd * abfd,arelent * reloc_entry,asymbol * symbol ATTRIBUTE_UNUSED,void * data,asection * input_section,bfd * output_bfd,char ** error_message)155 coff_aarch64_addr32nb_reloc (bfd *abfd,
156 			     arelent *reloc_entry,
157 			     asymbol *symbol ATTRIBUTE_UNUSED,
158 			     void *data,
159 			     asection *input_section,
160 			     bfd *output_bfd,
161 			     char **error_message)
162 {
163   if (output_bfd != NULL && output_bfd != abfd)
164     return bfd_reloc_continue;
165 
166   if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
167 				  input_section, reloc_entry->address))
168     return bfd_reloc_outofrange;
169 
170   bfd_vma relocation = reloc_entry->addend;
171   bfd_reloc_status_type ret = bfd_reloc_ok;
172   if (output_bfd == NULL)
173     {
174       if (bfd_is_und_section (symbol->section))
175 	{
176 	  if ((symbol->flags & BSF_WEAK) == 0)
177 	    ret = bfd_reloc_undefined;
178 	}
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
187 	  && obj_pe (obfd))
188 	relocation -= pe_data (obfd)->pe_opthdr.ImageBase;
189       else
190 	{
191 	  *error_message = "unsupported";
192 	  return bfd_reloc_dangerous;
193 	}
194     }
195 
196   if (relocation + 0x80000000 > 0xffffffff)
197     ret = bfd_reloc_overflow;
198 
199   bfd_putl32 (relocation, data + reloc_entry->address);
200 
201   return ret;
202 }
203 
204 static bfd_reloc_status_type
coff_aarch64_secrel_reloc(bfd * abfd,arelent * reloc_entry,asymbol * symbol ATTRIBUTE_UNUSED,void * data,asection * input_section,bfd * output_bfd,char ** error_message ATTRIBUTE_UNUSED)205 coff_aarch64_secrel_reloc (bfd *abfd,
206 			   arelent *reloc_entry,
207 			   asymbol *symbol ATTRIBUTE_UNUSED,
208 			   void *data,
209 			   asection *input_section,
210 			   bfd *output_bfd,
211 			   char **error_message ATTRIBUTE_UNUSED)
212 {
213   if (output_bfd != NULL && output_bfd != abfd)
214     return bfd_reloc_continue;
215 
216   if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
217 				  input_section, reloc_entry->address))
218     return bfd_reloc_outofrange;
219 
220   bfd_vma relocation = reloc_entry->addend;
221   bfd_reloc_status_type ret = bfd_reloc_ok;
222   if (output_bfd == NULL)
223     {
224       if (bfd_is_und_section (symbol->section))
225 	{
226 	  if ((symbol->flags & BSF_WEAK) == 0)
227 	    ret = bfd_reloc_undefined;
228 	}
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;
234     }
235   if (relocation > 0xffffffff)
236     ret = bfd_reloc_overflow;
237 
238   bfd_putl32 (relocation, data + reloc_entry->address);
239 
240   return ret;
241 }
242 
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)
249 
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);
253 
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));
257 
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);
261 
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);
265 
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);
269 
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);
273 
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);
277 
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);
281 
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);
285 
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);
289 
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);
293 
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);
297 
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);
301 
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);
305 
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
321 };
322 
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;
329 
330 #ifndef NUM_ELEM
331 #define NUM_ELEM(a) ((sizeof (a)) / sizeof ((a)[0]))
332 #endif
333 
334 #define NUM_RELOCS NUM_ELEM (arm64_howto_table)
335 
336 #define coff_bfd_reloc_type_lookup		coff_aarch64_reloc_type_lookup
337 #define coff_bfd_reloc_name_lookup		coff_aarch64_reloc_name_lookup
338 
339 static reloc_howto_type *
coff_aarch64_reloc_type_lookup(bfd * abfd ATTRIBUTE_UNUSED,bfd_reloc_code_real_type code)340 coff_aarch64_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code)
341 {
342   switch (code)
343   {
344   case BFD_RELOC_64:
345     return &arm64_reloc_howto_64;
346   case BFD_RELOC_32:
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;
370   case BFD_RELOC_RVA:
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;
376   default:
377     BFD_FAIL ();
378     return NULL;
379   }
380 
381   return NULL;
382 }
383 
384 static reloc_howto_type *
coff_aarch64_reloc_name_lookup(bfd * abfd ATTRIBUTE_UNUSED,const char * r_name)385 coff_aarch64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
386 			    const char *r_name)
387 {
388 	unsigned int i;
389 
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];
394 
395   return NULL;
396 }
397 
398 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER  2
399 #define COFF_PAGE_SIZE			      0x1000
400 
401 static reloc_howto_type *
coff_aarch64_rtype_lookup(unsigned int code)402 coff_aarch64_rtype_lookup (unsigned int code)
403 {
404   switch (code)
405   {
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;
434     default:
435       return NULL;
436   }
437 
438   return NULL;
439 }
440 
441 #define RTYPE2HOWTO(cache_ptr, dst)					\
442   ((cache_ptr)->howto = coff_aarch64_rtype_lookup((dst)->r_type))
443 
444 static reloc_howto_type *
coff_aarch64_rtype_to_howto(bfd * abfd ATTRIBUTE_UNUSED,asection * sec ATTRIBUTE_UNUSED,struct internal_reloc * rel,struct coff_link_hash_entry * h ATTRIBUTE_UNUSED,struct internal_syment * sym ATTRIBUTE_UNUSED,bfd_vma * addendp)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,
450 			     bfd_vma *addendp)
451 {
452   reloc_howto_type *howto = coff_aarch64_rtype_lookup (rel->r_type);
453 
454   /* Cancel out code in _bfd_coff_generic_relocate_section.  */
455   *addendp = 0;
456 
457   return howto;
458 }
459 
460 #define coff_rtype_to_howto coff_aarch64_rtype_to_howto
461 
462 #define SELECT_RELOC(x,howto) { (x).r_type = (howto)->type; }
463 
464 #ifndef bfd_pe_print_pdata
465 #define bfd_pe_print_pdata      NULL
466 #endif
467 
468 #ifdef COFF_WITH_PE
469 /* Return TRUE if this relocation should
470    appear in the output .reloc section.  */
471 
472 static bool
in_reloc_p(bfd * abfd ATTRIBUTE_UNUSED,reloc_howto_type * howto)473 in_reloc_p (bfd * abfd ATTRIBUTE_UNUSED,
474             reloc_howto_type * howto)
475 {
476   return !howto->pc_relative;
477 }
478 #endif
479 
480 static bool
coff_pe_aarch64_relocate_section(bfd * output_bfd,struct bfd_link_info * info,bfd * input_bfd,asection * input_section,bfd_byte * contents,struct internal_reloc * relocs,struct internal_syment * syms,asection ** sections)481 coff_pe_aarch64_relocate_section (bfd *output_bfd,
482 				  struct bfd_link_info *info,
483 				  bfd *input_bfd,
484 				  asection *input_section,
485 				  bfd_byte *contents,
486 				  struct internal_reloc *relocs,
487 				  struct internal_syment *syms,
488 				  asection **sections)
489 {
490   struct internal_reloc *rel;
491   struct internal_reloc *relend;
492 
493   if (bfd_link_relocatable (info))
494     return true;
495 
496   rel = relocs;
497   relend = rel + input_section->reloc_count;
498 
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.  */
503 
504   for (; rel < relend; rel++)
505     {
506       long symndx;
507       struct coff_link_hash_entry *h;
508       bfd_vma sym_value;
509       asection *sec = NULL;
510       uint64_t dest_vma;
511 
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)
516 	continue;
517 
518       symndx = rel->r_symndx;
519       sym_value = syms[symndx].n_value;
520 
521       h = obj_coff_sym_hashes (input_bfd)[symndx];
522 
523       if (h && h->root.type == bfd_link_hash_defined)
524 	{
525 	  sec = h->root.u.def.section;
526 	  sym_value = h->root.u.def.value;
527 	}
528       else
529 	{
530 	  sec = sections[symndx];
531 	}
532 
533       if (!sec)
534 	continue;
535 
536       if (bfd_is_und_section (sec))
537 	continue;
538 
539       if (discarded_section (sec))
540 	continue;
541 
542       dest_vma = sec->output_section->vma + sec->output_offset + sym_value;
543 
544       if (symndx < 0
545 	  || (unsigned long) symndx >= obj_raw_syment_count (input_bfd))
546 	continue;
547 
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)
551 	{
552 	  _bfd_error_handler
553 	    /* xgettext: c-format */
554 	    (_("%pB: bad reloc address %#" PRIx64 " in section `%pA'"),
555 	     input_bfd, (uint64_t) rel->r_vaddr, input_section);
556 	  continue;
557 	}
558 
559       switch (rel->r_type)
560 	{
561 	case IMAGE_REL_ARM64_ADDR32NB:
562 	  {
563 	    uint64_t val;
564 	    int32_t addend;
565 
566 	    addend = bfd_getl32 (contents + rel->r_vaddr);
567 
568 	    dest_vma += addend;
569 
570 	    val = dest_vma;
571 	    val -= pe_data (output_bfd)->pe_opthdr.ImageBase;
572 
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);
578 
579 	    bfd_putl32 (val, contents + rel->r_vaddr);
580 	    rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
581 
582 	    break;
583 	  }
584 
585 	case IMAGE_REL_ARM64_BRANCH26:
586 	  {
587 	    uint64_t cur_vma;
588 	    uint32_t opcode;
589 	    int64_t addend, val;
590 
591 	    opcode = bfd_getl32 (contents + rel->r_vaddr);
592 
593 	    addend = (opcode & 0x3ffffff) << 2;
594 
595 	    if (addend & 0x8000000)
596 	      addend |= 0xfffffffff0000000;
597 
598 	    dest_vma += addend;
599 	    cur_vma = input_section->output_section->vma
600 		      + input_section->output_offset
601 		      + rel->r_vaddr;
602 
603 	    val = (dest_vma >> 2) - (cur_vma >> 2);
604 
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);
610 
611 	    opcode &= 0xfc000000;
612 	    opcode |= val & 0x3ffffff;
613 
614 	    bfd_putl32 (opcode, contents + rel->r_vaddr);
615 	    rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
616 
617 	    break;
618 	  }
619 
620 	case IMAGE_REL_ARM64_BRANCH19:
621 	  {
622 	    uint64_t cur_vma;
623 	    uint32_t opcode;
624 	    int64_t addend, val;
625 
626 	    opcode = bfd_getl32 (contents + rel->r_vaddr);
627 
628 	    addend = (opcode & 0xffffe0) >> 3;
629 
630 	    if (addend & 0x100000)
631 	      addend |= 0xffffffffffe00000;
632 
633 	    dest_vma += addend;
634 	    cur_vma = input_section->output_section->vma
635 		      + input_section->output_offset
636 		      + rel->r_vaddr;
637 
638 	    val = (dest_vma >> 2) - (cur_vma >> 2);
639 
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);
645 
646 	    opcode &= 0xff00001f;
647 	    opcode |= (val & 0x7ffff) << 5;
648 
649 	    bfd_putl32 (opcode, contents + rel->r_vaddr);
650 	    rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
651 
652 	    break;
653 	  }
654 
655 	case IMAGE_REL_ARM64_BRANCH14:
656 	  {
657 	    uint64_t cur_vma;
658 	    uint32_t opcode;
659 	    int64_t addend, val;
660 
661 	    opcode = bfd_getl32 (contents + rel->r_vaddr);
662 
663 	    addend = (opcode & 0x7ffe0) >> 3;
664 
665 	    if (addend & 0x8000)
666 	      addend |= 0xffffffffffff0000;
667 
668 	    dest_vma += addend;
669 	    cur_vma = input_section->output_section->vma
670 		      + input_section->output_offset
671 		      + rel->r_vaddr;
672 
673 	    val = (dest_vma >> 2) - (cur_vma >> 2);
674 
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);
680 
681 	    opcode &= 0xfff8001f;
682 	    opcode |= (val & 0x3fff) << 5;
683 
684 	    bfd_putl32 (opcode, contents + rel->r_vaddr);
685 	    rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
686 
687 	    break;
688 	  }
689 
690 	case IMAGE_REL_ARM64_PAGEBASE_REL21:
691 	  {
692 	    uint64_t cur_vma;
693 	    uint32_t opcode;
694 	    int64_t addend, val;
695 
696 	    opcode = bfd_getl32 (contents + rel->r_vaddr);
697 
698 	    addend = ((opcode & 0xffffe0) >> 3)
699 		     | ((opcode & 0x60000000) >> 29);
700 
701 	    if (addend & 0x100000)
702 	      addend |= 0xffffffffffe00000;
703 
704 	    dest_vma += addend;
705 	    cur_vma = input_section->output_section->vma
706 		      + input_section->output_offset
707 		      + rel->r_vaddr;
708 
709 	    val = (dest_vma >> 12) - (cur_vma >> 12);
710 
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);
716 
717 	    opcode &= 0x9f00001f;
718 	    opcode |= (val & 0x3) << 29;
719 	    opcode |= (val & 0x1ffffc) << 3;
720 
721 	    bfd_putl32 (opcode, contents + rel->r_vaddr);
722 	    rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
723 
724 	    break;
725 	  }
726 
727 	case IMAGE_REL_ARM64_REL21:
728 	  {
729 	    uint64_t cur_vma;
730 	    uint32_t opcode;
731 	    int64_t addend, val;
732 
733 	    opcode = bfd_getl32 (contents + rel->r_vaddr);
734 
735 	    addend = ((opcode & 0xffffe0) >> 3)
736 		     | ((opcode & 0x60000000) >> 29);
737 
738 	    if (addend & 0x100000)
739 	      addend |= 0xffffffffffe00000;
740 
741 	    dest_vma += addend;
742 	    cur_vma = input_section->output_section->vma
743 		      + input_section->output_offset
744 		      + rel->r_vaddr;
745 
746 	    val = dest_vma - cur_vma;
747 
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);
753 
754 	    opcode &= 0x9f00001f;
755 	    opcode |= (val & 0x3) << 29;
756 	    opcode |= (val & 0x1ffffc) << 3;
757 
758 	    bfd_putl32 (opcode, contents + rel->r_vaddr);
759 	    rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
760 
761 	    break;
762 	  }
763 
764 	case IMAGE_REL_ARM64_PAGEOFFSET_12L:
765 	  {
766 	    uint32_t opcode, val;
767 	    uint8_t shift;
768 	    int32_t addend;
769 
770 	    opcode = bfd_getl32 (contents + rel->r_vaddr);
771 
772 	    addend = (opcode & 0x3ffc00) >> 10;
773 
774 	    if ((opcode & 0xff800000) == 0x3d800000)
775 	      {
776 		/* LDR / STR with q register */
777 		shift = 4;
778 	      }
779 	    else
780 	      {
781 		/* top two bits represent how much addend should be shifted */
782 		shift = opcode >> 30;
783 	      }
784 
785 	    addend <<= shift;
786 
787 	    dest_vma += addend;
788 
789 	    /* only interested in bottom 12 bits */
790 	    val = dest_vma & 0xfff;
791 
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);
797 
798 	    val >>= shift;
799 
800 	    opcode &= 0xffc003ff;
801 	    opcode |= val << 10;
802 
803 	    bfd_putl32 (opcode, contents + rel->r_vaddr);
804 	    rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
805 
806 	    break;
807 	  }
808 
809 	case IMAGE_REL_ARM64_PAGEOFFSET_12A:
810 	  {
811 	    uint32_t opcode, val;
812 	    int32_t addend;
813 
814 	    opcode = bfd_getl32 (contents + rel->r_vaddr);
815 
816 	    addend = (opcode & 0x3ffc00) >> 10;
817 
818 	    dest_vma += addend;
819 
820 	    /* only interested in bottom 12 bits */
821 	    val = dest_vma & 0xfff;
822 
823 	    opcode &= 0xffc003ff;
824 	    opcode |= val << 10;
825 
826 	    bfd_putl32 (opcode, contents + rel->r_vaddr);
827 	    rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
828 
829 	    break;
830 	  }
831 
832 	case IMAGE_REL_ARM64_SECREL:
833 	  {
834 	    uint64_t val;
835 	    int32_t addend;
836 
837 	    addend = bfd_getl32 (contents + rel->r_vaddr);
838 
839 	    val = sec->output_offset + sym_value + addend;
840 
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);
846 
847 	    bfd_putl32 (val, contents + rel->r_vaddr);
848 	    rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
849 
850 	    break;
851 	  }
852 
853 	case IMAGE_REL_ARM64_SECTION:
854 	  {
855 	    uint16_t idx = 0, i = 1;
856 	    asection *s;
857 
858 	    s = output_bfd->sections;
859 	    while (s)
860 	      {
861 		if (s == sec->output_section)
862 		  {
863 		    idx = i;
864 		    break;
865 		  }
866 
867 		i++;
868 		s = s->next;
869 	      }
870 
871 
872 	    bfd_putl16 (idx, contents + rel->r_vaddr);
873 	    rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
874 
875 	    break;
876 	  }
877 
878 	default:
879 	  info->callbacks->einfo (_("%F%P: Unhandled relocation type %u\n"),
880 				  rel->r_type);
881 	  BFD_FAIL ();
882 	  return false;
883 	}
884     }
885 
886   return _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
887 					     input_section, contents,
888 					     relocs, syms, sections);
889 }
890 
891 #define coff_relocate_section coff_pe_aarch64_relocate_section
892 
893 #include "coffcode.h"
894 
895 /* Prevent assertion in md_apply_fix by forcing use_rela_p on for new
896    sections.  */
897 static bool
coff_aarch64_new_section_hook(bfd * abfd,asection * section)898 coff_aarch64_new_section_hook (bfd *abfd, asection *section)
899 {
900   if (!coff_new_section_hook (abfd, section))
901     return false;
902 
903   section->use_rela_p = 1;
904 
905   return true;
906 }
907 
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
912 
913 /* Target vectors.  */
914 const bfd_target
915 #ifdef TARGET_SYM
916   TARGET_SYM =
917 #else
918 # error "target symbol name not specified"
919 #endif
920 {
921 #ifdef TARGET_NAME
922   TARGET_NAME,
923 #else
924 # error "target name not specified"
925 #endif
926   bfd_target_coff_flavour,
927   BFD_ENDIAN_LITTLE,		/* Data byte order is little.  */
928   BFD_ENDIAN_LITTLE,		/* Header byte order is little.  */
929 
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),
933 
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
937 #endif
938    | SEC_CODE | SEC_DATA | SEC_EXCLUDE ),
939 
940 #ifdef TARGET_UNDERSCORE
941   TARGET_UNDERSCORE,		/* Leading underscore.  */
942 #else
943   0,				/* Leading underscore.  */
944 #endif
945   '/',				/* Ar_pad_char.  */
946   15,				/* Ar_max_namelen.  */
947   0,				/* match priority.  */
948   TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
949 
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.  */
958 
959   /* Note that we allow an object file to be treated as a core file as well.  */
960   {				/* bfd_check_format.  */
961     _bfd_dummy_target,
962     coff_object_p,
963     bfd_generic_archive_p,
964     coff_object_p
965   },
966   {				/* bfd_set_format.  */
967     _bfd_bool_bfd_false_error,
968     coff_mkobject,
969     _bfd_generic_mkarchive,
970     _bfd_bool_bfd_false_error
971   },
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
977   },
978 
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),
988 
989   NULL,
990 
991   COFF_SWAP_TABLE
992 };
993