diff options
Diffstat (limited to 'gdb/gnu-v3-abi.c')
-rw-r--r-- | gdb/gnu-v3-abi.c | 36 |
1 files changed, 20 insertions, 16 deletions
diff --git a/gdb/gnu-v3-abi.c b/gdb/gnu-v3-abi.c index e86af89..fbab8af 100644 --- a/gdb/gnu-v3-abi.c +++ b/gdb/gnu-v3-abi.c @@ -25,6 +25,7 @@ #include "cp-abi.h" #include "demangle.h" #include "gdb_assert.h" +#include "gdb_string.h" static struct cp_abi_ops gnu_v3_abi_ops; @@ -173,7 +174,7 @@ build_gdb_vtable_type (struct gdbarch *arch) gdb_gnu_v3_abi_vtable' object to the vtable's "address point" (i.e., where objects' virtual table pointers point). */ static int -vtable_address_point_offset () +vtable_address_point_offset (void) { struct type *vtable_type = gdbarch_data (current_gdbarch, vtable_type_gdbarch_data); @@ -374,15 +375,11 @@ gnuv3_baseclass_offset (struct type *type, int index, char *valaddr, { struct type *vtable_type = gdbarch_data (current_gdbarch, vtable_type_gdbarch_data); - struct type *basetype = TYPE_BASECLASS (type, index); - struct value *full_object, *vbase_object, *orig_object; - struct value *vtable, *orig_typeinfo, *orig_base_info; - struct type *orig_type, *vbasetype; + struct value *vtable; + struct type *vbasetype; struct value *offset_val, *vbase_array; CORE_ADDR vtable_address; long int cur_base_offset, base_offset; - int to_top; - int baseclasses, i; /* If it isn't a virtual base, this is easy. The offset is in the type definition. */ @@ -405,15 +402,22 @@ gnuv3_baseclass_offset (struct type *type, int index, char *valaddr, / ((int) TYPE_LENGTH (builtin_type_void_data_ptr)); /* We're now looking for the cur_base_offset'th entry (negative index) - in the vcall_and_vbase_offsets array. */ - - orig_object = value_at_lazy (type, address, NULL); - vbasetype = TYPE_VPTR_BASETYPE (VALUE_TYPE (orig_object)); - vbase_object = value_cast (vbasetype, orig_object); - - vtable_address - = value_as_address (value_field (vbase_object, - TYPE_VPTR_FIELDNO (vbasetype))); + in the vcall_and_vbase_offsets array. We used to cast the object to + its TYPE_VPTR_BASETYPE, and reference the vtable as TYPE_VPTR_FIELDNO; + however, that cast can not be done without calling baseclass_offset again + if the TYPE_VPTR_BASETYPE is a virtual base class, as described in the + v3 C++ ABI Section 2.4.I.2.b. Fortunately the ABI guarantees that the + vtable pointer will be located at the beginning of the object, so we can + bypass the casting. Verify that the TYPE_VPTR_FIELDNO is in fact at the + start of whichever baseclass it resides in, as a sanity measure. */ + + vbasetype = TYPE_VPTR_BASETYPE (type); + if (TYPE_FIELD_BITPOS (vbasetype, TYPE_VPTR_FIELDNO (vbasetype)) != 0) + error ("Illegal vptr offset in class %s", + TYPE_NAME (vbasetype) ? TYPE_NAME (vbasetype) : "<unknown>"); + + vtable_address = value_as_address (value_at_lazy (builtin_type_void_data_ptr, + address, NULL)); vtable = value_at_lazy (vtable_type, vtable_address - vtable_address_point_offset (), NULL); |