Home | History | Annotate | Line # | Download | only in bfd
      1      1.1  christos /* AArch-64 Mach-O support for BFD.
      2  1.1.1.6  christos    Copyright (C) 2015-2024 Free Software Foundation, Inc.
      3      1.1  christos 
      4      1.1  christos    This file is part of BFD, the Binary File Descriptor library.
      5      1.1  christos 
      6      1.1  christos    This program is free software; you can redistribute it and/or modify
      7      1.1  christos    it under the terms of the GNU General Public License as published by
      8      1.1  christos    the Free Software Foundation; either version 3 of the License, or
      9      1.1  christos    (at your option) any later version.
     10      1.1  christos 
     11      1.1  christos    This program is distributed in the hope that it will be useful,
     12      1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13      1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14      1.1  christos    GNU General Public License for more details.
     15      1.1  christos 
     16      1.1  christos    You should have received a copy of the GNU General Public License
     17      1.1  christos    along with this program; if not, write to the Free Software
     18      1.1  christos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     19      1.1  christos    MA 02110-1301, USA.  */
     20      1.1  christos 
     21      1.1  christos #include "sysdep.h"
     22      1.1  christos #include "bfd.h"
     23      1.1  christos #include "libbfd.h"
     24      1.1  christos #include "libiberty.h"
     25  1.1.1.3  christos #include "mach-o.h"
     26      1.1  christos #include "mach-o/arm64.h"
     27      1.1  christos 
     28      1.1  christos #define bfd_mach_o_object_p bfd_mach_o_arm64_object_p
     29      1.1  christos #define bfd_mach_o_core_p bfd_mach_o_arm64_core_p
     30      1.1  christos #define bfd_mach_o_mkobject bfd_mach_o_arm64_mkobject
     31      1.1  christos 
     32      1.1  christos #define bfd_mach_o_canonicalize_one_reloc \
     33      1.1  christos   bfd_mach_o_arm64_canonicalize_one_reloc
     34      1.1  christos #define bfd_mach_o_swap_reloc_out NULL
     35      1.1  christos 
     36      1.1  christos #define bfd_mach_o_bfd_reloc_type_lookup bfd_mach_o_arm64_bfd_reloc_type_lookup
     37      1.1  christos #define bfd_mach_o_bfd_reloc_name_lookup bfd_mach_o_arm64_bfd_reloc_name_lookup
     38      1.1  christos 
     39      1.1  christos #define bfd_mach_o_print_thread NULL
     40      1.1  christos #define bfd_mach_o_tgt_seg_table NULL
     41      1.1  christos #define bfd_mach_o_section_type_valid_for_tgt NULL
     42      1.1  christos 
     43  1.1.1.4  christos static bfd_cleanup
     44      1.1  christos bfd_mach_o_arm64_object_p (bfd *abfd)
     45      1.1  christos {
     46      1.1  christos   return bfd_mach_o_header_p (abfd, 0, 0, BFD_MACH_O_CPU_TYPE_ARM64);
     47      1.1  christos }
     48      1.1  christos 
     49  1.1.1.4  christos static bfd_cleanup
     50      1.1  christos bfd_mach_o_arm64_core_p (bfd *abfd)
     51      1.1  christos {
     52      1.1  christos   return bfd_mach_o_header_p (abfd, 0,
     53  1.1.1.3  christos 			      BFD_MACH_O_MH_CORE, BFD_MACH_O_CPU_TYPE_ARM64);
     54      1.1  christos }
     55      1.1  christos 
     56  1.1.1.5  christos static bool
     57      1.1  christos bfd_mach_o_arm64_mkobject (bfd *abfd)
     58      1.1  christos {
     59      1.1  christos   bfd_mach_o_data_struct *mdata;
     60      1.1  christos 
     61      1.1  christos   if (!bfd_mach_o_mkobject_init (abfd))
     62  1.1.1.5  christos     return false;
     63      1.1  christos 
     64      1.1  christos   mdata = bfd_mach_o_get_data (abfd);
     65      1.1  christos   mdata->header.magic = BFD_MACH_O_MH_MAGIC;
     66      1.1  christos   mdata->header.cputype = BFD_MACH_O_CPU_TYPE_ARM64;
     67      1.1  christos   mdata->header.cpusubtype = BFD_MACH_O_CPU_SUBTYPE_ARM64_ALL;
     68      1.1  christos   mdata->header.byteorder = BFD_ENDIAN_LITTLE;
     69      1.1  christos   mdata->header.version = 1;
     70      1.1  christos 
     71  1.1.1.5  christos   return true;
     72      1.1  christos }
     73      1.1  christos 
     74      1.1  christos /* In case we're on a 32-bit machine, construct a 64-bit "-1" value.  */
     75      1.1  christos #define MINUS_ONE (~ (bfd_vma) 0)
     76      1.1  christos 
     77      1.1  christos static reloc_howto_type arm64_howto_table[]=
     78      1.1  christos {
     79      1.1  christos   /* 0 */
     80  1.1.1.5  christos   HOWTO (BFD_RELOC_64, 0, 8, 64, false, 0,
     81      1.1  christos 	 complain_overflow_bitfield,
     82      1.1  christos 	 NULL, "64",
     83  1.1.1.5  christos 	 false, MINUS_ONE, MINUS_ONE, false),
     84  1.1.1.5  christos   HOWTO (BFD_RELOC_32, 0, 4, 32, false, 0,
     85      1.1  christos 	 complain_overflow_bitfield,
     86      1.1  christos 	 NULL, "32",
     87  1.1.1.5  christos 	 false, 0xffffffff, 0xffffffff, false),
     88  1.1.1.5  christos   HOWTO (BFD_RELOC_16, 0, 2, 16, false, 0,
     89      1.1  christos 	 complain_overflow_bitfield,
     90      1.1  christos 	 NULL, "16",
     91  1.1.1.5  christos 	 false, 0xffff, 0xffff, false),
     92  1.1.1.5  christos   HOWTO (BFD_RELOC_8, 0, 1, 8, false, 0,
     93      1.1  christos 	 complain_overflow_bitfield,
     94      1.1  christos 	 NULL, "8",
     95  1.1.1.5  christos 	 false, 0xff, 0xff, false),
     96      1.1  christos   /* 4 */
     97  1.1.1.5  christos   HOWTO (BFD_RELOC_64_PCREL, 0, 8, 64, true, 0,
     98      1.1  christos 	 complain_overflow_bitfield,
     99      1.1  christos 	 NULL, "DISP64",
    100  1.1.1.5  christos 	 false, MINUS_ONE, MINUS_ONE, true),
    101  1.1.1.5  christos   HOWTO (BFD_RELOC_32_PCREL, 0, 4, 32, true, 0,
    102      1.1  christos 	 complain_overflow_bitfield,
    103      1.1  christos 	 NULL, "DISP32",
    104  1.1.1.5  christos 	 false, 0xffffffff, 0xffffffff, true),
    105  1.1.1.5  christos   HOWTO (BFD_RELOC_16_PCREL, 0, 2, 16, true, 0,
    106      1.1  christos 	 complain_overflow_bitfield,
    107      1.1  christos 	 NULL, "DISP16",
    108  1.1.1.5  christos 	 false, 0xffff, 0xffff, true),
    109  1.1.1.5  christos   HOWTO (BFD_RELOC_AARCH64_CALL26, 0, 4, 26, true, 0,
    110      1.1  christos 	 complain_overflow_bitfield,
    111      1.1  christos 	 NULL, "BRANCH26",
    112  1.1.1.5  christos 	 false, 0x03ffffff, 0x03ffffff, true),
    113      1.1  christos   /* 8 */
    114  1.1.1.5  christos   HOWTO (BFD_RELOC_AARCH64_ADR_HI21_PCREL, 12, 4, 21, true, 0,
    115      1.1  christos 	 complain_overflow_signed,
    116      1.1  christos 	 NULL, "PAGE21",
    117  1.1.1.5  christos 	 false, 0x1fffff, 0x1fffff, true),
    118  1.1.1.5  christos   HOWTO (BFD_RELOC_AARCH64_LDST16_LO12, 1, 4, 12, true, 0,
    119      1.1  christos 	 complain_overflow_signed,
    120      1.1  christos 	 NULL, "PGOFF12",
    121  1.1.1.5  christos 	 false, 0xffe, 0xffe, true),
    122  1.1.1.5  christos   HOWTO (BFD_RELOC_MACH_O_ARM64_ADDEND, 0, 4, 32, false, 0,
    123      1.1  christos 	 complain_overflow_signed,
    124      1.1  christos 	 NULL, "ADDEND",
    125  1.1.1.5  christos 	 false, 0xffffffff, 0xffffffff, false),
    126  1.1.1.5  christos   HOWTO (BFD_RELOC_MACH_O_SUBTRACTOR32, 0, 4, 32, false, 0,
    127      1.1  christos 	 complain_overflow_bitfield,
    128      1.1  christos 	 NULL, "SUBTRACTOR32",
    129  1.1.1.5  christos 	 false, 0xffffffff, 0xffffffff, false),
    130      1.1  christos   /* 12 */
    131  1.1.1.5  christos   HOWTO (BFD_RELOC_MACH_O_SUBTRACTOR64, 0, 8, 64, false, 0,
    132      1.1  christos 	 complain_overflow_bitfield,
    133      1.1  christos 	 NULL, "SUBTRACTOR64",
    134  1.1.1.5  christos 	 false, MINUS_ONE, MINUS_ONE, false),
    135  1.1.1.5  christos   HOWTO (BFD_RELOC_MACH_O_ARM64_GOT_LOAD_PAGE21, 12, 4, 21, true, 0,
    136      1.1  christos 	 complain_overflow_signed,
    137      1.1  christos 	 NULL, "GOT_LD_PG21",
    138  1.1.1.5  christos 	 false, 0x1fffff, 0x1fffff, true),
    139  1.1.1.5  christos   HOWTO (BFD_RELOC_MACH_O_ARM64_GOT_LOAD_PAGEOFF12, 1, 4, 12, true, 0,
    140      1.1  christos 	 complain_overflow_signed,
    141      1.1  christos 	 NULL, "GOT_LD_PGOFF12",
    142  1.1.1.5  christos 	 false, 0xffe, 0xffe, true),
    143  1.1.1.5  christos   HOWTO (BFD_RELOC_MACH_O_ARM64_POINTER_TO_GOT, 0, 4, 32, true, 0,
    144      1.1  christos 	 complain_overflow_bitfield,
    145      1.1  christos 	 NULL, "PTR_TO_GOT",
    146  1.1.1.5  christos 	 false, 0xffffffff, 0xffffffff, true),
    147      1.1  christos };
    148      1.1  christos 
    149  1.1.1.5  christos static bool
    150  1.1.1.3  christos bfd_mach_o_arm64_canonicalize_one_reloc (bfd *       abfd,
    151  1.1.1.3  christos 					 struct mach_o_reloc_info_external * raw,
    152  1.1.1.3  christos 					 arelent *   res,
    153  1.1.1.3  christos 					 asymbol **  syms,
    154  1.1.1.3  christos 					 arelent *   res_base ATTRIBUTE_UNUSED)
    155      1.1  christos {
    156      1.1  christos   bfd_mach_o_reloc_info reloc;
    157      1.1  christos 
    158      1.1  christos   res->address = bfd_get_32 (abfd, raw->r_address);
    159      1.1  christos   if (res->address & BFD_MACH_O_SR_SCATTERED)
    160      1.1  christos     {
    161      1.1  christos       /* Only non-scattered relocations.  */
    162  1.1.1.5  christos       return false;
    163      1.1  christos     }
    164      1.1  christos 
    165      1.1  christos   /* The value and info fields have to be extracted dependent on target
    166      1.1  christos      endian-ness.  */
    167      1.1  christos   bfd_mach_o_swap_in_non_scattered_reloc (abfd, &reloc, raw->r_symbolnum);
    168      1.1  christos 
    169      1.1  christos   if (reloc.r_type == BFD_MACH_O_ARM64_RELOC_ADDEND)
    170      1.1  christos     {
    171      1.1  christos       if (reloc.r_length == 2 && reloc.r_pcrel == 0)
    172      1.1  christos 	{
    173  1.1.1.7  christos 	  res->sym_ptr_ptr = &bfd_abs_section_ptr->symbol;
    174      1.1  christos 	  res->addend = reloc.r_value;
    175      1.1  christos 	  res->howto = &arm64_howto_table[10];
    176  1.1.1.5  christos 	  return true;
    177      1.1  christos 	}
    178  1.1.1.5  christos       return false;
    179      1.1  christos     }
    180      1.1  christos 
    181      1.1  christos   if (!bfd_mach_o_canonicalize_non_scattered_reloc (abfd, &reloc, res, syms))
    182  1.1.1.5  christos     return false;
    183      1.1  christos 
    184      1.1  christos   switch (reloc.r_type)
    185      1.1  christos     {
    186      1.1  christos     case BFD_MACH_O_ARM64_RELOC_UNSIGNED:
    187      1.1  christos       switch ((reloc.r_length << 1) | reloc.r_pcrel)
    188      1.1  christos 	{
    189      1.1  christos 	case 0: /* len = 0, pcrel = 0  */
    190      1.1  christos 	  res->howto = &arm64_howto_table[3];
    191  1.1.1.5  christos 	  return true;
    192      1.1  christos 	case 2: /* len = 1, pcrel = 0  */
    193      1.1  christos 	  res->howto = &arm64_howto_table[2];
    194  1.1.1.5  christos 	  return true;
    195      1.1  christos 	case 3: /* len = 1, pcrel = 1  */
    196      1.1  christos 	  res->howto = &arm64_howto_table[6];
    197  1.1.1.5  christos 	  return true;
    198      1.1  christos 	case 4: /* len = 2, pcrel = 0  */
    199      1.1  christos 	  res->howto = &arm64_howto_table[1];
    200  1.1.1.5  christos 	  return true;
    201      1.1  christos 	case 5: /* len = 2, pcrel = 1  */
    202      1.1  christos 	  res->howto = &arm64_howto_table[5];
    203  1.1.1.5  christos 	  return true;
    204      1.1  christos 	case 6: /* len = 3, pcrel = 0  */
    205      1.1  christos 	  res->howto = &arm64_howto_table[0];
    206  1.1.1.5  christos 	  return true;
    207      1.1  christos 	case 7: /* len = 3, pcrel = 1  */
    208      1.1  christos 	  res->howto = &arm64_howto_table[4];
    209  1.1.1.5  christos 	  return true;
    210      1.1  christos 	default:
    211  1.1.1.5  christos 	  return false;
    212      1.1  christos 	}
    213      1.1  christos       break;
    214      1.1  christos     case BFD_MACH_O_ARM64_RELOC_SUBTRACTOR:
    215      1.1  christos       if (reloc.r_pcrel)
    216  1.1.1.5  christos 	return false;
    217      1.1  christos       switch (reloc.r_length)
    218  1.1.1.3  christos 	{
    219  1.1.1.3  christos 	case 2:
    220  1.1.1.3  christos 	  res->howto = &arm64_howto_table[11];
    221  1.1.1.5  christos 	  return true;
    222  1.1.1.3  christos 	case 3:
    223  1.1.1.3  christos 	  res->howto = &arm64_howto_table[12];
    224  1.1.1.5  christos 	  return true;
    225  1.1.1.3  christos 	default:
    226  1.1.1.5  christos 	  return false;
    227  1.1.1.3  christos 	}
    228      1.1  christos       break;
    229      1.1  christos     case BFD_MACH_O_ARM64_RELOC_BRANCH26:
    230      1.1  christos       if (reloc.r_length == 2 && reloc.r_pcrel == 1)
    231      1.1  christos 	{
    232      1.1  christos 	  res->howto = &arm64_howto_table[7];
    233  1.1.1.5  christos 	  return true;
    234      1.1  christos 	}
    235      1.1  christos       break;
    236      1.1  christos     case BFD_MACH_O_ARM64_RELOC_PAGE21:
    237      1.1  christos       if (reloc.r_length == 2 && reloc.r_pcrel == 1)
    238      1.1  christos 	{
    239      1.1  christos 	  res->howto = &arm64_howto_table[8];
    240  1.1.1.5  christos 	  return true;
    241      1.1  christos 	}
    242      1.1  christos       break;
    243      1.1  christos     case BFD_MACH_O_ARM64_RELOC_PAGEOFF12:
    244      1.1  christos       if (reloc.r_length == 2 && reloc.r_pcrel == 0)
    245      1.1  christos 	{
    246      1.1  christos 	  res->howto = &arm64_howto_table[9];
    247  1.1.1.5  christos 	  return true;
    248      1.1  christos 	}
    249      1.1  christos       break;
    250      1.1  christos     case BFD_MACH_O_ARM64_RELOC_GOT_LOAD_PAGE21:
    251      1.1  christos       if (reloc.r_length == 2 && reloc.r_pcrel == 1)
    252      1.1  christos 	{
    253      1.1  christos 	  res->howto = &arm64_howto_table[13];
    254  1.1.1.5  christos 	  return true;
    255      1.1  christos 	}
    256      1.1  christos       break;
    257      1.1  christos     case BFD_MACH_O_ARM64_RELOC_GOT_LOAD_PAGEOFF12:
    258      1.1  christos       if (reloc.r_length == 2 && reloc.r_pcrel == 0)
    259      1.1  christos 	{
    260      1.1  christos 	  res->howto = &arm64_howto_table[14];
    261  1.1.1.5  christos 	  return true;
    262      1.1  christos 	}
    263      1.1  christos       break;
    264      1.1  christos     case BFD_MACH_O_ARM64_RELOC_POINTER_TO_GOT:
    265      1.1  christos       if (reloc.r_length == 2 && reloc.r_pcrel == 1)
    266      1.1  christos 	{
    267      1.1  christos 	  res->howto = &arm64_howto_table[15];
    268  1.1.1.5  christos 	  return true;
    269      1.1  christos 	}
    270      1.1  christos       break;
    271      1.1  christos     default:
    272      1.1  christos       break;
    273      1.1  christos     }
    274  1.1.1.5  christos   return false;
    275      1.1  christos }
    276      1.1  christos 
    277      1.1  christos static reloc_howto_type *
    278      1.1  christos bfd_mach_o_arm64_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    279      1.1  christos 					bfd_reloc_code_real_type code)
    280      1.1  christos {
    281      1.1  christos   unsigned int i;
    282      1.1  christos 
    283      1.1  christos   for (i = 0;
    284      1.1  christos        i < sizeof (arm64_howto_table) / sizeof (*arm64_howto_table);
    285      1.1  christos        i++)
    286      1.1  christos     if (code == arm64_howto_table[i].type)
    287      1.1  christos       return &arm64_howto_table[i];
    288      1.1  christos   return NULL;
    289      1.1  christos }
    290      1.1  christos 
    291      1.1  christos static reloc_howto_type *
    292      1.1  christos bfd_mach_o_arm64_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    293      1.1  christos 				      const char *name ATTRIBUTE_UNUSED)
    294      1.1  christos {
    295      1.1  christos   return NULL;
    296      1.1  christos }
    297      1.1  christos 
    298  1.1.1.3  christos #define TARGET_NAME		aarch64_mach_o_vec
    299  1.1.1.3  christos #define TARGET_STRING		"mach-o-arm64"
    300      1.1  christos #define TARGET_ARCHITECTURE	bfd_arch_aarch64
    301      1.1  christos #define TARGET_PAGESIZE		4096
    302  1.1.1.3  christos #define TARGET_BIG_ENDIAN	0
    303  1.1.1.3  christos #define TARGET_ARCHIVE		0
    304      1.1  christos #define TARGET_PRIORITY		0
    305      1.1  christos #include "mach-o-target.c"
    306      1.1  christos 
    307      1.1  christos #undef TARGET_NAME
    308      1.1  christos #undef TARGET_STRING
    309      1.1  christos #undef TARGET_ARCHIVE
    310      1.1  christos #undef TARGET_PRIORITY
    311