--- gdb/eval.c | 11 ++++- gdb/infcall.c | 9 ++++ gdb/testsuite/gdb.base/printcmds.exp | 8 +++ gdb/valarith.c | 1 gdb/valops.c | 72 ++++++++++++++++++++++++++--------- gdb/value.h | 2 6 files changed, 84 insertions(+), 19 deletions(-) Index: src/gdb/eval.c =================================================================== --- src.orig/gdb/eval.c 2007-06-14 15:13:02.000000000 -0400 +++ src/gdb/eval.c 2007-07-31 16:37:02.000000000 -0400 @@ -1549,7 +1549,16 @@ evaluate_subexp_standard (struct type *e } if (noside == EVAL_AVOID_SIDE_EFFECTS) - return value_zero (TYPE_TARGET_TYPE (type), VALUE_LVAL (arg1)); + { + /* FIXME: This check is duplicated from value_coerce_to_target. */ + if ((TYPE_CODE (type) == TYPE_CODE_ARRAY + || TYPE_CODE (type) == TYPE_CODE_STRING) + && (VALUE_LVAL (arg1) == not_lval + || VALUE_LVAL (arg1) == lval_internalvar)) + return value_zero (TYPE_TARGET_TYPE (type), lval_memory); + else + return value_zero (TYPE_TARGET_TYPE (type), VALUE_LVAL (arg1)); + } else return value_subscript (arg1, arg2); } Index: src/gdb/infcall.c =================================================================== --- src.orig/gdb/infcall.c 2007-07-29 17:38:55.000000000 -0400 +++ src/gdb/infcall.c 2007-07-31 16:37:02.000000000 -0400 @@ -106,6 +106,15 @@ value_arg_coerce (struct value *arg, str struct type *type = param_type ? check_typedef (param_type) : arg_type; + /* Force the value to the target if we will need its address. + + FIXME drow/2006-12-24: This was added at the same time as support + for arrays and strings not already in target memory, to preserve + the existing behavior. We could choose to force them to the + stack, instead of calling malloc, if we didn't need them to be + permanent. */ + arg = value_coerce_to_target (arg); + switch (TYPE_CODE (type)) { case TYPE_CODE_REF: Index: src/gdb/valarith.c =================================================================== --- src.orig/gdb/valarith.c 2007-06-14 15:13:19.000000000 -0400 +++ src/gdb/valarith.c 2007-07-31 16:37:02.000000000 -0400 @@ -192,6 +192,7 @@ value_subscript (struct value *array, st LONGEST lowerbound, upperbound; get_discrete_bounds (range_type, &lowerbound, &upperbound); + array = value_coerce_to_target (array); if (VALUE_LVAL (array) != lval_memory) return value_subscripted_rvalue (array, idx, lowerbound); Index: src/gdb/valops.c =================================================================== --- src.orig/gdb/valops.c 2007-06-14 15:13:19.000000000 -0400 +++ src/gdb/valops.c 2007-07-31 16:37:02.000000000 -0400 @@ -556,9 +556,19 @@ value_assign (struct value *toval, struc 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 an array + which only lives in GDB's storage. */ + if (VALUE_LVAL (fromval) != not_lval + && VALUE_LVAL (fromval) != lval_internalvar) + fromval = coerce_array (fromval); + } + CHECK_TYPEDEF (type); /* Since modifying a register can trash the frame chain, and modifying memory @@ -800,6 +810,35 @@ value_of_variable (struct symbol *var, s return val; } +/* 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) +{ + struct type *valtype; + + if (VALUE_LVAL (val) != not_lval + && VALUE_LVAL (val) != lval_internalvar) + return val; + + valtype = check_typedef (value_type (val)); + /* FIXME: Other types? Structs? */ + if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY + || TYPE_CODE (valtype) == TYPE_CODE_STRING) + { + struct value *newval; + CORE_ADDR addr; + + addr = allocate_space_in_inferior (TYPE_LENGTH (valtype)); + write_memory (addr, value_contents (val), TYPE_LENGTH (valtype)); + return value_at_lazy (value_type (val), addr); + } + + return val; +} + /* 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. @@ -828,6 +867,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 do 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.")); @@ -956,7 +1000,7 @@ value_ind (struct value *arg1) return 0; /* For lint -- never reached */ } -/* Create a value for an array by allocating space in the inferior, copying +/* Create a value for an array by allocating space in GDB, copying the data into that space, and then setting up an array value. The array bounds are set from LOWBOUND and HIGHBOUND, and the array is @@ -1011,23 +1055,15 @@ value_array (int lowbound, int highbound 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 inferior, Index: src/gdb/value.h =================================================================== --- src.orig/gdb/value.h 2007-06-14 15:13:19.000000000 -0400 +++ src/gdb/value.h 2007-07-31 16:37:02.000000000 -0400 @@ -332,6 +332,8 @@ extern struct value *value_add (struct v extern struct value *value_sub (struct value *arg1, struct value *arg2); +extern struct value *value_coerce_to_target (struct value *arg1); + extern struct value *value_coerce_array (struct value *arg1); extern struct value *value_coerce_function (struct value *arg1); Index: src/gdb/testsuite/gdb.base/printcmds.exp =================================================================== --- src.orig/gdb/testsuite/gdb.base/printcmds.exp 2007-02-27 07:49:37.000000000 -0500 +++ src/gdb/testsuite/gdb.base/printcmds.exp 2007-07-31 16:37:02.000000000 -0400 @@ -688,6 +688,14 @@ gdb_test "print \$pc" "No registers\\." # FIXME: should also test "print $pc" when there is an execfile but no # remote debugging target, process or corefile. +# Some simple operations on strings should work even without a target +# (and therefore without calling malloc). +gdb_test "print \"abc\"" " = \"abc\"" +gdb_test "print sizeof (\"abc\")" " = 4" +gdb_test "ptype \"abc\"" " = char \\\[4\\\]" +gdb_test "print \$cvar = \"abc\"" " = \"abc\"" +gdb_test "print sizeof (\$cvar)" " = 4" + gdb_load ${binfile} gdb_test "set print sevenbit-strings" ""