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)) {