(root)/
binutils-2.41/
bfd/
mach-o-i386.c
       1  /* Intel i386 Mach-O support for BFD.
       2     Copyright (C) 2009-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/reloc.h"
      27  
      28  #define bfd_mach_o_object_p bfd_mach_o_i386_object_p
      29  #define bfd_mach_o_core_p bfd_mach_o_i386_core_p
      30  #define bfd_mach_o_mkobject bfd_mach_o_i386_mkobject
      31  
      32  static bfd_cleanup
      33  bfd_mach_o_i386_object_p (bfd *abfd)
      34  {
      35    return bfd_mach_o_header_p (abfd, 0, 0, BFD_MACH_O_CPU_TYPE_I386);
      36  }
      37  
      38  static bfd_cleanup
      39  bfd_mach_o_i386_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_I386);
      43  }
      44  
      45  static bool
      46  bfd_mach_o_i386_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;
      55    mdata->header.cputype = BFD_MACH_O_CPU_TYPE_I386;
      56    mdata->header.cpusubtype = BFD_MACH_O_CPU_SUBTYPE_X86_ALL;
      57    mdata->header.byteorder = BFD_ENDIAN_LITTLE;
      58    mdata->header.version = 1;
      59  
      60    return true;
      61  }
      62  
      63  static reloc_howto_type i386_howto_table[]=
      64  {
      65    /* 0 */
      66    HOWTO(BFD_RELOC_32, 0, 4, 32, false, 0,
      67  	complain_overflow_bitfield,
      68  	NULL, "32",
      69  	false, 0xffffffff, 0xffffffff, false),
      70    HOWTO(BFD_RELOC_16, 0, 2, 16, false, 0,
      71  	complain_overflow_bitfield,
      72  	NULL, "16",
      73  	false, 0xffff, 0xffff, false),
      74    HOWTO(BFD_RELOC_8, 0, 1, 8, false, 0,
      75  	complain_overflow_bitfield,
      76  	NULL, "8",
      77  	false, 0xff, 0xff, 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    /* 4 */
      83    HOWTO(BFD_RELOC_16_PCREL, 0, 2, 16, true, 0,
      84  	complain_overflow_bitfield,
      85  	NULL, "DISP16",
      86  	false, 0xffff, 0xffff, true),
      87    HOWTO(BFD_RELOC_MACH_O_SECTDIFF, 0, 4, 32, false, 0,
      88  	complain_overflow_bitfield,
      89  	NULL, "SECTDIFF_32",
      90  	false, 0xffffffff, 0xffffffff, false),
      91    HOWTO(BFD_RELOC_MACH_O_LOCAL_SECTDIFF, 0, 4, 32, false, 0,
      92  	complain_overflow_bitfield,
      93  	NULL, "LSECTDIFF_32",
      94  	false, 0xffffffff, 0xffffffff, false),
      95    HOWTO(BFD_RELOC_MACH_O_PAIR, 0, 4, 32, false, 0,
      96  	complain_overflow_bitfield,
      97  	NULL, "PAIR_32",
      98  	false, 0xffffffff, 0xffffffff, false),
      99    /* 8 */
     100    HOWTO(BFD_RELOC_MACH_O_SECTDIFF, 0, 2, 16, false, 0,
     101  	complain_overflow_bitfield,
     102  	NULL, "SECTDIFF_16",
     103  	false, 0xffff, 0xffff, false),
     104    HOWTO(BFD_RELOC_MACH_O_LOCAL_SECTDIFF, 0, 2, 16, false, 0,
     105  	complain_overflow_bitfield,
     106  	NULL, "LSECTDIFF_16",
     107  	false, 0xffff, 0xffff, false),
     108    HOWTO(BFD_RELOC_MACH_O_PAIR, 0, 2, 16, false, 0,
     109  	complain_overflow_bitfield,
     110  	NULL, "PAIR_16",
     111  	false, 0xffff, 0xffff, false),
     112  };
     113  
     114  static bool
     115  bfd_mach_o_i386_canonicalize_one_reloc (bfd *       abfd,
     116  					struct mach_o_reloc_info_external * raw,
     117  					arelent *   res,
     118  					asymbol **  syms,
     119  					arelent *   res_base)
     120  {
     121    bfd_mach_o_reloc_info reloc;
     122  
     123    if (!bfd_mach_o_pre_canonicalize_one_reloc (abfd, raw, &reloc, res, syms))
     124      return false;
     125  
     126    if (reloc.r_scattered)
     127      {
     128        switch (reloc.r_type)
     129  	{
     130  	case BFD_MACH_O_GENERIC_RELOC_PAIR:
     131  	  /* PR 21813: Check for a corrupt PAIR reloc at the start.  */
     132  	  if (res == res_base)
     133  	    return false;
     134  	  if (reloc.r_length == 2)
     135  	    {
     136  	      res->howto = &i386_howto_table[7];
     137  	      res->address = res[-1].address;
     138  	      return true;
     139  	    }
     140  	  else if (reloc.r_length == 1)
     141  	    {
     142  	      res->howto = &i386_howto_table[10];
     143  	      res->address = res[-1].address;
     144  	      return true;
     145  	    }
     146  	  return false;
     147  	case BFD_MACH_O_GENERIC_RELOC_SECTDIFF:
     148  	  if (reloc.r_length == 2)
     149  	    {
     150  	      res->howto = &i386_howto_table[5];
     151  	      return true;
     152  	    }
     153  	  else if (reloc.r_length == 1)
     154  	    {
     155  	      res->howto = &i386_howto_table[8];
     156  	      return true;
     157  	    }
     158  	  return false;
     159  	case BFD_MACH_O_GENERIC_RELOC_LOCAL_SECTDIFF:
     160  	  if (reloc.r_length == 2)
     161  	    {
     162  	      res->howto = &i386_howto_table[6];
     163  	      return true;
     164  	    }
     165  	  else if (reloc.r_length == 1)
     166  	    {
     167  	      res->howto = &i386_howto_table[9];
     168  	      return true;
     169  	    }
     170  	  return false;
     171  	default:
     172  	  break;
     173  	}
     174      }
     175    else
     176      {
     177        switch (reloc.r_type)
     178  	{
     179  	case BFD_MACH_O_GENERIC_RELOC_VANILLA:
     180  	  switch ((reloc.r_length << 1) | reloc.r_pcrel)
     181  	    {
     182  	    case 0: /* len = 0, pcrel = 0  */
     183  	      res->howto = &i386_howto_table[2];
     184  	      return true;
     185  	    case 2: /* len = 1, pcrel = 0  */
     186  	      res->howto = &i386_howto_table[1];
     187  	      return true;
     188  	    case 3: /* len = 1, pcrel = 1  */
     189  	      res->howto = &i386_howto_table[4];
     190  	      return true;
     191  	    case 4: /* len = 2, pcrel = 0  */
     192  	      res->howto = &i386_howto_table[0];
     193  	      return true;
     194  	    case 5: /* len = 2, pcrel = 1  */
     195  	      res->howto = &i386_howto_table[3];
     196  	      return true;
     197  	    default:
     198  	      return false;
     199  	    }
     200  	default:
     201  	  break;
     202  	}
     203      }
     204    return false;
     205  }
     206  
     207  static bool
     208  bfd_mach_o_i386_swap_reloc_out (arelent *rel, bfd_mach_o_reloc_info *rinfo)
     209  {
     210    rinfo->r_address = rel->address;
     211    switch (rel->howto->type)
     212      {
     213      case BFD_RELOC_32:
     214      case BFD_RELOC_32_PCREL:
     215      case BFD_RELOC_16:
     216      case BFD_RELOC_16_PCREL:
     217      case BFD_RELOC_8:
     218        rinfo->r_scattered = 0;
     219        rinfo->r_type = BFD_MACH_O_GENERIC_RELOC_VANILLA;
     220        rinfo->r_pcrel = rel->howto->pc_relative;
     221        rinfo->r_length = bfd_log2 (bfd_get_reloc_size (rel->howto));
     222        if ((*rel->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
     223  	{
     224  	  rinfo->r_extern = 0;
     225  	  rinfo->r_value =
     226  	    (*rel->sym_ptr_ptr)->section->output_section->target_index;
     227  	}
     228        else
     229  	{
     230  	  rinfo->r_extern = 1;
     231  	  rinfo->r_value = (*rel->sym_ptr_ptr)->udata.i;
     232  	}
     233        break;
     234      case BFD_RELOC_MACH_O_SECTDIFF:
     235        rinfo->r_scattered = 1;
     236        rinfo->r_type = BFD_MACH_O_GENERIC_RELOC_SECTDIFF;
     237        rinfo->r_pcrel = 0;
     238        rinfo->r_length = bfd_log2 (bfd_get_reloc_size (rel->howto));
     239        rinfo->r_extern = 0;
     240        rinfo->r_value = rel->addend;
     241        break;
     242      case BFD_RELOC_MACH_O_LOCAL_SECTDIFF:
     243        rinfo->r_scattered = 1;
     244        rinfo->r_type = BFD_MACH_O_GENERIC_RELOC_LOCAL_SECTDIFF;
     245        rinfo->r_pcrel = 0;
     246        rinfo->r_length = bfd_log2 (bfd_get_reloc_size (rel->howto));
     247        rinfo->r_extern = 0;
     248        rinfo->r_value = rel->addend;
     249        break;
     250      case BFD_RELOC_MACH_O_PAIR:
     251        rinfo->r_address = 0;
     252        rinfo->r_scattered = 1;
     253        rinfo->r_type = BFD_MACH_O_GENERIC_RELOC_PAIR;
     254        rinfo->r_pcrel = 0;
     255        rinfo->r_length = bfd_log2 (bfd_get_reloc_size (rel->howto));
     256        rinfo->r_extern = 0;
     257        rinfo->r_value = rel->addend;
     258        break;
     259      default:
     260        return false;
     261      }
     262    return true;
     263  }
     264  
     265  static reloc_howto_type *
     266  bfd_mach_o_i386_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
     267  				       bfd_reloc_code_real_type code)
     268  {
     269    unsigned int i;
     270  
     271    for (i = 0; i < sizeof (i386_howto_table) / sizeof (*i386_howto_table); i++)
     272      if (code == i386_howto_table[i].type)
     273        return &i386_howto_table[i];
     274    return NULL;
     275  }
     276  
     277  static reloc_howto_type *
     278  bfd_mach_o_i386_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
     279  				       const char *name ATTRIBUTE_UNUSED)
     280  {
     281    return NULL;
     282  }
     283  
     284  static bool
     285  bfd_mach_o_i386_print_thread (bfd *abfd, bfd_mach_o_thread_flavour *thread,
     286  			      void *vfile, char *buf)
     287  {
     288    FILE *file = (FILE *)vfile;
     289  
     290    switch (thread->flavour)
     291      {
     292      case BFD_MACH_O_x86_THREAD_STATE:
     293        if (thread->size < (8 + 16 * 4))
     294  	return false;
     295        fprintf (file, "   x86_THREAD_STATE:\n");
     296        fprintf (file, "    flavor: 0x%08lx  count: 0x%08lx\n",
     297  	       (unsigned long)bfd_get_32 (abfd, buf + 0),
     298  	       (unsigned long)bfd_get_32 (abfd, buf + 4));
     299        fprintf (file, "     eax: %08lx  ebx: %08lx  ecx: %08lx  edx: %08lx\n",
     300  	       (unsigned long)bfd_get_32 (abfd, buf + 8),
     301  	       (unsigned long)bfd_get_32 (abfd, buf + 12),
     302  	       (unsigned long)bfd_get_32 (abfd, buf + 16),
     303  	       (unsigned long)bfd_get_32 (abfd, buf + 20));
     304        fprintf (file, "     edi: %08lx  esi: %08lx  ebp: %08lx  esp: %08lx\n",
     305  	       (unsigned long)bfd_get_32 (abfd, buf + 24),
     306  	       (unsigned long)bfd_get_32 (abfd, buf + 28),
     307  	       (unsigned long)bfd_get_32 (abfd, buf + 32),
     308  	       (unsigned long)bfd_get_32 (abfd, buf + 36));
     309        fprintf (file, "      ss: %08lx  flg: %08lx  eip: %08lx   cs: %08lx\n",
     310  	       (unsigned long)bfd_get_32 (abfd, buf + 40),
     311  	       (unsigned long)bfd_get_32 (abfd, buf + 44),
     312  	       (unsigned long)bfd_get_32 (abfd, buf + 48),
     313  	       (unsigned long)bfd_get_32 (abfd, buf + 52));
     314        fprintf (file, "      ds: %08lx   es: %08lx   fs: %08lx   gs: %08lx\n",
     315  	       (unsigned long)bfd_get_32 (abfd, buf + 56),
     316  	       (unsigned long)bfd_get_32 (abfd, buf + 60),
     317  	       (unsigned long)bfd_get_32 (abfd, buf + 64),
     318  	       (unsigned long)bfd_get_32 (abfd, buf + 68));
     319        return true;
     320      case BFD_MACH_O_x86_FLOAT_STATE:
     321        if (thread->size < 8)
     322  	return false;
     323        fprintf (file, "   x86_FLOAT_STATE:\n");
     324        fprintf (file, "    flavor: 0x%08lx  count: 0x%08lx\n",
     325  	       (unsigned long)bfd_get_32 (abfd, buf + 0),
     326  	       (unsigned long)bfd_get_32 (abfd, buf + 4));
     327        return true;
     328      case BFD_MACH_O_x86_EXCEPTION_STATE:
     329        if (thread->size < 8 + 3 * 4)
     330  	return false;
     331        fprintf (file, "   x86_EXCEPTION_STATE:\n");
     332        fprintf (file, "    flavor: 0x%08lx  count: 0x%08lx\n",
     333  	       (unsigned long)bfd_get_32 (abfd, buf + 0),
     334  	       (unsigned long)bfd_get_32 (abfd, buf + 4));
     335        fprintf (file, "    trapno: %08lx  err: %08lx  faultaddr: %08lx\n",
     336  	       (unsigned long)bfd_get_32 (abfd, buf + 8),
     337  	       (unsigned long)bfd_get_32 (abfd, buf + 12),
     338  	       (unsigned long)bfd_get_32 (abfd, buf + 16));
     339        return true;
     340      default:
     341        break;
     342      }
     343    return false;
     344  }
     345  
     346  static const mach_o_section_name_xlat text_section_names_xlat[] =
     347    {
     348      {	".symbol_stub",			"__symbol_stub",
     349  	SEC_CODE | SEC_LOAD,		BFD_MACH_O_S_SYMBOL_STUBS,
     350  	BFD_MACH_O_S_ATTR_PURE_INSTRUCTIONS,
     351  					0},
     352      {	".picsymbol_stub",		"__picsymbol_stub",
     353  	SEC_CODE | SEC_LOAD,		BFD_MACH_O_S_SYMBOL_STUBS,
     354  	BFD_MACH_O_S_ATTR_PURE_INSTRUCTIONS,
     355  					0},
     356      { NULL, NULL, 0, 0, 0, 0}
     357    };
     358  
     359  static const mach_o_section_name_xlat data_section_names_xlat[] =
     360    {
     361      /* The first two are recognized by i386, but not emitted for x86 by
     362         modern GCC.  */
     363      {	".non_lazy_symbol_pointer",	"__nl_symbol_ptr",
     364  	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS,
     365  	BFD_MACH_O_S_ATTR_NONE,		2},
     366      {	".lazy_symbol_pointer",		"__la_symbol_ptr",
     367  	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_LAZY_SYMBOL_POINTERS,
     368  	BFD_MACH_O_S_ATTR_NONE,		2},
     369      {	".lazy_symbol_pointer2",	"__la_sym_ptr2",
     370  	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_LAZY_SYMBOL_POINTERS,
     371  	BFD_MACH_O_S_ATTR_NONE,		2},
     372      {	".lazy_symbol_pointer3",	"__la_sym_ptr3",
     373  	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_LAZY_SYMBOL_POINTERS,
     374  	BFD_MACH_O_S_ATTR_NONE,		2},
     375      { NULL, NULL, 0, 0, 0, 0}
     376    };
     377  
     378  static const mach_o_section_name_xlat import_section_names_xlat[] =
     379    {
     380      {	".picsymbol_stub3",		"__jump_table",
     381  	SEC_CODE | SEC_LOAD,		BFD_MACH_O_S_SYMBOL_STUBS,
     382  	BFD_MACH_O_S_ATTR_PURE_INSTRUCTIONS
     383  	| BFD_MACH_O_S_SELF_MODIFYING_CODE,
     384  					6},
     385      {	".non_lazy_symbol_pointer_x86",	"__pointers",
     386  	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS,
     387  	BFD_MACH_O_S_ATTR_NONE,		2},
     388      { NULL, NULL, 0, 0, 0, 0}
     389    };
     390  
     391  const mach_o_segment_name_xlat mach_o_i386_segsec_names_xlat[] =
     392    {
     393      { "__TEXT", text_section_names_xlat },
     394      { "__DATA", data_section_names_xlat },
     395      { "__IMPORT", import_section_names_xlat },
     396      { NULL, NULL }
     397    };
     398  
     399  #define bfd_mach_o_canonicalize_one_reloc  bfd_mach_o_i386_canonicalize_one_reloc
     400  #define bfd_mach_o_swap_reloc_out	   bfd_mach_o_i386_swap_reloc_out
     401  #define bfd_mach_o_print_thread		   bfd_mach_o_i386_print_thread
     402  
     403  #define bfd_mach_o_tgt_seg_table mach_o_i386_segsec_names_xlat
     404  #define bfd_mach_o_section_type_valid_for_tgt NULL
     405  
     406  #define bfd_mach_o_bfd_reloc_type_lookup bfd_mach_o_i386_bfd_reloc_type_lookup
     407  #define bfd_mach_o_bfd_reloc_name_lookup bfd_mach_o_i386_bfd_reloc_name_lookup
     408  
     409  #define TARGET_NAME		i386_mach_o_vec
     410  #define TARGET_STRING		"mach-o-i386"
     411  #define TARGET_ARCHITECTURE	bfd_arch_i386
     412  #define TARGET_PAGESIZE		4096
     413  #define TARGET_BIG_ENDIAN	0
     414  #define TARGET_ARCHIVE		0
     415  #define TARGET_PRIORITY		0
     416  #include "mach-o-target.c"