Home | History | Annotate | Line # | Download | only in bfd
mach-o-x86-64.c revision 1.1
      1  1.1  christos /* Intel x86-64 Mach-O support for BFD.
      2  1.1  christos    Copyright 2010
      3  1.1  christos    Free Software Foundation, Inc.
      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; if not, write to the Free Software
     19  1.1  christos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     20  1.1  christos    MA 02110-1301, USA.  */
     21  1.1  christos 
     22  1.1  christos #include "sysdep.h"
     23  1.1  christos #include "mach-o.h"
     24  1.1  christos #include "bfd.h"
     25  1.1  christos #include "libbfd.h"
     26  1.1  christos #include "libiberty.h"
     27  1.1  christos #include "mach-o/x86-64.h"
     28  1.1  christos 
     29  1.1  christos #define bfd_mach_o_object_p bfd_mach_o_x86_64_object_p
     30  1.1  christos #define bfd_mach_o_core_p bfd_mach_o_x86_64_core_p
     31  1.1  christos #define bfd_mach_o_mkobject bfd_mach_o_x86_64_mkobject
     32  1.1  christos 
     33  1.1  christos static const bfd_target *
     34  1.1  christos bfd_mach_o_x86_64_object_p (bfd *abfd)
     35  1.1  christos {
     36  1.1  christos   return bfd_mach_o_header_p (abfd, 0, BFD_MACH_O_CPU_TYPE_X86_64);
     37  1.1  christos }
     38  1.1  christos 
     39  1.1  christos static const bfd_target *
     40  1.1  christos bfd_mach_o_x86_64_core_p (bfd *abfd)
     41  1.1  christos {
     42  1.1  christos   return bfd_mach_o_header_p (abfd,
     43  1.1  christos                               BFD_MACH_O_MH_CORE, BFD_MACH_O_CPU_TYPE_X86_64);
     44  1.1  christos }
     45  1.1  christos 
     46  1.1  christos static bfd_boolean
     47  1.1  christos bfd_mach_o_x86_64_mkobject (bfd *abfd)
     48  1.1  christos {
     49  1.1  christos   bfd_mach_o_data_struct *mdata;
     50  1.1  christos 
     51  1.1  christos   if (!bfd_mach_o_mkobject_init (abfd))
     52  1.1  christos     return FALSE;
     53  1.1  christos 
     54  1.1  christos   mdata = bfd_mach_o_get_data (abfd);
     55  1.1  christos   mdata->header.magic = BFD_MACH_O_MH_MAGIC_64;
     56  1.1  christos   mdata->header.cputype = BFD_MACH_O_CPU_TYPE_X86_64;
     57  1.1  christos   mdata->header.cpusubtype = BFD_MACH_O_CPU_SUBTYPE_X86_ALL;
     58  1.1  christos   mdata->header.byteorder = BFD_ENDIAN_LITTLE;
     59  1.1  christos   mdata->header.version = 2;
     60  1.1  christos 
     61  1.1  christos   return TRUE;
     62  1.1  christos }
     63  1.1  christos 
     64  1.1  christos /* In case we're on a 32-bit machine, construct a 64-bit "-1" value.  */
     65  1.1  christos #define MINUS_ONE (~ (bfd_vma) 0)
     66  1.1  christos 
     67  1.1  christos static reloc_howto_type x86_64_howto_table[]=
     68  1.1  christos {
     69  1.1  christos   /* 0 */
     70  1.1  christos   HOWTO(BFD_RELOC_64, 0, 4, 64, FALSE, 0,
     71  1.1  christos 	complain_overflow_bitfield,
     72  1.1  christos 	NULL, "64",
     73  1.1  christos 	FALSE, MINUS_ONE, MINUS_ONE, FALSE),
     74  1.1  christos   HOWTO(BFD_RELOC_32, 0, 2, 32, FALSE, 0,
     75  1.1  christos 	complain_overflow_bitfield,
     76  1.1  christos 	NULL, "32",
     77  1.1  christos 	FALSE, 0xffffffff, 0xffffffff, FALSE),
     78  1.1  christos   HOWTO(BFD_RELOC_32_PCREL, 0, 2, 32, TRUE, 0,
     79  1.1  christos 	complain_overflow_bitfield,
     80  1.1  christos 	NULL, "DISP32",
     81  1.1  christos 	FALSE, 0xffffffff, 0xffffffff, TRUE),
     82  1.1  christos   HOWTO(BFD_RELOC_MACH_O_X86_64_PCREL32_1, 0, 2, 32, TRUE, 0,
     83  1.1  christos 	complain_overflow_bitfield,
     84  1.1  christos 	NULL, "DISP32_1",
     85  1.1  christos 	FALSE, 0xffffffff, 0xffffffff, TRUE),
     86  1.1  christos   /* 4 */
     87  1.1  christos   HOWTO(BFD_RELOC_MACH_O_X86_64_PCREL32_2, 0, 2, 32, TRUE, 0,
     88  1.1  christos 	complain_overflow_bitfield,
     89  1.1  christos 	NULL, "DISP32_2",
     90  1.1  christos 	FALSE, 0xffffffff, 0xffffffff, TRUE),
     91  1.1  christos   HOWTO(BFD_RELOC_MACH_O_X86_64_PCREL32_4, 0, 2, 32, TRUE, 0,
     92  1.1  christos 	complain_overflow_bitfield,
     93  1.1  christos 	NULL, "DISP32_4",
     94  1.1  christos 	FALSE, 0xffffffff, 0xffffffff, TRUE),
     95  1.1  christos   HOWTO(BFD_RELOC_MACH_O_X86_64_BRANCH32, 0, 2, 32, TRUE, 0,
     96  1.1  christos 	complain_overflow_bitfield,
     97  1.1  christos 	NULL, "BRANCH32",
     98  1.1  christos 	FALSE, 0xffffffff, 0xffffffff, TRUE),
     99  1.1  christos   HOWTO(BFD_RELOC_MACH_O_X86_64_GOT_LOAD, 0, 2, 32, TRUE, 0,
    100  1.1  christos 	complain_overflow_bitfield,
    101  1.1  christos 	NULL, "GOT_LOAD",
    102  1.1  christos 	FALSE, 0xffffffff, 0xffffffff, TRUE),
    103  1.1  christos   /* 8 */
    104  1.1  christos   HOWTO(BFD_RELOC_MACH_O_X86_64_SUBTRACTOR32, 0, 2, 32, FALSE, 0,
    105  1.1  christos 	complain_overflow_bitfield,
    106  1.1  christos 	NULL, "SUBTRACTOR32",
    107  1.1  christos 	FALSE, 0xffffffff, 0xffffffff, FALSE),
    108  1.1  christos   HOWTO(BFD_RELOC_MACH_O_X86_64_SUBTRACTOR64, 0, 4, 64, FALSE, 0,
    109  1.1  christos 	complain_overflow_bitfield,
    110  1.1  christos 	NULL, "SUBTRACTOR64",
    111  1.1  christos 	FALSE, MINUS_ONE, MINUS_ONE, FALSE),
    112  1.1  christos   HOWTO(BFD_RELOC_MACH_O_X86_64_GOT, 0, 2, 32, TRUE, 0,
    113  1.1  christos 	complain_overflow_bitfield,
    114  1.1  christos 	NULL, "GOT",
    115  1.1  christos 	FALSE, 0xffffffff, 0xffffffff, TRUE),
    116  1.1  christos   HOWTO(BFD_RELOC_MACH_O_X86_64_BRANCH8, 0, 0, 8, TRUE, 0,
    117  1.1  christos 	complain_overflow_bitfield,
    118  1.1  christos 	NULL, "BRANCH8",
    119  1.1  christos 	FALSE, 0xff, 0xff, TRUE),
    120  1.1  christos };
    121  1.1  christos 
    122  1.1  christos static bfd_boolean
    123  1.1  christos bfd_mach_o_x86_64_swap_reloc_in (arelent *res, bfd_mach_o_reloc_info *reloc)
    124  1.1  christos {
    125  1.1  christos   /* On x86-64, scattered relocs are not used.  */
    126  1.1  christos   if (reloc->r_scattered)
    127  1.1  christos     return FALSE;
    128  1.1  christos 
    129  1.1  christos   switch (reloc->r_type)
    130  1.1  christos     {
    131  1.1  christos     case BFD_MACH_O_X86_64_RELOC_UNSIGNED:
    132  1.1  christos       if (reloc->r_pcrel)
    133  1.1  christos         return FALSE;
    134  1.1  christos       switch (reloc->r_length)
    135  1.1  christos         {
    136  1.1  christos         case 2:
    137  1.1  christos           res->howto = &x86_64_howto_table[1];
    138  1.1  christos           return TRUE;
    139  1.1  christos         case 3:
    140  1.1  christos           res->howto = &x86_64_howto_table[0];
    141  1.1  christos           return TRUE;
    142  1.1  christos         default:
    143  1.1  christos           return FALSE;
    144  1.1  christos         }
    145  1.1  christos     case BFD_MACH_O_X86_64_RELOC_SIGNED:
    146  1.1  christos       if (reloc->r_length == 2 && reloc->r_pcrel)
    147  1.1  christos         {
    148  1.1  christos           res->howto = &x86_64_howto_table[2];
    149  1.1  christos           return TRUE;
    150  1.1  christos         }
    151  1.1  christos       break;
    152  1.1  christos     case BFD_MACH_O_X86_64_RELOC_BRANCH:
    153  1.1  christos       if (!reloc->r_pcrel)
    154  1.1  christos         return FALSE;
    155  1.1  christos       switch (reloc->r_length)
    156  1.1  christos         {
    157  1.1  christos         case 2:
    158  1.1  christos           res->howto = &x86_64_howto_table[6];
    159  1.1  christos           return TRUE;
    160  1.1  christos         default:
    161  1.1  christos           return FALSE;
    162  1.1  christos         }
    163  1.1  christos       break;
    164  1.1  christos     case BFD_MACH_O_X86_64_RELOC_GOT_LOAD:
    165  1.1  christos       if (reloc->r_length == 2 && reloc->r_pcrel && reloc->r_extern)
    166  1.1  christos         {
    167  1.1  christos           res->howto = &x86_64_howto_table[7];
    168  1.1  christos           return TRUE;
    169  1.1  christos         }
    170  1.1  christos       break;
    171  1.1  christos     case BFD_MACH_O_X86_64_RELOC_GOT:
    172  1.1  christos       if (reloc->r_length == 2 && reloc->r_pcrel && reloc->r_extern)
    173  1.1  christos         {
    174  1.1  christos           res->howto = &x86_64_howto_table[10];
    175  1.1  christos           return TRUE;
    176  1.1  christos         }
    177  1.1  christos       break;
    178  1.1  christos     case BFD_MACH_O_X86_64_RELOC_SUBTRACTOR:
    179  1.1  christos       if (reloc->r_pcrel)
    180  1.1  christos         return FALSE;
    181  1.1  christos       switch (reloc->r_length)
    182  1.1  christos         {
    183  1.1  christos         case 2:
    184  1.1  christos           res->howto = &x86_64_howto_table[8];
    185  1.1  christos           return TRUE;
    186  1.1  christos         case 3:
    187  1.1  christos           res->howto = &x86_64_howto_table[9];
    188  1.1  christos           return TRUE;
    189  1.1  christos         default:
    190  1.1  christos           return FALSE;
    191  1.1  christos         }
    192  1.1  christos       break;
    193  1.1  christos     case BFD_MACH_O_X86_64_RELOC_SIGNED_1:
    194  1.1  christos       if (reloc->r_length == 2 && reloc->r_pcrel)
    195  1.1  christos         {
    196  1.1  christos           res->howto = &x86_64_howto_table[3];
    197  1.1  christos           return TRUE;
    198  1.1  christos         }
    199  1.1  christos       break;
    200  1.1  christos     case BFD_MACH_O_X86_64_RELOC_SIGNED_2:
    201  1.1  christos       if (reloc->r_length == 2 && reloc->r_pcrel)
    202  1.1  christos         {
    203  1.1  christos           res->howto = &x86_64_howto_table[4];
    204  1.1  christos           return TRUE;
    205  1.1  christos         }
    206  1.1  christos       break;
    207  1.1  christos     case BFD_MACH_O_X86_64_RELOC_SIGNED_4:
    208  1.1  christos       if (reloc->r_length == 2 && reloc->r_pcrel)
    209  1.1  christos         {
    210  1.1  christos           res->howto = &x86_64_howto_table[5];
    211  1.1  christos           return TRUE;
    212  1.1  christos         }
    213  1.1  christos       break;
    214  1.1  christos     default:
    215  1.1  christos       return FALSE;
    216  1.1  christos     }
    217  1.1  christos   return FALSE;
    218  1.1  christos }
    219  1.1  christos 
    220  1.1  christos static bfd_boolean
    221  1.1  christos bfd_mach_o_x86_64_swap_reloc_out (arelent *rel, bfd_mach_o_reloc_info *rinfo)
    222  1.1  christos {
    223  1.1  christos   rinfo->r_address = rel->address;
    224  1.1  christos   rinfo->r_scattered = 0;
    225  1.1  christos   switch (rel->howto->type)
    226  1.1  christos     {
    227  1.1  christos     case BFD_RELOC_32:
    228  1.1  christos       rinfo->r_type = BFD_MACH_O_X86_64_RELOC_UNSIGNED;
    229  1.1  christos       rinfo->r_pcrel = 0;
    230  1.1  christos       rinfo->r_length = 2;
    231  1.1  christos       break;
    232  1.1  christos     case BFD_RELOC_64:
    233  1.1  christos       rinfo->r_type = BFD_MACH_O_X86_64_RELOC_UNSIGNED;
    234  1.1  christos       rinfo->r_pcrel = 0;
    235  1.1  christos       rinfo->r_length = 3;
    236  1.1  christos       break;
    237  1.1  christos     case BFD_RELOC_32_PCREL:
    238  1.1  christos       rinfo->r_type = BFD_MACH_O_X86_64_RELOC_SIGNED;
    239  1.1  christos       rinfo->r_pcrel = 1;
    240  1.1  christos       rinfo->r_length = 2;
    241  1.1  christos       break;
    242  1.1  christos     case BFD_RELOC_MACH_O_X86_64_PCREL32_1:
    243  1.1  christos       rinfo->r_type = BFD_MACH_O_X86_64_RELOC_SIGNED_1;
    244  1.1  christos       rinfo->r_pcrel = 1;
    245  1.1  christos       rinfo->r_length = 2;
    246  1.1  christos       break;
    247  1.1  christos     case BFD_RELOC_MACH_O_X86_64_PCREL32_2:
    248  1.1  christos       rinfo->r_type = BFD_MACH_O_X86_64_RELOC_SIGNED_2;
    249  1.1  christos       rinfo->r_pcrel = 1;
    250  1.1  christos       rinfo->r_length = 2;
    251  1.1  christos       break;
    252  1.1  christos     case BFD_RELOC_MACH_O_X86_64_PCREL32_4:
    253  1.1  christos       rinfo->r_type = BFD_MACH_O_X86_64_RELOC_SIGNED_4;
    254  1.1  christos       rinfo->r_pcrel = 1;
    255  1.1  christos       rinfo->r_length = 2;
    256  1.1  christos       break;
    257  1.1  christos     case BFD_RELOC_MACH_O_X86_64_BRANCH32:
    258  1.1  christos       rinfo->r_type = BFD_MACH_O_X86_64_RELOC_BRANCH;
    259  1.1  christos       rinfo->r_pcrel = 1;
    260  1.1  christos       rinfo->r_length = 2;
    261  1.1  christos       break;
    262  1.1  christos     case BFD_RELOC_MACH_O_X86_64_SUBTRACTOR32:
    263  1.1  christos       rinfo->r_type = BFD_MACH_O_X86_64_RELOC_SUBTRACTOR;
    264  1.1  christos       rinfo->r_pcrel = 0;
    265  1.1  christos       rinfo->r_length = 2;
    266  1.1  christos       break;
    267  1.1  christos     case BFD_RELOC_MACH_O_X86_64_SUBTRACTOR64:
    268  1.1  christos       rinfo->r_type = BFD_MACH_O_X86_64_RELOC_SUBTRACTOR;
    269  1.1  christos       rinfo->r_pcrel = 0;
    270  1.1  christos       rinfo->r_length = 3;
    271  1.1  christos       break;
    272  1.1  christos     case BFD_RELOC_MACH_O_X86_64_GOT:
    273  1.1  christos       rinfo->r_type = BFD_MACH_O_X86_64_RELOC_GOT;
    274  1.1  christos       rinfo->r_pcrel = 1;
    275  1.1  christos       rinfo->r_length = 2;
    276  1.1  christos       break;
    277  1.1  christos     case BFD_RELOC_MACH_O_X86_64_GOT_LOAD:
    278  1.1  christos       rinfo->r_type = BFD_MACH_O_X86_64_RELOC_GOT_LOAD;
    279  1.1  christos       rinfo->r_pcrel = 1;
    280  1.1  christos       rinfo->r_length = 2;
    281  1.1  christos       break;
    282  1.1  christos     default:
    283  1.1  christos       return FALSE;
    284  1.1  christos     }
    285  1.1  christos   if ((*rel->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
    286  1.1  christos     {
    287  1.1  christos       rinfo->r_extern = 0;
    288  1.1  christos       rinfo->r_value = (*rel->sym_ptr_ptr)->section->target_index;
    289  1.1  christos     }
    290  1.1  christos   else
    291  1.1  christos     {
    292  1.1  christos       rinfo->r_extern = 1;
    293  1.1  christos       rinfo->r_value = (*rel->sym_ptr_ptr)->udata.i;
    294  1.1  christos     }
    295  1.1  christos   return TRUE;
    296  1.1  christos }
    297  1.1  christos 
    298  1.1  christos static reloc_howto_type *
    299  1.1  christos bfd_mach_o_x86_64_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    300  1.1  christos                                          bfd_reloc_code_real_type code)
    301  1.1  christos {
    302  1.1  christos   unsigned int i;
    303  1.1  christos 
    304  1.1  christos   for (i = 0;
    305  1.1  christos        i < sizeof (x86_64_howto_table) / sizeof (*x86_64_howto_table);
    306  1.1  christos        i++)
    307  1.1  christos     if (code == x86_64_howto_table[i].type)
    308  1.1  christos       return &x86_64_howto_table[i];
    309  1.1  christos   return NULL;
    310  1.1  christos }
    311  1.1  christos 
    312  1.1  christos static reloc_howto_type *
    313  1.1  christos bfd_mach_o_x86_64_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    314  1.1  christos                                          const char *name ATTRIBUTE_UNUSED)
    315  1.1  christos {
    316  1.1  christos   return NULL;
    317  1.1  christos }
    318  1.1  christos 
    319  1.1  christos static bfd_boolean
    320  1.1  christos bfd_mach_o_section_type_valid_for_x86_64 (unsigned long val)
    321  1.1  christos {
    322  1.1  christos   if (val == BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS
    323  1.1  christos       || val == BFD_MACH_O_S_LAZY_SYMBOL_POINTERS
    324  1.1  christos       || val == BFD_MACH_O_S_SYMBOL_STUBS)
    325  1.1  christos     return FALSE;
    326  1.1  christos   return TRUE;
    327  1.1  christos }
    328  1.1  christos 
    329  1.1  christos /* We want to bump the alignment of some sections.  */
    330  1.1  christos static const mach_o_section_name_xlat text_section_names_xlat[] =
    331  1.1  christos   {
    332  1.1  christos     {	".eh_frame",				"__eh_frame",
    333  1.1  christos 	SEC_READONLY | SEC_DATA | SEC_LOAD,	BFD_MACH_O_S_COALESCED,
    334  1.1  christos 	BFD_MACH_O_S_ATTR_LIVE_SUPPORT
    335  1.1  christos 	| BFD_MACH_O_S_ATTR_STRIP_STATIC_SYMS
    336  1.1  christos 	| BFD_MACH_O_S_ATTR_NO_TOC,		3},
    337  1.1  christos     { NULL, NULL, 0, 0, 0, 0}
    338  1.1  christos   };
    339  1.1  christos 
    340  1.1  christos const mach_o_segment_name_xlat mach_o_x86_64_segsec_names_xlat[] =
    341  1.1  christos   {
    342  1.1  christos     { "__TEXT", text_section_names_xlat },
    343  1.1  christos     { NULL, NULL }
    344  1.1  christos   };
    345  1.1  christos 
    346  1.1  christos #define bfd_mach_o_swap_reloc_in bfd_mach_o_x86_64_swap_reloc_in
    347  1.1  christos #define bfd_mach_o_swap_reloc_out bfd_mach_o_x86_64_swap_reloc_out
    348  1.1  christos 
    349  1.1  christos #define bfd_mach_o_bfd_reloc_type_lookup bfd_mach_o_x86_64_bfd_reloc_type_lookup
    350  1.1  christos #define bfd_mach_o_bfd_reloc_name_lookup bfd_mach_o_x86_64_bfd_reloc_name_lookup
    351  1.1  christos #define bfd_mach_o_print_thread NULL
    352  1.1  christos #define bfd_mach_o_tgt_seg_table mach_o_x86_64_segsec_names_xlat
    353  1.1  christos #define bfd_mach_o_section_type_valid_for_tgt bfd_mach_o_section_type_valid_for_x86_64
    354  1.1  christos 
    355  1.1  christos #define TARGET_NAME 		mach_o_x86_64_vec
    356  1.1  christos #define TARGET_STRING 		"mach-o-x86-64"
    357  1.1  christos #define TARGET_ARCHITECTURE	bfd_arch_i386
    358  1.1  christos #define TARGET_BIG_ENDIAN 	0
    359  1.1  christos #define TARGET_ARCHIVE 		0
    360  1.1  christos #define TARGET_PRIORITY		0
    361  1.1  christos #include "mach-o-target.c"
    362