Re: [RFA/c++] Fix printing classes with virtual base classes

Daniel Jacobowitz
2001-11-27T02:02:28Z

On Mon, Nov 26, 2001 at 08:19:45PM -0500, Daniel Jacobowitz wrote:
> Whew. Finally tracked this down.

[snip correct explanation]

[snip incorrect patch]

I find the use of VALUE_OFFSET and VALUE_EMBEDDED_OFFSET exceedingly
unintuitive. Go figure. This one works a little bit better yet.

--
Daniel Jacobowitz Carnegie Mellon University
MontaVista Software Debian GNU/Linux Developer

2001-11-26 Daniel Jacobowitz <drow@mvista.com>

* 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 02:00:22
@@ -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, *vtable_field;
struct minimal_symbol *vtable_symbol;
const char *vtable_symbol_name;
const char *class_name;
@@ -207,9 +207,20 @@ 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_field = value_field (value,
+ TYPE_VPTR_FIELDNO (value_type));
+ vtable_addr_value =
+ value_at (builtin_type_void_data_ptr,
+ VALUE_ADDRESS (vtable_field)
+ + VALUE_OFFSET (vtable_field)
+ + VALUE_EMBEDDED_OFFSET (vtable_field),
+ 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 +288,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, *vtable_field;
struct value *vfn;

/* Some simple sanity checks. */
@@ -309,9 +320,19 @@ 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_field = value_field (value,
+ TYPE_VPTR_FIELDNO (vfn_base));
+ vtable_addr_value =
+ value_at (builtin_type_void_data_ptr,
+ VALUE_ADDRESS (vtable_field)
+ + VALUE_OFFSET (vtable_field)
+ + VALUE_EMBEDDED_OFFSET (vtable_field),
+ 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));