Various fixes to improve g++ debugging. See ChangeLog.

This commit is contained in:
Per Bothner 1991-10-26 02:05:14 +00:00
parent 5ab580ccf8
commit bcccec8c8d
6 changed files with 134 additions and 97 deletions

View File

@ -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) 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 * tm-sparc.h, tm-68k.h (EXTRACT_RETURN_VALUE): fix output of

View File

@ -4628,21 +4628,33 @@ read_struct_type (pp, type)
*pp = p + 1; *pp = p + 1;
new_sublist->visibility = *(*pp)++ - '0'; new_sublist->visibility = *(*pp)++ - '0';
if (**pp == '\\') *pp = next_symbol_text (); if (**pp == '\\') *pp = next_symbol_text ();
/* FIXME-tiemann: need to add const/volatile info switch (**pp)
to the methods. For now, just skip the char. {
In future, here's what we need to implement: case 'A': /* Normal functions. */
new_sublist->fn_field.is_const = 0;
A for normal functions. new_sublist->fn_field.is_volatile = 0;
B for `const' member functions. (*pp)++;
C for `volatile' member functions. break;
D for `const volatile' member functions. */ case 'B': /* `const' member functions. */
if (**pp == 'A' || **pp == 'B' || **pp == 'C' || **pp == 'D') new_sublist->fn_field.is_const = 1;
(*pp)++; new_sublist->fn_field.is_volatile = 0;
(*pp)++;
/* This probably just means we're processing a file compiled break;
with g++ version 1. */ case 'C': /* `volatile' member function. */
else new_sublist->fn_field.is_const = 0;
complain(&const_vol_complaint, **pp); 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)++) switch (*(*pp)++)
{ {
@ -4655,7 +4667,7 @@ read_struct_type (pp, type)
the sign bit out, and usable as a valid index into the sign bit out, and usable as a valid index into
the array. Remove the sign bit here. */ the array. Remove the sign bit here. */
new_sublist->fn_field.voffset = new_sublist->fn_field.voffset =
(0x7fffffff & read_number (pp, ';')) + 1; (0x7fffffff & read_number (pp, ';')) + 2;
if (**pp == '\\') *pp = next_symbol_text (); if (**pp == '\\') *pp = next_symbol_text ();
@ -4697,6 +4709,7 @@ read_struct_type (pp, type)
new_sublist->next = sublist; new_sublist->next = sublist;
sublist = new_sublist; sublist = new_sublist;
length++; length++;
if (**pp == '\\') *pp = next_symbol_text ();
} }
while (**pp != ';' && **pp != '\0'); while (**pp != ';' && **pp != '\0');

View File

@ -41,6 +41,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
extern char *getenv (); extern char *getenv ();
extern char *cplus_demangle (); extern char *cplus_demangle ();
extern char *cplus_mangle_opname ();
extern struct value *value_of_this (); extern struct value *value_of_this ();
extern void break_command (); extern void break_command ();
extern void select_source_symtab (); extern void select_source_symtab ();
@ -224,31 +225,52 @@ check_stub_type(type)
/* Demangle a GDB method stub type. */ /* Demangle a GDB method stub type. */
char * char *
gdb_mangle_typename (type) gdb_mangle_name (type, i, j)
struct type *type; struct type *type;
int i, j;
{ {
static struct type *last_type; int mangled_name_len;
static char *mangled_typename; 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))
{ {
/* Need a new type prefix. */ char *opname = cplus_mangle_opname (field_name + 3);
char *strchr (); if (opname == NULL)
char *newname = type_name_no_tag (type); error ("No mangling for \"%s\"", field_name);
char buf[20]; mangled_name_len += strlen (opname);
int len; mangled_name = (char *)xmalloc (mangled_name_len);
if (mangled_typename) strncpy (mangled_name, field_name, 3);
free (mangled_typename); mangled_name[3] = '\0';
strcat (mangled_name, opname);
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". */
} }
return mangled_typename; else
{
mangled_name = (char *)xmalloc (mangled_name_len);
strcpy (mangled_name, TYPE_FN_FIELDLIST_NAME (type, i));
}
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. /* Lookup a primitive type named NAME.

View File

@ -247,10 +247,12 @@ struct type
/* For virtual functions. */ /* For virtual functions. */
/* First baseclass that defines this virtual function. */ /* First baseclass that defines this virtual function. */
struct type *fcontext; struct type *fcontext;
unsigned int is_const : 1;
unsigned int is_volatile : 1;
/* Index into that baseclass's virtual function table, /* Index into that baseclass's virtual function table,
minus 1; else if static: VOFFSET_STATIC; else: 0. */ minus 2; else if static: VOFFSET_STATIC; else: 0. */
int voffset; unsigned long voffset : 30;
# define VOFFSET_STATIC (-1) # define VOFFSET_STATIC 1
} *fn_fields; } *fn_fields;
B_TYPE *private_fn_field_bits; 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_TYPE(thistype, n) (thistype)[n].type
#define TYPE_FN_FIELD_ARGS(thistype, n) TYPE_ARG_TYPES ((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_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_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_FIELD_FCONTEXT(thistype, n) ((thistype)[n].fcontext)
#define TYPE_FN_PRIVATE_BITS(thistype) (thistype).private_fn_field_bits #define TYPE_FN_PRIVATE_BITS(thistype) (thistype).private_fn_field_bits

