(root)/
binutils-2.41/
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  };