Back to index

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