diff options
-rw-r--r-- | ChangeLog.csl | 18 | ||||
-rw-r--r-- | gdb/dwarf2read.c | 96 | ||||
-rw-r--r-- | gdb/eval.c | 1 | ||||
-rw-r--r-- | gdb/gnu-v3-abi.c | 17 | ||||
-rw-r--r-- | gdb/varobj.c | 2 |
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) |