* xcoffexec.c (exec_ops): child_attach and child_create_inferior
[deliverable/binutils-gdb.git] / gdb / mipsread.c
index 4bd8786936dffa97ceba0fb46d56195be5e7ff75..90dd8af5a2d11439a8a8dba24850cf8c8f8602b4 100644 (file)
@@ -1,6 +1,7 @@
 /* Read a symbol table in MIPS' format (Third-Eye).
-   Copyright 1986, 1987, 1989, 1990, 1991 Free Software Foundation, Inc.
-   Contributed by Alessandro Forin (af@cs.cmu.edu) at CMU.
+   Copyright 1986, 1987, 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+   Contributed by Alessandro Forin (af@cs.cmu.edu) at CMU.  Major
+   work by Per Bothner and John Gilmore at Cygnus Support.
 
 This file is part of GDB.
 
@@ -19,7 +20,7 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 /* This module provides three functions: mipscoff_symfile_init,
-   which initializes to read a symbol file; mipscoff_new_init, which 
+   which initializes to read a symbol file; mipscoff_new_init, which
    discards existing cached information when all symbols are being
    discarded; and mipscoff_symfile_read, which reads a symbol table
    from a file.
@@ -31,38 +32,58 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
    file, the corresponding partial symbol table is mutated into a full
    fledged symbol table by going back and reading the symbols
    for real.  mipscoff_psymtab_to_symtab() is called indirectly through
-   a pointer in the psymtab to do this.  */
-
-#include <stdio.h>
+   a pointer in the psymtab to do this.
+
+   ECOFF symbol tables are mostly written in the byte order of the
+   target machine.  However, one section of the table (the auxiliary
+   symbol information) is written in the host byte order.  There is a
+   bit in the other symbol info which describes which host byte order
+   was used.  ECOFF thereby takes the trophy from Intel `b.out' for
+   the most brain-dead adaptation of a file format to byte order.
+
+   This module can read all four of the known byte-order combinations,
+   on any type of host.  However, it does make (and check) the assumption
+   that the external form of a symbol table structure (on disk)
+   occupies the same number of bytes as the internal form (in a struct).
+   Fixing this is possible but requires larger structural changes.  */
+
+#define        TM_FILE_OVERRIDE
 #include "defs.h"
+#include "tm-mips.h"
 #include "symtab.h"
+#include "gdbtypes.h"
 #include "gdbcore.h"
 #include "symfile.h"
+#include "objfiles.h"
 #include "obstack.h"
 #include "buildsym.h"
+
+#ifdef USG
+#include <sys/types.h>
+#define L_SET 0
+#define L_INCR 1
+#endif
+
 #include <sys/param.h>
 #include <sys/file.h>
 #include <sys/stat.h>
-#ifdef CMUCS
-#include <mips/syms.h>
-#else /* not CMUCS */
-#include <symconst.h>
-#include <sym.h>
-#endif /* not CMUCS */
-
-#include "coff/mips.h"
-#include "libaout.h"           /* FIXME Secret internal BFD stuff for a.out */
+
+#include "coff/mips.h"         /* COFF-like aspects of ecoff files */
+#include "coff/ecoff-ext.h"    /* External forms of ecoff sym structures */
+
+#include "libbfd.h"            /* FIXME Secret internal BFD stuff (bfd_read) */
+#include "libaout.h"           /* FIXME Secret internal BFD stuff for a.out */
 #include "aout/aout64.h"
-#include "aout/stab_gnu.h"     /* We always use GNU stabs, not native, now */
+#include "aout/stab_gnu.h"     /* STABS information */
 
 struct coff_exec {
        struct external_filehdr f;
        struct external_aouthdr a;
 };
 
-/* These must match the corresponding definition in mips-tfile.c.
-   At some point, these should probably go into an include file,
-   but currently gcc does use/need the ../include directory. */
+/* These must match the corresponding definition in gcc/config/xm-mips.h.
+   At some point, these should probably go into a shared include file,
+   but currently gcc and gdb do not share any directories. */
 
 #define CODE_MASK 0x8F300
 #define MIPS_IS_STAB(sym) (((sym)->index & 0xFFF00) == CODE_MASK)
@@ -78,48 +99,73 @@ struct coff_exec {
    represents and a pointer to the symbol table header HDRR from the symbol
    file that the psymtab was created from.  */
 
-#define FDR_IDX(p) (((struct symloc *)((p)->read_symtab_private))->fdr_idx)
-#define CUR_HDR(p) (((struct symloc *)((p)->read_symtab_private))->cur_hdr)
+#define PST_PRIVATE(p) ((struct symloc *)(p)->read_symtab_private)
+#define FDR_IDX(p) (PST_PRIVATE(p)->fdr_idx)
+#define CUR_HDR(p) (PST_PRIVATE(p)->cur_hdr)
 
 struct symloc {
   int fdr_idx;
   HDRR *cur_hdr;
+  EXTR **extern_tab; /* Pointer to external symbols for this file. */
+  int extern_count; /* Size of extern_tab. */
 };
 
 /* Things we import explicitly from other modules */
 
 extern int          info_verbose;
-extern struct block *block_for_pc();
-extern void         sort_symtab_syms();
 
 /* Various complaints about symbol reading that don't abort the process */
-   
-struct complaint unknown_ext_complaint = 
+
+struct complaint bad_file_number_complaint =
+       {"bad file number %d", 0, 0};
+
+struct complaint index_complaint =
+       {"bad aux index at symbol %s", 0, 0};
+
+struct complaint aux_index_complaint =
+       {"bad proc end in aux found from symbol %s", 0, 0};
+
+struct complaint unknown_ext_complaint =
        {"unknown external symbol %s", 0, 0};
 
-struct complaint unknown_sym_complaint = 
+struct complaint unknown_sym_complaint =
        {"unknown local symbol %s", 0, 0};
 
-struct complaint unknown_st_complaint = 
+struct complaint unknown_st_complaint =
        {"with type %d", 0, 0};
 
-struct complaint block_overflow_complaint = 
+struct complaint block_overflow_complaint =
        {"block containing %s overfilled", 0, 0};
 
-struct complaint basic_type_complaint = 
+struct complaint basic_type_complaint =
        {"cannot map MIPS basic type 0x%x", 0, 0};
 
-struct complaint unknown_type_qual_complaint = 
+struct complaint unknown_type_qual_complaint =
        {"unknown type qualifier 0x%x", 0, 0};
 
-struct complaint array_bitsize_complaint = 
+struct complaint array_bitsize_complaint =
        {"size of array target type not known, assuming %d bits", 0, 0};
 
-struct complaint array_parse_complaint = 
-       {"array type with strange relative symbol", 0, 0};
+struct complaint bad_tag_guess_complaint =
+       {"guessed tag type of %s incorrectly", 0, 0};
+
+struct complaint block_member_complaint =
+       {"declaration block contains unhandled symbol type %d", 0, 0};
+
+struct complaint stEnd_complaint =
+       {"stEnd with storage class %d not handled", 0, 0};
 
-struct complaint bad_tag_guess_complaint = 
-       {"guessed tag type incorrectly", 0, 0};
+struct complaint unknown_mips_symtype_complaint =
+       {"unknown symbol type 0x%x", 0, 0};
+
+struct complaint stab_unknown_complaint =
+       {"unknown stabs symbol %s", 0, 0};
+
+struct complaint pdr_for_nonsymbol_complaint =
+       {"PDR for %s, but no symbol", 0, 0};
+
+struct complaint pdr_static_symbol_complaint =
+       {"can't handle PDR for static proc at 0x%x", 0, 0};
 
 /* Macros and extra defs */
 
@@ -143,10 +189,6 @@ struct complaint bad_tag_guess_complaint =
 \f
 /* Things that really are local to this module */
 
-/* GDB symtable for the current compilation unit */
-
-static struct symtab *cur_stab;
-
 /* MIPS symtab header for the current file */
 
 static HDRR    *cur_hdr;
@@ -184,34 +226,90 @@ struct type *builtin_type_string;
 
 /* Forward declarations */
 
-static struct symbol   *new_symbol();
-static struct type     *new_type();
-static struct block    *new_block();
-static struct symtab   *new_symtab();
-static struct linetable        *new_linetable();
-static struct blockvector *new_bvect();
-
-static struct type     *parse_type();
-static struct type     *make_type();
-static struct symbol   *mylookup_symbol();
-static struct block    *shrink_block();
-static void sort_blocks();
-
-static int compare_symtabs();
-static int compare_psymtabs();
-static int compare_blocks();
-
-static struct partial_symtab *new_psymtab();
-static struct partial_symtab *parse_fdr();
-static int compare_psymbols();
-
-static void psymtab_to_symtab_1();
-static void add_block();
-static void add_symbol();
-static int  add_line();
-static struct linetable *shrink_linetable();
-static char* mips_next_symbol_text ();
+static void
+fixup_symtab PARAMS ((HDRR *, char *, int, bfd *));
+
+static void
+read_mips_symtab PARAMS ((struct objfile *));
+
+static void
+read_the_mips_symtab PARAMS ((bfd *, CORE_ADDR *));
+
+static int
+upgrade_type PARAMS ((struct type **, int, union aux_ext *, int));
+
+static void
+parse_partial_symbols PARAMS ((int, struct objfile *));
+
+static int
+cross_ref PARAMS ((union aux_ext *, struct type **, enum type_code, char **,
+                  int));
+
+static void
+fixup_sigtramp PARAMS ((void));
+
+static struct symbol *
+new_symbol PARAMS ((char *));
+
+static struct type *
+new_type PARAMS ((char *));
+
+static struct block *
+new_block PARAMS ((int));
+
+static struct symtab *
+new_symtab PARAMS ((char *, int, int, struct objfile *));
+
+static struct linetable *
+new_linetable PARAMS ((int));
+
+static struct blockvector *
+new_bvect PARAMS ((int));
+
+static struct type *
+parse_type PARAMS ((union aux_ext *, int *, int));
+
+static struct symbol *
+mylookup_symbol PARAMS ((char *, struct block *, enum namespace,
+                        enum address_class));
+
+static struct block *
+shrink_block PARAMS ((struct block *, struct symtab *));
+
+static PTR
+xzalloc PARAMS ((unsigned int));
+
+static void
+sort_blocks PARAMS ((struct symtab *));
+
+static int
+compare_blocks PARAMS ((const void *, const void *));
+
+static struct partial_symtab *
+new_psymtab PARAMS ((char *, struct objfile *));
+
+#if 0
+static struct partial_symtab *
+parse_fdr PARAMS ((int, int, struct objfile *));
+#endif
+
+static void
+psymtab_to_symtab_1 PARAMS ((struct partial_symtab *, char *));
+
+static void
+add_block PARAMS ((struct block *, struct symtab *));
+
+static void
+add_symbol PARAMS ((struct symbol *, struct block *));
+
+static int
+add_line PARAMS ((struct linetable *, int, CORE_ADDR, int));
+
+static struct linetable *
+shrink_linetable PARAMS ((struct linetable *));
 
+static char *
+mips_next_symbol_text PARAMS ((void));
 \f
 /* Things we export to other modules */
 
@@ -220,72 +318,76 @@ static char* mips_next_symbol_text ();
 
 CORE_ADDR sigtramp_address, sigtramp_end;
 
-/* The entry point (starting address) of the file, if it is an executable.  */
-
-extern CORE_ADDR startup_file_start;   /* From blockframe.c */
-extern CORE_ADDR startup_file_end;     /* From blockframe.c */
-
-void
-mipscoff_new_init()
+static void
+mipscoff_new_init (ignore)
+     struct objfile *ignore;
 {
-  /* If we have a file symbol header lying around, blow it away.  */
-  if (cur_hdr)
-    free ((char *)cur_hdr);
-  cur_hdr = 0;
 }
 
-void
-mipscoff_symfile_init (sf)
-     struct sym_fns *sf;
+static void
+mipscoff_symfile_init (objfile)
+     struct objfile *objfile;
 {
-  sf->sym_private = NULL;
+  if (objfile -> sym_private != NULL)
+    {
+      mfree (objfile -> md, objfile -> sym_private);
+    }
+  objfile -> sym_private = NULL;
 }
 
-void
-mipscoff_symfile_read(sf, addr, mainline)
-     struct sym_fns *sf;
+static void
+mipscoff_symfile_read (objfile, addr, mainline)
+     struct objfile *objfile;
      CORE_ADDR addr;
      int mainline;
 {
-  struct coff_symfile_info *info = (struct coff_symfile_info *)sf->sym_private;
-  bfd *abfd = sf->objfile->obfd;
-  char *name = bfd_get_filename (abfd);
-  int desc;
-  register int val;
-  int symtab_offset;
-  int stringtab_offset;
-
-/* WARNING WILL ROBINSON!  ACCESSING BFD-PRIVATE DATA HERE!  FIXME!  */
-   desc = fileno ((FILE *)(abfd->iostream));   /* Raw file descriptor */
-/* End of warning */
-
-  /* Position to read the symbol table.  */
-  val = lseek (desc, (long)symtab_offset, 0);
-  if (val < 0)
-    perror_with_name (name);
-
-  init_misc_bunches ();
-  make_cleanup (discard_misc_bunches, 0);
+  init_minimal_symbol_collection ();
+  make_cleanup (discard_minimal_symbols, 0);
 
   /* Now that the executable file is positioned at symbol table,
      process it and define symbols accordingly.  */
 
-  read_mips_symtab(sf->objfile, desc);
+  read_mips_symtab(objfile);
 
-  /* Go over the misc symbol bunches and install them in vector.  */
+  /* Install any minimal symbols that have been collected as the current
+     minimal symbols for this objfile. */
 
-  condense_misc_bunches (!mainline);
+  install_minimal_symbols (objfile);
 }
-  
-/* Exported procedure: Allocate zeroed memory */
 
-char *
+/* Perform any local cleanups required when we are done with a particular
+   objfile.  I.E, we are in the process of discarding all symbol information
+   for an objfile, freeing up all memory held for it, and unlinking the
+   objfile struct from the global list of known objfiles. */
+
+static void
+mipscoff_symfile_finish (objfile)
+     struct objfile *objfile;
+{
+  if (objfile -> sym_private != NULL)
+    {
+      mfree (objfile -> md, objfile -> sym_private);
+    }
+
+  /* If we have a file symbol header lying around, blow it away.  */
+
+  if (cur_hdr)
+    {
+      free ((PTR)cur_hdr);
+    }
+  cur_hdr = 0;
+}
+
+/* Allocate zeroed memory */
+
+static PTR
 xzalloc(size)
+     unsigned int size;
 {
-       char           *p = xmalloc(size);
+  PTR p = xmalloc (size);
 
-       memset(p, 0, size);
-       return p;
+  memset (p, 0, size);
+  return p;
 }
 
 /* Exported procedure: Builds a symtab from the PST partial one.
@@ -297,8 +399,6 @@ static void
 mipscoff_psymtab_to_symtab(pst)
        struct partial_symtab *pst;
 {
-       struct symtab  *ret;
-       int             i;
 
        if (!pst)
                return;
@@ -316,7 +416,7 @@ mipscoff_psymtab_to_symtab(pst)
 
        /* Match with global symbols.  This only needs to be done once,
           after all of the symtabs and dependencies have been read in.   */
-       scan_file_globals ();
+       scan_file_globals (pst->objfile);
 
        if (info_verbose)
                printf_filtered("done.\n");
@@ -325,9 +425,9 @@ mipscoff_psymtab_to_symtab(pst)
 /* Exported procedure: Is PC in the signal trampoline code */
 
 int
-in_sigtramp(pc, name)
+in_sigtramp(pc, ignore)
        CORE_ADDR pc;
-       char *name;
+       char *ignore;           /* function name */
 {
        if (sigtramp_address == 0)
                fixup_sigtramp();
@@ -336,25 +436,25 @@ in_sigtramp(pc, name)
 \f
 /* File-level interface functions */
 
-/* Read the symtab information from file FSYM into memory.  Also,
+/* Read the symtab information from file ABFD into memory.  Also,
    return address just past end of our text segment in *END_OF_TEXT_SEGP.  */
 
-static
-read_the_mips_symtab(abfd, fsym, end_of_text_segp)
-       bfd             *abfd;
-       int             fsym;
+static void
+read_the_mips_symtab(abfd, end_of_text_segp)
+       bfd             *abfd;
        CORE_ADDR       *end_of_text_segp;
 {
        int             stsize, st_hdrsize;
        unsigned        st_filptr;
+       struct hdr_ext  hdr_ext;
        HDRR            st_hdr;
        /* Header for executable/object file we read symbols from */
        struct coff_exec filhdr;
+       int val;
 
-       /* We get here with DESC pointing to the symtab header. But we need
-        * other info from the initial headers */
-       lseek(fsym, 0L, 0);
-       myread(fsym, &filhdr, sizeof filhdr);
+       /* We need some info from the initial headers */
+       val = bfd_seek(abfd, 0L, L_SET);
+       val = bfd_read((PTR)&filhdr, sizeof filhdr, 1, abfd);
 
        if (end_of_text_segp)
                *end_of_text_segp =
@@ -365,13 +465,16 @@ read_the_mips_symtab(abfd, fsym, end_of_text_segp)
        st_hdrsize = bfd_h_get_32 (abfd, filhdr.f.f_nsyms);
        st_filptr  = bfd_h_get_32 (abfd, filhdr.f.f_symptr);
        if (st_filptr == 0)
-               return 0;
+               return;
 
-       lseek(fsym, st_filptr, L_SET);
-       if (st_hdrsize > sizeof (st_hdr))       /* Profanity check */
-               abort();
-       if (read(fsym, &st_hdr, st_hdrsize) != st_hdrsize)
+       bfd_seek (abfd, st_filptr, L_SET);
+       if (st_hdrsize != sizeof (hdr_ext)) {   /* Profanity check */
+               error ("Wrong header size: %d, not %d", st_hdrsize,
+                       sizeof (hdr_ext));
+       }
+       if (bfd_read((PTR)&hdr_ext, st_hdrsize, 1, abfd) != st_hdrsize)
                goto readerr;
+       ecoff_swap_hdr_in (abfd, &hdr_ext, &st_hdr);
 
        /* Find out how large the symbol table is */
        stsize = (st_hdr.cbExtOffset - (st_filptr + st_hdrsize))
@@ -380,13 +483,13 @@ read_the_mips_symtab(abfd, fsym, end_of_text_segp)
        /* Allocate space for the symbol table.  Read it in.  */
        cur_hdr = (HDRR *) xmalloc(stsize + st_hdrsize);
 
-       memcpy(cur_hdr, &st_hdr, st_hdrsize);
-       if (read(fsym, (char *) cur_hdr + st_hdrsize, stsize) != stsize)
+       memcpy((PTR)cur_hdr, (PTR)&hdr_ext, st_hdrsize);
+       if (bfd_read((char *)cur_hdr + st_hdrsize, stsize, 1, abfd) != stsize)
                goto readerr;
 
        /* Fixup file_pointers in it */
        fixup_symtab(cur_hdr, (char *) cur_hdr + st_hdrsize,
-                    st_filptr + st_hdrsize);
+                    st_filptr + st_hdrsize, abfd);
 
        return;
 readerr:
@@ -396,19 +499,47 @@ readerr:
 
 /* Turn all file-relative pointers in the symtab described by HDR
    into memory pointers, given that the symtab itself is located
-   at DATA in memory and F_PTR in the file. */
+   at DATA in memory and F_PTR in the file.
+
+   Byte-swap all the data structures, in place, while we are at it --
+   except AUX entries, which we leave in their original byte order.
+   They will be swapped as they are used instead.  (FIXME:  we ought to
+   do all the data structures that way.)  */
 
-static
-fixup_symtab( hdr, data, f_ptr)
+static void
+fixup_symtab (hdr, data, f_ptr, abfd)
        HDRR *hdr;
        char *data;
+       int f_ptr;
+       bfd *abfd;
 {
-       int             f_idx, s_idx;
+       int             f_idx, s_idx, i;
        FDR            *fh;
        SYMR           *sh;
-       OPTR           *op;
        PDR            *pr;
        EXTR           *esh;
+       struct rfd_ext *rbase;
+
+       /* This function depends on the external and internal forms
+          of the MIPS symbol table taking identical space.  Check this
+          assumption at compile-time.  */
+#if 0  /* FIXME: Unused */
+       static check_hdr1[1 + sizeof (struct hdr_ext) - sizeof (HDRR)] = {0};
+       static check_hdr2[1 + sizeof (HDRR) - sizeof (struct hdr_ext)] = {0};
+       static check_fdr1[1 + sizeof (struct fdr_ext) - sizeof (FDR)] = {0};
+       static check_fdr2[1 + sizeof (FDR) - sizeof (struct fdr_ext)] = {0};
+       static check_pdr1[1 + sizeof (struct pdr_ext) - sizeof (PDR)] = {0};
+       static check_pdr2[1 + sizeof (PDR) - sizeof (struct pdr_ext)] = {0};
+       static check_sym1[1 + sizeof (struct sym_ext) - sizeof (SYMR)] = {0};
+       static check_sym2[1 + sizeof (SYMR) - sizeof (struct sym_ext)] = {0};
+       static check_ext1[1 + sizeof (struct ext_ext) - sizeof (EXTR)] = {0};
+       static check_ext2[1 + sizeof (EXTR) - sizeof (struct ext_ext)] = {0};
+       static check_rfd1[1 + sizeof (struct rfd_ext) - sizeof (RFDT)] = {0};
+       static check_rfd2[1 + sizeof (RFDT) - sizeof (struct rfd_ext)] = {0};
+#endif
+
+       /* Swap in the header record.  */
+       ecoff_swap_hdr_in (abfd, hdr, hdr);
 
        /*
         * These fields are useless (and empty) by now:
@@ -433,16 +564,24 @@ fixup_symtab( hdr, data, f_ptr)
         FIX(cbExtOffset);
 #undef FIX
 
+       /* Fix all the RFD's.  */
+       rbase = (struct rfd_ext *)(hdr->cbRfdOffset);
+       for (i = 0; i < hdr->crfd; i++) {
+         ecoff_swap_rfd_in (abfd, rbase+i, (pRFDT) rbase+i);
+       }
+
+       /* Fix all string pointers inside the symtab, and
+          the FDR records.  Also fix other miscellany.  */
 
-       /*
-        * Fix all string pointers inside the symtab, and
-        * the FDR records.  Also fix other miscellany.
-        */
        for (f_idx = 0; f_idx < hdr->ifdMax; f_idx++) {
                register unsigned code_offset;
 
                /* Header itself, and strings */
                fh = (FDR *) (hdr->cbFdOffset) + f_idx;
+
+               /* Swap in the FDR */
+               ecoff_swap_fdr_in (abfd, fh, fh);
+
                fh->issBase += hdr->cbSsOffset;
                if (fh->rss != -1)
                        fh->rss = (long)fh->rss + fh->issBase;
@@ -453,6 +592,8 @@ fixup_symtab( hdr, data, f_ptr)
                /* FIXME! Probably don't want to do this here! */
                for (s_idx = 0; s_idx < fh->csym; s_idx++) {
                        sh = (SYMR*)fh->isymBase + s_idx;
+                       ecoff_swap_sym_in (abfd, sh, sh);
+
                        sh->iss = (long) sh->iss + fh->issBase;
                        sh->reserved = 0;
                }
@@ -469,7 +610,7 @@ fixup_symtab( hdr, data, f_ptr)
 
                /* Aux symbols */
                if (fh->caux)
-                       fh->iauxBase = hdr->cbAuxOffset + fh->iauxBase * sizeof(AUXU);
+                       fh->iauxBase = hdr->cbAuxOffset + fh->iauxBase * sizeof(union aux_ext);
                /* Relative file descriptor table */
                fh->rfdBase = hdr->cbRfdOffset + fh->rfdBase * sizeof(RFDT);
 
@@ -483,6 +624,7 @@ fixup_symtab( hdr, data, f_ptr)
                        unsigned name, only_ext;
 
                        pr = (PDR*)(IPDFIRST(hdr,fh)) + s_idx;
+                       ecoff_swap_pdr_in (abfd, pr, pr);
 
                        /* Simple rule to find files linked "-x" */
                        only_ext = fh->rss == -1;
@@ -515,9 +657,10 @@ fixup_symtab( hdr, data, f_ptr)
                }               
        }
 
-       /* External symbols: fix string */
+       /* External symbols: swap in, and fix string */
        for (s_idx = 0; s_idx < hdr->iextMax; s_idx++) {
                esh = (EXTR*)(hdr->cbExtOffset) + s_idx;
+               ecoff_swap_ext_in (abfd, esh, esh);
                esh->asym.iss = esh->asym.iss + hdr->cbSsExtOffset;
        }
 }
@@ -554,17 +697,16 @@ fdr_name(name)
 
 
 /* Read in and parse the symtab of the file DESC. INCREMENTAL says
-   whether we are adding to the general symtab or not. 
+   whether we are adding to the general symtab or not.
    FIXME:  INCREMENTAL is currently always zero, though it should not be. */
 
-static
-read_mips_symtab (objfile, desc)
+static void
+read_mips_symtab (objfile)
        struct objfile *objfile;
-       int desc;
 {
        CORE_ADDR end_of_text_seg;
 
-       read_the_mips_symtab(objfile->obfd, desc, &end_of_text_seg);
+       read_the_mips_symtab(objfile->obfd, &end_of_text_seg);
 
        parse_partial_symbols(end_of_text_seg, objfile);
 
@@ -589,9 +731,11 @@ read_mips_symtab (objfile, desc)
 
 /* Map of FDR indexes to partial symtabs */
 
-static struct pst_map {
-       struct partial_symtab *pst;     /* the psymtab proper */
-} * fdr_to_pst;
+struct pst_map {
+    struct partial_symtab *pst;        /* the psymtab proper */
+    int n_globals; /* exported globals (external symbols) */
+    int globals_offset;  /* cumulative */
+};
 
 
 /* Utility stack, used to nest procedures and blocks properly.
@@ -614,7 +758,8 @@ static struct parse_stack {
 
 /* Enter a new lexical context */
 
-static push_parse_stack()
+static void
+push_parse_stack()
 {
        struct parse_stack *new;
 
@@ -637,7 +782,8 @@ static push_parse_stack()
 
 /* Exit a lexical context */
 
-static pop_parse_stack()
+static void
+pop_parse_stack()
 {
        if (!top_stack)
                return;
@@ -660,8 +806,8 @@ static struct mips_pending {
 
 /* Check whether we already saw symbol SH in file FH as undefined */
 
-static
-struct mips_pending *is_pending_symbol(fh, sh)
+static struct mips_pending *
+is_pending_symbol(fh, sh)
        FDR *fh;
        SYMR *sh;
 {
@@ -675,25 +821,9 @@ struct mips_pending *is_pending_symbol(fh, sh)
        return p;
 }
 
-/* Check whether we already saw type T in file FH as undefined */
-
-static
-struct mips_pending *is_pending_type(fh, t)
-       FDR *fh;
-       struct type *t;
-{
-       int             f_idx = fh - (FDR *) cur_hdr->cbFdOffset;
-       register struct mips_pending *p;
-
-       for (p = pending_list[f_idx]; p; p = p->next)
-               if (p->t == t)
-                       break;
-       return p;
-}
-
 /* Add a new undef symbol SH of type T */
 
-static
+static void
 add_pending(fh, sh, t)
        FDR *fh;
        SYMR *sh;
@@ -714,67 +844,50 @@ add_pending(fh, sh, t)
 }
 
 /* Throw away undef entries when done with file index F_IDX */
+/* FIXME -- storage leak.  This is never called!!!   --gnu */
+
+#if 0
 
-static
+static void
 free_pending(f_idx)
+       int f_idx;
 {
        register struct mips_pending *p, *q;
 
        for (p = pending_list[f_idx]; p; p = q) {
                q = p->next;
-               free(p);
+               free((PTR)p);
        }
        pending_list[f_idx] = 0;
 }
 
-/* The number of args to a procedure is not explicit in the symtab,
-   this is the list of all those we know of.
-   This makes parsing more reasonable and avoids extra passes */
-
-static struct numarg {
-       struct numarg   *next;          /* link */
-       unsigned         adr;           /* procedure's start address */
-       unsigned         num;           /* arg count */
-} *numargs_list;
-
-/* Record that the procedure at ADR takes NUM arguments. */
-
-static
-got_numargs(adr,num)
-{
-       struct numarg  *n = (struct numarg *) xmalloc(sizeof(struct numarg));
-
-       n->adr = adr;
-       n->num = num;
-       n->next = numargs_list;
-       numargs_list = n;
-}
-
-/* See if we know how many arguments the procedure at ADR takes */
-
-static
-lookup_numargs(adr)
-{
-       struct numarg  *n = numargs_list;
-
-       while (n && n->adr != adr)
-               n = n->next;
-       return (n) ? n->num : -1;
-}
-
-/* Release storage when done with this file */
+#endif
 
-static void
-free_numargs()
+static char *
+prepend_tag_kind(tag_name, type_code)
+     char *tag_name;
+     enum type_code type_code;
 {
-       struct numarg  *n = numargs_list, *m;
+    char *prefix;
+    char *result;
+    switch (type_code) {
+      case TYPE_CODE_ENUM:
+       prefix = "enum ";
+       break;
+      case TYPE_CODE_STRUCT:
+       prefix = "struct ";
+       break;
+      case TYPE_CODE_UNION:
+       prefix = "union ";
+       break;
+      default:
+       prefix = "";
+    }
 
-       while (n) {
-               m = n->next;
-               free(n);
-               n = m;
-       }
-       numargs_list = 0;
+    result = (char*)obstack_alloc (&current_objfile->symbol_obstack,
+                                  strlen(prefix) + strlen(tag_name) + 1);
+    sprintf(result, "%s%s", prefix, tag_name);
+    return result;
 }
 
 \f
@@ -783,12 +896,15 @@ free_numargs()
 /* Parse a single symbol. Mostly just make up a GDB symbol for it.
    For blocks, procedures and types we open a new lexical context.
    This is basically just a big switch on the symbol's type.
+   Argument AX is the base pointer of aux symbols for this file (fh->iauxBase).
+   BIGEND says whether aux symbols are big-endian or little-endian.
    Return count of SYMR's handled (normally one). */
 
 static int
-parse_symbol(sh, ax)
+parse_symbol(sh, ax, bigend)
        SYMR *sh;
-       AUXU *ax;
+       union aux_ext *ax;
+       int bigend;
 {
        char *name;
        struct symbol  *s;
@@ -800,6 +916,7 @@ parse_symbol(sh, ax)
           we mark it explicitly */
        int             pend = (sh->reserved == 1);
        enum address_class class;
+       TIR             tir;
 
        switch (sh->st) {
 
@@ -810,14 +927,14 @@ parse_symbol(sh, ax)
                class = LOC_STATIC;
                b = BLOCKVECTOR_BLOCK(BLOCKVECTOR(top_stack->cur_st),
                                      GLOBAL_BLOCK);
-               s = new_symbol(sh->iss);
+               s = new_symbol((char *)sh->iss);
                SYMBOL_VALUE_ADDRESS(s) = (CORE_ADDR)sh->value;
                goto data;
 
            case stStatic:      /* static data, goes into current block. */
                class = LOC_STATIC;
                b = top_stack->cur_block;
-               s = new_symbol(sh->iss);
+               s = new_symbol((char *)sh->iss);
                SYMBOL_VALUE_ADDRESS(s) = (CORE_ADDR)sh->value;
                goto data;
 
@@ -825,11 +942,11 @@ parse_symbol(sh, ax)
                if (sh->sc == scRegister) {
                        class = LOC_REGISTER;
                        if (sh->value > 31)
-                               sh->value += 6;
+                               sh->value += FP0_REGNUM-32;
                } else
                        class = LOC_LOCAL;
                b = top_stack->cur_block;
-               s = new_symbol(sh->iss);
+               s = new_symbol((char *)sh->iss);
                SYMBOL_VALUE(s) = sh->value;
 
 data:          /* Common code for symbols describing data */
@@ -842,7 +959,7 @@ data:               /* Common code for symbols describing data */
                    sh->index == 0xfffff)
                        SYMBOL_TYPE(s) = builtin_type_int;      /* undefined? */
                else
-                       SYMBOL_TYPE(s) = parse_type(ax + sh->index, sh, 0);
+                       SYMBOL_TYPE(s) = parse_type(ax + sh->index, 0, bigend);
                /* Value of a data symbol is its memory address */
                break;
 
@@ -853,18 +970,18 @@ data:             /* Common code for symbols describing data */
                name = (char*)sh->iss;
                /* Special GNU C++ name.  */
                if (name[0] == CPLUS_MARKER && name[1] == 't' && name[2] == 0)
-                   name = "this";
+                   name = "this";      /* FIXME, not alloc'd in obstack */
                s = new_symbol(name);
 
                SYMBOL_NAMESPACE(s) = VAR_NAMESPACE;
                if (sh->sc == scRegister) {
                        SYMBOL_CLASS(s) = LOC_REGPARM;
                        if (sh->value > 31)
-                               sh->value += 6;
+                               sh->value += FP0_REGNUM-32;
                } else
                        SYMBOL_CLASS(s) = LOC_ARG;
                SYMBOL_VALUE(s) = sh->value;
-               SYMBOL_TYPE(s) = parse_type(ax + sh->index, sh, 0);
+               SYMBOL_TYPE(s) = parse_type(ax + sh->index, 0, bigend);
                add_symbol(s, top_stack->cur_block);
 #if 0
                /* FIXME:  This has not been tested.  See dbxread.c */
@@ -875,7 +992,7 @@ data:               /* Common code for symbols describing data */
                break;
 
            case stLabel:       /* label, goes into current block */
-               s = new_symbol(sh->iss);
+               s = new_symbol((char *)sh->iss);
                SYMBOL_NAMESPACE(s) = VAR_NAMESPACE;    /* so that it can be used */
                SYMBOL_CLASS(s) = LOC_LABEL;            /* but not misused */
                SYMBOL_VALUE_ADDRESS(s) = (CORE_ADDR)sh->value;
@@ -885,14 +1002,14 @@ data:            /* Common code for symbols describing data */
 
            case stProc:        /* Procedure, usually goes into global block */
            case stStaticProc:  /* Static procedure, goes into current block */
-               s = new_symbol(sh->iss);
+               s = new_symbol((char *)sh->iss);
                SYMBOL_NAMESPACE(s) = VAR_NAMESPACE;
                SYMBOL_CLASS(s) = LOC_BLOCK;
                /* Type of the return value */
                if (sh->sc == scUndefined || sh->sc == scNil)
                        t = builtin_type_int;
                else
-                       t = parse_type(ax + sh->index, sh, 0);
+                       t = parse_type(ax + sh->index + 1, 0, bigend);
                b = top_stack->cur_block;
                if (sh->st == stProc) {
                    struct blockvector *bv = BLOCKVECTOR(top_stack->cur_st);
@@ -907,8 +1024,8 @@ data:              /* Common code for symbols describing data */
                /* Make a type for the procedure itself */
 #if 0
                /* FIXME:  This has not been tested yet!  See dbxread.c */
-               /* Generate a template for the type of this function.  The 
-                  types of the arguments will be added as we read the symbol 
+               /* Generate a template for the type of this function.  The
+                  types of the arguments will be added as we read the symbol
                   table. */
                bcopy(SYMBOL_TYPE(s),lookup_function_type(t),sizeof(struct type));
 #else
@@ -938,157 +1055,182 @@ data:          /* Common code for symbols describing data */
                sh->value = (long) SYMBOL_TYPE(s);
                break;
 
+           /* Beginning of code for structure, union, and enum definitions.
+              They all share a common set of local variables, defined here.  */
+           {
+               enum type_code type_code;
+               SYMR *tsym;
+               int nfields;
+               long max_value;
+               struct field *f;
 
-#ifndef btVoid  /* btVoid was added late. */
-#define btVoid 26
-#endif                         
-/* These new symbol types have been recently added to SGI machines. */
-#ifndef stStruct
-#define stStruct 26
-#endif
-#ifndef stUnion
-#define stUnion 27
-#endif
-#ifndef stEnum
-#define stEnum 28
-#endif
-           case stStruct:
-           case stUnion:
-           case stEnum:
+           case stStruct:      /* Start a block defining a struct type */
+               type_code = TYPE_CODE_STRUCT;
+               goto structured_common;
+
+           case stUnion:       /* Start a block defining a union type */
+               type_code = TYPE_CODE_UNION;
+               goto structured_common;
+
+           case stEnum:        /* Start a block defining an enum type */
+               type_code = TYPE_CODE_ENUM;
+               goto structured_common;
 
            case stBlock:       /* Either a lexical block, or some type */
+               if (sh->sc != scInfo)
+                 goto case_stBlock_code;       /* Lexical block */
+
+               type_code = TYPE_CODE_UNDEF;    /* We have a type.  */
+
+           /* Common code for handling struct, union, enum, and/or as-yet-
+              unknown-type blocks of info about structured data.  `type_code'
+              has been set to the proper TYPE_CODE, if we know it.  */
+           structured_common:
                push_parse_stack();
                top_stack->blocktype = stBlock;
