diff options
author | Daniel Jacobowitz <drow@false.org> | 2008-03-21 15:02:38 +0000 |
---|---|---|
committer | Daniel Jacobowitz <drow@false.org> | 2008-03-21 15:02:38 +0000 |
commit | 6309237547d076d68daaf8f4d0cd55c5964e1411 (patch) | |
tree | ff4100d106e01c43dd82f47a59d0071d99cae1c6 /gdb/valops.c | |
parent | b21991b00cf16b94e9646a054e786c1fa4d5501a (diff) | |
download | gdb-6309237547d076d68daaf8f4d0cd55c5964e1411.zip gdb-6309237547d076d68daaf8f4d0cd55c5964e1411.tar.gz gdb-6309237547d076d68daaf8f4d0cd55c5964e1411.tar.bz2 |
* eval.c (evaluate_subexp_for_address): Clarify error message.
Use value_must_coerce_to_target.
* infcall.c (value_arg_coerce): Call value_coerce_to_target.
* valops.c (value_assign): Call value_coerce_to_target when
assigning to anything but internalvars. Leave GDB-side arrays
as arrays when assigning to internalvars.
(value_must_coerce_to_target, value_coerce_to_target): New.
(value_coerce_array, value_addr): Call value_coerce_to_target.
(value_array): Create the array in GDB's memory instead of
the inferior's.
* value.h (value_must_coerce_to_target, value_coerce_to_target):
Declare.
* gdb.texinfo (Expressions): Update description of malloced arrays.
* gdb.base/printcmds.exp (test_print_array_constants): Do not expect
*& to work on created array elements.
(Top level): Test print $pc with a file. Test string operations
without a target.
* gdb.base/ptype.exp: Do not expect *& to work on created array
elements.
Diffstat (limited to 'gdb/valops.c')
-rw-r--r-- | gdb/valops.c | 91 |
1 files changed, 72 insertions, 19 deletions
diff --git a/gdb/valops.c b/gdb/valops.c index 69ebb15..80bee1e 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -600,9 +600,18 @@ value_assign (struct value *toval, struct value *fromval) type = value_type (toval); if (VALUE_LVAL (toval) != lval_internalvar) - fromval = value_cast (type, fromval); + { + toval = value_coerce_to_target (toval); + fromval = value_cast (type, fromval); + } else - fromval = coerce_array (fromval); + { + /* Coerce arrays and functions to pointers, except for arrays + which only live in GDB's storage. */ + if (!value_must_coerce_to_target (fromval)) + fromval = coerce_array (fromval); + } + CHECK_TYPEDEF (type); /* Since modifying a register can trash the frame chain, and @@ -852,6 +861,50 @@ value_of_variable (struct symbol *var, struct block *b) return val; } +/* Return one if VAL does not live in target memory, but should in order + to operate on it. Otherwise return zero. */ + +int +value_must_coerce_to_target (struct value *val) +{ + struct type *valtype; + + /* The only lval kinds which do not live in target memory. */ + if (VALUE_LVAL (val) != not_lval + && VALUE_LVAL (val) != lval_internalvar) + return 0; + + valtype = check_typedef (value_type (val)); + + switch (TYPE_CODE (valtype)) + { + case TYPE_CODE_ARRAY: + case TYPE_CODE_STRING: + return 1; + default: + return 0; + } +} + +/* Make sure that VAL lives in target memory if it's supposed to. For instance, + strings are constructed as character arrays in GDB's storage, and this + function copies them to the target. */ + +struct value * +value_coerce_to_target (struct value *val) +{ + LONGEST length; + CORE_ADDR addr; + + if (!value_must_coerce_to_target (val)) + return val; + + length = TYPE_LENGTH (check_typedef (value_type (val))); + addr = allocate_space_in_inferior (length); + write_memory (addr, value_contents (val), length); + return value_at_lazy (value_type (val), addr); +} + /* Given a value which is an array, return a value which is a pointer to its first element, regardless of whether or not the array has a nonzero lower bound. @@ -881,6 +934,11 @@ value_coerce_array (struct value *arg1) { struct type *type = check_typedef (value_type (arg1)); + /* If the user tries to do something requiring a pointer with an + array that has not yet been pushed to the target, then this would + be a good time to do so. */ + arg1 = value_coerce_to_target (arg1); + if (VALUE_LVAL (arg1) != lval_memory) error (_("Attempt to take address of value not located in memory.")); @@ -926,6 +984,10 @@ value_addr (struct value *arg1) if (TYPE_CODE (type) == TYPE_CODE_FUNC) return value_coerce_function (arg1); + /* If this is an array that has not yet been pushed to the target, + then this would be a good time to force it to memory. */ + arg1 = value_coerce_to_target (arg1); + if (VALUE_LVAL (arg1) != lval_memory) error (_("Attempt to take address of value not located in memory.")); @@ -1016,7 +1078,7 @@ value_ind (struct value *arg1) return 0; /* For lint -- never reached. */ } -/* Create a value for an array by allocating space in the inferior, +/* Create a value for an array by allocating space in GDB, copying copying the data into that space, and then setting up an array value. @@ -1074,24 +1136,15 @@ value_array (int lowbound, int highbound, struct value **elemvec) return val; } - /* Allocate space to store the array in the inferior, and then - initialize it by copying in each element. FIXME: Is it worth it - to create a local buffer in which to collect each value and then - write all the bytes in one operation? */ + /* Allocate space to store the array, and then initialize it by + copying in each element. */ - addr = allocate_space_in_inferior (nelem * typelength); + val = allocate_value (arraytype); for (idx = 0; idx < nelem; idx++) - { - write_memory (addr + (idx * typelength), - value_contents_all (elemvec[idx]), - typelength); - } - - /* Create the array type and set up an array value to be evaluated - lazily. */ - - val = value_at_lazy (arraytype, addr); - return (val); + memcpy (value_contents_writeable (val) + (idx * typelength), + value_contents_all (elemvec[idx]), + typelength); + return val; } /* Create a value for a string constant by allocating space in the |