mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-10-17 04:43:17 +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:
192
gdb/values.c
192
gdb/values.c
@ -45,7 +45,6 @@ static void show_values (char *, int);
|
||||
|
||||
static void show_convenience (char *, int);
|
||||
|
||||
static int vb_match (struct type *, int, struct type *);
|
||||
|
||||
/* The value-history records all the values printed
|
||||
by print commands during this session. Each chunk
|
||||
@ -890,197 +889,6 @@ value_fn_field (value_ptr *arg1p, struct fn_field *f, int j, struct type *type,
|
||||
return v;
|
||||
}
|
||||
|
||||
/* Return a virtual function as a value.
|
||||
ARG1 is the object which provides the virtual function
|
||||
table pointer. *ARG1P is side-effected in calling this function.
|
||||
F is the list of member functions which contains the desired virtual
|
||||
function.
|
||||
J is an index into F which provides the desired virtual function.
|
||||
|
||||
TYPE is the type in which F is located. */
|
||||
value_ptr
|
||||
value_virtual_fn_field (value_ptr *arg1p, struct fn_field *f, int j,
|
||||
struct type *type, int offset)
|
||||
{
|
||||
value_ptr arg1 = *arg1p;
|
||||
struct type *type1 = check_typedef (VALUE_TYPE (arg1));
|
||||
|
||||
if (TYPE_HAS_VTABLE (type))
|
||||
{
|
||||
/* Deal with HP/Taligent runtime model for virtual functions */
|
||||
value_ptr vp;
|
||||
value_ptr argp; /* arg1 cast to base */
|
||||
CORE_ADDR coreptr; /* pointer to target address */
|
||||
int class_index; /* which class segment pointer to use */
|
||||
struct type *ftype = TYPE_FN_FIELD_TYPE (f, j); /* method type */
|
||||
|
||||
argp = value_cast (type, *arg1p);
|
||||
|
||||
if (VALUE_ADDRESS (argp) == 0)
|
||||
error ("Address of object is null; object may not have been created.");
|
||||
|
||||
/* pai: FIXME -- 32x64 possible problem? */
|
||||
/* First word (4 bytes) in object layout is the vtable pointer */
|
||||
coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (argp)); /* pai: (temp) */
|
||||
/* + offset + VALUE_EMBEDDED_OFFSET (argp)); */
|
||||
|
||||
if (!coreptr)
|
||||
error ("Virtual table pointer is null for object; object may not have been created.");
|
||||
|
||||
/* pai/1997-05-09
|
||||
* FIXME: The code here currently handles only
|
||||
* the non-RRBC case of the Taligent/HP runtime spec; when RRBC
|
||||
* is introduced, the condition for the "if" below will have to
|
||||
* be changed to be a test for the RRBC case. */
|
||||
|
||||
if (1)
|
||||
{
|
||||
/* Non-RRBC case; the virtual function pointers are stored at fixed
|
||||
* offsets in the virtual table. */
|
||||
|
||||
/* Retrieve the offset in the virtual table from the debug
|
||||
* info. The offset of the vfunc's entry is in words from
|
||||
* the beginning of the vtable; but first we have to adjust
|
||||
* by HP_ACC_VFUNC_START to account for other entries */
|
||||
|
||||
/* pai: FIXME: 32x64 problem here, a word may be 8 bytes in
|
||||
* which case the multiplier should be 8 and values should be long */
|
||||
vp = value_at (builtin_type_int,
|
||||
coreptr + 4 * (TYPE_FN_FIELD_VOFFSET (f, j) + HP_ACC_VFUNC_START), NULL);
|
||||
|
||||
coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
|
||||
/* coreptr now contains the address of the virtual function */
|
||||
/* (Actually, it contains the pointer to the plabel for the function. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* RRBC case; the virtual function pointers are found by double
|
||||
* indirection through the class segment tables. */
|
||||
|
||||
/* Choose class segment depending on type we were passed */
|
||||
class_index = class_index_in_primary_list (type);
|
||||
|
||||
/* Find class segment pointer. These are in the vtable slots after
|
||||
* some other entries, so adjust by HP_ACC_VFUNC_START for that. */
|
||||
/* pai: FIXME 32x64 problem here, if words are 8 bytes long
|
||||
* the multiplier below has to be 8 and value should be long. */
|
||||
vp = value_at (builtin_type_int,
|
||||
coreptr + 4 * (HP_ACC_VFUNC_START + class_index), NULL);
|
||||
/* Indirect once more, offset by function index */
|
||||
/* pai: FIXME 32x64 problem here, again multiplier could be 8 and value long */
|
||||
coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp) + 4 * TYPE_FN_FIELD_VOFFSET (f, j));
|
||||
vp = value_at (builtin_type_int, coreptr, NULL);
|
||||
coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
|
||||
|
||||
/* coreptr now contains the address of the virtual function */
|
||||
/* (Actually, it contains the pointer to the plabel for the function.) */
|
||||
|
||||
}
|
||||
|
||||
if (!coreptr)
|
||||
error ("Address of virtual function is null; error in virtual table?");
|
||||
|
||||
/* Wrap this addr in a value and return pointer */
|
||||
vp = allocate_value (ftype);
|
||||
VALUE_TYPE (vp) = ftype;
|
||||
VALUE_ADDRESS (vp) = coreptr;
|
||||
|
||||
/* pai: (temp) do we need the value_ind stuff in value_fn_field? */
|
||||
return vp;
|
||||
}
|
||||
else
|
||||
{ /* Not using HP/Taligent runtime conventions; so try to
|
||||
* use g++ conventions for virtual table */
|
||||
|
||||
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
|
||||
should serve just fine as a function type). Then, index into
|
||||
the table, and convert final value to appropriate function type. */
|
||||
value_ptr entry, vfn, vtbl;
|
||||
value_ptr vi = value_from_longest (builtin_type_int,
|
||||
(LONGEST) TYPE_FN_FIELD_VOFFSET (f, j));
|
||||
struct type *fcontext = TYPE_FN_FIELD_FCONTEXT (f, j);
|
||||
struct type *context;
|
||||
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.
|
||||
This won't work right for multiple inheritance, but at least we
|
||||
should do as well as GDB 3.x did. */
|
||||
fcontext = TYPE_VPTR_BASETYPE (type);
|
||||
context = lookup_pointer_type (fcontext);
|
||||
/* Now context is a pointer to the basetype containing the vtbl. */
|
||||
if (TYPE_TARGET_TYPE (context) != type1)
|
||||
{
|
||||
value_ptr tmp = value_cast (context, value_addr (arg1));
|
||||
VALUE_POINTED_TO_OFFSET (tmp) = 0;
|
||||
arg1 = value_ind (tmp);
|
||||
type1 = check_typedef (VALUE_TYPE (arg1));
|
||||
}
|
||||
|
||||
context = type1;
|
||||
/* Now context is the basetype containing the vtbl. */
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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));
|
||||
|
||||
/* With older versions of g++, the vtbl field pointed to an array
|
||||
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. */
|
||||
vtbl = value_ind (vtbl);
|
||||
|
||||
/* Index into the virtual function table. This is hard-coded because
|
||||
looking up a field is not cheap, and it may be important to save
|
||||
time, e.g. if the user has set a conditional breakpoint calling
|
||||
a virtual function. */
|
||||
entry = value_subscript (vtbl, vi);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Handle the case where the vtbl field points directly to a structure. */
|
||||
vtbl = value_add (vtbl, vi);
|
||||
entry = value_ind (vtbl);
|
||||
}
|
||||
|
||||
entry_type = check_typedef (VALUE_TYPE (entry));
|
||||
|
||||
if (TYPE_CODE (entry_type) == TYPE_CODE_STRUCT)
|
||||
{
|
||||
/* Move the `this' pointer according to the virtual function table. */
|
||||
VALUE_OFFSET (arg1) += value_as_long (value_field (entry, 0));
|
||||
|
||||
if (!VALUE_LAZY (arg1))
|
||||
{
|
||||
VALUE_LAZY (arg1) = 1;
|
||||
value_fetch_lazy (arg1);
|
||||
}
|
||||
|
||||
vfn = value_field (entry, 2);
|
||||
}
|
||||
else if (TYPE_CODE (entry_type) == TYPE_CODE_PTR)
|
||||
vfn = entry;
|
||||
else
|
||||
error ("I'm confused: virtual function table has bad type");
|
||||
/* Reinstantiate the function pointer with the correct type. */
|
||||
VALUE_TYPE (vfn) = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j));
|
||||
|
||||
*arg1p = arg1;
|
||||
return vfn;
|
||||
}
|
||||
}
|
||||
|
||||
/* ARG is a pointer to an object we know to be at least
|
||||
a DTYPE. BTYPE is the most derived basetype that has
|
||||
already been searched (and need not be searched again).
|
||||
|
Reference in New Issue
Block a user