-               if (sh->sc == scInfo) { /* structure/union/enum def */
-                   int type_code =
-                       sh->st == stStruct ? TYPE_CODE_STRUCT
-                     : sh->st == stUnion ? TYPE_CODE_UNION
-                     : sh->st == stEnum ? TYPE_CODE_ENUM
-                     : TYPE_CODE_UNDEF;
-                   int nfields = 0;
-                   SYMR *tsym;
-                   long max_value = 0;
-                   struct field *f;
-
-                   s = new_symbol(sh->iss);
-                   SYMBOL_NAMESPACE(s) = STRUCT_NAMESPACE;
-                   SYMBOL_CLASS(s) = LOC_TYPEDEF;
-                   SYMBOL_VALUE(s) = 0;
-                   add_symbol(s, top_stack->cur_block);
-                   /* If this type was expected, use its partial definition */
-                   if (pend)
-                       t = is_pending_symbol(cur_fdr, sh)->t;
-                   else
-                       t = new_type(sh->iss);
-
-                   /* First count the number of fields. */
-                   for (tsym = sh+1; tsym->st != stEnd; tsym++)
-                       if (tsym->st == stMember) {
-                           if (nfields == 0 && type_code == TYPE_CODE_UNDEF)
-                               /* If the type of the member is Void,
-                                  assume the tag is an enumeration. */
-                               if (tsym->index == indexNil
-                                   || ax[tsym->index].ti.bt == btVoid)
+
+               s = new_symbol((char *)sh->iss);
+               SYMBOL_NAMESPACE(s) = STRUCT_NAMESPACE;
+               SYMBOL_CLASS(s) = LOC_TYPEDEF;
+               SYMBOL_VALUE(s) = 0;
+               add_symbol(s, top_stack->cur_block);
+
+               /* First count the number of fields and the highest value. */
+               nfields = 0;
+               max_value = 0;
+               for (tsym = sh+1; tsym->st != stEnd; tsym++)
+                 {
+                   if (tsym->st == stMember) {
+                       if (nfields == 0 && type_code == TYPE_CODE_UNDEF)
+                           /* If the type of the member is Nil (or Void),
+                              assume the tag is an enumeration. */
+                           if (tsym->index == indexNil)
+                               type_code = TYPE_CODE_ENUM;
+                           else {
+                               ecoff_swap_tir_in (bigend,
+                                                  &ax[tsym->index].a_ti,
+                                                  &tir);
+                               if (tir.bt == btNil || tir.bt == btVoid)
                                    type_code = TYPE_CODE_ENUM;
-                           nfields++;
-                           if (tsym->value > max_value)
-                               max_value = tsym->value;
-                       }
-                       else if (tsym->st == stBlock
-                                || tsym->st == stParsed) {
-                           if (tsym->sc == scVariant) ; /*UNIMPLEMENTED*/
-                           if (tsym->index != 0)
-                               tsym = ((SYMR*)cur_fdr->isymBase)
-                                   + tsym->index-1;
-                       }
-                   
-                   
-                   /* There is no guaranteed way to distinguish struct,
-                      unions, and enums at this point.  This is a bug in the
-                      original design (that has been fixed with the
-                      recent addition of the stStruct, stUnion, and stEnum
-                      symbol types.)  The way you can tell is if/when you
-                      see a variable or field of that type:  In that case
-                      the variable's type (in the AUX table) says if the
-                      type is struct, union, or enum,
-                      and points back to the stBlock here.
-                      So you can patch the tag kind up later - but only
-                      if there actually is a variable or field of that type.
-
-                      So until we know for sure, we will guess at this point.
-                      The heuristic is:
-                      If the first member has index==indexNil or a void type,
-                      assume we have an enumeration.
-                      Otherwise, if all the members have offset 0,
-                      assume we have a union.
-                      Otherwise, assume we have a struct.
-
-                      The heuristic could guess wrong in the case of
-                      of an enumeration with no members or a union
-                      with one (or zero) members, or when all except the
-                      last field of a struct have width zero.
-                      These are uncommon and/or illegal situations, and
-                      in any case guessing wrong probably doesn't matter much.
-
-                      But if we later do find out we were wrong,
-                      we fixup the tag kind.  Members of an enumeration
-                      must be handled differently from struct/union fields,
-                      and that is harder to patch up, but luckily we
-                      shouldn't need to.  (If there are any enumeration
-                      members, we can tell for sure it's an enum here.) */
-
-                   if (type_code == TYPE_CODE_UNDEF)
-                       if (max_value == 0) type_code = TYPE_CODE_UNION;
-                       else type_code = TYPE_CODE_STRUCT;
-                   
-                   TYPE_CODE(t) = type_code;
-                   TYPE_NFIELDS(t) = nfields;
-                   TYPE_FIELDS(t) = f = (struct field*)
-                       obstack_alloc (symbol_obstack,
-                                      nfields * sizeof (struct field));
-                   
-                   if (type_code == TYPE_CODE_ENUM) {
-                       /* This is a non-empty enum. */
-                       while (sh[1].st == stMember) {
-                           struct symbol *enum_sym;
-                           sh++;
-                           f->bitpos = sh->value;
-                           f->type = t;
-                           f->name = (char*)sh->iss;
-                           f->bitsize = 0;
-                           
-                           enum_sym = (struct symbol *)
-                               obstack_alloc (symbol_obstack,
-                                              sizeof (struct symbol));
-                           memset (enum_sym, 0, sizeof (struct symbol));
-                           SYMBOL_NAME (enum_sym) = f->name;
-                           SYMBOL_CLASS (enum_sym) = LOC_CONST;
-                           SYMBOL_TYPE (enum_sym) = t;
-                           SYMBOL_NAMESPACE (enum_sym) = VAR_NAMESPACE;
-                           SYMBOL_VALUE (enum_sym) = sh->value;
-                           add_symbol(enum_sym, top_stack->cur_block);
-                           
-                           /* Skip the stMembers that we've handled. */
-                           count++;
-                           f++;
-                       }
+                           }
+                       nfields++;
+                       if (tsym->value > max_value)
+                           max_value = tsym->value;
+                   }
+                   else if (tsym->st == stBlock
+                            || tsym->st == stUnion
+                            || tsym->st == stEnum
+                            || tsym->st == stStruct
+                            || tsym->st == stParsed) {
+                       if (tsym->sc == scVariant) ; /*UNIMPLEMENTED*/
+                       if (tsym->index != 0)
+                           tsym = ((SYMR*)cur_fdr->isymBase)
+                               + tsym->index-1;
+                   }
+                   else complain (&block_member_complaint, (char *)tsym->st);
+                 }
+               
+               /* In an stBlock, there is no way to distinguish structs,
+                  unions, and enums at this point.  This is a bug in the
+                  original design (that has been fixed with the
+                  recent addition of the stStruct, stUnion, and stEnum
+                  symbol types.)  The way you can tell is if/when you
+                  see a variable or field of that type.  In that case
+                  the variable's type (in the AUX table) says if the
+                  type is struct, union, or enum,
+                  and points back to the stBlock here.
+                  So you can patch the tag kind up later - but only
+                  if there actually is a variable or field of that type.
+
+                  So until we know for sure, we will guess at this point.
+                  The heuristic is:
+                  If the first member has index==indexNil or a void type,
+                  assume we have an enumeration.
+                  Otherwise, if there is more than one member, and all
+                  the members have offset 0, assume we have a union.
+                  Otherwise, assume we have a struct.
+
+                  The heuristic could guess wrong in the case of
+                  of an enumeration with no members or a union
+                  with one (or zero) members, or when all except the
+                  last field of a struct have width zero.
+                  These are uncommon and/or illegal situations, and
+                  in any case guessing wrong probably doesn't matter much.
+
+                  But if we later do find out we were wrong,
+                  we fixup the tag kind.  Members of an enumeration
+                  must be handled differently from struct/union fields,
+                  and that is harder to patch up, but luckily we
+                  shouldn't need to.  (If there are any enumeration
+                  members, we can tell for sure it's an enum here.) */
+
+               if (type_code == TYPE_CODE_UNDEF)
+                   if (nfields > 1 && max_value == 0)
+                     type_code = TYPE_CODE_UNION;
+                   else
+                     type_code = TYPE_CODE_STRUCT;
+               
+               /* If this type was expected, use its partial definition */
+               if (pend)
+                   t = is_pending_symbol(cur_fdr, sh)->t;
+               else
+                   t = new_type(prepend_tag_kind((char *)sh->iss,
+                                                 type_code));
+
+               TYPE_CODE(t) = type_code;
+               TYPE_LENGTH(t) = sh->value;
+               TYPE_NFIELDS(t) = nfields;
+               TYPE_FIELDS(t) = f = (struct field*)
+                 obstack_alloc (&current_objfile -> type_obstack,
+                                nfields * sizeof (struct field));
+               
+               if (type_code == TYPE_CODE_ENUM) {
+                   /* This is a non-empty enum. */
+                   for (tsym = sh + 1; tsym->st == stMember; tsym++) {
+                       struct symbol *enum_sym;
+                       f->bitpos = tsym->value;
+                       f->type = t;
+                       f->name = (char*)tsym->iss;
+                       f->bitsize = 0;
+                       
+                       enum_sym = (struct symbol *)
+                           obstack_alloc (&current_objfile->symbol_obstack,
+                                          sizeof (struct symbol));
+                       memset ((PTR)enum_sym, 0, sizeof (struct symbol));
+                       SYMBOL_NAME (enum_sym) = f->name;
+                       SYMBOL_CLASS (enum_sym) = LOC_CONST;
+                       SYMBOL_TYPE (enum_sym) = t;
+                       SYMBOL_NAMESPACE (enum_sym) = VAR_NAMESPACE;
+                       SYMBOL_VALUE (enum_sym) = tsym->value;
+                       add_symbol(enum_sym, top_stack->cur_block);
+                       
+                       /* Skip the stMembers that we've handled. */
+                       count++;
+                       f++;
                    }
-                   SYMBOL_TYPE(s) = t;
-                   /* make this the current type */
-                   top_stack->cur_type = t;
-                   top_stack->cur_field = 0;
-                   TYPE_LENGTH(t) = sh->value;
-                   /* Mark that symbol has a type, and say which one */
-                   sh->value = (long) t;
-               } else {
-                       /* beginnning of (code) block. Value of symbol
-                          is the displacement from procedure start */
-                       b = new_block(top_stack->maxsyms);
-                       BLOCK_START(b) = sh->value + top_stack->procadr;
-                       BLOCK_SUPERBLOCK(b) = top_stack->cur_block;
-                       top_stack->cur_block = b;
-                       add_block(b, top_stack->cur_st);
                }
+               SYMBOL_TYPE(s) = t;
+               /* make this the current type */
+               top_stack->cur_type = t;
+               top_stack->cur_field = 0;
+               /* Mark that symbol has a type, and say which one */
+               sh->value = (long) t;
+               break;
+
+           /* End of local variables shared by struct, union, enum, and
+              block (as yet unknown struct/union/enum) processing.  */
+           }
+
+           case_stBlock_code:
+               /* beginnning of (code) block. Value of symbol
+                  is the displacement from procedure start */
+               push_parse_stack();
+               top_stack->blocktype = stBlock;
+               b = new_block(top_stack->maxsyms);
+               BLOCK_START(b) = sh->value + top_stack->procadr;
+               BLOCK_SUPERBLOCK(b) = top_stack->cur_block;
+               top_stack->cur_block = b;
+               add_block(b, top_stack->cur_st);
                break;
 
            case stEnd:         /* end (of anything) */
@@ -1100,11 +1242,25 @@ data:           /* Common code for symbols describing data */
                            top_stack->blocktype == stStaticProc)) {
                    /* Finished with procedure */
                    struct blockvector *bv = BLOCKVECTOR(top_stack->cur_st);
+                   struct mips_extra_func_info *e;
                    struct block *b;
                    int i;
 
                    BLOCK_END(top_stack->cur_block) += sh->value; /* size */
-                   got_numargs(top_stack->procadr, top_stack->numargs);
+
+                   /* Make up special symbol to contain procedure specific
+                      info */
+                   s = new_symbol(".gdbinfo.");
+                   SYMBOL_NAMESPACE(s) = LABEL_NAMESPACE;
+                   SYMBOL_CLASS(s) = LOC_CONST;
+                   SYMBOL_TYPE(s) = builtin_type_void;
+                   e = (struct mips_extra_func_info *)
+                     obstack_alloc (&current_objfile->symbol_obstack,
+                                    sizeof (struct mips_extra_func_info));
+                   SYMBOL_VALUE(s) = (int)e;
+                   e->numargs = top_stack->numargs;
+                   add_symbol(s, top_stack->cur_block);
+
                    /* Reallocate symbols, saving memory */
                    b = shrink_block(top_stack->cur_block, top_stack->cur_st);
 
@@ -1124,8 +1280,9 @@ data:             /* Common code for symbols describing data */
                           is the displacement from the procedure`s start
                           address of the end of this block. */
                        BLOCK_END(top_stack->cur_block) = sh->value + top_stack->procadr;
-                       (void) shrink_block(top_stack->cur_block, top_stack->cur_st);
-               }
+                       shrink_block(top_stack->cur_block, top_stack->cur_st);
+               } else complain (&stEnd_complaint, (char *)sh->sc);
+
                pop_parse_stack();      /* restore previous lexical context */
                break;
 
@@ -1134,16 +1291,16 @@ data:           /* Common code for symbols describing data */
                f->name = (char*)sh->iss;
                f->bitpos = sh->value;
                f->bitsize = 0;
-               f->type = parse_type(ax + sh->index, sh, &f->bitsize);
+               f->type = parse_type(ax + sh->index, &f->bitsize, bigend);
                break;
 
            case stTypedef:     /* type definition */
-               s = new_symbol(sh->iss);
+               s = new_symbol((char *)sh->iss);
                SYMBOL_NAMESPACE(s) = VAR_NAMESPACE;
                SYMBOL_CLASS(s) = LOC_TYPEDEF;
                SYMBOL_BLOCK_VALUE(s) = top_stack->cur_block;
                add_symbol(s, top_stack->cur_block);                    
-               SYMBOL_TYPE(s) = parse_type(ax + sh->index, sh, 0);
+               SYMBOL_TYPE(s) = parse_type(ax + sh->index, 0, bigend);
                sh->value = (long) SYMBOL_TYPE(s);
                break;
 
@@ -1160,19 +1317,23 @@ data:           /* Common code for symbols describing data */
            case stConstant:
                break;          /* constant */
            default:
-               error("Unknown symbol type %x.", sh->st);
+               complain(&unknown_mips_symtype_complaint, (char *)sh->st);
+               break;
        }
        sh->st = stParsed;
        return count;
 }
 
-/* Parse the type information provided in the AX entries for
-   the symbol SH. Return the bitfield size in BS, in case. */
+/* Parse the type information provided in the raw AX entries for
+   the symbol SH. Return the bitfield size in BS, in case.
+   We must byte-swap the AX entries before we use them; BIGEND says whether
+   they are big-endian or little-endian (from fh->fBigendian).  */
 
-static struct type *parse_type(ax, sh, bs)
-       AUXU    *ax;
-       SYMR    *sh;
+static struct type *
+parse_type(ax, bs, bigend)
+       union aux_ext   *ax;
        int     *bs;
+       int     bigend;
 {
        /* Null entries in this map are treated specially */
        static struct type **map_bt[] =
@@ -1204,27 +1365,21 @@ static struct type *parse_type(ax, sh, bs)
                 0,                             /* btBit */
                 0,                             /* btPicture */
                 &builtin_type_void,            /* btVoid */
+                &builtin_type_long_long,       /* btLongLong */
+                &builtin_type_unsigned_long_long,/* btULongLong */
        };
 
-       TIR            *t;
+       TIR            t[1];
        struct type    *tp = 0;
        char           *fmt;
-       int             i;
-       int type_code;
-
-       /* Procedures start off by one */
-       if (sh->st == stProc || sh->st == stStaticProc)
-               ax++;
-
-       /* Undefined ? Should not happen */
-       if (ax->rndx.rfd == 0xfff) {
-               return builtin_type_void;
-       }
+       union aux_ext *tax;
+       enum type_code type_code;
 
-       /* Use aux as a type information record, map its basic type */
-       t = &ax->ti;
+       /* Use aux as a type information record, map its basic type.  */
+       tax = ax;
+       ecoff_swap_tir_in (bigend, &tax->a_ti, t);
        if (t->bt > (sizeof (map_bt)/sizeof (*map_bt))) {
-               complain (&basic_type_complaint, t->bt);
+               complain (&basic_type_complaint, (char *)t->bt);
                return builtin_type_int;
        }
        if (map_bt[t->bt]) {
@@ -1260,22 +1415,26 @@ static struct type *parse_type(ax, sh, bs)
                        break;
                    case btTypedef:
                    default:
-                       complain (&basic_type_complaint, t->bt);
+                       complain (&basic_type_complaint, (char *)t->bt);
                        return builtin_type_int;
                }
        }
 
-       /* Move on to next aux */
-       ax++;
+       /* Skip over any further type qualifiers (FIXME).  */
        if (t->continued) {
                /* This is the way it would work if the compiler worked */
-               register TIR *t1 = t;
-               while (t1->continued)
+               TIR t1[1];
+               do {
                        ax++;
+                       ecoff_swap_tir_in (bigend, ax, t1);
+               } while (t1->continued);
        }
 
+       /* Move on to next aux */
+       ax++;
+
        if (t->fBitfield) {
-               *bs = ax->width;
+               *bs = AUX_GET_WIDTH (bigend, ax);
                ax++;
        }
 
@@ -1292,35 +1451,38 @@ static struct type *parse_type(ax, sh, bs)
                char            name[256], *pn;
 
                /* Try to cross reference this type */
-               ax += cross_ref(ax, &tp, type_code, &pn);
+               ax += cross_ref(ax, &tp, type_code, &pn, bigend);
                /* reading .o file ? */
                if (UNSAFE_DATA_ADDR(tp))
-                   tp = make_type(type_code, 0, 0, 0);
+                   tp = init_type(type_code, 0, 0, (char *) NULL,
+                                  (struct objfile *) NULL);
                /* SOMEONE OUGHT TO FIX DBXREAD TO DROP "STRUCT" */
                sprintf(name, fmt, pn);
 
                /* Usually, TYPE_CODE(tp) is already type_code.  The main
                   exception is if we guessed wrong re struct/union/enum. */
                if (TYPE_CODE(tp) != type_code) {
-                   complain (&bad_tag_guess_complaint, 0);
+                   complain (&bad_tag_guess_complaint, name);
                    TYPE_CODE(tp) = type_code;
                }
-               TYPE_NAME(tp) = obsavestring(pn, strlen(pn));
+               if (TYPE_NAME(tp) == NULL || strcmp(TYPE_NAME(tp), name) != 0)
+                   TYPE_NAME(tp) = obsavestring(name, strlen(name),
+                                                &current_objfile -> type_obstack);
        }
 
        /* Deal with range types */
        if (t->bt == btRange) {
-               struct field   *f;
-
                TYPE_NFIELDS (tp) = 2;
                TYPE_FIELDS (tp) =
-                   (struct field *) obstack_alloc (symbol_obstack,
-                                                   2 * sizeof (struct field));
-               TYPE_FIELD_NAME (tp, 0) = "Low";
-               TYPE_FIELD_BITPOS (tp, 0) = ax->dnLow;
+                 (struct field *) obstack_alloc (&current_objfile -> type_obstack,
+                                                 2 * sizeof (struct field));
+               TYPE_FIELD_NAME (tp, 0) = obsavestring ("Low", strlen ("Low"),
+                                                       &current_objfile -> type_obstack);
+               TYPE_FIELD_BITPOS (tp, 0) = AUX_GET_DNLOW (bigend, ax);
                ax++;
-               TYPE_FIELD_NAME (tp, 1) = "High";
-               TYPE_FIELD_BITPOS (tp, 1) = ax->dnHigh;
+               TYPE_FIELD_NAME (tp, 1) = obsavestring ("High", strlen ("High"),
+                                                       &current_objfile -> type_obstack);
+               TYPE_FIELD_BITPOS (tp, 1) = AUX_GET_DNHIGH (bigend, ax);
                ax++;
        }
 
@@ -1328,7 +1490,7 @@ static struct type *parse_type(ax, sh, bs)
           than 6 the game will continue in the next aux */
 
 #define PARSE_TQ(tq) \
-       if (t->tq != tqNil) ax += upgrade_type(&tp, t->tq, ax, sh);
+       if (t->tq != tqNil) ax += upgrade_type(&tp, t->tq, ax, bigend);
 
 again: PARSE_TQ(tq0);
        PARSE_TQ(tq1);
@@ -1339,7 +1501,8 @@ again:    PARSE_TQ(tq0);
 #undef PARSE_TQ
 
        if (t->continued) {
-               t++;
+               tax++;
+               ecoff_swap_tir_in (bigend, &tax->a_ti, t);
                goto again;
        }
        return tp;
@@ -1348,24 +1511,26 @@ again:  PARSE_TQ(tq0);
 /* Make up a complex type from a basic one.  Type is passed by
    reference in TPP and side-effected as necessary. The type
    qualifier TQ says how to handle the aux symbols at AX for
-   the symbol SX we are currently analyzing.
+   the symbol SX we are currently analyzing.  BIGEND says whether
+   aux symbols are big-endian or little-endian.
    Returns the number of aux symbols we parsed. */
 
 static int
-upgrade_type(tpp, tq, ax, sh)
-       struct type   **tpp;
-       AUXU           *ax;
-       SYMR           *sh;
+upgrade_type(tpp, tq, ax, bigend)
+       struct type  **tpp;
+       int            tq;
+       union aux_ext *ax;
+       int            bigend;
 {
-       int             off;
-       struct type    *t;
+       int            off;
+       struct type   *t;
 
        /* Used in array processing */
        int             rf, id;
        FDR            *fh;
        struct field   *f;
-       SYMR            ss;
        int             lower, upper;
+       RNDXR           rndx;
 
        switch (tq) {
        case tqPtr:
@@ -1380,14 +1545,17 @@ upgrade_type(tpp, tq, ax, sh)
 
        case tqArray:
                off = 0;
-               t = make_type(TYPE_CODE_ARRAY, 0, 0, 0);
+               t = init_type(TYPE_CODE_ARRAY, 0, 0, (char *) NULL,
+                             (struct objfile *) NULL);
                TYPE_TARGET_TYPE(t) = *tpp;
 
                /* Determine and record the domain type (type of index) */
-               id = ax->rndx.index;
-               rf = ax->rndx.rfd;
+               ecoff_swap_rndx_in (bigend, ax, &rndx);
+               id = rndx.index;
+               rf = rndx.rfd;
                if (rf == 0xfff) {
-                       rf = (++ax)->isym;
+                       ax++;
+                       rf = AUX_GET_ISYM (bigend, ax);
                        off++;
                }
                fh = get_rfd(cur_fd, rf);
@@ -1396,37 +1564,24 @@ upgrade_type(tpp, tq, ax, sh)
                /* FIXME - Memory leak! */
                if (TYPE_NFIELDS(t))
                    TYPE_FIELDS(t) = (struct field*)
-                       xrealloc(TYPE_FIELDS(t),
+                       xrealloc((PTR) TYPE_FIELDS(t),
                                 (TYPE_NFIELDS(t)+1) * sizeof(struct field));
                else
                    TYPE_FIELDS(t) = (struct field*)
                        xzalloc(sizeof(struct field));
                f = &(TYPE_FIELD(t,TYPE_NFIELDS(t)));
                TYPE_NFIELDS(t)++;
-               memset(f, 0, sizeof(struct field));
+               memset((PTR)f, 0, sizeof(struct field));
 
-               memset(&ss, 0, sizeof ss);
-/* XXX */      f->type = parse_type(fh->iauxBase + id * sizeof(AUXU),
-                                    &ss, &f->bitsize);
+/* XXX */      f->type = parse_type(id + (union aux_ext *)fh->iauxBase,
+                                    &f->bitsize, bigend);
 
-               if (off == 0) {
-               /*
-                * This seems to be a pointer to the end of the Block defining
-                * the type.  Why it is here is magic for me, and I have no
-                * good use for it anyways.
-                */
-                       /* This used to occur because cross_ref returned
-                          the wrong result (ax pointed wrong).  FIXME,
-                          delete this code in a while.  -- gnu@cygnus jul91 */
-                       complain (&array_parse_complaint, 0);
-                       off++;
-                       id = (++ax)->rndx.index;
-                       if ((rf = ax->rndx.rfd) == 0xfff)
-                               rf = (++ax)->isym, off++;
-               }
-               lower = (++ax)->dnLow;
-               upper = (++ax)->dnHigh;
-               rf = (++ax)->width;     /* bit size of array element */
+               ax++;
+               lower = AUX_GET_DNLOW (bigend, ax);
+               ax++;
+               upper = AUX_GET_DNHIGH (bigend, ax);
+               ax++;
+               rf = AUX_GET_WIDTH (bigend, ax);        /* bit size of array element */
 
                /* Check whether supplied array element bit size matches
                   the known size of the element type.  If this complaint
@@ -1440,7 +1595,7 @@ upgrade_type(tpp, tq, ax, sh)
                        TYPE_LENGTH(TYPE_TARGET_TYPE(t)) = id >> 3;
                }
                if (id != rf)
-                       complain (&array_bitsize_complaint, rf);
+                       complain (&array_bitsize_complaint, (char *)rf);
 
                TYPE_LENGTH(t) = (upper < 0) ? 0 :
                        (upper - lower + 1) * (rf >> 3);
@@ -1451,74 +1606,82 @@ upgrade_type(tpp, tq, ax, sh)
                /* Volatile -- currently ignored */
                return 0;
 
+       case tqConst:
+               /* Const -- currently ignored */
+               return 0;
+
        default:
-               complain (&unknown_type_qual_complaint, tq);
+               complain (&unknown_type_qual_complaint, (char *)tq);
                return 0;
        }
 }
 
 
 /* Parse a procedure descriptor record PR.  Note that the procedure
-   is parsed _after_ the local symbols, now we just make up the
-   extra information we need into a special symbol that we insert
-   in the procedure's main block.  Note also that images that
+   is parsed _after_ the local symbols, now we just insert the extra
+   information we need into a special ".gdbinfo." symbol that has already
+   been placed in the procedure's main block.  Note also that images that
    have been partially stripped (ld -x) have been deprived
    of local symbols, and we have to cope with them here.
    The procedure's code ends at BOUND */
 
-static
-parse_procedure(pr, bound)
+static void
+parse_procedure (pr, bound, have_stabs)
        PDR *pr;
+       int bound;
+       int have_stabs;
 {
-       struct symbol *s, *i;
-       SYMR *sh = (SYMR*)pr->isym;
-       struct block *b;
-       struct mips_extra_func_info *e;
-       char name[100];
-       char *sh_name;
-
-       /* Reuse the MIPS record */
-       e = (struct mips_extra_func_info *) pr;
-       e->numargs = lookup_numargs(pr->adr);
-
-       /* Make up our special symbol */
-       i = new_symbol(".gdbinfo.");
-       SYMBOL_VALUE(i) = (int)e;
-       SYMBOL_NAMESPACE(i) = LABEL_NAMESPACE;
-       SYMBOL_CLASS(i) = LOC_CONST;
-       SYMBOL_TYPE(i) = builtin_type_void;
-
-       /* Make up a name for static procedures. Sigh. */
-       if (sh == (SYMR*)-1) {
-           sprintf(name,".static_procedure@%x",pr->adr);
-           sh_name = savestring(name, strlen(name));
-           s = NULL;
-       }
-       else {
-           sh_name = (char*)sh->iss;
-           s = mylookup_symbol(sh_name, top_stack->cur_block,
-                               VAR_NAMESPACE, LOC_BLOCK);
-       }
-       if (s != 0) {
-               b = SYMBOL_BLOCK_VALUE(s);
-       } else {
-               s = new_symbol(sh_name);
-               SYMBOL_NAMESPACE(s) = VAR_NAMESPACE;
-               SYMBOL_CLASS(s) = LOC_BLOCK;
-               /* Donno its type, hope int is ok */
-               SYMBOL_TYPE(s) = lookup_function_type (builtin_type_int);
-               add_symbol(s, top_stack->cur_block);
-               /* Wont have symbols for this one */
-               b = new_block(2);
-               SYMBOL_BLOCK_VALUE(s) = b;
-               BLOCK_FUNCTION(b) = s;
-               BLOCK_START(b) = pr->adr;
-               BLOCK_END(b) = bound;
-               BLOCK_SUPERBLOCK(b) = top_stack->cur_block;
-               add_block(b, top_stack->cur_st);
-       }
-       e->isym = (long)s;
-       add_symbol(i,b);
+    struct symbol *s, *i;
+    SYMR *sh = (SYMR*)pr->isym;
+    struct block *b;
+    struct mips_extra_func_info *e;
+    char *sh_name;
+
+    /* Static procedure at address pr->adr.  Sigh. */
+    if (sh == (SYMR*)-1) {
+       complain (&pdr_static_symbol_complaint, (char *)pr->adr);
+       return;
+    }
+    sh_name = (char*)sh->iss;
+    if (have_stabs)
+       s = lookup_symbol(sh_name, NULL, VAR_NAMESPACE, 0, NULL);
+    else
+       s = mylookup_symbol(sh_name, top_stack->cur_block,
+                           VAR_NAMESPACE, LOC_BLOCK);
+
+    if (s != 0) {
+           b = SYMBOL_BLOCK_VALUE(s);
+    } else {
+           complain (&pdr_for_nonsymbol_complaint, sh_name);
+#if 1
+       return;
+#else    
+/* FIXME -- delete.  We can't do symbol allocation now; it's all done.  */
+           s = new_symbol(sh_name);
+           SYMBOL_NAMESPACE(s) = VAR_NAMESPACE;
+           SYMBOL_CLASS(s) = LOC_BLOCK;
+           /* Donno its type, hope int is ok */
+           SYMBOL_TYPE(s) = lookup_function_type (builtin_type_int);
+           add_symbol(s, top_stack->cur_block);
+           /* Wont have symbols for this one */
+           b = new_block(2);
+           SYMBOL_BLOCK_VALUE(s) = b;
+           BLOCK_FUNCTION(b) = s;
+           BLOCK_START(b) = pr->adr;
+           BLOCK_END(b) = bound;
+           BLOCK_SUPERBLOCK(b) = top_stack->cur_block;
+           add_block(b, top_stack->cur_st);
+#endif
+    }
+
+    i = mylookup_symbol(".gdbinfo.", b, LABEL_NAMESPACE, LOC_CONST);
+
+    if (i)
+      {
+       e = (struct mips_extra_func_info *)SYMBOL_VALUE(i);
+       e->pdr = *pr;
+       e->pdr.isym = (long)s;
+      }
 }
 
 /* Parse the external symbol ES. Just call parse_symbol() after
@@ -1526,26 +1689,26 @@ parse_procedure(pr, bound)
    parsing of the PDRs has already provided all the needed
    information, we only parse them if SKIP_PROCEDURES is false,
    and only if this causes no symbol duplication.
+   BIGEND says whether aux entries are big-endian or little-endian.
 
    This routine clobbers top_stack->cur_block and ->cur_st. */
 
-static
-parse_external(es, skip_procedures)
+static void
+parse_external(es, skip_procedures, bigend)
        EXTR *es;
+       int skip_procedures;
+       int bigend;
 {
-       AUXU *ax;
+       union aux_ext *ax;
 
        if (es->ifd != ifdNil) {
                cur_fd = es->ifd;
                cur_fdr = (FDR*)(cur_hdr->cbFdOffset) + cur_fd;
-               ax = (AUXU*)cur_fdr->iauxBase;
+               ax = (union aux_ext *)cur_fdr->iauxBase;
        } else {
                cur_fdr = (FDR*)(cur_hdr->cbFdOffset);
                ax = 0;
        }
-       top_stack->cur_st = cur_stab;
-       top_stack->cur_block = BLOCKVECTOR_BLOCK(BLOCKVECTOR(top_stack->cur_st),
-                                                GLOBAL_BLOCK);
 
        /* Reading .o files */
        if (es->asym.sc == scUndefined || es->asym.sc == scNil) {
@@ -1558,9 +1721,10 @@ parse_external(es, skip_procedures)
                default :       what = "symbol";                      break;
                }
                n_undef_symbols++;
+               /* FIXME:  Turn this into a complaint? */
                if (info_verbose)
-                       printf_filtered("Warning: %s `%s' is undefined (in %s)\n", what,
-                               es->asym.iss, fdr_name(cur_fdr->rss));
+                   printf_filtered("Warning: %s `%s' is undefined (in %s)\n",
+                        what, es->asym.iss, fdr_name((char *)cur_fdr->rss));
                return;
        }
 
