mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-10-17 21:03:55 +08:00
(Changes from Daniel Berlin, with revisions by Jim Blandy.)
Abstract out operations specific to particular C++ ABI's, and invoke them through a function table. This removes the C++ ABI dependencies scattered throughout the code, and allows us to cleanly add support for new C++ ABI's. * cp-abi.h, cp-abi.h, gnu-v2-abi.c, hpacc-abi.c: New files. * c-typeprint.c, c-valprint.c, dbxread.c, eval.c, gdbtypes.c, jv-typeprint.c, linespec.c, symtab.c, typeprint.c, valops.c: #include "cp-abi.h". These files all use functions now declared there. * symtab.h (OPNAME_PREFIX_P, VTBL_PREFIX_P, DESTRUCTOR_PREFIX_P): Deleted. These services are now provided by functions declared in cp-abi.h. * value.h (value_rtti_type, value_virtual_fn_field): Same. * values.c (value_virtual_fn_field): Same, for this definition. * valops.c (value_rtti_type): Same. * c-typeprint.c (c_type_print_base): Use the functions from "cp-abi.h", instead of the old macros, or hard-coded ABI-specific tests. * dbxread.c (record_minimal_symbol): Same. * gdbtypes.c (get_destructor_fn_field, virtual_base_index, virtual_base_index_skip_primaries): Same. * jv-typeprint.c (java_type_print_base): Same. * linespec.c (find_methods, decode_line_1): Same. * symtab.c (gdb_mangle_name): Same. * Makefile.in (SFILES): Add the new .c files mentioned above. (cp_abi_h): New variable. (COMMON_OBS): Add gnu-v2-abi.o, hpacc-abi.o, and cp-abi.o. (cp-abi.o, gnu-v2-abi.o, hpacc-abi.o): New targets. (c-typeprint.o, c-valprint.o, dbxread.o, eval.o, gdbtypes.o, jv-typeprint.o, symtab.o, linespec.o, typeprint.o, valops.o): Add dependency on $(cp_abi_h).
This commit is contained in:
221
gdb/valops.c
221
gdb/valops.c
@ -31,6 +31,7 @@
|
||||
#include "language.h"
|
||||
#include "gdbcmd.h"
|
||||
#include "regcache.h"
|
||||
#include "cp-abi.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include "gdb_string.h"
|
||||
@ -3111,226 +3112,6 @@ value_struct_elt_for_reference (struct type *domain, int offset,
|
||||
}
|
||||
|
||||
|
||||
/* Find the real run-time type of a value using RTTI.
|
||||
* V is a pointer to the value.
|
||||
* A pointer to the struct type entry of the run-time type
|
||||
* is returneed.
|
||||
* FULL is a flag that is set only if the value V includes
|
||||
* the entire contents of an object of the RTTI type.
|
||||
* TOP is the offset to the top of the enclosing object of
|
||||
* the real run-time type. This offset may be for the embedded
|
||||
* object, or for the enclosing object of V.
|
||||
* USING_ENC is the flag that distinguishes the two cases.
|
||||
* If it is 1, then the offset is for the enclosing object,
|
||||
* otherwise for the embedded object.
|
||||
*
|
||||
*/
|
||||
|
||||
struct type *
|
||||
value_rtti_type (value_ptr v, int *full, int *top, int *using_enc)
|
||||
{
|
||||
struct type *known_type;
|
||||
struct type *rtti_type;
|
||||
CORE_ADDR coreptr;
|
||||
value_ptr vp;
|
||||
int using_enclosing = 0;
|
||||
long top_offset = 0;
|
||||
char rtti_type_name[256];
|
||||
|
||||
if (full)
|
||||
*full = 0;
|
||||
if (top)
|
||||
*top = -1;
|
||||
if (using_enc)
|
||||
*using_enc = 0;
|
||||
|
||||
/* Get declared type */
|
||||
known_type = VALUE_TYPE (v);
|
||||
CHECK_TYPEDEF (known_type);
|
||||
/* RTTI works only or class objects */
|
||||
if (TYPE_CODE (known_type) != TYPE_CODE_CLASS)
|
||||
return NULL;
|
||||
if (TYPE_HAS_VTABLE(known_type))
|
||||
{
|
||||
/* If neither the declared type nor the enclosing type of the
|
||||
* value structure has a HP ANSI C++ style virtual table,
|
||||
* we can't do anything. */
|
||||
if (!TYPE_HAS_VTABLE (known_type))
|
||||
{
|
||||
known_type = VALUE_ENCLOSING_TYPE (v);
|
||||
CHECK_TYPEDEF (known_type);
|
||||
if ((TYPE_CODE (known_type) != TYPE_CODE_CLASS) ||
|
||||
!TYPE_HAS_VTABLE (known_type))
|
||||
return NULL; /* No RTTI, or not HP-compiled types */
|
||||
CHECK_TYPEDEF (known_type);
|
||||
using_enclosing = 1;
|
||||
}
|
||||
|
||||
if (using_enclosing && using_enc)
|
||||
*using_enc = 1;
|
||||
|
||||
/* First get the virtual table address */
|
||||
coreptr = *(CORE_ADDR *) ((VALUE_CONTENTS_ALL (v))
|
||||
+ VALUE_OFFSET (v)
|
||||
+ (using_enclosing ? 0 : VALUE_EMBEDDED_OFFSET (v)));
|
||||
if (coreptr == 0)
|
||||
return NULL; /* return silently -- maybe called on gdb-generated value */
|
||||
|
||||
/* Fetch the top offset of the object */
|
||||
/* FIXME possible 32x64 problem with pointer size & arithmetic */
|
||||
vp = value_at (builtin_type_int,
|
||||
coreptr + 4 * HP_ACC_TOP_OFFSET_OFFSET,
|
||||
VALUE_BFD_SECTION (v));
|
||||
top_offset = value_as_long (vp);
|
||||
if (top)
|
||||
*top = top_offset;
|
||||
|
||||
/* Fetch the typeinfo pointer */
|
||||
/* FIXME possible 32x64 problem with pointer size & arithmetic */
|
||||
vp = value_at (builtin_type_int, coreptr + 4 * HP_ACC_TYPEINFO_OFFSET, VALUE_BFD_SECTION (v));
|
||||
/* Indirect through the typeinfo pointer and retrieve the pointer
|
||||
* to the string name */
|
||||
coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
|
||||
if (!coreptr)
|
||||
error ("Retrieved null typeinfo pointer in trying to determine run-time type");
|
||||
vp = value_at (builtin_type_int, coreptr + 4, VALUE_BFD_SECTION (v)); /* 4 -> offset of name field */
|
||||
/* FIXME possible 32x64 problem */
|
||||
|
||||
coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
|
||||
|
||||
read_memory_string (coreptr, rtti_type_name, 256);
|
||||
|
||||
if (strlen (rtti_type_name) == 0)
|
||||
error ("Retrieved null type name from typeinfo");
|
||||
|
||||
/* search for type */
|
||||
rtti_type = lookup_typename (rtti_type_name, (struct block *) 0, 1);
|
||||
|
||||
if (!rtti_type)
|
||||
error ("Could not find run-time type: invalid type name %s in typeinfo??", rtti_type_name);
|
||||
CHECK_TYPEDEF (rtti_type);
|
||||
#if 0
|
||||
printf ("RTTI type name %s, tag %s, full? %d\n", TYPE_NAME (rtti_type), TYPE_TAG_NAME (rtti_type), full ? *full : -1);
|
||||
#endif
|
||||
/* Check whether we have the entire object */
|
||||
if (full /* Non-null pointer passed */
|
||||
&&
|
||||
/* Either we checked on the whole object in hand and found the
|
||||
top offset to be zero */
|
||||
(((top_offset == 0) &&
|
||||
using_enclosing &&
|
||||
TYPE_LENGTH (known_type) == TYPE_LENGTH (rtti_type))
|
||||
||
|
||||
/* Or we checked on the embedded object and top offset was the
|
||||
same as the embedded offset */
|
||||
((top_offset == VALUE_EMBEDDED_OFFSET (v)) &&
|
||||
!using_enclosing &&
|
||||
TYPE_LENGTH (VALUE_ENCLOSING_TYPE (v)) == TYPE_LENGTH (rtti_type))))
|
||||
|
||||
*full = 1;
|
||||
}
|
||||
else
|
||||
/*
|
||||
Right now this is G++ RTTI. Plan on this changing in the
|
||||
future as i get around to setting the vtables properly for G++
|
||||
compiled stuff. Also, i'll be using the type info functions,
|
||||
which are always right. Deal with it until then.
|
||||
*/
|
||||
{
|
||||
CORE_ADDR vtbl;
|
||||
struct minimal_symbol *minsym;
|
||||
struct symbol *sym;
|
||||
char *demangled_name;
|
||||
struct type *btype;
|
||||
/* 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);
|
||||
|
||||
/* If we still can't find one, give up */
|
||||
if (TYPE_VPTR_FIELDNO(known_type) < 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);
|
||||
CHECK_TYPEDEF (btype);
|
||||
if (btype != known_type )
|
||||
{
|
||||
v = value_cast (btype, v);
|
||||
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)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
If we are enclosed by something that isn't us, adjust the
|
||||
address properly and set using_enclosing.
|
||||
*/
|
||||
if (VALUE_ENCLOSING_TYPE(v) != VALUE_TYPE(v))
|
||||
{
|
||||
value_ptr tempval;
|
||||
tempval=value_field(v,TYPE_VPTR_FIELDNO(known_type));
|
||||
VALUE_ADDRESS(tempval)+=(TYPE_BASECLASS_BITPOS(known_type,TYPE_VPTR_FIELDNO(known_type))/8);
|
||||
vtbl=value_as_pointer(tempval);
|
||||
using_enclosing=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
vtbl=value_as_pointer(value_field(v,TYPE_VPTR_FIELDNO(known_type)));
|
||||
using_enclosing=0;
|
||||
}
|
||||
|
||||
/* Try to find a symbol that is the vtable */
|
||||
minsym=lookup_minimal_symbol_by_pc(vtbl);
|
||||
if (minsym==NULL || (demangled_name=SYMBOL_NAME(minsym))==NULL || !VTBL_PREFIX_P(demangled_name))
|
||||
return NULL;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Lookup the type for the name */
|
||||
rtti_type=lookup_typename(demangled_name, (struct block *)0,1);
|
||||
|
||||
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;
|
||||
if (top && ((*top) >0))
|
||||
{
|
||||
if (TYPE_LENGTH(rtti_type) > TYPE_LENGTH(known_type))
|
||||
{
|
||||
if (full)
|
||||
*full=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (full)
|
||||
*full=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (full)
|
||||
*full=1;
|
||||
}
|
||||
if (using_enc)
|
||||
*using_enc=using_enclosing;
|
||||
}
|
||||
return rtti_type;
|
||||
}
|
||||
|
||||
/* Given a pointer value V, find the real (RTTI) type
|
||||
of the object it points to.
|
||||
Other parameters FULL, TOP, USING_ENC as with value_rtti_type()
|
||||
|
Reference in New Issue
Block a user