From 6309237547d076d68daaf8f4d0cd55c5964e1411 Mon Sep 17 00:00:00 2001 From: Daniel Jacobowitz Date: Fri, 21 Mar 2008 15:02:38 +0000 Subject: [PATCH] * 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. --- gdb/ChangeLog | 15 +++++ gdb/doc/ChangeLog | 4 ++ gdb/doc/gdb.texinfo | 6 +- gdb/eval.c | 4 +- gdb/infcall.c | 6 ++ gdb/testsuite/ChangeLog | 9 +++ gdb/testsuite/gdb.base/printcmds.exp | 14 ++++- gdb/testsuite/gdb.base/ptype.exp | 2 +- gdb/valops.c | 91 ++++++++++++++++++++++------ gdb/value.h | 4 ++ 10 files changed, 128 insertions(+), 27 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 638b8d97fc0..b56a87e0268 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,18 @@ +2008-03-21 Daniel Jacobowitz + + * 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. + 2008-03-21 Daniel Jacobowitz * top.c (quit_confirm): Warn that we will kill the program. diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index d32caf6636e..4b5ae97c69d 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,7 @@ +2008-03-21 Daniel Jacobowitz + + * gdb.texinfo (Expressions): Update description of malloced arrays. + 2008-03-15 Vladimir Prus * gdb.texinfo (Thread Commands): Document diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 2ed036ca4f3..67c3dee2844 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -5597,8 +5597,10 @@ you compiled your program to include this information; see @cindex arrays in expressions @value{GDBN} supports array constants in expressions input by the user. The syntax is @{@var{element}, @var{element}@dots{}@}. For example, -you can use the command @code{print @{1, 2, 3@}} to build up an array in -memory that is @code{malloc}ed in the target program. +you can use the command @code{print @{1, 2, 3@}} to create an array +of three integers. If you pass an array to a function or assign it +to a program variable, @value{GDBN} copies the array to memory that +is @code{malloc}ed in the target program. Because C is so widespread, most of the expressions shown in examples in this manual are in C. @xref{Languages, , Using @value{GDBN} with Different diff --git a/gdb/eval.c b/gdb/eval.c index efe1dc28d82..79defebe84e 100644 --- a/gdb/eval.c +++ b/gdb/eval.c @@ -2204,14 +2204,14 @@ evaluate_subexp_for_address (struct expression *exp, int *pos, { struct type *type = check_typedef (value_type (x)); - if (VALUE_LVAL (x) == lval_memory) + if (VALUE_LVAL (x) == lval_memory || value_must_coerce_to_target (x)) return value_zero (lookup_pointer_type (value_type (x)), not_lval); else if (TYPE_CODE (type) == TYPE_CODE_REF) return value_zero (lookup_pointer_type (TYPE_TARGET_TYPE (type)), not_lval); else - error (_("Attempt to take address of non-lval")); + error (_("Attempt to take address of value not located in memory.")); } return value_addr (x); } diff --git a/gdb/infcall.c b/gdb/infcall.c index 9242c46fcc1..721b32df28c 100644 --- a/gdb/infcall.c +++ b/gdb/infcall.c @@ -111,6 +111,12 @@ value_arg_coerce (struct value *arg, struct type *param_type, if (current_language->la_language == language_ada) arg = ada_convert_actual (arg, type, sp); + /* Force the value to the target if we will need its address. At + this point, we could allocate arguments on the stack instead of + calling malloc if we knew that their addresses would not be + saved by the called function. */ + arg = value_coerce_to_target (arg); + switch (TYPE_CODE (type)) { case TYPE_CODE_REF: diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 3e5f8676602..0438144fb87 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2008-03-21 Daniel Jacobowitz + + * 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. + 2008-03-21 Daniel Jacobowitz * gdb.threads/killed.exp, gdb.threads/manythreads.exp, diff --git a/gdb/testsuite/gdb.base/printcmds.exp b/gdb/testsuite/gdb.base/printcmds.exp index bad73beec41..0f1786e124f 100644 --- a/gdb/testsuite/gdb.base/printcmds.exp +++ b/gdb/testsuite/gdb.base/printcmds.exp @@ -651,7 +651,7 @@ proc test_print_array_constants {} { gdb_test_escape_braces "print {(long)0,(long)1,(long)2}" " = {0, 1, 2}" gdb_test_escape_braces "print {{0,1,2},{3,4,5}}" " = {{0, 1, 2}, {3, 4, 5}}" gdb_test "print {4,5,6}\[2\]" " = 6" - gdb_test "print *&{4,5,6}\[1\]" " = 5" + gdb_test "print *&{4,5,6}\[1\]" "Attempt to take address of value not located in memory." } proc test_printf {} { @@ -735,11 +735,19 @@ gdb_start gdb_reinitialize_dir $srcdir/$subdir 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 "print \$pc" "No registers\\." "print \$pc (with file)" + gdb_test "set print sevenbit-strings" "" gdb_test "set print address off" "" gdb_test "set width 0" "" diff --git a/gdb/testsuite/gdb.base/ptype.exp b/gdb/testsuite/gdb.base/ptype.exp index 10272c87021..41504902fb7 100644 --- a/gdb/testsuite/gdb.base/ptype.exp +++ b/gdb/testsuite/gdb.base/ptype.exp @@ -638,7 +638,7 @@ if [runto_main] then { gdb_test "ptype {(float)0,(float)1,(float)2}" "type = float \\\[3\\\]" gdb_test "ptype {{0,1,2},{3,4,5}}" "type = int \\\[2\\\]\\\[3\\\]" gdb_test "ptype {4,5,6}\[2\]" "type = int" - gdb_test "ptype *&{4,5,6}\[1\]" "type = int" + gdb_test "ptype *&{4,5,6}\[1\]" "Attempt to take address of value not located in memory." # Test ptype of user register gdb_test "ptype \$pc" "void \\(\\*\\)\\(\\)" "ptype \$pc" diff --git a/gdb/valops.c b/gdb/valops.c index 69ebb15f821..80bee1e8968 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 diff --git a/gdb/value.h b/gdb/value.h index 1289a9726f7..ba226e5a367 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -332,6 +332,10 @@ extern struct value *value_add (struct value *arg1, struct value *arg2); extern struct value *value_sub (struct value *arg1, struct value *arg2); +extern int value_must_coerce_to_target (struct value *arg1); + +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); -- 2.30.2