mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-21 01:12:32 +08:00
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:
parent
7f8c928258
commit
1514d34ee0
@ -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
|
||||
|
10
gdb/cp-abi.c
10
gdb/cp-abi.c
@ -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)
|
||||
{
|
||||
|
12
gdb/cp-abi.h
12
gdb/cp-abi.h
@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 *);
|
||||
|
95
gdb/values.c
95
gdb/values.c
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user