mdt@YAHI.STANFORD.EDU (Michael Tiemann) (03/12/89)
Some people have noticed that GDB 3.1 does not quite replace GDB+
2.8.1 when it comes to debugging GNU C++ code. This is more my fault
than Randy's. The following diffs should go a long way toward
remedying the problem. You will also need a small patch for dbxout.c
for GNU C++ 1.34.0, which is enclosed at the bottom.
Michael
yahi% diff -c2 dbxread.c~ dbxread.c
*** dbxread.c~ Mon Jan 30 08:59:56 1989
--- dbxread.c Sat Mar 11 17:59:56 1989
***************
*** 3786,3789 ****
--- 3786,3794 ----
int read_possible_virtual_info = 0;
+ if (TYPE_CODE (type) == TYPE_CODE_UNDEF)
+ {
+ TYPE_MAIN_VARIANT (type) = type;
+ }
+
TYPE_CODE (type) = TYPE_CODE_STRUCT;
***************
*** 4010,4013 ****
--- 4015,4021 ----
new_sublist->fn_field.type = read_type (pp);
+ smash_to_method_type (new_sublist->fn_field.type,
+ TYPE_DOMAIN_TYPE (new_sublist->fn_field.type),
+ TYPE_TARGET_TYPE (new_sublist->fn_field.type));
new_sublist->fn_field.args = read_args (pp, ':');
p = *pp;
yahi% diff -c2 values.c~ values.c
*** values.c~ Tue Jan 31 09:55:59 1989
--- values.c Sat Mar 11 18:14:26 1989
***************
*** 659,669 ****
= fill_in_vptr_fieldno (type);
! /* Pretend that this array is just an array of pointers to integers.
! This will have to change for multiple inheritance. */
! vtbl = value_copy (value_field (arg1, TYPE_VPTR_FIELDNO (type)));
! VALUE_TYPE (vtbl) = lookup_pointer_type (builtin_type_int);
/* Index into the virtual function table. */
! vfn = value_subscript (vtbl, vi);
/* Reinstantiate the function pointer with the correct type. */
--- 659,669 ----
= fill_in_vptr_fieldno (type);
! /* The virtual function table is now an array of structures
! which have the form { int16 offset, delta; void* pfn; }. */
! vtbl = value_ind (value_field (arg1, TYPE_VPTR_FIELDNO (type)));
/* Index into the virtual function table. */
! vfn = value_struct_elt (value_subscript (vtbl, vi), 0, "pfn",
! "internal error in virtual function lookup");
/* Reinstantiate the function pointer with the correct type. */
yahi% diff -c2 symseg.h~ symseg.h
*** symseg.h~ Mon Jan 23 12:42:18 1989
--- symseg.h Sat Mar 11 17:44:56 1989
***************
*** 122,125 ****
--- 122,126 ----
/* C++ */
TYPE_CODE_MEMBER, /* Member type */
+ TYPE_CODE_METHOD, /* Method type */
TYPE_CODE_REF, /* C++ Reference types */
};
***************
*** 147,151 ****
/* For a pointer type, describes the type of object pointed to.
For an array type, describes the type of the elements.
! For a function type, describes the type of the value.
For a range type, describes the type of the full range.
Unused otherwise. */
--- 148,152 ----
/* For a pointer type, describes the type of object pointed to.
For an array type, describes the type of the elements.
! For a function or method type, describes the type of the value.
For a range type, describes the type of the full range.
Unused otherwise. */
***************
*** 240,244 ****
char *name;
#endif
! /* The type of the argument */
struct type *type;
/* The argument list */
--- 241,245 ----
char *name;
#endif
! /* The return value of the method */
struct type *type;
/* The argument list */
yahi% diff -c2 symtab.c~ symtab.c
*** symtab.c~ Tue Jan 17 11:29:19 1989
--- symtab.c Sat Mar 11 17:47:40 1989
***************
*** 362,365 ****
--- 362,419 ----
}
+ struct type *
+ lookup_method_type (type, domain)
+ struct type *type, *domain;
+ {
+ register struct type *mtype = TYPE_MAIN_VARIANT (type);
+ struct type *main_type;
+
+ main_type = mtype;
+ while (mtype)
+ {
+ if (TYPE_DOMAIN_TYPE (mtype) == domain)
+ return mtype;
+ mtype = TYPE_NEXT_VARIANT (mtype);
+ }
+
+ /* This is the first time anyone wanted this member type. */
+ if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+ mtype = (struct type *) xmalloc (sizeof (struct type));
+ else
+ mtype = (struct type *) obstack_alloc (symbol_obstack,
+ sizeof (struct type));
+
+ bzero (mtype, sizeof (struct type));
+ if (main_type == 0)
+ main_type = mtype;
+ else
+ {
+ TYPE_NEXT_VARIANT (mtype) = TYPE_NEXT_VARIANT (main_type);
+ TYPE_NEXT_VARIANT (main_type) = mtype;
+ }
+ TYPE_MAIN_VARIANT (mtype) = main_type;
+ TYPE_TARGET_TYPE (mtype) = type;
+ TYPE_DOMAIN_TYPE (mtype) = domain;
+ /* New type is permanent if type pointed to is permanent. */
+ if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
+ TYPE_FLAGS (mtype) |= TYPE_FLAG_PERM;
+
+ /* In practice, this is never used. */
+ TYPE_LENGTH (mtype) = 1;
+ TYPE_CODE (mtype) = TYPE_CODE_MEMBER;
+
+ #if 0
+ /* Now splice in the new member pointer type. */
+ if (main_type)
+ {
+ /* This type was not "smashed". */
+ TYPE_CHAIN (mtype) = TYPE_CHAIN (main_type);
+ TYPE_CHAIN (main_type) = mtype;
+ }
+ #endif
+
+ return mtype;
+ }
+
/* Given a type TYPE, return a type which has offset OFFSET,
via_virtual VIA_VIRTUAL, and via_public VIA_PUBLIC.
***************
*** 491,494 ****
--- 545,565 ----
TYPE_MAIN_VARIANT (type) = lookup_member_type (domain, to_type);
+ }
+
+ /* Smash TYPE to be a type of method of DOMAIN with type TO_TYPE. */
+
+ void
+ smash_to_method_type (type, domain, to_type)
+ struct type *type, *domain, *to_type;
+ {
+ bzero (type, sizeof (struct type));
+ TYPE_TARGET_TYPE (type) = to_type;
+ TYPE_DOMAIN_TYPE (type) = domain;
+
+ /* In practice, this is never needed. */
+ TYPE_LENGTH (type) = 1;
+ TYPE_CODE (type) = TYPE_CODE_METHOD;
+
+ TYPE_MAIN_VARIANT (type) = lookup_method_type (domain, to_type);
}
yahi% diff -c2 valops.c~ valops.c
*** valops.c~ Thu Jan 19 15:09:14 1989
--- valops.c Fri Mar 10 22:03:47 1989
***************
*** 525,536 ****
/* If it's a member function, just look at the function
part of it. */
- if (code == TYPE_CODE_MEMBER)
- {
- ftype = TYPE_TARGET_TYPE (ftype);
- code = TYPE_CODE (ftype);
- }
-
/* Determine address to call. */
! if (code == TYPE_CODE_FUNC)
{
funaddr = VALUE_ADDRESS (function);
--- 525,530 ----
/* If it's a member function, just look at the function
part of it. */
/* Determine address to call. */
! if (code == TYPE_CODE_FUNC || code == TYPE_CODE_METHOD)
{
funaddr = VALUE_ADDRESS (function);
***************
*** 540,545 ****
{
funaddr = value_as_long (function);
! if (TYPE_CODE (TYPE_TARGET_TYPE (ftype))
! == TYPE_CODE_FUNC)
value_type = TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (ftype));
else
--- 534,539 ----
{
funaddr = value_as_long (function);
! if (TYPE_CODE (TYPE_TARGET_TYPE (ftype)) == TYPE_CODE_FUNC
! || TYPE_CODE (TYPE_TARGET_TYPE (ftype)) == TYPE_CODE_METHOD)
value_type = TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (ftype));
else
yahi% diff -c2 valprint.c~ valprint.c
*** valprint.c~ Wed Jan 11 10:51:31 1989
--- valprint.c Fri Mar 10 22:41:35 1989
***************
*** 186,190 ****
break;
}
! if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_MEMBER)
{
struct type *domain = TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type));
--- 186,190 ----
break;
}
! if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_METHOD)
{
struct type *domain = TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type));
***************
*** 195,297 ****
val = unpack_long (builtin_type_int, valaddr);
! if (TYPE_CODE (target) == TYPE_CODE_FUNC)
{
! if (val < 128)
{
! len = TYPE_NFN_FIELDS (domain);
! for (i = 0; i < len; i++)
! {
! f = TYPE_FN_FIELDLIST1 (domain, i);
! len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
! for (j = 0; j < len2; j++)
! {
! QUIT;
! if (TYPE_FN_FIELD_VOFFSET (f, j) == val)
! {
! kind = "virtual";
! goto common;
! }
! }
! }
! }
! else
! {
! struct symbol *sym = find_pc_function ((CORE_ADDR) val);
! if (sym == 0)
! error ("invalid pointer to member function");
! len = TYPE_NFN_FIELDS (domain);
! for (i = 0; i < len; i++)
{
! f = TYPE_FN_FIELDLIST1 (domain, i);
! len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
!
! for (j = 0; j < len2; j++)
{
! QUIT;
! if (!strcmp (SYMBOL_NAME (sym), TYPE_FN_FIELD_PHYSNAME (f, j)))
! goto common;
}
}
}
- common:
- if (i < len)
- {
- fputc ('&', stream);
- type_print_varspec_prefix (TYPE_FN_FIELD_TYPE (f, j), stream, 0, 0);
- fprintf (stream, kind);
- if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_'
- && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$')
- type_print_method_args
- (TYPE_FN_FIELD_ARGS (f, j) + 1, "~",
- TYPE_FN_FIELDLIST_NAME (domain, i), stream);
- else
- type_print_method_args
- (TYPE_FN_FIELD_ARGS (f, j), "",
- TYPE_FN_FIELDLIST_NAME (domain, i), stream);
- break;
- }
}
else
{
! /* VAL is a byte offset into the structure type DOMAIN.
! Find the name of the field for that offset and
! print it. */
! int extra = 0;
! int bits = 0;
! len = TYPE_NFIELDS (domain);
! val <<= 3; /* @@ Make VAL into bit offset */
for (i = 0; i < len; i++)
{
! int bitpos = TYPE_FIELD_BITPOS (domain, i);
! QUIT;
! if (val == bitpos)
! break;
! if (val < bitpos && i > 0)
{
! int ptrsize = (TYPE_LENGTH (builtin_type_char) * TYPE_LENGTH (target));
! /* Somehow pointing into a field. */
! i -= 1;
! extra = (val - TYPE_FIELD_BITPOS (domain, i));
! if (extra & 0x3)
! bits = 1;
! else
! extra >>= 3;
! break;
}
}
! if (i < len)
{
! fputc ('&', stream);
! type_print_base (domain, stream, 0, 0);
! fprintf (stream, "::");
! fprintf (stream, "%s", TYPE_FIELD_NAME (domain, i));
! if (extra)
! fprintf (stream, " + %d bytes", extra);
! if (bits)
! fprintf (stream, " (offset in bits)");
break;
}
}
fputc ('(', stream);
type_print (type, "", stream, -1);
--- 195,303 ----
val = unpack_long (builtin_type_int, valaddr);
! if (val < 128)
{
! len = TYPE_NFN_FIELDS (domain);
! for (i = 0; i < len; i++)
{
! f = TYPE_FN_FIELDLIST1 (domain, i);
! len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
! for (j = 0; j < len2; j++)
{
! QUIT;
! if (TYPE_FN_FIELD_VOFFSET (f, j) == val)
{
! kind = "virtual";
! goto common;
}
}
}
}
else
{
! struct symbol *sym = find_pc_function ((CORE_ADDR) val);
! if (sym == 0)
! error ("invalid pointer to member function");
! len = TYPE_NFN_FIELDS (domain);
for (i = 0; i < len; i++)
{
! f = TYPE_FN_FIELDLIST1 (domain, i);
! len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
!
! for (j = 0; j < len2; j++)
{
! QUIT;
! if (!strcmp (SYMBOL_NAME (sym), TYPE_FN_FIELD_PHYSNAME (f, j)))
! goto common;
}
}
! }
! common:
! if (i < len)
! {
! fputc ('&', stream);
! type_print_varspec_prefix (TYPE_FN_FIELD_TYPE (f, j), stream, 0, 0);
! fprintf (stream, kind);
! if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_'
! && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$')
! type_print_method_args
! (TYPE_FN_FIELD_ARGS (f, j) + 1, "~",
! TYPE_FN_FIELDLIST_NAME (domain, i), stream);
! else
! type_print_method_args
! (TYPE_FN_FIELD_ARGS (f, j), "",
! TYPE_FN_FIELDLIST_NAME (domain, i), stream);
! break;
! }
! fputc ('(', stream);
! type_print (type, "", stream, -1);
! fprintf (stream, ") %d", val >> 3);
! }
! else if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_MEMBER)
! {
! struct type *domain = TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type));
! struct type *target = TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (type));
! struct fn_field *f;
! int j, len2;
! char *kind = "";
!
! /* VAL is a byte offset into the structure type DOMAIN.
! Find the name of the field for that offset and
! print it. */
! int extra = 0;
! int bits = 0;
! len = TYPE_NFIELDS (domain);
! val <<= 3; /* @@ Make VAL into bit offset */
! for (i = 0; i < len; i++)
! {
! int bitpos = TYPE_FIELD_BITPOS (domain, i);
! QUIT;
! if (val == bitpos)
! break;
! if (val < bitpos && i > 0)
{
! int ptrsize = (TYPE_LENGTH (builtin_type_char) * TYPE_LENGTH (target));
! /* Somehow pointing into a field. */
! i -= 1;
! extra = (val - TYPE_FIELD_BITPOS (domain, i));
! if (extra & 0x3)
! bits = 1;
! else
! extra >>= 3;
break;
}
}
+ if (i < len)
+ {
+ fputc ('&', stream);
+ type_print_base (domain, stream, 0, 0);
+ fprintf (stream, "::");
+ fprintf (stream, "%s", TYPE_FIELD_NAME (domain, i));
+ if (extra)
+ fprintf (stream, " + %d bytes", extra);
+ if (bits)
+ fprintf (stream, " (offset in bits)");
+ break;
+ }
fputc ('(', stream);
type_print (type, "", stream, -1);
***************
*** 573,576 ****
--- 579,583 ----
&&
(code == TYPE_CODE_PTR || code == TYPE_CODE_FUNC
+ || code == TYPE_CODE_METHOD
|| code == TYPE_CODE_ARRAY
|| code == TYPE_CODE_MEMBER
***************
*** 702,705 ****
--- 709,721 ----
break;
+ case TYPE_CODE_METHOD:
+ type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0,
+ passed_a_ptr);
+ fputc (' ', stream);
+ type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0,
+ passed_a_ptr);
+ fprintf (stream, "::");
+ break;
+
case TYPE_CODE_REF:
type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1);
***************
*** 758,761 ****
--- 774,783 ----
break;
+ case TYPE_CODE_METHOD:
+ if (passed_a_ptr)
+ fputc (')', stream);
+ type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0);
+ break;
+
case TYPE_CODE_PTR:
case TYPE_CODE_REF:
***************
*** 819,822 ****
--- 841,845 ----
case TYPE_CODE_REF:
case TYPE_CODE_FUNC:
+ case TYPE_CODE_METHOD:
type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
break;
***************
*** 887,891 ****
if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
fprintf (stream, "virtual ");
! type_print (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j))), "", stream, 0);
if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_'
&& TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$')
--- 910,914 ----
if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
fprintf (stream, "virtual ");
! type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)), "", stream, 0);
if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_'
&& TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$')
yahi% gdb a.out
GDB 3.1, Copyright (C) 1988 Free Software Foundation, Inc.
There is ABSOLUTELY NO WARRANTY for GDB; type "info warranty" for details.
GDB is free software and you are welcome to distribute copies of it
under certain conditions; type "info copying" to see the conditions.
Reading symbol data from /home/sioux/mdt/dist-gdb/a.out...done.
Function fatal not defined.
Type "help" for a list of commands.
(gdb) pty a
struct a {
int x;
int y;
int f ();
int f (int, int);
}
(gdb) pty b
struct b : public a {
int z;
int w;
int f ();
int f (int, int);
}
(gdb) b main
Breakpoint 1 at 0x21a8: file test.c, line 30.
(gdb) r
Starting program: /home/sioux/mdt/dist-gdb/a.out
Bpt 1, main () (test.c line 33)
33 x.f (5, 6);
(gdb) p x
$1 = {x = 0, y = 0}
(gdb) p x.f (-1, -2)
$2 = -134218336
(gdb) p x.f()
calling f for a(-1,-2)
$3 = -134218336
(gdb) b a::f
[0] cancel
[1] all
[2] file:test.c; line number:10
[3] file:test.c; line number:6
> 1
Breakpoint 2 at 0x2138: file test.c, line 10.
Breakpoint 3 at 0x2178: file test.c, line 6.
Multiple breakpoints were set.
Use the "delete" command to delete unwanted breakpoints.
(gdb) c
Continuing.
Bpt 2, f_PSa_SI_SI ($this=(struct a *) 0xf7fffda0, i=5, j=6) (test.c line 10)
10 x = i;
(gdb) p x
$4 = -1
(gdb) i ad this
No symbol "this" in current context.
(gdb) p ad $this
No symbol "ad" in current context.
(gdb) i ad $this
Symbol "$this" is a local variable at frame offset 68.
(gdb) i ad x
Symbol "x" is a field of the local class variable `this'
(gdb) set x = 10
(gdb) p *$this
Attempt to take contents of a non-pointer value.
(gdb) p $this
$5 = void
(gdb) p x
$6 = 10
(gdb) quit
The program is running. Quit anyway? (y or n) y
yahi%
As you can see, GDB 3.1 now behaves more like a C++ debugger.
yahi% diff -c2 dbxout.c~ dbxout.c
*** dbxout.c~ Mon Feb 27 17:43:02 1989
--- dbxout.c Sat Mar 11 17:24:26 1989
***************
*** 523,527 ****
t = tem; /* Get to the FUNCTION_DECL */
dbxout_type (TREE_TYPE (t), 0); /* METHOD_TYPE */
- dbxout_args (TYPE_ARG_TYPES (TREE_TYPE (t)));
fprintf (asmfile, ":%s;%c%c",
IDENTIFIER_POINTER (DECL_NAME (t)),
--- 523,526 ----
***************
*** 575,579 ****
t = tem; /* Get to the FUNCTION_DECL */
dbxout_type (TREE_TYPE (t), 0); /* METHOD_TYPE */
- dbxout_args (TYPE_ARG_TYPES (TREE_TYPE (t)));
fprintf (asmfile, ":%s;%c%c",
IDENTIFIER_POINTER (DECL_NAME (t)),
--- 574,577 ----
***************
*** 695,698 ****
--- 693,697 ----
CHARS (1);
dbxout_type (TREE_TYPE (type), 0);
+ dbxout_args (TYPE_ARG_TYPES (type));
}
else
***************
*** 786,791 ****
break;
FORCE_TEXT;
fprintf (asmfile, ".stabs \"%s:%c",
! IDENTIFIER_POINTER (DECL_ORIGINAL_NAME (decl)),
TREE_PUBLIC (decl) ? 'F' : 'f');
--- 785,792 ----
break;
FORCE_TEXT;
+ /* For GDB 3.1, it may be better to use DECL_NAME (instead of DECL_ORIGINAL_NAME
+ in this case. */
fprintf (asmfile, ".stabs \"%s:%c",
! IDENTIFIER_POINTER (DECL_NAME (decl)),
TREE_PUBLIC (decl) ? 'F' : 'f');
yahi%
Michael