/* Abstraction of GNU v2 abi.
- Copyright (C) 2001, 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2003, 2005, 2007, 2008, 2009, 2010, 2011
+ Free Software Foundation, Inc.
Contributed by Daniel Berlin <dberlin@redhat.com>
#include "demangle.h"
#include "cp-abi.h"
#include "cp-support.h"
-#include "gnu-v2-abi.h"
+#include "exceptions.h"
#include <ctype.h>
{
struct value *arg1 = *arg1p;
struct type *type1 = check_typedef (value_type (arg1));
-
-
struct type *entry_type;
/* First, get the virtual function table pointer. That comes
with a strange type, so cast it to type `pointer to long' (which
struct value *entry;
struct value *vfn;
struct value *vtbl;
- struct value *vi = value_from_longest (builtin_type_int,
- (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j));
+ LONGEST vi = (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j);
struct type *fcontext = TYPE_FN_FIELD_FCONTEXT (f, j);
struct type *context;
+ struct type *context_vptr_basetype;
+ int context_vptr_fieldno;
+
if (fcontext == NULL)
/* We don't have an fcontext (e.g. the program was compiled with
g++ version 1). Try to get the vtbl from the TYPE_VPTR_BASETYPE.
if (TYPE_TARGET_TYPE (context) != type1)
{
struct value *tmp = value_cast (context, value_addr (arg1));
+
arg1 = value_ind (tmp);
type1 = check_typedef (value_type (arg1));
}
/* This type may have been defined before its virtual function table
was. If so, fill in the virtual function table entry for the
type now. */
- if (TYPE_VPTR_FIELDNO (context) < 0)
- fill_in_vptr_fieldno (context);
+ context_vptr_fieldno = get_vptr_fieldno (context, &context_vptr_basetype);
+ /* FIXME: What to do if vptr_fieldno is still -1? */
/* The virtual function table is now an array of structures
which have the form { int16 offset, delta; void *pfn; }. */
- vtbl = value_primitive_field (arg1, 0, TYPE_VPTR_FIELDNO (context),
- TYPE_VPTR_BASETYPE (context));
+ vtbl = value_primitive_field (arg1, 0, context_vptr_fieldno,
+ context_vptr_basetype);
/* With older versions of g++, the vtbl field pointed to an array
- of structures. Nowadays it points directly to the structure. */
+ of structures. Nowadays it points directly to the structure. */
if (TYPE_CODE (value_type (vtbl)) == TYPE_CODE_PTR
&& TYPE_CODE (TYPE_TARGET_TYPE (value_type (vtbl))) == TYPE_CODE_ARRAY)
{
/* Handle the case where the vtbl field points to an
- array of structures. */
+ array of structures. */
vtbl = value_ind (vtbl);
/* Index into the virtual function table. This is hard-coded because
}
else
{
- /* Handle the case where the vtbl field points directly to a structure. */
- vtbl = value_add (vtbl, vi);
+ /* Handle the case where the vtbl field points directly to a
+ structure. */
+ vtbl = value_ptradd (vtbl, vi);
entry = value_ind (vtbl);
}
if (TYPE_CODE (entry_type) == TYPE_CODE_STRUCT)
{
- /* Move the `this' pointer according to the virtual function table. */
- set_value_offset (arg1, value_offset (arg1) + value_as_long (value_field (entry, 0)));
+ /* Move the `this' pointer according to the virtual function table. */
+ set_value_offset (arg1, value_offset (arg1)
+ + value_as_long (value_field (entry, 0)));
if (!value_lazy (arg1))
{
else
error (_("I'm confused: virtual function table has bad type"));
/* Reinstantiate the function pointer with the correct type. */
- deprecated_set_value_type (vfn, lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j)));
+ deprecated_set_value_type (vfn,
+ lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j)));
*arg1p = arg1;
return vfn;
{
struct type *known_type;
struct type *rtti_type;
- CORE_ADDR coreptr;
- struct value *vp;
- long top_offset = 0;
- char rtti_type_name[256];
CORE_ADDR vtbl;
struct minimal_symbol *minsym;
- struct symbol *sym;
- char *demangled_name;
+ char *demangled_name, *p;
struct type *btype;
+ struct type *known_type_vptr_basetype;
+ int known_type_vptr_fieldno;
if (full)
*full = 0;
if (using_enc)
*using_enc = 0;
- /* Get declared type */
+ /* Get declared type. */
known_type = value_type (v);
CHECK_TYPEDEF (known_type);
- /* RTTI works only or class objects */
+ /* RTTI works only or class objects. */
if (TYPE_CODE (known_type) != TYPE_CODE_CLASS)
return NULL;
the type info functions, which are always right. Deal with it
until then. */
- /* If the type has no vptr fieldno, try to get it filled in */
- if (TYPE_VPTR_FIELDNO(known_type) < 0)
- fill_in_vptr_fieldno(known_type);
+ /* Try to get the vptr basetype, fieldno. */
+ known_type_vptr_fieldno = get_vptr_fieldno (known_type,
+ &known_type_vptr_basetype);
- /* If we still can't find one, give up */
- if (TYPE_VPTR_FIELDNO(known_type) < 0)
+ /* If we can't find it, give up. */
+ if (known_type_vptr_fieldno < 0)
return NULL;
/* Make sure our basetype and known type match, otherwise, cast
- so we can get at the vtable properly.
- */
- btype = TYPE_VPTR_BASETYPE (known_type);
+ so we can get at the vtable properly. */
+ btype = known_type_vptr_basetype;
CHECK_TYPEDEF (btype);
if (btype != known_type )
{
if (using_enc)
*using_enc=1;
}
- /*
- We can't use value_ind here, because it would want to use RTTI, and
- we'd waste a bunch of time figuring out we already know the type.
- Besides, we don't care about the type, just the actual pointer
- */
- if (VALUE_ADDRESS (value_field (v, TYPE_VPTR_FIELDNO (known_type))) == 0)
+ /* We can't use value_ind here, because it would want to use RTTI, and
+ we'd waste a bunch of time figuring out we already know the type.
+ Besides, we don't care about the type, just the actual pointer. */
+ if (value_address (value_field (v, known_type_vptr_fieldno)) == 0)
return NULL;
- vtbl=value_as_address(value_field(v,TYPE_VPTR_FIELDNO(known_type)));
+ vtbl = value_as_address (value_field (v, known_type_vptr_fieldno));
- /* Try to find a symbol that is the vtable */
+ /* Try to find a symbol that is the vtable. */
minsym=lookup_minimal_symbol_by_pc(vtbl);
if (minsym==NULL
- || (demangled_name=DEPRECATED_SYMBOL_NAME (minsym))==NULL
+ || (demangled_name=SYMBOL_LINKAGE_NAME (minsym))==NULL
|| !is_vtable_name (demangled_name))
return NULL;
- /* If we just skip the prefix, we get screwed by namespaces */
+ /* If we just skip the prefix, we get screwed by namespaces. */
demangled_name=cplus_demangle(demangled_name,DMGL_PARAMS|DMGL_ANSI);
- *(strchr(demangled_name,' '))=0;
+ p = strchr (demangled_name, ' ');
+ if (p)
+ *p = '\0';
- /* Lookup the type for the name */
- /* FIXME: chastain/2003-11-26: block=NULL is bogus. See pr gdb/1465. */
+ /* Lookup the type for the name. */
+ /* FIXME: chastain/2003-11-26: block=NULL is bogus. See pr gdb/1465. */
rtti_type = cp_lookup_rtti_type (demangled_name, NULL);
if (rtti_type == NULL)
return NULL;
if (TYPE_N_BASECLASSES(rtti_type) > 1 && full && (*full) != 1)
{
if (top)
- *top=TYPE_BASECLASS_BITPOS(rtti_type,TYPE_VPTR_FIELDNO(rtti_type))/8;
+ *top = TYPE_BASECLASS_BITPOS (rtti_type,
+ TYPE_VPTR_FIELDNO(rtti_type)) / 8;
if (top && ((*top) >0))
{
if (TYPE_LENGTH(rtti_type) > TYPE_LENGTH(known_type))
return 0;
}
-/* 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. */
+/* 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. */
-int
+static int
gnuv2_baseclass_offset (struct type *type, int index,
- const bfd_byte *valaddr, CORE_ADDR address)
+ const bfd_byte *valaddr, int embedded_offset,
+ CORE_ADDR address, const struct value *val)
{
struct type *basetype = TYPE_BASECLASS (type, index);
{
if (vb_match (type, i, basetype))
{
- CORE_ADDR addr
- = unpack_pointer (TYPE_FIELD_TYPE (type, i),
- valaddr + (TYPE_FIELD_BITPOS (type, i) / 8));
+ struct type *field_type;
+ int field_offset;
+ int field_length;
+ CORE_ADDR addr;
- return addr - (LONGEST) address;
+ 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 =
- baseclass_offset (type, i, valaddr, address);
+ gnuv2_baseclass_offset (type, i, valaddr,
+ embedded_offset, address, val);
+
if (boffset)
return boffset;
}
- /* Not found. */
- return -1;
+
+ error (_("Baseclass offset not found"));
}
/* Baseclass is easily computed. */