Improve G++ debugging support.
[binutils-gdb.git] / gdb / mipsread.c
index 2c7112f78cbf62e325087ca0fe1fdcdfa23e0413..1002dee5873975db7b992fc7044261d11591a191 100644 (file)
@@ -1,63 +1,76 @@
 /* Read a symbol table in MIPS' format (Third-Eye).
-   Copyright (C) 1986, 1987, 1989-1991 Free Software Foundation, Inc.
-   Contributed by Alessandro Forin (af@cs.cmu.edu) at CMU
+   Copyright 1986, 1987, 1989, 1990, 1991 Free Software Foundation, Inc.
+   Contributed by Alessandro Forin (af@cs.cmu.edu) at CMU.
 
 This file is part of GDB.
 
-GDB is free software; you can redistribute it and/or modify
+This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
-any later version.
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
 
-GDB is distributed in the hope that it will be useful,
+This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GDB; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+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 
+   discards existing cached information when all symbols are being
+   discarded; and mipscoff_symfile_read, which reads a symbol table
+   from a file.
+
+   mipscoff_symfile_read only does the minimum work necessary for letting the
+   user "name" things symbolically; it does not read the entire symtab.
+   Instead, it reads the external and static symbols and puts them in partial
+   symbol tables.  When more extensive information is requested of a
+   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>
-#include "param.h"
-#include "obstack.h"
-#include <sys/param.h>
-#include <sys/file.h>
-#include <sys/stat.h>
 #include "defs.h"
 #include "symtab.h"
 #include "gdbcore.h"
 #include "symfile.h"
+#include "obstack.h"
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/stat.h>
 #ifdef CMUCS
 #include <mips/syms.h>
-#endif CMUCS
+#else /* not CMUCS */
+#include <symconst.h>
+#include <sym.h>
+#endif /* not CMUCS */
 
-/* Since these things are defined differently on various systems I'll
-   (re)define here what I really need in this module.  I only assume the
-   three standard COFF structure definitions: filehdr, aouthdr, scnhdr */
-#define MIPS           /* Kludge to get MIPS version of coff */
-#include "intel-coff.h"
+#include "coff-mips.h"
 
 struct coff_exec {
-       struct filehdr f;
-       struct aouthdr a;
+       struct external_filehdr f;
+       struct external_aouthdr a;
+};
+
+/* Each partial symbol table entry contains a pointer to private data for the
+   read_symtab() function to use when expanding a partial symbol table entry
+   to a full symbol table entry.
+
+   For mipsread this structure contains the index of the FDR that this psymtab
+   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)
+
+struct symloc {
+  int fdr_idx;
+  HDRR *cur_hdr;
 };
-#undef a_magic
-#undef a_text
-#undef a_data
-#undef a_bss
-#undef a_syms
-#undef a_entry
-#define a_magic        a.magic         /* magic number */
-#define a_text a.tsize         /* size of text segment */
-#define a_data a.dsize         /* size of initialized data */
-#define a_bss  a.bsize         /* size of uninitialized data */
-#define a_syms f.f_nsyms       /* size of symbol table */
-#define a_entry        a.entry         /* entry point */
-
-#undef N_BADMAG
-#define        N_BADMAG(x) \
-    (((x).a_magic)!=OMAGIC && ((x).a_magic)!=NMAGIC && ((x).a_magic)!=ZMAGIC)
 
 /* Things we import explicitly from other modules */
 
@@ -65,16 +78,35 @@ extern int       info_verbose;
 extern struct block *block_for_pc();
 extern void         sort_symtab_syms();
 
-/* Forward declarations */
+/* Various complaints about symbol reading that don't abort the process */
+   
+struct complaint unknown_ext_complaint = 
+       {"unknown external symbol %s", 0, 0};
 
-static void psymtab_to_symtab_1();
+struct complaint unknown_sym_complaint = 
+       {"unknown local symbol %s", 0, 0};
 
-/* Macros and extra defs */
+struct complaint unknown_st_complaint = 
+       {"with type %d", 0, 0};
 
-struct complaint unknown_ext_complaint = 
-       {"unknown external symbol %s", 0, 0};
+struct complaint block_overflow_complaint = 
+       {"block containing %s overfilled", 0, 0};
+
+struct complaint basic_type_complaint = 
+       {"cannot map MIPS basic type 0x%x", 0, 0};
+
+struct complaint unknown_type_qual_complaint = 
+       {"unknown type qualifier 0x%x", 0, 0};
+
+struct complaint array_bitsize_complaint = 
+       {"size of array target type not known, assuming %d bits", 0, 0};
 
-/* Already parsed symbols are marked specially */
+struct complaint array_parse_complaint = 
+       {"array type with strange relative symbol", 0, 0};
+
+/* Macros and extra defs */
+
+/* Already-parsed symbols are marked specially */
 
 #define stParsed stType
 
@@ -85,44 +117,89 @@ struct complaint unknown_ext_complaint =
        (((a) == GLEVEL_3) ? ((b) < GLEVEL_3) :                 \
         ((b) == GLEVEL_3) ? -1 : (int)((b) - (a)))
 
-/* When looking at .o files avoid tripping over bad addresses */
+/* When looking at .o files, avoid tripping over bad addresses */
 
 #define SAFE_TEXT_ADDR 0x400000
 #define SAFE_DATA_ADDR 0x10000000
 
 #define UNSAFE_DATA_ADDR(p)    ((unsigned)p < SAFE_DATA_ADDR || (unsigned)p > 2*SAFE_DATA_ADDR)
-
 \f
-/* Things we export to other modules */
+/* Things that really are local to this module */
 
+/* GDB symtable for the current compilation unit */
 
-/* Lists of partial symbols */
+static struct symtab *cur_stab;
 
-struct psymbol_allocation_list global_psymbols, static_psymbols;
+/* MIPS symtab header for the current file */
 
-/* Address bounds for the signal trampoline in inferior, if any */
+static HDRR    *cur_hdr;
 
-CORE_ADDR sigtramp_address, sigtramp_end;
+/* Pointer to current file decriptor record, and its index */
+
+static FDR     *cur_fdr;
+static int      cur_fd;
 
+/* Index of current symbol */
 
-/* Functions that we really export */
+static int      cur_sdx;
 
-/* THIS DESCRIPTION IS OBSOLETE POST-BFD; FIXME! */
-/* Basically, this module must provide two functions: symbol_file_command()
-   which loads the symbol table from a file, and add_file_command() which
-   adds more symbols to the symbol table (incrementally).
+/* Note how much "debuggable" this image is.  We would like
+   to see at least one FDR with full symbols */
 
-   These two functions only do the minimum work necessary for letting the
-   user "name" things symbolically, they do not read the entire symtab.
-   Instead, they read in the external symbols and put them in partial
-   symbol tables.  When more extensive information is requested of a
-   file the corresponding partial symbol table is mutated into a full
-   fledged symbol table by going back and reading the relative symbols
-   for real.  mipscoff_psymtab_to_symtab() is the function that does this */
+static max_gdbinfo;
+static max_glevel;
 
-/* The entry point (starting address) of the file, if it is an executable.  */
+/* When examining .o files, report on undefined symbols */
 
-static CORE_ADDR entry_point;
+static int n_undef_symbols, n_undef_labels, n_undef_vars, n_undef_procs;
+
+/* Extra builtin types */
+
+struct type *builtin_type_complex;
+struct type *builtin_type_double_complex;
+struct type *builtin_type_fixed_dec;
+struct type *builtin_type_float_dec;
+struct type *builtin_type_string;
+
+/* Forward declarations */
+
+static struct symbol   *new_symbol();
+static struct type     *new_type();
+static struct field    *new_field();
+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 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 void reorder_symtabs();
+static void reorder_psymtabs();
+static void shrink_linetable();
+\f
+/* Things we export to other modules */
+
+/* Address bounds for the signal trampoline in inferior, if any */
+/* FIXME:  Nothing really seems to use this.  Why is it here? */
+
+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 */
@@ -130,31 +207,17 @@ extern CORE_ADDR startup_file_end;        /* From blockframe.c */
 void
 mipscoff_new_init()
 {
+  /* 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;
 {
-  bfd *abfd = sf->sym_bfd;
   sf->sym_private = NULL;
-  /* Save startup file's range of PC addresses to help blockframe.c
-     decide where the bottom of the stack is.  */
-  if (bfd_get_file_flags (abfd) & EXEC_P)
-    {
-      /* Executable file -- record its entry point so we'll recognize
-        the startup file because it contains the entry point.  */
-      entry_point = bfd_get_start_address (abfd);
-    }
-  else
-    {
-      /* Examination of non-executable.o files.  Short-circuit this stuff.  */
-      /* ~0 will not be in any file, we hope.  */
-      entry_point = ~0;
-      /* set the startup file to be an empty range.  */
-      startup_file_start = 0;
-      startup_file_end = 0;
-    }
 }
 
 void
