static const char * gnuv3_find_method_in (struct type *domain, CORE_ADDR voffset, LONGEST adjustment) { int i; const char *physname; /* Search this class first. */ physname = NULL; if (adjustment == 0) { int len; len = TYPE_NFN_FIELDS (domain); for (i = 0; i < len; i++) { int len2, j; struct fn_field *f; f = TYPE_FN_FIELDLIST1 (domain, i); len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i); check_stub_method_group (domain, i); for (j = 0; j < len2; j++) if (TYPE_FN_FIELD_VOFFSET (f, j) == voffset) return TYPE_FN_FIELD_PHYSNAME (f, j); } } /* Next search non-virtual bases. If it's in a virtual base, we're out of luck. */ for (i = 0; i < TYPE_N_BASECLASSES (domain); i++) { int pos; struct type *basetype; if (BASETYPE_VIA_VIRTUAL (domain, i)) continue; pos = TYPE_BASECLASS_BITPOS (domain, i) / 8; basetype = TYPE_FIELD_TYPE (domain, i); /* Recurse with a modified adjustment. We don't need to adjust voffset. */ if (adjustment >= pos && adjustment < pos + TYPE_LENGTH (basetype)) return gnuv3_find_method_in (basetype, voffset, adjustment - pos); } return NULL; }
static struct value * gnuv3_virtual_fn_field (struct value **value_p, struct fn_field *f, int j, struct type *vfn_base, int offset) { struct type *values_type = check_typedef (value_type (*value_p)); struct gdbarch *gdbarch; /* Some simple sanity checks. */ if (TYPE_CODE (values_type) != TYPE_CODE_CLASS) error (_("Only classes can have virtual functions.")); /* Determine architecture. */ gdbarch = get_type_arch (values_type); /* Cast our value to the base class which defines this virtual function. This takes care of any necessary `this' adjustments. */ if (vfn_base != values_type) *value_p = value_cast (vfn_base, *value_p); return gnuv3_get_virtual_fn (gdbarch, *value_p, TYPE_FN_FIELD_TYPE (f, j), TYPE_FN_FIELD_VOFFSET (f, j)); }
/* 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. */ static struct value * gnuv2_virtual_fn_field (struct value **arg1p, struct fn_field * f, int j, struct type * type, int offset) { 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 should serve just fine as a function type). Then, index into the table, and convert final value to appropriate function type. */ 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)); 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) { struct value *tmp = value_cast (context, value_addr (arg1)); 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. */ set_value_offset (arg1, value_offset (arg1) + value_as_long (value_field (entry, 0))); if (!value_lazy (arg1)) { set_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. */ deprecated_set_value_type (vfn, lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j))); *arg1p = arg1; return vfn; }
/* 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. */ static struct value * hpacc_virtual_fn_field (struct value **arg1p, struct fn_field * f, int j, struct type * type, int offset) { struct value *arg1 = *arg1p; struct type *type1 = check_typedef (value_type (arg1)); /* Deal with HP/Taligent runtime model for virtual functions */ struct value *vp; struct value *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)); 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)); /* 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); 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); deprecated_set_value_type (vp, ftype); VALUE_ADDRESS (vp) = coreptr; /* pai: (temp) do we need the value_ind stuff in value_fn_field? */ return vp; }