+2013-10-02 Pedro Alves <palves@redhat.com>
+
+ * cp-valprint.c (cp_print_value_fields): Adjust calls to
+ val_print_optimized_out.
+ * jv-valprint.c (java_print_value_fields): Likewise.
+ * p-valprint.c (pascal_object_print_value_fields): Likewise.
+ * dwarf2loc.c (dwarf2_evaluate_loc_desc_full)
+ <DWARF_VALUE_REGISTER>: If the register was not saved, return a
+ new optimized out value.
+ * findvar.c (address_from_register): Likewise.
+ * frame.c (put_frame_register): Tweak error string to say the
+ register was not saved, rather than optimized out.
+ * infcmd.c (default_print_one_register_info): Adjust call to
+ val_print_optimized_out. Use value_of_register instead of
+ get_frame_register_value.
+ * mi/mi-main.c (output_register): Use value_of_register instead of
+ get_frame_register_value.
+ * valprint.c (valprint_check_validity): Likewise.
+ (val_print_optimized_out): New value parameter. If the value is
+ lval_register, print <not saved> instead.
+ (value_check_printable, val_print_scalar_formatted): Adjust calls
+ to val_print_optimized_out.
+ * valprint.h (val_print_optimized_out): New value parameter.
+ * value.c (struct value) <optimized_out>: Extend comment.
+ (error_value_optimized_out): New function.
+ (require_not_optimized_out): Use it. Use a different string for
+ lval_register values.
+ * value.h (error_value_optimized_out): New declaration.
+ * NEWS: Mention <not saved>.
+
2013-10-02 Joel Brobecker <brobecker@adacore.com>
* symtab.c (compare_search_syms): Use FILENAME_CMP instead of
* The "catch syscall" command now works on arm*-linux* targets.
+* GDB now consistently shows "<not saved>" when printing values of
+ registers the debug info indicates have not been saved in the frame
+ and there's nowhere to retrieve them from
+ (callee-saved/call-clobbered registers):
+
+ (gdb) p $rax
+ $1 = <not saved>
+
+ (gdb) info registers rax
+ rax <not saved>
+
+ Before, the former would print "<optimized out>", and the latter
+ "*value not available*".
+
* Python scripting
** Frame filters and frame decorators have been added.
TYPE_FIELD_BITPOS (type, i),
TYPE_FIELD_BITSIZE (type, i)))
{
- val_print_optimized_out (stream);
+ val_print_optimized_out (val, stream);
}
else
{
_("<error reading variable: %s>"),
ex.message);
else if (v == NULL)
- val_print_optimized_out (stream);
+ val_print_optimized_out (NULL, stream);
else
cp_print_static_field (TYPE_FIELD_TYPE (type, i),
v, stream, recurse + 1,
+2013-10-02 Pedro Alves <palves@redhat.com>
+
+ * gdb.texinfo (Registers): Expand description of saved registers
+ in frames. Explain <not saved>.
+
2013-09-25 Doug Evans <dje@google.com>
* gdb.texinfo (Debugging Output): Document set/show debug symfile.
true contents of hardware registers, you must select the innermost
frame (with @samp{frame 0}).
-However, @value{GDBN} must deduce where registers are saved, from the machine
-code generated by your compiler. If some registers are not saved, or if
-@value{GDBN} is unable to locate the saved registers, the selected stack
-frame makes no difference.
+@cindex caller-saved registers
+@cindex call-clobbered registers
+@cindex volatile registers
+@cindex <not saved> values
+Usually ABIs reserve some registers as not needed to be saved by the
+callee (a.k.a.: ``caller-saved'', ``call-clobbered'' or ``volatile''
+registers). It may therefore not be possible for @value{GDBN} to know
+the value a register had before the call (in other words, in the outer
+frame), if the register value has since been changed by the callee.
+@value{GDBN} tries to deduce where the inner frame saved
+(``callee-saved'') registers, from the debug info, unwind info, or the
+machine code generated by your compiler. If some register is not
+saved, and @value{GDBN} knows the register is ``caller-saved'' (via
+its own knowledge of the ABI, or because the debug/unwind info
+explicitly says the register's value is undefined), @value{GDBN}
+displays @w{@samp{<not saved>}} as the register's value. With targets
+that @value{GDBN} has no knowledge of the register saving convention,
+if a register was not saved by the callee, then its value and location
+in the outer frame are assumed to be the same of the inner frame.
+This is usually harmless, because if the register is call-clobbered,
+the caller either does not care what is in the register after the
+call, or has code to restore the value that it does care about. Note,
+however, that if you change such a register in the outer frame, you
+may also be affecting the inner frame. Also, the more ``outer'' the
+frame is you're looking at, the more likely a call-clobbered
+register's value is to be wrong, in the sense that it doesn't actually
+represent the value the register had just before the call.
@node Floating Point Hardware
@section Floating Point Hardware
if (byte_offset != 0)
error (_("cannot use offset on synthetic pointer to register"));
do_cleanups (value_chain);
- if (gdb_regnum != -1)
- retval = value_from_register (type, gdb_regnum, frame);
- else
+ if (gdb_regnum == -1)
error (_("Unable to access DWARF register number %d"),
dwarf_regnum);
+ retval = value_from_register (type, gdb_regnum, frame);
+ if (value_optimized_out (retval))
+ {
+ /* This means the register has undefined value / was
+ not saved. As we're computing the location of some
+ variable etc. in the program, not a value for
+ inspecting a register ($pc, $sp, etc.), return a
+ generic optimized out value instead, so that we show
+ <optimized out> instead of <not saved>. */
+ do_cleanups (value_chain);
+ retval = allocate_optimized_out_value (type);
+ }
}
break;
value = value_from_register (type, regnum, frame);
gdb_assert (value);
+ if (value_optimized_out (value))
+ {
+ /* This function is used while computing a location expression.
+ Complain about the value being optimized out, rather than
+ letting value_as_address complain about some random register
+ the expression depends on not being saved. */
+ error_value_optimized_out ();
+ }
+
result = value_as_address (value);
release_value (value);
value_free (value);
frame_register (frame, regnum, &optim, &unavail,
&lval, &addr, &realnum, NULL);
if (optim)
- error (_("Attempt to assign to a value that was optimized out."));
+ error (_("Attempt to assign to a register that was not saved."));
switch (lval)
{
case lval_memory:
}
else if (value_optimized_out (val))
{
- val_print_optimized_out (file);
+ val_print_optimized_out (val, file);
fprintf_filtered (file, "\n");
return;
}
default_print_one_register_info (file,
gdbarch_register_name (gdbarch, i),
- get_frame_register_value (frame, i));
+ value_of_register (i, frame));
}
}
else if (!value_bits_valid (val, TYPE_FIELD_BITPOS (type, i),
TYPE_FIELD_BITSIZE (type, i)))
{
- val_print_optimized_out (stream);
+ val_print_optimized_out (val, stream);
}
else
{
struct value *v = value_static_field (type, i);
if (v == NULL)
- val_print_optimized_out (stream);
+ val_print_optimized_out (NULL, stream);
else
{
struct value_print_options opts;
{
struct gdbarch *gdbarch = get_frame_arch (frame);
struct ui_out *uiout = current_uiout;
- struct value *val = get_frame_register_value (frame, regnum);
+ struct value *val = value_of_register (regnum, frame);
struct cleanup *tuple_cleanup;
struct value_print_options opts;
struct ui_file *stb;
else if (!value_bits_valid (val, TYPE_FIELD_BITPOS (type, i),
TYPE_FIELD_BITSIZE (type, i)))
{
- val_print_optimized_out (stream);
+ val_print_optimized_out (val, stream);
}
else
{
v = value_field_bitfield (type, i, valaddr, offset, val);
if (v == NULL)
- val_print_optimized_out (stream);
+ val_print_optimized_out (NULL, stream);
else
pascal_object_print_static_field (v, stream, recurse + 1,
options);
+2013-10-02 Pedro Alves <palves@redhat.com>
+
+ * gdb.dwarf2/dw2-reg-undefined.exp <pattern_rax_rbx_rcx_print,
+ pattern_rax_rbx_rcx_info>: Set to "<not saved>".
+ * gdb.mi/mi-reg-undefined.exp (opt_out_pattern): Delete.
+ (not_saved_pattern): New.
+ Replace use of the former with the latter.
+
2013-10-02 Pedro Alves <palves@redhat.com>
* README (Board Settings): Document "exit_is_reliable".
set pattern_r8_r9_print "$hex"
set pattern_r8_r9_info "$hex\\s+$decimal"
} else {
- set pattern_rax_rbx_rcx_print "<optimized out>"
- set pattern_rax_rbx_rcx_info "<optimized out>"
+ set pattern_rax_rbx_rcx_print "<not saved>"
+ set pattern_rax_rbx_rcx_info "<not saved>"
set pattern_r8_r9_print "$hex"
set pattern_r8_r9_info "$hex\\s+$decimal"
}
"111\\^done,stack=\\\[frame=\{level=\"0\",addr=\"$hex\",func=\"stop_frame\",.*\},frame=\{level=\"1\",addr=\"$hex\",func=\"first_frame\",.*\},frame=\{level=\"2\",addr=\"$hex\",func=\"main\",.*\}\\\]" \
"stack frame listing"
-set opt_out_pattern "<optimized out>"
+set not_saved_pattern "<not saved>"
for {set f 0} {$f < 3} {incr f} {
if {${f} == 0} {
set pattern_0_1_2 ${hex}
} else {
- set pattern_0_1_2 ${opt_out_pattern}
+ set pattern_0_1_2 ${not_saved_pattern}
}
mi_gdb_test "22${f}-data-list-register-values --thread 1 --frame ${f} x 0 1 2 8 9" \
if (!value_bits_valid (val, TARGET_CHAR_BIT * embedded_offset,
TARGET_CHAR_BIT * TYPE_LENGTH (type)))
{
- val_print_optimized_out (stream);
+ val_print_optimized_out (val, stream);
return 0;
}
}
void
-val_print_optimized_out (struct ui_file *stream)
+val_print_optimized_out (const struct value *val, struct ui_file *stream)
{
- fprintf_filtered (stream, _("<optimized out>"));
+ if (val != NULL && value_lval_const (val) == lval_register)
+ fprintf_filtered (stream, _("<not saved>"));
+ else
+ fprintf_filtered (stream, _("<optimized out>"));
}
void
if (options->summary && !val_print_scalar_type_p (value_type (val)))
fprintf_filtered (stream, "...");
else
- val_print_optimized_out (stream);
+ val_print_optimized_out (val, stream);
return 0;
}
printed, because all bits contribute to its representation. */
if (!value_bits_valid (val, TARGET_CHAR_BIT * embedded_offset,
TARGET_CHAR_BIT * TYPE_LENGTH (type)))
- val_print_optimized_out (stream);
+ val_print_optimized_out (val, stream);
else if (!value_bytes_available (val, embedded_offset, TYPE_LENGTH (type)))
val_print_unavailable (stream);
else
enum bfd_endian byte_order, gdb_byte **buffer,
int *bytes_read);
-extern void val_print_optimized_out (struct ui_file *stream);
+extern void val_print_optimized_out (const struct value *val,
+ struct ui_file *stream);
extern void val_print_unavailable (struct ui_file *stream);
reset, be sure to consider this use as well! */
unsigned int lazy : 1;
- /* If nonzero, this is the value of a variable which does not
- actually exist in the program. */
+ /* If nonzero, this is the value of a variable that does not
+ actually exist in the program. If nonzero, and LVAL is
+ lval_register, this is a register ($pc, $sp, etc., never a
+ program variable) that has not been saved in the frame. All
+ optimized-out values are treated pretty much the same, except
+ registers have a different string representation and related
+ error strings. */
unsigned int optimized_out : 1;
/* If value is a variable, is it initialized or not. */
return result;
}
+void
+error_value_optimized_out (void)
+{
+ error (_("value has been optimized out"));
+}
+
static void
require_not_optimized_out (const struct value *value)
{
if (value->optimized_out)
- error (_("value has been optimized out"));
+ {
+ if (value->lval == lval_register)
+ error (_("register has not been saved in frame"));
+ else
+ error_value_optimized_out ();
+ }
}
static void
extern int value_stack (struct value *);
extern void set_value_stack (struct value *value, int val);
+/* Throw an error complaining that the value has been optimized
+ out. */
+
+extern void error_value_optimized_out (void);
+
/* value_contents() and value_contents_raw() both return the address
of the gdb buffer used to hold a copy of the contents of the lval.
value_contents() is used when the contents of the buffer are needed