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