From bcccec8c8d084669c7469b8578448fa18ddbe2f3 Mon Sep 17 00:00:00 2001 From: Per Bothner Date: Sat, 26 Oct 1991 02:05:14 +0000 Subject: [PATCH] Various fixes to improve g++ debugging. See ChangeLog. --- gdb/ChangeLog | 25 ++++++++++++++++++ gdb/dbxread.c | 45 ++++++++++++++++++++----------- gdb/symtab.c | 62 +++++++++++++++++++++++++++++-------------- gdb/symtab.h | 12 +++++---- gdb/valprint.c | 17 +++--------- gdb/values.c | 72 ++++++++++++++++++++------------------------------ 6 files changed, 135 insertions(+), 98 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 89099cd8559..139a92433a0 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,28 @@ +Fri Oct 25 18:59:32 1991 Per Bothner (bothner at cygnus.com) + + Various fixes to improve g++ debugging. + * symtab.h: Add is_const and is_volatile flags for each method. + These are bit fields - take their space from voffset, + which shrinks to 30 bits. Since voffset is now a bitfield, + make it unsigned for portability. This changes its interpretation + slightly: Static methods now have voffset 1 instead of -1, + and virtual offsets start at 2, not 1. + * symtab.c: Renamed gdb_mangle_typename to gdb_mangle_name, + since it now returns an entire magled method name, not just + the type part. This avoids some duplication. + It also allows us to correctly mangle const and volatile + methods (using the new is_const and is_volatile bit fields + mentioned above). + * valprint.c (type_print_base), values.c (check_stub_method): + Simplify by using new gdb_mangle_name. + * values.c (value_headof): Fix to correctly handle single + inheritance (actually two fixes, either of which suffices). + * dbxread.c (read_struct_type): Handle const and volatile + method specifiers. + * dbxread.c (read_struct_type): Yet one more place where + we must handle '\\' continuations. + * valprint.c (vtbl_ptr_name): Add final '\0'. + Fri Oct 25 16:06:38 1991 Stu Grossman (grossman at cygnus.com) * tm-sparc.h, tm-68k.h (EXTRACT_RETURN_VALUE): fix output of diff --git a/gdb/dbxread.c b/gdb/dbxread.c index dbb786a9ae8..7fb59c7f0c1 100644 --- a/gdb/dbxread.c +++ b/gdb/dbxread.c @@ -4628,21 +4628,33 @@ read_struct_type (pp, type) *pp = p + 1; new_sublist->visibility = *(*pp)++ - '0'; if (**pp == '\\') *pp = next_symbol_text (); - /* FIXME-tiemann: need to add const/volatile info - to the methods. For now, just skip the char. - In future, here's what we need to implement: - - A for normal functions. - B for `const' member functions. - C for `volatile' member functions. - D for `const volatile' member functions. */ - if (**pp == 'A' || **pp == 'B' || **pp == 'C' || **pp == 'D') - (*pp)++; - - /* This probably just means we're processing a file compiled - with g++ version 1. */ - else - complain(&const_vol_complaint, **pp); + switch (**pp) + { + case 'A': /* Normal functions. */ + new_sublist->fn_field.is_const = 0; + new_sublist->fn_field.is_volatile = 0; + (*pp)++; + break; + case 'B': /* `const' member functions. */ + new_sublist->fn_field.is_const = 1; + new_sublist->fn_field.is_volatile = 0; + (*pp)++; + break; + case 'C': /* `volatile' member function. */ + new_sublist->fn_field.is_const = 0; + new_sublist->fn_field.is_volatile = 1; + (*pp)++; + break; + case 'D': /* `const volatile' member function. */ + new_sublist->fn_field.is_const = 1; + new_sublist->fn_field.is_volatile = 1; + (*pp)++; + break; + default: + /* This probably just means we're processing a file compiled + with g++ version 1. */ + complain(&const_vol_complaint, **pp); + } switch (*(*pp)++) { @@ -4655,7 +4667,7 @@ read_struct_type (pp, type) the sign bit out, and usable as a valid index into the array. Remove the sign bit here. */ new_sublist->fn_field.voffset = - (0x7fffffff & read_number (pp, ';')) + 1; + (0x7fffffff & read_number (pp, ';')) + 2; if (**pp == '\\') *pp = next_symbol_text (); @@ -4697,6 +4709,7 @@ read_struct_type (pp, type) new_sublist->next = sublist; sublist = new_sublist; length++; + if (**pp == '\\') *pp = next_symbol_text (); } while (**pp != ';' && **pp != '\0'); diff --git a/gdb/symtab.c b/gdb/symtab.c index 0a53dcc2111..81f7ec10218 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -41,6 +41,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ extern char *getenv (); extern char *cplus_demangle (); +extern char *cplus_mangle_opname (); extern struct value *value_of_this (); extern void break_command (); extern void select_source_symtab (); @@ -224,31 +225,52 @@ check_stub_type(type) /* Demangle a GDB method stub type. */ char * -gdb_mangle_typename (type) +gdb_mangle_name (type, i, j) struct type *type; + int i, j; { - static struct type *last_type; - static char *mangled_typename; + int mangled_name_len; + char *mangled_name; + struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i); + struct fn_field *method = &f[j]; + char *field_name = TYPE_FN_FIELDLIST_NAME (type, i); - if (type != last_type) + /* Need a new type prefix. */ + char *strchr (); + char *const_prefix = method->is_const ? "C" : ""; + char *volatile_prefix = method->is_volatile ? "V" : ""; + char *newname = type_name_no_tag (type); + char buf[20]; + int len = strlen (newname); + + sprintf (buf, "__%s%s%d", const_prefix, volatile_prefix, len); + mangled_name_len = (strlen (field_name) + + strlen (buf) + len + + strlen (TYPE_FN_FIELD_PHYSNAME (f, j)) + + 1); + + if (OPNAME_PREFIX_P (field_name)) + { + char *opname = cplus_mangle_opname (field_name + 3); + if (opname == NULL) + error ("No mangling for \"%s\"", field_name); + mangled_name_len += strlen (opname); + mangled_name = (char *)xmalloc (mangled_name_len); + + strncpy (mangled_name, field_name, 3); + mangled_name[3] = '\0'; + strcat (mangled_name, opname); + } + else { - /* Need a new type prefix. */ - char *strchr (); - char *newname = type_name_no_tag (type); - char buf[20]; - int len; - - if (mangled_typename) - free (mangled_typename); - - len = strlen (newname); - sprintf (buf, "__%d", len); - mangled_typename = (char *)xmalloc (strlen (buf) + len + 1); - strcpy (mangled_typename, buf); - strcat (mangled_typename, newname); - /* Now we have built "__#newname". */ + mangled_name = (char *)xmalloc (mangled_name_len); + strcpy (mangled_name, TYPE_FN_FIELDLIST_NAME (type, i)); } - return mangled_typename; + strcat (mangled_name, buf); + strcat (mangled_name, newname); + strcat (mangled_name, TYPE_FN_FIELD_PHYSNAME (f, j)); + + return mangled_name; } /* Lookup a primitive type named NAME. diff --git a/gdb/symtab.h b/gdb/symtab.h index 1f8ff418acc..d220a8398ba 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -247,10 +247,12 @@ struct type /* For virtual functions. */ /* First baseclass that defines this virtual function. */ struct type *fcontext; + unsigned int is_const : 1; + unsigned int is_volatile : 1; /* Index into that baseclass's virtual function table, - minus 1; else if static: VOFFSET_STATIC; else: 0. */ - int voffset; -# define VOFFSET_STATIC (-1) + minus 2; else if static: VOFFSET_STATIC; else: 0. */ + unsigned long voffset : 30; +# define VOFFSET_STATIC 1 } *fn_fields; B_TYPE *private_fn_field_bits; @@ -729,9 +731,9 @@ int current_source_line; #define TYPE_FN_FIELD_TYPE(thistype, n) (thistype)[n].type #define TYPE_FN_FIELD_ARGS(thistype, n) TYPE_ARG_TYPES ((thistype)[n].type) #define TYPE_FN_FIELD_PHYSNAME(thistype, n) (thistype)[n].physname -#define TYPE_FN_FIELD_VIRTUAL_P(thistype, n) ((thistype)[n].voffset > 0) +#define TYPE_FN_FIELD_VIRTUAL_P(thistype, n) ((thistype)[n].voffset > 1) #define TYPE_FN_FIELD_STATIC_P(thistype, n) ((thistype)[n].voffset == VOFFSET_STATIC) -#define TYPE_FN_FIELD_VOFFSET(thistype, n) ((thistype)[n].voffset-1) +#define TYPE_FN_FIELD_VOFFSET(thistype, n) ((thistype)[n].voffset-2) #define TYPE_FN_FIELD_FCONTEXT(thistype, n) ((thistype)[n].fcontext) #define TYPE_FN_PRIVATE_BITS(thistype) (thistype).private_fn_field_bits diff --git a/gdb/valprint.c b/gdb/valprint.c index f893eda4d3e..d10b55dea3c 100644 --- a/gdb/valprint.c +++ b/gdb/valprint.c @@ -409,7 +409,7 @@ is_vtbl_ptr_type(type) { char *typename = TYPE_NAME(type); static const char vtbl_ptr_name[] = - { CPLUS_MARKER,'v','t','b','l','_','p','t','r','_','t','y','p','e' }; + { CPLUS_MARKER,'v','t','b','l','_','p','t','r','_','t','y','p','e', 0 }; return (typename != NULL && !strcmp(typename, vtbl_ptr_name)); } @@ -1718,18 +1718,9 @@ type_print_base (type, stream, show, level) if (TYPE_FLAGS (TYPE_FN_FIELD_TYPE (f, j)) & TYPE_FLAG_STUB) { /* Build something we can demangle. */ - char *strchr (), *gdb_mangle_typename (); - char *inner_name = gdb_mangle_typename (type); - char *mangled_name - = (char *)xmalloc (strlen (TYPE_FN_FIELDLIST_NAME (type, i)) - + strlen (inner_name) - + strlen (TYPE_FN_FIELD_PHYSNAME (f, j)) - + 1); - char *demangled_name, *cplus_demangle (); - strcpy (mangled_name, TYPE_FN_FIELDLIST_NAME (type, i)); - strcat (mangled_name, inner_name); - strcat (mangled_name, TYPE_FN_FIELD_PHYSNAME (f, j)); - demangled_name = cplus_demangle (mangled_name, 1); + char *strchr (), *gdb_mangle_name (), *cplus_demangle (); + char *mangled_name = gdb_mangle_name (type, i, j); + char *demangled_name = cplus_demangle (mangled_name, 1); if (demangled_name == 0) fprintf_filtered (stream, " ", mangled_name); diff --git a/gdb/values.c b/gdb/values.c index 0f5e1e7c364..a5b2c69f6c2 100644 --- a/gdb/values.c +++ b/gdb/values.c @@ -29,7 +29,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "gdbcmd.h" extern char *cplus_demangle (); -extern char *cplus_mangle_opname (); /* The value-history records all the values printed by print commands during this session. Each chunk @@ -995,7 +994,6 @@ value_headof (arg, btype, dtype) struct symbol *sym; CORE_ADDR pc_for_sym; char *demangled_name; - btype = TYPE_VPTR_BASETYPE (dtype); check_stub_type (btype); if (btype != dtype) @@ -1006,7 +1004,7 @@ value_headof (arg, btype, dtype) /* Check that VTBL looks like it points to a virtual function table. */ i = find_pc_misc_function (VALUE_ADDRESS (vtbl)); - if (i < 0 || ! VTBL_PREFIX_P (misc_function_vector[i].name)) + if (i < 0 || ! VTBL_PREFIX_P (demangled_name = misc_function_vector[i].name)) { /* If we expected to find a vtable, but did not, let the user know that we aren't happy, but don't throw an error. @@ -1026,27 +1024,40 @@ value_headof (arg, btype, dtype) entry = value_subscript (vtbl, value_from_longest (builtin_type_int, (LONGEST) i)); offset = longest_to_int (value_as_long (value_field (entry, 0))); - if (offset < best_offset) + /* If we use '<=' we can handle single inheritance + * where all offsets are zero - just use the first entry found. */ + if (offset <= best_offset) { best_offset = offset; best_entry = entry; } } - if (best_entry == 0) - return arg; - /* Move the pointer according to BEST_ENTRY's offset, and figure out what type we should return as the new pointer. */ - pc_for_sym = value_as_pointer (value_field (best_entry, 2)); - sym = find_pc_function (pc_for_sym); - demangled_name = cplus_demangle (SYMBOL_NAME (sym), -1); - *(strchr (demangled_name, ':')) = '\0'; + if (best_entry == 0) + { + /* An alternative method (which should no longer be necessary). + * But we leave it in for future use, when we will hopefully + * have optimizes the vtable to use thunks instead of offsets. */ + /* Use the name of vtable itself to extract a base type. */ + demangled_name += 4; /* Skip _vt$ prefix. */ + } + else + { + pc_for_sym = value_as_pointer (value_field (best_entry, 2)); + sym = find_pc_function (pc_for_sym); + demangled_name = cplus_demangle (SYMBOL_NAME (sym), -1); + *(strchr (demangled_name, ':')) = '\0'; + } sym = lookup_symbol (demangled_name, 0, VAR_NAMESPACE, 0, 0); if (sym == 0) error ("could not find type declaration for `%s'", SYMBOL_NAME (sym)); - free (demangled_name); - arg = value_add (value_cast (builtin_type_int, arg), - value_field (best_entry, 0)); + if (best_entry) + { + free (demangled_name); + arg = value_add (value_cast (builtin_type_int, arg), + value_field (best_entry, 0)); + } VALUE_TYPE (arg) = lookup_pointer_type (SYMBOL_TYPE (sym)); return arg; } @@ -1241,41 +1252,14 @@ check_stub_method (type, i, j) struct type *type; int i, j; { - extern char *gdb_mangle_typename (), *strchr (); + extern char *gdb_mangle_name (), *strchr (); struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i); - char *field_name = TYPE_FN_FIELDLIST_NAME (type, i); - char *inner_name = gdb_mangle_typename (type); - int mangled_name_len = (strlen (field_name) - + strlen (inner_name) - + strlen (TYPE_FN_FIELD_PHYSNAME (f, j)) - + 1); - char *mangled_name; - char *demangled_name; + char *mangled_name = gdb_mangle_name (type, i, j); + char *demangled_name = cplus_demangle (mangled_name, 0); char *argtypetext, *p; int depth = 0, argcount = 1; struct type **argtypes; - if (OPNAME_PREFIX_P (field_name)) - { - char *opname = cplus_mangle_opname (field_name + 3); - if (opname == NULL) - error ("No mangling for \"%s\"", field_name); - mangled_name_len += strlen (opname); - mangled_name = (char *)xmalloc (mangled_name_len); - - strncpy (mangled_name, field_name, 3); - mangled_name[3] = '\0'; - strcat (mangled_name, opname); - } - else - { - mangled_name = (char *)xmalloc (mangled_name_len); - strcpy (mangled_name, TYPE_FN_FIELDLIST_NAME (type, i)); - } - strcat (mangled_name, inner_name); - strcat (mangled_name, TYPE_FN_FIELD_PHYSNAME (f, j)); - demangled_name = cplus_demangle (mangled_name, 0); - /* Now, read in the parameters that define this type. */ argtypetext = strchr (demangled_name, '(') + 1; p = argtypetext; -- 2.30.2