]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
This commit was manufactured by cvs2svn to create branch
authornobody <>
Fri, 15 Nov 2002 08:38:39 +0000 (08:38 +0000)
committernobody <>
Fri, 15 Nov 2002 08:38:39 +0000 (08:38 +0000)
'carlton_dictionary-branch'.

Cherrypick from master 2002-11-15 08:38:38 UTC Klee Dienes <kdienes@apple.com> '2002-11-15  Klee Dienes  <kdienes@apple.com>':
    bfd/mach-o-target.c
    bfd/mach-o.c
    bfd/mach-o.h
    bfd/pef-traceback.h
    bfd/pef.c
    bfd/pef.h
    bfd/xsym.c
    bfd/xsym.h
    gdb/config/i386/interix.mh
    gdb/config/i386/interix.mt
    gdb/config/i386/nm-interix.h
    gdb/dummy-frame.c
    gdb/dummy-frame.h
    gdb/i386-interix-nat.c
    gdb/i386-interix-tdep.c
    gdb/reggroups.c
    gdb/reggroups.h
    gdb/testsuite/gdb.mi/gdb792.cc
    gdb/testsuite/gdb.mi/gdb792.exp

19 files changed:
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/xsym.c [new file with mode: 0644]
bfd/xsym.h [new file with mode: 0644]
gdb/config/i386/interix.mh [new file with mode: 0644]
gdb/config/i386/interix.mt [new file with mode: 0644]
gdb/config/i386/nm-interix.h [new file with mode: 0644]
gdb/dummy-frame.c [new file with mode: 0644]
gdb/dummy-frame.h [new file with mode: 0644]
gdb/i386-interix-nat.c [new file with mode: 0644]
gdb/i386-interix-tdep.c [new file with mode: 0644]
gdb/reggroups.c [new file with mode: 0644]
gdb/reggroups.h [new file with mode: 0644]
gdb/testsuite/gdb.mi/gdb792.cc [new file with mode: 0644]
gdb/testsuite/gdb.mi/gdb792.exp [new file with mode: 0644]

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..1daaf98
--- /dev/null
@@ -0,0 +1,2194 @@
+/* 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;
+  unsigned 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 j = 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, j);
+         if (bfd_get_section_by_name (abfd, sname) == NULL)
+           break;
+         j++;
+       }
+
+      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;
+
+         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;
+
+         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, mdata)
+     bfd *abfd;
+     bfd_mach_o_header *header;
+     bfd_mach_o_data_struct *mdata;
+{
+  unsigned int i;
+  enum bfd_architecture cputype;
+  unsigned long cpusubtype;
+
+  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;
+{
+  struct bfd_preserve preserve;
+  bfd_mach_o_header header;
+
+  preserve.marker = NULL;
+  if (bfd_mach_o_read_header (abfd, &header) != 0)
+    goto wrong;
+
+  if (! (header.byteorder == BFD_ENDIAN_BIG
+        || header.byteorder == BFD_ENDIAN_LITTLE))
+    {
+      fprintf (stderr, "unknown header byte-order value 0x%lx\n",
+              (long) header.byteorder);
+      goto wrong;
+    }
+
+  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)))
+    goto wrong;
+
+  preserve.marker = bfd_zalloc (abfd, sizeof (bfd_mach_o_data_struct));
+  if (preserve.marker == NULL
+      || !bfd_preserve_save (abfd, &preserve))
+    goto fail;
+
+  if (bfd_mach_o_scan (abfd, &header,
+                      (bfd_mach_o_data_struct *) preserve.marker) != 0)
+    goto wrong;
+
+  bfd_preserve_finish (abfd, &preserve);
+  return abfd->xvec;
+
+ wrong:
+  bfd_set_error (bfd_error_wrong_format);
+
+ fail:
+  if (preserve.marker != NULL)
+    bfd_preserve_restore (abfd, &preserve);
+  return NULL;
+}
+
+const bfd_target *
+bfd_mach_o_core_p (abfd)
+     bfd *abfd;
+{
+  struct bfd_preserve preserve;
+  bfd_mach_o_header header;
+
+  preserve.marker = NULL;
+  if (bfd_mach_o_read_header (abfd, &header) != 0)
+    goto wrong;
+
+  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)))
+    goto wrong;
+
+  if (header.filetype != BFD_MACH_O_MH_CORE)
+    goto wrong;
+
+  preserve.marker = bfd_zalloc (abfd, sizeof (bfd_mach_o_data_struct));
+  if (preserve.marker == NULL
+      || !bfd_preserve_save (abfd, &preserve))
+    goto fail;
+
+  if (bfd_mach_o_scan (abfd, &header,
+                      (bfd_mach_o_data_struct *) preserve.marker) != 0)
+    goto wrong;
+
+  bfd_preserve_finish (abfd, &preserve);
+  return abfd->xvec;
+
+ wrong:
+  bfd_set_error (bfd_error_wrong_format);
+
+ fail:
+  if (preserve.marker != NULL)
+    bfd_preserve_restore (abfd, &preserve);
+  return NULL;
+}
+
+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 = NULL;
+  unsigned char buf[20];
+  unsigned long i;
+
+  bfd_seek (abfd, 0, SEEK_SET);
+  if (bfd_bread ((PTR) buf, 8, abfd) != 8)
+    goto error;
+
+  adata = (mach_o_fat_data_struct *)
+    bfd_alloc (abfd, sizeof (mach_o_fat_data_struct));
+  if (adata == NULL)
+    goto error;
+
+  adata->magic = bfd_getb32 (buf);
+  adata->nfat_arch = bfd_getb32 (buf + 4);
+  if (adata->magic != 0xcafebabe)
+    goto error;
+
+  adata->archentries = (mach_o_fat_archentry *)
+    bfd_alloc (abfd, adata->nfat_arch * sizeof (mach_o_fat_archentry));
+  if (adata->archentries == NULL)
+    goto error;
+
+  for (i = 0; i < adata->nfat_arch; i++)
+    {
+      bfd_seek (abfd, 8 + 20 * i, SEEK_SET);
+
+      if (bfd_bread ((PTR) buf, 20, abfd) != 20)
+       goto error;
+      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;
+
+ error:
+  if (adata != NULL)
+    bfd_release (abfd, adata);
+  bfd_set_error (bfd_error_wrong_format);
+  return NULL;
+}
+
+bfd *
+bfd_mach_o_openr_next_archived_file (archive, prev)
+  bfd *archive;
+  bfd *prev;
+{
+  mach_o_fat_data_struct *adata;
+  mach_o_fat_archentry *entry = NULL;
+  unsigned long i;
+
+  adata = (mach_o_fat_data_struct *) archive->tdata.mach_o_fat_data;
+  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 (abfd, section, mcommand, msection)
+     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 (abfd, type, mcommand)
+     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;
+
+                 val = *((unsigned long *) (buf + size - offset));
+                 if (! found_nonnull)
+                   {
+                     if (val != 0)
+                       found_nonnull = 1;
+                   }
+                 else if (val == 0x0)
+                   {
+                     unsigned long bottom;
+                     unsigned long top;
+
+                     bottom = seg->fileoff + seg->filesize - offset;
+                     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..f780273
--- /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 *, bfd_mach_o_data_struct *));
+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..2f12028
--- /dev/null
+++ b/bfd/pef.c
@@ -0,0 +1,1312 @@
+/* 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;
+{
+  const unsigned long ARCH_POWERPC = 0x70777063; /* 'pwpc' */
+  const unsigned long ARCH_M68K = 0x6d36386b; /* 'm68k' */
+
+  *subtype = bfd_arch_unknown;
+  *type = bfd_arch_unknown;
+
+  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, mdata)
+     bfd *abfd;
+     bfd_pef_header *header;
+     bfd_pef_data_struct *mdata;
+{
+  unsigned int i;
+  enum bfd_architecture cputype;
+  unsigned long cpusubtype;
+
+  mdata->header = *header;
+
+  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 ()));
+      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;
+{
+  struct bfd_preserve preserve;
+  bfd_pef_header header;
+
+  preserve.marker = NULL;
+  if (bfd_pef_read_header (abfd, &header) != 0)
+    goto wrong;
+
+  if (header.tag1 != BFD_PEF_TAG1 || header.tag2 != BFD_PEF_TAG2)
+    goto wrong;
+
+  preserve.marker = bfd_zalloc (abfd, sizeof (bfd_pef_data_struct));
+  if (preserve.marker == NULL
+      || !bfd_preserve_save (abfd, &preserve))
+    goto fail;
+
+  if (bfd_pef_scan (abfd, &header,
+                   (bfd_pef_data_struct *) preserve.marker) != 0)
+    goto wrong;
+
+  bfd_preserve_finish (abfd, &preserve);
+  return abfd->xvec;
+
+ wrong:
+  bfd_set_error (bfd_error_wrong_format);
+
+ fail:
+  if (preserve.marker != NULL)
+    bfd_preserve_restore (abfd, &preserve);
+  return NULL;
+}
+
+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;
+
+  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;
+{
+  struct bfd_preserve preserve;
+  bfd_pef_xlib_header header;
+
+  if (bfd_pef_xlib_read_header (abfd, &header) != 0)
+    {
+      bfd_set_error (bfd_error_wrong_format);
+      return NULL;
+    }
+
+  if ((header.tag1 != BFD_PEF_XLIB_TAG1)
+      || ((header.tag2 != BFD_PEF_VLIB_TAG2)
+         && (header.tag2 != BFD_PEF_BLIB_TAG2)))
+    {
+      bfd_set_error (bfd_error_wrong_format);
+      return NULL;
+    }
+
+  if (! bfd_preserve_save (abfd, &preserve))
+    {
+      bfd_set_error (bfd_error_wrong_format);
+      return NULL;
+    }
+
+  if (bfd_pef_xlib_scan (abfd, &header) != 0)
+    {
+      bfd_preserve_restore (abfd, &preserve);
+      bfd_set_error (bfd_error_wrong_format);
+      return NULL;
+    }
+
+  bfd_preserve_finish (abfd, &preserve);
+  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..caeb710
--- /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 *, bfd_pef_data_struct *));
diff --git a/bfd/xsym.c b/bfd/xsym.c
new file mode 100644 (file)
index 0000000..e6b3c4b
--- /dev/null
@@ -0,0 +1,2484 @@
+/* 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) PARAMS ((unsigned char *, size_t,
+                         bfd_sym_resources_table_entry *));
+  unsigned long offset;
+  unsigned long entry_size;
+  unsigned char buf[18];
+  bfd_sym_data_struct *sdata = NULL;
+
+  parser = 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) PARAMS ((unsigned char *, size_t,
+                         bfd_sym_modules_table_entry *));
+  unsigned long offset;
+  unsigned long entry_size;
+  unsigned char buf[46];
+  bfd_sym_data_struct *sdata = NULL;
+
+  parser = 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) PARAMS ((unsigned char *, size_t,
+                         bfd_sym_file_references_table_entry *));
+  unsigned long offset;
+  unsigned long entry_size = 0;
+  unsigned char buf[8];
+  bfd_sym_data_struct *sdata = NULL;
+
+  parser = 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) PARAMS ((unsigned char *, size_t,
+                         bfd_sym_contained_modules_table_entry *));
+  unsigned long offset;
+  unsigned long entry_size = 0;
+  unsigned char buf[6];
+  bfd_sym_data_struct *sdata = NULL;
+
+  parser = 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) PARAMS ((unsigned char *, size_t,
+                         bfd_sym_contained_variables_table_entry *));
+  unsigned long offset;
+  unsigned long entry_size = 0;
+  unsigned char buf[26];
+  bfd_sym_data_struct *sdata = NULL;
+
+  parser = 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) PARAMS ((unsigned char *, size_t,
+                         bfd_sym_contained_statements_table_entry *));
+  unsigned long offset;
+  unsigned long entry_size = 0;
+  unsigned char buf[8];
+  bfd_sym_data_struct *sdata = NULL;
+
+  parser = 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) PARAMS ((unsigned char *, size_t,
+                         bfd_sym_contained_labels_table_entry *));
+  unsigned long offset;
+  unsigned long entry_size = 0;
+  unsigned char buf[12];
+  bfd_sym_data_struct *sdata = NULL;
+
+  parser = 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) PARAMS ((unsigned char *, size_t,
+                         bfd_sym_contained_types_table_entry *));
+  unsigned long offset;
+  unsigned long entry_size = 0;
+  unsigned char buf[0];
+  bfd_sym_data_struct *sdata = NULL;
+
+  parser = 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) PARAMS ((unsigned char *, size_t,
+                         bfd_sym_file_references_index_table_entry *));
+  unsigned long offset;
+  unsigned long entry_size = 0;
+  unsigned char buf[0];
+  bfd_sym_data_struct *sdata = NULL;
+
+  parser = 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) PARAMS ((unsigned char *, size_t,
+                         bfd_sym_constant_pool_entry *));
+  unsigned long offset;
+  unsigned long entry_size = 0;
+  unsigned char buf[0];
+  bfd_sym_data_struct *sdata = NULL;
+
+  parser = 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) PARAMS ((unsigned char *, size_t,
+                         bfd_sym_type_table_entry *));
+  unsigned long offset;
+  unsigned long entry_size = 0;
+  unsigned char buf[4];
+  bfd_sym_data_struct *sdata = NULL;
+
+  parser = 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");
+       }
+    }
+}
+
+int
+bfd_sym_scan (abfd, version, mdata)
+     bfd *abfd;
+     bfd_sym_version version;
+     bfd_sym_data_struct *mdata;
+{
+  asection *bfdsec;
+  const char *name = "symbols";
+
+  mdata->name_table = 0;
+  mdata->sbfd = abfd;
+  mdata->version = version;
+
+  bfd_seek (abfd, 0, SEEK_SET);
+  if (bfd_sym_read_header (abfd, &mdata->header, mdata->version) != 0)
+    return -1;
+
+  mdata->name_table = bfd_sym_read_name_table (abfd, &mdata->header);
+  if (mdata->name_table == NULL)
+    return -1;
+
+  bfdsec = bfd_make_section_anyway (abfd, name);
+  if (bfdsec == NULL)
+    return -1;
+
+  bfdsec->vma = 0;
+  bfdsec->lma = 0;
+  bfdsec->_raw_size = 0;
+  bfdsec->filepos = 0;
+  bfdsec->alignment_power = 0;
+
+  bfdsec->flags = SEC_HAS_CONTENTS;
+
+  abfd->tdata.sym_data = mdata;
+
+  return 0;
+}
+
+const bfd_target *
+bfd_sym_object_p (abfd)
+     bfd *abfd;
+{
+  struct bfd_preserve preserve;
+  bfd_sym_version version = -1;
+
+  preserve.marker = NULL;
+  bfd_seek (abfd, 0, SEEK_SET);
+  if (bfd_sym_read_version (abfd, &version) != 0)
+    goto wrong;
+
+  preserve.marker = bfd_alloc (abfd, sizeof (bfd_sym_data_struct));
+  if (preserve.marker == NULL
+      || ! bfd_preserve_save (abfd, &preserve))
+    goto fail;
+
+  if (bfd_sym_scan (abfd, version,
+                   (bfd_sym_data_struct *) preserve.marker) != 0)
+    goto wrong;
+
+  bfd_preserve_finish (abfd, &preserve);
+  return abfd->xvec;
+
+ wrong:
+  bfd_set_error (bfd_error_wrong_format);
+
+ fail:
+  if (preserve.marker != NULL)
+    bfd_preserve_restore (abfd, &preserve);
+  return NULL;
+}
+
+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..a381c55
--- /dev/null
@@ -0,0 +1,701 @@
+/* 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 int                   bfd_sym_scan
+  PARAMS ((bfd *, bfd_sym_version, bfd_sym_data_struct *));
+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__ */
diff --git a/gdb/config/i386/interix.mh b/gdb/config/i386/interix.mh
new file mode 100644 (file)
index 0000000..23311d6
--- /dev/null
@@ -0,0 +1,9 @@
+# Host: Intel 386 running Interix
+XDEPFILES= 
+NATDEPFILES= corelow.o core-regset.o fork-child.o i386-interix-nat.o \
+       procfs.o proc-api.o proc-events.o proc-flags.o proc-why.o
+NAT_FILE= nm-interix.h
+XM_FILE= xm-interix.h
+# The below may be temporary; mmalloc relies on sbrk() at the moment
+MMALLOC=
+MMALLOC_CFLAGS=-DNO_MMALLOC
diff --git a/gdb/config/i386/interix.mt b/gdb/config/i386/interix.mt
new file mode 100644 (file)
index 0000000..8d60962
--- /dev/null
@@ -0,0 +1,3 @@
+# Target: Intel 386 running Interix
+TDEPFILES= i386-tdep.o i387-tdep.o i386-interix-tdep.o solib.o solib-pei.o
+TM_FILE= tm-i386.h
diff --git a/gdb/config/i386/nm-interix.h b/gdb/config/i386/nm-interix.h
new file mode 100644 (file)
index 0000000..b8b003a
--- /dev/null
@@ -0,0 +1,35 @@
+/* Native-dependent definitions for Intel 386 running Interix, for GDB.
+   Copyright 1986, 1987, 1989, 1992, 1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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 NM_INTERIX_H
+#define NM_INTERIX_H
+
+/* Be shared lib aware.  */
+#include "solib.h"
+
+/* submodes of USE_PROC_FS.  */
+#define UNIXWARE
+
+/* It's ALMOST coff; bfd does the same thing. Mostly used in coffread.c.  */
+#define COFF_IMAGE_WITH_PE
+
+/* Turn on our own child_pid_to_exec_file.  */
+#define CHILD_PID_TO_EXEC_FILE
+
+#endif /* NM_INTERIX_H */
diff --git a/gdb/dummy-frame.c b/gdb/dummy-frame.c
new file mode 100644 (file)
index 0000000..ddc4db8
--- /dev/null
@@ -0,0 +1,310 @@
+/* Code dealing with dummy stack frames, for GDB, the GNU debugger.
+
+   Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
+   1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 Free Software
+   Foundation, Inc.
+
+   This file is part of GDB.
+
+   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 "defs.h"
+#include "dummy-frame.h"
+#include "regcache.h"
+#include "frame.h"
+#include "inferior.h"
+#include "gdb_assert.h"
+
+/* Dummy frame.  This saves the processor state just prior to setting
+   up the inferior function call.  Older targets save the registers
+   on the target stack (but that really slows down function calls).  */
+
+struct dummy_frame
+{
+  struct dummy_frame *next;
+
+  CORE_ADDR pc;
+  CORE_ADDR fp;
+  CORE_ADDR sp;
+  CORE_ADDR top;
+  struct regcache *regcache;
+
+  /* Address range of the call dummy code.  Look for PC in the range
+     [LO..HI) (after allowing for DECR_PC_AFTER_BREAK).  */
+  CORE_ADDR call_lo;
+  CORE_ADDR call_hi;
+};
+
+static struct dummy_frame *dummy_frame_stack = NULL;
+
+/* Function: find_dummy_frame(pc, fp, sp)
+
+   Search the stack of dummy frames for one matching the given PC and
+   FP/SP.  Unlike PC_IN_CALL_DUMMY, this function doesn't need to
+   adjust for DECR_PC_AFTER_BREAK.  This is because it is only legal
+   to call this function after the PC has been adjusted.  */
+
+static struct dummy_frame *
+find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp)
+{
+  struct dummy_frame *dummyframe;
+
+  for (dummyframe = dummy_frame_stack; dummyframe != NULL;
+       dummyframe = dummyframe->next)
+    {
+      /* Does the PC fall within the dummy frame's breakpoint
+         instruction.  If not, discard this one.  */
+      if (!(pc >= dummyframe->call_lo && pc < dummyframe->call_hi))
+       continue;
+      /* Does the FP match?  */
+      if (dummyframe->top != 0)
+       {
+         /* If the target architecture explicitly saved the
+            top-of-stack before the inferior function call, assume
+            that that same architecture will always pass in an FP
+            (frame base) value that eactly matches that saved TOS.
+            Don't check the saved SP and SP as they can lead to false
+            hits.  */
+         if (fp != dummyframe->top)
+           continue;
+       }
+      else
+       {
+         /* An older target that hasn't explicitly or implicitly
+             saved the dummy frame's top-of-stack.  Try matching the
+             FP against the saved SP and FP.  NOTE: If you're trying
+             to fix a problem with GDB not correctly finding a dummy
+             frame, check the comments that go with FRAME_ALIGN() and
+             SAVE_DUMMY_FRAME_TOS().  */
+         if (fp != dummyframe->fp && fp != dummyframe->sp)
+           continue;
+       }
+      /* The FP matches this dummy frame.  */
+      return dummyframe;
+    }
+
+  return NULL;
+}
+
+struct dummy_frame *
+cached_find_dummy_frame (struct frame_info *frame, void **cache)
+{
+  if ((*cache) == NULL)
+    (*cache) = find_dummy_frame (frame->pc, frame->frame);
+  return (*cache);
+}
+
+struct regcache *
+generic_find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp)
+{
+  struct dummy_frame *dummy = find_dummy_frame (pc, fp);
+  if (dummy != NULL)
+    return dummy->regcache;
+  else
+    return NULL;
+}
+
+char *
+deprecated_generic_find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp)
+{
+  struct regcache *regcache = generic_find_dummy_frame (pc, fp);
+  if (regcache == NULL)
+    return NULL;
+  return deprecated_grub_regcache_for_registers (regcache);
+}
+
+/* Function: pc_in_call_dummy (pc, sp, fp)
+
+   Return true if the PC falls in a dummy frame created by gdb for an
+   inferior call.  The code below which allows DECR_PC_AFTER_BREAK is
+   for infrun.c, which may give the function a PC without that
+   subtracted out.  */
+
+int
+generic_pc_in_call_dummy (CORE_ADDR pc, CORE_ADDR sp, CORE_ADDR fp)
+{
+  struct dummy_frame *dummyframe;
+  for (dummyframe = dummy_frame_stack;
+       dummyframe != NULL;
+       dummyframe = dummyframe->next)
+    {
+      if ((pc >= dummyframe->call_lo)
+         && (pc < dummyframe->call_hi + DECR_PC_AFTER_BREAK))
+       return 1;
+    }
+  return 0;
+}
+
+/* Function: read_register_dummy 
+   Find a saved register from before GDB calls a function in the inferior */
+
+CORE_ADDR
+deprecated_read_register_dummy (CORE_ADDR pc, CORE_ADDR fp, int regno)
+{
+  struct regcache *dummy_regs = generic_find_dummy_frame (pc, fp);
+
+  if (dummy_regs)
+    {
+      /* NOTE: cagney/2002-08-12: Replaced a call to
+        regcache_raw_read_as_address() with a call to
+        regcache_cooked_read_unsigned().  The old, ...as_address
+        function was eventually calling extract_unsigned_integer (via
+        extract_address) to unpack the registers value.  The below is
+        doing an unsigned extract so that it is functionally
+        equivalent.  The read needs to be cooked as, otherwise, it
+        will never correctly return the value of a register in the
+        [NUM_REGS .. NUM_REGS+NUM_PSEUDO_REGS) range.  */
+      ULONGEST val;
+      regcache_cooked_read_unsigned (dummy_regs, regno, &val);
+      return val;
+    }
+  else
+    return 0;
+}
+
+/* Save all the registers on the dummy frame stack.  Most ports save the
+   registers on the target stack.  This results in lots of unnecessary memory
+   references, which are slow when debugging via a serial line.  Instead, we
+   save all the registers internally, and never write them to the stack.  The
+   registers get restored when the called function returns to the entry point,
+   where a breakpoint is laying in wait.  */
+
+void
+generic_push_dummy_frame (void)
+{
+  struct dummy_frame *dummy_frame;
+  CORE_ADDR fp = (get_current_frame ())->frame;
+
+  /* check to see if there are stale dummy frames, 
+     perhaps left over from when a longjump took us out of a 
+     function that was called by the debugger */
+
+  dummy_frame = dummy_frame_stack;
+  while (dummy_frame)
+    if (INNER_THAN (dummy_frame->fp, fp))      /* stale -- destroy! */
+      {
+       dummy_frame_stack = dummy_frame->next;
+       regcache_xfree (dummy_frame->regcache);
+       xfree (dummy_frame);
+       dummy_frame = dummy_frame_stack;
+      }
+    else
+      dummy_frame = dummy_frame->next;
+
+  dummy_frame = xmalloc (sizeof (struct dummy_frame));
+  dummy_frame->regcache = regcache_xmalloc (current_gdbarch);
+
+  dummy_frame->pc = read_pc ();
+  dummy_frame->sp = read_sp ();
+  dummy_frame->top = 0;
+  dummy_frame->fp = fp;
+  regcache_cpy (dummy_frame->regcache, current_regcache);
+  dummy_frame->next = dummy_frame_stack;
+  dummy_frame_stack = dummy_frame;
+}
+
+void
+generic_save_dummy_frame_tos (CORE_ADDR sp)
+{
+  dummy_frame_stack->top = sp;
+}
+
+/* Record the upper/lower bounds on the address of the call dummy.  */
+
+void
+generic_save_call_dummy_addr (CORE_ADDR lo, CORE_ADDR hi)
+{
+  dummy_frame_stack->call_lo = lo;
+  dummy_frame_stack->call_hi = hi;
+}
+
+/* Restore the machine state from either the saved dummy stack or a
+   real stack frame. */
+
+void
+generic_pop_current_frame (void (*popper) (struct frame_info * frame))
+{
+  struct frame_info *frame = get_current_frame ();
+
+  if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
+    generic_pop_dummy_frame ();
+  else
+    (*popper) (frame);
+}
+
+/* Function: pop_dummy_frame
+   Restore the machine state from a saved dummy stack frame. */
+
+void
+generic_pop_dummy_frame (void)
+{
+  struct dummy_frame *dummy_frame = dummy_frame_stack;
+
+  /* FIXME: what if the first frame isn't the right one, eg..
+     because one call-by-hand function has done a longjmp into another one? */
+
+  if (!dummy_frame)
+    error ("Can't pop dummy frame!");
+  dummy_frame_stack = dummy_frame->next;
+  regcache_cpy (current_regcache, dummy_frame->regcache);
+  flush_cached_frames ();
+
+  regcache_xfree (dummy_frame->regcache);
+  xfree (dummy_frame);
+}
+
+/* Function: fix_call_dummy
+   Stub function.  Generic dummy frames typically do not need to fix
+   the frame being created */
+
+void
+generic_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
+                       struct value **args, struct type *type, int gcc_p)
+{
+  return;
+}
+
+/* Given a call-dummy dummy-frame, return the registers.  Here the
+   register value is taken from the local copy of the register buffer.  */
+
+void
+dummy_frame_register_unwind (struct frame_info *frame, void **cache,
+                            int regnum, int *optimized,
+                            enum lval_type *lvalp, CORE_ADDR *addrp,
+                            int *realnum, void *bufferp)
+{
+  struct dummy_frame *dummy = cached_find_dummy_frame (frame, cache);
+  gdb_assert (dummy != NULL);
+
+  /* Describe the register's location.  Generic dummy frames always
+     have the register value in an ``expression''.  */
+  *optimized = 0;
+  *lvalp = not_lval;
+  *addrp = 0;
+  *realnum = -1;
+
+  /* If needed, find and return the value of the register.  */
+  if (bufferp != NULL)
+    {
+      /* Return the actual value.  */
+      /* Use the regcache_cooked_read() method so that it, on the fly,
+         constructs either a raw or pseudo register from the raw
+         register cache.  */
+      regcache_cooked_read (dummy->regcache, regnum, bufferp);
+    }
+}
+
diff --git a/gdb/dummy-frame.h b/gdb/dummy-frame.h
new file mode 100644 (file)
index 0000000..bd4e199
--- /dev/null
@@ -0,0 +1,65 @@
+/* Code dealing with dummy stack frames, for GDB, the GNU debugger.
+
+   Copyright 2002 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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.  */
+
+#if !defined (DUMMY_FRAME_H)
+#define DUMMY_FRAME_H 1
+
+struct frame_info;
+struct regcache;
+
+/* GENERIC DUMMY FRAMES
+  
+   The following code serves to maintain the dummy stack frames for
+   inferior function calls (ie. when gdb calls into the inferior via
+   call_function_by_hand).  This code saves the machine state before
+   the call in host memory, so we must maintain an independent stack
+   and keep it consistant etc.  I am attempting to make this code
+   generic enough to be used by many targets.
+   The cheapest and most generic way to do CALL_DUMMY on a new target
+   is probably to define CALL_DUMMY to be empty, CALL_DUMMY_LENGTH to
+   zero, and CALL_DUMMY_LOCATION to AT_ENTRY.  Then you must remember
+   to define PUSH_RETURN_ADDRESS, because no call instruction will be
+   being executed by the target.  Also FRAME_CHAIN_VALID as
+   generic_{file,func}_frame_chain_valid and FIX_CALL_DUMMY as
+   generic_fix_call_dummy.  */
+
+/* Assuming that FRAME is a dummy, return a register value for the
+   previous frame.  */
+
+extern void dummy_frame_register_unwind (struct frame_info *frame,
+                                        void **unwind_cache,
+                                        int regnum,
+                                        int *optimized,
+                                        enum lval_type *lvalp,
+                                        CORE_ADDR *addrp,
+                                        int *realnump,
+                                        void *valuep);
+
+/* Return the regcache that belongs to the dummy-frame identifed by PC
+   and FP, or NULL if no such frame exists.  */
+/* FIXME: cagney/2002-11-08: The function only exists because of
+   deprecated_generic_get_saved_register.  Eliminate that function and
+   this, to, can go.  */
+
+extern struct regcache *generic_find_dummy_frame (CORE_ADDR pc,
+                                                 CORE_ADDR fp);
+#endif /* !defined (DUMMY_FRAME_H)  */
diff --git a/gdb/i386-interix-nat.c b/gdb/i386-interix-nat.c
new file mode 100644 (file)
index 0000000..9c4daed
--- /dev/null
@@ -0,0 +1,190 @@
+/* Native-dependent code for Interix running on i386's, for GDB.
+   Copyright 2002 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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 "defs.h"
+
+#include <sys/procfs.h>
+#include <inferior.h>
+#include <fcntl.h>
+
+#include <i386-tdep.h>
+#include "gdb_string.h"
+#include "gdbcore.h"
+#include "gregset.h"
+#include "regcache.h"
+
+typedef unsigned long greg_t;
+
+/* This is a duplicate of the table in i386-linux-nat.c.  */
+
+static int regmap[] = {
+  EAX, ECX, EDX, EBX,
+  UESP, EBP, ESI, EDI,
+  EIP, EFL, CS, SS,
+  DS, ES, FS, GS,
+};
+
+/* Forward declarations.  */
+extern void _initialize_core_interix (void);
+extern initialize_file_ftype _initialize_core_interix;
+
+/*  Given a pointer to a general register set in /proc format (gregset_t *),
+    unpack the register contents and supply them as gdb's idea of the current
+    register values.  */
+
+void
+supply_gregset (gregset_t *gregsetp)
+{
+  int regi;
+  greg_t *regp = (greg_t *) & gregsetp->gregs;
+
+  for (regi = 0; regi < I386_NUM_GREGS; regi++)
+    {
+      supply_register (regi, (char *) (regp + regmap[regi]));
+    }
+}
+
+/* Store GDB's value for REGNO in *GREGSETP.  If REGNO is -1, do all
+   of them.  */
+
+void
+fill_gregset (gregset_t *gregsetp, int regno)
+{
+  int regi;
+  greg_t *regp = (greg_t *) gregsetp->gregs;
+
+  for (regi = 0; regi < I386_NUM_GREGS; regi++)
+    if (regno == -1 || regi == regno)
+      regcache_collect (regi, (void *) (regp + regmap[regi]));
+}
+
+/* Fill GDB's register file with the floating-point register values in
+   *FPREGSETP.  */
+
+void
+supply_fpregset (fpregset_t *fpregsetp)
+{
+  i387_supply_fsave ((char *) fpregsetp);
+}
+
+/* Given a pointer to a floating point register set in (fpregset_t *)
+   format, update all of the registers from gdb's idea of the current
+   floating point register set.  */
+
+void
+fill_fpregset (fpregset_t *fpregsetp, int regno)
+{
+  i387_fill_fsave ((char *) fpregsetp, regno);
+}
+
+/* Read the values of either the general register set (WHICH equals 0)
+   or the floating point register set (WHICH equals 2) from the core
+   file data (pointed to by CORE_REG_SECT), and update gdb's idea of
+   their current values.  The CORE_REG_SIZE parameter is compared to
+   the size of the gregset or fpgregset structures (as appropriate) to
+   validate the size of the structure from the core file.  The
+   REG_ADDR parameter is ignored.  */
+
+static void
+fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
+                      CORE_ADDR reg_addr)
+{
+  gdb_gregset_t gregset;
+  gdb_fpregset_t fpregset;
+
+  if (which == 0)
+    {
+      if (core_reg_size != sizeof (gregset))
+        {
+          warning ("wrong size gregset struct in core file");
+        }
+      else
+        {
+          memcpy ((char *) &gregset, core_reg_sect, sizeof (gregset));
+          supply_gregset (&gregset);
+        }
+    }
+  else if (which == 2)
+    {
+      if (core_reg_size != sizeof (fpregset))
+        {
+          warning ("wrong size fpregset struct in core file");
+        }
+      else
+        {
+          memcpy ((char *) &fpregset, core_reg_sect, sizeof (fpregset));
+          supply_fpregset (&fpregset);
+        }
+    }
+}
+
+#include <setjmp.h>
+
+static struct core_fns interix_core_fns =
+{
+  bfd_target_coff_flavour,      /* core_flavour (more or less) */
+  default_check_format,         /* check_format */
+  default_core_sniffer,         /* core_sniffer */
+  fetch_core_registers,         /* core_read_registers */
+  NULL                          /* next */
+};
+
+void
+_initialize_core_interix (void)
+{
+  add_core_fns (&interix_core_fns);
+}
+
+/* We don't have a /proc/pid/file or /proc/pid/exe to read a link from,
+   so read it from the same place ps gets the name.  */
+
+char *
+child_pid_to_exec_file (int pid)
+{
+  char *path;
+  char *buf;
+  int fd, c;
+  char *p;
+
+  xasprintf (&path, "/proc/%d/stat", pid);
+  buf = xcalloc (MAXPATHLEN + 1, sizeof (char));
+  make_cleanup (xfree, path);
+  make_cleanup (xfree, buf);
+
+  fd = open (path, O_RDONLY);
+
+  if (fd < 0)
+    return NULL;
+
+  /* Skip over "Argv0\t".  */
+  lseek (fd, 6, SEEK_SET);
+
+  c = read (fd, buf, MAXPATHLEN);
+  close (fd);
+
+  if (c < 0)
+    return NULL;
+
+  buf[c] = '\0';                /* Ensure null termination.  */
+  p = strchr (buf, '\n');
+  if (p != NULL)
+    *p = '\0';
+
+  return buf;
+}
diff --git a/gdb/i386-interix-tdep.c b/gdb/i386-interix-tdep.c
new file mode 100644 (file)
index 0000000..ff310ec
--- /dev/null
@@ -0,0 +1,365 @@
+/* Target-dependent code for Interix running on i386's, for GDB.
+   Copyright 2002 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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 "defs.h"
+#include "arch-utils.h"
+
+#include "frame.h"
+#include "gdb_string.h"
+#include "gdb-stabs.h"
+#include "gdbcore.h"
+#include "gdbtypes.h"
+#include "i386-tdep.h"
+#include "inferior.h"
+#include "libbfd.h"
+#include "objfiles.h"
+#include "osabi.h"
+#include "regcache.h"
+
+/* offsetof (mcontext_t, gregs.gregs[EBP]) */
+static const int mcontext_EBP_greg_offset = 180;
+
+/* offsetof (mcontext_t, gregs.gregs[EIP]) */
+static const int mcontext_EIP_greg_offset = 184;
+
+/* offsetof (mcontext_t, gregs.gregs[UESP]) */
+static const int mcontext_UESP_greg_offset = 196;
+
+/* offsetof (mcontext_t, gregs.reserved[1]) */
+static const int mcontext_syscall_greg_offset = 4;
+
+/* offsetof (_JUMP_BUFFER, Eip) */
+static const int jump_buffer_Eip_offset = 20;
+
+/* See procfs.c and *interix*.h in config/[alpha,i386].  */
+/* ??? These should be static, but this needs a bit of work before this
+   can be done.  */
+CORE_ADDR tramp_start;
+CORE_ADDR tramp_end;
+CORE_ADDR null_start;
+CORE_ADDR null_end;
+int winver;                     /* Windows NT version number */
+
+/* Forward declarations.  */
+extern void _initialize_i386_interix_tdep (void);
+extern initialize_file_ftype _initialize_i386_interix_tdep;
+
+/* Adjust the section offsets in an objfile structure so that it's correct
+   for the type of symbols being read (or undo it with the _restore
+   arguments).  
+
+   If main programs ever start showing up at other than the default Image
+   Base, this is where that would likely be applied.  */
+
+void
+pei_adjust_objfile_offsets (struct objfile *objfile,
+                            enum objfile_adjusts type)
+{
+  int i;
+  CORE_ADDR symbols_offset;
+
+  switch (type)
+    {
+    case adjust_for_symtab:
+      symbols_offset = NONZERO_LINK_BASE (objfile->obfd);
+      break;
+    case adjust_for_symtab_restore:
+      symbols_offset = -NONZERO_LINK_BASE (objfile->obfd);
+      break;
+    case adjust_for_stabs:
+    case adjust_for_stabs_restore:
+    case adjust_for_dwarf:
+    case adjust_for_dwarf_restore:
+    default:
+      return;
+    }
+
+  for (i = 0; i < SECT_OFF_MAX; i++)
+    {
+      (objfile->section_offsets)->offsets[i] += symbols_offset;
+    }
+}
+
+static int
+i386_interix_pc_in_sigtramp (CORE_ADDR pc, char *name)
+{
+  /* This is sufficient, where used, but is NOT a complete test; There
+     is more in INIT_EXTRA_FRAME_INFO (a.k.a. interix_back_one_frame).  */
+  return ((pc >= tramp_start && pc < tramp_end)
+          || (pc >= null_start && pc < null_end));
+}
+
+static int
+i386_interix_in_solib_call_trampoline (CORE_ADDR pc, char *name)
+{
+  return i386_pe_skip_trampoline_code (pc, name);
+}
+
+static CORE_ADDR
+i386_interix_skip_trampoline_code (CORE_ADDR pc)
+{
+  return i386_pe_skip_trampoline_code (pc, 0);
+}
+
+static void
+i386_interix_init_frame_pc (int fromleaf, struct frame_info *prev)
+{
+  /* Nothing to do on Interix.  */
+}
+
+static int
+i386_interix_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe)
+{
+  /* In the context where this is used, we get the saved PC before we've
+     successfully unwound far enough to be sure what we've got (it may
+     be a signal handler caller).  If we're dealing with a signal
+     handler caller, this will return valid, which is fine.  If not,
+     it'll make the correct test.  */
+  return (thisframe->signal_handler_caller
+          || (chain != 0
+              && !inside_entry_file (read_memory_integer
+                                     (thisframe->frame + 4, 4))));
+}
+
+/* We want to find the previous frame, which on Interix is tricky when signals
+   are involved; set frame->frame appropriately, and also get the pc
+   and tweak signal_handler_caller; this replaces a boatload of nested
+   macros, as well.  */
+static void
+i386_interix_back_one_frame (int fromleaf, struct frame_info *frame)
+{
+  CORE_ADDR ra;
+  CORE_ADDR fm;
+  CORE_ADDR context;
+  long t;
+
+  if (frame == NULL)
+    internal_error (__FILE__, __LINE__, "unexpected NULL frame");
+
+  if (fromleaf)
+    {
+      frame->pc = SAVED_PC_AFTER_CALL (frame->next);
+      return;
+    }
+
+  if (!frame->next)
+    {
+      frame->pc = read_pc ();
+
+      /* Part of the signal stuff...  See below.  */
+      if (stopped_by_random_signal)
+        {
+          /* We know we're in a system call mini-frame; was it
+             NullApi or something else?  */
+          ra = SAVED_PC_AFTER_CALL (frame);
+          if (ra >= null_start && ra < null_end)
+            frame->signal_handler_caller = 1;
+          /* There might also be an indirect call to the mini-frame,
+             putting one more return address on the stack.  (XP only,
+             I think?)  This can't (reasonably) return the address of the 
+             signal handler caller unless it's that situation, so this
+             is safe.  */
+          ra = read_memory_unsigned_integer (read_register (SP_REGNUM) + 4, 4);
+          if (ra >= null_start && ra < null_end)
+            frame->signal_handler_caller = 1;
+        }
+      return;
+    }
+
+  if (!frame->next->signal_handler_caller)
+    {
+      frame->pc = read_memory_integer (frame->next->frame + 4, 4);
+      return;
+    }
+
+  /* This is messy (actually AWFUL)...  The "trampoline" might be 2, 3 
+     or all 5 entities on the frame. 
+
+     Chunk 1 will be present when we're actually in a signal handler.
+     Chunk 2 will be present when an asynchronous signal (one that
+     didn't come in with a system call) is present.
+     We may not (yet) be in the handler, if we're just returning
+     from the call.
+     When we're actually in a handler taken from an asynchronous
+     signal, both will be present.
+
+     Chunk 1:
+     PdxSignalDeliverer's frame 
+     + Context struct    -- not accounted for in any frame
+
+     Chunk 2:
+     + PdxNullPosixApi's frame 
+     + PdxNullApiCaller's frame
+     + Context struct = 0x230  not accounted for in any frame
+
+     The symbol names come from examining objdumps of psxdll.dll;
+     they don't appear in the runtime image.
+
+     For gdb's purposes, we can pile all this into one frame.  */
+
+  ra = frame->next->pc;
+  /* Are we already pointing at PdxNullPosixApi?  We are if
+     this is a signal frame, we're at next-to-top, and were stopped
+     by a random signal (if it wasn't the right address under
+     these circumstances, we wouldn't be here at all by tests above
+     on the prior frame).  */
+  if (frame->next->next == NULL && stopped_by_random_signal)
+    {
+      /* We're pointing at the frame FOR PdxNullApi.  */
+      fm = frame->frame;
+    }
+  else
+    {
+      /* No...  We must be pointing at the frame that was called
+         by PdxSignalDeliverer; back up across the whole mess.  */
+
+      /* Extract the frame for PdxSignalDeliverer.
+         Note: FRAME_CHAIN used the "old" frame pointer because we were
+         a deliverer.  Get the address of the context record that's on
+         here frameless.  */
+      context = read_memory_integer (frame->frame, 4);  /* an Arg */
+
+      /* Now extract the frame pointer contained in the context.  */
+      fm = read_memory_integer (context + mcontext_EBP_greg_offset, 4);
+
+      ra = read_memory_integer (context + mcontext_EIP_greg_offset, 4);
+
+      /* We need to know if we're in a system call because we'll be
+         in a syscall mini-frame, if so, and the rules are different.  */
+      t = (long) read_memory_integer (context + mcontext_syscall_greg_offset,
+                                      4);
+      /* t contains 0 if running free, 1 if blocked on a system call,
+         and 2 if blocked on an exception message (e.g. a trap);
+         we don't expect to get here with a 2.  */
+      if (t != 1)
+        {
+          /* Not at a system call, therefore it can't be NullApi.  */
+          frame->pc = ra;
+          frame->frame = fm;
+          return;
+        }
+
+      /* It's a system call...  Mini frame, then look for NullApi.  */
+      /* Get the RA (on the stack) associated with this...  It's
+         a system call mini-frame.  */
+      ra = read_memory_integer (context + mcontext_UESP_greg_offset, 4);
+
+      if (winver >= 51)
+        {
+          /* Newer versions of Windows NT interpose another return
+             address (but no other "stack frame" stuff) that we need
+             to simply ignore here.  */
+          ra += 4;
+        }
+
+      ra = read_memory_integer (ra, 4);
+
+      if (!(ra >= null_start && ra < null_end))
+        {
+          /* No Null API present; we're done.  */
+          frame->pc = ra;
+          frame->frame = fm;
+          return;
+        }
+    }
+
+  /* At this point, we're looking at the frame for PdxNullPosixApi,
+     in either case.
+
+     PdxNullPosixApi is called by PdxNullApiCaller (which in turn
+     is called by _PdxNullApiCaller (note the _).)
+     PdxNullPosixApiCaller (no _) is a frameless function.
+
+     The saved frame pointer is as fm, but it's not of interest
+     to us because it skips us over the saved context, which is
+     the wrong thing to do, because it skips the interrrupted
+     routine!  PdxNullApiCaller takes as its only argument the
+     address of the context of the interrupded function (which
+     is really in no frame, but jammed on the stack by the system)
+
+     So: fm+0: saved bp
+     fm+4: return address to _PdxNullApiCaller
+     fm+8: arg to PdxNullApiCaller pushed by _Pdx...  */
+
+  fm = read_memory_integer (fm + 0x8, 4);
+
+  /* Extract the second context record.  */
+
+  ra = read_memory_integer (fm + mcontext_EIP_greg_offset, 4);
+  fm = read_memory_integer (fm + mcontext_EBP_greg_offset, 4);
+
+  frame->frame = fm;
+  frame->pc = ra;
+
+  return;
+}
+
+static CORE_ADDR
+i386_interix_frame_saved_pc (struct frame_info *fi)
+{
+  /* Assume that we've already unwound enough to have the caller's address
+     if we're dealing with a signal handler caller (And if that fails,
+     return 0).  */
+  if (fi->signal_handler_caller)
+    return fi->next ? fi->next->pc : 0;
+  else
+    return read_memory_integer (fi->frame + 4, 4);
+}
+
+static void
+i386_interix_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  tdep->struct_return = reg_struct_return;
+  tdep->jb_pc_offset = jump_buffer_Eip_offset;
+
+  set_gdbarch_decr_pc_after_break (gdbarch, 0);
+  set_gdbarch_pc_in_sigtramp (gdbarch, i386_interix_pc_in_sigtramp);
+  set_gdbarch_in_solib_call_trampoline (gdbarch,
+                                        i386_interix_in_solib_call_trampoline);
+  set_gdbarch_skip_trampoline_code (gdbarch,
+                                    i386_interix_skip_trampoline_code);
+  set_gdbarch_init_extra_frame_info (gdbarch, i386_interix_back_one_frame);
+  set_gdbarch_init_frame_pc (gdbarch, i386_interix_init_frame_pc);
+  set_gdbarch_frame_chain_valid (gdbarch, i386_interix_frame_chain_valid);
+  set_gdbarch_frame_saved_pc (gdbarch, i386_interix_frame_saved_pc);
+  set_gdbarch_name_of_malloc (gdbarch, "_malloc");
+}
+
+static enum gdb_osabi
+i386_interix_osabi_sniffer (bfd * abfd)
+{
+  char *target_name = bfd_get_target (abfd);
+
+  if (strcmp (target_name, "pei-i386") == 0)
+    return GDB_OSABI_INTERIX;
+
+  return GDB_OSABI_UNKNOWN;
+}
+
+void
+_initialize_i386_interix_tdep (void)
+{
+  gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour,
+                                  i386_interix_osabi_sniffer);
+
+  gdbarch_register_osabi (bfd_arch_i386, GDB_OSABI_INTERIX,
+                          i386_interix_init_abi);
+}
diff --git a/gdb/reggroups.c b/gdb/reggroups.c
new file mode 100644 (file)
index 0000000..8c3cbb7
--- /dev/null
@@ -0,0 +1,268 @@
+/* Register groupings for GDB, the GNU debugger.
+
+   Copyright 2002 Free Software Foundation, Inc.
+
+   Contributed by Red Hat.
+
+   This file is part of GDB.
+
+   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 "defs.h"
+#include "reggroups.h"
+#include "gdbtypes.h"
+#include "gdb_assert.h"
+#include "regcache.h"
+#include "command.h"
+#include "gdbcmd.h"            /* For maintenanceprintlist.  */
+
+/* Individual register groups.  */
+
+struct reggroup
+{
+  const char *name;
+  enum reggroup_type type;
+};
+
+struct reggroup *
+reggroup_new (const char *name, enum reggroup_type type)
+{
+  struct reggroup *group = XMALLOC (struct reggroup);
+  group->name = name;
+  group->type = type;
+  return group;
+}
+
+/* Register group attributes.  */
+
+const char *
+reggroup_name (struct reggroup *group)
+{
+  return group->name;
+}
+
+enum reggroup_type
+reggroup_type (struct reggroup *group)
+{
+  return group->type;
+}
+
+/* All the groups for a given architecture.  */
+
+struct reggroups
+{
+  int nr_group;
+  struct reggroup **group;
+};
+
+static struct gdbarch_data *reggroups_data;
+
+static void *
+reggroups_init (struct gdbarch *gdbarch)
+{
+  struct reggroups *groups = XMALLOC (struct reggroups);
+  groups->nr_group = 0;
+  groups->group = NULL;
+  return groups;
+}
+
+static void
+reggroups_free (struct gdbarch *gdbarch, void *data)
+{
+  struct reggroups *groups = data;
+  xfree (groups->group);
+  xfree (groups);
+}
+
+/* Add a register group (with attribute values) to the pre-defined
+   list.  This function can be called during architecture
+   initialization and hence needs to handle NULL architecture groups.  */
+
+static void
+add_group (struct reggroups *groups, struct reggroup *group)
+{
+  gdb_assert (group != NULL);
+  groups->nr_group++;
+  groups->group = xrealloc (groups->group, (sizeof (struct reggroup *)
+                                           * (groups->nr_group + 1)));
+  groups->group[groups->nr_group - 1] = group;
+  groups->group[groups->nr_group] = NULL;
+}
+
+void
+reggroup_add (struct gdbarch *gdbarch, struct reggroup *group)
+{
+  struct reggroups *groups = gdbarch_data (gdbarch, reggroups_data);
+  if (groups == NULL)
+    {
+      /* ULGH, called during architecture initialization.  Patch
+         things up.  */
+      groups = reggroups_init (gdbarch);
+      set_gdbarch_data (gdbarch, reggroups_data, groups);
+    }
+  add_group (groups, group);
+}
+
+/* The register groups for the current architecture.  Mumble something
+   about the lifetime of the buffer....  */
+
+static struct reggroups *default_groups;
+
+struct reggroup * const*
+reggroups (struct gdbarch *gdbarch)
+{
+  struct reggroups *groups = gdbarch_data (gdbarch, reggroups_data);
+  /* Don't allow this function to be called during architecture
+     creation.  */
+  gdb_assert (groups != NULL);
+  if (groups->group == NULL)
+    return default_groups->group;
+  else
+    return groups->group;
+}
+
+/* Is REGNUM a member of REGGROUP?  */
+int
+default_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
+                            struct reggroup *group)
+{
+  int vector_p;
+  int float_p;
+  int raw_p;
+  if (REGISTER_NAME (regnum) == NULL
+      || *REGISTER_NAME (regnum) == '\0')
+    return 0;
+  if (group == all_reggroup)
+    return 1;
+  vector_p = TYPE_VECTOR (register_type (gdbarch, regnum));
+  float_p = TYPE_CODE (register_type (gdbarch, regnum)) == TYPE_CODE_FLT;
+  raw_p = regnum < gdbarch_num_regs (gdbarch);
+  if (group == float_reggroup)
+    return float_p;
+  if (group == vector_reggroup)
+    return vector_p;
+  if (group == general_reggroup)
+    return (!vector_p && !float_p);
+  if (group == save_reggroup || group == restore_reggroup)
+    return raw_p;
+  return 0;   
+}
+
+/* Dump out a table of register groups for the current architecture.  */
+
+static void
+reggroups_dump (struct gdbarch *gdbarch, struct ui_file *file)
+{
+  struct reggroup *const *groups = reggroups (gdbarch);
+  int i = -1;
+  do
+    {
+      /* Group name.  */
+      {
+       const char *name;
+       if (i < 0)
+         name = "Group";
+       else
+         name = reggroup_name (groups[i]);
+       fprintf_unfiltered (file, " %-10s", name);
+      }
+      
+      /* Group type.  */
+      {
+       const char *type;
+       if (i < 0)
+         type = "Type";
+       else
+         {
+           switch (reggroup_type (groups[i]))
+             {
+             case USER_REGGROUP:
+               type = "user";
+               break;
+             case INTERNAL_REGGROUP:
+               type = "internal";
+               break;
+             default:
+               internal_error (__FILE__, __LINE__, "bad switch");
+             }
+         }
+       fprintf_unfiltered (file, " %-10s", type);
+      }
+
+      /* Note: If you change this, be sure to also update the
+         documentation.  */
+      
+      fprintf_unfiltered (file, "\n");
+      i++;
+    }
+  while (groups[i] != NULL);
+}
+
+static void
+maintenance_print_reggroups (char *args, int from_tty)
+{
+  if (args == NULL)
+    reggroups_dump (current_gdbarch, gdb_stdout);
+  else
+    {
+      struct ui_file *file = gdb_fopen (args, "w");
+      if (file == NULL)
+       perror_with_name ("maintenance print reggroups");
+      reggroups_dump (current_gdbarch, file);    
+      ui_file_delete (file);
+    }
+}
+
+/* Pre-defined register groups.  */
+static struct reggroup general_group = { "general", USER_REGGROUP };
+static struct reggroup float_group = { "float", USER_REGGROUP };
+static struct reggroup system_group = { "system", USER_REGGROUP };
+static struct reggroup vector_group = { "vector", USER_REGGROUP };
+static struct reggroup all_group = { "all", USER_REGGROUP };
+static struct reggroup save_group = { "save", INTERNAL_REGGROUP };
+static struct reggroup restore_group = { "restore", INTERNAL_REGGROUP };
+
+struct reggroup *const general_reggroup = &general_group;
+struct reggroup *const float_reggroup = &float_group;
+struct reggroup *const system_reggroup = &system_group;
+struct reggroup *const vector_reggroup = &vector_group;
+struct reggroup *const all_reggroup = &all_group;
+struct reggroup *const save_reggroup = &save_group;
+struct reggroup *const restore_reggroup = &restore_group;
+
+void
+_initialize_reggroup (void)
+{
+  reggroups_data = register_gdbarch_data (reggroups_init, reggroups_free);
+
+  /* The pre-defined list of groups.  */
+  default_groups = reggroups_init (NULL);
+  add_group (default_groups, general_reggroup);
+  add_group (default_groups, float_reggroup);
+  add_group (default_groups, system_reggroup);
+  add_group (default_groups, vector_reggroup);
+  add_group (default_groups, all_reggroup);
+  add_group (default_groups, save_reggroup);
+  add_group (default_groups, restore_reggroup);
+
+
+  add_cmd ("reggroups", class_maintenance,
+          maintenance_print_reggroups, "\
+Print the internal register group names.\n\
+Takes an optional file parameter.",
+          &maintenanceprintlist);
+
+}
diff --git a/gdb/reggroups.h b/gdb/reggroups.h
new file mode 100644 (file)
index 0000000..0088a85
--- /dev/null
@@ -0,0 +1,61 @@
+/* Register groupings for GDB, the GNU debugger.
+
+   Copyright 2002 Free Software Foundation, Inc.
+
+   Contributed by Red Hat.
+
+   This file is part of GDB.
+
+   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 REGGROUPS_H
+#define REGGROUPS_H
+
+struct gdbarch;
+struct reggroup;
+
+enum reggroup_type { USER_REGGROUP, INTERNAL_REGGROUP };
+
+/* Pre-defined, user visible, register groups.  */
+extern struct reggroup *const general_reggroup;
+extern struct reggroup *const float_reggroup;
+extern struct reggroup *const system_reggroup;
+extern struct reggroup *const vector_reggroup;
+extern struct reggroup *const all_reggroup;
+
+/* Pre-defined, internal, register groups.  */
+extern struct reggroup *const save_reggroup;
+extern struct reggroup *const restore_reggroup;
+
+/* Create a new local register group.  */
+extern struct reggroup *reggroup_new (const char *name,
+                                     enum reggroup_type type);
+
+/* Add a register group (with attribute values) to the pre-defined list.  */
+extern void reggroup_add (struct gdbarch *gdbarch, struct reggroup *group);
+
+/* Register group attributes.  */
+extern const char *reggroup_name (struct reggroup *reggroup);
+extern enum reggroup_type reggroup_type (struct reggroup *reggroup);
+
+/* The register groups for the current architecture.  */
+extern struct reggroup *const *reggroups (struct gdbarch *gdbarch);
+
+/* Is REGNUM a member of REGGROUP?  */
+extern int default_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
+                                       struct reggroup *reggroup);
+
+#endif
diff --git a/gdb/testsuite/gdb.mi/gdb792.cc b/gdb/testsuite/gdb.mi/gdb792.cc
new file mode 100644 (file)
index 0000000..a698a12
--- /dev/null
@@ -0,0 +1,59 @@
+#include <string.h>
+#include <stdio.h>
+
+class Q
+{
+       int v;
+       protected:
+               int qx;
+               int qy;
+       int w;
+};
+
+class B
+{
+       int k;
+       public:
+               int bx;
+               int by;
+};
+
+class A
+{
+       int u;
+
+       public:
+               A()
+               {
+               };
+               int x;
+               char buffer[10];
+       
+       protected:
+               int y;
+               B b;
+       
+       private:
+               float z;
+};
+
+class C : public A
+{
+       public:
+               C()
+               {
+               };
+               int zzzz;
+       private:
+               int ssss;
+};
+
+int main()
+{
+       A a;
+       C c;
+       Q q;
+       strcpy( a.buffer, "test" );
+       printf ( "%.10s\n", a.buffer );
+       return 0;
+}
diff --git a/gdb/testsuite/gdb.mi/gdb792.exp b/gdb/testsuite/gdb.mi/gdb792.exp
new file mode 100644 (file)
index 0000000..ce5ac31
--- /dev/null
@@ -0,0 +1,90 @@
+# Copyright 2002 Free Software Foundation, Inc.
+
+# 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.  
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+#
+# test gdb/792
+#
+
+load_lib mi-support.exp
+set MIFLAGS "-i=mi"
+
+gdb_exit
+if [mi_gdb_start] {
+    continue
+}
+
+set testfile gdb792
+set srcfile "$testfile.cc"
+set binfile $objdir/$subdir/$testfile
+
+if [get_compiler_info ${binfile} "c++"] {
+    return -1;
+}
+
+if {[gdb_compile $srcdir/$subdir/$srcfile $binfile executable {debug c++}] != ""} {
+  gdb_suppress_entire_file "Testcase compile failed, so all test in this file will automatically fail."
+}
+
+# Test that children of classes are properly reported
+
+# Run to main
+mi_run_to_main
+
+mi_gdb_test "-var-create - * a" \
+  "(&\".*\"\r\n)*\\^done,name=\"var1\",numchild=\"3\",type=\"A\"" \
+  "create var for class A"
+
+mi_gdb_test "-var-list-children var1" \
+  "(&\".*\"\r\n)*\\^done,numchild=\"3\",children=\{child=\{name=\"var1\.public\",exp=\"public\",numchild=\"2\"\},child=\{name=\"var1\.private\",exp=\"private\",numchild=\"2\"\},child=\{name=\"var1\.protected\",exp=\"protected\",numchild=\"2\"\}\}" \
+  "list children of class A"
+
+mi_gdb_test "-var-list-children var1.public" \
+  "(&\".*\"\r\n)*\\^done,numchild=\"2\",children=\{child=\{name=\"var1\.public\.x\",exp=\"x\",numchild=\"0\",type=\"int\"\},child=\{name=\"var1\.public\.buffer\",exp=\"buffer\",numchild=\"10\",type=\"char \\\[10\\\]\"\}\}" \
+  "list children of A.public"
+
+mi_gdb_test "-var-list-children var1.private" \
+  "(&\".*\"\r\n)*\\^done,numchild=\"2\",children=\{child=\{name=\"var1\.private\.u\",exp=\"u\",numchild=\"0\",type=\"int\"\},child=\{name=\"var1\.private\.z\",exp=\"z\",numchild=\"0\",type=\"float\"\}\}" \
+  "list children of A.private"
+
+mi_gdb_test "-var-list-children var1.protected" \
+  "(&\".*\"\r\n)*\\^done,numchild=\"2\",children=\{child=\{name=\"var1\.protected\.y\",exp=\"y\",numchild=\"0\",type=\"int\"\},child=\{name=\"var1\.protected\.b\",exp=\"b\",numchild=\"2\",type=\"B\"\}\}" \
+  "list children of A.protected"
+
+mi_gdb_test "-var-list-children var1.protected.b" \
+  "(&\".*\"\r\n)*\\^done,numchild=\"2\",children=\{child=\{name=\"var1\.protected\.b\.public\",exp=\"public\",numchild=\"2\"\},child=\{name=\"var1\.protected\.b\.private\",exp=\"private\",numchild=\"1\"\}\}" \
+  "list children of A.protected.b"
+
+mi_gdb_test "-var-list-children var1.protected.b.public" \
+  "(&\".*\"\r\n)*\\^done,numchild=\"2\",children=\{child=\{name=\"var1\.protected\.b\.public\.bx\",exp=\"bx\",numchild=\"0\",type=\"int\"\},child=\{name=\"var1\.protected\.b\.public\.by\",exp=\"by\",numchild=\"0\",type=\"int\"\}\}" \
+  "list children of A.protected.b.public"
+
+mi_gdb_test "-var-list-children var1.protected.b.private" \
+  "(&\".*\"\r\n)*\\^done,numchild=\"1\",children=\{child=\{name=\"var1\.protected\.b\.private\.k\",exp=\"k\",numchild=\"0\",type=\"int\"\}\}" \
+  "list children of A.protected.b.private"
+
+mi_gdb_test "-var-create - * c" \
+  "(&\".*\"\r\n)*\\^done,name=\"var2\",numchild=\"3\",type=\"C\"" \
+  "create var for class C which has baseclass A"
+
+mi_gdb_test "-var-list-children var2" \
+  "(&\".*\"\r\n)*\\^done,numchild=\"3\",children=\{child=\{name=\"var2\.A\",exp=\"A\",numchild=\"3\",type=\"A\"\},child=\{name=\"var2\.public\",exp=\"public\",numchild=\"1\"\},child=\{name=\"var2\.private\",exp=\"private\",numchild=\"1\"\}\}" \
+  "list children of class C"
+
+mi_gdb_exit
+return 0