]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Add support for PEF, Mach-O, xSYM
authorNick Clifton <nickc@redhat.com>
Wed, 6 Nov 2002 13:26:29 +0000 (13:26 +0000)
committerNick Clifton <nickc@redhat.com>
Wed, 6 Nov 2002 13:26:29 +0000 (13:26 +0000)
16 files changed:
bfd/ChangeLog
bfd/Makefile.am
bfd/Makefile.in
bfd/archures.c
bfd/bfd-in2.h
bfd/bfd.c
bfd/doc/Makefile.in
bfd/mach-o-target.c [new file with mode: 0644]
bfd/mach-o.c [new file with mode: 0644]
bfd/mach-o.h [new file with mode: 0644]
bfd/pef-traceback.h [new file with mode: 0644]
bfd/pef.c [new file with mode: 0644]
bfd/pef.h [new file with mode: 0644]
bfd/targets.c
bfd/xsym.c [new file with mode: 0644]
bfd/xsym.h [new file with mode: 0644]

index 09714d1e04b9c974829f21da5db929697cb5a6d6..d78a72d57974141350f6c06ae640a5524561dac6 100644 (file)
@@ -1,3 +1,33 @@
+2002-11-06  Klee Dienes  <kdienes@apple.com>
+
+       * Makefile.am (BFD32_BACKENDS): Add mach-o.lo, pef.lo, and 
+       xsym.lo.
+       (BFD32_BACKENDS_CFILES): Add mach-o.c, pef.c, and xsym.c.
+       (SOURCE_HFILES): Add mach-o.h, pef.h, pef-traceback.h, xsym.h
+       * archures.c (enum bfd_architecture): Add bfd_arch_m98k.
+       * bfd.c (struct bfd): Add private data for mach-o, pef, and sym.
+       * targets.c (enum bfd_flavour): Add flavours for mach-o, pef, and
+       sym.
+        (_bfd_target_vector): Add target vectors for mach-o, pef, and sym.
+       * Makefile.in: Regenerate.
+       * doc/Makefile.in: Regenerate.
+        * bfd-in2.h: Regenerate.
+       * xsym.c: New file.  Contains support for the Apple/Metrowerks
+       xSYM debugging format.
+       * xsym.h: New file.
+       * pef.c: New file.  Contains support for the Apple Code Fragment
+       Manager Preferred Executable Format
+       * pef.h: New file.
+       * pef-traceback.h: New file.  Contains support for parsing PowerPC
+       traceback tables as used by PEF executables (and perhaps other
+       systems as well).
+        * mach-o.c: New file.  Contains support for the Mach-O object file
+       format.
+       * mach-o.h: New file.
+       * mach-o-target.c: New file.  Declares the mach-o targets
+       themselves.  Included three times by mach-o.c; each time with a
+       different set of macros set.
+       
 2002-11-06  Graeme Peterson  <gp@qnx.com>
 
        * Makefile.am: Remove entries for elf32-qnx.[ch].
index 59c2668be50da3e5e0b928de21d833e29bc92d1c..0c1a798044071761bdc4823f87d3ff3f71817529 100644 (file)
@@ -266,6 +266,7 @@ BFD32_BACKENDS = \
        m68klynx.lo \
        m68knetbsd.lo \
        m88kmach3.lo \
+       mach-o.lo \
        mipsbsd.lo \
        newsos3.lo \
        nlm.lo \
@@ -277,6 +278,7 @@ BFD32_BACKENDS = \
        oasys.lo \
        pc532-mach.lo \
        pdp11.lo \
+       pef.lo \
        pe-arm.lo \
        pei-arm.lo \
        pe-i386.lo \
@@ -306,7 +308,8 @@ BFD32_BACKENDS = \
        vms-hdr.lo \
        vms-misc.lo \
        vms-tir.lo \
-       xcofflink.lo
+       xcofflink.lo \
+       xsym.lo
 
 BFD32_BACKENDS_CFILES = \
        aout-adobe.c \
@@ -420,6 +423,7 @@ BFD32_BACKENDS_CFILES = \
        m68klynx.c \
        m68knetbsd.c \
        m88kmach3.c \
+       mach-o.c \
        mipsbsd.c \
        newsos3.c \
        nlm.c \
@@ -431,6 +435,7 @@ BFD32_BACKENDS_CFILES = \
        oasys.c \
        pc532-mach.c \
        pdp11.c \
+       pef.c \
        pe-arm.c \
        pei-arm.c \
        pe-i386.c \
@@ -459,7 +464,8 @@ BFD32_BACKENDS_CFILES = \
        vms-hdr.c \
        vms-misc.c \
        vms-tir.c \
-       xcofflink.c
+       xcofflink.c \
+       xsym.c
 
 # The .o files needed by all of the 64 bit vectors that are configured into
 # target_vector in targets.c if configured with --enable-targets=all
@@ -563,9 +569,10 @@ SOURCE_HFILES = \
        elf64-hppa.h elfcode.h elfcore.h elflink.h \
        freebsd.h genlink.h go32stub.h \
        libaout.h libbfd.h libcoff.h libecoff.h libhppa.h libieee.h \
-       libnlm.h liboasys.h libpei.h libxcoff.h \
+       libnlm.h liboasys.h libpei.h libxcoff.h mach-o.h \
        netbsd.h nlm-target.h nlmcode.h nlmswap.h ns32k.h \
-       peicode.h som.h version.h vms.h xcoff-target.h
+       pef.h pef-traceback.h peicode.h som.h version.h \
+       vms.h xcoff-target.h xsym.h
 
 ## ... and all .h files which are in the build tree.
 BUILD_HFILES = \
@@ -1327,6 +1334,8 @@ m68knetbsd.lo: m68knetbsd.c netbsd.h $(INCDIR)/filenames.h \
 m88kmach3.lo: m88kmach3.c $(INCDIR)/filenames.h libaout.h \
   $(INCDIR)/bfdlink.h aout-target.h $(INCDIR)/aout/aout64.h \
   $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h
+mach-o.lo: mach-o.c mach-o.h $(INCDIR)/filenames.h \
+  $(INCDIR)/libiberty.h mach-o-target.c
 mipsbsd.lo: mipsbsd.c $(INCDIR)/filenames.h libaout.h \
   $(INCDIR)/bfdlink.h aout-target.h $(INCDIR)/aout/aout64.h \
   $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h
@@ -1358,6 +1367,8 @@ pc532-mach.lo: pc532-mach.c $(INCDIR)/filenames.h libaout.h \
 pdp11.lo: pdp11.c $(INCDIR)/filenames.h libaout.h $(INCDIR)/bfdlink.h \
   aout-target.h $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h \
   $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h $(INCDIR)/safe-ctype.h
+pef.lo: pef.c pef.h pef-traceback.h $(INCDIR)/filenames.h \
+  $(INCDIR)/libiberty.h
 pe-arm.lo: pe-arm.c $(INCDIR)/filenames.h coff-arm.c \
   $(INCDIR)/coff/arm.h $(INCDIR)/coff/external.h $(INCDIR)/coff/internal.h \
   $(INCDIR)/coff/pe.h libcoff.h $(INCDIR)/bfdlink.h coffcode.h \
@@ -1450,6 +1461,7 @@ vms-tir.lo: vms-tir.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \
 xcofflink.lo: xcofflink.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \
   $(INCDIR)/coff/internal.h $(INCDIR)/coff/xcoff.h libcoff.h \
   libxcoff.h
+xsym.lo: xsym.c xsym.h $(INCDIR)/filenames.h
 aix5ppc-core.lo: aix5ppc-core.c
 aout64.lo: aout64.c aoutx.h $(INCDIR)/filenames.h $(INCDIR)/safe-ctype.h \
   $(INCDIR)/bfdlink.h libaout.h $(INCDIR)/aout/aout64.h \
index bce5486a9e819cbdfa7cd39ec39736e80b320c8b..0104743b6fa1d9ba82f811e4594bedb6f23fb931 100644 (file)
@@ -393,6 +393,7 @@ BFD32_BACKENDS = \
        m68klynx.lo \
        m68knetbsd.lo \
        m88kmach3.lo \
+       mach-o.lo \
        mipsbsd.lo \
        newsos3.lo \
        nlm.lo \
@@ -404,6 +405,7 @@ BFD32_BACKENDS = \
        oasys.lo \
        pc532-mach.lo \
        pdp11.lo \
+       pef.lo \
        pe-arm.lo \
        pei-arm.lo \
        pe-i386.lo \
@@ -433,7 +435,8 @@ BFD32_BACKENDS = \
        vms-hdr.lo \
        vms-misc.lo \
        vms-tir.lo \
-       xcofflink.lo
+       xcofflink.lo \
+       xsym.lo
 
 
 BFD32_BACKENDS_CFILES = \
@@ -548,6 +551,7 @@ BFD32_BACKENDS_CFILES = \
        m68klynx.c \
        m68knetbsd.c \
        m88kmach3.c \
+       mach-o.c \
        mipsbsd.c \
        newsos3.c \
        nlm.c \
@@ -559,6 +563,7 @@ BFD32_BACKENDS_CFILES = \
        oasys.c \
        pc532-mach.c \
        pdp11.c \
+       pef.c \
        pe-arm.c \
        pei-arm.c \
        pe-i386.c \
@@ -587,7 +592,8 @@ BFD32_BACKENDS_CFILES = \
        vms-hdr.c \
        vms-misc.c \
        vms-tir.c \
-       xcofflink.c
+       xcofflink.c \
+       xsym.c
 
 
 # The .o files needed by all of the 64 bit vectors that are configured into
@@ -697,9 +703,10 @@ SOURCE_HFILES = \
        elf64-hppa.h elfcode.h elfcore.h elflink.h \
        freebsd.h genlink.h go32stub.h \
        libaout.h libbfd.h libcoff.h libecoff.h libhppa.h libieee.h \
-       libnlm.h liboasys.h libpei.h libxcoff.h \
+       libnlm.h liboasys.h libpei.h libxcoff.h mach-o.h \
        netbsd.h nlm-target.h nlmcode.h nlmswap.h ns32k.h \
-       peicode.h som.h version.h vms.h xcoff-target.h
+       pef.h pef-traceback.h peicode.h som.h version.h \
+       vms.h xcoff-target.h xsym.h
 
 
 BUILD_HFILES = \
@@ -778,7 +785,7 @@ configure.in version.h
 
 DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
 
-TAR = tar
+TAR = gtar
 GZIP_ENV = --best
 SOURCES = $(libbfd_a_SOURCES) $(libbfd_la_SOURCES)
 OBJECTS = $(libbfd_a_OBJECTS) $(libbfd_la_OBJECTS)
@@ -1858,6 +1865,8 @@ m68knetbsd.lo: m68knetbsd.c netbsd.h $(INCDIR)/filenames.h \
 m88kmach3.lo: m88kmach3.c $(INCDIR)/filenames.h libaout.h \
   $(INCDIR)/bfdlink.h aout-target.h $(INCDIR)/aout/aout64.h \
   $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h
+mach-o.lo: mach-o.c mach-o.h $(INCDIR)/filenames.h \
+  $(INCDIR)/libiberty.h mach-o-target.c
 mipsbsd.lo: mipsbsd.c $(INCDIR)/filenames.h libaout.h \
   $(INCDIR)/bfdlink.h aout-target.h $(INCDIR)/aout/aout64.h \
   $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h
@@ -1889,6 +1898,8 @@ pc532-mach.lo: pc532-mach.c $(INCDIR)/filenames.h libaout.h \
 pdp11.lo: pdp11.c $(INCDIR)/filenames.h libaout.h $(INCDIR)/bfdlink.h \
   aout-target.h $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h \
   $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h $(INCDIR)/safe-ctype.h
+pef.lo: pef.c pef.h pef-traceback.h $(INCDIR)/filenames.h \
+  $(INCDIR)/libiberty.h
 pe-arm.lo: pe-arm.c $(INCDIR)/filenames.h coff-arm.c \
   $(INCDIR)/coff/arm.h $(INCDIR)/coff/external.h $(INCDIR)/coff/internal.h \
   $(INCDIR)/coff/pe.h libcoff.h $(INCDIR)/bfdlink.h coffcode.h \
@@ -1981,6 +1992,7 @@ vms-tir.lo: vms-tir.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \
 xcofflink.lo: xcofflink.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \
   $(INCDIR)/coff/internal.h $(INCDIR)/coff/xcoff.h libcoff.h \
   libxcoff.h
+xsym.lo: xsym.c xsym.h $(INCDIR)/filenames.h
 aix5ppc-core.lo: aix5ppc-core.c
 aout64.lo: aout64.c aoutx.h $(INCDIR)/filenames.h $(INCDIR)/safe-ctype.h \
   $(INCDIR)/bfdlink.h libaout.h $(INCDIR)/aout/aout64.h \
index 1ab0cfa52c38b7523854113d10efc0e39c5f90f4..485fef27401a1447d23577bd8086bb2461d79256 100644 (file)
@@ -4,21 +4,21 @@
    Free Software Foundation, Inc.
    Hacked by John Gilmore and Steve Chamberlain of Cygnus Support.
 
-This file is part of BFD, the Binary File Descriptor library.
+   This file is part of BFD, the Binary File Descriptor library.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "bfd.h"
 #include "sysdep.h"
@@ -160,6 +160,7 @@ DESCRIPTION
 .  bfd_arch_alliant,   {* Alliant *}
 .  bfd_arch_convex,    {* Convex *}
 .  bfd_arch_m88k,      {* Motorola 88xxx *}
+.  bfd_arch_m98k,      {* Motorola 98xxx *}
 .  bfd_arch_pyramid,   {* Pyramid Technology *}
 .  bfd_arch_h8300,     {* Hitachi H8/300 *}
 .#define bfd_mach_h8300   1
index 018a0fd292cc79b0021614df21165b35da868a74..b58e7f5d393a4d7adca8d8982200308cc74222de 100644 (file)
@@ -1551,6 +1551,7 @@ enum bfd_architecture
   bfd_arch_alliant,   /* Alliant */
   bfd_arch_convex,    /* Convex */
   bfd_arch_m88k,      /* Motorola 88xxx */
+  bfd_arch_m98k,      /* Motorola 98xxx */
   bfd_arch_pyramid,   /* Pyramid Technology */
   bfd_arch_h8300,     /* Hitachi H8/300 */
 #define bfd_mach_h8300   1
@@ -3533,6 +3534,11 @@ struct _bfd
       struct cisco_core_struct *cisco_core_data;
       struct versados_data_struct *versados_data;
       struct netbsd_core_struct *netbsd_core_data;
+      struct mach_o_data_struct *mach_o_data;
+      struct mach_o_fat_data_struct *mach_o_fat_data;
+      struct bfd_pef_data_struct *pef_data;
+      struct bfd_pef_xlib_data_struct *pef_xlib_data;
+      struct bfd_sym_data_struct *sym_data;
       PTR any;
     }
   tdata;
@@ -3795,7 +3801,11 @@ enum bfd_flavour
   bfd_target_msdos_flavour,
   bfd_target_ovax_flavour,
   bfd_target_evax_flavour,
-  bfd_target_mmo_flavour
+  bfd_target_mmo_flavour,
+  bfd_target_mach_o_flavour,
+  bfd_target_pef_flavour,
+  bfd_target_pef_xlib_flavour,
+  bfd_target_sym_flavour
 };
 
 enum bfd_endian { BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN };
index bf4516216576e2234f6bac75e45e02dbf5cb49f6..cff7119ee29555b479f1221d61dfeee5f4fe9363 100644 (file)
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -4,21 +4,21 @@
    Free Software Foundation, Inc.
    Written by Cygnus Support.
 
