aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog18
-rw-r--r--gdb/cp-abi.c10
-rw-r--r--gdb/cp-abi.h12
-rw-r--r--gdb/gnu-v2-abi.c97
-rw-r--r--gdb/gnu-v3-abi.c61
-rw-r--r--gdb/hpacc-abi.c7
-rw-r--r--gdb/value.h2
-rw-r--r--gdb/values.c95
8 files changed, 205 insertions, 97 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 0f2c835..27ecf63 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,23 @@
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
reference parameter. Update it before returning.
* value.h (find_overload_match): Update prototype.
diff --git a/gdb/cp-abi.c b/gdb/cp-abi.c
index b9dac53..d4eb0a0 100644
--- a/gdb/cp-abi.c
+++ b/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)
{
diff --git a/gdb/cp-abi.h b/gdb/cp-abi.h
index ae62478..7c1e952 100644
--- a/gdb/cp-abi.h
+++ b/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);
};
diff --git a/gdb/gnu-v2-abi.c b/gdb/gnu-v2-abi.c
index ef46055..2b086c5 100644
--- a/gdb/gnu-v2-abi.c
+++ b/gdb/gnu-v2-abi.c
@@ -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
diff --git a/gdb/gnu-v3-abi.c b/gdb/gnu-v3-abi.c
index b9cc0db..93bc995 100644
--- a/gdb/gnu-v3-abi.c
+++ b/gdb/gnu-v3-abi.c
@@ -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;
}
diff --git a/gdb/hpacc-abi.c b/gdb/hpacc-abi.c
index 4dcb1c3..6753cd7 100644
--- a/gdb/hpacc-abi.c
+++ b/gdb/hpacc-abi.c
@@ -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;
}
diff --git a/gdb/value.h b/gdb/value.h
index a6a517c..78f615f 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -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 *);
diff --git a/gdb/values.c b/gdb/values.c
index 4546622..68230e6 100644
--- a/gdb/values.c
+++ b/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.