+ /* The name. */
+ field->set_name ("__name");
+ field->set_type (char_ptr_type);
+ field->set_loc_bitpos (offset * TARGET_CHAR_BIT);
+ offset += TYPE_LENGTH (field->type ());
+ field++;
+
+ gdb_assert (field == (field_list + 2));
+
+ t = arch_type (arch, TYPE_CODE_STRUCT, offset * TARGET_CHAR_BIT, NULL);
+ t->set_num_fields (field - field_list);
+ t->set_fields (field_list);
+ t->set_name ("gdb_gnu_v3_type_info");
+ INIT_CPLUS_SPECIFIC (t);
+
+ return t;
+}
+
+/* Implement the 'get_typeid_type' method. */
+
+static struct type *
+gnuv3_get_typeid_type (struct gdbarch *gdbarch)
+{
+ struct symbol *typeinfo;
+ struct type *typeinfo_type;
+
+ typeinfo = lookup_symbol ("std::type_info", NULL, STRUCT_DOMAIN,
+ NULL).symbol;
+ if (typeinfo == NULL)
+ typeinfo_type
+ = (struct type *) gdbarch_data (gdbarch, std_type_info_gdbarch_data);
+ else
+ typeinfo_type = typeinfo->type ();
+
+ return typeinfo_type;
+}
+
+/* Implement the 'get_typeid' method. */
+
+static struct value *
+gnuv3_get_typeid (struct value *value)
+{
+ struct type *typeinfo_type;
+ struct type *type;
+ struct gdbarch *gdbarch;
+ struct value *result;
+ std::string type_name;
+ gdb::unique_xmalloc_ptr<char> canonical;
+
+ /* We have to handle values a bit trickily here, to allow this code
+ to work properly with non_lvalue values that are really just
+ disguised types. */
+ if (value_lval_const (value) == lval_memory)
+ value = coerce_ref (value);
+
+ type = check_typedef (value_type (value));
+
+ /* In the non_lvalue case, a reference might have slipped through
+ here. */
+ if (type->code () == TYPE_CODE_REF)
+ type = check_typedef (TYPE_TARGET_TYPE (type));
+
+ /* Ignore top-level cv-qualifiers. */
+ type = make_cv_type (0, 0, type, NULL);
+ gdbarch = type->arch ();
+
+ type_name = type_to_string (type);
+ if (type_name.empty ())
+ error (_("cannot find typeinfo for unnamed type"));
+
+ /* We need to canonicalize the type name here, because we do lookups
+ using the demangled name, and so we must match the format it
+ uses. E.g., GDB tends to use "const char *" as a type name, but
+ the demangler uses "char const *". */
+ canonical = cp_canonicalize_string (type_name.c_str ());
+ const char *name = (canonical == nullptr
+ ? type_name.c_str ()
+ : canonical.get ());
+
+ typeinfo_type = gnuv3_get_typeid_type (gdbarch);
+
+ /* We check for lval_memory because in the "typeid (type-id)" case,
+ the type is passed via a not_lval value object. */
+ if (type->code () == TYPE_CODE_STRUCT
+ && value_lval_const (value) == lval_memory
+ && gnuv3_dynamic_class (type))
+ {
+ struct value *vtable, *typeinfo_value;
+ CORE_ADDR address = value_address (value) + value_embedded_offset (value);
+
+ vtable = gnuv3_get_vtable (gdbarch, type, address);
+ if (vtable == NULL)
+ error (_("cannot find typeinfo for object of type '%s'"),
+ name);
+ typeinfo_value = value_field (vtable, vtable_field_type_info);
+ result = value_ind (value_cast (make_pointer_type (typeinfo_type, NULL),
+ typeinfo_value));
+ }
+ else
+ {
+ std::string sym_name = std::string ("typeinfo for ") + name;
+ bound_minimal_symbol minsym
+ = lookup_minimal_symbol (sym_name.c_str (), NULL, NULL);
+
+ if (minsym.minsym == NULL)
+ error (_("could not find typeinfo symbol for '%s'"), name);
+
+ result = value_at_lazy (typeinfo_type, BMSYMBOL_VALUE_ADDRESS (minsym));
+ }
+
+ return result;
+}
+
+/* Implement the 'get_typename_from_type_info' method. */
+
+static std::string
+gnuv3_get_typename_from_type_info (struct value *type_info_ptr)
+{
+ struct gdbarch *gdbarch = value_type (type_info_ptr)->arch ();
+ struct bound_minimal_symbol typeinfo_sym;
+ CORE_ADDR addr;
+ const char *symname;
+ const char *class_name;
+ const char *atsign;
+
+ addr = value_as_address (type_info_ptr);
+ typeinfo_sym = lookup_minimal_symbol_by_pc (addr);
+ if (typeinfo_sym.minsym == NULL)
+ error (_("could not find minimal symbol for typeinfo address %s"),
+ paddress (gdbarch, addr));
+
+#define TYPEINFO_PREFIX "typeinfo for "
+#define TYPEINFO_PREFIX_LEN (sizeof (TYPEINFO_PREFIX) - 1)
+ symname = typeinfo_sym.minsym->demangled_name ();
+ if (symname == NULL || strncmp (symname, TYPEINFO_PREFIX,
+ TYPEINFO_PREFIX_LEN))
+ error (_("typeinfo symbol '%s' has unexpected name"),
+ typeinfo_sym.minsym->linkage_name ());
+ class_name = symname + TYPEINFO_PREFIX_LEN;
+
+ /* Strip off @plt and version suffixes. */
+ atsign = strchr (class_name, '@');
+ if (atsign != NULL)
+ return std::string (class_name, atsign - class_name);
+ return class_name;
+}
+
+/* Implement the 'get_type_from_type_info' method. */
+
+static struct type *
+gnuv3_get_type_from_type_info (struct value *type_info_ptr)
+{
+ /* We have to parse the type name, since in general there is not a
+ symbol for a type. This is somewhat bogus since there may be a
+ mis-parse. Another approach might be to re-use the demangler's
+ internal form to reconstruct the type somehow. */
+ std::string type_name = gnuv3_get_typename_from_type_info (type_info_ptr);
+ expression_up expr (parse_expression (type_name.c_str ()));
+ struct value *type_val = evaluate_type (expr.get ());
+ return value_type (type_val);