00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "mach-o.h"
00026 #include "bfd.h"
00027 #include "sysdep.h"
00028 #include "libbfd.h"
00029 #include "libiberty.h"
00030 #include <ctype.h>
00031
00032 #ifndef BFD_IO_FUNCS
00033 #define BFD_IO_FUNCS 0
00034 #endif
00035
00036 #define bfd_mach_o_mkarchive _bfd_noarchive_mkarchive
00037 #define bfd_mach_o_read_ar_hdr _bfd_noarchive_read_ar_hdr
00038 #define bfd_mach_o_slurp_armap _bfd_noarchive_slurp_armap
00039 #define bfd_mach_o_slurp_extended_name_table _bfd_noarchive_slurp_extended_name_table
00040 #define bfd_mach_o_construct_extended_name_table _bfd_noarchive_construct_extended_name_table
00041 #define bfd_mach_o_truncate_arname _bfd_noarchive_truncate_arname
00042 #define bfd_mach_o_write_armap _bfd_noarchive_write_armap
00043 #define bfd_mach_o_get_elt_at_index _bfd_noarchive_get_elt_at_index
00044 #define bfd_mach_o_generic_stat_arch_elt _bfd_noarchive_generic_stat_arch_elt
00045 #define bfd_mach_o_update_armap_timestamp _bfd_noarchive_update_armap_timestamp
00046 #define bfd_mach_o_close_and_cleanup _bfd_generic_close_and_cleanup
00047 #define bfd_mach_o_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
00048 #define bfd_mach_o_new_section_hook _bfd_generic_new_section_hook
00049 #define bfd_mach_o_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
00050 #define bfd_mach_o_bfd_is_local_label_name _bfd_nosymbols_bfd_is_local_label_name
00051 #define bfd_mach_o_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
00052 #define bfd_mach_o_bfd_is_local_label_name _bfd_nosymbols_bfd_is_local_label_name
00053 #define bfd_mach_o_get_lineno _bfd_nosymbols_get_lineno
00054 #define bfd_mach_o_find_nearest_line _bfd_nosymbols_find_nearest_line
00055 #define bfd_mach_o_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
00056 #define bfd_mach_o_read_minisymbols _bfd_generic_read_minisymbols
00057 #define bfd_mach_o_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
00058 #define bfd_mach_o_get_reloc_upper_bound _bfd_norelocs_get_reloc_upper_bound
00059 #define bfd_mach_o_canonicalize_reloc _bfd_norelocs_canonicalize_reloc
00060 #define bfd_mach_o_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
00061 #define bfd_mach_o_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
00062 #define bfd_mach_o_bfd_relax_section bfd_generic_relax_section
00063 #define bfd_mach_o_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
00064 #define bfd_mach_o_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
00065 #define bfd_mach_o_bfd_link_add_symbols _bfd_generic_link_add_symbols
00066 #define bfd_mach_o_bfd_link_just_syms _bfd_generic_link_just_syms
00067 #define bfd_mach_o_bfd_final_link _bfd_generic_final_link
00068 #define bfd_mach_o_bfd_link_split_section _bfd_generic_link_split_section
00069 #define bfd_mach_o_set_arch_mach bfd_default_set_arch_mach
00070 #define bfd_mach_o_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data
00071 #define bfd_mach_o_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
00072 #define bfd_mach_o_bfd_print_private_bfd_data _bfd_generic_bfd_print_private_bfd_data
00073 #define bfd_mach_o_get_section_contents _bfd_generic_get_section_contents
00074 #define bfd_mach_o_set_section_contents _bfd_generic_set_section_contents
00075 #define bfd_mach_o_bfd_gc_sections bfd_generic_gc_sections
00076 #define bfd_mach_o_bfd_merge_sections bfd_generic_merge_sections
00077 #define bfd_mach_o_bfd_is_group_section bfd_generic_is_group_section
00078 #define bfd_mach_o_bfd_discard_group bfd_generic_discard_group
00079 #define bfd_mach_o_section_already_linked \
00080 _bfd_generic_section_already_linked
00081 #define bfd_mach_o_bfd_copy_private_header_data _bfd_generic_bfd_copy_private_header_data
00082
00083 static bfd_boolean bfd_mach_o_bfd_copy_private_symbol_data
00084 PARAMS ((bfd *, asymbol *, bfd *, asymbol *));
00085 static bfd_boolean bfd_mach_o_bfd_copy_private_section_data
00086 PARAMS ((bfd *, asection *, bfd *, asection *));
00087 static bfd_boolean bfd_mach_o_bfd_copy_private_bfd_data
00088 PARAMS ((bfd *, bfd *));
00089 static long bfd_mach_o_count_symbols
00090 PARAMS ((bfd *));
00091 static long bfd_mach_o_get_symtab_upper_bound
00092 PARAMS ((bfd *));
00093 static long bfd_mach_o_canonicalize_symtab
00094 PARAMS ((bfd *, asymbol **));
00095 static void bfd_mach_o_get_symbol_info
00096 PARAMS ((bfd *, asymbol *, symbol_info *));
00097 static void bfd_mach_o_print_symbol
00098 PARAMS ((bfd *, PTR, asymbol *, bfd_print_symbol_type));
00099 static void bfd_mach_o_convert_architecture
00100 PARAMS ((bfd_mach_o_cpu_type, bfd_mach_o_cpu_subtype,
00101 enum bfd_architecture *, unsigned long *));
00102 static bfd_boolean bfd_mach_o_write_contents
00103 PARAMS ((bfd *));
00104 static int bfd_mach_o_sizeof_headers
00105 PARAMS ((bfd *, bfd_boolean));
00106 static asymbol * bfd_mach_o_make_empty_symbol
00107 PARAMS ((bfd *));
00108 static int bfd_mach_o_write_header
00109 PARAMS ((bfd *, bfd_mach_o_header *));
00110 static int bfd_mach_o_read_header
00111 PARAMS ((bfd *, bfd_mach_o_header *));
00112 static asection * bfd_mach_o_make_bfd_section
00113 PARAMS ((bfd *, bfd_mach_o_section *));
00114 static int bfd_mach_o_scan_read_section
00115 PARAMS ((bfd *, bfd_mach_o_section *, bfd_vma));
00116 static int bfd_mach_o_scan_write_section
00117 PARAMS ((bfd *, bfd_mach_o_section *, bfd_vma));
00118 static int bfd_mach_o_scan_write_symtab_symbols
00119 PARAMS ((bfd *, bfd_mach_o_load_command *));
00120 static int bfd_mach_o_scan_write_thread
00121 PARAMS ((bfd *, bfd_mach_o_load_command *));
00122 static int bfd_mach_o_scan_read_dylinker
00123 PARAMS ((bfd *, bfd_mach_o_load_command *));
00124 static int bfd_mach_o_scan_read_dylib
00125 PARAMS ((bfd *, bfd_mach_o_load_command *));
00126 static int bfd_mach_o_scan_read_prebound_dylib
00127 PARAMS ((bfd *, bfd_mach_o_load_command *));
00128 static int bfd_mach_o_scan_read_thread
00129 PARAMS ((bfd *, bfd_mach_o_load_command *));
00130 static int bfd_mach_o_scan_write_symtab
00131 PARAMS ((bfd *, bfd_mach_o_load_command *));
00132 static int bfd_mach_o_scan_read_dysymtab
00133 PARAMS ((bfd *, bfd_mach_o_load_command *));
00134 static int bfd_mach_o_scan_read_symtab
00135 PARAMS ((bfd *, bfd_mach_o_load_command *));
00136 static int bfd_mach_o_scan_read_segment
00137 PARAMS ((bfd *, bfd_mach_o_load_command *));
00138 static int bfd_mach_o_scan_write_segment
00139 PARAMS ((bfd *, bfd_mach_o_load_command *));
00140 static int bfd_mach_o_scan_read_command
00141 PARAMS ((bfd *, bfd_mach_o_load_command *));
00142 static void bfd_mach_o_flatten_sections
00143 PARAMS ((bfd *));
00144 static const char * bfd_mach_o_i386_flavour_string
00145 PARAMS ((unsigned int));
00146 static const char * bfd_mach_o_ppc_flavour_string
00147 PARAMS ((unsigned int));
00148
00149
00150
00151
00152
00153
00154 #define SECTION_TYPE 0x000000ff
00155 #define SECTION_ATTRIBUTES 0xffffff00
00156
00157
00158
00159
00160 #define SECTION_ATTRIBUTES_USR 0xff000000
00161 #define S_ATTR_PURE_INSTRUCTIONS 0x80000000
00162 #define SECTION_ATTRIBUTES_SYS 0x00ffff00
00163 #define S_ATTR_SOME_INSTRUCTIONS 0x00000400
00164 #define S_ATTR_EXT_RELOC 0x00000200
00165 #define S_ATTR_LOC_RELOC 0x00000100
00166
00167 #define N_STAB 0xe0
00168 #define N_TYPE 0x1e
00169 #define N_EXT 0x01
00170 #define N_UNDF 0x0
00171 #define N_ABS 0x2
00172 #define N_SECT 0xe
00173 #define N_INDR 0xa
00174
00175 bfd_boolean
00176 bfd_mach_o_valid (abfd)
00177 bfd *abfd;
00178 {
00179 if (abfd == NULL || abfd->xvec == NULL)
00180 return 0;
00181
00182 if (! ((abfd->xvec == &mach_o_be_vec)
00183 || (abfd->xvec == &mach_o_le_vec)
00184 || (abfd->xvec == &mach_o_fat_vec)))
00185 return 0;
00186
00187 if (abfd->tdata.mach_o_data == NULL)
00188 return 0;
00189 return 1;
00190 }
00191
00192
00193
00194
00195 static bfd_boolean
00196 bfd_mach_o_bfd_copy_private_symbol_data (ibfd, isymbol, obfd, osymbol)
00197 bfd *ibfd ATTRIBUTE_UNUSED;
00198 asymbol *isymbol ATTRIBUTE_UNUSED;
00199 bfd *obfd ATTRIBUTE_UNUSED;
00200 asymbol *osymbol ATTRIBUTE_UNUSED;
00201 {
00202 return TRUE;
00203 }
00204
00205
00206
00207
00208 static bfd_boolean
00209 bfd_mach_o_bfd_copy_private_section_data (ibfd, isection, obfd, osection)
00210 bfd *ibfd ATTRIBUTE_UNUSED;
00211 asection *isection ATTRIBUTE_UNUSED;
00212 bfd *obfd ATTRIBUTE_UNUSED;
00213 asection *osection ATTRIBUTE_UNUSED;
00214 {
00215 return TRUE;
00216 }
00217
00218
00219
00220
00221 static bfd_boolean
00222 bfd_mach_o_bfd_copy_private_bfd_data (ibfd, obfd)
00223 bfd *ibfd;
00224 bfd *obfd;
00225 {
00226 BFD_ASSERT (bfd_mach_o_valid (ibfd));
00227 BFD_ASSERT (bfd_mach_o_valid (obfd));
00228
00229 obfd->tdata.mach_o_data = ibfd->tdata.mach_o_data;
00230 obfd->tdata.mach_o_data->ibfd = ibfd;
00231 return TRUE;
00232 }
00233
00234 static long
00235 bfd_mach_o_count_symbols (abfd)
00236 bfd *abfd;
00237 {
00238 bfd_mach_o_data_struct *mdata = NULL;
00239 long nsyms = 0;
00240 unsigned long i;
00241
00242 BFD_ASSERT (bfd_mach_o_valid (abfd));
00243 mdata = abfd->tdata.mach_o_data;
00244
00245 for (i = 0; i < mdata->header.ncmds; i++)
00246 if (mdata->commands[i].type == BFD_MACH_O_LC_SYMTAB)
00247 {
00248 bfd_mach_o_symtab_command *sym = &mdata->commands[i].command.symtab;
00249 nsyms += sym->nsyms;
00250 }
00251
00252 return nsyms;
00253 }
00254
00255 static long
00256 bfd_mach_o_get_symtab_upper_bound (abfd)
00257 bfd *abfd;
00258 {
00259 long nsyms = bfd_mach_o_count_symbols (abfd);
00260
00261 if (nsyms < 0)
00262 return nsyms;
00263
00264 return ((nsyms + 1) * sizeof (asymbol *));
00265 }
00266
00267 static long
00268 bfd_mach_o_canonicalize_symtab (abfd, alocation)
00269 bfd *abfd;
00270 asymbol **alocation;
00271 {
00272 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
00273 long nsyms = bfd_mach_o_count_symbols (abfd);
00274 asymbol **csym = alocation;
00275 unsigned long i, j;
00276
00277 if (nsyms < 0)
00278 return nsyms;
00279
00280 for (i = 0; i < mdata->header.ncmds; i++)
00281 {
00282 if (mdata->commands[i].type == BFD_MACH_O_LC_SYMTAB)
00283 {
00284 bfd_mach_o_symtab_command *sym = &mdata->commands[i].command.symtab;
00285
00286 if (bfd_mach_o_scan_read_symtab_symbols (abfd, &mdata->commands[i].command.symtab) != 0)
00287 {
00288 fprintf (stderr, "bfd_mach_o_canonicalize_symtab: unable to load symbols for section %lu\n", i);
00289 return 0;
00290 }
00291
00292 BFD_ASSERT (sym->symbols != NULL);
00293
00294 for (j = 0; j < sym->nsyms; j++)
00295 {
00296 BFD_ASSERT (csym < (alocation + nsyms));
00297 *csym++ = &sym->symbols[j];
00298 }
00299 }
00300 }
00301
00302 *csym++ = NULL;
00303
00304 return nsyms;
00305 }
00306
00307 static void
00308 bfd_mach_o_get_symbol_info (abfd, symbol, ret)
00309 bfd *abfd ATTRIBUTE_UNUSED;
00310 asymbol *symbol;
00311 symbol_info *ret;
00312 {
00313 bfd_symbol_info (symbol, ret);
00314 }
00315
00316 static void
00317 bfd_mach_o_print_symbol (abfd, afile, symbol, how)
00318 bfd *abfd;
00319 PTR afile;
00320 asymbol *symbol;
00321 bfd_print_symbol_type how;
00322 {
00323 FILE *file = (FILE *) afile;
00324
00325 switch (how)
00326 {
00327 case bfd_print_symbol_name:
00328 fprintf (file, "%s", symbol->name);
00329 break;
00330 default:
00331 bfd_print_symbol_vandf (abfd, (PTR) file, symbol);
00332 fprintf (file, " %-5s %s", symbol->section->name, symbol->name);
00333 }
00334 }
00335
00336 static void
00337 bfd_mach_o_convert_architecture (mtype, msubtype, type, subtype)
00338 bfd_mach_o_cpu_type mtype;
00339 bfd_mach_o_cpu_subtype msubtype ATTRIBUTE_UNUSED;
00340 enum bfd_architecture *type;
00341 unsigned long *subtype;
00342 {
00343 *subtype = bfd_arch_unknown;
00344
00345 switch (mtype)
00346 {
00347 case BFD_MACH_O_CPU_TYPE_VAX: *type = bfd_arch_vax; break;
00348 case BFD_MACH_O_CPU_TYPE_MC680x0: *type = bfd_arch_m68k; break;
00349 case BFD_MACH_O_CPU_TYPE_I386: *type = bfd_arch_i386; break;
00350 case BFD_MACH_O_CPU_TYPE_MIPS: *type = bfd_arch_mips; break;
00351 case BFD_MACH_O_CPU_TYPE_MC98000: *type = bfd_arch_m98k; break;
00352 case BFD_MACH_O_CPU_TYPE_HPPA: *type = bfd_arch_hppa; break;
00353 case BFD_MACH_O_CPU_TYPE_ARM: *type = bfd_arch_arm; break;
00354 case BFD_MACH_O_CPU_TYPE_MC88000: *type = bfd_arch_m88k; break;
00355 case BFD_MACH_O_CPU_TYPE_SPARC: *type = bfd_arch_sparc; break;
00356 case BFD_MACH_O_CPU_TYPE_I860: *type = bfd_arch_i860; break;
00357 case BFD_MACH_O_CPU_TYPE_ALPHA: *type = bfd_arch_alpha; break;
00358 case BFD_MACH_O_CPU_TYPE_POWERPC: *type = bfd_arch_powerpc; break;
00359 default: *type = bfd_arch_unknown; break;
00360 }
00361
00362 switch (*type)
00363 {
00364 case bfd_arch_i386: *subtype = bfd_mach_i386_i386; break;
00365 case bfd_arch_sparc: *subtype = bfd_mach_sparc; break;
00366 default:
00367 *subtype = bfd_arch_unknown;
00368 }
00369 }
00370
00371 static bfd_boolean
00372 bfd_mach_o_write_contents (abfd)
00373 bfd *abfd;
00374 {
00375 unsigned int i;
00376 asection *s;
00377
00378 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
00379
00380
00381
00382
00383 for (s = abfd->sections; s != (asection *) NULL; s = s->next)
00384 ;
00385
00386
00387 if (bfd_mach_o_write_header (abfd, &mdata->header) != 0)
00388 return FALSE;
00389
00390 for (i = 0; i < mdata->header.ncmds; i++)
00391 {
00392 unsigned char buf[8];
00393 bfd_mach_o_load_command *cur = &mdata->commands[i];
00394 unsigned long typeflag;
00395
00396 typeflag = cur->type_required ? cur->type & BFD_MACH_O_LC_REQ_DYLD : cur->type;
00397
00398 bfd_h_put_32 (abfd, typeflag, buf);
00399 bfd_h_put_32 (abfd, cur->len, buf + 4);
00400
00401 bfd_seek (abfd, cur->offset, SEEK_SET);
00402 if (bfd_bwrite ((PTR) buf, 8, abfd) != 8)
00403 return FALSE;
00404
00405 switch (cur->type)
00406 {
00407 case BFD_MACH_O_LC_SEGMENT:
00408 if (bfd_mach_o_scan_write_segment (abfd, cur) != 0)
00409 return FALSE;
00410 break;
00411 case BFD_MACH_O_LC_SYMTAB:
00412 if (bfd_mach_o_scan_write_symtab (abfd, cur) != 0)
00413 return FALSE;
00414 break;
00415 case BFD_MACH_O_LC_SYMSEG:
00416 break;
00417 case BFD_MACH_O_LC_THREAD:
00418 case BFD_MACH_O_LC_UNIXTHREAD:
00419 if (bfd_mach_o_scan_write_thread (abfd, cur) != 0)
00420 return FALSE;
00421 break;
00422 case BFD_MACH_O_LC_LOADFVMLIB:
00423 case BFD_MACH_O_LC_IDFVMLIB:
00424 case BFD_MACH_O_LC_IDENT:
00425 case BFD_MACH_O_LC_FVMFILE:
00426 case BFD_MACH_O_LC_PREPAGE:
00427 case BFD_MACH_O_LC_DYSYMTAB:
00428 case BFD_MACH_O_LC_LOAD_DYLIB:
00429 case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
00430 case BFD_MACH_O_LC_ID_DYLIB:
00431 case BFD_MACH_O_LC_LOAD_DYLINKER:
00432 case BFD_MACH_O_LC_ID_DYLINKER:
00433 case BFD_MACH_O_LC_PREBOUND_DYLIB:
00434 case BFD_MACH_O_LC_ROUTINES:
00435 case BFD_MACH_O_LC_SUB_FRAMEWORK:
00436 break;
00437 default:
00438 fprintf (stderr,
00439 "unable to write unknown load command 0x%lx\n",
00440 (long) cur->type);
00441 return FALSE;
00442 }
00443 }
00444
00445 return TRUE;
00446 }
00447
00448 static int
00449 bfd_mach_o_sizeof_headers (a, b)
00450 bfd *a ATTRIBUTE_UNUSED;
00451 bfd_boolean b ATTRIBUTE_UNUSED;
00452 {
00453 return 0;
00454 }
00455
00456
00457
00458
00459 static asymbol *
00460 bfd_mach_o_make_empty_symbol (abfd)
00461 bfd *abfd;
00462 {
00463 asymbol *new;
00464
00465 new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol));
00466 if (new == NULL)
00467 return new;
00468 new->the_bfd = abfd;
00469 return new;
00470 }
00471
00472 static int
00473 bfd_mach_o_write_header (abfd, header)
00474 bfd *abfd;
00475 bfd_mach_o_header *header;
00476 {
00477 unsigned char buf[28];
00478
00479 bfd_h_put_32 (abfd, header->magic, buf + 0);
00480 bfd_h_put_32 (abfd, header->cputype, buf + 4);
00481 bfd_h_put_32 (abfd, header->cpusubtype, buf + 8);
00482 bfd_h_put_32 (abfd, header->filetype, buf + 12);
00483 bfd_h_put_32 (abfd, header->ncmds, buf + 16);
00484 bfd_h_put_32 (abfd, header->sizeofcmds, buf + 20);
00485 bfd_h_put_32 (abfd, header->flags, buf + 24);
00486
00487 bfd_seek (abfd, 0, SEEK_SET);
00488 if (bfd_bwrite ((PTR) buf, 28, abfd) != 28)
00489 return -1;
00490
00491 return 0;
00492 }
00493
00494 static int
00495 bfd_mach_o_read_header (abfd, header)
00496 bfd *abfd;
00497 bfd_mach_o_header *header;
00498 {
00499 unsigned char buf[28];
00500 bfd_vma (*get32) (const void *) = NULL;
00501
00502 bfd_seek (abfd, 0, SEEK_SET);
00503
00504 if (bfd_bread ((PTR) buf, 28, abfd) != 28)
00505 return -1;
00506
00507 if (bfd_getb32 (buf) == 0xfeedface)
00508 {
00509 header->byteorder = BFD_ENDIAN_BIG;
00510 header->magic = 0xfeedface;
00511 get32 = bfd_getb32;
00512 }
00513 else if (bfd_getl32 (buf) == 0xfeedface)
00514 {
00515 header->byteorder = BFD_ENDIAN_LITTLE;
00516 header->magic = 0xfeedface;
00517 get32 = bfd_getl32;
00518 }
00519 else
00520 {
00521 header->byteorder = BFD_ENDIAN_UNKNOWN;
00522 return -1;
00523 }
00524
00525 header->cputype = (*get32) (buf + 4);
00526 header->cpusubtype = (*get32) (buf + 8);
00527 header->filetype = (*get32) (buf + 12);
00528 header->ncmds = (*get32) (buf + 16);
00529 header->sizeofcmds = (*get32) (buf + 20);
00530 header->flags = (*get32) (buf + 24);
00531
00532 return 0;
00533 }
00534
00535 static asection *
00536 bfd_mach_o_make_bfd_section (abfd, section)
00537 bfd *abfd;
00538 bfd_mach_o_section *section;
00539 {
00540 asection *bfdsec;
00541 char *sname;
00542 const char *prefix = "LC_SEGMENT";
00543 unsigned int snamelen;
00544
00545 snamelen = strlen (prefix) + 1
00546 + strlen (section->segname) + 1
00547 + strlen (section->sectname) + 1;
00548
00549 sname = (char *) bfd_alloc (abfd, snamelen);
00550 if (sname == NULL)
00551 return NULL;
00552 sprintf (sname, "%s.%s.%s", prefix, section->segname, section->sectname);
00553
00554 bfdsec = bfd_make_section_anyway (abfd, sname);
00555 if (bfdsec == NULL)
00556 return NULL;
00557
00558 bfdsec->vma = section->addr;
00559 bfdsec->lma = section->addr;
00560 bfdsec->size = section->size;
00561 bfdsec->filepos = section->offset;
00562 bfdsec->alignment_power = section->align;
00563
00564 if (section->flags & BFD_MACH_O_S_ZEROFILL)
00565 bfdsec->flags = SEC_ALLOC;
00566 else
00567 bfdsec->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC | SEC_CODE;
00568
00569 return bfdsec;
00570 }
00571
00572 static int
00573 bfd_mach_o_scan_read_section (abfd, section, offset)
00574 bfd *abfd;
00575 bfd_mach_o_section *section;
00576 bfd_vma offset;
00577 {
00578 unsigned char buf[68];
00579
00580 bfd_seek (abfd, offset, SEEK_SET);
00581 if (bfd_bread ((PTR) buf, 68, abfd) != 68)
00582 return -1;
00583
00584 memcpy (section->sectname, buf, 16);
00585 section->sectname[16] = '\0';
00586 memcpy (section->segname, buf + 16, 16);
00587 section->segname[16] = '\0';
00588 section->addr = bfd_h_get_32 (abfd, buf + 32);
00589 section->size = bfd_h_get_32 (abfd, buf + 36);
00590 section->offset = bfd_h_get_32 (abfd, buf + 40);
00591 section->align = bfd_h_get_32 (abfd, buf + 44);
00592 section->reloff = bfd_h_get_32 (abfd, buf + 48);
00593 section->nreloc = bfd_h_get_32 (abfd, buf + 52);
00594 section->flags = bfd_h_get_32 (abfd, buf + 56);
00595 section->reserved1 = bfd_h_get_32 (abfd, buf + 60);
00596 section->reserved2 = bfd_h_get_32 (abfd, buf + 64);
00597 section->bfdsection = bfd_mach_o_make_bfd_section (abfd, section);
00598
00599 if (section->bfdsection == NULL)
00600 return -1;
00601
00602 return 0;
00603 }
00604
00605 static int
00606 bfd_mach_o_scan_write_section (abfd, section, offset)
00607 bfd *abfd;
00608 bfd_mach_o_section *section;
00609 bfd_vma offset;
00610 {
00611 unsigned char buf[68];
00612
00613 memcpy (buf, section->sectname, 16);
00614 memcpy (buf + 16, section->segname, 16);
00615 bfd_h_put_32 (abfd, section->addr, buf + 32);
00616 bfd_h_put_32 (abfd, section->size, buf + 36);
00617 bfd_h_put_32 (abfd, section->offset, buf + 40);
00618 bfd_h_put_32 (abfd, section->align, buf + 44);
00619 bfd_h_put_32 (abfd, section->reloff, buf + 48);
00620 bfd_h_put_32 (abfd, section->nreloc, buf + 52);
00621 bfd_h_put_32 (abfd, section->flags, buf + 56);
00622
00623
00624
00625 bfd_seek (abfd, offset, SEEK_SET);
00626 if (bfd_bwrite ((PTR) buf, 68, abfd) != 68)
00627 return -1;
00628
00629 return 0;
00630 }
00631
00632 static int
00633 bfd_mach_o_scan_write_symtab_symbols (abfd, command)
00634 bfd *abfd;
00635 bfd_mach_o_load_command *command;
00636 {
00637 bfd_mach_o_symtab_command *sym = &command->command.symtab;
00638 asymbol *s = NULL;
00639 unsigned long i;
00640
00641 for (i = 0; i < sym->nsyms; i++)
00642 {
00643 unsigned char buf[12];
00644 bfd_vma symoff = sym->symoff + (i * 12);
00645 unsigned char ntype = 0;
00646 unsigned char nsect = 0;
00647 short ndesc = 0;
00648
00649 s = &sym->symbols[i];
00650
00651
00652 ntype = (s->udata.i >> 24) & 0xff;
00653 nsect = (s->udata.i >> 16) & 0xff;
00654 ndesc = s->udata.i & 0xffff;
00655
00656 bfd_h_put_32 (abfd, s->name - sym->strtab, buf);
00657 bfd_h_put_8 (abfd, ntype, buf + 4);
00658 bfd_h_put_8 (abfd, nsect, buf + 5);
00659 bfd_h_put_16 (abfd, ndesc, buf + 6);
00660 bfd_h_put_32 (abfd, s->section->vma + s->value, buf + 8);
00661
00662 bfd_seek (abfd, symoff, SEEK_SET);
00663 if (bfd_bwrite ((PTR) buf, 12, abfd) != 12)
00664 {
00665 fprintf (stderr, "bfd_mach_o_scan_write_symtab_symbols: unable to write %d bytes at %lu\n",
00666 12, (unsigned long) symoff);
00667 return -1;
00668 }
00669 }
00670
00671 return 0;
00672 }
00673
00674 int
00675 bfd_mach_o_scan_read_symtab_symbol (abfd, sym, s, i)
00676 bfd *abfd;
00677 bfd_mach_o_symtab_command *sym;
00678 asymbol *s;
00679 unsigned long i;
00680 {
00681 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
00682 bfd_vma symoff = sym->symoff + (i * 12);
00683 unsigned char buf[12];
00684 unsigned char type = -1;
00685 unsigned char section = -1;
00686 short desc = -1;
00687 unsigned long value = -1;
00688 unsigned long stroff = -1;
00689 unsigned int symtype = -1;
00690
00691 BFD_ASSERT (sym->strtab != NULL);
00692
00693 bfd_seek (abfd, symoff, SEEK_SET);
00694 if (bfd_bread ((PTR) buf, 12, abfd) != 12)
00695 {
00696 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: unable to read %d bytes at %lu\n",
00697 12, (unsigned long) symoff);
00698 return -1;
00699 }
00700
00701 stroff = bfd_h_get_32 (abfd, buf);
00702 type = bfd_h_get_8 (abfd, buf + 4);
00703 symtype = (type & 0x0e);
00704 section = bfd_h_get_8 (abfd, buf + 5) - 1;
00705 desc = bfd_h_get_16 (abfd, buf + 6);
00706 value = bfd_h_get_32 (abfd, buf + 8);
00707
00708 if (stroff >= sym->strsize)
00709 {
00710 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: symbol name out of range (%lu >= %lu)\n",
00711 (unsigned long) stroff, (unsigned long) sym->strsize);
00712 return -1;
00713 }
00714
00715 s->the_bfd = abfd;
00716 s->name = sym->strtab + stroff;
00717 s->value = value;
00718 s->udata.i = (type << 24) | (section << 16) | desc;
00719 s->flags = 0x0;
00720
00721 if (type & BFD_MACH_O_N_STAB)
00722 {
00723 s->flags |= BSF_DEBUGGING;
00724 s->section = bfd_und_section_ptr;
00725 }
00726 else
00727 {
00728 if (type & BFD_MACH_O_N_PEXT)
00729 {
00730 type &= ~BFD_MACH_O_N_PEXT;
00731 s->flags |= BSF_GLOBAL;
00732 }
00733
00734 if (type & BFD_MACH_O_N_EXT)
00735 {
00736 type &= ~BFD_MACH_O_N_EXT;
00737 s->flags |= BSF_GLOBAL;
00738 }
00739
00740 switch (symtype)
00741 {
00742 case BFD_MACH_O_N_UNDF:
00743 s->section = bfd_und_section_ptr;
00744 break;
00745 case BFD_MACH_O_N_PBUD:
00746 s->section = bfd_und_section_ptr;
00747 break;
00748 case BFD_MACH_O_N_ABS:
00749 s->section = bfd_abs_section_ptr;
00750 break;
00751 case BFD_MACH_O_N_SECT:
00752 if ((section > 0) && (section <= mdata->nsects))
00753 {
00754 s->section = mdata->sections[section - 1]->bfdsection;
00755 s->value = s->value - mdata->sections[section - 1]->addr;
00756 }
00757 else
00758 {
00759
00760 if (section != 0)
00761 {
00762 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: "
00763 "symbol \"%s\" specified invalid section %d (max %lu): setting to undefined\n",
00764 s->name, section, mdata->nsects);
00765 }
00766 s->section = bfd_und_section_ptr;
00767 }
00768 break;
00769 case BFD_MACH_O_N_INDR:
00770 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: "
00771 "symbol \"%s\" is unsupported 'indirect' reference: setting to undefined\n",
00772 s->name);
00773 s->section = bfd_und_section_ptr;
00774 break;
00775 default:
00776 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: "
00777 "symbol \"%s\" specified invalid type field 0x%x: setting to undefined\n",
00778 s->name, symtype);
00779 s->section = bfd_und_section_ptr;
00780 break;
00781 }
00782 }
00783
00784 return 0;
00785 }
00786
00787 int
00788 bfd_mach_o_scan_read_symtab_strtab (abfd, sym)
00789 bfd *abfd;
00790 bfd_mach_o_symtab_command *sym;
00791 {
00792 BFD_ASSERT (sym->strtab == NULL);
00793
00794 if (abfd->flags & BFD_IN_MEMORY)
00795 {
00796 struct bfd_in_memory *b;
00797
00798 b = (struct bfd_in_memory *) abfd->iostream;
00799
00800 if ((sym->stroff + sym->strsize) > b->size)
00801 {
00802 bfd_set_error (bfd_error_file_truncated);
00803 return -1;
00804 }
00805 sym->strtab = (char *) b->buffer + sym->stroff;
00806 return 0;
00807 }
00808
00809 sym->strtab = bfd_alloc (abfd, sym->strsize);
00810 if (sym->strtab == NULL)
00811 return -1;
00812
00813 bfd_seek (abfd, sym->stroff, SEEK_SET);
00814 if (bfd_bread ((PTR) sym->strtab, sym->strsize, abfd) != sym->strsize)
00815 {
00816 fprintf (stderr, "bfd_mach_o_scan_read_symtab_strtab: unable to read %lu bytes at %lu\n",
00817 sym->strsize, sym->stroff);
00818 return -1;
00819 }
00820
00821 return 0;
00822 }
00823
00824 int
00825 bfd_mach_o_scan_read_symtab_symbols (abfd, sym)
00826 bfd *abfd;
00827 bfd_mach_o_symtab_command *sym;
00828 {
00829 unsigned long i;
00830 int ret;
00831
00832 BFD_ASSERT (sym->symbols == NULL);
00833 sym->symbols = bfd_alloc (abfd, sym->nsyms * sizeof (asymbol));
00834
00835 if (sym->symbols == NULL)
00836 {
00837 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbols: unable to allocate memory for symbols\n");
00838 return -1;
00839 }
00840
00841 ret = bfd_mach_o_scan_read_symtab_strtab (abfd, sym);
00842 if (ret != 0)
00843 return ret;
00844
00845 for (i = 0; i < sym->nsyms; i++)
00846 {
00847 ret = bfd_mach_o_scan_read_symtab_symbol (abfd, sym, &sym->symbols[i], i);
00848 if (ret != 0)
00849 return ret;
00850 }
00851
00852 return 0;
00853 }
00854
00855 int
00856 bfd_mach_o_scan_read_dysymtab_symbol (abfd, dysym, sym, s, i)
00857 bfd *abfd;
00858 bfd_mach_o_dysymtab_command *dysym;
00859 bfd_mach_o_symtab_command *sym;
00860 asymbol *s;
00861 unsigned long i;
00862 {
00863 unsigned long isymoff = dysym->indirectsymoff + (i * 4);
00864 unsigned long symindex;
00865 unsigned char buf[4];
00866
00867 BFD_ASSERT (i < dysym->nindirectsyms);
00868
00869 bfd_seek (abfd, isymoff, SEEK_SET);
00870 if (bfd_bread ((PTR) buf, 4, abfd) != 4)
00871 {
00872 fprintf (stderr, "bfd_mach_o_scan_read_dysymtab_symbol: unable to read %lu bytes at %lu\n",
00873 (unsigned long) 4, isymoff);
00874 return -1;
00875 }
00876 symindex = bfd_h_get_32 (abfd, buf);
00877
00878 return bfd_mach_o_scan_read_symtab_symbol (abfd, sym, s, symindex);
00879 }
00880
00881 static const char *
00882 bfd_mach_o_i386_flavour_string (flavour)
00883 unsigned int flavour;
00884 {
00885 switch ((int) flavour)
00886 {
00887 case BFD_MACH_O_i386_NEW_THREAD_STATE: return "i386_NEW_THREAD_STATE";
00888 case BFD_MACH_O_i386_FLOAT_STATE: return "i386_FLOAT_STATE";
00889 case BFD_MACH_O_i386_ISA_PORT_MAP_STATE: return "i386_ISA_PORT_MAP_STATE";
00890 case BFD_MACH_O_i386_V86_ASSIST_STATE: return "i386_V86_ASSIST_STATE";
00891 case BFD_MACH_O_i386_REGS_SEGS_STATE: return "i386_REGS_SEGS_STATE";
00892 case BFD_MACH_O_i386_THREAD_SYSCALL_STATE: return "i386_THREAD_SYSCALL_STATE";
00893 case BFD_MACH_O_i386_THREAD_STATE_NONE: return "i386_THREAD_STATE_NONE";
00894 case BFD_MACH_O_i386_SAVED_STATE: return "i386_SAVED_STATE";
00895 case BFD_MACH_O_i386_THREAD_STATE: return "i386_THREAD_STATE";
00896 case BFD_MACH_O_i386_THREAD_FPSTATE: return "i386_THREAD_FPSTATE";
00897 case BFD_MACH_O_i386_THREAD_EXCEPTSTATE: return "i386_THREAD_EXCEPTSTATE";
00898 case BFD_MACH_O_i386_THREAD_CTHREADSTATE: return "i386_THREAD_CTHREADSTATE";
00899 default: return "UNKNOWN";
00900 }
00901 }
00902
00903 static const char *
00904 bfd_mach_o_ppc_flavour_string (flavour)
00905 unsigned int flavour;
00906 {
00907 switch ((int) flavour)
00908 {
00909 case BFD_MACH_O_PPC_THREAD_STATE: return "PPC_THREAD_STATE";
00910 case BFD_MACH_O_PPC_FLOAT_STATE: return "PPC_FLOAT_STATE";
00911 case BFD_MACH_O_PPC_EXCEPTION_STATE: return "PPC_EXCEPTION_STATE";
00912 case BFD_MACH_O_PPC_VECTOR_STATE: return "PPC_VECTOR_STATE";
00913 default: return "UNKNOWN";
00914 }
00915 }
00916
00917 static int
00918 bfd_mach_o_scan_write_thread (abfd, command)
00919 bfd *abfd;
00920 bfd_mach_o_load_command *command;
00921 {
00922 bfd_mach_o_thread_command *cmd = &command->command.thread;
00923 unsigned int i;
00924 unsigned char buf[8];
00925 bfd_vma offset;
00926 unsigned int nflavours;
00927
00928 BFD_ASSERT ((command->type == BFD_MACH_O_LC_THREAD)
00929 || (command->type == BFD_MACH_O_LC_UNIXTHREAD));
00930
00931 offset = 8;
00932 nflavours = 0;
00933 for (i = 0; i < cmd->nflavours; i++)
00934 {
00935 BFD_ASSERT ((cmd->flavours[i].size % 4) == 0);
00936 BFD_ASSERT (cmd->flavours[i].offset == (command->offset + offset + 8));
00937
00938 bfd_h_put_32 (abfd, cmd->flavours[i].flavour, buf);
00939 bfd_h_put_32 (abfd, (cmd->flavours[i].size / 4), buf + 4);
00940
00941 bfd_seek (abfd, command->offset + offset, SEEK_SET);
00942 if (bfd_bwrite ((PTR) buf, 8, abfd) != 8)
00943 return -1;
00944
00945 offset += cmd->flavours[i].size + 8;
00946 }
00947
00948 return 0;
00949 }
00950
00951 static int
00952 bfd_mach_o_scan_read_dylinker (abfd, command)
00953 bfd *abfd;
00954 bfd_mach_o_load_command *command;
00955 {
00956 bfd_mach_o_dylinker_command *cmd = &command->command.dylinker;
00957 unsigned char buf[4];
00958 unsigned int nameoff;
00959 asection *bfdsec;
00960 char *sname;
00961 const char *prefix;
00962
00963 BFD_ASSERT ((command->type == BFD_MACH_O_LC_ID_DYLINKER)
00964 || (command->type == BFD_MACH_O_LC_LOAD_DYLINKER));
00965
00966 bfd_seek (abfd, command->offset + 8, SEEK_SET);
00967 if (bfd_bread ((PTR) buf, 4, abfd) != 4)
00968 return -1;
00969
00970 nameoff = bfd_h_get_32 (abfd, buf + 0);
00971
00972 cmd->name_offset = command->offset + nameoff;
00973 cmd->name_len = command->len - nameoff;
00974
00975 if (command->type == BFD_MACH_O_LC_LOAD_DYLINKER)
00976 prefix = "LC_LOAD_DYLINKER";
00977 else if (command->type == BFD_MACH_O_LC_ID_DYLINKER)
00978 prefix = "LC_ID_DYLINKER";
00979 else
00980 abort ();
00981
00982 sname = (char *) bfd_alloc (abfd, strlen (prefix) + 1);
00983 if (sname == NULL)
00984 return -1;
00985 strcpy (sname, prefix);
00986
00987 bfdsec = bfd_make_section_anyway (abfd, sname);
00988 if (bfdsec == NULL)
00989 return -1;
00990
00991 bfdsec->vma = 0;
00992 bfdsec->lma = 0;
00993 bfdsec->size = command->len - 8;
00994 bfdsec->filepos = command->offset + 8;
00995 bfdsec->alignment_power = 0;
00996 bfdsec->flags = SEC_HAS_CONTENTS;
00997
00998 cmd->section = bfdsec;
00999
01000 return 0;
01001 }
01002
01003 static int
01004 bfd_mach_o_scan_read_dylib (abfd, command)
01005 bfd *abfd;
01006 bfd_mach_o_load_command *command;
01007 {
01008 bfd_mach_o_dylib_command *cmd = &command->command.dylib;
01009 unsigned char buf[16];
01010 unsigned int nameoff;
01011 asection *bfdsec;
01012 char *sname;
01013 const char *prefix;
01014
01015 BFD_ASSERT ((command->type == BFD_MACH_O_LC_ID_DYLIB)
01016 || (command->type == BFD_MACH_O_LC_LOAD_DYLIB)
01017 || (command->type == BFD_MACH_O_LC_LOAD_WEAK_DYLIB));
01018
01019 bfd_seek (abfd, command->offset + 8, SEEK_SET);
01020 if (bfd_bread ((PTR) buf, 16, abfd) != 16)
01021 return -1;
01022
01023 nameoff = bfd_h_get_32 (abfd, buf + 0);
01024 cmd->timestamp = bfd_h_get_32 (abfd, buf + 4);
01025 cmd->current_version = bfd_h_get_32 (abfd, buf + 8);
01026 cmd->compatibility_version = bfd_h_get_32 (abfd, buf + 12);
01027
01028 cmd->name_offset = command->offset + nameoff;
01029 cmd->name_len = command->len - nameoff;
01030
01031 if (command->type == BFD_MACH_O_LC_LOAD_DYLIB)
01032 prefix = "LC_LOAD_DYLIB";
01033 else if (command->type == BFD_MACH_O_LC_LOAD_WEAK_DYLIB)
01034 prefix = "LC_LOAD_WEAK_DYLIB";
01035 else if (command->type == BFD_MACH_O_LC_ID_DYLIB)
01036 prefix = "LC_ID_DYLIB";
01037 else
01038 abort ();
01039
01040 sname = (char *) bfd_alloc (abfd, strlen (prefix) + 1);
01041 if (sname == NULL)
01042 return -1;
01043 strcpy (sname, prefix);
01044
01045 bfdsec = bfd_make_section_anyway (abfd, sname);
01046 if (bfdsec == NULL)
01047 return -1;
01048
01049 bfdsec->vma = 0;
01050 bfdsec->lma = 0;
01051 bfdsec->size = command->len - 8;
01052 bfdsec->filepos = command->offset + 8;
01053 bfdsec->alignment_power = 0;
01054 bfdsec->flags = SEC_HAS_CONTENTS;
01055
01056 cmd->section = bfdsec;
01057
01058 return 0;
01059 }
01060
01061 static int
01062 bfd_mach_o_scan_read_prebound_dylib (abfd, command)
01063 bfd *abfd ATTRIBUTE_UNUSED;
01064 bfd_mach_o_load_command *command ATTRIBUTE_UNUSED;
01065 {
01066
01067
01068 BFD_ASSERT (command->type == BFD_MACH_O_LC_PREBOUND_DYLIB);
01069 return 0;
01070 }
01071
01072 static int
01073 bfd_mach_o_scan_read_thread (abfd, command)
01074 bfd *abfd;
01075 bfd_mach_o_load_command *command;
01076 {
01077 bfd_mach_o_data_struct *mdata = NULL;
01078 bfd_mach_o_thread_command *cmd = &command->command.thread;
01079 unsigned char buf[8];
01080 bfd_vma offset;
01081 unsigned int nflavours;
01082 unsigned int i;
01083
01084 BFD_ASSERT ((command->type == BFD_MACH_O_LC_THREAD)
01085 || (command->type == BFD_MACH_O_LC_UNIXTHREAD));
01086
01087 BFD_ASSERT (bfd_mach_o_valid (abfd));
01088 mdata = abfd->tdata.mach_o_data;
01089
01090 offset = 8;
01091 nflavours = 0;
01092 while (offset != command->len)
01093 {
01094 if (offset >= command->len)
01095 return -1;
01096
01097 bfd_seek (abfd, command->offset + offset, SEEK_SET);
01098
01099 if (bfd_bread ((PTR) buf, 8, abfd) != 8)
01100 return -1;
01101
01102 offset += 8 + bfd_h_get_32 (abfd, buf + 4) * 4;
01103 nflavours++;
01104 }
01105
01106 cmd->flavours =
01107 ((bfd_mach_o_thread_flavour *)
01108 bfd_alloc (abfd, nflavours * sizeof (bfd_mach_o_thread_flavour)));
01109 if (cmd->flavours == NULL)
01110 return -1;
01111 cmd->nflavours = nflavours;
01112
01113 offset = 8;
01114 nflavours = 0;
01115 while (offset != command->len)
01116 {
01117 if (offset >= command->len)
01118 return -1;
01119
01120 if (nflavours >= cmd->nflavours)
01121 return -1;
01122
01123 bfd_seek (abfd, command->offset + offset, SEEK_SET);
01124
01125 if (bfd_bread ((PTR) buf, 8, abfd) != 8)
01126 return -1;
01127
01128 cmd->flavours[nflavours].flavour = bfd_h_get_32 (abfd, buf);
01129 cmd->flavours[nflavours].offset = command->offset + offset + 8;
01130 cmd->flavours[nflavours].size = bfd_h_get_32 (abfd, buf + 4) * 4;
01131 offset += cmd->flavours[nflavours].size + 8;
01132 nflavours++;
01133 }
01134
01135 for (i = 0; i < nflavours; i++)
01136 {
01137 asection *bfdsec;
01138 unsigned int snamelen;
01139 char *sname;
01140 const char *flavourstr;
01141 const char *prefix = "LC_THREAD";
01142 unsigned int j = 0;
01143
01144 switch (mdata->header.cputype)
01145 {
01146 case BFD_MACH_O_CPU_TYPE_POWERPC:
01147 flavourstr = bfd_mach_o_ppc_flavour_string (cmd->flavours[i].flavour);
01148 break;
01149 case BFD_MACH_O_CPU_TYPE_I386:
01150 flavourstr = bfd_mach_o_i386_flavour_string (cmd->flavours[i].flavour);
01151 break;
01152 default:
01153 flavourstr = "UNKNOWN_ARCHITECTURE";
01154 break;
01155 }
01156
01157 snamelen = strlen (prefix) + 1 + 20 + 1 + strlen (flavourstr) + 1;
01158 sname = (char *) bfd_alloc (abfd, snamelen);
01159 if (sname == NULL)
01160 return -1;
01161
01162 for (;;)
01163 {
01164 sprintf (sname, "%s.%s.%u", prefix, flavourstr, j);
01165 if (bfd_get_section_by_name (abfd, sname) == NULL)
01166 break;
01167 j++;
01168 }
01169
01170 bfdsec = bfd_make_section (abfd, sname);
01171
01172 bfdsec->vma = 0;
01173 bfdsec->lma = 0;
01174 bfdsec->size = cmd->flavours[i].size;
01175 bfdsec->filepos = cmd->flavours[i].offset;
01176 bfdsec->alignment_power = 0x0;
01177 bfdsec->flags = SEC_HAS_CONTENTS;
01178
01179 cmd->section = bfdsec;
01180 }
01181
01182 return 0;
01183 }
01184
01185 static int
01186 bfd_mach_o_scan_write_symtab (abfd, command)
01187 bfd *abfd;
01188 bfd_mach_o_load_command *command;
01189 {
01190 bfd_mach_o_symtab_command *seg = &command->command.symtab;
01191 unsigned char buf[16];
01192
01193 BFD_ASSERT (command->type == BFD_MACH_O_LC_SYMTAB);
01194
01195 bfd_h_put_32 (abfd, seg->symoff, buf);
01196 bfd_h_put_32 (abfd, seg->nsyms, buf + 4);
01197 bfd_h_put_32 (abfd, seg->stroff, buf + 8);
01198 bfd_h_put_32 (abfd, seg->strsize, buf + 12);
01199
01200 bfd_seek (abfd, command->offset + 8, SEEK_SET);
01201 if (bfd_bwrite ((PTR) buf, 16, abfd) != 16)
01202 return -1;
01203
01204 if (bfd_mach_o_scan_write_symtab_symbols (abfd, command) != 0)
01205 return -1;
01206
01207 return 0;
01208 }
01209
01210 static int
01211 bfd_mach_o_scan_read_dysymtab (abfd, command)
01212 bfd *abfd;
01213 bfd_mach_o_load_command *command;
01214 {
01215 bfd_mach_o_dysymtab_command *seg = &command->command.dysymtab;
01216 unsigned char buf[72];
01217
01218 BFD_ASSERT (command->type == BFD_MACH_O_LC_DYSYMTAB);
01219
01220 bfd_seek (abfd, command->offset + 8, SEEK_SET);
01221 if (bfd_bread ((PTR) buf, 72, abfd) != 72)
01222 return -1;
01223
01224 seg->ilocalsym = bfd_h_get_32 (abfd, buf + 0);
01225 seg->nlocalsym = bfd_h_get_32 (abfd, buf + 4);
01226 seg->iextdefsym = bfd_h_get_32 (abfd, buf + 8);
01227 seg->nextdefsym = bfd_h_get_32 (abfd, buf + 12);
01228 seg->iundefsym = bfd_h_get_32 (abfd, buf + 16);
01229 seg->nundefsym = bfd_h_get_32 (abfd, buf + 20);
01230 seg->tocoff = bfd_h_get_32 (abfd, buf + 24);
01231 seg->ntoc = bfd_h_get_32 (abfd, buf + 28);
01232 seg->modtaboff = bfd_h_get_32 (abfd, buf + 32);
01233 seg->nmodtab = bfd_h_get_32 (abfd, buf + 36);
01234 seg->extrefsymoff = bfd_h_get_32 (abfd, buf + 40);
01235 seg->nextrefsyms = bfd_h_get_32 (abfd, buf + 44);
01236 seg->indirectsymoff = bfd_h_get_32 (abfd, buf + 48);
01237 seg->nindirectsyms = bfd_h_get_32 (abfd, buf + 52);
01238 seg->extreloff = bfd_h_get_32 (abfd, buf + 56);
01239 seg->nextrel = bfd_h_get_32 (abfd, buf + 60);
01240 seg->locreloff = bfd_h_get_32 (abfd, buf + 64);
01241 seg->nlocrel = bfd_h_get_32 (abfd, buf + 68);
01242
01243 return 0;
01244 }
01245
01246 static int
01247 bfd_mach_o_scan_read_symtab (abfd, command)
01248 bfd *abfd;
01249 bfd_mach_o_load_command *command;
01250 {
01251 bfd_mach_o_symtab_command *seg = &command->command.symtab;
01252 unsigned char buf[16];
01253 asection *bfdsec;
01254 char *sname;
01255 const char *prefix = "LC_SYMTAB.stabs";
01256
01257 BFD_ASSERT (command->type == BFD_MACH_O_LC_SYMTAB);
01258
01259 bfd_seek (abfd, command->offset + 8, SEEK_SET);
01260 if (bfd_bread ((PTR) buf, 16, abfd) != 16)
01261 return -1;
01262
01263 seg->symoff = bfd_h_get_32 (abfd, buf);
01264 seg->nsyms = bfd_h_get_32 (abfd, buf + 4);
01265 seg->stroff = bfd_h_get_32 (abfd, buf + 8);
01266 seg->strsize = bfd_h_get_32 (abfd, buf + 12);
01267 seg->symbols = NULL;
01268 seg->strtab = NULL;
01269
01270 sname = (char *) bfd_alloc (abfd, strlen (prefix) + 1);
01271 if (sname == NULL)
01272 return -1;
01273 strcpy (sname, prefix);
01274
01275 bfdsec = bfd_make_section_anyway (abfd, sname);
01276 if (bfdsec == NULL)
01277 return -1;
01278
01279 bfdsec->vma = 0;
01280 bfdsec->lma = 0;
01281 bfdsec->size = seg->nsyms * 12;
01282 bfdsec->filepos = seg->symoff;
01283 bfdsec->alignment_power = 0;
01284 bfdsec->flags = SEC_HAS_CONTENTS;
01285
01286 seg->stabs_segment = bfdsec;
01287
01288 prefix = "LC_SYMTAB.stabstr";
01289 sname = (char *) bfd_alloc (abfd, strlen (prefix) + 1);
01290 if (sname == NULL)
01291 return -1;
01292 strcpy (sname, prefix);
01293
01294 bfdsec = bfd_make_section_anyway (abfd, sname);
01295 if (bfdsec == NULL)
01296 return -1;
01297
01298 bfdsec->vma = 0;
01299 bfdsec->lma = 0;
01300 bfdsec->size = seg->strsize;
01301 bfdsec->filepos = seg->stroff;
01302 bfdsec->alignment_power = 0;
01303 bfdsec->flags = SEC_HAS_CONTENTS;
01304
01305 seg->stabstr_segment = bfdsec;
01306
01307 return 0;
01308 }
01309
01310 static int
01311 bfd_mach_o_scan_read_segment (abfd, command)
01312 bfd *abfd;
01313 bfd_mach_o_load_command *command;
01314 {
01315 unsigned char buf[48];
01316 bfd_mach_o_segment_command *seg = &command->command.segment;
01317 unsigned long i;
01318 asection *bfdsec;
01319 char *sname;
01320 const char *prefix = "LC_SEGMENT";
01321 unsigned int snamelen;
01322
01323 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT);
01324
01325 bfd_seek (abfd, command->offset + 8, SEEK_SET);
01326 if (bfd_bread ((PTR) buf, 48, abfd) != 48)
01327 return -1;
01328
01329 memcpy (seg->segname, buf, 16);
01330 seg->vmaddr = bfd_h_get_32 (abfd, buf + 16);
01331 seg->vmsize = bfd_h_get_32 (abfd, buf + 20);
01332 seg->fileoff = bfd_h_get_32 (abfd, buf + 24);
01333 seg->filesize = bfd_h_get_32 (abfd, buf + 28);
01334
01335
01336 seg->nsects = bfd_h_get_32 (abfd, buf + 40);
01337 seg->flags = bfd_h_get_32 (abfd, buf + 44);
01338
01339 snamelen = strlen (prefix) + 1 + strlen (seg->segname) + 1;
01340 sname = (char *) bfd_alloc (abfd, snamelen);
01341 if (sname == NULL)
01342 return -1;
01343 sprintf (sname, "%s.%s", prefix, seg->segname);
01344
01345 bfdsec = bfd_make_section_anyway (abfd, sname);
01346 if (bfdsec == NULL)
01347 return -1;
01348
01349 bfdsec->vma = seg->vmaddr;
01350 bfdsec->lma = seg->vmaddr;
01351 bfdsec->size = seg->filesize;
01352 bfdsec->filepos = seg->fileoff;
01353 bfdsec->alignment_power = 0x0;
01354 bfdsec->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC | SEC_CODE;
01355
01356 seg->segment = bfdsec;
01357
01358 if (seg->nsects != 0)
01359 {
01360 seg->sections =
01361 ((bfd_mach_o_section *)
01362 bfd_alloc (abfd, seg->nsects * sizeof (bfd_mach_o_section)));
01363 if (seg->sections == NULL)
01364 return -1;
01365
01366 for (i = 0; i < seg->nsects; i++)
01367 {
01368 bfd_vma segoff = command->offset + 48 + 8 + (i * 68);
01369
01370 if (bfd_mach_o_scan_read_section (abfd, &seg->sections[i],
01371 segoff) != 0)
01372 return -1;
01373 }
01374 }
01375
01376 return 0;
01377 }
01378
01379 static int
01380 bfd_mach_o_scan_write_segment (abfd, command)
01381 bfd *abfd;
01382 bfd_mach_o_load_command *command;
01383 {
01384 unsigned char buf[48];
01385 bfd_mach_o_segment_command *seg = &command->command.segment;
01386 unsigned long i;
01387
01388 BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT);
01389
01390 memcpy (buf, seg->segname, 16);
01391 bfd_h_put_32 (abfd, seg->vmaddr, buf + 16);
01392 bfd_h_put_32 (abfd, seg->vmsize, buf + 20);
01393 bfd_h_put_32 (abfd, seg->fileoff, buf + 24);
01394 bfd_h_put_32 (abfd, seg->filesize, buf + 28);
01395 bfd_h_put_32 (abfd, 0 , buf + 32);
01396 bfd_h_put_32 (abfd, 0 , buf + 36);
01397 bfd_h_put_32 (abfd, seg->nsects, buf + 40);
01398 bfd_h_put_32 (abfd, seg->flags, buf + 44);
01399
01400 bfd_seek (abfd, command->offset + 8, SEEK_SET);
01401 if (bfd_bwrite ((PTR) buf, 48, abfd) != 48)
01402 return -1;
01403
01404 {
01405 char buf[1024];
01406 bfd_vma nbytes = seg->filesize;
01407 bfd_vma curoff = seg->fileoff;
01408
01409 while (nbytes > 0)
01410 {
01411 bfd_vma thisread = nbytes;
01412
01413 if (thisread > 1024)
01414 thisread = 1024;
01415
01416 bfd_seek (abfd, curoff, SEEK_SET);
01417 if (bfd_bread ((PTR) buf, thisread, abfd) != thisread)
01418 return -1;
01419
01420 bfd_seek (abfd, curoff, SEEK_SET);
01421 if (bfd_bwrite ((PTR) buf, thisread, abfd) != thisread)
01422 return -1;
01423
01424 nbytes -= thisread;
01425 curoff += thisread;
01426 }
01427 }
01428
01429 for (i = 0; i < seg->nsects; i++)
01430 {
01431 bfd_vma segoff = command->offset + 48 + 8 + (i * 68);
01432
01433 if (bfd_mach_o_scan_write_section (abfd, &seg->sections[i], segoff) != 0)
01434 return -1;
01435 }
01436
01437 return 0;
01438 }
01439
01440 static int
01441 bfd_mach_o_scan_read_command (abfd, command)
01442 bfd *abfd;
01443 bfd_mach_o_load_command *command;
01444 {
01445 unsigned char buf[8];
01446
01447 bfd_seek (abfd, command->offset, SEEK_SET);
01448 if (bfd_bread ((PTR) buf, 8, abfd) != 8)
01449 return -1;
01450
01451 command->type = (bfd_h_get_32 (abfd, buf) & ~BFD_MACH_O_LC_REQ_DYLD);
01452 command->type_required = (bfd_h_get_32 (abfd, buf) & BFD_MACH_O_LC_REQ_DYLD
01453 ? 1 : 0);
01454 command->len = bfd_h_get_32 (abfd, buf + 4);
01455
01456 switch (command->type)
01457 {
01458 case BFD_MACH_O_LC_SEGMENT:
01459 if (bfd_mach_o_scan_read_segment (abfd, command) != 0)
01460 return -1;
01461 break;
01462 case BFD_MACH_O_LC_SYMTAB:
01463 if (bfd_mach_o_scan_read_symtab (abfd, command) != 0)
01464 return -1;
01465 break;
01466 case BFD_MACH_O_LC_SYMSEG:
01467 break;
01468 case BFD_MACH_O_LC_THREAD:
01469 case BFD_MACH_O_LC_UNIXTHREAD:
01470 if (bfd_mach_o_scan_read_thread (abfd, command) != 0)
01471 return -1;
01472 break;
01473 case BFD_MACH_O_LC_LOAD_DYLINKER:
01474 case BFD_MACH_O_LC_ID_DYLINKER:
01475 if (bfd_mach_o_scan_read_dylinker (abfd, command) != 0)
01476 return -1;
01477 break;
01478 case BFD_MACH_O_LC_LOAD_DYLIB:
01479 case BFD_MACH_O_LC_ID_DYLIB:
01480 case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
01481 if (bfd_mach_o_scan_read_dylib (abfd, command) != 0)
01482 return -1;
01483 break;
01484 case BFD_MACH_O_LC_PREBOUND_DYLIB:
01485 if (bfd_mach_o_scan_read_prebound_dylib (abfd, command) != 0)
01486 return -1;
01487 break;
01488 case BFD_MACH_O_LC_LOADFVMLIB:
01489 case BFD_MACH_O_LC_IDFVMLIB:
01490 case BFD_MACH_O_LC_IDENT:
01491 case BFD_MACH_O_LC_FVMFILE:
01492 case BFD_MACH_O_LC_PREPAGE:
01493 case BFD_MACH_O_LC_ROUTINES:
01494 case BFD_MACH_O_LC_SUB_FRAMEWORK:
01495 break;
01496 case BFD_MACH_O_LC_DYSYMTAB:
01497 if (bfd_mach_o_scan_read_dysymtab (abfd, command) != 0)
01498 return -1;
01499 break;
01500 case BFD_MACH_O_LC_SUB_UMBRELLA:
01501 case BFD_MACH_O_LC_SUB_CLIENT:
01502 case BFD_MACH_O_LC_SUB_LIBRARY:
01503 case BFD_MACH_O_LC_TWOLEVEL_HINTS:
01504 case BFD_MACH_O_LC_PREBIND_CKSUM:
01505 break;
01506 default:
01507 fprintf (stderr, "unable to read unknown load command 0x%lx\n",
01508 (unsigned long) command->type);
01509 break;
01510 }
01511
01512 return 0;
01513 }
01514
01515 static void
01516 bfd_mach_o_flatten_sections (abfd)
01517 bfd *abfd;
01518 {
01519 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
01520 long csect = 0;
01521 unsigned long i, j;
01522
01523 mdata->nsects = 0;
01524
01525 for (i = 0; i < mdata->header.ncmds; i++)
01526 {
01527 if (mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT)
01528 {
01529 bfd_mach_o_segment_command *seg;
01530
01531 seg = &mdata->commands[i].command.segment;
01532 mdata->nsects += seg->nsects;
01533 }
01534 }
01535
01536 mdata->sections = bfd_alloc (abfd,
01537 mdata->nsects * sizeof (bfd_mach_o_section *));
01538 csect = 0;
01539
01540 for (i = 0; i < mdata->header.ncmds; i++)
01541 {
01542 if (mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT)
01543 {
01544 bfd_mach_o_segment_command *seg;
01545
01546 seg = &mdata->commands[i].command.segment;
01547 BFD_ASSERT (csect + seg->nsects <= mdata->nsects);
01548
01549 for (j = 0; j < seg->nsects; j++)
01550 mdata->sections[csect++] = &seg->sections[j];
01551 }
01552 }
01553 }
01554
01555 int
01556 bfd_mach_o_scan_start_address (abfd)
01557 bfd *abfd;
01558 {
01559 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
01560 bfd_mach_o_thread_command *cmd = NULL;
01561 unsigned long i;
01562
01563 for (i = 0; i < mdata->header.ncmds; i++)
01564 {
01565 if ((mdata->commands[i].type == BFD_MACH_O_LC_THREAD) ||
01566 (mdata->commands[i].type == BFD_MACH_O_LC_UNIXTHREAD))
01567 {
01568 if (cmd == NULL)
01569 cmd = &mdata->commands[i].command.thread;
01570 else
01571 return 0;
01572 }
01573 }
01574
01575 if (cmd == NULL)
01576 return 0;
01577
01578 for (i = 0; i < cmd->nflavours; i++)
01579 {
01580 if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_I386)
01581 && (cmd->flavours[i].flavour
01582 == (unsigned long) BFD_MACH_O_i386_THREAD_STATE))
01583 {
01584 unsigned char buf[4];
01585
01586 bfd_seek (abfd, cmd->flavours[i].offset + 40, SEEK_SET);
01587
01588 if (bfd_bread (buf, 4, abfd) != 4)
01589 return -1;
01590
01591 abfd->start_address = bfd_h_get_32 (abfd, buf);
01592 }
01593 else if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_POWERPC)
01594 && (cmd->flavours[i].flavour == BFD_MACH_O_PPC_THREAD_STATE))
01595 {
01596 unsigned char buf[4];
01597
01598 bfd_seek (abfd, cmd->flavours[i].offset + 0, SEEK_SET);
01599
01600 if (bfd_bread (buf, 4, abfd) != 4)
01601 return -1;
01602
01603 abfd->start_address = bfd_h_get_32 (abfd, buf);
01604 }
01605 }
01606
01607 return 0;
01608 }
01609
01610 int
01611 bfd_mach_o_scan (abfd, header, mdata)
01612 bfd *abfd;
01613 bfd_mach_o_header *header;
01614 bfd_mach_o_data_struct *mdata;
01615 {
01616 unsigned int i;
01617 enum bfd_architecture cputype;
01618 unsigned long cpusubtype;
01619
01620 mdata->header = *header;
01621 mdata->symbols = NULL;
01622
01623 abfd->flags = (abfd->xvec->object_flags
01624 | (abfd->flags & (BFD_IN_MEMORY | BFD_IO_FUNCS)));
01625 abfd->tdata.mach_o_data = mdata;
01626
01627 bfd_mach_o_convert_architecture (header->cputype, header->cpusubtype,
01628 &cputype, &cpusubtype);
01629 if (cputype == bfd_arch_unknown)
01630 {
01631 fprintf (stderr, "bfd_mach_o_scan: unknown architecture 0x%lx/0x%lx\n",
01632 header->cputype, header->cpusubtype);
01633 return -1;
01634 }
01635
01636 bfd_set_arch_mach (abfd, cputype, cpusubtype);
01637
01638 if (header->ncmds != 0)
01639 {
01640 mdata->commands =
01641 ((bfd_mach_o_load_command *)
01642 bfd_alloc (abfd, header->ncmds * sizeof (bfd_mach_o_load_command)));
01643 if (mdata->commands == NULL)
01644 return -1;
01645
01646 for (i = 0; i < header->ncmds; i++)
01647 {
01648 bfd_mach_o_load_command *cur = &mdata->commands[i];
01649
01650 if (i == 0)
01651 cur->offset = 28;
01652 else
01653 {
01654 bfd_mach_o_load_command *prev = &mdata->commands[i - 1];
01655 cur->offset = prev->offset + prev->len;
01656 }
01657
01658 if (bfd_mach_o_scan_read_command (abfd, cur) < 0)
01659 return -1;
01660 }
01661 }
01662
01663 if (bfd_mach_o_scan_start_address (abfd) < 0)
01664 return -1;
01665
01666 bfd_mach_o_flatten_sections (abfd);
01667 return 0;
01668 }
01669
01670 bfd_boolean
01671 bfd_mach_o_mkobject (abfd)
01672 bfd *abfd;
01673 {
01674 bfd_mach_o_data_struct *mdata = NULL;
01675
01676 mdata = ((bfd_mach_o_data_struct *)
01677 bfd_alloc (abfd, sizeof (bfd_mach_o_data_struct)));
01678 if (mdata == NULL)
01679 return FALSE;
01680 abfd->tdata.mach_o_data = mdata;
01681
01682 mdata->header.magic = 0;
01683 mdata->header.cputype = 0;
01684 mdata->header.cpusubtype = 0;
01685 mdata->header.filetype = 0;
01686 mdata->header.ncmds = 0;
01687 mdata->header.sizeofcmds = 0;
01688 mdata->header.flags = 0;
01689 mdata->header.byteorder = BFD_ENDIAN_UNKNOWN;
01690 mdata->commands = NULL;
01691 mdata->nsymbols = 0;
01692 mdata->symbols = NULL;
01693 mdata->nsects = 0;
01694 mdata->sections = NULL;
01695 mdata->ibfd = NULL;
01696
01697 return TRUE;
01698 }
01699
01700 const bfd_target *
01701 bfd_mach_o_object_p (abfd)
01702 bfd *abfd;
01703 {
01704 struct bfd_preserve preserve;
01705 bfd_mach_o_header header;
01706
01707 preserve.marker = NULL;
01708 if (bfd_mach_o_read_header (abfd, &header) != 0)
01709 goto wrong;
01710
01711 if (! (header.byteorder == BFD_ENDIAN_BIG
01712 || header.byteorder == BFD_ENDIAN_LITTLE))
01713 {
01714 fprintf (stderr, "unknown header byte-order value 0x%lx\n",
01715 (long) header.byteorder);
01716 goto wrong;
01717 }
01718
01719 if (! ((header.byteorder == BFD_ENDIAN_BIG
01720 && abfd->xvec->byteorder == BFD_ENDIAN_BIG
01721 && abfd->xvec->header_byteorder == BFD_ENDIAN_BIG)
01722 || (header.byteorder == BFD_ENDIAN_LITTLE
01723 && abfd->xvec->byteorder == BFD_ENDIAN_LITTLE
01724 && abfd->xvec->header_byteorder == BFD_ENDIAN_LITTLE)))
01725 goto wrong;
01726
01727 preserve.marker = bfd_zalloc (abfd, sizeof (bfd_mach_o_data_struct));
01728 if (preserve.marker == NULL
01729 || !bfd_preserve_save (abfd, &preserve))
01730 goto fail;
01731
01732 if (bfd_mach_o_scan (abfd, &header,
01733 (bfd_mach_o_data_struct *) preserve.marker) != 0)
01734 goto wrong;
01735
01736 bfd_preserve_finish (abfd, &preserve);
01737 return abfd->xvec;
01738
01739 wrong:
01740 bfd_set_error (bfd_error_wrong_format);
01741
01742 fail:
01743 if (preserve.marker != NULL)
01744 bfd_preserve_restore (abfd, &preserve);
01745 return NULL;
01746 }
01747
01748 const bfd_target *
01749 bfd_mach_o_core_p (abfd)
01750 bfd *abfd;
01751 {
01752 struct bfd_preserve preserve;
01753 bfd_mach_o_header header;
01754
01755 preserve.marker = NULL;
01756 if (bfd_mach_o_read_header (abfd, &header) != 0)
01757 goto wrong;
01758
01759 if (! (header.byteorder == BFD_ENDIAN_BIG
01760 || header.byteorder == BFD_ENDIAN_LITTLE))
01761 {
01762 fprintf (stderr, "unknown header byte-order value 0x%lx\n",
01763 (long) header.byteorder);
01764 abort ();
01765 }
01766
01767 if (! ((header.byteorder == BFD_ENDIAN_BIG
01768 && abfd->xvec->byteorder == BFD_ENDIAN_BIG
01769 && abfd->xvec->header_byteorder == BFD_ENDIAN_BIG)
01770 || (header.byteorder == BFD_ENDIAN_LITTLE
01771 && abfd->xvec->byteorder == BFD_ENDIAN_LITTLE
01772 && abfd->xvec->header_byteorder == BFD_ENDIAN_LITTLE)))
01773 goto wrong;
01774
01775 if (header.filetype != BFD_MACH_O_MH_CORE)
01776 goto wrong;
01777
01778 preserve.marker = bfd_zalloc (abfd, sizeof (bfd_mach_o_data_struct));
01779 if (preserve.marker == NULL
01780 || !bfd_preserve_save (abfd, &preserve))
01781 goto fail;
01782
01783 if (bfd_mach_o_scan (abfd, &header,
01784 (bfd_mach_o_data_struct *) preserve.marker) != 0)
01785 goto wrong;
01786
01787 bfd_preserve_finish (abfd, &preserve);
01788 return abfd->xvec;
01789
01790 wrong:
01791 bfd_set_error (bfd_error_wrong_format);
01792
01793 fail:
01794 if (preserve.marker != NULL)
01795 bfd_preserve_restore (abfd, &preserve);
01796 return NULL;
01797 }
01798
01799 typedef struct mach_o_fat_archentry
01800 {
01801 unsigned long cputype;
01802 unsigned long cpusubtype;
01803 unsigned long offset;
01804 unsigned long size;
01805 unsigned long align;
01806 bfd *abfd;
01807 } mach_o_fat_archentry;
01808
01809 typedef struct mach_o_fat_data_struct
01810 {
01811 unsigned long magic;
01812 unsigned long nfat_arch;
01813 mach_o_fat_archentry *archentries;
01814 } mach_o_fat_data_struct;
01815
01816 const bfd_target *
01817 bfd_mach_o_archive_p (abfd)
01818 bfd *abfd;
01819 {
01820 mach_o_fat_data_struct *adata = NULL;
01821 unsigned char buf[20];
01822 unsigned long i;
01823
01824 bfd_seek (abfd, 0, SEEK_SET);
01825 if (bfd_bread ((PTR) buf, 8, abfd) != 8)
01826 goto error;
01827
01828 adata = (mach_o_fat_data_struct *)
01829 bfd_alloc (abfd, sizeof (mach_o_fat_data_struct));
01830 if (adata == NULL)
01831 goto error;
01832
01833 adata->magic = bfd_getb32 (buf);
01834 adata->nfat_arch = bfd_getb32 (buf + 4);
01835 if (adata->magic != 0xcafebabe)
01836 goto error;
01837
01838 adata->archentries = (mach_o_fat_archentry *)
01839 bfd_alloc (abfd, adata->nfat_arch * sizeof (mach_o_fat_archentry));
01840 if (adata->archentries == NULL)
01841 goto error;
01842
01843 for (i = 0; i < adata->nfat_arch; i++)
01844 {
01845 bfd_seek (abfd, 8 + 20 * i, SEEK_SET);
01846
01847 if (bfd_bread ((PTR) buf, 20, abfd) != 20)
01848 goto error;
01849 adata->archentries[i].cputype = bfd_getb32 (buf);
01850 adata->archentries[i].cpusubtype = bfd_getb32 (buf + 4);
01851 adata->archentries[i].offset = bfd_getb32 (buf + 8);
01852 adata->archentries[i].size = bfd_getb32 (buf + 12);
01853 adata->archentries[i].align = bfd_getb32 (buf + 16);
01854 adata->archentries[i].abfd = NULL;
01855 }
01856
01857 abfd->tdata.mach_o_fat_data = adata;
01858 return abfd->xvec;
01859
01860 error:
01861 if (adata != NULL)
01862 bfd_release (abfd, adata);
01863 bfd_set_error (bfd_error_wrong_format);
01864 return NULL;
01865 }
01866
01867 bfd *
01868 bfd_mach_o_openr_next_archived_file (archive, prev)
01869 bfd *archive;
01870 bfd *prev;
01871 {
01872 mach_o_fat_data_struct *adata;
01873 mach_o_fat_archentry *entry = NULL;
01874 unsigned long i;
01875
01876 adata = (mach_o_fat_data_struct *) archive->tdata.mach_o_fat_data;
01877 BFD_ASSERT (adata != NULL);
01878
01879
01880 if (prev == NULL)
01881 i = 0;
01882 else
01883 {
01884 for (i = 0; i < adata->nfat_arch; i++)
01885 {
01886 if (adata->archentries[i].abfd == prev)
01887 break;
01888 }
01889
01890 if (i == adata->nfat_arch)
01891 {
01892
01893 bfd_set_error (bfd_error_bad_value);
01894 return NULL;
01895 }
01896 i++;
01897 }
01898
01899 if (i >= adata->nfat_arch)
01900 {
01901 bfd_set_error (bfd_error_no_more_archived_files);
01902 return NULL;
01903 }
01904
01905 entry = &adata->archentries[i];
01906 if (entry->abfd == NULL)
01907 {
01908 bfd *nbfd = _bfd_new_bfd_contained_in (archive);
01909 char *s = NULL;
01910
01911 if (nbfd == NULL)
01912 return NULL;
01913
01914 nbfd->origin = entry->offset;
01915 s = bfd_malloc (strlen (archive->filename) + 1);
01916 if (s == NULL)
01917 return NULL;
01918 strcpy (s, archive->filename);
01919 nbfd->filename = s;
01920 nbfd->iostream = NULL;
01921 entry->abfd = nbfd;
01922 }
01923
01924 return entry->abfd;
01925 }
01926
01927 int
01928 bfd_mach_o_lookup_section (abfd, section, mcommand, msection)
01929 bfd *abfd;
01930 asection *section;
01931 bfd_mach_o_load_command **mcommand;
01932 bfd_mach_o_section **msection;
01933 {
01934 struct mach_o_data_struct *md = abfd->tdata.mach_o_data;
01935 unsigned int i, j, num;
01936
01937 bfd_mach_o_load_command *ncmd = NULL;
01938 bfd_mach_o_section *nsect = NULL;
01939
01940 BFD_ASSERT (mcommand != NULL);
01941 BFD_ASSERT (msection != NULL);
01942
01943 num = 0;
01944 for (i = 0; i < md->header.ncmds; i++)
01945 {
01946 struct bfd_mach_o_load_command *cmd = &md->commands[i];
01947 struct bfd_mach_o_segment_command *seg = NULL;
01948
01949 if (cmd->type != BFD_MACH_O_LC_SEGMENT)
01950 continue;
01951 seg = &cmd->command.segment;
01952
01953 if (seg->segment == section)
01954 {
01955 if (num == 0)
01956 ncmd = cmd;
01957 num++;
01958 }
01959
01960 for (j = 0; j < seg->nsects; j++)
01961 {
01962 struct bfd_mach_o_section *sect = &seg->sections[j];
01963
01964 if (sect->bfdsection == section)
01965 {
01966 if (num == 0)
01967 nsect = sect;
01968 num++;
01969 }
01970 }
01971 }
01972
01973 *mcommand = ncmd;
01974 *msection = nsect;
01975 return num;
01976 }
01977
01978 int
01979 bfd_mach_o_lookup_command (abfd, type, mcommand)
01980 bfd *abfd;
01981 bfd_mach_o_load_command_type type;
01982 bfd_mach_o_load_command **mcommand;
01983 {
01984 struct mach_o_data_struct *md = NULL;
01985 bfd_mach_o_load_command *ncmd = NULL;
01986 unsigned int i, num;
01987
01988 md = abfd->tdata.mach_o_data;
01989
01990 BFD_ASSERT (md != NULL);
01991 BFD_ASSERT (mcommand != NULL);
01992
01993 num = 0;
01994 for (i = 0; i < md->header.ncmds; i++)
01995 {
01996 struct bfd_mach_o_load_command *cmd = &md->commands[i];
01997
01998 if (cmd->type != type)
01999 continue;
02000
02001 if (num == 0)
02002 ncmd = cmd;
02003 num++;
02004 }
02005
02006 *mcommand = ncmd;
02007 return num;
02008 }
02009
02010 unsigned long
02011 bfd_mach_o_stack_addr (type)
02012 enum bfd_mach_o_cpu_type type;
02013 {
02014 switch (type)
02015 {
02016 case BFD_MACH_O_CPU_TYPE_MC680x0:
02017 return 0x04000000;
02018 case BFD_MACH_O_CPU_TYPE_MC88000:
02019 return 0xffffe000;
02020 case BFD_MACH_O_CPU_TYPE_POWERPC:
02021 return 0xc0000000;
02022 case BFD_MACH_O_CPU_TYPE_I386:
02023 return 0xc0000000;
02024 case BFD_MACH_O_CPU_TYPE_SPARC:
02025 return 0xf0000000;
02026 case BFD_MACH_O_CPU_TYPE_I860:
02027 return 0;
02028 case BFD_MACH_O_CPU_TYPE_HPPA:
02029 return 0xc0000000 - 0x04000000;
02030 default:
02031 return 0;
02032 }
02033 }
02034
02035 int
02036 bfd_mach_o_core_fetch_environment (abfd, rbuf, rlen)
02037 bfd *abfd;
02038 unsigned char **rbuf;
02039 unsigned int *rlen;
02040 {
02041 bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
02042 unsigned long stackaddr = bfd_mach_o_stack_addr (mdata->header.cputype);
02043 unsigned int i = 0;
02044
02045 for (i = 0; i < mdata->header.ncmds; i++)
02046 {
02047 bfd_mach_o_load_command *cur = &mdata->commands[i];
02048 bfd_mach_o_segment_command *seg = NULL;
02049
02050 if (cur->type != BFD_MACH_O_LC_SEGMENT)
02051 continue;
02052
02053 seg = &cur->command.segment;
02054
02055 if ((seg->vmaddr + seg->vmsize) == stackaddr)
02056 {
02057 unsigned long start = seg->fileoff;
02058 unsigned long end = seg->fileoff + seg->filesize;
02059 unsigned char *buf = bfd_malloc (1024);
02060 unsigned long size = 1024;
02061
02062 for (;;)
02063 {
02064 bfd_size_type nread = 0;
02065 unsigned long offset;
02066 int found_nonnull = 0;
02067
02068 if (size > (end - start))
02069 size = (end - start);
02070
02071 buf = bfd_realloc (buf, size);
02072
02073 bfd_seek (abfd, end - size, SEEK_SET);
02074 nread = bfd_bread (buf, size, abfd);
02075
02076 if (nread != size)
02077 return -1;
02078
02079 for (offset = 4; offset <= size; offset += 4)
02080 {
02081 unsigned long val;
02082
02083 val = *((unsigned long *) (buf + size - offset));
02084 if (! found_nonnull)
02085 {
02086 if (val != 0)
02087 found_nonnull = 1;
02088 }
02089 else if (val == 0x0)
02090 {
02091 unsigned long bottom;
02092 unsigned long top;
02093
02094 bottom = seg->fileoff + seg->filesize - offset;
02095 top = seg->fileoff + seg->filesize - 4;
02096 *rbuf = bfd_malloc (top - bottom);
02097 *rlen = top - bottom;
02098
02099 memcpy (*rbuf, buf + size - *rlen, *rlen);
02100 return 0;
02101 }
02102 }
02103
02104 if (size == (end - start))
02105 break;
02106
02107 size *= 2;
02108 }
02109 }
02110 }
02111
02112 return -1;
02113 }
02114
02115 char *
02116 bfd_mach_o_core_file_failing_command (abfd)
02117 bfd *abfd;
02118 {
02119 unsigned char *buf = NULL;
02120 unsigned int len = 0;
02121 int ret = -1;
02122
02123 ret = bfd_mach_o_core_fetch_environment (abfd, &buf, &len);
02124 if (ret < 0)
02125 return NULL;
02126
02127 return (char *) buf;
02128 }
02129
02130 int
02131 bfd_mach_o_core_file_failing_signal (abfd)
02132 bfd *abfd ATTRIBUTE_UNUSED;
02133 {
02134 return 0;
02135 }
02136
02137 bfd_boolean
02138 bfd_mach_o_core_file_matches_executable_p (core_bfd, exec_bfd)
02139 bfd *core_bfd ATTRIBUTE_UNUSED;
02140 bfd *exec_bfd ATTRIBUTE_UNUSED;
02141 {
02142 return TRUE;
02143 }
02144
02145 #define TARGET_NAME mach_o_be_vec
02146 #define TARGET_STRING "mach-o-be"
02147 #define TARGET_BIG_ENDIAN 1
02148 #define TARGET_ARCHIVE 0
02149
02150 #include "mach-o-target.c"
02151
02152 #undef TARGET_NAME
02153 #undef TARGET_STRING
02154 #undef TARGET_BIG_ENDIAN
02155 #undef TARGET_ARCHIVE
02156
02157 #define TARGET_NAME mach_o_le_vec
02158 #define TARGET_STRING "mach-o-le"
02159 #define TARGET_BIG_ENDIAN 0
02160 #define TARGET_ARCHIVE 0
02161
02162 #include "mach-o-target.c"
02163
02164 #undef TARGET_NAME
02165 #undef TARGET_STRING
02166 #undef TARGET_BIG_ENDIAN
02167 #undef TARGET_ARCHIVE
02168
02169 #define TARGET_NAME mach_o_fat_vec
02170 #define TARGET_STRING "mach-o-fat"
02171 #define TARGET_BIG_ENDIAN 1
02172 #define TARGET_ARCHIVE 1
02173
02174 #include "mach-o-target.c"
02175
02176 #undef TARGET_NAME
02177 #undef TARGET_STRING
02178 #undef TARGET_BIG_ENDIAN
02179 #undef TARGET_ARCHIVE