Bug 14605 - Display of partially optimised out variables from registers, using dwarf piece info.
Summary: Display of partially optimised out variables from registers, using dwarf piec...
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: symtab (show other bugs)
Version: HEAD
: P2 normal
Target Milestone: 7.9
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-09-21 16:33 UTC by Andrew Burgess
Modified: 2014-08-21 11:40 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
An x86-64 assembler test file for this bug. (4.07 KB, application/octet-stream)
2012-09-21 16:33 UTC, Andrew Burgess
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew Burgess 2012-09-21 16:33:35 UTC
Created attachment 6645 [details]
An x86-64 assembler test file for this bug.

Raising defect as requested in this gdb-patches mailing list thread:
  http://sourceware.org/ml/gdb-patches/2012-08/msg00715.html

This bug is for a failure in the test gdb.dwarf2/dw2-op-out-param.exp that
was added at the end of the above mailing list thread.

If a variable is described by the DWARF as being split over multiple
registers using DWARF piece information, but some of those register are
marked as optimised out by a later frame then gdb incorrectly believes the
value of those pieces is zero.

Having a variable help in a register that is marked as optimised out by a
later frame should probably be fixed in the dwarf producer, however, it is
interesting in this case that gdb, without error or warning displays
the *wrong* answer.  However, no example of this bug has yet been seen in
the wild.

The test creates two call stacks:
  main --> struct_param_two_reg_pieces --> breakpt
  main --> int_param_two_reg_pieces --> breakpt

In each function "struct_param_two_reg_pieces" and
"int_param_two_reg_pieces" variables are placed in multiple register using
piece information, and the function "breakpt" marks some of these
registers as optimised out.

The test file is x86-64 specific, download test.S, and assemble as:
gcc -o test test.S

Then run gdb as:
> gdb test
(gdb) break breakpt 
Breakpoint 1 at 0x4004fb
(gdb) r
Starting program: /projects/firepath_work/aburgess/tmp/gdb/test 
warning: no loadable sections found in added symbol-file system-supplied DSO at 0x2aaaaaaab000

Breakpoint 1, 0x00000000004004fb in breakpt ()
(gdb) c
Continuing.

Breakpoint 1, 0x00000000004004fb in breakpt ()
(gdb) c
Continuing.

Breakpoint 1, 0x00000000004004fb in breakpt ()
(gdb) set output-radix 16
Output radix now set to decimal 16, hex 10, octal 20.
(gdb) set print frame-arguments all
(gdb) bt
#0  0x00000000004004fb in breakpt ()
#1  0x000000000040052e in struct_param_two_reg_pieces (operand0=
      {a = 0xdeadbe04deadbe05, b = 0x0}, operand1=
      {a = 0x0, b = 0xdeadbe00deadbe01}, operand2={a = 0x0, b = 0x0})
#2  0x00000000004004ef in main ()
(gdb) c
Continuing.

Breakpoint 1, 0x00000000004004fb in breakpt ()
(gdb) bt
#0  0x00000000004004fb in breakpt ()
#1  0x000000000040053e in int_param_two_reg_pieces (operand0=0xdeadbe05, 
    operand1=0xdeadbe0100000000, operand2=0x0)
#2  0x00000000004004f5 in main ()
(gdb) quit

## END ##

In both backtraces the values for operand0, operand1, and operand2 are
wrong.

In the first backtrace the correct values are:
operand0={a = 0xdeadbe04deadbe05, b = <optimized out>}
operand1={a = <optimized out>, b = 0xdeadbe00deadbe01}
operand2=<optimized out>

In the second backtrace the correct values are:
operand0=<optimized out>
operand1=<optimized out>
operand2=<optimized out>

In the second case we must mark the whole value as optimised out as the
variable is an integer type, I can't imagine how we'd show a partially
optimised out integer variable.
Comment 1 Sourceware Commits 2014-08-19 23:36:09 UTC
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "gdb and binutils".

The branch, master has been updated
       via  9a0dc9e3699018b15980bb6a39eb33dea8fefa34 (commit)
      from  6694c4110a37bc951d01132d6e56445d57350627 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=9a0dc9e3699018b15980bb6a39eb33dea8fefa34

