Home | History | Annotate | Line # | Download | only in bfd
elfxx-aarch64.c revision 1.1.1.3
      1      1.1  christos /* AArch64-specific support for ELF.
      2  1.1.1.3  christos    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.3  christos     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.3  christos 	 12 bits of the page offset following
    261  1.1.1.3  christos 	 BFD_RELOC_AARCH64_ADR_HI21_PCREL which computes the
    262  1.1.1.3  christos 	 (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.3  christos     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  christos       if (old_addend & ((1 << howto->rightshift) - 1))
    289      1.1  christos 	return bfd_reloc_overflow;
    290      1.1  christos       /* Used for ldr*|str* rt, [rn, #uimm12] to provide the low order
    291  1.1.1.3  christos 	 12 bits of the page offset following BFD_RELOC_AARCH64_ADR_HI21_PCREL
    292  1.1.1.3  christos 	 which computes the (pc-relative) page base.  */
    293      1.1  christos       contents = reencode_ldst_pos_imm (contents, addend);
    294      1.1  christos       break;
    295      1.1  christos 
    296      1.1  christos       /* Group relocations to create high bits of a 16, 32, 48 or 64
    297  1.1.1.3  christos 	 bit signed data or abs address inline. Will change
    298  1.1.1.3  christos 	 instruction to MOVN or MOVZ depending on sign of calculated
    299  1.1.1.3  christos 	 value.  */
    300      1.1  christos 
    301      1.1  christos     case BFD_RELOC_AARCH64_MOVW_G0_S:
    302      1.1  christos     case BFD_RELOC_AARCH64_MOVW_G1_S:
    303      1.1  christos     case BFD_RELOC_AARCH64_MOVW_G2_S:
    304      1.1  christos     case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0:
    305      1.1  christos     case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1:
    306      1.1  christos     case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G2:
    307      1.1  christos     case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0:
    308      1.1  christos     case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1:
    309      1.1  christos     case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2:
    310      1.1  christos       /* NOTE: We can only come here with movz or movn.  */
    311      1.1  christos       if (addend < 0)
    312      1.1  christos 	{
    313      1.1  christos 	  /* Force use of MOVN.  */
    314      1.1  christos 	  addend = ~addend;
    315      1.1  christos 	  contents = reencode_movzn_to_movn (contents);
    316      1.1  christos 	}
    317      1.1  christos       else
    318      1.1  christos 	{
    319      1.1  christos 	  /* Force use of MOVZ.  */
    320      1.1  christos 	  contents = reencode_movzn_to_movz (contents);
    321      1.1  christos 	}
    322  1.1.1.3  christos       /* Fall through.  */
    323      1.1  christos 
    324      1.1  christos       /* Group relocations to create a 16, 32, 48 or 64 bit unsigned
    325  1.1.1.3  christos 	 data or abs address inline.  */
    326      1.1  christos 
    327      1.1  christos     case BFD_RELOC_AARCH64_MOVW_G0:
    328      1.1  christos     case BFD_RELOC_AARCH64_MOVW_G0_NC:
    329      1.1  christos     case BFD_RELOC_AARCH64_MOVW_G1:
    330      1.1  christos     case BFD_RELOC_AARCH64_MOVW_G1_NC:
    331      1.1  christos     case BFD_RELOC_AARCH64_MOVW_G2:
    332      1.1  christos     case BFD_RELOC_AARCH64_MOVW_G2_NC:
    333      1.1  christos     case BFD_RELOC_AARCH64_MOVW_G3:
    334      1.1  christos     case BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC:
    335      1.1  christos     case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1:
    336      1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC:
    337      1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_OFF_G1:
    338      1.1  christos     case BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC:
    339      1.1  christos     case BFD_RELOC_AARCH64_TLSGD_MOVW_G1:
    340      1.1  christos     case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC:
    341      1.1  christos     case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1:
    342      1.1  christos     case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0_NC:
    343      1.1  christos     case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1_NC:
    344      1.1  christos     case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
    345      1.1  christos     case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
    346      1.1  christos       contents = reencode_movw_imm (contents, addend);
    347      1.1  christos       break;
    348      1.1  christos 
    349      1.1  christos     default:
    350      1.1  christos       /* Repack simple data */
    351      1.1  christos       if (howto->dst_mask & (howto->dst_mask + 1))
    352      1.1  christos 	return bfd_reloc_notsupported;
    353      1.1  christos 
    354      1.1  christos       contents = ((contents & ~howto->dst_mask) | (addend & howto->dst_mask));
    355      1.1  christos       break;
    356      1.1  christos     }
    357      1.1  christos 
    358      1.1  christos   switch (size)
    359      1.1  christos     {
    360      1.1  christos     case 2:
    361      1.1  christos       bfd_put_16 (abfd, contents, address);
    362      1.1  christos       break;
    363      1.1  christos     case 4:
    364      1.1  christos       if (howto->dst_mask != 0xffffffff)
    365      1.1  christos 	/* must be 32-bit instruction, always little-endian */
    366      1.1  christos 	bfd_putl32 (contents, address);
    367      1.1  christos       else
    368      1.1  christos 	/* must be 32-bit data (endianness dependent) */
    369      1.1  christos 	bfd_put_32 (abfd, contents, address);
    370      1.1  christos       break;
    371      1.1  christos     case 8:
    372      1.1  christos       bfd_put_64 (abfd, contents, address);
    373      1.1  christos       break;
    374      1.1  christos     default:
    375      1.1  christos       abort ();
    376      1.1  christos     }
    377      1.1  christos 
    378      1.1  christos   return status;
    379      1.1  christos }
    380      1.1  christos 
    381      1.1  christos bfd_vma
    382      1.1  christos _bfd_aarch64_elf_resolve_relocation (bfd_reloc_code_real_type r_type,
    383      1.1  christos 				     bfd_vma place, bfd_vma value,
    384      1.1  christos 				     bfd_vma addend, bfd_boolean weak_undef_p)
    385      1.1  christos {
    386      1.1  christos   switch (r_type)
    387      1.1  christos     {
    388      1.1  christos     case BFD_RELOC_AARCH64_NONE:
    389      1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_CALL:
    390      1.1  christos       break;
    391      1.1  christos 
    392      1.1  christos     case BFD_RELOC_AARCH64_16_PCREL:
    393      1.1  christos     case BFD_RELOC_AARCH64_32_PCREL:
    394      1.1  christos     case BFD_RELOC_AARCH64_64_PCREL:
    395      1.1  christos     case BFD_RELOC_AARCH64_ADR_LO21_PCREL:
    396      1.1  christos     case BFD_RELOC_AARCH64_BRANCH19:
    397      1.1  christos     case BFD_RELOC_AARCH64_LD_LO19_PCREL:
    398      1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21:
    399      1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19:
    400      1.1  christos     case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21:
    401      1.1  christos     case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19:
    402      1.1  christos     case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21:
    403      1.1  christos     case BFD_RELOC_AARCH64_TSTBR14:
    404      1.1  christos       if (weak_undef_p)
    405      1.1  christos 	value = place;
    406      1.1  christos       value = value + addend - place;
    407      1.1  christos       break;
    408      1.1  christos 
    409      1.1  christos     case BFD_RELOC_AARCH64_CALL26:
    410      1.1  christos     case BFD_RELOC_AARCH64_JUMP26:
    411      1.1  christos       value = value + addend - place;
    412      1.1  christos       break;
    413      1.1  christos 
    414      1.1  christos     case BFD_RELOC_AARCH64_16:
    415      1.1  christos     case BFD_RELOC_AARCH64_32:
    416      1.1  christos     case BFD_RELOC_AARCH64_MOVW_G0:
    417      1.1  christos     case BFD_RELOC_AARCH64_MOVW_G0_NC:
    418      1.1  christos     case BFD_RELOC_AARCH64_MOVW_G0_S:
    419      1.1  christos     case BFD_RELOC_AARCH64_MOVW_G1:
    420      1.1  christos     case BFD_RELOC_AARCH64_MOVW_G1_NC:
    421      1.1  christos     case BFD_RELOC_AARCH64_MOVW_G1_S:
    422      1.1  christos     case BFD_RELOC_AARCH64_MOVW_G2:
    423      1.1  christos     case BFD_RELOC_AARCH64_MOVW_G2_NC:
    424      1.1  christos     case BFD_RELOC_AARCH64_MOVW_G2_S:
    425      1.1  christos     case BFD_RELOC_AARCH64_MOVW_G3:
    426      1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC:
    427      1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_OFF_G1:
    428      1.1  christos     case BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC:
    429      1.1  christos     case BFD_RELOC_AARCH64_TLSGD_MOVW_G1:
    430      1.1  christos     case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_HI12:
    431      1.1  christos     case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_LO12:
    432      1.1  christos     case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_LO12_NC:
    433      1.1  christos     case BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12:
    434      1.1  christos     case BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC:
    435      1.1  christos     case BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12:
    436      1.1  christos     case BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC:
    437      1.1  christos     case BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12:
    438      1.1  christos     case BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC:
    439      1.1  christos     case BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12:
    440      1.1  christos     case BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC:
    441      1.1  christos     case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0:
    442      1.1  christos     case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0_NC:
    443      1.1  christos     case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1:
    444      1.1  christos     case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1_NC:
    445      1.1  christos     case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G2:
    446      1.1  christos       value = value + addend;
    447      1.1  christos       break;
    448      1.1  christos 
    449      1.1  christos     case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL:
    450      1.1  christos     case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
    451      1.1  christos       if (weak_undef_p)
    452      1.1  christos 	value = PG (place);
    453      1.1  christos       value = PG (value + addend) - PG (place);
    454      1.1  christos       break;
    455      1.1  christos 
    456      1.1  christos     case BFD_RELOC_AARCH64_GOT_LD_PREL19:
    457      1.1  christos       value = value + addend - place;
    458      1.1  christos       break;
    459      1.1  christos 
    460      1.1  christos     case BFD_RELOC_AARCH64_ADR_GOT_PAGE:
    461      1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21:
    462      1.1  christos     case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21:
    463      1.1  christos     case BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
    464      1.1  christos     case BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21:
    465      1.1  christos       value = PG (value + addend) - PG (place);
    466      1.1  christos       break;
    467      1.1  christos 
    468  1.1.1.3  christos     /* Caller must make sure addend is the base address of .got section.  */
    469      1.1  christos     case BFD_RELOC_AARCH64_LD32_GOTPAGE_LO14:
    470      1.1  christos     case BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15:
    471  1.1.1.3  christos       addend = PG (addend);
    472  1.1.1.3  christos       /* Fall through.  */
    473  1.1.1.3  christos     case BFD_RELOC_AARCH64_LD64_GOTOFF_LO15:
    474  1.1.1.3  christos     case BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC:
    475  1.1.1.3  christos     case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1:
    476  1.1.1.3  christos       value = value - addend;
    477      1.1  christos       break;
    478      1.1  christos 
    479      1.1  christos     case BFD_RELOC_AARCH64_ADD_LO12:
    480      1.1  christos     case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC:
    481      1.1  christos     case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC:
    482      1.1  christos     case BFD_RELOC_AARCH64_LDST128_LO12:
    483      1.1  christos     case BFD_RELOC_AARCH64_LDST16_LO12:
    484      1.1  christos     case BFD_RELOC_AARCH64_LDST32_LO12:
    485      1.1  christos     case BFD_RELOC_AARCH64_LDST64_LO12:
    486      1.1  christos     case BFD_RELOC_AARCH64_LDST8_LO12:
    487      1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_ADD:
    488  1.1.1.3  christos     case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12:
    489      1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC:
    490  1.1.1.3  christos     case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12:
    491      1.1  christos     case BFD_RELOC_AARCH64_TLSDESC_LDR:
    492      1.1  christos     case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
    493      1.1  christos     case BFD_RELOC_AARCH64_TLSIE_LD32_GOTTPREL_LO12_NC:
    494      1.1  christos     case BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
    495      1.1  christos     case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
    496      1.1  christos       value = PG_OFFSET (value + addend);
    497      1.1  christos       break;
    498      1.1  christos 
    499      1.1  christos     case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12:
    500      1.1  christos       value = value + addend;
    501      1.1  christos       break;
    502      1.1  christos 
    503      1.1  christos     case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1:
    504      1.1  christos     case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1:
    505      1.1  christos     case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
    506      1.1  christos       value = (value + addend) & (bfd_vma) 0xffff0000;
    507      1.1  christos       break;
    508      1.1  christos     case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12:
    509      1.1  christos       /* Mask off low 12bits, keep all other high bits, so that the later
    510      1.1  christos 	 generic code could check whehter there is overflow.  */
    511      1.1  christos       value = (value + addend) & ~(bfd_vma) 0xfff;
    512      1.1  christos       break;
    513      1.1  christos 
    514      1.1  christos     case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC:
    515      1.1  christos     case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0:
    516      1.1  christos     case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
    517      1.1  christos       value = (value + addend) & (bfd_vma) 0xffff;
    518      1.1  christos       break;
    519      1.1  christos 
    520      1.1  christos     case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2:
    521      1.1  christos       value = (value + addend) & ~(bfd_vma) 0xffffffff;
    522      1.1  christos       value -= place & ~(bfd_vma) 0xffffffff;
    523      1.1  christos       break;
    524      1.1  christos 
    525      1.1  christos     default:
    526      1.1  christos       break;
    527      1.1  christos     }
    528      1.1  christos 
    529      1.1  christos   return value;
    530      1.1  christos }
    531      1.1  christos 
    532      1.1  christos /* Hook called by the linker routine which adds symbols from an object
    533      1.1  christos    file.  */
    534      1.1  christos 
    535      1.1  christos bfd_boolean
    536      1.1  christos _bfd_aarch64_elf_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
    537      1.1  christos 				  Elf_Internal_Sym *sym,
    538      1.1  christos 				  const char **namep ATTRIBUTE_UNUSED,
    539      1.1  christos 				  flagword *flagsp ATTRIBUTE_UNUSED,
    540      1.1  christos 				  asection **secp ATTRIBUTE_UNUSED,
    541      1.1  christos 				  bfd_vma *valp ATTRIBUTE_UNUSED)
    542      1.1  christos {
    543  1.1.1.2  christos   if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
    544      1.1  christos       && (abfd->flags & DYNAMIC) == 0
    545      1.1  christos       && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour)
    546  1.1.1.2  christos     elf_tdata (info->output_bfd)->has_gnu_symbols |= elf_gnu_symbol_ifunc;
    547      1.1  christos 
    548      1.1  christos   return TRUE;
    549      1.1  christos }
    550      1.1  christos 
    551      1.1  christos /* Support for core dump NOTE sections.  */
    552      1.1  christos 
    553      1.1  christos bfd_boolean
    554      1.1  christos _bfd_aarch64_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
    555      1.1  christos {
    556      1.1  christos   int offset;
    557      1.1  christos   size_t size;
    558      1.1  christos 
    559      1.1  christos   switch (note->descsz)
    560      1.1  christos     {
    561      1.1  christos       default:
    562      1.1  christos 	return FALSE;
    563      1.1  christos 
    564      1.1  christos       case 392:		/* sizeof(struct elf_prstatus) on Linux/arm64.  */
    565      1.1  christos 	/* pr_cursig */
    566      1.1  christos 	elf_tdata (abfd)->core->signal
    567      1.1  christos 	  = bfd_get_16 (abfd, note->descdata + 12);
    568      1.1  christos 
    569      1.1  christos 	/* pr_pid */
    570      1.1  christos 	elf_tdata (abfd)->core->lwpid
    571      1.1  christos 	  = bfd_get_32 (abfd, note->descdata + 32);
    572      1.1  christos 
    573      1.1  christos 	/* pr_reg */
    574      1.1  christos 	offset = 112;
    575      1.1  christos 	size = 272;
    576      1.1  christos 
    577      1.1  christos 	break;
    578      1.1  christos     }
    579      1.1  christos 
    580      1.1  christos   /* Make a ".reg/999" section.  */
    581      1.1  christos   return _bfd_elfcore_make_pseudosection (abfd, ".reg",
    582      1.1  christos 					  size, note->descpos + offset);
    583      1.1  christos }
    584      1.1  christos 
    585      1.1  christos bfd_boolean
    586      1.1  christos _bfd_aarch64_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
    587      1.1  christos {
    588      1.1  christos   switch (note->descsz)
    589      1.1  christos     {
    590      1.1  christos     default:
    591      1.1  christos       return FALSE;
    592      1.1  christos 
    593  1.1.1.3  christos     case 136:	     /* This is sizeof(struct elf_prpsinfo) on Linux/aarch64.  */
    594      1.1  christos       elf_tdata (abfd)->core->pid = bfd_get_32 (abfd, note->descdata + 24);
    595      1.1  christos       elf_tdata (abfd)->core->program
    596      1.1  christos 	= _bfd_elfcore_strndup (abfd, note->descdata + 40, 16);
    597      1.1  christos       elf_tdata (abfd)->core->command
    598      1.1  christos 	= _bfd_elfcore_strndup (abfd, note->descdata + 56, 80);
    599      1.1  christos     }
    600      1.1  christos 
    601      1.1  christos   /* Note that for some reason, a spurious space is tacked
    602      1.1  christos      onto the end of the args in some (at least one anyway)
    603      1.1  christos      implementations, so strip it off if it exists.  */
    604      1.1  christos 
    605      1.1  christos   {
    606      1.1  christos     char *command = elf_tdata (abfd)->core->command;
    607      1.1  christos     int n = strlen (command);
    608      1.1  christos 
    609      1.1  christos     if (0 < n && command[n - 1] == ' ')
    610      1.1  christos       command[n - 1] = '\0';
    611      1.1  christos   }
    612      1.1  christos 
    613      1.1  christos   return TRUE;
    614      1.1  christos }
    615      1.1  christos 
    616      1.1  christos char *
    617      1.1  christos _bfd_aarch64_elf_write_core_note (bfd *abfd, char *buf, int *bufsiz, int note_type,
    618      1.1  christos 				  ...)
    619      1.1  christos {
    620      1.1  christos   switch (note_type)
    621      1.1  christos     {
    622      1.1  christos     default:
    623      1.1  christos       return NULL;
    624      1.1  christos 
    625      1.1  christos     case NT_PRPSINFO:
    626      1.1  christos       {
    627  1.1.1.3  christos 	char data[136];
    628  1.1.1.3  christos 	va_list ap;
    629      1.1  christos 
    630  1.1.1.3  christos 	va_start (ap, note_type);
    631  1.1.1.3  christos 	memset (data, 0, sizeof (data));
    632  1.1.1.3  christos 	strncpy (data + 40, va_arg (ap, const char *), 16);
    633  1.1.1.3  christos 	strncpy (data + 56, va_arg (ap, const char *), 80);
    634  1.1.1.3  christos 	va_end (ap);
    635      1.1  christos 
    636  1.1.1.3  christos 	return elfcore_write_note (abfd, buf, bufsiz, "CORE",
    637      1.1  christos 				   note_type, data, sizeof (data));
    638      1.1  christos       }
    639      1.1  christos 
    640      1.1  christos     case NT_PRSTATUS:
    641      1.1  christos       {
    642  1.1.1.3  christos 	char data[392];
    643  1.1.1.3  christos 	va_list ap;
    644  1.1.1.3  christos 	long pid;
    645  1.1.1.3  christos 	int cursig;
    646  1.1.1.3  christos 	const void *greg;
    647  1.1.1.3  christos 
    648  1.1.1.3  christos 	va_start (ap, note_type);
    649  1.1.1.3  christos 	memset (data, 0, sizeof (data));
    650  1.1.1.3  christos 	pid = va_arg (ap, long);
    651  1.1.1.3  christos 	bfd_put_32 (abfd, pid, data + 32);
    652  1.1.1.3  christos 	cursig = va_arg (ap, int);
    653  1.1.1.3  christos 	bfd_put_16 (abfd, cursig, data + 12);
    654  1.1.1.3  christos 	greg = va_arg (ap, const void *);
    655  1.1.1.3  christos 	memcpy (data + 112, greg, 272);
    656  1.1.1.3  christos 	va_end (ap);
    657      1.1  christos 
    658  1.1.1.3  christos 	return elfcore_write_note (abfd, buf, bufsiz, "CORE",
    659      1.1  christos 				   note_type, data, sizeof (data));
    660      1.1  christos       }
    661      1.1  christos     }
    662      1.1  christos }
    663