@@ -164,54 +227,18 @@ mipscoff_symfile_read(sf, addr, mainline)
      int mainline;
 {
   struct coff_symfile_info *info = (struct coff_symfile_info *)sf->sym_private;
-  bfd *abfd = sf->sym_bfd;
+  bfd *abfd = sf->objfile->obfd;
   char *name = bfd_get_filename (abfd);
   int desc;
   register int val;
-  int num_symbols;
   int symtab_offset;
   int stringtab_offset;
 
 /* WARNING WILL ROBINSON!  ACCESSING BFD-PRIVATE DATA HERE!  FIXME!  */
    desc = fileno ((FILE *)(abfd->iostream));   /* Raw file descriptor */
-   num_symbols = bfd_get_symcount (abfd);      /* How many syms */
-/*   symtab_offset = obj_sym_filepos (abfd);   * Symbol table file offset */
-/*   stringtab_offset = symtab_offset + num_symbols * SYMESZ;  * String tab */
 /* End of warning */
 
-#ifdef TDESC
-  debug_info = text_hdr.s_relptr;
-  if (tdesc_handle)
-    {
-       dc_terminate (tdesc_handle);
-       tdesc_handle = 0;
-    }
-#endif
-
-#if 0
-  /* Read the line number table, all at once.  */
-  info->min_lineno_offset = 0;
-  info->max_lineno_offset = 0;
-  bfd_map_over_sections (abfd, find_linenos, info);
-
-  val = init_lineno (desc, info->min_lineno_offset, 
-                    info->max_lineno_offset - info->min_lineno_offset);
-  if (val < 0)
-    error ("\"%s\": error reading line numbers\n", name);
-
-  /* Now read the string table, all at once.  */
-
-  val = init_stringtab (desc, stringtab_offset);
-  if (val < 0)
-    {
-      free_all_symtabs ();             /* FIXME blows whole symtab */
-      printf ("\"%s\": can't get string table", name);
-      fflush (stdout);
-      return;
-    }
-  make_cleanup (free_stringtab, 0);
-#endif
-  /* Position to read the symbol table.  Do not read it all at once. */
+  /* Position to read the symbol table.  */
   val = lseek (desc, (long)symtab_offset, 0);
   if (val < 0)
     perror_with_name (name);
@@ -222,262 +249,17 @@ mipscoff_symfile_read(sf, addr, mainline)
   /* Now that the executable file is positioned at symbol table,
      process it and define symbols accordingly.  */
 
-  printf("Reading symbol data from %s...", name);
-  fflush(stdout);
-  read_mips_symtab(desc, 0);
-
-/*  patch_opaque_types ();*/
-
-  /* Sort symbols alphabetically within each block.  */
-
-  sort_all_symtab_syms ();
+  read_mips_symtab(sf->objfile, desc);
 
   /* Go over the misc symbol bunches and install them in vector.  */
 
-  condense_misc_bunches (0);
-
-  /* Make a default for file to list.  */
-
-  select_source_symtab (0);    /* FIXME, this might be too slow, see dbxread */
-}  
-  
-void
-mipscoff_symfile_discard()
-{
+  condense_misc_bunches (!mainline);
 }
   
-  
-#if 0
-/* Exported procedure: Reads symbols from file NAME.
-   Invoked at startup time if executable was given.
-   When invoked cleans up the world */
-
-void
-symbol_file_command(name, from_tty)
-     char *name;
-     int from_tty;
-{
-  int                  desc;
-  struct coff_exec     hdr;
-  register int         val;
-  extern void          close();
-  struct cleanup *old_chain;
-
-  dont_repeat();
-
-  /*
-   * Make sure s/he means it 
-   */
-  if (name == 0) {
-    if ((symtab_list || partial_symtab_list)
-       && from_tty
-       && !query("Discard symbol table? ", 0))
-       error("Not confirmed.");
-    destroy_all_symtabs();
-    return;
-  }
-
-  name = tilde_expand(name);
-  make_cleanup(free, name);
-
-  if (symtab_list &&
-      !query("Load new symbol table from \"%s\"? ", name))
-      error("Not confirmed.");
-
-  /* Open the file */
-  {
-    char *absolute_name;
-    desc = openp (getenv ("PATH"), 1, name, O_RDONLY, 0, &absolute_name);
-    if (desc < 0)
-      perror_with_name (name);
-    else
-      name = absolute_name;
-  }
-
-  old_chain = make_cleanup (close, desc);
-  make_cleanup (free_current_contents, &name);
-
-  /*
-   * Check file is indeed executable 
-   */
-  val = myread(desc, &hdr, sizeof hdr);
-  if (val < 0)
-     perror_with_name(name);
-
-  if (N_BADMAG(hdr))
-    error("File \"%s\" not in executable format.", name);
-
-  if (hdr.a.entry < SAFE_TEXT_ADDR && access(name, 1))
-      printf_filtered("Warning: %s is not executable!\n", name);
-
-  if (hdr.a_syms == 0) {
-    printf_filtered("%s does not have a symbol-table.\n", name);
-    fflush(stdout);
-    return;
-  }
-
-  /* Get the modification time.  */
-  {
-    struct stat symstat;
-
-    if (fstat (desc, &symstat) < 0)
-      perror_with_name (name);
-
-    symfile_mtime = symstat.st_mtime;
-  }
-
-  /*
-   * Throw away the old symbol table.  
-   */
-
-  destroy_all_symtabs();
-
-  /* Make a default for file to list.  */
-
-  symfile = savestring (name, strlen (name));
-
-  /* Prepare to remember misc symbol values */
-
-  init_misc_bunches ();
-  make_cleanup (discard_misc_bunches, 0);
-
-  /*
-   * Now read the new symbol table 
-   */
-
-  read_mips_symtab(desc, 0);
-
-  /* Go over the misc symbol bunches and install them in vector.  */
-
-  condense_misc_bunches (0);
-
-  /* Don't allow char * to have a typename (else would get caddr_t.)  */
-
-  TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0;
-
-  /* Force reinit of the sigtramp info */
-  sigtramp_address = 0;
-
-  do_cleanups (old_chain);     /* Descriptor closed here */
-
-  if (!partial_symtab_list)
-    printf ("\n(no debugging symbols found)...");
-
-  printf ("done.\n");
-  fflush(stdout);
-}
-#endif
-
-/* C++:
-   This function allows the addition of incrementally linked object files.
-   Since this has a fair amount of code in common with symbol_file_command,
-   it might be worthwhile to consolidate things, as was done with
-   read_dbx_symtab and condense_misc_bunches. */
-
-/* Exported procedure: add more symbols from file NAME. */
-
-void
-add_file_command(arg_string)
-     char* arg_string;
-{
-  int                  desc;
-  struct coff_exec     hdr;
-  register int         val;
-  extern void          close();
-  struct cleanup *old_chain;
-  char *name;
-  unsigned text_addr;
-
-  if (arg_string == 0)
-    error ("add-file takes a file name and an address");
-
-  if (arg_string == 0)
-    error ("add-file takes a file name and an address");
-
-  arg_string = tilde_expand (arg_string);
-  make_cleanup (free, arg_string);
-
-  for( ; *arg_string == ' '; arg_string++ );
-  name = arg_string;
-  for( ; *arg_string && *arg_string != ' ' ; arg_string++ );
-  *arg_string++ = (char) 0;
-
-  if (name[0] == 0)
-    error ("add-file takes a file name and an address");
-
-  text_addr = parse_and_eval_address (arg_string);
-
-  dont_repeat();
-
-  if (!query ("add symbol table from filename \"%s\" at text_addr = 0x%x\n",
-             name, text_addr))
-    error ("Not confirmed.");
-
-  /*
-   * Open the file 
-   */
-  {
-    char           *absolute_name;
-
-    desc = openp(getenv("PATH"), 1, name, O_RDONLY, 0, &absolute_name);
-    if (desc < 0)
-      perror_with_name(name);
-    else
-      name = absolute_name;
-  }
-  old_chain = make_cleanup (close, desc);
-
-
-  /*
-   * Check file is indeed executable 
-   */
-  val = myread(desc, &hdr, sizeof hdr);
-  if (val < 0)
-      perror_with_name(name);
-
-  if (N_BADMAG(hdr))
-      error("File \"%s\" not in executable format.", name);
-
-  if (hdr.a.entry < SAFE_TEXT_ADDR && access(name, 1))
-      printf_filtered("Warning: %s is not executable!\n", name);
-
-  if (hdr.a_syms == 0) {
-      printf_filtered("%s does not have a symbol-table.\n", name);
-      fflush(stdout);
-      return;
-  }
-
-  if (symfile)
-      free(symfile);
-  symfile = 0;
-
-  /*
-   * Now read the new symbol table 
-   */
-
-  symfile = savestring(name, strlen(name));
-
-  init_misc_bunches ();
-  make_cleanup (discard_misc_bunches, 0);
-  read_mips_symtab(desc, 1);
-
-  /* Go over the misc symbol bunches and install them in vector.  */
-
-  condense_misc_bunches (1);
-
-  /* Don't allow char * to have a typename (else would get caddr_t.)  */
-
-  TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0;
-
-  do_cleanups (old_chain);
-
-  printf_filtered("done.\n");
-  fflush(stdout);
-}
-
 /* Exported procedure: Allocate zeroed memory */
 
-char *xzalloc(size)
+char *
+xzalloc(size)
 {
        char           *p = xmalloc(size);
 
@@ -490,10 +272,7 @@ char *xzalloc(size)
    most of the work to an ancillary procedure, and sorts
    and reorders the symtab list at the end */
 
-/* Forward decls */
-static HDRR    *cur_hdr;       /* MIPS symtab header for the current file */
-
-void
+static void
 mipscoff_psymtab_to_symtab(pst)
        struct partial_symtab *pst;
 {
@@ -508,123 +287,64 @@ mipscoff_psymtab_to_symtab(pst)
                fflush(stdout);
        }
        /* Restore the header and list of pending typedefs */
-       cur_hdr = (HDRR *) pst->ldsymlen;
+       cur_hdr = CUR_HDR(pst);
 
-       psymtab_to_symtab_1(pst);
+       psymtab_to_symtab_1(pst, pst->filename);
 
        reorder_symtabs();
 
-       /* Finish up the debug error message.  */
        if (info_verbose)
                printf_filtered("done.\n");
 }
 
 /* Exported procedure: Is PC in the signal trampoline code */
 
-int in_sigtramp(pc,name)
+int
+in_sigtramp(pc, name)
        CORE_ADDR pc;
+       char *name;
 {
        if (sigtramp_address == 0)
                fixup_sigtramp();
        return (pc >= sigtramp_address && pc < sigtramp_end);
 }
