📄 values.c
字号:
struct type *error_type = (struct type *)xmalloc (sizeof (struct type)); memcpy (error_type, VALUE_TYPE (arg), 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); nelems = longest_to_int (value_as_long (value_field (entry, 2))); for (i = 1; i <= nelems; i++) { entry = value_subscript (vtbl, value_from_longest (builtin_type_int, (LONGEST) i)); offset = longest_to_int (value_as_long (value_field (entry, 0))); /* If we use '<=' we can handle single inheritance * where all offsets are zero - just use the first entry found. */ if (offset <= best_offset) { best_offset = offset; best_entry = entry; } } /* Move the pointer according to BEST_ENTRY's offset, and figure out what type we should return as the new pointer. */ if (best_entry == 0) { /* An alternative method (which should no longer be necessary). * But we leave it in for future use, when we will hopefully * have optimizes the vtable to use thunks instead of offsets. */ /* Use the name of vtable itself to extract a base type. */ demangled_name += 4; /* Skip _vt$ prefix. */ } else { pc_for_sym = value_as_pointer (value_field (best_entry, 2)); sym = find_pc_function (pc_for_sym); demangled_name = cplus_demangle (SYMBOL_NAME (sym), DMGL_ANSI); *(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)); if (best_entry) { 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. */valuevalue_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);}/* Compute the offset of the baseclass which is the INDEXth baseclass of class TYPE, for a value ARG, wih extra offset of OFFSET. The result is the offste of the baseclass value relative to (the address of)(ARG) + OFFSET. -1 is returned on error. */intbaseclass_offset (type, index, arg, offset) struct type *type; int index; value arg; int offset;{ struct type *basetype = TYPE_BASECLASS (type, index); if (BASETYPE_VIA_VIRTUAL (type, index)) { /* Must hunt for the pointer to this virtual baseclass. */ register int i, len = TYPE_NFIELDS (type); register int n_baseclasses = TYPE_N_BASECLASSES (type); char *vbase_name, *type_name = type_name_no_tag (basetype); vbase_name = (char *)alloca (strlen (type_name) + 8); sprintf (vbase_name, "_vb%c%s", CPLUS_MARKER, type_name); /* First look for the virtual baseclass pointer in the fields. */ for (i = n_baseclasses; i < len; i++) { if (! strcmp (vbase_name, TYPE_FIELD_NAME (type, i))) { CORE_ADDR addr = unpack_pointer (TYPE_FIELD_TYPE (type, i), VALUE_CONTENTS (arg) + VALUE_OFFSET (arg) + offset + (TYPE_FIELD_BITPOS (type, i) / 8)); if (VALUE_LVAL (arg) != lval_memory) return -1; return addr - (LONGEST) (VALUE_ADDRESS (arg) + VALUE_OFFSET (arg) + offset); } } /* Not in the fields, so try looking through the baseclasses. */ for (i = index+1; i < n_baseclasses; i++) { int boffset = baseclass_offset (type, i, arg, offset); if (boffset) return boffset; } /* Not found. */ return -1; } /* Baseclass is easily computed. */ return TYPE_BASECLASS_BITPOS (type, index) / 8;}/* Compute the address of the baseclass which is the INDEXth baseclass of class TYPE. The TYPE base 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. *//* FIXME Fix remaining uses of baseclass_addr to use baseclass_offset */char *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. */ register int i, len = TYPE_NFIELDS (type); register int n_baseclasses = TYPE_N_BASECLASSES (type); char *vbase_name, *type_name = type_name_no_tag (basetype); vbase_name = (char *)alloca (strlen (type_name) + 8); sprintf (vbase_name, "_vb$%s", type_name); /* First look for the virtual baseclass pointer in the fields. */ for (i = n_baseclasses; i < len; i++) { if (! strcmp (vbase_name, TYPE_FIELD_NAME (type, i))) { value val = allocate_value (basetype); CORE_ADDR addr; int status; addr = unpack_pointer (TYPE_FIELD_TYPE (type, i), valaddr + (TYPE_FIELD_BITPOS (type, i) / 8)); status = target_read_memory (addr, VALUE_CONTENTS_RAW (val), TYPE_LENGTH (basetype)); 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. */ for (i = index+1; i < n_baseclasses; i++) { char *baddr; baddr = baseclass_addr (type, i, valaddr, valuep, errp); if (baddr) return baddr; } /* Not found. */ if (valuep) *valuep = 0; return 0; } /* Baseclass is easily computed. */ if (valuep) *valuep = 0; return valaddr + TYPE_BASECLASS_BITPOS (type, index) / 8;}/* Unpack a field FIELDNO of the specified TYPE, from the anonymous object at VALADDR. Extracting bits depends on endianness of the machine. Compute the number of least significant bits to discard. For big endian machines, we compute the total number of bits in the anonymous object, subtract off the bit count from the MSB of the object to the MSB of the bitfield, then the size of the bitfield, which leaves the LSB discard count. For little endian machines, the discard count is simply the number of bits from the LSB of the anonymous object to the LSB of the bitfield. If the field is signed, we also do sign extension. */LONGESTunpack_field_as_long (type, valaddr, fieldno) struct type *type; char *valaddr; int fieldno;{ unsigned LONGEST val; unsigned LONGEST valmask; int bitpos = TYPE_FIELD_BITPOS (type, fieldno); int bitsize = TYPE_FIELD_BITSIZE (type, fieldno); int lsbcount; memcpy (&val, valaddr + bitpos / 8, sizeof (val)); SWAP_TARGET_AND_HOST (&val, sizeof (val)); /* Extract bits. See comment above. */#if BITS_BIG_ENDIAN lsbcount = (sizeof val * 8 - bitpos % 8 - bitsize);#else lsbcount = (bitpos % 8);#endif val >>= lsbcount; /* If the field does not entirely fill a LONGEST, then zero the sign bits. If the field is signed, and is negative, then sign extend. */ if ((bitsize > 0) && (bitsize < 8 * sizeof (val))) { valmask = (((unsigned LONGEST) 1) << bitsize) - 1; val &= valmask; if (!TYPE_UNSIGNED (TYPE_FIELD_TYPE (type, fieldno))) { if (val & (valmask ^ (valmask >> 1))) { val |= ~valmask; } } } return (val);}/* Modify the value of a bitfield. ADDR points to a block of memory in target byte order; the bitfield starts in the byte pointed to. FIELDVAL is the desired value of the field, in host byte order. BITPOS and BITSIZE indicate which bits (in target bit order) comprise the bitfield. */voidmodify_field (addr, fieldval, bitpos, bitsize) char *addr; int fieldval; int bitpos, bitsize;{ long oword; /* Reject values too big to fit in the field in question, otherwise adjoining fields may be corrupted. */ if (bitsize < (8 * sizeof (fieldval)) && 0 != (fieldval & ~((1<<bitsize)-1))) error ("Value %d does not fit in %d bits.", fieldval, bitsize); memcpy (&oword, addr, sizeof oword); SWAP_TARGET_AND_HOST (&oword, sizeof oword); /* To host format */ /* Shifting for bit field depends on endianness of the target machine. */#if BITS_BIG_ENDIAN bitpos = sizeof (oword) * 8 - bitpos - bitsize;#endif /* Mask out old value, while avoiding shifts >= longword size */ if (bitsize < 8 * sizeof (oword)) oword &= ~(((((unsigned long)1) << bitsize) - 1) << bitpos); else oword &= ~((-1) << bitpos); oword |= fieldval << bitpos; SWAP_TARGET_AND_HOST (&oword, sizeof oword); /* To target format */ memcpy (addr, &oword, sizeof oword);}/* Convert C numbers into newly allocated values */valuevalue_from_longest (type, num) struct type *type; register LONGEST num;{ register value val = allocate_value (type); register enum type_code code = TYPE_CODE (type); register int len = TYPE_LENGTH (type); /* FIXME, we assume that pointers have the same form and byte order as integers, and that all pointers have the same form. */ if (code == TYPE_CODE_INT || code == TYPE_CODE_ENUM || code == TYPE_CODE_CHAR || code == TYPE_CODE_PTR || code == TYPE_CODE_REF) { if (len == sizeof (char)) * (char *) VALUE_CONTENTS_RAW (val) = num; else if (len == sizeof (short)) * (short *) VALUE_CONTENTS_RAW (val) = num; else if (len == sizeof (int)) * (int *) VALUE_CONTENTS_RAW (val) = num; else if (len == sizeof (long)) * (long *) VALUE_CONTENTS_RAW (val) = num;#ifdef LONG_LONG else if (len == sizeof (long long)) * (long long *) VALUE_CONTENTS_RAW (val) = num;#endif else error ("Integer type encountered with unexpected data length."); } else error ("Unexpected type encountered for integer constant."); /* num was in host byte order. So now put the value's contents into target byte order. */ SWAP_TARGET_AND_HOST (VALUE_CONTENTS_RAW (val), len); return val;}valuevalue_from_double (type, num) struct type *type; double num;{ register value val = allocate_value (type); register enum type_code code = TYPE_CODE (type); register int len = TYPE_LENGTH (type); if (code == TYPE_CODE_FLT) { if (len == sizeof (float)) * (float *) VALUE_CONTENTS_RAW (val) = num; else if (len == sizeof (double)) * (double *) VALUE_CONTENTS_RAW (val) = num; else error ("Floating type encountered with unexpected data length."); } else error ("Unexpected type encountered for floating constant."); /* num was in host byte order. So now put the value's contents into target byte order. */ SWAP_TARGET_AND_HOST (VALUE_CONTENTS_RAW (val), len); return val;}/* Deal with the value that is "about to be returned". *//* Return the value that a function returning now would be returning to its caller, assuming its type is VALTYPE. RETBUF is where we look for what ought to be the contents of the registers (in raw form). This is because it is often desirable to restore old values to those registers after saving the contents of interest, and then call this function using the saved values. struct_return is non-zero when the function in question is using the structure return conventions on the machine in question; 0 when it is using the value returning conventions (this often means returning pointer to where structure is vs. returning value). */valuevalue_being_returned (valtype, retbuf, struct_return) register struct type *valtype; char retbuf[REGISTER_BYTES]; int struct_return; /*ARGSUSED*/{ register value val; CORE_ADDR addr;#if defined (EXTRACT_STRUCT_VALUE_ADDRESS) /* If this is not defined, just use EXTRACT_RETURN_VALUE instead. */ if (struct_return) { addr = EXTRACT_STRUCT_VALUE_ADDRESS (retbuf); if (!addr) error ("Function return value unknown"); return value_at (valtype, addr); }#endif val = allocate_value (valtype); EXTRACT_RETURN_VALUE (valtype, retbuf, VALUE_CONTENTS_RAW (val)); return val;}/* Should we use EXTRACT_STRUCT_VALUE_ADDRESS instead of EXTRACT_RETURN_VALUE? GCC_P is true if compiled with gcc and TYPE is the type (which is known to be struct, union or array). On most machines, the struct convention is used unless we are using gcc and the type is of a special size. */#if !defined (USE_STRUCT_CONVENTION)#define USE_STRUCT_CONVENTION(gcc_p, type)\ (!((gcc_p) && (TYPE_LENGTH (value_type) == 1 \ || TYPE_LENGTH (value_type) == 2 \ || TYPE_LENGTH (value_type) == 4 \ || TYPE_LENGTH (value_type) == 8 \ ) \ ))#endif/* Return true if the function specified is using the structure returning convention on this machine to return arguments, or 0 if it is using the value returning convention. FUNCTION is the value representing the function, FUNCADDR is the address of the function, and VALUE_TYPE is the type returned by the function. GCC_P is nonzero if compiled with GCC. */intusing_struct_return (function, funcaddr, value_type, gcc_p) value function; CORE_ADDR funcaddr; struct type *value_type; int gcc_p; /*ARGSUSED*/{ register enum type_code code = TYPE_CODE (value_type); if (code == TYPE_CODE_ERROR) error ("Function return type unknown."); if (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION || code == TYPE_CODE_ARRAY) return USE_STRUCT_CONVENTION (gcc_p, value_type); return 0;}/* Store VAL so it will be returned if a function returns now. Does not verify that VAL's type matches what the current function wants to return. */voidset_return_value (val) value val;{ register enum type_code code = TYPE_CODE (VALUE_TYPE (val)); double dbuf; LONGEST lbuf; if (code == TYPE_CODE_ERROR) error ("Function return type unknown."); if ( code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION) /* FIXME, implement struct return. */ error ("GDB does not support specifying a struct or union return value."); /* FIXME, this is bogus. We don't know what the return conventions are, or how values should be promoted.... */ if (code == TYPE_CODE_FLT) { dbuf = value_as_double (val); STORE_RETURN_VALUE (VALUE_TYPE (val), (char *)&dbuf); } else { lbuf = value_as_long (val); STORE_RETURN_VALUE (VALUE_TYPE (val), (char *)&lbuf); }}void_initialize_values (){ add_cmd ("convenience", no_class, show_convenience, "Debugger convenience (\"$foo\") variables.\n\These variables are created when you assign them values;\n\thus, \"print $foo=1\" gives \"$foo\" the value 1. Values may be any type.\n\n\A few convenience variables are given values automatically:\n\\"$_\"holds the last address examined with \"x\" or \"info lines\",\n\\"$__\" holds the contents of the last address examined with \"x\".", &showlist); add_cmd ("values", no_class, show_values, "Elements of value history around item number IDX (or last ten).", &showlist);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -