2002-01-04 Daniel Jacobowitz <drow@mvista.com>

* cp-abi.c: Fix whitespace.
        (baseclass_offset): New wrapper function.
        * cp-abi.h (baseclass_offset): Add prototype.
        (struct cp_abi_ops): Add baseclass_offset pointer.

        * valops.c (vb_match): Move to...
        * gnu-v2-abi.c (vb_match): here.
        * valops.c (baseclass_offset): Move to...
        * gnu-v2-abi.c (gnuv2_baseclass_offset): here, and rename.

        * gnu-v3-abi.c (gnuv3_baseclass_offset): New function.

        * gnu-v2-abi.c (init_gnuv2_ops): Initialize baseclass_offset.
        * gnu-v3-abi.c (init_gnuv3_ops): Likewise.
        * hpacc-abi.c (init_hpacc_ops): Likewise.
This commit is contained in:
Daniel Jacobowitz 2002-01-04 18:20:19 +00:00
parent 7f8c928258
commit 1514d34ee0
8 changed files with 205 additions and 97 deletions

View File

@ -1,3 +1,21 @@
2002-01-04 Daniel Jacobowitz <drow@mvista.com>
* cp-abi.c: Fix whitespace.
(baseclass_offset): New wrapper function.
* cp-abi.h (baseclass_offset): Add prototype.
(struct cp_abi_ops): Add baseclass_offset pointer.
* valops.c (vb_match): Move to...
* gnu-v2-abi.c (vb_match): here.
* valops.c (baseclass_offset): Move to...
* gnu-v2-abi.c (gnuv2_baseclass_offset): here, and rename.
* gnu-v3-abi.c (gnuv3_baseclass_offset): New function.
* gnu-v2-abi.c (init_gnuv2_ops): Initialize baseclass_offset.
* gnu-v3-abi.c (init_gnuv3_ops): Likewise.
* hpacc-abi.c (init_hpacc_ops): Likewise.
2002-01-04 Daniel Jacobowitz <drow@mvista.com>
* valops.c (find_overload_match): Accept obj as a

View File

@ -60,6 +60,15 @@ is_operator_name (const char *name)
return (*current_cp_abi.is_operator_name) (name);
}
int
baseclass_offset (struct type *type, int index, char *valaddr,
CORE_ADDR address)
{
if (current_cp_abi.baseclass_offset == NULL)
error ("ABI doesn't define required function baseclass_offset");
return (*current_cp_abi.baseclass_offset) (type, index, valaddr, address);
}
struct value *
value_virtual_fn_field (struct value **arg1p, struct fn_field * f, int j,
struct type * type, int offset)
@ -68,6 +77,7 @@ value_virtual_fn_field (struct value **arg1p, struct fn_field * f, int j,
return NULL;
return (*current_cp_abi.virtual_fn_field) (arg1p, f, j, type, offset);
}
struct type *
value_rtti_type (struct value *v, int *full, int *top, int *using_enc)
{

View File

@ -132,7 +132,17 @@ extern struct value *value_virtual_fn_field (struct value **valuep,
extern struct type *value_rtti_type (struct value *value,
int *full, int *top, int *using_enc);
/* Compute the offset of the baseclass which is
the INDEXth baseclass of class TYPE,
for value at VALADDR (in host) at ADDRESS (in target).
The result is the offset of the baseclass value relative
to (the address of)(ARG) + OFFSET.
-1 is returned on error. */
extern int baseclass_offset (struct type *type, int index, char *valaddr,
CORE_ADDR address);
struct cp_abi_ops
{
const char *shortname;
@ -148,6 +158,8 @@ struct cp_abi_ops
int j, struct type * type, int offset);
struct type *(*rtti_type) (struct value *v, int *full, int *top,
int *using_enc);
int (*baseclass_offset) (struct type *type, int index, char *valaddr,
CORE_ADDR address);
};

View File

@ -34,6 +34,8 @@
struct cp_abi_ops gnu_v2_abi_ops;
static int vb_match (struct type *, int, struct type *);
int gnuv2_baseclass_offset (struct type *type, int index, char *valaddr,
CORE_ADDR address);
static enum dtor_kinds
gnuv2_is_destructor_name (const char *name)
@ -308,6 +310,100 @@ gnuv2_value_rtti_type (struct value *v, int *full, int *top, int *using_enc)
return rtti_type;
}
/* Return true if the INDEXth field of TYPE is a virtual baseclass
pointer which is for the base class whose type is BASECLASS. */
static int
vb_match (struct type *type, int index, struct type *basetype)
{
struct type *fieldtype;
char *name = TYPE_FIELD_NAME (type, index);
char *field_class_name = NULL;
if (*name != '_')
return 0;
/* gcc 2.4 uses _vb$. */
if (name[1] == 'v' && name[2] == 'b' && is_cplus_marker (name[3]))
field_class_name = name + 4;
/* gcc 2.5 will use __vb_. */
if (name[1] == '_' && name[2] == 'v' && name[3] == 'b' && name[4] == '_')
field_class_name = name + 5;
if (field_class_name == NULL)
/* This field is not a virtual base class pointer. */
return 0;
/* It's a virtual baseclass pointer, now we just need to find out whether
it is for this baseclass. */
fieldtype = TYPE_FIELD_TYPE (type, index);
if (fieldtype == NULL
|| TYPE_CODE (fieldtype) != TYPE_CODE_PTR)
/* "Can't happen". */
return 0;
/* What we check for is that either the types are equal (needed for
nameless types) or have the same name. This is ugly, and a more
elegant solution should be devised (which would probably just push
the ugliness into symbol reading unless we change the stabs format). */
if (TYPE_TARGET_TYPE (fieldtype) == basetype)
return 1;
if (TYPE_NAME (basetype) != NULL
&& TYPE_NAME (TYPE_TARGET_TYPE (fieldtype)) != NULL
&& STREQ (TYPE_NAME (basetype),
TYPE_NAME (TYPE_TARGET_TYPE (fieldtype))))
return 1;
return 0;
}
/* Compute the offset of the baseclass which is
the INDEXth baseclass of class TYPE,
for value at VALADDR (in host) at ADDRESS (in target).
The result is the offset of the baseclass value relative
to (the address of)(ARG) + OFFSET.
-1 is returned on error. */
int
gnuv2_baseclass_offset (struct type *type, int index, char *valaddr,
CORE_ADDR address)
{
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);
/* First look for the virtual baseclass pointer
in the fields. */
for (i = n_baseclasses; i < len; i++)
{
if (vb_match (type, i, basetype))
{
CORE_ADDR addr
= unpack_pointer (TYPE_FIELD_TYPE (type, i),
valaddr + (TYPE_FIELD_BITPOS (type, i) / 8));
return addr - (LONGEST) address;
}
}
/* Not in the fields, so try looking through the baseclasses. */
for (i = index + 1; i < n_baseclasses; i++)
{
int boffset =
baseclass_offset (type, i, valaddr, address);
if (boffset)
return boffset;
}
/* Not found. */
return -1;
}
/* Baseclass is easily computed. */
return TYPE_BASECLASS_BITPOS (type, index) / 8;
}
static void
init_gnuv2_ops (void)
@ -321,6 +417,7 @@ init_gnuv2_ops (void)
gnu_v2_abi_ops.is_operator_name = gnuv2_is_operator_name;
gnu_v2_abi_ops.virtual_fn_field = gnuv2_virtual_fn_field;
gnu_v2_abi_ops.rtti_type = gnuv2_value_rtti_type;
gnu_v2_abi_ops.baseclass_offset = gnuv2_baseclass_offset;
}
void