-
-\f
-/* Things that really are local to this module */
-
-/* All allocated symtabs and psymtabs */
-
-static int all_symtabs_count;
-static int all_psymtabs_count;
-
-/* GDB symtable for the current compilation unit */
-
-static struct symtab *cur_stab;
-
-/* Header for executable/object file we read symbols from */
-
-static struct coff_exec filhdr;
-#define END_OF_TEXT_SEGMENT(f) ((f).a.text_start + (f).a.tsize)
-
-/* Pointer to current file decriptor record, and its index */
-
-static FDR     *cur_fdr;
-static int      cur_fd;
-
-/* Index of current symbol */
-
-static int      cur_sdx;
-
-/* Note how much "debuggable" this image is.  We would like
-   to see at least one FDR with full symbols */
-
-static max_gdbinfo;
-static max_glevel;
-
-/* When examining .o files, report on undefined symbols */
-
-static int n_undef_symbols, n_undef_labels, n_undef_vars, n_undef_procs;
-
-/* Extra builtin types */
-
-struct type *builtin_type_complex;
-struct type *builtin_type_double_complex;
-struct type *builtin_type_fixed_dec;
-struct type *builtin_type_float_dec;
-struct type *builtin_type_string;
-
-/* Template types */
-
-static struct type *builtin_type_ptr;
-static struct type *builtin_type_struct;
-static struct type *builtin_type_union;
-static struct type *builtin_type_enum;
-static struct type *builtin_type_range;
-static struct type *builtin_type_set;
-
-
-/* Forward decls */
-
-static struct symbol   *new_symbol();
-static struct type     *new_type();
-static struct field    *new_field();
-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 int compare_symtabs();
-static int compare_psymtabs();
-static int compare_blocks();
-
-static struct partial_symtab *new_psymtab();
-static struct partial_symbol *new_psymbol();
-static struct partial_symtab *parse_fdr();
-static int compare_psymbols();
 \f
 /* File-level interface functions */
 
-/* Read the symtab information from file FSYM into memory */
+/* Read the symtab information from file FSYM into memory.  Also,
+   return address just past end of our text segment in *END_OF_TEXT_SEGP.  */
 
 static
-read_the_mips_symtab(fsym)
+read_the_mips_symtab(abfd, fsym, end_of_text_segp)
+       bfd             *abfd;
+       int             fsym;
+       CORE_ADDR       *end_of_text_segp;
 {
        int             stsize, st_hdrsize;
        unsigned        st_filptr;
        HDRR            st_hdr;
+       /* Header for executable/object file we read symbols from */
+       struct coff_exec filhdr;
+
+       /* 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);
+
+       if (end_of_text_segp)
+               *end_of_text_segp =
+                       bfd_h_get_32 (abfd, filhdr.a.text_start) +
+                       bfd_h_get_32 (abfd, filhdr.a.tsize);
 
        /* Find and read the symbol table header */
-       st_hdrsize = filhdr.f.f_nsyms;
-       st_filptr = filhdr.f.f_symptr;
+       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;
 
        lseek(fsym, st_filptr, L_SET);
+       if (st_hdrsize > sizeof (st_hdr))       /* Profanity check */
+               abort();
        if (read(fsym, &st_hdr, st_hdrsize) != st_hdrsize)
                goto readerr;
 
@@ -645,7 +365,7 @@ read_the_mips_symtab(fsym)
 
        return;
 readerr:
-       error("Short read on %s", symfile);
+       error("Short read on %s", bfd_get_filename (abfd));
 }
 
 
@@ -778,8 +498,9 @@ fixup_symtab( hdr, data, f_ptr)
 
 /* Find a file descriptor given its index RF relative to a file CF */
 
