/* Abstraction of GNU v3 abi.
Contributed by Jim Blandy <jimb@redhat.com>
- Copyright (C) 2001-2014 Free Software Foundation, Inc.
+ Copyright (C) 2001-2015 Free Software Foundation, Inc.
This file is part of GDB.
#include "objfiles.h"
#include "valprint.h"
#include "c-lang.h"
-#include "exceptions.h"
#include "typeprint.h"
-#include "gdb_assert.h"
-#include <string.h>
-
static struct cp_abi_ops gnu_v3_abi_ops;
/* A gdbarch key for std::type_info, in the event that it can't be
static int
gnuv3_is_vtable_name (const char *name)
{
- return strncmp (name, "_ZTV", 4) == 0;
+ return startswith (name, "_ZTV");
}
static int
gnuv3_is_operator_name (const char *name)
{
- return strncmp (name, "operator", 8) == 0;
+ return startswith (name, "operator");
}
{
int fieldnum, fieldelem;
+ type = check_typedef (type);
+ gdb_assert (TYPE_CODE (type) == TYPE_CODE_STRUCT
+ || TYPE_CODE (type) == TYPE_CODE_UNION);
+
+ if (TYPE_CODE (type) == TYPE_CODE_UNION)
+ return 0;
+
if (TYPE_CPLUS_DYNAMIC (type))
return TYPE_CPLUS_DYNAMIC (type) == 1;
struct value *vtable_pointer;
CORE_ADDR vtable_address;
+ container_type = check_typedef (container_type);
+ gdb_assert (TYPE_CODE (container_type) == TYPE_CODE_STRUCT);
+
/* If this type does not have a virtual table, don't read the first
field. */
- if (!gnuv3_dynamic_class (check_typedef (container_type)))
+ if (!gnuv3_dynamic_class (container_type))
return NULL;
/* We do not consult the debug information to find the virtual table.
char *atsign;
/* We only have RTTI for class objects. */
- if (TYPE_CODE (values_type) != TYPE_CODE_CLASS)
+ if (TYPE_CODE (values_type) != TYPE_CODE_STRUCT)
return NULL;
/* Java doesn't have RTTI following the C++ ABI. */
if (using_enc_p)
*using_enc_p = 0;
- vtable = gnuv3_get_vtable (gdbarch, value_type (value),
+ vtable = gnuv3_get_vtable (gdbarch, values_type,
value_as_address (value_addr (value)));
if (vtable == NULL)
return NULL;
should work just as well, and doesn't read target memory. */
vtable_symbol_name = MSYMBOL_DEMANGLED_NAME (vtable_symbol);
if (vtable_symbol_name == NULL
- || strncmp (vtable_symbol_name, "vtable for ", 11))
+ || !startswith (vtable_symbol_name, "vtable for "))
{
warning (_("can't find linker symbol for virtual table for `%s' value"),
TYPE_SAFE_NAME (values_type));
struct gdbarch *gdbarch;
/* Some simple sanity checks. */
- if (TYPE_CODE (values_type) != TYPE_CODE_CLASS)
+ if (TYPE_CODE (values_type) != TYPE_CODE_STRUCT)
error (_("Only classes can have virtual functions."));
/* Determine architecture. */
struct type *type,
struct ui_file *stream)
{
- struct type *domain = TYPE_DOMAIN_TYPE (type);
- struct gdbarch *gdbarch = get_type_arch (domain);
+ struct type *self_type = TYPE_SELF_TYPE (type);
+ struct gdbarch *gdbarch = get_type_arch (self_type);
CORE_ADDR ptr_value;
LONGEST adjustment;
int vbit;
to an index, as used in TYPE_FN_FIELD_VOFFSET. */
voffset = ptr_value / TYPE_LENGTH (vtable_ptrdiff_type (gdbarch));
- physname = gnuv3_find_method_in (domain, voffset, adjustment);
+ physname = gnuv3_find_method_in (self_type, voffset, adjustment);
/* If we found a method, print that. We don't bother to disambiguate
possible paths to the method based on the adjustment. */
struct gdbarch *gdbarch;
const gdb_byte *contents = value_contents (method_ptr);
CORE_ADDR ptr_value;
- struct type *domain_type, *final_type, *method_type;
+ struct type *self_type, *final_type, *method_type;
LONGEST adjustment;
int vbit;
- domain_type = TYPE_DOMAIN_TYPE (check_typedef (value_type (method_ptr)));
- final_type = lookup_pointer_type (domain_type);
+ self_type = TYPE_SELF_TYPE (check_typedef (value_type (method_ptr)));
+ final_type = lookup_pointer_type (self_type);
method_type = TYPE_TARGET_TYPE (check_typedef (value_type (method_ptr)));
/* Extract the pointer to member. */
- gdbarch = get_type_arch (domain_type);
+ gdbarch = get_type_arch (self_type);
vbit = gnuv3_decode_method_ptr (gdbarch, contents, &ptr_value, &adjustment);
/* First convert THIS to match the containing type of the pointer to
void **slot;
struct value_and_voffset search_vo, *current_vo;
+ gdb_assert (TYPE_CODE (type) == TYPE_CODE_STRUCT);
+
/* If the object is not dynamic, then we are done; as it cannot have
dynamic base types either. */
if (!gnuv3_dynamic_class (type))
{
/* Initialize it just to avoid a GCC false warning. */
CORE_ADDR addr = 0;
+ int got_error = 0;
struct value *vfn;
- volatile struct gdb_exception ex;
printf_filtered ("[%d]: ", i);
if (gdbarch_vtable_function_descriptors (gdbarch))
vfn = value_addr (vfn);
- TRY_CATCH (ex, RETURN_MASK_ERROR)
+ TRY
{
addr = value_as_address (vfn);
}
- if (ex.reason < 0)
- printf_filtered (_("<error: %s>"), ex.message);
- else
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ printf_filtered (_("<error: %s>"), ex.message);
+ got_error = 1;
+ }
+ END_CATCH
+
+ if (!got_error)
print_function_pointer_address (opts, gdbarch, addr, gdb_stdout);
printf_filtered ("\n");
}
}
gdbarch = get_type_arch (type);
- vtable = gnuv3_get_vtable (gdbarch, type,
- value_as_address (value_addr (value)));
+
+ vtable = NULL;
+ if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
+ vtable = gnuv3_get_vtable (gdbarch, type,
+ value_as_address (value_addr (value)));
if (!vtable)
{
struct gdbarch *gdbarch;
struct cleanup *cleanup;
struct value *result;
- char *typename, *canonical;
+ char *type_name, *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
type = make_cv_type (0, 0, type, NULL);
gdbarch = get_type_arch (type);
- typename = type_to_string (type);
- if (typename == NULL)
+ type_name = type_to_string (type);
+ if (type_name == NULL)
error (_("cannot find typeinfo for unnamed type"));
- cleanup = make_cleanup (xfree, typename);
+ cleanup = make_cleanup (xfree, type_name);
/* 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 (typename);
+ canonical = cp_canonicalize_string (type_name);
if (canonical != NULL)
{
make_cleanup (xfree, canonical);
- typename = canonical;
+ type_name = canonical;
}
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) == TYPE_CODE_CLASS
+ if (TYPE_CODE (type) == TYPE_CODE_STRUCT
&& value_lval_const (value) == lval_memory
&& gnuv3_dynamic_class (type))
{
vtable = gnuv3_get_vtable (gdbarch, type, address);
if (vtable == NULL)
- error (_("cannot find typeinfo for object of type '%s'"), typename);
+ error (_("cannot find typeinfo for object of type '%s'"), type_name);
typeinfo_value = value_field (vtable, vtable_field_type_info);
result = value_ind (value_cast (make_pointer_type (typeinfo_type, NULL),
typeinfo_value));
else
{
char *sym_name;
- struct minimal_symbol *minsym;
+ struct bound_minimal_symbol minsym;
- sym_name = concat ("typeinfo for ", typename, (char *) NULL);
+ sym_name = concat ("typeinfo for ", type_name, (char *) NULL);
make_cleanup (xfree, sym_name);
minsym = lookup_minimal_symbol (sym_name, NULL, NULL);
- if (minsym == NULL)
- error (_("could not find typeinfo symbol for '%s'"), typename);
+ if (minsym.minsym == NULL)
+ error (_("could not find typeinfo symbol for '%s'"), type_name);
- result = value_at_lazy (typeinfo_type, MSYMBOL_VALUE_ADDRESS (minsym));
+ result = value_at_lazy (typeinfo_type, BMSYMBOL_VALUE_ADDRESS (minsym));
}
do_cleanups (cleanup);
static struct type *
gnuv3_get_type_from_type_info (struct value *type_info_ptr)
{
- char *typename;
+ char *type_name;
struct cleanup *cleanup;
struct value *type_val;
struct expression *expr;
struct type *result;
- typename = gnuv3_get_typename_from_type_info (type_info_ptr);
- cleanup = make_cleanup (xfree, typename);
+ type_name = gnuv3_get_typename_from_type_info (type_info_ptr);
+ cleanup = make_cleanup (xfree, type_name);
/* 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. */
- expr = parse_expression (typename);
+ expr = parse_expression (type_name);
make_cleanup (xfree, expr);
type_val = evaluate_type (expr);
{
CORE_ADDR real_stop_pc, method_stop_pc, func_addr;
struct gdbarch *gdbarch = get_frame_arch (frame);
- struct minimal_symbol *thunk_sym, *fn_sym;
+ struct bound_minimal_symbol thunk_sym, fn_sym;
struct obj_section *section;
const char *thunk_name, *fn_name;
real_stop_pc = stop_pc;
/* Find the linker symbol for this potential thunk. */
- thunk_sym = lookup_minimal_symbol_by_pc (real_stop_pc).minsym;
+ thunk_sym = lookup_minimal_symbol_by_pc (real_stop_pc);
section = find_pc_section (real_stop_pc);
- if (thunk_sym == NULL || section == NULL)
+ if (thunk_sym.minsym == NULL || section == NULL)
return 0;
/* The symbol's demangled name should be something like "virtual
thunk to FUNCTION", where FUNCTION is the name of the function
being thunked to. */
- thunk_name = MSYMBOL_DEMANGLED_NAME (thunk_sym);
+ thunk_name = MSYMBOL_DEMANGLED_NAME (thunk_sym.minsym);
if (thunk_name == NULL || strstr (thunk_name, " thunk to ") == NULL)
return 0;
fn_name = strstr (thunk_name, " thunk to ") + strlen (" thunk to ");
fn_sym = lookup_minimal_symbol (fn_name, NULL, section->objfile);
- if (fn_sym == NULL)
+ if (fn_sym.minsym == NULL)
return 0;
- method_stop_pc = MSYMBOL_VALUE_ADDRESS (fn_sym);
+ method_stop_pc = BMSYMBOL_VALUE_ADDRESS (fn_sym);
/* Some targets have minimal symbols pointing to function descriptors
(powerpc 64 for example). Make sure to retrieve the address
{
int fieldnum, fieldelem;
- CHECK_TYPEDEF (type);
+ type = check_typedef (type);
/* We're only interested in things that can have methods. */
if (TYPE_CODE (type) != TYPE_CODE_STRUCT
- && TYPE_CODE (type) != TYPE_CODE_CLASS
&& TYPE_CODE (type) != TYPE_CODE_UNION)
return 0;
+ /* A dynamic class has a non-trivial copy constructor.
+ See c++98 section 12.8 Copying class objects [class.copy]. */
+ if (gnuv3_dynamic_class (type))
+ return 1;
+
for (fieldnum = 0; fieldnum < TYPE_NFN_FIELDS (type); fieldnum++)
for (fieldelem = 0; fieldelem < TYPE_FN_FIELDLIST_LENGTH (type, fieldnum);
fieldelem++)
/* If this method takes two arguments, and the second argument is
a reference to this class, then it is a copy constructor. */
- if (TYPE_NFIELDS (fieldtype) == 2
- && TYPE_CODE (TYPE_FIELD_TYPE (fieldtype, 1)) == TYPE_CODE_REF
- && check_typedef (TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (fieldtype,
- 1))) == type)
- return 1;
+ if (TYPE_NFIELDS (fieldtype) == 2)
+ {
+ struct type *arg_type = TYPE_FIELD_TYPE (fieldtype, 1);
+
+ if (TYPE_CODE (arg_type) == TYPE_CODE_REF)
+ {
+ struct type *arg_target_type;
+
+ arg_target_type = check_typedef (TYPE_TARGET_TYPE (arg_type));
+ if (class_types_same_p (arg_target_type, type))
+ return 1;
+ }
+ }
}
/* Even if all the constructors and destructors were artificial, one