Various fixes to improve g++ debugging. See ChangeLog.
This commit is contained in:
parent
5ab580ccf8
commit
bcccec8c8d
6 changed files with 134 additions and 97 deletions
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
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. */
|
||||
else
|
||||
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');
|
||||
|
||||
|
|
52
gdb/symtab.c
52
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;
|
||||
int len = strlen (newname);
|
||||
|
||||
if (mangled_typename)
|
||||
free (mangled_typename);
|
||||
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);
|
||||
|
||||
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". */
|
||||
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);
|
||||
}
|
||||
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.
|
||||
|
|
12
gdb/symtab.h
12
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
|
||||
|
|
|
@ -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, " <badly mangled name %s>",
|
||||
mangled_name);
|
||||
|
|
58
gdb/values.c
58
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. */
|
||||
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));
|
||||
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;
|
||||
|
|
Loading…
Add table
Reference in a new issue