-static
-FDR *get_rfd( cf, rf)
+static FDR *
+get_rfd (cf, rf)
+       int cf, rf;
 {
        register FDR   *f;
 
@@ -793,8 +514,8 @@ FDR *get_rfd( cf, rf)
 
 /* Return a safer print NAME for a file descriptor */
 
-static
-char *fdr_name(name)
+static char *
+fdr_name(name)
        char *name;
 {
        if (name == (char *) -1)
@@ -806,22 +527,19 @@ char *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( desc, incremental)
+read_mips_symtab (objfile, desc)
+       struct objfile *objfile;
+       int desc;
 {
-       /*
-        * We get here with DESC pointing to the symtab header. But we need
-        * other info from the initial headers 
-        */
-       lseek(desc, 0L, 0);
-       myread(desc, &filhdr, sizeof filhdr);
+       CORE_ADDR end_of_text_seg;
 
-       read_the_mips_symtab(desc);
+       read_the_mips_symtab(objfile->obfd, desc, &end_of_text_seg);
 
-       parse_partial_symbols(cur_hdr, incremental);
-       cur_hdr = 0;
+       parse_partial_symbols(end_of_text_seg, objfile);
 
        /*
         * Check to make sure file was compiled with -g.
@@ -829,27 +547,23 @@ read_mips_symtab( desc, incremental)
         */
        if (compare_glevel(max_glevel, GLEVEL_2) < 0) {
                if (max_gdbinfo == 0)
-                       printf("\n%s not compiled with -g, debugging support is limited.", symfile);
-               printf("\nYou should compile with -g2 or -g3 for best debugging support.\n");
+                       printf (
+"\n%s not compiled with -g, debugging support is limited.\n",
+                               objfile->name);
+               printf(
+"You should compile with -g2 or -g3 for best debugging support.\n");
                fflush(stdout);
        }
-
-       /*
-        * Dont allow char * to have a typename (else would get
-        * caddr_t.)  
-        */
-       TYPE_NAME(lookup_pointer_type(builtin_type_char)) = 0;
 }
-
 \f
 /* Local utilities */
 
-
 /* Map of FDR indexes to partial symtabs */
 
 static struct pst_map {
        struct partial_symtab *pst;     /* the psymtab proper */
        int n_globals;                  /* globals it exports */
+       int n_statics;                  /* statics (locals) it contains */
 } * fdr_to_pst;
 
 
@@ -1022,7 +736,7 @@ lookup_numargs(adr)
 
 /* Release storage when done with this file */
 
-static
+static void
 free_numargs()
 {
        struct numarg  *n = numargs_list, *m;
@@ -1042,7 +756,7 @@ free_numargs()
    For blocks, procedures and types we open a new lexical context.
    This is basically just a big switch on the symbol's type */
 
-static
+static void
 parse_symbol(sh, ax)
        SYMR *sh;
        AUXU *ax;
@@ -1061,17 +775,22 @@ parse_symbol(sh, ax)
            case stNil:
                break;
 
-           case stGlobal:      /* external symbol, goes into the primary block */
+           case stGlobal:      /* external symbol, goes into global block */
                class = LOC_STATIC;
-               b = BLOCKVECTOR_BLOCK(BLOCKVECTOR(top_stack->cur_st), 0);
+               b = BLOCKVECTOR_BLOCK(BLOCKVECTOR(top_stack->cur_st),
+                                     GLOBAL_BLOCK);
+               s = new_symbol(sh->iss);
+               SYMBOL_VALUE_ADDRESS(s) = (CORE_ADDR)sh->value;
                goto data;
 
-           case stStatic:      /* static data, goes into the current block. */
+           case stStatic:      /* static data, goes into current block. */
                class = LOC_STATIC;
                b = top_stack->cur_block;
+               s = new_symbol(sh->iss);
+               SYMBOL_VALUE_ADDRESS(s) = (CORE_ADDR)sh->value;
                goto data;
 
-           case stLocal:       /* local variable, goes into the current block */
+           case stLocal:       /* local variable, goes into current block */
                if (sh->sc == scRegister) {
                        class = LOC_REGISTER;
                        if (sh->value > 31)
@@ -1079,9 +798,10 @@ parse_symbol(sh, ax)
                } else
                        class = LOC_LOCAL;
                b = top_stack->cur_block;
+               s = new_symbol(sh->iss);
+               SYMBOL_VALUE(s) = sh->value;
 
 data:          /* Common code for symbols describing data */
-               s = new_symbol(sh->iss);
                SYMBOL_NAMESPACE(s) = VAR_NAMESPACE;
                SYMBOL_CLASS(s) = class;
                add_symbol(s, b);
@@ -1093,10 +813,9 @@ data:             /* Common code for symbols describing data */
                else
                        SYMBOL_TYPE(s) = parse_type(ax + sh->index, sh, 0);
                /* Value of a data symbol is its memory address */
-               SYMBOL_VALUE(s) = sh->value;
                break;
 
-           case stParam:       /* argument to procedure, goes into current block */
+           case stParam:       /* arg to procedure, goes into current block */
                max_gdbinfo++;
                top_stack->numargs++;
                s = new_symbol(sh->iss);
@@ -1110,19 +829,25 @@ data:            /* Common code for symbols describing data */
                SYMBOL_VALUE(s) = sh->value;
                SYMBOL_TYPE(s) = parse_type(ax + sh->index, sh, 0);
                add_symbol(s, top_stack->cur_block);
+#if 0
+               /* FIXME:  This has not been tested.  See dbxread.c */
+               /* Add the type of this parameter to the function/procedure
+                  type of this block. */
+               add_param_to_type(&top_stack->cur_block->function->type,s);
+#endif
                break;
 
-           case stLabel:       /* label, we do make a symbol for it */
+           case stLabel:       /* label, goes into current block */
                s = new_symbol(sh->iss);
                SYMBOL_NAMESPACE(s) = VAR_NAMESPACE;    /* so that it can be used */
                SYMBOL_CLASS(s) = LOC_LABEL;            /* but not misused */
-               SYMBOL_VALUE(s) = sh->value;
+               SYMBOL_VALUE_ADDRESS(s) = (CORE_ADDR)sh->value;
                SYMBOL_TYPE(s) = builtin_type_int;
                add_symbol(s, top_stack->cur_block);
                break;
 
-           case stProc:        /* Procedure */
-           case stStaticProc:  /* Static procedure */
+           case stProc:        /* Procedure, usually goes into global block */
+           case stStaticProc:  /* Static procedure, goes into current block */
                s = new_symbol(sh->iss);
                SYMBOL_NAMESPACE(s) = VAR_NAMESPACE;
                SYMBOL_CLASS(s) = LOC_BLOCK;
@@ -1131,10 +856,27 @@ data:            /* Common code for symbols describing data */
                        t = builtin_type_int;
                else
                        t = parse_type(ax + sh->index, sh, 0);
-               add_symbol(s, top_stack->cur_block);
+               b = top_stack->cur_block;
+               if (sh->st == stProc) {
+                   struct blockvector *bv = BLOCKVECTOR(top_stack->cur_st);
+                   /* The next test should normally be true,
+                      but provides a hook for nested functions
+                      (which we don't want to make global). */
+                   if (b == BLOCKVECTOR_BLOCK(bv, STATIC_BLOCK))
+                       b = BLOCKVECTOR_BLOCK(bv, GLOBAL_BLOCK);
+               }
+               add_symbol(s, b);
 
                /* 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 
+                  table. */
+               bcopy(SYMBOL_TYPE(s),lookup_function_type(t),sizeof(struct type));
+#else
                SYMBOL_TYPE(s) = lookup_function_type (t);
+#endif
 
                /* Create and enter a new lexical context */
                b = new_block(top_stack->maxsyms);
@@ -1221,6 +963,11 @@ data:             /* Common code for symbols describing data */
                            BLOCK_END(b_bad) = BLOCK_END(b);
                        }
                    }
+                   if (entry_point < BLOCK_END(b)
+                     && entry_point >= BLOCK_START(b)) {
+                       startup_file_start = BLOCK_START(b);
+                       startup_file_end = BLOCK_END(b);
+                   }
                } else if (sh->sc == scText && top_stack->blocktype == stBlock) {
                        /* End of (code) block. The value of the symbol
                           is the displacement from the procedure`s start
@@ -1307,7 +1054,7 @@ static struct type *parse_type(ax, sh, bs)
 
        TIR            *t;
        struct type    *tp = 0, *tp1;
-       char           *fmt = "%s";
+       char           *fmt;
 
        /* Procedures start off by one */
        if (sh->st == stProc || sh->st == stStaticProc)
@@ -1320,38 +1067,43 @@ static struct type *parse_type(ax, sh, bs)
 
        /* Use aux as a type information record, map its basic type */
        t = &ax->ti;
-       if (t->bt > 26 || t->bt == btPicture) {
-               printf_filtered("Internal: cannot map MIPS basic type x%x\n", t->bt);
+       if (t->bt > (sizeof (map_bt)/sizeof (*map_bt))) {
+               complain (&basic_type_complaint, t->bt);
                return builtin_type_int;
        }
        if (map_bt[t->bt])
                tp = *map_bt[t->bt];
+               fmt = "%s";
        else {
-               /* Cannot use builtin types, use templates */
-               tp = make_type(TYPE_CODE_VOID, 0, 0, 0);
+               /* Cannot use builtin types -- build our own */
                switch (t->bt) {
                    case btAdr:
-                       *tp = *builtin_type_ptr;
+                       tp = lookup_pointer_type (builtin_type_void);
+                       fmt = "%s";
                        break;
                    case btStruct:
-                       *tp = *builtin_type_struct;
+                       tp = make_struct_type(TYPE_CODE_STRUCT, 0, 0, 0);
                        fmt = "struct %s";
                        break;
                    case btUnion:
-                       *tp = *builtin_type_union;
+                       tp = make_struct_type(TYPE_CODE_UNION, 0, 0, 0);
                        fmt = "union %s";
                        break;
                    case btEnum:
-                       *tp = *builtin_type_enum;
+                       tp = make_type(TYPE_CODE_ENUM, 0, 0, 0);
                        fmt = "enum %s";
                        break;
                    case btRange:
-                       *tp = *builtin_type_range;
+                       tp = make_type(TYPE_CODE_RANGE, 0, 0, 0);
+                       fmt = "%s";
                        break;
                    case btSet:
-                       *tp = *builtin_type_set;
+                       tp = make_type(TYPE_CODE_SET, 0, 0, 0);
                        fmt = "set %s";
                        break;
+                   default:
+                       complain (&basic_type_complaint, t->bt);
+                       return builtin_type_int;
                }
        }
 
@@ -1457,72 +1209,97 @@ again:  PARSE_TQ(tq0);
    the symbol SX we are currently analyzing.
    Returns the number of aux symbols we parsed. */
 
-static
+static int
 upgrade_type(tpp, tq, ax, sh)
        struct type   **tpp;
        AUXU           *ax;
        SYMR           *sh;
 {
-       int             off = 0;
-       int             ret = 0;
+       int             off;
        struct type    *t;
 
-       if (tq == tqPtr) {
+       /* Used in array processing */
+       int             rf, id;
+       FDR            *fh;
+       struct field   *f;
+       SYMR            ss;
+       int             lower, upper;
+
+       switch (tq) {
+       case tqPtr:
                t = lookup_pointer_type (*tpp);
-       } else if (tq == tqProc) {
+               *tpp = t;
+               return 0;
+
+       case tqProc:
                t = lookup_function_type (*tpp);
-       } else if (tq == tqArray) {
-               int             rf, id;
-               FDR            *fh;
-               struct field   *f;
-               SYMR            ss;
+               *tpp = t;
+               return 0;
 
+       case tqArray:
+               off = 0;
                t = make_type(TYPE_CODE_ARRAY, 0, 0, 0);
                TYPE_TARGET_TYPE(t) = *tpp;
 
-               /* Pointer to domain type (type of index) */
+               /* Determine and record the domain type (type of index) */
                id = ax->rndx.index;
-               if ((rf = ax->rndx.rfd) == 0xfff)
-                       rf = (++ax)->isym, off++;
-
+               rf = ax->rndx.rfd;
+               if (rf == 0xfff) {
+                       rf = (++ax)->isym;
+                       off++;
+               }
                fh = get_rfd(cur_fd, rf);
-               f = new_field(t, 0);
+               f = new_field(t, (char *)0);
                bzero(&ss, sizeof ss);
 /* XXX */      f->type = parse_type(fh->iauxBase + id * sizeof(AUXU),
                                     &ss, &f->bitsize);
 
+               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.
                 */
-               if (off == 0) {
+                       /* 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++;
                }
-               f->bitpos = (++ax)->dnLow;      /* ?? */
-               f->bitsize = (++ax)->dnHigh;    /* ?? */
-               rf = (++ax)->width - 1; /* bit alignment */
+               lower = (++ax)->dnLow;
+               upper = (++ax)->dnHigh;
+               rf = (++ax)->width;     /* bit size of array element */
+
+               /* Check whether supplied array element bit size matches
+                  the known size of the element type.  If this complaint
+                  ends up not happening, we can remove this code.  It's
+                  here because we aren't sure we understand this *&%&$
+                  symbol format.  */
                id = TYPE_LENGTH(TYPE_TARGET_TYPE(t)) << 3; /* bitsize */
-
                if (id == 0) {
                        /* Most likely an undefined type */
-                       id = rf + 1;
+                       id = rf;
                        TYPE_LENGTH(TYPE_TARGET_TYPE(t)) = id >> 3;
                }
-               TYPE_LENGTH(t) = (f->bitsize < 0) ? 0 :
-                       (f->bitsize - f->bitpos + 1) * (id >> 3);
-               ret = 4 + off;
-       } else {
-               if (tq != tqVol)
-                       printf_filtered("Internal: unknown type qualifier %x\n", tq);
-               return ret;
-       }
+               if (id != rf)
+                       complain (&array_bitsize_complaint, rf);
+
+               TYPE_LENGTH(t) = (upper < 0) ? 0 :
+                       (upper - lower + 1) * (rf >> 3);
+               *tpp = t;
+               return 4 + off;
+
+       case tqVol:
+               /* Volatile -- currently ignored */
+               return 0;
 
-       *tpp = t;
-       return ret;
+       default:
+               complain (&unknown_type_qual_complaint, tq);
+               return 0;
+       }
 }
 
 
@@ -1593,7 +1370,9 @@ parse_procedure(pr, bound)
    making sure we know where the aux are for it. For procedures,
    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 */
+   and only if this causes no symbol duplication.
+
+   This routine clobbers top_stack->cur_block and ->cur_st. */
 
 static
 parse_external(es, skip_procedures)
@@ -1610,21 +1389,22 @@ parse_external(es, skip_procedures)
                ax = 0;
        }
        top_stack->cur_st = cur_stab;
-       top_stack->cur_block = BLOCKVECTOR_BLOCK(BLOCKVECTOR(top_stack->cur_st),0);
+       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) {
                char *what;
                switch (es->asym.st) {
                case stStaticProc:
-               case stProc:    what = "Procedure"; n_undef_procs++;  break;
-               case stGlobal:  what = "Variable";  n_undef_vars++;   break;
-               case stLabel:   what = "Label";     n_undef_labels++; break;
-               default :       what = "Symbol";                      break;
+               case stProc:    what = "procedure"; n_undef_procs++;  break;
+               case stGlobal:  what = "variable";  n_undef_vars++;   break;
+               case stLabel:   what = "label";     n_undef_labels++; break;
+               default :       what = "symbol";                      break;
                }
                n_undef_symbols++;
                if (info_verbose)
-                       printf_filtered("Warning: %s %s is undefined (in %s)\n", what,
+                       printf_filtered("Warning: %s `%s' is undefined (in %s)\n", what,
                                es->asym.iss, fdr_name(cur_fdr->rss));
                return;
        }
@@ -1662,7 +1442,7 @@ parse_lines(fh, lt)
        FDR *fh;
        struct linetable *lt;
 {
-       char *base = (char*)fh->cbLineOffset;
+       unsigned char *base = (unsigned char*)fh->cbLineOffset;
        int i, j, k;
        int delta, count, lineno = 0;
        PDR *pr;
@@ -1696,14 +1476,18 @@ parse_lines(fh, lt)
                 */
                if (pr->iline >= halt) continue;
 
-               base = (char*)pr->cbLineOffset;
+               base = (unsigned char*)pr->cbLineOffset;
                l = pr->adr >> 2;       /* in words */
                halt += (pr->adr >> 2) - pr->iline;
                for (lineno = pr->lnLow; l < halt;) {
                        count = *base & 0x0f;
                        delta = *base++ >> 4;
+                       if (delta >= 8)
+                               delta -= 16;
                        if (delta == -8) {
-                               delta = (base[0] << 8) | (base[1] & 0xff);
+                               delta = (base[0] << 8) | base[1];
+                               if (delta >= 0x8000)
+                                       delta -= 0x10000;
                                base += 2;
                        }
                        lineno += delta;/* first delta is 0 */
@@ -1750,32 +1534,38 @@ parse_one_file(fh, f_idx, bound)
        if (LINETABLE(cur_stab)->nitems < fh->cline)
                shrink_linetable(cur_stab);
 }
+\f
+/* Master parsing procedure for first-pass reading of file symbols
+   into a partial_symtab.
 
+   Parses the symtab described by the global symbolic header CUR_HDR.
+   END_OF_TEXT_SEG gives the address just after the text segment for
+   the symtab we are reading.  */
 
-/* Master parsing procedure. Parses the symtab described by the
-   symbolic header HDR.  If INCREMENTAL is true we are called
-   by add-file and must preserve the old symtabs */
 static
-parse_partial_symbols(hdr, incremental)
-       HDRR *hdr;
+parse_partial_symbols(end_of_text_seg, objfile)
+       int end_of_text_seg;
+       struct objfile *objfile;
 {
-       int             f_idx, s_idx, h_max;
-       CORE_ADDR       dummy, *prevhigh;
+       int             f_idx, s_idx, h_max, stat_idx;
+       HDRR            *hdr;
        /* Running pointers */
-       FDR            *fh;
-       RFDT           *rh;
-       register EXTR           *esh;
+       FDR             *fh;
+       RFDT            *rh;
+       register EXTR   *esh;
+       register SYMR   *sh;
+       struct partial_symtab *pst;
 
        /*
         * Big plan: 
         *
-        * Only parse the External symbols, and the Relative FDR.
+        * 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
+        * Allocate space only for the file's portions we need to
         * look at. (XXX)
         */
 
-       cur_hdr = hdr;
+       hdr = cur_hdr;
        max_gdbinfo = 0;
        max_glevel = MIN_GLEVEL;
 
@@ -1785,47 +1575,76 @@ parse_partial_symbols(hdr, incremental)
        fdr_to_pst = (struct pst_map *)xzalloc((hdr->ifdMax+1) * sizeof *fdr_to_pst);
        fdr_to_pst++;
        {
-               struct partial_symtab * pst = new_psymtab("");
+               struct partial_symtab * pst = new_psymtab("", objfile);
                fdr_to_pst[-1].pst = pst;
-               pst->ldsymoff = -1;
+               FDR_IDX(pst) = -1;
        }
 
        /* Now scan the FDRs, mostly for dependencies */
        for (f_idx = 0; f_idx < hdr->ifdMax; f_idx++)
-               (void) parse_fdr(f_idx, 1);
+               (void) parse_fdr(f_idx, 1, objfile);
 
        /* Take a good guess at how many symbols we might ever need */
        h_max = hdr->iextMax;
 
        /* Parse externals: two passes because they can be ordered
-          in any way */
+          in any way, but gdb likes to have them segregated by their
+          source file.  */
 
-       /* Pass 1: Presize and partition the list */
+       /* 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++;
        }
 
        if (global_psymbols.list) {
+               int origsize = global_psymbols.next - global_psymbols.list;
+
                global_psymbols.list = (struct partial_symbol *)
-                       xrealloc( global_psymbols.list, (h_max +
-                               global_psymbols.size) * sizeof(struct partial_symbol));
-               global_psymbols.next = global_psymbols.list + global_psymbols.size;
-               global_psymbols.size += h_max;
+                       xrealloc (global_psymbols.list,
+                          (h_max + origsize) * sizeof(struct partial_symbol));
+               global_psymbols.next = global_psymbols.list + origsize;
+               global_psymbols.size = h_max + origsize;
        } else {
                global_psymbols.list = (struct partial_symbol *)
-                               xmalloc( h_max * sizeof(struct partial_symbol));
-               global_psymbols.size = h_max;
+                               xmalloc (h_max * sizeof(struct partial_symbol));
                global_psymbols.next = global_psymbols.list;
+               global_psymbols.size = h_max;
        }
 
-       s_idx = global_psymbols.next - global_psymbols.list;
+       /* Pass 1.5 over files:  partition out global symbol space */
+       s_idx    = global_psymbols.next - global_psymbols.list;
        for (f_idx = -1; f_idx < hdr->ifdMax; f_idx++) {
                fdr_to_pst[f_idx].pst->globals_offset = s_idx;
                s_idx += fdr_to_pst[f_idx].n_globals;
        }
 
-       /* Pass 2: fill in symbols */
+       /* Pass 1.6 over files:  partition out static symbol space.
+          Note that this loop starts at 0, not at -1. */
+       stat_idx = static_psymbols.next - static_psymbols.list;
+       for (f_idx = 0; f_idx < hdr->ifdMax; f_idx++) {
+               fdr_to_pst[f_idx].pst->statics_offset = stat_idx;
+               fh = f_idx + (FDR *)(hdr->cbFdOffset);
+               stat_idx += fh->csym;
+       }
+
+       /* Now that we know its max size, allocate static symbol list */
+       if (static_psymbols.list) {
+               int origsize = static_psymbols.next - static_psymbols.list;
+
+               static_psymbols.list = (struct partial_symbol *)
+                       xrealloc (static_psymbols.list,
+                          stat_idx * sizeof(struct partial_symbol));
+               static_psymbols.next = static_psymbols.list + origsize;
+               static_psymbols.size = stat_idx;
+       } else {
+               static_psymbols.list = (struct partial_symbol *)
+                       xmalloc (stat_idx * sizeof(struct partial_symbol));
+               static_psymbols.next = static_psymbols.list;
+               static_psymbols.size = stat_idx;
+       }
+
+       /* 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;
@@ -1833,20 +1652,27 @@ parse_partial_symbols(hdr, incremental)
 
                if (esh->asym.sc == scUndefined || esh->asym.sc == scNil)
                        continue;
-               p = new_psymbol(&global_psymbols, esh->asym.iss, esh->ifd);
-               SYMBOL_VALUE(p) = esh->asym.value;
+
+               /* Locate the psymtab and the preallocated psymbol.  */
+               pst = fdr_to_pst[esh->ifd].pst;
+               p = global_psymbols.list + pst->globals_offset +
+                        pst->n_global_syms++;
+               SYMBOL_NAME(p) = (char *)(esh->asym.iss);
                SYMBOL_NAMESPACE(p) = VAR_NAMESPACE;
 
                switch (esh->asym.st) {
                case stProc:
                        SYMBOL_CLASS(p) = LOC_BLOCK;
+                       SYMBOL_VALUE(p) = esh->asym.value;
                        break;
                case stGlobal:
                        SYMBOL_CLASS(p) = LOC_STATIC;
+                       SYMBOL_VALUE_ADDRESS(p) = (CORE_ADDR)esh->asym.value;
                        misc_type = mf_data;
                        break;
                case stLabel:
                        SYMBOL_CLASS(p) = LOC_LABEL;
+                       SYMBOL_VALUE_ADDRESS(p) = (CORE_ADDR)esh->asym.value;
                        break;
                default:
                        misc_type = mf_unknown;
@@ -1857,38 +1683,107 @@ parse_partial_symbols(hdr, incremental)
                                           misc_type);
        }
 
+       /* Pass 3 over files, over local syms: fill in static symbols */
+       for (f_idx = 0; f_idx < hdr->ifdMax; f_idx++) {
+               fh = f_idx + (FDR *)(cur_hdr->cbFdOffset);
+               pst = fdr_to_pst[f_idx].pst;
+               pst->texthigh = pst->textlow;
+               
+               for (s_idx = 0; s_idx < fh->csym; ) {
+                       register struct partial_symbol *p;
+
+                       sh = s_idx + (SYMR *) fh->isymBase;
+
+                       if (sh->sc == scUndefined || sh->sc == scNil ||
+                           sh->index == 0xfffff) {
+                               /* FIXME, premature? */
+                               s_idx++;
+                               continue;
+                       }
 
-       /* The array (of lists) of globals must be sorted.
-          Take care, since we are at it, of pst->texthigh.
+                       /* Locate the preallocated psymbol.  */
+                       p = static_psymbols.list + pst->statics_offset +
+                                pst->n_static_syms;
+                       SYMBOL_NAME(p) = (char *)(sh->iss);
+                       SYMBOL_VALUE(p) = sh->value;
+                       SYMBOL_NAMESPACE(p) = VAR_NAMESPACE;
+
+                       switch (sh->st) {
+                       case stProc:            /* Asm labels apparently */
+                       case stStaticProc:              /* Function */
+                               SYMBOL_CLASS(p) = LOC_BLOCK;
+                               pst->n_static_syms++;   /* Use gdb symbol */
+                               /* Skip over procedure to next one. */
+                               s_idx = (sh->index + (AUXU *)fh->iauxBase)
+                                         ->isym;
+                                       {
+                                       long high;
+                                       long procaddr = sh->value;
+
+                                       sh = s_idx + (SYMR *) fh->isymBase - 1;
+                                       if (sh->st != stEnd)
+                                               continue;
+                                       high = procaddr + sh->value;
+                                       if (high > pst->texthigh)
+                                               pst->texthigh = high;
+                                       }
+                               continue;
+                       case stStatic:                  /* Variable */
+                               SYMBOL_CLASS(p) = LOC_STATIC;
+                               SYMBOL_VALUE_ADDRESS(p) = (CORE_ADDR)sh->value;
+                               break;
+                       case stTypedef:                 /* Typedef */
+                               SYMBOL_CLASS(p) = LOC_TYPEDEF;
+                               break;
+                       case stConstant:                /* Constant decl */
+                               SYMBOL_CLASS(p) = LOC_CONST;
+                               break;
+                       case stBlock:                   /* { }, str, un, enum*/
+                               if (sh->sc == scInfo) {
+                                      SYMBOL_NAMESPACE(p) = STRUCT_NAMESPACE;
+                                      SYMBOL_CLASS(p) = LOC_TYPEDEF;
+                                      pst->n_static_syms++;
+                               }
+                               /* Skip over the block */
+                               s_idx = 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);
+                               s_idx++;
+                               continue;
+                       }
+                       pst->n_static_syms++;   /* Use this gdb symbol */
+               skip:
+                       s_idx++;                /* Go to next file symbol */
+#if 0
+/* We don't usually record static syms, but some we seem to.  chk dbxread. */
+/*FIXME*/              prim_record_misc_function (SYMBOL_NAME(p),
+                                                  SYMBOL_VALUE(p),
+                                                  misc_type);
+#endif
+               }
+       }
 
-          NOTE: The way we handle textlow/high is incorrect, but good
-          enough for a first approximation. The case we fail is on a
-          file "foo.c" that looks like
-               proc1() {...}
-               #include "bar.c"        -- this contains proc2()
-               proc3() {...}
-          where proc3() is attributed to bar.c.  But since this is a
-          dependent file it will cause loading of foo.c as well, so
-          everything will be fine at the end.  */
+       /* The array (of lists) of globals must be sorted. */
+       reorder_psymtabs();
 
-       prevhigh = &dummy;
+       /* Now sort the global psymbols.  */
        for (f_idx = 0; f_idx < hdr->ifdMax; f_idx++) {
                struct partial_symtab *pst = fdr_to_pst[f_idx].pst;
                if (pst->n_global_syms > 1)
                        qsort (global_psymbols.list + pst->globals_offset,
                                pst->n_global_syms, sizeof (struct partial_symbol),
                                compare_psymbols);
-               if (pst->textlow) {
-                       *prevhigh = pst->textlow;
-                       prevhigh = &pst->texthigh;
-               }
        }
 
        /* Mark the last code address, and remember it for later */
-       *prevhigh = END_OF_TEXT_SEGMENT(filhdr);
-       hdr->cbDnOffset = END_OF_TEXT_SEGMENT(filhdr);
+       hdr->cbDnOffset = end_of_text_seg;
 
-       reorder_psymtabs();
        free(&fdr_to_pst[-1]);
        fdr_to_pst = 0;
 }
@@ -1900,8 +1795,10 @@ parse_partial_symbols(hdr, incremental)
    of recursion we are called (to pretty up debug traces) */
 
 static struct partial_symtab *
-parse_fdr(f_idx, lev)
+parse_fdr(f_idx, lev, objfile)
        int f_idx;
+       int lev;
+       struct objfile *objfile;
 {
        register FDR *fh;
        register struct partial_symtab *pst;
@@ -1918,7 +1815,7 @@ parse_fdr(f_idx, lev)
                max_glevel = fh->glevel;
 
        /* Make a new partial_symtab */
-       pst = new_psymtab(fh->rss);
+       pst = new_psymtab(fh->rss, objfile);
        if (fh->cpd == 0){
                pst->textlow = 0;
                pst->texthigh = 0;
@@ -1926,9 +1823,9 @@ parse_fdr(f_idx, lev)
                pst->textlow = fh->adr;
                pst->texthigh = fh->cpd;        /* To be fixed later */
        }
-       /* Reverse mapping PST -> FDR */
-       pst->ldsymoff = f_idx;
 
+       /* Make everything point to everything. */
+       FDR_IDX(pst) = f_idx;
        fdr_to_pst[f_idx].pst = pst;
        fh->ioptBase = (int)pst;
 
@@ -1950,12 +1847,12 @@ parse_fdr(f_idx, lev)
        pst->number_of_dependencies = fh->crfd - s_id0;
        pst->dependencies = (struct partial_symtab **)
                obstack_alloc (psymbol_obstack,
-                              pst->number_of_dependencies * sizeof(char*));
+                                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;
 
-               pst->dependencies[s_idx-s_id0] = parse_fdr(*rh, lev+1);
-
+               pst->dependencies[s_idx-s_id0] = parse_fdr(*rh, lev+1, objfile);
        }
 
        return pst;
@@ -1964,10 +1861,14 @@ parse_fdr(f_idx, lev)
 
 /* Ancillary function to psymtab_to_symtab().  Does all the work
    for turning the partial symtab PST into a symtab, recurring
-   first on all dependent psymtabs */
+   first on all dependent psymtabs.  The argument FILENAME is
+   only passed so we can see in debug stack traces what file
+   is being read. */
 
-static void psymtab_to_symtab_1(pst)
+static void
+psymtab_to_symtab_1(pst, filename)
        struct partial_symtab *pst;
+       char *filename;
 {
        int             i, f_max;
        struct symtab  *st;
@@ -1985,32 +1886,44 @@ static void psymtab_to_symtab_1(pst)
        }
 
        /* How many symbols will we need */
+       /* FIXME, this does not count enum values. */
        f_max = pst->n_global_syms + pst->n_static_syms;
-       if (pst->ldsymoff == -1) {
+       if (FDR_IDX(pst) == -1) {
                fh = 0;
-               st = new_symtab( "unknown", f_max, 0);
+               st = new_symtab ("unknown", f_max, 0, pst->objfile);
        } else {
-               fh = (FDR *) (cur_hdr->cbFdOffset) + pst->ldsymoff;
+               fh = (FDR *) (cur_hdr->cbFdOffset) + FDR_IDX(pst);
                f_max += fh->csym + fh->cpd;
-               st = new_symtab(pst->filename, 2 * f_max, 2 * fh->cline);
+               st = new_symtab (pst->filename, 2 * f_max, 2 * fh->cline,
+                                pst->objfile);
        }
 
-       /*
-        * Read in all partial symbtabs on which this one is dependent.
-        * NOTE that we do have circular dependencies, sigh. 
-        */
+       /* 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) {
-                       /*
-                        * DO NOT inform about additional files that need to
-                        * be read in, it would only annoy the user.
-                        */
-                       psymtab_to_symtab_1(pst->dependencies[i]);
+                       /* Inform about additional files to be read in.  */
+                       if (info_verbose)
+                         {
+                           fputs_filtered (" ", stdout);
+                           wrap_here ("");
+                           fputs_filtered ("and ", stdout);
+                           wrap_here ("");
+                           printf_filtered ("%s...",
+                                            pst->dependencies[i]->filename);
+                           wrap_here ("");             /* Flush output */
+                           fflush (stdout);
+                         }
+                       /* We only pass the filename for debug purposes */
+                       psymtab_to_symtab_1(pst->dependencies[i], 
+                               pst->dependencies[i]->filename);
                }
 
        /* Now read the symbols for this symtab */
 
-       cur_fd = pst->ldsymoff;
+       cur_fd = FDR_IDX(pst);
        cur_fdr = fh;
        cur_stab = st;
 
@@ -2018,11 +1931,12 @@ static void psymtab_to_symtab_1(pst)
 
        push_parse_stack();
        top_stack->cur_st = cur_stab;
-       top_stack->cur_block = BLOCKVECTOR_BLOCK(BLOCKVECTOR(cur_stab), 0);
+       top_stack->cur_block = BLOCKVECTOR_BLOCK(BLOCKVECTOR(cur_stab),
+                                                STATIC_BLOCK);
        BLOCK_START(top_stack->cur_block) = fh ? fh->adr : 0;
        BLOCK_END(top_stack->cur_block) = 0;
        top_stack->blocktype = stFile;
-       top_stack->maxsyms = f_max;
+       top_stack->maxsyms = 2*f_max;
        top_stack->cur_type = 0;
        top_stack->procadr = 0;
        top_stack->numargs = 0;
@@ -2033,7 +1947,9 @@ static void psymtab_to_symtab_1(pst)
                                cur_hdr->cbDnOffset : fh[1].adr);
 
        /* .. 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->blocktype = stFile;
        top_stack->maxsyms = cur_hdr->isymMax + cur_hdr->ipdMax + cur_hdr->iextMax;
        for (i = 0; i < cur_hdr->iextMax; i++) {
@@ -2057,10 +1973,10 @@ static void psymtab_to_symtab_1(pst)
         * Sort the symbol table now, we are done adding symbols to it.
         */
        sort_symtab_syms(st);
