X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fvalues.c;h=0ffd5a63cb3fa2209fdad2f8da6d87ddd1b6afd4;hb=8ed44d196817ad04f542d03d40908d2f1ae375fc;hp=0f5e1e7c364bd33abe71260002720c79dfee64b3;hpb=afe4ca159ba3a3dc7a7af235fb13c4c234e550c3;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/values.c b/gdb/values.c index 0f5e1e7c36..0ffd5a63cb 100644 --- a/gdb/values.c +++ b/gdb/values.c @@ -1,5 +1,6 @@ -/* Low level packing and unpacking of values for GDB. - Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc. +/* Low level packing and unpacking of values for GDB, the GNU Debugger. + Copyright 1986, 1987, 1989, 1991, 1993, 1994, 1995, 1996, 1997 + Free Software Foundation, Inc. This file is part of GDB. @@ -15,21 +16,32 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include -#include #include "defs.h" -#include "param.h" +#include "gdb_string.h" #include "symtab.h" +#include "gdbtypes.h" #include "value.h" #include "gdbcore.h" #include "frame.h" #include "command.h" #include "gdbcmd.h" +#include "target.h" +#include "language.h" +#include "scm-lang.h" +#include "demangle.h" -extern char *cplus_demangle (); -extern char *cplus_mangle_opname (); +/* Local function prototypes. */ + +static value_ptr value_headof PARAMS ((value_ptr, struct type *, + struct type *)); + +static void show_values PARAMS ((char *, int)); + +static void show_convenience PARAMS ((char *, int)); + +static int vb_match PARAMS ((struct type *, int, struct type *)); /* The value-history records all the values printed by print commands during this session. Each chunk @@ -42,7 +54,7 @@ extern char *cplus_mangle_opname (); struct value_history_chunk { struct value_history_chunk *next; - value values[VALUE_HISTORY_CHUNK]; + value_ptr values[VALUE_HISTORY_CHUNK]; }; /* Chain of chunks now in use. */ @@ -55,19 +67,18 @@ static int value_history_count; /* Abs number of last entry stored */ (except for those released by calls to release_value) This is so they can be freed after each command. */ -static value all_values; +static value_ptr all_values; /* Allocate a value that has the correct length for type TYPE. */ -value +value_ptr allocate_value (type) struct type *type; { - register value val; - - check_stub_type (type); + register value_ptr val; + struct type *atype = check_typedef (type); - val = (value) xmalloc (sizeof (struct value) + TYPE_LENGTH (type)); + val = (struct value *) xmalloc (sizeof (struct value) + TYPE_LENGTH (atype)); VALUE_NEXT (val) = all_values; all_values = val; VALUE_TYPE (val) = type; @@ -77,46 +88,38 @@ allocate_value (type) VALUE_OFFSET (val) = 0; VALUE_BITPOS (val) = 0; VALUE_BITSIZE (val) = 0; - VALUE_REPEATED (val) = 0; - VALUE_REPETITIONS (val) = 0; VALUE_REGNO (val) = -1; VALUE_LAZY (val) = 0; VALUE_OPTIMIZED_OUT (val) = 0; + VALUE_BFD_SECTION (val) = NULL; + val->modifiable = 1; return val; } /* Allocate a value that has the correct length for COUNT repetitions type TYPE. */ -value +value_ptr allocate_repeat_value (type, count) struct type *type; int count; { - register value val; - - val = (value) xmalloc (sizeof (struct value) + TYPE_LENGTH (type) * count); - VALUE_NEXT (val) = all_values; - all_values = val; - VALUE_TYPE (val) = type; - VALUE_LVAL (val) = not_lval; - VALUE_ADDRESS (val) = 0; - VALUE_FRAME (val) = 0; - VALUE_OFFSET (val) = 0; - VALUE_BITPOS (val) = 0; - VALUE_BITSIZE (val) = 0; - VALUE_REPEATED (val) = 1; - VALUE_REPETITIONS (val) = count; - VALUE_REGNO (val) = -1; - VALUE_LAZY (val) = 0; - VALUE_OPTIMIZED_OUT (val) = 0; - return val; + int low_bound = current_language->string_lower_bound; /* ??? */ + /* FIXME-type-allocation: need a way to free this type when we are + done with it. */ + struct type *range_type + = create_range_type ((struct type *) NULL, builtin_type_int, + low_bound, count + low_bound - 1); + /* FIXME-type-allocation: need a way to free this type when we are + done with it. */ + return allocate_value (create_array_type ((struct type *) NULL, + type, range_type)); } /* Return a mark in the value chain. All values allocated after the mark is obtained (except for those released) are subject to being freed if a subsequent value_free_to_mark is passed the mark. */ -value +value_ptr value_mark () { return all_values; @@ -126,9 +129,9 @@ value_mark () (except for those released). */ void value_free_to_mark (mark) - value mark; + value_ptr mark; { - value val, next; + value_ptr val, next; for (val = all_values; val && val != mark; val = next) { @@ -144,7 +147,7 @@ value_free_to_mark (mark) void free_all_values () { - register value val, next; + register value_ptr val, next; for (val = all_values; val; val = next) { @@ -160,9 +163,9 @@ free_all_values () void release_value (val) - register value val; + register value_ptr val; { - register value v; + register value_ptr v; if (all_values == val) { @@ -180,32 +183,49 @@ release_value (val) } } +/* Release all values up to mark */ +value_ptr +value_release_to_mark (mark) + value_ptr mark; +{ + value_ptr val, next; + + for (val = next = all_values; next; next = VALUE_NEXT (next)) + if (VALUE_NEXT (next) == mark) + { + all_values = VALUE_NEXT (next); + VALUE_NEXT (next) = 0; + return val; + } + all_values = 0; + return val; +} + /* Return a copy of the value ARG. It contains the same contents, for same memory address, but it's a different block of storage. */ -static value +value_ptr value_copy (arg) - value arg; + value_ptr arg; { - register value val; register struct type *type = VALUE_TYPE (arg); - if (VALUE_REPEATED (arg)) - val = allocate_repeat_value (type, VALUE_REPETITIONS (arg)); - else - val = allocate_value (type); + register value_ptr val = allocate_value (type); VALUE_LVAL (val) = VALUE_LVAL (arg); VALUE_ADDRESS (val) = VALUE_ADDRESS (arg); VALUE_OFFSET (val) = VALUE_OFFSET (arg); VALUE_BITPOS (val) = VALUE_BITPOS (arg); VALUE_BITSIZE (val) = VALUE_BITSIZE (arg); + VALUE_FRAME (val) = VALUE_FRAME (arg); VALUE_REGNO (val) = VALUE_REGNO (arg); VALUE_LAZY (val) = VALUE_LAZY (arg); + VALUE_OPTIMIZED_OUT (val) = VALUE_OPTIMIZED_OUT (arg); + VALUE_BFD_SECTION (val) = VALUE_BFD_SECTION (arg); + val->modifiable = arg->modifiable; if (!VALUE_LAZY (val)) { - bcopy (VALUE_CONTENTS_RAW (arg), VALUE_CONTENTS_RAW (val), - TYPE_LENGTH (VALUE_TYPE (arg)) - * (VALUE_REPEATED (arg) ? VALUE_REPETITIONS (arg) : 1)); + memcpy (VALUE_CONTENTS_RAW (val), VALUE_CONTENTS_RAW (arg), + TYPE_LENGTH (VALUE_TYPE (arg))); } return val; } @@ -219,16 +239,21 @@ value_copy (arg) int record_latest_value (val) - value val; + value_ptr val; { int i; - /* Check error now if about to store an invalid float. We return -1 - to the caller, but allow them to continue, e.g. to print it as "Nan". */ - if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_FLT) { - (void) unpack_double (VALUE_TYPE (val), VALUE_CONTENTS (val), &i); - if (i) return -1; /* Indicate value not saved in history */ - } + /* We don't want this value to have anything to do with the inferior anymore. + In particular, "set $1 = 50" should not affect the variable from which + the value was taken, and fast watchpoints should be able to assume that + a value on the value history never changes. */ + if (VALUE_LAZY (val)) + value_fetch_lazy (val); + /* We preserve VALUE_LVAL so that the user can find out where it was fetched + from. This is a bit dubious, because then *&$1 does not just return $1 + but the current contents of that location. c'est la vie... */ + val->modifiable = 0; + release_value (val); /* Here we treat value_history_count as origin-zero and applying to the value being stored now. */ @@ -239,13 +264,12 @@ record_latest_value (val) register struct value_history_chunk *new = (struct value_history_chunk *) xmalloc (sizeof (struct value_history_chunk)); - bzero (new->values, sizeof new->values); + memset (new->values, 0, sizeof new->values); new->next = value_history_chain; value_history_chain = new; } value_history_chain->values[i] = val; - release_value (val); /* Now we regard value_history_count as origin-one and applying to the value just stored. */ @@ -255,7 +279,7 @@ record_latest_value (val) /* Return a copy of the value in the history with sequence number NUM. */ -value +value_ptr access_value_history (num) int num; { @@ -299,15 +323,15 @@ clear_value_history () { register struct value_history_chunk *next; register int i; - register value val; + register value_ptr val; while (value_history_chain) { for (i = 0; i < VALUE_HISTORY_CHUNK; i++) - if (val = value_history_chain->values[i]) - free (val); + if ((val = value_history_chain->values[i]) != NULL) + free ((PTR)val); next = value_history_chain->next; - free (value_history_chain); + free ((PTR)value_history_chain); value_history_chain = next; } value_history_count = 0; @@ -319,16 +343,14 @@ show_values (num_exp, from_tty) int from_tty; { register int i; - register value val; + register value_ptr val; static int num = 1; if (num_exp) { - if (num_exp[0] == '+' && num_exp[1] == '\0') - /* "info history +" should print from the stored position. */ - ; - else - /* "info history " should print around value number . */ + /* "info history +" should print from the stored position. + "info history " should print around value number . */ + if (num_exp[0] != '+' || num_exp[1] != '\0') num = parse_and_eval_address (num_exp) - 5; } else @@ -344,7 +366,7 @@ show_values (num_exp, from_tty) { val = access_value_history (i); printf_filtered ("$%d = ", i); - value_print (val, stdout, 0, Val_pretty_default); + value_print (val, gdb_stdout, 0, Val_pretty_default); printf_filtered ("\n"); } @@ -381,11 +403,11 @@ lookup_internalvar (name) register struct internalvar *var; for (var = internalvars; var; var = var->next) - if (!strcmp (var->name, name)) + if (STREQ (var->name, name)) return var; var = (struct internalvar *) xmalloc (sizeof (struct internalvar)); - var->name = concat (name, "", ""); + var->name = concat (name, NULL); var->value = allocate_value (builtin_type_void); release_value (var->value); var->next = internalvars; @@ -393,11 +415,11 @@ lookup_internalvar (name) return var; } -value +value_ptr value_of_internalvar (var) struct internalvar *var; { - register value val; + register value_ptr val; #ifdef IS_TRAPPED_INTERNALVAR if (IS_TRAPPED_INTERNALVAR (var->name)) @@ -416,7 +438,7 @@ void set_internalvar_component (var, offset, bitpos, bitsize, newval) struct internalvar *var; int offset, bitpos, bitsize; - value newval; + value_ptr newval; { register char *addr = VALUE_CONTENTS (var->value) + offset; @@ -426,26 +448,43 @@ set_internalvar_component (var, offset, bitpos, bitsize, newval) #endif if (bitsize) - modify_field (addr, (int) value_as_long (newval), + modify_field (addr, value_as_long (newval), bitpos, bitsize); else - bcopy (VALUE_CONTENTS (newval), addr, - TYPE_LENGTH (VALUE_TYPE (newval))); + memcpy (addr, VALUE_CONTENTS (newval), TYPE_LENGTH (VALUE_TYPE (newval))); } void set_internalvar (var, val) struct internalvar *var; - value val; + value_ptr val; { + value_ptr newval; + #ifdef IS_TRAPPED_INTERNALVAR if (IS_TRAPPED_INTERNALVAR (var->name)) SET_TRAPPED_INTERNALVAR (var, val, 0, 0, 0); #endif - free (var->value); - var->value = value_copy (val); - release_value (var->value); + newval = value_copy (val); + newval->modifiable = 1; + + /* Force the value to be fetched from the target now, to avoid problems + later when this internalvar is referenced and the target is gone or + has changed. */ + if (VALUE_LAZY (newval)) + value_fetch_lazy (newval); + + /* Begin code which must not call error(). If var->value points to + something free'd, an error() obviously leaves a dangling pointer. + But we also get a danling pointer if var->value points to + something in the value chain (i.e., before release_value is + called), because after the error free_all_values will get called before + long. */ + free ((PTR)var->value); + var->value = newval; + release_value (newval); + /* End code which must not call error(). */ } char * @@ -467,14 +506,16 @@ clear_internalvars () { var = internalvars; internalvars = var->next; - free (var->name); - free (var->value); - free (var); + free ((PTR)var->name); + free ((PTR)var->value); + free ((PTR)var); } } static void -show_convenience () +show_convenience (ignore, from_tty) + char *ignore; + int from_tty; { register struct internalvar *var; int varseen = 0; @@ -487,18 +528,14 @@ show_convenience () #endif if (!varseen) { -#if 0 - /* Useless noise. */ - printf ("Debugger convenience variables:\n\n"); -#endif varseen = 1; } printf_filtered ("$%s = ", var->name); - value_print (var->value, stdout, 0, Val_pretty_default); + value_print (var->value, gdb_stdout, 0, Val_pretty_default); printf_filtered ("\n"); } if (!varseen) - printf ("No debugger convenience variables now defined.\n\ + printf_unfiltered ("No debugger convenience variables now defined.\n\ Convenience variables have names starting with \"$\";\n\ use \"set\" as in \"set $foo = 5\" to define them.\n"); } @@ -510,21 +547,20 @@ use \"set\" as in \"set $foo = 5\" to define them.\n"); LONGEST value_as_long (val) - register value val; + register value_ptr val; { /* This coerces arrays and functions, which is necessary (e.g. in disassemble_command). It also dereferences references, which I suspect is the most logical thing to do. */ - if (TYPE_CODE (VALUE_TYPE (val)) != TYPE_CODE_ENUM) - COERCE_ARRAY (val); + COERCE_ARRAY (val); return unpack_long (VALUE_TYPE (val), VALUE_CONTENTS (val)); } -double +DOUBLEST value_as_double (val) - register value val; + register value_ptr val; { - double foo; + DOUBLEST foo; int inv; foo = unpack_double (VALUE_TYPE (val), VALUE_CONTENTS (val), &inv); @@ -536,11 +572,18 @@ value_as_double (val) Does not deallocate the value. */ CORE_ADDR value_as_pointer (val) - value val; + value_ptr val; { /* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure whether we want this to be true eventually. */ +#if 0 + /* ADDR_BITS_REMOVE is wrong if we are being called for a + non-address (e.g. argument to "signal", "info break", etc.), or + for pointers to char, in which the low bits *are* significant. */ + return ADDR_BITS_REMOVE(value_as_long (val)); +#else return value_as_long (val); +#endif } /* Unpack raw data (copied from debugee, target byte order) at VALADDR @@ -557,9 +600,6 @@ value_as_pointer (val) to member which reaches here is considered to be equivalent to an INT (or some size). After all, it is only an offset. */ -/* FIXME: This should be rewritten as a switch statement for speed and - ease of comprehension. */ - LONGEST unpack_long (type, valaddr) struct type *type; @@ -569,144 +609,40 @@ unpack_long (type, valaddr) register int len = TYPE_LENGTH (type); register int nosign = TYPE_UNSIGNED (type); - if (code == TYPE_CODE_ENUM || code == TYPE_CODE_BOOL) - code = TYPE_CODE_INT; - if (code == TYPE_CODE_FLT) - { - if (len == sizeof (float)) - { - float retval; - bcopy (valaddr, &retval, sizeof (retval)); - SWAP_TARGET_AND_HOST (&retval, sizeof (retval)); - return retval; - } + if (current_language->la_language == language_scm + && is_scmvalue_type (type)) + return scm_unpack (type, valaddr, TYPE_CODE_INT); - if (len == sizeof (double)) - { - double retval; - bcopy (valaddr, &retval, sizeof (retval)); - SWAP_TARGET_AND_HOST (&retval, sizeof (retval)); - return retval; - } - else - { - error ("Unexpected type of floating point number."); - } - } - else if (code == TYPE_CODE_INT && nosign) + switch (code) { - if (len == sizeof (char)) - { - unsigned char retval = * (unsigned char *) valaddr; - /* SWAP_TARGET_AND_HOST (&retval, sizeof (unsigned char)); */ - return retval; - } - - if (len == sizeof (short)) - { - unsigned short retval; - bcopy (valaddr, &retval, sizeof (retval)); - SWAP_TARGET_AND_HOST (&retval, sizeof (retval)); - return retval; - } - - if (len == sizeof (int)) - { - unsigned int retval; - bcopy (valaddr, &retval, sizeof (retval)); - SWAP_TARGET_AND_HOST (&retval, sizeof (retval)); - return retval; - } - - if (len == sizeof (long)) - { - unsigned long retval; - bcopy (valaddr, &retval, sizeof (retval)); - SWAP_TARGET_AND_HOST (&retval, sizeof (retval)); - return retval; - } -#ifdef LONG_LONG - if (len == sizeof (long long)) - { - unsigned long long retval; - bcopy (valaddr, &retval, sizeof (retval)); - SWAP_TARGET_AND_HOST (&retval, sizeof (retval)); - return retval; - } -#endif + case TYPE_CODE_TYPEDEF: + return unpack_long (check_typedef (type), valaddr); + case TYPE_CODE_ENUM: + case TYPE_CODE_BOOL: + case TYPE_CODE_INT: + case TYPE_CODE_CHAR: + case TYPE_CODE_RANGE: + if (nosign) + return extract_unsigned_integer (valaddr, len); else - { - error ("That operation is not possible on an integer of that size."); - } - } - else if (code == TYPE_CODE_INT) - { - if (len == sizeof (char)) - { - char retval; - bcopy (valaddr, &retval, sizeof (retval)); - SWAP_TARGET_AND_HOST (&retval, sizeof (retval)); - return retval; - } + return extract_signed_integer (valaddr, len); - if (len == sizeof (short)) - { - short retval; - bcopy (valaddr, &retval, sizeof (retval)); - SWAP_TARGET_AND_HOST (&retval, sizeof (retval)); - return retval; - } + case TYPE_CODE_FLT: + return extract_floating (valaddr, len); - if (len == sizeof (int)) - { - int retval; - bcopy (valaddr, &retval, sizeof (retval)); - SWAP_TARGET_AND_HOST (&retval, sizeof (retval)); - return retval; - } + case TYPE_CODE_PTR: + case TYPE_CODE_REF: + /* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure + whether we want this to be true eventually. */ + return extract_address (valaddr, len); - if (len == sizeof (long)) - { - long retval; - bcopy (valaddr, &retval, sizeof (retval)); - SWAP_TARGET_AND_HOST (&retval, sizeof (retval)); - return retval; - } + case TYPE_CODE_MEMBER: + error ("not implemented: member types in unpack_long"); -#ifdef LONG_LONG - if (len == sizeof (long long)) - { - long long retval; - bcopy (valaddr, &retval, sizeof (retval)); - SWAP_TARGET_AND_HOST (&retval, sizeof (retval)); - return retval; - } -#endif - else - { - error ("That operation is not possible on an integer of that size."); - } - } - /* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure - whether we want this to be true eventually. */ - else if (code == TYPE_CODE_PTR - || code == TYPE_CODE_REF) - { - if (len == sizeof (CORE_ADDR)) - { - CORE_ADDR retval; - bcopy (valaddr, &retval, sizeof (retval)); - SWAP_TARGET_AND_HOST (&retval, sizeof (retval)); - return retval; - } + default: + error ("Value can't be converted to integer."); } - else if (code == TYPE_CODE_MEMBER) - error ("not implemented: member types in unpack_long"); - else if (code == TYPE_CODE_CHAR) - return *(unsigned char *)valaddr; - - error ("Value not integer or pointer."); - return 0; /* For lint -- never reached */ + return 0; /* Placate lint. */ } /* Return a double value from the specified type and address. @@ -715,7 +651,7 @@ unpack_long (type, valaddr) the returned double is OK to use. Argument is in target format, result is in host format. */ -double +DOUBLEST unpack_double (type, valaddr, invp) struct type *type; char *valaddr; @@ -726,46 +662,33 @@ unpack_double (type, valaddr, invp) register int nosign = TYPE_UNSIGNED (type); *invp = 0; /* Assume valid. */ + CHECK_TYPEDEF (type); if (code == TYPE_CODE_FLT) { +#ifdef INVALID_FLOAT if (INVALID_FLOAT (valaddr, len)) { *invp = 1; return 1.234567891011121314; } - - if (len == sizeof (float)) - { - float retval; - bcopy (valaddr, &retval, sizeof (retval)); - SWAP_TARGET_AND_HOST (&retval, sizeof (retval)); - return retval; - } - - if (len == sizeof (double)) - { - double retval; - bcopy (valaddr, &retval, sizeof (retval)); - SWAP_TARGET_AND_HOST (&retval, sizeof (retval)); - return retval; - } - else - { - error ("Unexpected type of floating point number."); - return 0; /* Placate lint. */ - } +#endif + return extract_floating (valaddr, len); } - else if (nosign) { - /* Unsigned -- be sure we compensate for signed LONGEST. */ -#ifdef LONG_LONG - return (unsigned long long) unpack_long (type, valaddr); + else if (nosign) + { + /* Unsigned -- be sure we compensate for signed LONGEST. */ +#if !defined (_MSC_VER) || (_MSC_VER > 900) + return (ULONGEST) unpack_long (type, valaddr); #else - return (unsigned long ) unpack_long (type, valaddr); -#endif - } else { - /* Signed -- we are OK with unpack_long. */ - return unpack_long (type, valaddr); - } + /* FIXME!!! msvc22 doesn't support unsigned __int64 -> double */ + return (LONGEST) unpack_long (type, valaddr); +#endif /* _MSC_VER */ + } + else + { + /* Signed -- we are OK with unpack_long. */ + return unpack_long (type, valaddr); + } } /* Unpack raw data (copied from debugee, target byte order) at VALADDR @@ -786,65 +709,65 @@ unpack_pointer (type, valaddr) struct type *type; char *valaddr; { -#if 0 - /* The user should be able to use an int (e.g. 0x7892) in contexts - where a pointer is expected. So this doesn't do enough. */ - register enum type_code code = TYPE_CODE (type); - register int len = TYPE_LENGTH (type); - - if (code == TYPE_CODE_PTR - || code == TYPE_CODE_REF) - { - if (len == sizeof (CORE_ADDR)) - { - CORE_ADDR retval; - bcopy (valaddr, &retval, sizeof (retval)); - SWAP_TARGET_AND_HOST (&retval, sizeof (retval)); - return retval; - } - error ("Unrecognized pointer size."); - } - else if (code == TYPE_CODE_MEMBER) - error ("not implemented: member types in unpack_pointer"); - - error ("Value is not a pointer."); - return 0; /* For lint -- never reached */ -#else /* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure whether we want this to be true eventually. */ return unpack_long (type, valaddr); -#endif } +/* Get the value of the FIELDN'th field (which must be static) of TYPE. */ + +value_ptr +value_static_field (type, fieldno) + struct type *type; + int fieldno; +{ + CORE_ADDR addr; + asection *sect; + if (TYPE_FIELD_STATIC_HAS_ADDR (type, fieldno)) + { + addr = TYPE_FIELD_STATIC_PHYSADDR (type, fieldno); + sect = NULL; + } + else + { + char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, fieldno); + struct symbol *sym = lookup_symbol (phys_name, 0, VAR_NAMESPACE, 0, NULL); + if (sym == NULL) + return NULL; + addr = SYMBOL_VALUE_ADDRESS (sym); + sect = SYMBOL_BFD_SECTION (sym); + SET_FIELD_PHYSADDR (TYPE_FIELD (type, fieldno), addr); + } + return value_at (TYPE_FIELD_TYPE (type, fieldno), addr, sect); +} + /* Given a value ARG1 (offset by OFFSET bytes) of a struct or union type ARG_TYPE, - extract and return the value of one of its fields. - FIELDNO says which field. + extract and return the value of one of its (non-static) fields. + FIELDNO says which field. */ - For C++, must also be able to return values from static fields */ - -value +value_ptr value_primitive_field (arg1, offset, fieldno, arg_type) - register value arg1; + register value_ptr arg1; int offset; register int fieldno; register struct type *arg_type; { - register value v; + register value_ptr v; register struct type *type; - check_stub_type (arg_type); + CHECK_TYPEDEF (arg_type); type = TYPE_FIELD_TYPE (arg_type, fieldno); /* Handle packed fields */ - offset += TYPE_FIELD_BITPOS (arg_type, fieldno) / 8; if (TYPE_FIELD_BITSIZE (arg_type, fieldno)) { v = value_from_longest (type, - unpack_field_as_long (arg_type, - VALUE_CONTENTS (arg1), - fieldno)); + unpack_field_as_long (arg_type, + VALUE_CONTENTS (arg1) + + offset, + fieldno)); VALUE_BITPOS (v) = TYPE_FIELD_BITPOS (arg_type, fieldno) % 8; VALUE_BITSIZE (v) = TYPE_FIELD_BITSIZE (arg_type, fieldno); } @@ -854,76 +777,101 @@ value_primitive_field (arg1, offset, fieldno, arg_type) if (VALUE_LAZY (arg1)) VALUE_LAZY (v) = 1; else - bcopy (VALUE_CONTENTS_RAW (arg1) + offset, - VALUE_CONTENTS_RAW (v), - TYPE_LENGTH (type)); + memcpy (VALUE_CONTENTS_RAW (v), + VALUE_CONTENTS_RAW (arg1) + offset + + TYPE_FIELD_BITPOS (arg_type, fieldno) / 8, + TYPE_LENGTH (type)); } VALUE_LVAL (v) = VALUE_LVAL (arg1); if (VALUE_LVAL (arg1) == lval_internalvar) VALUE_LVAL (v) = lval_internalvar_component; VALUE_ADDRESS (v) = VALUE_ADDRESS (arg1); - VALUE_OFFSET (v) = offset + VALUE_OFFSET (arg1); + VALUE_OFFSET (v) = VALUE_OFFSET (arg1) + offset + + TYPE_FIELD_BITPOS (arg_type, fieldno) / 8; return v; } /* Given a value ARG1 of a struct or union type, - extract and return the value of one of its fields. - FIELDNO says which field. - - For C++, must also be able to return values from static fields */ + extract and return the value of one of its (non-static) fields. + FIELDNO says which field. */ -value +value_ptr value_field (arg1, fieldno) - register value arg1; + register value_ptr arg1; register int fieldno; { return value_primitive_field (arg1, 0, fieldno, VALUE_TYPE (arg1)); } -value -value_fn_field (arg1, fieldno, subfieldno) - register value arg1; - register int fieldno; - int subfieldno; +/* Return a non-virtual function as a value. + F is the list of member functions which contains the desired method. + J is an index into F which provides the desired method. */ + +value_ptr +value_fn_field (arg1p, f, j, type, offset) + value_ptr *arg1p; + struct fn_field *f; + int j; + struct type *type; + int offset; { - register value v; - struct fn_field *f = TYPE_FN_FIELDLIST1 (VALUE_TYPE (arg1), fieldno); - register struct type *type = TYPE_FN_FIELD_TYPE (f, subfieldno); + register value_ptr v; + register struct type *ftype = TYPE_FN_FIELD_TYPE (f, j); struct symbol *sym; - sym = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, subfieldno), + sym = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j), 0, VAR_NAMESPACE, 0, NULL); - if (! sym) error ("Internal error: could not find physical method named %s", - TYPE_FN_FIELD_PHYSNAME (f, subfieldno)); + if (! sym) + return NULL; +/* + error ("Internal error: could not find physical method named %s", + TYPE_FN_FIELD_PHYSNAME (f, j)); +*/ - v = allocate_value (type); + v = allocate_value (ftype); VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)); - VALUE_TYPE (v) = type; + VALUE_TYPE (v) = ftype; + + if (arg1p) + { + if (type != VALUE_TYPE (*arg1p)) + *arg1p = value_ind (value_cast (lookup_pointer_type (type), + value_addr (*arg1p))); + + /* Move the `this' pointer according to the offset. + VALUE_OFFSET (*arg1p) += offset; + */ + } + return v; } /* Return a virtual function as a value. ARG1 is the object which provides the virtual function - table pointer. ARG1 is side-effected in calling this 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 -value_virtual_fn_field (arg1, f, j, type) - value arg1; +value_ptr +value_virtual_fn_field (arg1p, f, j, type, offset) + 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)); + 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 entry, vfn, vtbl; - value vi = value_from_longest (builtin_type_int, - (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j)); + 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) @@ -934,10 +882,13 @@ value_virtual_fn_field (arg1, f, j, type) 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) != VALUE_TYPE (arg1)) - arg1 = value_ind (value_cast (context, value_addr (arg1))); + if (TYPE_TARGET_TYPE (context) != type1) + { + arg1 = value_ind (value_cast (context, value_addr (arg1))); + type1 = check_typedef (VALUE_TYPE (arg1)); + } - context = VALUE_TYPE (arg1); + context = type1; /* Now context is the basetype containing the vtbl. */ /* This type may have been defined before its virtual function table @@ -948,26 +899,38 @@ value_virtual_fn_field (arg1, f, j, type) /* The virtual function table is now an array of structures which have the form { int16 offset, delta; void *pfn; }. */ - vtbl = value_ind (value_field (arg1, TYPE_VPTR_FIELDNO (context))); + vtbl = value_ind (value_primitive_field (arg1, 0, + TYPE_VPTR_FIELDNO (context), + TYPE_VPTR_BASETYPE (context))); /* 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); + entry_type = check_typedef (VALUE_TYPE (entry)); - /* Move the `this' pointer according to the virtual function table. */ - VALUE_OFFSET (arg1) += value_as_long (value_field (entry, 0)); - if (! VALUE_LAZY (arg1)) + if (TYPE_CODE (entry_type) == TYPE_CODE_STRUCT) { - VALUE_LAZY (arg1) = 1; - value_fetch_lazy (arg1); - } + /* 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); + 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; } @@ -980,42 +943,42 @@ value_virtual_fn_field (arg1, f, j, type) FIXME-tiemann: should work with dossier entries as well. */ -static value -value_headof (arg, btype, dtype) - value arg; +static value_ptr +value_headof (in_arg, btype, dtype) + value_ptr in_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; - /* FIXME: entry_type is never used. */ - struct type *entry_type; + value_ptr arg, vtbl, entry, best_entry = 0; int i, nelems; int offset, best_offset = 0; struct symbol *sym; CORE_ADDR pc_for_sym; char *demangled_name; + struct minimal_symbol *msymbol; btype = TYPE_VPTR_BASETYPE (dtype); - check_stub_type (btype); + CHECK_TYPEDEF (btype); + arg = in_arg; if (btype != dtype) - vtbl = value_cast (lookup_pointer_type (btype), arg); - else - vtbl = arg; - vtbl = value_ind (value_field (value_ind (vtbl), TYPE_VPTR_FIELDNO (btype))); + arg = value_cast (lookup_pointer_type (btype), arg); + vtbl = value_ind (value_field (value_ind (arg), TYPE_VPTR_FIELDNO (btype))); /* 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)) + msymbol = lookup_minimal_symbol_by_pc (VALUE_ADDRESS (vtbl)); + if (msymbol == NULL + || (demangled_name = SYMBOL_NAME (msymbol)) == NULL + || !VTBL_PREFIX_P (demangled_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)); + memcpy (error_type, VALUE_TYPE (in_arg), sizeof (struct type)); TYPE_NAME (error_type) = savestring ("suspicious *", sizeof ("suspicious *")); - VALUE_TYPE (arg) = error_type; - return arg; + VALUE_TYPE (in_arg) = error_type; + return in_arg; } /* Now search through the virtual function table. */ @@ -1025,28 +988,45 @@ value_headof (arg, btype, dtype) { entry = value_subscript (vtbl, value_from_longest (builtin_type_int, (LONGEST) i)); + /* This won't work if we're using thunks. */ + if (TYPE_CODE (check_typedef (VALUE_TYPE (entry))) != TYPE_CODE_STRUCT) + break; offset = longest_to_int (value_as_long (value_field (entry, 0))); - if (offset < best_offset) + /* 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; } } - 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_pointer (value_field (best_entry, 2)); - sym = find_pc_function (pc_for_sym); - demangled_name = cplus_demangle (SYMBOL_NAME (sym), -1); - *(strchr (demangled_name, ':')) = '\0'; + 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)); - free (demangled_name); - arg = value_add (value_cast (builtin_type_int, arg), - value_field (best_entry, 0)); + if (sym == NULL) + error ("could not find type declaration for `%s'", demangled_name); + if (best_entry) + { + free (demangled_name); + arg = value_add (value_cast (builtin_type_int, arg), + value_field (best_entry, 0)); + } + else arg = in_arg; VALUE_TYPE (arg) = lookup_pointer_type (SYMBOL_TYPE (sym)); return arg; } @@ -1056,310 +1036,173 @@ value_headof (arg, btype, dtype) of its baseclasses) to figure out the most derived type that ARG could actually be a pointer to. */ -value +value_ptr value_from_vtable_info (arg, type) - value arg; + value_ptr 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)) + if (TYPE_VPTR_FIELDNO (type) < 0) 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. - - 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; - char *fieldname; - register int fieldno; -{ - register value v; - struct symbol *sym; - char *phys_name; - - if (fieldno < 0) - { - /* Look for static field. */ - 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)) - { - fieldno = i; - goto found; - } - 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; - } +/* Return true if the INDEXth field of TYPE is a virtual baseclass + pointer which is for the base class whose type is BASECLASS. */ - if (destructor_name_p (fieldname, type)) - error ("Cannot get value of destructor"); +static int +vb_match (type, index, basetype) + struct type *type; + int index; + struct type *basetype; +{ + struct type *fieldtype; + char *name = TYPE_FIELD_NAME (type, index); + char *field_class_name = NULL; - for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; i--) - { - 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); - } + if (*name != '_') + return 0; + /* gcc 2.4 uses _vb$. */ + if (name[1] == 'v' && name[2] == 'b' && is_cplus_marker (name[3])) + field_class_name = name + 4; + /* gcc 2.5 will use __vb_. */ + if (name[1] == '_' && name[2] == 'v' && name[3] == 'b' && name[4] == '_') + field_class_name = name + 5; + + if (field_class_name == NULL) + /* This field is not a virtual base class pointer. */ + return 0; - found: - phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, fieldno); - sym = lookup_symbol (phys_name, 0, VAR_NAMESPACE, 0, NULL); - if (! sym) error ("Internal error: could not find physical static variable named %s", phys_name); + /* It's a virtual baseclass pointer, now we just need to find out whether + it is for this baseclass. */ + fieldtype = TYPE_FIELD_TYPE (type, index); + if (fieldtype == NULL + || TYPE_CODE (fieldtype) != TYPE_CODE_PTR) + /* "Can't happen". */ + return 0; - type = TYPE_FIELD_TYPE (type, fieldno); - v = value_at (type, (CORE_ADDR)SYMBOL_BLOCK_VALUE (sym)); - return v; + /* What we check for is that either the types are equal (needed for + nameless types) or have the same name. This is ugly, and a more + elegant solution should be devised (which would probably just push + the ugliness into symbol reading unless we change the stabs format). */ + if (TYPE_TARGET_TYPE (fieldtype) == basetype) + return 1; + + if (TYPE_NAME (basetype) != NULL + && TYPE_NAME (TYPE_TARGET_TYPE (fieldtype)) != NULL + && STREQ (TYPE_NAME (basetype), + TYPE_NAME (TYPE_TARGET_TYPE (fieldtype)))) + return 1; + return 0; } -/* Compute the address of the baseclass which is - the INDEXth baseclass of TYPE. The TYPE base - of the object is at VALADDR. +/* Compute the offset of the baseclass which is + the INDEXth baseclass of class TYPE, + for value at VALADDR (in host) at ADDRESS (in target). + The result is the offset of the baseclass value relative + to (the address of)(ARG) + OFFSET. - 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. */ + -1 is returned on error. */ -char * -baseclass_addr (type, index, valaddr, valuep, errp) +int +baseclass_offset (type, index, valaddr, address) struct type *type; int index; char *valaddr; - value *valuep; - int *errp; + CORE_ADDR address; { 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); - if (TYPE_MAIN_VARIANT (basetype)) - basetype = TYPE_MAIN_VARIANT (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))) + if (vb_match (type, i, basetype)) { - value val = allocate_value (basetype); - CORE_ADDR addr; - int status; - - addr + CORE_ADDR 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); - } + return addr - (LONGEST) address; } } /* 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; + int boffset = + baseclass_offset (type, i, valaddr, address); + if (boffset) + return boffset; } /* Not found. */ - if (valuep) - *valuep = 0; - return 0; + return -1; } /* Baseclass is easily computed. */ - if (valuep) - *valuep = 0; - return valaddr + TYPE_BASECLASS_BITPOS (type, index) / 8; + return TYPE_BASECLASS_BITPOS (type, index) / 8; } + +/* Unpack a field FIELDNO of the specified TYPE, from the anonymous object at + VALADDR. -/* Ugly hack to convert method stubs into method types. - - He ain't kiddin'. This demangles the name of the method into a string - including argument types, parses out each argument type, generates - a string casting a zero to that type, evaluates the string, and stuffs - the resulting type into an argtype vector!!! Then it knows the type - of the whole function (including argument types for overloading), - which info used to be in the stab's but was removed to hack back - the space required for them. */ -void -check_stub_method (type, i, j) - struct type *type; - int 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); - 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; - - if (OPNAME_PREFIX_P (field_name)) - { - char *opname = cplus_mangle_opname (field_name + 3); - if (opname == NULL) - error ("No mangling for \"%s\"", field_name); - 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); - - /* Now, read in the parameters that define this type. */ - argtypetext = strchr (demangled_name, '(') + 1; - p = argtypetext; - while (*p) - { - if (*p == '(') - depth += 1; - else if (*p == ')') - depth -= 1; - else if (*p == ',' && depth == 0) - argcount += 1; - - p += 1; - } - /* We need one more slot for the void [...] or NULL [end of arglist] */ - argtypes = (struct type **)xmalloc ((argcount+1) * sizeof (struct type *)); - p = argtypetext; - argtypes[0] = lookup_pointer_type (type); - argcount = 1; - - if (*p != ')') /* () means no args, skip while */ - { - while (*p) - { - if (*p == '(') - depth += 1; - else if (*p == ')') - depth -= 1; - - if (depth <= 0 && (*p == ',' || *p == ')')) - { - char *tmp = (char *)alloca (p - argtypetext + 4); - value val; - tmp[0] = '('; - bcopy (argtypetext, tmp+1, p - argtypetext); - tmp[p-argtypetext+1] = ')'; - tmp[p-argtypetext+2] = '0'; - tmp[p-argtypetext+3] = '\0'; - val = parse_and_eval (tmp); - argtypes[argcount] = VALUE_TYPE (val); - argcount += 1; - argtypetext = p + 1; - } - p += 1; - } - } - - if (p[-2] != '.') /* ... */ - argtypes[argcount] = builtin_type_void; /* Ellist terminator */ - else - argtypes[argcount] = NULL; /* List terminator */ + 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. - free (demangled_name); + If the field is signed, we also do sign extension. */ - 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_FN_FIELD_TYPE (f, j) = type; -} - -long +LONGEST unpack_field_as_long (type, valaddr, fieldno) struct type *type; char *valaddr; int fieldno; { - long val; + ULONGEST val; + ULONGEST valmask; int bitpos = TYPE_FIELD_BITPOS (type, fieldno); int bitsize = TYPE_FIELD_BITSIZE (type, fieldno); + int lsbcount; - bcopy (valaddr + bitpos / 8, &val, sizeof val); - SWAP_TARGET_AND_HOST (&val, sizeof val); + val = extract_unsigned_integer (valaddr + bitpos / 8, sizeof (val)); - /* Extracting bits depends on endianness of the machine. */ -#if BITS_BIG_ENDIAN - val = val >> (sizeof val * 8 - bitpos % 8 - bitsize); -#else - val = val >> (bitpos % 8); -#endif + /* Extract bits. See comment above. */ - if (bitsize < 8 * sizeof (val)) - val &= (((unsigned long)1) << bitsize) - 1; - return val; + if (BITS_BIG_ENDIAN) + lsbcount = (sizeof val * 8 - bitpos % 8 - bitsize); + else + lsbcount = (bitpos % 8); + 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 * (int) sizeof (val))) + { + valmask = (((ULONGEST) 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 @@ -1370,102 +1213,102 @@ unpack_field_as_long (type, valaddr, fieldno) void modify_field (addr, fieldval, bitpos, bitsize) char *addr; - int fieldval; + LONGEST fieldval; int bitpos, bitsize; { - long oword; + LONGEST oword; - /* Reject values too big to fit in the field in question, - otherwise adjoining fields may be corrupted. */ - if (bitsize < (8 * sizeof (fieldval)) + /* If a negative fieldval fits in the field in question, chop + off the sign extension bits. */ + if (bitsize < (8 * (int) sizeof (fieldval)) + && (~fieldval & ~((1 << (bitsize - 1)) - 1)) == 0) + fieldval = fieldval & ((1 << bitsize) - 1); + + /* Warn if value is too big to fit in the field in question. */ + if (bitsize < (8 * (int) sizeof (fieldval)) && 0 != (fieldval & ~((1<= longword size */ - if (bitsize < 8 * sizeof (oword)) - oword &= ~(((((unsigned long)1) << bitsize) - 1) << bitpos); + /* Mask out old value, while avoiding shifts >= size of oword */ + if (bitsize < 8 * (int) sizeof (oword)) + oword &= ~(((((ULONGEST)1) << bitsize) - 1) << bitpos); else - oword &= ~((-1) << bitpos); + oword &= ~((~(ULONGEST)0) << bitpos); oword |= fieldval << bitpos; - SWAP_TARGET_AND_HOST (&oword, sizeof oword); /* To target format */ - bcopy (&oword, addr, sizeof oword); + store_signed_integer (addr, sizeof oword, oword); } /* Convert C numbers into newly allocated values */ -value +value_ptr value_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) + register value_ptr val = allocate_value (type); + register enum type_code code; + register int len; + retry: + code = TYPE_CODE (type); + len = TYPE_LENGTH (type); + + switch (code) { - 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."); + case TYPE_CODE_TYPEDEF: + type = check_typedef (type); + goto retry; + case TYPE_CODE_INT: + case TYPE_CODE_CHAR: + case TYPE_CODE_ENUM: + case TYPE_CODE_BOOL: + case TYPE_CODE_RANGE: + store_signed_integer (VALUE_CONTENTS_RAW (val), len, num); + break; + + case TYPE_CODE_REF: + case TYPE_CODE_PTR: + /* This assumes that all pointers of a given length + have the same form. */ + store_address (VALUE_CONTENTS_RAW (val), len, (CORE_ADDR) num); + break; + + default: + error ("Unexpected type encountered for integer constant."); } - 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; } -value +value_ptr value_from_double (type, num) struct type *type; - double num; + DOUBLEST num; { - register value val = allocate_value (type); - register enum type_code code = TYPE_CODE (type); - register int len = TYPE_LENGTH (type); + register value_ptr val = allocate_value (type); + struct type *base_type = check_typedef (type); + register enum type_code code = TYPE_CODE (base_type); + register int len = TYPE_LENGTH (base_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."); + store_floating (VALUE_CONTENTS_RAW (val), len, num); } 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; } @@ -1483,14 +1326,14 @@ value_from_double (type, num) 0 when it is using the value returning conventions (this often means returning pointer to where structure is vs. returning value). */ -value +value_ptr value_being_returned (valtype, retbuf, struct_return) register struct type *valtype; char retbuf[REGISTER_BYTES]; int struct_return; /*ARGSUSED*/ { - register value val; + register value_ptr val; CORE_ADDR addr; #if defined (EXTRACT_STRUCT_VALUE_ADDRESS) @@ -1499,11 +1342,12 @@ value_being_returned (valtype, retbuf, struct_return) addr = EXTRACT_STRUCT_VALUE_ADDRESS (retbuf); if (!addr) error ("Function return value unknown"); - return value_at (valtype, addr); + return value_at (valtype, addr, NULL); } #endif val = allocate_value (valtype); + CHECK_TYPEDEF (valtype); EXTRACT_RETURN_VALUE (valtype, retbuf, VALUE_CONTENTS_RAW (val)); return val; @@ -1515,16 +1359,32 @@ value_being_returned (valtype, retbuf, struct_return) On most machines, the struct convention is used unless we are using gcc and the type is of a special size. */ +/* As of about 31 Mar 93, GCC was changed to be compatible with the + native compiler. GCC 2.3.3 was the last release that did it the + old way. Since gcc2_compiled was not changed, we have no + way to correctly win in all cases, so we just do the right thing + for gcc1 and for gcc2 after this change. Thus it loses for gcc + 2.0-2.3.3. This is somewhat unfortunate, but changing gcc2_compiled + would cause more chaos than dealing with some struct returns being + handled wrong. */ #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 \ - ) \ + (!((gcc_p == 1) && (TYPE_LENGTH (value_type) == 1 \ + || TYPE_LENGTH (value_type) == 2 \ + || TYPE_LENGTH (value_type) == 4 \ + || TYPE_LENGTH (value_type) == 8 \ + ) \ )) #endif +/* Some fundamental types (such as long double) are returned on the stack for + certain architectures. This macro should return true for any type besides + struct, union or array that gets returned on the stack. */ + +#ifndef RETURN_VALUE_ON_STACK +#define RETURN_VALUE_ON_STACK(TYPE) 0 +#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 @@ -1534,7 +1394,7 @@ value_being_returned (valtype, retbuf, struct_return) int using_struct_return (function, funcaddr, value_type, gcc_p) - value function; + value_ptr function; CORE_ADDR funcaddr; struct type *value_type; int gcc_p; @@ -1545,9 +1405,10 @@ using_struct_return (function, funcaddr, value_type, gcc_p) if (code == TYPE_CODE_ERROR) error ("Function return type unknown."); - if (code == TYPE_CODE_STRUCT || - code == TYPE_CODE_UNION || - code == TYPE_CODE_ARRAY) + if (code == TYPE_CODE_STRUCT + || code == TYPE_CODE_UNION + || code == TYPE_CODE_ARRAY + || RETURN_VALUE_ON_STACK (value_type)) return USE_STRUCT_CONVENTION (gcc_p, value_type); return 0; @@ -1559,32 +1420,19 @@ using_struct_return (function, funcaddr, value_type, gcc_p) void set_return_value (val) - value val; + value_ptr val; { - register enum type_code code = TYPE_CODE (VALUE_TYPE (val)); - double dbuf; - LONGEST lbuf; + struct type *type = check_typedef (VALUE_TYPE (val)); + register enum type_code code = TYPE_CODE (type); if (code == TYPE_CODE_ERROR) error ("Function return type unknown."); - if (code == TYPE_CODE_STRUCT - || code == TYPE_CODE_UNION) - error ("Specifying a struct or union return value is not supported."); - - /* 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); + 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."); - STORE_RETURN_VALUE (VALUE_TYPE (val), (char *)&dbuf); - } - else - { - lbuf = value_as_long (val); - STORE_RETURN_VALUE (VALUE_TYPE (val), (char *)&lbuf); - } + STORE_RETURN_VALUE (type, VALUE_CONTENTS (val)); } void