View File

@ -339,6 +339,66 @@ gnuv3_virtual_fn_field (struct value **value_p,
return vfn;
}
/* Compute the offset of the baseclass which is
the INDEXth baseclass of class TYPE,
for value at VALADDR (in host) at ADDRESS (in target).
The result is the offset of the baseclass value relative
to (the address of)(ARG) + OFFSET.
-1 is returned on error. */
int
gnuv3_baseclass_offset (struct type *type, int index, char *valaddr,
CORE_ADDR address)
{
struct type *vtable_type = gdbarch_data (vtable_type_gdbarch_data);
struct type *basetype = TYPE_BASECLASS (type, index);
struct value *full_object, *vbase_object, *orig_object;
struct value *vtable, *orig_typeinfo, *orig_base_info;
struct type *orig_type, *vbasetype;
struct value *offset_val, *vbase_array;
CORE_ADDR vtable_address;
long int cur_base_offset, base_offset;
int to_top;
int baseclasses, i;
/* If it isn't a virtual base, this is easy. The offset is in the
type definition. */
if (!BASETYPE_VIA_VIRTUAL (type, index))
return TYPE_BASECLASS_BITPOS (type, index) / 8;
/* To access a virtual base, we need to use the vbase offset stored in
our vtable. Recent GCC versions provide this information. If it isn't
available, we could get what we needed from RTTI, or from drawing the
complete inheritance graph based on the debug info. Neither is
worthwhile. */
cur_base_offset = TYPE_BASECLASS_BITPOS (type, index) / 8;
if (cur_base_offset >= - vtable_address_point_offset ())
error ("Expected a negative vbase offset (old compiler?)");
cur_base_offset = cur_base_offset + vtable_address_point_offset ();
if ((- cur_base_offset) % TYPE_LENGTH (builtin_type_void_data_ptr) != 0)
error ("Misaligned vbase offset.");
cur_base_offset = cur_base_offset
/ ((int) TYPE_LENGTH (builtin_type_void_data_ptr));
/* We're now looking for the cur_base_offset'th entry (negative index)
in the vcall_and_vbase_offsets array. */
orig_object = value_at_lazy (type, address, NULL);
vbasetype = TYPE_VPTR_BASETYPE (VALUE_TYPE (orig_object));
vbase_object = value_cast (vbasetype, orig_object);
vtable_address
= value_as_address (value_field (vbase_object,
TYPE_VPTR_FIELDNO (vbasetype)));
vtable = value_at_lazy (vtable_type,
vtable_address - vtable_address_point_offset (),
NULL);
offset_val = value_from_longest(builtin_type_int, cur_base_offset);
vbase_array = value_field (vtable, vtable_field_vcall_and_vbase_offsets);
base_offset = value_as_long (value_subscript (vbase_array, offset_val));
return base_offset;
}
static void
init_gnuv3_ops (void)
@ -354,6 +414,7 @@ init_gnuv3_ops (void)
gnu_v3_abi_ops.is_operator_name = gnuv3_is_operator_name;
gnu_v3_abi_ops.rtti_type = gnuv3_rtti_type;
gnu_v3_abi_ops.virtual_fn_field = gnuv3_virtual_fn_field;
gnu_v3_abi_ops.baseclass_offset = gnuv3_baseclass_offset;
}