-}
-
-
 
+       /* Now link the psymtab and the symtab.  */
+       pst->symtab = st;
+}
 \f
 /* Ancillary parsing procedures. */
 
@@ -2123,7 +2039,9 @@ cross_ref(rn, tpp, pname)
                                add_pending(fh, sh, *tpp);
                }
        }
-       return (rn->rfd == 0xfff);
+
+       /* We used one auxent normally, two if we got a "next one" rf. */
+       return (rn->rfd == 0xfff? 2: 1);
 }
 
 
@@ -2158,23 +2076,44 @@ mylookup_symbol (name, block, namespace, class)
 }
 
 
-/* Add a new symbol S to a block B */
+/* Add a new symbol S to a block B.
+   Infrequently, we will need to reallocate the block to make it bigger.
+   We only detect this case when adding to top_stack->cur_block, since
+   that's the only time we know how big the block is.  FIXME.  */
 
-static
+static void
 add_symbol(s,b)
        struct symbol *s;
        struct block *b;
 {
-       BLOCK_SYM(b,BLOCK_NSYMS(b)++) = s;
+       int nsyms = BLOCK_NSYMS(b)++;
+       struct block *origb;
+       struct parse_stack *stackp;
+
        if (b == top_stack->cur_block &&
-           BLOCK_NSYMS(b) > top_stack->maxsyms)
-               printf_filtered("Internal: block at @%x overfilled (by %d)\n",
-                       b, BLOCK_NSYMS(b) - top_stack->maxsyms);
+           nsyms >= top_stack->maxsyms) {
+               complain (&block_overflow_complaint, s->name);
+               /* In this case shrink_block is actually grow_block, since
+                  BLOCK_NSYMS(b) is larger than its current size.  */
+               origb = b;
+               b = shrink_block (top_stack->cur_block, top_stack->cur_st);
+
+               /* Now run through the stack replacing pointers to the
+                  original block.  shrink_block has already done this
+                  for the blockvector and BLOCK_FUNCTION.  */
+               for (stackp = top_stack; stackp; stackp = stackp->next) {
+                       if (stackp->cur_block == origb) {
+                               stackp->cur_block = b;
+                               stackp->maxsyms = BLOCK_NSYMS (b);
+                       }
+               }
+       }
+       BLOCK_SYM(b,nsyms) = s;
 }
 
 /* Add a new block B to a symtab S */
 
