Print registers not saved in the frame as "<not saved>" instead of "<optimized out>".

Currently, in some scenarios, GDB prints <optimized out> when printing
outer frame registers.  An <optimized out> register is a confusing
concept.  What this really means is that the register is
call-clobbered, or IOW, not saved by the callee.  This patch makes GDB
say that instead.

Before patch:

 (gdb) p/x $rax $1 = <optimized out>
 (gdb) info registers rax
 rax            <optimized out>

After patch:

 (gdb) p/x $rax
 $1 = <not saved>
 (gdb) info registers rax
 rax            <not saved>

However, if for some reason the debug info describes a variable as
being in such a register (**), we still want to print <optimized out>
when printing the variable.  IOW, <not saved> is reserved for
inspecting registers at the machine level.  The patch uses
lval_register+optimized_out to encode the not saved registers, and
makes it so that optimized out variables always end up in
!lval_register values.

** See <https://sourceware.org/ml/gdb-patches/2012-08/msg00787.html>.
Current/recent enough GCC doesn't mark variables/arguments as being in
call-clobbered registers in the ranges corresponding to function
calls, while older GCCs did.  Newer GCCs will just not say where the
variable is, so GDB will end up realizing the variable is optimized
out.

frame_unwind_got_optimized creates not_lval optimized out registers,
so by default, in most cases, we'll see <optimized out>.

value_of_register is the function eval.c uses for evaluating
OP_REGISTER (again, $pc, etc.), and related bits.  It isn't used for
anything else.  This function makes sure to return lval_register
values.  The patch makes "info registers" and the MI equivalent use it
too.  I think it just makes a lot of sense, as this makes it so that
when printing machine registers ($pc, etc.), we go through a central
function.

We're likely to need a different encoding at some point, if/when we
support partially saved registers.  Even then, I think
value_of_register will still be the spot to tag the intention to print
machine register values differently.

value_from_register however may also return optimized out
lval_register values, so at a couple places where we're computing a
variable's location from a dwarf expression, we convert the resulting
value away from lval_register to a regular optimized out value.

Tested on x86_64 Fedora 17

gdb/
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>.

gdb/testsuite/
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.

gdb/doc/
2013-10-02  Pedro Alves  <palves@redhat.com>

	* gdb.texinfo (Registers): Expand description of saved registers
	in frames.  Explain <not saved>.
This commit is contained in:
Pedro Alves 2013-10-02 16:15:46 +00:00
parent b477a5e649
commit 901461f8eb
19 changed files with 154 additions and 30 deletions

View File

@ -1,3 +1,33 @@
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

View File

@ -15,6 +15,20 @@
* 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.

View File

@ -298,7 +298,7 @@ cp_print_value_fields (struct type *type, struct type *real_type,
TYPE_FIELD_BITPOS (type, i),
TYPE_FIELD_BITSIZE (type, i)))
{
val_print_optimized_out (stream);
val_print_optimized_out (val, stream);
}
else
{
@ -334,7 +334,7 @@ cp_print_value_fields (struct type *type, struct type *real_type,
_("<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,

View File

@ -1,3 +1,8 @@
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.

View File

@ -10031,10 +10031,33 @@ were exited and their saved registers restored. In order to see the
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

View File

@ -2290,11 +2290,21 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
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;

View File

@ -757,6 +757,15 @@ address_from_register (struct type *type, int regnum, struct frame_info *frame)
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);

View File

@ -1143,7 +1143,7 @@ put_frame_register (struct frame_info *frame, int regnum,
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:

View File

@ -2035,7 +2035,7 @@ default_print_one_register_info (struct ui_file *file,
}
else if (value_optimized_out (val))
{
val_print_optimized_out (file);
val_print_optimized_out (val, file);
fprintf_filtered (file, "\n");
return;
}
@ -2142,7 +2142,7 @@ default_print_registers_info (struct gdbarch *gdbarch,
default_print_one_register_info (file,
gdbarch_register_name (gdbarch, i),
get_frame_register_value (frame, i));
value_of_register (i, frame));
}
}

View File

@ -395,7 +395,7 @@ java_print_value_fields (struct type *type, const gdb_byte *valaddr,
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
{
@ -420,7 +420,7 @@ java_print_value_fields (struct type *type, const gdb_byte *valaddr,
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;

View File

@ -1161,7 +1161,7 @@ output_register (struct frame_info *frame, int regnum, int format,
{
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;

View File

@ -629,7 +629,7 @@ pascal_object_print_value_fields (struct type *type, const gdb_byte *valaddr,
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
{
@ -657,7 +657,7 @@ pascal_object_print_value_fields (struct type *type, const gdb_byte *valaddr,
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);

View File

@ -1,3 +1,11 @@
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".

View File

@ -45,8 +45,8 @@ for {set f 0} {$f < 3} {incr f} {
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"
}

View File

@ -52,13 +52,13 @@ mi_gdb_test "111-stack-list-frames" \
"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" \

View File

@ -314,7 +314,7 @@ valprint_check_validity (struct ui_file *stream,
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;
}
@ -336,9 +336,12 @@ valprint_check_validity (struct ui_file *stream,
}
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
@ -805,7 +808,7 @@ value_check_printable (struct value *val, struct ui_file *stream,
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;
}
@ -966,7 +969,7 @@ val_print_scalar_formatted (struct type *type,
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

View File

@ -160,7 +160,8 @@ extern int read_string (CORE_ADDR addr, int len, int width,
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);

View File

@ -197,8 +197,13 @@ struct value
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. */
@ -902,11 +907,22 @@ value_actual_type (struct value *value, int resolve_simple_types,
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

View File

@ -273,6 +273,11 @@ extern void set_value_lazy (struct value *value, int val);
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