Home | History | Annotate | Line # | Download | only in bfd
mach-o-x86-64.c revision 1.1.1.4
      1      1.1  christos /* Intel x86-64 Mach-O support for BFD.
      2  1.1.1.4  christos    Copyright (C) 2010-2017 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 "mach-o.h"
     23      1.1  christos #include "bfd.h"
     24      1.1  christos #include "libbfd.h"
     25      1.1  christos #include "libiberty.h"
     26      1.1  christos #include "mach-o/x86-64.h"
     27      1.1  christos 
     28      1.1  christos #define bfd_mach_o_object_p bfd_mach_o_x86_64_object_p
     29      1.1  christos #define bfd_mach_o_core_p bfd_mach_o_x86_64_core_p
     30      1.1  christos #define bfd_mach_o_mkobject bfd_mach_o_x86_64_mkobject
     31      1.1  christos 
     32      1.1  christos static const bfd_target *
     33      1.1  christos bfd_mach_o_x86_64_object_p (bfd *abfd)
     34      1.1  christos {
     35  1.1.1.3  christos   return bfd_mach_o_header_p (abfd, 0, 0, BFD_MACH_O_CPU_TYPE_X86_64);
     36      1.1  christos }
     37      1.1  christos 
     38      1.1  christos static const bfd_target *
     39      1.1  christos bfd_mach_o_x86_64_core_p (bfd *abfd)
     40      1.1  christos {
     41  1.1.1.3  christos   return bfd_mach_o_header_p (abfd, 0,
     42      1.1  christos                               BFD_MACH_O_MH_CORE, BFD_MACH_O_CPU_TYPE_X86_64);
     43      1.1  christos }
     44      1.1  christos 
     45      1.1  christos static bfd_boolean
     46      1.1  christos bfd_mach_o_x86_64_mkobject (bfd *abfd)
     47      1.1  christos {
     48      1.1  christos   bfd_mach_o_data_struct *mdata;
     49      1.1  christos 
     50      1.1  christos   if (!bfd_mach_o_mkobject_init (abfd))
     51      1.1  christos     return FALSE;
     52      1.1  christos 
     53      1.1  christos   mdata = bfd_mach_o_get_data (abfd);
     54      1.1  christos   mdata->header.magic = BFD_MACH_O_MH_MAGIC_64;
     55      1.1  christos   mdata->header.cputype = BFD_MACH_O_CPU_TYPE_X86_64;
     56  1.1.1.2  christos   mdata->header.cpusubtype =
     57  1.1.1.2  christos     BFD_MACH_O_CPU_SUBTYPE_X86_ALL | BFD_MACH_O_CPU_SUBTYPE_LIB64;
     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.1.3  christos   HOWTO(BFD_RELOC_MACH_O_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.1.3  christos   HOWTO(BFD_RELOC_MACH_O_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.1.3  christos bfd_mach_o_x86_64_canonicalize_one_reloc (bfd *abfd,
    124  1.1.1.3  christos 				        struct mach_o_reloc_info_external *raw,
    125  1.1.1.3  christos 					arelent *res, asymbol **syms)
    126      1.1  christos {
    127  1.1.1.3  christos   bfd_mach_o_reloc_info reloc;
    128  1.1.1.3  christos 
    129  1.1.1.3  christos   if (!bfd_mach_o_pre_canonicalize_one_reloc (abfd, raw, &reloc, res, syms))
    130  1.1.1.3  christos     return FALSE;
    131  1.1.1.3  christos 
    132      1.1  christos   /* On x86-64, scattered relocs are not used.  */
    133  1.1.1.3  christos   if (reloc.r_scattered)
    134      1.1  christos     return FALSE;
    135      1.1  christos 
    136  1.1.1.3  christos   switch (reloc.r_type)
    137      1.1  christos     {
    138      1.1  christos     case BFD_MACH_O_X86_64_RELOC_UNSIGNED:
    139  1.1.1.3  christos       if (reloc.r_pcrel)
    140      1.1  christos         return FALSE;
    141  1.1.1.3  christos       switch (reloc.r_length)
    142      1.1  christos         {
    143      1.1  christos         case 2:
    144      1.1  christos           res->howto = &x86_64_howto_table[1];
    145      1.1  christos           return TRUE;
    146      1.1  christos         case 3:
    147      1.1  christos           res->howto = &x86_64_howto_table[0];
    148      1.1  christos           return TRUE;
    149      1.1  christos         default:
    150      1.1  christos           return FALSE;
    151      1.1  christos         }
    152      1.1  christos     case BFD_MACH_O_X86_64_RELOC_SIGNED:
    153  1.1.1.3  christos       if (reloc.r_length == 2 && reloc.r_pcrel)
    154      1.1  christos         {
    155      1.1  christos           res->howto = &x86_64_howto_table[2];
    156      1.1  christos           return TRUE;
    157      1.1  christos         }
    158      1.1  christos       break;
    159      1.1  christos     case BFD_MACH_O_X86_64_RELOC_BRANCH:
    160  1.1.1.3  christos       if (!reloc.r_pcrel)
    161      1.1  christos         return FALSE;
    162  1.1.1.3  christos       switch (reloc.r_length)
    163      1.1  christos         {
    164      1.1  christos         case 2:
    165      1.1  christos           res->howto = &x86_64_howto_table[6];
    166      1.1  christos           return TRUE;
    167      1.1  christos         default:
    168      1.1  christos           return FALSE;
    169      1.1  christos         }
    170      1.1  christos       break;
    171      1.1  christos     case BFD_MACH_O_X86_64_RELOC_GOT_LOAD:
    172  1.1.1.3  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[7];
    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_GOT:
    179  1.1.1.3  christos       if (reloc.r_length == 2 && reloc.r_pcrel && reloc.r_extern)
    180      1.1  christos         {
    181      1.1  christos           res->howto = &x86_64_howto_table[10];
    182      1.1  christos           return TRUE;
    183      1.1  christos         }
    184      1.1  christos       break;
    185      1.1  christos     case BFD_MACH_O_X86_64_RELOC_SUBTRACTOR:
    186  1.1.1.3  christos       if (reloc.r_pcrel)
    187      1.1  christos         return FALSE;
    188  1.1.1.3  christos       switch (reloc.r_length)
    189      1.1  christos         {
    190      1.1  christos         case 2:
    191      1.1  christos           res->howto = &x86_64_howto_table[8];
    192      1.1  christos           return TRUE;
    193      1.1  christos         case 3:
    194      1.1  christos           res->howto = &x86_64_howto_table[9];
    195      1.1  christos           return TRUE;
    196      1.1  christos         default:
    197      1.1  christos           return FALSE;
    198      1.1  christos         }
    199      1.1  christos       break;
    200      1.1  christos     case BFD_MACH_O_X86_64_RELOC_SIGNED_1:
    201  1.1.1.3  christos       if (reloc.r_length == 2 && reloc.r_pcrel)
    202      1.1  christos         {
    203      1.1  christos           res->howto = &x86_64_howto_table[3];
    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_2:
    208  1.1.1.3  christos       if (reloc.r_length == 2 && reloc.r_pcrel)
    209      1.1  christos         {
    210      1.1  christos           res->howto = &x86_64_howto_table[4];
    211      1.1  christos           return TRUE;
    212      1.1  christos         }
    213      1.1  christos       break;
    214      1.1  christos     case BFD_MACH_O_X86_64_RELOC_SIGNED_4:
    215  1.1.1.3  christos       if (reloc.r_length == 2 && reloc.r_pcrel)
    216      1.1  christos         {
    217      1.1  christos           res->howto = &x86_64_howto_table[5];
    218      1.1  christos           return TRUE;
    219      1.1  christos         }
    220      1.1  christos       break;
    221      1.1  christos     default:
    222      1.1  christos       return FALSE;
    223      1.1  christos     }
    224      1.1  christos   return FALSE;
    225      1.1  christos }
    226      1.1  christos 
    227      1.1  christos static bfd_boolean
    228      1.1  christos bfd_mach_o_x86_64_swap_reloc_out (arelent *rel, bfd_mach_o_reloc_info *rinfo)
    229      1.1  christos {
    230      1.1  christos   rinfo->r_address = rel->address;
    231      1.1  christos   rinfo->r_scattered = 0;
    232      1.1  christos   switch (rel->howto->type)
    233      1.1  christos     {
    234      1.1  christos     case BFD_RELOC_32:
    235      1.1  christos       rinfo->r_type = BFD_MACH_O_X86_64_RELOC_UNSIGNED;
    236      1.1  christos       rinfo->r_pcrel = 0;
    237      1.1  christos       rinfo->r_length = 2;
    238      1.1  christos       break;
    239      1.1  christos     case BFD_RELOC_64:
    240      1.1  christos       rinfo->r_type = BFD_MACH_O_X86_64_RELOC_UNSIGNED;
    241      1.1  christos       rinfo->r_pcrel = 0;
    242      1.1  christos       rinfo->r_length = 3;
    243      1.1  christos       break;
    244      1.1  christos     case BFD_RELOC_32_PCREL:
    245      1.1  christos       rinfo->r_type = BFD_MACH_O_X86_64_RELOC_SIGNED;
    246      1.1  christos       rinfo->r_pcrel = 1;
    247      1.1  christos       rinfo->r_length = 2;
    248      1.1  christos       break;
    249      1.1  christos     case BFD_RELOC_MACH_O_X86_64_PCREL32_1:
    250      1.1  christos       rinfo->r_type = BFD_MACH_O_X86_64_RELOC_SIGNED_1;
    251      1.1  christos       rinfo->r_pcrel = 1;
    252      1.1  christos       rinfo->r_length = 2;
    253      1.1  christos       break;
    254      1.1  christos     case BFD_RELOC_MACH_O_X86_64_PCREL32_2:
    255      1.1  christos       rinfo->r_type = BFD_MACH_O_X86_64_RELOC_SIGNED_2;
    256      1.1  christos       rinfo->r_pcrel = 1;
    257      1.1  christos       rinfo->r_length = 2;
    258      1.1  christos       break;
    259      1.1  christos     case BFD_RELOC_MACH_O_X86_64_PCREL32_4:
    260      1.1  christos       rinfo->r_type = BFD_MACH_O_X86_64_RELOC_SIGNED_4;
    261      1.1  christos       rinfo->r_pcrel = 1;
    262      1.1  christos       rinfo->r_length = 2;
    263      1.1  christos       break;
    264      1.1  christos     case BFD_RELOC_MACH_O_X86_64_BRANCH32:
    265      1.1  christos       rinfo->r_type = BFD_MACH_O_X86_64_RELOC_BRANCH;
    266      1.1  christos       rinfo->r_pcrel = 1;
    267      1.1  christos       rinfo->r_length = 2;
    268      1.1  christos       break;
    269  1.1.1.3  christos     case BFD_RELOC_MACH_O_SUBTRACTOR32:
    270      1.1  christos       rinfo->r_type = BFD_MACH_O_X86_64_RELOC_SUBTRACTOR;
    271      1.1  christos       rinfo->r_pcrel = 0;
    272      1.1  christos       rinfo->r_length = 2;
    273      1.1  christos       break;
    274  1.1.1.3  christos     case BFD_RELOC_MACH_O_SUBTRACTOR64:
    275      1.1  christos       rinfo->r_type = BFD_MACH_O_X86_64_RELOC_SUBTRACTOR;
    276      1.1  christos       rinfo->r_pcrel = 0;
    277      1.1  christos       rinfo->r_length = 3;
    278      1.1  christos       break;
    279      1.1  christos     case BFD_RELOC_MACH_O_X86_64_GOT:
    280      1.1  christos       rinfo->r_type = BFD_MACH_O_X86_64_RELOC_GOT;
    281      1.1  christos       rinfo->r_pcrel = 1;
    282      1.1  christos       rinfo->r_length = 2;
    283      1.1  christos       break;
    284      1.1  christos     case BFD_RELOC_MACH_O_X86_64_GOT_LOAD:
    285      1.1  christos       rinfo->r_type = BFD_MACH_O_X86_64_RELOC_GOT_LOAD;
    286      1.1  christos       rinfo->r_pcrel = 1;
    287      1.1  christos       rinfo->r_length = 2;
    288      1.1  christos       break;
    289      1.1  christos     default:
    290      1.1  christos       return FALSE;
    291      1.1  christos     }
    292      1.1  christos   if ((*rel->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
    293      1.1  christos     {
    294      1.1  christos       rinfo->r_extern = 0;
    295  1.1.1.2  christos       rinfo->r_value =
    296  1.1.1.2  christos 	(*rel->sym_ptr_ptr)->section->output_section->target_index;
    297      1.1  christos     }
    298      1.1  christos   else
    299      1.1  christos     {
    300      1.1  christos       rinfo->r_extern = 1;
    301      1.1  christos       rinfo->r_value = (*rel->sym_ptr_ptr)->udata.i;
    302      1.1  christos     }
    303      1.1  christos   return TRUE;
    304      1.1  christos }
    305      1.1  christos 
    306      1.1  christos static reloc_howto_type *
    307      1.1  christos bfd_mach_o_x86_64_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    308      1.1  christos                                          bfd_reloc_code_real_type code)
    309      1.1  christos {
    310      1.1  christos   unsigned int i;
    311      1.1  christos 
    312      1.1  christos   for (i = 0;
    313      1.1  christos        i < sizeof (x86_64_howto_table) / sizeof (*x86_64_howto_table);
    314      1.1  christos        i++)
    315      1.1  christos     if (code == x86_64_howto_table[i].type)
    316      1.1  christos       return &x86_64_howto_table[i];
    317      1.1  christos   return NULL;
    318      1.1  christos }
    319      1.1  christos 
    320      1.1  christos static reloc_howto_type *
    321      1.1  christos bfd_mach_o_x86_64_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    322      1.1  christos                                          const char *name ATTRIBUTE_UNUSED)
    323      1.1  christos {
    324      1.1  christos   return NULL;
    325      1.1  christos }
    326      1.1  christos 
    327      1.1  christos static bfd_boolean
    328      1.1  christos bfd_mach_o_section_type_valid_for_x86_64 (unsigned long val)
    329      1.1  christos {
    330      1.1  christos   if (val == BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS
    331      1.1  christos       || val == BFD_MACH_O_S_LAZY_SYMBOL_POINTERS
    332      1.1  christos       || val == BFD_MACH_O_S_SYMBOL_STUBS)
    333      1.1  christos     return FALSE;
    334      1.1  christos   return TRUE;
    335      1.1  christos }
    336      1.1  christos 
    337      1.1  christos /* We want to bump the alignment of some sections.  */
    338      1.1  christos static const mach_o_section_name_xlat text_section_names_xlat[] =
    339      1.1  christos   {
    340      1.1  christos     {	".eh_frame",				"__eh_frame",
    341      1.1  christos 	SEC_READONLY | SEC_DATA | SEC_LOAD,	BFD_MACH_O_S_COALESCED,
    342      1.1  christos 	BFD_MACH_O_S_ATTR_LIVE_SUPPORT
    343      1.1  christos 	| BFD_MACH_O_S_ATTR_STRIP_STATIC_SYMS
    344      1.1  christos 	| BFD_MACH_O_S_ATTR_NO_TOC,		3},
    345      1.1  christos     { NULL, NULL, 0, 0, 0, 0}
    346      1.1  christos   };
    347      1.1  christos 
    348      1.1  christos const mach_o_segment_name_xlat mach_o_x86_64_segsec_names_xlat[] =
    349      1.1  christos   {
    350      1.1  christos     { "__TEXT", text_section_names_xlat },
    351      1.1  christos     { NULL, NULL }
    352      1.1  christos   };
    353      1.1  christos 
    354  1.1.1.3  christos #define bfd_mach_o_canonicalize_one_reloc bfd_mach_o_x86_64_canonicalize_one_reloc
    355      1.1  christos #define bfd_mach_o_swap_reloc_out bfd_mach_o_x86_64_swap_reloc_out
    356      1.1  christos 
    357      1.1  christos #define bfd_mach_o_bfd_reloc_type_lookup bfd_mach_o_x86_64_bfd_reloc_type_lookup
    358      1.1  christos #define bfd_mach_o_bfd_reloc_name_lookup bfd_mach_o_x86_64_bfd_reloc_name_lookup
    359      1.1  christos #define bfd_mach_o_print_thread NULL
    360      1.1  christos #define bfd_mach_o_tgt_seg_table mach_o_x86_64_segsec_names_xlat
    361      1.1  christos #define bfd_mach_o_section_type_valid_for_tgt bfd_mach_o_section_type_valid_for_x86_64
    362      1.1  christos 
    363  1.1.1.2  christos #define TARGET_NAME 		x86_64_mach_o_vec
    364      1.1  christos #define TARGET_STRING 		"mach-o-x86-64"
    365      1.1  christos #define TARGET_ARCHITECTURE	bfd_arch_i386
    366  1.1.1.2  christos #define TARGET_PAGESIZE		4096
    367      1.1  christos #define TARGET_BIG_ENDIAN 	0
    368      1.1  christos #define TARGET_ARCHIVE 		0
    369      1.1  christos #define TARGET_PRIORITY		0
    370      1.1  christos #include "mach-o-target.c"
    371