This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[commit] Handle virtual functions without a GCC extension


GDB only supports the form of DW_AT_vtable_elem_location generated by
GCC:

 <2><23c>: Abbrev Number: 12 (DW_TAG_subprogram)
    <23d>   DW_AT_external    : 1
    <23e>   DW_AT_name        : vvb
    <242>   DW_AT_decl_file   : 1
    <243>   DW_AT_decl_line   : 220
    <244>   DW_AT_MIPS_linkage_name: (indirect string, offset: 0xf6): _ZN2VB3vvbEv
    <248>   DW_AT_type        : <0x1c7>
    <24c>   DW_AT_virtuality  : 1       (virtual)
    <24d>   DW_AT_vtable_elem_location: 2 byte block: 10 0 (DW_OP_constu: 0)
    <250>   DW_AT_containing_type: <0x1ce>
    <254>   DW_AT_declaration : 1

This means that the vtable is in the zero'th virtual function slot, in
the virtual table contained in the type at DIE 0x1ce.  But the DWARF
standard does not define the meaning of DW_AT_containing_type here and
this directly conflicts with how the standard defines
DW_AT_vtable_elem_location: an expression that, given the address of
the enclosing type on the stack, yields the address of the slot for
the function.

This patch uses the current behavior if DW_AT_containing_type was
seen, and otherwise implements limited support for the normal
semantics of DW_AT_vtable_elem_location.  The limited support is
necessary because the rest of GCC expects a static integer voffset,
and it is currently sufficient because we expect DW_OP_deref at the
start of the expression for any program using the Itanium C++ ABI.

Tested on arm-none-eabi (RealView and GCC) and on x86_64-linux.
Checked in.

2009-11-12  Paul Brook  <paul@codesourcery.com>
	    Daniel Jacobowitz  <dan@codesourcery.com>

	* dwarf2read.c (dwarf2_add_member_fn): Calculate virtual function
	offset for classes without DW_AT_containing_type.

---
 gdb/dwarf2read.c |   35 +++++++++++++++++++++++++++++++----
 1 file changed, 31 insertions(+), 4 deletions(-)

Index: gdb-mainline/gdb/dwarf2read.c
===================================================================
--- gdb-mainline.orig/gdb/dwarf2read.c	2009-11-11 11:28:06.000000000 -0800
+++ gdb-mainline/gdb/dwarf2read.c	2009-11-11 12:16:11.000000000 -0800
@@ -4756,9 +4756,14 @@ dwarf2_add_member_fn (struct field_info 
   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))
@@ -4774,7 +4779,28 @@ dwarf2_add_member_fn (struct field_info 
 	  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.  */
@@ -5036,7 +5062,8 @@ read_structure_type (struct die_info *di
 
 	  /* 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)
 	    {

-- 
Daniel Jacobowitz
CodeSourcery


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]