Re: [PATCH] Consistent display of ""

Pedro Alves
2013-08-16T18:41:33Z

On 08/12/2013 09:01 PM, Mark Kettenis wrote:
>> Date: Mon, 12 Aug 2013 14:55:04 +0100
>> From: Pedro Alves <palves@redhat.com>
>>
>> On 08/12/2013 02:31 PM, Andrew Burgess wrote:
>>> On 06/08/2013 7:39 PM, Pedro Alves wrote:
>>>> On 08/06/2013 04:41 PM, Mark Kettenis wrote:
>>>>>> Date: Tue, 6 Aug 2013 14:49:03 +0100
>>>>>> From: "Andrew Burgess" <aburgess@broadcom.com>
>>>>
>>>>>> 3. My understanding was that values lost due to the ABI of a call site
>>>>>> were recorded as optimized out. For evidence I would present
>>>>>> dwarf2_frame_prev_register, and how DWARF2_FRAME_REG_UNDEFINED is handled.
>>>>>>
>>>>>> For these reasons I believe my patch should still be considered, what do
>>>>>> you think?
>>>>>
>>>>> I think that registers are either available or unavailble. A register
>>>>> being unavailble implies that a variable that is supposed to live in
>>>>> such a register may have been optimized out. Whether GDB's pseudo
>>>>> variables that respresent registers are considered unavailable or
>>>>> optimized out in that case is arguable.
>>>>
>>>> I think improving consistency as in Andrew's patch is good.
>>>
>>> Given almost a week has passed with no further feedback I plan to
>>> commit this patch tomorrow unless there's any further discussion to be had.
>>
>> TBC, note my opinion doesn't get to overrule Mark's. Consensus
>> works much better, and Mark does have deep knowledge of all
>> ABI/pseudo registers/etc. gdb things.
>> That said, Mark, if you still disagree, please counter argue,
>> otherwise, we'll just have to assume you do agree with the
>> rationales and clarifications.
>
> Can't say I agree. It simply doesn't make sense for registers to be
> "optimized out". I guess there are two reasons why GDB can't display
> the contents of a register in a frame:
>
> 1. The register contents aren't made available by the debugging
> interface, i.e. ptrace(2) or the remote stub doesn't tell us.
>
> 2. The register wasn't saved before calling another function.
>
> I guess after Andrew's chnages 1) would be shown as <unavailable> and
> 2) would become <optimized out>. But in the latter case something
> like <not saved> would make more sense.
>
> That said, Pedro, you're pretty much the expert for this area of GDB.
> So If you think Andrew should go ahead with this, feel free to ignore
> me.

This is a tough call. I do agree that "optimized out" for registers
is a bit confusing. However, we already do print "<optimized out>" in
other places, such as when printing expressions, and consistency
is good. If we did add a distinction, I agree with Andrew that it should
be done in a more systematic way. However, I'm not really sure we need
much machinery. Wouldn't something like:

void
val_print_optimized_out (const struct value *val, struct ui_file *stream)
{
if (value_lval_const (val) == lval_register)
fprintf_filtered (stream, _("<not saved>"));
else
fprintf_filtered (stream, _("<optimized out>"));
}

work? What could be the register value cases that would print
"not saved" that we'd still want to print "optimized out" ?

...

Hmm, I spent a bit playing with this, and here's what I got. At
first glance, the changes in output all look reasonable to me.

frame_unwind_got_optimized needed a tweak to return an
lval_register value; it's returning not_lval presently.