View File

@ -287,6 +287,8 @@ hpacc_value_rtti_type (struct value *v, int *full, int *top, int *using_enc)
return rtti_type;
}
extern int gnuv2_baseclass_offset (struct type *type, int index,
char *valaddr, CORE_ADDR address);
static void
init_hpacc_ops (void)
@ -300,6 +302,11 @@ init_hpacc_ops (void)
hpacc_abi_ops.is_operator_name = hpacc_is_operator_name;
hpacc_abi_ops.virtual_fn_field = hpacc_virtual_fn_field;
hpacc_abi_ops.rtti_type = hpacc_value_rtti_type;
/* It seems that this function is specific to GNU G++ < 3.0.
However, it is called for data members even in the HP
case (although not for member functions).
FIXME: Is that correct? */
hpacc_abi_ops.baseclass_offset = gnuv2_baseclass_offset;
}

View File

@ -547,8 +547,6 @@ extern void clear_internalvars (void);
extern struct value *value_copy (struct value *);
extern int baseclass_offset (struct type *, int, char *, CORE_ADDR);
/* From valops.c */
extern struct value *varying_to_slice (struct value *);

View File

@ -1098,101 +1098,6 @@ value_from_vtable_info (struct value *arg, struct type *type)
return value_headof (arg, 0, type);
}
/* Return true if the INDEXth field of TYPE is a virtual baseclass
pointer which is for the base class whose type is BASECLASS. */
static int
vb_match (struct type *type, int index, struct type *basetype)
{
struct type *fieldtype;
char *name = TYPE_FIELD_NAME (type, index);
char *field_class_name = NULL;
if (*name != '_')
return 0;
/* gcc 2.4 uses _vb$. */
if (name[1] == 'v' && name[2] == 'b' && is_cplus_marker (name[3]))
field_class_name = name + 4;
/* gcc 2.5 will use __vb_. */
if (name[1] == '_' && name[2] == 'v' && name[3] == 'b' && name[4] == '_')
field_class_name = name + 5;
if (field_class_name == NULL)
/* This field is not a virtual base class pointer. */
return 0;
/* It's a virtual baseclass pointer, now we just need to find out whether
it is for this baseclass. */
fieldtype = TYPE_FIELD_TYPE (type, index);
if (fieldtype == NULL
|| TYPE_CODE (fieldtype) != TYPE_CODE_PTR)
/* "Can't happen". */
return 0;
/* What we check for is that either the types are equal (needed for
nameless types) or have the same name. This is ugly, and a more
elegant solution should be devised (which would probably just push
the ugliness into symbol reading unless we change the stabs format). */
if (TYPE_TARGET_TYPE (fieldtype) == basetype)
return 1;
if (TYPE_NAME (basetype) != NULL
&& TYPE_NAME (TYPE_TARGET_TYPE (fieldtype)) != NULL
&& STREQ (TYPE_NAME (basetype),
TYPE_NAME (TYPE_TARGET_TYPE (fieldtype))))
return 1;
return 0;
}
/* Compute the offset of the baseclass which is
the INDEXth baseclass of class TYPE,
for value at VALADDR (in host) at ADDRESS (in target).
The result is the offset of the baseclass value relative
to (the address of)(ARG) + OFFSET.
-1 is returned on error. */
int
baseclass_offset (struct type *type, int index, char *valaddr,
CORE_ADDR address)
{
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);
/* First look for the virtual baseclass pointer
in the fields. */
for (i = n_baseclasses; i < len; i++)
{
if (vb_match (type, i, basetype))
{
CORE_ADDR addr
= unpack_pointer (TYPE_FIELD_TYPE (type, i),
valaddr + (TYPE_FIELD_BITPOS (type, i) / 8));
return addr - (LONGEST) address;
}
}
/* Not in the fields, so try looking through the baseclasses. */
for (i = index + 1; i < n_baseclasses; i++)
{
int boffset =
baseclass_offset (type, i, valaddr, address);
if (boffset)
return boffset;
}
/* Not found. */
return -1;
}
/* Baseclass is easily computed. */
return TYPE_BASECLASS_BITPOS (type, index) / 8;
}
/* Unpack a field FIELDNO of the specified TYPE, from the anonymous object at
VALADDR.