mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-29 10:30:46 +00:00
A bunch of changes mostly to improve debugging of C++ programs.
Specifically, the calling of inferiors methods is improved. * value.h: New macros METHOD_PTR_IS_VIRTUAL, METHOD_PTR_FROM_VOFFSET, METHOD_PTR_TO_VOFFSET to partially hide the implementation details of pointer-to-method objects. How to tell if the pointer points to a virtual method is still very dependent on the particular compiler, but this should make it easier to find the places to change. * eval.c (evaluate_subexp [case OP_FUNCALL]), valprint.c (val_print [case TYPE_CODE_PTR]): Use the new METHOD_PTR_* macros, instead of a hard-wired-in code that incorrectly assumed a no-longerused representation of pointer-to-method values. And otherwise fix the relevant bit-rotted code. * valprint.c (type_print_base [case TYPE_CODE_STRUCT]): If there are both fields and methods, put a space between. * stabsread.c (read_struct_type): Fix bug in handling of GNU C++ anonymous type (indicated by CPLUS_MARKER followed by '_'). (It used to prematurely exit the loop reading in the fields, so it would think it should start reading methods while still in the fields. This could crash gdb given a gcc that can emit nested type information.) * valops.c (search_struct_method): Pass 'this' value by reference instead of by value. This provides a more consistent interface through a recursive search where the "bottom" functions may need to adjust offsets (due to multiple inheritance). * valops.c, value.h, values.c: Pass extra parameters to value_fn_field and value_virtual_fn_field so we can correctly adjust offset for multiple inheritance. * eval.c (evaluate_subexp [case OP_FUNCALL]): Simplify virtual function calls by using value_virtual_fn_field(). * values.c: New function baseclass_offset, derived from baseclass_addr (which perhaps can be made obsolete?). It returns an offset rather than an address. This is a cleaner interface since it doesn't mess around allocating new values. * valops.c (search_struct_method): Use baseclass_offset rather than baseclass_addr.
This commit is contained in:
@@ -1,3 +1,48 @@
|
||||
Fri Sep 4 00:34:30 1992 Per Bothner (bothner@rtl.cygnus.com)
|
||||
|
||||
A bunch of changes mostly to improve debugging of C++ programs.
|
||||
Specifically, the calling of inferiors methods is improved.
|
||||
|
||||
* value.h: New macros METHOD_PTR_IS_VIRTUAL,
|
||||
METHOD_PTR_FROM_VOFFSET, METHOD_PTR_TO_VOFFSET to partially
|
||||
hide the implementation details of pointer-to-method objects.
|
||||
How to tell if the pointer points to a virtual method is
|
||||
still very dependent on the particular compiler, but this
|
||||
should make it easier to find the places to change.
|
||||
* eval.c (evaluate_subexp [case OP_FUNCALL]), valprint.c
|
||||
(val_print [case TYPE_CODE_PTR]): Use the new METHOD_PTR_*
|
||||
macros, instead of a hard-wired-in code that incorrectly
|
||||
assumed a no-longerused representation of pointer-to-method
|
||||
values. And otherwise fix the relevant bit-rotted code.
|
||||
|
||||
* valprint.c (type_print_base [case TYPE_CODE_STRUCT]):
|
||||
If there are both fields and methods, put a space between.
|
||||
|
||||
* stabsread.c (read_struct_type): Fix bug in handling of
|
||||
GNU C++ anonymous type (indicated by CPLUS_MARKER followed
|
||||
by '_'). (It used to prematurely exit the loop reading in
|
||||
the fields, so it would think it should start reading
|
||||
methods while still in the fields. This could crash gdb
|
||||
given a gcc that can emit nested type information.)
|
||||
|
||||
* valops.c (search_struct_method): Pass 'this' value by
|
||||
reference instead of by value. This provides a more
|
||||
consistent interface through a recursive search where the
|
||||
"bottom" functions may need to adjust offsets (due to multiple
|
||||
inheritance).
|
||||
* valops.c, value.h, values.c: Pass extra parameters to
|
||||
value_fn_field and value_virtual_fn_field so we can
|
||||
correctly adjust offset for multiple inheritance.
|
||||
* eval.c (evaluate_subexp [case OP_FUNCALL]): Simplify
|
||||
virtual function calls by using value_virtual_fn_field().
|
||||
* values.c: New function baseclass_offset, derived from
|
||||
baseclass_addr (which perhaps can be made obsolete?).
|
||||
It returns an offset rather than an address. This is a
|
||||
cleaner interface since it doesn't mess around allocating
|
||||
new values.
|
||||
* valops.c (search_struct_method): Use baseclass_offset
|
||||
rather than baseclass_addr.
|
||||
|
||||
Mon Oct 5 16:02:04 1992 Stu Grossman (grossman at cygnus.com)
|
||||
|
||||
* Makefile.in: Re-install 29K/UDI stuff.
|
||||
|
||||
@@ -1430,8 +1430,10 @@ read_struct_type (pp, type, objfile)
|
||||
p = *pp;
|
||||
if (*p == CPLUS_MARKER)
|
||||
{
|
||||
if (*p == '_') /* GNU C++ anonymous type. */
|
||||
;
|
||||
/* Special GNU C++ name. */
|
||||
if (*++p == 'v')
|
||||
else if (*++p == 'v')
|
||||
{
|
||||
const char *prefix;
|
||||
char *name = 0;
|
||||
@@ -1470,15 +1472,12 @@ read_struct_type (pp, type, objfile)
|
||||
list->field.bitsize = 0;
|
||||
list->visibility = 0; /* private */
|
||||
non_public_fields++;
|
||||
|
||||
nfields++;
|
||||
continue;
|
||||
}
|
||||
/* GNU C++ anonymous type. */
|
||||
else if (*p == '_')
|
||||
break;
|
||||
else
|
||||
complain (&invalid_cpp_abbrev_complaint, *pp);
|
||||
|
||||
nfields++;
|
||||
continue;
|
||||
}
|
||||
|
||||
while (*p != ':') p++;
|
||||
|
||||
100
gdb/values.c
100
gdb/values.c
@@ -903,12 +903,15 @@ value_field (arg1, fieldno)
|
||||
J is an index into F which provides the desired method. */
|
||||
|
||||
value
|
||||
value_fn_field (f, j)
|
||||
value_fn_field (arg1p, f, j, type, offset)
|
||||
value *arg1p;
|
||||
struct fn_field *f;
|
||||
int j;
|
||||
struct type *type;
|
||||
int offset;
|
||||
{
|
||||
register value v;
|
||||
register struct type *type = TYPE_FN_FIELD_TYPE (f, j);
|
||||
register struct type *ftype = TYPE_FN_FIELD_TYPE (f, j);
|
||||
struct symbol *sym;
|
||||
|
||||
sym = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j),
|
||||
@@ -916,27 +919,40 @@ value_fn_field (f, j)
|
||||
if (! sym) error ("Internal error: could not find physical method named %s",
|
||||
TYPE_FN_FIELD_PHYSNAME (f, j));
|
||||
|
||||
v = allocate_value (type);
|
||||
v = allocate_value (ftype);
|
||||
VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
|
||||
VALUE_TYPE (v) = type;
|
||||
VALUE_TYPE (v) = ftype;
|
||||
|
||||
if (arg1p)
|
||||
{
|
||||
if (type != VALUE_TYPE (*arg1p))
|
||||
*arg1p = value_ind (value_cast (lookup_pointer_type (type),
|
||||
value_addr (*arg1p)));
|
||||
|
||||
/* Move the `this' pointer according to the offset. */
|
||||
VALUE_OFFSET (*arg1p) += offset;
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/* Return a virtual function as a value.
|
||||
ARG1 is the object which provides the virtual function
|
||||
table pointer. ARG1 is side-effected in calling this function.
|
||||
table pointer. *ARG1P is side-effected in calling this function.
|
||||
F is the list of member functions which contains the desired virtual
|
||||
function.
|
||||
J is an index into F which provides the desired virtual function.
|
||||
|
||||
TYPE is the type in which F is located. */
|
||||
value
|
||||
value_virtual_fn_field (arg1, f, j, type)
|
||||
value arg1;
|
||||
value_virtual_fn_field (arg1p, f, j, type, offset)
|
||||
value *arg1p;
|
||||
struct fn_field *f;
|
||||
int j;
|
||||
struct type *type;
|
||||
int offset;
|
||||
{
|
||||
value arg1 = *arg1p;
|
||||
/* First, get the virtual function table pointer. That comes
|
||||
with a strange type, so cast it to type `pointer to long' (which
|
||||
should serve just fine as a function type). Then, index into
|
||||
@@ -968,7 +984,9 @@ value_virtual_fn_field (arg1, f, j, 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 (context)));
|
||||
vtbl = value_ind (value_primitive_field (arg1, 0,
|
||||
TYPE_VPTR_FIELDNO (context),
|
||||
TYPE_VPTR_BASETYPE (context)));
|
||||
|
||||
/* Index into the virtual function table. This is hard-coded because
|
||||
looking up a field is not cheap, and it may be important to save
|
||||
@@ -977,7 +995,7 @@ value_virtual_fn_field (arg1, f, j, type)
|
||||
entry = value_subscript (vtbl, vi);
|
||||
|
||||
/* Move the `this' pointer according to the virtual function table. */
|
||||
VALUE_OFFSET (arg1) += value_as_long (value_field (entry, 0));
|
||||
VALUE_OFFSET (arg1) += value_as_long (value_field (entry, 0)) + offset;
|
||||
if (! VALUE_LAZY (arg1))
|
||||
{
|
||||
VALUE_LAZY (arg1) = 1;
|
||||
@@ -988,6 +1006,7 @@ value_virtual_fn_field (arg1, f, j, type)
|
||||
/* Reinstantiate the function pointer with the correct type. */
|
||||
VALUE_TYPE (vfn) = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j));
|
||||
|
||||
*arg1p = arg1;
|
||||
return vfn;
|
||||
}
|
||||
|
||||
@@ -1103,6 +1122,67 @@ value_from_vtable_info (arg, type)
|
||||
return value_headof (arg, 0, type);
|
||||
}
|
||||
|
||||
/* Compute the offset of the baseclass which is
|
||||
the INDEXth baseclass of class TYPE, for a value ARG,
|
||||
wih extra offset of OFFSET.
|
||||
The result is the offste of the baseclass value relative
|
||||
to (the address of)(ARG) + OFFSET.
|
||||
|
||||
-1 is returned on error. */
|
||||
|
||||
int
|
||||
baseclass_offset (type, index, arg, offset)
|
||||
struct type *type;
|
||||
int index;
|
||||
value arg;
|
||||
int offset;
|
||||
{
|
||||
struct type *basetype = TYPE_BASECLASS (type, index);
|
||||
|
||||
if (BASETYPE_VIA_VIRTUAL (type, index))
|
||||
{
|
||||
/* Must hunt for the pointer to this virtual baseclass. */
|
||||
register int i, len = TYPE_NFIELDS (type);
|
||||
register int n_baseclasses = TYPE_N_BASECLASSES (type);
|
||||
char *vbase_name, *type_name = type_name_no_tag (basetype);
|
||||
|
||||
vbase_name = (char *)alloca (strlen (type_name) + 8);
|
||||
sprintf (vbase_name, "_vb%c%s", CPLUS_MARKER, type_name);
|
||||
/* First look for the virtual baseclass pointer
|
||||
in the fields. */
|
||||
for (i = n_baseclasses; i < len; i++)
|
||||
{
|
||||
if (! strcmp (vbase_name, TYPE_FIELD_NAME (type, i)))
|
||||
{
|
||||
CORE_ADDR addr
|
||||
= unpack_pointer (TYPE_FIELD_TYPE (type, i),
|
||||
VALUE_CONTENTS (arg) + VALUE_OFFSET (arg)
|
||||
+ offset
|
||||
+ (TYPE_FIELD_BITPOS (type, i) / 8));
|
||||
|
||||
if (VALUE_LVAL (arg) != lval_memory)
|
||||
return -1;
|
||||
|
||||
return addr -
|
||||
(LONGEST) (VALUE_ADDRESS (arg) + VALUE_OFFSET (arg) + offset);
|
||||
}
|
||||
}
|
||||
/* Not in the fields, so try looking through the baseclasses. */
|
||||
for (i = index+1; i < n_baseclasses; i++)
|
||||
{
|
||||
int boffset =
|
||||
baseclass_offset (type, i, arg, offset);
|
||||
if (boffset)
|
||||
return boffset;
|
||||
}
|
||||
/* Not found. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Baseclass is easily computed. */
|
||||
return TYPE_BASECLASS_BITPOS (type, index) / 8;
|
||||
}
|
||||
|
||||
/* Compute the address of the baseclass which is
|
||||
the INDEXth baseclass of class TYPE. The TYPE base
|
||||
of the object is at VALADDR.
|
||||
@@ -1112,6 +1192,8 @@ value_from_vtable_info (arg, type)
|
||||
of the baseclasss, but the address which could not be read
|
||||
successfully. */
|
||||
|
||||
/* FIXME Fix remaining uses of baseclass_addr to use baseclass_offset */
|
||||
|
||||
char *
|
||||
baseclass_addr (type, index, valaddr, valuep, errp)
|
||||
struct type *type;
|
||||
|
||||
Reference in New Issue
Block a user