@@ -1569,8 +1733,8 @@ parse_external(es, skip_procedures)
                /* If we have full symbols we do not need more */
                if (skip_procedures)
                        return;
-               if (mylookup_symbol (es->asym.iss, top_stack->cur_block,
-                                       VAR_NAMESPACE, LOC_BLOCK))
+               if (mylookup_symbol ((char *)es->asym.iss, top_stack->cur_block,
+                                    VAR_NAMESPACE, LOC_BLOCK))
                        break;
                /* fall through */
        case stGlobal:
@@ -1579,7 +1743,7 @@ parse_external(es, skip_procedures)
                 * Note that the case of a symbol with indexNil
                 * must be handled anyways by parse_symbol().
                 */
-               parse_symbol(&es->asym, ax);
+               parse_symbol(&es->asym, ax, bigend);
                break;
        default:
                break;
@@ -1592,13 +1756,13 @@ parse_external(es, skip_procedures)
    numbers can go back and forth, apparently we can live
    with that and do not need to reorder our linetables */
 
-static
+static void
 parse_lines(fh, lt)
        FDR *fh;
        struct linetable *lt;
 {
        unsigned char *base = (unsigned char*)fh->cbLineOffset;
-       int i, j, k;
+       int j, k;
        int delta, count, lineno = 0;
        PDR *pr;
 
@@ -1606,7 +1770,7 @@ parse_lines(fh, lt)
                return;
 
        /* Scan by procedure descriptors */
-       i = 0; j = 0, k = 0;
+       j = 0, k = 0;
        for (pr = (PDR*)IPDFIRST(cur_hdr,fh); j < fh->cpd; j++, pr++) {
                int l, halt;
 
@@ -1651,7 +1815,6 @@ parse_lines(fh, lt)
                }
        }
 }
