[gnu.gdb.bug] Fixes for SegFaults in GDB 3.1.2

rfg@MCC.COM (Ron Guilmette) (05/13/89)

We here have recently noted a number of cases in which GDB 3.1.2 will
segfault.  Fixes are provided below.  Many/most of these cases appear
to be cases in which the user has tried to do something (e.g. list,
print, etc.) some member (data or function member, or especially a
non-existant member) of some derived class.  There were also some
other cases in which Segfaults occured but I cannot recall the precise
details now.

Anyway, I tracked down the problems to two causes.  First, it
seems that in 3.1.2, each symbol table record which describes
a "struct" (or a class) has a pointer to an array of pointers
to records which describe each of the fields of the "struct".
These arrays of pointers to the field descriptors are used all
over to search for particular field names.  The unfortunate
fact however is that the initial part of each of these lists
now contains a set of pointers to records which describe
BASE CLASSES (only for derived classes of course).  These
pointers can sometime point to records (for base classes)
which have NULL name fields.  Thus, when an attempt is made
to call strcmp() to see if these names match a given field
name (which is being searched for) WACKO!  SegFault.

The apparent solution is that, when GDB is searching for a matching
field name, it should not be looking at the initial parts of
these lists (i.e. the parts corresponding to the base classes).
The following patches implement this fix.

Another problem relates to the use of the TYPE_MAIN_VARIANT()
macro.  It seem that some symbol table records are *not* getting
their main_variant field filled in when they are created.  Thus
in some symbol table records, this field is left NULL.  This
was causing segfaults also because one part of the code was
assuming that these fields were never null.

It seems that the value which is typically used as a default for
the main_variant field is a pointer to the record containing
the field itself (i.e. the "main_variant" of a type is normally
the type itself).  Knowing that, I kludged around the segfaults
caused by NULL main_variant fields simply by making that part
of the code use a pointer to the type itself if the main_variant
field was/is NULL.

Also in the patches given below are some minor changes to the
way derived classes are formatted and displayed.  Some other
minor cleanups in symtab.c are also included.

Enjoy,

// Ron Guilmette  -  MCC  -  Experimental Systems Kit Project
// 3500 West Balcones Center Drive,  Austin, TX  78759  -  (512)338-3740
// ARPA: rfg@mcc.com
// UUCP: {rutgers,uunet,gatech,ames,pyramid}!cs.utexas.edu!pp!rfg


diff -rc2 3.1.2-/dbxread.c 3.1.2+/dbxread.c
*** 3.1.2-/dbxread.c	Wed Mar 22 17:02:39 1989
--- 3.1.2+/dbxread.c	Fri May 12 17:25:40 1989
***************
*** 4171,4183 ****
  	      if (TYPE_FIELD_NAME (t, 0) == 0)
  		TYPE_VPTR_FIELDNO (type) = i = 0;
! 	      else for (i = TYPE_NFIELDS (t) - 1; i >= 0; --i)
! 		if (! strncmp (TYPE_FIELD_NAME (t, i), *pp,
! 			       strlen (TYPE_FIELD_NAME (t, i))))
! 		  {
! 		    TYPE_VPTR_FIELDNO (type) = i;
! 		    break;
! 		  }
! 	      if (i < 0)
! 		error ("virtual function table field not found");
  	    }
  	  else
--- 4171,4190 ----
  	      if (TYPE_FIELD_NAME (t, 0) == 0)
  		TYPE_VPTR_FIELDNO (type) = i = 0;
! 	      else
! 		{
! 		  int found = 0;
! 
! 		  for (i = TYPE_NFIELDS (t) - 1; i > TYPE_N_BASECLASSES (t); --i)
! 		    if (TYPE_FIELD_NAME (t, i)
! 		      && (! strncmp (TYPE_FIELD_NAME (t, i), *pp,
! 			       strlen (TYPE_FIELD_NAME (t, i)))))
! 		    {
! 		      TYPE_VPTR_FIELDNO (type) = i;
! 		      found = -1;
! 		      break;
! 		    }
! 	          if (!found)
! 		    error ("vtable field not found for class %s", TYPE_NAME (t));
! 		}
  	    }
  	  else
