From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9060 invoked by alias); 27 Nov 2001 01:19:40 -0000 Mailing-List: contact gdb-patches-help@sourceware.cygnus.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 8979 invoked from network); 27 Nov 2001 01:19:27 -0000 Received: from unknown (HELO nevyn.them.org) (128.2.145.6) by hostedprojects.ges.redhat.com with SMTP; 27 Nov 2001 01:19:27 -0000 Received: from drow by nevyn.them.org with local (Exim 3.32 #1 (Debian)) id 168WuX-0007y4-00 for ; Mon, 26 Nov 2001 20:19:45 -0500 Date: Tue, 13 Nov 2001 09:24:00 -0000 From: Daniel Jacobowitz To: gdb-patches@sources.redhat.com Subject: [RFA/c++] Fix printing classes with virtual base classes Message-ID: <20011126201945.A27754@nevyn.them.org> Mail-Followup-To: gdb-patches@sources.redhat.com Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.3.23i X-SW-Source: 2001-11/txt/msg00251.txt.bz2 Whew. Finally tracked this down. The problem is in the layout of a class whose base class has a virtual table. Given: class Bar { virtual int thunk (); }; class Foo : public Bar { int test; }; A Foo will look like this: /-----------------------\ | Foo | test | \-----------------------/ Its own vptr will be conveniently Foo's vptr. But the type of Bar's field 0 (which is marked as having the vptr in it) is Foo, not some pointer type. If I explicitly cast to pointer, everything works more-or-less OK. I'm pretty sure of the C++ side of this. If there's a more appropriate function for doing the cast to pointer I'd love to hear about it; otherwise, OK to commit? Can't really tell what effect it has on the testsuite, as just about everything else in the relevant tests is failing anyway. I have a few more low-hanging bugs in this area that I'm debugging now. -- Daniel Jacobowitz Carnegie Mellon University MontaVista Software Debian GNU/Linux Developer 2001-11-26 Daniel Jacobowitz * gnu-v3-abi.c (gnuv3_rtti_type): Explicitly cast the vtable pointer to a pointer before loading it. (gnuv3_virtual_fn_field): Likewise. Index: gnu-v3-abi.c =================================================================== RCS file: /cvs/src/src/gdb/gnu-v3-abi.c,v retrieving revision 1.4 diff -u -p -r1.4 gnu-v3-abi.c --- gnu-v3-abi.c 2001/10/16 01:58:07 1.4 +++ gnu-v3-abi.c 2001/11/27 00:21:44 @@ -188,7 +188,7 @@ gnuv3_rtti_type (struct value *value, struct type *vtable_type = gdbarch_data (vtable_type_gdbarch_data); struct type *value_type = check_typedef (VALUE_TYPE (value)); CORE_ADDR vtable_address; - struct value *vtable; + struct value *vtable, *vtable_addr_value; struct minimal_symbol *vtable_symbol; const char *vtable_symbol_name; const char *class_name; @@ -207,9 +207,17 @@ gnuv3_rtti_type (struct value *value, return NULL; /* Fetch VALUE's virtual table pointer, and tweak it to point at - an instance of our imaginary gdb_gnu_v3_abi_vtable structure. */ + an instance of our imaginary gdb_gnu_v3_abi_vtable structure. + The type of the field may not be a pointer type. In a derived + class with a virtual base class, it will be the type of the base + class. Thus we need to cast. */ + vtable_addr_value = + value_at (builtin_type_void_data_ptr, + VALUE_ADDRESS (value_field (value, + TYPE_VPTR_FIELDNO (value_type))), + VALUE_BFD_SECTION (value)); vtable_address - = value_as_address (value_field (value, TYPE_VPTR_FIELDNO (value_type))); + = value_as_address (vtable_addr_value); vtable = value_at_lazy (vtable_type, vtable_address - vtable_address_point_offset (), VALUE_BFD_SECTION (value)); @@ -277,7 +285,7 @@ gnuv3_virtual_fn_field (struct value **v struct type *value_type = check_typedef (VALUE_TYPE (value)); struct type *vfn_base; CORE_ADDR vtable_address; - struct value *vtable; + struct value *vtable, *vtable_addr_value; struct value *vfn; /* Some simple sanity checks. */ @@ -309,9 +317,16 @@ gnuv3_virtual_fn_field (struct value **v value = value_ind (value_cast (vfn_base, value_addr (value))); /* Now value is an object of the appropriate base type. Fetch its - virtual table. */ + virtual table. As in gnuv3_rtti_type, the type of the field may + not be a pointer type. In a derived class with a virtual base class, + it will be the type of the base class. Thus we need to cast. */ + vtable_addr_value = + value_at (builtin_type_void_data_ptr, + VALUE_ADDRESS (value_field (value, + TYPE_VPTR_FIELDNO (vfn_base))), + VALUE_BFD_SECTION (value)); vtable_address - = value_as_address (value_field (value, TYPE_VPTR_FIELDNO (vfn_base))); + = value_as_address (vtable_addr_value); vtable = value_at_lazy (vtable_type, vtable_address - vtable_address_point_offset (), VALUE_BFD_SECTION (value)); From mboxrd@z Thu Jan 1 00:00:00 1970 From: Daniel Jacobowitz To: gdb-patches@sources.redhat.com Subject: [RFA/c++] Fix printing classes with virtual base classes Date: Mon, 26 Nov 2001 17:19:00 -0000 Message-ID: <20011126201945.A27754@nevyn.them.org> X-SW-Source: 2001-11/msg00466.html Message-ID: <20011126171900.4m-AliJedmKI-mh_zz6Di5HHCwRb67BVjyFAL8JG0OQ@z> Whew. Finally tracked this down. The problem is in the layout of a class whose base class has a virtual table. Given: class Bar { virtual int thunk (); }; class Foo : public Bar { int test; }; A Foo will look like this: /-----------------------\ | Foo | test | \-----------------------/ Its own vptr will be conveniently Foo's vptr. But the type of Bar's field 0 (which is marked as having the vptr in it) is Foo, not some pointer type. If I explicitly cast to pointer, everything works more-or-less OK. I'm pretty sure of the C++ side of this. If there's a more appropriate function for doing the cast to pointer I'd love to hear about it; otherwise, OK to commit? Can't really tell what effect it has on the testsuite, as just about everything else in the relevant tests is failing anyway. I have a few more low-hanging bugs in this area that I'm debugging now. -- Daniel Jacobowitz Carnegie Mellon University MontaVista Software Debian GNU/Linux Developer 2001-11-26 Daniel Jacobowitz * gnu-v3-abi.c (gnuv3_rtti_type): Explicitly cast the vtable pointer to a pointer before loading it. (gnuv3_virtual_fn_field): Likewise. Index: gnu-v3-abi.c =================================================================== RCS file: /cvs/src/src/gdb/gnu-v3-abi.c,v retrieving revision 1.4 diff -u -p -r1.4 gnu-v3-abi.c --- gnu-v3-abi.c 2001/10/16 01:58:07 1.4 +++ gnu-v3-abi.c 2001/11/27 00:21:44 @@ -188,7 +188,7 @@ gnuv3_rtti_type (struct value *value, struct type *vtable_type = gdbarch_data (vtable_type_gdbarch_data); struct type *value_type = check_typedef (VALUE_TYPE (value)); CORE_ADDR vtable_address; - struct value *vtable; + struct value *vtable, *vtable_addr_value; struct minimal_symbol *vtable_symbol; const char *vtable_symbol_name; const char *class_name; @@ -207,9 +207,17 @@ gnuv3_rtti_type (struct value *value, return NULL; /* Fetch VALUE's virtual table pointer, and tweak it to point at - an instance of our imaginary gdb_gnu_v3_abi_vtable structure. */ + an instance of our imaginary gdb_gnu_v3_abi_vtable structure. + The type of the field may not be a pointer type. In a derived + class with a virtual base class, it will be the type of the base + class. Thus we need to cast. */ + vtable_addr_value = + value_at (builtin_type_void_data_ptr, + VALUE_ADDRESS (value_field (value, + TYPE_VPTR_FIELDNO (value_type))), + VALUE_BFD_SECTION (value)); vtable_address - = value_as_address (value_field (value, TYPE_VPTR_FIELDNO (value_type))); + = value_as_address (vtable_addr_value); vtable = value_at_lazy (vtable_type, vtable_address - vtable_address_point_offset (), VALUE_BFD_SECTION (value)); @@ -277,7 +285,7 @@ gnuv3_virtual_fn_field (struct value **v struct type *value_type = check_typedef (VALUE_TYPE (value)); struct type *vfn_base; CORE_ADDR vtable_address; - struct value *vtable; + struct value *vtable, *vtable_addr_value; struct value *vfn; /* Some simple sanity checks. */ @@ -309,9 +317,16 @@ gnuv3_virtual_fn_field (struct value **v value = value_ind (value_cast (vfn_base, value_addr (value))); /* Now value is an object of the appropriate base type. Fetch its - virtual table. */ + virtual table. As in gnuv3_rtti_type, the type of the field may + not be a pointer type. In a derived class with a virtual base class, + it will be the type of the base class. Thus we need to cast. */ + vtable_addr_value = + value_at (builtin_type_void_data_ptr, + VALUE_ADDRESS (value_field (value, + TYPE_VPTR_FIELDNO (vfn_base))), + VALUE_BFD_SECTION (value)); vtable_address - = value_as_address (value_field (value, TYPE_VPTR_FIELDNO (vfn_base))); + = value_as_address (vtable_addr_value); vtable = value_at_lazy (vtable_type, vtable_address - vtable_address_point_offset (), VALUE_BFD_SECTION (value));