From 71b16efa43348381c82f4e8f494fe327e7d6493e Mon Sep 17 00:00:00 2001 From: Jim Kingdon Date: Fri, 26 Apr 1991 23:04:10 +0000 Subject: [PATCH] * values.c (check_stub_method): Do lookup_method_type and stuff rather than smash_to_method_type. * values.c (check_stub_method): Deal with operator names. * values.c: Move declaration of cplus_demangle to top of file. * values.c (baseclass_addr): If can't read memory, set *ERRP rather than calling error(). * values.c (value_static_field): Recursively check all baseclasses. Return NULL if not found. * values.c, value.h: New functions value_{headof,from_vtable_info}. values.c (value_virtual_fn_field): Don't bother to do anything with return value from fill_in_vptr_fieldno.CVS: Modified Files: --- gdb/values.c | 237 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 187 insertions(+), 50 deletions(-) diff --git a/gdb/values.c b/gdb/values.c index 88ceb3d92e..e4578a0cd5 100644 --- a/gdb/values.c +++ b/gdb/values.c @@ -28,6 +28,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "command.h" #include "gdbcmd.h" +extern char *cplus_demangle (); +extern char *cplus_mangle_opname (); + /* The value-history records all the values printed by print commands during this session. Each chunk records 60 consecutive values. The first chunk on @@ -876,8 +879,7 @@ value_virtual_fn_field (arg1, f, j, type) was. If so, fill in the virtual function table entry for the type now. */ if (TYPE_VPTR_FIELDNO (context) < 0) - TYPE_VPTR_FIELDNO (context) - = fill_in_vptr_fieldno (context); + fill_in_vptr_fieldno (context); /* The virtual function table is now an array of structures which have the form { int16 offset, delta; void *pfn; }. */ @@ -904,13 +906,109 @@ value_virtual_fn_field (arg1, f, j, type) 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). + After looking at the vtables between BTYPE and DTYPE, + return the most derived type we find. The caller must + be satisfied when the return value == DTYPE. + + FIXME-tiemann: should work with dossier entries as well. */ + +static value +value_headof (arg, btype, dtype) + value arg; + struct type *btype, *dtype; +{ + /* First collect the vtables we must look at for this object. */ + /* FIXME-tiemann: right now, just look at top-most vtable. */ + value vtbl, entry, best_entry = 0; + struct type *entry_type; + int i, nelems; + int offset, best_offset = 0; + struct symbol *sym; + CORE_ADDR pc_for_sym; + char *demangled_name; + + vtbl = value_ind (value_field (value_ind (arg), TYPE_VPTR_FIELDNO (dtype))); + + /* Check that VTBL looks like it points to a virtual function table. */ + i = find_pc_misc_function (VALUE_ADDRESS (vtbl)); + if (i < 0 || ! VTBL_PREFIX_P (misc_function_vector[i].name)) + { + /* If we expected to find a vtable, but did not, let the user + know that we aren't happy, but don't throw an error. + FIXME: there has to be a better way to do this. */ + struct type *error_type = (struct type *)xmalloc (sizeof (struct type)); + bcopy (VALUE_TYPE (arg), error_type, sizeof (struct type)); + TYPE_NAME (error_type) = savestring ("suspicious *", sizeof ("suspicious *")); + VALUE_TYPE (arg) = error_type; + return arg; + } + + /* Now search through the virtual function table. */ + entry = value_ind (vtbl); + entry_type = VALUE_TYPE (entry); + nelems = value_as_long (value_field (entry, 2)); + for (i = 1; i <= nelems; i++) + { + entry = value_subscript (vtbl, value_from_long (builtin_type_int, i)); + offset = value_as_long (value_field (entry, 0)); + if (offset < best_offset) + { + best_offset = offset; + best_entry = entry; + } + } + if (best_entry == 0) + return arg; + + /* Move the pointer according to BEST_ENTRY's offset, and figure + out what type we should return as the new pointer. */ + pc_for_sym = value_as_long (value_field (best_entry, 2)); + sym = find_pc_function (pc_for_sym); + demangled_name = cplus_demangle (SYMBOL_NAME (sym), -1); + *(strchr (demangled_name, ':')) = '\0'; + sym = lookup_symbol (demangled_name, 0, VAR_NAMESPACE, 0, 0); + if (sym == 0) + error ("could not find type declaration for `%s'", SYMBOL_NAME (sym)); + free (demangled_name); + arg = value_add (value_cast (builtin_type_int, arg), + value_field (best_entry, 0)); + VALUE_TYPE (arg) = lookup_pointer_type (SYMBOL_TYPE (sym)); + return arg; +} + +/* ARG is a pointer object of type TYPE. If TYPE has virtual + function tables, probe ARG's tables (including the vtables + of its baseclasses) to figure out the most derived type that ARG + could actually be a pointer to. */ + +value +value_from_vtable_info (arg, type) + value arg; + struct type *type; +{ + /* Take care of preliminaries. */ + if (TYPE_VPTR_FIELDNO (type) < 0) + fill_in_vptr_fieldno (type); + if (TYPE_VPTR_FIELDNO (type) < 0 || VALUE_REPEATED (arg)) + return 0; + + return value_headof (arg, 0, type); +} + /* The value of a static class member does not depend on its instance, only on its type. If FIELDNO >= 0, then fieldno is a valid field number and is used directly. Otherwise, FIELDNAME is the name of the field we are searching for. If it is not a static field name, an error is signaled. TYPE is the type in which we look for the - static field member. */ + static field member. + + Return zero if we couldn't find anything; the caller may signal + an error in that case. */ + value value_static_field (type, fieldname, fieldno) register struct type *type; @@ -925,41 +1023,32 @@ value_static_field (type, fieldname, fieldno) { register struct type *t = type; /* Look for static field. */ - while (t) - { - int i; - for (i = TYPE_NFIELDS (t) - 1; i >= TYPE_N_BASECLASSES (t); i--) - if (! strcmp (TYPE_FIELD_NAME (t, i), fieldname)) + int i; + for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--) + if (! strcmp (TYPE_FIELD_NAME (type, i), fieldname)) + { + if (TYPE_FIELD_STATIC (type, i)) { - if (TYPE_FIELD_STATIC (t, i)) - { - fieldno = i; - goto found; - } - else - error ("field `%s' is not static"); + fieldno = i; + goto found; } - /* FIXME: this does not recursively check multiple baseclasses. */ - t = TYPE_N_BASECLASSES (t) ? TYPE_BASECLASS (t, 0) : 0; + else + error ("field `%s' is not static", fieldname); + } + for (; i > 0; i--) + { + v = value_static_field (TYPE_BASECLASS (type, i), fieldname, -1); + if (v != 0) + return v; } - t = type; - - if (destructor_name_p (fieldname, t)) + if (destructor_name_p (fieldname, type)) error ("Cannot get value of destructor"); - while (t) + for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; i--) { - int i; - - for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; i--) - { - if (! strcmp (TYPE_FN_FIELDLIST_NAME (t, i), fieldname)) - { - error ("Cannot get value of method \"%s\"", fieldname); - } - } - t = TYPE_N_BASECLASSES (t) ? TYPE_BASECLASS (t, 0) : 0; + if (! strcmp (TYPE_FN_FIELDLIST_NAME (type, i), fieldname)) + error ("Cannot get value of method \"%s\"", fieldname); } error("there is no field named %s", fieldname); } @@ -976,17 +1065,26 @@ value_static_field (type, fieldname, fieldno) /* Compute the address of the baseclass which is the INDEXth baseclass of TYPE. The TYPE base - of the object is at VALADDR. */ + of the object is at VALADDR. + + If ERRP is non-NULL, set *ERRP to be the errno code of any error, + or 0 if no error. In that case the return value is not the address + of the baseclasss, but the address which could not be read + successfully. */ char * -baseclass_addr (type, index, valaddr, valuep) +baseclass_addr (type, index, valaddr, valuep, errp) struct type *type; int index; char *valaddr; value *valuep; + int *errp; { struct type *basetype = TYPE_BASECLASS (type, index); + if (errp) + *errp = 0; + if (BASETYPE_VIA_VIRTUAL (type, index)) { /* Must hunt for the pointer to this virtual baseclass. */ @@ -1005,12 +1103,35 @@ baseclass_addr (type, index, valaddr, valuep) { if (! strcmp (vbase_name, TYPE_FIELD_NAME (type, i))) { - value v = value_at (basetype, - unpack_long (TYPE_FIELD_TYPE (type, i), - valaddr + (TYPE_FIELD_BITPOS (type, i) / 8))); - if (valuep) - *valuep = v; - return (char *) VALUE_CONTENTS (v); + value val = allocate_value (basetype); + CORE_ADDR addr; + int status; + + addr = unpack_long (TYPE_FIELD_TYPE (type, i), + valaddr + (TYPE_FIELD_BITPOS (type, i) / 8)); + + status = target_read_memory (addr, + VALUE_CONTENTS_RAW (val), + TYPE_LENGTH (type)); + VALUE_LVAL (val) = lval_memory; + VALUE_ADDRESS (val) = addr; + + if (status != 0) + { + if (valuep) + *valuep = NULL; + release_value (val); + value_free (val); + if (errp) + *errp = status; + return (char *)addr; + } + else + { + if (valuep) + *valuep = val; + return (char *) VALUE_CONTENTS (val); + } } } /* Not in the fields, so try looking through the baseclasses. */ @@ -1050,18 +1171,33 @@ check_stub_method (type, i, j) { extern char *gdb_mangle_typename (), *strchr (); struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i); + char *field_name = TYPE_FN_FIELDLIST_NAME (type, i); char *inner_name = gdb_mangle_typename (type); - char *mangled_name - = (char *)xmalloc (strlen (TYPE_FN_FIELDLIST_NAME (type, i)) - + strlen (inner_name) - + strlen (TYPE_FN_FIELD_PHYSNAME (f, j)) - + 1); - char *demangled_name, *cplus_demangle (); + int mangled_name_len = (strlen (field_name) + + strlen (inner_name) + + strlen (TYPE_FN_FIELD_PHYSNAME (f, j)) + + 1); + char *mangled_name; + char *demangled_name; char *argtypetext, *p; int depth = 0, argcount = 1; struct type **argtypes; - strcpy (mangled_name, TYPE_FN_FIELDLIST_NAME (type, i)); + if (OPNAME_PREFIX_P (field_name)) + { + char *opname = cplus_mangle_opname (field_name + 3); + mangled_name_len += strlen (opname); + mangled_name = (char *)xmalloc (mangled_name_len); + + strncpy (mangled_name, field_name, 3); + mangled_name[3] = '\0'; + strcat (mangled_name, opname); + } + else + { + mangled_name = (char *)xmalloc (mangled_name_len); + strcpy (mangled_name, TYPE_FN_FIELDLIST_NAME (type, i)); + } strcat (mangled_name, inner_name); strcat (mangled_name, TYPE_FN_FIELD_PHYSNAME (f, j)); demangled_name = cplus_demangle (mangled_name, 0); @@ -1119,11 +1255,12 @@ check_stub_method (type, i, j) argtypes[argcount] = NULL; /* List terminator */ free (demangled_name); - smash_to_method_type (TYPE_FN_FIELD_TYPE (f, j), type, - TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)), - argtypes); + + type = lookup_method_type (type, TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)), argtypes); + /* Free the stub type...it's no longer needed. */ + free (TYPE_FN_FIELD_TYPE (f, j)); TYPE_FN_FIELD_PHYSNAME (f, j) = mangled_name; - TYPE_FLAGS (TYPE_FN_FIELD_TYPE (f, j)) &= ~TYPE_FLAG_STUB; + TYPE_FN_FIELD_TYPE (f, j) = type; } long -- 2.34.1