summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Brook <paul@codesourcery.com>2006-05-03 01:51:29 +0000
committerPaul Brook <paul@codesourcery.com>2006-05-03 01:51:29 +0000
commit38c25e15a68cc5d30329d62087b183ee23df05cc (patch)
treecc5a0de3f1ad6c58b5532e8de60e63c203b016a0
parent25f7e38cb7f32d3b033ec30bd162f2863fb79463 (diff)
downloadgdb-38c25e15a68cc5d30329d62087b183ee23df05cc.tar.gz
2006-05-03 Paul Brook <paul@codesourcery.com>
* gdb/dwarf2read.c (field_info): Add baseclasses. (dwarf2_add_field): Check base classes. (dwarf2_attach_fields_to_type): Ditto. * gdb/gnu-v3-abi.c (gnuv3_rtti_type): Check for NULL base_type. (gnuv3_virtual_fn_field): Handle missing base. (gnuv3_baseclass_offset): Handle missing vptr. * gdb/varobj.c (cplus_class_num_children): Call fill_in_vptr_fieldno. (cplus_name_of_child): Ditto. * gdb/eval.c (evaluate_subexp_standard): Ditto. * gdb/dwarf2read.c (read_structure_type): Search for vtable pointer by name in objects built by ARM compiler. * gdb/dwarf2read.c (dwarf2_add_member_fn): Calculate virtual function offset for classes without DW_AT_containing_type.
-rw-r--r--ChangeLog.csl18
-rw-r--r--gdb/dwarf2read.c96
-rw-r--r--gdb/eval.c1
-rw-r--r--gdb/gnu-v3-abi.c17
-rw-r--r--gdb/varobj.c2
5 files changed, 118 insertions, 16 deletions
diff --git a/ChangeLog.csl b/ChangeLog.csl
index 655a71cc44e..6360714e4ea 100644
--- a/ChangeLog.csl
+++ b/ChangeLog.csl
@@ -1,3 +1,21 @@
+2006-05-03 Paul Brook <paul@codesourcery.com>
+
+ * gdb/dwarf2read.c (field_info): Add baseclasses.
+ (dwarf2_add_field): Check base classes.
+ (dwarf2_attach_fields_to_type): Ditto.
+
+ * gdb/gnu-v3-abi.c (gnuv3_rtti_type): Check for NULL base_type.
+ (gnuv3_virtual_fn_field): Handle missing base.
+ (gnuv3_baseclass_offset): Handle missing vptr.
+ * gdb/varobj.c (cplus_class_num_children): Call fill_in_vptr_fieldno.
+ (cplus_name_of_child): Ditto.
+ * gdb/eval.c (evaluate_subexp_standard): Ditto.
+ * gdb/dwarf2read.c (read_structure_type): Search for vtable pointer
+ by name in objects built by ARM compiler.
+
+ * gdb/dwarf2read.c (dwarf2_add_member_fn): Calculate virtual function
+ offset for classes without DW_AT_containing_type.
+
2006-04-28 Mark Mitchell <mark@codesourcery.com>
* gdb/mt-tdep.c (mt_register_name): Correct out-of-range logic to
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 6fe9245f4a2..ecca17f11d1 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -604,9 +604,9 @@ struct field_info
int virtuality;
struct field field;
}
- *fields;
+ *fields, *baseclasses;
- /* Number of fields. */
+ /* Number of fields (including baseclasses). */
int nfields;
/* Number of baseclasses. */
@@ -3257,8 +3257,17 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
new_field = (struct nextfield *) xmalloc (sizeof (struct nextfield));
make_cleanup (xfree, new_field);
memset (new_field, 0, sizeof (struct nextfield));
- new_field->next = fip->fields;
- fip->fields = new_field;
+
+ if (die->tag == DW_TAG_inheritance)
+ {
+ new_field->next = fip->baseclasses;
+ fip->baseclasses = new_field;
+ }
+ else
+ {
+ new_field->next = fip->fields;
+ fip->fields = new_field;
+ }
fip->nfields++;
/* Handle accessibility and virtuality of field.
@@ -3464,8 +3473,21 @@ dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type,
up in the same order in the array in which they were added to the list. */
while (nfields-- > 0)
{
- TYPE_FIELD (type, nfields) = fip->fields->field;
- switch (fip->fields->accessibility)
+ struct nextfield *fieldp;
+
+ if (fip->fields)
+ {
+ fieldp = fip->fields;
+ fip->fields = fieldp->next;
+ }
+ else
+ {
+ fieldp = fip->baseclasses;
+ fip->baseclasses = fieldp->next;
+ }
+
+ TYPE_FIELD (type, nfields) = fieldp->field;
+ switch (fieldp->accessibility)
{
case DW_ACCESS_private:
SET_TYPE_FIELD_PRIVATE (type, nfields);
@@ -3482,13 +3504,13 @@ dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type,
/* Unknown accessibility. Complain and treat it as public. */
{
complaint (&symfile_complaints, _("unsupported accessibility %d"),
- fip->fields->accessibility);
+ fieldp->accessibility);
}
break;
}
if (nfields < fip->nbaseclasses)
{
- switch (fip->fields->virtuality)
+ switch (fieldp->virtuality)
{
case DW_VIRTUALITY_virtual:
case DW_VIRTUALITY_pure_virtual:
@@ -3496,7 +3518,6 @@ dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type,
break;
}
}
- fip->fields = fip->fields->next;
}
}
@@ -3620,9 +3641,14 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
if (attr && DW_UNSND (attr) != 0)
fnp->is_artificial = 1;
- /* Get index in virtual function table if it is a virtual member function. */
+ /* Get index in virtual function table if it is a virtual member
+ function. For GCC, this is an offset in the appropriate
+ virtual table, as specified by DW_AT_containing_type. For
+ everyone else, it is an expression to be evaluated relative
+ to the object address. */
+
attr = dwarf2_attr (die, DW_AT_vtable_elem_location, cu);
- if (attr)
+ if (attr && fnp->fcontext)
{
/* Support the .debug_loc offsets */
if (attr_form_is_block (attr))
@@ -3638,7 +3664,28 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
dwarf2_invalid_attrib_class_complaint ("DW_AT_vtable_elem_location",
fieldname);
}
- }
+ }
+ else if (attr)
+ {
+ /* We only support trivial expressions here. This hack will work
+ for v3 classes, which always start with the vtable pointer. */
+ if (attr_form_is_block (attr) && DW_BLOCK (attr)->size > 0
+ && DW_BLOCK (attr)->data[0] == DW_OP_deref)
+ {
+ struct dwarf_block blk;
+ blk.size = DW_BLOCK (attr)->size - 1;
+ blk.data = DW_BLOCK (attr)->data + 1;
+ fnp->voffset = decode_locdesc (&blk, cu);
+ if ((fnp->voffset % cu->header.addr_size) != 0)
+ dwarf2_complex_location_expr_complaint ();
+ else
+ fnp->voffset /= cu->header.addr_size;
+ fnp->voffset += 2;
+ fnp->fcontext = TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (die->type, 0));
+ }
+ else
+ dwarf2_complex_location_expr_complaint ();
+ }
}
/* Create the vector of member function fields, and attach it to the type. */
@@ -3825,7 +3872,8 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
/* Get the type which refers to the base class (possibly this
class itself) which contains the vtable pointer for the current
- class from the DW_AT_containing_type attribute. */
+ class from the DW_AT_containing_type attribute. This use of
+ DW_AT_containing_type is a GNU extension. */
if (dwarf2_attr (die, DW_AT_containing_type, cu) != NULL)
{
@@ -3884,6 +3932,28 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
}
}
}
+ else if (cu->producer
+ && strncmp (cu->producer,
+ "ARM/Thumb C/C++ Compiler, RVCT", 30) == 0)
+ {
+ /* The ARM compiler does not provide direct indication
+ of the containing type, but the vtable pointer is
+ always named __vptr. */
+
+ int i;
+
+ for (i = TYPE_NFIELDS (type) - 1;
+ i >= TYPE_N_BASECLASSES (type);
+ --i)
+ {
+ if (strcmp (TYPE_FIELD_NAME (type, i), "__vptr") == 0)
+ {
+ TYPE_VPTR_FIELDNO (type) = i;
+ TYPE_VPTR_BASETYPE (type) = type;
+ break;
+ }
+ }
+ }
}
do_cleanups (back_to);
diff --git a/gdb/eval.c b/gdb/eval.c
index 66776ea3cac..ac9a5ee19de 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -1035,6 +1035,7 @@ evaluate_subexp_standard (struct type *expect_type,
basetype = TYPE_TARGET_TYPE (value_type (arg2));
if (domain_type != basetype)
arg2 = value_cast (lookup_pointer_type (domain_type), arg2);
+ fill_in_vptr_fieldno (domain_type);
basetype = TYPE_VPTR_BASETYPE (domain_type);
for (i = TYPE_NFN_FIELDS (basetype) - 1; i >= 0; i--)
{
diff --git a/gdb/gnu-v3-abi.c b/gdb/gnu-v3-abi.c
index 383b475f1b1..c5fcfa7a5fa 100644
--- a/gdb/gnu-v3-abi.c
+++ b/gdb/gnu-v3-abi.c
@@ -216,7 +216,10 @@ gnuv3_rtti_type (struct value *value,
/* Fetch VALUE's virtual table pointer, and tweak it to point at
an instance of our imaginary gdb_gnu_v3_abi_vtable structure. */
- base_type = check_typedef (TYPE_VPTR_BASETYPE (values_type));
+ base_type = TYPE_VPTR_BASETYPE (values_type);
+ if (base_type == NULL)
+ return NULL;
+ base_type = check_typedef (base_type);
if (values_type != base_type)
{
value = value_cast (base_type, value);
@@ -302,6 +305,10 @@ gnuv3_virtual_fn_field (struct value **value_p,
multiple inheritance, but it's better than nothing. */
vfn_base = TYPE_VPTR_BASETYPE (type);
+ if (! vfn_base)
+ error (_("Could not find virtual table pointer for class \"%s\"."),
+ TYPE_TAG_NAME (type) ? TYPE_TAG_NAME (type) : "<unknown>");
+
/* This type may have been defined before its virtual function table
was. If so, fill in the virtual function table entry for the
type now. */
@@ -397,9 +404,13 @@ gnuv3_baseclass_offset (struct type *type, int index, const bfd_byte *valaddr,
start of whichever baseclass it resides in, as a sanity measure - iff
we have debugging information for that baseclass. */
+ if (TYPE_VPTR_FIELDNO (type) < 0)
+ fill_in_vptr_fieldno (type);
+ if (TYPE_VPTR_FIELDNO (type) < 0)
+ error (_("Could not find virtual table pointer for class \"%s\"."),
+ TYPE_TAG_NAME (type) ? TYPE_TAG_NAME (type) : "<unknown>");
+
vbasetype = TYPE_VPTR_BASETYPE (type);
- if (TYPE_VPTR_FIELDNO (vbasetype) < 0)
- fill_in_vptr_fieldno (vbasetype);
if (TYPE_VPTR_FIELDNO (vbasetype) >= 0
&& TYPE_FIELD_BITPOS (vbasetype, TYPE_VPTR_FIELDNO (vbasetype)) != 0)
diff --git a/gdb/varobj.c b/gdb/varobj.c
index 532d819917a..babb685fbf5 100644
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -2169,6 +2169,7 @@ cplus_class_num_children (struct type *type, int children[3])
children[v_private] = 0;
children[v_protected] = 0;
+ fill_in_vptr_fieldno (type);
for (i = TYPE_N_BASECLASSES (type); i < TYPE_NFIELDS (type); i++)
{
/* If we have a virtual table pointer, omit it. */
@@ -2218,6 +2219,7 @@ cplus_name_of_child (struct varobj *parent, int index)
have the access control we are looking for to properly
find the indexed field. */
int type_index = TYPE_N_BASECLASSES (type);
+ fill_in_vptr_fieldno (type);
if (strcmp (parent->name, "private") == 0)
{
while (index >= 0)