-
 \f
 /* Master parsing procedure for first-pass reading of file symbols
    into a partial_symtab.
@@ -1660,156 +1823,181 @@ parse_lines(fh, lt)
    END_OF_TEXT_SEG gives the address just after the text segment for
    the symtab we are reading.  */
 
-static
-parse_partial_symbols(end_of_text_seg, objfile)
-       int end_of_text_seg;
-       struct objfile *objfile;
+static void
+parse_partial_symbols (end_of_text_seg, objfile)
+     int end_of_text_seg;
+     struct objfile *objfile;
 {
-       int             f_idx, s_idx;
-/*     int  stat_idx, h_max;*/
-       HDRR            *hdr;
-       /* Running pointers */
-       FDR             *fh;
-       RFDT            *rh;
-       register EXTR   *esh;
-       register SYMR   *sh;
-       struct partial_symtab *pst;
-
-  int past_first_source_file = 0;
-
-  /* List of current psymtab's include files */
-  char **psymtab_include_list;
-  int includes_allocated;
-  int includes_used;
+    int                         f_idx, s_idx;
+    HDRR               *hdr = cur_hdr;
+    /* Running pointers */
+    FDR                        *fh;
+    register EXTR      *esh;
+    register SYMR      *sh;
+    struct partial_symtab *pst;
+
+    int past_first_source_file = 0;
+
+    /* List of current psymtab's include files */
+    char **psymtab_include_list;
+    int includes_allocated;
+    int includes_used;
+    EXTR **extern_tab;
+    struct pst_map * fdr_to_pst;
+    /* Index within current psymtab dependency list */
+    struct partial_symtab **dependency_list;
+    int dependencies_used, dependencies_allocated;
+    struct cleanup *old_chain;
+
+    extern_tab = (EXTR**)obstack_alloc (&objfile->psymbol_obstack,
+                                       sizeof(EXTR *) * hdr->iextMax);
+
+    includes_allocated = 30;
+    includes_used = 0;
+    psymtab_include_list = (char **) alloca (includes_allocated *
+                                            sizeof (char *));
+    next_symbol_text_func = mips_next_symbol_text;
+
+    dependencies_allocated = 30;
+    dependencies_used = 0;
+    dependency_list =
+       (struct partial_symtab **) alloca (dependencies_allocated *
+                                          sizeof (struct partial_symtab *));
+
+    last_source_file = 0;
+
+    /*
+     * Big plan:
+     *
+     * Only parse the Local and External symbols, and the Relative FDR.
+     * Fixup enough of the loader symtab to be able to use it.
+     * Allocate space only for the file's portions we need to
+     * look at. (XXX)
+     */
+
+    max_gdbinfo = 0;
+    max_glevel = MIN_GLEVEL;
+
+    /* Allocate the map FDR -> PST.
+       Minor hack: -O3 images might claim some global data belongs
+       to FDR -1. We`ll go along with that */
+    fdr_to_pst = (struct pst_map *)xzalloc((hdr->ifdMax+1) * sizeof *fdr_to_pst);
+    old_chain = make_cleanup (free, fdr_to_pst);
+    fdr_to_pst++;
+    {
+       struct partial_symtab * pst = new_psymtab("", objfile);
+       fdr_to_pst[-1].pst = pst;
+       FDR_IDX(pst) = -1;
+    }
 
-  /* Index within current psymtab dependency list */
-  struct partial_symtab **dependency_list;
-  int dependencies_used, dependencies_allocated;
+    /* Pass 1 over external syms: Presize and partition the list */
+    for (s_idx = 0; s_idx < hdr->iextMax; s_idx++) {
+       esh = (EXTR *) (hdr->cbExtOffset) + s_idx;
+       fdr_to_pst[esh->ifd].n_globals++;
+    }
 
-  includes_allocated = 30;
-  includes_used = 0;
-  psymtab_include_list = (char **) alloca (includes_allocated *
-                                          sizeof (char *));
-  next_symbol_text_func = mips_next_symbol_text;
+    /* Pass 1.5 over files:  partition out global symbol space */
+    s_idx = 0;
+    for (f_idx = -1; f_idx < hdr->ifdMax; f_idx++) {
+       fdr_to_pst[f_idx].globals_offset = s_idx;
+       s_idx += fdr_to_pst[f_idx].n_globals;
+       fdr_to_pst[f_idx].n_globals = 0;
+    }
 
-  dependencies_allocated = 30;
-  dependencies_used = 0;
-  dependency_list =
-    (struct partial_symtab **) alloca (dependencies_allocated *
-                                      sizeof (struct partial_symtab *));
+    /* Pass 2 over external syms: fill in external symbols */
+    for (s_idx = 0; s_idx < hdr->iextMax; s_idx++) {
+       enum minimal_symbol_type ms_type = mst_text;
+       esh = (EXTR *) (hdr->cbExtOffset) + s_idx;
 
-  last_source_file = 0;
+       extern_tab[fdr_to_pst[esh->ifd].globals_offset
+                  + fdr_to_pst[esh->ifd].n_globals++] = esh;
 
-       /*
-        * Big plan: 
-        *
-        * Only parse the Local and External symbols, and the Relative FDR.
-        * Fixup enough of the loader symtab to be able to use it.
-        * Allocate space only for the file's portions we need to
-        * look at. (XXX)
-        */
-
-       hdr = cur_hdr;
-       max_gdbinfo = 0;
-       max_glevel = MIN_GLEVEL;
+       if (esh->asym.sc == scUndefined || esh->asym.sc == scNil)
+               continue;
 
-       /* Allocate the map FDR -> PST.
-          Minor hack: -O3 images might claim some global data belongs
-          to FDR -1. We`ll go along with that */
-       fdr_to_pst = (struct pst_map *)xzalloc((hdr->ifdMax+1) * sizeof *fdr_to_pst);
-       fdr_to_pst++;
-       {
-               struct partial_symtab * pst = new_psymtab("", objfile);
-               fdr_to_pst[-1].pst = pst;
-               FDR_IDX(pst) = -1;
+       switch (esh->asym.st) {
+       case stProc:
+               break;
+       case stGlobal:
+               ms_type = mst_data;
+               break;
+       case stLabel:
+               break;
+       default:
+               ms_type = mst_unknown;
+               complain (&unknown_ext_complaint, (char *)esh->asym.iss);
        }
+       prim_record_minimal_symbol ((char *)esh->asym.iss,
+                                   esh->asym.value,
+                                   ms_type);
+    }
 
-       /* Pass 2 over external syms: fill in external symbols */
-       for (s_idx = 0; s_idx < hdr->iextMax; s_idx++) {
-               register struct partial_symbol *p;
-               enum misc_function_type misc_type = mf_text;
-               esh = (EXTR *) (hdr->cbExtOffset) + s_idx;
-
-               if (esh->asym.sc == scUndefined || esh->asym.sc == scNil)
-                       continue;
+    /* Pass 3 over files, over local syms: fill in static symbols */
+    for (f_idx = 0; f_idx < hdr->ifdMax; f_idx++) {
+       struct partial_symtab *save_pst;
+       EXTR **ext_ptr;
+       cur_fdr = fh = f_idx + (FDR *)(cur_hdr->cbFdOffset);
 
-               switch (esh->asym.st) {
-               case stProc:
-                       break;
-               case stGlobal:
-                       misc_type = mf_data;
-                       break;
-               case stLabel:
-                       break;
-               default:
-                       misc_type = mf_unknown;
-                       complain (&unknown_ext_complaint, SYMBOL_NAME(p));
-               }
-               prim_record_misc_function ((char *)(esh->asym.iss),
-                                          esh->asym.value,
-                                          misc_type);
+       if (fh->csym == 0) {
+           fdr_to_pst[f_idx].pst = NULL;
+           continue;
        }
-
-       /* Pass 3 over files, over local syms: fill in static symbols */
-       for (f_idx = 0; f_idx < hdr->ifdMax; f_idx++) {
-           struct partial_symtab *save_pst;
-           
-           cur_fdr = fh = f_idx + (FDR *)(cur_hdr->cbFdOffset);
-
-           if (fh->csym == 0) {
-               fdr_to_pst[f_idx].pst = NULL;
-               continue;
-           }
-           pst = start_psymtab (objfile, 0, (char*)fh->rss,
-                                fh->cpd ? fh->adr : 0,
-                                -1,
-                                global_psymbols.next,
-                                static_psymbols.next);
-           save_pst = pst;
-           /* Make everything point to everything. */
-           FDR_IDX(pst) = f_idx;
-           fdr_to_pst[f_idx].pst = pst;
-           fh->ioptBase = (int)pst;
-           
-           CUR_HDR(pst) = cur_hdr;
-           
-           /* The way to turn this into a symtab is to call... */
-           pst->read_symtab = mipscoff_psymtab_to_symtab;
-           
-           pst->texthigh = pst->textlow;
-           
-           pst->globals_offset = global_psymbols.next - global_psymbols.list;
-           pst->statics_offset = static_psymbols.next - static_psymbols.list;
-           
-           pst->n_global_syms = 0;
-           pst->n_static_syms = 0;
-           
-           /* The second symbol must be @stab.
-              This symbol is emitted by mips-tfile to signal
-              that the current object file uses encapsulated stabs
-              instead of mips ecoff for local symbols.
-              (It is the second symbol because the first symbol is
-              the stFile used to signal the start of a file). */
-           if (fh->csym >= 2
-               && strcmp(((SYMR *)fh->isymBase)[1].iss, stabs_symbol) == 0) {
-               for (cur_sdx = 2; cur_sdx < fh->csym; cur_sdx++) {
-                   int type_code;
-                   char *namestring;
-                   sh = cur_sdx + (SYMR *) fh->isymBase;
-                   type_code = MIPS_UNMARK_STAB(sh->index);
-                   if (!MIPS_IS_STAB(sh)) {
-                       if (sh->st == stProc || sh->st == stStaticProc) {
-                           long procaddr = sh->value;
-                           sh = (sh->index + (AUXU *)fh->iauxBase)->isym
-                               + (SYMR *) fh->isymBase - 1;
-                           if (sh->st == stEnd) {
-                               long high = procaddr + sh->value;
-                               if (high > pst->texthigh)
-                                   pst->texthigh = high;
-                           }
+       pst = start_psymtab_common (objfile, 0, (char*)fh->rss,
+                                   fh->cpd ? fh->adr : 0,
+                                   objfile->global_psymbols.next,
+                                   objfile->static_psymbols.next);
+       pst->read_symtab_private = (char *)
+           obstack_alloc (&objfile->psymbol_obstack, sizeof (struct symloc));
+
+       save_pst = pst;
+       /* Make everything point to everything. */
+       FDR_IDX(pst) = f_idx;
+       fdr_to_pst[f_idx].pst = pst;
+       fh->ioptBase = (int)pst;
+       
+       CUR_HDR(pst) = cur_hdr;
+       
+       /* The way to turn this into a symtab is to call... */
+       pst->read_symtab = mipscoff_psymtab_to_symtab;
+       
+       pst->texthigh = pst->textlow;
+       
+#if 0      /* This is done in start_psymtab_common */
+       pst->globals_offset = global_psymbols.next - global_psymbols.list;
+       pst->statics_offset = static_psymbols.next - static_psymbols.list;
+       
+       pst->n_global_syms = 0;
+       pst->n_static_syms = 0;
+#endif
+       
+       /* The second symbol must be @stab.
+          This symbol is emitted by mips-tfile to signal
+          that the current object file uses encapsulated stabs
+          instead of mips ecoff for local symbols.
+          (It is the second symbol because the first symbol is
+          the stFile used to signal the start of a file). */
+       if (fh->csym >= 2
+           && strcmp((char *)(((SYMR *)fh->isymBase)[1].iss),
+                     stabs_symbol) == 0) {
+           for (cur_sdx = 2; cur_sdx < fh->csym; cur_sdx++) {
+               int type_code;
+               char *namestring;
+               sh = cur_sdx + (SYMR *) fh->isymBase;
+               type_code = MIPS_UNMARK_STAB(sh->index);
+               if (!MIPS_IS_STAB(sh)) {
+                   if (sh->st == stProc || sh->st == stStaticProc) {
+                       long procaddr = sh->value;
+                       sh = AUX_GET_ISYM (fh->fBigendian,
+                              sh->index + (union aux_ext *)(fh->iauxBase))
+                           + (SYMR *) fh->isymBase - 1;
+                       if (sh->st == stEnd) {
+                           long high = procaddr + sh->value;
+                           if (high > pst->texthigh)
+                               pst->texthigh = high;
                        }
-                       continue;
                    }
+                   continue;
+               }
 #define SET_NAMESTRING() namestring = (char*)sh->iss
 #define CUR_SYMBOL_TYPE type_code
 #define CUR_SYMBOL_VALUE sh->value
@@ -1821,103 +2009,202 @@ parse_partial_symbols(end_of_text_seg, objfile)
   if ((val) > save_pst->texthigh) save_pst->texthigh = (val);
 #include "partial-stab.h"
 #undef addr
-               }
            }
-           else {
-               for (cur_sdx = 0; cur_sdx < fh->csym; ) {
-                   register struct partial_symbol *p;
-                   char *name;
-                   int class;
-                   sh = cur_sdx + (SYMR *) fh->isymBase;
-                   
-                   if (MIPS_IS_STAB(sh)) {
-                       cur_sdx++;
-                       continue;
-                   }
+       }
+       else {
+           for (cur_sdx = 0; cur_sdx < fh->csym; ) {
+               char *name;
+               enum address_class class;
+               sh = cur_sdx + (SYMR *) fh->isymBase;
+               
+               if (MIPS_IS_STAB(sh)) {
+                   cur_sdx++;
+                   continue;
+               }
 
-                   if (sh->sc == scUndefined || sh->sc == scNil ||
-                       sh->index == 0xfffff) {
-                       /* FIXME, premature? */
-                       cur_sdx++;
+               if (sh->sc == scUndefined || sh->sc == scNil ||
+                   sh->index == 0xfffff) {
+                   /* FIXME, premature? */
+                   cur_sdx++;
+                   continue;
+               }
+               
+               name = (char *)(sh->iss);
+               
+               switch (sh->st) {
+                   long high;
+                   long procaddr;
+                   int new_sdx;
+
+                 case stProc:          /* Asm labels apparently */
+                 case stStaticProc:            /* Function */
+                   ADD_PSYMBOL_TO_LIST(name, strlen(name),
+                                       VAR_NAMESPACE, LOC_BLOCK,
+                                       objfile->static_psymbols, sh->value);
+                   /* Skip over procedure to next one. */
+                   if (sh->index >= hdr->iauxMax)
+                     {
+                       /* Should not happen, but does when cross-compiling
+                          with the MIPS compiler.  FIXME -- pull later.  */
+                       complain (&index_complaint, name);
+                       new_sdx = cur_sdx+1;    /* Don't skip at all */
+                     }
+                   else
+                     new_sdx = AUX_GET_ISYM (fh->fBigendian,
+                               sh->index + (union aux_ext *)fh->iauxBase);
+                   procaddr = sh->value;
+
+                   if (new_sdx <= cur_sdx)
+                     {
+                       /* This should not happen either... FIXME.  */
+                       complain (&aux_index_complaint, name);
+                       new_sdx = cur_sdx + 1;  /* Don't skip backward */
+                     }
+
+                   cur_sdx = new_sdx;
+                   sh = cur_sdx + (SYMR *) fh->isymBase - 1;
+                   if (sh->st != stEnd)
                        continue;
-                   }
-                   
-                   name = (char *)(sh->iss);
-                   
-                   switch (sh->st) {
-                       long high;
-                       long procaddr;
-                     case stProc:              /* Asm labels apparently */
-                     case stStaticProc:                /* Function */
+                   high = procaddr + sh->value;
+                   if (high > pst->texthigh)
+                       pst->texthigh = high;
+                   continue;
+
+                 case stStatic:                        /* Variable */
+                   class = LOC_STATIC;
+                   break;
+
+                 case stTypedef:                       /* Typedef */
+                   class = LOC_TYPEDEF;
+                   break;
+
+                 case stConstant:              /* Constant decl */
+                   class = LOC_CONST;
+                   break;
+
+                 case stUnion:
+                 case stStruct:
+                 case stEnum:
+                 case stBlock:                 /* { }, str, un, enum*/
+                   if (sh->sc == scInfo) {
                        ADD_PSYMBOL_TO_LIST(name, strlen(name),
-                                           VAR_NAMESPACE, LOC_BLOCK,
-                                           static_psymbols, sh->value);
-                       /* Skip over procedure to next one. */
-                       cur_sdx = (sh->index + (AUXU *)fh->iauxBase)->isym;
-                       procaddr = sh->value;
-                       
-                       sh = cur_sdx + (SYMR *) fh->isymBase - 1;
-                       if (sh->st != stEnd)
-                           continue;
-                       high = procaddr + sh->value;
-                       if (high > pst->texthigh)
-                           pst->texthigh = high;
-                       continue;
-                     case stStatic:                    /* Variable */
-                       class = LOC_STATIC;
-                       break;
-                     case stTypedef:                   /* Typedef */
-                       class = LOC_TYPEDEF;
-                       break;
-                     case stConstant:          /* Constant decl */
-                       class = LOC_CONST;
-                       break;
-                     case stBlock:                     /* { }, str, un, enum*/
-                       if (sh->sc == scInfo) {
-                           ADD_PSYMBOL_TO_LIST(name, strlen(name),
-                                               STRUCT_NAMESPACE, LOC_TYPEDEF,
-                                               static_psymbols, sh->value);
-                       }
-                       /* Skip over the block */
-                       cur_sdx = sh->index;
-                       continue;
-                     case stFile:                      /* File headers */
-                     case stLabel:                     /* Labels */
-                     case stEnd:                       /* Ends of files */
-                       goto skip;
-                     default:
-                       complain (&unknown_sym_complaint, SYMBOL_NAME(p));
-                       complain (&unknown_st_complaint, sh->st);
-                       cur_sdx++;
-                       continue;
+                                           STRUCT_NAMESPACE, LOC_TYPEDEF,
+                                           objfile->static_psymbols, sh->value);
                    }
-                   /* Use this gdb symbol */
-                   ADD_PSYMBOL_TO_LIST(name, strlen(name),
-                                       VAR_NAMESPACE, class,
-                                       static_psymbols, sh->value);
-                 skip:
-                   cur_sdx++;          /* Go to next file symbol */
+                   /* Skip over the block */
+                   cur_sdx = sh->index;
+                   continue;
+
+                 case stFile:                  /* File headers */
+                 case stLabel:                 /* Labels */
+                 case stEnd:                   /* Ends of files */
+                   goto skip;
+
+                 default:
+                   /* Both complaints are valid:  one gives symbol name,
+                      the other the offending symbol type.  */
+                   complain (&unknown_sym_complaint, (char *)sh->iss);
+                   complain (&unknown_st_complaint, (char *)sh->st);
+                   cur_sdx++;
+                   continue;
                }
+               /* Use this gdb symbol */
+               ADD_PSYMBOL_TO_LIST(name, strlen(name),
+                                   VAR_NAMESPACE, class,
+                                   objfile->static_psymbols, sh->value);
+             skip:
+               cur_sdx++;              /* Go to next file symbol */
            }
-           end_psymtab (save_pst, psymtab_include_list, includes_used,
-                        -1, save_pst->texthigh,
-                        dependency_list, dependencies_used,
-                        global_psymbols.next, static_psymbols.next);
-           if (entry_point < save_pst->texthigh
-               && entry_point >= save_pst->textlow) {
-               startup_file_start = save_pst->textlow;
-               startup_file_end = save_pst->texthigh;
+
+           /* Now do enter the external symbols. */
+           ext_ptr = &extern_tab[fdr_to_pst[f_idx].globals_offset];
+           cur_sdx = fdr_to_pst[f_idx].n_globals;
+           PST_PRIVATE(save_pst)->extern_count = cur_sdx;
+           PST_PRIVATE(save_pst)->extern_tab = ext_ptr;
+           for (; --cur_sdx >= 0; ext_ptr++) {
+               register struct partial_symbol *psym;
+               enum address_class class;
+
+               if ((*ext_ptr)->ifd != f_idx)
+                   abort();
+               sh = &(*ext_ptr)->asym;
+               switch (sh->st) {
+                 case stProc:
+                   class = LOC_BLOCK;
+                   break;
+                 case stLabel:
+                   class = LOC_LABEL;
+                   break;
+                 default:
+                   complain (&unknown_ext_complaint, (char *)sh->iss);
+                   /* Fall through, pretend it's global.  */
+                 case stGlobal:
+                   class = LOC_STATIC;
+                   break;
+               }
+               if (objfile->global_psymbols.next >=
+                   objfile->global_psymbols.list + objfile->global_psymbols.size)
+                   extend_psymbol_list (&objfile->global_psymbols, objfile);
+               psym = objfile->global_psymbols.next++;
+               SYMBOL_NAME (psym) = (char*)sh->iss;
+               SYMBOL_NAMESPACE (psym) = VAR_NAMESPACE;
+               SYMBOL_CLASS (psym) = class;
+               SYMBOL_VALUE_ADDRESS (psym) = (CORE_ADDR)sh->value;
            }
        }
 
-       /* Mark the last code address, and remember it for later */
-       hdr->cbDnOffset = end_of_text_seg;
+       end_psymtab (save_pst, psymtab_include_list, includes_used,
+                    -1, save_pst->texthigh,
+                    dependency_list, dependencies_used);
+       if (objfile -> ei.entry_point >= save_pst->textlow &&
+           objfile -> ei.entry_point <  save_pst->texthigh)
+         {
+           objfile -> ei.entry_file_lowpc = save_pst->textlow;
+           objfile -> ei.entry_file_highpc = save_pst->texthigh;
+         }
+    }
+
+    /* Mark the last code address, and remember it for later */
+    hdr->cbDnOffset = end_of_text_seg;
+
+    /* Now scan the FDRs for dependencies */
+    for (f_idx = 0; f_idx < hdr->ifdMax; f_idx++) {
+       int s_id0 = 0;
+       fh = f_idx + (FDR *)(cur_hdr->cbFdOffset);
+       pst = fdr_to_pst[f_idx].pst;
 
-       free(&fdr_to_pst[-1]);
-       fdr_to_pst = 0;
+       /* This should catch stabs-in-ecoff. */
+       if (fh->crfd <= 1)
+               continue;
+
+       if (fh->cpd == 0) {  /* If there are no functions defined here ... */
+               /* ...then presumably a .h file: drop reverse depends .h->.c */
+               for (; s_id0 < fh->crfd; s_id0++) {
+                       RFDT *rh = (RFDT *) (fh->rfdBase) + s_id0;
+                       if (*rh == f_idx) {
+                               s_id0++;        /* Skip self-dependency */
+                               break;
+                       }
+               }
+       }
+       pst->number_of_dependencies = fh->crfd - s_id0;
+       pst->dependencies = (struct partial_symtab **)
+               obstack_alloc (&objfile->psymbol_obstack,
+                              pst->number_of_dependencies *
+                              sizeof (struct partial_symtab *));
+       for (s_idx = s_id0; s_idx < fh->crfd; s_idx++) {
+           RFDT *rh = (RFDT *) (fh->rfdBase) + s_idx;
+           if (*rh < 0 || *rh >= hdr->ifdMax)
+               complain(&bad_file_number_complaint, (char *)*rh);
+           else
+               pst->dependencies[s_idx-s_id0] = fdr_to_pst[*rh].pst;
+       }
+    }
+    do_cleanups (old_chain);
 }
 
 
+#if 0
 /* Do the initial analisys of the F_IDX-th file descriptor.
    Allocates a partial symtab for it, and builds the list
    of dependent files by recursion. LEV says at which level
@@ -1975,7 +2262,7 @@ parse_fdr(f_idx, lev, objfile)
        }
        pst->number_of_dependencies = fh->crfd - s_id0;
        pst->dependencies = (struct partial_symtab **)
-               obstack_alloc (psymbol_obstack,
+               obstack_alloc (&objfile->psymbol_obstack,
                                 pst->number_of_dependencies *
                                   sizeof (struct partial_symtab *));
        for (s_idx = s_id0; s_idx < fh->crfd; s_idx++) {
@@ -1986,6 +2273,7 @@ parse_fdr(f_idx, lev, objfile)
 
        return pst;
 }
+#endif
 
 static char*
 mips_next_symbol_text ()
@@ -1998,60 +2286,31 @@ mips_next_symbol_text ()
    for turning the partial symtab PST into a symtab, recurring
    first on all dependent psymtabs.  The argument FILENAME is
    only passed so we can see in debug stack traces what file
-   is being read. */
+   is being read.
+
+   This function has a split personality, based on whether the
+   symbol table contains ordinary ecoff symbols, or stabs-in-ecoff.
+   The flow of control and even the memory allocation differs.  FIXME.  */
 
 static void
 psymtab_to_symtab_1(pst, filename)
      struct partial_symtab *pst;
      char *filename;
 {
-    int have_stabs;
-    int             i, f_max;
+    int i;
     struct symtab  *st;
     FDR *fh;
-    int maxlines;
     struct linetable *lines;
+    int bound;
 
     if (pst->readin)
        return;
     pst->readin = 1;
-    
-    /* How many symbols will we need */
-    /* FIXME, this does not count enum values. */
-    f_max = pst->n_global_syms + pst->n_static_syms;
-    if (FDR_IDX(pst) == -1) {
-       fh = 0;
-       maxlines = 0;
-    } else {
-       fh = (FDR *) (cur_hdr->cbFdOffset) + FDR_IDX(pst);
-       f_max += fh->csym + fh->cpd;
-       maxlines = 2 * fh->cline;
-    }
 
-    /* See comment in parse_partial_symbols about the @stabs sentinel. */
-    have_stabs =
-       fh && fh->csym >= 2
-           && strcmp(((SYMR *)fh->isymBase)[1].iss, stabs_symbol) == 0;
-
-    if (!have_stabs) {
-       if (fh)
-           st = new_symtab (pst->filename, 2 * f_max, maxlines,
-                            pst->objfile);
-       else
-           st = new_symtab ("unknown", f_max, 0, pst->objfile);
-       lines = LINETABLE(st);
-       pending_list = (struct mips_pending **) cur_hdr->cbOptOffset;
-       if (pending_list == 0) {
-           pending_list = (struct mips_pending **)
-               xzalloc(cur_hdr->ifdMax * sizeof(struct mips_pending *));
-           cur_hdr->cbOptOffset = (int)pending_list;
-       }
-    }
-    
     /* Read in all partial symbtabs on which this one is dependent.
        NOTE that we do have circular dependencies, sigh.  We solved
        that by setting pst->readin before this point.  */
-    
+
     for (i = 0; i < pst->number_of_dependencies; i++)
        if (!pst->dependencies[i]->readin) {
            /* Inform about additional files to be read in.  */
@@ -2067,22 +2326,120 @@ psymtab_to_symtab_1(pst, filename)
                    fflush (stdout);
                }
            /* We only pass the filename for debug purposes */
-           psymtab_to_symtab_1(pst->dependencies[i], 
+           psymtab_to_symtab_1(pst->dependencies[i],
                                pst->dependencies[i]->filename);
        }
-    
-    cur_fdr = fh;
+
     /* Now read the symbols for this symtab */
-    
-    if (!have_stabs) {
-       cur_fd = FDR_IDX(pst);
-       cur_stab = st;
+
+    current_objfile = pst->objfile;
+    cur_fd = FDR_IDX(pst);
+    fh = (cur_fd == -1) ? 0 : (FDR *) (cur_hdr->cbFdOffset) + FDR_IDX(pst);
+    cur_fdr = fh;
+
+    /* BOUND is the highest core address of this file's procedures */
+    bound = (cur_fd == cur_hdr->ifdMax - 1) ?
+                   cur_hdr->cbDnOffset :
+                   fh[1].adr;
+
+    /* See comment in parse_partial_symbols about the @stabs sentinel. */
+    if (fh && fh->csym >= 2
+           && strcmp((char *)(((SYMR *)fh->isymBase)[1].iss), stabs_symbol)
+               == 0) {
+
+       /*
+        * This symbol table contains stabs-in-ecoff entries.
+        */
+
+       PDR *pr;
        
+       /* Parse local symbols first */
+
+       if (fh->csym <= 2)      /* FIXME, this blows psymtab->symtab ptr */
+         {
+           current_objfile = NULL;
+           return;
+         }
+       for (cur_sdx = 2; cur_sdx < fh->csym; cur_sdx++) {
+           register SYMR       *sh = cur_sdx + (SYMR *) fh->isymBase;
+           char *name = (char*)sh->iss;
+           CORE_ADDR valu = sh->value;
+           if (MIPS_IS_STAB(sh)) {
+               int type_code = MIPS_UNMARK_STAB(sh->index);
+               process_one_symbol (type_code, 0, valu, name, /*FIXME*/ 0,
+                                   pst->objfile);
+               if (type_code == N_FUN) {
+                   /* Make up special symbol to contain
+                      procedure specific info */
+                   struct mips_extra_func_info *e =
+                     (struct mips_extra_func_info *)
+                       obstack_alloc(&current_objfile->symbol_obstack,
+                                     sizeof(struct mips_extra_func_info));
+                   struct symbol *s = new_symbol(".gdbinfo.");
+                   SYMBOL_NAMESPACE(s) = LABEL_NAMESPACE;
+                   SYMBOL_CLASS(s) = LOC_CONST;
+                   SYMBOL_TYPE(s) = builtin_type_void;
+                   SYMBOL_VALUE(s) = (int)e;
+                   add_symbol_to_list (s, &local_symbols);
+               }
+           }
+           else if (sh->st == stLabel && sh->index != indexNil) {
+               /* Handle encoded stab line number. */
+               record_line (current_subfile, sh->index, valu);
+           }
+           else complain (&stab_unknown_complaint, (char *)sh->iss);
+       }
+       st = end_symtab (pst->texthigh, 0, 0, pst->objfile);
+
+       /* Sort the symbol table now, we are done adding symbols to it.
+          We must do this before parse_procedure calls lookup_symbol.  */
+       sort_symtab_syms(st);
+
+       /* This may not be necessary for stabs symtabs.  FIXME.  */
+       sort_blocks (st);
+
+       /* Fill in procedure info next.  We need to look-ahead to
+          find out where each procedure's code ends.  */
+
+       for (i = 0; i <= fh->cpd-1; i++) {
+           pr = (PDR *) (IPDFIRST(cur_hdr, fh)) + i;
+           parse_procedure (pr, i < fh->cpd-1 ? pr[1].adr : bound, 1);
+       }
+    } else {
+
+       /*
+        * This symbol table contains ordinary ecoff entries.
+        */
+
+       int f_max;
+       int maxlines;
+       EXTR **ext_ptr;
+
+       /* How many symbols will we need */
+       /* FIXME, this does not count enum values. */
+       f_max = pst->n_global_syms + pst->n_static_syms;
+       if (fh == 0) {
+           maxlines = 0;
+           st = new_symtab ("unknown", f_max, 0, pst->objfile);
+       } else {
+           f_max += fh->csym + fh->cpd;
+           maxlines = 2 * fh->cline;
+           st = new_symtab (pst->filename, 2 * f_max, maxlines, pst->objfile);
+       }
+
+       lines = LINETABLE(st);
+       pending_list = (struct mips_pending **) cur_hdr->cbOptOffset;
+       if (pending_list == 0) {
+           pending_list = (struct mips_pending **)
+               xzalloc(cur_hdr->ifdMax * sizeof(struct mips_pending *));
+           cur_hdr->cbOptOffset = (int)pending_list;
+       }
+
        /* Get a new lexical context */
        
        push_parse_stack();
-       top_stack->cur_st = cur_stab;
-       top_stack->cur_block = BLOCKVECTOR_BLOCK(BLOCKVECTOR(cur_stab),
+       top_stack->cur_st = st;
+       top_stack->cur_block = BLOCKVECTOR_BLOCK(BLOCKVECTOR(st),
                                                 STATIC_BLOCK);
        BLOCK_START(top_stack->cur_block) = fh ? fh->adr : 0;
        BLOCK_END(top_stack->cur_block) = 0;
@@ -2091,80 +2448,50 @@ psymtab_to_symtab_1(pst, filename)
        top_stack->cur_type = 0;
        top_stack->procadr = 0;
        top_stack->numargs = 0;
-    }
-    
-    /* Parse locals and procedures */
-    if (fh) {
-       SYMR *sh;
-       PDR *pr;
-       int f_idx = cur_fd;
-       char *fh_name = (char*)fh->rss;
-       
-       /* Parse local symbols first */
-       
-       
-       if (have_stabs) {
-           if (fh->csym <= 2)
-               return;
-           for (cur_sdx = 2; cur_sdx < fh->csym; cur_sdx++) {
-               register SYMR   *sh = cur_sdx + (SYMR *) fh->isymBase;
-               char *name = (char*)sh->iss;
-               CORE_ADDR valu = sh->value;
-               if (MIPS_IS_STAB(sh)) {
-                   int type_code = MIPS_UNMARK_STAB(sh->index);
-                   process_one_symbol (type_code, 0, valu, name, /*FIXME*/ 0);
-               }
-               else if (sh->st == stLabel && sh->index != indexNil) {
-                   /* Handle encoded stab line number. */
-                   record_line (current_subfile, sh->index, valu);
-               }
-           }
-           st = end_symtab (pst->texthigh, 0, 0, pst->objfile);
-       }
-       else {
-           /* BOUND is the highest core address of this file's procedures */
-           int bound =  cur_fd == cur_hdr->ifdMax - 1 ? cur_hdr->cbDnOffset
-               : fh[1].adr;
+
+       if (fh) {
+           SYMR *sh;
+           PDR *pr;
+
+           /* Parse local symbols first */
+
            for (cur_sdx = 0; cur_sdx < fh->csym; ) {
                sh = (SYMR *) (fh->isymBase) + cur_sdx;
-               cur_sdx += parse_symbol(sh, fh->iauxBase);
+               cur_sdx += parse_symbol(sh, (union aux_ent *)fh->iauxBase,
+                                       fh->fBigendian);
            }
 
-           /* Procedures next, note we need to look-ahead to
-              find out where the procedure's code ends */
+           /* Linenumbers.  At the end, check if we can save memory */
 
-           for (i = 0; i < fh->cpd-1; i++) {
-               pr = (PDR *) (IPDFIRST(cur_hdr, fh)) + i;
-               parse_procedure(pr, pr[1].adr); /* next proc up */
-           }
-           if (fh->cpd) {
-               pr = (PDR *) (IPDFIRST(cur_hdr, fh)) + i;
-               parse_procedure(pr, bound);     /* next file up */
-           }
-           /* Linenumbers. At the end, check if we can save memory */
            parse_lines(fh, lines);
            if (lines->nitems < fh->cline)
                lines = shrink_linetable(lines);
+
+           /* Fill in procedure info next.  We need to look-ahead to
+              find out where each procedure's code ends.  */
+
+           for (i = 0; i <= fh->cpd-1; i++) {
+               pr = (PDR *) (IPDFIRST(cur_hdr, fh)) + i;
+               parse_procedure(pr, i < fh->cpd-1 ? pr[1].adr : bound, 0);
+           }
        }
 
-    }
-    if (!have_stabs) {
        LINETABLE(st) = lines;
-    
+
        /* .. and our share of externals.
-          XXX use the global list to speed up things here. how ? 
+          XXX use the global list to speed up things here. how?
           FIXME, Maybe quit once we have found the right number of ext's? */
-       /* parse_external clobbers top_stack->cur_block and ->cur_st here. */
+       top_stack->cur_st = st;
+       top_stack->cur_block = BLOCKVECTOR_BLOCK(BLOCKVECTOR(top_stack->cur_st),
+                                                GLOBAL_BLOCK);
        top_stack->blocktype = stFile;
        top_stack->maxsyms =
            cur_hdr->isymMax + cur_hdr->ipdMax + cur_hdr->iextMax;
 
-       for (i = 0; i < cur_hdr->iextMax; i++) {
-           register EXTR *esh = (EXTR *) (cur_hdr->cbExtOffset) + i;
-           if (esh->ifd == cur_fd)
-               parse_external(esh, 1);
-       }
-    
+       ext_ptr = PST_PRIVATE(pst)->extern_tab;
+       for (i = PST_PRIVATE(pst)->extern_count; --i >= 0; ext_ptr++)
+           parse_external(*ext_ptr, 1, fh->fBigendian);
+
        /* If there are undefined, tell the user */
        if (n_undef_symbols) {
            printf_filtered("File %s contains %d unresolved references:",
@@ -2175,44 +2502,54 @@ psymtab_to_symtab_1(pst, filename)
 
        }
        pop_parse_stack();
+
+       /* Sort the symbol table now, we are done adding symbols to it.*/
+       sort_symtab_syms(st);
+
+       sort_blocks (st);
     }
-    
-    /* Sort the symbol table now, we are done adding symbols to it.*/
-    sort_symtab_syms(st);
 
-    sort_blocks (st);
-    
     /* Now link the psymtab and the symtab.  */
     pst->symtab = st;
+
+    current_objfile = NULL;
 }
 \f
 /* Ancillary parsing procedures. */
 
 /* Lookup the type at relative index RN.  Return it in TPP
    if found and in any event come up with its name PNAME.
-   Return value says how many aux symbols we ate */
+   BIGEND says whether aux symbols are big-endian or not (from fh->fBigendian).
+   Return value says how many aux symbols we ate. */
 
-static
-cross_ref(rn, tpp, type_code, pname)
-     RNDXR *rn;
+static int
+cross_ref(ax, tpp, type_code, pname, bigend)
+     union aux_ext *ax;
      struct type **tpp;
-     int type_code; /* Use to alloc new type if none is found. */
+     enum type_code type_code; /* Use to alloc new type if none is found. */
      char **pname;
+     int bigend;
 {
+       RNDXR           rn[1];
        unsigned        rf;
+       int             result = 1;
+
+       ecoff_swap_rndx_in (bigend, ax, rn);
 
        /* Escape index means 'the next one' */
-       if (rn->rfd == 0xfff)
-               rf = *(unsigned *) (rn + 1);
-       else
+       if (rn->rfd == 0xfff) {
+               result++;
+               rf = AUX_GET_ISYM (bigend, ax + 1);
+       } else {
                rf = rn->rfd;
+       }
 
        if (rf == -1) {
                /* Ooops */
                *pname = "<undefined>";
        } else {
                /*
-                * Find the relative file descriptor and the symbol in it 
+                * Find the relative file descriptor and the symbol in it
                 */
                FDR            *fh = get_rfd(cur_fd, rf);
                SYMR           *sh;
@@ -2224,7 +2561,7 @@ cross_ref(rn, tpp, type_code, pname)
                 * it in a list of pending symbols, to be processed later when
                 * the file f will be.  In any event, we collect the name for
                 * the type here. Which is why we made a first pass at
-                * strings. 
+                * strings.
                 */
                sh = (SYMR *) (fh->isymBase) + rn->index;
 
@@ -2242,14 +2579,15 @@ cross_ref(rn, tpp, type_code, pname)
                    if (p)
                        *tpp = p->t;
                    else {
-                       *tpp = make_type(type_code, 0, 0, 0);
+                       *tpp = init_type(type_code, 0, 0, (char *) NULL,
+                                        (struct objfile *) NULL);
                        add_pending(fh, sh, *tpp);
                    }
                }
        }
 
        /* We used one auxent normally, two if we got a "next one" rf. */
-       return (rn->rfd == 0xfff? 2: 1);
+       return result;
 }
 
 
@@ -2278,7 +2616,8 @@ mylookup_symbol (name, block, namespace, class)
                        return sym;
                bot++;
        }
-       if (block = BLOCK_SUPERBLOCK (block))
+       block = BLOCK_SUPERBLOCK (block);
+       if (block)
                return mylookup_symbol (name, block, namespace, class);
        return 0;
 }
@@ -2328,8 +2667,10 @@ add_block(b,s)
 {
        struct blockvector *bv = BLOCKVECTOR(s);
 
-       bv = (struct blockvector *)xrealloc(bv, sizeof(struct blockvector) +
-                                           BLOCKVECTOR_NBLOCKS(bv) * sizeof(bv->block));
+       bv = (struct blockvector *)xrealloc((PTR) bv,
+                                           sizeof(struct blockvector) +
+                                                BLOCKVECTOR_NBLOCKS(bv)
+                                                * sizeof(bv->block));
        if (bv != BLOCKVECTOR(s))
                BLOCKVECTOR(s) = bv;
 
@@ -2357,52 +2698,18 @@ add_line(lt, lineno, adr, last)
        lt->item[lt->nitems++].pc = adr << 2;
        return lineno;
 }
-
-
 \f
-/* Comparison functions, used when sorting things */
-
-/*  Symtabs must be ordered viz the code segments they cover */
-
-static int
-compare_symtabs( s1, s2)
-       struct symtab **s1, **s2;
-{
-       /* "most specific" first */
-
-       register struct block *b1, *b2;
-       b1 = BLOCKVECTOR_BLOCK(BLOCKVECTOR(*s1),GLOBAL_BLOCK);
-       b2 = BLOCKVECTOR_BLOCK(BLOCKVECTOR(*s2),GLOBAL_BLOCK);
-       if (BLOCK_END(b1) == BLOCK_END(b2))
-               return BLOCK_START(b1) - BLOCK_START(b2);
-       return BLOCK_END(b1) - BLOCK_END(b2);
-}
-
-
-/*  Partial Symtabs, same */
-
-static int
-compare_psymtabs( s1, s2)
-       struct partial_symtab **s1, **s2;
-{
-       /* Perf twist: put the ones with no code at the end */
-
-       register int a = (*s1)->textlow;
-       register int b = (*s2)->textlow;
-       if (a == 0)
-               return b;
-       if (b == 0)
-               return -a;
-       return a - b;
-}
-
+/* Sorting and reordering procedures */
 
 /* Blocks with a smaller low bound should come first */
 
-static int compare_blocks(b1,b2)
-       struct block **b1, **b2;
+static int
+compare_blocks(arg1, arg2)
+     const void *arg1, *arg2;
 {
        register int addr_diff;
+       struct block **b1 = (struct block **) arg1;
+       struct block **b2 = (struct block **) arg2;
 
        addr_diff = (BLOCK_START((*b1))) - (BLOCK_START((*b2)));
        if (addr_diff == 0)
@@ -2410,9 +2717,6 @@ static int compare_blocks(b1,b2)
        return addr_diff;
 }
 
-\f
-/* Sorting and reordering procedures */
-
 /* Sort the blocks of a symtab S.
    Reorder the blocks in the blockvector by code-address,
    as required by some MI search routines */
@@ -2456,7 +2760,7 @@ sort_blocks(s)
        BLOCK_START(BLOCKVECTOR_BLOCK(bv,GLOBAL_BLOCK)) =
                BLOCK_START(BLOCKVECTOR_BLOCK(bv,FIRST_LOCAL_BLOCK));
 
-       BLOCK_START(BLOCKVECTOR_BLOCK(bv,STATIC_BLOCK)) = 
+       BLOCK_START(BLOCKVECTOR_BLOCK(bv,STATIC_BLOCK)) =
                BLOCK_START(BLOCKVECTOR_BLOCK(bv,GLOBAL_BLOCK));
        BLOCK_END  (BLOCKVECTOR_BLOCK(bv,STATIC_BLOCK)) =
                BLOCK_END  (BLOCKVECTOR_BLOCK(bv,GLOBAL_BLOCK));
@@ -2468,29 +2772,27 @@ sort_blocks(s)
 /* Allocate a new symtab for NAME.  Needs an estimate of how many symbols
    MAXSYMS and linenumbers MAXLINES we'll put in it */
 
-static
-struct symtab *
+static struct symtab *
 new_symtab(name, maxsyms, maxlines, objfile)
        char *name;
+       int maxsyms;
+       int maxlines;
+       struct objfile *objfile;
 {
-       struct symtab *s = allocate_symtab (name, objfile);
-
-       LINETABLE(s) = new_linetable(maxlines);
+  struct symtab *s = allocate_symtab (name, objfile);
 
-       /* All symtabs must have at least two blocks */
-       BLOCKVECTOR(s) = new_bvect(2);
-       BLOCKVECTOR_BLOCK(BLOCKVECTOR(s), GLOBAL_BLOCK) = new_block(maxsyms);
-       BLOCKVECTOR_BLOCK(BLOCKVECTOR(s), STATIC_BLOCK) = new_block(maxsyms);
-       BLOCK_SUPERBLOCK( BLOCKVECTOR_BLOCK(BLOCKVECTOR(s),STATIC_BLOCK)) =
-               BLOCKVECTOR_BLOCK(BLOCKVECTOR(s), GLOBAL_BLOCK);
+  LINETABLE(s) = new_linetable(maxlines);
 
-       s->free_code = free_linetable;
+  /* All symtabs must have at least two blocks */
+  BLOCKVECTOR(s) = new_bvect(2);
+  BLOCKVECTOR_BLOCK(BLOCKVECTOR(s), GLOBAL_BLOCK) = new_block(maxsyms);
+  BLOCKVECTOR_BLOCK(BLOCKVECTOR(s), STATIC_BLOCK) = new_block(maxsyms);
+  BLOCK_SUPERBLOCK( BLOCKVECTOR_BLOCK(BLOCKVECTOR(s),STATIC_BLOCK)) =
+    BLOCKVECTOR_BLOCK(BLOCKVECTOR(s), GLOBAL_BLOCK);
 
-       /* Link the new symtab into the list of such.  */
-       s->next = symtab_list;
-       symtab_list = s;
+  s->free_code = free_linetable;
 
-       return s;
+  return (s);
 }
 
 /* Allocate a new partial_symtab NAME */
@@ -2500,69 +2802,61 @@ new_psymtab(name, objfile)
        char *name;
        struct objfile *objfile;
 {
-       struct partial_symtab *pst;
+  struct partial_symtab *psymtab;
 
-       pst = (struct partial_symtab *)
-             obstack_alloc (psymbol_obstack, sizeof (*pst));
-       memset (pst, 0, sizeof (*pst));
-
-       if (name == (char*)-1)          /* FIXME -- why not null here? */
-               pst->filename = "<no name>";
-       else
-               pst->filename = name;
+  /* FIXME -- why (char *) -1 rather than NULL? */
+  psymtab = allocate_psymtab (name == (char *) -1 ? "<no name>" : name,
+                             objfile);
 
-       /* Chain it to its object file */
-       pst->objfile = objfile;
-       pst->objfile_chain = objfile->psymtabs;
-       objfile->psymtabs = pst;
-       
-       pst->next = partial_symtab_list;
-       partial_symtab_list = pst;
-
-       /* Keep a backpointer to the file's symbols */
-       pst->read_symtab_private = (char *) obstack_alloc (psymbol_obstack,
-                                                 sizeof (struct symloc));
-       CUR_HDR(pst) = cur_hdr;
+  /* Keep a backpointer to the file's symbols */
 
-       /* The way to turn this into a symtab is to call... */
-       pst->read_symtab = mipscoff_psymtab_to_symtab;
+  psymtab -> read_symtab_private = (char *)
+    obstack_alloc (&objfile->psymbol_obstack, sizeof (struct symloc));
+  CUR_HDR(psymtab) = cur_hdr;
 
-       return pst;
+  /* The way to turn this into a symtab is to call... */
+  psymtab->read_symtab = mipscoff_psymtab_to_symtab;
+  return (psymtab);
 }
 
 
-/* Allocate a linetable array of the given SIZE */
+/* Allocate a linetable array of the given SIZE.  Since the struct
+   already includes one item, we subtract one when calculating the
+   proper size to allocate.  */
 
 static struct linetable *
 new_linetable(size)
+       int size;
 {
        struct linetable *l;
 
-       size = size * sizeof(l->item) + sizeof(struct linetable);
+       size = (size-1) * sizeof(l->item) + sizeof(struct linetable);
        l = (struct linetable *)xmalloc(size);
        l->nitems = 0;
        return l;
 }
 
 /* Oops, too big. Shrink it.  This was important with the 2.4 linetables,
-   I am not so sure about the 3.4 ones */
+   I am not so sure about the 3.4 ones.
+
+   Since the struct linetable already includes one item, we subtract one when
+   calculating the proper size to allocate.  */
 
 static struct linetable *
 shrink_linetable(lt)
        struct linetable * lt;
 {
-       struct linetable *l = new_linetable(lt->nitems);
 
-       memcpy(l, lt, lt->nitems * sizeof(l->item) + sizeof(struct linetable));
-       free (lt);
-       return l;
+       return (struct linetable *) xrealloc ((PTR)lt,
+                                       sizeof(struct linetable)
+                                       + (lt->nitems - 1) * sizeof(lt->item));
 }
 
 /* Allocate and zero a new blockvector of NBLOCKS blocks. */
 
-static
-struct blockvector *
+static struct blockvector *
 new_bvect(nblocks)
+       int nblocks;
 {
        struct blockvector *bv;
        int size;
@@ -2577,14 +2871,13 @@ new_bvect(nblocks)
 
 /* Allocate and zero a new block of MAXSYMS symbols */
 
-static
-struct block *
+static struct block *
 new_block(maxsyms)
+       int maxsyms;
 {
        int size = sizeof(struct block) + (maxsyms-1) * sizeof(struct symbol *);
-       struct block *b = (struct block *)xzalloc(size);
 
-       return b;
+       return (struct block *)xzalloc (size);
 }
 
 /* Ooops, too big. Shrink block B in symtab S to its minimal size.
@@ -2601,8 +2894,8 @@ shrink_block(b, s)
 
        /* Just reallocate it and fix references to the old one */
 
-       new = (struct block *) xrealloc ((char *)b, sizeof(struct block) +
-               (BLOCK_NSYMS(b)-1) * sizeof(struct symbol *));
+       new = (struct block *) xrealloc ((PTR)b, sizeof(struct block) +
+               (BLOCK_NSYMS(b)-1) * sizeof(struct symbol *));
 
        /* Should chase pointers to old one.  Fortunately, that`s just
           the block`s function and inferior blocks */
@@ -2618,61 +2911,33 @@ shrink_block(b, s)
 
 /* Create a new symbol with printname NAME */
 
-static
-struct symbol *
+static struct symbol *
 new_symbol(name)
        char *name;
 {
-       struct symbol *s = (struct symbol *) 
-               obstack_alloc (symbol_obstack, sizeof (struct symbol));
+       struct symbol *s = (struct symbol *)
+               obstack_alloc (&current_objfile->symbol_obstack, sizeof (struct symbol));
 
-       memset (s, 0, sizeof (*s));
+       memset ((PTR)s, 0, sizeof (*s));
        SYMBOL_NAME(s) = name;
        return s;
 }
 
 /* Create a new type with printname NAME */
 
-static
-struct type *
+static struct type *
 new_type(name)
        char *name;
 {
-       struct type *t = (struct type *)
-               obstack_alloc (symbol_obstack, sizeof (struct type));
+       struct type *t;
 
-       memset (t, 0, sizeof (*t));
-       TYPE_VPTR_FIELDNO (t) = -1;
+       t = alloc_type (current_objfile);
        TYPE_NAME(t) = name;
-       TYPE_CPLUS_SPECIFIC(t) = &cplus_struct_default;
+       TYPE_CPLUS_SPECIFIC(t) = (struct cplus_struct_type *)
+                                &cplus_struct_default;
        return t;
 }
 
-/* Create and initialize a new type with printname NAME.
-   CODE and LENGTH are the initial info we put in,
-   UNS says whether the type is unsigned or not.  */
-
-static
-struct type *
-make_type(code, length, uns, name)
-     enum type_code code;
-     int length, uns;
-     char *name;
-{
-    register struct type *type;
-    
-    /* FIXME, I don't think this ever gets freed.  */
-    type = (struct type *) xzalloc(sizeof(struct type));
-    TYPE_CODE(type) = code;
-    TYPE_LENGTH(type) = length;
-    TYPE_FLAGS(type) = uns ? TYPE_FLAG_UNSIGNED : 0;
-    TYPE_NAME(type) = name;
-    TYPE_VPTR_FIELDNO (type) = -1;
-    
-    if (code != TYPE_CODE_METHOD && code != TYPE_CODE_FUNC)
-       TYPE_CPLUS_SPECIFIC(type) = &cplus_struct_default;
-    return type;
-}
 \f
 /* Things used for calling functions in the inferior.
    These functions are exported to our companion
@@ -2684,7 +2949,7 @@ make_type(code, length, uns, name)
    from MIPS does not do so, we make up that information ourselves.
    If they fix the library (unlikely) this code will neutralize itself. */
 
-static
+static void
 fixup_sigtramp()
 {
        struct symbol  *s;
@@ -2698,23 +2963,29 @@ fixup_sigtramp()
 
        /* Most programs do not play with signals */
        if (s == 0)
-               return;
-
-       b0 = SYMBOL_BLOCK_VALUE(s);
+         s = lookup_symbol("_sigtramp", 0, VAR_NAMESPACE, 0, NULL);
+       else
+         {
+           b0 = SYMBOL_BLOCK_VALUE(s);
 
-       /* A label of sigvec, to be more precise */
-       s = lookup_symbol("sigtramp", b0, VAR_NAMESPACE, 0, NULL);
+           /* A label of sigvec, to be more precise */
+           s = lookup_symbol("sigtramp", b0, VAR_NAMESPACE, 0, NULL);
+         }
 
        /* But maybe this program uses its own version of sigvec */
        if (s == 0)
                return;
 
-       sigtramp_address = SYMBOL_VALUE(s);
-       sigtramp_end = sigtramp_address + 0x88; /* black magic */
-
        /* Did we or MIPSco fix the library ? */
        if (SYMBOL_CLASS(s) == LOC_BLOCK)
-               return;
+         {
+           sigtramp_address = BLOCK_START(SYMBOL_BLOCK_VALUE(s));
+           sigtramp_end = BLOCK_END(SYMBOL_BLOCK_VALUE(s));
+           return;
+         }
+
+       sigtramp_address = SYMBOL_VALUE(s);
+       sigtramp_end = sigtramp_address + 0x88; /* black magic */
 
        /* But what symtab does it live in ? */
        st = find_pc_symtab(SYMBOL_VALUE(s));
@@ -2726,7 +2997,8 @@ fixup_sigtramp()
         */
        SYMBOL_NAMESPACE(s) = VAR_NAMESPACE;
        SYMBOL_CLASS(s) = LOC_BLOCK;
-       SYMBOL_TYPE(s) = make_type(TYPE_CODE_FUNC, 4, 0, 0);
+       SYMBOL_TYPE(s) = init_type(TYPE_CODE_FUNC, 4, 0, (char *) NULL,
+                                  (struct objfile *) NULL);
        TYPE_TARGET_TYPE(SYMBOL_TYPE(s)) = builtin_type_void;
 
        /* Need a block to allocate .gdbinfo. in */
@@ -2747,20 +3019,22 @@ fixup_sigtramp()
 
                e->numargs = 0; /* the kernel thinks otherwise */
                /* align_longword(sigcontext + SIGFRAME) */
-               e->framesize = 0x150;
-               e->framereg = SP_REGNUM;
-               e->pcreg = 31;
-               e->regmask = -2;
-               e->regoffset = -(41 * sizeof(int));
-               e->fregmask = -1;
-               e->fregoffset = -(37 * sizeof(int));
-               e->isym = (long)s;
-
+               e->pdr.frameoffset = 0x150;
+               e->pdr.framereg = SP_REGNUM;
+               e->pdr.pcreg = 31;
+               e->pdr.regmask = -2;
+               e->pdr.regoffset = -(41 * sizeof(int));
+               e->pdr.fregmask = -1;
+               e->pdr.fregoffset = -(37 * sizeof(int));
+               e->pdr.isym = (long)s;
+
+               current_objfile = st->objfile; /* Keep new_symbol happy */
                s = new_symbol(".gdbinfo.");
                SYMBOL_VALUE(s) = (int) e;
                SYMBOL_NAMESPACE(s) = LABEL_NAMESPACE;
                SYMBOL_CLASS(s) = LOC_CONST;
                SYMBOL_TYPE(s) = builtin_type_void;
+               current_objfile = NULL;
        }
 
        BLOCK_SYM(b,BLOCK_NSYMS(b)++) = s;
@@ -2768,23 +3042,48 @@ fixup_sigtramp()
 \f
 /* Initialization */
 
-static struct sym_fns ecoff_sym_fns = {"ecoff", 5,
-               mipscoff_new_init, mipscoff_symfile_init,
-               mipscoff_symfile_read};
+static struct sym_fns ecoff_sym_fns =
+{
+  "ecoff",             /* sym_name: name or name prefix of BFD target type */
+  5,                   /* sym_namelen: number of significant sym_name chars */
+  mipscoff_new_init,   /* sym_new_init: init anything gbl to entire symtab */
+  mipscoff_symfile_init,/* sym_init: read initial info, setup for sym_read() */
+  mipscoff_symfile_read,/* sym_read: read a symbol file into symtab */
+  mipscoff_symfile_finish,/* sym_finish: finished with file, cleanup */
+  NULL                 /* next: pointer to next struct sym_fns */
+};
 
+
+void
 _initialize_mipsread ()
 {
        add_symtab_fns (&ecoff_sym_fns);
 
        /* Missing basic types */
-       builtin_type_string = make_type(TYPE_CODE_PASCAL_ARRAY,
-                                       1, 0, "string");
-       builtin_type_complex = make_type(TYPE_CODE_FLT,
-                                        2 * sizeof(float), 0, "complex");
-       builtin_type_double_complex = make_type(TYPE_CODE_FLT,
-                                   2 * sizeof(double), 0, "double_complex");
-       builtin_type_fixed_dec = make_type(TYPE_CODE_INT, sizeof(int),
-                                          0, "fixed_decimal");
-       builtin_type_float_dec = make_type(TYPE_CODE_FLT, sizeof(double),
-                                          0, "floating_decimal");
+
+       builtin_type_string =
+           init_type(TYPE_CODE_PASCAL_ARRAY,
+                     TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+                     0, "string",
+                     (struct objfile *) NULL);
+       builtin_type_complex =
+           init_type(TYPE_CODE_FLT,
+                     TARGET_COMPLEX_BIT / TARGET_CHAR_BIT,
+                     0, "complex",
+                     (struct objfile *) NULL);
+       builtin_type_double_complex =
+           init_type(TYPE_CODE_FLT,
+                     TARGET_DOUBLE_COMPLEX_BIT / TARGET_CHAR_BIT,
+                     0, "double complex",
+                     (struct objfile *) NULL);
+       builtin_type_fixed_dec =
+           init_type(TYPE_CODE_INT,
+                     TARGET_INT_BIT / TARGET_CHAR_BIT,
+                     0, "fixed decimal",
+                     (struct objfile *) NULL);
+       builtin_type_float_dec =
+           init_type(TYPE_CODE_FLT,
+                     TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+                     0, "floating decimal",
+                     (struct objfile *) NULL);
 }
This page took 0.061541 seconds and 4 git commands to generate.