-static
+static void
 add_block(b,s)
        struct block *b;
        struct symtab *s;
@@ -2193,10 +2132,12 @@ add_block(b,s)
    MIPS' linenumber encoding might need more than one byte
    to describe it, LAST is used to detect these continuation lines */
 
-static 
+static int
 add_line(lt, lineno, adr, last)
        struct linetable *lt;
+       int lineno;
        CORE_ADDR adr;
+       int last;
 {
        if (last == 0)
                last = -2;      /* make sure we record first line */
@@ -2222,8 +2163,8 @@ compare_symtabs( s1, s2)
        /* "most specific" first */
 
        register struct block *b1, *b2;
-       b1 = BLOCKVECTOR_BLOCK(BLOCKVECTOR(*s1),0);
-       b2 = BLOCKVECTOR_BLOCK(BLOCKVECTOR(*s2),0);
+       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);
@@ -2282,7 +2223,7 @@ static int compare_blocks(b1,b2)
    Reorder the blocks in the blockvector by code-address,
    as required by some MI search routines */
 
-static
+static void
 sort_blocks(s)
        struct symtab *s;
 {
@@ -2290,8 +2231,10 @@ sort_blocks(s)
 
        if (BLOCKVECTOR_NBLOCKS(bv) <= 2) {
                /* Cosmetic */
-               if (BLOCK_END(BLOCKVECTOR_BLOCK(bv,0)) == 0)
-                       BLOCK_START(BLOCKVECTOR_BLOCK(bv,0)) = 0;
+               if (BLOCK_END(BLOCKVECTOR_BLOCK(bv,GLOBAL_BLOCK)) == 0)
+                       BLOCK_START(BLOCKVECTOR_BLOCK(bv,GLOBAL_BLOCK)) = 0;
+               if (BLOCK_END(BLOCKVECTOR_BLOCK(bv,STATIC_BLOCK)) == 0)
+                       BLOCK_START(BLOCKVECTOR_BLOCK(bv,STATIC_BLOCK)) = 0;
                return;
        }
        /*
@@ -2301,8 +2244,8 @@ sort_blocks(s)
         * to detect -O3 images in advance.
         */
        if (BLOCKVECTOR_NBLOCKS(bv) > 3)
-               qsort(&BLOCKVECTOR_BLOCK(bv,2),
-                     BLOCKVECTOR_NBLOCKS(bv) - 2,
+               qsort(&BLOCKVECTOR_BLOCK(bv,FIRST_LOCAL_BLOCK),
+                     BLOCKVECTOR_NBLOCKS(bv) - FIRST_LOCAL_BLOCK,
                      sizeof(struct block *),
                      compare_blocks);
 
@@ -2310,72 +2253,84 @@ sort_blocks(s)
                register CORE_ADDR high = 0;
                register int    i, j = BLOCKVECTOR_NBLOCKS(bv);
 
-               for (i = 2; i < j; i++)
+               for (i = FIRST_LOCAL_BLOCK; i < j; i++)
                        if (high < BLOCK_END(BLOCKVECTOR_BLOCK(bv,i)))
                                high = BLOCK_END(BLOCKVECTOR_BLOCK(bv,i));
-               BLOCK_END(BLOCKVECTOR_BLOCK(bv,0)) = high;
+               BLOCK_END(BLOCKVECTOR_BLOCK(bv,GLOBAL_BLOCK)) = high;
        }
 
-       BLOCK_START(BLOCKVECTOR_BLOCK(bv,0)) = BLOCK_START(BLOCKVECTOR_BLOCK(bv,2));
+       BLOCK_START(BLOCKVECTOR_BLOCK(bv,GLOBAL_BLOCK)) =
+               BLOCK_START(BLOCKVECTOR_BLOCK(bv,FIRST_LOCAL_BLOCK));
 
-       BLOCK_START(BLOCKVECTOR_BLOCK(bv,1)) = BLOCK_START(BLOCKVECTOR_BLOCK(bv,0));
-       BLOCK_END  (BLOCKVECTOR_BLOCK(bv,1)) = BLOCK_END  (BLOCKVECTOR_BLOCK(bv,0));
+       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));
 }
 
 /* Sort the symtab list, as required by some search procedures.
    We want files ordered to make them look right to users, and for
    searching (see block_for_pc).  */
 
