/* Abstraction of GNU v3 abi.
Contributed by Jim Blandy <jimb@redhat.com>
- Copyright (C) 2001-2016 Free Software Foundation, Inc.
+ Copyright (C) 2001-2019 Free Software Foundation, Inc.
This file is part of GDB.
#include "valprint.h"
#include "c-lang.h"
#include "typeprint.h"
+#include <algorithm>
+#include "cli/cli-style.h"
static struct cp_abi_ops gnu_v3_abi_ops;
static int
gnuv3_is_operator_name (const char *name)
{
- return startswith (name, "operator");
+ return startswith (name, CP_OPERATOR_STR);
}
/* We assumed in the allocation above that there were four fields. */
gdb_assert (field == (field_list + 4));
- t = arch_type (arch, TYPE_CODE_STRUCT, offset, NULL);
+ t = arch_type (arch, TYPE_CODE_STRUCT, offset * TARGET_CHAR_BIT, NULL);
TYPE_NFIELDS (t) = field - field_list;
TYPE_FIELDS (t) = field_list;
- TYPE_TAG_NAME (t) = "gdb_gnu_v3_abi_vtable";
+ TYPE_NAME (t) = "gdb_gnu_v3_abi_vtable";
INIT_CPLUS_SPECIFIC (t);
return make_type_with_address_space (t, TYPE_INSTANCE_FLAG_CODE_SPACE);
LONGEST offset_to_top;
const char *atsign;
- /* We only have RTTI for class objects. */
- if (TYPE_CODE (values_type) != TYPE_CODE_STRUCT)
- return NULL;
-
- /* Java doesn't have RTTI following the C++ ABI. */
- if (TYPE_CPLUS_REALLY_JAVA (values_type))
+ /* We only have RTTI for dynamic class objects. */
+ if (TYPE_CODE (values_type) != TYPE_CODE_STRUCT
+ || !gnuv3_dynamic_class (values_type))
return NULL;
/* Determine architecture. */
If we didn't like this approach, we could instead look in the
type_info object itself to get the class name. But this way
should work just as well, and doesn't read target memory. */
- vtable_symbol_name = MSYMBOL_DEMANGLED_NAME (vtable_symbol);
+ vtable_symbol_name = vtable_symbol->demangled_name ();
if (vtable_symbol_name == NULL
|| !startswith (vtable_symbol_name, "vtable for "))
{
/* If this architecture uses function descriptors directly in the vtable,
then the address of the vtable entry is actually a "function pointer"
(i.e. points to the descriptor). We don't need to scale the index
- by the size of a function descriptor; GCC does that before outputing
+ by the size of a function descriptor; GCC does that before outputting
debug information. */
if (gdbarch_vtable_function_descriptors (gdbarch))
vfn = value_addr (vfn);
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))
+ 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
{
struct gdbarch *gdbarch = get_type_arch (type);
int size = TYPE_LENGTH (builtin_type (gdbarch)->builtin_data_ptr);
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ enum bfd_endian byte_order = type_byte_order (type);
/* FIXME drow/2006-12-24: The adjustment of "this" is currently
always zero, since the method pointer is of the correct type.
int max_voffset;
};
-typedef struct value_and_voffset *value_and_voffset_p;
-DEF_VEC_P (value_and_voffset_p);
-
/* Hash function for value_and_voffset. */
static hashval_t
== value_address (ovb->value) + value_embedded_offset (ovb->value));
}
-/* qsort comparison function for value_and_voffset. */
+/* Comparison function for value_and_voffset. */
-static int
-compare_value_and_voffset (const void *a, const void *b)
+static bool
+compare_value_and_voffset (const struct value_and_voffset *va,
+ const struct value_and_voffset *vb)
{
- const struct value_and_voffset * const *ova
- = (const struct value_and_voffset * const *) a;
- CORE_ADDR addra = (value_address ((*ova)->value)
- + value_embedded_offset ((*ova)->value));
- const struct value_and_voffset * const *ovb
- = (const struct value_and_voffset * const *) b;
- CORE_ADDR addrb = (value_address ((*ovb)->value)
- + value_embedded_offset ((*ovb)->value));
-
- if (addra < addrb)
- return -1;
- if (addra > addrb)
- return 1;
- return 0;
+ CORE_ADDR addra = (value_address (va->value)
+ + value_embedded_offset (va->value));
+ CORE_ADDR addrb = (value_address (vb->value)
+ + value_embedded_offset (vb->value));
+
+ return addra < addrb;
}
/* A helper function used when printing vtables. This determines the
static void
compute_vtable_size (htab_t offset_hash,
- VEC (value_and_voffset_p) **offset_vec,
+ std::vector<value_and_voffset *> *offset_vec,
struct value *value)
{
int i;
current_vo->value = value;
current_vo->max_voffset = -1;
*slot = current_vo;
- VEC_safe_push (value_and_voffset_p, *offset_vec, current_vo);
+ offset_vec->push_back (current_vo);
}
/* Update the value_and_voffset object with the highest vtable
if (gdbarch_vtable_function_descriptors (gdbarch))
vfn = value_addr (vfn);
- TRY
+ try
{
addr = value_as_address (vfn);
}
- CATCH (ex, RETURN_MASK_ERROR)
+ catch (const gdb_exception_error &ex)
{
- printf_filtered (_("<error: %s>"), ex.message);
+ fprintf_styled (gdb_stdout, metadata_style.style (),
+ _("<error: %s>"), ex.what ());
got_error = 1;
}
- END_CATCH
if (!got_error)
print_function_pointer_address (opts, gdbarch, addr, gdb_stdout);
struct type *type;
struct value *vtable;
struct value_print_options opts;
- htab_t offset_hash;
- struct cleanup *cleanup;
- VEC (value_and_voffset_p) *result_vec = NULL;
- struct value_and_voffset *iter;
- int i, count;
+ int count;
value = coerce_ref (value);
type = check_typedef (value_type (value));
return;
}
- offset_hash = htab_create_alloc (1, hash_value_and_voffset,
- eq_value_and_voffset,
- xfree, xcalloc, xfree);
- cleanup = make_cleanup_htab_delete (offset_hash);
- make_cleanup (VEC_cleanup (value_and_voffset_p), &result_vec);
+ htab_up offset_hash (htab_create_alloc (1, hash_value_and_voffset,
+ eq_value_and_voffset,
+ xfree, xcalloc, xfree));
+ std::vector<value_and_voffset *> result_vec;
- compute_vtable_size (offset_hash, &result_vec, value);
-
- qsort (VEC_address (value_and_voffset_p, result_vec),
- VEC_length (value_and_voffset_p, result_vec),
- sizeof (value_and_voffset_p),
- compare_value_and_voffset);
+ compute_vtable_size (offset_hash.get (), &result_vec, value);
+ std::sort (result_vec.begin (), result_vec.end (),
+ compare_value_and_voffset);
count = 0;
- for (i = 0; VEC_iterate (value_and_voffset_p, result_vec, i, iter); ++i)
+ for (value_and_voffset *iter : result_vec)
{
if (iter->max_voffset >= 0)
{
++count;
}
}
-
- do_cleanups (cleanup);
}
/* Return a GDB type representing `struct std::type_info', laid out
gdb_assert (field == (field_list + 2));
- t = arch_type (arch, TYPE_CODE_STRUCT, offset, NULL);
+ t = arch_type (arch, TYPE_CODE_STRUCT, offset * TARGET_CHAR_BIT, NULL);
TYPE_NFIELDS (t) = field - field_list;
TYPE_FIELDS (t) = field_list;
- TYPE_TAG_NAME (t) = "gdb_gnu_v3_type_info";
+ TYPE_NAME (t) = "gdb_gnu_v3_type_info";
INIT_CPLUS_SPECIFIC (t);
return t;
struct type *typeinfo_type;
struct type *type;
struct gdbarch *gdbarch;
- struct cleanup *cleanup;
struct value *result;
- char *type_name, *canonical;
+ std::string 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
gdbarch = get_type_arch (type);
type_name = type_to_string (type);
- if (type_name == NULL)
+ if (type_name.empty ())
error (_("cannot find typeinfo for unnamed type"));
- 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 (type_name);
- if (canonical != NULL)
- {
- make_cleanup (xfree, canonical);
- type_name = canonical;
- }
+ canonical = cp_canonicalize_string (type_name.c_str ());
+ if (!canonical.empty ())
+ type_name = canonical;
typeinfo_type = gnuv3_get_typeid_type (gdbarch);
vtable = gnuv3_get_vtable (gdbarch, type, address);
if (vtable == NULL)
- error (_("cannot find typeinfo for object of type '%s'"), type_name);
+ error (_("cannot find typeinfo for object of type '%s'"),
+ type_name.c_str ());
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 bound_minimal_symbol minsym;
-
- sym_name = concat ("typeinfo for ", type_name, (char *) NULL);
- make_cleanup (xfree, sym_name);
- minsym = lookup_minimal_symbol (sym_name, NULL, NULL);
+ std::string sym_name = std::string ("typeinfo for ") + type_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'"), type_name);
+ error (_("could not find typeinfo symbol for '%s'"), type_name.c_str ());
result = value_at_lazy (typeinfo_type, BMSYMBOL_VALUE_ADDRESS (minsym));
}
- do_cleanups (cleanup);
return result;
}
/* Implement the 'get_typename_from_type_info' method. */
-static char *
+static std::string
gnuv3_get_typename_from_type_info (struct value *type_info_ptr)
{
struct gdbarch *gdbarch = get_type_arch (value_type (type_info_ptr));
#define TYPEINFO_PREFIX "typeinfo for "
#define TYPEINFO_PREFIX_LEN (sizeof (TYPEINFO_PREFIX) - 1)
- symname = MSYMBOL_DEMANGLED_NAME (typeinfo_sym.minsym);
+ symname = typeinfo_sym.minsym->demangled_name ();
if (symname == NULL || strncmp (symname, TYPEINFO_PREFIX,
TYPEINFO_PREFIX_LEN))
error (_("typeinfo symbol '%s' has unexpected name"),
- MSYMBOL_LINKAGE_NAME (typeinfo_sym.minsym));
+ 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 savestring (class_name, atsign - class_name);
- return xstrdup (class_name);
+ 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)
{
- char *type_name;
- struct cleanup *cleanup;
- struct value *type_val;
- struct expression *expr;
- struct type *result;
-
- 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 (type_name);
- make_cleanup (xfree, expr);
-
- type_val = evaluate_type (expr);
- result = value_type (type_val);
-
- do_cleanups (cleanup);
- return result;
+ 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);
}
/* Determine if we are currently in a C++ thunk. If so, get the address
/* 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.minsym);
+ thunk_name = thunk_sym.minsym->demangled_name ();
if (thunk_name == NULL || strstr (thunk_name, " thunk to ") == NULL)
return 0;
of the real function from the function descriptor before passing on
the address to other layers of GDB. */
func_addr = gdbarch_convert_from_func_ptr_addr (gdbarch, method_stop_pc,
- ¤t_target);
+ current_top_target ());
if (func_addr != 0)
method_stop_pc = func_addr;
gnu_v3_abi_ops.pass_by_reference = gnuv3_pass_by_reference;
}
-extern initialize_file_ftype _initialize_gnu_v3_abi; /* -Wmissing-prototypes */
-
void
_initialize_gnu_v3_abi (void)
{