1 /* Intel i386 Mach-O support for BFD. 2 Copyright 2009 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_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 const bfd_target * 33 bfd_mach_o_i386_object_p (bfd *abfd) 34 { 35 return bfd_mach_o_header_p (abfd, 0, BFD_MACH_O_CPU_TYPE_I386); 36 } 37 38 static const bfd_target * 39 bfd_mach_o_i386_core_p (bfd *abfd) 40 { 41 return bfd_mach_o_header_p (abfd, 42 BFD_MACH_O_MH_CORE, BFD_MACH_O_CPU_TYPE_I386); 43 } 44 45 static bfd_boolean 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 HOWTO(BFD_RELOC_32, 0, 2, 32, FALSE, 0, 66 complain_overflow_bitfield, 67 NULL, "32", 68 FALSE, 0xffffffff, 0xffffffff, FALSE), 69 HOWTO(BFD_RELOC_16, 0, 1, 16, FALSE, 0, 70 complain_overflow_bitfield, 71 NULL, "16", 72 FALSE, 0xffff, 0xffff, FALSE), 73 HOWTO(BFD_RELOC_8, 0, 0, 8, FALSE, 0, 74 complain_overflow_bitfield, 75 NULL, "8", 76 FALSE, 0xff, 0xff, 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_16_PCREL, 0, 1, 16, TRUE, 0, 82 complain_overflow_bitfield, 83 NULL, "DISP16", 84 FALSE, 0xffff, 0xffff, TRUE), 85 HOWTO(BFD_RELOC_MACH_O_SECTDIFF, 0, 2, 32, FALSE, 0, 86 complain_overflow_bitfield, 87 NULL, "SECTDIFF_32", 88 FALSE, 0xffffffff, 0xffffffff, FALSE), 89 HOWTO(BFD_RELOC_MACH_O_PAIR, 0, 2, 32, FALSE, 0, 90 complain_overflow_bitfield, 91 NULL, "PAIR_32", 92 FALSE, 0xffffffff, 0xffffffff, FALSE), 93 }; 94 95 static bfd_boolean 96 bfd_mach_o_i386_swap_reloc_in (arelent *res, bfd_mach_o_reloc_info *reloc) 97 { 98 if (reloc->r_scattered) 99 { 100 switch (reloc->r_type) 101 { 102 case BFD_MACH_O_GENERIC_RELOC_PAIR: 103 if (reloc->r_length != 2) 104 return FALSE; 105 res->howto = &i386_howto_table[6]; 106 res->address = res[-1].address; 107 return TRUE; 108 case BFD_MACH_O_GENERIC_RELOC_SECTDIFF: 109 case BFD_MACH_O_GENERIC_RELOC_LOCAL_SECTDIFF: 110 if (reloc->r_length != 2) 111 return FALSE; 112 res->howto = &i386_howto_table[5]; 113 return TRUE; 114 default: 115 return FALSE; 116 } 117 } 118 else 119 { 120 switch (reloc->r_type) 121 { 122 case BFD_MACH_O_GENERIC_RELOC_VANILLA: 123 switch ((reloc->r_length << 1) | reloc->r_pcrel) 124 { 125 case 0: /* len = 0, pcrel = 0 */ 126 res->howto = &i386_howto_table[2]; 127 return TRUE; 128 case 2: /* len = 1, pcrel = 0 */ 129 res->howto = &i386_howto_table[1]; 130 return TRUE; 131 case 3: /* len = 1, pcrel = 1 */ 132 res->howto = &i386_howto_table[4]; 133 return TRUE; 134 case 4: /* len = 2, pcrel = 0 */ 135 res->howto = &i386_howto_table[0]; 136 return TRUE; 137 case 5: /* len = 2, pcrel = 1 */ 138 res->howto = &i386_howto_table[3]; 139 return TRUE; 140 default: 141 return FALSE; 142 } 143 break; 144 default: 145 return FALSE; 146 } 147 } 148 } 149 150 static bfd_boolean 151 bfd_mach_o_i386_swap_reloc_out (arelent *rel, bfd_mach_o_reloc_info *rinfo) 152 { 153 rinfo->r_address = rel->address; 154 switch (rel->howto->type) 155 { 156 case BFD_RELOC_32: 157 case BFD_RELOC_32_PCREL: 158 case BFD_RELOC_16: 159 case BFD_RELOC_16_PCREL: 160 case BFD_RELOC_8: 161 rinfo->r_scattered = 0; 162 rinfo->r_type = BFD_MACH_O_GENERIC_RELOC_VANILLA; 163 rinfo->r_pcrel = rel->howto->pc_relative; 164 rinfo->r_length = rel->howto->size; /* Correct in practice. */ 165 if ((*rel->sym_ptr_ptr)->flags & BSF_SECTION_SYM) 166 { 167 rinfo->r_extern = 0; 168 rinfo->r_value = (*rel->sym_ptr_ptr)->section->target_index; 169 } 170 else 171 { 172 rinfo->r_extern = 1; 173 rinfo->r_value = (*rel->sym_ptr_ptr)->udata.i; 174 } 175 break; 176 case BFD_RELOC_MACH_O_SECTDIFF: 177 rinfo->r_scattered = 1; 178 rinfo->r_type = BFD_MACH_O_GENERIC_RELOC_SECTDIFF; 179 rinfo->r_pcrel = 0; 180 rinfo->r_length = 2; 181 rinfo->r_extern = 0; 182 rinfo->r_value = (*rel->sym_ptr_ptr)->value 183 + (*rel->sym_ptr_ptr)->section->vma; 184 break; 185 case BFD_RELOC_MACH_O_PAIR: 186 rinfo->r_address = 0; 187 rinfo->r_scattered = 1; 188 rinfo->r_type = BFD_MACH_O_GENERIC_RELOC_PAIR; 189 rinfo->r_pcrel = 0; 190 rinfo->r_length = 2; 191 rinfo->r_extern = 0; 192 rinfo->r_value = (*rel->sym_ptr_ptr)->value 193 + (*rel->sym_ptr_ptr)->section->vma; 194 break; 195 default: 196 return FALSE; 197 } 198 return TRUE; 199 } 200 201 static reloc_howto_type * 202 bfd_mach_o_i386_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 203 bfd_reloc_code_real_type code) 204 { 205 unsigned int i; 206 207 for (i = 0; i < sizeof (i386_howto_table) / sizeof (*i386_howto_table); i++) 208 if (code == i386_howto_table[i].type) 209 return &i386_howto_table[i]; 210 return NULL; 211 } 212 213 static reloc_howto_type * 214 bfd_mach_o_i386_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 215 const char *name ATTRIBUTE_UNUSED) 216 { 217 return NULL; 218 } 219 220 static bfd_boolean 221 bfd_mach_o_i386_print_thread (bfd *abfd, bfd_mach_o_thread_flavour *thread, 222 void *vfile, char *buf) 223 { 224 FILE *file = (FILE *)vfile; 225 226 switch (thread->flavour) 227 { 228 case BFD_MACH_O_x86_THREAD_STATE: 229 if (thread->size < (8 + 16 * 4)) 230 return FALSE; 231 fprintf (file, " x86_THREAD_STATE:\n"); 232 fprintf (file, " flavor: 0x%08lx count: 0x%08lx\n", 233 (unsigned long)bfd_get_32 (abfd, buf + 0), 234 (unsigned long)bfd_get_32 (abfd, buf + 4)); 235 fprintf (file, " eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n", 236 (unsigned long)bfd_get_32 (abfd, buf + 8), 237 (unsigned long)bfd_get_32 (abfd, buf + 12), 238 (unsigned long)bfd_get_32 (abfd, buf + 16), 239 (unsigned long)bfd_get_32 (abfd, buf + 20)); 240 fprintf (file, " edi: %08lx esi: %08lx ebp: %08lx esp: %08lx\n", 241 (unsigned long)bfd_get_32 (abfd, buf + 24), 242 (unsigned long)bfd_get_32 (abfd, buf + 28), 243 (unsigned long)bfd_get_32 (abfd, buf + 32), 244 (unsigned long)bfd_get_32 (abfd, buf + 36)); 245 fprintf (file, " ss: %08lx flg: %08lx eip: %08lx cs: %08lx\n", 246 (unsigned long)bfd_get_32 (abfd, buf + 40), 247 (unsigned long)bfd_get_32 (abfd, buf + 44), 248 (unsigned long)bfd_get_32 (abfd, buf + 48), 249 (unsigned long)bfd_get_32 (abfd, buf + 52)); 250 fprintf (file, " ds: %08lx es: %08lx fs: %08lx gs: %08lx\n", 251 (unsigned long)bfd_get_32 (abfd, buf + 56), 252 (unsigned long)bfd_get_32 (abfd, buf + 60), 253 (unsigned long)bfd_get_32 (abfd, buf + 64), 254 (unsigned long)bfd_get_32 (abfd, buf + 68)); 255 return TRUE; 256 case BFD_MACH_O_x86_FLOAT_STATE: 257 if (thread->size < 8) 258 return FALSE; 259 fprintf (file, " x86_FLOAT_STATE:\n"); 260 fprintf (file, " flavor: 0x%08lx count: 0x%08lx\n", 261 (unsigned long)bfd_get_32 (abfd, buf + 0), 262 (unsigned long)bfd_get_32 (abfd, buf + 4)); 263 return TRUE; 264 case BFD_MACH_O_x86_EXCEPTION_STATE: 265 if (thread->size < 8 + 3 * 4) 266 return FALSE; 267 fprintf (file, " x86_EXCEPTION_STATE:\n"); 268 fprintf (file, " flavor: 0x%08lx count: 0x%08lx\n", 269 (unsigned long)bfd_get_32 (abfd, buf + 0), 270 (unsigned long)bfd_get_32 (abfd, buf + 4)); 271 fprintf (file, " trapno: %08lx err: %08lx faultaddr: %08lx\n", 272 (unsigned long)bfd_get_32 (abfd, buf + 8), 273 (unsigned long)bfd_get_32 (abfd, buf + 12), 274 (unsigned long)bfd_get_32 (abfd, buf + 16)); 275 return TRUE; 276 default: 277 break; 278 } 279 return FALSE; 280 } 281 282 #define bfd_mach_o_swap_reloc_in bfd_mach_o_i386_swap_reloc_in 283 #define bfd_mach_o_swap_reloc_out bfd_mach_o_i386_swap_reloc_out 284 #define bfd_mach_o_print_thread bfd_mach_o_i386_print_thread 285 286 #define bfd_mach_o_bfd_reloc_type_lookup bfd_mach_o_i386_bfd_reloc_type_lookup 287 #define bfd_mach_o_bfd_reloc_name_lookup bfd_mach_o_i386_bfd_reloc_name_lookup 288 289 #define TARGET_NAME mach_o_i386_vec 290 #define TARGET_STRING "mach-o-i386" 291 #define TARGET_ARCHITECTURE bfd_arch_i386 292 #define TARGET_BIG_ENDIAN 0 293 #define TARGET_ARCHIVE 0 294 #include "mach-o-target.c" 295