static void java_type_print_derivation_info (struct ui_file *stream, struct type *type) { char *name; int i; int n_bases; int prev; n_bases = TYPE_N_BASECLASSES (type); for (i = 0, prev = 0; i < n_bases; i++) { int kind; kind = BASETYPE_VIA_VIRTUAL (type, i) ? 'I' : 'E'; fputs_filtered (kind == prev ? ", " : kind == 'I' ? " implements " : " extends ", stream); prev = kind; name = type_name_no_tag (TYPE_BASECLASS (type, i)); fprintf_filtered (stream, "%s", name ? name : "(null)"); } if (i > 0) fputs_filtered (" ", stream); }
static int gnuv3_dynamic_class (struct type *type) { int fieldnum, fieldelem; if (TYPE_CPLUS_DYNAMIC (type)) return TYPE_CPLUS_DYNAMIC (type) == 1; ALLOCATE_CPLUS_STRUCT_TYPE (type); for (fieldnum = 0; fieldnum < TYPE_N_BASECLASSES (type); fieldnum++) if (BASETYPE_VIA_VIRTUAL (type, fieldnum) || gnuv3_dynamic_class (TYPE_FIELD_TYPE (type, fieldnum))) { TYPE_CPLUS_DYNAMIC (type) = 1; return 1; } for (fieldnum = 0; fieldnum < TYPE_NFN_FIELDS (type); fieldnum++) for (fieldelem = 0; fieldelem < TYPE_FN_FIELDLIST_LENGTH (type, fieldnum); fieldelem++) { struct fn_field *f = TYPE_FN_FIELDLIST1 (type, fieldnum); if (TYPE_FN_FIELD_VIRTUAL_P (f, fieldelem)) { TYPE_CPLUS_DYNAMIC (type) = 1; return 1; } } TYPE_CPLUS_DYNAMIC (type) = -1; return 0; }
static void cp_type_print_derivation_info (struct ui_file *stream, struct type *type, const struct type_print_options *flags) { const char *name; int i; for (i = 0; i < TYPE_N_BASECLASSES (type); i++) { wrap_here (" "); fputs_filtered (i == 0 ? ": " : ", ", stream); fprintf_filtered (stream, "%s%s ", BASETYPE_VIA_PUBLIC (type, i) ? "public" : (TYPE_FIELD_PROTECTED (type, i) ? "protected" : "private"), BASETYPE_VIA_VIRTUAL (type, i) ? " virtual" : ""); name = type_name_no_tag (TYPE_BASECLASS (type, i)); if (name) print_name_maybe_canonical (name, flags, stream); else fprintf_filtered (stream, "(null)"); } if (i > 0) { fputs_filtered (" ", stream); } }
static int gnuv2_baseclass_offset (struct type *type, int index, const bfd_byte *valaddr, int embedded_offset, CORE_ADDR address, const struct value *val) { struct type *basetype = TYPE_BASECLASS (type, index); if (BASETYPE_VIA_VIRTUAL (type, index)) { /* Must hunt for the pointer to this virtual baseclass. */ int i, len = TYPE_NFIELDS (type); int n_baseclasses = TYPE_N_BASECLASSES (type); /* First look for the virtual baseclass pointer in the fields. */ for (i = n_baseclasses; i < len; i++) { if (vb_match (type, i, basetype)) { struct type *field_type; int field_offset; int field_length; CORE_ADDR addr; field_type = check_typedef (TYPE_FIELD_TYPE (type, i)); field_offset = TYPE_FIELD_BITPOS (type, i) / 8; field_length = TYPE_LENGTH (field_type); if (!value_bytes_available (val, embedded_offset + field_offset, field_length)) throw_error (NOT_AVAILABLE_ERROR, _("Virtual baseclass pointer is not available")); addr = unpack_pointer (field_type, valaddr + embedded_offset + field_offset); return addr - (LONGEST) address + embedded_offset; } } /* Not in the fields, so try looking through the baseclasses. */ for (i = index + 1; i < n_baseclasses; i++) { /* Don't go through baseclass_offset, as that wraps exceptions, thus, inner exceptions would be wrapped more than once. */ int boffset = gnuv2_baseclass_offset (type, i, valaddr, embedded_offset, address, val); if (boffset) return boffset; } error (_("Baseclass offset not found")); } /* Baseclass is easily computed. */ return TYPE_BASECLASS_BITPOS (type, index) / 8; }
static const char * gnuv3_find_method_in (struct type *domain, CORE_ADDR voffset, LONGEST adjustment) { int i; const char *physname; /* Search this class first. */ physname = NULL; if (adjustment == 0) { int len; len = TYPE_NFN_FIELDS (domain); for (i = 0; i < len; i++) { int len2, j; struct fn_field *f; f = TYPE_FN_FIELDLIST1 (domain, i); len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i); check_stub_method_group (domain, i); for (j = 0; j < len2; j++) if (TYPE_FN_FIELD_VOFFSET (f, j) == voffset) return TYPE_FN_FIELD_PHYSNAME (f, j); } } /* Next search non-virtual bases. If it's in a virtual base, we're out of luck. */ for (i = 0; i < TYPE_N_BASECLASSES (domain); i++) { int pos; struct type *basetype; if (BASETYPE_VIA_VIRTUAL (domain, i)) continue; pos = TYPE_BASECLASS_BITPOS (domain, i) / 8; basetype = TYPE_FIELD_TYPE (domain, i); /* Recurse with a modified adjustment. We don't need to adjust voffset. */ if (adjustment >= pos && adjustment < pos + TYPE_LENGTH (basetype)) return gnuv3_find_method_in (basetype, voffset, adjustment - pos); } return NULL; }
static void pascal_type_print_derivation_info (struct ui_file *stream, struct type *type) { char *name; int i; for (i = 0; i < TYPE_N_BASECLASSES (type); i++) { fputs_filtered (i == 0 ? ": " : ", ", stream); fprintf_filtered (stream, "%s%s ", BASETYPE_VIA_PUBLIC (type, i) ? "public" : "private", BASETYPE_VIA_VIRTUAL (type, i) ? " virtual" : ""); name = type_name_no_tag (TYPE_BASECLASS (type, i)); fprintf_filtered (stream, "%s", name ? name : "(null)"); } if (i > 0) { fputs_filtered (" ", stream); } }
static int gnuv3_baseclass_offset (struct type *type, int index, const bfd_byte *valaddr, int embedded_offset, CORE_ADDR address, const struct value *val) { struct gdbarch *gdbarch; struct type *ptr_type; struct value *vtable; struct value *vbase_array; long int cur_base_offset, base_offset; /* Determine architecture. */ gdbarch = get_type_arch (type); ptr_type = builtin_type (gdbarch)->builtin_data_ptr; /* If it isn't a virtual base, this is easy. The offset is in the type definition. Likewise for Java, which doesn't really have virtual inheritance in the C++ sense. */ if (!BASETYPE_VIA_VIRTUAL (type, index) || TYPE_CPLUS_REALLY_JAVA (type)) 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 (gdbarch)) error (_("Expected a negative vbase offset (old compiler?)")); cur_base_offset = cur_base_offset + vtable_address_point_offset (gdbarch); if ((- cur_base_offset) % TYPE_LENGTH (ptr_type) != 0) error (_("Misaligned vbase offset.")); cur_base_offset = cur_base_offset / ((int) TYPE_LENGTH (ptr_type)); vtable = gnuv3_get_vtable (gdbarch, type, address + embedded_offset); gdb_assert (vtable != NULL); vbase_array = value_field (vtable, vtable_field_vcall_and_vbase_offsets); base_offset = value_as_long (value_subscript (vbase_array, cur_base_offset)); return base_offset; }
int gnuv2_baseclass_offset (struct type *type, int index, const bfd_byte *valaddr, CORE_ADDR address) { struct type *basetype = TYPE_BASECLASS (type, index); if (BASETYPE_VIA_VIRTUAL (type, index)) { /* Must hunt for the pointer to this virtual baseclass. */ int i, len = TYPE_NFIELDS (type); int n_baseclasses = TYPE_N_BASECLASSES (type); /* First look for the virtual baseclass pointer in the fields. */ for (i = n_baseclasses; i < len; i++) { if (vb_match (type, i, basetype)) { CORE_ADDR addr = unpack_pointer (TYPE_FIELD_TYPE (type, i), valaddr + (TYPE_FIELD_BITPOS (type, i) / 8)); return addr - (LONGEST) address; } } /* Not in the fields, so try looking through the baseclasses. */ for (i = index + 1; i < n_baseclasses; i++) { int boffset = baseclass_offset (type, i, valaddr, address); if (boffset) return boffset; } /* Not found. */ return -1; } /* Baseclass is easily computed. */ return TYPE_BASECLASS_BITPOS (type, index) / 8; }
static void java_print_value_fields (struct type *type, const gdb_byte *valaddr, CORE_ADDR address, struct ui_file *stream, int recurse, const struct value_print_options *options) { int i, len, n_baseclasses; CHECK_TYPEDEF (type); fprintf_filtered (stream, "{"); len = TYPE_NFIELDS (type); n_baseclasses = TYPE_N_BASECLASSES (type); if (n_baseclasses > 0) { int i, n_baseclasses = TYPE_N_BASECLASSES (type); for (i = 0; i < n_baseclasses; i++) { int boffset; struct type *baseclass = check_typedef (TYPE_BASECLASS (type, i)); char *basename = TYPE_NAME (baseclass); const gdb_byte *base_valaddr; if (BASETYPE_VIA_VIRTUAL (type, i)) continue; if (basename != NULL && strcmp (basename, "java.lang.Object") == 0) continue; boffset = 0; if (options->pretty) { fprintf_filtered (stream, "\n"); print_spaces_filtered (2 * (recurse + 1), stream); } fputs_filtered ("<", stream); /* Not sure what the best notation is in the case where there is no baseclass name. */ fputs_filtered (basename ? basename : "", stream); fputs_filtered ("> = ", stream); base_valaddr = valaddr; java_print_value_fields (baseclass, base_valaddr, address + boffset, stream, recurse + 1, options); fputs_filtered (", ", stream); } } if (!len && n_baseclasses == 1) fprintf_filtered (stream, "<No data fields>"); else { int fields_seen = 0; for (i = n_baseclasses; i < len; i++) { /* If requested, skip printing of static fields. */ if (field_is_static (&TYPE_FIELD (type, i))) { char *name = TYPE_FIELD_NAME (type, i); if (!options->static_field_print) continue; if (name != NULL && strcmp (name, "class") == 0) continue; } if (fields_seen) fprintf_filtered (stream, ", "); else if (n_baseclasses > 0) { if (options->pretty) { fprintf_filtered (stream, "\n"); print_spaces_filtered (2 + 2 * recurse, stream); fputs_filtered ("members of ", stream); fputs_filtered (type_name_no_tag (type), stream); fputs_filtered (": ", stream); } } fields_seen = 1; if (options->pretty) { fprintf_filtered (stream, "\n"); print_spaces_filtered (2 + 2 * recurse, stream); } else { wrap_here (n_spaces (2 + 2 * recurse)); } if (options->inspect_it) { if (TYPE_CODE (TYPE_FIELD_TYPE (type, i)) == TYPE_CODE_PTR) fputs_filtered ("\"( ptr \"", stream); else fputs_filtered ("\"( nodef \"", stream); if (field_is_static (&TYPE_FIELD (type, i))) fputs_filtered ("static ", stream); fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i), language_cplus, DMGL_PARAMS | DMGL_ANSI); fputs_filtered ("\" \"", stream); fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i), language_cplus, DMGL_PARAMS | DMGL_ANSI); fputs_filtered ("\") \"", stream); } else { annotate_field_begin (TYPE_FIELD_TYPE (type, i)); if (field_is_static (&TYPE_FIELD (type, i))) fputs_filtered ("static ", stream); fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i), language_cplus, DMGL_PARAMS | DMGL_ANSI); annotate_field_name_end (); fputs_filtered (": ", stream); annotate_field_value (); } if (!field_is_static (&TYPE_FIELD (type, i)) && TYPE_FIELD_PACKED (type, i)) { struct value *v; /* Bitfields require special handling, especially due to byte order problems. */ if (TYPE_FIELD_IGNORE (type, i)) { fputs_filtered ("<optimized out or zero length>", stream); } else { struct value_print_options opts; v = value_from_longest (TYPE_FIELD_TYPE (type, i), unpack_field_as_long (type, valaddr, i)); opts = *options; opts.deref_ref = 0; common_val_print (v, stream, recurse + 1, &opts, current_language); } } else { if (TYPE_FIELD_IGNORE (type, i)) { fputs_filtered ("<optimized out or zero length>", stream); } else if (field_is_static (&TYPE_FIELD (type, i))) { struct value *v = value_static_field (type, i); if (v == NULL) fputs_filtered ("<optimized out>", stream); else { struct value_print_options opts; struct type *t = check_typedef (value_type (v)); if (TYPE_CODE (t) == TYPE_CODE_STRUCT) v = value_addr (v); opts = *options; opts.deref_ref = 0; common_val_print (v, stream, recurse + 1, &opts, current_language); } } else if (TYPE_FIELD_TYPE (type, i) == NULL) fputs_filtered ("<unknown type>", stream); else { struct value_print_options opts = *options; opts.deref_ref = 0; val_print (TYPE_FIELD_TYPE (type, i), valaddr + TYPE_FIELD_BITPOS (type, i) / 8, 0, address + TYPE_FIELD_BITPOS (type, i) / 8, stream, recurse + 1, &opts, current_language); } } annotate_field_end (); } if (options->pretty) { fprintf_filtered (stream, "\n"); print_spaces_filtered (2 * recurse, stream); } } fprintf_filtered (stream, "}"); }
static void pascal_object_print_value (struct type *type, const gdb_byte *valaddr, int offset, CORE_ADDR address, struct ui_file *stream, int recurse, const struct value *val, const struct value_print_options *options, struct type **dont_print_vb) { struct type **last_dont_print = (struct type **) obstack_next_free (&dont_print_vb_obstack); struct obstack tmp_obstack = dont_print_vb_obstack; int i, n_baseclasses = TYPE_N_BASECLASSES (type); if (dont_print_vb == 0) { /* If we're at top level, carve out a completely fresh chunk of the obstack and use that until this particular invocation returns. */ /* Bump up the high-water mark. Now alpha is omega. */ obstack_finish (&dont_print_vb_obstack); } for (i = 0; i < n_baseclasses; i++) { int boffset = 0; struct type *baseclass = check_typedef (TYPE_BASECLASS (type, i)); const char *basename = type_name_no_tag (baseclass); const gdb_byte *base_valaddr = NULL; int thisoffset; int skip = 0; if (BASETYPE_VIA_VIRTUAL (type, i)) { struct type **first_dont_print = (struct type **) obstack_base (&dont_print_vb_obstack); int j = (struct type **) obstack_next_free (&dont_print_vb_obstack) - first_dont_print; while (--j >= 0) if (baseclass == first_dont_print[j]) goto flush_it; obstack_ptr_grow (&dont_print_vb_obstack, baseclass); } thisoffset = offset; TRY { boffset = baseclass_offset (type, i, valaddr, offset, address, val); } CATCH (ex, RETURN_MASK_ERROR) { if (ex.error == NOT_AVAILABLE_ERROR) skip = -1; else skip = 1; } END_CATCH if (skip == 0) { /* The virtual base class pointer might have been clobbered by the user program. Make sure that it still points to a valid memory location. */ if (boffset < 0 || boffset >= TYPE_LENGTH (type)) { gdb_byte *buf; struct cleanup *back_to; buf = (gdb_byte *) xmalloc (TYPE_LENGTH (baseclass)); back_to = make_cleanup (xfree, buf); base_valaddr = buf; if (target_read_memory (address + boffset, buf, TYPE_LENGTH (baseclass)) != 0) skip = 1; address = address + boffset; thisoffset = 0; boffset = 0; do_cleanups (back_to); } else base_valaddr = valaddr; } if (options->prettyformat) { fprintf_filtered (stream, "\n"); print_spaces_filtered (2 * recurse, stream); } fputs_filtered ("<", stream); /* Not sure what the best notation is in the case where there is no baseclass name. */ fputs_filtered (basename ? basename : "", stream); fputs_filtered ("> = ", stream); if (skip < 0) val_print_unavailable (stream); else if (skip > 0) val_print_invalid_address (stream); else pascal_object_print_value_fields (baseclass, base_valaddr, thisoffset + boffset, address, stream, recurse, val, options, (struct type **) obstack_base (&dont_print_vb_obstack), 0); fputs_filtered (", ", stream); flush_it: ; } if (dont_print_vb == 0) { /* Free the space used to deal with the printing of this type from top level. */ obstack_free (&dont_print_vb_obstack, last_dont_print); /* Reset watermark so that we can continue protecting ourselves from whatever we were protecting ourselves. */ dont_print_vb_obstack = tmp_obstack; } }
static void pascal_object_print_value (struct type *type, const gdb_byte *valaddr, CORE_ADDR address, struct ui_file *stream, int format, int recurse, enum val_prettyprint pretty, struct type **dont_print_vb) { struct type **last_dont_print = (struct type **) obstack_next_free (&dont_print_vb_obstack); struct obstack tmp_obstack = dont_print_vb_obstack; int i, n_baseclasses = TYPE_N_BASECLASSES (type); if (dont_print_vb == 0) { /* If we're at top level, carve out a completely fresh chunk of the obstack and use that until this particular invocation returns. */ /* Bump up the high-water mark. Now alpha is omega. */ obstack_finish (&dont_print_vb_obstack); } for (i = 0; i < n_baseclasses; i++) { int boffset; struct type *baseclass = check_typedef (TYPE_BASECLASS (type, i)); char *basename = type_name_no_tag (baseclass); const gdb_byte *base_valaddr; if (BASETYPE_VIA_VIRTUAL (type, i)) { struct type **first_dont_print = (struct type **) obstack_base (&dont_print_vb_obstack); int j = (struct type **) obstack_next_free (&dont_print_vb_obstack) - first_dont_print; while (--j >= 0) if (baseclass == first_dont_print[j]) goto flush_it; obstack_ptr_grow (&dont_print_vb_obstack, baseclass); } boffset = baseclass_offset (type, i, valaddr, address); if (pretty) { fprintf_filtered (stream, "\n"); print_spaces_filtered (2 * recurse, stream); } fputs_filtered ("<", stream); /* Not sure what the best notation is in the case where there is no baseclass name. */ fputs_filtered (basename ? basename : "", stream); fputs_filtered ("> = ", stream); /* The virtual base class pointer might have been clobbered by the user program. Make sure that it still points to a valid memory location. */ if (boffset != -1 && (boffset < 0 || boffset >= TYPE_LENGTH (type))) { /* FIXME (alloc): not safe is baseclass is really really big. */ gdb_byte *buf = alloca (TYPE_LENGTH (baseclass)); base_valaddr = buf; if (target_read_memory (address + boffset, buf, TYPE_LENGTH (baseclass)) != 0) boffset = -1; } else base_valaddr = valaddr + boffset; if (boffset == -1) fprintf_filtered (stream, "<invalid address>"); else pascal_object_print_value_fields (baseclass, base_valaddr, address + boffset, stream, format, recurse, pretty, (struct type **) obstack_base (&dont_print_vb_obstack), 0); fputs_filtered (", ", stream); flush_it: ; } if (dont_print_vb == 0) { /* Free the space used to deal with the printing of this type from top level. */ obstack_free (&dont_print_vb_obstack, last_dont_print); /* Reset watermark so that we can continue protecting ourselves from whatever we were protecting ourselves. */ dont_print_vb_obstack = tmp_obstack; } }
static gcc_type compile_cplus_convert_struct_or_union (compile_cplus_instance *instance, struct type *type, enum gcc_cp_symbol_kind nested_access) { const char *filename = nullptr; unsigned short line = 0; /* Get the decl name of this type. */ gdb::unique_xmalloc_ptr<char> name = compile_cplus_instance::decl_name (TYPE_NAME (type)); /* Create a new scope for TYPE. */ compile_scope scope = instance->new_scope (TYPE_NAME (type), type); if (scope.nested_type () != GCC_TYPE_NONE) { /* The type requested was actually defined inside another type, such as a nested class definition. Return that type. */ return scope.nested_type (); } /* Push all scopes. */ instance->enter_scope (std::move (scope)); /* First we create the resulting type and enter it into our hash table. This lets recursive types work. */ gcc_decl resuld; if (TYPE_CODE (type) == TYPE_CODE_STRUCT) { const char *what = TYPE_DECLARED_CLASS (type) ? "struct" : "class"; resuld = instance->plugin ().build_decl (what, name.get (), (GCC_CP_SYMBOL_CLASS | nested_access | (TYPE_DECLARED_CLASS (type) ? GCC_CP_FLAG_CLASS_NOFLAG : GCC_CP_FLAG_CLASS_IS_STRUCT)), 0, nullptr, 0, filename, line); } else { gdb_assert (TYPE_CODE (type) == TYPE_CODE_UNION); resuld = instance->plugin ().build_decl ("union", name.get (), GCC_CP_SYMBOL_UNION | nested_access, 0, nullptr, 0, filename, line); } gcc_type result; if (TYPE_CODE (type) == TYPE_CODE_STRUCT) { struct gcc_vbase_array bases; int num_baseclasses = TYPE_N_BASECLASSES (type); memset (&bases, 0, sizeof (bases)); if (num_baseclasses > 0) { bases.elements = XNEWVEC (gcc_type, num_baseclasses); bases.flags = XNEWVEC (enum gcc_cp_symbol_kind, num_baseclasses); bases.n_elements = num_baseclasses; for (int i = 0; i < num_baseclasses; ++i) { struct type *base_type = TYPE_BASECLASS (type, i); bases.flags[i] = GCC_CP_SYMBOL_BASECLASS | get_field_access_flag (type, i) | (BASETYPE_VIA_VIRTUAL (type, i) ? GCC_CP_FLAG_BASECLASS_VIRTUAL : GCC_CP_FLAG_BASECLASS_NOFLAG); bases.elements[i] = instance->convert_type (base_type); } } result = instance->plugin ().start_class_type (name.get (), resuld, &bases, filename, line); xfree (bases.flags); xfree (bases.elements); }
/* 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 gdbarch *gdbarch; struct type *vtable_type; struct type *ptr_type; struct value *vtable; struct type *vbasetype; struct value *offset_val, *vbase_array; CORE_ADDR vtable_address; long int cur_base_offset, base_offset; int vbasetype_vptr_fieldno; /* Determine architecture. */ gdbarch = get_class_arch (type); vtable_type = gdbarch_data (gdbarch, vtable_type_gdbarch_data); ptr_type = builtin_type (gdbarch)->builtin_data_ptr; /* 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 (gdbarch)) error (_("Expected a negative vbase offset (old compiler?)")); cur_base_offset = cur_base_offset + vtable_address_point_offset (gdbarch); if ((- cur_base_offset) % TYPE_LENGTH (ptr_type) != 0) error (_("Misaligned vbase offset.")); cur_base_offset = cur_base_offset / ((int) TYPE_LENGTH (ptr_type)); /* 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 = check_typedef (TYPE_VPTR_BASETYPE (type)); vbasetype_vptr_fieldno = get_vptr_fieldno (vbasetype, NULL); if (vbasetype_vptr_fieldno >= 0 && TYPE_FIELD_BITPOS (vbasetype, vbasetype_vptr_fieldno) != 0) error (_("Illegal vptr offset in class %s"), TYPE_NAME (vbasetype) ? TYPE_NAME (vbasetype) : "<unknown>"); vtable_address = value_as_address (value_at_lazy (ptr_type, address)); vtable = value_at_lazy (vtable_type, vtable_address - vtable_address_point_offset (gdbarch)); offset_val = value_from_longest (builtin_type_int32, 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; }