+/* Compute the offset of the baseclass which is
+ the INDEXth baseclass of class TYPE,
+ for value at VALADDR (in host) at ADDRESS (in target).
+ The result is the offset of the baseclass value relative
+ to (the address of)(ARG) + OFFSET.
+
+ -1 is returned on error. */
+static int
+gnuv3_baseclass_offset (struct type *type, int index, const bfd_byte *valaddr,
+ CORE_ADDR address)
+{
+ struct type *vtable_type = gdbarch_data (current_gdbarch,
+ vtable_type_gdbarch_data);
+ struct value *vtable;
+ struct type *vbasetype;
+ struct value *offset_val, *vbase_array;
+ CORE_ADDR vtable_address;
+ long int cur_base_offset, base_offset;
+
+ /* If it isn't a virtual base, this is easy. The offset is in the
+ type definition. */
+ if (!BASETYPE_VIA_VIRTUAL (type, index))
+ return TYPE_BASECLASS_BITPOS (type, index) / 8;
+
+ /* To access a virtual base, we need to use the vbase offset stored in
+ our vtable. Recent GCC versions provide this information. If it isn't
+ available, we could get what we needed from RTTI, or from drawing the
+ complete inheritance graph based on the debug info. Neither is
+ worthwhile. */
+ cur_base_offset = TYPE_BASECLASS_BITPOS (type, index) / 8;
+ if (cur_base_offset >= - vtable_address_point_offset ())
+ error (_("Expected a negative vbase offset (old compiler?)"));
+
+ cur_base_offset = cur_base_offset + vtable_address_point_offset ();
+ if ((- cur_base_offset) % TYPE_LENGTH (builtin_type_void_data_ptr) != 0)
+ error (_("Misaligned vbase offset."));
+ cur_base_offset = cur_base_offset
+ / ((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. 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 - iff
+ we have debugging information for that baseclass. */
+
+ vbasetype = TYPE_VPTR_BASETYPE (type);
+ if (TYPE_VPTR_FIELDNO (vbasetype) < 0)
+ fill_in_vptr_fieldno (vbasetype);
+
+ if (TYPE_VPTR_FIELDNO (vbasetype) >= 0
+ && 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));
+ vtable = value_at_lazy (vtable_type,
+ vtable_address - vtable_address_point_offset ());
+ offset_val = value_from_longest(builtin_type_int, cur_base_offset);
+ vbase_array = value_field (vtable, vtable_field_vcall_and_vbase_offsets);
+ base_offset = value_as_long (value_subscript (vbase_array, offset_val));
+ return base_offset;
+}