diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index c64bcf1c3f2..3759d21fb5e 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,14 @@
+Mon Mar 30 16:50:43 1992  Stu Grossman  (grossman at cygnus.com)
+
+	* mipsread.c (parse_symbol, parse_procedure):  Re-do the way that
+	.gdbinfo. symbols are created.  Move creation from parse_procedure
+	to parse_symbol, where it is fairly easy to grow the symtab.  This
+	also fixes a symtab trashing bug on all mips-based systems.
+	* (got_numargs, lookup_numargs, free_numargs):  Delete.  Not
+	needed anymore.
+	* tm-mips.h, tm-iris3.h, mips-tdep.c, mipsread.c:  Re-do struct
+	mips_extra_func_info, and all the PROC_xxx macros that look at it.
+
 Mon Mar 30 14:17:53 1992  Per Bothner  (bothner@cygnus.com)
 
 	* c-exp.y:  Add missing return type to yyparse() prototype.
diff --git a/gdb/mipsread.c b/gdb/mipsread.c
index f5fae21596d..96e6b67d239 100644
--- a/gdb/mipsread.c
+++ b/gdb/mipsread.c
@@ -60,15 +60,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include <sys/param.h>
 #include <sys/file.h>
 #include <sys/stat.h>
-#ifdef	CMUCS
-#include <mips/syms.h>
-#else /* not CMUCS */
-#ifndef LANGUAGE_C
-#define	LANGUAGE_C
-#endif
-#include "symconst.h"
-#include "sym.h"
-#endif /* not CMUCS */
 
 #include "coff/mips.h"
 #include "libaout.h"		/* FIXME Secret internal BFD stuff for a.out */
@@ -843,57 +834,6 @@ free_pending(f_idx)
 	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 */
-/* FIXME -- storage leak.  This is never called!  --gnu */
-
-static void
-free_numargs()
-{
-	struct numarg  *n = numargs_list, *m;
-
-	while (n) {
-		m = n->next;
-		free((PTR)n);
-		n = m;
-	}
-	numargs_list = 0;
-}
-
 char*
 prepend_tag_kind(tag_name, type_code)
      char *tag_name;
@@ -1144,6 +1084,9 @@ data:		/* Common code for symbols describing data */
 				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)
@@ -1256,11 +1199,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);
 
@@ -1615,7 +1572,7 @@ upgrade_type(tpp, tq, ax, bigend)
    of local symbols, and we have to cope with them here.
    The procedure's code ends at BOUND */
 
-static
+static void
 parse_procedure(pr, bound)
 	PDR *pr;
 {
@@ -1626,17 +1583,6 @@ parse_procedure(pr, bound)
 	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);
@@ -1666,8 +1612,15 @@ parse_procedure(pr, bound)
 		BLOCK_SUPERBLOCK(b) = top_stack->cur_block;
 		add_block(b, top_stack->cur_st);
 	}
-	e->isym = (long)s;
-	add_symbol(i,b);
+
+	s = mylookup_symbol(".gdbinfo.", b, LABEL_NAMESPACE, LOC_CONST);
+
+	if (s)
+	  {
+	    e = (struct mips_extra_func_info *)SYMBOL_VALUE(s);
+	    e->pdr = *pr;
+	    e->pdr.isym = (long)s;
+	  }
 }
 
 /* Parse the external symbol ES. Just call parse_symbol() after
@@ -2052,6 +2005,9 @@ parse_partial_symbols(end_of_text_seg, objfile)
 		      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),
@@ -2940,14 +2896,14 @@ 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.");
diff --git a/gdb/tm-irix3.h b/gdb/tm-irix3.h
index 2a99f62b307..df3b0546cdb 100644
--- a/gdb/tm-irix3.h
+++ b/gdb/tm-irix3.h
@@ -1,5 +1,5 @@
 /* Target machine description for SGI Iris under Irix, for GDB.
-   Copyright 1990, 1991 Free Software Foundation, Inc.
+   Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
 
 This file is part of GDB.
 
@@ -17,6 +17,12 @@ You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
+#ifndef LANGUAGE_C
+#define LANGUAGE_C
+#endif
+#include <sym.h>
+#include <symconst.h>
+
 #define TARGET_BYTE_ORDER BIG_ENDIAN
 
 /* Floating point is IEEE compliant */
@@ -296,20 +302,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
    mipsread.c (ab)uses this to save memory */
 
 typedef struct mips_extra_func_info {
-	unsigned long	adr;	/* memory address of start of procedure */
-	long	isym;		/* pointer to procedure symbol */
-	long	pad2;		/* iline: start of line number entries*/
-	long	regmask;	/* save register mask */
-	long	regoffset;	/* save register offset */
 	long	numargs;	/* number of args to procedure (was iopt) */
-	long	fregmask;	/* save floating point register mask */
-	long	fregoffset;	/* save floating point register offset */
-	long	framesize;	/* frameoffset: frame size */
-	short	framereg;	/* frame pointer register */
-	short	pcreg;		/* offset or reg of return pc */
-	long	lnLow;		/* lowest line in the procedure */
-	long	lnHigh;		/* highest line in the procedure */
-	long	pad3;		/* cbLineOffset: byte offset for this procedure from the fd base */
+	PDR	pdr;		/* Procedure descriptor record */
 } *mips_extra_func_info_t;
 
 #define EXTRA_FRAME_INFO \
diff --git a/gdb/tm-mips.h b/gdb/tm-mips.h
index 0716c9faf1e..f7a5cd0c3f3 100644
--- a/gdb/tm-mips.h
+++ b/gdb/tm-mips.h
@@ -19,6 +19,12 @@ You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
+#ifndef LANGUAGE_C
+#define LANGUAGE_C
+#endif
+#include <sym.h>
+#include <symconst.h>
+
 #if !defined (TARGET_BYTE_ORDER)
 #define TARGET_BYTE_ORDER LITTLE_ENDIAN
 #endif
@@ -320,20 +326,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
    mipsread.c (ab)uses this to save memory */
 
 typedef struct mips_extra_func_info {
-	unsigned long	adr;	/* memory address of start of procedure */
-	long	isym;		/* pointer to procedure symbol */
-	long	pad2;		/* iline: start of line number entries*/
-	long	regmask;	/* save register mask */
-	long	regoffset;	/* save register offset */
 	long	numargs;	/* number of args to procedure (was iopt) */
-	long	fregmask;	/* save floating point register mask */
-	long	fregoffset;	/* save floating point register offset */
-	long	framesize;	/* frameoffset: frame size */
-	short	framereg;	/* frame pointer register */
-	short	pcreg;		/* offset or reg of return pc */
-	long	lnLow;		/* lowest line in the procedure */
-	long	lnHigh;		/* highest line in the procedure */
-	long	pad3;		/* cbLineOffset: byte offset for this procedure from the fd base */
+	PDR	pdr;		/* Procedure descriptor record */
 } *mips_extra_func_info_t;
 
 #define EXTRA_FRAME_INFO \