Home | History | Annotate | Line # | Download | only in bfd
elfxx-aarch64.c revision 1.1.1.2.12.2
      1           1.1  christos /* AArch64-specific support for ELF.
      2  1.1.1.2.12.1  pgoyette    Copyright (C) 2009-2018 Free Software Foundation, Inc.
      3           1.1  christos    Contributed by ARM Ltd.
      4           1.1  christos 
      5           1.1  christos    This file is part of BFD, the Binary File Descriptor library.
      6           1.1  christos 
      7           1.1  christos    This program is free software; you can redistribute it and/or modify
      8           1.1  christos    it under the terms of the GNU General Public License as published by
      9           1.1  christos    the Free Software Foundation; either version 3 of the License, or
     10           1.1  christos    (at your option) any later version.
     11           1.1  christos 
     12           1.1  christos    This program is distributed in the hope that it will be useful,
     13           1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14           1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15           1.1  christos    GNU General Public License for more details.
     16           1.1  christos 
     17           1.1  christos    You should have received a copy of the GNU General Public License
     18           1.1  christos    along with this program; see the file COPYING3. If not,
     19           1.1  christos    see <http://www.gnu.org/licenses/>.  */
     20           1.1  christos 
     21           1.1  christos #include "sysdep.h"
     22           1.1  christos #include "elfxx-aarch64.h"
     23           1.1  christos #include <stdarg.h>
     24           1.1  christos #include <string.h>
     25           1.1  christos 
     26           1.1  christos #define MASK(n) ((1u << (n)) - 1)
     27           1.1  christos 
     28           1.1  christos /* Sign-extend VALUE, which has the indicated number of BITS.  */
     29           1.1  christos 
     30           1.1  christos bfd_signed_vma
     31           1.1  christos _bfd_aarch64_sign_extend (bfd_vma value, int bits)
     32           1.1  christos {
     33           1.1  christos   if (value & ((bfd_vma) 1 << (bits - 1)))
     34           1.1  christos     /* VALUE is negative.  */
     35           1.1  christos     value |= ((bfd_vma) - 1) << bits;
     36           1.1  christos 
     37           1.1  christos   return value;
     38           1.1  christos }
     39           1.1  christos 
     40           1.1  christos /* Decode the IMM field of ADRP.  */
     41           1.1  christos 
     42           1.1  christos uint32_t
     43           1.1  christos _bfd_aarch64_decode_adrp_imm (uint32_t insn)
     44           1.1  christos {
     45           1.1  christos   return (((insn >> 5) & MASK (19)) << 2) | ((insn >> 29) & MASK (2));
     46           1.1  christos }
     47           1.1  christos 
     48           1.1  christos /* Reencode the imm field of add immediate.  */
     49           1.1  christos static inline uint32_t
     50           1.1  christos reencode_add_imm (uint32_t insn, uint32_t imm)
     51           1.1  christos {
     52           1.1  christos   return (insn & ~(MASK (12) << 10)) | ((imm & MASK (12)) << 10);
     53           1.1  christos }
     54           1.1  christos 
     55           1.1  christos /* Reencode the IMM field of ADR.  */
     56           1.1  christos 
     57           1.1  christos uint32_t
     58           1.1  christos _bfd_aarch64_reencode_adr_imm (uint32_t insn, uint32_t imm)
     59           1.1  christos {
     60           1.1  christos   return (insn & ~((MASK (2) << 29) | (MASK (19) << 5)))
     61           1.1  christos     | ((imm & MASK (2)) << 29) | ((imm & (MASK (19) << 2)) << 3);
     62           1.1  christos }
     63           1.1  christos 
     64           1.1  christos /* Reencode the imm field of ld/st pos immediate.  */
     65           1.1  christos static inline uint32_t
     66           1.1  christos reencode_ldst_pos_imm (uint32_t insn, uint32_t imm)
     67           1.1  christos {
     68           1.1  christos   return (insn & ~(MASK (12) << 10)) | ((imm & MASK (12)) << 10);
     69           1.1  christos }
     70           1.1  christos 
     71           1.1  christos /* Encode the 26-bit offset of unconditional branch.  */
     72           1.1  christos static inline uint32_t
     73           1.1  christos reencode_branch_ofs_26 (uint32_t insn, uint32_t ofs)
     74           1.1  christos {
     75           1.1  christos   return (insn & ~MASK (26)) | (ofs & MASK (26));
     76           1.1  christos }
     77           1.1  christos 
     78           1.1  christos /* Encode the 19-bit offset of conditional branch and compare & branch.  */
     79           1.1  christos static inline uint32_t
     80           1.1  christos reencode_cond_branch_ofs_19 (uint32_t insn, uint32_t ofs)
     81           1.1  christos {
     82           1.1  christos   return (insn & ~(MASK (19) << 5)) | ((ofs & MASK (19)) << 5);
     83           1.1  christos }
     84           1.1  christos 
     85           1.1  christos /* Decode the 19-bit offset of load literal.  */
     86           1.1  christos static inline uint32_t
     87           1.1  christos reencode_ld_lit_ofs_19 (uint32_t insn, uint32_t ofs)
     88           1.1  christos {
     89           1.1  christos   return (insn & ~(MASK (19) << 5)) | ((ofs & MASK (19)) << 5);
     90           1.1  christos }
     91           1.1  christos 
     92           1.1  christos /* Encode the 14-bit offset of test & branch.  */
     93           1.1  christos static inline uint32_t
     94           1.1  christos reencode_tst_branch_ofs_14 (uint32_t insn, uint32_t ofs)
     95           1.1  christos {
     96           1.1  christos   return (insn & ~(MASK (14) << 5)) | ((ofs & MASK (14)) << 5);
     97           1.1  christos }
     98           1.1  christos 
     99           1.1  christos /* Reencode the imm field of move wide.  */
    100           1.1  christos static inline uint32_t
    101           1.1  christos reencode_movw_imm (uint32_t insn, uint32_t imm)
    102           1.1  christos {
    103           1.1  christos   return (insn & ~(MASK (16) << 5)) | ((imm & MASK (16)) << 5);
    104           1.1  christos }
    105           1.1  christos 
    106           1.1  christos /* Reencode mov[zn] to movz.  */
    107           1.1  christos static inline uint32_t
    108           1.1  christos reencode_movzn_to_movz (uint32_t opcode)
    109           1.1  christos {
    110           1.1  christos   return opcode | (1 << 30);
    111           1.1  christos }
    112           1.1  christos 
    113           1.1  christos /* Reencode mov[zn] to movn.  */
    114           1.1  christos static inline uint32_t
    115           1.1  christos reencode_movzn_to_movn (uint32_t opcode)
    116           1.1  christos {
    117           1.1  christos   return opcode & ~(1 << 30);
    118           1.1  christos }
    119           1.1  christos 
    120           1.1  christos /* Return non-zero if the indicated VALUE has overflowed the maximum
    121           1.1  christos    range expressible by a unsigned number with the indicated number of
    122           1.1  christos    BITS.  */
    123           1.1  christos 
    124           1.1  christos static bfd_reloc_status_type
    125           1.1  christos aarch64_unsigned_overflow (bfd_vma value, unsigned int bits)
    126           1.1  christos {
    127           1.1  christos   bfd_vma lim;
    128           1.1  christos   if (bits >= sizeof (bfd_vma) * 8)
    129           1.1  christos     return bfd_reloc_ok;
    130           1.1  christos   lim = (bfd_vma) 1 << bits;
    131           1.1  christos   if (value >= lim)
    132           1.1  christos     return bfd_reloc_overflow;
    133           1.1  christos   return bfd_reloc_ok;
    134           1.1  christos }
    135           1.1  christos 
    136           1.1  christos /* Return non-zero if the indicated VALUE has overflowed the maximum
    137           1.1  christos    range expressible by an signed number with the indicated number of
    138           1.1  christos    BITS.  */
    139           1.1  christos 
    140           1.1  christos static bfd_reloc_status_type
    141           1.1  christos aarch64_signed_overflow (bfd_vma value, unsigned int bits)
    142           1.1  christos {
    143           1.1  christos   bfd_signed_vma svalue = (bfd_signed_vma) value;
    144           1.1  christos   bfd_signed_vma lim;
    145           1.1  christos 
    146           1.1  christos   if (bits >= sizeof (bfd_vma) * 8)
    147           1.1  christos     return bfd_reloc_ok;
    148           1.1  christos   lim = (bfd_signed_vma) 1 << (bits - 1);
    149           1.1  christos   if (svalue < -lim || svalue >= lim)
    150           1.1  christos     return bfd_reloc_overflow;
    151           1.1  christos   return bfd_reloc_ok;
    152           1.1  christos }
    153           1.1  christos 
    154           1.1  christos /* Insert the addend/value into the instruction or data object being
    155           1.1  christos    relocated.  */
    156           1.1  christos bfd_reloc_status_type
    157           1.1  christos _bfd_aarch64_elf_put_addend (bfd *abfd,
    158           1.1  christos 			     bfd_byte *address, bfd_reloc_code_real_type r_type,
    159           1.1  christos 			     reloc_howto_type *howto, bfd_signed_vma addend)
    160           1.1  christos {
    161           1.1  christos   bfd_reloc_status_type status = bfd_reloc_ok;
    162           1.1  christos   bfd_signed_vma old_addend = addend;
    163           1.1  christos   bfd_vma contents;
    164           1.1  christos   int size;
    165           1.1  christos 
    166           1.1  christos   size = bfd_get_reloc_size (howto);
    167           1.1  christos   switch (size)
    168           1.1  christos     {
    169           1.1  christos     case 0:
    170           1.1  christos       return status;
    171           1.1  christos     case 2:
    172           1.1  christos       contents = bfd_get_16 (abfd, address);
    173           1.1  christos       break;
    174           1.1  christos     case 4:
    175           1.1  christos       if (howto->src_mask != 0xffffffff)
    176           1.1  christos 	/* Must be 32-bit instruction, always little-endian.  */
    177           1.1  christos 	contents = bfd_getl32 (address);
    178           1.1  christos       else
    179           1.1  christos 	/* Must be 32-bit data (endianness dependent).  */
    180           1.1  christos 	contents = bfd_get_32 (abfd, address);
    181           1.1  christos       break;
    182           1.1  christos     case 8:
    183           1.1  christos       contents = bfd_get_64 (abfd, address);
    184           1.1  christos       break;
    185           1.1  christos     default:
    186           1.1  christos       abort ();
    187           1.1  christos     }
    188           1.1  christos 
    189           1.1  christos   switch (howto->complain_on_overflow)
    190           1.1  christos     {
    191           1.1  christos     case complain_overflow_dont:
    192           1.1  christos       break;
    193           1.1  christos     case complain_overflow_signed:
    194           1.1  christos       status = aarch64_signed_overflow (addend,
    195           1.1  christos 					howto->bitsize + howto->rightshift);
    196           1.1  christos       break;
    197           1.1  christos     case complain_overflow_unsigned:
    198           1.1  christos       status = aarch64_unsigned_overflow (addend,
    199           1.1  christos 					  howto->bitsize + howto->rightshift);
    200           1.1  christos       break;
    201           1.1  christos     case complain_overflow_bitfield:
    202           1.1  christos     default:
    203           1.1  christos       abort ();
    204           1.1  christos     }
    205           1.1  christos 
    206           1.1  christos   addend >>= howto->rightshift;
    207           1.1  christos 
    208           1.1  christos   switch (r_type)
    209           1.1  christos     {
    210           1.1  christos     case BFD_RELOC_AARCH64_CALL26:
    211           1.1  christos     case BFD_RELOC_AARCH64_JUMP26:
    212           1.1  christos       contents = reencode_branch_ofs_26 (contents, addend);
    213           1.1  christos       break;
    214           1.1  christos 
    215           1.1  christos     case BFD_RELOC_AARCH64_BRANCH19:
    216           1.1  christos       contents = reencode_cond_branch_ofs_19 (contents, addend);
    217           1.1  christos       break;
    218           1.1  christos 
    219           1.1  christos     case BFD_RELOC_AARCH64_TSTBR14:
    220           1.1  christos       contents = reencode_tst_branch_ofs_14 (contents, addend);
    221           1.1  christos       break;
    222           1.1  christos 
    223           1.1  christos     case BFD_RELOC_AARCH64_GOT_LD_PREL19:
    224           1.1  christos     case BFD_RELOC_AARCH64_LD_LO19_PCREL:
    225           1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19:
    226           1.1  christos     case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19:
    227           1.1  christos       if (old_addend & ((1 << howto->rightshift) - 1))
    228           1.1  christos 	return bfd_reloc_overflow;
    229           1.1  christos       contents = reencode_ld_lit_ofs_19 (contents, addend);
    230           1.1  christos       break;
    231           1.1  christos 
    232           1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_CALL:
    233           1.1  christos       break;
    234           1.1  christos 
    235           1.1  christos     case BFD_RELOC_AARCH64_ADR_GOT_PAGE:
    236           1.1  christos     case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL:
    237           1.1  christos     case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
    238           1.1  christos     case BFD_RELOC_AARCH64_ADR_LO21_PCREL:
    239           1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21:
    240           1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21:
    241           1.1  christos     case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21:
    242           1.1  christos     case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21:
    243           1.1  christos     case BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
    244           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21:
    245           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21:
    246           1.1  christos       contents = _bfd_aarch64_reencode_adr_imm (contents, addend);
    247           1.1  christos       break;
    248           1.1  christos 
    249           1.1  christos     case BFD_RELOC_AARCH64_ADD_LO12:
    250  1.1.1.2.12.1  pgoyette     case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12:
    251           1.1  christos     case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
    252           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_HI12:
    253           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_LO12:
    254           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_LO12_NC:
    255           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC:
    256           1.1  christos     case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12:
    257           1.1  christos     case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12:
    258           1.1  christos     case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
    259           1.1  christos       /* Corresponds to: add rd, rn, #uimm12 to provide the low order
    260  1.1.1.2.12.1  pgoyette 	 12 bits of the page offset following
    261  1.1.1.2.12.1  pgoyette 	 BFD_RELOC_AARCH64_ADR_HI21_PCREL which computes the
    262  1.1.1.2.12.1  pgoyette 	 (pc-relative) page base.  */
    263           1.1  christos       contents = reencode_add_imm (contents, addend);
    264           1.1  christos       break;
    265           1.1  christos 
    266           1.1  christos     case BFD_RELOC_AARCH64_LD32_GOTPAGE_LO14:
    267           1.1  christos     case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC:
    268           1.1  christos     case BFD_RELOC_AARCH64_LD64_GOTOFF_LO15:
    269           1.1  christos     case BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15:
    270           1.1  christos     case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC:
    271           1.1  christos     case BFD_RELOC_AARCH64_LDST128_LO12:
    272           1.1  christos     case BFD_RELOC_AARCH64_LDST16_LO12:
    273           1.1  christos     case BFD_RELOC_AARCH64_LDST32_LO12:
    274           1.1  christos     case BFD_RELOC_AARCH64_LDST64_LO12:
    275           1.1  christos     case BFD_RELOC_AARCH64_LDST8_LO12:
    276           1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC:
    277  1.1.1.2.12.1  pgoyette     case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12:
    278           1.1  christos     case BFD_RELOC_AARCH64_TLSIE_LD32_GOTTPREL_LO12_NC:
    279           1.1  christos     case BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
    280           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12:
    281           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC:
    282           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12:
    283           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC:
    284           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12:
    285           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC:
    286           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12:
    287           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC:
    288  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12:
    289  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12_NC:
    290  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12:
    291  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12_NC:
    292  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12:
    293  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:
    294  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12:
    295  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12_NC:
    296           1.1  christos       if (old_addend & ((1 << howto->rightshift) - 1))
    297           1.1  christos 	return bfd_reloc_overflow;
    298           1.1  christos       /* Used for ldr*|str* rt, [rn, #uimm12] to provide the low order
    299  1.1.1.2.12.2  pgoyette 	 12 bits address offset.  */
    300           1.1  christos       contents = reencode_ldst_pos_imm (contents, addend);
    301           1.1  christos       break;
    302           1.1  christos 
    303           1.1  christos       /* Group relocations to create high bits of a 16, 32, 48 or 64
    304  1.1.1.2.12.1  pgoyette 	 bit signed data or abs address inline. Will change
    305  1.1.1.2.12.1  pgoyette 	 instruction to MOVN or MOVZ depending on sign of calculated
    306  1.1.1.2.12.1  pgoyette 	 value.  */
    307           1.1  christos 
    308           1.1  christos     case BFD_RELOC_AARCH64_MOVW_G0_S:
    309           1.1  christos     case BFD_RELOC_AARCH64_MOVW_G1_S:
    310           1.1  christos     case BFD_RELOC_AARCH64_MOVW_G2_S:
    311  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_MOVW_PREL_G0:
    312  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_MOVW_PREL_G1:
    313  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_MOVW_PREL_G2:
    314  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_MOVW_PREL_G3:
    315           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0:
    316           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1:
    317           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G2:
    318           1.1  christos     case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0:
    319           1.1  christos     case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1:
    320           1.1  christos     case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2:
    321           1.1  christos       /* NOTE: We can only come here with movz or movn.  */
    322           1.1  christos       if (addend < 0)
    323           1.1  christos 	{
    324           1.1  christos 	  /* Force use of MOVN.  */
    325           1.1  christos 	  addend = ~addend;
    326           1.1  christos 	  contents = reencode_movzn_to_movn (contents);
    327           1.1  christos 	}
    328           1.1  christos       else
    329           1.1  christos 	{
    330           1.1  christos 	  /* Force use of MOVZ.  */
    331           1.1  christos 	  contents = reencode_movzn_to_movz (contents);
    332           1.1  christos 	}
    333  1.1.1.2.12.1  pgoyette       /* Fall through.  */
    334           1.1  christos 
    335           1.1  christos       /* Group relocations to create a 16, 32, 48 or 64 bit unsigned
    336  1.1.1.2.12.1  pgoyette 	 data or abs address inline.  */
    337           1.1  christos 
    338           1.1  christos     case BFD_RELOC_AARCH64_MOVW_G0:
    339           1.1  christos     case BFD_RELOC_AARCH64_MOVW_G0_NC:
    340           1.1  christos     case BFD_RELOC_AARCH64_MOVW_G1:
    341           1.1  christos     case BFD_RELOC_AARCH64_MOVW_G1_NC:
    342           1.1  christos     case BFD_RELOC_AARCH64_MOVW_G2:
    343           1.1  christos     case BFD_RELOC_AARCH64_MOVW_G2_NC:
    344           1.1  christos     case BFD_RELOC_AARCH64_MOVW_G3:
    345           1.1  christos     case BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC:
    346           1.1  christos     case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1:
    347  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_MOVW_PREL_G0_NC:
    348  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_MOVW_PREL_G1_NC:
    349  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_MOVW_PREL_G2_NC:
    350           1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC:
    351           1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_OFF_G1:
    352           1.1  christos     case BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC:
    353           1.1  christos     case BFD_RELOC_AARCH64_TLSGD_MOVW_G1:
    354           1.1  christos     case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC:
    355           1.1  christos     case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1:
    356           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0_NC:
    357           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1_NC:
    358           1.1  christos     case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
    359           1.1  christos     case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
    360           1.1  christos       contents = reencode_movw_imm (contents, addend);
    361           1.1  christos       break;
    362           1.1  christos 
    363           1.1  christos     default:
    364           1.1  christos       /* Repack simple data */
    365           1.1  christos       if (howto->dst_mask & (howto->dst_mask + 1))
    366           1.1  christos 	return bfd_reloc_notsupported;
    367           1.1  christos 
    368           1.1  christos       contents = ((contents & ~howto->dst_mask) | (addend & howto->dst_mask));
    369           1.1  christos       break;
    370           1.1  christos     }
    371           1.1  christos 
    372           1.1  christos   switch (size)
    373           1.1  christos     {
    374           1.1  christos     case 2:
    375           1.1  christos       bfd_put_16 (abfd, contents, address);
    376           1.1  christos       break;
    377           1.1  christos     case 4:
    378           1.1  christos       if (howto->dst_mask != 0xffffffff)
    379           1.1  christos 	/* must be 32-bit instruction, always little-endian */
    380           1.1  christos 	bfd_putl32 (contents, address);
    381           1.1  christos       else
    382           1.1  christos 	/* must be 32-bit data (endianness dependent) */
    383           1.1  christos 	bfd_put_32 (abfd, contents, address);
    384           1.1  christos       break;
    385           1.1  christos     case 8:
    386           1.1  christos       bfd_put_64 (abfd, contents, address);
    387           1.1  christos       break;
    388           1.1  christos     default:
    389           1.1  christos       abort ();
    390           1.1  christos     }
    391           1.1  christos 
    392           1.1  christos   return status;
    393           1.1  christos }
    394           1.1  christos 
    395           1.1  christos bfd_vma
    396           1.1  christos _bfd_aarch64_elf_resolve_relocation (bfd_reloc_code_real_type r_type,
    397           1.1  christos 				     bfd_vma place, bfd_vma value,
    398           1.1  christos 				     bfd_vma addend, bfd_boolean weak_undef_p)
    399           1.1  christos {
    400           1.1  christos   switch (r_type)
    401           1.1  christos     {
    402           1.1  christos     case BFD_RELOC_AARCH64_NONE:
    403           1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_CALL:
    404           1.1  christos       break;
    405           1.1  christos 
    406           1.1  christos     case BFD_RELOC_AARCH64_16_PCREL:
    407           1.1  christos     case BFD_RELOC_AARCH64_32_PCREL:
    408           1.1  christos     case BFD_RELOC_AARCH64_64_PCREL:
    409           1.1  christos     case BFD_RELOC_AARCH64_ADR_LO21_PCREL:
    410           1.1  christos     case BFD_RELOC_AARCH64_BRANCH19:
    411           1.1  christos     case BFD_RELOC_AARCH64_LD_LO19_PCREL:
    412  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_MOVW_PREL_G0:
    413  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_MOVW_PREL_G0_NC:
    414  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_MOVW_PREL_G1:
    415  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_MOVW_PREL_G1_NC:
    416  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_MOVW_PREL_G2:
    417  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_MOVW_PREL_G2_NC:
    418  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_MOVW_PREL_G3:
    419           1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21:
    420           1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19:
    421           1.1  christos     case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21:
    422           1.1  christos     case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19:
    423           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21:
    424           1.1  christos     case BFD_RELOC_AARCH64_TSTBR14:
    425           1.1  christos       if (weak_undef_p)
    426           1.1  christos 	value = place;
    427           1.1  christos       value = value + addend - place;
    428           1.1  christos       break;
    429           1.1  christos 
    430           1.1  christos     case BFD_RELOC_AARCH64_CALL26:
    431           1.1  christos     case BFD_RELOC_AARCH64_JUMP26:
    432           1.1  christos       value = value + addend - place;
    433           1.1  christos       break;
    434           1.1  christos 
    435           1.1  christos     case BFD_RELOC_AARCH64_16:
    436           1.1  christos     case BFD_RELOC_AARCH64_32:
    437           1.1  christos     case BFD_RELOC_AARCH64_MOVW_G0:
    438           1.1  christos     case BFD_RELOC_AARCH64_MOVW_G0_NC:
    439           1.1  christos     case BFD_RELOC_AARCH64_MOVW_G0_S:
    440           1.1  christos     case BFD_RELOC_AARCH64_MOVW_G1:
    441           1.1  christos     case BFD_RELOC_AARCH64_MOVW_G1_NC:
    442           1.1  christos     case BFD_RELOC_AARCH64_MOVW_G1_S:
    443           1.1  christos     case BFD_RELOC_AARCH64_MOVW_G2:
    444           1.1  christos     case BFD_RELOC_AARCH64_MOVW_G2_NC:
    445           1.1  christos     case BFD_RELOC_AARCH64_MOVW_G2_S:
    446           1.1  christos     case BFD_RELOC_AARCH64_MOVW_G3:
    447           1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC:
    448           1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_OFF_G1:
    449           1.1  christos     case BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC:
    450           1.1  christos     case BFD_RELOC_AARCH64_TLSGD_MOVW_G1:
    451           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_HI12:
    452           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_LO12:
    453           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_LO12_NC:
    454           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12:
    455           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12:
    456           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12:
    457           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12:
    458           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0:
    459           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0_NC:
    460           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1:
    461           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1_NC:
    462           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G2:
    463  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12:
    464  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12:
    465  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12:
    466  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12:
    467           1.1  christos       value = value + addend;
    468           1.1  christos       break;
    469           1.1  christos 
    470           1.1  christos     case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL:
    471           1.1  christos     case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
    472           1.1  christos       if (weak_undef_p)
    473           1.1  christos 	value = PG (place);
    474           1.1  christos       value = PG (value + addend) - PG (place);
    475           1.1  christos       break;
    476           1.1  christos 
    477           1.1  christos     case BFD_RELOC_AARCH64_GOT_LD_PREL19:
    478           1.1  christos       value = value + addend - place;
    479           1.1  christos       break;
    480           1.1  christos 
    481           1.1  christos     case BFD_RELOC_AARCH64_ADR_GOT_PAGE:
    482           1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21:
    483           1.1  christos     case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21:
    484           1.1  christos     case BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
    485           1.1  christos     case BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21:
    486           1.1  christos       value = PG (value + addend) - PG (place);
    487           1.1  christos       break;
    488           1.1  christos 
    489  1.1.1.2.12.1  pgoyette     /* Caller must make sure addend is the base address of .got section.  */
    490           1.1  christos     case BFD_RELOC_AARCH64_LD32_GOTPAGE_LO14:
    491           1.1  christos     case BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15:
    492  1.1.1.2.12.1  pgoyette       addend = PG (addend);
    493  1.1.1.2.12.1  pgoyette       /* Fall through.  */
    494  1.1.1.2.12.1  pgoyette     case BFD_RELOC_AARCH64_LD64_GOTOFF_LO15:
    495  1.1.1.2.12.1  pgoyette     case BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC:
    496  1.1.1.2.12.1  pgoyette     case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1:
    497  1.1.1.2.12.1  pgoyette       value = value - addend;
    498           1.1  christos       break;
    499           1.1  christos 
    500           1.1  christos     case BFD_RELOC_AARCH64_ADD_LO12:
    501           1.1  christos     case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC:
    502           1.1  christos     case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC:
    503           1.1  christos     case BFD_RELOC_AARCH64_LDST128_LO12:
    504           1.1  christos     case BFD_RELOC_AARCH64_LDST16_LO12:
    505           1.1  christos     case BFD_RELOC_AARCH64_LDST32_LO12:
    506           1.1  christos     case BFD_RELOC_AARCH64_LDST64_LO12:
    507           1.1  christos     case BFD_RELOC_AARCH64_LDST8_LO12:
    508           1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_ADD:
    509  1.1.1.2.12.1  pgoyette     case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12:
    510           1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC:
    511  1.1.1.2.12.1  pgoyette     case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12:
    512           1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_LDR:
    513           1.1  christos     case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
    514           1.1  christos     case BFD_RELOC_AARCH64_TLSIE_LD32_GOTTPREL_LO12_NC:
    515           1.1  christos     case BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
    516  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC:
    517  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC:
    518  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC:
    519  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC:
    520           1.1  christos     case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
    521  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12_NC:
    522  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12_NC:
    523  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:
    524  1.1.1.2.12.2  pgoyette     case BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12_NC:
    525           1.1  christos       value = PG_OFFSET (value + addend);
    526           1.1  christos       break;
    527           1.1  christos 
    528           1.1  christos     case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12:
    529           1.1  christos       value = value + addend;
    530           1.1  christos       break;
    531           1.1  christos 
    532           1.1  christos     case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1:
    533           1.1  christos     case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1:
    534           1.1  christos     case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
    535           1.1  christos       value = (value + addend) & (bfd_vma) 0xffff0000;
    536           1.1  christos       break;
    537           1.1  christos     case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12:
    538           1.1  christos       /* Mask off low 12bits, keep all other high bits, so that the later
    539           1.1  christos 	 generic code could check whehter there is overflow.  */
    540           1.1  christos       value = (value + addend) & ~(bfd_vma) 0xfff;
    541           1.1  christos       break;
    542           1.1  christos 
    543           1.1  christos     case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC:
    544           1.1  christos     case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0:
    545           1.1  christos     case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
    546           1.1  christos       value = (value + addend) & (bfd_vma) 0xffff;
    547           1.1  christos       break;
    548           1.1  christos 
    549           1.1  christos     case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2:
    550           1.1  christos       value = (value + addend) & ~(bfd_vma) 0xffffffff;
    551           1.1  christos       value -= place & ~(bfd_vma) 0xffffffff;
    552           1.1  christos       break;
    553           1.1  christos 
    554           1.1  christos     default:
    555           1.1  christos       break;
    556           1.1  christos     }
    557           1.1  christos 
    558           1.1  christos   return value;
    559           1.1  christos }
    560           1.1  christos 
    561           1.1  christos /* Support for core dump NOTE sections.  */
    562           1.1  christos 
    563           1.1  christos bfd_boolean
    564           1.1  christos _bfd_aarch64_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
    565           1.1  christos {
    566           1.1  christos   int offset;
    567           1.1  christos   size_t size;
    568           1.1  christos 
    569           1.1  christos   switch (note->descsz)
    570           1.1  christos     {
    571           1.1  christos       default:
    572           1.1  christos 	return FALSE;
    573           1.1  christos 
    574           1.1  christos       case 392:		/* sizeof(struct elf_prstatus) on Linux/arm64.  */
    575           1.1  christos 	/* pr_cursig */
    576           1.1  christos 	elf_tdata (abfd)->core->signal
    577           1.1  christos 	  = bfd_get_16 (abfd, note->descdata + 12);
    578           1.1  christos 
    579           1.1  christos 	/* pr_pid */
    580           1.1  christos 	elf_tdata (abfd)->core->lwpid
    581           1.1  christos 	  = bfd_get_32 (abfd, note->descdata + 32);
    582           1.1  christos 
    583           1.1  christos 	/* pr_reg */
    584           1.1  christos 	offset = 112;
    585           1.1  christos 	size = 272;
    586           1.1  christos 
    587           1.1  christos 	break;
    588           1.1  christos     }
    589           1.1  christos 
    590           1.1  christos   /* Make a ".reg/999" section.  */
    591           1.1  christos   return _bfd_elfcore_make_pseudosection (abfd, ".reg",
    592           1.1  christos 					  size, note->descpos + offset);
    593           1.1  christos }
    594           1.1  christos 
    595           1.1  christos bfd_boolean
    596           1.1  christos _bfd_aarch64_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
    597           1.1  christos {
    598           1.1  christos   switch (note->descsz)
    599           1.1  christos     {
    600           1.1  christos     default:
    601           1.1  christos       return FALSE;
    602           1.1  christos 
    603  1.1.1.2.12.1  pgoyette     case 136:	     /* This is sizeof(struct elf_prpsinfo) on Linux/aarch64.  */
    604           1.1  christos       elf_tdata (abfd)->core->pid = bfd_get_32 (abfd, note->descdata + 24);
    605           1.1  christos       elf_tdata (abfd)->core->program
    606           1.1  christos 	= _bfd_elfcore_strndup (abfd, note->descdata + 40, 16);
    607           1.1  christos       elf_tdata (abfd)->core->command
    608           1.1  christos 	= _bfd_elfcore_strndup (abfd, note->descdata + 56, 80);
    609           1.1  christos     }
    610           1.1  christos 
    611           1.1  christos   /* Note that for some reason, a spurious space is tacked
    612           1.1  christos      onto the end of the args in some (at least one anyway)
    613           1.1  christos      implementations, so strip it off if it exists.  */
    614           1.1  christos 
    615           1.1  christos   {
    616           1.1  christos     char *command = elf_tdata (abfd)->core->command;
    617           1.1  christos     int n = strlen (command);
    618           1.1  christos 
    619           1.1  christos     if (0 < n && command[n - 1] == ' ')
    620           1.1  christos       command[n - 1] = '\0';
    621           1.1  christos   }
    622           1.1  christos 
    623           1.1  christos   return TRUE;
    624           1.1  christos }
    625           1.1  christos 
    626           1.1  christos char *
    627           1.1  christos _bfd_aarch64_elf_write_core_note (bfd *abfd, char *buf, int *bufsiz, int note_type,
    628           1.1  christos 				  ...)
    629           1.1  christos {
    630           1.1  christos   switch (note_type)
    631           1.1  christos     {
    632           1.1  christos     default:
    633           1.1  christos       return NULL;
    634           1.1  christos 
    635           1.1  christos     case NT_PRPSINFO:
    636           1.1  christos       {
    637  1.1.1.2.12.2  pgoyette 	char data[136] ATTRIBUTE_NONSTRING;
    638  1.1.1.2.12.1  pgoyette 	va_list ap;
    639           1.1  christos 
    640  1.1.1.2.12.1  pgoyette 	va_start (ap, note_type);
    641  1.1.1.2.12.1  pgoyette 	memset (data, 0, sizeof (data));
    642  1.1.1.2.12.1  pgoyette 	strncpy (data + 40, va_arg (ap, const char *), 16);
    643  1.1.1.2.12.2  pgoyette #if GCC_VERSION == 8001
    644  1.1.1.2.12.2  pgoyette 	DIAGNOSTIC_PUSH;
    645  1.1.1.2.12.2  pgoyette 	/* GCC 8.1 warns about 80 equals destination size with
    646  1.1.1.2.12.2  pgoyette 	   -Wstringop-truncation:
    647  1.1.1.2.12.2  pgoyette 	   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85643
    648  1.1.1.2.12.2  pgoyette 	 */
    649  1.1.1.2.12.2  pgoyette 	DIAGNOSTIC_IGNORE_STRINGOP_TRUNCATION;
    650  1.1.1.2.12.2  pgoyette #endif
    651  1.1.1.2.12.1  pgoyette 	strncpy (data + 56, va_arg (ap, const char *), 80);
    652  1.1.1.2.12.2  pgoyette #if GCC_VERSION == 8001
    653  1.1.1.2.12.2  pgoyette 	DIAGNOSTIC_POP;
    654  1.1.1.2.12.2  pgoyette #endif
    655  1.1.1.2.12.1  pgoyette 	va_end (ap);
    656           1.1  christos 
    657  1.1.1.2.12.1  pgoyette 	return elfcore_write_note (abfd, buf, bufsiz, "CORE",
    658           1.1  christos 				   note_type, data, sizeof (data));
    659           1.1  christos       }
    660           1.1  christos 
    661           1.1  christos     case NT_PRSTATUS:
    662           1.1  christos       {
    663  1.1.1.2.12.1  pgoyette 	char data[392];
    664  1.1.1.2.12.1  pgoyette 	va_list ap;
    665  1.1.1.2.12.1  pgoyette 	long pid;
    666  1.1.1.2.12.1  pgoyette 	int cursig;
    667  1.1.1.2.12.1  pgoyette 	const void *greg;
    668  1.1.1.2.12.1  pgoyette 
    669  1.1.1.2.12.1  pgoyette 	va_start (ap, note_type);
    670  1.1.1.2.12.1  pgoyette 	memset (data, 0, sizeof (data));
    671  1.1.1.2.12.1  pgoyette 	pid = va_arg (ap, long);
    672  1.1.1.2.12.1  pgoyette 	bfd_put_32 (abfd, pid, data + 32);
    673  1.1.1.2.12.1  pgoyette 	cursig = va_arg (ap, int);
    674  1.1.1.2.12.1  pgoyette 	bfd_put_16 (abfd, cursig, data + 12);
    675  1.1.1.2.12.1  pgoyette 	greg = va_arg (ap, const void *);
    676  1.1.1.2.12.1  pgoyette 	memcpy (data + 112, greg, 272);
    677  1.1.1.2.12.1  pgoyette 	va_end (ap);
    678           1.1  christos 
    679  1.1.1.2.12.1  pgoyette 	return elfcore_write_note (abfd, buf, bufsiz, "CORE",
    680           1.1  christos 				   note_type, data, sizeof (data));
    681           1.1  christos       }
    682           1.1  christos     }
    683           1.1  christos }
    684