1/* Intel x86-64 Mach-O support for BFD. 2 Copyright 2010 3 Free Software Foundation, Inc. 4 5 This file is part of BFD, the Binary File Descriptor library. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 20 MA 02110-1301, USA. */ 21 22#include "sysdep.h" 23#include "mach-o.h" 24#include "bfd.h" 25#include "libbfd.h" 26#include "libiberty.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 32static const bfd_target * 33bfd_mach_o_x86_64_object_p (bfd *abfd) 34{ 35 return bfd_mach_o_header_p (abfd, 0, BFD_MACH_O_CPU_TYPE_X86_64); 36} 37 38static const bfd_target * 39bfd_mach_o_x86_64_core_p (bfd *abfd) 40{ 41 return bfd_mach_o_header_p (abfd, 42 BFD_MACH_O_MH_CORE, BFD_MACH_O_CPU_TYPE_X86_64); 43} 44 45static bfd_boolean 46bfd_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; 55 mdata->header.cputype = BFD_MACH_O_CPU_TYPE_X86_64; 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/* In case we're on a 32-bit machine, construct a 64-bit "-1" value. */ 64#define MINUS_ONE (~ (bfd_vma) 0) 65 66static reloc_howto_type x86_64_howto_table[]= 67{ 68 /* 0 */ 69 HOWTO(BFD_RELOC_64, 0, 4, 64, FALSE, 0, 70 complain_overflow_bitfield, 71 NULL, "64", 72 FALSE, MINUS_ONE, MINUS_ONE, FALSE), 73 HOWTO(BFD_RELOC_32, 0, 2, 32, FALSE, 0, 74 complain_overflow_bitfield, 75 NULL, "32", 76 FALSE, 0xffffffff, 0xffffffff, FALSE), 77 HOWTO(BFD_RELOC_32_PCREL, 0, 2, 32, TRUE, 0, 78 complain_overflow_bitfield, 79 NULL, "DISP32", 80 FALSE, 0xffffffff, 0xffffffff, TRUE), 81 HOWTO(BFD_RELOC_MACH_O_X86_64_PCREL32_1, 0, 2, 32, TRUE, 0, 82 complain_overflow_bitfield, 83 NULL, "DISP32_1", 84 FALSE, 0xffffffff, 0xffffffff, TRUE), 85 /* 4 */ 86 HOWTO(BFD_RELOC_MACH_O_X86_64_PCREL32_2, 0, 2, 32, TRUE, 0, 87 complain_overflow_bitfield, 88 NULL, "DISP32_2", 89 FALSE, 0xffffffff, 0xffffffff, TRUE), 90 HOWTO(BFD_RELOC_MACH_O_X86_64_PCREL32_4, 0, 2, 32, TRUE, 0, 91 complain_overflow_bitfield, 92 NULL, "DISP32_4", 93 FALSE, 0xffffffff, 0xffffffff, TRUE), 94 HOWTO(BFD_RELOC_MACH_O_X86_64_BRANCH32, 0, 2, 32, TRUE, 0, 95 complain_overflow_bitfield, 96 NULL, "BRANCH32", 97 FALSE, 0xffffffff, 0xffffffff, TRUE), 98 HOWTO(BFD_RELOC_MACH_O_X86_64_GOT_LOAD, 0, 2, 32, TRUE, 0, 99 complain_overflow_bitfield, 100 NULL, "GOT_LOAD", 101 FALSE, 0xffffffff, 0xffffffff, TRUE), 102 /* 8 */ 103 HOWTO(BFD_RELOC_MACH_O_X86_64_SUBTRACTOR32, 0, 2, 32, FALSE, 0, 104 complain_overflow_bitfield, 105 NULL, "SUBTRACTOR32", 106 FALSE, 0xffffffff, 0xffffffff, FALSE), 107 HOWTO(BFD_RELOC_MACH_O_X86_64_SUBTRACTOR64, 0, 4, 64, FALSE, 0, 108 complain_overflow_bitfield, 109 NULL, "SUBTRACTOR64", 110 FALSE, MINUS_ONE, MINUS_ONE, FALSE), 111 HOWTO(BFD_RELOC_MACH_O_X86_64_GOT, 0, 2, 32, TRUE, 0, 112 complain_overflow_bitfield, 113 NULL, "GOT", 114 FALSE, 0xffffffff, 0xffffffff, TRUE), 115 HOWTO(BFD_RELOC_MACH_O_X86_64_BRANCH8, 0, 0, 8, TRUE, 0, 116 complain_overflow_bitfield, 117 NULL, "BRANCH8", 118 FALSE, 0xff, 0xff, TRUE), 119}; 120 121static bfd_boolean 122bfd_mach_o_x86_64_swap_reloc_in (arelent *res, bfd_mach_o_reloc_info *reloc) 123{ 124 /* On x86-64, scattered relocs are not used. */ 125 if (reloc->r_scattered) 126 return FALSE; 127 128 switch (reloc->r_type) 129 { 130 case BFD_MACH_O_X86_64_RELOC_UNSIGNED: 131 if (reloc->r_pcrel) 132 return FALSE; 133 switch (reloc->r_length) 134 { 135 case 2: 136 res->howto = &x86_64_howto_table[1]; 137 return TRUE; 138 case 3: 139 res->howto = &x86_64_howto_table[0]; 140 return TRUE; 141 default: 142 return FALSE; 143 } 144 case BFD_MACH_O_X86_64_RELOC_SIGNED: 145 if (reloc->r_length == 2 && reloc->r_pcrel) 146 { 147 res->howto = &x86_64_howto_table[2]; 148 return TRUE; 149 } 150 break; 151 case BFD_MACH_O_X86_64_RELOC_BRANCH: 152 if (!reloc->r_pcrel) 153 return FALSE; 154 switch (reloc->r_length) 155 { 156 case 2: 157 res->howto = &x86_64_howto_table[6]; 158 return TRUE; 159 default: 160 return FALSE; 161 } 162 break; 163 case BFD_MACH_O_X86_64_RELOC_GOT_LOAD: 164 if (reloc->r_length == 2 && reloc->r_pcrel && reloc->r_extern) 165 { 166 res->howto = &x86_64_howto_table[7]; 167 return TRUE; 168 } 169 break; 170 case BFD_MACH_O_X86_64_RELOC_GOT: 171 if (reloc->r_length == 2 && reloc->r_pcrel && reloc->r_extern) 172 { 173 res->howto = &x86_64_howto_table[10]; 174 return TRUE; 175 } 176 break; 177 case BFD_MACH_O_X86_64_RELOC_SUBTRACTOR: 178 if (reloc->r_pcrel) 179 return FALSE; 180 switch (reloc->r_length) 181 { 182 case 2: 183 res->howto = &x86_64_howto_table[8]; 184 return TRUE; 185 case 3: 186 res->howto = &x86_64_howto_table[9]; 187 return TRUE; 188 default: 189 return FALSE; 190 } 191 break; 192 case BFD_MACH_O_X86_64_RELOC_SIGNED_1: 193 if (reloc->r_length == 2 && reloc->r_pcrel) 194 { 195 res->howto = &x86_64_howto_table[3]; 196 return TRUE; 197 } 198 break; 199 case BFD_MACH_O_X86_64_RELOC_SIGNED_2: 200 if (reloc->r_length == 2 && reloc->r_pcrel) 201 { 202 res->howto = &x86_64_howto_table[4]; 203 return TRUE; 204 } 205 break; 206 case BFD_MACH_O_X86_64_RELOC_SIGNED_4: 207 if (reloc->r_length == 2 && reloc->r_pcrel) 208 { 209 res->howto = &x86_64_howto_table[5]; 210 return TRUE; 211 } 212 break; 213 default: 214 return FALSE; 215 } 216 return FALSE; 217} 218 219static bfd_boolean 220bfd_mach_o_x86_64_swap_reloc_out (arelent *rel, bfd_mach_o_reloc_info *rinfo) 221{ 222 rinfo->r_address = rel->address; 223 switch (rel->howto->type) 224 { 225 case BFD_RELOC_64: 226 rinfo->r_scattered = 0; 227 rinfo->r_type = BFD_MACH_O_X86_64_RELOC_UNSIGNED; 228 rinfo->r_pcrel = 0; 229 rinfo->r_length = rel->howto->size; /* Correct in practice. */ 230 if ((*rel->sym_ptr_ptr)->flags & BSF_SECTION_SYM) 231 { 232 rinfo->r_extern = 0; 233 rinfo->r_value = (*rel->sym_ptr_ptr)->section->target_index; 234 } 235 else 236 { 237 rinfo->r_extern = 1; 238 rinfo->r_value = (*rel->sym_ptr_ptr)->udata.i; 239 } 240 break; 241 default: 242 return FALSE; 243 } 244 return TRUE; 245} 246 247static reloc_howto_type * 248bfd_mach_o_x86_64_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 249 bfd_reloc_code_real_type code) 250{ 251 unsigned int i; 252 253 for (i = 0; 254 i < sizeof (x86_64_howto_table) / sizeof (*x86_64_howto_table); 255 i++) 256 if (code == x86_64_howto_table[i].type) 257 return &x86_64_howto_table[i]; 258 return NULL; 259} 260 261static reloc_howto_type * 262bfd_mach_o_x86_64_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 263 const char *name ATTRIBUTE_UNUSED) 264{ 265 return NULL; 266} 267 268#define bfd_mach_o_swap_reloc_in bfd_mach_o_x86_64_swap_reloc_in 269#define bfd_mach_o_swap_reloc_out bfd_mach_o_x86_64_swap_reloc_out 270 271#define bfd_mach_o_bfd_reloc_type_lookup bfd_mach_o_x86_64_bfd_reloc_type_lookup 272#define bfd_mach_o_bfd_reloc_name_lookup bfd_mach_o_x86_64_bfd_reloc_name_lookup 273#define bfd_mach_o_print_thread NULL 274 275#define TARGET_NAME mach_o_x86_64_vec 276#define TARGET_STRING "mach-o-x86-64" 277#define TARGET_ARCHITECTURE bfd_arch_i386 278#define TARGET_BIG_ENDIAN 0 279#define TARGET_ARCHIVE 0 280#include "mach-o-target.c" 281