From 0d564a3135fb9efc029ac00a3822130a23522c1b Mon Sep 17 00:00:00 2001 From: Daniel Jacobowitz Date: Thu, 12 Nov 2009 19:10:06 +0000 Subject: [PATCH] 2009-11-12 Paul Brook Daniel Jacobowitz * dwarf2read.c (dwarf2_add_member_fn): Calculate virtual function offset for classes without DW_AT_containing_type. --- gdb/ChangeLog | 6 ++++++ gdb/dwarf2read.c | 35 +++++++++++++++++++++++++++++++---- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index f8fadf6f25..a2dbfaae42 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,9 @@ +2009-11-12 Paul Brook + Daniel Jacobowitz + + * dwarf2read.c (dwarf2_add_member_fn): Calculate virtual function + offset for classes without DW_AT_containing_type. + 2009-11-12 Paul Brook Daniel Jacobowitz diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 8ba61b1a68..33a83e2a67 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -4758,9 +4758,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)) @@ -4776,7 +4781,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 (this_type, 0)); + } + else + dwarf2_complex_location_expr_complaint (); + } } /* Create the vector of member function fields, and attach it to the type. */ @@ -5038,7 +5064,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) { -- 2.34.1