commit 9a0dc9e3699018b15980bb6a39eb33dea8fefa34
Author: Pedro Alves <palves@redhat.com>
Date:   Wed Aug 20 00:07:40 2014 +0100

    Handle partially optimized out values similarly to unavailable values
    
    This fixes PR symtab/14604, PR symtab/14605, and Jan's test at
    https://sourceware.org/ml/gdb-patches/2014-07/msg00158.html, in a tree
    with bddbbed reverted:
    
     2014-07-22  Pedro Alves  <palves@redhat.com>
    
     	* value.c (allocate_optimized_out_value): Don't mark value as
     	non-lazy.
    
    The PRs are about variables described by the DWARF as being split over
    multiple registers using DWARF piece information, but some of those
    registers being marked as optimised out (not saved) by a later frame.
    GDB currently incorrectly mishandles these partially-optimized-out
    values.
    
    Even though we can usually tell from the debug info whether a local or
    global is optimized out, handling the case of a local living in a
    register that was not saved in a frame requires fetching the variable.
    GDB also needs to fetch a value to tell whether parts of it are
    "<unavailable>".  Given this, it's not worth it to try to avoid
    fetching lazy optimized-out values based on debug info alone.
    
    So this patch makes GDB track which chunks of a value's contents are
    optimized out like it tracks <unavailable> contents.  That is, it
    makes value->optimized_out be a bit range vector instead of a boolean,
    and removes the struct lval_funcs check_validity and check_any_valid
    hooks.
    
    Unlike Andrew's series which this is based on (at
    https://sourceware.org/ml/gdb-patches/2013-08/msg00300.html, note some
    pieces have gone in since), this doesn't merge optimized out and
    unavailable contents validity/availability behind a single interface,
    nor does it merge the bit range vectors themselves (at least yet).
    While it may be desirable to have a single entry point that returns
    existence of contents irrespective of what may make them
    invalid/unavailable, several places want to treat optimized out /
    unavailable / etc. differently, so each spot that potentially could
    use it will need to be careful considered on case-by-case basis, and
    best done as a separate change.
    
    This fixes Jan's test, because value_available_contents_eq wasn't
    considering optimized out value contents.  It does now, and because of
    that it's been renamed to value_contents_eq.
    
    A new intro comment is added to value.h describing "<optimized out>",
    "<not saved>" and "<unavailable>" values.
    
    gdb/
    	PR symtab/14604
    	PR symtab/14605
    	* ada-lang.c (coerce_unspec_val_to_type): Use
    	value_contents_copy_raw.
    	* ada-valprint.c (val_print_packed_array_elements): Adjust.
    	* c-valprint.c (c_val_print): Use value_bits_any_optimized_out.
    	* cp-valprint.c (cp_print_value_fields): Let the common printing
    	code handle optimized out values.
    	(cp_print_value_fields_rtti): Use value_bits_any_optimized_out.
    	* d-valprint.c (dynamic_array_type): Use
    	value_bits_any_optimized_out.
    	* dwarf2loc.c (entry_data_value_funcs): Remove check_validity and
    	check_any_valid fields.
    	(check_pieced_value_bits): Delete and inline ...
    	(check_pieced_synthetic_pointer): ... here.
    	(check_pieced_value_validity): Delete.
    	(check_pieced_value_invalid): Delete.
    	(pieced_value_funcs): Remove check_validity and check_any_valid
    	fields.
    	(read_pieced_value): Use mark_value_bits_optimized_out.
    	(write_pieced_value): Switch to use
    	mark_value_bytes_optimized_out.
    	(dwarf2_evaluate_loc_desc_full): Copy the value contents instead
    	of assuming the whole value is optimized out.
    	* findvar.c (read_frame_register_value): Remove special handling
    	of optimized out registers.
    	(value_from_register): Use mark_value_bytes_optimized_out.
    	* frame-unwind.c (frame_unwind_got_optimized): Use
    	mark_value_bytes_optimized_out.
    	* jv-valprint.c (java_value_print): Adjust.
    	(java_print_value_fields): Let the common printing code handle
    	optimized out values.
    	* mips-tdep.c (mips_print_register): Remove special handling of
    	optimized out registers.
    	* opencl-lang.c (lval_func_check_validity): Delete.
    	(lval_func_check_any_valid): Delete.
    	(opencl_value_funcs): Remove check_validity and check_any_valid
    	fields.
    	* p-valprint.c (pascal_object_print_value_fields): Let the common
    	printing code handle optimized out values.
    	* stack.c (read_frame_arg): Remove special handling of optimized
    	out values.  Fetch both VAL and ENTRYVAL before comparing
    	contents.  Adjust to value_available_contents_eq rename.
    	* valprint.c (valprint_check_validity)
    	(val_print_scalar_formatted): Use value_bits_any_optimized_out.
    	(val_print_array_elements): Adjust.
    	* value.c (struct value) <optimized_out>: Now a VEC(range_s).
    	(value_bits_any_optimized_out): New function.
    	(value_entirely_covered_by_range_vector): New function, factored
    	out from value_entirely_unavailable.
    	(value_entirely_unavailable): Reimplement.
    	(value_entirely_optimized_out): New function.
    	(insert_into_bit_range_vector): New function, factored out from
    	mark_value_bits_unavailable.
    	(mark_value_bits_unavailable): Reimplement.
    	(struct ranges_and_idx): New struct.
    	(find_first_range_overlap_and_match): New function, factored out
    	from value_available_contents_bits_eq.
    	(value_available_contents_bits_eq): Rename to ...
    	(value_contents_bits_eq): ... this.  Check both unavailable
    	contents and optimized out contents.
    	(value_available_contents_eq): Rename to ...
    	(value_contents_eq): ... this.
    	(allocate_value_lazy): Remove reference to the old optimized_out
    	boolean.
    	(allocate_optimized_out_value): Use
    	mark_value_bytes_optimized_out.
    	(require_not_optimized_out): Adjust to check whether the
    	optimized_out vec is empty.
    	(ranges_copy_adjusted): New function, factored out from
    	value_contents_copy_raw.
    	(value_contents_copy_raw): Also copy the optimized out ranges.
    	Assert the destination ranges aren't optimized out.
    	(value_contents_copy): Update comment, remove call to
    	require_not_optimized_out.
    	(value_contents_equal): Adjust to check whether the optimized_out
    	vec is empty.
    	(set_value_optimized_out, value_optimized_out_const): Delete.
    	(mark_value_bytes_optimized_out, mark_value_bits_optimized_out):
    	New functions.
    	(value_entirely_optimized_out, value_bits_valid): Delete.
    	(value_copy): Take a VEC copy of the 'optimized_out' field.
    	(value_primitive_field): Remove special handling of optimized out.
    	(value_fetch_lazy): Assert that lazy values have no unavailable
    	regions.  Use value_bits_any_optimized_out.  Remove some special
    	handling for optimized out values.
    	* value.h: Add intro comment about <optimized out> and
    	<unavailable>.
    	(struct lval_funcs): Remove check_validity and check_any_valid
    	fields.
    	(set_value_optimized_out, value_optimized_out_const): Remove.
    	(mark_value_bytes_optimized_out, mark_value_bits_optimized_out):
    	New declarations.
    	(value_bits_any_optimized_out): New declaration.
    	(value_bits_valid): Delete declaration.
    	(value_available_contents_eq): Rename to ...
    	(value_contents_eq): ... this, and extend comments.
    
    gdb/testsuite/
    	PR symtab/14604
    	PR symtab/14605
    	* gdb.dwarf2/dw2-op-out-param.exp: Remove kfail branches and use
    	gdb_test.

-----------------------------------------------------------------------

Summary of changes:
 gdb/ChangeLog                                 |  101 ++++++
 gdb/ada-lang.c                                |    4 +-
 gdb/ada-valprint.c                            |    6 +-
 gdb/c-valprint.c                              |    6 +-
 gdb/cp-valprint.c                             |   11 +-
 gdb/d-valprint.c                              |    5 +-
 gdb/dwarf2loc.c                               |   81 +----
 gdb/findvar.c                                 |    8 +-
 gdb/frame-unwind.c                            |    2 +-
 gdb/jv-valprint.c                             |   13 +-
 gdb/mips-tdep.c                               |    6 -
 gdb/opencl-lang.c                             |   54 ---
 gdb/p-valprint.c                              |    5 -
 gdb/stack.c                                   |   17 +-
 gdb/testsuite/ChangeLog                       |    8 +
 gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp |   30 +--
 gdb/valprint.c                                |   22 +-
 gdb/value.c                                   |  467 +++++++++++++++----------
 gdb/value.h                                   |  158 ++++++---
 19 files changed, 554 insertions(+), 450 deletions(-)
Comment 2 Pedro Alves 2014-08-21 11:40:52 UTC
Fixed.