View File

@ -409,7 +409,7 @@ is_vtbl_ptr_type(type)
{ {
char *typename = TYPE_NAME(type); char *typename = TYPE_NAME(type);
static const char vtbl_ptr_name[] = 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)); 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) if (TYPE_FLAGS (TYPE_FN_FIELD_TYPE (f, j)) & TYPE_FLAG_STUB)
{ {
/* Build something we can demangle. */ /* Build something we can demangle. */
char *strchr (), *gdb_mangle_typename (); char *strchr (), *gdb_mangle_name (), *cplus_demangle ();
char *inner_name = gdb_mangle_typename (type); char *mangled_name = gdb_mangle_name (type, i, j);
char *mangled_name char *demangled_name = cplus_demangle (mangled_name, 1);
= (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);
if (demangled_name == 0) if (demangled_name == 0)
fprintf_filtered (stream, " <badly mangled name %s>", fprintf_filtered (stream, " <badly mangled name %s>",
mangled_name); mangled_name);

View File

@ -29,7 +29,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "gdbcmd.h" #include "gdbcmd.h"
extern char *cplus_demangle (); extern char *cplus_demangle ();
extern char *cplus_mangle_opname ();
/* The value-history records all the values printed /* The value-history records all the values printed
by print commands during this session. Each chunk by print commands during this session. Each chunk
@ -995,7 +994,6 @@ value_headof (arg, btype, dtype)
struct symbol *sym; struct symbol *sym;
CORE_ADDR pc_for_sym; CORE_ADDR pc_for_sym;
char *demangled_name; char *demangled_name;
btype = TYPE_VPTR_BASETYPE (dtype); btype = TYPE_VPTR_BASETYPE (dtype);
check_stub_type (btype); check_stub_type (btype);
if (btype != dtype) if (btype != dtype)
@ -1006,7 +1004,7 @@ value_headof (arg, btype, dtype)
/* Check that VTBL looks like it points to a virtual function table. */ /* Check that VTBL looks like it points to a virtual function table. */
i = find_pc_misc_function (VALUE_ADDRESS (vtbl)); 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 /* 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. 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, entry = value_subscript (vtbl, value_from_longest (builtin_type_int,
(LONGEST) i)); (LONGEST) i));
offset = longest_to_int (value_as_long (value_field (entry, 0))); 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_offset = offset;
best_entry = entry; best_entry = entry;
} }
} }
if (best_entry == 0)
return arg;
/* Move the pointer according to BEST_ENTRY's offset, and figure /* Move the pointer according to BEST_ENTRY's offset, and figure
out what type we should return as the new pointer. */ out what type we should return as the new pointer. */
pc_for_sym = value_as_pointer (value_field (best_entry, 2)); if (best_entry == 0)
sym = find_pc_function (pc_for_sym); {
demangled_name = cplus_demangle (SYMBOL_NAME (sym), -1); /* An alternative method (which should no longer be necessary).
*(strchr (demangled_name, ':')) = '\0'; * 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); sym = lookup_symbol (demangled_name, 0, VAR_NAMESPACE, 0, 0);
if (sym == 0) if (sym == 0)
error ("could not find type declaration for `%s'", SYMBOL_NAME (sym)); error ("could not find type declaration for `%s'", SYMBOL_NAME (sym));
free (demangled_name); if (best_entry)
arg = value_add (value_cast (builtin_type_int, arg), {
value_field (best_entry, 0)); 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)); VALUE_TYPE (arg) = lookup_pointer_type (SYMBOL_TYPE (sym));
return arg; return arg;
} }
@ -1241,41 +1252,14 @@ check_stub_method (type, i, j)
struct type *type; struct type *type;
int i, j; int i, j;
{ {
extern char *gdb_mangle_typename (), *strchr (); extern char *gdb_mangle_name (), *strchr ();
struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i); struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
char *field_name = TYPE_FN_FIELDLIST_NAME (type, i); char *mangled_name = gdb_mangle_name (type, i, j);
char *inner_name = gdb_mangle_typename (type); char *demangled_name = cplus_demangle (mangled_name, 0);
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 *argtypetext, *p; char *argtypetext, *p;
int depth = 0, argcount = 1; int depth = 0, argcount = 1;
struct type **argtypes; 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. */ /* Now, read in the parameters that define this type. */
argtypetext = strchr (demangled_name, '(') + 1; argtypetext = strchr (demangled_name, '(') + 1;
p = argtypetext; p = argtypetext;