-static
+static void
 reorder_symtabs()
 {
        register int i;
        struct symtab *stab;
-       struct symtab **all_symtabs = (struct symtab **)
-               obstack_alloc (psymbol_obstack,
-                               all_symtabs_count * sizeof (struct symtab *));
+       register struct symtab **all_symtabs;
+       register int symtab_count;
+
+       if (!symtab_list)
+               return;
 
        /* Create an array of pointers to all the symtabs.  */
-       for (i = 0, stab = symtab_list;
-            i < all_symtabs_count;
-            i++, stab = stab->next) {
-               all_symtabs[i] = stab;
-               /* FIXME: Only do this for new symtabs ??? */
-               sort_blocks(all_symtabs[i]);
+       for (symtab_count = 0, stab = symtab_list;
+            stab;
+            symtab_count++, stab = stab->next) {
+               obstack_grow (psymbol_obstack, &stab, sizeof (stab));
+               /* FIXME: Only sort blocks for new symtabs ??? */
+               sort_blocks(stab);
        }
 
-       qsort(all_symtabs, all_symtabs_count,
+       all_symtabs = (struct symtab **)
+               obstack_base (psymbol_obstack);
+       qsort((char *)all_symtabs, symtab_count,
                sizeof(struct symtab *), compare_symtabs);
 
        /* Re-construct the symtab list, but now it is sorted.  */
-       for (i = 0; i < all_symtabs_count-1; i++)
+       for (i = 0; i < symtab_count-1; i++)
                all_symtabs[i]->next = all_symtabs[i+1];
        all_symtabs[i]->next = 0;
        symtab_list = all_symtabs[0];
+
        obstack_free (psymbol_obstack, all_symtabs);
 }
 
-/* Sort the partial symtab list, as required by some search procedures */
+/* Sort the partial symtab list, as required by some search procedures.
+   PC lookups stop at the first psymtab such that textlow <= PC < texthigh */
 
-static reorder_psymtabs()
+static void
+reorder_psymtabs()
 {
        register int i;
+       register int all_psymtabs_count;
        struct partial_symtab *pstab;
+       struct partial_symtab **all_psymtabs;
+
+       if (!partial_symtab_list)
+               return;
 
-       /*
-        * PC lookups stop at the first psymtab such that
-        *      textlow <= PC < texthigh 
-        */
        /* Create an array of pointers to all the partial_symtabs.  */
-       struct partial_symtab **all_psymtabs = (struct partial_symtab **)
-         obstack_alloc (psymbol_obstack,
-                        all_psymtabs_count*sizeof(struct partial_symtab*));
-       for (i = 0, pstab = partial_symtab_list;
-            i < all_psymtabs_count;
-            i++, pstab = pstab->next)
-         all_psymtabs[i] = pstab;
-
-       qsort(all_psymtabs, all_psymtabs_count,
+
+       for (all_psymtabs_count = 0, pstab = partial_symtab_list;
+            pstab;
+            all_psymtabs_count++, pstab = pstab->next)
+         obstack_grow (psymbol_obstack, &pstab, sizeof (pstab));
+
+       all_psymtabs = (struct partial_symtab **)
+                obstack_base (psymbol_obstack);
+
+       qsort((char *)all_psymtabs, all_psymtabs_count,
                sizeof(struct partial_symtab *), compare_psymtabs);
 
        /* Re-construct the partial_symtab_list, but now it is sorted.  */
@@ -2387,8 +2342,6 @@ static reorder_psymtabs()
 
        obstack_free (psymbol_obstack, all_psymtabs);
 }
-
-
 \f
 /* Constructor/restructor/destructor procedures */
 
@@ -2397,22 +2350,19 @@ static reorder_psymtabs()
 
 static
 struct symtab *
-new_symtab(name, maxsyms, maxlines)
+new_symtab(name, maxsyms, maxlines, objfile)
        char *name;
 {
-       struct symtab *s = (struct symtab *) xzalloc(sizeof(struct symtab));
-       int i;
+       struct symtab *s = allocate_symtab (name, objfile);
 
        LINETABLE(s) = new_linetable(maxlines);
 
-       s->filename = name;
-
        /* All symtabs must have at least two blocks */
        BLOCKVECTOR(s) = new_bvect(2);
-       BLOCKVECTOR_BLOCK(BLOCKVECTOR(s), 0) = new_block(maxsyms);
-       BLOCKVECTOR_BLOCK(BLOCKVECTOR(s), 1) = new_block(maxsyms);
-       BLOCK_SUPERBLOCK( BLOCKVECTOR_BLOCK(BLOCKVECTOR(s),1)) =
-               BLOCKVECTOR_BLOCK(BLOCKVECTOR(s), 0);
+       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);
 
        s->free_code = free_linetable;
 
@@ -2420,30 +2370,15 @@ new_symtab(name, maxsyms, maxlines)
        s->next = symtab_list;
        symtab_list = s;
 
-       all_symtabs_count++;
-
        return s;
 }
 
-/* Cleanup before loading a fresh image */
-
-static destroy_all_symtabs()
-{
-  if (symfile)
-    free(symfile);
-  symfile = 0;
-
-  free_all_symtabs();
-  all_symtabs_count = 0;
-  current_source_symtab = 0;
-  /* psymtabs! */
-}
-
 /* Allocate a new partial_symtab NAME */
 
 static struct partial_symtab *
-new_psymtab(name)
+new_psymtab(name, objfile)
        char *name;
+       struct objfile *objfile;
 {
        struct partial_symtab *pst;
 
@@ -2456,12 +2391,18 @@ new_psymtab(name)
        else
                pst->filename = name;
 
+       /* 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;
-       all_psymtabs_count++;
 
-       /* Keep a backpointer to the file`s symbols */
-       pst->ldsymlen = (int)cur_hdr;
+       /* 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;
 
        /* The way to turn this into a symtab is to call... */
        pst->read_symtab = mipscoff_psymtab_to_symtab;
@@ -2470,25 +2411,6 @@ new_psymtab(name)
 }
 
 
-/* Allocate a new NAME psymbol from LIST, extending it if necessary.
-   The psymbol belongs to the psymtab at index PST_IDX */
-
-static struct partial_symbol *
-new_psymbol(list, name, pst_idx)
-       struct psymbol_allocation_list *list;
-       char *name;
-{
-       struct partial_symbol *p;
-       struct partial_symtab *pst = fdr_to_pst[pst_idx].pst;
-
-       /* Lists are pre-sized, we won`t overflow */
-
-       p = list->list + pst->globals_offset + pst->n_global_syms++;
-       SYMBOL_NAME(p) = name;
-       return p;
-}
-
-
 /* Allocate a linetable array of the given SIZE */
 
 static
@@ -2505,7 +2427,8 @@ struct linetable *new_linetable(size)
 /* Oops, too big. Shrink it.  This was important with the 2.4 linetables,
    I am not so sure about the 3.4 ones */
 
-static shrink_linetable(s)
+static void
+shrink_linetable(s)
        struct symtab *s;
 {
        struct linetable *l = new_linetable(LINETABLE(s)->nitems);
@@ -2519,7 +2442,8 @@ static shrink_linetable(s)
 /* Allocate and zero a new blockvector of NBLOCKS blocks. */
 
 static
-struct blockvector *new_bvect(nblocks)
+struct blockvector *
+new_bvect(nblocks)
 {
        struct blockvector *bv;
        int size;
@@ -2535,7 +2459,8 @@ struct blockvector *new_bvect(nblocks)
 /* Allocate and zero a new block of MAXSYMS symbols */
 
 static
-struct block *new_block(maxsyms)
+struct block *
+new_block(maxsyms)
 {
        int size = sizeof(struct block) + (maxsyms-1) * sizeof(struct symbol *);
        struct block *b = (struct block *)xzalloc(size);
@@ -2543,7 +2468,8 @@ struct block *new_block(maxsyms)
        return b;
 }
 
-/* Ooops, too big. Shrink block B in symtab S to its minimal size */
+/* Ooops, too big. Shrink block B in symtab S to its minimal size.
+   Shrink_block can also be used by add_symbol to grow a block.  */
 
 static struct block *
 shrink_block(b, s)
@@ -2554,23 +2480,20 @@ shrink_block(b, s)
        struct blockvector *bv = BLOCKVECTOR(s);
        int i;
 
-       /* Just get a new one, copy, and fix references to the old one */
+       /* Just reallocate it and fix references to the old one */
 
-       new = (struct block *)xmalloc(sizeof(struct block) +
+       new = (struct block *) xrealloc ((char *)b, sizeof(struct block) +
                (BLOCK_NSYMS(b)-1) * sizeof(struct symbol *));
 
-       bcopy(b, new, sizeof(*new) + (BLOCK_NSYMS(b) - 1) * sizeof(struct symbol*));
-
        /* Should chase pointers to old one.  Fortunately, that`s just
           the block`s function and inferior blocks */
-       if (BLOCK_FUNCTION(b) && SYMBOL_BLOCK_VALUE(BLOCK_FUNCTION(b)) == b)
-               SYMBOL_BLOCK_VALUE(BLOCK_FUNCTION(b)) = new;
+       if (BLOCK_FUNCTION(new) && SYMBOL_BLOCK_VALUE(BLOCK_FUNCTION(new)) == b)
+               SYMBOL_BLOCK_VALUE(BLOCK_FUNCTION(new)) = new;
        for (i = 0; i < BLOCKVECTOR_NBLOCKS(bv); i++)
                if (BLOCKVECTOR_BLOCK(bv,i) == b)
                        BLOCKVECTOR_BLOCK(bv,i) = new;
                else if (BLOCK_SUPERBLOCK(BLOCKVECTOR_BLOCK(bv,i)) == b)
                        BLOCK_SUPERBLOCK(BLOCKVECTOR_BLOCK(bv,i)) = new;
-       free(b);
        return new;
 }
 
@@ -2600,6 +2523,7 @@ new_type(name)
                obstack_alloc (symbol_obstack, sizeof (struct type));
 
        bzero (t, sizeof (*t));
+       TYPE_VPTR_FIELDNO (t) = -1;
        TYPE_NAME(t) = name;
        return t;
 }
@@ -2617,19 +2541,41 @@ make_type(code, length, uns, 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;
 
        return type;
 }
 
+/* Create and initialize a new struct or union type, a la make_type.  */
+
+static
+struct type *
+make_struct_type(code, length, uns, name)
+     enum type_code code;
+     int length, uns;
+     char *name;
+{
+       register struct type *type;
+
+       type = make_type (code, length, uns, name);
+       
+       /* FIXME, I don't think this ever gets freed.  */
+       TYPE_CPLUS_SPECIFIC (type) = (struct cplus_struct_type *)
+         xzalloc (sizeof (struct cplus_struct_type));
+       return type;
+}
+
 /* Allocate a new field named NAME to the type TYPE */
 
 static
-struct field *new_field(type,name)
+struct field *
+new_field(type,name)
        struct type *type;
        char *name;
 {
@@ -2640,11 +2586,11 @@ struct field *new_field(type,name)
                TYPE_FIELDS(type) = (struct field*)xrealloc(TYPE_FIELDS(type),
                        (TYPE_NFIELDS(type)+1) * sizeof(struct field));
        else
-               TYPE_FIELDS(type) = (struct field*)xzalloc(2*sizeof(struct field));
-       f = &(TYPE_FIELD(type,TYPE_NFIELDS(type)++));
+               TYPE_FIELDS(type) = (struct field*)xzalloc(sizeof(struct field));
+       f = &(TYPE_FIELD(type,TYPE_NFIELDS(type)));
+       TYPE_NFIELDS(type)++;
        bzero(f, sizeof(struct field));
-       if (name)
-               f->name = name;
+       f->name = name;         /* Whether or not NAME is zero, this works. */
        return f;
 }
 
@@ -2702,7 +2648,8 @@ mips_create_dummy_symbol(end_pc, size, nargs, framesize)
        BLOCK_START(bl) = end_pc - size;
        BLOCK_END(bl) = end_pc;
 
-       BLOCK_SUPERBLOCK(bl) = BLOCKVECTOR_BLOCK(BLOCKVECTOR(dummy_symtab),0);
+       BLOCK_SUPERBLOCK(bl) =
+               BLOCKVECTOR_BLOCK(BLOCKVECTOR(dummy_symtab),GLOBAL_BLOCK);
        add_block(bl, dummy_symtab);
        sort_blocks(dummy_symtab);
 
@@ -2742,7 +2689,7 @@ mips_destroy_dummy_symbol(end_pc)
        free(SYMBOL_VALUE(BLOCK_SYM(bl,0)));
        free(BLOCK_SYM(bl,0));
 
-       for (i = 2; i < BLOCKVECTOR_NBLOCKS(bv); i++)
+       for (i = FIRST_LOCAL_BLOCK; i < BLOCKVECTOR_NBLOCKS(bv); i++)
                if (BLOCKVECTOR_BLOCK(bv,i) == bl)
                        break;
        for (; i < BLOCKVECTOR_NBLOCKS(bv) - 1; i++)
@@ -2839,24 +2786,17 @@ fixup_sigtramp()
 
        BLOCK_SYM(b,BLOCK_NSYMS(b)++) = s;
 }
-
 \f
 /* Initialization */
 
 static struct sym_fns ecoff_sym_fns = {"ecoff", 5,
                mipscoff_new_init, mipscoff_symfile_init,
-               mipscoff_symfile_read, mipscoff_symfile_discard};
+               mipscoff_symfile_read};
 
 _initialize_mipsread ()
 {
        add_symtab_fns (&ecoff_sym_fns);
 
-       bzero (&global_psymbols, sizeof (global_psymbols));
-       bzero (&static_psymbols, sizeof (static_psymbols));
-
-       add_com("add-file", class_files, add_file_command,
-               "Add a new symbol table (in mips format) from file FILE.");
-
        /* Missing basic types */
        builtin_type_string = make_type(TYPE_CODE_PASCAL_ARRAY,
                                        1, 0, "string");
@@ -2868,12 +2808,4 @@ _initialize_mipsread ()
                                           0, "fixed_decimal");
        builtin_type_float_dec = make_type(TYPE_CODE_FLT, sizeof(double),
                                           0, "floating_decimal");
-
-       /* Templates types */
-       builtin_type_ptr = lookup_pointer_type (builtin_type_void);
-       builtin_type_struct = make_type(TYPE_CODE_STRUCT, 0, 0, 0);
-       builtin_type_union = make_type(TYPE_CODE_UNION, 0, 0, 0);
-       builtin_type_enum = make_type(TYPE_CODE_ENUM, 0, 0, 0);
-       builtin_type_range = make_type(TYPE_CODE_RANGE, 0, 0, 0);
-       builtin_type_set = make_type(TYPE_CODE_SET, 0, 0, 0);
 }