Pushed here (along with Andrew's patch) for convenience:
https://github.com/palves/gdb/commits/register_not_saved
git@github.com:palves/gdb.git register_not_saved

Here's the (trimmed for brevity) diff of the resulting gdb.log between
after Andrew's path and after my patch, of a run of
gdb.dwarf2/dw2-op-out-param.exp gdb.dwarf2/dw2-reg-undefined.exp
gdb.mi/mi-reg-undefined.exp, the only tests affected.

(Code patch further below.)

~~~~

(gdb) PASS: gdb.dwarf2/dw2-reg-undefined.exp: Switch to frame 1
p/x $rax
-$6 = <optimized out>
+$6 = <not saved>
(gdb) PASS: gdb.dwarf2/dw2-reg-undefined.exp: print $rax in frame 1
p/x $rbx
-$7 = <optimized out>
+$7 = <not saved>
(gdb) PASS: gdb.dwarf2/dw2-reg-undefined.exp: print $rbx in frame 1
p/x $rcx
-$8 = <optimized out>
+$8 = <not saved>
(gdb) PASS: gdb.dwarf2/dw2-reg-undefined.exp: print $rcx in frame 1
p/x $r8
$9 = 0x323d7b1f40
@@ -109,9 +109,9 @@ p/x $r9
$10 = 0x323d00f310
(gdb) PASS: gdb.dwarf2/dw2-reg-undefined.exp: print $r9 in frame 1
info registers rax rbx rcx r8 r9
-rax <optimized out>
-rbx <optimized out>
-rcx <optimized out>
+rax <not saved>
+rbx <not saved>
+rcx <not saved>
r8 0x323d7b1f40 215779843904
r9 0x323d00f310 215771837200
(gdb) PASS: gdb.dwarf2/dw2-reg-undefined.exp: Check values of rax, rbx, rcx, r8, r9 in frame 1
@@ -120,13 +120,13 @@ frame 2
33 first_frame ();
(gdb) PASS: gdb.dwarf2/dw2-reg-undefined.exp: Switch to frame 2
p/x $rax
-$11 = <optimized out>
+$11 = <not saved>
(gdb) PASS: gdb.dwarf2/dw2-reg-undefined.exp: print $rax in frame 2
p/x $rbx
-$12 = <optimized out>
+$12 = <not saved>
(gdb) PASS: gdb.dwarf2/dw2-reg-undefined.exp: print $rbx in frame 2
p/x $rcx
-$13 = <optimized out>
+$13 = <not saved>
(gdb) PASS: gdb.dwarf2/dw2-reg-undefined.exp: print $rcx in frame 2
p/x $r8
$14 = 0x323d7b1f40
@@ -135,13 +135,13 @@ p/x $r9
$15 = 0x323d00f310
(gdb) PASS: gdb.dwarf2/dw2-reg-undefined.exp: print $r9 in frame 2
info registers rax rbx rcx r8 r9
-rax <optimized out>
-rbx <optimized out>
-rcx <optimized out>
+rax <not saved>
+rbx <not saved>
+rcx <not saved>
r8 0x323d7b1f40 215779843904
r9 0x323d00f310 215771837200
(gdb) PASS: gdb.dwarf2/dw2-reg-undefined.exp: Check values of rax, rbx, rcx, r8, r9 in frame 2

PASS: gdb.mi/mi-reg-undefined.exp: mi runto stop_frame
@@ -247,35 +247,35 @@ Expecting: ^(330-data-list-register-valu
(gdb)
PASS: gdb.mi/mi-reg-undefined.exp: register values, format r, frame 0
Expecting: ^(221-data-list-register-values --thread 1 --frame 1 x 0 1 2 8 9[
-]+)?(221\^done,register-values=\[{number="0",value="<optimized out>"},{number="1",value="<optimized out>"},{number="2",value="<optimized out>"},{number="8",value="0x[0-9A-Fa-f]+"},{number="9",value="0x[0-9A-Fa-f]+"}\][
+]+)?(221\^done,register-values=\[{number="0",value="<not saved>"},{number="1",value="<not saved>"},{number="2",value="<not saved>"},{number="8",value="0x[0-9A-Fa-f]+"},{number="9",value="0x[0-9A-Fa-f]+"}\][
]+[(]gdb[)]
[ ]*)
221-data-list-register-values --thread 1 --frame 1 x 0 1 2 8 9
-221^done,register-values=[{number="0",value="<optimized out>"},{number="1",value="<optimized out>"},{number="2",value="<optimized out>"},{number="8",value="0x323d7b1f40"},{number="9",value="0x323d00f310"}]
+221^done,register-values=[{number="0",value="<not saved>"},{number="1",value="<not saved>"},{number="2",value="<not saved>"},{number="8",value="0x323d7b1f40"},{number="9",value="0x323d00f310"}]
(gdb)
PASS: gdb.mi/mi-reg-undefined.exp: register values, format x, frame 1
Expecting: ^(331-data-list-register-values --thread 1 --frame 1 r 0 1 2 8 9[
-]+)?(331\^done,register-values=\[{number="0",value="<optimized out>"},{number="1",value="<optimized out>"},{number="2",value="<optimized out>"},{number="8",value="0x[0-9A-Fa-f]+"},{number="9",value="0x[0-9A-Fa-f]+"}\][
+]+)?(331\^done,register-values=\[{number="0",value="<not saved>"},{number="1",value="<not saved>"},{number="2",value="<not saved>"},{number="8",value="0x[0-9A-Fa-f]+"},{number="9",value="0x[0-9A-Fa-f]+"}\][
]+[(]gdb[)]
[ ]*)
331-data-list-register-values --thread 1 --frame 1 r 0 1 2 8 9
-331^done,register-values=[{number="0",value="<optimized out>"},{number="1",value="<optimized out>"},{number="2",value="<optimized out>"},{number="8",value="0x000000323d7b1f40"},{number="9",value="0x000000323d00f310"}]
+331^done,register-values=[{number="0",value="<not saved>"},{number="1",value="<not saved>"},{number="2",value="<not saved>"},{number="8",value="0x000000323d7b1f40"},{number="9",value="0x000000323d00f310"}]
(gdb)
PASS: gdb.mi/mi-reg-undefined.exp: register values, format r, frame 1
Expecting: ^(222-data-list-register-values --thread 1 --frame 2 x 0 1 2 8 9[
-]+)?(222\^done,register-values=\[{number="0",value="<optimized out>"},{number="1",value="<optimized out>"},{number="2",value="<optimized out>"},{number="8",value="0x[0-9A-Fa-f]+"},{number="9",value="0x[0-9A-Fa-f]+"}\][
+]+)?(222\^done,register-values=\[{number="0",value="<not saved>"},{number="1",value="<not saved>"},{number="2",value="<not saved>"},{number="8",value="0x[0-9A-Fa-f]+"},{number="9",value="0x[0-9A-Fa-f]+"}\][
]+[(]gdb[)]
[ ]*)
222-data-list-register-values --thread 1 --frame 2 x 0 1 2 8 9
-222^done,register-values=[{number="0",value="<optimized out>"},{number="1",value="<optimized out>"},{number="2",value="<optimized out>"},{number="8",value="0x323d7b1f40"},{number="9",value="0x323d00f310"}]
+222^done,register-values=[{number="0",value="<not saved>"},{number="1",value="<not saved>"},{number="2",value="<not saved>"},{number="8",value="0x323d7b1f40"},{number="9",value="0x323d00f310"}]
(gdb)
PASS: gdb.mi/mi-reg-undefined.exp: register values, format x, frame 2
Expecting: ^(332-data-list-register-values --thread 1 --frame 2 r 0 1 2 8 9[
-]+)?(332\^done,register-values=\[{number="0",value="<optimized out>"},{number="1",value="<optimized out>"},{number="2",value="<optimized out>"},{number="8",value="0x[0-9A-Fa-f]+"},{number="9",value="0x[0-9A-Fa-f]+"}\][
+]+)?(332\^done,register-values=\[{number="0",value="<not saved>"},{number="1",value="<not saved>"},{number="2",value="<not saved>"},{number="8",value="0x[0-9A-Fa-f]+"},{number="9",value="0x[0-9A-Fa-f]+"}\][
]+[(]gdb[)]
[ ]*)
332-data-list-register-values --thread 1 --frame 2 r 0 1 2 8 9
-332^done,register-values=[{number="0",value="<optimized out>"},{number="1",value="<optimized out>"},{number="2",value="<optimized out>"},{number="8",value="0x000000323d7b1f40"},{number="9",value="0x000000323d00f310"}]
+332^done,register-values=[{number="0",value="<not saved>"},{number="1",value="<not saved>"},{number="2",value="<not saved>"},{number="8",value="0x000000323d7b1f40"},{number="9",value="0x000000323d00f310"}]
(gdb)
PASS: gdb.mi/mi-reg-undefined.exp: register values, format r, frame 2
testcase ../../../src/gdb/testsuite/gdb.mi/mi-reg-undefined.exp completed in 0 seconds
@@ -338,7 +338,7 @@ Breakpoint 2, 0x000000000040058f in brea
(gdb) PASS: gdb.dwarf2/dw2-op-out-param.exp: continue to breakpoint: Stop in breakpt for test int_param_single_reg_loc
bt
#0 0x000000000040058f in breakpt ()
-#1 0x00000000004005a2 in int_param_single_reg_loc (operand0=<optimized out>, operand1=0xdeadbe00deadbe01, operand2=<optimized out>)
+#1 0x00000000004005a2 in int_param_single_reg_loc (operand0=<not saved>, operand1=0xdeadbe00deadbe01, operand2=<not saved>)
#2 0x0000000000400577 in main ()
(gdb) PASS: gdb.dwarf2/dw2-op-out-param.exp: Backtrace for test int_param_single_reg_loc
continue
@@ -348,7 +348,7 @@ Breakpoint 2, 0x000000000040058f in brea
(gdb) PASS: gdb.dwarf2/dw2-op-out-param.exp: continue to breakpoint: Stop in breakpt for struct_param_single_reg_loc
bt
#0 0x000000000040058f in breakpt ()
-#1 0x00000000004005b2 in struct_param_single_reg_loc (operand0=<optimized out>, operand1=<optimized out>, operand2=<optimized out>)
+#1 0x00000000004005b2 in struct_param_single_reg_loc (operand0=<not saved>, operand1=<not saved>, operand2=<not saved>)
#2 0x000000000040057d in main ()
(gdb) KFAIL: gdb.dwarf2/dw2-op-out-param.exp: Backtrace for test struct_param_single_reg_loc (PRMS: symtab/14604)
continue
@@ -371,7 +371,7 @@ bt
#1 0x00000000004005d2 in int_param_two_reg_pieces (operand0=0xdeadbe05, operand1=0xdeadbe0100000000, operand2=0x0)
#2 0x0000000000400589 in main ()
(gdb) KFAIL: gdb.dwarf2/dw2-op-out-param.exp: Backtrace for test int_param_two_reg_pieces (PRMS: symtab/14605)
~~~~

-------
From 2e7a45e5752bbdd3344b540dd27fafe0faf4e627 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Fri, 16 Aug 2013 11:31:13 +0100
Subject: [PATCH] WIP: print "optimized out" register values as "<not saved>"
instead of "optimized out".

---
gdb/cp-valprint.c | 4 ++--
gdb/frame-unwind.c | 2 +-
gdb/infcmd.c | 2 +-
gdb/jv-valprint.c | 4 ++--
gdb/p-valprint.c | 4 ++--
gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp | 10 +++++-----
gdb/testsuite/gdb.dwarf2/dw2-reg-undefined.exp | 4 ++--
gdb/testsuite/gdb.mi/mi-reg-undefined.exp | 4 ++--
gdb/valprint.c | 13 ++++++++-----
gdb/valprint.h | 3 ++-
gdb/value.c | 23 ++++++++++++++++++++++-
gdb/value.h | 4 ++++
12 files changed, 53 insertions(+), 24 deletions(-)

diff --git a/gdb/cp-valprint.c b/gdb/cp-valprint.c
index e83d979..1d7147c 100644
--- a/gdb/cp-valprint.c
+++ b/gdb/cp-valprint.c
@@ -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,
diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c
index ce2f6da..69c977e 100644
--- a/gdb/frame-unwind.c
+++ b/gdb/frame-unwind.c
@@ -164,7 +164,7 @@ frame_unwind_got_optimized (struct frame_info *frame, int regnum)
struct gdbarch *gdbarch = frame_unwind_arch (frame);
struct type *reg_type = register_type (gdbarch, regnum);

- return allocate_optimized_out_value (reg_type);
+ return allocate_not_saved_value (reg_type, frame, regnum);
}

/* Return a value which indicates that FRAME copied REGNUM into
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index f6a5290..76e84c9 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -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;
}
diff --git a/gdb/jv-valprint.c b/gdb/jv-valprint.c
index 3b90e54..961a8e8 100644
--- a/gdb/jv-valprint.c
+++ b/gdb/jv-valprint.c
@@ -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 (v, stream);
else
{
struct value_print_options opts;
diff --git a/gdb/p-valprint.c b/gdb/p-valprint.c
index 05d4c6f..6e8a408 100644
--- a/gdb/p-valprint.c
+++ b/gdb/p-valprint.c
@@ -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 (v, stream);
else
pascal_object_print_static_field (v, stream, recurse + 1,
options);
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp b/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp
index 5e4ca01..fecb0df 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp
@@ -46,16 +46,16 @@ gdb_test_no_output "set print frame-arguments all"

# (1) int_param_single_reg_loc
gdb_continue_to_breakpoint "Stop in breakpt for test int_param_single_reg_loc"
-gdb_test "bt" "#0 ($hex in )?breakpt \\(\\)\r\n#1 ($hex in )?int_param_single_reg_loc \\(operand0=<optimized out>, operand1=0xdeadbe00deadbe01, operand2=<optimized out>\\)\r\n#2 ($hex in )?main \\(\\)" "Backtrace for test int_param_single_reg_loc"
+gdb_test "bt" "#0 ($hex in )?breakpt \\(\\)\r\n#1 ($hex in )?int_param_single_reg_loc \\(operand0=<not saved>, operand1=0xdeadbe00deadbe01, operand2=<not saved>\\)\r\n#2 ($hex in )?main \\(\\)" "Backtrace for test int_param_single_reg_loc"

# (2) struct_param_single_reg_loc
gdb_continue_to_breakpoint "Stop in breakpt for struct_param_single_reg_loc"
set test "Backtrace for test struct_param_single_reg_loc"
gdb_test_multiple "bt" "$test" {
- -re "#0 ($hex in )?breakpt \\(\\)\r\n#1 ($hex in )?struct_param_single_reg_loc \\(operand0={a = 0xdeadbe00deadbe01, b = <optimized out>}, operand1={a = <optimized out>, b = 0xdeadbe04deadbe05}, operand2=<optimized out>\\)\r\n#2 ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
+ -re "#0 ($hex in )?breakpt \\(\\)\r\n#1 ($hex in )?struct_param_single_reg_loc \\(operand0={a = 0xdeadbe00deadbe01, b = <not saved>}, operand1={a = <not saved>, b = 0xdeadbe04deadbe05}, operand2=<not saved>\\)\r\n#2 ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
xpass $test
}
- -re "#0 ($hex in )?breakpt \\(\\)\r\n#1 ($hex in )?struct_param_single_reg_loc \\(operand0=<optimized out>, operand1=<optimized out>, operand2=<optimized out>\\)\r\n#2 ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
+ -re "#0 ($hex in )?breakpt \\(\\)\r\n#1 ($hex in )?struct_param_single_reg_loc \\(operand0=<not saved>, operand1=<not saved>, operand2=<not saved>\\)\r\n#2 ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
kfail "symtab/14604" $test
}
}
@@ -64,7 +64,7 @@ gdb_test_multiple "bt" "$test" {
gdb_continue_to_breakpoint "Stop in breakpt for struct_param_two_reg_pieces"
set test "Backtrace for test struct_param_two_reg_pieces"
gdb_test_multiple "bt" "$test" {
- -re "#0 ($hex in )?breakpt \\(\\)\r\n#1 ($hex in )?struct_param_two_reg_pieces \\(operand0={a = 0xdeadbe04deadbe05, b = <optimized out>}, operand1={a = <optimized out>, b = 0xdeadbe00deadbe01}, operand2=<optimized out>\\)\r\n#2 ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
+ -re "#0 ($hex in )?breakpt \\(\\)\r\n#1 ($hex in )?struct_param_two_reg_pieces \\(operand0={a = 0xdeadbe04deadbe05, b = <not saved>}, operand1={a = <not saved>, b = 0xdeadbe00deadbe01}, operand2=<not saved>\\)\r\n#2 ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
xpass $test
}
-re "#0 ($hex in )?breakpt \\(\\)\r\n#1 ($hex in )?struct_param_two_reg_pieces \\(operand0=.*, operand1=.*, operand2=.*\\)\r\n#2 ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
@@ -76,7 +76,7 @@ gdb_test_multiple "bt" "$test" {
gdb_continue_to_breakpoint "Stop in breakpt for int_param_two_reg_pieces"
set test "Backtrace for test int_param_two_reg_pieces"
gdb_test_multiple "bt" "$test" {
- -re "#0 ($hex in )?breakpt \\(\\)\r\n#1 ($hex in )?int_param_two_reg_pieces \\(operand0=<optimized out>, operand1=<optimized out>, operand2=<optimized out>\\)\r\n#2 ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
+ -re "#0 ($hex in )?breakpt \\(\\)\r\n#1 ($hex in )?int_param_two_reg_pieces \\(operand0=<not saved>, operand1=<not saved>, operand2=<not saved>\\)\r\n#2 ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
xpass $test
}
-re "#0 ($hex in )?breakpt \\(\\)\r\n#1 ($hex in )?int_param_two_reg_pieces \\(operand0=.*, operand1=.*, operand2=.*\\)\r\n#2 ($hex in )?main \\(\\)\r\n$gdb_prompt $" {
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-reg-undefined.exp b/gdb/testsuite/gdb.dwarf2/dw2-reg-undefined.exp
index 4686648..44bf8e9 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-reg-undefined.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-reg-undefined.exp
@@ -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"
}
diff --git a/gdb/testsuite/gdb.mi/mi-reg-undefined.exp b/gdb/testsuite/gdb.mi/mi-reg-undefined.exp
index 8bcbb21..cb3a716 100644
--- a/gdb/testsuite/gdb.mi/mi-reg-undefined.exp
+++ b/gdb/testsuite/gdb.mi/mi-reg-undefined.exp
@@ -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" \
diff --git a/gdb/valprint.c b/gdb/valprint.c
index 753ae34..285a7fe 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -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 && !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
diff --git a/gdb/valprint.h b/gdb/valprint.h
index 2959098..40e2ebb 100644
--- a/gdb/valprint.h
+++ b/gdb/valprint.h
@@ -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);

diff --git a/gdb/value.c b/gdb/value.c
index 09ab1bb..6032267 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -747,6 +747,22 @@ allocate_optimized_out_value (struct type *type)
return retval;
}

+/* Allocate a "not saved" value for type TYPE. */
+
+struct value *
+allocate_not_saved_value (struct type *type,
+ struct frame_info *frame, int regnum)
+{
+ struct value *retval = allocate_value (type);
+
+ set_value_optimized_out (retval, 1);
+ VALUE_LVAL (retval) = lval_register;
+ VALUE_FRAME_ID (retval) = get_frame_id (frame);
+ VALUE_REGNUM (retval) = regnum;
+
+ return retval;
+}
+
/* Accessor methods. */

struct value *
@@ -886,7 +902,12 @@ 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 has been optimized out"));
+ }
}

static void
diff --git a/gdb/value.h b/gdb/value.h
index bef193c..d4463bf 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -243,6 +243,10 @@ extern int valprint_check_validity (struct ui_file *stream, struct type *type,

extern struct value *allocate_optimized_out_value (struct type *type);

+extern struct value *allocate_not_saved_value (struct type *type,
+ struct frame_info *frame,
+ int regnum);
+
/* If VALUE is lval_computed, return its lval_funcs structure. */

extern const struct lval_funcs *value_computed_funcs (const struct value *);
--
1.7.11.7