aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobody <>2002-11-15 08:38:39 +0000
committernobody <>2002-11-15 08:38:39 +0000
commit1e04139942197a796f7ab9dadeeaac2e78a301d4 (patch)
treef0f6862dc3f59ffc8448166b40365acda03aff86
parent5ed92c4602037e0f39a6a089e3842319a48b7af0 (diff)
downloadgdb-1e04139942197a796f7ab9dadeeaac2e78a301d4.zip
gdb-1e04139942197a796f7ab9dadeeaac2e78a301d4.tar.gz
gdb-1e04139942197a796f7ab9dadeeaac2e78a301d4.tar.bz2
This commit was manufactured by cvs2svn to create branch
'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
-rw-r--r--bfd/mach-o-target.c117
-rw-r--r--bfd/mach-o.c2194
-rw-r--r--bfd/mach-o.h490
-rw-r--r--bfd/pef-traceback.h215
-rw-r--r--bfd/pef.c1312
-rw-r--r--bfd/pef.h186
-rw-r--r--bfd/xsym.c2484
-rw-r--r--bfd/xsym.h701
-rw-r--r--gdb/config/i386/interix.mh9
-rw-r--r--gdb/config/i386/interix.mt3
-rw-r--r--gdb/config/i386/nm-interix.h35
-rw-r--r--gdb/dummy-frame.c310
-rw-r--r--gdb/dummy-frame.h65
-rw-r--r--gdb/i386-interix-nat.c190
-rw-r--r--gdb/i386-interix-tdep.c365
-rw-r--r--gdb/reggroups.c268
-rw-r--r--gdb/reggroups.h61
-rw-r--r--gdb/testsuite/gdb.mi/gdb792.cc59
-rw-r--r--gdb/testsuite/gdb.mi/gdb792.exp90
19 files changed, 9154 insertions, 0 deletions
diff --git a/bfd/mach-o-target.c b/bfd/mach-o-target.c
new file mode 100644
index 0000000..b271bfc
--- /dev/null
+++ b/bfd/mach-o-target.c
@@ -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
index 0000000..1daaf98
--- /dev/null
+++ b/bfd/mach-o.c
@@ -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
index 0000000..f780273
--- /dev/null
+++ b/bfd/mach-o.h
@@ -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
index 0000000..15f43b6
--- /dev/null
+++ b/bfd/pef-traceback.h
@@ -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
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
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
index 0000000..e6b3c4b
--- /dev/null
+++ b/bfd/xsym.c
@@ -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
index 0000000..a381c55
--- /dev/null
+++ b/bfd/xsym.h
@@ -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
index 0000000..23311d6
--- /dev/null
+++ b/gdb/config/i386/interix.mh
@@ -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
index 0000000..8d60962
--- /dev/null
+++ b/gdb/config/i386/interix.mt
@@ -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
index 0000000..b8b003a
--- /dev/null
+++ b/gdb/config/i386/nm-interix.h
@@ -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
index 0000000..ddc4db8
--- /dev/null
+++ b/gdb/dummy-frame.c
@@ -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
index 0000000..bd4e199
--- /dev/null
+++ b/gdb/dummy-frame.h
@@ -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
index 0000000..9c4daed
--- /dev/null
+++ b/gdb/i386-interix-nat.c
@@ -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
index 0000000..ff310ec
--- /dev/null
+++ b/gdb/i386-interix-tdep.c
@@ -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
index 0000000..8c3cbb7
--- /dev/null
+++ b/gdb/reggroups.c
@@ -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
index 0000000..0088a85
--- /dev/null
+++ b/gdb/reggroups.h
@@ -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
index 0000000..a698a12
--- /dev/null
+++ b/gdb/testsuite/gdb.mi/gdb792.cc
@@ -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
index 0000000..ce5ac31
--- /dev/null
+++ b/gdb/testsuite/gdb.mi/gdb792.exp
@@ -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