(root)/
binutils-2.41/
bfd/
mach-o-x86-64.c
       1  /* Intel x86-64 Mach-O support for BFD.
       2     Copyright (C) 2010-2023 Free Software Foundation, Inc.
       3  
       4     This file is part of BFD, the Binary File Descriptor library.
       5  
       6     This program is free software; you can redistribute it and/or modify
       7     it under the terms of the GNU General Public License as published by
       8     the Free Software Foundation; either version 3 of the License, or
       9     (at your option) any later version.
      10  
      11     This program is distributed in the hope that it will be useful,
      12     but WITHOUT ANY WARRANTY; without even the implied warranty of
      13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14     GNU General Public License for more details.
      15  
      16     You should have received a copy of the GNU General Public License
      17     along with this program; if not, write to the Free Software
      18     Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
      19     MA 02110-1301, USA.  */
      20  
      21  #include "sysdep.h"
      22  #include "bfd.h"
      23  #include "libbfd.h"
      24  #include "libiberty.h"
      25  #include "mach-o.h"
      26  #include "mach-o/x86-64.h"
      27  
      28  #define bfd_mach_o_object_p bfd_mach_o_x86_64_object_p
      29  #define bfd_mach_o_core_p bfd_mach_o_x86_64_core_p
      30  #define bfd_mach_o_mkobject bfd_mach_o_x86_64_mkobject
      31  
      32  static bfd_cleanup
      33  bfd_mach_o_x86_64_object_p (bfd *abfd)
      34  {
      35    return bfd_mach_o_header_p (abfd, 0, 0, BFD_MACH_O_CPU_TYPE_X86_64);
      36  }
      37  
      38  static bfd_cleanup
      39  bfd_mach_o_x86_64_core_p (bfd *abfd)
      40  {
      41    return bfd_mach_o_header_p (abfd, 0,
      42  			      BFD_MACH_O_MH_CORE, BFD_MACH_O_CPU_TYPE_X86_64);
      43  }
      44  
      45  static bool
      46  bfd_mach_o_x86_64_mkobject (bfd *abfd)
      47  {
      48    bfd_mach_o_data_struct *mdata;
      49  
      50    if (!bfd_mach_o_mkobject_init (abfd))
      51      return false;
      52  
      53    mdata = bfd_mach_o_get_data (abfd);
      54    mdata->header.magic = BFD_MACH_O_MH_MAGIC_64;
      55    mdata->header.cputype = BFD_MACH_O_CPU_TYPE_X86_64;
      56    mdata->header.cpusubtype =
      57      BFD_MACH_O_CPU_SUBTYPE_X86_ALL | BFD_MACH_O_CPU_SUBTYPE_LIB64;
      58    mdata->header.byteorder = BFD_ENDIAN_LITTLE;
      59    mdata->header.version = 2;
      60  
      61    return true;
      62  }
      63  
      64  /* In case we're on a 32-bit machine, construct a 64-bit "-1" value.  */
      65  #define MINUS_ONE (~ (bfd_vma) 0)
      66  
      67  static reloc_howto_type x86_64_howto_table[]=
      68  {
      69    /* 0 */
      70    HOWTO(BFD_RELOC_64, 0, 8, 64, false, 0,
      71  	complain_overflow_bitfield,
      72  	NULL, "64",
      73  	false, MINUS_ONE, MINUS_ONE, false),
      74    HOWTO(BFD_RELOC_32, 0, 4, 32, false, 0,
      75  	complain_overflow_bitfield,
      76  	NULL, "32",
      77  	false, 0xffffffff, 0xffffffff, false),
      78    HOWTO(BFD_RELOC_32_PCREL, 0, 4, 32, true, 0,
      79  	complain_overflow_bitfield,
      80  	NULL, "DISP32",
      81  	false, 0xffffffff, 0xffffffff, true),
      82    HOWTO(BFD_RELOC_MACH_O_X86_64_PCREL32_1, 0, 4, 32, true, 0,
      83  	complain_overflow_bitfield,
      84  	NULL, "DISP32_1",
      85  	false, 0xffffffff, 0xffffffff, true),
      86    /* 4 */
      87    HOWTO(BFD_RELOC_MACH_O_X86_64_PCREL32_2, 0, 4, 32, true, 0,
      88  	complain_overflow_bitfield,
      89  	NULL, "DISP32_2",
      90  	false, 0xffffffff, 0xffffffff, true),
      91    HOWTO(BFD_RELOC_MACH_O_X86_64_PCREL32_4, 0, 4, 32, true, 0,
      92  	complain_overflow_bitfield,
      93  	NULL, "DISP32_4",
      94  	false, 0xffffffff, 0xffffffff, true),
      95    HOWTO(BFD_RELOC_MACH_O_X86_64_BRANCH32, 0, 4, 32, true, 0,
      96  	complain_overflow_bitfield,
      97  	NULL, "BRANCH32",
      98  	false, 0xffffffff, 0xffffffff, true),
      99    HOWTO(BFD_RELOC_MACH_O_X86_64_GOT_LOAD, 0, 4, 32, true, 0,
     100  	complain_overflow_bitfield,
     101  	NULL, "GOT_LOAD",
     102  	false, 0xffffffff, 0xffffffff, true),
     103    /* 8 */
     104    HOWTO(BFD_RELOC_MACH_O_SUBTRACTOR32, 0, 4, 32, false, 0,
     105  	complain_overflow_bitfield,
     106  	NULL, "SUBTRACTOR32",
     107  	false, 0xffffffff, 0xffffffff, false),
     108    HOWTO(BFD_RELOC_MACH_O_SUBTRACTOR64, 0, 8, 64, false, 0,
     109  	complain_overflow_bitfield,
     110  	NULL, "SUBTRACTOR64",
     111  	false, MINUS_ONE, MINUS_ONE, false),
     112    HOWTO(BFD_RELOC_MACH_O_X86_64_GOT, 0, 4, 32, true, 0,
     113  	complain_overflow_bitfield,
     114  	NULL, "GOT",
     115  	false, 0xffffffff, 0xffffffff, true),
     116    HOWTO(BFD_RELOC_MACH_O_X86_64_BRANCH8, 0, 1, 8, true, 0,
     117  	complain_overflow_bitfield,
     118  	NULL, "BRANCH8",
     119  	false, 0xff, 0xff, true),
     120    /* 12 */
     121    HOWTO(BFD_RELOC_MACH_O_X86_64_TLV, 0, 4, 32, true, 0,
     122  	complain_overflow_bitfield,
     123  	NULL, "TLV",
     124  	false, 0xffffffff, 0xffffffff, true),
     125  };
     126  
     127  static bool
     128  bfd_mach_o_x86_64_canonicalize_one_reloc (bfd *       abfd,
     129  					  struct mach_o_reloc_info_external * raw,
     130  					  arelent *   res,
     131  					  asymbol **  syms,
     132  					  arelent *   res_base ATTRIBUTE_UNUSED)
     133  {
     134    bfd_mach_o_reloc_info reloc;
     135  
     136    if (!bfd_mach_o_pre_canonicalize_one_reloc (abfd, raw, &reloc, res, syms))
     137      return false;
     138  
     139    /* On x86-64, scattered relocs are not used.  */
     140    if (reloc.r_scattered)
     141      return false;
     142  
     143    switch (reloc.r_type)
     144      {
     145      case BFD_MACH_O_X86_64_RELOC_UNSIGNED:
     146        if (reloc.r_pcrel)
     147  	return false;
     148        switch (reloc.r_length)
     149  	{
     150  	case 2:
     151  	  res->howto = &x86_64_howto_table[1];
     152  	  return true;
     153  	case 3:
     154  	  res->howto = &x86_64_howto_table[0];
     155  	  return true;
     156  	default:
     157  	  return false;
     158  	}
     159      case BFD_MACH_O_X86_64_RELOC_SIGNED:
     160        if (reloc.r_length == 2 && reloc.r_pcrel)
     161  	{
     162  	  res->howto = &x86_64_howto_table[2];
     163  	  return true;
     164  	}
     165        break;
     166      case BFD_MACH_O_X86_64_RELOC_BRANCH:
     167        if (!reloc.r_pcrel)
     168  	return false;
     169        switch (reloc.r_length)
     170  	{
     171  	case 2:
     172  	  res->howto = &x86_64_howto_table[6];
     173  	  return true;
     174  	default:
     175  	  return false;
     176  	}
     177        break;
     178      case BFD_MACH_O_X86_64_RELOC_GOT_LOAD:
     179        if (reloc.r_length == 2 && reloc.r_pcrel && reloc.r_extern)
     180  	{
     181  	  res->howto = &x86_64_howto_table[7];
     182  	  return true;
     183  	}
     184        break;
     185      case BFD_MACH_O_X86_64_RELOC_GOT:
     186        if (reloc.r_length == 2 && reloc.r_pcrel && reloc.r_extern)
     187  	{
     188  	  res->howto = &x86_64_howto_table[10];
     189  	  return true;
     190  	}
     191        break;
     192      case BFD_MACH_O_X86_64_RELOC_SUBTRACTOR:
     193        if (reloc.r_pcrel)
     194  	return false;
     195        switch (reloc.r_length)
     196  	{
     197  	case 2:
     198  	  res->howto = &x86_64_howto_table[8];
     199  	  return true;
     200  	case 3:
     201  	  res->howto = &x86_64_howto_table[9];
     202  	  return true;
     203  	default:
     204  	  return false;
     205  	}
     206        break;
     207      case BFD_MACH_O_X86_64_RELOC_SIGNED_1:
     208        if (reloc.r_length == 2 && reloc.r_pcrel)
     209  	{
     210  	  res->howto = &x86_64_howto_table[3];
     211  	  return true;
     212  	}
     213        break;
     214      case BFD_MACH_O_X86_64_RELOC_SIGNED_2:
     215        if (reloc.r_length == 2 && reloc.r_pcrel)
     216  	{
     217  	  res->howto = &x86_64_howto_table[4];
     218  	  return true;
     219  	}
     220        break;
     221      case BFD_MACH_O_X86_64_RELOC_SIGNED_4:
     222        if (reloc.r_length == 2 && reloc.r_pcrel)
     223  	{
     224  	  res->howto = &x86_64_howto_table[5];
     225  	  return true;
     226  	}
     227        break;
     228      case BFD_MACH_O_X86_64_RELOC_TLV:
     229        if (reloc.r_length == 2 && reloc.r_pcrel && reloc.r_extern)
     230  	{
     231  	  res->howto = &x86_64_howto_table[12];
     232  	  return true;
     233  	}
     234        break;
     235      default:
     236        return false;
     237      }
     238    return false;
     239  }
     240  
     241  static bool
     242  bfd_mach_o_x86_64_swap_reloc_out (arelent *rel, bfd_mach_o_reloc_info *rinfo)
     243  {
     244    rinfo->r_address = rel->address;
     245    rinfo->r_scattered = 0;
     246    switch (rel->howto->type)
     247      {
     248      case BFD_RELOC_32:
     249        rinfo->r_type = BFD_MACH_O_X86_64_RELOC_UNSIGNED;
     250        rinfo->r_pcrel = 0;
     251        rinfo->r_length = 2;
     252        break;
     253      case BFD_RELOC_64:
     254        rinfo->r_type = BFD_MACH_O_X86_64_RELOC_UNSIGNED;
     255        rinfo->r_pcrel = 0;
     256        rinfo->r_length = 3;
     257        break;
     258      case BFD_RELOC_32_PCREL:
     259        rinfo->r_type = BFD_MACH_O_X86_64_RELOC_SIGNED;
     260        rinfo->r_pcrel = 1;
     261        rinfo->r_length = 2;
     262        break;
     263      case BFD_RELOC_MACH_O_X86_64_PCREL32_1:
     264        rinfo->r_type = BFD_MACH_O_X86_64_RELOC_SIGNED_1;
     265        rinfo->r_pcrel = 1;
     266        rinfo->r_length = 2;
     267        break;
     268      case BFD_RELOC_MACH_O_X86_64_PCREL32_2:
     269        rinfo->r_type = BFD_MACH_O_X86_64_RELOC_SIGNED_2;
     270        rinfo->r_pcrel = 1;
     271        rinfo->r_length = 2;
     272        break;
     273      case BFD_RELOC_MACH_O_X86_64_PCREL32_4:
     274        rinfo->r_type = BFD_MACH_O_X86_64_RELOC_SIGNED_4;
     275        rinfo->r_pcrel = 1;
     276        rinfo->r_length = 2;
     277        break;
     278      case BFD_RELOC_MACH_O_X86_64_BRANCH32:
     279        rinfo->r_type = BFD_MACH_O_X86_64_RELOC_BRANCH;
     280        rinfo->r_pcrel = 1;
     281        rinfo->r_length = 2;
     282        break;
     283      case BFD_RELOC_MACH_O_SUBTRACTOR32:
     284        rinfo->r_type = BFD_MACH_O_X86_64_RELOC_SUBTRACTOR;
     285        rinfo->r_pcrel = 0;
     286        rinfo->r_length = 2;
     287        break;
     288      case BFD_RELOC_MACH_O_SUBTRACTOR64:
     289        rinfo->r_type = BFD_MACH_O_X86_64_RELOC_SUBTRACTOR;
     290        rinfo->r_pcrel = 0;
     291        rinfo->r_length = 3;
     292        break;
     293      case BFD_RELOC_MACH_O_X86_64_GOT:
     294        rinfo->r_type = BFD_MACH_O_X86_64_RELOC_GOT;
     295        rinfo->r_pcrel = 1;
     296        rinfo->r_length = 2;
     297        break;
     298      case BFD_RELOC_MACH_O_X86_64_GOT_LOAD:
     299        rinfo->r_type = BFD_MACH_O_X86_64_RELOC_GOT_LOAD;
     300        rinfo->r_pcrel = 1;
     301        rinfo->r_length = 2;
     302        break;
     303      case BFD_RELOC_MACH_O_X86_64_TLV:
     304        rinfo->r_type = BFD_MACH_O_X86_64_RELOC_TLV;
     305        rinfo->r_pcrel = 1;
     306        rinfo->r_length = 2;
     307        break;
     308      default:
     309        return false;
     310      }
     311    if ((*rel->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
     312      {
     313        rinfo->r_extern = 0;
     314        rinfo->r_value =
     315  	(*rel->sym_ptr_ptr)->section->output_section->target_index;
     316      }
     317    else
     318      {
     319        rinfo->r_extern = 1;
     320        rinfo->r_value = (*rel->sym_ptr_ptr)->udata.i;
     321      }
     322    return true;
     323  }
     324  
     325  static reloc_howto_type *
     326  bfd_mach_o_x86_64_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
     327  					 bfd_reloc_code_real_type code)
     328  {
     329    unsigned int i;
     330  
     331    for (i = 0;
     332         i < sizeof (x86_64_howto_table) / sizeof (*x86_64_howto_table);
     333         i++)
     334      if (code == x86_64_howto_table[i].type)
     335        return &x86_64_howto_table[i];
     336    return NULL;
     337  }
     338  
     339  static reloc_howto_type *
     340  bfd_mach_o_x86_64_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
     341  					 const char *name ATTRIBUTE_UNUSED)
     342  {
     343    return NULL;
     344  }
     345  
     346  static bool
     347  bfd_mach_o_section_type_valid_for_x86_64 (unsigned long val)
     348  {
     349    if (val == BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS
     350        || val == BFD_MACH_O_S_LAZY_SYMBOL_POINTERS
     351        || val == BFD_MACH_O_S_SYMBOL_STUBS)
     352      return false;
     353    return true;
     354  }
     355  
     356  /* We want to bump the alignment of some sections.  */
     357  static const mach_o_section_name_xlat text_section_names_xlat[] =
     358    {
     359      {	".eh_frame",				"__eh_frame",
     360  	SEC_READONLY | SEC_DATA | SEC_LOAD,	BFD_MACH_O_S_COALESCED,
     361  	BFD_MACH_O_S_ATTR_LIVE_SUPPORT
     362  	| BFD_MACH_O_S_ATTR_STRIP_STATIC_SYMS
     363  	| BFD_MACH_O_S_ATTR_NO_TOC,		3},
     364      { NULL, NULL, 0, 0, 0, 0}
     365    };
     366  
     367  const mach_o_segment_name_xlat mach_o_x86_64_segsec_names_xlat[] =
     368    {
     369      { "__TEXT", text_section_names_xlat },
     370      { NULL, NULL }
     371    };
     372  
     373  #define bfd_mach_o_canonicalize_one_reloc bfd_mach_o_x86_64_canonicalize_one_reloc
     374  #define bfd_mach_o_swap_reloc_out bfd_mach_o_x86_64_swap_reloc_out
     375  
     376  #define bfd_mach_o_bfd_reloc_type_lookup bfd_mach_o_x86_64_bfd_reloc_type_lookup
     377  #define bfd_mach_o_bfd_reloc_name_lookup bfd_mach_o_x86_64_bfd_reloc_name_lookup
     378  #define bfd_mach_o_print_thread NULL
     379  #define bfd_mach_o_tgt_seg_table mach_o_x86_64_segsec_names_xlat
     380  #define bfd_mach_o_section_type_valid_for_tgt bfd_mach_o_section_type_valid_for_x86_64
     381  
     382  #define TARGET_NAME		x86_64_mach_o_vec
     383  #define TARGET_STRING		"mach-o-x86-64"
     384  #define TARGET_ARCHITECTURE	bfd_arch_i386
     385  #define TARGET_PAGESIZE		4096
     386  #define TARGET_BIG_ENDIAN	0
     387  #define TARGET_ARCHIVE		0
     388  #define TARGET_PRIORITY		0
     389  #include "mach-o-target.c"