-This file is part of BFD, the Binary File Descriptor library.
+   This file is part of BFD, the Binary File Descriptor library.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 /*
 SECTION
@@ -180,6 +180,11 @@ CODE_FRAGMENT
 .      struct cisco_core_struct *cisco_core_data;
 .      struct versados_data_struct *versados_data;
 .      struct netbsd_core_struct *netbsd_core_data;
+.      struct mach_o_data_struct *mach_o_data;
+.      struct mach_o_fat_data_struct *mach_o_fat_data;
+.      struct bfd_pef_data_struct *pef_data;
+.      struct bfd_pef_xlib_data_struct *pef_xlib_data;
+.      struct bfd_sym_data_struct *sym_data;
 .      PTR any;
 .    }
 .  tdata;
index d25bbf2c74339e77ce6b662f0ae26712a55d828b..ec09ffb70fc1878164f8f941f7a213a529f0b7d8 100644 (file)
@@ -245,7 +245,7 @@ DIST_COMMON =  ChangeLog Makefile.am Makefile.in
 
 DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
 
-TAR = tar
+TAR = gtar
 GZIP_ENV = --best
 all: all-redirect
 .SUFFIXES:
diff --git a/bfd/mach-o-target.c b/bfd/mach-o-target.c
new file mode 100644 (file)
index 0000000..b271bfc
--- /dev/null
@@ -0,0 +1,117 @@
+/* Mach-O support for BFD.
+   Copyright 1999, 2000, 2001, 2002
+   Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software 
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifndef TARGET_NAME
+#error TARGET_NAME must be defined
+#endif /* TARGET_NAME */
+
+#ifndef TARGET_STRING
+#error TARGET_STRING must be defined
+#endif /* TARGET_STRING */
+
+#ifndef TARGET_BIG_ENDIAN
+#error TARGET_BIG_ENDIAN must be defined
+#endif /* TARGET_BIG_ENDIAN */
+
+#ifndef TARGET_ARCHIVE
+#error TARGET_ARCHIVE must be defined
+#endif /* TARGET_ARCHIVE */
+
+#if ((TARGET_ARCHIVE) && (! TARGET_BIG_ENDIAN))
+#error Mach-O fat files must always be big-endian.
+#endif /* ((TARGET_ARCHIVE) && (! TARGET_BIG_ENDIAN)) */
+
+const bfd_target TARGET_NAME =
+{
+  TARGET_STRING,               /* Name.  */
+  bfd_target_mach_o_flavour,
+#if TARGET_BIG_ENDIAN
+  BFD_ENDIAN_BIG,              /* Target byte order.  */
+  BFD_ENDIAN_BIG,              /* Target headers byte order.  */
+#else
+  BFD_ENDIAN_LITTLE,           /* Target byte order.  */
+  BFD_ENDIAN_LITTLE,           /* Target headers byte order.  */
+#endif
+  (HAS_RELOC | EXEC_P |                /* Object flags.  */
+   HAS_LINENO | HAS_DEBUG |
+   HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
+  (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
+   | SEC_ALLOC | SEC_LOAD | SEC_RELOC),        /* Section flags.  */
+  '_',                         /* symbol_leading_char.  */
+  ' ',                         /* ar_pad_char.  */
+  16,                          /* ar_max_namelen.  */
+
+#if TARGET_BIG_ENDIAN
+  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+  bfd_getb16, bfd_getb_signed_16, bfd_putb16,  /* Data.  */
+  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+  bfd_getb16, bfd_getb_signed_16, bfd_putb16,  /* Hdrs.  */
+#else
+  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+  bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+  bfd_getl16, bfd_getl_signed_16, bfd_putl16,  /* data */
+  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+  bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+  bfd_getl16, bfd_getl_signed_16, bfd_putl16,  /* hdrs */
+#endif /* TARGET_BIG_ENDIAN */
+
+  {                            /* bfd_check_format.  */
+#if TARGET_ARCHIVE
+    _bfd_dummy_target,
+    _bfd_dummy_target,
+    bfd_mach_o_archive_p,
+    _bfd_dummy_target,
+#else
+    _bfd_dummy_target,
+    bfd_mach_o_object_p,
+    _bfd_dummy_target,
+    bfd_mach_o_core_p
+#endif
+  },
+  {                            /* bfd_set_format.  */
+    bfd_false,
+    bfd_mach_o_mkobject,
+    bfd_false,
+    bfd_mach_o_mkobject,
+  },
+  {                            /* bfd_write_contents.  */
+    bfd_false,
+    bfd_mach_o_write_contents,
+    bfd_false,
+    bfd_mach_o_write_contents,
+  },
+
+  BFD_JUMP_TABLE_GENERIC (bfd_mach_o),
+  BFD_JUMP_TABLE_COPY (bfd_mach_o),
+  BFD_JUMP_TABLE_CORE (bfd_mach_o),
+  BFD_JUMP_TABLE_ARCHIVE (bfd_mach_o),
+  BFD_JUMP_TABLE_SYMBOLS (bfd_mach_o),
+  BFD_JUMP_TABLE_RELOCS (bfd_mach_o),
+  BFD_JUMP_TABLE_WRITE (bfd_mach_o),
+  BFD_JUMP_TABLE_LINK (bfd_mach_o),
+  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+  NULL,
+
+  NULL
+};
+
diff --git a/bfd/mach-o.c b/bfd/mach-o.c
new file mode 100644 (file)
index 0000000..6243220
--- /dev/null
@@ -0,0 +1,2163 @@
+/* Mach-O support for BFD.
+   Copyright 1999, 2000, 2001, 2002
+   Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software 
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include "mach-o.h"
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "libiberty.h"
+#include <ctype.h>
+
+#ifndef BFD_IO_FUNCS
+#define BFD_IO_FUNCS 0
+#endif
+
+#define bfd_mach_o_mkarchive _bfd_noarchive_mkarchive
+#define bfd_mach_o_read_ar_hdr _bfd_noarchive_read_ar_hdr
+#define bfd_mach_o_slurp_armap _bfd_noarchive_slurp_armap
+#define bfd_mach_o_slurp_extended_name_table _bfd_noarchive_slurp_extended_name_table
+#define bfd_mach_o_construct_extended_name_table _bfd_noarchive_construct_extended_name_table
+#define bfd_mach_o_truncate_arname _bfd_noarchive_truncate_arname
+#define bfd_mach_o_write_armap _bfd_noarchive_write_armap
+#define bfd_mach_o_get_elt_at_index _bfd_noarchive_get_elt_at_index
+#define bfd_mach_o_generic_stat_arch_elt _bfd_noarchive_generic_stat_arch_elt
+#define bfd_mach_o_update_armap_timestamp _bfd_noarchive_update_armap_timestamp
+#define        bfd_mach_o_close_and_cleanup _bfd_generic_close_and_cleanup
+#define bfd_mach_o_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
+#define bfd_mach_o_new_section_hook _bfd_generic_new_section_hook
+#define bfd_mach_o_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
+#define bfd_mach_o_bfd_is_local_label_name _bfd_nosymbols_bfd_is_local_label_name
+#define bfd_mach_o_get_lineno _bfd_nosymbols_get_lineno
+#define bfd_mach_o_find_nearest_line _bfd_nosymbols_find_nearest_line
+#define bfd_mach_o_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
+#define bfd_mach_o_read_minisymbols _bfd_generic_read_minisymbols
+#define bfd_mach_o_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
+#define bfd_mach_o_get_reloc_upper_bound _bfd_norelocs_get_reloc_upper_bound
+#define bfd_mach_o_canonicalize_reloc _bfd_norelocs_canonicalize_reloc
+#define bfd_mach_o_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
+#define bfd_mach_o_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
+#define bfd_mach_o_bfd_relax_section bfd_generic_relax_section
+#define bfd_mach_o_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
+#define bfd_mach_o_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
+#define bfd_mach_o_bfd_link_add_symbols _bfd_generic_link_add_symbols
+#define bfd_mach_o_bfd_link_just_syms _bfd_generic_link_just_syms
+#define bfd_mach_o_bfd_final_link _bfd_generic_final_link
+#define bfd_mach_o_bfd_link_split_section _bfd_generic_link_split_section
+#define bfd_mach_o_set_arch_mach bfd_default_set_arch_mach
+#define bfd_mach_o_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data
+#define bfd_mach_o_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
+#define bfd_mach_o_bfd_print_private_bfd_data _bfd_generic_bfd_print_private_bfd_data
+#define bfd_mach_o_get_section_contents _bfd_generic_get_section_contents
+#define bfd_mach_o_set_section_contents _bfd_generic_set_section_contents
+#define bfd_mach_o_bfd_gc_sections bfd_generic_gc_sections
+#define bfd_mach_o_bfd_merge_sections bfd_generic_merge_sections
+#define bfd_mach_o_bfd_discard_group bfd_generic_discard_group
+
+static boolean  bfd_mach_o_bfd_copy_private_symbol_data  PARAMS ((bfd *, asymbol *, bfd *, asymbol *));
+static boolean  bfd_mach_o_bfd_copy_private_section_data PARAMS ((bfd *, asection *, bfd *, asection *));
+static boolean  bfd_mach_o_bfd_copy_private_bfd_data PARAMS ((bfd *, bfd *));
+static long     bfd_mach_o_count_symbols             PARAMS ((bfd *));
+static long     bfd_mach_o_get_symtab_upper_bound    PARAMS ((bfd *));
+static long     bfd_mach_o_get_symtab                PARAMS ((bfd *, asymbol **));
+static void     bfd_mach_o_get_symbol_info           PARAMS ((bfd *, asymbol *, symbol_info *));
+static void     bfd_mach_o_print_symbol              PARAMS ((bfd *, PTR, asymbol *, bfd_print_symbol_type));
+static void     bfd_mach_o_convert_architecture      PARAMS ((bfd_mach_o_cpu_type, bfd_mach_o_cpu_subtype, enum bfd_architecture *, unsigned long *));
+static boolean  bfd_mach_o_write_contents            PARAMS ((bfd *));
+static int      bfd_mach_o_sizeof_headers            PARAMS ((bfd *, boolean));
+static asymbol *   bfd_mach_o_make_empty_symbol      PARAMS ((bfd *));
+static int      bfd_mach_o_write_header              PARAMS ((bfd *, bfd_mach_o_header *));
+static int      bfd_mach_o_read_header               PARAMS ((bfd *, bfd_mach_o_header *));
+static asection *  bfd_mach_o_make_bfd_section       PARAMS ((bfd *, bfd_mach_o_section *));
+static int      bfd_mach_o_scan_read_section         PARAMS ((bfd *, bfd_mach_o_section *, bfd_vma));
+static int      bfd_mach_o_scan_write_section        PARAMS ((bfd *, bfd_mach_o_section *, bfd_vma));
+static int      bfd_mach_o_scan_write_symtab_symbols PARAMS ((bfd *, bfd_mach_o_load_command *));
+static int      bfd_mach_o_scan_write_thread         PARAMS ((bfd *, bfd_mach_o_load_command *));
+static int      bfd_mach_o_scan_read_dylinker        PARAMS ((bfd *, bfd_mach_o_load_command *));
+static int      bfd_mach_o_scan_read_dylib           PARAMS ((bfd *, bfd_mach_o_load_command *));
+static int      bfd_mach_o_scan_read_prebound_dylib  PARAMS ((bfd *, bfd_mach_o_load_command *));
+static int      bfd_mach_o_scan_read_thread          PARAMS ((bfd *, bfd_mach_o_load_command *));
+static int      bfd_mach_o_scan_write_symtab         PARAMS ((bfd *, bfd_mach_o_load_command *));
+static int      bfd_mach_o_scan_read_dysymtab        PARAMS ((bfd *, bfd_mach_o_load_command *));
+static int      bfd_mach_o_scan_read_symtab          PARAMS ((bfd *, bfd_mach_o_load_command *));
+static int      bfd_mach_o_scan_read_segment         PARAMS ((bfd *, bfd_mach_o_load_command *));
+static int      bfd_mach_o_scan_write_segment        PARAMS ((bfd *, bfd_mach_o_load_command *));
+static int      bfd_mach_o_scan_read_command         PARAMS ((bfd *, bfd_mach_o_load_command *));
+static void     bfd_mach_o_flatten_sections          PARAMS ((bfd *));
+static const char * bfd_mach_o_i386_flavour_string   PARAMS ((unsigned int));
+static const char * bfd_mach_o_ppc_flavour_string    PARAMS ((unsigned int));
+
+/* The flags field of a section structure is separated into two parts a section
+   type and section attributes.  The section types are mutually exclusive (it
+   can only have one type) but the section attributes are not (it may have more
+   than one attribute).  */
+
+#define SECTION_TYPE             0x000000ff     /* 256 section types.  */
+#define SECTION_ATTRIBUTES       0xffffff00     /*  24 section attributes.  */
+
+/* Constants for the section attributes part of the flags field of a section
+   structure.  */
+
+#define SECTION_ATTRIBUTES_USR   0xff000000     /* User-settable attributes.  */
+#define S_ATTR_PURE_INSTRUCTIONS 0x80000000     /* Section contains only true machine instructions.  */
+#define SECTION_ATTRIBUTES_SYS   0x00ffff00     /* System setable attributes.  */
+#define S_ATTR_SOME_INSTRUCTIONS 0x00000400     /* Section contains some machine instructions.  */
+#define S_ATTR_EXT_RELOC         0x00000200     /* Section has external relocation entries.  */
+#define S_ATTR_LOC_RELOC         0x00000100     /* Section has local relocation entries.  */
+
+#define N_STAB 0xe0
+#define N_TYPE 0x1e
+#define N_EXT  0x01
+#define N_UNDF 0x0
+#define N_ABS  0x2
+#define N_SECT 0xe
+#define N_INDR 0xa
+
+boolean
+bfd_mach_o_valid (abfd)
+     bfd *abfd;
+{
+  if (abfd == NULL || abfd->xvec == NULL)
+    return 0;
+
+  if (! ((abfd->xvec == &mach_o_be_vec)
+        || (abfd->xvec == &mach_o_le_vec)
+        || (abfd->xvec == &mach_o_fat_vec)))
+    return 0;
+
+  if (abfd->tdata.mach_o_data == NULL)
+    return 0;
+  return 1;
+}
+
+/* Copy any private info we understand from the input symbol
+   to the output symbol.  */
+
+static boolean
+bfd_mach_o_bfd_copy_private_symbol_data (ibfd, isymbol, obfd, osymbol)
+     bfd *ibfd ATTRIBUTE_UNUSED;
+     asymbol *isymbol ATTRIBUTE_UNUSED;
+     bfd *obfd ATTRIBUTE_UNUSED;
+     asymbol *osymbol ATTRIBUTE_UNUSED;
+{
+  return true;
+}
+
+/* Copy any private info we understand from the input section
+   to the output section.  */
+
+static boolean
+bfd_mach_o_bfd_copy_private_section_data (ibfd, isection, obfd, osection)
+     bfd *ibfd ATTRIBUTE_UNUSED;
+     asection *isection ATTRIBUTE_UNUSED;
+     bfd *obfd ATTRIBUTE_UNUSED;
+     asection *osection ATTRIBUTE_UNUSED;
+{
+  return true;
+}
+
+/* Copy any private info we understand from the input bfd
+   to the output bfd.  */
+
+static boolean
+bfd_mach_o_bfd_copy_private_bfd_data (ibfd, obfd)
+     bfd *ibfd;
+     bfd *obfd;
+{
+  BFD_ASSERT (bfd_mach_o_valid (ibfd));
+  BFD_ASSERT (bfd_mach_o_valid (obfd));
+
+  obfd->tdata.mach_o_data = ibfd->tdata.mach_o_data;
+  obfd->tdata.mach_o_data->ibfd = ibfd;
+  return true;
+}
+
+static long
+bfd_mach_o_count_symbols (abfd)
+     bfd *abfd;
+{
+  bfd_mach_o_data_struct *mdata = NULL;
+  long nsyms = 0;
+  unsigned long i;
+  
+  BFD_ASSERT (bfd_mach_o_valid (abfd));
+  mdata = abfd->tdata.mach_o_data;
+
+  for (i = 0; i < mdata->header.ncmds; i++)
+    if (mdata->commands[i].type == BFD_MACH_O_LC_SYMTAB)
+      {
+       bfd_mach_o_symtab_command *sym = &mdata->commands[i].command.symtab;
+       nsyms += sym->nsyms;
+      }
+
+  return nsyms;
+}
+
+static long
+bfd_mach_o_get_symtab_upper_bound (abfd)
+     bfd *abfd;
+{
+  long nsyms = bfd_mach_o_count_symbols (abfd);
+
+  if (nsyms < 0)
+    return nsyms;
+
+  return ((nsyms + 1) * sizeof (asymbol *));
+}
+
+static long
+bfd_mach_o_get_symtab (abfd, alocation)
+     bfd *abfd;
+     asymbol **alocation;
+{
+  bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
+  long nsyms = bfd_mach_o_count_symbols (abfd);
+  asymbol **csym = alocation;
+  unsigned long i, j;
+
+  if (nsyms < 0)
+    return nsyms;
+
+  for (i = 0; i < mdata->header.ncmds; i++)
+    {
+      if (mdata->commands[i].type == BFD_MACH_O_LC_SYMTAB)
+       {
+         bfd_mach_o_symtab_command *sym = &mdata->commands[i].command.symtab;
+
+         if (bfd_mach_o_scan_read_symtab_symbols (abfd, &mdata->commands[i].command.symtab) != 0)
+           {
+             fprintf (stderr, "bfd_mach_o_get_symtab: unable to load symbols for section %lu\n", i);
+             return 0;
+           }
+
+         BFD_ASSERT (sym->symbols != NULL);
+
+         for (j = 0; j < sym->nsyms; j++)
+           {
+             BFD_ASSERT (csym < (alocation + nsyms));
+             *csym++ = &sym->symbols[j];
+           }
+       }
+    }
+
+  *csym++ = NULL;
+  
+  return nsyms;
+}
+
+static void
+bfd_mach_o_get_symbol_info (abfd, symbol, ret)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     asymbol *symbol;
+     symbol_info *ret;
+{
+  bfd_symbol_info (symbol, ret);
+}
+
+static void
+bfd_mach_o_print_symbol (abfd, afile, symbol, how)
+     bfd *abfd;
+     PTR afile;
+     asymbol *symbol;
+     bfd_print_symbol_type how;
+{
+  FILE *file = (FILE *) afile;
+
+  switch (how)
+    {
+    case bfd_print_symbol_name:
+      fprintf (file, "%s", symbol->name);
+      break;
+    default:
+      bfd_print_symbol_vandf (abfd, (PTR) file, symbol);
+      fprintf (file, " %-5s %s", symbol->section->name, symbol->name);
+    }
+}
+
+static void
+bfd_mach_o_convert_architecture (mtype, msubtype, type, subtype)
+     bfd_mach_o_cpu_type mtype;
+     bfd_mach_o_cpu_subtype msubtype ATTRIBUTE_UNUSED;
+     enum bfd_architecture *type;
+     unsigned long *subtype;
+{
+  *subtype = bfd_arch_unknown;
+
+  switch (mtype)
+    {
+    case BFD_MACH_O_CPU_TYPE_VAX: *type = bfd_arch_vax; break;
+    case BFD_MACH_O_CPU_TYPE_MC680x0: *type = bfd_arch_m68k; break;
+    case BFD_MACH_O_CPU_TYPE_I386: *type = bfd_arch_i386; break;
+    case BFD_MACH_O_CPU_TYPE_MIPS: *type = bfd_arch_mips; break;
+    case BFD_MACH_O_CPU_TYPE_MC98000: *type = bfd_arch_m98k; break;
+    case BFD_MACH_O_CPU_TYPE_HPPA: *type = bfd_arch_hppa; break;
+    case BFD_MACH_O_CPU_TYPE_ARM: *type = bfd_arch_arm; break;
+    case BFD_MACH_O_CPU_TYPE_MC88000: *type = bfd_arch_m88k; break;
+    case BFD_MACH_O_CPU_TYPE_SPARC: *type = bfd_arch_sparc; break;
+    case BFD_MACH_O_CPU_TYPE_I860: *type = bfd_arch_i860; break;
+    case BFD_MACH_O_CPU_TYPE_ALPHA: *type = bfd_arch_alpha; break;
+    case BFD_MACH_O_CPU_TYPE_POWERPC: *type = bfd_arch_powerpc; break;
+    default: *type = bfd_arch_unknown; break;
+    }
+
+  switch (*type)
+    {
+    case bfd_arch_i386: *subtype = bfd_mach_i386_i386; break;
+    case bfd_arch_sparc: *subtype = bfd_mach_sparc; break;
+    default:
+      *subtype = bfd_arch_unknown;
+    }
+}
+  
+static boolean
+bfd_mach_o_write_contents (abfd)
+     bfd *abfd;
+{
+  unsigned int i;
+  asection *s;
+
+  bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
+
+  /* Write data sections first in case they overlap header data to be
+     written later.  */
+
+  for (s = abfd->sections; s != (asection *) NULL; s = s->next)
+    ;
+
+#if 0
+  for (i = 0; i < mdata->header.ncmds; i++)
+    {
+      bfd_mach_o_load_command *cur = &mdata->commands[i];
+      if (cur->type != BFD_MACH_O_LC_SEGMENT)
+       break;
+
+      {
+       bfd_mach_o_segment_command *seg = &cur->command.segment;
+       char buf[1024];
+       bfd_vma nbytes = seg->filesize;
+       bfd_vma curoff = seg->fileoff;
+
+       while (nbytes > 0)
+         {
+           bfd_vma thisread = nbytes;
+
+           if (thisread > 1024)
+             thisread = 1024;
+
+           bfd_seek (abfd, curoff, SEEK_SET);
+           if (bfd_bread ((PTR) buf, thisread, abfd) != thisread)
+             return false;
+
+           bfd_seek (abfd, curoff, SEEK_SET);
+           if (bfd_bwrite ((PTR) buf, thisread, abfd) != thisread)
+             return false;
+
+           nbytes -= thisread;
+           curoff += thisread;
+         }
+      }
+  }
+#endif
+
+  /* Now write header information.  */
+  if (bfd_mach_o_write_header (abfd, &mdata->header) != 0)
+    return false;
+
+  for (i = 0; i < mdata->header.ncmds; i++)
+    {
+      unsigned char buf[8];
+      bfd_mach_o_load_command *cur = &mdata->commands[i];
+      unsigned long typeflag;
+
+      typeflag = cur->type_required ? cur->type & BFD_MACH_O_LC_REQ_DYLD : cur->type;
+
+      bfd_h_put_32 (abfd, typeflag, buf);
+      bfd_h_put_32 (abfd, cur->len, buf + 4);
+
+      bfd_seek (abfd, cur->offset, SEEK_SET);
+      if (bfd_bwrite ((PTR) buf, 8, abfd) != 8)
+       return false;
+
+      switch (cur->type)
+       {
+       case BFD_MACH_O_LC_SEGMENT:
+         if (bfd_mach_o_scan_write_segment (abfd, cur) != 0)
+           return false;
+         break;
+       case BFD_MACH_O_LC_SYMTAB:
+         if (bfd_mach_o_scan_write_symtab (abfd, cur) != 0)
+           return false;
+         break;
+       case BFD_MACH_O_LC_SYMSEG:
+         break;
+       case BFD_MACH_O_LC_THREAD:
+       case BFD_MACH_O_LC_UNIXTHREAD:
+         if (bfd_mach_o_scan_write_thread (abfd, cur) != 0)
+           return false;
+         break;
+       case BFD_MACH_O_LC_LOADFVMLIB:
+       case BFD_MACH_O_LC_IDFVMLIB:
+       case BFD_MACH_O_LC_IDENT:
+       case BFD_MACH_O_LC_FVMFILE:
+       case BFD_MACH_O_LC_PREPAGE:
+       case BFD_MACH_O_LC_DYSYMTAB:
+       case BFD_MACH_O_LC_LOAD_DYLIB:
+       case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
+       case BFD_MACH_O_LC_ID_DYLIB:
+       case BFD_MACH_O_LC_LOAD_DYLINKER:
+       case BFD_MACH_O_LC_ID_DYLINKER:
+       case BFD_MACH_O_LC_PREBOUND_DYLIB:
+       case BFD_MACH_O_LC_ROUTINES:
+       case BFD_MACH_O_LC_SUB_FRAMEWORK:
+         break;
+       default:
+         fprintf (stderr,
+                  "unable to write unknown load command 0x%lx\n",
+                  (long) cur->type);
+         return false;
+       }
+    }
+
+  return true;
+}
+
+static int
+bfd_mach_o_sizeof_headers (a, b)
+     bfd *a ATTRIBUTE_UNUSED;
+     boolean b ATTRIBUTE_UNUSED;
+{
+  return 0;
+}
+
+/* Make an empty symbol.  This is required only because
+   bfd_make_section_anyway wants to create a symbol for the section.  */
+
+static asymbol *
+bfd_mach_o_make_empty_symbol (abfd)
+     bfd *abfd;
+{
+  asymbol *new;
+
+  new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol));
+  if (new == NULL)
+    return new;
+  new->the_bfd = abfd;
+  return new;
+}
+
+static int
+bfd_mach_o_write_header (abfd, header)
+     bfd *abfd;
+     bfd_mach_o_header *header;
+{
+  unsigned char buf[28];
+
+  bfd_h_put_32 (abfd, header->magic, buf + 0);
+  bfd_h_put_32 (abfd, header->cputype, buf + 4);
+  bfd_h_put_32 (abfd, header->cpusubtype, buf + 8);
+  bfd_h_put_32 (abfd, header->filetype, buf + 12);
+  bfd_h_put_32 (abfd, header->ncmds, buf + 16);
+  bfd_h_put_32 (abfd, header->sizeofcmds, buf + 20);
+  bfd_h_put_32 (abfd, header->flags, buf + 24);
+      
+  bfd_seek (abfd, 0, SEEK_SET);
+  if (bfd_bwrite ((PTR) buf, 28, abfd) != 28)
+    return -1;
+
+  return 0;
+}
+
+static int
+bfd_mach_o_read_header (abfd, header)
+     bfd *abfd;
+     bfd_mach_o_header *header;
+{
+  unsigned char buf[28];
+  bfd_vma (*get32) PARAMS ((const bfd_byte *)) = NULL;
+
+  bfd_seek (abfd, 0, SEEK_SET);
+
+  if (bfd_bread ((PTR) buf, 28, abfd) != 28)
+    return -1;
+
+  if (bfd_getb32 (buf) == 0xfeedface)
+    {
+      header->byteorder = BFD_ENDIAN_BIG;
+      header->magic = 0xfeedface;
+      get32 = bfd_getb32;
+    }
+  else if (bfd_getl32 (buf) == 0xfeedface)
+    {
+      header->byteorder = BFD_ENDIAN_LITTLE; 
+      header->magic = 0xfeedface;
+      get32 = bfd_getl32;
+    }
+  else
+    {
+      header->byteorder = BFD_ENDIAN_UNKNOWN;
+      return -1;
+    }
+      
+  header->cputype = (*get32) (buf + 4);
+  header->cpusubtype = (*get32) (buf + 8);
+  header->filetype = (*get32) (buf + 12);
+  header->ncmds = (*get32) (buf + 16);
+  header->sizeofcmds = (*get32) (buf + 20);
+  header->flags = (*get32) (buf + 24);
+
+  return 0;
+}
+
+static asection *
+bfd_mach_o_make_bfd_section (abfd, section)
+     bfd *abfd;
+     bfd_mach_o_section *section;
+{
+  asection *bfdsec;
+  char *sname;
+  const char *prefix = "LC_SEGMENT";
+  unsigned int snamelen;
+
+  snamelen = strlen (prefix) + 1
+    + strlen (section->segname) + 1
+    + strlen (section->sectname) + 1;
+
+  sname = (char *) bfd_alloc (abfd, snamelen);
+  if (sname == NULL)
+    return NULL;
+  sprintf (sname, "%s.%s.%s", prefix, section->segname, section->sectname);
+
+  bfdsec = bfd_make_section_anyway (abfd, sname);
+  if (bfdsec == NULL)
+    return NULL;
+  
+  bfdsec->vma = section->addr;
+  bfdsec->lma = section->addr;
+  bfdsec->_raw_size = section->size;
+  bfdsec->filepos = section->offset;
+  bfdsec->alignment_power = section->align;
+
+  if (section->flags & BFD_MACH_O_S_ZEROFILL)
+    bfdsec->flags = SEC_ALLOC;
+  else
+    bfdsec->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC | SEC_CODE;
+
+  return bfdsec;
+}
+
+static int
+bfd_mach_o_scan_read_section (abfd, section, offset)
+     bfd *abfd;
+     bfd_mach_o_section *section;
+     bfd_vma offset;
+{
+  unsigned char buf[68];
+
+  bfd_seek (abfd, offset, SEEK_SET);
+  if (bfd_bread ((PTR) buf, 68, abfd) != 68)
+    return -1;
+  
+  memcpy (section->sectname, buf, 16);
+  section->sectname[16] = '\0';
+  memcpy (section->segname, buf + 16, 16);
+  section->segname[16] = '\0';
+  section->addr = bfd_h_get_32 (abfd, buf + 32);
+  section->size = bfd_h_get_32 (abfd, buf + 36);
+  section->offset = bfd_h_get_32 (abfd, buf + 40);
+  section->align = bfd_h_get_32 (abfd, buf + 44);
+  section->reloff = bfd_h_get_32 (abfd, buf + 48);
+  section->nreloc = bfd_h_get_32 (abfd, buf + 52);
+  section->flags = bfd_h_get_32 (abfd, buf + 56);
+  section->reserved1 = bfd_h_get_32 (abfd, buf + 60);
+  section->reserved2 = bfd_h_get_32 (abfd, buf + 64);
+  section->bfdsection = bfd_mach_o_make_bfd_section (abfd, section);
+
+  if (section->bfdsection == NULL)
+    return -1;
+
+  return 0;
+}
+
+static int
+bfd_mach_o_scan_write_section (abfd, section, offset)
+     bfd *abfd;
+     bfd_mach_o_section *section;
+     bfd_vma offset;
+{
+  unsigned char buf[68];
+
+  memcpy (buf, section->sectname, 16);
+  memcpy (buf + 16, section->segname, 16);
+  bfd_h_put_32 (abfd, section->addr, buf + 32);
+  bfd_h_put_32 (abfd, section->size, buf + 36);
+  bfd_h_put_32 (abfd, section->offset, buf + 40);
+  bfd_h_put_32 (abfd, section->align, buf + 44);
+  bfd_h_put_32 (abfd, section->reloff, buf + 48);
+  bfd_h_put_32 (abfd, section->nreloc, buf + 52);
+  bfd_h_put_32 (abfd, section->flags, buf + 56);
+  /* bfd_h_put_32 (abfd, section->reserved1, buf + 60); */
+  /* bfd_h_put_32 (abfd, section->reserved2, buf + 64); */
+
+  bfd_seek (abfd, offset, SEEK_SET);
+  if (bfd_bwrite ((PTR) buf, 68, abfd) != 68)
+    return -1;
+  
+  return 0;
+}
+
+static int
+bfd_mach_o_scan_write_symtab_symbols (abfd, command)
+     bfd *abfd;
+     bfd_mach_o_load_command *command;
+{
+  bfd_mach_o_symtab_command *sym = &command->command.symtab;
+  asymbol *s = NULL;
+  unsigned long i;
+
+  for (i = 0; i < sym->nsyms; i++)
+    {
+      unsigned char buf[12];
+      bfd_vma symoff = sym->symoff + (i * 12);
+      unsigned char ntype = 0;
+      unsigned char nsect = 0;
+      short ndesc = 0;
+
+      s = &sym->symbols[i];
+
+      /* Don't set this from the symbol information; use stored values.  */
+#if 0 
+      if (s->flags & BSF_GLOBAL)
+       ntype |= N_EXT;
+      if (s->flags & BSF_DEBUGGING)
+       ntype |= N_STAB;
+
+      if (s->section == bfd_und_section_ptr)
+       ntype |= N_UNDF;
+      else if (s->section == bfd_abs_section_ptr)
+       ntype |= N_ABS;
+      else
+       ntype |= N_SECT;
+#endif
+      
+      /* Instead just set from the stored values.  */
+      ntype = (s->udata.i >> 24) & 0xff;
+      nsect = (s->udata.i >> 16) & 0xff;
+      ndesc = s->udata.i & 0xffff;
+
+      bfd_h_put_32 (abfd, s->name - sym->strtab, buf);
+      bfd_h_put_8 (abfd, ntype, buf + 4);
+      bfd_h_put_8 (abfd, nsect, buf + 5);
+      bfd_h_put_16 (abfd, ndesc, buf + 6);
+      bfd_h_put_32 (abfd, s->section->vma + s->value, buf + 8);
+
+      bfd_seek (abfd, symoff, SEEK_SET);
+      if (bfd_bwrite ((PTR) buf, 12, abfd) != 12)
+       {
+         fprintf (stderr, "bfd_mach_o_scan_write_symtab_symbols: unable to write %d bytes at %lu\n", 
+                  12, (unsigned long) symoff);
+         return -1; 
+       }
+    }
+
+  return 0;
+}
+
+int
+bfd_mach_o_scan_read_symtab_symbol (abfd, sym, s, i)
+     bfd *abfd;
+     bfd_mach_o_symtab_command *sym;
+     asymbol *s;
+     unsigned long i;
+{
+  bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
+  bfd_vma symoff = sym->symoff + (i * 12);
+  unsigned char buf[12];
+  unsigned char type = -1;
+  unsigned char section = -1;
+  short desc = -1;
+  long value = -1;
+  unsigned long stroff = -1;
+  unsigned int symtype = -1;
+
+  BFD_ASSERT (sym->strtab != NULL);
+
+  bfd_seek (abfd, symoff, SEEK_SET);
+  if (bfd_bread ((PTR) buf, 12, abfd) != 12)
+    {
+      fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: unable to read %d bytes at %lu\n",
+              12, (unsigned long) symoff);
+      return -1;
+    }
+
+  stroff = bfd_h_get_32 (abfd, buf);
+  type = bfd_h_get_8 (abfd, buf + 4);
+  symtype = (type & 0x0e);
+  section = bfd_h_get_8 (abfd, buf + 5) - 1;
+  desc = bfd_h_get_16 (abfd, buf + 6);
+  value = bfd_h_get_32 (abfd, buf + 8);
+
+  if (stroff >= sym->strsize)
+    {
+      fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: symbol name out of range (%lu >= %lu)\n",
+              (unsigned long) stroff, (unsigned long) sym->strsize);
+      return -1; 
+    }
+
+  s->the_bfd = abfd;
+  s->name = sym->strtab + stroff;
+  s->value = value;
+  s->udata.i = (type << 24) | (section << 16) | desc;
+  s->flags = 0x0;
+
+  if (type & BFD_MACH_O_N_STAB)
+    {
+      s->flags |= BSF_DEBUGGING;
+      s->section = bfd_und_section_ptr;
+    }
+  else
+    {
+      if (type & BFD_MACH_O_N_PEXT)
+       {
+         type &= ~BFD_MACH_O_N_PEXT;
+         s->flags |= BSF_GLOBAL;
+       }
+
+      if (type & BFD_MACH_O_N_EXT)
+       {
+         type &= ~BFD_MACH_O_N_EXT;
+         s->flags |= BSF_GLOBAL;
+       }
+
+      switch (symtype)
+       {
+       case BFD_MACH_O_N_UNDF:
+         s->section = bfd_und_section_ptr;
+         break;
+       case BFD_MACH_O_N_PBUD:
+         s->section = bfd_und_section_ptr;
+         break;
+       case BFD_MACH_O_N_ABS:
+         s->section = bfd_abs_section_ptr;
+         break;
+       case BFD_MACH_O_N_SECT:
+         if ((section > 0) && (section <= mdata->nsects))
+           {
+             s->section = mdata->sections[section - 1]->bfdsection;
+             s->value = s->value - mdata->sections[section - 1]->addr;
+           }
+         else
+           {
+             /* Mach-O uses 0 to mean "no section"; not an error.  */
+             if (section != 0)
+               {
+                 fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: "
+                          "symbol \"%s\" specified invalid section %d (max %lu): setting to undefined\n", 
+                          s->name, section, mdata->nsects);
+               }
+             s->section = bfd_und_section_ptr;
+           }
+         break;
+       case BFD_MACH_O_N_INDR:
+         fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: "
+                  "symbol \"%s\" is unsupported 'indirect' reference: setting to undefined\n", 
+                  s->name);
+         s->section = bfd_und_section_ptr;
+         break;
+       default:
+         fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbol: "
+                  "symbol \"%s\" specified invalid type field 0x%x: setting to undefined\n", 
+                  s->name, symtype);
+         s->section = bfd_und_section_ptr;
+         break;
+       }
+    }
+
+  return 0;
+}
+
+int
+bfd_mach_o_scan_read_symtab_strtab (abfd, sym)
+     bfd *abfd;
+     bfd_mach_o_symtab_command *sym;
+{
+  BFD_ASSERT (sym->strtab == NULL);
+
+  if (abfd->flags & BFD_IN_MEMORY)
+    {
+      struct bfd_in_memory *b;
+
+      b = (struct bfd_in_memory *) abfd->iostream;
+
+      if ((sym->stroff + sym->strsize) > b->size)
+       {
+         bfd_set_error (bfd_error_file_truncated);
+         return -1;
+       }
+      sym->strtab = b->buffer + sym->stroff;
+      return 0;
+    }
+
+  sym->strtab = bfd_alloc (abfd, sym->strsize);
+  if (sym->strtab == NULL)
+    return -1;
+
+  bfd_seek (abfd, sym->stroff, SEEK_SET);
+  if (bfd_bread ((PTR) sym->strtab, sym->strsize, abfd) != sym->strsize)
+    {
+      fprintf (stderr, "bfd_mach_o_scan_read_symtab_strtab: unable to read %lu bytes at %lu\n",
+              sym->strsize, sym->stroff);
+      return -1; 
+    }
+
+  return 0;
+}
+
+int 
+bfd_mach_o_scan_read_symtab_symbols (abfd, sym)
+     bfd *abfd;
+     bfd_mach_o_symtab_command *sym;
+{
+  unsigned long i;
+  int ret;
+
+  BFD_ASSERT (sym->symbols == NULL);
+  sym->symbols = bfd_alloc (abfd, sym->nsyms * sizeof (asymbol));
+
+  if (sym->symbols == NULL)
+    {
+      fprintf (stderr, "bfd_mach_o_scan_read_symtab_symbols: unable to allocate memory for symbols\n");
+      return -1; 
+    }
+  
+  ret = bfd_mach_o_scan_read_symtab_strtab (abfd, sym);
+  if (ret != 0)
+    return ret;
+
+  for (i = 0; i < sym->nsyms; i++)
+    {
+      ret = bfd_mach_o_scan_read_symtab_symbol (abfd, sym, &sym->symbols[i], i);
+      if (ret != 0)
+       return ret;
+    }
+  
+  return 0;
+}
+
+int
+bfd_mach_o_scan_read_dysymtab_symbol (abfd, dysym, sym, s, i)
+     bfd *abfd;
+     bfd_mach_o_dysymtab_command *dysym;
+     bfd_mach_o_symtab_command *sym;
+     asymbol *s;
+     unsigned long i;
+{
+  unsigned long isymoff = dysym->indirectsymoff + (i * 4);
+  unsigned long symindex;
+  unsigned char buf[4];
+
+  BFD_ASSERT (i < dysym->nindirectsyms);
+  
+  bfd_seek (abfd, isymoff, SEEK_SET);
+  if (bfd_bread ((PTR) buf, 4, abfd) != 4)
+    {
+      fprintf (stderr, "bfd_mach_o_scan_read_dysymtab_symbol: unable to read %lu bytes at %lu\n",
+              (unsigned long) 4, isymoff);
+      return -1;
+    }
+  symindex = bfd_h_get_32 (abfd, buf);
+  
+  return bfd_mach_o_scan_read_symtab_symbol (abfd, sym, s, symindex);
+}
+
+static const char *
+bfd_mach_o_i386_flavour_string (flavour)
+     unsigned int flavour;
+{
+  switch ((int) flavour)
+    {
+    case BFD_MACH_O_i386_NEW_THREAD_STATE: return "i386_NEW_THREAD_STATE";
+    case BFD_MACH_O_i386_FLOAT_STATE: return "i386_FLOAT_STATE";
+    case BFD_MACH_O_i386_ISA_PORT_MAP_STATE: return "i386_ISA_PORT_MAP_STATE";
+    case BFD_MACH_O_i386_V86_ASSIST_STATE: return "i386_V86_ASSIST_STATE";
+    case BFD_MACH_O_i386_REGS_SEGS_STATE: return "i386_REGS_SEGS_STATE";
+    case BFD_MACH_O_i386_THREAD_SYSCALL_STATE: return "i386_THREAD_SYSCALL_STATE";
+    case BFD_MACH_O_i386_THREAD_STATE_NONE: return "i386_THREAD_STATE_NONE";
+    case BFD_MACH_O_i386_SAVED_STATE: return "i386_SAVED_STATE";
+    case BFD_MACH_O_i386_THREAD_STATE: return "i386_THREAD_STATE";
+    case BFD_MACH_O_i386_THREAD_FPSTATE: return "i386_THREAD_FPSTATE";
+    case BFD_MACH_O_i386_THREAD_EXCEPTSTATE: return "i386_THREAD_EXCEPTSTATE";
+    case BFD_MACH_O_i386_THREAD_CTHREADSTATE: return "i386_THREAD_CTHREADSTATE";
+    default: return "UNKNOWN";
+    }
+}
+
+static const char *
+bfd_mach_o_ppc_flavour_string (flavour)
+     unsigned int flavour;
+{
+  switch ((int) flavour)
+    {
+    case BFD_MACH_O_PPC_THREAD_STATE: return "PPC_THREAD_STATE";
+    case BFD_MACH_O_PPC_FLOAT_STATE: return "PPC_FLOAT_STATE";
+    case BFD_MACH_O_PPC_EXCEPTION_STATE: return "PPC_EXCEPTION_STATE";
+    case BFD_MACH_O_PPC_VECTOR_STATE: return "PPC_VECTOR_STATE";
+    default: return "UNKNOWN";
+    }
+}
+
+static int
+bfd_mach_o_scan_write_thread (abfd, command)
+     bfd *abfd;
+     bfd_mach_o_load_command *command;
+{
+  bfd_mach_o_thread_command *cmd = &command->command.thread;
+  unsigned int i;
+  unsigned char buf[8];
+  bfd_vma offset;
+  unsigned int nflavours;
+
+  BFD_ASSERT ((command->type == BFD_MACH_O_LC_THREAD)
+             || (command->type == BFD_MACH_O_LC_UNIXTHREAD));
+
+  offset = 8;
+  nflavours = 0;
+  for (i = 0; i < cmd->nflavours; i++)
+    {
+      BFD_ASSERT ((cmd->flavours[i].size % 4) == 0);
+      BFD_ASSERT (cmd->flavours[i].offset == (command->offset + offset + 8));
+
+      bfd_h_put_32 (abfd, cmd->flavours[i].flavour, buf);
+      bfd_h_put_32 (abfd, (cmd->flavours[i].size / 4), buf + 4);
+
+      bfd_seek (abfd, command->offset + offset, SEEK_SET);
+      if (bfd_bwrite ((PTR) buf, 8, abfd) != 8)
+       return -1;
+
+      offset += cmd->flavours[i].size + 8;
+    }
+
+  return 0;
+}
+
+static int
+bfd_mach_o_scan_read_dylinker (abfd, command)
+     bfd *abfd;
+     bfd_mach_o_load_command *command;
+{
+  bfd_mach_o_dylinker_command *cmd = &command->command.dylinker;
+  unsigned char buf[4];
+  unsigned int nameoff;
+  asection *bfdsec;
+  char *sname;
+  const char *prefix;
+
+  BFD_ASSERT ((command->type == BFD_MACH_O_LC_ID_DYLINKER)
+             || (command->type == BFD_MACH_O_LC_LOAD_DYLINKER));
+
+  bfd_seek (abfd, command->offset + 8, SEEK_SET);
+  if (bfd_bread ((PTR) buf, 4, abfd) != 4)
+    return -1;
+
+  nameoff = bfd_h_get_32 (abfd, buf + 0);
+
+  cmd->name_offset = command->offset + nameoff;
+  cmd->name_len = command->len - nameoff;
+
+  if (command->type == BFD_MACH_O_LC_LOAD_DYLINKER)
+    prefix = "LC_LOAD_DYLINKER";
+  else if (command->type == BFD_MACH_O_LC_ID_DYLINKER)
+    prefix = "LC_ID_DYLINKER";
+  else
+    abort ();
+
+  sname = (char *) bfd_alloc (abfd, strlen (prefix) + 1);
+  if (sname == NULL)
+    return -1;
+  strcpy (sname, prefix);
+
+  bfdsec = bfd_make_section_anyway (abfd, sname);
+  if (bfdsec == NULL)
+    return -1;
+  
+  bfdsec->vma = 0;
+  bfdsec->lma = 0;
+  bfdsec->_raw_size = command->len - 8;
+  bfdsec->filepos = command->offset + 8;
+  bfdsec->alignment_power = 0;
+  bfdsec->flags = SEC_HAS_CONTENTS;
+
+  cmd->section = bfdsec;
+
+  return 0;
+}
+
+static int
+bfd_mach_o_scan_read_dylib (abfd, command)
+     bfd *abfd;
+     bfd_mach_o_load_command *command;
+{
+  bfd_mach_o_dylib_command *cmd = &command->command.dylib;
+  unsigned char buf[16];
+  unsigned int nameoff;
+  asection *bfdsec;
+  char *sname;
+  const char *prefix;
+
+  BFD_ASSERT ((command->type == BFD_MACH_O_LC_ID_DYLIB)
+             || (command->type == BFD_MACH_O_LC_LOAD_DYLIB)
+             || (command->type == BFD_MACH_O_LC_LOAD_WEAK_DYLIB));
+
+  bfd_seek (abfd, command->offset + 8, SEEK_SET);
+  if (bfd_bread ((PTR) buf, 16, abfd) != 16)
+    return -1;
+
+  nameoff = bfd_h_get_32 (abfd, buf + 0);
+  cmd->timestamp = bfd_h_get_32 (abfd, buf + 4);
+  cmd->current_version = bfd_h_get_32 (abfd, buf + 8);
+  cmd->compatibility_version = bfd_h_get_32 (abfd, buf + 12);
+
+  cmd->name_offset = command->offset + nameoff;
+  cmd->name_len = command->len - nameoff;
+
+  if (command->type == BFD_MACH_O_LC_LOAD_DYLIB)
+    prefix = "LC_LOAD_DYLIB";
+  else if (command->type == BFD_MACH_O_LC_LOAD_WEAK_DYLIB)
+    prefix = "LC_LOAD_WEAK_DYLIB";
+  else if (command->type == BFD_MACH_O_LC_ID_DYLIB)
+    prefix = "LC_ID_DYLIB";
+  else
+    abort ();
+
+  sname = (char *) bfd_alloc (abfd, strlen (prefix) + 1);
+  if (sname == NULL)
+    return -1;
+  strcpy (sname, prefix);
+
+  bfdsec = bfd_make_section_anyway (abfd, sname);
+  if (bfdsec == NULL)
+    return -1;
+  
+  bfdsec->vma = 0;
+  bfdsec->lma = 0;
+  bfdsec->_raw_size = command->len - 8;
+  bfdsec->filepos = command->offset + 8;
+  bfdsec->alignment_power = 0;
+  bfdsec->flags = SEC_HAS_CONTENTS;
+
+  cmd->section = bfdsec;
+
+  return 0;
+}
+
+static int
+bfd_mach_o_scan_read_prebound_dylib (abfd, command)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     bfd_mach_o_load_command *command ATTRIBUTE_UNUSED;
+{
+  /* bfd_mach_o_prebound_dylib_command *cmd = &command->command.prebound_dylib; */
+
+  BFD_ASSERT (command->type == BFD_MACH_O_LC_PREBOUND_DYLIB);
+  return 0;
+}
+
+static int
+bfd_mach_o_scan_read_thread (abfd, command)
+     bfd *abfd;
+     bfd_mach_o_load_command *command;
+{
+  bfd_mach_o_data_struct *mdata = NULL;
+  bfd_mach_o_thread_command *cmd = &command->command.thread;
+  unsigned char buf[8];
+  bfd_vma offset;
+  unsigned int nflavours;
+  unsigned int i;
+
+  BFD_ASSERT ((command->type == BFD_MACH_O_LC_THREAD)
+             || (command->type == BFD_MACH_O_LC_UNIXTHREAD));
+
+  BFD_ASSERT (bfd_mach_o_valid (abfd));
+  mdata = abfd->tdata.mach_o_data;
+  
+  offset = 8;
+  nflavours = 0;
+  while (offset != command->len)
+    {
+      if (offset >= command->len)
+       return -1;
+
+      bfd_seek (abfd, command->offset + offset, SEEK_SET);
+
+      if (bfd_bread ((PTR) buf, 8, abfd) != 8)
+       return -1;
+
+      offset += 8 + bfd_h_get_32 (abfd, buf + 4) * 4;
+      nflavours++;
+    }
+
+  cmd->flavours =
+    ((bfd_mach_o_thread_flavour *)
+     bfd_alloc (abfd, nflavours * sizeof (bfd_mach_o_thread_flavour)));
+  if (cmd->flavours == NULL)
+    return -1;
+  cmd->nflavours = nflavours;
+
+  offset = 8;
+  nflavours = 0;
+  while (offset != command->len)
+    {
+      if (offset >= command->len)
+       return -1;
+
+      if (nflavours >= cmd->nflavours)
+       return -1;
+
+      bfd_seek (abfd, command->offset + offset, SEEK_SET);
+
+      if (bfd_bread ((PTR) buf, 8, abfd) != 8)
+       return -1;
+
+      cmd->flavours[nflavours].flavour = bfd_h_get_32 (abfd, buf);
+      cmd->flavours[nflavours].offset = command->offset + offset + 8;
+      cmd->flavours[nflavours].size = bfd_h_get_32 (abfd, buf + 4) * 4;
+      offset += cmd->flavours[nflavours].size + 8;
+      nflavours++;
+    }
+
+  for (i = 0; i < nflavours; i++)
+    {
+      asection *bfdsec;
+      unsigned int snamelen;
+      char *sname;
+      const char *flavourstr;
+      const char *prefix = "LC_THREAD";
+      unsigned int i = 0;
+    
+      switch (mdata->header.cputype)
+       {
+       case BFD_MACH_O_CPU_TYPE_POWERPC:
+         flavourstr = bfd_mach_o_ppc_flavour_string (cmd->flavours[i].flavour);
+         break;
+       case BFD_MACH_O_CPU_TYPE_I386:
+         flavourstr = bfd_mach_o_i386_flavour_string (cmd->flavours[i].flavour);
+         break;
+       default:
+         flavourstr = "UNKNOWN_ARCHITECTURE";
+         break;
+       }
+    
+      snamelen = strlen (prefix) + 1 + 20 + 1 + strlen (flavourstr) + 1;
+      sname = (char *) bfd_alloc (abfd, snamelen);
+      if (sname == NULL)
+       return -1;
+
+      for (;;)
+       {
+         sprintf (sname, "%s.%s.%u", prefix, flavourstr, i);
+         if (bfd_get_section_by_name (abfd, sname) == NULL) {
+           break;
+         }
+         i++;
+       }
+
+      bfdsec = bfd_make_section (abfd, sname);
+  
+      bfdsec->vma = 0;
+      bfdsec->lma = 0;
+      bfdsec->_raw_size = cmd->flavours[i].size;
+      bfdsec->filepos = cmd->flavours[i].offset;
+      bfdsec->alignment_power = 0x0;
+      bfdsec->flags = SEC_HAS_CONTENTS;
+
+      cmd->section = bfdsec;
+    }
+
+  return 0;
+}
+
+static int 
+bfd_mach_o_scan_write_symtab (abfd, command)
+     bfd *abfd;
+     bfd_mach_o_load_command *command;
+{
+  bfd_mach_o_symtab_command *seg = &command->command.symtab;
+  unsigned char buf[16];
+
+  BFD_ASSERT (command->type == BFD_MACH_O_LC_SYMTAB);
+
+  bfd_h_put_32 (abfd, seg->symoff, buf);
+  bfd_h_put_32 (abfd, seg->nsyms, buf + 4);
+  bfd_h_put_32 (abfd, seg->stroff, buf + 8);
+  bfd_h_put_32 (abfd, seg->strsize, buf + 12);
+
+  bfd_seek (abfd, command->offset + 8, SEEK_SET);
+  if (bfd_bwrite ((PTR) buf, 16, abfd) != 16)
+    return -1;
+  
+  if (bfd_mach_o_scan_write_symtab_symbols (abfd, command) != 0)
+    return -1;
+
+  return 0;
+}
+
+static int 
+bfd_mach_o_scan_read_dysymtab (abfd, command)
+     bfd *abfd;
+     bfd_mach_o_load_command *command;
+{
+  bfd_mach_o_dysymtab_command *seg = &command->command.dysymtab;
+  unsigned char buf[72];
+
+  BFD_ASSERT (command->type == BFD_MACH_O_LC_DYSYMTAB);
+
+  bfd_seek (abfd, command->offset + 8, SEEK_SET);
+  if (bfd_bread ((PTR) buf, 72, abfd) != 72)
+    return -1;
+
+  seg->ilocalsym = bfd_h_get_32 (abfd, buf + 0);
+  seg->nlocalsym = bfd_h_get_32 (abfd, buf + 4);
+  seg->iextdefsym = bfd_h_get_32 (abfd, buf + 8);
+  seg->nextdefsym = bfd_h_get_32 (abfd, buf + 12);
+  seg->iundefsym = bfd_h_get_32 (abfd, buf + 16);
+  seg->nundefsym = bfd_h_get_32 (abfd, buf + 20);
+  seg->tocoff = bfd_h_get_32 (abfd, buf + 24);
+  seg->ntoc = bfd_h_get_32 (abfd, buf + 28);
+  seg->modtaboff = bfd_h_get_32 (abfd, buf + 32);
+  seg->nmodtab = bfd_h_get_32 (abfd, buf + 36);
+  seg->extrefsymoff = bfd_h_get_32 (abfd, buf + 40);
+  seg->nextrefsyms = bfd_h_get_32 (abfd, buf + 44);
+  seg->indirectsymoff = bfd_h_get_32 (abfd, buf + 48);
+  seg->nindirectsyms = bfd_h_get_32 (abfd, buf + 52);
+  seg->extreloff = bfd_h_get_32 (abfd, buf + 56);
+  seg->nextrel = bfd_h_get_32 (abfd, buf + 60);
+  seg->locreloff = bfd_h_get_32 (abfd, buf + 64);
+  seg->nlocrel = bfd_h_get_32 (abfd, buf + 68);
+
+  return 0;
+}
+
+static int 
+bfd_mach_o_scan_read_symtab (abfd, command)
+     bfd *abfd;
+     bfd_mach_o_load_command *command;
+{
+  bfd_mach_o_symtab_command *seg = &command->command.symtab;
+  unsigned char buf[16];
+  asection *bfdsec;
+  char *sname;
+  const char *prefix = "LC_SYMTAB.stabs";
+
+  BFD_ASSERT (command->type == BFD_MACH_O_LC_SYMTAB);
+
+  bfd_seek (abfd, command->offset + 8, SEEK_SET);
+  if (bfd_bread ((PTR) buf, 16, abfd) != 16)
+    return -1;
+  
+  seg->symoff = bfd_h_get_32 (abfd, buf);
+  seg->nsyms = bfd_h_get_32 (abfd, buf + 4);
+  seg->stroff = bfd_h_get_32 (abfd, buf + 8);
+  seg->strsize = bfd_h_get_32 (abfd, buf + 12);
+  seg->symbols = NULL;
+  seg->strtab = NULL;
+
+  sname = (char *) bfd_alloc (abfd, strlen (prefix) + 1);
+  if (sname == NULL)
+    return -1;
+  strcpy (sname, prefix);
+
+  bfdsec = bfd_make_section_anyway (abfd, sname);
+  if (bfdsec == NULL)
+    return -1;
+  
+  bfdsec->vma = 0;
+  bfdsec->lma = 0;
+  bfdsec->_raw_size = seg->nsyms * 12;
+  bfdsec->filepos = seg->symoff;
+  bfdsec->alignment_power = 0;
+  bfdsec->flags = SEC_HAS_CONTENTS;
+
+  seg->stabs_segment = bfdsec;
+
+  prefix = "LC_SYMTAB.stabstr";
+  sname = (char *) bfd_alloc (abfd, strlen (prefix) + 1);
+  if (sname == NULL)
+    return -1;
+  strcpy (sname, prefix);
+
+  bfdsec = bfd_make_section_anyway (abfd, sname);
+  if (bfdsec == NULL)
+    return -1;
+  
+  bfdsec->vma = 0;
+  bfdsec->lma = 0;
+  bfdsec->_raw_size = seg->strsize;
+  bfdsec->filepos = seg->stroff;
+  bfdsec->alignment_power = 0;
+  bfdsec->flags = SEC_HAS_CONTENTS;
+
+  seg->stabstr_segment = bfdsec;
+
+  return 0;
+}
+
+static int
+bfd_mach_o_scan_read_segment (abfd, command)
+     bfd *abfd;
+     bfd_mach_o_load_command *command;
+{
+  unsigned char buf[48];
+  bfd_mach_o_segment_command *seg = &command->command.segment;
+  unsigned long i;
+  asection *bfdsec;
+  char *sname;
+  const char *prefix = "LC_SEGMENT";
+  unsigned int snamelen;
+  BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT);
+
+  bfd_seek (abfd, command->offset + 8, SEEK_SET);
+  if (bfd_bread ((PTR) buf, 48, abfd) != 48)
+    return -1;
+
+  memcpy (seg->segname, buf, 16);
+  seg->vmaddr = bfd_h_get_32 (abfd, buf + 16);
+  seg->vmsize = bfd_h_get_32 (abfd, buf + 20);
+  seg->fileoff = bfd_h_get_32 (abfd, buf + 24);
+  seg->filesize = bfd_h_get_32 (abfd, buf +  28);
+  /* seg->maxprot = bfd_h_get_32 (abfd, buf + 32); */
+  /* seg->initprot = bfd_h_get_32 (abfd, buf + 36); */
+  seg->nsects = bfd_h_get_32 (abfd, buf + 40);
+  seg->flags = bfd_h_get_32 (abfd, buf + 44);
+
+  snamelen = strlen (prefix) + 1 + strlen (seg->segname) + 1;
+  sname = (char *) bfd_alloc (abfd, snamelen);
+  if (sname == NULL)
+    return -1;
+  sprintf (sname, "%s.%s", prefix, seg->segname);
+
+  bfdsec = bfd_make_section_anyway (abfd, sname);
+  if (bfdsec == NULL)
+    return -1;
+
+  bfdsec->vma = seg->vmaddr;
+  bfdsec->lma = seg->vmaddr;
+  bfdsec->_raw_size = seg->filesize;
+  bfdsec->filepos = seg->fileoff;
+  bfdsec->alignment_power = 0x0;
+  bfdsec->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC | SEC_CODE;
+
+  seg->segment = bfdsec;
+
+  if (seg->nsects != 0)
+    {
+      seg->sections = 
+       ((bfd_mach_o_section *)
+        bfd_alloc (abfd, seg->nsects * sizeof (bfd_mach_o_section)));
+      if (seg->sections == NULL)
+       return -1;
+    
+      for (i = 0; i < seg->nsects; i++)
+       {
+         bfd_vma segoff = command->offset + 48 + 8 + (i * 68);
+
+         if (bfd_mach_o_scan_read_section (abfd, &seg->sections[i], segoff) != 0)
+           return -1;
+       }    
+    }
+
+  return 0;
+}
+
+static int
+bfd_mach_o_scan_write_segment (abfd, command)
+     bfd *abfd;
+     bfd_mach_o_load_command *command;
+{
+  unsigned char buf[48];
+  bfd_mach_o_segment_command *seg = &command->command.segment;
+  unsigned long i;
+  
+  BFD_ASSERT (command->type == BFD_MACH_O_LC_SEGMENT);
+
+  memcpy (buf, seg->segname, 16);
+  bfd_h_put_32 (abfd, seg->vmaddr, buf + 16);
+  bfd_h_put_32 (abfd, seg->vmsize, buf + 20);
+  bfd_h_put_32 (abfd, seg->fileoff, buf + 24);
+  bfd_h_put_32 (abfd, seg->filesize, buf + 28);
+  bfd_h_put_32 (abfd, 0 /* seg->maxprot */, buf + 32);
+  bfd_h_put_32 (abfd, 0 /* seg->initprot */, buf + 36);
+  bfd_h_put_32 (abfd, seg->nsects, buf + 40);
+  bfd_h_put_32 (abfd, seg->flags, buf + 44);
+
+  bfd_seek (abfd, command->offset + 8, SEEK_SET);
+  if (bfd_bwrite ((PTR) buf, 48, abfd) != 48)
+    return -1;
+
+  {
+    char buf[1024];
+    bfd_vma nbytes = seg->filesize;
+    bfd_vma curoff = seg->fileoff;
+    
+    while (nbytes > 0)
+      {
+       bfd_vma thisread = nbytes;
+
+       if (thisread > 1024)
+         thisread = 1024;
+
+       bfd_seek (abfd, curoff, SEEK_SET);
+       if (bfd_bread ((PTR) buf, thisread, abfd) != thisread)
+         return -1;
+
+       bfd_seek (abfd, curoff, SEEK_SET);
+       if (bfd_bwrite ((PTR) buf, thisread, abfd) != thisread)
+         return -1;
+
+       nbytes -= thisread;
+       curoff += thisread;
+      }
+  }
+
+  for (i = 0; i < seg->nsects; i++)
+    {
+      bfd_vma segoff = command->offset + 48 + 8 + (i * 68);
+
+      if (bfd_mach_o_scan_write_section (abfd, &seg->sections[i], segoff) != 0)
+       return -1;
+    }
+
+  return 0;
+}
+
+static int
+bfd_mach_o_scan_read_command (abfd, command)
+     bfd *abfd;
+     bfd_mach_o_load_command *command;
+{
+  unsigned char buf[8];
+
+  bfd_seek (abfd, command->offset, SEEK_SET);
+  if (bfd_bread ((PTR) buf, 8, abfd) != 8)
+    return -1;
+
+  command->type = (bfd_h_get_32 (abfd, buf) & ~BFD_MACH_O_LC_REQ_DYLD);
+  command->type_required = (bfd_h_get_32 (abfd, buf) & BFD_MACH_O_LC_REQ_DYLD) ? 1 : 0;
+  command->len = bfd_h_get_32 (abfd, buf + 4);
+
+  switch (command->type)
+    {
+    case BFD_MACH_O_LC_SEGMENT:
+      if (bfd_mach_o_scan_read_segment (abfd, command) != 0)
+       return -1;
+      break;
+    case BFD_MACH_O_LC_SYMTAB:
+      if (bfd_mach_o_scan_read_symtab (abfd, command) != 0)
+       return -1;
+      break;
+    case BFD_MACH_O_LC_SYMSEG:
+      break;
+    case BFD_MACH_O_LC_THREAD:
+    case BFD_MACH_O_LC_UNIXTHREAD:
+      if (bfd_mach_o_scan_read_thread (abfd, command) != 0)
+       return -1;
+      break;
+    case BFD_MACH_O_LC_LOAD_DYLINKER:
+    case BFD_MACH_O_LC_ID_DYLINKER:
+      if (bfd_mach_o_scan_read_dylinker (abfd, command) != 0)
+       return -1;
+      break;
+    case BFD_MACH_O_LC_LOAD_DYLIB:
+    case BFD_MACH_O_LC_ID_DYLIB:
+    case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
+      if (bfd_mach_o_scan_read_dylib (abfd, command) != 0)
+       return -1;
+      break;
+    case BFD_MACH_O_LC_PREBOUND_DYLIB:
+      if (bfd_mach_o_scan_read_prebound_dylib (abfd, command) != 0)
+       return -1;
+      break;
+    case BFD_MACH_O_LC_LOADFVMLIB:
+    case BFD_MACH_O_LC_IDFVMLIB:
+    case BFD_MACH_O_LC_IDENT:
+    case BFD_MACH_O_LC_FVMFILE:
+    case BFD_MACH_O_LC_PREPAGE:
+    case BFD_MACH_O_LC_ROUTINES:
+    case BFD_MACH_O_LC_SUB_FRAMEWORK:
+      break;
+    case BFD_MACH_O_LC_DYSYMTAB:
+      if (bfd_mach_o_scan_read_dysymtab (abfd, command) != 0)
+       return -1;
+      break;
+    case BFD_MACH_O_LC_SUB_UMBRELLA:
+    case BFD_MACH_O_LC_SUB_CLIENT:
+    case BFD_MACH_O_LC_SUB_LIBRARY:
+    case BFD_MACH_O_LC_TWOLEVEL_HINTS:
+    case BFD_MACH_O_LC_PREBIND_CKSUM:
+      break;
+    default:
+      fprintf (stderr, "unable to read unknown load command 0x%lx\n",
+              (unsigned long) command->type);
+      break;
+    }
+
+  return 0;
+}
+
+static void
+bfd_mach_o_flatten_sections (abfd)
+     bfd *abfd;
+{
+  bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
+  long csect = 0;
+  unsigned long i, j;
+  
+  mdata->nsects = 0;
+
+  for (i = 0; i < mdata->header.ncmds; i++)
+    {
+      if (mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT)
+       {
+         bfd_mach_o_segment_command *seg = &mdata->commands[i].command.segment;
+         mdata->nsects += seg->nsects;
+       }
+    }
+
+  mdata->sections = bfd_alloc (abfd, mdata->nsects * sizeof (bfd_mach_o_section *));
+  csect = 0;
+
+  for (i = 0; i < mdata->header.ncmds; i++)
+    {
+      if (mdata->commands[i].type == BFD_MACH_O_LC_SEGMENT)
+       {
+         bfd_mach_o_segment_command *seg = &mdata->commands[i].command.segment;
+
+         BFD_ASSERT (csect + seg->nsects <= mdata->nsects);
+
+         for (j = 0; j < seg->nsects; j++)
+           mdata->sections[csect++] = &seg->sections[j];
+       }
+    }
+}
+
+int
+bfd_mach_o_scan_start_address (abfd)
+     bfd *abfd;
+{
+  bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
+  bfd_mach_o_thread_command *cmd = NULL;
+  unsigned long i;
+
+  for (i = 0; i < mdata->header.ncmds; i++)
+    {
+      if ((mdata->commands[i].type == BFD_MACH_O_LC_THREAD) ||
+         (mdata->commands[i].type == BFD_MACH_O_LC_UNIXTHREAD))
+       {
+         if (cmd == NULL)
+           cmd = &mdata->commands[i].command.thread;
+         else
+           return 0;
+       }
+    }
+
+  if (cmd == NULL)
+    return 0;
+
+  for (i = 0; i < cmd->nflavours; i++)
+    {
+      if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_I386) 
+         && (cmd->flavours[i].flavour == (unsigned long) BFD_MACH_O_i386_THREAD_STATE))
+       {
+         unsigned char buf[4];
+
+         bfd_seek (abfd, cmd->flavours[i].offset + 40, SEEK_SET);
+
+         if (bfd_bread (buf, 4, abfd) != 4)
+           return -1;
+
+         abfd->start_address = bfd_h_get_32 (abfd, buf);
+       }
+      else if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_POWERPC) 
+              && (cmd->flavours[i].flavour == BFD_MACH_O_PPC_THREAD_STATE))
+       {
+         unsigned char buf[4];
+
+         bfd_seek (abfd, cmd->flavours[i].offset + 0, SEEK_SET);
+
+         if (bfd_bread (buf, 4, abfd) != 4)
+           return -1;
+
+         abfd->start_address = bfd_h_get_32 (abfd, buf);
+       }
+    }
+
+  return 0;
+}
+
+int
+bfd_mach_o_scan (abfd, header)
+     bfd *abfd;
+     bfd_mach_o_header *header;
+{
+  unsigned int i;
+  bfd_mach_o_data_struct *mdata = NULL;
+  enum bfd_architecture cputype;
+  unsigned long cpusubtype;
+
+  mdata = ((bfd_mach_o_data_struct *) 
+          bfd_alloc (abfd, sizeof (bfd_mach_o_data_struct)));
+  if (mdata == NULL)
+    return -1;
+
+  mdata->header = *header;
+  mdata->symbols = NULL;
+
+  abfd->flags = abfd->xvec->object_flags | (abfd->flags & (BFD_IN_MEMORY | BFD_IO_FUNCS));  
+  abfd->tdata.mach_o_data = mdata;
+
+  bfd_mach_o_convert_architecture (header->cputype, header->cpusubtype, &cputype, &cpusubtype);
+  if (cputype == bfd_arch_unknown)
+    {
+      fprintf (stderr, "bfd_mach_o_scan: unknown architecture 0x%lx/0x%lx\n",
+              header->cputype, header->cpusubtype);
+      return -1;
+    }
+
+  bfd_set_arch_mach (abfd, cputype, cpusubtype);
+  
+  if (header->ncmds != 0)
+    {
+      mdata->commands = 
+       ((bfd_mach_o_load_command *)
+        bfd_alloc (abfd, header->ncmds * sizeof (bfd_mach_o_load_command)));
+      if (mdata->commands == NULL)
+       return -1;
+    
+      for (i = 0; i < header->ncmds; i++)
+       {
+         bfd_mach_o_load_command *cur = &mdata->commands[i];
+
+         if (i == 0)
+           cur->offset = 28;
+         else
+           {
+             bfd_mach_o_load_command *prev = &mdata->commands[i - 1];
+             cur->offset = prev->offset + prev->len;
+           }
+
+         if (bfd_mach_o_scan_read_command (abfd, cur) < 0)
+           return -1;
+       } 
+    }
+
+  if (bfd_mach_o_scan_start_address (abfd) < 0)
+    {
+#if 0
+      fprintf (stderr, "bfd_mach_o_scan: unable to scan start address: %s\n",
+              bfd_errmsg (bfd_get_error ()));
+      abfd->tdata.mach_o_data = NULL;
+      return -1;
+#endif
+    }
+
+  bfd_mach_o_flatten_sections (abfd);
+
+  return 0;
+}
+
+boolean
+bfd_mach_o_mkobject (abfd)
+     bfd *abfd;
+{
+  bfd_mach_o_data_struct *mdata = NULL;
+
+  mdata = ((bfd_mach_o_data_struct *) 
+          bfd_alloc (abfd, sizeof (bfd_mach_o_data_struct)));
+  if (mdata == NULL)
+    return false;
+  abfd->tdata.mach_o_data = mdata;
+
+  mdata->header.magic = 0;
+  mdata->header.cputype = 0;
+  mdata->header.cpusubtype = 0;
+  mdata->header.filetype = 0;
+  mdata->header.ncmds = 0;
+  mdata->header.sizeofcmds = 0;
+  mdata->header.flags = 0;
+  mdata->header.byteorder = BFD_ENDIAN_UNKNOWN;
+  mdata->commands = NULL;
+  mdata->nsymbols = 0;
+  mdata->symbols = NULL;
+  mdata->nsects = 0;
+  mdata->sections = NULL;
+  mdata->ibfd = NULL;
+
+  return true;
+}
+
+const bfd_target *
+bfd_mach_o_object_p (abfd)
+     bfd *abfd;
+{
+  bfd_mach_o_header header;
+
+  if (bfd_mach_o_read_header (abfd, &header) != 0)
+    {
+      bfd_set_error (bfd_error_wrong_format);
+      return NULL;
+    }
+
+  if (! ((header.byteorder == BFD_ENDIAN_BIG)
+        || (header.byteorder == BFD_ENDIAN_LITTLE)))
+    {
+      fprintf (stderr, "unknown header byte-order value 0x%lx\n", (long) header.byteorder);
+      bfd_set_error (bfd_error_wrong_format);
+      return NULL;
+    }
+
+  if (! (((header.byteorder == BFD_ENDIAN_BIG) 
+         && (abfd->xvec->byteorder == BFD_ENDIAN_BIG)
+         && (abfd->xvec->header_byteorder == BFD_ENDIAN_BIG))
+        ||
+        ((header.byteorder == BFD_ENDIAN_LITTLE) 
+         && (abfd->xvec->byteorder == BFD_ENDIAN_LITTLE) 
+         && (abfd->xvec->header_byteorder == BFD_ENDIAN_LITTLE))))
+    {
+      bfd_set_error (bfd_error_wrong_format);
+      return NULL;
+    }
+
+  abfd->tdata.mach_o_data = NULL;
+
+  if (bfd_mach_o_scan (abfd, &header) != 0)
+    {
+      abfd->tdata.mach_o_data = NULL;
+      bfd_set_error (bfd_error_wrong_format);
+      return NULL;
+    }
+  
+  return abfd->xvec;
+}
+
+const bfd_target *
+bfd_mach_o_core_p (abfd)
+     bfd *abfd;
+{
+  bfd_mach_o_header header;
+
+  bfd_set_error (bfd_error_wrong_format);
+
+  if (bfd_mach_o_read_header (abfd, &header) != 0)
+    return NULL;
+
+  if (! ((header.byteorder == BFD_ENDIAN_BIG)
+        || (header.byteorder == BFD_ENDIAN_LITTLE)))
+    {
+      fprintf (stderr, "unknown header byte-order value 0x%lx\n", (long) header.byteorder);
+      abort ();
+    }
+
+  if (! (((header.byteorder == BFD_ENDIAN_BIG) 
+         && (abfd->xvec->byteorder == BFD_ENDIAN_BIG)
+         && (abfd->xvec->header_byteorder == BFD_ENDIAN_BIG))
+        ||
+        ((header.byteorder == BFD_ENDIAN_LITTLE) 
+         && (abfd->xvec->byteorder == BFD_ENDIAN_LITTLE) 
+         && (abfd->xvec->header_byteorder == BFD_ENDIAN_LITTLE))))
+    return NULL;
+
+  if (header.filetype != BFD_MACH_O_MH_CORE)
+    return NULL;
+
+  abfd->tdata.mach_o_data = NULL;
+  if (bfd_mach_o_scan (abfd, &header) != 0)
+    {
+      abfd->tdata.mach_o_data = NULL;
+      return NULL;
+    }
+  
+  return abfd->xvec;
+}
+
+typedef struct mach_o_fat_archentry
+{
+  unsigned long cputype;
+  unsigned long cpusubtype;
+  unsigned long offset;
+  unsigned long size;
+  unsigned long align;
+  bfd *abfd;
+} mach_o_fat_archentry;
+
+typedef struct mach_o_fat_data_struct
+{
+  unsigned long magic;
+  unsigned long nfat_arch;
+  mach_o_fat_archentry *archentries;
+} mach_o_fat_data_struct;
+
+const bfd_target *
+bfd_mach_o_archive_p (abfd)
+     bfd *abfd;
+{
+  mach_o_fat_data_struct *adata;
+  unsigned char buf[20];
+  unsigned long i;
+
+  bfd_seek (abfd, 0, SEEK_SET);
+  if (bfd_bread ((PTR) buf, 8, abfd) != 8)
+    return NULL;
+
+  adata = (mach_o_fat_data_struct *) 
+    bfd_alloc (abfd, sizeof (mach_o_fat_data_struct));
+  if (adata == NULL)
+    return NULL;
+  
+  adata->magic = bfd_getb32 (buf);
+  adata->nfat_arch = bfd_getb32 (buf + 4);
+  if (adata->magic != 0xcafebabe)
+    return NULL;
+
+  adata->archentries = (mach_o_fat_archentry *) 
+    bfd_alloc (abfd, adata->nfat_arch * sizeof (mach_o_fat_archentry));
+  if (adata->archentries == NULL)
+    return NULL;
+
+  for (i = 0; i < adata->nfat_arch; i++)
+    {
+      bfd_seek (abfd, 8 + 20 * i, SEEK_SET);
+
+      if (bfd_bread ((PTR) buf, 20, abfd) != 20)
+       return NULL;
+      adata->archentries[i].cputype = bfd_getb32 (buf);
+      adata->archentries[i].cpusubtype = bfd_getb32 (buf + 4);
+      adata->archentries[i].offset = bfd_getb32 (buf + 8);
+      adata->archentries[i].size = bfd_getb32 (buf + 12);
+      adata->archentries[i].align = bfd_getb32 (buf + 16);
+      adata->archentries[i].abfd = NULL;
+    }
+
+  abfd->tdata.mach_o_fat_data = adata;
+  return abfd->xvec;
+}
+
+bfd *
+bfd_mach_o_openr_next_archived_file (archive, prev)
+  bfd *archive;
+  bfd *prev;
+{
+  mach_o_fat_data_struct *adata = (mach_o_fat_data_struct *) archive->tdata.mach_o_fat_data;
+  mach_o_fat_archentry *entry = NULL;
+  unsigned long i;
+
+  BFD_ASSERT (adata != NULL);
+
+  /* Find index of previous entry.  */
+  if (prev == NULL)
+    i = 0;     /* Start at first one.  */
+  else
+    {
+      for (i = 0; i < adata->nfat_arch; i++)
+       {
+         if (adata->archentries[i].abfd == prev)
+           break;
+       }
+
+      if (i == adata->nfat_arch)
+       {
+         /* Not found.  */
+         bfd_set_error (bfd_error_bad_value);
+         return NULL; 
+       }
+    i++;       /* Get next entry.  */
+  }
+  
+  if (i >= adata->nfat_arch)
+    {
+      bfd_set_error (bfd_error_no_more_archived_files);
+      return NULL;
+    }
+
+  entry = &adata->archentries[i];
+  if (entry->abfd == NULL)
+    {
+      bfd *nbfd = _bfd_new_bfd_contained_in (archive);
+      char *s = NULL;
+
+      if (nbfd == NULL)
+       return NULL;
+
+      nbfd->origin = entry->offset;
+      s = bfd_malloc (strlen (archive->filename) + 1);
+      if (s == NULL)
+       return NULL;
+      strcpy (s, archive->filename);
+      nbfd->filename = s;
+      nbfd->iostream = NULL;
+      entry->abfd = nbfd;
+    }
+
+  return entry->abfd;
+}
+
+int bfd_mach_o_lookup_section 
+  (bfd *abfd, asection *section, 
+   bfd_mach_o_load_command **mcommand, bfd_mach_o_section **msection)
+{
+  struct mach_o_data_struct *md = abfd->tdata.mach_o_data;
+  unsigned int i, j, num;
+
+  bfd_mach_o_load_command *ncmd = NULL;
+  bfd_mach_o_section *nsect = NULL;
+
+  BFD_ASSERT (mcommand != NULL);
+  BFD_ASSERT (msection != NULL);
+
+  num = 0;
+  for (i = 0; i < md->header.ncmds; i++)
+    {
+      struct bfd_mach_o_load_command *cmd = &md->commands[i];
+      struct bfd_mach_o_segment_command *seg = NULL;
+
+      if (cmd->type != BFD_MACH_O_LC_SEGMENT)
+       continue;
+      seg = &cmd->command.segment;
+    
+      if (seg->segment == section)
+       {
+         if (num == 0)
+           ncmd = cmd;
+         num++;
+       }
+
+      for (j = 0; j < seg->nsects; j++)
+       {
+         struct bfd_mach_o_section *sect = &seg->sections[j];
+
+         if (sect->bfdsection == section)
+           {
+             if (num == 0)
+               nsect = sect;
+             num++;
+           }
+       }
+    }
+  
+  *mcommand = ncmd;
+  *msection = nsect;
+  return num;
+}
+
+int
+bfd_mach_o_lookup_command 
+  (bfd *abfd, bfd_mach_o_load_command_type type,
+   bfd_mach_o_load_command **mcommand)
+{
+  struct mach_o_data_struct *md = NULL;
+  bfd_mach_o_load_command *ncmd = NULL;
+  unsigned int i, num;
+
+  md = abfd->tdata.mach_o_data;
+
+  BFD_ASSERT (md != NULL);
+  BFD_ASSERT (mcommand != NULL);
+
+  num = 0;
+  for (i = 0; i < md->header.ncmds; i++)
+    {
+      struct bfd_mach_o_load_command *cmd = &md->commands[i];
+
+      if (cmd->type != type)
+       continue;
+
+      if (num == 0)
+       ncmd = cmd;
+      num++;
+    }
+
+  *mcommand = ncmd;
+  return num;
+}
+
+unsigned long
+bfd_mach_o_stack_addr (type)
+     enum bfd_mach_o_cpu_type type;
+{
+  switch (type)
+    {
+    case BFD_MACH_O_CPU_TYPE_MC680x0:
+      return 0x04000000;
+    case BFD_MACH_O_CPU_TYPE_MC88000:
+      return 0xffffe000;
+    case BFD_MACH_O_CPU_TYPE_POWERPC:
+      return 0xc0000000;
+    case BFD_MACH_O_CPU_TYPE_I386:
+      return 0xc0000000;
+    case BFD_MACH_O_CPU_TYPE_SPARC:
+      return 0xf0000000;
+    case BFD_MACH_O_CPU_TYPE_I860:
+      return 0;
+    case BFD_MACH_O_CPU_TYPE_HPPA:
+      return (0xc0000000-0x04000000);
+    default:
+      return 0;
+    }
+}
+
+int
+bfd_mach_o_core_fetch_environment (abfd, rbuf, rlen)
+     bfd *abfd;
+     unsigned char **rbuf;
+     unsigned int *rlen;
+{
+  bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data;
+  unsigned long stackaddr = bfd_mach_o_stack_addr (mdata->header.cputype);
+  unsigned int i = 0;
+
+  for (i = 0; i < mdata->header.ncmds; i++)
+    {
+      bfd_mach_o_load_command *cur = &mdata->commands[i];
+      bfd_mach_o_segment_command *seg = NULL;
+
+      if (cur->type != BFD_MACH_O_LC_SEGMENT)
+       continue;
+
+      seg = &cur->command.segment;
+
+      if ((seg->vmaddr + seg->vmsize) == stackaddr)
+       {
+         unsigned long start = seg->fileoff;
+         unsigned long end = seg->fileoff + seg->filesize;
+         unsigned char *buf = bfd_malloc (1024);
+         unsigned long size = 1024;
+
+         for (;;)
+           {
+             bfd_size_type nread = 0;
+             unsigned long offset;
+             int found_nonnull = 0;
+
+             if (size > (end - start))
+               size = (end - start);
+
+             buf = bfd_realloc (buf, size);
+
+             bfd_seek (abfd, end - size, SEEK_SET);
+             nread = bfd_bread (buf, size, abfd);
+       
+             if (nread != size)
+               return -1;
+      
+             for (offset = 4; offset <= size; offset += 4)
+               {
+                 unsigned long val =  *((unsigned long *) (buf + size - offset));
+
+                 if (! found_nonnull)
+                   {
+                     if (val != 0)
+                       found_nonnull = 1;
+                   }
+                 else if (val == 0x0)
+                   {
+                     unsigned long bottom = seg->fileoff + seg->filesize - offset;
+                     unsigned long top = seg->fileoff + seg->filesize - 4;
+
+                     *rbuf = bfd_malloc (top - bottom);
+                     *rlen = top - bottom;
+
+                     memcpy (*rbuf, buf + size - *rlen, *rlen);
+                     return 0;
+                   }
+               }
+
+             if (size == (end - start))
+               break;
+
+             size *= 2;
+           }
+       }
+    }
+
+  return -1;
+}
+
+char *
+bfd_mach_o_core_file_failing_command (abfd)
+     bfd *abfd;
+{
+  unsigned char *buf = NULL;
+  unsigned int len = 0;
+  int ret = -1;
+
+  ret = bfd_mach_o_core_fetch_environment (abfd, &buf, &len);
+  if (ret < 0)
+    return NULL;
+
+  return buf;
+}
+
+int
+bfd_mach_o_core_file_failing_signal (abfd)
+     bfd *abfd ATTRIBUTE_UNUSED;
+{
+  return 0;
+}
+
+boolean
+bfd_mach_o_core_file_matches_executable_p (core_bfd, exec_bfd)
+     bfd *core_bfd ATTRIBUTE_UNUSED;
+     bfd *exec_bfd ATTRIBUTE_UNUSED;
+{
+  return true;
+}
+
+#define TARGET_NAME mach_o_be_vec
+#define TARGET_STRING "mach-o-be"
+#define TARGET_BIG_ENDIAN 1
+#define TARGET_ARCHIVE 0
+
+#include "mach-o-target.c"
+
+#undef TARGET_NAME
+#undef TARGET_STRING
+#undef TARGET_BIG_ENDIAN
+#undef TARGET_ARCHIVE
+
+#define TARGET_NAME mach_o_le_vec
+#define TARGET_STRING "mach-o-le"
+#define TARGET_BIG_ENDIAN 0
+#define TARGET_ARCHIVE 0
+
+#include "mach-o-target.c"
+
+#undef TARGET_NAME
+#undef TARGET_STRING
+#undef TARGET_BIG_ENDIAN
+#undef TARGET_ARCHIVE
+
+#define TARGET_NAME mach_o_fat_vec
+#define TARGET_STRING "mach-o-fat"
+#define TARGET_BIG_ENDIAN 1
+#define TARGET_ARCHIVE 1
+
+#include "mach-o-target.c"
+
+#undef TARGET_NAME
+#undef TARGET_STRING
+#undef TARGET_BIG_ENDIAN
+#undef TARGET_ARCHIVE
+
diff --git a/bfd/mach-o.h b/bfd/mach-o.h
new file mode 100644 (file)
index 0000000..c368c1e
--- /dev/null
@@ -0,0 +1,490 @@
+/* Mach-O support for BFD.
+   Copyright 1999, 2000, 2001, 2002
+   Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software 
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifndef _BFD_MACH_O_H_
+#define _BFD_MACH_O_H_
+
+#include "bfd.h"
+
+#define BFD_MACH_O_N_STAB  0xe0        /* If any of these bits set, a symbolic debugging entry.  */
+#define BFD_MACH_O_N_PEXT  0x10        /* Private external symbol bit.  */
+#define BFD_MACH_O_N_TYPE  0x0e        /* Mask for the type bits.  */
+#define BFD_MACH_O_N_EXT   0x01        /* External symbol bit, set for external symbols.  */
+#define BFD_MACH_O_N_UNDF  0x00        /* Undefined, n_sect == NO_SECT.  */
+#define BFD_MACH_O_N_ABS   0x02        /* Absolute, n_sect == NO_SECT.  */
+#define BFD_MACH_O_N_SECT  0x0e        /* Defined in section number n_sect.  */
+#define BFD_MACH_O_N_PBUD  0x0c /* Prebound undefined (defined in a dylib).  */
+#define BFD_MACH_O_N_INDR  0x0a        /* Indirect.  */
+
+typedef enum bfd_mach_o_ppc_thread_flavour
+  {
+    BFD_MACH_O_PPC_THREAD_STATE = 1,
+    BFD_MACH_O_PPC_FLOAT_STATE = 2,
+    BFD_MACH_O_PPC_EXCEPTION_STATE = 3,
+    BFD_MACH_O_PPC_VECTOR_STATE = 4
+  }
+bfd_mach_o_ppc_thread_flavour;
+
+typedef enum bfd_mach_o_i386_thread_flavour
+  {
+    BFD_MACH_O_i386_NEW_THREAD_STATE = 1,
+    BFD_MACH_O_i386_FLOAT_STATE = 2,
+    BFD_MACH_O_i386_ISA_PORT_MAP_STATE = 3,
+    BFD_MACH_O_i386_V86_ASSIST_STATE = 4,
+    BFD_MACH_O_i386_REGS_SEGS_STATE = 5,
+    BFD_MACH_O_i386_THREAD_SYSCALL_STATE = 6,
+    BFD_MACH_O_i386_THREAD_STATE_NONE = 7,
+    BFD_MACH_O_i386_SAVED_STATE = 8,
+    BFD_MACH_O_i386_THREAD_STATE = -1,
+    BFD_MACH_O_i386_THREAD_FPSTATE = -2,
+    BFD_MACH_O_i386_THREAD_EXCEPTSTATE = -3,
+    BFD_MACH_O_i386_THREAD_CTHREADSTATE = -4,
+  }
+bfd_mach_o_i386_thread_flavour;
+
+#define BFD_MACH_O_LC_REQ_DYLD 0x80000000
+
+typedef enum bfd_mach_o_load_command_type
+  {
+    BFD_MACH_O_LC_SEGMENT = 0x1,       /* File segment to be mapped.  */
+    BFD_MACH_O_LC_SYMTAB = 0x2,                /* Link-edit stab symbol table info (obsolete).  */
+    BFD_MACH_O_LC_SYMSEG = 0x3,                /* Link-edit gdb symbol table info.  */
+    BFD_MACH_O_LC_THREAD = 0x4,                /* Thread.  */
+    BFD_MACH_O_LC_UNIXTHREAD = 0x5,    /* UNIX thread (includes a stack).  */
+    BFD_MACH_O_LC_LOADFVMLIB = 0x6,    /* Load a fixed VM shared library.  */
+    BFD_MACH_O_LC_IDFVMLIB = 0x7,      /* Fixed VM shared library id.  */
+    BFD_MACH_O_LC_IDENT = 0x8,         /* Object identification information (obsolete).  */
+    BFD_MACH_O_LC_FVMFILE = 0x9,       /* Fixed VM file inclusion.  */
+    BFD_MACH_O_LC_PREPAGE = 0xa,       /* Prepage command (internal use).  */
+    BFD_MACH_O_LC_DYSYMTAB = 0xb,      /* Dynamic link-edit symbol table info.  */
+    BFD_MACH_O_LC_LOAD_DYLIB = 0xc,    /* Load a dynamicly linked shared library.  */
+    BFD_MACH_O_LC_ID_DYLIB = 0xd,      /* Dynamicly linked shared lib identification.  */
+    BFD_MACH_O_LC_LOAD_DYLINKER = 0xe, /* Load a dynamic linker.  */
+    BFD_MACH_O_LC_ID_DYLINKER = 0xf,   /* Dynamic linker identification.  */
+    BFD_MACH_O_LC_PREBOUND_DYLIB = 0x10,/* Modules prebound for a dynamicly.  */
+    BFD_MACH_O_LC_ROUTINES = 0x11,     /* Image routines.  */
+    BFD_MACH_O_LC_SUB_FRAMEWORK = 0x12,        /* Sub framework.  */
+    BFD_MACH_O_LC_SUB_UMBRELLA = 0x13, /* Sub umbrella.  */
+    BFD_MACH_O_LC_SUB_CLIENT = 0x14,   /* Sub client.  */
+    BFD_MACH_O_LC_SUB_LIBRARY = 0x15,   /* Sub library.  */
+    BFD_MACH_O_LC_TWOLEVEL_HINTS = 0x16,/* Two-level namespace lookup hints.  */
+    BFD_MACH_O_LC_PREBIND_CKSUM = 0x17, /* Prebind checksum.  */
+    /* Load a dynamicly linked shared library that is allowed to be
+       missing (weak).  */
+    BFD_MACH_O_LC_LOAD_WEAK_DYLIB = 0x18
+  }
+bfd_mach_o_load_command_type;
+
+typedef enum bfd_mach_o_cpu_type
+  {
+    BFD_MACH_O_CPU_TYPE_VAX = 1,
+    BFD_MACH_O_CPU_TYPE_MC680x0 = 6,
+    BFD_MACH_O_CPU_TYPE_I386 = 7,
+    BFD_MACH_O_CPU_TYPE_MIPS = 8,
+    BFD_MACH_O_CPU_TYPE_MC98000 = 10,
+    BFD_MACH_O_CPU_TYPE_HPPA = 11,
+    BFD_MACH_O_CPU_TYPE_ARM = 12,
+    BFD_MACH_O_CPU_TYPE_MC88000 = 13,
+    BFD_MACH_O_CPU_TYPE_SPARC = 14,
+    BFD_MACH_O_CPU_TYPE_I860 = 15,
+    BFD_MACH_O_CPU_TYPE_ALPHA = 16,
+    BFD_MACH_O_CPU_TYPE_POWERPC = 18
+  }
+bfd_mach_o_cpu_type;
+
+typedef enum bfd_mach_o_filetype
+  {
+    BFD_MACH_O_MH_OBJECT = 1,
+    BFD_MACH_O_MH_EXECUTE = 2,
+    BFD_MACH_O_MH_FVMLIB = 3,
+    BFD_MACH_O_MH_CORE = 4,
+    BFD_MACH_O_MH_PRELOAD = 5,
+    BFD_MACH_O_MH_DYLIB = 6,
+    BFD_MACH_O_MH_DYLINKER = 7,
+    BFD_MACH_O_MH_BUNDLE = 8
+  }
+bfd_mach_o_filetype;
+
+/* Constants for the type of a section.  */
+
+typedef enum bfd_mach_o_section_type
+  {
+    /* Regular section.  */
+    BFD_MACH_O_S_REGULAR = 0x0,        
+
+    /* Zero fill on demand section.  */
+    BFD_MACH_O_S_ZEROFILL = 0x1,
+
+    /* Section with only literal C strings.  */
+    BFD_MACH_O_S_CSTRING_LITERALS = 0x2, 
+
+    /* Section with only 4 byte literals.  */
+    BFD_MACH_O_S_4BYTE_LITERALS = 0x3,
+
+    /* Section with only 8 byte literals.  */
+    BFD_MACH_O_S_8BYTE_LITERALS = 0x4,
+
+    /* Section with only pointers to literals.  */
+    BFD_MACH_O_S_LITERAL_POINTERS = 0x5,
+
+    /* For the two types of symbol pointers sections and the symbol stubs
+       section they have indirect symbol table entries.  For each of the
+       entries in the section the indirect symbol table entries, in
+       corresponding order in the indirect symbol table, start at the index
+       stored in the reserved1 field of the section structure.  Since the
+       indirect symbol table entries correspond to the entries in the
+       section the number of indirect symbol table entries is inferred from
+       the size of the section divided by the size of the entries in the
+       section.  For symbol pointers sections the size of the entries in
+       the section is 4 bytes and for symbol stubs sections the byte size
+       of the stubs is stored in the reserved2 field of the section
+       structure.  */
+
+    /* Section with only non-lazy symbol pointers.  */
+    BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS = 0x6,
+  
+    /* Section with only lazy symbol pointers.  */
+    BFD_MACH_O_S_LAZY_SYMBOL_POINTERS = 0x7,
+  
+    /* Section with only symbol stubs, byte size of stub in the reserved2 field.  */
+    BFD_MACH_O_S_SYMBOL_STUBS = 0x8,
+  
+    /* Section with only function pointers for initialization.  */
+    BFD_MACH_O_S_MOD_INIT_FUNC_POINTERS = 0x9
+  }
+bfd_mach_o_section_type;
+
+typedef unsigned long bfd_mach_o_cpu_subtype;
+
+typedef struct bfd_mach_o_header
+{
+  unsigned long magic;
+  unsigned long cputype;
+  unsigned long cpusubtype;
+  unsigned long filetype;
+  unsigned long ncmds;
+  unsigned long sizeofcmds;
+  unsigned long flags;
+  enum bfd_endian byteorder;
+}
+bfd_mach_o_header;
+
+typedef struct bfd_mach_o_section
+{
+  asection *bfdsection;
+  char sectname[16 + 1];
+  char segname[16 + 1];
+  bfd_vma addr;
+  bfd_vma size;
+  bfd_vma offset;
+  unsigned long align;
+  bfd_vma reloff;
+  unsigned long nreloc;
+  unsigned long flags;
+  unsigned long reserved1;
+  unsigned long reserved2;
+}
+bfd_mach_o_section;
+
+typedef struct bfd_mach_o_segment_command
+{
+  char segname[16];
+  bfd_vma vmaddr;
+  bfd_vma vmsize;
+  bfd_vma fileoff;
+  unsigned long filesize;
+  unsigned long nsects;
+  unsigned long flags;
+  bfd_mach_o_section *sections;
+  asection *segment;
+}
+bfd_mach_o_segment_command;
+
+typedef struct bfd_mach_o_symtab_command
+{
+  unsigned long symoff;
+  unsigned long nsyms;
+  unsigned long stroff;
+  unsigned long strsize;
+  asymbol *symbols;
+  char *strtab;
+  asection *stabs_segment;
+  asection *stabstr_segment;
+}
+bfd_mach_o_symtab_command;
+
+/* This is the second set of the symbolic information which is used to support
+   the data structures for the dynamicly link editor.
+   The original set of symbolic information in the symtab_command which contains
+   the symbol and string tables must also be present when this load command is
+   present.  When this load command is present the symbol table is organized
+   into three groups of symbols:
+       local symbols (static and debugging symbols) - grouped by module
+       defined external symbols - grouped by module (sorted by name if not lib)
+       undefined external symbols (sorted by name)
+   In this load command there are offsets and counts to each of the three groups
+   of symbols.
+   This load command contains a the offsets and sizes of the following new
+   symbolic information tables:
+       table of contents
+       module table
+       reference symbol table
+       indirect symbol table
+   The first three tables above (the table of contents, module table and
+   reference symbol table) are only present if the file is a dynamicly linked
+   shared library.  For executable and object modules, which are files
+   containing only one module, the information that would be in these three
+   tables is determined as follows:
+       table of contents - the defined external symbols are sorted by name
+       module table - the file contains only one module so everything in the
+                      file is part of the module.
+       reference symbol table - is the defined and undefined external symbols
+   For dynamicly linked shared library files this load command also contains
+   offsets and sizes to the pool of relocation entries for all sections
+   separated into two groups:
+       external relocation entries
+       local relocation entries
+   For executable and object modules the relocation entries continue to hang
+   off the section structures.  */
+
+typedef struct bfd_mach_o_dysymtab_command
+{
+  /* The symbols indicated by symoff and nsyms of the LC_SYMTAB load command
+     are grouped into the following three groups:
+       local symbols (further grouped by the module they are from)
+       defined external symbols (further grouped by the module they are from)
+       undefined symbols
+   
+     The local symbols are used only for debugging.  The dynamic binding
+     process may have to use them to indicate to the debugger the local
+     symbols for a module that is being bound.
+   
+     The last two groups are used by the dynamic binding process to do the
+     binding (indirectly through the module table and the reference symbol
+     table when this is a dynamicly linked shared library file).  */
+
+  unsigned long ilocalsym;    /* Index to local symbols.  */
+  unsigned long nlocalsym;    /* Number of local symbols.  */
+  unsigned long iextdefsym;   /* Index to externally defined symbols.  */
+  unsigned long nextdefsym;   /* Number of externally defined symbols.  */
+  unsigned long iundefsym;    /* Index to undefined symbols.  */
+  unsigned long nundefsym;    /* Number of undefined symbols.  */
+
+  /* For the for the dynamic binding process to find which module a symbol
+     is defined in the table of contents is used (analogous to the ranlib
+     structure in an archive) which maps defined external symbols to modules
+     they are defined in.  This exists only in a dynamicly linked shared
+     library file.  For executable and object modules the defined external
+     symbols are sorted by name and is use as the table of contents.  */
+
+  unsigned long tocoff;       /* File offset to table of contents.  */
+  unsigned long ntoc;         /* Number of entries in table of contents.  */
+
+  /* To support dynamic binding of "modules" (whole object files) the symbol
+     table must reflect the modules that the file was created from.  This is
+     done by having a module table that has indexes and counts into the merged
+     tables for each module.  The module structure that these two entries
+     refer to is described below.  This exists only in a dynamicly linked
+     shared library file.  For executable and object modules the file only
+     contains one module so everything in the file belongs to the module.  */
+
+  unsigned long modtaboff;    /* File offset to module table.  */
+  unsigned long nmodtab;      /* Number of module table entries.  */
+
+  /* To support dynamic module binding the module structure for each module
+     indicates the external references (defined and undefined) each module
+     makes.  For each module there is an offset and a count into the
+     reference symbol table for the symbols that the module references.
+     This exists only in a dynamicly linked shared library file.  For
+     executable and object modules the defined external symbols and the
+     undefined external symbols indicates the external references.  */
+
+  unsigned long extrefsymoff;  /* Offset to referenced symbol table.  */
+  unsigned long nextrefsyms;   /* Number of referenced symbol table entries.  */
+
+  /* The sections that contain "symbol pointers" and "routine stubs" have
+     indexes and (implied counts based on the size of the section and fixed
+     size of the entry) into the "indirect symbol" table for each pointer
+     and stub.  For every section of these two types the index into the
+     indirect symbol table is stored in the section header in the field
+     reserved1.  An indirect symbol table entry is simply a 32bit index into
+     the symbol table to the symbol that the pointer or stub is referring to.
+     The indirect symbol table is ordered to match the entries in the section.  */
+
+  unsigned long indirectsymoff; /* File offset to the indirect symbol table.  */
+  unsigned long nindirectsyms;  /* Number of indirect symbol table entries.  */
+
+  /* To support relocating an individual module in a library file quickly the
+     external relocation entries for each module in the library need to be
+     accessed efficiently.  Since the relocation entries can't be accessed
+     through the section headers for a library file they are separated into
+     groups of local and external entries further grouped by module.  In this
+     case the presents of this load command who's extreloff, nextrel,
+     locreloff and nlocrel fields are non-zero indicates that the relocation
+     entries of non-merged sections are not referenced through the section
+     structures (and the reloff and nreloc fields in the section headers are
+     set to zero).
+
+     Since the relocation entries are not accessed through the section headers
+     this requires the r_address field to be something other than a section
+     offset to identify the item to be relocated.  In this case r_address is
+     set to the offset from the vmaddr of the first LC_SEGMENT command.
+
+     The relocation entries are grouped by module and the module table
+     entries have indexes and counts into them for the group of external
+     relocation entries for that the module.
+
+     For sections that are merged across modules there must not be any
+     remaining external relocation entries for them (for merged sections
+     remaining relocation entries must be local).  */
+
+  unsigned long extreloff;    /* Offset to external relocation entries.  */
+  unsigned long nextrel;      /* Number of external relocation entries.  */
+
+  /* All the local relocation entries are grouped together (they are not
+     grouped by their module since they are only used if the object is moved
+     from it staticly link edited address).  */
+
+  unsigned long locreloff;    /* Offset to local relocation entries.  */
+  unsigned long nlocrel;      /* Number of local relocation entries.  */
+}
+bfd_mach_o_dysymtab_command;      
+
+/* An indirect symbol table entry is simply a 32bit index into the symbol table 
+   to the symbol that the pointer or stub is refering to.  Unless it is for a
+   non-lazy symbol pointer section for a defined symbol which strip(1) as 
+   removed.  In which case it has the value INDIRECT_SYMBOL_LOCAL.  If the
+   symbol was also absolute INDIRECT_SYMBOL_ABS is or'ed with that.  */
+
+#define INDIRECT_SYMBOL_LOCAL 0x80000000
+#define INDIRECT_SYMBOL_ABS   0x40000000
+
+typedef struct bfd_mach_o_thread_flavour
+{
+  unsigned long flavour;
+  bfd_vma offset;
+  unsigned long size;
+}
+bfd_mach_o_thread_flavour;
+
+typedef struct bfd_mach_o_thread_command
+{
+  unsigned long nflavours;
+  bfd_mach_o_thread_flavour *flavours; 
+  asection *section;
+}
+bfd_mach_o_thread_command;
+
+typedef struct bfd_mach_o_dylinker_command
+{
+  unsigned long cmd;                   /* LC_ID_DYLIB or LC_LOAD_DYLIB.  */
+  unsigned long cmdsize;               /* Includes pathname string.  */
+  unsigned long name_offset;           /* Offset to library's path name.  */
+  unsigned long name_len;              /* Offset to library's path name.  */
+  asection *section;
+}
+bfd_mach_o_dylinker_command;
+
+typedef struct bfd_mach_o_dylib_command
+{
+  unsigned long cmd;                   /* LC_ID_DYLIB or LC_LOAD_DYLIB.  */
+  unsigned long cmdsize;               /* Includes pathname string.  */
+  unsigned long name_offset;           /* Offset to library's path name.  */
+  unsigned long name_len;              /* Offset to library's path name.  */
+  unsigned long timestamp;            /* Library's build time stamp.  */
+  unsigned long current_version;       /* Library's current version number.  */
+  unsigned long compatibility_version; /* Library's compatibility vers number.  */
+  asection *section;
+}
+bfd_mach_o_dylib_command;
+
+typedef struct bfd_mach_o_prebound_dylib_command
+{
+  unsigned long cmd;                 /* LC_PREBOUND_DYLIB.  */
+  unsigned long cmdsize;             /* Includes strings.  */
+  unsigned long name;                /* Library's path name.  */
+  unsigned long nmodules;            /* Number of modules in library.  */
+  unsigned long linked_modules;      /* Bit vector of linked modules.  */
+  asection *section;
+}
+bfd_mach_o_prebound_dylib_command;
+
+typedef struct bfd_mach_o_load_command
+{
+  bfd_mach_o_load_command_type type;
+  unsigned int type_required;
+  bfd_vma offset;
+  bfd_vma len;
+  union
+  {
+    bfd_mach_o_segment_command segment;
+    bfd_mach_o_symtab_command symtab;
+    bfd_mach_o_dysymtab_command dysymtab;
+    bfd_mach_o_thread_command thread;
+    bfd_mach_o_dylib_command dylib;
+    bfd_mach_o_dylinker_command dylinker;
+    bfd_mach_o_prebound_dylib_command prebound_dylib;
+  }
+  command;
+}
+bfd_mach_o_load_command;
+
+typedef struct mach_o_data_struct
+{
+  bfd_mach_o_header header;
+  bfd_mach_o_load_command *commands;
+  unsigned long nsymbols;
+  asymbol *symbols;
+  unsigned long nsects;
+  bfd_mach_o_section **sections;
+  bfd *ibfd;
+}
+mach_o_data_struct;
+
+typedef struct mach_o_data_struct bfd_mach_o_data_struct;
+
+boolean            bfd_mach_o_valid                     PARAMS ((bfd *));
+int                bfd_mach_o_scan_read_symtab_symbol   PARAMS ((bfd *, bfd_mach_o_symtab_command *, asymbol *, unsigned long));
+int                bfd_mach_o_scan_read_symtab_strtab   PARAMS ((bfd *, bfd_mach_o_symtab_command *));
+int                bfd_mach_o_scan_read_symtab_symbols  PARAMS ((bfd *, bfd_mach_o_symtab_command *));
+int                bfd_mach_o_scan_read_dysymtab_symbol PARAMS ((bfd *, bfd_mach_o_dysymtab_command *, bfd_mach_o_symtab_command *, asymbol *, unsigned long));
+int                bfd_mach_o_scan_start_address        PARAMS ((bfd *));
+int                bfd_mach_o_scan                      PARAMS ((bfd *, bfd_mach_o_header *));
+boolean            bfd_mach_o_mkobject                  PARAMS ((bfd *));
+const bfd_target * bfd_mach_o_object_p                  PARAMS ((bfd *));
+const bfd_target * bfd_mach_o_core_p                    PARAMS ((bfd *));
+const bfd_target * bfd_mach_o_archive_p                 PARAMS ((bfd *));
+bfd *              bfd_mach_o_openr_next_archived_file  PARAMS ((bfd *, bfd *));
+int                bfd_mach_o_lookup_section            PARAMS ((bfd *, asection *, bfd_mach_o_load_command **, bfd_mach_o_section **));
+int                bfd_mach_o_lookup_command            PARAMS ((bfd *, bfd_mach_o_load_command_type, bfd_mach_o_load_command **));
+unsigned long      bfd_mach_o_stack_addr                PARAMS ((enum bfd_mach_o_cpu_type));
+int                bfd_mach_o_core_fetch_environment    PARAMS ((bfd *, unsigned char **, unsigned int *));
+char *             bfd_mach_o_core_file_failing_command PARAMS ((bfd *));
+int                bfd_mach_o_core_file_failing_signal  PARAMS ((bfd *));
+boolean            bfd_mach_o_core_file_matches_executable_p PARAMS ((bfd *, bfd *));
+
+extern const bfd_target mach_o_be_vec;
+extern const bfd_target mach_o_le_vec;
+extern const bfd_target mach_o_fat_vec;
+
+#endif /* _BFD_MACH_O_H_ */
diff --git a/bfd/pef-traceback.h b/bfd/pef-traceback.h
new file mode 100644 (file)
index 0000000..15f43b6
--- /dev/null
@@ -0,0 +1,215 @@
+/* PowerPC traceback table support for BFD.
+   Copyright 1993, 1998, 1999, 2000, 2001, 2002
+   Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software 
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* Originally written by Ira Ruben, 06/28/93 */
+
+/*  This is a compiler independent representation of the AIX Version 3 traceback table (in
+    sys/debug.h), which occurs, usually, one per procedure (routine). The table is marked by
+    a multiple of 4 32-bit word of zeroes in the instruction space. The traceback table is
+    also referred to as "procedure-end table".
+    The AIX traceback table representation on which this header is based is defined as a
+    series of bit field struct specifications. Bit fields are compiler dependent! Thus,
+    the definitions presented here follow the original header and the existing documentation
+    (such as it is), but define the fields as BIT MASKS and other macros. The mask names,
+    however, where chosen as the original field names to give some compatibility with the 
+    original header and to agree with the documentation.  */
+
+#ifndef __TRACEBACK__
+#define __TRACEBACK__
+
+#define TB_C 0U                        /* C */
+#define TB_FORTRAN 1U          /* FORTRAN */
+#define TB_PASCAL 2U           /* Pascal */
+#define TB_ADA 3U              /* ADA */
+#define TB_PL1 4U              /* PL1 */
+#define TB_BASIC 5U            /* Basic */
+#define TB_LISP 6U             /* Lisp */
+#define TB_COBOL 7U            /* eCobol */
+#define TB_MODULA2 8U          /* Modula2 */
+#define TB_CPLUSPLUS 9U                /* C++ */
+#define TB_RPG 10U             /* RPG */
+#define TB_PL8 11U             /* PL8 */
+#define TB_ASM 12U             /* Asm */
+/* flags 1 */
+
+#define TB_GLOBALLINK 0x80U    /* Routine is Global Linkage.  */
+#define TB_is_eprol 0x40U      /* Out-of-line prolog or epilog routine.  */
+#define TB_HAS_TBOFF 0x20U     /* tb_offset set (extension field).  */
+#define TB_INT_PROC 0x10U      /* Internal leaf routine.  */
+#define TB_HAS_CTL 0x08U       /* Has controlled automatic storage.  */
+#define TB_TOCLESS 0X04U       /* Routine has no TOC.  */
+#define TB_FP_PRESENT 0x02U    /* Routine has floating point ops.  */ 
+#define TB_LOG_ABORT 0x01U     /* fp_present && log/abort compiler opt.  */
+/* flags 2 */
+
+#define TB_INT_HNDL 0x80U      /* Routine is an interrupt handler.  */
+#define TB_NAME_PRESENT 0x40U  /* Name_len/name set (extension field).  */
+#define TB_USES_ALLOCA 0x20U   /* Uses alloca() to allocate storage.  */
+#define TB_CL_DIS_inv 0x1CU    /* On-condition directives (see below).  */
+#define TB_SAVES_CR 0x02U      /* Routine saves the CR.  */
+#define TB_SAVES_LR 0x01U      /* Routine saves the LR.  */
+  
+/* cl_dis_inv "on condition" settings: */
+#define TB_CL_DIS_INV(x) (((x) & cl_dis_inv) >> 2U)
+
+#define TB_WALK_ONCOND 0U      /* Walk stack without restoring state.  */
+#define TB_DISCARD_ONCOND 1U   /* Walk stack and discard.  */
+#define TB_INVOKE_ONCOND 2U    /* Invoke a specific system routine.  */
+/* flags 3 */
+
+#define TB_STORES_BC 0x80U     /* Routine saves frame ptr of caller.  */
+#define TB_SPARE2 0X40U                /* Spare bit.  */
+#define TB_FPR_SAVED 0x3fU     /* Number of FPRs saved (max of 32).  */
+                               /* (Last reg saved is ALWAYS fpr31).  */
+
+#define TB_NUM_FPR_SAVED(x) ((x) & fpr_saved)
+/* flags 4 */
+
+#define TB_HAS_VEC_INFO 0x80U  /* Routine uses vectors.  */
+#define TB_SPARE3 0X40U                /* Spare bit.  */
+#define TB_GPR_SAVED 0x3fU     /* Number of GPRs saved (max of 32).  */
+                               /* (Last reg saved is ALWAYS gpr31).  */
+
+#define TB_NUM_GPR_SAVED(x) ((x) & gpr_saved)
+/* flags 5 */
+
+#define TB_FLOATPARAMS 0xfeU   /* Number of floating point parameters.  */
+#define TB_PARAMSONSTK 0X01U   /* All parameters are on the stack.  */
+#define TB_NUM_FLOATPARAMS(X) (((x) & floatparams) >> 1U)
+
+/* traceback_table (fixed portion).  */
+
+struct traceback_table
+{
+  /* Traceback table layout (fixed portion):  */
+
+  unsigned char version;       /* Traceback format version.  */
+  unsigned char lang;          /* Language indicators:  */
+  unsigned char flags1;                /* Flag bits #1:  */
+  unsigned char flags2;                /* Flag bits #2:  */
+  unsigned char flags3;                /* Flag bits #3:  */
+  unsigned char flags4;                /* Flag bits #4:  */
+  unsigned char fixedparams;   /* Number of fixed point parameters.  */
+  unsigned char flags5;                /* Flag bits #5:  */
+};
+
+/* traceback_table (optional) extensions.  */
+
+/* Optional portions exist independently in the order presented below,
+   not as a structure or a union. Whether or not portions exist is
+   determinable from bit-fields within the fixed portion above.  */
+
+/* The following is present only if fixedparams or floatparams are non
+   zero and it immediately follows the fixed portion of the traceback
+   table...  */
+
+/* Order and type encoding of parameters:  */
+struct traceback_table_fixedparams
+{
+  unsigned long paraminfo;             
+};
+
+/* Left-justified bit-encoding as follows:  */
+#define FIXED_PARAM 0          /* '0'  ==> fixed param (1 gpr or word).  */
+#define SPFP_PARAM 2           /* '10' ==> single-precision float param.  */
+#define DPFP_PARAM 3           /* '11' ==> double-precision float param.  */
+
+#define PARAM_ENCODING(x, bit) /* Yields xxx_PARAM as a function of "bit".  */         \
+ ((((x)&(1UL<<(31UL-(bit++))))==0UL) /* Values 0:31 (left-to-right). "bit" is */       \
+ ? FIXED_PARAM /* an L-value that's left incremented to */                             \
+ : ((((x)&(1UL<<(31UL-(bit++))))==0)/* the next bit position for the next */           \
+ ? SPFP_PARAM /* parameter.  This will be 1 or 2 bit */                                        \
+ : DPFP_PARAM)) /* positions later.  */
+
+/* The following is present only if has_tboff (in flags1) in fixed part is present...  */
+
+/* Offset from start of code to TracebackTbl.  */
+struct traceback_table_tboff
+{
+  unsigned long tb_offset;
+};
+
+/* The following is present only if int_hndl (in flags2) in fixed part is present ...  */
+
+/* What interrupts are handled by the routine.  */
+struct traceback_table_interrupts
+{
+  long hand_mask;
+};
+
+/* The following are present only if has_ctl (in flags1) in fixed part is present...  */
+
+/* Controlled automatic storage info:  */
+struct traceback_table_anchors
+{
+  unsigned long ctl_info;      /* Number of controlled automatic anchors.  */ 
+  long ctl_info_disp[1];       /* Array of stack displacements where each.  */
+};                             /* Anchor is located (array STARTS here).  */
+
+/* The following are present only if name_present (in flags2) in fixed
+   part is present...  */
+
+/* Routine name:  */
+struct traceback_table_routine
+{
+  unsigned short name_len;     /* Length of name that follows.  */
+  char name[1];                        /* Name starts here (NOT null terminated).  */
+};
+
+/* The following are present only if uses_alloca (in flags2) in fixed
+   part is present...  */
+
+/* Register auto storage when alloca() is used.  */
+struct traceback_table_alloca
+{
+  char alloca_reg;
+};
+
+/* The following are present only if has_vec_info (in flags4) in fixed
+   part is present...  */
+
+/* Vector info:  */
+struct traceback_table_vector
+{
+  unsigned char vec_flags1;    /* Vec info bits #1:  */
+
+#define TB_VR_SAVED 0xFCU      /* Number of saved vector registers.  */
+#define TB_SAVES_VRSAVE 0x02U  /* Saves VRsave.  */
+#define TB_HAS_VARARGS 0x01U   /* Routine has a variable argument list.  */
+
+#define TB_NUM_VR_SAVED(x) (((x) & TB_VR_SAVED) >> 2U)
+  unsigned char vec_flags2;    /* Vec info bits #2:  */
+
+#define TB_VECTORPARAMS 0xfeU  /* Number of vector parameters.  */
+#define TB_VEC_PRESENT 0x01U   /* Routine uses at least one vec instr.  */
+#define VECPARAMS(x) (((x) & TB_VECTORPARAMS) >> 1U)
+};
+
+#endif
diff --git a/bfd/pef.c b/bfd/pef.c
new file mode 100644 (file)
index 0000000..bb0d6c5
--- /dev/null
+++ b/bfd/pef.c
@@ -0,0 +1,1207 @@
+/* PEF support for BFD.
+   Copyright 1999, 2000, 2001, 2002
+   Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software 
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include <ctype.h>
+
+#include "pef.h"
+#include "pef-traceback.h"
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+#include "libiberty.h"
+
+#ifndef BFD_IO_FUNCS
+#define BFD_IO_FUNCS 0
+#endif
+
+#define bfd_pef_close_and_cleanup _bfd_generic_close_and_cleanup
+#define bfd_pef_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
+#define bfd_pef_new_section_hook _bfd_generic_new_section_hook
+#define bfd_pef_bfd_is_local_label_name bfd_generic_is_local_label_name
+#define bfd_pef_get_lineno _bfd_nosymbols_get_lineno
+#define bfd_pef_find_nearest_line _bfd_nosymbols_find_nearest_line
+#define bfd_pef_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
+#define bfd_pef_read_minisymbols _bfd_generic_read_minisymbols
+#define bfd_pef_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
+
+#define bfd_pef_get_reloc_upper_bound _bfd_norelocs_get_reloc_upper_bound
+#define bfd_pef_canonicalize_reloc _bfd_norelocs_canonicalize_reloc
+#define bfd_pef_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
+
+#define bfd_pef_set_arch_mach _bfd_generic_set_arch_mach
+
+#define bfd_pef_get_section_contents _bfd_generic_get_section_contents
+#define bfd_pef_set_section_contents _bfd_generic_set_section_contents
+
+#define bfd_pef_bfd_get_relocated_section_contents \
+  bfd_generic_get_relocated_section_contents
+#define bfd_pef_bfd_relax_section bfd_generic_relax_section
+#define bfd_pef_bfd_gc_sections bfd_generic_gc_sections
+#define bfd_pef_bfd_merge_sections bfd_generic_merge_sections
+#define bfd_pef_bfd_discard_group bfd_generic_discard_group
+#define bfd_pef_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
+#define bfd_pef_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
+#define bfd_pef_bfd_link_add_symbols _bfd_generic_link_add_symbols
+#define bfd_pef_bfd_link_just_syms _bfd_generic_link_just_syms
+#define bfd_pef_bfd_final_link _bfd_generic_final_link
+#define bfd_pef_bfd_link_split_section _bfd_generic_link_split_section
+#define bfd_pef_get_section_contents_in_window \
+  _bfd_generic_get_section_contents_in_window
+
+static void bfd_pef_print_symbol
+PARAMS ((bfd *abfd, PTR afile, asymbol *symbol, bfd_print_symbol_type how));
+static void bfd_pef_convert_architecture
+PARAMS ((unsigned long architecture, 
+        enum bfd_architecture *type, unsigned long *subtype));
+static boolean bfd_pef_mkobject PARAMS ((bfd *abfd));
+static int bfd_pef_parse_traceback_table
+PARAMS ((bfd *abfd, asection *section, unsigned char *buf,
+        size_t len, size_t pos, asymbol *sym, FILE *file));
+static const char *bfd_pef_section_name PARAMS ((bfd_pef_section *section));
+static unsigned long bfd_pef_section_flags PARAMS ((bfd_pef_section *section));
+static asection *bfd_pef_make_bfd_section PARAMS ((bfd *abfd, bfd_pef_section *section));
+static int bfd_pef_read_header PARAMS ((bfd *abfd, bfd_pef_header *header));
+static const bfd_target *bfd_pef_object_p PARAMS ((bfd *));
+static int bfd_pef_parse_traceback_tables
+PARAMS ((bfd *abfd, asection *sec, unsigned char *buf,
+        size_t len, long *nsym, asymbol **csym));
+static int bfd_pef_parse_function_stub
+PARAMS ((bfd *abfd, unsigned char *buf, size_t len, unsigned long *offset));
+static int bfd_pef_parse_function_stubs 
+PARAMS ((bfd *abfd, asection *codesec, unsigned char *codebuf, size_t codelen,
+        unsigned char *loaderbuf, size_t loaderlen, unsigned long *nsym, asymbol **csym));
+static long bfd_pef_parse_symbols PARAMS ((bfd *abfd, asymbol **csym));
+static long bfd_pef_count_symbols PARAMS ((bfd *abfd));
+static long bfd_pef_get_symtab_upper_bound PARAMS ((bfd *));
+static long bfd_pef_get_symtab PARAMS ((bfd *, asymbol **));
+static asymbol *bfd_pef_make_empty_symbol PARAMS ((bfd *));
+static void bfd_pef_get_symbol_info PARAMS ((bfd *, asymbol *, symbol_info *));
+static int bfd_pef_sizeof_headers PARAMS ((bfd *, boolean));
+
+static int bfd_pef_xlib_read_header PARAMS ((bfd *abfd, bfd_pef_xlib_header *header));
+static int bfd_pef_xlib_scan PARAMS ((bfd *abfd, bfd_pef_xlib_header *header));
+static const bfd_target *bfd_pef_xlib_object_p PARAMS ((bfd *abfd));
+
+static void
+bfd_pef_print_symbol (abfd, afile, symbol, how)
+     bfd *abfd;
+     PTR afile;
+     asymbol *symbol;
+     bfd_print_symbol_type how;
+{
+  FILE *file = (FILE *) afile;
+  switch (how) {
+  case bfd_print_symbol_name:
+    fprintf (file, "%s", symbol->name);
+    break;
+  default:
+    bfd_print_symbol_vandf (abfd, (PTR) file, symbol);
+    fprintf (file, " %-5s %s", symbol->section->name, symbol->name);
+    if (strncmp (symbol->name, "__traceback_", strlen ("__traceback_")) == 0) {
+      char *buf = alloca (symbol->udata.i);
+      size_t offset = symbol->value + 4;
+      size_t len = symbol->udata.i;
+      int ret;
+      
+      bfd_get_section_contents (abfd, symbol->section, buf, offset, len);
+      ret = bfd_pef_parse_traceback_table (abfd, symbol->section, buf, len, 0, NULL, file);
+      if (ret < 0) {
+       fprintf (file, " [ERROR]");
+      }
+    }
+  }
+}
+
+static void bfd_pef_convert_architecture (architecture, type, subtype)
+     unsigned long architecture;
+     enum bfd_architecture *type;
+     unsigned long *subtype;
+{
+  *subtype = bfd_arch_unknown;
+  *type = bfd_arch_unknown;
+
+  const unsigned long ARCH_POWERPC = 0x70777063; /* 'pwpc' */
+  const unsigned long ARCH_M68K = 0x6d36386b; /* 'm68k' */
+  
+  if (architecture == ARCH_POWERPC)
+    *type = bfd_arch_powerpc;
+  else if (architecture == ARCH_M68K)
+    *type = bfd_arch_m68k;
+}
+
+static boolean
+bfd_pef_mkobject (abfd)
+     bfd *abfd ATTRIBUTE_UNUSED;
+{
+  return true;
+}
+
+static int
+bfd_pef_parse_traceback_table (abfd, section, buf, len, pos, sym, file)
+     bfd *abfd;
+     asection *section;
+     unsigned char *buf;
+     size_t len;
+     size_t pos;
+     asymbol *sym;
+     FILE *file;
+{
+  struct traceback_table table;
+  size_t offset;
+  const char *s;
+  asymbol tmpsymbol;
+  
+  if (sym == NULL) { sym = &tmpsymbol; }
+
+  sym->name = NULL;
+  sym->value = 0;
+  sym->the_bfd = abfd;
+  sym->section = section;
+  sym->flags = 0;
+  sym->udata.i = 0;
+
+  /* memcpy is fine since all fields are unsigned char */
+
+  if ((pos + 8) > len) { return -1; }
+  memcpy (&table, buf + pos, 8);
+  
+  /* calling code relies on returned symbols having a name and correct offset */
+
+  if ((table.lang != TB_C) && (table.lang != TB_CPLUSPLUS)) { 
+    return -1;
+  }
+  if (! (table.flags2 & TB_NAME_PRESENT)) {
+    return -1;
+  }
+  if (! table.flags1 & TB_HAS_TBOFF) {
+    return -1;
+  }
+
+  offset = 8;
+
+  if ((table.flags5 & TB_FLOATPARAMS) || (table.fixedparams)) {
+    offset += 4; 
+  }
+
+  if (table.flags1 & TB_HAS_TBOFF) {
+
+    struct traceback_table_tboff off;
+    
+    if ((pos + offset + 4) > len) { return -1; }
+    off.tb_offset = bfd_getb32 (buf + pos + offset);
+    offset += 4;
+
+    /* need to subtract 4 because the offset includes the 0x0L
+       preceding the table */
+
+    if (file != NULL) {
+      fprintf (file, " [offset = 0x%lx]", off.tb_offset);
+    }
+
+    if ((file == NULL) && ((off.tb_offset + 4) > (pos + offset))) {
+      return -1;
+    }
+    sym->value = pos - off.tb_offset - 4;
+  }
+
+  if (table.flags2 & TB_INT_HNDL) {
+    offset += 4;
+  }
+
+  if (table.flags1 & TB_HAS_CTL) {
+
+    struct traceback_table_anchors anchors;
+
+    if ((pos + offset + 4) > len) { return -1; }
+    anchors.ctl_info = bfd_getb32 (buf + pos + offset);
+    offset += 4;
+
+    if (anchors.ctl_info > 1024) { 
+      return -1;
+    }
+
+    offset += anchors.ctl_info * 4;
+  }
+
+  if (table.flags2 & TB_NAME_PRESENT) {
+
+    struct traceback_table_routine name;
+    char *namebuf;
+
+    if ((pos + offset + 2) > len) { return -1; }
+    name.name_len = bfd_getb16 (buf + pos + offset);
+    offset += 2;
+
+    if (name.name_len > 4096) { return -1; }
+
+    if ((pos + offset + name.name_len) > len) { return -1; }
+
+    namebuf = (char *) bfd_alloc (abfd, name.name_len + 1);
+    if (namebuf == NULL) { return -1; }
+
+    memcpy (namebuf, buf + pos + offset, name.name_len);
+    namebuf[name.name_len] = '\0';
+    
+    /* strip leading period inserted by compiler */
+    if (namebuf[0] == '.') {
+      memmove (namebuf, namebuf + 1, name.name_len + 1);
+    }
+
+    sym->name = namebuf;
+
+    for (s = sym->name; (*s != '\0'); s++) {
+      if (! isprint (*s)) {
+       return -1;
+      }
+    }
+
+    offset += name.name_len;
+  }
+
+  if (table.flags2 & TB_USES_ALLOCA) {
+    offset += 4;
+  }
+
+  if (table.flags4 & TB_HAS_VEC_INFO) {
+    offset += 4;
+  }
+
+  if (file != NULL) {
+    fprintf (file, " [length = 0x%lx]", (long) offset);
+  }
+  return offset;
+}
+
+static const char *bfd_pef_section_name (section)
+     bfd_pef_section *section;
+{
+  switch (section->section_kind) {
+  case BFD_PEF_SECTION_CODE: return "code";
+  case BFD_PEF_SECTION_UNPACKED_DATA: return "unpacked-data";
+  case BFD_PEF_SECTION_PACKED_DATA: return "packed-data";
+  case BFD_PEF_SECTION_CONSTANT: return "constant";
+  case BFD_PEF_SECTION_LOADER: return "loader";
+  case BFD_PEF_SECTION_DEBUG: return "debug";
+  case BFD_PEF_SECTION_EXEC_DATA: return "exec-data";
+  case BFD_PEF_SECTION_EXCEPTION: return "exception";
+  case BFD_PEF_SECTION_TRACEBACK: return "traceback";
+  default: return "unknown";
+  }
+}
+
+static unsigned long bfd_pef_section_flags (section)
+     bfd_pef_section *section;
+{
+  switch (section->section_kind) {
+  case BFD_PEF_SECTION_CODE:
+    return SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC | SEC_CODE;
+  case BFD_PEF_SECTION_UNPACKED_DATA:
+  case BFD_PEF_SECTION_PACKED_DATA:
+  case BFD_PEF_SECTION_CONSTANT:
+  case BFD_PEF_SECTION_LOADER:
+  case BFD_PEF_SECTION_DEBUG:
+  case BFD_PEF_SECTION_EXEC_DATA:
+  case BFD_PEF_SECTION_EXCEPTION:
+  case BFD_PEF_SECTION_TRACEBACK:
+  default:
+    return SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
+  }
+}
+
+static asection *
+bfd_pef_make_bfd_section (abfd, section)
+     bfd *abfd;
+     bfd_pef_section *section;
+{
+  asection *bfdsec;
+  const char *name = bfd_pef_section_name (section);
+
+  bfdsec = bfd_make_section_anyway (abfd, name);
+  if (bfdsec == NULL) { return NULL; }
+  
+  bfdsec->vma = section->default_address + section->container_offset;
+  bfdsec->lma = section->default_address + section->container_offset;
+  bfdsec->_raw_size = section->container_length;
+  bfdsec->filepos = section->container_offset;
+  bfdsec->alignment_power = section->alignment;
+
+  bfdsec->flags = bfd_pef_section_flags (section);
+
+  return bfdsec;
+}
+
+int bfd_pef_parse_loader_header (abfd, buf, len, header)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     unsigned char *buf;
+     size_t len;
+     bfd_pef_loader_header *header;
+{
+  BFD_ASSERT (len == 56);
+
+  header->main_section = bfd_getb32 (buf);
+  header->main_offset = bfd_getb32 (buf + 4);
+  header->init_section = bfd_getb32 (buf + 8);
+  header->init_offset = bfd_getb32 (buf + 12);
+  header->term_section = bfd_getb32 (buf + 16);
+  header->term_offset = bfd_getb32 (buf + 20);
+  header->imported_library_count = bfd_getb32 (buf + 24);
+  header->total_imported_symbol_count = bfd_getb32 (buf + 28);
+  header->reloc_section_count = bfd_getb32 (buf + 32);
+  header->reloc_instr_offset = bfd_getb32 (buf + 36);
+  header->loader_strings_offset = bfd_getb32 (buf + 40);
+  header->export_hash_offset = bfd_getb32 (buf + 44);
+  header->export_hash_table_power = bfd_getb32 (buf + 48);
+  header->exported_symbol_count = bfd_getb32 (buf + 52);
+
+  return 0;
+}
+
+int bfd_pef_parse_imported_library (abfd, buf, len, header)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     unsigned char *buf;
+     size_t len;
+     bfd_pef_imported_library *header;
+{
+  BFD_ASSERT (len == 24);
+
+  header->name_offset = bfd_getb32 (buf);
+  header->old_implementation_version = bfd_getb32 (buf + 4);
+  header->current_version = bfd_getb32 (buf + 8);
+  header->imported_symbol_count = bfd_getb32 (buf + 12);
+  header->first_imported_symbol = bfd_getb32 (buf + 16);
+  header->options = buf[20];
+  header->reserved_a = buf[21];
+  header->reserved_b = bfd_getb16 (buf + 22);
+
+  return 0;
+}
+
+int bfd_pef_parse_imported_symbol (abfd, buf, len, symbol)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     unsigned char *buf;
+     size_t len;
+     bfd_pef_imported_symbol *symbol;
+{
+  unsigned long value;
+
+  BFD_ASSERT (len == 4);
+
+  value = bfd_getb32 (buf);
+  symbol->class = value >> 24;
+  symbol->name = value & 0x00ffffff;
+
+  return 0;
+}
+
+int bfd_pef_scan_section (abfd, section)
+     bfd *abfd;
+     bfd_pef_section *section;
+{
+  unsigned char buf[28];
+  
+  bfd_seek (abfd, section->header_offset, SEEK_SET);
+  if (bfd_bread ((PTR) buf, 28, abfd) != 28) { return -1; }
+
+  section->name_offset = bfd_h_get_32 (abfd, buf);
+  section->default_address = bfd_h_get_32 (abfd, buf + 4);
+  section->total_length = bfd_h_get_32 (abfd, buf + 8);
+  section->unpacked_length = bfd_h_get_32 (abfd, buf + 12);
+  section->container_length = bfd_h_get_32 (abfd, buf + 16);
+  section->container_offset = bfd_h_get_32 (abfd, buf + 20);
+  section->section_kind = buf[24];
+  section->share_kind = buf[25];
+  section->alignment = buf[26];
+  section->reserved = buf[27];
+
+  section->bfd_section = bfd_pef_make_bfd_section (abfd, section);
+  if (section->bfd_section == NULL) { return -1; }
+
+  return 0;
+}
+
+void
+bfd_pef_print_loader_header (abfd, header, file)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     bfd_pef_loader_header *header;
+     FILE *file;
+{
+  fprintf (file, "main_section: %ld\n", header->main_section);
+  fprintf (file, "main_offset: %lu\n", header->main_offset);
+  fprintf (file, "init_section: %ld\n", header->init_section);
+  fprintf (file, "init_offset: %lu\n", header->init_offset);
+  fprintf (file, "term_section: %ld\n", header->term_section);
+  fprintf (file, "term_offset: %lu\n", header->term_offset);
+  fprintf (file, "imported_library_count: %lu\n", header->imported_library_count);
+  fprintf (file, "total_imported_symbol_count: %lu\n", header->total_imported_symbol_count);
+  fprintf (file, "reloc_section_count: %lu\n", header->reloc_section_count);
+  fprintf (file, "reloc_instr_offset: %lu\n", header->reloc_instr_offset);
+  fprintf (file, "loader_strings_offset: %lu\n", header->loader_strings_offset);
+  fprintf (file, "export_hash_offset: %lu\n", header->export_hash_offset);
+  fprintf (file, "export_hash_table_power: %lu\n", header->export_hash_table_power);
+  fprintf (file, "exported_symbol_count: %lu\n", header->exported_symbol_count);
+}
+
+int
+bfd_pef_print_loader_section (abfd, file)
+     bfd *abfd;
+     FILE *file;
+{
+  bfd_pef_loader_header header;
+  asection *loadersec = NULL;
+  unsigned char *loaderbuf = NULL;
+  size_t loaderlen = 0;
+  int ret;
+
+  loadersec = bfd_get_section_by_name (abfd, "loader");
+  if (loadersec == NULL) { return -1; }
+    
+  loaderlen = bfd_section_size (abfd, loadersec);
+  loaderbuf = (unsigned char *) bfd_malloc (loaderlen);
+  if (bfd_seek (abfd, loadersec->filepos, SEEK_SET) < 0)
+    { free (loaderbuf); return -1; }
+  if (bfd_bread ((PTR) loaderbuf, loaderlen, abfd) != loaderlen)
+    { free (loaderbuf); return -1; }
+
+  if (loaderlen < 56) { free (loaderbuf); return -1; }
+  ret = bfd_pef_parse_loader_header (abfd, loaderbuf, 56, &header);
+  if (ret < 0) { free (loaderbuf); return -1; }
+
+  bfd_pef_print_loader_header (abfd, &header, file);
+  return 0;
+}
+
+int
+bfd_pef_scan_start_address (abfd)
+     bfd *abfd;
+{
+  bfd_pef_loader_header header;
+  asection *section;
+
+  asection *loadersec = NULL;
+  unsigned char *loaderbuf = NULL;
+  size_t loaderlen = 0;
+  int ret;
+
+  loadersec = bfd_get_section_by_name (abfd, "loader");
+  if (loadersec == NULL) { goto end; }
+    
+  loaderlen = bfd_section_size (abfd, loadersec);
+  loaderbuf = (unsigned char *) bfd_malloc (loaderlen);
+  if (bfd_seek (abfd, loadersec->filepos, SEEK_SET) < 0) { goto error; }
+  if (bfd_bread ((PTR) loaderbuf, loaderlen, abfd) != loaderlen) { goto error; }
+
+  if (loaderlen < 56) { goto error; }
+  ret = bfd_pef_parse_loader_header (abfd, loaderbuf, 56, &header);
+  if (ret < 0) { goto error; }
+
+  if (header.main_section < 0) { goto end; }
+
+  for (section = abfd->sections; section != NULL; section = section->next) {
+    if ((section->index + 1) == header.main_section) { break; }
+  }
+  
+  if (section == NULL) { goto error; }
+  
+  abfd->start_address = section->vma + header.main_offset;
+
+ end:
+  if (loaderbuf != NULL) { free (loaderbuf); }
+  return 0;
+
+ error:
+  if (loaderbuf != NULL) { free (loaderbuf); }
+  return -1;
+}
+
+int
+bfd_pef_scan (abfd, header)
+     bfd *abfd;
+     bfd_pef_header *header;
+{
+  unsigned int i;
+  bfd_pef_data_struct *mdata = NULL;
+  enum bfd_architecture cputype;
+  unsigned long cpusubtype;
+
+  if ((header->tag1 != BFD_PEF_TAG1) || (header->tag2 != BFD_PEF_TAG2)) {
+    return -1;
+  }
+
+  mdata = ((bfd_pef_data_struct *) 
+          bfd_alloc (abfd, sizeof (bfd_pef_data_struct)));
+  if (mdata == NULL) { return -1; }
+  
+  bfd_pef_convert_architecture (header->architecture, &cputype, &cpusubtype);
+  if (cputype == bfd_arch_unknown) {
+    fprintf (stderr, "bfd_pef_scan: unknown architecture 0x%lx\n", header->architecture);
+    return -1;
+  }
+  bfd_set_arch_mach (abfd, cputype, cpusubtype);
+
+  mdata->header = *header;
+
+  abfd->flags = abfd->xvec->object_flags | (abfd->flags & (BFD_IN_MEMORY | BFD_IO_FUNCS));
+
+  if (header->section_count != 0) {
+    
+    mdata->sections = 
+      ((bfd_pef_section *)
+       bfd_alloc (abfd, header->section_count * sizeof (bfd_pef_section)));
+    if (mdata->sections == NULL) { return -1; } 
+
+    for (i = 0; i < header->section_count; i++) {
+      bfd_pef_section *cur = &mdata->sections[i];
+      cur->header_offset = 40 + (i * 28);
+      if (bfd_pef_scan_section (abfd, cur) < 0) {
+       return -1;
+      }
+    }
+  }
+
+  if (bfd_pef_scan_start_address (abfd) < 0) { 
+#if 0
+    fprintf (stderr, "bfd_pef_scan: unable to scan start address: %s\n",
+            bfd_errmsg (bfd_get_error ()));
+    abfd->tdata.pef_data = NULL;
+    return -1; 
+#endif
+  }
+
+  abfd->tdata.pef_data = mdata;
+
+  return 0;
+}
+
+static int
+bfd_pef_read_header (abfd, header)
+     bfd *abfd;
+     bfd_pef_header *header;
+{
+  unsigned char buf[40];
+
+  bfd_seek (abfd, 0, SEEK_SET);
+
+  if (bfd_bread ((PTR) buf, 40, abfd) != 40) { return -1; }
+
+  header->tag1 = bfd_getb32 (buf);
+  header->tag2 = bfd_getb32 (buf + 4);
+  header->architecture = bfd_getb32 (buf + 8);
+  header->format_version = bfd_getb32 (buf + 12);
+  header->timestamp = bfd_getb32 (buf + 16);
+  header->old_definition_version = bfd_getb32 (buf + 20);
+  header->old_implementation_version = bfd_getb32 (buf + 24);
+  header->current_version = bfd_getb32 (buf + 28);
+  header->section_count = bfd_getb32 (buf + 32) + 1;
+  header->instantiated_section_count = bfd_getb32 (buf + 34);
+  header->reserved = bfd_getb32 (buf + 36);
+
+  return 0;
+}
+
+static const bfd_target *
+bfd_pef_object_p (abfd)
+     bfd *abfd;
+{
+  bfd_pef_header header;
+  
+  abfd->tdata.pef_data = NULL;
+
+  if (bfd_pef_read_header (abfd, &header) != 0) {
+    abfd->tdata.pef_data = NULL;
+    bfd_set_error (bfd_error_wrong_format);
+    return NULL;
+  }
+
+  if (bfd_pef_scan (abfd, &header) != 0) {
+    abfd->tdata.pef_data = NULL;
+    bfd_set_error (bfd_error_wrong_format);
+    return NULL;
+  }
+
+  return abfd->xvec;
+}
+
+static int bfd_pef_parse_traceback_tables (abfd, sec, buf, len, nsym, csym)
+     bfd *abfd;
+     asection *sec;
+     unsigned char *buf;
+     size_t len;
+     long *nsym;
+     asymbol **csym;
+{
+  char *name;
+
+  asymbol function;
+  asymbol traceback;
+
+  const char *const tbprefix = "__traceback_";
+  size_t tbnamelen;
+
+  size_t pos = 0;
+  unsigned long count = 0;
+  int ret;
+
+  for (;;) {
+       
+    /* we're reading symbols two at a time */
+
+    if (csym && ((csym[count] == NULL) || (csym[count + 1] == NULL))) {
+      break;
+    }
+
+    pos += 3;
+    pos -= (pos % 4);
+
+    while ((pos + 4) <= len) {
+      if (bfd_getb32 (buf + pos) == 0) {
+       break;
+      }
+      pos += 4;
+    }
+
+    if ((pos + 4) > len) {
+      break;
+    }
+       
+    ret = bfd_pef_parse_traceback_table (abfd, sec, buf, len, pos + 4, &function, 0);
+    if (ret < 0) {
+      /* skip over 0x0L to advance to next possible traceback table */
+      pos += 4;
+      continue;
+    }
+       
+    BFD_ASSERT (function.name != NULL);
+
+    /* Don't bother to compute the name if we are just
+       counting symbols */
+
+    if (csym)
+      {
+       tbnamelen = strlen (tbprefix) + strlen (function.name);
+       name = bfd_alloc (abfd, tbnamelen + 1);
+       if (name == NULL) { 
+         bfd_release (abfd, (PTR) function.name);
+         function.name = NULL;
+         break;
+       }
+       snprintf (name, tbnamelen + 1, "%s%s", tbprefix, function.name);
+       traceback.name = name;
+       traceback.value = pos;
+       traceback.the_bfd = abfd;
+       traceback.section = sec;
+       traceback.flags = 0;
+       traceback.udata.i = ret;
+
+       *(csym[count]) = function;
+       *(csym[count + 1]) = traceback;
+      }
+
+    pos += ret;
+    count += 2;
+  }
+
+  *nsym = count;
+  return 0;
+}
+
+static int bfd_pef_parse_function_stub (abfd, buf, len, offset)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     unsigned char *buf;
+     size_t len;
+     unsigned long *offset;
+{
+  BFD_ASSERT (len == 24);
+
+  if ((bfd_getb32 (buf) & 0xffff0000) != 0x81820000) { return -1; }
+  if (bfd_getb32 (buf + 4) != 0x90410014) { return -1; }
+  if (bfd_getb32 (buf + 8) != 0x800c0000) { return -1; }
+  if (bfd_getb32 (buf + 12) != 0x804c0004) { return -1; }
+  if (bfd_getb32 (buf + 16) != 0x7c0903a6) { return -1; }
+  if (bfd_getb32 (buf + 20) != 0x4e800420) { return -1; }
+  
+  if (offset != NULL) {
+    *offset = (bfd_getb32 (buf) & 0x0000ffff) / 4;
+  }
+
+  return 0;
+}
+
+static int bfd_pef_parse_function_stubs (abfd, codesec, codebuf, codelen, loaderbuf, loaderlen, nsym, csym)
+     bfd *abfd;
+     asection *codesec;
+     unsigned char *codebuf;
+     size_t codelen;
+     unsigned char *loaderbuf;
+     size_t loaderlen;
+     unsigned long *nsym;
+     asymbol **csym;
+{
+  const char *const sprefix = "__stub_";
+
+  size_t codepos = 0;
+  unsigned long count = 0;
+
+  bfd_pef_loader_header header;
+  bfd_pef_imported_library *libraries = NULL;
+  bfd_pef_imported_symbol *imports = NULL;
+
+  unsigned long i;
+  int ret;
+
+  if (loaderlen < 56) { goto error; }
+
+  ret = bfd_pef_parse_loader_header (abfd, loaderbuf, 56, &header);
+  if (ret < 0) { goto error; }
+
+  libraries = (bfd_pef_imported_library *) bfd_malloc
+    (header.imported_library_count * sizeof (bfd_pef_imported_library));
+  imports = (bfd_pef_imported_symbol *) bfd_malloc
+    (header.total_imported_symbol_count * sizeof (bfd_pef_imported_symbol));
+  
+  if (loaderlen < (56 + (header.imported_library_count * 24))) { goto error; }
+  for (i = 0; i < header.imported_library_count; i++) {
+    ret = bfd_pef_parse_imported_library
+      (abfd, loaderbuf + 56 + (i * 24), 24, &libraries[i]);
+    if (ret < 0) { goto error; }
+  }
+  
+  if (loaderlen < (56 + (header.imported_library_count * 24) + (header.total_imported_symbol_count * 4)))
+    { goto error; }
+  for (i = 0; i < header.total_imported_symbol_count; i++) {
+    ret = bfd_pef_parse_imported_symbol 
+      (abfd, loaderbuf + 56 + (header.imported_library_count * 24) + (i * 4), 4, &imports[i]);
+    if (ret < 0) { goto error; }
+  }
+    
+  codepos = 0;
+
+  for (;;) {
+
+    asymbol sym;
+    const char *symname;
+    char *name;
+    unsigned long index;
+    int ret;
+
+    if (csym && (csym[count] == NULL)) { break; }
+
+    codepos += 3;
+    codepos -= (codepos % 4);
+
+    while ((codepos + 4) <= codelen) {
+      if ((bfd_getb32 (codebuf + codepos) & 0xffff0000) == 0x81820000) { 
+       break;
+      }
+      codepos += 4;
+    }
+
+    if ((codepos + 4) > codelen) {
+      break;
+    }
+
+    ret = bfd_pef_parse_function_stub (abfd, codebuf + codepos, 24, &index);
+    if (ret < 0) { codepos += 24; continue; }
+    
+    if (index >= header.total_imported_symbol_count) { codepos += 24; continue; }
+
+    {
+      size_t max, namelen;
+      const char *s;
+
+      if (loaderlen < (header.loader_strings_offset + imports[index].name)) { goto error; }
+
+      max = loaderlen - (header.loader_strings_offset + imports[index].name);
+      symname = loaderbuf + header.loader_strings_offset + imports[index].name;
+      namelen = 0;
+      for (s = symname; s < (symname + max); s++) {
+       if (*s == '\0') { break; }
+       if (! isprint (*s)) { goto error; }
+       namelen++;
+      }
+      if (*s != '\0') { goto error; }
+
+      name = bfd_alloc (abfd, strlen (sprefix) + namelen + 1);
+      if (name == NULL) { break; }
+
+      snprintf (name, strlen (sprefix) + namelen + 1, "%s%s", sprefix, symname);
+      sym.name = name;
+    }
+
+    sym.value = codepos;
+    sym.the_bfd = abfd;
+    sym.section = codesec;
+    sym.flags = 0;
+    sym.udata.i = 0;
+
+    codepos += 24;
+
+    if (csym != NULL) {
+      *(csym[count]) = sym;
+    }
+    count++;
+  }  
+
+  goto end;
+
+ end:
+  if (libraries != NULL) { free (libraries); }
+  if (imports != NULL) { free (imports); }
+  *nsym = count;
+  return 0;
+
+ error:
+  if (libraries != NULL) { free (libraries); }
+  if (imports != NULL) { free (imports); }
+  *nsym = count;
+  return -1;
+}   
+
+static long bfd_pef_parse_symbols (abfd, csym)
+     bfd *abfd;
+     asymbol **csym;
+{
+  unsigned long count = 0;
+
+  asection *codesec = NULL;
+  unsigned char *codebuf = NULL;
+  size_t codelen = 0;
+
+  asection *loadersec = NULL;
+  unsigned char *loaderbuf = NULL;
+  size_t loaderlen = 0;
+
+  codesec = bfd_get_section_by_name (abfd, "code");
+  if (codesec != NULL)
+    {
+      codelen = bfd_section_size (abfd, codesec);
+      codebuf = (unsigned char *) bfd_malloc (codelen);
+      if (bfd_seek (abfd, codesec->filepos, SEEK_SET) < 0) { goto end; }
+      if (bfd_bread ((PTR) codebuf, codelen, abfd) != codelen) { goto end; }
+    }
+
+  loadersec = bfd_get_section_by_name (abfd, "loader");
+  if (loadersec != NULL)
+    {
+      loaderlen = bfd_section_size (abfd, loadersec);
+      loaderbuf = (unsigned char *) bfd_malloc (loaderlen);
+      if (bfd_seek (abfd, loadersec->filepos, SEEK_SET) < 0) { goto end; }
+      if (bfd_bread ((PTR) loaderbuf, loaderlen, abfd) != loaderlen) { goto end; }
+    }
+  
+  count = 0;
+  if (codesec != NULL)
+    {
+      unsigned long ncount = 0;
+      bfd_pef_parse_traceback_tables (abfd, codesec, codebuf, codelen, &ncount, csym);
+      count += ncount;
+    }
+
+  if ((codesec != NULL) && (loadersec != NULL))
+    {
+      unsigned long ncount = 0;
+      bfd_pef_parse_function_stubs
+       (abfd, codesec, codebuf, codelen, loaderbuf, loaderlen, &ncount,
+        (csym != NULL) ? (csym + count) : NULL);
+      count += ncount;
+    }
+  
+  if (csym != NULL) {
+    csym[count] = NULL;
+  }
+  
+ end:
+  if (codebuf != NULL) 
+    free (codebuf);
+
+  if (loaderbuf != NULL) 
+    free (loaderbuf); 
+  
+  return count;
+}
+
+static long
+bfd_pef_count_symbols (abfd)
+     bfd *abfd;
+{
+  return bfd_pef_parse_symbols (abfd, NULL);
+}
+
+static long
+bfd_pef_get_symtab_upper_bound (abfd)
+     bfd *abfd;
+{
+  long nsyms = bfd_pef_count_symbols (abfd);
+  if (nsyms < 0) { return nsyms; }
+  return ((nsyms + 1) * sizeof (asymbol *));
+}
+
+static long
+bfd_pef_get_symtab (abfd, alocation)
+     bfd *abfd;
+     asymbol **alocation;
+{
+  long i;
+  asymbol *syms;
+  long ret;
+
+  long nsyms = bfd_pef_count_symbols (abfd);
+  if (nsyms < 0) { return nsyms; }
+
+  syms = bfd_alloc (abfd, nsyms * sizeof (asymbol));
+  if (syms == NULL) { return -1; }
+
+  for (i = 0; i < nsyms; i++) {
+    alocation[i] = &syms[i];
+  }
+  alocation[nsyms] = NULL;
+
+  ret = bfd_pef_parse_symbols (abfd, alocation);
+  if (ret != nsyms) {
+    return 0;
+  }
+
+  return ret;
+}
+
+static asymbol *
+bfd_pef_make_empty_symbol (abfd)
+     bfd *abfd;
+{
+  return (asymbol *) bfd_alloc (abfd, sizeof (asymbol));
+}
+
+static void
+bfd_pef_get_symbol_info (abfd, symbol, ret)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     asymbol *symbol;
+     symbol_info *ret;
+{
+  bfd_symbol_info (symbol, ret);
+}
+
+static int
+bfd_pef_sizeof_headers (abfd, exec)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     boolean exec ATTRIBUTE_UNUSED;
+{
+  return 0;
+}
+
+const bfd_target pef_vec =
+{
+  "pef",                       /* name */
+  bfd_target_pef_flavour,      /* flavour */
+  BFD_ENDIAN_BIG,              /* byteorder */
+  BFD_ENDIAN_BIG,              /* header_byteorder */
+  (HAS_RELOC | EXEC_P |                /* object flags */
+   HAS_LINENO | HAS_DEBUG |
+   HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
+  (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_DATA
+   | SEC_ROM | SEC_HAS_CONTENTS), /* section_flags */
+  0,                           /* symbol_leading_char */
+  ' ',                         /* ar_pad_char */
+  16,                          /* ar_max_namelen */
+  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+  bfd_getb16, bfd_getb_signed_16, bfd_putb16,  /* data */
+  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+  bfd_getb16, bfd_getb_signed_16, bfd_putb16,  /* hdrs */
+  {                            /* bfd_check_format */
+    _bfd_dummy_target,
+    bfd_pef_object_p,          /* bfd_check_format */
+    _bfd_dummy_target,
+    _bfd_dummy_target,
+  },
+  {                            /* bfd_set_format */
+    bfd_false,
+    bfd_pef_mkobject,
+    bfd_false,
+    bfd_false,
+  },
+  {                            /* bfd_write_contents */
+    bfd_false,
+    bfd_true,
+    bfd_false,
+    bfd_false,
+  },
+
+  BFD_JUMP_TABLE_GENERIC (bfd_pef),
+  BFD_JUMP_TABLE_COPY (_bfd_generic),
+  BFD_JUMP_TABLE_CORE (_bfd_nocore),
+  BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
+  BFD_JUMP_TABLE_SYMBOLS (bfd_pef),
+  BFD_JUMP_TABLE_RELOCS (bfd_pef),
+  BFD_JUMP_TABLE_WRITE (bfd_pef),
+  BFD_JUMP_TABLE_LINK (bfd_pef),
+  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+  NULL,
+  
+  NULL
+};
+
+#define bfd_pef_xlib_close_and_cleanup _bfd_generic_close_and_cleanup
+#define bfd_pef_xlib_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
+#define bfd_pef_xlib_new_section_hook _bfd_generic_new_section_hook
+#define bfd_pef_xlib_get_section_contents _bfd_generic_get_section_contents
+#define bfd_pef_xlib_set_section_contents _bfd_generic_set_section_contents
+#define bfd_pef_xlib_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
+#define bfd_pef_xlib_set_section_contents_in_window _bfd_generic_set_section_contents_in_window
+
+static int
+bfd_pef_xlib_read_header (abfd, header)
+     bfd *abfd;
+     bfd_pef_xlib_header *header;
+{
+  unsigned char buf[76];
+
+  bfd_seek (abfd, 0, SEEK_SET);
+
+  if (bfd_bread ((PTR) buf, 76, abfd) != 76) { return -1; }
+
+  header->tag1 = bfd_getb32 (buf);
+  header->tag2 = bfd_getb32 (buf + 4);
+  header->current_format = bfd_getb32 (buf + 8);
+  header->container_strings_offset = bfd_getb32 (buf + 12);
+  header->export_hash_offset = bfd_getb32 (buf + 16);
+  header->export_key_offset = bfd_getb32 (buf + 20);
+  header->export_symbol_offset = bfd_getb32 (buf + 24);
+  header->export_names_offset = bfd_getb32 (buf + 28);
+  header->export_hash_table_power = bfd_getb32 (buf + 32);
+  header->exported_symbol_count = bfd_getb32 (buf + 36);
+  header->frag_name_offset = bfd_getb32 (buf + 40);
+  header->frag_name_length = bfd_getb32 (buf + 44);
+  header->dylib_path_offset = bfd_getb32 (buf + 48);
+  header->dylib_path_length = bfd_getb32 (buf + 52);
+  header->cpu_family = bfd_getb32 (buf + 56);
+  header->cpu_model = bfd_getb32 (buf + 60);
+  header->date_time_stamp = bfd_getb32 (buf + 64);
+  header->current_version = bfd_getb32 (buf + 68);
+  header->old_definition_version = bfd_getb32 (buf + 72);
+  header->old_implementation_version = bfd_getb32 (buf + 76);
+
+  return 0;
+}
+
+int
+bfd_pef_xlib_scan (abfd, header)
+     bfd *abfd;
+     bfd_pef_xlib_header *header;
+{
+  bfd_pef_xlib_data_struct *mdata = NULL;
+
+  if ((header->tag1 != BFD_PEF_XLIB_TAG1) 
+      || ((header->tag2 != BFD_PEF_VLIB_TAG2) && (header->tag2 != BFD_PEF_BLIB_TAG2))) {
+    return -1;
+  }
+
+  mdata = ((bfd_pef_xlib_data_struct *) 
+          bfd_alloc (abfd, sizeof (bfd_pef_xlib_data_struct)));
+  if (mdata == NULL) { return -1; }
+  
+  mdata->header = *header;
+
+  abfd->flags = abfd->xvec->object_flags | (abfd->flags & (BFD_IN_MEMORY | BFD_IO_FUNCS));
+
+  abfd->tdata.pef_xlib_data = mdata;
+
+  return 0;
+}
+
+static const bfd_target *
+bfd_pef_xlib_object_p (abfd)
+     bfd *abfd;
+{
+  bfd_pef_xlib_header header;
+  
+  abfd->tdata.pef_xlib_data = NULL;
+
+  if (bfd_pef_xlib_read_header (abfd, &header) != 0) {
+    abfd->tdata.pef_xlib_data = NULL;
+    bfd_set_error (bfd_error_wrong_format);
+    return NULL;
+  }
+
+  if (bfd_pef_xlib_scan (abfd, &header) != 0) {
+    abfd->tdata.pef_xlib_data = NULL;
+    bfd_set_error (bfd_error_wrong_format);
+    return NULL;
+  }
+
+  return abfd->xvec;
+}
+
+const bfd_target pef_xlib_vec =
+{
+  "pef-xlib",                  /* name */
+  bfd_target_pef_xlib_flavour, /* flavour */
+  BFD_ENDIAN_BIG,              /* byteorder */
+  BFD_ENDIAN_BIG,              /* header_byteorder */
+  (HAS_RELOC | EXEC_P |                /* object flags */
+   HAS_LINENO | HAS_DEBUG |
+   HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
+  (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_DATA
+   | SEC_ROM | SEC_HAS_CONTENTS), /* section_flags */
+  0,                           /* symbol_leading_char */
+  ' ',                         /* ar_pad_char */
+  16,                          /* ar_max_namelen */
+  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+  bfd_getb16, bfd_getb_signed_16, bfd_putb16,  /* data */
+  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+  bfd_getb16, bfd_getb_signed_16, bfd_putb16,  /* hdrs */
+  {                            /* bfd_check_format */
+    _bfd_dummy_target,
+    bfd_pef_xlib_object_p,     /* bfd_check_format */
+    _bfd_dummy_target,
+    _bfd_dummy_target,
+  },
+  {                            /* bfd_set_format */
+    bfd_false,
+    bfd_pef_mkobject,
+    bfd_false,
+    bfd_false,
+  },
+  {                            /* bfd_write_contents */
+    bfd_false,
+    bfd_true,
+    bfd_false,
+    bfd_false,
+  },
+
+  BFD_JUMP_TABLE_GENERIC (bfd_pef_xlib),
+  BFD_JUMP_TABLE_COPY (_bfd_generic),
+  BFD_JUMP_TABLE_CORE (_bfd_nocore),
+  BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
+  BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
+  BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
+  BFD_JUMP_TABLE_WRITE (_bfd_nowrite),
+  BFD_JUMP_TABLE_LINK (_bfd_nolink),
+  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+  NULL,
+  
+  NULL
+};
+
diff --git a/bfd/pef.h b/bfd/pef.h
new file mode 100644 (file)
index 0000000..e909be4
--- /dev/null
+++ b/bfd/pef.h
@@ -0,0 +1,186 @@
+/* PEF support for BFD.
+   Copyright 1999, 2000, 2001, 2002
+   Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software 
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include "bfd.h"
+
+#include <stdio.h>
+
+struct bfd_pef_header
+{
+  unsigned long tag1;
+  unsigned long tag2;
+  unsigned long architecture;
+  unsigned long format_version;
+  unsigned long timestamp;
+  unsigned long old_definition_version;
+  unsigned long old_implementation_version;
+  unsigned long current_version;
+  unsigned short section_count;
+  unsigned short instantiated_section_count;
+  unsigned long reserved;
+};
+typedef struct bfd_pef_header bfd_pef_header;
+
+struct bfd_pef_loader_header
+{
+  long main_section;
+  unsigned long main_offset;
+  long init_section;
+  unsigned long init_offset; 
+  long term_section;
+  unsigned long term_offset;
+  unsigned long imported_library_count;
+  unsigned long total_imported_symbol_count;
+  unsigned long reloc_section_count;
+  unsigned long reloc_instr_offset;
+  unsigned long loader_strings_offset;
+  unsigned long export_hash_offset;
+  unsigned long export_hash_table_power;
+  unsigned long exported_symbol_count;
+};
+typedef struct bfd_pef_loader_header bfd_pef_loader_header;
+
+struct bfd_pef_imported_library
+{
+  unsigned long name_offset;
+  unsigned long old_implementation_version;
+  unsigned long current_version;
+  unsigned long imported_symbol_count;
+  unsigned long first_imported_symbol;
+  unsigned char options;
+  unsigned char reserved_a;
+  unsigned short reserved_b;
+};
+typedef struct bfd_pef_imported_library bfd_pef_imported_library;
+
+enum bfd_pef_imported_library_options
+  {
+    BFD_PEF_WEAK_IMPORT_LIB = 0x40,
+    BFD_PEF_INIT_LIB_BEFORE = 0x80
+  };
+
+struct bfd_pef_imported_symbol
+{
+  unsigned char class;
+  unsigned long name;
+};
+typedef struct bfd_pef_imported_symbol bfd_pef_imported_symbol;
+
+enum bfd_pef_imported_symbol_class
+  {
+    BFD_PEF_CODE_SYMBOL = 0x00,
+    BFD_PEF_DATA_SYMBOL = 0x01,
+    BFD_PEF_TVECTOR_SYMBOL = 0x02,
+    BFD_PEF_TOC_SYMBOL = 0x03,
+    BFD_PEF_GLUE_SYMBOL = 0x04,
+    BFD_PEF_UNDEFINED_SYMBOL = 0x0F,
+    BFD_PEF_WEAK_IMPORT_SYMBOL_MASK = 0x80
+  };
+
+#define BFD_PEF_TAG1 0x4A6F7921 /* 'Joy!' */
+#define BFD_PEF_TAG2 0x70656666 /* 'peff' */
+
+#define BFD_PEF_VERSION 0x00000001
+
+struct bfd_pef_section
+{
+  long name_offset;
+  unsigned long header_offset;
+  unsigned long default_address;
+  unsigned long total_length;
+  unsigned long unpacked_length;
+  unsigned long container_length;
+  unsigned long container_offset;
+  unsigned char section_kind;
+  unsigned char share_kind;
+  unsigned char alignment;
+  unsigned char reserved;
+  asection *bfd_section;
+};
+typedef struct bfd_pef_section bfd_pef_section;
+
+#define BFD_PEF_SECTION_CODE 0
+#define BFD_PEF_SECTION_UNPACKED_DATA 1
+#define BFD_PEF_SECTION_PACKED_DATA 2
+#define BFD_PEF_SECTION_CONSTANT 3
+#define BFD_PEF_SECTION_LOADER 4
+#define BFD_PEF_SECTION_DEBUG 5
+#define BFD_PEF_SECTION_EXEC_DATA 6
+#define BFD_PEF_SECTION_EXCEPTION 7
+#define BFD_PEF_SECTION_TRACEBACK 8
+
+#define BFD_PEF_SHARE_PROCESS 1
+#define BFD_PEF_SHARE_GLOBAL 4
+#define BFD_PEF_SHARE_PROTECTED 5
+
+struct bfd_pef_data_struct
+{
+  bfd_pef_header header;
+  bfd_pef_section *sections;
+  bfd *ibfd;
+};
+typedef struct bfd_pef_data_struct bfd_pef_data_struct;
+
+#define BFD_PEF_XLIB_TAG1 0xF04D6163 /* '?Mac' */
+#define BFD_PEF_VLIB_TAG2 0x564C6962 /* 'VLib' */
+#define BFD_PEF_BLIB_TAG2 0x424C6962 /* 'BLib' */
+
+#define BFD_PEF_XLIB_VERSION 0x00000001
+
+struct bfd_pef_xlib_header
+{
+  unsigned long tag1;
+  unsigned long tag2;
+  unsigned long current_format;
+  unsigned long container_strings_offset;
+  unsigned long export_hash_offset;
+  unsigned long export_key_offset;
+  unsigned long export_symbol_offset;
+  unsigned long export_names_offset;
+  unsigned long export_hash_table_power;
+  unsigned long exported_symbol_count;
+
+  unsigned long frag_name_offset;
+  unsigned long frag_name_length;
+  unsigned long dylib_path_offset;
+  unsigned long dylib_path_length;
+  unsigned long cpu_family;
+  unsigned long cpu_model;
+  unsigned long date_time_stamp;
+  unsigned long current_version;
+  unsigned long old_definition_version;
+  unsigned long old_implementation_version;
+};
+typedef struct bfd_pef_xlib_header bfd_pef_xlib_header;
+
+struct bfd_pef_xlib_data_struct
+{
+  bfd_pef_xlib_header header;
+};
+typedef struct bfd_pef_xlib_data_struct bfd_pef_xlib_data_struct;
+
+int  bfd_pef_parse_loader_header    PARAMS ((bfd *, unsigned char *, size_t, bfd_pef_loader_header *));
+int  bfd_pef_print_loader_section   PARAMS ((bfd *, FILE *));
+void bfd_pef_print_loader_header    PARAMS ((bfd *, bfd_pef_loader_header *, FILE *));
+int  bfd_pef_parse_imported_library PARAMS ((bfd *, unsigned char *, size_t, bfd_pef_imported_library *));
+int  bfd_pef_parse_imported_symbol  PARAMS ((bfd *, unsigned char *, size_t, bfd_pef_imported_symbol *));
+int  bfd_pef_scan_section           PARAMS ((bfd *, bfd_pef_section *));
+int  bfd_pef_scan_start_address     PARAMS ((bfd *));
+int  bfd_pef_scan                   PARAMS ((bfd *, bfd_pef_header *));
index b9c86a1bdd5bb5927db5453371724837c0b0c346..6a68eaa13f0e2dab081a4ee6f399dd3748be7d39 100644 (file)
@@ -4,21 +4,21 @@
    Free Software Foundation, Inc.
    Written by Cygnus Support.
 
-This file is part of BFD, the Binary File Descriptor library.
+   This file is part of BFD, the Binary File Descriptor library.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "bfd.h"
 #include "sysdep.h"
@@ -155,7 +155,11 @@ DESCRIPTION
 .  bfd_target_msdos_flavour,
 .  bfd_target_ovax_flavour,
 .  bfd_target_evax_flavour,
-.  bfd_target_mmo_flavour
+.  bfd_target_mmo_flavour,
+.  bfd_target_mach_o_flavour,
+.  bfd_target_pef_flavour,
+.  bfd_target_pef_xlib_flavour,
+.  bfd_target_sym_flavour
 .};
 .
 .enum bfd_endian { BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN };
@@ -645,6 +649,9 @@ extern const bfd_target m68knetbsd_vec;
 extern const bfd_target m68ksysvcoff_vec;
 extern const bfd_target m88kbcs_vec;
 extern const bfd_target m88kmach3_vec;
+extern const bfd_target mach_o_be_vec;
+extern const bfd_target mach_o_le_vec;
+extern const bfd_target mach_o_fat_vec;
 extern const bfd_target mcore_pe_big_vec;
 extern const bfd_target mcore_pe_little_vec;
 extern const bfd_target mcore_pei_big_vec;
@@ -661,6 +668,8 @@ extern const bfd_target or32coff_big_vec;
 extern const bfd_target pc532machaout_vec;
 extern const bfd_target pc532netbsd_vec;
 extern const bfd_target pdp11_aout_vec;
+extern const bfd_target pef_vec;
+extern const bfd_target pef_xlib_vec;
 extern const bfd_target pmac_xcoff_vec;
 extern const bfd_target ppcboot_vec;
 extern const bfd_target riscix_vec;
@@ -680,6 +689,7 @@ extern const bfd_target sparclynx_aout_vec;
 extern const bfd_target sparclynx_coff_vec;
 extern const bfd_target sparcnetbsd_vec;
 extern const bfd_target sunos_big_vec;
+extern const bfd_target sym_vec;
 extern const bfd_target tic30_aout_vec;
 extern const bfd_target tic30_coff_vec;
 extern const bfd_target tic4x_coff0_beh_vec;
@@ -957,6 +967,9 @@ static const bfd_target * const _bfd_target_vector[] = {
        &m68ksysvcoff_vec,
        &m88kbcs_vec,
        &m88kmach3_vec,
+       &mach_o_be_vec,
+       &mach_o_le_vec,
+       &mach_o_fat_vec,
        &mcore_pe_big_vec,
        &mcore_pe_little_vec,
        &mcore_pei_big_vec,
@@ -984,6 +997,8 @@ static const bfd_target * const _bfd_target_vector[] = {
        &pc532machaout_vec,
        &pc532netbsd_vec,
        &pdp11_aout_vec,
+       &pef_vec,
+       &pef_xlib_vec,
 #if 0
        /* This has the same magic number as RS/6000.  */
        &pmac_xcoff_vec,
@@ -1013,6 +1028,7 @@ static const bfd_target * const _bfd_target_vector[] = {
        &sparclynx_coff_vec,
        &sparcnetbsd_vec,
        &sunos_big_vec,
+       &sym_vec,
        &tic30_aout_vec,
        &tic30_coff_vec,
        &tic54x_coff0_beh_vec,
diff --git a/bfd/xsym.c b/bfd/xsym.c
new file mode 100644 (file)
index 0000000..99b4eb7
--- /dev/null
@@ -0,0 +1,2449 @@
+/* xSYM symbol-file support for BFD.
+   Copyright 1999, 2000, 2001, 2002
+   Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software 
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include "xsym.h"
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+#define bfd_sym_close_and_cleanup _bfd_generic_close_and_cleanup
+#define bfd_sym_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
+#define bfd_sym_new_section_hook _bfd_generic_new_section_hook
+#define bfd_sym_bfd_is_local_label_name bfd_generic_is_local_label_name
+#define bfd_sym_get_lineno _bfd_nosymbols_get_lineno
+#define bfd_sym_find_nearest_line _bfd_nosymbols_find_nearest_line
+#define bfd_sym_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
+#define bfd_sym_read_minisymbols _bfd_generic_read_minisymbols
+#define bfd_sym_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
+#define bfd_sym_get_reloc_upper_bound _bfd_norelocs_get_reloc_upper_bound
+#define bfd_sym_canonicalize_reloc _bfd_norelocs_canonicalize_reloc
+#define bfd_sym_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
+#define bfd_sym_set_arch_mach _bfd_generic_set_arch_mach
+#define bfd_sym_get_section_contents _bfd_generic_get_section_contents
+#define bfd_sym_set_section_contents _bfd_generic_set_section_contents
+#define bfd_sym_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
+#define bfd_sym_bfd_relax_section bfd_generic_relax_section
+#define bfd_sym_bfd_gc_sections bfd_generic_gc_sections
+#define bfd_sym_bfd_merge_sections bfd_generic_merge_sections
+#define bfd_sym_bfd_discard_group bfd_generic_discard_group
+#define bfd_sym_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
+#define bfd_sym_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
+#define bfd_sym_bfd_link_add_symbols _bfd_generic_link_add_symbols
+#define bfd_sym_bfd_link_just_syms _bfd_generic_link_just_syms
+#define bfd_sym_bfd_final_link _bfd_generic_final_link
+#define bfd_sym_bfd_link_split_section _bfd_generic_link_split_section
+#define bfd_sym_get_section_contents_in_window  _bfd_generic_get_section_contents_in_window
+
+static int pstrcmp PARAMS ((unsigned char *, unsigned char *));
+static unsigned long compute_offset
+  PARAMS ((unsigned long, unsigned long, unsigned long, unsigned long));
+
+extern const bfd_target sym_vec;
+
+static int
+pstrcmp (a, b)
+     unsigned char *a;
+     unsigned char *b;
+{
+  unsigned char clen;
+  int ret;
+
+  clen = (a[0] > b[0]) ? a[0] : b[0];
+  ret = memcmp (a + 1, b + 1, clen);
+  if (ret != 0)
+    return ret;
+
+  if (a[0] == b[0])
+    return 0;
+  else if (a[0] < b[0])
+    return -1;
+  else
+    return 0;
+}
+
+static unsigned long
+compute_offset (first_page, page_size, entry_size, index)
+     unsigned long first_page;
+     unsigned long page_size;
+     unsigned long entry_size;
+     unsigned long index;
+{
+  unsigned long entries_per_page = page_size / entry_size;
+  unsigned long page_number = first_page + (index / entries_per_page);
+  unsigned long page_offset = (index % entries_per_page) * entry_size;
+
+  return (page_number * page_size) + page_offset;
+}
+
+boolean
+bfd_sym_mkobject (abfd)
+     bfd *abfd ATTRIBUTE_UNUSED;
+{
+  return (boolean) true;
+}
+
+void
+bfd_sym_print_symbol (abfd, afile, symbol, how)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     PTR afile ATTRIBUTE_UNUSED;
+     asymbol *symbol ATTRIBUTE_UNUSED;
+     bfd_print_symbol_type how ATTRIBUTE_UNUSED;
+{
+  return;
+}
+
+boolean
+bfd_sym_valid (abfd)
+     bfd *abfd;
+{
+  if (abfd == NULL || abfd->xvec == NULL)
+    return 0;
+
+  return (abfd->xvec == &sym_vec);
+}
+
+unsigned char *
+bfd_sym_read_name_table (abfd, dshb)
+     bfd *abfd;
+     bfd_sym_header_block *dshb;
+{
+  unsigned char *rstr;
+  long ret;
+  size_t table_size = dshb->dshb_nte.dti_page_count * dshb->dshb_page_size;
+  size_t table_offset = dshb->dshb_nte.dti_first_page * dshb->dshb_page_size;
+  
+  rstr = (unsigned char *) bfd_alloc (abfd, table_size);
+  if (rstr == NULL)
+    return rstr;
+
+  bfd_seek (abfd, table_offset, SEEK_SET);
+  ret = bfd_bread (rstr, table_size, abfd);
+  if ((ret < 0) || ((unsigned long) ret != table_size))
+    {
+      bfd_release (abfd, rstr);
+      return NULL;
+    }
+  
+  return rstr;
+}
+
+void
+bfd_sym_parse_file_reference_v32 (buf, len, entry)
+     unsigned char *buf;
+     size_t len;
+     bfd_sym_file_reference *entry;
+{
+  BFD_ASSERT (len == 6);
+
+  entry->fref_frte_index = bfd_getb16 (buf);
+  entry->fref_offset = bfd_getb32 (buf + 2);
+}
+
+void
+bfd_sym_parse_disk_table_v32 (buf, len, table)
+     unsigned char *buf;
+     size_t len;
+     bfd_sym_table_info *table;
+{
+  BFD_ASSERT (len == 8);
+  
+  table->dti_first_page = bfd_getb16 (buf);
+  table->dti_page_count = bfd_getb16 (buf + 2);
+  table->dti_object_count = bfd_getb32 (buf + 4);
+} 
+
+void
+bfd_sym_parse_header_v32 (buf, len, header)
+     unsigned char *buf;
+     size_t len;
+     bfd_sym_header_block *header;
+{
+  BFD_ASSERT (len == 154);
+  
+  memcpy (header->dshb_id, buf, 32);
+  header->dshb_page_size = bfd_getb16 (buf + 32);
+  header->dshb_hash_page = bfd_getb16 (buf + 34);
+  header->dshb_root_mte = bfd_getb16 (buf + 36);
+  header->dshb_mod_date = bfd_getb32 (buf + 38);
+  
+  bfd_sym_parse_disk_table_v32 (buf + 42, 8, &header->dshb_frte);
+  bfd_sym_parse_disk_table_v32 (buf + 50, 8, &header->dshb_rte);
+  bfd_sym_parse_disk_table_v32 (buf + 58, 8, &header->dshb_mte);
+  bfd_sym_parse_disk_table_v32 (buf + 66, 8, &header->dshb_cmte);
+  bfd_sym_parse_disk_table_v32 (buf + 74, 8, &header->dshb_cvte);
+  bfd_sym_parse_disk_table_v32 (buf + 82, 8, &header->dshb_csnte);
+  bfd_sym_parse_disk_table_v32 (buf + 90, 8, &header->dshb_clte);
+  bfd_sym_parse_disk_table_v32 (buf + 98, 8, &header->dshb_ctte);
+  bfd_sym_parse_disk_table_v32 (buf + 106, 8, &header->dshb_tte);
+  bfd_sym_parse_disk_table_v32 (buf + 114, 8, &header->dshb_nte);
+  bfd_sym_parse_disk_table_v32 (buf + 122, 8, &header->dshb_tinfo);
+  bfd_sym_parse_disk_table_v32 (buf + 130, 8, &header->dshb_fite);
+  bfd_sym_parse_disk_table_v32 (buf + 138, 8, &header->dshb_const);
+  
+  memcpy (&header->dshb_file_creator, buf + 146, 4);
+  memcpy (&header->dshb_file_type, buf + 150, 4);
+}
+
+int
+bfd_sym_read_header_v32 (abfd, header)
+     bfd *abfd;
+     bfd_sym_header_block *header;
+{
+  unsigned char buf[154];
+  long ret;
+  
+  ret = bfd_bread (buf, 154, abfd);
+  if (ret != 154)
+    return -1;
+  
+  bfd_sym_parse_header_v32 (buf, 154, header);
+  
+  return 0;
+}
+
+int
+bfd_sym_read_header_v34 (abfd, header)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     bfd_sym_header_block *header ATTRIBUTE_UNUSED;
+{
+  abort ();
+}
+
+int
+bfd_sym_read_header (abfd, header, version)
+     bfd *abfd;
+     bfd_sym_header_block *header;
+     bfd_sym_version version;
+{
+  switch (version)
+    {
+    case BFD_SYM_VERSION_3_5:
+    case BFD_SYM_VERSION_3_4:
+      return bfd_sym_read_header_v34 (abfd, header);
+    case BFD_SYM_VERSION_3_3:
+    case BFD_SYM_VERSION_3_2:
+      return bfd_sym_read_header_v32 (abfd, header);
+    case BFD_SYM_VERSION_3_1:
+    default:
+      return false;
+    }
+}
+
+int
+bfd_sym_read_version (abfd, version)
+     bfd *abfd;
+     bfd_sym_version *version;
+{
+  unsigned char version_string[32];
+  long ret;
+  
+  ret = bfd_bread (version_string, sizeof (version_string), abfd);
+  if (ret != sizeof (version_string))
+    return -1;
+  
+  if (pstrcmp (version_string, BFD_SYM_VERSION_STR_3_1) == 0)
+    *version = BFD_SYM_VERSION_3_1;
+  else if (pstrcmp (version_string, BFD_SYM_VERSION_STR_3_2) == 0)
+    *version = BFD_SYM_VERSION_3_2;
+  else if (pstrcmp (version_string, BFD_SYM_VERSION_STR_3_3) == 0)
+    *version = BFD_SYM_VERSION_3_3;
+  else if (pstrcmp (version_string, BFD_SYM_VERSION_STR_3_4) == 0)
+    *version = BFD_SYM_VERSION_3_4;
+  else if (pstrcmp (version_string, BFD_SYM_VERSION_STR_3_5) == 0)
+    *version = BFD_SYM_VERSION_3_5;
+  else
+    return -1;
+  
+  return 0;
+}
+
+void
+bfd_sym_display_table_summary (f, dti, name)
+     FILE *f;
+     bfd_sym_table_info *dti;
+     const char *name;
+{
+  fprintf (f, "%-6s %13ld %13ld %13ld\n",
+          name,
+          dti->dti_first_page,
+          dti->dti_page_count,
+          dti->dti_object_count);
+}
+
+void
+bfd_sym_display_header (f, dshb)
+     FILE *f;
+     bfd_sym_header_block *dshb;
+{
+  fprintf (f, "            Version: %.*s\n", dshb->dshb_id[0], dshb->dshb_id + 1);
+  fprintf (f, "          Page Size: 0x%x\n", dshb->dshb_page_size);
+  fprintf (f, "          Hash Page: %lu\n", dshb->dshb_hash_page);
+  fprintf (f, "           Root MTE: %lu\n", dshb->dshb_root_mte);
+  fprintf (f, "  Modification Date: ");
+  fprintf (f, "[unimplemented]");
+  fprintf (f, " (0x%lx)\n", dshb->dshb_mod_date);
+
+  fprintf (f, "       File Creator:  %.4s  Type: %.4s\n\n",
+          dshb->dshb_file_creator, dshb->dshb_file_type);
+  
+  fprintf (f, "Table Name   First Page    Page Count   Object Count\n");
+  fprintf (f, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
+  
+  bfd_sym_display_table_summary (f, &dshb->dshb_nte, "NTE");
+  bfd_sym_display_table_summary (f, &dshb->dshb_rte, "RTE");
+  bfd_sym_display_table_summary (f, &dshb->dshb_mte, "MTE");
+  bfd_sym_display_table_summary (f, &dshb->dshb_frte, "FRTE");
+  bfd_sym_display_table_summary (f, &dshb->dshb_cmte, "CMTE");
+  bfd_sym_display_table_summary (f, &dshb->dshb_cvte, "CVTE");
+  bfd_sym_display_table_summary (f, &dshb->dshb_csnte, "CSNTE");
+  bfd_sym_display_table_summary (f, &dshb->dshb_clte, "CLTE");
+  bfd_sym_display_table_summary (f, &dshb->dshb_ctte, "CTTE");
+  bfd_sym_display_table_summary (f, &dshb->dshb_tte, "TTE");
+  bfd_sym_display_table_summary (f, &dshb->dshb_tinfo, "TINFO");
+  bfd_sym_display_table_summary (f, &dshb->dshb_fite, "FITE");
+  bfd_sym_display_table_summary (f, &dshb->dshb_const, "CONST");
+  
+  fprintf (f, "\n");
+}
+
+void
+bfd_sym_parse_resources_table_entry_v32 (buf, len, entry)
+     unsigned char *buf;
+     size_t len;
+     bfd_sym_resources_table_entry *entry;
+{
+  BFD_ASSERT (len == 18);
+
+  memcpy (&entry->rte_res_type, buf, 4);
+  entry->rte_res_number = bfd_getb16 (buf + 4);
+  entry->rte_nte_index = bfd_getb32 (buf + 6);
+  entry->rte_mte_first = bfd_getb16 (buf + 10);
+  entry->rte_mte_last = bfd_getb16 (buf + 12);
+  entry->rte_res_size = bfd_getb32 (buf + 14);
+}
+
+void
+bfd_sym_parse_modules_table_entry_v33 (buf, len, entry)
+     unsigned char *buf;
+     size_t len;
+     bfd_sym_modules_table_entry *entry;
+{
+  BFD_ASSERT (len == 46);
+
+  entry->mte_rte_index = bfd_getb16 (buf);
+  entry->mte_res_offset = bfd_getb32 (buf + 2);
+  entry->mte_size = bfd_getb32 (buf + 6);
+  entry->mte_kind = buf[10];
+  entry->mte_scope = buf[11];
+  entry->mte_parent = bfd_getb16 (buf + 12);
+  bfd_sym_parse_file_reference_v32 (buf + 14, 6, &entry->mte_imp_fref);
+  entry->mte_imp_end = bfd_getb32 (buf + 20);
+  entry->mte_nte_index = bfd_getb32 (buf + 24);
+  entry->mte_cmte_index = bfd_getb16 (buf + 28);
+  entry->mte_cvte_index = bfd_getb32 (buf + 30);
+  entry->mte_clte_index = bfd_getb16 (buf + 34);
+  entry->mte_ctte_index = bfd_getb16 (buf + 36);
+  entry->mte_csnte_idx_1 = bfd_getb32 (buf + 38);
+  entry->mte_csnte_idx_2 = bfd_getb32 (buf + 42);
+}
+
+void
+bfd_sym_parse_file_references_table_entry_v32 (buf, len, entry)
+     unsigned char *buf;
+     size_t len;
+     bfd_sym_file_references_table_entry *entry;
+{
+  unsigned int type;
+  
+  BFD_ASSERT (len == 10);
+
+  memset (entry, 0, sizeof (bfd_sym_file_references_table_entry));
+  type = bfd_getb16 (buf);
+
+  switch (type)
+    {
+    case BFD_SYM_END_OF_LIST_3_2:
+      entry->generic.type = BFD_SYM_END_OF_LIST;
+      break;
+
+    case BFD_SYM_FILE_NAME_INDEX_3_2:
+      entry->filename.type = BFD_SYM_FILE_NAME_INDEX;
+      entry->filename.nte_index = bfd_getb32 (buf + 2);
+      entry->filename.mod_date = bfd_getb32 (buf + 6);
+      break;
+
+    default:
+      entry->entry.mte_index = type;
+      entry->entry.file_offset = bfd_getb32 (buf + 2);
+    }
+}
+
+void
+bfd_sym_parse_contained_modules_table_entry_v32 (buf, len, entry)
+     unsigned char *buf;
+     size_t len;
+     bfd_sym_contained_modules_table_entry *entry;
+{
+  unsigned int type;
+
+  BFD_ASSERT (len == 6);
+
+  memset (entry, 0, sizeof (bfd_sym_contained_modules_table_entry));
+  type = bfd_getb16 (buf);
+  
+  switch (type)
+    {
+    case BFD_SYM_END_OF_LIST_3_2:
+      entry->generic.type = BFD_SYM_END_OF_LIST;
+      break;
+
+    default:
+      entry->entry.mte_index = type;
+      entry->entry.nte_index = bfd_getb32 (buf + 2);
+      break;
+    }
+}
+
+void
+bfd_sym_parse_contained_variables_table_entry_v32 (buf, len, entry)
+     unsigned char *buf;
+     size_t len;
+     bfd_sym_contained_variables_table_entry *entry;
+{
+  unsigned int type;
+  
+  BFD_ASSERT (len == 26);
+
+  memset (entry, 0, sizeof (bfd_sym_contained_variables_table_entry));
+  type = bfd_getb16 (buf);
+
+  switch (type)
+    {
+    case BFD_SYM_END_OF_LIST_3_2:
+      entry->generic.type = BFD_SYM_END_OF_LIST;
+      break;
+
+    case BFD_SYM_SOURCE_FILE_CHANGE_3_2:
+      entry->file.type = BFD_SYM_SOURCE_FILE_CHANGE;
+      bfd_sym_parse_file_reference_v32 (buf + 2, 6, &entry->file.fref);
+      break;
+
+    default:
+      entry->entry.tte_index = type;
+      entry->entry.nte_index = bfd_getb32 (buf + 2);
+      entry->entry.file_delta = bfd_getb16 (buf + 6);
+      entry->entry.scope = buf[8];
+      entry->entry.la_size = buf[9];
+
+      if (entry->entry.la_size == BFD_SYM_CVTE_SCA)
+       {
+         entry->entry.address.scstruct.sca_kind = buf[10];
+         entry->entry.address.scstruct.sca_class = buf[11];
+         entry->entry.address.scstruct.sca_offset = bfd_getb32 (buf + 12);
+       }
+      else if (entry->entry.la_size <= BFD_SYM_CVTE_SCA)
+       {
+         memcpy (&entry->entry.address.lastruct.la, buf + 10, BFD_SYM_CVTE_SCA);
+         entry->entry.address.lastruct.la_kind = buf[23];
+       }
+      else if (entry->entry.la_size == BFD_SYM_CVTE_BIG_LA)
+       {
+         entry->entry.address.biglastruct.big_la = bfd_getb32 (buf + 10);
+         entry->entry.address.biglastruct.big_la_kind = buf[12];
+       }
+    }
+}
+
+void
+bfd_sym_parse_contained_statements_table_entry_v32 (buf, len, entry)
+     unsigned char *buf;
+     size_t len;
+     bfd_sym_contained_statements_table_entry *entry;
+{
+  unsigned int type;
+
+  BFD_ASSERT (len == 8);
+
+  memset (entry, 0, sizeof (bfd_sym_contained_statements_table_entry));
+  type = bfd_getb16 (buf);
+  
+  switch (type)
+    {
+    case BFD_SYM_END_OF_LIST_3_2:
+      entry->generic.type = BFD_SYM_END_OF_LIST;
+      break;
+
+    case BFD_SYM_SOURCE_FILE_CHANGE_3_2:
+      entry->file.type = BFD_SYM_SOURCE_FILE_CHANGE;
+      bfd_sym_parse_file_reference_v32 (buf + 2, 6, &entry->file.fref);
+      break;
+
+    default:
+      entry->entry.mte_index = type;
+      entry->entry.mte_offset = bfd_getb16 (buf + 2);
+      entry->entry.file_delta = bfd_getb32 (buf + 4);
+      break;
+    }
+}
+
+void
+bfd_sym_parse_contained_labels_table_entry_v32 (buf, len, entry)
+     unsigned char *buf;
+     size_t len;
+     bfd_sym_contained_labels_table_entry *entry;
+{
+  unsigned int type;
+
+  BFD_ASSERT (len == 12);
+
+  memset (entry, 0, sizeof (bfd_sym_contained_labels_table_entry));
+  type = bfd_getb16 (buf);
+  
+  switch (type)
+    {
+    case BFD_SYM_END_OF_LIST_3_2:
+      entry->generic.type = BFD_SYM_END_OF_LIST;
+      break;
+
+    case BFD_SYM_SOURCE_FILE_CHANGE_3_2:
+      entry->file.type = BFD_SYM_SOURCE_FILE_CHANGE;
+      bfd_sym_parse_file_reference_v32 (buf + 2, 6, &entry->file.fref);
+      break;
+
+    default:
+      entry->entry.mte_index = type;
+      entry->entry.mte_offset = bfd_getb16 (buf + 2);
+      entry->entry.nte_index = bfd_getb32 (buf + 4);
+      entry->entry.file_delta = bfd_getb16 (buf + 8);
+      entry->entry.scope = bfd_getb16 (buf + 10);
+      break;
+    }
+}
+
+void
+bfd_sym_parse_type_table_entry_v32 (buf, len, entry)
+     unsigned char *buf;
+     size_t len;
+     bfd_sym_type_table_entry *entry;
+{
+  BFD_ASSERT (len == 4);
+  
+  *entry = bfd_getb32 (buf);
+}
+
+int
+bfd_sym_fetch_resources_table_entry (abfd, entry, index)
+     bfd *abfd;
+     bfd_sym_resources_table_entry *entry;
+     unsigned long index;
+{
+  void (*parser) (unsigned char *, size_t, bfd_sym_resources_table_entry *) = NULL;  
+  unsigned long offset;
+  unsigned long entry_size;
+  unsigned char buf[18];
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+
+  if (index == 0)
+    return -1;
+
+  switch (sdata->version)
+    {
+    case BFD_SYM_VERSION_3_5:
+    case BFD_SYM_VERSION_3_4:
+      return -1;
+
+    case BFD_SYM_VERSION_3_3:
+    case BFD_SYM_VERSION_3_2:
+      entry_size = 18;
+      parser = bfd_sym_parse_resources_table_entry_v32;
+      break;
+
+    case BFD_SYM_VERSION_3_1:
+    default:
+      return -1;
+    }
+  if (parser == NULL)
+    return -1;
+
+  offset = compute_offset (sdata->header.dshb_rte.dti_first_page,
+                          sdata->header.dshb_page_size,
+                          entry_size, index);
+  
+  if (bfd_seek (abfd, offset, SEEK_SET) < 0)
+    return -1;
+  if (bfd_bread (buf, entry_size, abfd) != entry_size)
+    return -1;
+
+  (*parser) (buf, entry_size, entry);
+  
+  return 0;
+}
+
+int
+bfd_sym_fetch_modules_table_entry (abfd, entry, index)
+     bfd *abfd;
+     bfd_sym_modules_table_entry *entry;
+     unsigned long index;
+{
+  void (*parser) (unsigned char *, size_t, bfd_sym_modules_table_entry *) = NULL;  
+  unsigned long offset;
+  unsigned long entry_size;
+  unsigned char buf[46];
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+
+  if (index == 0)
+    return -1;
+
+  switch (sdata->version)
+    {
+    case BFD_SYM_VERSION_3_5:
+    case BFD_SYM_VERSION_3_4:
+      return -1;
+
+    case BFD_SYM_VERSION_3_3:
+      entry_size = 46;
+      parser = bfd_sym_parse_modules_table_entry_v33;
+      break;
+
+    case BFD_SYM_VERSION_3_2:
+    case BFD_SYM_VERSION_3_1:
+    default:
+      return -1;
+    }
+  if (parser == NULL)
+    return -1;
+
+  offset = compute_offset (sdata->header.dshb_mte.dti_first_page,
+                          sdata->header.dshb_page_size,
+                          entry_size, index);
+  
+  if (bfd_seek (abfd, offset, SEEK_SET) < 0)
+    return -1;
+  if (bfd_bread (buf, entry_size, abfd) != entry_size)
+    return -1;
+
+  (*parser) (buf, entry_size, entry);
+  
+  return 0;
+}
+
+int
+bfd_sym_fetch_file_references_table_entry (abfd, entry, index)
+     bfd *abfd;
+     bfd_sym_file_references_table_entry *entry;
+     unsigned long index;
+{
+  void (*parser) (unsigned char *, size_t, bfd_sym_file_references_table_entry *) = NULL;  
+  unsigned long offset;
+  unsigned long entry_size = 0;
+  unsigned char buf[8];
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+
+  if (index == 0)
+    return -1;
+
+  switch (sdata->version)
+    {
+    case BFD_SYM_VERSION_3_3:
+    case BFD_SYM_VERSION_3_2:
+      entry_size = 10;
+      parser = bfd_sym_parse_file_references_table_entry_v32;
+      break;
+
+    case BFD_SYM_VERSION_3_5:
+    case BFD_SYM_VERSION_3_4:
+    case BFD_SYM_VERSION_3_1:
+    default:
+      break;
+    }
+
+  if (parser == NULL)
+    return -1;
+
+  offset = compute_offset (sdata->header.dshb_frte.dti_first_page,
+                          sdata->header.dshb_page_size,
+                          entry_size, index);
+  
+  if (bfd_seek (abfd, offset, SEEK_SET) < 0)
+    return -1;
+  if (bfd_bread (buf, entry_size, abfd) != entry_size)
+    return -1;
+
+  (*parser) (buf, entry_size, entry);
+  
+  return 0;
+}
+
+int
+bfd_sym_fetch_contained_modules_table_entry (abfd, entry, index)
+     bfd *abfd;
+     bfd_sym_contained_modules_table_entry *entry;
+     unsigned long index;
+{
+  void (*parser) (unsigned char *, size_t, bfd_sym_contained_modules_table_entry *) = NULL;
+  unsigned long offset;
+  unsigned long entry_size = 0;
+  unsigned char buf[6];
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+
+  if (index == 0)
+    return -1;
+
+  switch (sdata->version)
+    {
+    case BFD_SYM_VERSION_3_3:
+    case BFD_SYM_VERSION_3_2:
+      entry_size = 6;
+      parser = bfd_sym_parse_contained_modules_table_entry_v32;
+      break;
+
+    case BFD_SYM_VERSION_3_5:
+    case BFD_SYM_VERSION_3_4:
+    case BFD_SYM_VERSION_3_1:
+    default:
+      break;
+    }
+
+  if (parser == NULL)
+    return -1;
+
+  offset = compute_offset (sdata->header.dshb_cmte.dti_first_page,
+                          sdata->header.dshb_page_size,
+                          entry_size, index);
+  if (bfd_seek (abfd, offset, SEEK_SET) < 0)
+    return -1;
+  if (bfd_bread (buf, entry_size, abfd) != entry_size)
+    return -1;
+
+  (*parser) (buf, entry_size, entry);
+  
+  return 0;
+}
+
+int
+bfd_sym_fetch_contained_variables_table_entry (abfd, entry, index)
+     bfd *abfd;
+     bfd_sym_contained_variables_table_entry *entry;
+     unsigned long index;
+{
+  void (*parser) (unsigned char *, size_t, bfd_sym_contained_variables_table_entry *) = NULL;
+  unsigned long offset;
+  unsigned long entry_size = 0;
+  unsigned char buf[26];
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+
+  if (index == 0)
+    return -1;
+
+  switch (sdata->version)
+    {
+    case BFD_SYM_VERSION_3_3:
+    case BFD_SYM_VERSION_3_2:
+      entry_size = 26;
+      parser = bfd_sym_parse_contained_variables_table_entry_v32;
+      break;
+
+    case BFD_SYM_VERSION_3_5:
+    case BFD_SYM_VERSION_3_4:
+    case BFD_SYM_VERSION_3_1:
+    default:
+      break;
+    }
+
+  if (parser == NULL)
+    return -1;
+
+  offset = compute_offset (sdata->header.dshb_cvte.dti_first_page,
+                          sdata->header.dshb_page_size,
+                          entry_size, index);
+  
+  if (bfd_seek (abfd, offset, SEEK_SET) < 0)
+    return -1;
+  if (bfd_bread (buf, entry_size, abfd) != entry_size)
+    return -1;
+
+  (*parser) (buf, entry_size, entry);
+  
+  return 0;
+}
+
+int
+bfd_sym_fetch_contained_statements_table_entry (abfd, entry, index)
+     bfd *abfd;
+     bfd_sym_contained_statements_table_entry *entry;
+     unsigned long index;
+{
+  void (*parser) (unsigned char *, size_t, bfd_sym_contained_statements_table_entry *) = NULL;  
+  unsigned long offset;
+  unsigned long entry_size = 0;
+  unsigned char buf[8];
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+
+  if (index == 0)
+    return -1;
+
+  switch (sdata->version)
+    {
+    case BFD_SYM_VERSION_3_3:
+    case BFD_SYM_VERSION_3_2:
+      entry_size = 8;
+      parser = bfd_sym_parse_contained_statements_table_entry_v32;
+      break;
+
+    case BFD_SYM_VERSION_3_5:
+    case BFD_SYM_VERSION_3_4:
+    case BFD_SYM_VERSION_3_1:
+    default:
+      break;
+    }
+
+  if (parser == NULL)
+    return -1;
+
+  offset = compute_offset (sdata->header.dshb_csnte.dti_first_page,
+                          sdata->header.dshb_page_size,
+                          entry_size, index);
+  
+  if (bfd_seek (abfd, offset, SEEK_SET) < 0)
+    return -1;
+  if (bfd_bread (buf, entry_size, abfd) != entry_size)
+    return -1;
+
+  (*parser) (buf, entry_size, entry);
+  
+  return 0;
+}
+
+int
+bfd_sym_fetch_contained_labels_table_entry (abfd, entry, index)
+     bfd *abfd;
+     bfd_sym_contained_labels_table_entry *entry;
+     unsigned long index;
+{
+  void (*parser) (unsigned char *, size_t, bfd_sym_contained_labels_table_entry *) = NULL;  
+  unsigned long offset;
+  unsigned long entry_size = 0;
+  unsigned char buf[12];
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+
+  if (index == 0)
+    return -1;
+
+  switch (sdata->version)
+    {
+    case BFD_SYM_VERSION_3_3:
+    case BFD_SYM_VERSION_3_2:
+      entry_size = 12;
+      parser = bfd_sym_parse_contained_labels_table_entry_v32;
+      break;
+
+    case BFD_SYM_VERSION_3_5:
+    case BFD_SYM_VERSION_3_4:
+    case BFD_SYM_VERSION_3_1:
+    default:
+      break;
+    }
+
+  if (parser == NULL)
+    return -1;
+
+  offset = compute_offset (sdata->header.dshb_clte.dti_first_page,
+                          sdata->header.dshb_page_size,
+                          entry_size, index);
+  
+  if (bfd_seek (abfd, offset, SEEK_SET) < 0)
+    return -1;
+  if (bfd_bread (buf, entry_size, abfd) != entry_size)
+    return -1;
+
+  (*parser) (buf, entry_size, entry);
+  
+  return 0;
+}
+
+int
+bfd_sym_fetch_contained_types_table_entry (abfd, entry, index)
+     bfd *abfd;
+     bfd_sym_contained_types_table_entry *entry;
+     unsigned long index;
+{
+  void (*parser) (unsigned char *, size_t, bfd_sym_contained_types_table_entry *) = NULL;  
+  unsigned long offset;
+  unsigned long entry_size = 0;
+  unsigned char buf[0];
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+
+  if (index == 0)
+    return -1;
+
+  switch (sdata->version)
+    {
+    case BFD_SYM_VERSION_3_3:
+    case BFD_SYM_VERSION_3_2:
+      entry_size = 0;
+      parser = NULL;
+      break;
+
+    case BFD_SYM_VERSION_3_5:
+    case BFD_SYM_VERSION_3_4:
+    case BFD_SYM_VERSION_3_1:
+    default:
+      break;
+    }
+
+  if (parser == NULL)
+    return -1;
+
+  offset = compute_offset (sdata->header.dshb_ctte.dti_first_page,
+                          sdata->header.dshb_page_size,
+                          entry_size, index);
+  
+  if (bfd_seek (abfd, offset, SEEK_SET) < 0)
+    return -1;
+  if (bfd_bread (buf, entry_size, abfd) != entry_size)
+    return -1;
+
+  (*parser) (buf, entry_size, entry);
+  
+  return 0;
+}
+
+int
+bfd_sym_fetch_file_references_index_table_entry (abfd, entry, index)
+     bfd *abfd;
+     bfd_sym_file_references_index_table_entry *entry;
+     unsigned long index;
+{
+  void (*parser) (unsigned char *, size_t, bfd_sym_file_references_index_table_entry *) = NULL;  
+  unsigned long offset;
+  unsigned long entry_size = 0;
+  unsigned char buf[0];
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+
+  if (index == 0)
+    return -1;
+
+  switch (sdata->version)
+    {
+    case BFD_SYM_VERSION_3_3:
+    case BFD_SYM_VERSION_3_2:
+      entry_size = 0;
+      parser = NULL;
+      break;
+
+    case BFD_SYM_VERSION_3_5:
+    case BFD_SYM_VERSION_3_4:
+    case BFD_SYM_VERSION_3_1:
+    default:
+      break;
+    }
+
+  if (parser == NULL)
+    return -1;
+
+  offset = compute_offset (sdata->header.dshb_fite.dti_first_page,
+                          sdata->header.dshb_page_size,
+                          entry_size, index);
+  
+  if (bfd_seek (abfd, offset, SEEK_SET) < 0)
+    return -1;
+  if (bfd_bread (buf, entry_size, abfd) != entry_size)
+    return -1;
+
+  (*parser) (buf, entry_size, entry);
+  
+  return 0;
+}
+
+int
+bfd_sym_fetch_constant_pool_entry (abfd, entry, index)
+     bfd *abfd;
+     bfd_sym_constant_pool_entry *entry;
+     unsigned long index;
+{
+  void (*parser) (unsigned char *, size_t, bfd_sym_constant_pool_entry *) = NULL;  
+  unsigned long offset;
+  unsigned long entry_size = 0;
+  unsigned char buf[0];
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+
+  if (index == 0)
+    return -1;
+
+  switch (sdata->version)
+    {
+    case BFD_SYM_VERSION_3_3:
+    case BFD_SYM_VERSION_3_2:
+      entry_size = 0;
+      parser = NULL;
+      break;
+
+    case BFD_SYM_VERSION_3_5:
+    case BFD_SYM_VERSION_3_4:
+    case BFD_SYM_VERSION_3_1:
+    default:
+      break;
+    }
+
+  if (parser == NULL)
+    return -1;
+
+  offset = compute_offset (sdata->header.dshb_fite.dti_first_page,
+                          sdata->header.dshb_page_size,
+                          entry_size, index);
+  
+  if (bfd_seek (abfd, offset, SEEK_SET) < 0)
+    return -1;
+  if (bfd_bread (buf, entry_size, abfd) != entry_size)
+    return -1;
+
+  (*parser) (buf, entry_size, entry);
+  
+  return 0;
+}
+
+int
+bfd_sym_fetch_type_table_entry (abfd, entry, index)
+     bfd *abfd;
+     bfd_sym_type_table_entry *entry;
+     unsigned long index;
+{
+  void (*parser) (unsigned char *, size_t, bfd_sym_type_table_entry *) = NULL;  
+  unsigned long offset;
+  unsigned long entry_size = 0;
+  unsigned char buf[4];
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+
+  switch (sdata->version)
+    {
+    case BFD_SYM_VERSION_3_3:
+    case BFD_SYM_VERSION_3_2:
+      entry_size = 4;
+      parser = bfd_sym_parse_type_table_entry_v32;
+      break;
+
+    case BFD_SYM_VERSION_3_5:
+    case BFD_SYM_VERSION_3_4:
+    case BFD_SYM_VERSION_3_1:
+    default:
+      break;
+    }
+
+  if (parser == NULL)
+    return -1;
+
+  offset = compute_offset (sdata->header.dshb_tte.dti_first_page,
+                          sdata->header.dshb_page_size,
+                          entry_size, index);
+  
+  if (bfd_seek (abfd, offset, SEEK_SET) < 0)
+    return -1;
+  if (bfd_bread (buf, entry_size, abfd) != entry_size)
+    return -1;
+
+  (*parser) (buf, entry_size, entry);
+  
+  return 0;
+}
+
+int
+bfd_sym_fetch_type_information_table_entry (abfd, entry, offset)
+     bfd *abfd;
+     bfd_sym_type_information_table_entry *entry;
+     unsigned long offset;
+{
+  unsigned char buf[4];
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+
+  if (index == 0)
+    return -1;
+
+  if (bfd_seek (abfd, offset, SEEK_SET) < 0)
+    return -1;
+
+  if (bfd_bread (buf, 4, abfd) != 4)
+    return -1;
+  entry->nte_index = bfd_getb32 (buf);
+  
+  if (bfd_bread (buf, 2, abfd) != 2)
+    return -1;
+  entry->physical_size = bfd_getb16 (buf);
+  
+  if (entry->physical_size & 0x8000)
+    {
+      if (bfd_bread (buf, 4, abfd) != 4)
+       return -1;
+      entry->physical_size &= 0x7fff;
+      entry->logical_size = bfd_getb32 (buf);
+      entry->offset = offset + 10;
+    }
+  else
+    {
+      if (bfd_bread (buf, 2, abfd) != 2)
+       return -1;
+      entry->physical_size &= 0x7fff;
+      entry->logical_size = bfd_getb16 (buf);
+      entry->offset = offset + 8;
+    }
+
+  return 0;
+}
+
+int
+bfd_sym_fetch_type_table_information (abfd, entry, index)
+     bfd *abfd;
+     bfd_sym_type_information_table_entry *entry;
+     unsigned long index;
+{
+  bfd_sym_type_table_entry tindex;
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+
+  if (sdata->header.dshb_tte.dti_object_count <= 99)
+    return -1;
+  if (index < 100)
+    return -1;
+
+  if (bfd_sym_fetch_type_table_entry (abfd, &tindex, index - 100) < 0)
+    return -1;
+  if (bfd_sym_fetch_type_information_table_entry (abfd, entry, tindex) < 0)
+    return -1;
+
+  return 0;
+}
+
+const unsigned char *
+bfd_sym_symbol_name (abfd, index)
+     bfd *abfd;
+     unsigned long index;
+{
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+
+  if (index == 0)
+    return "";
+  
+  index *= 2;
+  if ((index / sdata->header.dshb_page_size) > sdata->header.dshb_nte.dti_page_count)
+    return "\009[INVALID]";
+  
+  return ((const unsigned char *) sdata->name_table + index);
+}
+
+const unsigned char *
+bfd_sym_module_name (abfd, index)
+     bfd *abfd;
+     unsigned long index;
+{
+  bfd_sym_modules_table_entry entry;
+  
+  if (bfd_sym_fetch_modules_table_entry (abfd, &entry, index) < 0)
+    return "\011[INVALID]";
+
+  return bfd_sym_symbol_name (abfd, entry.mte_nte_index);
+}
+
+const char *
+bfd_sym_unparse_storage_kind (kind)
+     enum bfd_sym_storage_kind kind;
+{
+  switch (kind)
+    {
+    case BFD_SYM_STORAGE_KIND_LOCAL: return "LOCAL";
+    case BFD_SYM_STORAGE_KIND_VALUE: return "VALUE";
+    case BFD_SYM_STORAGE_KIND_REFERENCE: return "REFERENCE";
+    case BFD_SYM_STORAGE_KIND_WITH: return "WITH";
+    default: return "[UNKNOWN]";
+    }
+}
+
+const char *
+bfd_sym_unparse_storage_class (kind)
+     enum bfd_sym_storage_class kind;
+{
+  switch (kind)
+    {
+    case BFD_SYM_STORAGE_CLASS_REGISTER: return "REGISTER";
+    case BFD_SYM_STORAGE_CLASS_GLOBAL: return "GLOBAL";
+    case BFD_SYM_STORAGE_CLASS_FRAME_RELATIVE: return "FRAME_RELATIVE";
+    case BFD_SYM_STORAGE_CLASS_STACK_RELATIVE: return "STACK_RELATIVE";
+    case BFD_SYM_STORAGE_CLASS_ABSOLUTE: return "ABSOLUTE";
+    case BFD_SYM_STORAGE_CLASS_CONSTANT: return "CONSTANT";
+    case BFD_SYM_STORAGE_CLASS_RESOURCE: return "RESOURCE";
+    case BFD_SYM_STORAGE_CLASS_BIGCONSTANT: return "BIGCONSTANT";
+    default: return "[UNKNOWN]";
+    }
+}
+
+const char *
+bfd_sym_unparse_module_kind (kind)
+     enum bfd_sym_module_kind kind;
+{
+  switch (kind)
+    {
+    case BFD_SYM_MODULE_KIND_NONE: return "NONE";
+    case BFD_SYM_MODULE_KIND_PROGRAM: return "PROGRAM";
+    case BFD_SYM_MODULE_KIND_UNIT: return "UNIT";
+    case BFD_SYM_MODULE_KIND_PROCEDURE: return "PROCEDURE";
+    case BFD_SYM_MODULE_KIND_FUNCTION: return "FUNCTION";
+    case BFD_SYM_MODULE_KIND_DATA: return "DATA";
+    case BFD_SYM_MODULE_KIND_BLOCK: return "BLOCK";
+    default: return "[UNKNOWN]";
+    }
+}
+
+const char *
+bfd_sym_unparse_symbol_scope (scope)
+     enum bfd_sym_symbol_scope scope;
+{
+  switch (scope)
+    {
+    case BFD_SYM_SYMBOL_SCOPE_LOCAL: return "LOCAL";
+    case BFD_SYM_SYMBOL_SCOPE_GLOBAL: return "GLOBAL";
+    default:
+      return "[UNKNOWN]";
+    }
+}
+
+void
+bfd_sym_print_file_reference (abfd, f, entry)
+     bfd *abfd;
+     FILE *f;
+     bfd_sym_file_reference *entry;
+{
+  bfd_sym_file_references_table_entry frtentry;
+  int ret;
+
+  ret = bfd_sym_fetch_file_references_table_entry (abfd, &frtentry, entry->fref_frte_index);
+  fprintf (f, "FILE ");
+
+  if ((ret < 0) || (frtentry.generic.type != BFD_SYM_FILE_NAME_INDEX))
+    fprintf (f, "[INVALID]");
+  else
+    fprintf (f, "\"%.*s\"",
+            bfd_sym_symbol_name (abfd, frtentry.filename.nte_index)[0],
+            &bfd_sym_symbol_name (abfd, frtentry.filename.nte_index)[1]);
+
+  fprintf (f, " (FRTE %lu)", entry->fref_frte_index);
+}
+
+void
+bfd_sym_print_resources_table_entry (abfd, f, entry)
+     bfd *abfd;
+     FILE *f;
+     bfd_sym_resources_table_entry *entry;
+{
+  fprintf (f, " \"%.*s\" (NTE %lu), type \"%.4s\", num %u, size %lu, MTE %lu -- %lu",
+          bfd_sym_symbol_name (abfd, entry->rte_nte_index)[0],
+          &bfd_sym_symbol_name (abfd, entry->rte_nte_index)[1],
+          entry->rte_nte_index, entry->rte_res_type, entry->rte_res_number,
+          entry->rte_res_size, entry->rte_mte_first, entry->rte_mte_last);
+}  
+
+void
+bfd_sym_print_modules_table_entry (abfd, f, entry)
+     bfd *abfd;
+     FILE *f;
+     bfd_sym_modules_table_entry *entry;
+{
+  fprintf (f, "\"%.*s\" (NTE %lu)",
+          bfd_sym_symbol_name (abfd, entry->mte_nte_index)[0],
+          &bfd_sym_symbol_name (abfd, entry->mte_nte_index)[1],
+          entry->mte_nte_index);
+  
+  fprintf (f, "\n            ");          
+
+  bfd_sym_print_file_reference (abfd, f, &entry->mte_imp_fref);
+  fprintf (f, " range %lu -- %lu", entry->mte_imp_fref.fref_offset, entry->mte_imp_end);
+
+  fprintf (f, "\n            ");          
+
+  fprintf (f, "kind %s", bfd_sym_unparse_module_kind (entry->mte_kind));
+  fprintf (f, ", scope %s", bfd_sym_unparse_symbol_scope (entry->mte_scope));
+  
+  fprintf (f, ", RTE %lu, offset %lu, size %lu",
+          entry->mte_rte_index, entry->mte_res_offset, entry->mte_size);
+
+  fprintf (f, "\n            ");          
+
+  fprintf (f, "CMTE %lu, CVTE %lu, CLTE %lu, CTTE %lu, CSNTE1 %lu, CSNTE2 %lu", 
+          entry->mte_cmte_index, entry->mte_cvte_index,
+          entry->mte_clte_index, entry->mte_ctte_index,
+          entry->mte_csnte_idx_1, entry->mte_csnte_idx_2);
+  
+  if (entry->mte_parent != 0)
+    fprintf (f, ", parent %lu", entry->mte_parent);
+  else
+    fprintf (f, ", no parent");
+
+  if (entry->mte_cmte_index != 0)
+    fprintf (f, ", child %lu", entry->mte_cmte_index);
+  else
+    fprintf (f, ", no child");
+
+#if 0
+  {
+    MTE bfd_sym_modules_table_entry pentry;
+
+    ret = bfd_sym_fetch_modules_table_entry (abfd, &pentry, entry->mte_parent);
+    if (ret < 0)
+      fprintf (f, " parent MTE %lu [INVALID]\n", entry->mte_parent);
+    else
+      fprintf (f, " parent MTE %lu \"%.*s\"\n",
+              entry->mte_parent,
+              bfd_sym_symbol_name (abfd, pentry.mte_nte_index)[0],
+              &bfd_sym_symbol_name (abfd, pentry.mte_nte_index)[1]);
+  }
+#endif
+}
+
+void
+bfd_sym_print_file_references_table_entry (abfd, f, entry)
+     bfd *abfd;
+     FILE *f;
+     bfd_sym_file_references_table_entry *entry;
+{
+  switch (entry->generic.type)
+    {
+    case BFD_SYM_FILE_NAME_INDEX:
+      fprintf (f, "FILE \"%.*s\" (NTE %lu), modtime ", 
+              bfd_sym_symbol_name (abfd, entry->filename.nte_index)[0],
+              &bfd_sym_symbol_name (abfd, entry->filename.nte_index)[1],
+              entry->filename.nte_index);
+
+      fprintf (f, "[UNIMPLEMENTED]");
+      /* printModDate (entry->filename.mod_date); */
+      fprintf (f, " (0x%lx)", entry->filename.mod_date);
+      break;
+
+    case BFD_SYM_END_OF_LIST:
+      fprintf (f, "END");
+      break;
+
+    default:
+      fprintf (f, "\"%.*s\" (MTE %lu), offset %lu",
+              bfd_sym_module_name (abfd, entry->entry.mte_index)[0],
+              &bfd_sym_module_name (abfd, entry->entry.mte_index)[1],
+              entry->entry.mte_index,
+              entry->entry.file_offset);
+      break;
+    }
+}
+
+void
+bfd_sym_print_contained_modules_table_entry (abfd, f, entry)
+     bfd *abfd;
+     FILE *f;
+     bfd_sym_contained_modules_table_entry *entry;
+{
+  switch (entry->generic.type)
+    {
+    case BFD_SYM_END_OF_LIST:
+      fprintf (f, "END");
+      break;
+
+    default:
+      fprintf (f, "\"%.*s\" (MTE %lu, NTE %lu)",
+              bfd_sym_module_name (abfd, entry->entry.mte_index)[0],
+              &bfd_sym_module_name (abfd, entry->entry.mte_index)[1],
+              entry->entry.mte_index,
+              entry->entry.nte_index);
+      break;
+    }
+}
+
+void
+bfd_sym_print_contained_variables_table_entry (abfd, f, entry)
+     bfd *abfd;
+     FILE *f;
+     bfd_sym_contained_variables_table_entry *entry;
+{
+  if (entry->generic.type == BFD_SYM_END_OF_LIST)
+    {
+      fprintf (f, "END");
+      return;
+    }
+  
+  if (entry->generic.type == BFD_SYM_SOURCE_FILE_CHANGE)
+    {
+      bfd_sym_print_file_reference (abfd, f, &entry->file.fref);
+      fprintf (f, " offset %lu", entry->file.fref.fref_offset);
+      return;
+    }
+  
+  fprintf (f, "\"%.*s\" (NTE %lu)",
+          bfd_sym_symbol_name (abfd, entry->entry.nte_index)[0],
+          &bfd_sym_symbol_name (abfd, entry->entry.nte_index)[1],
+          entry->entry.nte_index);
+          
+  fprintf (f, ", TTE %lu", entry->entry.tte_index);
+  fprintf (f, ", offset %lu", entry->entry.file_delta);
+  fprintf (f, ", scope %s", bfd_sym_unparse_symbol_scope (entry->entry.scope));
+
+  if (entry->entry.la_size == BFD_SYM_CVTE_SCA)
+    fprintf (f, ", latype %s, laclass %s, laoffset %lu",
+            bfd_sym_unparse_storage_kind (entry->entry.address.scstruct.sca_kind),
+            bfd_sym_unparse_storage_class (entry->entry.address.scstruct.sca_class),
+            entry->entry.address.scstruct.sca_offset);
+  else if (entry->entry.la_size <= BFD_SYM_CVTE_LA_MAX_SIZE)
+    {
+      unsigned long i;
+
+      fprintf (f, ", la [");
+      for (i = 0; i < entry->entry.la_size; i++)
+       fprintf (f, "0x%02x ", entry->entry.address.lastruct.la[i]);
+      fprintf (f, "]");
+    }
+  else if (entry->entry.la_size == BFD_SYM_CVTE_BIG_LA)
+    fprintf (f, ", bigla %lu, biglakind %u",
+            entry->entry.address.biglastruct.big_la, 
+            entry->entry.address.biglastruct.big_la_kind);
+
+  else
+    fprintf (f, ", la [INVALID]");
+}
+
+void
+bfd_sym_print_contained_statements_table_entry (abfd, f, entry)
+     bfd *abfd;
+     FILE *f;
+     bfd_sym_contained_statements_table_entry *entry;
+{
+  if (entry->generic.type == BFD_SYM_END_OF_LIST)
+    {
+      fprintf (f, "END");
+      return;
+    }
+      
+  if (entry->generic.type == BFD_SYM_SOURCE_FILE_CHANGE)
+    {
+      bfd_sym_print_file_reference (abfd, f, &entry->file.fref);
+      fprintf (f, " offset %lu", entry->file.fref.fref_offset);
+      return;
+    }
+
+  fprintf (f, "\"%.*s\" (MTE %lu), offset %lu, delta %lu",
+          bfd_sym_module_name (abfd, entry->entry.mte_index)[0],
+          &bfd_sym_module_name (abfd, entry->entry.mte_index)[1],
+          entry->entry.mte_index,
+          entry->entry.mte_offset,
+          entry->entry.file_delta);
+}
+
+void
+bfd_sym_print_contained_labels_table_entry (abfd, f, entry)
+     bfd *abfd;
+     FILE *f;
+     bfd_sym_contained_labels_table_entry *entry;
+{
+  if (entry->generic.type == BFD_SYM_END_OF_LIST)
+    {
+      fprintf (f, "END");
+      return;
+    }
+
+  if (entry->generic.type == BFD_SYM_SOURCE_FILE_CHANGE)
+    {
+      bfd_sym_print_file_reference (abfd, f, &entry->file.fref);
+      fprintf (f, " offset %lu", entry->file.fref.fref_offset);
+      return;
+    }
+
+  fprintf (f, "\"%.*s\" (MTE %lu), offset %lu, delta %lu, scope %s",
+          bfd_sym_module_name (abfd, entry->entry.mte_index)[0],
+          &bfd_sym_module_name (abfd, entry->entry.mte_index)[1],
+          entry->entry.mte_index,
+          entry->entry.mte_offset,
+          entry->entry.file_delta,
+          bfd_sym_unparse_symbol_scope (entry->entry.scope));
+}
+
+void
+bfd_sym_print_contained_types_table_entry (abfd, f, entry)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     FILE *f;
+     bfd_sym_contained_types_table_entry *entry ATTRIBUTE_UNUSED;
+{
+  fprintf (f, "[UNIMPLEMENTED]");
+}
+
+const char *
+bfd_sym_type_operator_name (num)
+     unsigned char num;
+{
+  switch (num)
+    {
+    case 1: return "TTE";
+    case 2: return "PointerTo";
+    case 3: return "ScalarOf";
+    case 4: return "ConstantOf";
+    case 5: return "EnumerationOf";
+    case 6: return "VectorOf";
+    case 7: return "RecordOf";
+    case 8: return "UnionOf";
+    case 9: return "SubRangeOf";
+    case 10: return "SetOf";
+    case 11: return "NamedTypeOf";
+    case 12: return "ProcOf";
+    case 13: return "ValueOf";
+    case 14: return "ArrayOf";
+    default: return "[UNKNOWN OPERATOR]";
+    }
+}
+
+const char *
+bfd_sym_type_basic_name (num)
+     unsigned char num;
+{
+  switch (num)
+    {
+    case 0: return "void";
+    case 1: return "pascal string";
+    case 2: return "unsigned long";
+    case 3: return "signed long";
+    case 4: return "extended (10 bytes)";
+    case 5: return "pascal boolean (1 byte)";
+    case 6: return "unsigned byte";
+    case 7: return "signed byte";
+    case 8: return "character (1 byte)";
+    case 9: return "wide character (2 bytes)";
+    case 10: return "unsigned short";
+    case 11: return "signed short";
+    case 12: return "singled";
+    case 13: return "double";
+    case 14: return "extended (12 bytes)";
+    case 15: return "computational (8 bytes)";
+    case 16: return "c string";
+    case 17: return "as-is string";
+    default: return "[UNKNOWN BASIC TYPE]";
+    }
+}
+
+int
+bfd_sym_fetch_long (buf, len, offset, offsetptr, value)
+     unsigned char *buf;
+     unsigned long len;
+     unsigned long offset;
+     unsigned long *offsetptr;
+     long *value;
+{
+  int ret;
+
+  if (offset >= len)
+    {
+      *value = 0;
+      offset += 0;
+      ret = -1;
+    }
+  else if (! (buf[offset] & 0x80))
+    {
+      *value = buf[offset];
+      offset += 1;
+      ret = 0;
+    }
+  else if (buf[offset] == 0xc0)
+    {
+      if ((offset + 5) > len)
+       {
+         *value = 0;
+         offset = len;
+         ret = -1;
+       }
+      else
+       {
+         *value = bfd_getb32 (buf + offset + 1);
+         offset += 5;
+         ret = 0;
+       }
+    }
+  else if ((buf[offset] & 0xc0) == 0xc0)
+    {
+      *value =  -(buf[offset] & 0x3f);
+      offset += 1;
+      ret = 0;
+    }
+  else if ((buf[offset] & 0xc0) == 0x80)
+    {
+      if ((offset + 2) > len)
+       {
+         *value = 0;
+         offset = len;
+         ret = -1;
+       }
+      else
+       {
+         *value = bfd_getb16 (buf + offset) & 0x3fff;
+         offset += 2;
+         ret = 0;
+       }
+    }
+  else
+    abort ();
+
+  if (offsetptr != NULL)
+    *offsetptr = offset;
+
+  return ret;
+}
+
+void
+bfd_sym_print_type_information (abfd, f, buf, len, offset, offsetptr)
+     bfd *abfd;
+     FILE *f;
+     unsigned char *buf;
+     unsigned long len;
+     unsigned long offset;
+     unsigned long *offsetptr;
+{
+  unsigned int type;
+
+  if (offset >= len)
+    {
+      fprintf (f, "[NULL]");
+
+      if (offsetptr != NULL)
+       *offsetptr = offset;
+      return; 
+  }
+  
+  type = buf[offset];
+  offset++;
+
+  if (! (type & 0x80))
+    {
+      fprintf (f, "[%s] (0x%x)", bfd_sym_type_basic_name (type & 0x7f), type);
+
+      if (offsetptr != NULL)
+       *offsetptr = offset;
+      return;
+    }
+
+  if (type & 0x40)
+    fprintf (f, "[packed ");
+  else
+    fprintf (f, "[");
+
+  switch (type & 0x3f)
+    {
+    case 1:
+      {
+       long value;
+       bfd_sym_type_information_table_entry tinfo;
+
+       bfd_sym_fetch_long (buf, len, offset, &offset, &value); 
+       if (value <= 0)
+         fprintf (f, "[INVALID]");
+       else
+         {
+           if (bfd_sym_fetch_type_table_information (abfd, &tinfo, value) < 0)
+             fprintf (f, "[INVALID]");
+           else
+             fprintf (f, "\"%.*s\"", 
+                      bfd_sym_symbol_name (abfd, tinfo.nte_index)[0],
+                      &bfd_sym_symbol_name (abfd, tinfo.nte_index)[1]);
+         }
+       fprintf (f, " (TTE %lu)", value);
+       break;
+      }
+
+    case 2:
+      fprintf (f, "pointer (0x%x) to ", type);
+      bfd_sym_print_type_information (abfd, f, buf, len, offset, &offset);
+      break;
+
+    case 3:
+      {
+       unsigned long value;
+
+       fprintf (f, "scalar (0x%x) of ", type);
+       bfd_sym_print_type_information (abfd, f, buf, len, offset, &offset);
+       bfd_sym_fetch_long (buf, len, offset, &offset, &value);
+       fprintf (f, " (%lu)", value);
+       break;
+      }
+    
+    case 5:
+      {
+       unsigned long lower, upper, nelem;
+       unsigned long i;
+
+       fprintf (f, "enumeration (0x%x) of ", type);
+       bfd_sym_print_type_information (abfd, f, buf, len, offset, &offset);
+       bfd_sym_fetch_long (buf, len, offset, &offset, &lower); 
+       bfd_sym_fetch_long (buf, len, offset, &offset, &upper); 
+       bfd_sym_fetch_long (buf, len, offset, &offset, &nelem); 
+       fprintf (f, " from %lu to %lu with %lu elements: ", lower, upper, nelem);
+
+       for (i = 0; i < nelem; i++)
+         {
+           fprintf (f, "\n                    ");
+           bfd_sym_print_type_information (abfd, f, buf, len, offset, &offset);
+         }
+       break;
+      }
+
+    case 6:
+      fprintf (f, "vector (0x%x)", type);
+      fprintf (f, "\n                index ");
+      bfd_sym_print_type_information (abfd, f, buf, len, offset, &offset);
+      fprintf (f, "\n                target ");
+      bfd_sym_print_type_information (abfd, f, buf, len, offset, &offset);
+      break;
+
+    case 7:
+    case 8:
+      {
+       long nrec, eloff, i;
+
+       if ((type & 0x3f) == 7)
+         fprintf (f, "record (0x%x) of ", type);
+       else
+         fprintf (f, "union (0x%x) of ", type);
+      
+       bfd_sym_fetch_long (buf, len, offset, &offset, &nrec); 
+       fprintf (f, "%lu elements: ", nrec); 
+
+       for (i = 0; i < nrec; i++)
+         {
+           bfd_sym_fetch_long (buf, len, offset, &offset, &eloff); 
+           fprintf (f, "\n                ");
+           fprintf (f, "offset %lu: ", eloff); 
+           bfd_sym_print_type_information (abfd, f, buf, len, offset, &offset);
+         }
+       break;
+      }
+
+    case 9:
+      fprintf (f, "subrange (0x%x) of ", type);
+      bfd_sym_print_type_information (abfd, f, buf, len, offset, &offset);
+      fprintf (f, " lower ");
+      bfd_sym_print_type_information (abfd, f, buf, len, offset, &offset);
+      fprintf (f, " upper ");
+      bfd_sym_print_type_information (abfd, f, buf, len, offset, &offset);
+      break;
+
+  case 11:
+    {
+      long value;
+
+      fprintf (f, "named type (0x%x) ", type);
+      bfd_sym_fetch_long (buf, len, offset, &offset, &value); 
+      if (value <= 0)
+       fprintf (f, "[INVALID]");
+      else
+       fprintf (f, "\"%.*s\"", 
+                bfd_sym_symbol_name (abfd, value)[0],
+                &bfd_sym_symbol_name (abfd, value)[1]);
+
+      fprintf (f, " (NTE %lu) with type ", value);
+      bfd_sym_print_type_information (abfd, f, buf, len, offset, &offset);
+      break;
+    }
+
+  default:
+    fprintf (f, "%s (0x%x)", bfd_sym_type_operator_name (type), type);
+    break;
+    }
+  
+  if (type == (0x40 | 0x6))
+    {
+      /* Vector.  */
+      long n, width, m;
+      long l;
+      long i;
+
+      bfd_sym_fetch_long (buf, len, offset, &offset, &n); 
+      bfd_sym_fetch_long (buf, len, offset, &offset, &width); 
+      bfd_sym_fetch_long (buf, len, offset, &offset, &m); 
+      /* fprintf (f, "\n                "); */
+      fprintf (f, " N %ld, width %ld, M %ld, ", n, width, m);
+      for (i = 0; i < m; i++)
+       {
+         bfd_sym_fetch_long (buf, len, offset, &offset, &l); 
+         if (i != 0)
+           fprintf (f, " ");
+         fprintf (f, "%ld", l);
+       }
+    }
+  else  if (type & 0x40)
+    {
+      /* Other packed type.  */
+      long msb, lsb;
+
+      bfd_sym_fetch_long (buf, len, offset, &offset, &msb); 
+      bfd_sym_fetch_long (buf, len, offset, &offset, &lsb); 
+      /* fprintf (f, "\n                "); */
+      fprintf (f, " msb %ld, lsb %ld", msb, lsb);
+    }
+
+  fprintf (f, "]");
+
+  if (offsetptr != NULL)
+    *offsetptr = offset;
+}
+
+void
+bfd_sym_print_type_information_table_entry (abfd, f, entry)
+     bfd *abfd;
+     FILE *f;
+     bfd_sym_type_information_table_entry *entry;
+{
+  unsigned char *buf;
+  unsigned long offset;
+  unsigned int i;
+
+  fprintf (f, "\"%.*s\" (NTE %lu), %lu bytes at %lu, logical size %lu",
+          bfd_sym_symbol_name (abfd, entry->nte_index)[0],
+          &bfd_sym_symbol_name (abfd, entry->nte_index)[1],
+          entry->nte_index,
+          entry->physical_size, entry->offset, entry->logical_size);
+
+  fprintf (f, "\n            ");          
+
+  buf = alloca (entry->physical_size);
+  if (buf == NULL)
+    {
+      fprintf (f, "[ERROR]\n");
+      return;
+    }
+  if (bfd_seek (abfd, entry->offset, SEEK_SET) < 0)
+    {
+      fprintf (f, "[ERROR]\n");
+      return;
+    }
+  if (bfd_bread (buf, entry->physical_size, abfd) != entry->physical_size)
+    {
+      fprintf (f, "[ERROR]\n");
+      return;
+    }
+
+  fprintf (f, "[");
+  for (i = 0; i < entry->physical_size; i++)
+    {
+      if (i == 0)
+       fprintf (f, "0x%02x", buf[i]);
+      else
+       fprintf (f, " 0x%02x", buf[i]);
+    }
+
+  fprintf (f, "]");
+  fprintf (f, "\n            ");          
+
+  bfd_sym_print_type_information (abfd, f, buf, entry->physical_size, 0, &offset);
+
+  if (offset != entry->physical_size)
+    fprintf (f, "\n            [parser used %lu bytes instead of %lu]", offset, entry->physical_size);        }
+
+void
+bfd_sym_print_file_references_index_table_entry (abfd, f, entry)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     FILE *f;
+     bfd_sym_file_references_index_table_entry *entry ATTRIBUTE_UNUSED;
+{
+  fprintf (f, "[UNIMPLEMENTED]");
+}
+
+void
+bfd_sym_print_constant_pool_entry (abfd, f, entry)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     FILE *f;
+     bfd_sym_constant_pool_entry *entry ATTRIBUTE_UNUSED;
+{
+  fprintf (f, "[UNIMPLEMENTED]");
+}
+
+unsigned char *
+bfd_sym_display_name_table_entry (abfd, f, entry)
+     bfd *abfd;
+     FILE *f;
+     unsigned char *entry;
+{
+  unsigned long index;
+  unsigned long offset;
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+  index = (entry - sdata->name_table) / 2;
+  
+  if ((sdata->version >= BFD_SYM_VERSION_3_4) && (entry[0] == 255) && (entry[1] == 0)) 
+    {
+      unsigned short length = bfd_getb16 (entry + 2);  
+      fprintf (f, "[%8lu] \"%.*s\"\n", index, length, entry + 4);
+      offset = 2 + length + 1;
+    }
+  else
+    {
+      if (! ((entry[0] == 0) || ((entry[0] == 1) && (entry[1] == '\0'))))
+       fprintf (f, "[%8lu] \"%.*s\"\n", index, entry[0], entry + 1);
+
+      if (sdata->version >= BFD_SYM_VERSION_3_4)
+       offset = entry[0] + 2;
+      else
+       offset = entry[0] + 1;
+    }
+
+  return (entry + offset + (offset % 2));
+}
+
+void
+bfd_sym_display_name_table (abfd, f)
+     bfd *abfd;
+     FILE *f;
+{
+  unsigned long name_table_len;
+  unsigned char *name_table, *name_table_end, *cur;
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+
+  name_table_len = sdata->header.dshb_nte.dti_page_count * sdata->header.dshb_page_size;
+  name_table = sdata->name_table;
+  name_table_end = name_table + name_table_len;
+  
+  fprintf (f, "name table (NTE) contains %lu bytes:\n\n", name_table_len);
+  
+  cur = name_table;
+  for (;;)
+    {
+      cur = bfd_sym_display_name_table_entry (abfd, f, cur);
+      if (cur >= name_table_end)
+       break;
+    }
+}
+
+void
+bfd_sym_display_resources_table (abfd, f)
+     bfd *abfd;
+     FILE *f;
+{
+  unsigned long i;
+  bfd_sym_resources_table_entry entry;
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+
+  fprintf (f, "resource table (RTE) contains %lu objects:\n\n",
+          sdata->header.dshb_rte.dti_object_count);
+  
+  for (i = 1; i <= sdata->header.dshb_rte.dti_object_count; i++)
+    {
+      if (bfd_sym_fetch_resources_table_entry (abfd, &entry, i) < 0)
+       fprintf (f, " [%8lu] [INVALID]\n", i);
+      else
+       {
+         fprintf (f, " [%8lu] ", i);
+         bfd_sym_print_resources_table_entry (abfd, f, &entry);
+         fprintf (f, "\n");
+       }
+    }
+}
+
+void
+bfd_sym_display_modules_table (abfd, f)
+     bfd *abfd;
+     FILE *f;
+{
+  unsigned long i;
+  bfd_sym_modules_table_entry entry;
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+
+  fprintf (f, "module table (MTE) contains %lu objects:\n\n",
+          sdata->header.dshb_mte.dti_object_count);
+
+  for (i = 1; i <= sdata->header.dshb_mte.dti_object_count; i++)
+    {
+      if (bfd_sym_fetch_modules_table_entry (abfd, &entry, i) < 0)
+       fprintf (f, " [%8lu] [INVALID]\n", i);
+      else
+       {
+         fprintf (f, " [%8lu] ", i);
+         bfd_sym_print_modules_table_entry (abfd, f, &entry);
+         fprintf (f, "\n");
+       }
+    }
+}
+
+void
+bfd_sym_display_file_references_table (abfd, f)
+     bfd *abfd;
+     FILE *f;
+{
+  unsigned long i;
+  bfd_sym_file_references_table_entry entry;
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+
+  fprintf (f, "file reference table (FRTE) contains %lu objects:\n\n",
+          sdata->header.dshb_frte.dti_object_count);
+
+  for (i = 1; i <= sdata->header.dshb_frte.dti_object_count; i++)
+    {
+      if (bfd_sym_fetch_file_references_table_entry (abfd, &entry, i) < 0)
+       fprintf (f, " [%8lu] [INVALID]\n", i);
+      else
+       {
+         fprintf (f, " [%8lu] ", i);
+         bfd_sym_print_file_references_table_entry (abfd, f, &entry);
+         fprintf (f, "\n");
+       }
+    }
+}
+
+void
+bfd_sym_display_contained_modules_table (abfd, f)
+     bfd *abfd;
+     FILE *f;
+{
+  unsigned long i;
+  bfd_sym_contained_modules_table_entry entry;  
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+
+  fprintf (f, "contained modules table (CMTE) contains %lu objects:\n\n",
+          sdata->header.dshb_cmte.dti_object_count);
+  
+  for (i = 1; i <= sdata->header.dshb_cmte.dti_object_count; i++)
+    {
+      if (bfd_sym_fetch_contained_modules_table_entry (abfd, &entry, i) < 0)
+       fprintf (f, " [%8lu] [INVALID]\n", i);
+      else
+       {
+         fprintf (f, " [%8lu] ", i);
+         bfd_sym_print_contained_modules_table_entry (abfd, f, &entry);
+         fprintf (f, "\n");
+       }
+    }
+}
+
+void
+bfd_sym_display_contained_variables_table (abfd, f)
+     bfd *abfd;
+     FILE *f;
+{
+  unsigned long i;
+  bfd_sym_contained_variables_table_entry entry;
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+
+  fprintf (f, "contained variables table (CVTE) contains %lu objects:\n\n",
+          sdata->header.dshb_cvte.dti_object_count);
+  
+  for (i = 1; i <= sdata->header.dshb_cvte.dti_object_count; i++)
+    {
+      if (bfd_sym_fetch_contained_variables_table_entry (abfd, &entry, i) < 0)
+       fprintf (f, " [%8lu] [INVALID]\n", i);
+      else
+       {
+         fprintf (f, " [%8lu] ", i);
+         bfd_sym_print_contained_variables_table_entry (abfd, f, &entry);
+         fprintf (f, "\n");
+       }
+    }
+
+  fprintf (f, "\n");
+}
+
+void
+bfd_sym_display_contained_statements_table (abfd, f)
+     bfd *abfd;
+     FILE *f;
+{
+  unsigned long i;
+  bfd_sym_contained_statements_table_entry entry;  
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+
+  fprintf (f, "contained statements table (CSNTE) contains %lu objects:\n\n",
+          sdata->header.dshb_csnte.dti_object_count);
+  
+  for (i = 1; i <= sdata->header.dshb_csnte.dti_object_count; i++)
+    {
+      if (bfd_sym_fetch_contained_statements_table_entry (abfd, &entry, i) < 0)
+       fprintf (f, " [%8lu] [INVALID]\n", i);
+      else
+       {
+         fprintf (f, " [%8lu] ", i);
+         bfd_sym_print_contained_statements_table_entry (abfd, f, &entry);
+         fprintf (f, "\n");
+       }
+    }
+}
+
+void
+bfd_sym_display_contained_labels_table (abfd, f)
+     bfd *abfd;
+     FILE *f;
+{
+  unsigned long i;
+  bfd_sym_contained_labels_table_entry entry;
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+
+  fprintf (f, "contained labels table (CLTE) contains %lu objects:\n\n",
+          sdata->header.dshb_clte.dti_object_count);
+  
+  for (i = 1; i <= sdata->header.dshb_clte.dti_object_count; i++)
+    {
+      if (bfd_sym_fetch_contained_labels_table_entry (abfd, &entry, i) < 0)
+       fprintf (f, " [%8lu] [INVALID]\n", i);
+      else
+       {
+         fprintf (f, " [%8lu] ", i);
+         bfd_sym_print_contained_labels_table_entry (abfd, f, &entry);
+         fprintf (f, "\n");
+       }
+    }
+}
+
+void
+bfd_sym_display_contained_types_table (abfd, f)
+     bfd *abfd;
+     FILE *f;
+{
+  unsigned long i;
+  bfd_sym_contained_types_table_entry entry;  
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+
+  fprintf (f, "contained types table (CTTE) contains %lu objects:\n\n",
+          sdata->header.dshb_ctte.dti_object_count);
+  
+  for (i = 1; i <= sdata->header.dshb_ctte.dti_object_count; i++)
+    {
+      if (bfd_sym_fetch_contained_types_table_entry (abfd, &entry, i) < 0)
+       fprintf (f, " [%8lu] [INVALID]\n", i);
+      else
+       {
+         fprintf (f, " [%8lu] ", i);
+         bfd_sym_print_contained_types_table_entry (abfd, f, &entry);
+         fprintf (f, "\n");
+       }
+    }
+}
+
+void
+bfd_sym_display_file_references_index_table (abfd, f)
+     bfd *abfd;
+     FILE *f;
+{
+  unsigned long i;
+  bfd_sym_file_references_index_table_entry entry;  
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+
+  fprintf (f, "file references index table (FITE) contains %lu objects:\n\n",
+          sdata->header.dshb_fite.dti_object_count);
+  
+  for (i = 1; i <= sdata->header.dshb_fite.dti_object_count; i++)
+    {
+      if (bfd_sym_fetch_file_references_index_table_entry (abfd, &entry, i) < 0)
+       fprintf (f, " [%8lu] [INVALID]\n", i);
+      else
+       {
+         fprintf (f, " [%8lu] ", i);
+         bfd_sym_print_file_references_index_table_entry (abfd, f, &entry);
+         fprintf (f, "\n");
+       }
+    }
+}
+
+void
+bfd_sym_display_constant_pool (abfd, f)
+     bfd *abfd;
+     FILE *f;
+{
+  unsigned long i;
+  bfd_sym_constant_pool_entry entry;  
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+
+  fprintf (f, "constant pool (CONST) contains %lu objects:\n\n",
+          sdata->header.dshb_const.dti_object_count);
+  
+  for (i = 1; i <= sdata->header.dshb_const.dti_object_count; i++)
+    {
+      if (bfd_sym_fetch_constant_pool_entry (abfd, &entry, i) < 0)
+       fprintf (f, " [%8lu] [INVALID]\n", i);
+      else
+       {
+         fprintf (f, " [%8lu] ", i);
+         bfd_sym_print_constant_pool_entry (abfd, f, &entry);
+         fprintf (f, "\n");
+       }
+    }
+}
+
+void
+bfd_sym_display_type_information_table (abfd, f)
+     bfd *abfd;
+     FILE *f;
+{
+  unsigned long i;
+  bfd_sym_type_table_entry index;
+  bfd_sym_type_information_table_entry entry;  
+  bfd_sym_data_struct *sdata = NULL;
+
+  BFD_ASSERT (bfd_sym_valid (abfd));
+  sdata = abfd->tdata.sym_data;
+
+  if (sdata->header.dshb_tte.dti_object_count > 99)
+    fprintf (f, "type table (TINFO) contains %lu objects:\n\n",
+            sdata->header.dshb_tte.dti_object_count - 99);
+  else
+    {
+      fprintf (f, "type table (TINFO) contains [INVALID] objects:\n\n");
+      return;
+    }
+  
+  for (i = 100; i <= sdata->header.dshb_tte.dti_object_count; i++)
+    {
+      if (bfd_sym_fetch_type_table_entry (abfd, &index, i - 100) < 0)
+       fprintf (f, " [%8lu] [INVALID]\n", i);
+      else
+       {
+         fprintf (f, " [%8lu] (TINFO %lu) ", i, index);
+
+         if (bfd_sym_fetch_type_information_table_entry (abfd, &entry, index) < 0)
+           fprintf (f, "[INVALID]");
+         else
+           bfd_sym_print_type_information_table_entry (abfd, f, &entry);
+
+         fprintf (f, "\n");
+       }
+    }
+}
+
+const bfd_target *
+bfd_sym_object_p (abfd)
+     bfd *abfd;
+{
+  bfd_sym_data_struct *mdata = NULL;
+  asection *bfdsec;
+  const char *name = "symbols";
+  
+  mdata = ((bfd_sym_data_struct *) 
+          bfd_alloc (abfd, sizeof (bfd_sym_data_struct)));
+  if (mdata == NULL)
+    return NULL;
+
+  abfd->tdata.sym_data = mdata;
+
+  mdata->name_table = 0;
+  mdata->sbfd = abfd;
+
+  bfd_seek (abfd, 0, SEEK_SET);
+  if (bfd_sym_read_version (abfd, &mdata->version) != 0)
+    {
+      abfd->tdata.sym_data = NULL;
+      bfd_set_error (bfd_error_wrong_format);
+      return NULL;
+    }
+  
+  bfd_seek (abfd, 0, SEEK_SET);
+  if (bfd_sym_read_header (abfd, &mdata->header, mdata->version) != 0)
+    {
+      abfd->tdata.sym_data = NULL;
+      bfd_set_error (bfd_error_wrong_format);
+      return NULL;
+    }
+
+  mdata->name_table = bfd_sym_read_name_table (abfd, &mdata->header);
+  if (mdata->name_table == NULL)
+    {
+      abfd->tdata.sym_data = NULL;
+      bfd_set_error (bfd_error_wrong_format);
+      return NULL;
+    }
+
+  bfdsec = bfd_make_section_anyway (abfd, name);
+  if (bfdsec == NULL)
+    {
+      abfd->tdata.sym_data = NULL;
+      bfd_set_error (bfd_error_wrong_format);
+      return NULL; 
+    }
+  
+  bfdsec->vma = 0;
+  bfdsec->lma = 0;
+  bfdsec->_raw_size = 0;
+  bfdsec->filepos = 0;
+  bfdsec->alignment_power = 0;
+  
+  bfdsec->flags = SEC_HAS_CONTENTS;
+
+  return abfd->xvec;
+}
+
+asymbol *
+bfd_sym_make_empty_symbol (abfd)
+     bfd *abfd;
+{
+  return (asymbol *) bfd_alloc (abfd, sizeof (asymbol));
+}
+
+void
+bfd_sym_get_symbol_info (abfd, symbol, ret)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     asymbol *symbol;
+     symbol_info *ret;
+{
+  bfd_symbol_info (symbol, ret);
+}
+
+long
+bfd_sym_get_symtab_upper_bound (abfd)
+     bfd *abfd ATTRIBUTE_UNUSED;
+{
+  return 0;
+}
+
+long
+bfd_sym_get_symtab (abfd, sym)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     asymbol **sym ATTRIBUTE_UNUSED;
+{
+  return 0;
+}
+
+int
+bfd_sym_sizeof_headers (abfd, exec)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     boolean exec ATTRIBUTE_UNUSED;
+{
+  return 0;
+}
+
+const bfd_target sym_vec =
+{
+  "sym",                       /* name */
+  bfd_target_sym_flavour,      /* flavour */
+  BFD_ENDIAN_BIG,              /* byteorder */
+  BFD_ENDIAN_BIG,              /* header_byteorder */
+  (HAS_RELOC | EXEC_P |                /* object flags */
+   HAS_LINENO | HAS_DEBUG |
+   HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
+  (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_DATA
+   | SEC_ROM | SEC_HAS_CONTENTS), /* section_flags */
+  0,                           /* symbol_leading_char */
+  ' ',                         /* ar_pad_char */
+  16,                          /* ar_max_namelen */
+  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+  bfd_getb16, bfd_getb_signed_16, bfd_putb16,  /* data */
+  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+  bfd_getb16, bfd_getb_signed_16, bfd_putb16,  /* hdrs */
+  {                            /* bfd_check_format */
+    _bfd_dummy_target,
+    bfd_sym_object_p,          /* bfd_check_format */
+    _bfd_dummy_target,
+    _bfd_dummy_target,
+  },
+  {                            /* bfd_set_format */
+    bfd_false,
+    bfd_sym_mkobject,
+    bfd_false,
+    bfd_false,
+  },
+  {                            /* bfd_write_contents */
+    bfd_false,
+    bfd_true,
+    bfd_false,
+    bfd_false,
+  },
+
+  BFD_JUMP_TABLE_GENERIC (bfd_sym),
+  BFD_JUMP_TABLE_COPY (_bfd_generic),
+  BFD_JUMP_TABLE_CORE (_bfd_nocore),
+  BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
+  BFD_JUMP_TABLE_SYMBOLS (bfd_sym),
+  BFD_JUMP_TABLE_RELOCS (bfd_sym),
+  BFD_JUMP_TABLE_WRITE (bfd_sym),
+  BFD_JUMP_TABLE_LINK (bfd_sym),
+  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+  NULL,
+  
+  NULL
+};
+
diff --git a/bfd/xsym.h b/bfd/xsym.h
new file mode 100644 (file)
index 0000000..388da85
--- /dev/null
@@ -0,0 +1,699 @@
+/* xSYM symbol-file support for BFD.
+   Copyright 1999, 2000, 2001, 2002
+   Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software 
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include "bfd.h"
+#include <stdio.h>
+
+#ifndef __xSYM_H__
+#define __xSYM_H__
+
+#define BFD_SYM_VERSION_STR_3_1        "\013Version 3.1"
+#define BFD_SYM_VERSION_STR_3_2        "\013Version 3.2"
+#define BFD_SYM_VERSION_STR_3_3        "\013Version 3.3"
+#define BFD_SYM_VERSION_STR_3_4        "\013Version 3.4"
+#define BFD_SYM_VERSION_STR_3_5        "\013Version 3.5"
+#define BFD_SYM_END_OF_LIST_3_2                0xffff
+#define BFD_SYM_END_OF_LIST_3_4                0xffffffff
+#define BFD_SYM_END_OF_LIST            BFD_SYM_END_OF_LIST_3_4
+#define BFD_SYM_FILE_NAME_INDEX_3_2    0xfffe
+#define BFD_SYM_FILE_NAME_INDEX_3_4    0xfffffffe
+#define BFD_SYM_FILE_NAME_INDEX                BFD_SYM_FILE_NAME_INDEX_3_4
+#define BFD_SYM_SOURCE_FILE_CHANGE_3_2 0xfffe
+#define BFD_SYM_SOURCE_FILE_CHANGE_3_4 0xfffffffe
+#define BFD_SYM_SOURCE_FILE_CHANGE     BFD_SYM_SOURCE_FILE_CHANGE_3_4
+#define BFD_SYM_MAXIMUM_LEGAL_INDEX_3_2 0xfffd
+#define BFD_SYM_MAXIMUM_LEGAL_INDEX_3_4 0xfffffffd
+#define BFD_SYM_MAXIMUM_LEGAL_INDEX    BFD_SYM_MAXIMUM_LEGAL_INDEX_3_4
+
+enum bfd_sym_storage_class
+{
+  BFD_SYM_STORAGE_CLASS_REGISTER = 0,
+  BFD_SYM_STORAGE_CLASS_GLOBAL = 1,
+  BFD_SYM_STORAGE_CLASS_FRAME_RELATIVE = 2,
+  BFD_SYM_STORAGE_CLASS_STACK_RELATIVE = 3,
+  BFD_SYM_STORAGE_CLASS_ABSOLUTE = 4,
+  BFD_SYM_STORAGE_CLASS_CONSTANT = 5,
+  BFD_SYM_STORAGE_CLASS_BIGCONSTANT = 6,
+  BFD_SYM_STORAGE_CLASS_RESOURCE = 99
+};
+typedef enum bfd_sym_storage_class bfd_sym_storage_class;
+
+enum bfd_sym_storage_kind
+{
+  BFD_SYM_STORAGE_KIND_LOCAL = 0,
+  BFD_SYM_STORAGE_KIND_VALUE = 1,
+  BFD_SYM_STORAGE_KIND_REFERENCE = 2,
+  BFD_SYM_STORAGE_KIND_WITH = 3
+};
+typedef enum bfd_sym_storage_kind bfd_sym_storage_kind;
+
+enum bfd_sym_version
+{
+  BFD_SYM_VERSION_3_1,
+  BFD_SYM_VERSION_3_2,
+  BFD_SYM_VERSION_3_3,
+  BFD_SYM_VERSION_3_4,
+  BFD_SYM_VERSION_3_5
+};
+typedef enum bfd_sym_version bfd_sym_version;
+
+enum bfd_sym_module_kind
+{
+  BFD_SYM_MODULE_KIND_NONE = 0,
+  BFD_SYM_MODULE_KIND_PROGRAM = 1,
+  BFD_SYM_MODULE_KIND_UNIT = 2,
+  BFD_SYM_MODULE_KIND_PROCEDURE = 3,
+  BFD_SYM_MODULE_KIND_FUNCTION = 4,
+  BFD_SYM_MODULE_KIND_DATA = 5,
+  BFD_SYM_MODULE_KIND_BLOCK = 6
+};
+typedef enum bfd_sym_module_kind bfd_sym_module_kind;
+
+enum bfd_sym_symbol_scope
+{
+  BFD_SYM_SYMBOL_SCOPE_LOCAL = 0,  /* Object is seen only inside current scope.  */
+  BFD_SYM_SYMBOL_SCOPE_GLOBAL = 1  /* Object has global scope.  */
+};
+typedef enum bfd_sym_symbol_scope bfd_sym_symbol_scope;
+
+struct bfd_sym_file_reference
+{
+  unsigned long fref_frte_index; /* File reference table index.  */
+  unsigned long fref_offset;     /* Absolute offset into source file.  */
+};
+typedef struct bfd_sym_file_reference bfd_sym_file_reference;
+
+/* NAME TABLE (NTE).  */
+
+/* RESOURCES TABLE (RTE)
+   
+   All code and data is *defined* to reside in a resource.  Even A5
+   relative data is defined to reside in a dummy resource of ResType
+   'gbld'.  Code always resides in a resource.  Because a code/data
+   is built of many modules, when walking through a resource we must
+   point back to the modules in the order they were defined.  This is
+   done by requiring the entries in the Modules Entry table to be
+   ordered by resource/resource-number and by the location in that
+   resource.  Hence, the resource table entry points to the first
+   module making up that resource.  All modules table entries following
+   that first one with the same restype/resnum are contiguous and offset
+   from that first entry.  */
+
+struct bfd_sym_resources_table_entry
+{
+  unsigned char rte_res_type[4];  /* Resource Type.  */
+  unsigned short rte_res_number;  /* Resource Number.  */
+  unsigned long rte_nte_index;    /* Name of the resource.  */
+  unsigned long rte_mte_first;    /* Index of first module in the resource.  */
+  unsigned long rte_mte_last;     /* Index of the last module in the resource. */
+  unsigned long        rte_res_size;     /* Size of the resource.  */
+};
+typedef struct bfd_sym_resources_table_entry bfd_sym_resources_table_entry;
+
+/* MODULES TABLE (MTE)
+   
+   Modules table entries are ordered by their appearance in a resource.
+   (Note that having a single module copied into two resources is not
+   possible).  Modules map back to their resource via an index into the
+   resource table and an offset into the resource.  Modules also point
+   to their source files, both the definition module and implemention
+   module.  Because modules can be textually nested within other
+   modules, a link to the parent (containing) module is required.  This
+   module can textually contain other modules.  A link to the contiguous
+   list of child (contained) modules is required.  Variables, statements,
+   and types defined in the module are pointed to by indexing the head of
+   the contiguous lists of contained variables, contained statements,
+   and contained types.  */
+
+struct bfd_sym_modules_table_entry
+{
+  unsigned long mte_rte_index;         /* Which resource it is in.  */
+  unsigned long mte_res_offset;        /* Offset into the resource.  */
+  unsigned long mte_size;              /* Size of module.  */
+  char mte_kind;                       /* What kind of module this is.  */
+  char mte_scope;                      /* How visible is it?  */
+  unsigned long mte_parent;            /* Containing module.  */
+  bfd_sym_file_reference mte_imp_fref; /* Implementation source.  */
+  unsigned long mte_imp_end;           /* End of implementation source.  */
+  unsigned long mte_nte_index;         /* The name of the module.  */
+  unsigned long mte_cmte_index;        /* Modules contained in this.  */
+  unsigned long mte_cvte_index;        /* Variables contained in this.  */
+  unsigned long mte_clte_index;        /* Local labels defined here.  */
+  unsigned long mte_ctte_index;        /* Types contained in this.  */
+  unsigned long mte_csnte_idx_1;       /* CSNTE index of mte_snbr_first.  */
+  unsigned long mte_csnte_idx_2;       /* CSNTE index of mte_snbr_last.  */
+}; 
+typedef struct bfd_sym_modules_table_entry bfd_sym_modules_table_entry;
+
+/* FILE REFERENCES TABLE (FRTE)
+   
+   The FILE REFERENCES TABLE maps from source file to module & offset.
+   The table is ordered by increasing file offset.  Each new offset
+   references a module.
+                               FRT     = FILE_SOURCE_START
+                                                       FILE_SOURCE_INCREMENT*
+                                                       END_OF_LIST.
+       *** THIS MECHANISM IS VERY SLOW FOR FILE+STATEMENT_NUMBER TO
+       *** MODULE/CODE ADDRESS OPERATIONS.  ANOTHER MECHANISM IS
+       ***     REQUIRED!!  */
+
+union bfd_sym_file_references_table_entry
+{
+  struct
+  {
+    /* END_OF_LIST, FILE_NAME_INDEX, or module table entry.  */
+    unsigned long type;
+  }
+  generic;
+
+  struct
+  {
+    /* FILE_NAME_INDEX.  */
+    unsigned long type;
+    unsigned long nte_index;
+    unsigned long mod_date;
+  }
+  filename;
+  
+  struct
+  {
+    /* < FILE_NAME_INDEX.  */
+    unsigned long mte_index;
+    unsigned long file_offset;
+  }
+  entry;
+};
+typedef union bfd_sym_file_references_table_entry bfd_sym_file_references_table_entry;
+
+/* CONTAINED MODULES TABLE (CMTE)
+
+   Contained Modules are lists of indices into the modules table.  The
+   lists are terminated by an END_OF_LIST index.  All entries are of the
+   same size, hence mapping an index into a CMTE list is simple.
+   CMT = MTE_INDEX* END_OF_LIST.  */
+
+union bfd_sym_contained_modules_table_entry
+{
+  struct
+  {
+    /* END_OF_LIST, index.  */
+    unsigned long type;
+  }
+  generic;
+  
+  struct
+  {
+    unsigned long mte_index; /* Index into the Modules Table.  */
+    unsigned long nte_index; /* The name of the module.  */
+  }
+  entry;
+};
+typedef union bfd_sym_contained_modules_table_entry bfd_sym_contained_modules_table_entry;
+
+/* CONTAINED VARIABLES TABLE (CVTE)
+   Contained Variables map into the module table, file table, name table, and type
+   table.  Contained Variables are a contiguous list of source file change record,
+   giving the name of and offset into the source file corresponding to all variables
+   following.  Variable definition records contain an index into the name table (giving
+   the text of the variable as it appears in the source code), an index into the type
+   table giving the type of the variable, an increment added to the source file
+   offset giving the start of the implementation of the variable, and a storage
+   class address, giving information on variable's runtime address.
+   CVT = SOURCE_FILE_CHANGE SYMBOL_INFO* END_OF_LIST.
+   SYMBOL_INFO = SYMBOL_DEFINITION | SOURCE_FILE_CHANGE .
+   All entries are of the same size, making the fetching of data simple.  The
+   variable entries in the list are in ALPHABETICAL ORDER to simplify the display of
+   available variables for several of the debugger's windows.  */
+
+/* 'la_size' determines the variant used below:
+     == BFD_SYM_CVTE_SCA
+     Traditional STORAGE_CLASS_ADDRESS;
+     <= BFD_SYM_CVTE_LA_MAX_SIZE
+     That many logical address bytes ("in-situ");
+     == BFD_SYM_CVTE_BIG_LA
+     Logical address bytes in constant pool, at offset 'big_la'.  */
+#define        BFD_SYM_CVTE_SCA 0          /* Indicate SCA variant of CVTE.  */
+#define        BFD_SYM_CVTE_LA_MAX_SIZE 13 /* Max# of logical address bytes in a CVTE.  */
+#define        BFD_SYM_CVTE_BIG_LA 127     /* Indicates LA redirection to constant pool.  */
+
+union bfd_sym_contained_variables_table_entry
+{
+  struct
+  {
+    /* END_OF_LIST, SOURCE_FILE_CHANGE, or type table entry.  */
+    unsigned long type;
+  }
+  generic;
+
+  struct
+  {
+    /* SOURCE_FILE_CHANGE.  */
+    unsigned long type;
+    bfd_sym_file_reference fref;
+  }
+  file;
+
+  struct
+  {
+    /* < SOURCE_FILE_CHANGE.  */
+    unsigned long tte_index;
+    unsigned long nte_index;
+    unsigned long file_delta;                       /* Increment from previous source.  */
+    unsigned char scope;
+    unsigned char la_size;                          /* #bytes of LAs below.  */
+
+    union
+    {
+      /* la_size == BFD_SYM_CVTE_SCA.  */
+      struct
+      {
+       unsigned char sca_kind;                     /* Distinguish local from value/var formal.  */
+       unsigned char sca_class;                    /* The storage class itself.  */
+       unsigned long sca_offset;
+      }
+      scstruct;
+
+      /* la_size <= BFD_SYM_CVTE_LA_MAX_SIZE.  */
+      struct {
+       unsigned char la[BFD_SYM_CVTE_LA_MAX_SIZE]; /* Logical address bytes.  */
+       unsigned char la_kind;                      /* Eqv. cvte_location.sca_kind.  */
+      }
+      lastruct;
+
+      /* la_size == BFD_SYM_CVTE_BIG_LA 127.  */
+      struct
+      {
+       unsigned long big_la;                       /* Logical address bytes in constant pool.  */
+       unsigned char big_la_kind;                  /* Eqv. cvte_location.sca_kind.  */
+      }
+      biglastruct;
+    }
+    address;
+  }
+  entry;
+};
+typedef union bfd_sym_contained_variables_table_entry bfd_sym_contained_variables_table_entry;
+
+/* CONTAINED STATEMENTS TABLE (CSNTE)
+   Contained Statements table.  This table is similar to the Contained
+   Variables table except that instead of VARIABLE_DEFINITION entries, this
+   module contains STATEMENT_NUMBER_DEFINITION entries.  A statement number
+   definition points back to the containing module (via an index into
+   the module entry table) and contains the file and resource deltas
+   to add to the previous values to get to this statement.
+   All entries are of the same size, making the fetching of data simple.  The
+   entries in the table are in order of increasing statement number within the
+   source file.
+   The Contained Statements table is indexed from two places.  An MTE contains
+   an index to the first statement number within the module.  An FRTE contains
+   an index to the first statement in the table (Possibly.  This is slow.)  Or
+   a table of fast statement number to CSNTE entry mappings indexes into the
+   table.  Choice not yet made.  */
+
+union bfd_sym_contained_statements_table_entry
+{
+  struct
+  {
+    /* END_OF_LIST, SOURCE_FILE_CHANGE, or statement table entry.  */
+    unsigned long type;
+  }
+  generic;
+
+  struct
+  {
+    /* SOURCE_FILE_CHANGE.  */
+    unsigned long type;
+    bfd_sym_file_reference fref; /* File name table.  */
+  }
+  file;
+
+  struct
+  {
+    unsigned long mte_index;     /* Which module contains it.  */
+    unsigned long file_delta;    /* Where it is defined.  */
+    unsigned long mte_offset;    /* Where it is in the module.  */
+  }
+  entry;
+};
+typedef union bfd_sym_contained_statements_table_entry bfd_sym_contained_statements_table_entry;
+
+/* CONTAINED LABELS TABLE (CLTE)
+   Contained Labels table names those labels local to the module.  It is similar
+   to the Contained Statements table.  */
+
+union bfd_sym_contained_labels_table_entry
+{
+  struct
+  {
+    /* END_OF_LIST, SOURCE_FILE_CHANGE, index.  */
+    unsigned long type;
+  }
+  generic;
+
+  struct
+  {
+    /* SOURCE_FILE_CHANGE.  */
+    unsigned long type;
+    bfd_sym_file_reference fref;
+  }
+  file;
+
+  struct
+  {
+    /* < SOURCE_FILE_CHANGE.  */
+    unsigned long mte_index;   /* Which module contains us.  */
+    unsigned long mte_offset;  /* Where it is in the module.  */
+    unsigned long nte_index;   /* The name of the label.  */
+    unsigned long file_delta;  /* Where it is defined.  */
+    unsigned short scope;      /* How visible the label is.  */
+  }
+  entry;
+};
+typedef union bfd_sym_contained_labels_table_entry bfd_sym_contained_labels_table_entry;
+
+/* CONTAINED TYPES TABLE (CTTE)
+   Contained Types define the named types that are in the module.  It is used to
+   map name indices into type indices.  The type entries in the table are in
+   alphabetical order by type name.  */
+
+union bfd_sym_contained_types_table_entry
+{
+  struct
+  {
+    /* END_OF_LIST, SOURCE_FILE_CHANGE, or type table entry.  */
+    unsigned long type;
+  }
+  generic;
+
+  struct
+  {
+    /* SOURCE_FILE_CHANGE.  */
+    unsigned long type;
+    bfd_sym_file_reference fref;
+  }
+  file;
+
+  struct
+  {
+    /* < SOURCE_FILE_CHANGE.  */
+    unsigned long tte_index; 
+    unsigned long nte_index;
+    unsigned long file_delta; /* From last file definition.  */
+  }
+  entry;
+};
+typedef union bfd_sym_contained_types_table_entry bfd_sym_contained_types_table_entry;
+
+/* TYPE TABLE (TTE).  */
+
+typedef unsigned long bfd_sym_type_table_entry;
+
+/* TYPE INFORMATION TABLE (TINFO).  */
+
+struct bfd_sym_type_information_table_entry
+{
+  unsigned long nte_index;
+  unsigned long physical_size;
+  unsigned long logical_size;
+  unsigned long offset;
+};
+typedef struct bfd_sym_type_information_table_entry bfd_sym_type_information_table_entry;
+
+/* FILE REFERENCES INDEX TABLE (FITE)
+   The FRTE INDEX TABLE indexes into the FILE REFERENCE TABLE above.  The FRTE
+   at that index is the FILE_SOURCE_START for a series of files.  The FRTEs are
+   indexed from 1.  The list is terminated with an END_OF_LIST.  */
+
+union bfd_sym_file_references_index_table_entry
+{
+  struct
+  {
+    unsigned long type;
+  }
+  generic;
+  
+  struct
+  {
+    unsigned long frte_index;  /* Index into the FRTE table.  */
+    unsigned long nte_index;   /* Name table index, gives filename.  */
+  }
+  entry;
+};
+typedef union bfd_sym_file_references_index_table_entry bfd_sym_file_references_index_table_entry;
+
+/* CONSTANT POOL (CONST)
+   The CONSTANT_POOL consists of entries that start on word boundaries.  The entries
+   are referenced by byte index into the constant pool, not by record number.
+   Each entry takes the form:
+   <16-bit size>
+   <that many bytes of stuff>
+   Entries do not cross page boundaries.  */
+
+typedef short bfd_sym_constant_pool_entry;
+
+/* The DISK_SYMBOL_HEADER_BLOCK is the first record in a .SYM file,
+   defining the physical characteristics of the symbolic information.
+   The remainder of the * .SYM file is stored in fixed block
+   allocations. For the purposes of paging, the * file is considered
+   to be an array of dshb_page_size blocks, with block 0 (and *
+   possibly more) devoted to the DISK_SYMBOL_HEADER_BLOCK.
+   The dti_object_count field means that the allowed indices for that
+   type of object are 0 .. dti_object_count. An index of 0, although
+   allowed, is never done.  However, an 0th entry is created in the
+   table.  That entry is filled with all zeroes.  The reason for this
+   is to avoid off-by-one programming errors that would otherwise
+   occur: an index of k *MEANS* k, not k-1 when going to the disk
+   table.  */
+
+struct bfd_sym_table_info
+{
+  unsigned long dti_first_page;   /* First page for this table.  */
+  unsigned long dti_page_count;   /* Number of pages for the table.  */
+  unsigned long dti_object_count; /* Number of objects in the table.  */
+};
+typedef struct bfd_sym_table_info bfd_sym_table_info;
+
+struct bfd_sym_header_block 
+{
+  unsigned char dshb_id[32];      /* Version information.  */
+  unsigned short dshb_page_size;  /* Size of the pages/blocks.  */
+  unsigned long dshb_hash_page;   /* Disk page for the hash table.  */
+  unsigned long dshb_root_mte;    /* MTE index of the program root.  */
+  unsigned long dshb_mod_date;    /* modification date of executable.  */
+  bfd_sym_table_info dshb_frte;   /* Per TABLE information.  */
+  bfd_sym_table_info dshb_rte;
+  bfd_sym_table_info dshb_mte;
+  bfd_sym_table_info dshb_cmte;
+  bfd_sym_table_info dshb_cvte;
+  bfd_sym_table_info dshb_csnte;
+  bfd_sym_table_info dshb_clte;
+  bfd_sym_table_info dshb_ctte;
+  bfd_sym_table_info dshb_tte;
+  bfd_sym_table_info dshb_nte;
+  bfd_sym_table_info dshb_tinfo;
+  bfd_sym_table_info dshb_fite;   /* File information.  */
+  bfd_sym_table_info dshb_const;  /* Constant pool.  */
+
+  unsigned char dshb_file_creator[4]; /* Executable's creator.  */
+  unsigned char dshb_file_type[4];    /* Executable's file type.  */
+};
+typedef struct bfd_sym_header_block bfd_sym_header_block;
+
+struct bfd_sym_data_struct
+{
+  unsigned char *name_table;
+  bfd_sym_header_block header;
+  bfd_sym_version version;
+  bfd *sbfd;
+};
+typedef struct bfd_sym_data_struct bfd_sym_data_struct;
+
+extern boolean               bfd_sym_mkobject
+  PARAMS ((bfd *));
+extern void                  bfd_sym_print_symbol
+  PARAMS ((bfd *, PTR, asymbol *, bfd_print_symbol_type));
+extern boolean               bfd_sym_valid
+  PARAMS ((bfd *));
+extern unsigned char *       bfd_sym_read_name_table
+  PARAMS ((bfd *, bfd_sym_header_block *));
+extern void                  bfd_sym_parse_file_reference_v32
+  PARAMS ((unsigned char *, size_t, bfd_sym_file_reference *));
+extern void                  bfd_sym_parse_disk_table_v32
+  PARAMS ((unsigned char *, size_t, bfd_sym_table_info *));
+extern void                  bfd_sym_parse_header_v32
+  PARAMS ((unsigned char *, size_t, bfd_sym_header_block *));
+extern int                   bfd_sym_read_header_v32
+  PARAMS ((bfd *, bfd_sym_header_block *));
+extern int                   bfd_sym_read_header_v34
+  PARAMS ((bfd *, bfd_sym_header_block *));
+extern int                   bfd_sym_read_header
+  PARAMS ((bfd *, bfd_sym_header_block *, bfd_sym_version));
+extern int                   bfd_sym_read_version
+  PARAMS ((bfd *, bfd_sym_version *));
+extern void                  bfd_sym_display_table_summary
+  PARAMS ((FILE *, bfd_sym_table_info *, const char *));
+extern void                  bfd_sym_display_header
+  PARAMS ((FILE *, bfd_sym_header_block *));
+extern void                  bfd_sym_parse_resources_table_entry_v32
+  PARAMS ((unsigned char *, size_t, bfd_sym_resources_table_entry *));
+extern void                  bfd_sym_parse_modules_table_entry_v33
+  PARAMS ((unsigned char *, size_t, bfd_sym_modules_table_entry *));
+extern void                  bfd_sym_parse_file_references_table_entry_v32
+  PARAMS ((unsigned char *, size_t, bfd_sym_file_references_table_entry *));
+extern void                  bfd_sym_parse_contained_modules_table_entry_v32
+  PARAMS ((unsigned char *, size_t, bfd_sym_contained_modules_table_entry *));
+extern void                  bfd_sym_parse_contained_variables_table_entry_v32
+  PARAMS ((unsigned char *, size_t, bfd_sym_contained_variables_table_entry *));
+extern void                  bfd_sym_parse_contained_statements_table_entry_v32
+  PARAMS ((unsigned char *, size_t, bfd_sym_contained_statements_table_entry *));
+extern void                  bfd_sym_parse_contained_labels_table_entry_v32
+  PARAMS ((unsigned char *, size_t, bfd_sym_contained_labels_table_entry *));
+extern void                  bfd_sym_parse_type_table_entry_v32
+  PARAMS ((unsigned char *, size_t, bfd_sym_type_table_entry *));
+extern int                   bfd_sym_fetch_resources_table_entry
+  PARAMS ((bfd *, bfd_sym_resources_table_entry *, unsigned long));
+extern int                   bfd_sym_fetch_modules_table_entry
+  PARAMS ((bfd *, bfd_sym_modules_table_entry *, unsigned long));
+extern int                   bfd_sym_fetch_file_references_table_entry
+  PARAMS ((bfd *, bfd_sym_file_references_table_entry *, unsigned long));
+extern int                   bfd_sym_fetch_contained_modules_table_entry
+  PARAMS ((bfd *, bfd_sym_contained_modules_table_entry *, unsigned long));
+extern int                   bfd_sym_fetch_contained_variables_table_entry
+  PARAMS ((bfd *, bfd_sym_contained_variables_table_entry *, unsigned long));
+extern int                   bfd_sym_fetch_contained_statements_table_entry
+  PARAMS ((bfd *, bfd_sym_contained_statements_table_entry *, unsigned long));
+extern int                   bfd_sym_fetch_contained_labels_table_entry
+  PARAMS ((bfd *, bfd_sym_contained_labels_table_entry *, unsigned long));
+extern int                   bfd_sym_fetch_contained_types_table_entry
+  PARAMS ((bfd *, bfd_sym_contained_types_table_entry *, unsigned long));
+extern int                   bfd_sym_fetch_file_references_index_table_entry
+  PARAMS ((bfd *, bfd_sym_file_references_index_table_entry *, unsigned long));
+extern int                   bfd_sym_fetch_constant_pool_entry
+  PARAMS ((bfd *, bfd_sym_constant_pool_entry *, unsigned long));
+extern int                   bfd_sym_fetch_type_table_entry
+  PARAMS ((bfd *, bfd_sym_type_table_entry *, unsigned long));
+extern int                   bfd_sym_fetch_type_information_table_entry
+  PARAMS ((bfd *, bfd_sym_type_information_table_entry *, unsigned long));
+extern int                   bfd_sym_fetch_type_table_information
+  PARAMS ((bfd *, bfd_sym_type_information_table_entry *, unsigned long));
+extern const unsigned char * bfd_sym_symbol_name
+  PARAMS ((bfd *, unsigned long));
+extern const unsigned char * bfd_sym_module_name
+  PARAMS ((bfd *, unsigned long));
+extern const char *          bfd_sym_unparse_storage_kind
+  PARAMS ((enum bfd_sym_storage_kind));
+extern const char *          bfd_sym_unparse_storage_class
+  PARAMS ((enum bfd_sym_storage_class));
+extern const char *          bfd_sym_unparse_module_kind
+  PARAMS ((enum bfd_sym_module_kind));
+extern const char *          bfd_sym_unparse_symbol_scope
+  PARAMS ((enum bfd_sym_symbol_scope));
+extern void                  bfd_sym_print_file_reference
+  PARAMS ((bfd *, FILE *, bfd_sym_file_reference *));
+extern void                  bfd_sym_print_resources_table_entry
+  PARAMS ((bfd *, FILE *, bfd_sym_resources_table_entry *));
+extern void                  bfd_sym_print_modules_table_entry
+  PARAMS ((bfd *, FILE *, bfd_sym_modules_table_entry *));
+extern void                  bfd_sym_print_file_references_table_entry
+  PARAMS ((bfd *, FILE *, bfd_sym_file_references_table_entry *));
+extern void                  bfd_sym_print_contained_modules_table_entry
+  PARAMS ((bfd *, FILE *, bfd_sym_contained_modules_table_entry *));
+extern void                  bfd_sym_print_contained_variables_table_entry
+  PARAMS ((bfd *, FILE *f, bfd_sym_contained_variables_table_entry *));
+extern void                  bfd_sym_print_contained_statements_table_entry
+  PARAMS ((bfd *, FILE *, bfd_sym_contained_statements_table_entry *));
+extern void                  bfd_sym_print_contained_labels_table_entry
+  PARAMS ((bfd *, FILE *, bfd_sym_contained_labels_table_entry *));
+extern void                  bfd_sym_print_contained_types_table_entry
+  PARAMS ((bfd *, FILE *, bfd_sym_contained_types_table_entry *));
+extern const char *          bfd_sym_type_operator_name
+  PARAMS ((unsigned char));
+extern const char *          bfd_sym_type_basic_name
+  PARAMS ((unsigned char));
+extern int                   bfd_sym_fetch_long
+  PARAMS ((unsigned char *, unsigned long, unsigned long, unsigned long *, long *));
+extern void                  bfd_sym_print_type_information
+  PARAMS ((bfd *, FILE *, unsigned char *, unsigned long, unsigned long, unsigned long *));
+extern void                  bfd_sym_print_type_information_table_entry
+  PARAMS ((bfd *, FILE *, bfd_sym_type_information_table_entry *));
+extern void                  bfd_sym_print_file_references_index_table_entry
+  PARAMS ((bfd *, FILE *, bfd_sym_file_references_index_table_entry *));
+extern void                  bfd_sym_print_constant_pool_entry
+  PARAMS ((bfd *, FILE *, bfd_sym_constant_pool_entry *));
+extern unsigned char *       bfd_sym_display_name_table_entry
+  PARAMS ((bfd *, FILE *, unsigned char *));
+extern void                  bfd_sym_display_name_table
+  PARAMS ((bfd *, FILE *));
+extern void                  bfd_sym_display_resources_table
+  PARAMS ((bfd *, FILE *));
+extern void                  bfd_sym_display_modules_table
+  PARAMS ((bfd *, FILE *));
+extern void                  bfd_sym_display_file_references_table
+  PARAMS ((bfd *, FILE *));
+extern void                  bfd_sym_display_contained_modules_table
+  PARAMS ((bfd *, FILE *));
+extern void                  bfd_sym_display_contained_variables_table
+  PARAMS ((bfd *, FILE *));
+extern void                  bfd_sym_display_contained_statements_table
+  PARAMS ((bfd *, FILE *));
+extern void                  bfd_sym_display_contained_labels_table
+  PARAMS ((bfd *, FILE *));
+extern void                  bfd_sym_display_contained_types_table
+  PARAMS ((bfd *, FILE *));
+extern void                  bfd_sym_display_file_references_index_table
+  PARAMS ((bfd *, FILE *));
+extern void                  bfd_sym_display_constant_pool
+  PARAMS ((bfd *, FILE *));
+extern void                  bfd_sym_display_type_information_table
+  PARAMS ((bfd *, FILE *));
+extern const bfd_target *    bfd_sym_object_p
+  PARAMS ((bfd *));
+extern asymbol *             bfd_sym_make_empty_symbol
+  PARAMS ((bfd *));
+extern void                  bfd_sym_get_symbol_info
+  PARAMS ((bfd *, asymbol *, symbol_info *));
+extern long                  bfd_sym_get_symtab_upper_bound
+  PARAMS ((bfd *));
+extern long                  bfd_sym_get_symtab
+  PARAMS ((bfd *, asymbol **));
+extern int                   bfd_sym_sizeof_headers
+  PARAMS ((bfd *, boolean));
+
+#endif /* __xSYM_H__ */