diff -rc2 3.1.2-/symtab.c 3.1.2+/symtab.c
*** 3.1.2-/symtab.c	Sat Mar 18 21:55:43 1989
--- 3.1.2+/symtab.c	Fri May 12 15:32:20 1989
***************
*** 438,445 ****
  {
    int i;
    for (i = TYPE_N_BASECLASSES (type); i > 0; i--)
      {
-       if (TYPE_FLAGS (type) & TYPE_FLAG_BASE_MEMBERS_FILLED)
- 	return;
        if (TYPE_FIELD_NAME (type, i - 1) == 0)
  	TYPE_FIELD_NAME (type, i - 1) = TYPE_NAME (TYPE_MAIN_VARIANT (TYPE_BASECLASS (type, i)));
--- 438,445 ----
  {
    int i;
+   if (TYPE_FLAGS (type) & TYPE_FLAG_BASE_MEMBERS_FILLED)
+     return;
    for (i = TYPE_N_BASECLASSES (type); i > 0; i--)
      {
        if (TYPE_FIELD_NAME (type, i - 1) == 0)
  	TYPE_FIELD_NAME (type, i - 1) = TYPE_NAME (TYPE_MAIN_VARIANT (TYPE_BASECLASS (type, i)));
***************
*** 595,599 ****
    TYPE_CODE (type) = TYPE_CODE_METHOD;
  
!   TYPE_MAIN_VARIANT (type) = lookup_method_type (domain, to_type, args);
  }
  
--- 595,599 ----
    TYPE_CODE (type) = TYPE_CODE_METHOD;
  
!   TYPE_MAIN_VARIANT (type) = lookup_method_type (to_type, domain, args);
  }
  
***************
*** 1338,1342 ****
  	      sym = 0;
  	      i1 = 0;		/*  counter for the symbol array */
! 	      t = TYPE_MAIN_VARIANT (SYMBOL_TYPE (sym_class));
  	      sym_arr = (struct symbol **) alloca (TYPE_NFN_FIELDS_TOTAL (t) * sizeof(struct symbol*));
  	      physnames = (char **) alloca (TYPE_NFN_FIELDS_TOTAL (t) * sizeof(char*));
--- 1338,1344 ----
  	      sym = 0;
  	      i1 = 0;		/*  counter for the symbol array */
! 	      if (TYPE_MAIN_VARIANT (t = SYMBOL_TYPE (sym_class)))
! 		  t = TYPE_MAIN_VARIANT (t);
! 
  	      sym_arr = (struct symbol **) alloca (TYPE_NFN_FIELDS_TOTAL (t) * sizeof(struct symbol*));
  	      physnames = (char **) alloca (TYPE_NFN_FIELDS_TOTAL (t) * sizeof(char*));
***************
*** 1354,1358 ****
  	      else while (t)
  		{
! 		  class_name = TYPE_NAME (TYPE_MAIN_VARIANT (t));
  		  while (*class_name++ != ' ');
  
--- 1356,1361 ----
  	      else while (t)
  		{
! 		  if (! (class_name = TYPE_NAME (t)))
! 		    goto decend_to_first_base;
  		  while (*class_name++ != ' ');
  
***************
*** 1379,1382 ****
--- 1382,1386 ----
  			  }
  		    }
+ decend_to_first_base:
  		  if (TYPE_N_BASECLASSES (t))
  		    t = TYPE_BASECLASS(t, 1);
diff -rc2 3.1.2-/valops.c 3.1.2+/valops.c
*** 3.1.2-/valops.c	Wed Mar 22 16:32:41 1989
--- 3.1.2+/valops.c	Fri May 12 16:41:31 1989
***************
*** 787,791 ****
        while (t)
  	{
! 	  for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--)
  	    {
  	      if (!strcmp (TYPE_FIELD_NAME (t, i), name))
--- 787,791 ----
        while (t)
  	{
! 	  for (i = TYPE_NFIELDS (t) - 1; i > TYPE_N_BASECLASSES (t); i--)
  	    {
  	      if (!strcmp (TYPE_FIELD_NAME (t, i), name))
***************
*** 796,800 ****
  	    }
  
! 	  if (i >= 0)
  	    {
  	      if (TYPE_FIELD_STATIC (t, i))
--- 796,800 ----
  	    }
  
! 	  if (found)
  	    {
  	      if (TYPE_FIELD_STATIC (t, i))
***************
*** 901,905 ****
        while (t)
  	{
! 	  for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--)
  	    {
  	      if (!strcmp (TYPE_FIELD_NAME (t, i), name))
--- 901,905 ----
        while (t)
  	{
! 	  for (i = TYPE_NFIELDS (t) - 1; i > TYPE_N_BASECLASSES (t); i--)
  	    {
  	      if (!strcmp (TYPE_FIELD_NAME (t, i), name))
***************
*** 910,914 ****
  	    }
  
! 	  if (i >= 0)
  	    {
  	      if (TYPE_FIELD_STATIC (t, i))
--- 910,914 ----
  	    }
  
! 	  if (found)
  	    {
  	      if (TYPE_FIELD_STATIC (t, i))
***************
*** 995,999 ****
    while (t)
      {
!       for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--)
  	{
  	  if (!strcmp (TYPE_FIELD_NAME (t, i), name))
--- 995,999 ----
    while (t)
      {
!       for (i = TYPE_NFIELDS (t) - 1; i > TYPE_N_BASECLASSES (t); i--)
  	{
  	  if (!strcmp (TYPE_FIELD_NAME (t, i), name))
***************
*** 1060,1064 ****
    while (t)
      {
!       for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--)
  	{
  	  if (!strcmp (TYPE_FIELD_NAME (t, i), name))
--- 1060,1064 ----
    while (t)
      {
!       for (i = TYPE_NFIELDS (t) - 1; i > TYPE_N_BASECLASSES (t); i--)
  	{
  	  if (!strcmp (TYPE_FIELD_NAME (t, i), name))
diff -rc2 3.1.2-/valprint.c 3.1.2+/valprint.c
*** 3.1.2-/valprint.c	Mon Mar 20 07:25:28 1989
--- 3.1.2+/valprint.c	Fri May 12 16:13:45 1989
***************
*** 398,402 ****
  	for (i = 1; i <= n_baseclasses; i++)
  	  {
! 	    fprintf (stream, "\n<%s> = ", TYPE_NAME (TYPE_MAIN_VARIANT (TYPE_BASECLASS (type, i))));
  	    val_print (TYPE_FIELD_TYPE (type, 0),
  		       valaddr + TYPE_FIELD_BITPOS (type, i-1) / 8,
--- 398,402 ----
  	for (i = 1; i <= n_baseclasses; i++)
  	  {
! 	    fprintf (stream, "<BASE %s> = ", TYPE_NAME (TYPE_MAIN_VARIANT (TYPE_BASECLASS (type, i))));
  	    val_print (TYPE_FIELD_TYPE (type, 0),
  		       valaddr + TYPE_FIELD_BITPOS (type, i-1) / 8,
***************
*** 403,407 ****
  		       0, stream, 0, 0);
  	  }
! 	if (i > 1) fprintf (stream, "\nmembers of %s: ", TYPE_NAME (type));
  	for (i -= 1; i < len; i++)
  	  {
--- 403,408 ----
  		       0, stream, 0, 0);
  	  }
!         if (n_baseclasses > 0)
! 	  fprintf (stream, ", ");
  	for (i -= 1; i < len; i++)
  	  {
diff -rc2 3.1.2-/values.c 3.1.2+/values.c
*** 3.1.2-/values.c	Sun Mar 19 09:56:03 1989
--- 3.1.2+/values.c	Fri May 12 16:31:45 1989
***************
*** 695,699 ****
  	{
  	  int i;
! 	  for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--)
  	    if (! strcmp (TYPE_FIELD_NAME (t, i), fieldname))
  	      {
--- 695,699 ----
  	{
  	  int i;
! 	  for (i = TYPE_NFIELDS (t) - 1; i > TYPE_N_BASECLASSES (t); i--)
  	    if (! strcmp (TYPE_FIELD_NAME (t, i), fieldname))
  	      {