public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [patchv2] Fix crash on optimized-out entry data values
@ 2014-07-09 10:33 Jan Kratochvil
  2014-07-09 11:52 ` Pedro Alves
  0 siblings, 1 reply; 28+ messages in thread
From: Jan Kratochvil @ 2014-07-09 10:33 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 813 bytes --]

Hi,

former post of this fix was for:
	[patch+7.8] Fix crash on optimized-out entry data values
	https://sourceware.org/ml/gdb-patches/2014-06/msg00797.html
=
	https://bugzilla.redhat.com/show_bug.cgi?id=1111910
	this can happen for real world -O2 -g executables:
	#9  0x0000003b6e0998b2 in wxEntry (argc=@0x7fffffffd86c: 1,
	    argc@entry=@0x7fffffffd86c: <optimized out>,
					^^^^^^^^^^^^^^^
	    argv=<optimized out>) at src/common/init.cpp:460
	GDB did crash in such case.

But the fix was wrong/regressing as shown here:
	https://bugzilla.redhat.com/show_bug.cgi?id=1117192
	https://bugzilla.redhat.com/attachment.cgi?id=916298 (at the bottom)

Here is a new fix, also with a new testcase reproducing crash of the wrong fix
above.

No regressions on {x86_64,x86_64-m32,i686}-fedorarawhide-linux-gnu.


Jan

[-- Attachment #2: optimfix2.patch --]
[-- Type: text/plain, Size: 31989 bytes --]

gdb/
2014-07-09  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* value.c (struct value): Extend the comment for fields optimized_out
	and unavailable.
	(value_available_contents_bits_eq): Handle OPTIMIZED_OUT values with
	empty UNAVAILABLE as special cases.

gdb/testsuite/
2014-07-09  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* gdb.arch/amd64-entry-value-paramref.S: New file.
	* gdb.arch/amd64-entry-value-paramref.cc: New file.
	* gdb.arch/amd64-entry-value-paramref.exp: New file.
	* gdb.arch/amd64-optimout-repeat.S: New file.
	* gdb.arch/amd64-optimout-repeat.c: New file.
	* gdb.arch/amd64-optimout-repeat.exp: New file.

diff --git a/gdb/value.c b/gdb/value.c
index 557056f..4b7495e 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -198,12 +198,13 @@ struct value
   unsigned int lazy : 1;
 
   /* If nonzero, this is the value of a variable that does not
-     actually exist in the program.  If nonzero, and LVAL is
+     actually fully 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.  */
+     error strings.  It is true also for only partially optimized
+     out variables - see the 'unavailable' field below.  */
   unsigned int optimized_out : 1;
 
   /* If value is a variable, is it initialized or not.  */
@@ -334,7 +335,10 @@ struct value
      valid if lazy is nonzero.  */
   gdb_byte *contents;
 
-  /* Unavailable ranges in CONTENTS.  We mark unavailable ranges,
+  /* If OPTIMIZED_OUT is false then UNAVAILABLE must be VEC_empty
+     (not necessarily NULL).  If OPTIMIZED_OUT is true then VEC_empty
+     UNAVAILABLE means the whole value range.  Otherwise it specifies
+     unavailable ranges in CONTENTS.  We mark unavailable ranges,
      rather than available, since the common and default case is for a
      value to be available.  This is filled in at value read time.  The
      unavailable ranges are tracked in bits.  */
@@ -701,6 +705,15 @@ value_available_contents_bits_eq (const struct value *val1, int offset1,
   /* See function description in value.h.  */
   gdb_assert (!val1->lazy && !val2->lazy);
 
+  gdb_assert (val1->optimized_out || VEC_empty (range_s, val1->unavailable));
+  gdb_assert (val2->optimized_out || VEC_empty (range_s, val2->unavailable));
+  if (val1->optimized_out != val2->optimized_out)
+    return 0;
+  if (val1->optimized_out && val2->optimized_out
+      && VEC_empty (range_s, val1->unavailable)
+      && VEC_empty (range_s, val2->unavailable))
+    return 1;
+
   while (length > 0)
     {
       range_s *r1, *r2;
diff --git a/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.S b/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.S
new file mode 100644
index 0000000..a1e9d0a
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.S
@@ -0,0 +1,459 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2014 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* This file is compiled from gdb.arch/amd64-entry-value-paramref.cc
+   using -g -dA -S -O2.
+   Additionally it has been patched.  */
+
+	.file	"amd64-entry-value-paramref.cc"
+	.text
+.Ltext0:
+	.p2align 4,,15
+	.type	_ZL3barRi.constprop.0, @function
+_ZL3barRi.constprop.0:
+.LFB2:
+	.file 1 "gdb.arch/amd64-entry-value-paramref.cc"
+	# gdb.arch/amd64-entry-value-paramref.cc:21
+	.loc 1 21 0
+	.cfi_startproc
+.LVL0:
+# BLOCK 2 freq:10000 seq:0
+# PRED: ENTRY [100.0%]  (FALLTHRU)
+	# gdb.arch/amd64-entry-value-paramref.cc:23
+	.loc 1 23 0
+	movl	vv(%rip), %eax
+	# gdb.arch/amd64-entry-value-paramref.cc:24
+	.loc 1 24 0
+	movq	%rdi, p(%rip)
+	# gdb.arch/amd64-entry-value-paramref.cc:23
+	.loc 1 23 0
+	addl	$1, %eax
+	movl	%eax, vv(%rip)
+	# gdb.arch/amd64-entry-value-paramref.cc:25
+	.loc 1 25 0
+	movl	(%rdi), %eax
+# SUCC: EXIT [100.0%] 
+	# gdb.arch/amd64-entry-value-paramref.cc:26
+	.loc 1 26 0
+	ret
+	.cfi_endproc
+.LFE2:
+	.size	_ZL3barRi.constprop.0, .-_ZL3barRi.constprop.0
+	.section	.text.startup,"ax",@progbits
+	.p2align 4,,15
+	.globl	main
+	.type	main, @function
+main:
+.LFB1:
+	# gdb.arch/amd64-entry-value-paramref.cc:30
+	.loc 1 30 0
+	.cfi_startproc
+# BLOCK 2 freq:10000 seq:0
+# PRED: ENTRY [100.0%]  (FALLTHRU)
+	subq	$16, %rsp
+	.cfi_def_cfa_offset 24
+.LBB2:
+	# gdb.arch/amd64-entry-value-paramref.cc:32
+	.loc 1 32 0
+	leaq	12(%rsp), %rdi
+	# gdb.arch/amd64-entry-value-paramref.cc:31
+	.loc 1 31 0
+	movl	$10, 12(%rsp)
+	# gdb.arch/amd64-entry-value-paramref.cc:32
+	.loc 1 32 0
+	call	_ZL3barRi.constprop.0
+.LVL1:
+.LBE2:
+	# gdb.arch/amd64-entry-value-paramref.cc:33
+	.loc 1 33 0
+	addq	$16, %rsp
+	.cfi_def_cfa_offset 8
+# SUCC: EXIT [100.0%] 
+	ret
+	.cfi_endproc
+.LFE1:
+	.size	main, .-main
+	.globl	p
+	.bss
+	.align 8
+	.type	p, @object
+	.size	p, 8
+p:
+	.zero	8
+	.globl	vv
+	.align 4
+	.type	vv, @object
+	.size	vv, 4
+vv:
+	.zero	4
+	.text
+.Letext0:
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+	.long	.Linfo_end - .Linfo_start	# Length of Compilation Unit Info
+.Linfo_start:
+	.value	0x4	# DWARF version number
+	.long	.Ldebug_abbrev0	# Offset Into Abbrev. Section
+	.byte	0x8	# Pointer Size (in bytes)
+	.uleb128 0x1	# (DIE (0xb) DW_TAG_compile_unit)
+	.long	.LASF0	# DW_AT_producer: "GNU C++ 4.8.2 20131212 (Red Hat 4.8.2-7) -mtune=generic -march=x86-64 -g -O2"
+	.byte	0x4	# DW_AT_language
+	.long	.LASF1	# DW_AT_name: "gdb.arch/amd64-entry-value-paramref.cc"
+	.long	.LASF2	# DW_AT_comp_dir: ""
+	.long	.Ldebug_ranges0+0	# DW_AT_ranges
+	.quad	0	# DW_AT_low_pc
+	.long	.Ldebug_line0	# DW_AT_stmt_list
+DIE29:	.uleb128 0x2	# (DIE (0x29) DW_TAG_subprogram)
+	.ascii "bar\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-entry-value-paramref.cc)
+	.byte	0x15	# DW_AT_decl_line
+	.long	DIE45	# DW_AT_type
+	.byte	0x1	# DW_AT_inline
+DIE39:	.uleb128 0x3	# (DIE (0x39) DW_TAG_formal_parameter)
+	.ascii "ref\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-entry-value-paramref.cc)
+	.byte	0x15	# DW_AT_decl_line
+	.long	DIE4c	# DW_AT_type
+	.byte	0	# end of children of DIE 0x29
+DIE45:	.uleb128 0x4	# (DIE (0x45) DW_TAG_base_type)
+	.byte	0x4	# DW_AT_byte_size
+	.byte	0x5	# DW_AT_encoding
+	.ascii "int\0"	# DW_AT_name
+DIE4c:	.uleb128 0x5	# (DIE (0x4c) DW_TAG_const_type)
+	.long	DIE51	# DW_AT_type
+DIE51:	.uleb128 0x6	# (DIE (0x51) DW_TAG_reference_type)
+	.byte	0x8	# DW_AT_byte_size
+	.long	DIE45	# DW_AT_type
+DIE57:	.uleb128 0x7	# (DIE (0x57) DW_TAG_subprogram)
+	.long	DIE29	# DW_AT_abstract_origin
+	.quad	.LFB2	# DW_AT_low_pc
+	.quad	.LFE2-.LFB2	# DW_AT_high_pc
+	.uleb128 0x1	# DW_AT_frame_base
+	.byte	0x9c	# DW_OP_call_frame_cfa
+			# DW_AT_GNU_all_call_sites
+DIE72:	.uleb128 0x8	# (DIE (0x72) DW_TAG_formal_parameter)
+	.long	DIE39	# DW_AT_abstract_origin
+	.uleb128 0x1	# DW_AT_location
+	.byte	0x55	# DW_OP_reg5
+	.byte	0	# end of children of DIE 0x57
+DIE7a:	.uleb128 0x9	# (DIE (0x7a) DW_TAG_subprogram)
+			# DW_AT_external
+	.long	.LASF3	# DW_AT_name: "main"
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-entry-value-paramref.cc)
+	.byte	0x1d	# DW_AT_decl_line
+	.long	DIE45	# DW_AT_type
+	.quad	.LFB1	# DW_AT_low_pc
+	.quad	.LFE1-.LFB1	# DW_AT_high_pc
+	.uleb128 0x1	# DW_AT_frame_base
+	.byte	0x9c	# DW_OP_call_frame_cfa
+			# DW_AT_GNU_all_call_sites
+DIE9b:	.uleb128 0xa	# (DIE (0x9b) DW_TAG_lexical_block)
+	.quad	.LBB2	# DW_AT_low_pc
+	.quad	.LBE2-.LBB2	# DW_AT_high_pc
+DIEac:	.uleb128 0xb	# (DIE (0xac) DW_TAG_variable)
+	.ascii "var\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-entry-value-paramref.cc)
+	.byte	0x1f	# DW_AT_decl_line
+	.long	DIE45	# DW_AT_type
+	.uleb128 0x2	# DW_AT_location
+	.byte	0x91	# DW_OP_fbreg
+	.sleb128 -12
+DIEba:	.uleb128 0xc	# (DIE (0xba) DW_TAG_GNU_call_site)
+	.quad	.LVL1	# DW_AT_low_pc
+	.long	DIE57	# DW_AT_abstract_origin
+DIEc7:	.uleb128 0xd	# (DIE (0xc7) DW_TAG_GNU_call_site_parameter)
+	.uleb128 0x1	# DW_AT_location
+	.byte	0x55	# DW_OP_reg5
+	.uleb128 0x2	# DW_AT_GNU_call_site_value
+	.byte	0x91	# DW_OP_fbreg
+	.sleb128 -12
+#if 0
+	.uleb128 0x1	# DW_AT_GNU_call_site_data_value
+	.byte	0x3a	# DW_OP_lit10
+#else
+	.uleb128 1f - 2f	# DW_AT_GNU_call_site_data_value
+2:
+	.byte	0xf3	# DW_OP_GNU_entry_value
+	.uleb128 1f - 3f
+3:
+	.byte	0x55	# DW_OP_reg5
+1:
+#endif
+	.byte	0	# end of children of DIE 0xba
+	.byte	0	# end of children of DIE 0x9b
+	.byte	0	# end of children of DIE 0x7a
+DIEd2:	.uleb128 0xe	# (DIE (0xd2) DW_TAG_variable)
+	.ascii "vv\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-entry-value-paramref.cc)
+	.byte	0x12	# DW_AT_decl_line
+	.long	DIEe6	# DW_AT_type
+			# DW_AT_external
+	.uleb128 0x9	# DW_AT_location
+	.byte	0x3	# DW_OP_addr
+	.quad	vv
+DIEe6:	.uleb128 0xf	# (DIE (0xe6) DW_TAG_volatile_type)
+	.long	DIE45	# DW_AT_type
+DIEeb:	.uleb128 0xe	# (DIE (0xeb) DW_TAG_variable)
+	.ascii "p\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-entry-value-paramref.cc)
+	.byte	0x12	# DW_AT_decl_line
+	.long	DIEfe	# DW_AT_type
+			# DW_AT_external
+	.uleb128 0x9	# DW_AT_location
+	.byte	0x3	# DW_OP_addr
+	.quad	p
+DIEfe:	.uleb128 0x10	# (DIE (0xfe) DW_TAG_pointer_type)
+	.byte	0x8	# DW_AT_byte_size
+	.long	DIEe6	# DW_AT_type
+	.byte	0	# end of children of DIE 0xb
+.Linfo_end:
+	.section	.debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1	# (abbrev code)
+	.uleb128 0x11	# (TAG: DW_TAG_compile_unit)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x25	# (DW_AT_producer)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x13	# (DW_AT_language)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x1b	# (DW_AT_comp_dir)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x55	# (DW_AT_ranges)
+	.uleb128 0x17	# (DW_FORM_sec_offset)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x10	# (DW_AT_stmt_list)
+	.uleb128 0x17	# (DW_FORM_sec_offset)
+	.byte	0
+	.byte	0
+	.uleb128 0x2	# (abbrev code)
+	.uleb128 0x2e	# (TAG: DW_TAG_subprogram)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x20	# (DW_AT_inline)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.byte	0
+	.byte	0
+	.uleb128 0x3	# (abbrev code)
+	.uleb128 0x5	# (TAG: DW_TAG_formal_parameter)
+	.byte	0	# DW_children_no
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x4	# (abbrev code)
+	.uleb128 0x24	# (TAG: DW_TAG_base_type)
+	.byte	0	# DW_children_no
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3e	# (DW_AT_encoding)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.byte	0
+	.byte	0
+	.uleb128 0x5	# (abbrev code)
+	.uleb128 0x26	# (TAG: DW_TAG_const_type)
+	.byte	0	# DW_children_no
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x6	# (abbrev code)
+	.uleb128 0x10	# (TAG: DW_TAG_reference_type)
+	.byte	0	# DW_children_no
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x7	# (abbrev code)
+	.uleb128 0x2e	# (TAG: DW_TAG_subprogram)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x31	# (DW_AT_abstract_origin)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x12	# (DW_AT_high_pc)
+	.uleb128 0x7	# (DW_FORM_data8)
+	.uleb128 0x40	# (DW_AT_frame_base)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.uleb128 0x2117	# (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.byte	0
+	.byte	0
+	.uleb128 0x8	# (abbrev code)
+	.uleb128 0x5	# (TAG: DW_TAG_formal_parameter)
+	.byte	0	# DW_children_no
+	.uleb128 0x31	# (DW_AT_abstract_origin)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x2	# (DW_AT_location)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.byte	0
+	.byte	0
+	.uleb128 0x9	# (abbrev code)
+	.uleb128 0x2e	# (TAG: DW_TAG_subprogram)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x3f	# (DW_AT_external)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x12	# (DW_AT_high_pc)
+	.uleb128 0x7	# (DW_FORM_data8)
+	.uleb128 0x40	# (DW_AT_frame_base)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.uleb128 0x2117	# (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.byte	0
+	.byte	0
+	.uleb128 0xa	# (abbrev code)
+	.uleb128 0xb	# (TAG: DW_TAG_lexical_block)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x12	# (DW_AT_high_pc)
+	.uleb128 0x7	# (DW_FORM_data8)
+	.byte	0
+	.byte	0
+	.uleb128 0xb	# (abbrev code)
+	.uleb128 0x34	# (TAG: DW_TAG_variable)
+	.byte	0	# DW_children_no
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x2	# (DW_AT_location)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.byte	0
+	.byte	0
+	.uleb128 0xc	# (abbrev code)
+	.uleb128 0x4109	# (TAG: DW_TAG_GNU_call_site)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x31	# (DW_AT_abstract_origin)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0xd	# (abbrev code)
+	.uleb128 0x410a	# (TAG: DW_TAG_GNU_call_site_parameter)
+	.byte	0	# DW_children_no
+	.uleb128 0x2	# (DW_AT_location)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.uleb128 0x2111	# (DW_AT_GNU_call_site_value)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.uleb128 0x2112	# (DW_AT_GNU_call_site_data_value)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.byte	0
+	.byte	0
+	.uleb128 0xe	# (abbrev code)
+	.uleb128 0x34	# (TAG: DW_TAG_variable)
+	.byte	0	# DW_children_no
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x3f	# (DW_AT_external)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x2	# (DW_AT_location)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.byte	0
+	.byte	0
+	.uleb128 0xf	# (abbrev code)
+	.uleb128 0x35	# (TAG: DW_TAG_volatile_type)
+	.byte	0	# DW_children_no
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x10	# (abbrev code)
+	.uleb128 0xf	# (TAG: DW_TAG_pointer_type)
+	.byte	0	# DW_children_no
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.byte	0
+	.section	.debug_aranges,"",@progbits
+	.long	0x3c	# Length of Address Ranges Info
+	.value	0x2	# DWARF Version
+	.long	.Ldebug_info0	# Offset of Compilation Unit Info
+	.byte	0x8	# Size of Address
+	.byte	0	# Size of Segment Descriptor
+	.value	0	# Pad to 16 byte boundary
+	.value	0
+	.quad	.Ltext0	# Address
+	.quad	.Letext0-.Ltext0	# Length
+	.quad	.LFB1	# Address
+	.quad	.LFE1-.LFB1	# Length
+	.quad	0
+	.quad	0
+	.section	.debug_ranges,"",@progbits
+.Ldebug_ranges0:
+	.quad	.Ltext0	# Offset 0
+	.quad	.Letext0
+	.quad	.LFB1	# Offset 0x10
+	.quad	.LFE1
+	.quad	0
+	.quad	0
+	.section	.debug_line,"",@progbits
+.Ldebug_line0:
+	.section	.debug_str,"MS",@progbits,1
+.LASF1:
+	.string	"gdb.arch/amd64-entry-value-paramref.cc"
+.LASF2:
+	.string	""
+.LASF0:
+	.string	"GNU C++ 4.8.2 20131212 (Red Hat 4.8.2-7) -mtune=generic -march=x86-64 -g -O2"
+.LASF3:
+	.string	"main"
+	.ident	"GCC: (GNU) 4.8.2 20131212 (Red Hat 4.8.2-7)"
+	.section	.note.GNU-stack,"",@progbits
diff --git a/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.cc b/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.cc
new file mode 100644
index 0000000..aa473a3
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.cc
@@ -0,0 +1,33 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2014 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+volatile int vv, *p;
+
+static __attribute__((noinline)) int
+bar (int &ref)
+{
+  vv++; /* break-here */
+  p = &ref;
+  return ref;
+}
+
+int
+main (void)
+{
+  int var = 10;
+  return bar (var);
+}
diff --git a/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.exp b/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.exp
new file mode 100644
index 0000000..f06247d
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.exp
@@ -0,0 +1,35 @@
+# Copyright (C) 2014 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile .S .cc
+
+if { ![istarget x86_64-*-* ] || ![is_lp64_target] } {
+    verbose "Skipping amd64-entry-value-paramref."
+    return
+}
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} "c++"] } {
+    return -1
+}
+
+if ![runto_main] {
+    return -1
+}
+
+set srcfile $srcfile2
+gdb_breakpoint [gdb_get_line_number "break-here"]
+
+gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+gdb_test "frame" {bar \(ref=@0x[0-9a-f]+: 10, ref@entry=@0x[0-9a-f]+: <optimized out>\) at .*}
diff --git a/gdb/testsuite/gdb.arch/amd64-optimout-repeat.S b/gdb/testsuite/gdb.arch/amd64-optimout-repeat.S
new file mode 100755
index 0000000..2f8f4d2
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-optimout-repeat.S
@@ -0,0 +1,297 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2012-2014 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* This file is compiled from gdb.arch/amd64-entry-value-param.c
+   using -g -dA -S -O2.  */
+
+	.file	"amd64-optimout-repeat.c"
+	.text
+.Ltext0:
+	.section	.text.unlikely,"ax",@progbits
+.LCOLDB0:
+	.section	.text.startup,"ax",@progbits
+.LHOTB0:
+	.p2align 4,,15
+	.section	.text.unlikely
+.Ltext_cold0:
+	.section	.text.startup
+	.globl	main
+	.type	main, @function
+main:
+.LFB0:
+	.file 1 "gdb.arch/amd64-optimout-repeat.c"
+	# gdb.arch/amd64-optimout-repeat.c:20
+	.loc 1 20 0
+	.cfi_startproc
+# BLOCK 2 freq:10000 seq:0
+# PRED: ENTRY [100.0%]  (FALLTHRU)
+.LVL0:
+	# gdb.arch/amd64-optimout-repeat.c:29
+	.loc 1 29 0
+	xorl	%eax, %eax
+# SUCC: EXIT [100.0%] 
+	ret
+	.cfi_endproc
+.LFE0:
+	.size	main, .-main
+	.section	.text.unlikely
+.LCOLDE0:
+	.section	.text.startup
+.LHOTE0:
+	.text
+.Letext0:
+	.section	.text.unlikely
+.Letext_cold0:
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+	.long	0x97	# Length of Compilation Unit Info
+	.value	0x4	# DWARF version number
+	.long	.Ldebug_abbrev0	# Offset Into Abbrev. Section
+	.byte	0x8	# Pointer Size (in bytes)
+	.uleb128 0x1	# (DIE (0xb) DW_TAG_compile_unit)
+	.long	.LASF1	# DW_AT_producer: "GNU C 4.9.1 20140709 (prerelease) -mtune=generic -march=x86-64 -g -O2"
+	.byte	0x1	# DW_AT_language
+	.long	.LASF2	# DW_AT_name: "gdb.arch/amd64-optimout-repeat.c"
+	.long	.LASF3	# DW_AT_comp_dir: ""
+	.long	.Ldebug_ranges0+0	# DW_AT_ranges
+	.quad	0	# DW_AT_low_pc
+	.long	.Ldebug_line0	# DW_AT_stmt_list
+	.uleb128 0x2	# (DIE (0x29) DW_TAG_subprogram)
+			# DW_AT_external
+	.long	.LASF4	# DW_AT_name: "main"
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-optimout-repeat.c)
+	.byte	0x13	# DW_AT_decl_line
+			# DW_AT_prototyped
+	.long	0x7c	# DW_AT_type
+	.quad	.LFB0	# DW_AT_low_pc
+	.quad	.LFE0-.LFB0	# DW_AT_high_pc
+	.uleb128 0x1	# DW_AT_frame_base
+	.byte	0x9c	# DW_OP_call_frame_cfa
+			# DW_AT_GNU_all_call_sites
+	.long	0x7c	# DW_AT_sibling
+	.uleb128 0x3	# (DIE (0x4a) DW_TAG_structure_type)
+	.value	0x404	# DW_AT_byte_size
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-optimout-repeat.c)
+	.byte	0x15	# DW_AT_decl_line
+	.long	0x6a	# DW_AT_sibling
+	.uleb128 0x4	# (DIE (0x53) DW_TAG_member)
+	.ascii "i\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-optimout-repeat.c)
+	.byte	0x17	# DW_AT_decl_line
+	.long	0x7c	# DW_AT_type
+	.byte	0	# DW_AT_data_member_location
+	.uleb128 0x4	# (DIE (0x5d) DW_TAG_member)
+	.ascii "xxx\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-optimout-repeat.c)
+	.byte	0x18	# DW_AT_decl_line
+	.long	0x83	# DW_AT_type
+	.byte	0x4	# DW_AT_data_member_location
+	.byte	0	# end of children of DIE 0x4a
+	.uleb128 0x5	# (DIE (0x6a) DW_TAG_variable)
+	.ascii "v\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-optimout-repeat.c)
+	.byte	0x1a	# DW_AT_decl_line
+	.long	0x4a	# DW_AT_type
+	.uleb128 0x7	# DW_AT_location
+	.byte	0x30	# DW_OP_lit0
+	.byte	0x9f	# DW_OP_stack_value
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x4
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x400
+	.byte	0	# end of children of DIE 0x29
+	.uleb128 0x6	# (DIE (0x7c) DW_TAG_base_type)
+	.byte	0x4	# DW_AT_byte_size
+	.byte	0x5	# DW_AT_encoding
+	.ascii "int\0"	# DW_AT_name
+	.uleb128 0x7	# (DIE (0x83) DW_TAG_array_type)
+	.long	0x7c	# DW_AT_type
+	.long	0x93	# DW_AT_sibling
+	.uleb128 0x8	# (DIE (0x8c) DW_TAG_subrange_type)
+	.long	0x93	# DW_AT_type
+	.byte	0xff	# DW_AT_upper_bound
+	.byte	0	# end of children of DIE 0x83
+	.uleb128 0x9	# (DIE (0x93) DW_TAG_base_type)
+	.byte	0x8	# DW_AT_byte_size
+	.byte	0x7	# DW_AT_encoding
+	.long	.LASF0	# DW_AT_name: "sizetype"
+	.byte	0	# end of children of DIE 0xb
+	.section	.debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1	# (abbrev code)
+	.uleb128 0x11	# (TAG: DW_TAG_compile_unit)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x25	# (DW_AT_producer)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x13	# (DW_AT_language)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x1b	# (DW_AT_comp_dir)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x55	# (DW_AT_ranges)
+	.uleb128 0x17	# (DW_FORM_sec_offset)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x10	# (DW_AT_stmt_list)
+	.uleb128 0x17	# (DW_FORM_sec_offset)
+	.byte	0
+	.byte	0
+	.uleb128 0x2	# (abbrev code)
+	.uleb128 0x2e	# (TAG: DW_TAG_subprogram)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x3f	# (DW_AT_external)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x27	# (DW_AT_prototyped)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x12	# (DW_AT_high_pc)
+	.uleb128 0x7	# (DW_FORM_data8)
+	.uleb128 0x40	# (DW_AT_frame_base)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.uleb128 0x2117	# (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x1	# (DW_AT_sibling)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x3	# (abbrev code)
+	.uleb128 0x13	# (TAG: DW_TAG_structure_type)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0x5	# (DW_FORM_data2)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x1	# (DW_AT_sibling)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x4	# (abbrev code)
+	.uleb128 0xd	# (TAG: DW_TAG_member)
+	.byte	0	# DW_children_no
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x38	# (DW_AT_data_member_location)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.byte	0
+	.byte	0
+	.uleb128 0x5	# (abbrev code)
+	.uleb128 0x34	# (TAG: DW_TAG_variable)
+	.byte	0	# DW_children_no
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x2	# (DW_AT_location)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.byte	0
+	.byte	0
+	.uleb128 0x6	# (abbrev code)
+	.uleb128 0x24	# (TAG: DW_TAG_base_type)
+	.byte	0	# DW_children_no
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3e	# (DW_AT_encoding)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.byte	0
+	.byte	0
+	.uleb128 0x7	# (abbrev code)
+	.uleb128 0x1	# (TAG: DW_TAG_array_type)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x1	# (DW_AT_sibling)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x8	# (abbrev code)
+	.uleb128 0x21	# (TAG: DW_TAG_subrange_type)
+	.byte	0	# DW_children_no
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x2f	# (DW_AT_upper_bound)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.byte	0
+	.byte	0
+	.uleb128 0x9	# (abbrev code)
+	.uleb128 0x24	# (TAG: DW_TAG_base_type)
+	.byte	0	# DW_children_no
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3e	# (DW_AT_encoding)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.byte	0
+	.byte	0
+	.byte	0
+	.section	.debug_aranges,"",@progbits
+	.long	0x2c	# Length of Address Ranges Info
+	.value	0x2	# DWARF Version
+	.long	.Ldebug_info0	# Offset of Compilation Unit Info
+	.byte	0x8	# Size of Address
+	.byte	0	# Size of Segment Descriptor
+	.value	0	# Pad to 16 byte boundary
+	.value	0
+	.quad	.LFB0	# Address
+	.quad	.LFE0-.LFB0	# Length
+	.quad	0
+	.quad	0
+	.section	.debug_ranges,"",@progbits
+.Ldebug_ranges0:
+	.quad	.LFB0	# Offset 0
+	.quad	.LFE0
+	.quad	0
+	.quad	0
+	.section	.debug_line,"",@progbits
+.Ldebug_line0:
+	.section	.debug_str,"MS",@progbits,1
+.LASF0:
+	.string	"sizetype"
+.LASF2:
+	.string	"gdb.arch/amd64-optimout-repeat.c"
+.LASF1:
+	.string	"GNU C 4.9.1 20140709 (prerelease) -mtune=generic -march=x86-64 -g -O2"
+.LASF3:
+	.string	""
+.LASF4:
+	.string	"main"
+	.ident	"GCC: (GNU) 4.9.1 20140709 (prerelease)"
+	.section	.note.GNU-stack,"",@progbits
diff --git a/gdb/testsuite/gdb.arch/amd64-optimout-repeat.c b/gdb/testsuite/gdb.arch/amd64-optimout-repeat.c
new file mode 100644
index 0000000..a32b6de
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-optimout-repeat.c
@@ -0,0 +1,29 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2014 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+int
+main (void)
+{
+  struct
+    {
+      int i;
+      int xxx[0x100];
+    }
+  v = { 0 };
+
+  return v.i;
+}
diff --git a/gdb/testsuite/gdb.arch/amd64-optimout-repeat.exp b/gdb/testsuite/gdb.arch/amd64-optimout-repeat.exp
new file mode 100644
index 0000000..f3c93a4
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-optimout-repeat.exp
@@ -0,0 +1,36 @@
+# Copyright (C) 2014 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile .S .c
+set opts {}
+
+if [info exists COMPILE] {
+    # make check RUNTESTFLAGS="gdb.arch/amd64-optimout-repeat.exp COMPILE=1"
+    set srcfile ${srcfile2}
+    lappend opts debug optimize=-O2
+} elseif { ![istarget x86_64-*-* ] || ![is_lp64_target] } {
+    verbose "Skipping amd64-optimout-repeat."
+    return
+}
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} $opts] } {
+    return -1
+}
+
+if ![runto_main] {
+    return -1
+}
+
+gdb_test "print v" { = {i = 0, xxx = {<optimized out> <repeats 256 times>}}}

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patchv2] Fix crash on optimized-out entry data values
  2014-07-09 10:33 [patchv2] Fix crash on optimized-out entry data values Jan Kratochvil
@ 2014-07-09 11:52 ` Pedro Alves
  2014-07-09 15:31   ` Jan Kratochvil
  0 siblings, 1 reply; 28+ messages in thread
From: Pedro Alves @ 2014-07-09 11:52 UTC (permalink / raw)
  To: Jan Kratochvil, gdb-patches

On 07/09/2014 11:33 AM, Jan Kratochvil wrote:
> Hi,
> 
> former post of this fix was for:
> 	[patch+7.8] Fix crash on optimized-out entry data values
> 	https://sourceware.org/ml/gdb-patches/2014-06/msg00797.html
> =
> 	https://bugzilla.redhat.com/show_bug.cgi?id=1111910
> 	this can happen for real world -O2 -g executables:
> 	#9  0x0000003b6e0998b2 in wxEntry (argc=@0x7fffffffd86c: 1,
> 	    argc@entry=@0x7fffffffd86c: <optimized out>,
> 					^^^^^^^^^^^^^^^
> 	    argv=<optimized out>) at src/common/init.cpp:460
> 	GDB did crash in such case.
> 
> But the fix was wrong/regressing as shown here:
> 	https://bugzilla.redhat.com/show_bug.cgi?id=1117192
> 	https://bugzilla.redhat.com/attachment.cgi?id=916298 (at the bottom)
> 
> Here is a new fix, also with a new testcase reproducing crash of the wrong fix
> above.
> 
> No regressions on {x86_64,x86_64-m32,i686}-fedorarawhide-linux-gnu.
> 
> 
> Jan
> 
> 
> optimfix2.patch
> 
> 
> gdb/
> 2014-07-09  Jan Kratochvil  <jan.kratochvil@redhat.com>
> 
> 	* value.c (struct value): Extend the comment for fields optimized_out
> 	and unavailable.
> 	(value_available_contents_bits_eq): Handle OPTIMIZED_OUT values with
> 	empty UNAVAILABLE as special cases.
> 
> gdb/testsuite/
> 2014-07-09  Jan Kratochvil  <jan.kratochvil@redhat.com>
> 
> 	* gdb.arch/amd64-entry-value-paramref.S: New file.
> 	* gdb.arch/amd64-entry-value-paramref.cc: New file.
> 	* gdb.arch/amd64-entry-value-paramref.exp: New file.
> 	* gdb.arch/amd64-optimout-repeat.S: New file.
> 	* gdb.arch/amd64-optimout-repeat.c: New file.
> 	* gdb.arch/amd64-optimout-repeat.exp: New file.
> 
> diff --git a/gdb/value.c b/gdb/value.c
> index 557056f..4b7495e 100644
> --- a/gdb/value.c
> +++ b/gdb/value.c
> @@ -198,12 +198,13 @@ struct value
>    unsigned int lazy : 1;
>  
>    /* If nonzero, this is the value of a variable that does not
> -     actually exist in the program.  If nonzero, and LVAL is
> +     actually fully 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.  */
> +     error strings.  It is true also for only partially optimized
> +     out variables - see the 'unavailable' field below.  */
>    unsigned int optimized_out : 1;
>  
>    /* If value is a variable, is it initialized or not.  */
> @@ -334,7 +335,10 @@ struct value
>       valid if lazy is nonzero.  */
>    gdb_byte *contents;
>  
> -  /* Unavailable ranges in CONTENTS.  We mark unavailable ranges,
> +  /* If OPTIMIZED_OUT is false then UNAVAILABLE must be VEC_empty
> +     (not necessarily NULL).  

Hmm, why?  We can collect only part of a non-optimized out value.
What am I missing?  Does this manage to somehow pass the tests
under gdb.trace/ (against --target_board=native-gdbserver) ?

> If OPTIMIZED_OUT is true then VEC_empty
> +     UNAVAILABLE means the whole value range.  Otherwise it specifies
> +     unavailable ranges in CONTENTS.  We mark unavailable ranges,
>       rather than available, since the common and default case is for a
>       value to be available.  This is filled in at value read time.  The
>       unavailable ranges are tracked in bits.  */
> @@ -701,6 +705,15 @@ value_available_contents_bits_eq (const struct value *val1, int offset1,
>    /* See function description in value.h.  */
>    gdb_assert (!val1->lazy && !val2->lazy);
>  
> +  gdb_assert (val1->optimized_out || VEC_empty (range_s, val1->unavailable));
> +  gdb_assert (val2->optimized_out || VEC_empty (range_s, val2->unavailable));

-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patchv2] Fix crash on optimized-out entry data values
  2014-07-09 11:52 ` Pedro Alves
@ 2014-07-09 15:31   ` Jan Kratochvil
  2014-07-11 16:07     ` [patchv3] " Jan Kratochvil
  2014-07-14 18:47     ` [PATCH] Handle partially optimized out values similarly to unavailable values (Re: [patchv2] Fix crash on optimized-out entry data values) Pedro Alves
  0 siblings, 2 replies; 28+ messages in thread
From: Jan Kratochvil @ 2014-07-09 15:31 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On Wed, 09 Jul 2014 13:52:00 +0200, Pedro Alves wrote:
> On 07/09/2014 11:33 AM, Jan Kratochvil wrote:
> > --- a/gdb/value.c
> > +++ b/gdb/value.c
> > @@ -198,12 +198,13 @@ struct value
> >    unsigned int lazy : 1;
> >  
> >    /* If nonzero, this is the value of a variable that does not
> > -     actually exist in the program.  If nonzero, and LVAL is
> > +     actually fully 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.  */
> > +     error strings.  It is true also for only partially optimized
> > +     out variables - see the 'unavailable' field below.  */
> >    unsigned int optimized_out : 1;
> >  
> >    /* If value is a variable, is it initialized or not.  */
> > @@ -334,7 +335,10 @@ struct value
> >       valid if lazy is nonzero.  */
> >    gdb_byte *contents;
> >  
> > -  /* Unavailable ranges in CONTENTS.  We mark unavailable ranges,
> > +  /* If OPTIMIZED_OUT is false then UNAVAILABLE must be VEC_empty
> > +     (not necessarily NULL).  
> 
> Hmm, why?  We can collect only part of a non-optimized out value.
> What am I missing?

I miss some documentation how these availability fields interact together.
value_available_contents_bits_eq is written according to the struct value
comments but they do not correspond to the real world struct value data.

'unavailable' suggests that optimized out variable should have it set to the
full range of the variable.  But struct value with OPTIMIZED_OUT field set
still has UNAVAILABLE empty. As the variable is optimized out the CONTENTS is
also NULL - this causes the crash reproduced by
'gdb.arch/amd64-entry-value-paramref.exp'.

There are also check_validity and check_any_valid methods but how they are
related to the 'unavailable' data field is also not documented.

This patch was my second attempt to fix/document the availability stuff, it
would be useful to suggest how it is designed.


> Does this manage to somehow pass the tests
> under gdb.trace/ (against --target_board=native-gdbserver) ?

You are right, this patch regresses during gdbserver mode.


> > If OPTIMIZED_OUT is true then VEC_empty
> > +     UNAVAILABLE means the whole value range.  Otherwise it specifies
> > +     unavailable ranges in CONTENTS.  We mark unavailable ranges,
> >       rather than available, since the common and default case is for a
> >       value to be available.  This is filled in at value read time.  The
> >       unavailable ranges are tracked in bits.  */
> > @@ -701,6 +705,15 @@ value_available_contents_bits_eq (const struct value *val1, int offset1,
> >    /* See function description in value.h.  */
> >    gdb_assert (!val1->lazy && !val2->lazy);
> >  
> > +  gdb_assert (val1->optimized_out || VEC_empty (range_s, val1->unavailable));
> > +  gdb_assert (val2->optimized_out || VEC_empty (range_s, val2->unavailable));


Thanks,
Jan

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [patchv3] Fix crash on optimized-out entry data values
  2014-07-09 15:31   ` Jan Kratochvil
@ 2014-07-11 16:07     ` Jan Kratochvil
  2014-07-14  7:02       ` Yao Qi
  2014-07-14 18:12       ` Pedro Alves
  2014-07-14 18:47     ` [PATCH] Handle partially optimized out values similarly to unavailable values (Re: [patchv2] Fix crash on optimized-out entry data values) Pedro Alves
  1 sibling, 2 replies; 28+ messages in thread
From: Jan Kratochvil @ 2014-07-11 16:07 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 2068 bytes --]

On Wed, 09 Jul 2014 17:31:21 +0200, Jan Kratochvil wrote:
> On Wed, 09 Jul 2014 13:52:00 +0200, Pedro Alves wrote:
> > On 07/09/2014 11:33 AM, Jan Kratochvil wrote:
> > > --- a/gdb/value.c
> > > +++ b/gdb/value.c
> > > @@ -198,12 +198,13 @@ struct value
> > >    unsigned int lazy : 1;
> > >  
> > >    /* If nonzero, this is the value of a variable that does not
> > > -     actually exist in the program.  If nonzero, and LVAL is
> > > +     actually fully 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.  */
> > > +     error strings.  It is true also for only partially optimized
> > > +     out variables - see the 'unavailable' field below.  */
> > >    unsigned int optimized_out : 1;
> > >  
> > >    /* If value is a variable, is it initialized or not.  */
> > > @@ -334,7 +335,10 @@ struct value
> > >       valid if lazy is nonzero.  */
> > >    gdb_byte *contents;
> > >  
> > > -  /* Unavailable ranges in CONTENTS.  We mark unavailable ranges,
> > > +  /* If OPTIMIZED_OUT is false then UNAVAILABLE must be VEC_empty
> > > +     (not necessarily NULL).  
> > 
> > Hmm, why?  We can collect only part of a non-optimized out value.
> > What am I missing?
> 
> I miss some documentation how these availability fields interact together.

From a comment in mail
	Message-Id: <201102071427.55970.pedro@codesourcery.com>
	We give preference to printing <optimized out> rather
	than <unavailable>, since if a value had been optimized out
	at compile time, it can never be collected at run-time.

it seems it is just reversed, that 'unavailable' can exist only for
!optimized_out and it cannot exist for for optimized_out values.


> You are right, this patch regresses during gdbserver mode.

It PASSes now even in gdbserver mode.


Thanks,
Jan

[-- Attachment #2: optimfix3.patch --]
[-- Type: text/plain, Size: 31821 bytes --]

gdb/
2014-07-09  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* value.c (struct value): Extend the comment for fields optimized_out
	and unavailable.
	(value_available_contents_bits_eq): Handle OPTIMIZED_OUT values as
	special cases.

gdb/testsuite/
2014-07-09  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* gdb.arch/amd64-entry-value-paramref.S: New file.
	* gdb.arch/amd64-entry-value-paramref.cc: New file.
	* gdb.arch/amd64-entry-value-paramref.exp: New file.
	* gdb.arch/amd64-optimout-repeat.S: New file.
	* gdb.arch/amd64-optimout-repeat.c: New file.
	* gdb.arch/amd64-optimout-repeat.exp: New file.

diff --git a/gdb/value.c b/gdb/value.c
index 557056f..c017c75 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -198,12 +198,14 @@ struct value
   unsigned int lazy : 1;
 
   /* If nonzero, this is the value of a variable that does not
-     actually exist in the program.  If nonzero, and LVAL is
+     actually exist in the program at all.  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.  */
+     error strings.  When it is zero it still maybe only partially
+     available (equally partially optimized out) - see the
+     'unavailable' field below.  */
   unsigned int optimized_out : 1;
 
   /* If value is a variable, is it initialized or not.  */
@@ -334,7 +336,9 @@ struct value
      valid if lazy is nonzero.  */
   gdb_byte *contents;
 
-  /* Unavailable ranges in CONTENTS.  We mark unavailable ranges,
+  /* If OPTIMIZED_OUT is nonzero then UNAVAILABLE must be VEC_empty
+     (not necessarily NULL).  Otherwise it specifies
+     unavailable ranges in CONTENTS.  We mark unavailable ranges,
      rather than available, since the common and default case is for a
      value to be available.  This is filled in at value read time.  The
      unavailable ranges are tracked in bits.  */
@@ -701,6 +705,13 @@ value_available_contents_bits_eq (const struct value *val1, int offset1,
   /* See function description in value.h.  */
   gdb_assert (!val1->lazy && !val2->lazy);
 
+  gdb_assert (!val1->optimized_out || VEC_empty (range_s, val1->unavailable));
+  gdb_assert (!val2->optimized_out || VEC_empty (range_s, val2->unavailable));
+  if (val1->optimized_out != val2->optimized_out)
+    return 0;
+  if (val1->optimized_out && val2->optimized_out)
+    return 1;
+
   while (length > 0)
     {
       range_s *r1, *r2;
diff --git a/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.S b/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.S
new file mode 100644
index 0000000..a1e9d0a
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.S
@@ -0,0 +1,459 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2014 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* This file is compiled from gdb.arch/amd64-entry-value-paramref.cc
+   using -g -dA -S -O2.
+   Additionally it has been patched.  */
+
+	.file	"amd64-entry-value-paramref.cc"
+	.text
+.Ltext0:
+	.p2align 4,,15
+	.type	_ZL3barRi.constprop.0, @function
+_ZL3barRi.constprop.0:
+.LFB2:
+	.file 1 "gdb.arch/amd64-entry-value-paramref.cc"
+	# gdb.arch/amd64-entry-value-paramref.cc:21
+	.loc 1 21 0
+	.cfi_startproc
+.LVL0:
+# BLOCK 2 freq:10000 seq:0
+# PRED: ENTRY [100.0%]  (FALLTHRU)
+	# gdb.arch/amd64-entry-value-paramref.cc:23
+	.loc 1 23 0
+	movl	vv(%rip), %eax
+	# gdb.arch/amd64-entry-value-paramref.cc:24
+	.loc 1 24 0
+	movq	%rdi, p(%rip)
+	# gdb.arch/amd64-entry-value-paramref.cc:23
+	.loc 1 23 0
+	addl	$1, %eax
+	movl	%eax, vv(%rip)
+	# gdb.arch/amd64-entry-value-paramref.cc:25
+	.loc 1 25 0
+	movl	(%rdi), %eax
+# SUCC: EXIT [100.0%] 
+	# gdb.arch/amd64-entry-value-paramref.cc:26
+	.loc 1 26 0
+	ret
+	.cfi_endproc
+.LFE2:
+	.size	_ZL3barRi.constprop.0, .-_ZL3barRi.constprop.0
+	.section	.text.startup,"ax",@progbits
+	.p2align 4,,15
+	.globl	main
+	.type	main, @function
+main:
+.LFB1:
+	# gdb.arch/amd64-entry-value-paramref.cc:30
+	.loc 1 30 0
+	.cfi_startproc
+# BLOCK 2 freq:10000 seq:0
+# PRED: ENTRY [100.0%]  (FALLTHRU)
+	subq	$16, %rsp
+	.cfi_def_cfa_offset 24
+.LBB2:
+	# gdb.arch/amd64-entry-value-paramref.cc:32
+	.loc 1 32 0
+	leaq	12(%rsp), %rdi
+	# gdb.arch/amd64-entry-value-paramref.cc:31
+	.loc 1 31 0
+	movl	$10, 12(%rsp)
+	# gdb.arch/amd64-entry-value-paramref.cc:32
+	.loc 1 32 0
+	call	_ZL3barRi.constprop.0
+.LVL1:
+.LBE2:
+	# gdb.arch/amd64-entry-value-paramref.cc:33
+	.loc 1 33 0
+	addq	$16, %rsp
+	.cfi_def_cfa_offset 8
+# SUCC: EXIT [100.0%] 
+	ret
+	.cfi_endproc
+.LFE1:
+	.size	main, .-main
+	.globl	p
+	.bss
+	.align 8
+	.type	p, @object
+	.size	p, 8
+p:
+	.zero	8
+	.globl	vv
+	.align 4
+	.type	vv, @object
+	.size	vv, 4
+vv:
+	.zero	4
+	.text
+.Letext0:
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+	.long	.Linfo_end - .Linfo_start	# Length of Compilation Unit Info
+.Linfo_start:
+	.value	0x4	# DWARF version number
+	.long	.Ldebug_abbrev0	# Offset Into Abbrev. Section
+	.byte	0x8	# Pointer Size (in bytes)
+	.uleb128 0x1	# (DIE (0xb) DW_TAG_compile_unit)
+	.long	.LASF0	# DW_AT_producer: "GNU C++ 4.8.2 20131212 (Red Hat 4.8.2-7) -mtune=generic -march=x86-64 -g -O2"
+	.byte	0x4	# DW_AT_language
+	.long	.LASF1	# DW_AT_name: "gdb.arch/amd64-entry-value-paramref.cc"
+	.long	.LASF2	# DW_AT_comp_dir: ""
+	.long	.Ldebug_ranges0+0	# DW_AT_ranges
+	.quad	0	# DW_AT_low_pc
+	.long	.Ldebug_line0	# DW_AT_stmt_list
+DIE29:	.uleb128 0x2	# (DIE (0x29) DW_TAG_subprogram)
+	.ascii "bar\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-entry-value-paramref.cc)
+	.byte	0x15	# DW_AT_decl_line
+	.long	DIE45	# DW_AT_type
+	.byte	0x1	# DW_AT_inline
+DIE39:	.uleb128 0x3	# (DIE (0x39) DW_TAG_formal_parameter)
+	.ascii "ref\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-entry-value-paramref.cc)
+	.byte	0x15	# DW_AT_decl_line
+	.long	DIE4c	# DW_AT_type
+	.byte	0	# end of children of DIE 0x29
+DIE45:	.uleb128 0x4	# (DIE (0x45) DW_TAG_base_type)
+	.byte	0x4	# DW_AT_byte_size
+	.byte	0x5	# DW_AT_encoding
+	.ascii "int\0"	# DW_AT_name
+DIE4c:	.uleb128 0x5	# (DIE (0x4c) DW_TAG_const_type)
+	.long	DIE51	# DW_AT_type
+DIE51:	.uleb128 0x6	# (DIE (0x51) DW_TAG_reference_type)
+	.byte	0x8	# DW_AT_byte_size
+	.long	DIE45	# DW_AT_type
+DIE57:	.uleb128 0x7	# (DIE (0x57) DW_TAG_subprogram)
+	.long	DIE29	# DW_AT_abstract_origin
+	.quad	.LFB2	# DW_AT_low_pc
+	.quad	.LFE2-.LFB2	# DW_AT_high_pc
+	.uleb128 0x1	# DW_AT_frame_base
+	.byte	0x9c	# DW_OP_call_frame_cfa
+			# DW_AT_GNU_all_call_sites
+DIE72:	.uleb128 0x8	# (DIE (0x72) DW_TAG_formal_parameter)
+	.long	DIE39	# DW_AT_abstract_origin
+	.uleb128 0x1	# DW_AT_location
+	.byte	0x55	# DW_OP_reg5
+	.byte	0	# end of children of DIE 0x57
+DIE7a:	.uleb128 0x9	# (DIE (0x7a) DW_TAG_subprogram)
+			# DW_AT_external
+	.long	.LASF3	# DW_AT_name: "main"
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-entry-value-paramref.cc)
+	.byte	0x1d	# DW_AT_decl_line
+	.long	DIE45	# DW_AT_type
+	.quad	.LFB1	# DW_AT_low_pc
+	.quad	.LFE1-.LFB1	# DW_AT_high_pc
+	.uleb128 0x1	# DW_AT_frame_base
+	.byte	0x9c	# DW_OP_call_frame_cfa
+			# DW_AT_GNU_all_call_sites
+DIE9b:	.uleb128 0xa	# (DIE (0x9b) DW_TAG_lexical_block)
+	.quad	.LBB2	# DW_AT_low_pc
+	.quad	.LBE2-.LBB2	# DW_AT_high_pc
+DIEac:	.uleb128 0xb	# (DIE (0xac) DW_TAG_variable)
+	.ascii "var\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-entry-value-paramref.cc)
+	.byte	0x1f	# DW_AT_decl_line
+	.long	DIE45	# DW_AT_type
+	.uleb128 0x2	# DW_AT_location
+	.byte	0x91	# DW_OP_fbreg
+	.sleb128 -12
+DIEba:	.uleb128 0xc	# (DIE (0xba) DW_TAG_GNU_call_site)
+	.quad	.LVL1	# DW_AT_low_pc
+	.long	DIE57	# DW_AT_abstract_origin
+DIEc7:	.uleb128 0xd	# (DIE (0xc7) DW_TAG_GNU_call_site_parameter)
+	.uleb128 0x1	# DW_AT_location
+	.byte	0x55	# DW_OP_reg5
+	.uleb128 0x2	# DW_AT_GNU_call_site_value
+	.byte	0x91	# DW_OP_fbreg
+	.sleb128 -12
+#if 0
+	.uleb128 0x1	# DW_AT_GNU_call_site_data_value
+	.byte	0x3a	# DW_OP_lit10
+#else
+	.uleb128 1f - 2f	# DW_AT_GNU_call_site_data_value
+2:
+	.byte	0xf3	# DW_OP_GNU_entry_value
+	.uleb128 1f - 3f
+3:
+	.byte	0x55	# DW_OP_reg5
+1:
+#endif
+	.byte	0	# end of children of DIE 0xba
+	.byte	0	# end of children of DIE 0x9b
+	.byte	0	# end of children of DIE 0x7a
+DIEd2:	.uleb128 0xe	# (DIE (0xd2) DW_TAG_variable)
+	.ascii "vv\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-entry-value-paramref.cc)
+	.byte	0x12	# DW_AT_decl_line
+	.long	DIEe6	# DW_AT_type
+			# DW_AT_external
+	.uleb128 0x9	# DW_AT_location
+	.byte	0x3	# DW_OP_addr
+	.quad	vv
+DIEe6:	.uleb128 0xf	# (DIE (0xe6) DW_TAG_volatile_type)
+	.long	DIE45	# DW_AT_type
+DIEeb:	.uleb128 0xe	# (DIE (0xeb) DW_TAG_variable)
+	.ascii "p\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-entry-value-paramref.cc)
+	.byte	0x12	# DW_AT_decl_line
+	.long	DIEfe	# DW_AT_type
+			# DW_AT_external
+	.uleb128 0x9	# DW_AT_location
+	.byte	0x3	# DW_OP_addr
+	.quad	p
+DIEfe:	.uleb128 0x10	# (DIE (0xfe) DW_TAG_pointer_type)
+	.byte	0x8	# DW_AT_byte_size
+	.long	DIEe6	# DW_AT_type
+	.byte	0	# end of children of DIE 0xb
+.Linfo_end:
+	.section	.debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1	# (abbrev code)
+	.uleb128 0x11	# (TAG: DW_TAG_compile_unit)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x25	# (DW_AT_producer)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x13	# (DW_AT_language)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x1b	# (DW_AT_comp_dir)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x55	# (DW_AT_ranges)
+	.uleb128 0x17	# (DW_FORM_sec_offset)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x10	# (DW_AT_stmt_list)
+	.uleb128 0x17	# (DW_FORM_sec_offset)
+	.byte	0
+	.byte	0
+	.uleb128 0x2	# (abbrev code)
+	.uleb128 0x2e	# (TAG: DW_TAG_subprogram)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x20	# (DW_AT_inline)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.byte	0
+	.byte	0
+	.uleb128 0x3	# (abbrev code)
+	.uleb128 0x5	# (TAG: DW_TAG_formal_parameter)
+	.byte	0	# DW_children_no
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x4	# (abbrev code)
+	.uleb128 0x24	# (TAG: DW_TAG_base_type)
+	.byte	0	# DW_children_no
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3e	# (DW_AT_encoding)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.byte	0
+	.byte	0
+	.uleb128 0x5	# (abbrev code)
+	.uleb128 0x26	# (TAG: DW_TAG_const_type)
+	.byte	0	# DW_children_no
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x6	# (abbrev code)
+	.uleb128 0x10	# (TAG: DW_TAG_reference_type)
+	.byte	0	# DW_children_no
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x7	# (abbrev code)
+	.uleb128 0x2e	# (TAG: DW_TAG_subprogram)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x31	# (DW_AT_abstract_origin)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x12	# (DW_AT_high_pc)
+	.uleb128 0x7	# (DW_FORM_data8)
+	.uleb128 0x40	# (DW_AT_frame_base)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.uleb128 0x2117	# (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.byte	0
+	.byte	0
+	.uleb128 0x8	# (abbrev code)
+	.uleb128 0x5	# (TAG: DW_TAG_formal_parameter)
+	.byte	0	# DW_children_no
+	.uleb128 0x31	# (DW_AT_abstract_origin)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x2	# (DW_AT_location)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.byte	0
+	.byte	0
+	.uleb128 0x9	# (abbrev code)
+	.uleb128 0x2e	# (TAG: DW_TAG_subprogram)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x3f	# (DW_AT_external)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x12	# (DW_AT_high_pc)
+	.uleb128 0x7	# (DW_FORM_data8)
+	.uleb128 0x40	# (DW_AT_frame_base)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.uleb128 0x2117	# (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.byte	0
+	.byte	0
+	.uleb128 0xa	# (abbrev code)
+	.uleb128 0xb	# (TAG: DW_TAG_lexical_block)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x12	# (DW_AT_high_pc)
+	.uleb128 0x7	# (DW_FORM_data8)
+	.byte	0
+	.byte	0
+	.uleb128 0xb	# (abbrev code)
+	.uleb128 0x34	# (TAG: DW_TAG_variable)
+	.byte	0	# DW_children_no
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x2	# (DW_AT_location)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.byte	0
+	.byte	0
+	.uleb128 0xc	# (abbrev code)
+	.uleb128 0x4109	# (TAG: DW_TAG_GNU_call_site)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x31	# (DW_AT_abstract_origin)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0xd	# (abbrev code)
+	.uleb128 0x410a	# (TAG: DW_TAG_GNU_call_site_parameter)
+	.byte	0	# DW_children_no
+	.uleb128 0x2	# (DW_AT_location)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.uleb128 0x2111	# (DW_AT_GNU_call_site_value)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.uleb128 0x2112	# (DW_AT_GNU_call_site_data_value)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.byte	0
+	.byte	0
+	.uleb128 0xe	# (abbrev code)
+	.uleb128 0x34	# (TAG: DW_TAG_variable)
+	.byte	0	# DW_children_no
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x3f	# (DW_AT_external)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x2	# (DW_AT_location)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.byte	0
+	.byte	0
+	.uleb128 0xf	# (abbrev code)
+	.uleb128 0x35	# (TAG: DW_TAG_volatile_type)
+	.byte	0	# DW_children_no
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x10	# (abbrev code)
+	.uleb128 0xf	# (TAG: DW_TAG_pointer_type)
+	.byte	0	# DW_children_no
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.byte	0
+	.section	.debug_aranges,"",@progbits
+	.long	0x3c	# Length of Address Ranges Info
+	.value	0x2	# DWARF Version
+	.long	.Ldebug_info0	# Offset of Compilation Unit Info
+	.byte	0x8	# Size of Address
+	.byte	0	# Size of Segment Descriptor
+	.value	0	# Pad to 16 byte boundary
+	.value	0
+	.quad	.Ltext0	# Address
+	.quad	.Letext0-.Ltext0	# Length
+	.quad	.LFB1	# Address
+	.quad	.LFE1-.LFB1	# Length
+	.quad	0
+	.quad	0
+	.section	.debug_ranges,"",@progbits
+.Ldebug_ranges0:
+	.quad	.Ltext0	# Offset 0
+	.quad	.Letext0
+	.quad	.LFB1	# Offset 0x10
+	.quad	.LFE1
+	.quad	0
+	.quad	0
+	.section	.debug_line,"",@progbits
+.Ldebug_line0:
+	.section	.debug_str,"MS",@progbits,1
+.LASF1:
+	.string	"gdb.arch/amd64-entry-value-paramref.cc"
+.LASF2:
+	.string	""
+.LASF0:
+	.string	"GNU C++ 4.8.2 20131212 (Red Hat 4.8.2-7) -mtune=generic -march=x86-64 -g -O2"
+.LASF3:
+	.string	"main"
+	.ident	"GCC: (GNU) 4.8.2 20131212 (Red Hat 4.8.2-7)"
+	.section	.note.GNU-stack,"",@progbits
diff --git a/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.cc b/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.cc
new file mode 100644
index 0000000..aa473a3
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.cc
@@ -0,0 +1,33 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2014 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+volatile int vv, *p;
+
+static __attribute__((noinline)) int
+bar (int &ref)
+{
+  vv++; /* break-here */
+  p = &ref;
+  return ref;
+}
+
+int
+main (void)
+{
+  int var = 10;
+  return bar (var);
+}
diff --git a/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.exp b/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.exp
new file mode 100644
index 0000000..f06247d
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.exp
@@ -0,0 +1,35 @@
+# Copyright (C) 2014 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile .S .cc
+
+if { ![istarget x86_64-*-* ] || ![is_lp64_target] } {
+    verbose "Skipping amd64-entry-value-paramref."
+    return
+}
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} "c++"] } {
+    return -1
+}
+
+if ![runto_main] {
+    return -1
+}
+
+set srcfile $srcfile2
+gdb_breakpoint [gdb_get_line_number "break-here"]
+
+gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+gdb_test "frame" {bar \(ref=@0x[0-9a-f]+: 10, ref@entry=@0x[0-9a-f]+: <optimized out>\) at .*}
diff --git a/gdb/testsuite/gdb.arch/amd64-optimout-repeat.S b/gdb/testsuite/gdb.arch/amd64-optimout-repeat.S
new file mode 100644
index 0000000..2f8f4d2
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-optimout-repeat.S
@@ -0,0 +1,297 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2012-2014 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* This file is compiled from gdb.arch/amd64-entry-value-param.c
+   using -g -dA -S -O2.  */
+
+	.file	"amd64-optimout-repeat.c"
+	.text
+.Ltext0:
+	.section	.text.unlikely,"ax",@progbits
+.LCOLDB0:
+	.section	.text.startup,"ax",@progbits
+.LHOTB0:
+	.p2align 4,,15
+	.section	.text.unlikely
+.Ltext_cold0:
+	.section	.text.startup
+	.globl	main
+	.type	main, @function
+main:
+.LFB0:
+	.file 1 "gdb.arch/amd64-optimout-repeat.c"
+	# gdb.arch/amd64-optimout-repeat.c:20
+	.loc 1 20 0
+	.cfi_startproc
+# BLOCK 2 freq:10000 seq:0
+# PRED: ENTRY [100.0%]  (FALLTHRU)
+.LVL0:
+	# gdb.arch/amd64-optimout-repeat.c:29
+	.loc 1 29 0
+	xorl	%eax, %eax
+# SUCC: EXIT [100.0%] 
+	ret
+	.cfi_endproc
+.LFE0:
+	.size	main, .-main
+	.section	.text.unlikely
+.LCOLDE0:
+	.section	.text.startup
+.LHOTE0:
+	.text
+.Letext0:
+	.section	.text.unlikely
+.Letext_cold0:
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+	.long	0x97	# Length of Compilation Unit Info
+	.value	0x4	# DWARF version number
+	.long	.Ldebug_abbrev0	# Offset Into Abbrev. Section
+	.byte	0x8	# Pointer Size (in bytes)
+	.uleb128 0x1	# (DIE (0xb) DW_TAG_compile_unit)
+	.long	.LASF1	# DW_AT_producer: "GNU C 4.9.1 20140709 (prerelease) -mtune=generic -march=x86-64 -g -O2"
+	.byte	0x1	# DW_AT_language
+	.long	.LASF2	# DW_AT_name: "gdb.arch/amd64-optimout-repeat.c"
+	.long	.LASF3	# DW_AT_comp_dir: ""
+	.long	.Ldebug_ranges0+0	# DW_AT_ranges
+	.quad	0	# DW_AT_low_pc
+	.long	.Ldebug_line0	# DW_AT_stmt_list
+	.uleb128 0x2	# (DIE (0x29) DW_TAG_subprogram)
+			# DW_AT_external
+	.long	.LASF4	# DW_AT_name: "main"
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-optimout-repeat.c)
+	.byte	0x13	# DW_AT_decl_line
+			# DW_AT_prototyped
+	.long	0x7c	# DW_AT_type
+	.quad	.LFB0	# DW_AT_low_pc
+	.quad	.LFE0-.LFB0	# DW_AT_high_pc
+	.uleb128 0x1	# DW_AT_frame_base
+	.byte	0x9c	# DW_OP_call_frame_cfa
+			# DW_AT_GNU_all_call_sites
+	.long	0x7c	# DW_AT_sibling
+	.uleb128 0x3	# (DIE (0x4a) DW_TAG_structure_type)
+	.value	0x404	# DW_AT_byte_size
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-optimout-repeat.c)
+	.byte	0x15	# DW_AT_decl_line
+	.long	0x6a	# DW_AT_sibling
+	.uleb128 0x4	# (DIE (0x53) DW_TAG_member)
+	.ascii "i\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-optimout-repeat.c)
+	.byte	0x17	# DW_AT_decl_line
+	.long	0x7c	# DW_AT_type
+	.byte	0	# DW_AT_data_member_location
+	.uleb128 0x4	# (DIE (0x5d) DW_TAG_member)
+	.ascii "xxx\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-optimout-repeat.c)
+	.byte	0x18	# DW_AT_decl_line
+	.long	0x83	# DW_AT_type
+	.byte	0x4	# DW_AT_data_member_location
+	.byte	0	# end of children of DIE 0x4a
+	.uleb128 0x5	# (DIE (0x6a) DW_TAG_variable)
+	.ascii "v\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-optimout-repeat.c)
+	.byte	0x1a	# DW_AT_decl_line
+	.long	0x4a	# DW_AT_type
+	.uleb128 0x7	# DW_AT_location
+	.byte	0x30	# DW_OP_lit0
+	.byte	0x9f	# DW_OP_stack_value
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x4
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x400
+	.byte	0	# end of children of DIE 0x29
+	.uleb128 0x6	# (DIE (0x7c) DW_TAG_base_type)
+	.byte	0x4	# DW_AT_byte_size
+	.byte	0x5	# DW_AT_encoding
+	.ascii "int\0"	# DW_AT_name
+	.uleb128 0x7	# (DIE (0x83) DW_TAG_array_type)
+	.long	0x7c	# DW_AT_type
+	.long	0x93	# DW_AT_sibling
+	.uleb128 0x8	# (DIE (0x8c) DW_TAG_subrange_type)
+	.long	0x93	# DW_AT_type
+	.byte	0xff	# DW_AT_upper_bound
+	.byte	0	# end of children of DIE 0x83
+	.uleb128 0x9	# (DIE (0x93) DW_TAG_base_type)
+	.byte	0x8	# DW_AT_byte_size
+	.byte	0x7	# DW_AT_encoding
+	.long	.LASF0	# DW_AT_name: "sizetype"
+	.byte	0	# end of children of DIE 0xb
+	.section	.debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1	# (abbrev code)
+	.uleb128 0x11	# (TAG: DW_TAG_compile_unit)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x25	# (DW_AT_producer)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x13	# (DW_AT_language)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x1b	# (DW_AT_comp_dir)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x55	# (DW_AT_ranges)
+	.uleb128 0x17	# (DW_FORM_sec_offset)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x10	# (DW_AT_stmt_list)
+	.uleb128 0x17	# (DW_FORM_sec_offset)
+	.byte	0
+	.byte	0
+	.uleb128 0x2	# (abbrev code)
+	.uleb128 0x2e	# (TAG: DW_TAG_subprogram)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x3f	# (DW_AT_external)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x27	# (DW_AT_prototyped)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x12	# (DW_AT_high_pc)
+	.uleb128 0x7	# (DW_FORM_data8)
+	.uleb128 0x40	# (DW_AT_frame_base)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.uleb128 0x2117	# (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x1	# (DW_AT_sibling)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x3	# (abbrev code)
+	.uleb128 0x13	# (TAG: DW_TAG_structure_type)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0x5	# (DW_FORM_data2)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x1	# (DW_AT_sibling)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x4	# (abbrev code)
+	.uleb128 0xd	# (TAG: DW_TAG_member)
+	.byte	0	# DW_children_no
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x38	# (DW_AT_data_member_location)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.byte	0
+	.byte	0
+	.uleb128 0x5	# (abbrev code)
+	.uleb128 0x34	# (TAG: DW_TAG_variable)
+	.byte	0	# DW_children_no
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x2	# (DW_AT_location)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.byte	0
+	.byte	0
+	.uleb128 0x6	# (abbrev code)
+	.uleb128 0x24	# (TAG: DW_TAG_base_type)
+	.byte	0	# DW_children_no
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3e	# (DW_AT_encoding)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.byte	0
+	.byte	0
+	.uleb128 0x7	# (abbrev code)
+	.uleb128 0x1	# (TAG: DW_TAG_array_type)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x1	# (DW_AT_sibling)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x8	# (abbrev code)
+	.uleb128 0x21	# (TAG: DW_TAG_subrange_type)
+	.byte	0	# DW_children_no
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x2f	# (DW_AT_upper_bound)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.byte	0
+	.byte	0
+	.uleb128 0x9	# (abbrev code)
+	.uleb128 0x24	# (TAG: DW_TAG_base_type)
+	.byte	0	# DW_children_no
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3e	# (DW_AT_encoding)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.byte	0
+	.byte	0
+	.byte	0
+	.section	.debug_aranges,"",@progbits
+	.long	0x2c	# Length of Address Ranges Info
+	.value	0x2	# DWARF Version
+	.long	.Ldebug_info0	# Offset of Compilation Unit Info
+	.byte	0x8	# Size of Address
+	.byte	0	# Size of Segment Descriptor
+	.value	0	# Pad to 16 byte boundary
+	.value	0
+	.quad	.LFB0	# Address
+	.quad	.LFE0-.LFB0	# Length
+	.quad	0
+	.quad	0
+	.section	.debug_ranges,"",@progbits
+.Ldebug_ranges0:
+	.quad	.LFB0	# Offset 0
+	.quad	.LFE0
+	.quad	0
+	.quad	0
+	.section	.debug_line,"",@progbits
+.Ldebug_line0:
+	.section	.debug_str,"MS",@progbits,1
+.LASF0:
+	.string	"sizetype"
+.LASF2:
+	.string	"gdb.arch/amd64-optimout-repeat.c"
+.LASF1:
+	.string	"GNU C 4.9.1 20140709 (prerelease) -mtune=generic -march=x86-64 -g -O2"
+.LASF3:
+	.string	""
+.LASF4:
+	.string	"main"
+	.ident	"GCC: (GNU) 4.9.1 20140709 (prerelease)"
+	.section	.note.GNU-stack,"",@progbits
diff --git a/gdb/testsuite/gdb.arch/amd64-optimout-repeat.c b/gdb/testsuite/gdb.arch/amd64-optimout-repeat.c
new file mode 100644
index 0000000..a32b6de
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-optimout-repeat.c
@@ -0,0 +1,29 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2014 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+int
+main (void)
+{
+  struct
+    {
+      int i;
+      int xxx[0x100];
+    }
+  v = { 0 };
+
+  return v.i;
+}
diff --git a/gdb/testsuite/gdb.arch/amd64-optimout-repeat.exp b/gdb/testsuite/gdb.arch/amd64-optimout-repeat.exp
new file mode 100644
index 0000000..f3c93a4
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-optimout-repeat.exp
@@ -0,0 +1,36 @@
+# Copyright (C) 2014 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile .S .c
+set opts {}
+
+if [info exists COMPILE] {
+    # make check RUNTESTFLAGS="gdb.arch/amd64-optimout-repeat.exp COMPILE=1"
+    set srcfile ${srcfile2}
+    lappend opts debug optimize=-O2
+} elseif { ![istarget x86_64-*-* ] || ![is_lp64_target] } {
+    verbose "Skipping amd64-optimout-repeat."
+    return
+}
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} $opts] } {
+    return -1
+}
+
+if ![runto_main] {
+    return -1
+}
+
+gdb_test "print v" { = {i = 0, xxx = {<optimized out> <repeats 256 times>}}}

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patchv3] Fix crash on optimized-out entry data values
  2014-07-11 16:07     ` [patchv3] " Jan Kratochvil
@ 2014-07-14  7:02       ` Yao Qi
  2014-07-14  8:32         ` Jan Kratochvil
  2014-07-14 18:12       ` Pedro Alves
  1 sibling, 1 reply; 28+ messages in thread
From: Yao Qi @ 2014-07-14  7:02 UTC (permalink / raw)
  To: Jan Kratochvil, Pedro Alves; +Cc: gdb-patches

On 07/11/2014 11:37 PM, Jan Kratochvil wrote:
> gdb/testsuite/
> 2014-07-09  Jan Kratochvil  <jan.kratochvil@redhat.com>
> 
> 	* gdb.arch/amd64-entry-value-paramref.S: New file.
> 	* gdb.arch/amd64-entry-value-paramref.cc: New file.
> 	* gdb.arch/amd64-entry-value-paramref.exp: New file.
> 	* gdb.arch/amd64-optimout-repeat.S: New file.
> 	* gdb.arch/amd64-optimout-repeat.c: New file.
> 	* gdb.arch/amd64-optimout-repeat.exp: New file.

IWBN to generate .S files by dwarf assembler
(gdb.trace/entry-values.exp, for example).  Although
DW_OP_GNU_entry_value isn't supported in dwarf assembler, it shouldn't
be hard to handle it.

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patchv3] Fix crash on optimized-out entry data values
  2014-07-14  7:02       ` Yao Qi
@ 2014-07-14  8:32         ` Jan Kratochvil
  0 siblings, 0 replies; 28+ messages in thread
From: Jan Kratochvil @ 2014-07-14  8:32 UTC (permalink / raw)
  To: Yao Qi; +Cc: Pedro Alves, gdb-patches

On Mon, 14 Jul 2014 02:28:05 +0200, Yao Qi wrote:
> On 07/11/2014 11:37 PM, Jan Kratochvil wrote:
> > gdb/testsuite/
> > 2014-07-09  Jan Kratochvil  <jan.kratochvil@redhat.com>
> > 
> > 	* gdb.arch/amd64-entry-value-paramref.S: New file.
> > 	* gdb.arch/amd64-entry-value-paramref.cc: New file.
> > 	* gdb.arch/amd64-entry-value-paramref.exp: New file.
> > 	* gdb.arch/amd64-optimout-repeat.S: New file.
> > 	* gdb.arch/amd64-optimout-repeat.c: New file.
> > 	* gdb.arch/amd64-optimout-repeat.exp: New file.
> 
> IWBN to generate .S files by dwarf assembler
> (gdb.trace/entry-values.exp, for example).

I am aware of it but I find it a lot of work while the gcc generated files are
IMO good enough.  So only if it is a patch acceptance requirement.


Jan

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [patchv3] Fix crash on optimized-out entry data values
  2014-07-11 16:07     ` [patchv3] " Jan Kratochvil
  2014-07-14  7:02       ` Yao Qi
@ 2014-07-14 18:12       ` Pedro Alves
  1 sibling, 0 replies; 28+ messages in thread
From: Pedro Alves @ 2014-07-14 18:12 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

On 07/11/2014 04:37 PM, Jan Kratochvil wrote:
> On Wed, 09 Jul 2014 17:31:21 +0200, Jan Kratochvil wrote:
>> On Wed, 09 Jul 2014 13:52:00 +0200, Pedro Alves wrote:
>>> On 07/09/2014 11:33 AM, Jan Kratochvil wrote:
>>>> --- a/gdb/value.c
>>>> +++ b/gdb/value.c
>>>> @@ -198,12 +198,13 @@ struct value
>>>>    unsigned int lazy : 1;
>>>>  
>>>>    /* If nonzero, this is the value of a variable that does not
>>>> -     actually exist in the program.  If nonzero, and LVAL is
>>>> +     actually fully 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.  */
>>>> +     error strings.  It is true also for only partially optimized
>>>> +     out variables - see the 'unavailable' field below.  */
>>>>    unsigned int optimized_out : 1;
>>>>  
>>>>    /* If value is a variable, is it initialized or not.  */
>>>> @@ -334,7 +335,10 @@ struct value
>>>>       valid if lazy is nonzero.  */
>>>>    gdb_byte *contents;
>>>>  
>>>> -  /* Unavailable ranges in CONTENTS.  We mark unavailable ranges,
>>>> +  /* If OPTIMIZED_OUT is false then UNAVAILABLE must be VEC_empty
>>>> +     (not necessarily NULL).  
>>>
>>> Hmm, why?  We can collect only part of a non-optimized out value.
>>> What am I missing?
>>
>> I miss some documentation how these availability fields interact together.
> 
> From a comment in mail
> 	Message-Id: <201102071427.55970.pedro@codesourcery.com>
> 	We give preference to printing <optimized out> rather
> 	than <unavailable>, since if a value had been optimized out
> 	at compile time, it can never be collected at run-time.
> 
> it seems it is just reversed, that 'unavailable' can exist only for
> !optimized_out and it cannot exist for for optimized_out values.

Not really true either.  A value can be partially optimized out.
And then when e.g., inspecting a traceframe or a partial core dump,
the bits that are not optimized out may well not have been
collected, so those will be unavailable.  I'm sending you a different
patch in a bit.

-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH] Handle partially optimized out values similarly to unavailable values (Re: [patchv2] Fix crash on optimized-out entry data values)
  2014-07-09 15:31   ` Jan Kratochvil
  2014-07-11 16:07     ` [patchv3] " Jan Kratochvil
@ 2014-07-14 18:47     ` Pedro Alves
  2014-07-17  8:04       ` Jan Kratochvil
  1 sibling, 1 reply; 28+ messages in thread
From: Pedro Alves @ 2014-07-14 18:47 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

On 07/09/2014 04:31 PM, Jan Kratochvil wrote:
> On Wed, 09 Jul 2014 13:52:00 +0200, Pedro Alves wrote:
>> On 07/09/2014 11:33 AM, Jan Kratochvil wrote:
>>> --- a/gdb/value.c
>>> +++ b/gdb/value.c
>>> @@ -198,12 +198,13 @@ struct value
>>>    unsigned int lazy : 1;
>>>  
>>>    /* If nonzero, this is the value of a variable that does not
>>> -     actually exist in the program.  If nonzero, and LVAL is
>>> +     actually fully 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.  */
>>> +     error strings.  It is true also for only partially optimized
>>> +     out variables - see the 'unavailable' field below.  */
>>>    unsigned int optimized_out : 1;
>>>  
>>>    /* If value is a variable, is it initialized or not.  */
>>> @@ -334,7 +335,10 @@ struct value
>>>       valid if lazy is nonzero.  */
>>>    gdb_byte *contents;
>>>  
>>> -  /* Unavailable ranges in CONTENTS.  We mark unavailable ranges,
>>> +  /* If OPTIMIZED_OUT is false then UNAVAILABLE must be VEC_empty
>>> +     (not necessarily NULL).  
>>
>> Hmm, why?  We can collect only part of a non-optimized out value.
>> What am I missing?
> 
> I miss some documentation how these availability fields interact together.
> value_available_contents_bits_eq is written according to the struct value
> comments but they do not correspond to the real world struct value data.

value_available_contents_bits_eq isn't paying attention to the optimized
out bits at all.  But as you found it, that's not sufficient.  Currently it
either returns that a zeroed value equals an optimized out value, because
allocate_value_contents zeros to buffer, which is bogus, or crashes,
if the optimized out value hasn't had its contents buffer allocated.

> 
> 'unavailable' suggests that optimized out variable should have it set to the
> full range of the variable.  

'unavailable' has a specific meaning here, and it doesn't include
"optimized out" values.  See comment added to value.h in the patch.

> But struct value with OPTIMIZED_OUT field set
> still has UNAVAILABLE empty. As the variable is optimized out the CONTENTS is
> also NULL - this causes the crash reproduced by
> 'gdb.arch/amd64-entry-value-paramref.exp'.
> 
> There are also check_validity and check_any_valid methods but how they are
> related to the 'unavailable' data field is also not documented.

Yeah, confusing terminology.  They are not related at all.
"valid" == "!optimized out" in the current sources.  A value can
be both "valid" and "not available".

> 
> This patch was my second attempt to fix/document the availability stuff, it
> would be useful to suggest how it is designed.

Time to pick up more pieces of
https://sourceware.org/ml/gdb-patches/2013-08/msg00300.html ...

I've picked that, and trimmed it to a bare minimal.  I've done
a few things differently, like not merging the range vectors,
and dropped the generic availability API (several spots in
that series look misconverted to me, best do this in smaller
baby steps).

No regressions for me on x86-64 F20, native and gdbserver, and
also fixes your test's crash.

Let me know what you think.

8<---------------------------
From c5d14e921f8ed79c861c74d41f05688aa2c8bf0e Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Mon, 14 Jul 2014 17:58:59 +0100
Subject: [PATCH] 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.

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>"
and "<unavailable>" values.

gdb/
2014-07-14  Andrew Burgess  <aburgess@broadcom.com>
	    Pedro Alves  <palves@redhat.com>

	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): Remove use of optimized_out.
	(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/
2014-07-14  Andrew Burgess  <aburgess@broadcom.com>
	    Pedro Alves  <palves@redhat.com>

	PR symtab/14604
	PR symtab/14605
	* gdb.dwarf2/dw2-op-out-param.exp: Remove kfail branches and use
	gdb_test.
---
 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                                   |  15 +-
 gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp |  30 +-
 gdb/valprint.c                                |  22 +-
 gdb/value.c                                   | 459 +++++++++++++++-----------
 gdb/value.h                                   | 147 ++++++---
 17 files changed, 430 insertions(+), 444 deletions(-)

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 6956909..63f84ea 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -682,14 +682,12 @@ coerce_unspec_val_to_type (struct value *val, struct type *type)
       else
 	{
 	  result = allocate_value (type);
-	  memcpy (value_contents_raw (result), value_contents (val),
-		  TYPE_LENGTH (type));
+	  value_contents_copy_raw (result, 0, val, 0, TYPE_LENGTH (type));
 	}
       set_value_component_location (result, val);
       set_value_bitsize (result, value_bitsize (val));
       set_value_bitpos (result, value_bitpos (val));
       set_value_address (result, value_address (val));
-      set_value_optimized_out (result, value_optimized_out_const (val));
       return result;
     }
 }
diff --git a/gdb/ada-valprint.c b/gdb/ada-valprint.c
index b7b3a9c..b4f191f 100644
--- a/gdb/ada-valprint.c
+++ b/gdb/ada-valprint.c
@@ -186,9 +186,9 @@ val_print_packed_array_elements (struct type *type, const gdb_byte *valaddr,
 					       (i * bitsize) / HOST_CHAR_BIT,
 					       (i * bitsize) % HOST_CHAR_BIT,
 					       bitsize, elttype);
-	  if (!value_available_contents_eq (v0, value_embedded_offset (v0),
-					    v1, value_embedded_offset (v1),
-					    eltlen))
+	  if (!value_contents_eq (v0, value_embedded_offset (v0),
+				  v1, value_embedded_offset (v1),
+				  eltlen))
 	    break;
 	}
 
diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c
index f4694b0..2f2789c 100644
--- a/gdb/c-valprint.c
+++ b/gdb/c-valprint.c
@@ -173,9 +173,9 @@ c_val_print (struct type *type, const gdb_byte *valaddr,
 				      options->format)
 	      && value_bytes_available (original_value, embedded_offset,
 					TYPE_LENGTH (type))
-	      && value_bits_valid (original_value,
-				   TARGET_CHAR_BIT * embedded_offset,
-				   TARGET_CHAR_BIT * TYPE_LENGTH (type)))
+	      && !value_bits_any_optimized_out (original_value,
+						TARGET_CHAR_BIT * embedded_offset,
+						TARGET_CHAR_BIT * TYPE_LENGTH (type)))
 	    {
 	      int force_ellipses = 0;
 
diff --git a/gdb/cp-valprint.c b/gdb/cp-valprint.c
index 3e1d6ed..0d6c3fc 100644
--- a/gdb/cp-valprint.c
+++ b/gdb/cp-valprint.c
@@ -294,12 +294,6 @@ cp_print_value_fields (struct type *type, struct type *real_type,
 		{
 		  fputs_filtered (_("<synthetic pointer>"), stream);
 		}
-	      else if (!value_bits_valid (val,
-					  TYPE_FIELD_BITPOS (type, i),
-					  TYPE_FIELD_BITSIZE (type, i)))
-		{
-		  val_print_optimized_out (val, stream);
-		}
 	      else
 		{
 		  struct value_print_options opts = *options;
@@ -434,8 +428,9 @@ cp_print_value_fields_rtti (struct type *type,
 
   /* We require all bits to be valid in order to attempt a
      conversion.  */
-  if (value_bits_valid (val, TARGET_CHAR_BIT * offset,
-			TARGET_CHAR_BIT * TYPE_LENGTH (type)))
+  if (!value_bits_any_optimized_out (val,
+				     TARGET_CHAR_BIT * offset,
+				     TARGET_CHAR_BIT * TYPE_LENGTH (type)))
     {
       struct value *value;
       int full, top, using_enc;
diff --git a/gdb/d-valprint.c b/gdb/d-valprint.c
index 755f180..788b3d5 100644
--- a/gdb/d-valprint.c
+++ b/gdb/d-valprint.c
@@ -38,8 +38,9 @@ dynamic_array_type (struct type *type, const gdb_byte *valaddr,
       && TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_INT
       && strcmp (TYPE_FIELD_NAME (type, 0), "length") == 0
       && strcmp (TYPE_FIELD_NAME (type, 1), "ptr") == 0
-      && value_bits_valid (val, TARGET_CHAR_BIT * embedded_offset,
-			   TARGET_CHAR_BIT * TYPE_LENGTH (type)))
+      && !value_bits_any_optimized_out (val,
+					TARGET_CHAR_BIT * embedded_offset,
+					TARGET_CHAR_BIT * TYPE_LENGTH (type)))
     {
       CORE_ADDR addr;
       struct type *elttype;
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index fcab9b9..37689d8 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -1285,8 +1285,6 @@ static const struct lval_funcs entry_data_value_funcs =
 {
   NULL,	/* read */
   NULL,	/* write */
-  NULL,	/* check_validity */
-  NULL,	/* check_any_valid */
   NULL,	/* indirect */
   entry_data_value_coerce_ref,
   NULL,	/* check_synthetic_pointer */
@@ -1704,7 +1702,7 @@ read_pieced_value (struct value *v)
 		    memset (buffer, 0, this_size);
 
 		    if (optim)
-		      set_value_optimized_out (v, 1);
+		      mark_value_bits_optimized_out (v, offset, this_size_bits);
 		    if (unavail)
 		      mark_value_bits_unavailable (v, offset, this_size_bits);
 		  }
@@ -1764,7 +1762,7 @@ read_pieced_value (struct value *v)
 	  break;
 
 	case DWARF_VALUE_OPTIMIZED_OUT:
-	  set_value_optimized_out (v, 1);
+	  mark_value_bits_optimized_out (v, offset, this_size_bits);
 	  break;
 
 	default:
@@ -1802,7 +1800,7 @@ write_pieced_value (struct value *to, struct value *from)
 
   if (frame == NULL)
     {
-      set_value_optimized_out (to, 1);
+      mark_value_bytes_optimized_out (to, 0, TYPE_LENGTH (value_type (to)));
       return;
     }
 
@@ -1934,7 +1932,7 @@ write_pieced_value (struct value *to, struct value *from)
 			source_buffer, this_size);
 	  break;
 	default:
-	  set_value_optimized_out (to, 1);
+	  mark_value_bytes_optimized_out (to, 0, TYPE_LENGTH (value_type (to)));
 	  break;
 	}
       offset += this_size_bits;
@@ -1943,24 +1941,16 @@ write_pieced_value (struct value *to, struct value *from)
   do_cleanups (cleanup);
 }
 
-/* A helper function that checks bit validity in a pieced value.
-   CHECK_FOR indicates the kind of validity checking.
-   DWARF_VALUE_MEMORY means to check whether any bit is valid.
-   DWARF_VALUE_OPTIMIZED_OUT means to check whether any bit is
-   optimized out.
-   DWARF_VALUE_IMPLICIT_POINTER means to check whether the bits are an
-   implicit pointer.  */
+/* An implementation of an lval_funcs method to see whether a value is
+   a synthetic pointer.  */
 
 static int
-check_pieced_value_bits (const struct value *value, int bit_offset,
-			 int bit_length,
-			 enum dwarf_value_location check_for)
+check_pieced_synthetic_pointer (const struct value *value, int bit_offset,
+				int bit_length)
 {
   struct piece_closure *c
     = (struct piece_closure *) value_computed_closure (value);
   int i;
-  int validity = (check_for == DWARF_VALUE_MEMORY
-		  || check_for == DWARF_VALUE_IMPLICIT_POINTER);
 
   bit_offset += 8 * value_offset (value);
   if (value_bitsize (value))
@@ -1985,52 +1975,11 @@ check_pieced_value_bits (const struct value *value, int bit_offset,
       else
 	bit_length -= this_size_bits;
 
-      if (check_for == DWARF_VALUE_IMPLICIT_POINTER)
-	{
-	  if (p->location != DWARF_VALUE_IMPLICIT_POINTER)
-	    return 0;
-	}
-      else if (p->location == DWARF_VALUE_OPTIMIZED_OUT
-	       || p->location == DWARF_VALUE_IMPLICIT_POINTER)
-	{
-	  if (validity)
-	    return 0;
-	}
-      else
-	{
-	  if (!validity)
-	    return 1;
-	}
+      if (p->location != DWARF_VALUE_IMPLICIT_POINTER)
+	return 0;
     }
 
-  return validity;
-}
-
-static int
-check_pieced_value_validity (const struct value *value, int bit_offset,
-			     int bit_length)
-{
-  return check_pieced_value_bits (value, bit_offset, bit_length,
-				  DWARF_VALUE_MEMORY);
-}
-
-static int
-check_pieced_value_invalid (const struct value *value)
-{
-  return check_pieced_value_bits (value, 0,
-				  8 * TYPE_LENGTH (value_type (value)),
-				  DWARF_VALUE_OPTIMIZED_OUT);
-}
-
-/* An implementation of an lval_funcs method to see whether a value is
-   a synthetic pointer.  */
-
-static int
-check_pieced_synthetic_pointer (const struct value *value, int bit_offset,
-				int bit_length)
-{
-  return check_pieced_value_bits (value, bit_offset, bit_length,
-				  DWARF_VALUE_IMPLICIT_POINTER);
+  return 1;
 }
 
 /* A wrapper function for get_frame_address_in_block.  */
@@ -2179,8 +2128,6 @@ free_pieced_value_closure (struct value *v)
 static const struct lval_funcs pieced_value_funcs = {
   read_pieced_value,
   write_pieced_value,
-  check_pieced_value_validity,
-  check_pieced_value_invalid,
   indirect_pieced_value,
   NULL,	/* coerce_ref */
   check_pieced_synthetic_pointer,
@@ -2308,6 +2255,8 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 	   retval = value_from_register (type, gdb_regnum, frame);
 	   if (value_optimized_out (retval))
 	     {
+	       struct value *tmp;
+
 	       /* 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
@@ -2315,7 +2264,9 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 		  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);
+	       tmp = allocate_value (type);
+	       value_contents_copy (tmp, 0, retval, 0, TYPE_LENGTH (type));
+	       retval = tmp;
 	     }
 	  }
 	  break;
diff --git a/gdb/findvar.c b/gdb/findvar.c
index 9390c8a..346a499 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -681,12 +681,6 @@ read_frame_register_value (struct value *value, struct frame_info *frame)
       struct value *regval = get_frame_register_value (frame, regnum);
       int reg_len = TYPE_LENGTH (value_type (regval)) - reg_offset;
 
-      if (value_optimized_out (regval))
-	{
-	  set_value_optimized_out (value, 1);
-	  break;
-	}
-
       /* If the register length is larger than the number of bytes
          remaining to copy, then only copy the appropriate bytes.  */
       if (reg_len > len)
@@ -732,7 +726,7 @@ value_from_register (struct type *type, int regnum, struct frame_info *frame)
       if (!ok)
 	{
 	  if (optim)
-	    set_value_optimized_out (v, 1);
+	    mark_value_bytes_optimized_out (v, 0, TYPE_LENGTH (type));
 	  if (unavail)
 	    mark_value_bytes_unavailable (v, 0, TYPE_LENGTH (type));
 	}
diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c
index fdfea6e..1cc3303 100644
--- a/gdb/frame-unwind.c
+++ b/gdb/frame-unwind.c
@@ -203,7 +203,7 @@ frame_unwind_got_optimized (struct frame_info *frame, int regnum)
      "<not saved>".  */
   val = allocate_value_lazy (type);
   set_value_lazy (val, 0);
-  set_value_optimized_out (val, 1);
+  mark_value_bytes_optimized_out (val, 0, TYPE_LENGTH (type));
   VALUE_LVAL (val) = lval_register;
   VALUE_REGNUM (val) = regnum;
   VALUE_FRAME_ID (val) = get_frame_id (frame);
diff --git a/gdb/jv-valprint.c b/gdb/jv-valprint.c
index a7bb494..93a827e 100644
--- a/gdb/jv-valprint.c
+++ b/gdb/jv-valprint.c
@@ -183,10 +183,10 @@ java_value_print (struct value *val, struct ui_file *stream,
 		  set_value_offset (next_v, value_offset (next_v)
 				    + TYPE_LENGTH (el_type));
 		  value_fetch_lazy (next_v);
-		  if (!(value_available_contents_eq
-			(v, value_embedded_offset (v),
-			 next_v, value_embedded_offset (next_v),
-			 TYPE_LENGTH (el_type))))
+		  if (!value_contents_eq (v, value_embedded_offset (v),
+					  next_v,
+					  value_embedded_offset (next_v),
+					  TYPE_LENGTH (el_type)))
 		    break;
 		}
 
@@ -393,11 +393,6 @@ java_print_value_fields (struct type *type, const gdb_byte *valaddr,
 		{
 		  fputs_filtered (_("<synthetic pointer>"), stream);
 		}
-	      else if (!value_bits_valid (val, TYPE_FIELD_BITPOS (type, i),
-					  TYPE_FIELD_BITSIZE (type, i)))
-		{
-		  val_print_optimized_out (val, stream);
-		}
 	      else
 		{
 		  struct value_print_options opts;
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index c3e8e77..34b75f7 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -6196,12 +6196,6 @@ mips_print_register (struct ui_file *file, struct frame_info *frame,
     }
 
   val = get_frame_register_value (frame, regnum);
-  if (value_optimized_out (val))
-    {
-      fprintf_filtered (file, "%s: [Invalid]",
-			gdbarch_register_name (gdbarch, regnum));
-      return;
-    }
 
   fputs_filtered (gdbarch_register_name (gdbarch, regnum), file);
 
diff --git a/gdb/opencl-lang.c b/gdb/opencl-lang.c
index 2dd76fa..6a3ba69 100644
--- a/gdb/opencl-lang.c
+++ b/gdb/opencl-lang.c
@@ -240,58 +240,6 @@ lval_func_write (struct value *v, struct value *fromval)
   value_free_to_mark (mark);
 }
 
-/* Return nonzero if all bits in V within OFFSET and LENGTH are valid.  */
-
-static int
-lval_func_check_validity (const struct value *v, int offset, int length)
-{
-  struct lval_closure *c = (struct lval_closure *) value_computed_closure (v);
-  /* Size of the target type in bits.  */
-  int elsize =
-      TYPE_LENGTH (TYPE_TARGET_TYPE (check_typedef (value_type (c->val)))) * 8;
-  int startrest = offset % elsize;
-  int start = offset / elsize;
-  int endrest = (offset + length) % elsize;
-  int end = (offset + length) / elsize;
-  int i;
-
-  if (endrest)
-    end++;
-
-  if (end > c->n)
-    return 0;
-
-  for (i = start; i < end; i++)
-    {
-      int comp_offset = (i == start) ? startrest : 0;
-      int comp_length = (i == end) ? endrest : elsize;
-
-      if (!value_bits_valid (c->val, c->indices[i] * elsize + comp_offset,
-			     comp_length))
-	return 0;
-    }
-
-  return 1;
-}
-
-/* Return nonzero if any bit in V is valid.  */
-
-static int
-lval_func_check_any_valid (const struct value *v)
-{
-  struct lval_closure *c = (struct lval_closure *) value_computed_closure (v);
-  /* Size of the target type in bits.  */
-  int elsize =
-      TYPE_LENGTH (TYPE_TARGET_TYPE (check_typedef (value_type (c->val)))) * 8;
-  int i;
-
-  for (i = 0; i < c->n; i++)
-    if (value_bits_valid (c->val, c->indices[i] * elsize, elsize))
-      return 1;
-
-  return 0;
-}
-
 /* Return nonzero if bits in V from OFFSET and LENGTH represent a
    synthetic pointer.  */
 
@@ -358,8 +306,6 @@ static const struct lval_funcs opencl_value_funcs =
   {
     lval_func_read,
     lval_func_write,
-    lval_func_check_validity,
-    lval_func_check_any_valid,
     NULL,	/* indirect */
     NULL,	/* coerce_ref */
     lval_func_check_synthetic_pointer,
diff --git a/gdb/p-valprint.c b/gdb/p-valprint.c
index 70eb3a8..c796218 100644
--- a/gdb/p-valprint.c
+++ b/gdb/p-valprint.c
@@ -627,11 +627,6 @@ pascal_object_print_value_fields (struct type *type, const gdb_byte *valaddr,
 		{
 		  fputs_filtered (_("<synthetic pointer>"), stream);
 		}
-	      else if (!value_bits_valid (val, TYPE_FIELD_BITPOS (type, i),
-					  TYPE_FIELD_BITSIZE (type, i)))
-		{
-		  val_print_optimized_out (val, stream);
-		}
 	      else
 		{
 		  struct value_print_options opts = *options;
diff --git a/gdb/stack.c b/gdb/stack.c
index 0d6d8e7..346ce29 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -385,9 +385,12 @@ read_frame_arg (struct symbol *sym, struct frame_info *frame,
 	    {
 	      struct type *type = value_type (val);
 
-	      if (!value_optimized_out (val)
-		  && value_available_contents_eq (val, 0, entryval, 0,
-						  TYPE_LENGTH (type)))
+	      if (value_lazy (val))
+		value_fetch_lazy (val);
+	      if (value_lazy (entryval))
+		value_fetch_lazy (entryval);
+
+	      if (value_contents_eq (val, 0, entryval, 0, TYPE_LENGTH (type)))
 		{
 		  /* Initialize it just to avoid a GCC false warning.  */
 		  struct value *val_deref = NULL, *entryval_deref;
@@ -413,9 +416,9 @@ read_frame_arg (struct symbol *sym, struct frame_info *frame,
 		      /* If the reference addresses match but dereferenced
 			 content does not match print them.  */
 		      if (val != val_deref
-			  && value_available_contents_eq (val_deref, 0,
-							  entryval_deref, 0,
-						      TYPE_LENGTH (type_deref)))
+			  && value_contents_eq (val_deref, 0,
+						entryval_deref, 0,
+						TYPE_LENGTH (type_deref)))
 			val_equal = 1;
 		    }
 
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp b/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp
index 5ab5817..d245951 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp
@@ -50,36 +50,12 @@ gdb_test "bt" "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?int_param_single_
 
 # (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 $" {
-	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 $" {
-	kfail "symtab/14604" $test
-    }
-}
+gdb_test "bt" "#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 \\(\\)" "Backtrace for test struct_param_single_reg_loc"
 
 # (3) struct_param_two_reg_pieces
 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 $" {
-	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 $" {
-	kfail "symtab/14605" $test
-    }
-}
+gdb_test "bt" "#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 \\(\\)" "Backtrace for test struct_param_two_reg_pieces"
 
 # (4) int_param_two_reg_pieces
 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 $" {
-	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 $" {
-	kfail "symtab/14605" $test
-    }
-}
+gdb_test "bt" "#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 \\(\\)" "Backtrace for test int_param_two_reg_pieces"
diff --git a/gdb/valprint.c b/gdb/valprint.c
index 8600b34..981ef9b 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -311,8 +311,9 @@ valprint_check_validity (struct ui_file *stream,
       && TYPE_CODE (type) != TYPE_CODE_STRUCT
       && TYPE_CODE (type) != TYPE_CODE_ARRAY)
     {
-      if (!value_bits_valid (val, TARGET_CHAR_BIT * embedded_offset,
-			     TARGET_CHAR_BIT * TYPE_LENGTH (type)))
+      if (value_bits_any_optimized_out (val,
+					TARGET_CHAR_BIT * embedded_offset,
+					TARGET_CHAR_BIT * TYPE_LENGTH (type)))
 	{
 	  val_print_optimized_out (val, stream);
 	  return 0;
@@ -983,8 +984,9 @@ val_print_scalar_formatted (struct type *type,
 
   /* A scalar object that does not have all bits available can't be
      printed, because all bits contribute to its representation.  */
-  if (!value_bits_valid (val, TARGET_CHAR_BIT * embedded_offset,
-			      TARGET_CHAR_BIT * TYPE_LENGTH (type)))
+  if (value_bits_any_optimized_out (val,
+				    TARGET_CHAR_BIT * embedded_offset,
+				    TARGET_CHAR_BIT * TYPE_LENGTH (type)))
     val_print_optimized_out (val, stream);
   else if (!value_bytes_available (val, embedded_offset, TYPE_LENGTH (type)))
     val_print_unavailable (stream);
@@ -1685,12 +1687,12 @@ val_print_array_elements (struct type *type,
       if (options->repeat_count_threshold < UINT_MAX)
 	{
 	  while (rep1 < len
-		 && value_available_contents_eq (val,
-						 embedded_offset + i * eltlen,
-						 val,
-						 (embedded_offset
-						  + rep1 * eltlen),
-						 eltlen))
+		 && value_contents_eq (val,
+				       embedded_offset + i * eltlen,
+				       val,
+				       (embedded_offset
+					+ rep1 * eltlen),
+				       eltlen))
 	    {
 	      ++reps;
 	      ++rep1;
diff --git a/gdb/value.c b/gdb/value.c
index 29abe5f..b97e85b 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -197,15 +197,6 @@ struct value
      reset, be sure to consider this use as well!  */
   unsigned int lazy : 1;
 
-  /* 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.  */
   unsigned int initialized : 1;
 
@@ -339,6 +330,15 @@ struct value
      value to be available.  This is filled in at value read time.  The
      unavailable ranges are tracked in bits.  */
   VEC(range_s) *unavailable;
+
+  /* Likewise, but for optimized out contents (a chunk of the value of
+     a variable that does not actually exist in the program).  If LVAL
+     is lval_register, this is a register ($pc, $sp, etc., never a
+     program variable) that has not been saved in the frame.  Not
+     saved registers and optimized-out program variables values are
+     treated pretty much the same, except not-saved registers have a
+     different string representation and related error strings.  */
+  VEC(range_s) *optimized_out;
 };
 
 int
@@ -358,6 +358,14 @@ value_bytes_available (const struct value *value, int offset, int length)
 }
 
 int
+value_bits_any_optimized_out (const struct value *value, int bit_offset, int bit_length)
+{
+  gdb_assert (!value->lazy);
+
+  return ranges_contain (value->optimized_out, bit_offset, bit_length);
+}
+
+int
 value_entirely_available (struct value *value)
 {
   /* We can only tell whether the whole value is available when we try
@@ -370,17 +378,22 @@ value_entirely_available (struct value *value)
   return 0;
 }
 
-int
-value_entirely_unavailable (struct value *value)
+/* Returns true if VALUE is entirely covered by RANGES.  If the value
+   is lazy, it'll be read now.  Note that RANGE is a pointer to
+   pointer because reading the value might change *RANGE.  */
+
+static int
+value_entirely_covered_by_range_vector (struct value *value,
+					VEC(range_s) **ranges)
 {
-  /* We can only tell whether the whole value is available when we try
-     to read it.  */
+  /* We can only tell whether the whole value is optimized out /
+     unavailable when we try to read it.  */
   if (value->lazy)
     value_fetch_lazy (value);
 
-  if (VEC_length (range_s, value->unavailable) == 1)
+  if (VEC_length (range_s, *ranges) == 1)
     {
-      struct range *t = VEC_index (range_s, value->unavailable, 0);
+      struct range *t = VEC_index (range_s, *ranges, 0);
 
       if (t->offset == 0
 	  && t->length == (TARGET_CHAR_BIT
@@ -391,8 +404,23 @@ value_entirely_unavailable (struct value *value)
   return 0;
 }
 
-void
-mark_value_bits_unavailable (struct value *value, int offset, int length)
+int
+value_entirely_unavailable (struct value *value)
+{
+  return value_entirely_covered_by_range_vector (value, &value->unavailable);
+}
+
+int
+value_entirely_optimized_out (struct value *value)
+{
+  return value_entirely_covered_by_range_vector (value, &value->optimized_out);
+}
+
+/* Insert into the vector pointed to by VECTORP the bit range starting of
+   OFFSET bits, and extending for the next LENGTH bits.  */
+
+static void
+insert_into_bit_range_vector (VEC(range_s) **vectorp, int offset, int length)
 {
   range_s newr;
   int i;
@@ -483,10 +511,10 @@ mark_value_bits_unavailable (struct value *value, int offset, int length)
 
   */
 
-  i = VEC_lower_bound (range_s, value->unavailable, &newr, range_lessthan);
+  i = VEC_lower_bound (range_s, *vectorp, &newr, range_lessthan);
   if (i > 0)
     {
-      struct range *bef = VEC_index (range_s, value->unavailable, i - 1);
+      struct range *bef = VEC_index (range_s, *vectorp, i - 1);
 
       if (ranges_overlap (bef->offset, bef->length, offset, length))
 	{
@@ -507,18 +535,18 @@ mark_value_bits_unavailable (struct value *value, int offset, int length)
       else
 	{
 	  /* #3 */
-	  VEC_safe_insert (range_s, value->unavailable, i, &newr);
+	  VEC_safe_insert (range_s, *vectorp, i, &newr);
 	}
     }
   else
     {
       /* #4 */
-      VEC_safe_insert (range_s, value->unavailable, i, &newr);
+      VEC_safe_insert (range_s, *vectorp, i, &newr);
     }
 
   /* Check whether the ranges following the one we've just added or
      touched can be folded in (#5 above).  */
-  if (i + 1 < VEC_length (range_s, value->unavailable))
+  if (i + 1 < VEC_length (range_s, *vectorp))
     {
       struct range *t;
       struct range *r;
@@ -526,11 +554,11 @@ mark_value_bits_unavailable (struct value *value, int offset, int length)
       int next = i + 1;
 
       /* Get the range we just touched.  */
-      t = VEC_index (range_s, value->unavailable, i);
+      t = VEC_index (range_s, *vectorp, i);
       removed = 0;
 
       i = next;
-      for (; VEC_iterate (range_s, value->unavailable, i, r); i++)
+      for (; VEC_iterate (range_s, *vectorp, i, r); i++)
 	if (r->offset <= t->offset + t->length)
 	  {
 	    ULONGEST l, h;
@@ -552,11 +580,17 @@ mark_value_bits_unavailable (struct value *value, int offset, int length)
 	  }
 
       if (removed != 0)
-	VEC_block_remove (range_s, value->unavailable, next, removed);
+	VEC_block_remove (range_s, *vectorp, next, removed);
     }
 }
 
 void
+mark_value_bits_unavailable (struct value *value, int offset, int length)
+{
+  insert_into_bit_range_vector (&value->unavailable, offset, length);
+}
+
+void
 mark_value_bytes_unavailable (struct value *value, int offset, int length)
 {
   mark_value_bits_unavailable (value,
@@ -684,48 +718,53 @@ memcmp_with_bit_offsets (const gdb_byte *ptr1, size_t offset1_bits,
   return 0;
 }
 
-/* Helper function for value_available_contents_eq. The only difference is
-   that this function is bit rather than byte based.
+/* Helper struct for cmp_ranges and value_contents_bits_eq.  Keep
+   track of which slot in a given ranges VEC have we last looked
+   at.  */
 
-   Compare LENGTH bits of VAL1's contents starting at OFFSET1 bits with
-   LENGTH bits of VAL2's contents starting at OFFSET2 bits.  Return true
-   if the available bits match.  */
+struct ranges_and_idx
+{
+  /* The ranges.  */
+  VEC(range_s) *ranges;
+
+  /* The range we've last found in RANGES.  Given ranges are sorted,
+     we can start the next lookup here.  */
+  int idx;
+};
+
+/* Helper function for value_contents_bits_eq.  Compare LENGTH bits of
+   RP1's ranges starting at OFFSET1 bits with LENGTH bits of RP2's
+   ranges starting at OFFSET2 bits.  Return true if the ranges match
+   and fill in *L and *H with the overlapping window relative to
+   (both) OFFSET1 or OFFSET2.  */
 
 static int
-value_available_contents_bits_eq (const struct value *val1, int offset1,
-				  const struct value *val2, int offset2,
-				  int length)
+find_first_range_overlap_and_match (struct ranges_and_idx *rp1,
+				    struct ranges_and_idx *rp2,
+				    int offset1, int offset2,
+				    int length, ULONGEST *l, ULONGEST *h)
 {
-  int idx1 = 0, idx2 = 0;
-
-  /* See function description in value.h.  */
-  gdb_assert (!val1->lazy && !val2->lazy);
+  rp1->idx = find_first_range_overlap (rp1->ranges, rp1->idx,
+				       offset1, length);
+  rp2->idx = find_first_range_overlap (rp2->ranges, rp2->idx,
+				       offset2, length);
 
-  while (length > 0)
+  if (rp1->idx == -1 && rp2->idx == -1)
+    {
+      *l = length;
+      *h = length;
+      return 1;
+    }
+  else if (rp1->idx == -1 || rp2->idx == -1)
+    return 0;
+  else
     {
       range_s *r1, *r2;
       ULONGEST l1, h1;
       ULONGEST l2, h2;
 
-      idx1 = find_first_range_overlap (val1->unavailable, idx1,
-				       offset1, length);
-      idx2 = find_first_range_overlap (val2->unavailable, idx2,
-				       offset2, length);
-
-      /* The usual case is for both values to be completely available.  */
-      if (idx1 == -1 && idx2 == -1)
-	return (memcmp_with_bit_offsets (val1->contents, offset1,
-					 val2->contents, offset2,
-					 length) == 0);
-      /* The contents only match equal if the available set matches as
-	 well.  */
-      else if (idx1 == -1 || idx2 == -1)
-	return 0;
-
-      gdb_assert (idx1 != -1 && idx2 != -1);
-
-      r1 = VEC_index (range_s, val1->unavailable, idx1);
-      r2 = VEC_index (range_s, val2->unavailable, idx2);
+      r1 = VEC_index (range_s, rp1->ranges, rp1->idx);
+      r2 = VEC_index (range_s, rp2->ranges, rp2->idx);
 
       /* Get the unavailable windows intersected by the incoming
 	 ranges.  The first and last ranges that overlap the argument
@@ -734,7 +773,7 @@ value_available_contents_bits_eq (const struct value *val1, int offset1,
       h1 = min (offset1 + length, r1->offset + r1->length);
 
       l2 = max (offset2, r2->offset);
-      h2 = min (offset2 + length, r2->offset + r2->length);
+      h2 = min (offset2 + length, offset2 + r2->length);
 
       /* Make them relative to the respective start offsets, so we can
 	 compare them for equality.  */
@@ -744,31 +783,93 @@ value_available_contents_bits_eq (const struct value *val1, int offset1,
       l2 -= offset2;
       h2 -= offset2;
 
-      /* Different availability, no match.  */
+      /* Different ranges, no match.  */
       if (l1 != l2 || h1 != h2)
 	return 0;
 
-      /* Compare the _available_ contents.  */
+      *h = h1;
+      *l = l1;
+      return 1;
+    }
+}
+
+/* Helper function for value_contents_eq.  The only difference is that
+   this function is bit rather than byte based.
+
+   Compare LENGTH bits of VAL1's contents starting at OFFSET1 bits
+   with LENGTH bits of VAL2's contents starting at OFFSET2 bits.
+   Return true if the available bits match.  */
+
+static int
+value_contents_bits_eq (const struct value *val1, int offset1,
+			const struct value *val2, int offset2,
+			int length)
+{
+  /* Each array element corresponds to a ranges source (unavailable,
+     optimized out).  '1' is for VAL1, '2' for VAL2.  */
+  struct ranges_and_idx rp1[2], rp2[2];
+
+  /* See function description in value.h.  */
+  gdb_assert (!val1->lazy && !val2->lazy);
+
+  /* We shouldn't be trying to compare past the end of the values.  */
+  gdb_assert (offset1 + length
+	      <= TYPE_LENGTH (val1->enclosing_type) * TARGET_CHAR_BIT);
+  gdb_assert (offset2 + length
+	      <= TYPE_LENGTH (val2->enclosing_type) * TARGET_CHAR_BIT);
+
+  memset (&rp1, 0, sizeof (rp1));
+  memset (&rp2, 0, sizeof (rp2));
+  rp1[0].ranges = val1->unavailable;
+  rp2[0].ranges = val2->unavailable;
+  rp1[1].ranges = val1->optimized_out;
+  rp2[1].ranges = val2->optimized_out;
+
+  while (length > 0)
+    {
+      ULONGEST l, h;
+      int i;
+
+      for (i = 0; i < 2; i++)
+	{
+	  ULONGEST l_tmp, h_tmp;
+
+	  /* The contents only match equal if the invalid/unavailable
+	     contents ranges match as well.  */
+	  if (!find_first_range_overlap_and_match (&rp1[i], &rp2[i],
+						   offset1, offset2, length,
+						   &l_tmp, &h_tmp))
+	    return 0;
+
+	  /* We're interested in the lowest/first range found.  */
+	  if (i == 0 || l_tmp < l)
+	    {
+	      l = l_tmp;
+	      h = h_tmp;
+	    }
+	}
+
+      /* Compare the available/valid contents.  */
       if (memcmp_with_bit_offsets (val1->contents, offset1,
-				   val2->contents, offset2, l1) != 0)
+				   val2->contents, offset2, l) != 0)
 	return 0;
 
-      length -= h1;
-      offset1 += h1;
-      offset2 += h1;
+      length -= h;
+      offset1 += h;
+      offset2 += h;
     }
 
   return 1;
 }
 
 int
-value_available_contents_eq (const struct value *val1, int offset1,
-			     const struct value *val2, int offset2,
-			     int length)
+value_contents_eq (const struct value *val1, int offset1,
+		   const struct value *val2, int offset2,
+		   int length)
 {
-  return value_available_contents_bits_eq (val1, offset1 * TARGET_CHAR_BIT,
-					   val2, offset2 * TARGET_CHAR_BIT,
-					   length * TARGET_CHAR_BIT);
+  return value_contents_bits_eq (val1, offset1 * TARGET_CHAR_BIT,
+				 val2, offset2 * TARGET_CHAR_BIT,
+				 length * TARGET_CHAR_BIT);
 }
 
 /* Prototypes for local functions.  */
@@ -836,7 +937,6 @@ allocate_value_lazy (struct type *type)
   val->bitsize = 0;
   VALUE_REGNUM (val) = -1;
   val->lazy = 1;
-  val->optimized_out = 0;
   val->embedded_offset = 0;
   val->pointed_to_offset = 0;
   val->modifiable = 1;
@@ -905,7 +1005,7 @@ allocate_optimized_out_value (struct type *type)
 {
   struct value *retval = allocate_value_lazy (type);
 
-  set_value_optimized_out (retval, 1);
+  mark_value_bytes_optimized_out (retval, 0, TYPE_LENGTH (type));
   set_value_lazy (retval, 0);
   return retval;
 }
@@ -1054,7 +1154,7 @@ error_value_optimized_out (void)
 static void
 require_not_optimized_out (const struct value *value)
 {
-  if (value->optimized_out)
+  if (!VEC_empty (range_s, value->optimized_out))
     {
       if (value->lval == lval_register)
 	error (_("register has not been saved in frame"));
@@ -1094,6 +1194,31 @@ value_contents_all (struct value *value)
   return result;
 }
 
+/* Copy ranges in SRC_RANGE that overlap [SRC_BIT_OFFSET,
+   SRC_BIT_OFFSET+BIT_LENGTH) ranges into *DST_RANGE, adjusted.  */
+
+static void
+ranges_copy_adjusted (VEC (range_s) **dst_range, int dst_bit_offset,
+		      VEC (range_s) *src_range, int src_bit_offset,
+		      int bit_length)
+{
+  range_s *r;
+  int i;
+
+  for (i = 0; VEC_iterate (range_s, src_range, i, r); i++)
+    {
+      ULONGEST h, l;
+
+      l = max (r->offset, src_bit_offset);
+      h = min (r->offset + r->length, src_bit_offset + bit_length);
+
+      if (l < h)
+	insert_into_bit_range_vector (dst_range,
+				      dst_bit_offset + (l - src_bit_offset),
+				      h - l);
+    }
+}
+
 /* Copy LENGTH bytes of SRC value's (all) contents
    (value_contents_all) starting at SRC_OFFSET, into DST value's (all)
    contents, starting at DST_OFFSET.  If unavailable contents are
@@ -1122,6 +1247,9 @@ value_contents_copy_raw (struct value *dst, int dst_offset,
      replaced.  Make sure to remember to implement replacing if it
      turns out actually necessary.  */
   gdb_assert (value_bytes_available (dst, dst_offset, length));
+  gdb_assert (!value_bits_any_optimized_out (dst,
+					     TARGET_CHAR_BIT * dst_offset,
+					     TARGET_CHAR_BIT * length));
 
   /* Copy the data.  */
   memcpy (value_contents_all_raw (dst) + dst_offset,
@@ -1132,18 +1260,14 @@ value_contents_copy_raw (struct value *dst, int dst_offset,
   src_bit_offset = src_offset * TARGET_CHAR_BIT;
   dst_bit_offset = dst_offset * TARGET_CHAR_BIT;
   bit_length = length * TARGET_CHAR_BIT;
-  for (i = 0; VEC_iterate (range_s, src->unavailable, i, r); i++)
-    {
-      ULONGEST h, l;
 
-      l = max (r->offset, src_bit_offset);
-      h = min (r->offset + r->length, src_bit_offset + bit_length);
+  ranges_copy_adjusted (&dst->unavailable, dst_bit_offset,
+			src->unavailable, src_bit_offset,
+			bit_length);
 
-      if (l < h)
-	mark_value_bits_unavailable (dst,
-				     dst_bit_offset + (l - src_bit_offset),
-				     h - l);
-    }
+  ranges_copy_adjusted (&dst->optimized_out, dst_bit_offset,
+			src->optimized_out, src_bit_offset,
+			bit_length);
 }
 
 /* Copy LENGTH bytes of SRC value's (all) contents
@@ -1151,8 +1275,7 @@ value_contents_copy_raw (struct value *dst, int dst_offset,
    (all) contents, starting at DST_OFFSET.  If unavailable contents
    are being copied from SRC, the corresponding DST contents are
    marked unavailable accordingly.  DST must not be lazy.  If SRC is
-   lazy, it will be fetched now.  If SRC is not valid (is optimized
-   out), an error is thrown.
+   lazy, it will be fetched now.
 
    It is assumed the contents of DST in the [DST_OFFSET,
    DST_OFFSET+LENGTH) range are wholly available.  */
@@ -1161,8 +1284,6 @@ void
 value_contents_copy (struct value *dst, int dst_offset,
 		     struct value *src, int src_offset, int length)
 {
-  require_not_optimized_out (src);
-
   if (src->lazy)
     value_fetch_lazy (src);
 
@@ -1213,47 +1334,31 @@ value_contents_writeable (struct value *value)
 int
 value_optimized_out (struct value *value)
 {
-  /* We can only know if a value is optimized out once we have tried to
-     fetch it.  */
-  if (!value->optimized_out && value->lazy)
+  /* We can only know if a value is optimized out once we have tried
+     to fetch it.  */
+  if (VEC_empty (range_s, value->optimized_out) && value->lazy)
     value_fetch_lazy (value);
 
-  return value->optimized_out;
+  return !VEC_empty (range_s, value->optimized_out);
 }
 
-int
-value_optimized_out_const (const struct value *value)
-{
-  return value->optimized_out;
-}
+/* Mark contents of VALUE as optimized out, starting at OFFSET bytes, and
+   the following LENGTH bytes.  */
 
 void
-set_value_optimized_out (struct value *value, int val)
+mark_value_bytes_optimized_out (struct value *value, int offset, int length)
 {
-  value->optimized_out = val;
+  mark_value_bits_optimized_out (value,
+				 offset * TARGET_CHAR_BIT,
+				 length * TARGET_CHAR_BIT);
 }
 
-int
-value_entirely_optimized_out (const struct value *value)
-{
-  if (!value->optimized_out)
-    return 0;
-  if (value->lval != lval_computed
-      || !value->location.computed.funcs->check_any_valid)
-    return 1;
-  return !value->location.computed.funcs->check_any_valid (value);
-}
+/* See value.h.  */
 
-int
-value_bits_valid (const struct value *value, int offset, int length)
+void
+mark_value_bits_optimized_out (struct value *value, int offset, int length)
 {
-  if (!value->optimized_out)
-    return 1;
-  if (value->lval != lval_computed
-      || !value->location.computed.funcs->check_validity)
-    return 0;
-  return value->location.computed.funcs->check_validity (value, offset,
-							 length);
+  insert_into_bit_range_vector (&value->optimized_out, offset, length);
 }
 
 int
@@ -1566,7 +1671,6 @@ value_copy (struct value *arg)
   VALUE_FRAME_ID (val) = VALUE_FRAME_ID (arg);
   VALUE_REGNUM (val) = VALUE_REGNUM (arg);
   val->lazy = arg->lazy;
-  val->optimized_out = arg->optimized_out;
   val->embedded_offset = value_embedded_offset (arg);
   val->pointed_to_offset = arg->pointed_to_offset;
   val->modifiable = arg->modifiable;
@@ -2851,24 +2955,19 @@ value_primitive_field (struct value *arg1, int offset,
       int bitpos = TYPE_FIELD_BITPOS (arg_type, fieldno);
       int container_bitsize = TYPE_LENGTH (type) * 8;
 
-      if (arg1->optimized_out)
-	v = allocate_optimized_out_value (type);
+      v = allocate_value_lazy (type);
+      v->bitsize = TYPE_FIELD_BITSIZE (arg_type, fieldno);
+      if ((bitpos % container_bitsize) + v->bitsize <= container_bitsize
+	  && TYPE_LENGTH (type) <= (int) sizeof (LONGEST))
+	v->bitpos = bitpos % container_bitsize;
       else
-	{
-	  v = allocate_value_lazy (type);
-	  v->bitsize = TYPE_FIELD_BITSIZE (arg_type, fieldno);
-	  if ((bitpos % container_bitsize) + v->bitsize <= container_bitsize
-	      && TYPE_LENGTH (type) <= (int) sizeof (LONGEST))
-	    v->bitpos = bitpos % container_bitsize;
-	  else
-	    v->bitpos = bitpos % 8;
-	  v->offset = (value_embedded_offset (arg1)
-		       + offset
-		       + (bitpos - v->bitpos) / 8);
-	  set_value_parent (v, arg1);
-	  if (!value_lazy (arg1))
-	    value_fetch_lazy (v);
-	}
+	v->bitpos = bitpos % 8;
+      v->offset = (value_embedded_offset (arg1)
+		   + offset
+		   + (bitpos - v->bitpos) / 8);
+      set_value_parent (v, arg1);
+      if (!value_lazy (arg1))
+	value_fetch_lazy (v);
     }
   else if (fieldno < TYPE_N_BASECLASSES (arg_type))
     {
@@ -2881,37 +2980,29 @@ value_primitive_field (struct value *arg1, int offset,
       if (VALUE_LVAL (arg1) == lval_register && value_lazy (arg1))
 	value_fetch_lazy (arg1);
 
-      /* The optimized_out flag is only set correctly once a lazy value is
-         loaded, having just loaded some lazy values we should check the
-         optimized out case now.  */
-      if (arg1->optimized_out)
-	v = allocate_optimized_out_value (type);
+      /* We special case virtual inheritance here because this
+	 requires access to the contents, which we would rather avoid
+	 for references to ordinary fields of unavailable values.  */
+      if (BASETYPE_VIA_VIRTUAL (arg_type, fieldno))
+	boffset = baseclass_offset (arg_type, fieldno,
+				    value_contents (arg1),
+				    value_embedded_offset (arg1),
+				    value_address (arg1),
+				    arg1);
       else
-	{
-	  /* We special case virtual inheritance here because this
-	     requires access to the contents, which we would rather avoid
-	     for references to ordinary fields of unavailable values.  */
-	  if (BASETYPE_VIA_VIRTUAL (arg_type, fieldno))
-	    boffset = baseclass_offset (arg_type, fieldno,
-					value_contents (arg1),
-					value_embedded_offset (arg1),
-					value_address (arg1),
-					arg1);
-	  else
-	    boffset = TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
+	boffset = TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
 
-	  if (value_lazy (arg1))
-	    v = allocate_value_lazy (value_enclosing_type (arg1));
-	  else
-	    {
-	      v = allocate_value (value_enclosing_type (arg1));
-	      value_contents_copy_raw (v, 0, arg1, 0,
-				       TYPE_LENGTH (value_enclosing_type (arg1)));
-	    }
-	  v->type = type;
-	  v->offset = value_offset (arg1);
-	  v->embedded_offset = offset + value_embedded_offset (arg1) + boffset;
+      if (value_lazy (arg1))
+	v = allocate_value_lazy (value_enclosing_type (arg1));
+      else
+	{
+	  v = allocate_value (value_enclosing_type (arg1));
+	  value_contents_copy_raw (v, 0, arg1, 0,
+				   TYPE_LENGTH (value_enclosing_type (arg1)));
 	}
+      v->type = type;
+      v->offset = value_offset (arg1);
+      v->embedded_offset = offset + value_embedded_offset (arg1) + boffset;
     }
   else
     {
@@ -2922,12 +3013,7 @@ value_primitive_field (struct value *arg1, int offset,
       if (VALUE_LVAL (arg1) == lval_register && value_lazy (arg1))
 	value_fetch_lazy (arg1);
 
-      /* The optimized_out flag is only set correctly once a lazy value is
-         loaded, having just loaded some lazy values we should check for
-         the optimized out case now.  */
-      if (arg1->optimized_out)
-	v = allocate_optimized_out_value (type);
-      else if (value_lazy (arg1))
+      if (value_lazy (arg1))
 	v = allocate_value_lazy (type);
       else
 	{
@@ -3646,6 +3732,11 @@ value_fetch_lazy (struct value *val)
 {
   gdb_assert (value_lazy (val));
   allocate_value_contents (val);
+  /* A value is either lazy, or fully fetched.  The
+     availability/validity is only established as we try to fetch a
+     value.  */
+  gdb_assert (VEC_empty (range_s, val->optimized_out));
+  gdb_assert (VEC_empty (range_s, val->unavailable));
   if (value_bitsize (val))
     {
       /* To read a lazy bitfield, read the entire enclosing value.  This
@@ -3662,10 +3753,11 @@ value_fetch_lazy (struct value *val)
       if (value_lazy (parent))
 	value_fetch_lazy (parent);
 
-      if (!value_bits_valid (parent,
-			     TARGET_CHAR_BIT * offset + value_bitpos (val),
-			     value_bitsize (val)))
-	set_value_optimized_out (val, 1);
+      if (value_bits_any_optimized_out (parent,
+					TARGET_CHAR_BIT * offset + value_bitpos (val),
+					value_bitsize (val)))
+	mark_value_bytes_optimized_out (val, value_embedded_offset (val),
+					TYPE_LENGTH (type));
       else if (!unpack_value_bits_as_long (value_type (val),
 				      value_contents_for_printing (parent),
 				      offset,
@@ -3740,16 +3832,12 @@ value_fetch_lazy (struct value *val)
       if (value_lazy (new_val))
 	value_fetch_lazy (new_val);
 
-      /* If the register was not saved, mark it optimized out.  */
-      if (value_optimized_out (new_val))
-	set_value_optimized_out (val, 1);
-      else
-	{
-	  set_value_lazy (val, 0);
-	  value_contents_copy (val, value_embedded_offset (val),
-			       new_val, value_embedded_offset (new_val),
-			       TYPE_LENGTH (type));
-	}
+      /* Copy the contents and the unavailability/optimized-out
+	 meta-data from NEW_VAL to VAL.  */
+      set_value_lazy (val, 0);
+      value_contents_copy (val, value_embedded_offset (val),
+			   new_val, value_embedded_offset (new_val),
+			   TYPE_LENGTH (type));
 
       if (frame_debug)
 	{
@@ -3802,11 +3890,6 @@ value_fetch_lazy (struct value *val)
   else if (VALUE_LVAL (val) == lval_computed
 	   && value_computed_funcs (val)->read != NULL)
     value_computed_funcs (val)->read (val);
-  /* Don't call value_optimized_out on val, doing so would result in a
-     recursive call back to value_fetch_lazy, instead check the
-     optimized_out flag directly.  */
-  else if (val->optimized_out)
-    /* Keep it optimized out.  */;
   else
     internal_error (__FILE__, __LINE__, _("Unexpected lazy value type."));
 
diff --git a/gdb/value.h b/gdb/value.h
index 86ebd70..5380f76 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -33,6 +33,43 @@ struct language_defn;
 struct value_print_options;
 struct xmethod_worker;
 
+/* Values can be partially 'optimized out' and/or 'unavailable'.
+   These are distinct states and have different string representations
+   and related error strings.
+
+   'unavailable' has a specific meaning in this context.  It means the
+   value exists in the program (at the machine level), but GDB has no
+   means to get to it.  Such a value is normally printed as.  Examples
+   of how to end up with an unavailable value would be:
+
+    - We're inspecting a traceframe, and the memory or registers the
+      debug information says the value lives on haven't been collected.
+
+    - We're inspecting a core dump, the memory or registers the debug
+      information says the value lives aren't present in the dump
+      (that is, we have a partial/trimmed core dump, or we don't fully
+      understand/handle the core dump's format).
+
+    - We're doing live debugging, but the debug API has no means to
+      get at where the value lives in the machine, like e.g., ptrace
+      not having access to some register or register set.
+
+    - Any other similar scenario.
+
+  OTOH, "optimized out" is about what the compiler decided to generate
+  (or not generate).  A chunk of a value that was optimized out does
+  not actually exist in the program.  There's no way to get at it
+  short of compiling the program differently.  A register that has not
+  been saved in a frame is likewise considered optimized out, except
+  not-saved registers have a different string representation and
+  related error strings.  E.g., we'll print them as <not-saved>
+  instead of <optimized out>.
+
+  When comparing value contents, optimized out chunks, unavailable
+  chunks, and valid contents data are all all considered different.
+  See value_contents_eq for more info.
+*/
+
 /* The structure which defines the type of a value.  It should never
    be possible for a program lval value to survive over a call to the
    inferior (i.e. to be put into the history list or an internal
@@ -181,14 +218,6 @@ struct lval_funcs
      TOVAL is not considered as an lvalue.  */
   void (*write) (struct value *toval, struct value *fromval);
 
-  /* Check the validity of some bits in VALUE.  This should return 1
-     if all the bits starting at OFFSET and extending for LENGTH bits
-     are valid, or 0 if any bit is invalid.  */
-  int (*check_validity) (const struct value *value, int offset, int length);
-
-  /* Return 1 if any bit in VALUE is valid, 0 if they are all invalid.  */
-  int (*check_any_valid) (const struct value *value);
-
   /* If non-NULL, this is used to implement pointer indirection for
      this value.  This method may return NULL, in which case value_ind
      will fall back to ordinary indirection.  */
@@ -327,16 +356,29 @@ extern int value_fetch_lazy (struct value *val);
    exist in the program, at least partially.  If the value is lazy,
    this may fetch it now.  */
 extern int value_optimized_out (struct value *value);
-extern void set_value_optimized_out (struct value *value, int val);
 
-/* Like value_optimized_out, but don't fetch the value even if it is
-   lazy.  Mainly useful for constructing other values using VALUE as
-   template.  */
-extern int value_optimized_out_const (const struct value *value);
+/* Given a value, return true if any of the contents bits starting at
+   OFFSET and extending for LENGTH bits is optimized out, false
+   otherwise.  */
+
+extern int value_bits_any_optimized_out (const struct value *value,
+					 int bit_offset, int bit_length);
+
+/* Like value_optimized_out, but return true iff the whole value is
+   optimized out.  */
+extern int value_entirely_optimized_out (struct value *value);
+
+/* Mark VALUE's content bytes starting at OFFSET and extending for
+   LENGTH bytes as optimized out.  */
+
+extern void mark_value_bytes_optimized_out (struct value *value,
+					    int offset, int length);
+
+/* Mark VALUE's content bits starting at OFFSET and extending for
+   LENGTH bits as optimized out.  */
 
-/* Like value_optimized_out, but return false if any bit in the object
-   is valid.  */
-extern int value_entirely_optimized_out (const struct value *value);
+extern void mark_value_bits_optimized_out (struct value *value,
+					   int offset, int length);
 
 /* Set or return field indicating whether a variable is initialized or
    not, based on debugging information supplied by the compiler.
@@ -416,13 +458,6 @@ extern struct value *coerce_ref (struct value *value);
 extern struct value *coerce_array (struct value *value);
 
 /* Given a value, determine whether the bits starting at OFFSET and
-   extending for LENGTH bits are valid.  This returns nonzero if all
-   bits in the given range are valid, zero if any bit is invalid.  */
-
-extern int value_bits_valid (const struct value *value,
-			     int offset, int length);
-
-/* Given a value, determine whether the bits starting at OFFSET and
    extending for LENGTH bits are a synthetic pointer.  */
 
 extern int value_bits_synthetic_pointer (const struct value *value,
@@ -473,35 +508,53 @@ extern void mark_value_bits_unavailable (struct value *value,
    its enclosing type chunk, you'd do:
 
      int len = TYPE_LENGTH (check_typedef (value_enclosing_type (val)));
-     value_available_contents (val, 0, val, 0, len);
+     value_contents_eq (val, 0, val, 0, len);
+
+   Returns true iff the set of available/valid contents match.
+
+   Optimized out contents compare equal with optimized out contents,
+   and different with any non-optimized-out byte.
 
-   Returns true iff the set of available contents match.  Unavailable
-   contents compare equal with unavailable contents, and different
-   with any available byte.  For example, if 'x's represent an
-   unavailable byte, and 'V' and 'Z' represent different available
-   bytes, in a value with length 16:
+   Unavailable contents compare equal with unavailable contents, and
+   different with any non-unavailable byte.
 
-   offset:   0   4   8   12  16
-   contents: xxxxVVVVxxxxVVZZ
+   For example, if 'x's represent an unavailable byte, and 'V' and 'Z'
+   represent different available/valid bytes, in a value with length
+   16:
+
+     offset:   0   4   8   12  16
+     contents: xxxxVVVVxxxxVVZZ
 
    then:
 
-   value_available_contents_eq(val, 0, val, 8, 6) => 1
-   value_available_contents_eq(val, 0, val, 4, 4) => 1
-   value_available_contents_eq(val, 0, val, 8, 8) => 0
-   value_available_contents_eq(val, 4, val, 12, 2) => 1
-   value_available_contents_eq(val, 4, val, 12, 4) => 0
-   value_available_contents_eq(val, 3, val, 4, 4) => 0
-
-   We only know whether a value chunk is available if we've tried to
-   read it.  As this routine is used by printing routines, which may
-   be printing values in the value history, long after the inferior is
-   gone, it works with const values.  Therefore, this routine must not
-   be called with lazy values.  */
-
-extern int value_available_contents_eq (const struct value *val1, int offset1,
-					const struct value *val2, int offset2,
-					int length);
+     value_contents_eq(val, 0, val, 8, 6) => 1
+     value_contents_eq(val, 0, val, 4, 4) => 0
+     value_contents_eq(val, 0, val, 8, 8) => 0
+     value_contents_eq(val, 4, val, 12, 2) => 1
+     value_contents_eq(val, 4, val, 12, 4) => 0
+     value_contents_eq(val, 3, val, 4, 4) => 0
+
+   If 'x's represent an unavailable byte, 'o' represents an optimized
+   out byte, in a value with length 8:
+
+   offset:   0   4   8
+   contents: xxxxoooo
+
+   then:
+
+     value_contents_eq(val, 0, val, 2, 2) => 1
+     value_contents_eq(val, 4, val, 6, 2) => 1
+     value_contents_eq(val, 0, val, 4, 4) => 0
+
+   We only know whether a value chunk is unavailable or optimized out
+   if we've tried to read it.  As this routine is used by printing
+   routines, which may be printing values in the value history, long
+   after the inferior is gone, it works with const values.  Therefore,
+   this routine must not be called with lazy values.  */
+
+extern int value_contents_eq (const struct value *val1, int offset1,
+			      const struct value *val2, int offset2,
+			      int length);
 
 /* Read LENGTH bytes of memory starting at MEMADDR into BUFFER, which
    is (or will be copied to) VAL's contents buffer offset by
-- 
1.9.3


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] Handle partially optimized out values similarly to unavailable values (Re: [patchv2] Fix crash on optimized-out entry data values)
  2014-07-14 18:47     ` [PATCH] Handle partially optimized out values similarly to unavailable values (Re: [patchv2] Fix crash on optimized-out entry data values) Pedro Alves
@ 2014-07-17  8:04       ` Jan Kratochvil
  2014-07-17  8:35         ` Jan Kratochvil
                           ` (2 more replies)
  0 siblings, 3 replies; 28+ messages in thread
From: Jan Kratochvil @ 2014-07-17  8:04 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On Mon, 14 Jul 2014 20:11:41 +0200, Pedro Alves wrote:
[...]
> --- a/gdb/value.c
> +++ b/gdb/value.c
[...]
> @@ -339,6 +330,15 @@ struct value
>       value to be available.  This is filled in at value read time.  The
>       unavailable ranges are tracked in bits.  */
>    VEC(range_s) *unavailable;
> +
> +  /* Likewise, but for optimized out contents (a chunk of the value of
> +     a variable that does not actually exist in the program).  If LVAL
> +     is lval_register, this is a register ($pc, $sp, etc., never a
> +     program variable) that has not been saved in the frame.  Not
> +     saved registers and optimized-out program variables values are
> +     treated pretty much the same, except not-saved registers have a
> +     different string representation and related error strings.  */
> +  VEC(range_s) *optimized_out;

I miss here explicit description if a bit of the range can appear on both 
'unavailable' and 'optimized_out'.  IMO it should not.


>  };
>  
>  int
[...]
> +/* Helper function for value_contents_eq.  The only difference is that
> +   this function is bit rather than byte based.
> +
> +   Compare LENGTH bits of VAL1's contents starting at OFFSET1 bits
> +   with LENGTH bits of VAL2's contents starting at OFFSET2 bits.
> +   Return true if the available bits match.  */
> +
> +static int
> +value_contents_bits_eq (const struct value *val1, int offset1,
> +			const struct value *val2, int offset2,
> +			int length)
> +{
> +  /* Each array element corresponds to a ranges source (unavailable,
> +     optimized out).  '1' is for VAL1, '2' for VAL2.  */
> +  struct ranges_and_idx rp1[2], rp2[2];
> +
> +  /* See function description in value.h.  */
> +  gdb_assert (!val1->lazy && !val2->lazy);
> +
> +  /* We shouldn't be trying to compare past the end of the values.  */
> +  gdb_assert (offset1 + length
> +	      <= TYPE_LENGTH (val1->enclosing_type) * TARGET_CHAR_BIT);
> +  gdb_assert (offset2 + length
> +	      <= TYPE_LENGTH (val2->enclosing_type) * TARGET_CHAR_BIT);
> +
> +  memset (&rp1, 0, sizeof (rp1));
> +  memset (&rp2, 0, sizeof (rp2));
> +  rp1[0].ranges = val1->unavailable;
> +  rp2[0].ranges = val2->unavailable;
> +  rp1[1].ranges = val1->optimized_out;
> +  rp2[1].ranges = val2->optimized_out;
> +
> +  while (length > 0)
> +    {
> +      ULONGEST l, h;
> +      int i;
> +
> +      for (i = 0; i < 2; i++)
> +	{
> +	  ULONGEST l_tmp, h_tmp;
> +
> +	  /* The contents only match equal if the invalid/unavailable
> +	     contents ranges match as well.  */
> +	  if (!find_first_range_overlap_and_match (&rp1[i], &rp2[i],
> +						   offset1, offset2, length,
> +						   &l_tmp, &h_tmp))
> +	    return 0;
> +
> +	  /* We're interested in the lowest/first range found.  */
> +	  if (i == 0 || l_tmp < l)

Here should be:
   	  if (i == 0 || l_tmp < l || (l_tmp == l && h_tmp < h))

It could skip [0]'s part which is non-equal otherwise.


> +	    {
> +	      l = l_tmp;
> +	      h = h_tmp;
> +	    }
> +	}
> +
> +      /* Compare the available/valid contents.  */
>        if (memcmp_with_bit_offsets (val1->contents, offset1,
> -				   val2->contents, offset2, l1) != 0)
> +				   val2->contents, offset2, l) != 0)
>  	return 0;
>  
> -      length -= h1;
> -      offset1 += h1;
> -      offset2 += h1;
> +      length -= h;
> +      offset1 += h;
> +      offset2 += h;
>      }
>  
>    return 1;
>  }
[...]
> @@ -1566,7 +1671,6 @@ value_copy (struct value *arg)
>    VALUE_FRAME_ID (val) = VALUE_FRAME_ID (arg);
>    VALUE_REGNUM (val) = VALUE_REGNUM (arg);
>    val->lazy = arg->lazy;
> -  val->optimized_out = arg->optimized_out;

Why 'optimized_out' no longer needs to be copied?


>    val->embedded_offset = value_embedded_offset (arg);
>    val->pointed_to_offset = arg->pointed_to_offset;
>    val->modifiable = arg->modifiable;
[...]
> @@ -3662,10 +3753,11 @@ value_fetch_lazy (struct value *val)
>        if (value_lazy (parent))
>  	value_fetch_lazy (parent);
>  
> -      if (!value_bits_valid (parent,
> -			     TARGET_CHAR_BIT * offset + value_bitpos (val),
> -			     value_bitsize (val)))
> -	set_value_optimized_out (val, 1);
> +      if (value_bits_any_optimized_out (parent,
> +					TARGET_CHAR_BIT * offset + value_bitpos (val),
> +					value_bitsize (val)))
> +	mark_value_bytes_optimized_out (val, value_embedded_offset (val),
> +					TYPE_LENGTH (type));

That was required before but it could handle partially optimized out
bitfields; but maybe it is not useful much.


>        else if (!unpack_value_bits_as_long (value_type (val),
>  				      value_contents_for_printing (parent),
>  				      offset,
[...]
> --- a/gdb/value.h
> +++ b/gdb/value.h
> @@ -33,6 +33,43 @@ struct language_defn;
>  struct value_print_options;
>  struct xmethod_worker;
>  
> +/* Values can be partially 'optimized out' and/or 'unavailable'.
> +   These are distinct states and have different string representations
> +   and related error strings.
> +
> +   'unavailable' has a specific meaning in this context.  It means the
> +   value exists in the program (at the machine level), but GDB has no
> +   means to get to it.  Such a value is normally printed as.  Examples

"printed as." - is the sentence finished?


> +   of how to end up with an unavailable value would be:
> +
> +    - We're inspecting a traceframe, and the memory or registers the
> +      debug information says the value lives on haven't been collected.
> +
> +    - We're inspecting a core dump, the memory or registers the debug
> +      information says the value lives aren't present in the dump
> +      (that is, we have a partial/trimmed core dump, or we don't fully
> +      understand/handle the core dump's format).
> +
> +    - We're doing live debugging, but the debug API has no means to
> +      get at where the value lives in the machine, like e.g., ptrace
> +      not having access to some register or register set.
> +
> +    - Any other similar scenario.
> +
> +  OTOH, "optimized out" is about what the compiler decided to generate
> +  (or not generate).  A chunk of a value that was optimized out does
> +  not actually exist in the program.  There's no way to get at it
> +  short of compiling the program differently.  A register that has not
> +  been saved in a frame is likewise considered optimized out, except
> +  not-saved registers have a different string representation and
> +  related error strings.  E.g., we'll print them as <not-saved>

s/<not-saved>/<unavailable>/?


> +  instead of <optimized out>.
> +
> +  When comparing value contents, optimized out chunks, unavailable
> +  chunks, and valid contents data are all all considered different.
> +  See value_contents_eq for more info.
> +*/
> +
>  /* The structure which defines the type of a value.  It should never
>     be possible for a program lval value to survive over a call to the
>     inferior (i.e. to be put into the history list or an internal
[...]
> @@ -473,35 +508,53 @@ extern void mark_value_bits_unavailable (struct value *value,
>     its enclosing type chunk, you'd do:
>  
>       int len = TYPE_LENGTH (check_typedef (value_enclosing_type (val)));
> -     value_available_contents (val, 0, val, 0, len);
> +     value_contents_eq (val, 0, val, 0, len);
> +
> +   Returns true iff the set of available/valid contents match.
> +
> +   Optimized out contents compare equal with optimized out contents,
> +   and different with any non-optimized-out byte.

English: s/different/differ/

>  
> -   Returns true iff the set of available contents match.  Unavailable
> -   contents compare equal with unavailable contents, and different
> -   with any available byte.  For example, if 'x's represent an
> -   unavailable byte, and 'V' and 'Z' represent different available
> -   bytes, in a value with length 16:
> +   Unavailable contents compare equal with unavailable contents, and
> +   different with any non-unavailable byte.

English: s/different/differ/

>  
> -   offset:   0   4   8   12  16
> -   contents: xxxxVVVVxxxxVVZZ
> +   For example, if 'x's represent an unavailable byte, and 'V' and 'Z'
> +   represent different available/valid bytes, in a value with length
> +   16:
> +
> +     offset:   0   4   8   12  16
> +     contents: xxxxVVVVxxxxVVZZ
>  
>     then:
>  
> -   value_available_contents_eq(val, 0, val, 8, 6) => 1
> -   value_available_contents_eq(val, 0, val, 4, 4) => 1
> -   value_available_contents_eq(val, 0, val, 8, 8) => 0
> -   value_available_contents_eq(val, 4, val, 12, 2) => 1
> -   value_available_contents_eq(val, 4, val, 12, 4) => 0
> -   value_available_contents_eq(val, 3, val, 4, 4) => 0
> -
> -   We only know whether a value chunk is available if we've tried to
> -   read it.  As this routine is used by printing routines, which may
> -   be printing values in the value history, long after the inferior is
> -   gone, it works with const values.  Therefore, this routine must not
> -   be called with lazy values.  */
> -
> -extern int value_available_contents_eq (const struct value *val1, int offset1,
> -					const struct value *val2, int offset2,
> -					int length);
> +     value_contents_eq(val, 0, val, 8, 6) => 1
> +     value_contents_eq(val, 0, val, 4, 4) => 0
> +     value_contents_eq(val, 0, val, 8, 8) => 0
> +     value_contents_eq(val, 4, val, 12, 2) => 1
> +     value_contents_eq(val, 4, val, 12, 4) => 0
> +     value_contents_eq(val, 3, val, 4, 4) => 0
> +
> +   If 'x's represent an unavailable byte, 'o' represents an optimized
> +   out byte, in a value with length 8:
> +
> +   offset:   0   4   8
> +   contents: xxxxoooo
> +
> +   then:
> +
> +     value_contents_eq(val, 0, val, 2, 2) => 1
> +     value_contents_eq(val, 4, val, 6, 2) => 1
> +     value_contents_eq(val, 0, val, 4, 4) => 0
> +
> +   We only know whether a value chunk is unavailable or optimized out
> +   if we've tried to read it.  As this routine is used by printing
> +   routines, which may be printing values in the value history, long
> +   after the inferior is gone, it works with const values.  Therefore,
> +   this routine must not be called with lazy values.  */
[...]


This patch is apparently not suitable for gdb-7.8 which is I guess often
crashing on -O2 -g entry values so there could be some rather minimal crash
avoiding patch instead.


Thanks,
Jan

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] Handle partially optimized out values similarly to unavailable values (Re: [patchv2] Fix crash on optimized-out entry data values)
  2014-07-17  8:04       ` Jan Kratochvil
@ 2014-07-17  8:35         ` Jan Kratochvil
  2014-07-17 13:38         ` Pedro Alves
  2014-07-24 12:51         ` [PATCH v2] Handle partially optimized out values similarly to unavailable values Pedro Alves
  2 siblings, 0 replies; 28+ messages in thread
From: Jan Kratochvil @ 2014-07-17  8:35 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On Wed, 16 Jul 2014 23:58:38 +0200, Jan Kratochvil wrote:
> On Mon, 14 Jul 2014 20:11:41 +0200, Pedro Alves wrote:
> > +	  /* The contents only match equal if the invalid/unavailable
> > +	     contents ranges match as well.  */
> > +	  if (!find_first_range_overlap_and_match (&rp1[i], &rp2[i],
> > +						   offset1, offset2, length,
> > +						   &l_tmp, &h_tmp))
> > +	    return 0;
> > +
> > +	  /* We're interested in the lowest/first range found.  */
> > +	  if (i == 0 || l_tmp < l)
> 
> Here should be:
>    	  if (i == 0 || l_tmp < l || (l_tmp == l && h_tmp < h))
> 
> It could skip [0]'s part which is non-equal otherwise.

No, the code was OK.  This comes from the fact that 'unavailable' and
'optimized_out' ranges cannot overlap (probably, I ask for its clarification
somewhere else in the mail).

Maybe it would be all easier to have there single map and each range mapping
into enum { VALID, OPTIMIZED_OUT, UNAVAILABLE }.


Jan

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] Handle partially optimized out values similarly to unavailable values (Re: [patchv2] Fix crash on optimized-out entry data values)
  2014-07-17  8:04       ` Jan Kratochvil
  2014-07-17  8:35         ` Jan Kratochvil
@ 2014-07-17 13:38         ` Pedro Alves
  2014-07-20 15:33           ` [read_frame_arg patch] " Jan Kratochvil
  2014-07-24 12:51         ` [PATCH v2] Handle partially optimized out values similarly to unavailable values Pedro Alves
  2 siblings, 1 reply; 28+ messages in thread
From: Pedro Alves @ 2014-07-17 13:38 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

On 07/16/2014 10:58 PM, Jan Kratochvil wrote:
> 
> 
> This patch is apparently not suitable for gdb-7.8 which is I guess often
> crashing on -O2 -g entry values so there could be some rather minimal crash
> avoiding patch instead.
> 

Yeah.

So this was originally "caused" (more exposed) by 4f14910f:
    
        gdb/ChangeLog
        2013-11-26  Andrew Burgess  <aburgess@broadcom.com>
    
            * value.c (allocate_optimized_out_value): Mark value as non-lazy.

I tried a few approaches in value_available_contents_eq
today, and ended up thinking that the simplest should be to
just revert that patch until we have the fuller fix in place.

While doing just that fixes the crash, it surprisingly causes
one of your new tests to FAIL:

 (gdb) frame
 #0  bar (ref=ref@entry=@0x7fffffffd184: 10) at gdb.arch/amd64-entry-value-paramref.cc:23
 23        vv++; /* break-here */
 (gdb) FAIL: gdb.arch/amd64-entry-value-paramref.exp: frame

If I instead make allocate_optimized_out_value not allocate
a lazy value, like:

 struct value *
 allocate_optimized_out_value (struct type *type)
 {
 -  struct value *retval = allocate_value_lazy (type);
 +  struct value *retval = allocate_value (type);
 
   set_value_optimized_out (retval, 1);
 -  set_value_lazy (retval, 0);
   return retval;
 }

Then the test passes.

 (gdb) PASS: gdb.arch/amd64-entry-value-paramref.exp: continue to breakpoint: break-here
 frame
 #0  bar (ref=@0x7fffffffd184: 10, ref@entry=@0x7fffffffd184: <optimized out>) at gdb.arch/amd64-entry-value-paramref.cc:23
 23        vv++; /* break-here */
 (gdb) PASS: gdb.arch/amd64-entry-value-paramref.exp: frame

The difference is that if we let the value be lazy, value_fetch_lazy
fetches contents from memory, and then those contents compare
equal with the non-entry value.

Hmm.  But that's odd, why would value_fetch_lazy fetch the value
from memory at all, it it started out as an optimized-out / not_lval
value?  What made it be lval_memory ?

Turns out it's the code disabled in value_of_dwarf_reg_entry:

  target_val = dwarf_entry_parameter_to_value (parameter,
					       TYPE_LENGTH (target_type),
					       target_type, caller_frame,
					       caller_per_cu);

  /* value_as_address dereferences TYPE_CODE_REF.  */
  addr = extract_typed_address (value_contents (outer_val), checked_type);

  /* The target entry value has artificial address of the entry value
     reference.  */
  VALUE_LVAL (target_val) = lval_memory;
  set_value_address (target_val, addr);

It looks quite wrong to me to just change a value's lval like that.

I ran the testsuite with that code disabled (like in the patch below),
and that caused no regressions.  I can't say I really understand the
intention here though.  What would we be missing if we removed that code?

------------------
From 91d05d6af2b36a701429219f37712e7c6f944c4f Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Thu, 17 Jul 2014 11:06:18 +0100
Subject: [PATCH] Fix crash on optimized-out entry data values

The tests at
<https://sourceware.org/ml/gdb-patches/2014-07/msg00277.html> show
that comparing a fully optimized out value's contents with a value
that has not been optimized out, or is partially optimized out crashes
GDB:

 (gdb) bt
 #0  __memcmp_sse4_1 () at ../sysdeps/x86_64/multiarch/memcmp-sse4.S:816
 #1  0x00000000005a1914 in memcmp_with_bit_offsets (ptr1=0x202b2f0 "\n", offset1_bits=0, ptr2=0x0, offset2_bits=0, length_bits=32)
     at /home/pedro/gdb/mygit/build/../src/gdb/value.c:678
 #2  0x00000000005a1a05 in value_available_contents_bits_eq (val1=0x2361ad0, offset1=0, val2=0x23683b0, offset2=0, length=32)
     at /home/pedro/gdb/mygit/build/../src/gdb/value.c:717
 #3  0x00000000005a1c09 in value_available_contents_eq (val1=0x2361ad0, offset1=0, val2=0x23683b0, offset2=0, length=4)
     at /home/pedro/gdb/mygit/build/../src/gdb/value.c:769
 #4  0x00000000006033ed in read_frame_arg (sym=0x1b78d20, frame=0x19bca50, argp=0x7fff4aba82b0, entryargp=0x7fff4aba82d0)
     at /home/pedro/gdb/mygit/build/../src/gdb/stack.c:416
 #5  0x0000000000603abb in print_frame_args (func=0x1b78cb0, frame=0x19bca50, num=-1, stream=0x1aea450) at /home/pedro/gdb/mygit/build/../src/gdb/stack.c:671
 #6  0x0000000000604ae8 in print_frame (frame=0x19bca50, print_level=0, print_what=SRC_AND_LOC, print_args=1, sal=...)
     at /home/pedro/gdb/mygit/build/../src/gdb/stack.c:1205
 #7  0x0000000000604050 in print_frame_info (frame=0x19bca50, print_level=0, print_what=SRC_AND_LOC, print_args=1, set_current_sal=1)
     at /home/pedro/gdb/mygit/build/../src/gdb/stack.c:857
 #8  0x00000000006029b3 in print_stack_frame (frame=0x19bca50, print_level=0, print_what=SRC_AND_LOC, set_current_sal=1)
     at /home/pedro/gdb/mygit/build/../src/gdb/stack.c:169
 #9  0x00000000005fc4b8 in print_stop_event (ws=0x7fff4aba8790) at /home/pedro/gdb/mygit/build/../src/gdb/infrun.c:6068
 #10 0x00000000005fc830 in normal_stop () at /home/pedro/gdb/mygit/build/../src/gdb/infrun.c:6214

The 'ptr2=0x0' in frame #1 is val2->contents, and since git 4f14910f:

    gdb/ChangeLog
    2013-11-26  Andrew Burgess  <aburgess@broadcom.com>

        * value.c (allocate_optimized_out_value): Mark value as non-lazy.

... a fully optimized-out value can have it's value contents buffer
NULL.

As a spotgap fix, revert 4f14910f, with a comment.  A full fix would
be too invasive for 7.8.

gdb/
2014-07-17  Pedro Alves  <palves@redhat.com>

	* value.c (allocate_optimized_out_value): Don't mark value as
          non-lazy.
---
 gdb/dwarf2loc.c | 2 ++
 gdb/value.c     | 5 ++++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index fcab9b9..8ed3be0 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -1335,6 +1335,7 @@ value_of_dwarf_reg_entry (struct type *type, struct frame_info *frame,
 					       target_type, caller_frame,
 					       caller_per_cu);
 
+#if 0
   /* value_as_address dereferences TYPE_CODE_REF.  */
   addr = extract_typed_address (value_contents (outer_val), checked_type);
 
@@ -1342,6 +1343,7 @@ value_of_dwarf_reg_entry (struct type *type, struct frame_info *frame,
      reference.  */
   VALUE_LVAL (target_val) = lval_memory;
   set_value_address (target_val, addr);
+#endif
 
   release_value (target_val);
   val = allocate_computed_value (type, &entry_data_value_funcs,
diff --git a/gdb/value.c b/gdb/value.c
index 29abe5f..8b44a6d 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -906,7 +906,10 @@ allocate_optimized_out_value (struct type *type)
   struct value *retval = allocate_value_lazy (type);
 
   set_value_optimized_out (retval, 1);
-  set_value_lazy (retval, 0);
+  /* FIXME: we should be able to avoid allocating the value's contents
+     buffer, but value_available_contents_bits_eq can't handle
+     that.  */
+  /* set_value_lazy (retval, 0); */
   return retval;
 }
 
-- 
1.9.3


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [read_frame_arg patch] Handle partially optimized out values similarly to unavailable values (Re: [patchv2] Fix crash on optimized-out entry data values)
  2014-07-17 13:38         ` Pedro Alves
@ 2014-07-20 15:33           ` Jan Kratochvil
  2014-07-22 19:33             ` Pedro Alves
  0 siblings, 1 reply; 28+ messages in thread
From: Jan Kratochvil @ 2014-07-20 15:33 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 6582 bytes --]

On Thu, 17 Jul 2014 14:23:06 +0200, Pedro Alves wrote:
> On 07/16/2014 10:58 PM, Jan Kratochvil wrote:
> > This patch is apparently not suitable for gdb-7.8 which is I guess often
> > crashing on -O2 -g entry values so there could be some rather minimal crash
> > avoiding patch instead.
> 
> Yeah.
> 
> So this was originally "caused" (more exposed) by 4f14910f:
>     
>         gdb/ChangeLog
>         2013-11-26  Andrew Burgess  <aburgess@broadcom.com>
>     
>             * value.c (allocate_optimized_out_value): Mark value as non-lazy.
> 
> I tried a few approaches in value_available_contents_eq
> today, and ended up thinking that the simplest should be to
> just revert that patch until we have the fuller fix in place.

OK, that seems as the best solution for 7.8 to me.


> While doing just that fixes the crash, it surprisingly causes
> one of your new tests to FAIL:
> 
>  (gdb) frame
>  #0  bar (ref=ref@entry=@0x7fffffffd184: 10) at gdb.arch/amd64-entry-value-paramref.cc:23
>  23        vv++; /* break-here */
>  (gdb) FAIL: gdb.arch/amd64-entry-value-paramref.exp: frame

There is a bug in that entry value code of mine, fix attached.
The testcase then PASSes with the reverted optimization by Andrew Burgess.

For the attached fix - if you nitpick the missing conditional case:
	value_optimized_out (val_deref) && value_optimized_out (entryval_deref)
It is not detected there but that IMO does not matter much as
 * It is for 7.8 only, for trunk it will get compared correctly thanks to the
   new implementation of value_available_contents_eq()
   called value_contents_eq().
 * If the conditional
                      if (val != val_deref
                          && !value_optimized_out (val_deref)
                          && !value_optimized_out (entryval_deref)
                          && value_available_contents_eq (val_deref, 0,
                                                          entryval_deref, 0,
                                                      TYPE_LENGTH (type_deref)))
                        val_equal = 1;
   fails it may just print
     bar (ref=@0x7fffffffd904: <optimized out>, ref@entry=@0x7fffffffd904: <optimized out>)
   (or some variant with some partially optimized-out/unavailable parts)
   instead of the more correct
     bar (ref=ref@entry=@0x7fffffffd904: <optimized out>)
   which is not much a bug.

The attached fix no longe makes sense after the new implementation
of value_available_contents_eq() called value_contents_eq() gets applied as it
handles all the optimized-out/unavailable values on its own, therefore the
attached patch is really only for 7.8.


> Turns out it's the code disabled in value_of_dwarf_reg_entry:
> 
>   target_val = dwarf_entry_parameter_to_value (parameter,
> 					       TYPE_LENGTH (target_type),
> 					       target_type, caller_frame,
> 					       caller_per_cu);
> 
>   /* value_as_address dereferences TYPE_CODE_REF.  */
>   addr = extract_typed_address (value_contents (outer_val), checked_type);
> 
>   /* The target entry value has artificial address of the entry value
>      reference.  */
>   VALUE_LVAL (target_val) = lval_memory;
>   set_value_address (target_val, addr);
> 
> It looks quite wrong to me to just change a value's lval like that.
> 
> I ran the testsuite with that code disabled (like in the patch below),
> and that caused no regressions.  I can't say I really understand the
> intention here though.  What would we be missing if we removed that code?

I cannot reproduce any wrong case having the code above #if 0-ed.

I just do not find it correct to have it disabled.  But at the same time I do
like much / I do not find correct the code myself.  It is a bit problematic to
have struct value describing a memory content which is no longer present
there.

What happens there:
------------------------------------------------------------------------------
volatile int vv;
static __attribute__((noinline)) int
bar (int &ref) {
  ref = 20;
  vv++; /* break-here */
  return ref;
}
int main (void) {
  int var = 10;
  return bar (var);
}
------------------------------------------------------------------------------
 <4><c7>: Abbrev Number: 13 (DW_TAG_GNU_call_site_parameter)
    <c8>   DW_AT_location    : 1 byte block: 55         (DW_OP_reg5 (rdi))
    <ca>   DW_AT_GNU_call_site_value: 2 byte block: 91 74       (DW_OP_fbreg: -12)
    <cd>   DW_AT_GNU_call_site_data_value: 1 byte block: 3a     (DW_OP_lit10)
------------------------------------------------------------------------------
gdb -ex 'b value_addr' -ex r --args ../gdb ./1 -ex 'watch vv' -ex r -ex 'p &ref@entry'
->
6    return ref;
bar (ref=@0x7fffffffd944: 20, ref@entry=@0x7fffffffd944: 10) at 1.C:25
------------------------------------------------------------------------------
At /* break-here */ struct value variable 'ref' is TYPE_CODE_REF.

With FSF GDB HEAD:
(gdb) x/gx arg1.contents
0x6004000a4ad0: 0x00007fffffffd944
(gdb) p ((struct value *)arg1.location.computed.closure).lval
$1 = lval_memory
(gdb) p/x ((struct value *)arg1.location.computed.closure).location.address
$3 = 0x7fffffffd944

With your #if0-ed code:
(gdb) x/gx arg1.contents
0x6004000a4ad0: 0x00007fffffffd944
(gdb) p ((struct value *)arg1.location.computed.closure).lval
$8 = not_lval
(gdb) p/x ((struct value *)arg1.location.computed.closure).location.address
$9 = 0x0

I do not see how to access
	((struct value *)arg1.location.computed.closure).location.address
from GDB CLI.  Trying
(gdb) p &ref@entry
will invoke value_addr()'s:
  if (TYPE_CODE (type) == TYPE_CODE_REF)
      /* Copy the value, but change the type from (T&) to (T*).  We
         keep the same location information, which is efficient, and
         allows &(&X) to get the location containing the reference.  */
and therefore the address gets fetched already from
  arg1.contents
and not from
  ((struct value *)arg1.location.computed.closure).location.address
.

And for any other type than TYPE_CODE_REF this code you #if 0-ed does not get
executed at all.  This DW_AT_GNU_call_site_data_value DWARF was meant
primarily for Fortran but with -O0 entry values do not get produced
and with -Og and higher Fortran always optimizes out the passing by reference.

If you do not like the #if 0 code there I am OK with removing it as I do not
know how to make it's use reproducible for user anyway.  In the worst case
- if there really is some way how to exploit it - one should just get
  Attempt to take address of value not located in memory.
instead of some wrong value and it may be easy to fix then.


Thanks for the analysis,
Jan

[-- Attachment #2: 1 --]
[-- Type: text/plain, Size: 711 bytes --]

gdb/
2014-07-20  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* stack.c (read_frame_arg): Verify value_optimized_out before calling
	value_available_contents_eq.

diff --git a/gdb/stack.c b/gdb/stack.c
index 0d6d8e7..4db5df5 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -413,6 +413,8 @@ read_frame_arg (struct symbol *sym, struct frame_info *frame,
 		      /* If the reference addresses match but dereferenced
 			 content does not match print them.  */
 		      if (val != val_deref
+		          && !value_optimized_out (val_deref)
+		          && !value_optimized_out (entryval_deref)
 			  && value_available_contents_eq (val_deref, 0,
 							  entryval_deref, 0,
 						      TYPE_LENGTH (type_deref)))

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [read_frame_arg patch] Handle partially optimized out values similarly to unavailable values (Re: [patchv2] Fix crash on optimized-out entry data values)
  2014-07-20 15:33           ` [read_frame_arg patch] " Jan Kratochvil
@ 2014-07-22 19:33             ` Pedro Alves
  2014-07-22 20:21               ` [commit+7.8] [read_frame_arg patch] Handle partially optimized out values similarly to unavailable values Jan Kratochvil
  2014-07-23 14:26               ` [commit] Remove setting value address for reference entry value target data value Jan Kratochvil
  0 siblings, 2 replies; 28+ messages in thread
From: Pedro Alves @ 2014-07-22 19:33 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

On 07/20/2014 04:07 PM, Jan Kratochvil wrote:
> On Thu, 17 Jul 2014 14:23:06 +0200, Pedro Alves wrote:
>> On 07/16/2014 10:58 PM, Jan Kratochvil wrote:
>>> This patch is apparently not suitable for gdb-7.8 which is I guess often
>>> crashing on -O2 -g entry values so there could be some rather minimal crash
>>> avoiding patch instead.
>>
>> Yeah.
>>
>> So this was originally "caused" (more exposed) by 4f14910f:
>>     
>>         gdb/ChangeLog
>>         2013-11-26  Andrew Burgess  <aburgess@broadcom.com>
>>     
>>             * value.c (allocate_optimized_out_value): Mark value as non-lazy.
>>
>> I tried a few approaches in value_available_contents_eq
>> today, and ended up thinking that the simplest should be to
>> just revert that patch until we have the fuller fix in place.
> 
> OK, that seems as the best solution for 7.8 to me.
> 
> 
>> While doing just that fixes the crash, it surprisingly causes
>> one of your new tests to FAIL:
>>
>>  (gdb) frame
>>  #0  bar (ref=ref@entry=@0x7fffffffd184: 10) at gdb.arch/amd64-entry-value-paramref.cc:23
>>  23        vv++; /* break-here */
>>  (gdb) FAIL: gdb.arch/amd64-entry-value-paramref.exp: frame
> 
> There is a bug in that entry value code of mine, fix attached.
> The testcase then PASSes with the reverted optimization by Andrew Burgess.
> 

OK, I've pushed the reversion (without the #if 0 bit) to both master
and 7.8.

> For the attached fix - if you nitpick the missing conditional case:
> 	value_optimized_out (val_deref) && value_optimized_out (entryval_deref)
> It is not detected there but that IMO does not matter much as
>  * It is for 7.8 only, for trunk it will get compared correctly thanks to the
>    new implementation of value_available_contents_eq()
>    called value_contents_eq().
>  * If the conditional
>                       if (val != val_deref
>                           && !value_optimized_out (val_deref)
>                           && !value_optimized_out (entryval_deref)
>                           && value_available_contents_eq (val_deref, 0,
>                                                           entryval_deref, 0,
>                                                       TYPE_LENGTH (type_deref)))
>                         val_equal = 1;
>    fails it may just print
>      bar (ref=@0x7fffffffd904: <optimized out>, ref@entry=@0x7fffffffd904: <optimized out>)
>    (or some variant with some partially optimized-out/unavailable parts)
>    instead of the more correct
>      bar (ref=ref@entry=@0x7fffffffd904: <optimized out>)
>    which is not much a bug.

That's fine with me.

> The attached fix no longe makes sense after the new implementation
> of value_available_contents_eq() called value_contents_eq() gets applied as it
> handles all the optimized-out/unavailable values on its own, therefore the
> attached patch is really only for 7.8.

As it's best not to get ourselves in a situation where we have a fix in
the branch but not in mainline, and avoid putting pressure on the
better fix, it's better to put your patch in mainline too.

> I do not see how to access
> 	((struct value *)arg1.location.computed.closure).location.address
> from GDB CLI.  Trying
> (gdb) p &ref@entry
> will invoke value_addr()'s:
>   if (TYPE_CODE (type) == TYPE_CODE_REF)
>       /* Copy the value, but change the type from (T&) to (T*).  We
>          keep the same location information, which is efficient, and
>          allows &(&X) to get the location containing the reference.  */
> and therefore the address gets fetched already from
>   arg1.contents
> and not from
>   ((struct value *)arg1.location.computed.closure).location.address
> .
> 

Yeah.

> And for any other type than TYPE_CODE_REF this code you #if 0-ed does not get
> executed at all.  This DW_AT_GNU_call_site_data_value DWARF was meant
> primarily for Fortran but with -O0 entry values do not get produced
> and with -Og and higher Fortran always optimizes out the passing by reference.
> 
> If you do not like the #if 0 code there I am OK with removing it as I do not
> know how to make it's use reproducible for user anyway.  In the worst case
> - if there really is some way how to exploit it - one should just get
>   Attempt to take address of value not located in memory.
> instead of some wrong value and it may be easy to fix then.

Thanks Jan.  Indeed I'd much prefer removing it.
It's fine with me to still leave it in 7.8 in case we missed
something.

-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [commit+7.8] [read_frame_arg patch] Handle partially optimized out values similarly to unavailable values
  2014-07-22 19:33             ` Pedro Alves
@ 2014-07-22 20:21               ` Jan Kratochvil
  2014-08-05 17:16                 ` Doug Evans
  2014-07-23 14:26               ` [commit] Remove setting value address for reference entry value target data value Jan Kratochvil
  1 sibling, 1 reply; 28+ messages in thread
From: Jan Kratochvil @ 2014-07-22 20:21 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 320 bytes --]

On Tue, 22 Jul 2014 21:19:22 +0200, Pedro Alves wrote:
> OK, I've pushed the reversion (without the #if 0 bit) to both master
> and 7.8.

Therefore pushed in the fix of read_frame_arg together with the testcase.
	e214cf6c2e05bcfc85dc6f335d8ffdc3629cf0cf
and also for 7.8:
	0f9e1204f3de3cbe46a2b9e54049c1df9a5df305


Jan

[-- Attachment #2: 1 --]
[-- Type: text/plain, Size: 31708 bytes --]

commit e214cf6c2e05bcfc85dc6f335d8ffdc3629cf0cf
Author: Jan Kratochvil <jan.kratochvil@redhat.com>
Date:   Tue Jul 22 22:09:35 2014 +0200

    Fix read_frame_arg for optimized-out entry values.
    
    gdb/
    2014-07-22  Jan Kratochvil  <jan.kratochvil@redhat.com>
    
    	* stack.c (read_frame_arg): Verify value_optimized_out before calling
    	value_available_contents_eq.
    
    gdb/testsuite/
    2014-07-22  Jan Kratochvil  <jan.kratochvil@redhat.com>
    
    	* gdb.arch/amd64-entry-value-paramref.S: New file.
    	* gdb.arch/amd64-entry-value-paramref.cc: New file.
    	* gdb.arch/amd64-entry-value-paramref.exp: New file.
    	* gdb.arch/amd64-optimout-repeat.S: New file.
    	* gdb.arch/amd64-optimout-repeat.c: New file.
    	* gdb.arch/amd64-optimout-repeat.exp: New file.
    
    Message-ID: <20140720150727.GA18488@host2.jankratochvil.net>
    Message-ID: <20140711153757.GA452@host2.jankratochvil.net>

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 6ce1e52..73a13d3 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,8 @@
+2014-07-22  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* stack.c (read_frame_arg): Verify value_optimized_out before calling
+	value_available_contents_eq.
+
 2014-07-22  Pedro Alves  <palves@redhat.com>
 
 	* value.c (allocate_optimized_out_value): Don't mark value as
diff --git a/gdb/stack.c b/gdb/stack.c
index 0d6d8e7..4db5df5 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -413,6 +413,8 @@ read_frame_arg (struct symbol *sym, struct frame_info *frame,
 		      /* If the reference addresses match but dereferenced
 			 content does not match print them.  */
 		      if (val != val_deref
+		          && !value_optimized_out (val_deref)
+		          && !value_optimized_out (entryval_deref)
 			  && value_available_contents_eq (val_deref, 0,
 							  entryval_deref, 0,
 						      TYPE_LENGTH (type_deref)))
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index d9c420e..f534f18 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,12 @@
+2014-07-22  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* gdb.arch/amd64-entry-value-paramref.S: New file.
+	* gdb.arch/amd64-entry-value-paramref.cc: New file.
+	* gdb.arch/amd64-entry-value-paramref.exp: New file.
+	* gdb.arch/amd64-optimout-repeat.S: New file.
+	* gdb.arch/amd64-optimout-repeat.c: New file.
+	* gdb.arch/amd64-optimout-repeat.exp: New file.
+
 2014-07-17  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
 	PR gdb/17170
diff --git a/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.S b/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.S
new file mode 100644
index 0000000..a1e9d0a
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.S
@@ -0,0 +1,459 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2014 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* This file is compiled from gdb.arch/amd64-entry-value-paramref.cc
+   using -g -dA -S -O2.
+   Additionally it has been patched.  */
+
+	.file	"amd64-entry-value-paramref.cc"
+	.text
+.Ltext0:
+	.p2align 4,,15
+	.type	_ZL3barRi.constprop.0, @function
+_ZL3barRi.constprop.0:
+.LFB2:
+	.file 1 "gdb.arch/amd64-entry-value-paramref.cc"
+	# gdb.arch/amd64-entry-value-paramref.cc:21
+	.loc 1 21 0
+	.cfi_startproc
+.LVL0:
+# BLOCK 2 freq:10000 seq:0
+# PRED: ENTRY [100.0%]  (FALLTHRU)
+	# gdb.arch/amd64-entry-value-paramref.cc:23
+	.loc 1 23 0
+	movl	vv(%rip), %eax
+	# gdb.arch/amd64-entry-value-paramref.cc:24
+	.loc 1 24 0
+	movq	%rdi, p(%rip)
+	# gdb.arch/amd64-entry-value-paramref.cc:23
+	.loc 1 23 0
+	addl	$1, %eax
+	movl	%eax, vv(%rip)
+	# gdb.arch/amd64-entry-value-paramref.cc:25
+	.loc 1 25 0
+	movl	(%rdi), %eax
+# SUCC: EXIT [100.0%] 
+	# gdb.arch/amd64-entry-value-paramref.cc:26
+	.loc 1 26 0
+	ret
+	.cfi_endproc
+.LFE2:
+	.size	_ZL3barRi.constprop.0, .-_ZL3barRi.constprop.0
+	.section	.text.startup,"ax",@progbits
+	.p2align 4,,15
+	.globl	main
+	.type	main, @function
+main:
+.LFB1:
+	# gdb.arch/amd64-entry-value-paramref.cc:30
+	.loc 1 30 0
+	.cfi_startproc
+# BLOCK 2 freq:10000 seq:0
+# PRED: ENTRY [100.0%]  (FALLTHRU)
+	subq	$16, %rsp
+	.cfi_def_cfa_offset 24
+.LBB2:
+	# gdb.arch/amd64-entry-value-paramref.cc:32
+	.loc 1 32 0
+	leaq	12(%rsp), %rdi
+	# gdb.arch/amd64-entry-value-paramref.cc:31
+	.loc 1 31 0
+	movl	$10, 12(%rsp)
+	# gdb.arch/amd64-entry-value-paramref.cc:32
+	.loc 1 32 0
+	call	_ZL3barRi.constprop.0
+.LVL1:
+.LBE2:
+	# gdb.arch/amd64-entry-value-paramref.cc:33
+	.loc 1 33 0
+	addq	$16, %rsp
+	.cfi_def_cfa_offset 8
+# SUCC: EXIT [100.0%] 
+	ret
+	.cfi_endproc
+.LFE1:
+	.size	main, .-main
+	.globl	p
+	.bss
+	.align 8
+	.type	p, @object
+	.size	p, 8
+p:
+	.zero	8
+	.globl	vv
+	.align 4
+	.type	vv, @object
+	.size	vv, 4
+vv:
+	.zero	4
+	.text
+.Letext0:
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+	.long	.Linfo_end - .Linfo_start	# Length of Compilation Unit Info
+.Linfo_start:
+	.value	0x4	# DWARF version number
+	.long	.Ldebug_abbrev0	# Offset Into Abbrev. Section
+	.byte	0x8	# Pointer Size (in bytes)
+	.uleb128 0x1	# (DIE (0xb) DW_TAG_compile_unit)
+	.long	.LASF0	# DW_AT_producer: "GNU C++ 4.8.2 20131212 (Red Hat 4.8.2-7) -mtune=generic -march=x86-64 -g -O2"
+	.byte	0x4	# DW_AT_language
+	.long	.LASF1	# DW_AT_name: "gdb.arch/amd64-entry-value-paramref.cc"
+	.long	.LASF2	# DW_AT_comp_dir: ""
+	.long	.Ldebug_ranges0+0	# DW_AT_ranges
+	.quad	0	# DW_AT_low_pc
+	.long	.Ldebug_line0	# DW_AT_stmt_list
+DIE29:	.uleb128 0x2	# (DIE (0x29) DW_TAG_subprogram)
+	.ascii "bar\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-entry-value-paramref.cc)
+	.byte	0x15	# DW_AT_decl_line
+	.long	DIE45	# DW_AT_type
+	.byte	0x1	# DW_AT_inline
+DIE39:	.uleb128 0x3	# (DIE (0x39) DW_TAG_formal_parameter)
+	.ascii "ref\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-entry-value-paramref.cc)
+	.byte	0x15	# DW_AT_decl_line
+	.long	DIE4c	# DW_AT_type
+	.byte	0	# end of children of DIE 0x29
+DIE45:	.uleb128 0x4	# (DIE (0x45) DW_TAG_base_type)
+	.byte	0x4	# DW_AT_byte_size
+	.byte	0x5	# DW_AT_encoding
+	.ascii "int\0"	# DW_AT_name
+DIE4c:	.uleb128 0x5	# (DIE (0x4c) DW_TAG_const_type)
+	.long	DIE51	# DW_AT_type
+DIE51:	.uleb128 0x6	# (DIE (0x51) DW_TAG_reference_type)
+	.byte	0x8	# DW_AT_byte_size
+	.long	DIE45	# DW_AT_type
+DIE57:	.uleb128 0x7	# (DIE (0x57) DW_TAG_subprogram)
+	.long	DIE29	# DW_AT_abstract_origin
+	.quad	.LFB2	# DW_AT_low_pc
+	.quad	.LFE2-.LFB2	# DW_AT_high_pc
+	.uleb128 0x1	# DW_AT_frame_base
+	.byte	0x9c	# DW_OP_call_frame_cfa
+			# DW_AT_GNU_all_call_sites
+DIE72:	.uleb128 0x8	# (DIE (0x72) DW_TAG_formal_parameter)
+	.long	DIE39	# DW_AT_abstract_origin
+	.uleb128 0x1	# DW_AT_location
+	.byte	0x55	# DW_OP_reg5
+	.byte	0	# end of children of DIE 0x57
+DIE7a:	.uleb128 0x9	# (DIE (0x7a) DW_TAG_subprogram)
+			# DW_AT_external
+	.long	.LASF3	# DW_AT_name: "main"
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-entry-value-paramref.cc)
+	.byte	0x1d	# DW_AT_decl_line
+	.long	DIE45	# DW_AT_type
+	.quad	.LFB1	# DW_AT_low_pc
+	.quad	.LFE1-.LFB1	# DW_AT_high_pc
+	.uleb128 0x1	# DW_AT_frame_base
+	.byte	0x9c	# DW_OP_call_frame_cfa
+			# DW_AT_GNU_all_call_sites
+DIE9b:	.uleb128 0xa	# (DIE (0x9b) DW_TAG_lexical_block)
+	.quad	.LBB2	# DW_AT_low_pc
+	.quad	.LBE2-.LBB2	# DW_AT_high_pc
+DIEac:	.uleb128 0xb	# (DIE (0xac) DW_TAG_variable)
+	.ascii "var\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-entry-value-paramref.cc)
+	.byte	0x1f	# DW_AT_decl_line
+	.long	DIE45	# DW_AT_type
+	.uleb128 0x2	# DW_AT_location
+	.byte	0x91	# DW_OP_fbreg
+	.sleb128 -12
+DIEba:	.uleb128 0xc	# (DIE (0xba) DW_TAG_GNU_call_site)
+	.quad	.LVL1	# DW_AT_low_pc
+	.long	DIE57	# DW_AT_abstract_origin
+DIEc7:	.uleb128 0xd	# (DIE (0xc7) DW_TAG_GNU_call_site_parameter)
+	.uleb128 0x1	# DW_AT_location
+	.byte	0x55	# DW_OP_reg5
+	.uleb128 0x2	# DW_AT_GNU_call_site_value
+	.byte	0x91	# DW_OP_fbreg
+	.sleb128 -12
+#if 0
+	.uleb128 0x1	# DW_AT_GNU_call_site_data_value
+	.byte	0x3a	# DW_OP_lit10
+#else
+	.uleb128 1f - 2f	# DW_AT_GNU_call_site_data_value
+2:
+	.byte	0xf3	# DW_OP_GNU_entry_value
+	.uleb128 1f - 3f
+3:
+	.byte	0x55	# DW_OP_reg5
+1:
+#endif
+	.byte	0	# end of children of DIE 0xba
+	.byte	0	# end of children of DIE 0x9b
+	.byte	0	# end of children of DIE 0x7a
+DIEd2:	.uleb128 0xe	# (DIE (0xd2) DW_TAG_variable)
+	.ascii "vv\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-entry-value-paramref.cc)
+	.byte	0x12	# DW_AT_decl_line
+	.long	DIEe6	# DW_AT_type
+			# DW_AT_external
+	.uleb128 0x9	# DW_AT_location
+	.byte	0x3	# DW_OP_addr
+	.quad	vv
+DIEe6:	.uleb128 0xf	# (DIE (0xe6) DW_TAG_volatile_type)
+	.long	DIE45	# DW_AT_type
+DIEeb:	.uleb128 0xe	# (DIE (0xeb) DW_TAG_variable)
+	.ascii "p\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-entry-value-paramref.cc)
+	.byte	0x12	# DW_AT_decl_line
+	.long	DIEfe	# DW_AT_type
+			# DW_AT_external
+	.uleb128 0x9	# DW_AT_location
+	.byte	0x3	# DW_OP_addr
+	.quad	p
+DIEfe:	.uleb128 0x10	# (DIE (0xfe) DW_TAG_pointer_type)
+	.byte	0x8	# DW_AT_byte_size
+	.long	DIEe6	# DW_AT_type
+	.byte	0	# end of children of DIE 0xb
+.Linfo_end:
+	.section	.debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1	# (abbrev code)
+	.uleb128 0x11	# (TAG: DW_TAG_compile_unit)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x25	# (DW_AT_producer)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x13	# (DW_AT_language)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x1b	# (DW_AT_comp_dir)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x55	# (DW_AT_ranges)
+	.uleb128 0x17	# (DW_FORM_sec_offset)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x10	# (DW_AT_stmt_list)
+	.uleb128 0x17	# (DW_FORM_sec_offset)
+	.byte	0
+	.byte	0
+	.uleb128 0x2	# (abbrev code)
+	.uleb128 0x2e	# (TAG: DW_TAG_subprogram)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x20	# (DW_AT_inline)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.byte	0
+	.byte	0
+	.uleb128 0x3	# (abbrev code)
+	.uleb128 0x5	# (TAG: DW_TAG_formal_parameter)
+	.byte	0	# DW_children_no
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x4	# (abbrev code)
+	.uleb128 0x24	# (TAG: DW_TAG_base_type)
+	.byte	0	# DW_children_no
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3e	# (DW_AT_encoding)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.byte	0
+	.byte	0
+	.uleb128 0x5	# (abbrev code)
+	.uleb128 0x26	# (TAG: DW_TAG_const_type)
+	.byte	0	# DW_children_no
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x6	# (abbrev code)
+	.uleb128 0x10	# (TAG: DW_TAG_reference_type)
+	.byte	0	# DW_children_no
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x7	# (abbrev code)
+	.uleb128 0x2e	# (TAG: DW_TAG_subprogram)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x31	# (DW_AT_abstract_origin)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x12	# (DW_AT_high_pc)
+	.uleb128 0x7	# (DW_FORM_data8)
+	.uleb128 0x40	# (DW_AT_frame_base)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.uleb128 0x2117	# (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.byte	0
+	.byte	0
+	.uleb128 0x8	# (abbrev code)
+	.uleb128 0x5	# (TAG: DW_TAG_formal_parameter)
+	.byte	0	# DW_children_no
+	.uleb128 0x31	# (DW_AT_abstract_origin)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x2	# (DW_AT_location)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.byte	0
+	.byte	0
+	.uleb128 0x9	# (abbrev code)
+	.uleb128 0x2e	# (TAG: DW_TAG_subprogram)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x3f	# (DW_AT_external)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x12	# (DW_AT_high_pc)
+	.uleb128 0x7	# (DW_FORM_data8)
+	.uleb128 0x40	# (DW_AT_frame_base)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.uleb128 0x2117	# (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.byte	0
+	.byte	0
+	.uleb128 0xa	# (abbrev code)
+	.uleb128 0xb	# (TAG: DW_TAG_lexical_block)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x12	# (DW_AT_high_pc)
+	.uleb128 0x7	# (DW_FORM_data8)
+	.byte	0
+	.byte	0
+	.uleb128 0xb	# (abbrev code)
+	.uleb128 0x34	# (TAG: DW_TAG_variable)
+	.byte	0	# DW_children_no
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x2	# (DW_AT_location)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.byte	0
+	.byte	0
+	.uleb128 0xc	# (abbrev code)
+	.uleb128 0x4109	# (TAG: DW_TAG_GNU_call_site)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x31	# (DW_AT_abstract_origin)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0xd	# (abbrev code)
+	.uleb128 0x410a	# (TAG: DW_TAG_GNU_call_site_parameter)
+	.byte	0	# DW_children_no
+	.uleb128 0x2	# (DW_AT_location)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.uleb128 0x2111	# (DW_AT_GNU_call_site_value)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.uleb128 0x2112	# (DW_AT_GNU_call_site_data_value)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.byte	0
+	.byte	0
+	.uleb128 0xe	# (abbrev code)
+	.uleb128 0x34	# (TAG: DW_TAG_variable)
+	.byte	0	# DW_children_no
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x3f	# (DW_AT_external)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x2	# (DW_AT_location)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.byte	0
+	.byte	0
+	.uleb128 0xf	# (abbrev code)
+	.uleb128 0x35	# (TAG: DW_TAG_volatile_type)
+	.byte	0	# DW_children_no
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x10	# (abbrev code)
+	.uleb128 0xf	# (TAG: DW_TAG_pointer_type)
+	.byte	0	# DW_children_no
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.byte	0
+	.section	.debug_aranges,"",@progbits
+	.long	0x3c	# Length of Address Ranges Info
+	.value	0x2	# DWARF Version
+	.long	.Ldebug_info0	# Offset of Compilation Unit Info
+	.byte	0x8	# Size of Address
+	.byte	0	# Size of Segment Descriptor
+	.value	0	# Pad to 16 byte boundary
+	.value	0
+	.quad	.Ltext0	# Address
+	.quad	.Letext0-.Ltext0	# Length
+	.quad	.LFB1	# Address
+	.quad	.LFE1-.LFB1	# Length
+	.quad	0
+	.quad	0
+	.section	.debug_ranges,"",@progbits
+.Ldebug_ranges0:
+	.quad	.Ltext0	# Offset 0
+	.quad	.Letext0
+	.quad	.LFB1	# Offset 0x10
+	.quad	.LFE1
+	.quad	0
+	.quad	0
+	.section	.debug_line,"",@progbits
+.Ldebug_line0:
+	.section	.debug_str,"MS",@progbits,1
+.LASF1:
+	.string	"gdb.arch/amd64-entry-value-paramref.cc"
+.LASF2:
+	.string	""
+.LASF0:
+	.string	"GNU C++ 4.8.2 20131212 (Red Hat 4.8.2-7) -mtune=generic -march=x86-64 -g -O2"
+.LASF3:
+	.string	"main"
+	.ident	"GCC: (GNU) 4.8.2 20131212 (Red Hat 4.8.2-7)"
+	.section	.note.GNU-stack,"",@progbits
diff --git a/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.cc b/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.cc
new file mode 100644
index 0000000..aa473a3
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.cc
@@ -0,0 +1,33 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2014 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+volatile int vv, *p;
+
+static __attribute__((noinline)) int
+bar (int &ref)
+{
+  vv++; /* break-here */
+  p = &ref;
+  return ref;
+}
+
+int
+main (void)
+{
+  int var = 10;
+  return bar (var);
+}
diff --git a/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.exp b/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.exp
new file mode 100644
index 0000000..f06247d
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-entry-value-paramref.exp
@@ -0,0 +1,35 @@
+# Copyright (C) 2014 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile .S .cc
+
+if { ![istarget x86_64-*-* ] || ![is_lp64_target] } {
+    verbose "Skipping amd64-entry-value-paramref."
+    return
+}
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} "c++"] } {
+    return -1
+}
+
+if ![runto_main] {
+    return -1
+}
+
+set srcfile $srcfile2
+gdb_breakpoint [gdb_get_line_number "break-here"]
+
+gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+gdb_test "frame" {bar \(ref=@0x[0-9a-f]+: 10, ref@entry=@0x[0-9a-f]+: <optimized out>\) at .*}
diff --git a/gdb/testsuite/gdb.arch/amd64-optimout-repeat.S b/gdb/testsuite/gdb.arch/amd64-optimout-repeat.S
new file mode 100644
index 0000000..2f8f4d2
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-optimout-repeat.S
@@ -0,0 +1,297 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2012-2014 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* This file is compiled from gdb.arch/amd64-entry-value-param.c
+   using -g -dA -S -O2.  */
+
+	.file	"amd64-optimout-repeat.c"
+	.text
+.Ltext0:
+	.section	.text.unlikely,"ax",@progbits
+.LCOLDB0:
+	.section	.text.startup,"ax",@progbits
+.LHOTB0:
+	.p2align 4,,15
+	.section	.text.unlikely
+.Ltext_cold0:
+	.section	.text.startup
+	.globl	main
+	.type	main, @function
+main:
+.LFB0:
+	.file 1 "gdb.arch/amd64-optimout-repeat.c"
+	# gdb.arch/amd64-optimout-repeat.c:20
+	.loc 1 20 0
+	.cfi_startproc
+# BLOCK 2 freq:10000 seq:0
+# PRED: ENTRY [100.0%]  (FALLTHRU)
+.LVL0:
+	# gdb.arch/amd64-optimout-repeat.c:29
+	.loc 1 29 0
+	xorl	%eax, %eax
+# SUCC: EXIT [100.0%] 
+	ret
+	.cfi_endproc
+.LFE0:
+	.size	main, .-main
+	.section	.text.unlikely
+.LCOLDE0:
+	.section	.text.startup
+.LHOTE0:
+	.text
+.Letext0:
+	.section	.text.unlikely
+.Letext_cold0:
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+	.long	0x97	# Length of Compilation Unit Info
+	.value	0x4	# DWARF version number
+	.long	.Ldebug_abbrev0	# Offset Into Abbrev. Section
+	.byte	0x8	# Pointer Size (in bytes)
+	.uleb128 0x1	# (DIE (0xb) DW_TAG_compile_unit)
+	.long	.LASF1	# DW_AT_producer: "GNU C 4.9.1 20140709 (prerelease) -mtune=generic -march=x86-64 -g -O2"
+	.byte	0x1	# DW_AT_language
+	.long	.LASF2	# DW_AT_name: "gdb.arch/amd64-optimout-repeat.c"
+	.long	.LASF3	# DW_AT_comp_dir: ""
+	.long	.Ldebug_ranges0+0	# DW_AT_ranges
+	.quad	0	# DW_AT_low_pc
+	.long	.Ldebug_line0	# DW_AT_stmt_list
+	.uleb128 0x2	# (DIE (0x29) DW_TAG_subprogram)
+			# DW_AT_external
+	.long	.LASF4	# DW_AT_name: "main"
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-optimout-repeat.c)
+	.byte	0x13	# DW_AT_decl_line
+			# DW_AT_prototyped
+	.long	0x7c	# DW_AT_type
+	.quad	.LFB0	# DW_AT_low_pc
+	.quad	.LFE0-.LFB0	# DW_AT_high_pc
+	.uleb128 0x1	# DW_AT_frame_base
+	.byte	0x9c	# DW_OP_call_frame_cfa
+			# DW_AT_GNU_all_call_sites
+	.long	0x7c	# DW_AT_sibling
+	.uleb128 0x3	# (DIE (0x4a) DW_TAG_structure_type)
+	.value	0x404	# DW_AT_byte_size
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-optimout-repeat.c)
+	.byte	0x15	# DW_AT_decl_line
+	.long	0x6a	# DW_AT_sibling
+	.uleb128 0x4	# (DIE (0x53) DW_TAG_member)
+	.ascii "i\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-optimout-repeat.c)
+	.byte	0x17	# DW_AT_decl_line
+	.long	0x7c	# DW_AT_type
+	.byte	0	# DW_AT_data_member_location
+	.uleb128 0x4	# (DIE (0x5d) DW_TAG_member)
+	.ascii "xxx\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-optimout-repeat.c)
+	.byte	0x18	# DW_AT_decl_line
+	.long	0x83	# DW_AT_type
+	.byte	0x4	# DW_AT_data_member_location
+	.byte	0	# end of children of DIE 0x4a
+	.uleb128 0x5	# (DIE (0x6a) DW_TAG_variable)
+	.ascii "v\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (gdb.arch/amd64-optimout-repeat.c)
+	.byte	0x1a	# DW_AT_decl_line
+	.long	0x4a	# DW_AT_type
+	.uleb128 0x7	# DW_AT_location
+	.byte	0x30	# DW_OP_lit0
+	.byte	0x9f	# DW_OP_stack_value
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x4
+	.byte	0x93	# DW_OP_piece
+	.uleb128 0x400
+	.byte	0	# end of children of DIE 0x29
+	.uleb128 0x6	# (DIE (0x7c) DW_TAG_base_type)
+	.byte	0x4	# DW_AT_byte_size
+	.byte	0x5	# DW_AT_encoding
+	.ascii "int\0"	# DW_AT_name
+	.uleb128 0x7	# (DIE (0x83) DW_TAG_array_type)
+	.long	0x7c	# DW_AT_type
+	.long	0x93	# DW_AT_sibling
+	.uleb128 0x8	# (DIE (0x8c) DW_TAG_subrange_type)
+	.long	0x93	# DW_AT_type
+	.byte	0xff	# DW_AT_upper_bound
+	.byte	0	# end of children of DIE 0x83
+	.uleb128 0x9	# (DIE (0x93) DW_TAG_base_type)
+	.byte	0x8	# DW_AT_byte_size
+	.byte	0x7	# DW_AT_encoding
+	.long	.LASF0	# DW_AT_name: "sizetype"
+	.byte	0	# end of children of DIE 0xb
+	.section	.debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1	# (abbrev code)
+	.uleb128 0x11	# (TAG: DW_TAG_compile_unit)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x25	# (DW_AT_producer)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x13	# (DW_AT_language)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x1b	# (DW_AT_comp_dir)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x55	# (DW_AT_ranges)
+	.uleb128 0x17	# (DW_FORM_sec_offset)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x10	# (DW_AT_stmt_list)
+	.uleb128 0x17	# (DW_FORM_sec_offset)
+	.byte	0
+	.byte	0
+	.uleb128 0x2	# (abbrev code)
+	.uleb128 0x2e	# (TAG: DW_TAG_subprogram)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x3f	# (DW_AT_external)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x27	# (DW_AT_prototyped)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x12	# (DW_AT_high_pc)
+	.uleb128 0x7	# (DW_FORM_data8)
+	.uleb128 0x40	# (DW_AT_frame_base)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.uleb128 0x2117	# (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x1	# (DW_AT_sibling)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x3	# (abbrev code)
+	.uleb128 0x13	# (TAG: DW_TAG_structure_type)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0x5	# (DW_FORM_data2)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x1	# (DW_AT_sibling)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x4	# (abbrev code)
+	.uleb128 0xd	# (TAG: DW_TAG_member)
+	.byte	0	# DW_children_no
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x38	# (DW_AT_data_member_location)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.byte	0
+	.byte	0
+	.uleb128 0x5	# (abbrev code)
+	.uleb128 0x34	# (TAG: DW_TAG_variable)
+	.byte	0	# DW_children_no
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x3a	# (DW_AT_decl_file)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3b	# (DW_AT_decl_line)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x2	# (DW_AT_location)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.byte	0
+	.byte	0
+	.uleb128 0x6	# (abbrev code)
+	.uleb128 0x24	# (TAG: DW_TAG_base_type)
+	.byte	0	# DW_children_no
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3e	# (DW_AT_encoding)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.byte	0
+	.byte	0
+	.uleb128 0x7	# (abbrev code)
+	.uleb128 0x1	# (TAG: DW_TAG_array_type)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x1	# (DW_AT_sibling)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x8	# (abbrev code)
+	.uleb128 0x21	# (TAG: DW_TAG_subrange_type)
+	.byte	0	# DW_children_no
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x2f	# (DW_AT_upper_bound)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.byte	0
+	.byte	0
+	.uleb128 0x9	# (abbrev code)
+	.uleb128 0x24	# (TAG: DW_TAG_base_type)
+	.byte	0	# DW_children_no
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3e	# (DW_AT_encoding)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0xe	# (DW_FORM_strp)
+	.byte	0
+	.byte	0
+	.byte	0
+	.section	.debug_aranges,"",@progbits
+	.long	0x2c	# Length of Address Ranges Info
+	.value	0x2	# DWARF Version
+	.long	.Ldebug_info0	# Offset of Compilation Unit Info
+	.byte	0x8	# Size of Address
+	.byte	0	# Size of Segment Descriptor
+	.value	0	# Pad to 16 byte boundary
+	.value	0
+	.quad	.LFB0	# Address
+	.quad	.LFE0-.LFB0	# Length
+	.quad	0
+	.quad	0
+	.section	.debug_ranges,"",@progbits
+.Ldebug_ranges0:
+	.quad	.LFB0	# Offset 0
+	.quad	.LFE0
+	.quad	0
+	.quad	0
+	.section	.debug_line,"",@progbits
+.Ldebug_line0:
+	.section	.debug_str,"MS",@progbits,1
+.LASF0:
+	.string	"sizetype"
+.LASF2:
+	.string	"gdb.arch/amd64-optimout-repeat.c"
+.LASF1:
+	.string	"GNU C 4.9.1 20140709 (prerelease) -mtune=generic -march=x86-64 -g -O2"
+.LASF3:
+	.string	""
+.LASF4:
+	.string	"main"
+	.ident	"GCC: (GNU) 4.9.1 20140709 (prerelease)"
+	.section	.note.GNU-stack,"",@progbits
diff --git a/gdb/testsuite/gdb.arch/amd64-optimout-repeat.c b/gdb/testsuite/gdb.arch/amd64-optimout-repeat.c
new file mode 100644
index 0000000..a32b6de
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-optimout-repeat.c
@@ -0,0 +1,29 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2014 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+int
+main (void)
+{
+  struct
+    {
+      int i;
+      int xxx[0x100];
+    }
+  v = { 0 };
+
+  return v.i;
+}
diff --git a/gdb/testsuite/gdb.arch/amd64-optimout-repeat.exp b/gdb/testsuite/gdb.arch/amd64-optimout-repeat.exp
new file mode 100644
index 0000000..f3c93a4
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/amd64-optimout-repeat.exp
@@ -0,0 +1,36 @@
+# Copyright (C) 2014 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile .S .c
+set opts {}
+
+if [info exists COMPILE] {
+    # make check RUNTESTFLAGS="gdb.arch/amd64-optimout-repeat.exp COMPILE=1"
+    set srcfile ${srcfile2}
+    lappend opts debug optimize=-O2
+} elseif { ![istarget x86_64-*-* ] || ![is_lp64_target] } {
+    verbose "Skipping amd64-optimout-repeat."
+    return
+}
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} $opts] } {
+    return -1
+}
+
+if ![runto_main] {
+    return -1
+}
+
+gdb_test "print v" { = {i = 0, xxx = {<optimized out> <repeats 256 times>}}}

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [commit] Remove setting value address for reference entry value target data value
  2014-07-22 19:33             ` Pedro Alves
  2014-07-22 20:21               ` [commit+7.8] [read_frame_arg patch] Handle partially optimized out values similarly to unavailable values Jan Kratochvil
@ 2014-07-23 14:26               ` Jan Kratochvil
  1 sibling, 0 replies; 28+ messages in thread
From: Jan Kratochvil @ 2014-07-23 14:26 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 207 bytes --]

On Tue, 22 Jul 2014 21:19:22 +0200, Pedro Alves wrote:
> Thanks Jan.  Indeed I'd much prefer removing it.
> It's fine with me to still leave it in 7.8 in case we missed
> something.

Removed on trunk.


Jan

[-- Attachment #2: 1 --]
[-- Type: text/plain, Size: 5404 bytes --]

commit 45326f6fbe28ef5bac22dac447a4181c44cb945a
Author: Jan Kratochvil <jan.kratochvil@redhat.com>
Date:   Tue Jul 22 22:15:27 2014 +0200

    Remove setting value address for reference entry value target data value.
    
    I cannot reproduce any wrong case having the code removed.
    
    I just do not find it correct to have it disabled.  But at the same time I do
    like much / I do not find correct the code myself.  It is a bit problematic to
    have struct value describing a memory content which is no longer present
    there.
    
    What happens there:
    ------------------------------------------------------------------------------
    volatile int vv;
    static __attribute__((noinline)) int
    bar (int &ref) {
      ref = 20;
      vv++; /* break-here */
      return ref;
    }
    int main (void) {
      int var = 10;
      return bar (var);
    }
    ------------------------------------------------------------------------------
     <4><c7>: Abbrev Number: 13 (DW_TAG_GNU_call_site_parameter)
        <c8>   DW_AT_location    : 1 byte block: 55         (DW_OP_reg5 (rdi))
        <ca>   DW_AT_GNU_call_site_value: 2 byte block: 91 74       (DW_OP_fbreg: -12)
        <cd>   DW_AT_GNU_call_site_data_value: 1 byte block: 3a     (DW_OP_lit10)
    ------------------------------------------------------------------------------
    gdb -ex 'b value_addr' -ex r --args ../gdb ./1 -ex 'watch vv' -ex r -ex 'p &ref@entry'
    ->
    6    return ref;
    bar (ref=@0x7fffffffd944: 20, ref@entry=@0x7fffffffd944: 10) at 1.C:25
    ------------------------------------------------------------------------------
    At /* break-here */ struct value variable 'ref' is TYPE_CODE_REF.
    
    With FSF GDB HEAD:
    (gdb) x/gx arg1.contents
    0x6004000a4ad0: 0x00007fffffffd944
    (gdb) p ((struct value *)arg1.location.computed.closure).lval
    $1 = lval_memory
    (gdb) p/x ((struct value *)arg1.location.computed.closure).location.address
    $3 = 0x7fffffffd944
    
    With your #if0-ed code:
    (gdb) x/gx arg1.contents
    0x6004000a4ad0: 0x00007fffffffd944
    (gdb) p ((struct value *)arg1.location.computed.closure).lval
    $8 = not_lval
    (gdb) p/x ((struct value *)arg1.location.computed.closure).location.address
    $9 = 0x0
    
    I do not see how to access
            ((struct value *)arg1.location.computed.closure).location.address
    from GDB CLI.  Trying
    (gdb) p &ref@entry
    will invoke value_addr()'s:
      if (TYPE_CODE (type) == TYPE_CODE_REF)
          /* Copy the value, but change the type from (T&) to (T*).  We
             keep the same location information, which is efficient, and
             allows &(&X) to get the location containing the reference.  */
    and therefore the address gets fetched already from
      arg1.contents
    and not from
      ((struct value *)arg1.location.computed.closure).location.address
    .
    
    And for any other type than TYPE_CODE_REF this code you removed does not get
    executed at all.  This DW_AT_GNU_call_site_data_value DWARF was meant
    primarily for Fortran but with -O0 entry values do not get produced
    and with -Og and higher Fortran always optimizes out the passing by reference.
    
    If you do not like the removed code there I am OK with removing it as I do not
    know how to make it's use reproducible for user anyway.  In the worst case
    - if there really is some way how to exploit it - one should just get
      Attempt to take address of value not located in memory.
    instead of some wrong value and it may be easy to fix then.
    
    gdb/
    2014-07-22  Jan Kratochvil  <jan.kratochvil@redhat.com>
    
    	* dwarf2loc.c (value_of_dwarf_reg_entry): Remove setting value address
    	for reference entry value target data value.
    
    Message-ID: <20140720150727.GA18488@host2.jankratochvil.net>

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 73a13d3..687e2fe 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,10 @@
 2014-07-22  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
+	* dwarf2loc.c (value_of_dwarf_reg_entry): Remove setting value address
+	for reference entry value target data value.
+
+2014-07-22  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
 	* stack.c (read_frame_arg): Verify value_optimized_out before calling
 	value_available_contents_eq.
 
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index fcab9b9..b1c7ee1 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -1312,7 +1312,6 @@ value_of_dwarf_reg_entry (struct type *type, struct frame_info *frame,
   struct value *outer_val, *target_val, *val;
   struct call_site_parameter *parameter;
   struct dwarf2_per_cu_data *caller_per_cu;
-  CORE_ADDR addr;
 
   parameter = dwarf_expr_reg_to_entry_parameter (frame, kind, kind_u,
 						 &caller_per_cu);
@@ -1335,14 +1334,6 @@ value_of_dwarf_reg_entry (struct type *type, struct frame_info *frame,
 					       target_type, caller_frame,
 					       caller_per_cu);
 
-  /* value_as_address dereferences TYPE_CODE_REF.  */
-  addr = extract_typed_address (value_contents (outer_val), checked_type);
-
-  /* The target entry value has artificial address of the entry value
-     reference.  */
-  VALUE_LVAL (target_val) = lval_memory;
-  set_value_address (target_val, addr);
-
   release_value (target_val);
   val = allocate_computed_value (type, &entry_data_value_funcs,
 				 target_val /* closure */);

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH v2] Handle partially optimized out values similarly to unavailable values
  2014-07-17  8:04       ` Jan Kratochvil
  2014-07-17  8:35         ` Jan Kratochvil
  2014-07-17 13:38         ` Pedro Alves
@ 2014-07-24 12:51         ` Pedro Alves
  2014-08-15 20:13           ` Jan Kratochvil
  2 siblings, 1 reply; 28+ messages in thread
From: Pedro Alves @ 2014-07-24 12:51 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

On 07/16/2014 10:58 PM, Jan Kratochvil wrote:
> On Mon, 14 Jul 2014 20:11:41 +0200, Pedro Alves wrote:
> [...]
>> --- a/gdb/value.c
>> +++ b/gdb/value.c
> [...]
>> @@ -339,6 +330,15 @@ struct value
>>       value to be available.  This is filled in at value read time.  The
>>       unavailable ranges are tracked in bits.  */
>>    VEC(range_s) *unavailable;
>> +
>> +  /* Likewise, but for optimized out contents (a chunk of the value of
>> +     a variable that does not actually exist in the program).  If LVAL
>> +     is lval_register, this is a register ($pc, $sp, etc., never a
>> +     program variable) that has not been saved in the frame.  Not
>> +     saved registers and optimized-out program variables values are
>> +     treated pretty much the same, except not-saved registers have a
>> +     different string representation and related error strings.  */
>> +  VEC(range_s) *optimized_out;
> 
> I miss here explicit description if a bit of the range can appear on both 
> 'unavailable' and 'optimized_out'.  IMO it should not.

Yeah, it should not.  Added:

 @@ -327,8 +327,10 @@ struct value
 
    /* Unavailable ranges in CONTENTS.  We mark unavailable ranges,
       rather than available, since the common and default case is for a
 -     value to be available.  This is filled in at value read time.  The
 -     unavailable ranges are tracked in bits.  */
 +     value to be available.  This is filled in at value read time.
 +     The unavailable ranges are tracked in bits.  Note that a contents
 +     bit that has been optimized out doesn't really exist in the
 +     program, so it can't be marked unavailable either.  */
    VEC(range_s) *unavailable;



>> @@ -1566,7 +1671,6 @@ value_copy (struct value *arg)
>>    VALUE_FRAME_ID (val) = VALUE_FRAME_ID (arg);
>>    VALUE_REGNUM (val) = VALUE_REGNUM (arg);
>>    val->lazy = arg->lazy;
>> -  val->optimized_out = arg->optimized_out;
> 
> Why 'optimized_out' no longer needs to be copied?

Hmm, I blindly assumed the function was using value_contents_copy.
Copying that now.  Thanks for spotting this.

>> @@ -3662,10 +3753,11 @@ value_fetch_lazy (struct value *val)
>>        if (value_lazy (parent))
>>  	value_fetch_lazy (parent);
>>  
>> -      if (!value_bits_valid (parent,
>> -			     TARGET_CHAR_BIT * offset + value_bitpos (val),
>> -			     value_bitsize (val)))
>> -	set_value_optimized_out (val, 1);
>> +      if (value_bits_any_optimized_out (parent,
>> +					TARGET_CHAR_BIT * offset + value_bitpos (val),
>> +					value_bitsize (val)))
>> +	mark_value_bytes_optimized_out (val, value_embedded_offset (val),
>> +					TYPE_LENGTH (type));
> 
> That was required before but it could handle partially optimized out
> bitfields; but maybe it is not useful much.

Yeah, though it doesn't look trivial.  We should be able to
copy the contents straight from the parent to VAL, but note
we're copying only a few bits off the parent, into a wider
VAL.  So it seems like we'd need to:

 - have a value_contents_copy function that knows to copy
   bits, not bytes.
 - handle sign/zero extension
 - and handle big/little endian at that

Best leave that out for now.

>>  
>> +/* Values can be partially 'optimized out' and/or 'unavailable'.
>> +   These are distinct states and have different string representations
>> +   and related error strings.
>> +
>> +   'unavailable' has a specific meaning in this context.  It means the
>> +   value exists in the program (at the machine level), but GDB has no
>> +   means to get to it.  Such a value is normally printed as.  Examples
> 
> "printed as." - is the sentence finished?

Whoops, it wasn't, thanks.  I meant to write:

 "Such a value is normally printed as <unavailable>."

> 
> 
>> +   of how to end up with an unavailable value would be:
>> +
>> +    - We're inspecting a traceframe, and the memory or registers the
>> +      debug information says the value lives on haven't been collected.
>> +
>> +    - We're inspecting a core dump, the memory or registers the debug
>> +      information says the value lives aren't present in the dump
>> +      (that is, we have a partial/trimmed core dump, or we don't fully
>> +      understand/handle the core dump's format).
>> +
>> +    - We're doing live debugging, but the debug API has no means to
>> +      get at where the value lives in the machine, like e.g., ptrace
>> +      not having access to some register or register set.
>> +
>> +    - Any other similar scenario.
>> +
>> +  OTOH, "optimized out" is about what the compiler decided to generate
>> +  (or not generate).  A chunk of a value that was optimized out does
>> +  not actually exist in the program.  There's no way to get at it
>> +  short of compiling the program differently.  A register that has not
>> +  been saved in a frame is likewise considered optimized out, except
>> +  not-saved registers have a different string representation and
>> +  related error strings.  E.g., we'll print them as <not-saved>
> 
> s/<not-saved>/<unavailable>/?

Nope, we really print them as <not-saved>.  More here:

 https://sourceware.org/ml/gdb-patches/2013-09/msg00176.html

I've extended the comment based on that email:

 @@ -60,11 +60,21 @@ struct xmethod_worker;
    OTOH, "optimized out" is about what the compiler decided to generate
    (or not generate).  A chunk of a value that was optimized out does
    not actually exist in the program.  There's no way to get at it
 -  short of compiling the program differently.  A register that has not
 -  been saved in a frame is likewise considered optimized out, except
 -  not-saved registers have a different string representation and
 -  related error strings.  E.g., we'll print them as <not-saved>
 -  instead of <optimized out>.
 +  short of compiling the program differently.
 +
 +  A register that has not been saved in a frame is likewise considered
 +  optimized out, except not-saved registers have a different string
 +  representation and related error strings.  E.g., we'll print them as
 +  <not-saved> instead of <optimized out>, as in:
 +
 +    (gdb) p/x $rax
 +    $1 = <not saved>
 +    (gdb) info registers rax
 +    rax            <not saved>
 +
 +  If the debug info describes a variable as being in such a register,
 +  we'll still print the variable as <optimized out>.  IOW, <not saved>
 +  is reserved for inspecting registers at the machine level.


>> +   Returns true iff the set of available/valid contents match.
>> +
>> +   Optimized out contents compare equal with optimized out contents,
>> +   and different with any non-optimized-out byte.
> 
> English: s/different/differ/

The "different" is bound to the "compare" before, so it results in
"contents compare ... different".   I don't know how I'd use differ
in a similar vein in the above.  Sounds like I best rewrite this then.
Here's what I came up with:

 @@ -513,11 +523,11 @@ extern void mark_value_bits_unavailable (struct value *value,
 
     Returns true iff the set of available/valid contents match.
 
 -   Optimized out contents compare equal with optimized out contents,
 -   and different with any non-optimized-out contents.
 +   Optimized-out contents are equal to optimized-out contents, and are
 +   not equal to non-optimized-out contents.
 
 -   Unavailable contents compare equal with unavailable contents, and
 -   different with non-unavailable contents.
 +   Unavailable contents are equal to unavailable contents, and are not
 +   equal to non-unavailable contents.


> Maybe it would be all easier to have there single map and each range mapping
> into enum { VALID, OPTIMIZED_OUT, UNAVAILABLE }.

Yeah, as mentioned in the commit log, that was part of Andrew's
original series, but I'd rather take baby steps and do that
separately, as it required new code in the range merging code.

New patch below.  Let me know what you think.

Thanks for the review.

8<------------
From d856ed9cb43ad48829c805a88dc6da55bfa149f0 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Thu, 24 Jul 2014 12:48:35 +0100
Subject: [PATCH] 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/
2014-07-24  Andrew Burgess  <aburgess@broadcom.com>
	    Pedro Alves  <palves@redhat.com>

	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/
2014-07-24  Andrew Burgess  <aburgess@broadcom.com>
	    Pedro Alves  <palves@redhat.com>

	PR symtab/14604
	PR symtab/14605
	* gdb.dwarf2/dw2-op-out-param.exp: Remove kfail branches and use
	gdb_test.
---
 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/gdb.dwarf2/dw2-op-out-param.exp |  30 +-
 gdb/valprint.c                                |  22 +-
 gdb/value.c                                   | 467 +++++++++++++++-----------
 gdb/value.h                                   | 158 ++++++---
 17 files changed, 445 insertions(+), 450 deletions(-)

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 6956909..63f84ea 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -682,14 +682,12 @@ coerce_unspec_val_to_type (struct value *val, struct type *type)
       else
 	{
 	  result = allocate_value (type);
-	  memcpy (value_contents_raw (result), value_contents (val),
-		  TYPE_LENGTH (type));
+	  value_contents_copy_raw (result, 0, val, 0, TYPE_LENGTH (type));
 	}
       set_value_component_location (result, val);
       set_value_bitsize (result, value_bitsize (val));
       set_value_bitpos (result, value_bitpos (val));
       set_value_address (result, value_address (val));
-      set_value_optimized_out (result, value_optimized_out_const (val));
       return result;
     }
 }
diff --git a/gdb/ada-valprint.c b/gdb/ada-valprint.c
index b7b3a9c..b4f191f 100644
--- a/gdb/ada-valprint.c
+++ b/gdb/ada-valprint.c
@@ -186,9 +186,9 @@ val_print_packed_array_elements (struct type *type, const gdb_byte *valaddr,
 					       (i * bitsize) / HOST_CHAR_BIT,
 					       (i * bitsize) % HOST_CHAR_BIT,
 					       bitsize, elttype);
-	  if (!value_available_contents_eq (v0, value_embedded_offset (v0),
-					    v1, value_embedded_offset (v1),
-					    eltlen))
+	  if (!value_contents_eq (v0, value_embedded_offset (v0),
+				  v1, value_embedded_offset (v1),
+				  eltlen))
 	    break;
 	}
 
diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c
index f4694b0..2f2789c 100644
--- a/gdb/c-valprint.c
+++ b/gdb/c-valprint.c
@@ -173,9 +173,9 @@ c_val_print (struct type *type, const gdb_byte *valaddr,
 				      options->format)
 	      && value_bytes_available (original_value, embedded_offset,
 					TYPE_LENGTH (type))
-	      && value_bits_valid (original_value,
-				   TARGET_CHAR_BIT * embedded_offset,
-				   TARGET_CHAR_BIT * TYPE_LENGTH (type)))
+	      && !value_bits_any_optimized_out (original_value,
+						TARGET_CHAR_BIT * embedded_offset,
+						TARGET_CHAR_BIT * TYPE_LENGTH (type)))
 	    {
 	      int force_ellipses = 0;
 
diff --git a/gdb/cp-valprint.c b/gdb/cp-valprint.c
index 3e1d6ed..0d6c3fc 100644
--- a/gdb/cp-valprint.c
+++ b/gdb/cp-valprint.c
@@ -294,12 +294,6 @@ cp_print_value_fields (struct type *type, struct type *real_type,
 		{
 		  fputs_filtered (_("<synthetic pointer>"), stream);
 		}
-	      else if (!value_bits_valid (val,
-					  TYPE_FIELD_BITPOS (type, i),
-					  TYPE_FIELD_BITSIZE (type, i)))
-		{
-		  val_print_optimized_out (val, stream);
-		}
 	      else
 		{
 		  struct value_print_options opts = *options;
@@ -434,8 +428,9 @@ cp_print_value_fields_rtti (struct type *type,
 
   /* We require all bits to be valid in order to attempt a
      conversion.  */
-  if (value_bits_valid (val, TARGET_CHAR_BIT * offset,
-			TARGET_CHAR_BIT * TYPE_LENGTH (type)))
+  if (!value_bits_any_optimized_out (val,
+				     TARGET_CHAR_BIT * offset,
+				     TARGET_CHAR_BIT * TYPE_LENGTH (type)))
     {
       struct value *value;
       int full, top, using_enc;
diff --git a/gdb/d-valprint.c b/gdb/d-valprint.c
index 755f180..788b3d5 100644
--- a/gdb/d-valprint.c
+++ b/gdb/d-valprint.c
@@ -38,8 +38,9 @@ dynamic_array_type (struct type *type, const gdb_byte *valaddr,
       && TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_INT
       && strcmp (TYPE_FIELD_NAME (type, 0), "length") == 0
       && strcmp (TYPE_FIELD_NAME (type, 1), "ptr") == 0
-      && value_bits_valid (val, TARGET_CHAR_BIT * embedded_offset,
-			   TARGET_CHAR_BIT * TYPE_LENGTH (type)))
+      && !value_bits_any_optimized_out (val,
+					TARGET_CHAR_BIT * embedded_offset,
+					TARGET_CHAR_BIT * TYPE_LENGTH (type)))
     {
       CORE_ADDR addr;
       struct type *elttype;
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index b1c7ee1..588abac 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -1285,8 +1285,6 @@ static const struct lval_funcs entry_data_value_funcs =
 {
   NULL,	/* read */
   NULL,	/* write */
-  NULL,	/* check_validity */
-  NULL,	/* check_any_valid */
   NULL,	/* indirect */
   entry_data_value_coerce_ref,
   NULL,	/* check_synthetic_pointer */
@@ -1695,7 +1693,7 @@ read_pieced_value (struct value *v)
 		    memset (buffer, 0, this_size);
 
 		    if (optim)
-		      set_value_optimized_out (v, 1);
+		      mark_value_bits_optimized_out (v, offset, this_size_bits);
 		    if (unavail)
 		      mark_value_bits_unavailable (v, offset, this_size_bits);
 		  }
@@ -1755,7 +1753,7 @@ read_pieced_value (struct value *v)
 	  break;
 
 	case DWARF_VALUE_OPTIMIZED_OUT:
-	  set_value_optimized_out (v, 1);
+	  mark_value_bits_optimized_out (v, offset, this_size_bits);
 	  break;
 
 	default:
@@ -1793,7 +1791,7 @@ write_pieced_value (struct value *to, struct value *from)
 
   if (frame == NULL)
     {
-      set_value_optimized_out (to, 1);
+      mark_value_bytes_optimized_out (to, 0, TYPE_LENGTH (value_type (to)));
       return;
     }
 
@@ -1925,7 +1923,7 @@ write_pieced_value (struct value *to, struct value *from)
 			source_buffer, this_size);
 	  break;
 	default:
-	  set_value_optimized_out (to, 1);
+	  mark_value_bytes_optimized_out (to, 0, TYPE_LENGTH (value_type (to)));
 	  break;
 	}
       offset += this_size_bits;
@@ -1934,24 +1932,16 @@ write_pieced_value (struct value *to, struct value *from)
   do_cleanups (cleanup);
 }
 
-/* A helper function that checks bit validity in a pieced value.
-   CHECK_FOR indicates the kind of validity checking.
-   DWARF_VALUE_MEMORY means to check whether any bit is valid.
-   DWARF_VALUE_OPTIMIZED_OUT means to check whether any bit is
-   optimized out.
-   DWARF_VALUE_IMPLICIT_POINTER means to check whether the bits are an
-   implicit pointer.  */
+/* An implementation of an lval_funcs method to see whether a value is
+   a synthetic pointer.  */
 
 static int
-check_pieced_value_bits (const struct value *value, int bit_offset,
-			 int bit_length,
-			 enum dwarf_value_location check_for)
+check_pieced_synthetic_pointer (const struct value *value, int bit_offset,
+				int bit_length)
 {
   struct piece_closure *c
     = (struct piece_closure *) value_computed_closure (value);
   int i;
-  int validity = (check_for == DWARF_VALUE_MEMORY
-		  || check_for == DWARF_VALUE_IMPLICIT_POINTER);
 
   bit_offset += 8 * value_offset (value);
   if (value_bitsize (value))
@@ -1976,52 +1966,11 @@ check_pieced_value_bits (const struct value *value, int bit_offset,
       else
 	bit_length -= this_size_bits;
 
-      if (check_for == DWARF_VALUE_IMPLICIT_POINTER)
-	{
-	  if (p->location != DWARF_VALUE_IMPLICIT_POINTER)
-	    return 0;
-	}
-      else if (p->location == DWARF_VALUE_OPTIMIZED_OUT
-	       || p->location == DWARF_VALUE_IMPLICIT_POINTER)
-	{
-	  if (validity)
-	    return 0;
-	}
-      else
-	{
-	  if (!validity)
-	    return 1;
-	}
+      if (p->location != DWARF_VALUE_IMPLICIT_POINTER)
+	return 0;
     }
 
-  return validity;
-}
-
-static int
-check_pieced_value_validity (const struct value *value, int bit_offset,
-			     int bit_length)
-{
-  return check_pieced_value_bits (value, bit_offset, bit_length,
-				  DWARF_VALUE_MEMORY);
-}
-
-static int
-check_pieced_value_invalid (const struct value *value)
-{
-  return check_pieced_value_bits (value, 0,
-				  8 * TYPE_LENGTH (value_type (value)),
-				  DWARF_VALUE_OPTIMIZED_OUT);
-}
-
-/* An implementation of an lval_funcs method to see whether a value is
-   a synthetic pointer.  */
-
-static int
-check_pieced_synthetic_pointer (const struct value *value, int bit_offset,
-				int bit_length)
-{
-  return check_pieced_value_bits (value, bit_offset, bit_length,
-				  DWARF_VALUE_IMPLICIT_POINTER);
+  return 1;
 }
 
 /* A wrapper function for get_frame_address_in_block.  */
@@ -2170,8 +2119,6 @@ free_pieced_value_closure (struct value *v)
 static const struct lval_funcs pieced_value_funcs = {
   read_pieced_value,
   write_pieced_value,
-  check_pieced_value_validity,
-  check_pieced_value_invalid,
   indirect_pieced_value,
   NULL,	/* coerce_ref */
   check_pieced_synthetic_pointer,
@@ -2299,6 +2246,8 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 	   retval = value_from_register (type, gdb_regnum, frame);
 	   if (value_optimized_out (retval))
 	     {
+	       struct value *tmp;
+
 	       /* 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
@@ -2306,7 +2255,9 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 		  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);
+	       tmp = allocate_value (type);
+	       value_contents_copy (tmp, 0, retval, 0, TYPE_LENGTH (type));
+	       retval = tmp;
 	     }
 	  }
 	  break;
diff --git a/gdb/findvar.c b/gdb/findvar.c
index 9390c8a..346a499 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -681,12 +681,6 @@ read_frame_register_value (struct value *value, struct frame_info *frame)
       struct value *regval = get_frame_register_value (frame, regnum);
       int reg_len = TYPE_LENGTH (value_type (regval)) - reg_offset;
 
-      if (value_optimized_out (regval))
-	{
-	  set_value_optimized_out (value, 1);
-	  break;
-	}
-
       /* If the register length is larger than the number of bytes
          remaining to copy, then only copy the appropriate bytes.  */
       if (reg_len > len)
@@ -732,7 +726,7 @@ value_from_register (struct type *type, int regnum, struct frame_info *frame)
       if (!ok)
 	{
 	  if (optim)
-	    set_value_optimized_out (v, 1);
+	    mark_value_bytes_optimized_out (v, 0, TYPE_LENGTH (type));
 	  if (unavail)
 	    mark_value_bytes_unavailable (v, 0, TYPE_LENGTH (type));
 	}
diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c
index fdfea6e..1cc3303 100644
--- a/gdb/frame-unwind.c
+++ b/gdb/frame-unwind.c
@@ -203,7 +203,7 @@ frame_unwind_got_optimized (struct frame_info *frame, int regnum)
      "<not saved>".  */
   val = allocate_value_lazy (type);
   set_value_lazy (val, 0);
-  set_value_optimized_out (val, 1);
+  mark_value_bytes_optimized_out (val, 0, TYPE_LENGTH (type));
   VALUE_LVAL (val) = lval_register;
   VALUE_REGNUM (val) = regnum;
   VALUE_FRAME_ID (val) = get_frame_id (frame);
diff --git a/gdb/jv-valprint.c b/gdb/jv-valprint.c
index a7bb494..93a827e 100644
--- a/gdb/jv-valprint.c
+++ b/gdb/jv-valprint.c
@@ -183,10 +183,10 @@ java_value_print (struct value *val, struct ui_file *stream,
 		  set_value_offset (next_v, value_offset (next_v)
 				    + TYPE_LENGTH (el_type));
 		  value_fetch_lazy (next_v);
-		  if (!(value_available_contents_eq
-			(v, value_embedded_offset (v),
-			 next_v, value_embedded_offset (next_v),
-			 TYPE_LENGTH (el_type))))
+		  if (!value_contents_eq (v, value_embedded_offset (v),
+					  next_v,
+					  value_embedded_offset (next_v),
+					  TYPE_LENGTH (el_type)))
 		    break;
 		}
 
@@ -393,11 +393,6 @@ java_print_value_fields (struct type *type, const gdb_byte *valaddr,
 		{
 		  fputs_filtered (_("<synthetic pointer>"), stream);
 		}
-	      else if (!value_bits_valid (val, TYPE_FIELD_BITPOS (type, i),
-					  TYPE_FIELD_BITSIZE (type, i)))
-		{
-		  val_print_optimized_out (val, stream);
-		}
 	      else
 		{
 		  struct value_print_options opts;
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index c3e8e77..34b75f7 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -6196,12 +6196,6 @@ mips_print_register (struct ui_file *file, struct frame_info *frame,
     }
 
   val = get_frame_register_value (frame, regnum);
-  if (value_optimized_out (val))
-    {
-      fprintf_filtered (file, "%s: [Invalid]",
-			gdbarch_register_name (gdbarch, regnum));
-      return;
-    }
 
   fputs_filtered (gdbarch_register_name (gdbarch, regnum), file);
 
diff --git a/gdb/opencl-lang.c b/gdb/opencl-lang.c
index 2dd76fa..6a3ba69 100644
--- a/gdb/opencl-lang.c
+++ b/gdb/opencl-lang.c
@@ -240,58 +240,6 @@ lval_func_write (struct value *v, struct value *fromval)
   value_free_to_mark (mark);
 }
 
-/* Return nonzero if all bits in V within OFFSET and LENGTH are valid.  */
-
-static int
-lval_func_check_validity (const struct value *v, int offset, int length)
-{
-  struct lval_closure *c = (struct lval_closure *) value_computed_closure (v);
-  /* Size of the target type in bits.  */
-  int elsize =
-      TYPE_LENGTH (TYPE_TARGET_TYPE (check_typedef (value_type (c->val)))) * 8;
-  int startrest = offset % elsize;
-  int start = offset / elsize;
-  int endrest = (offset + length) % elsize;
-  int end = (offset + length) / elsize;
-  int i;
-
-  if (endrest)
-    end++;
-
-  if (end > c->n)
-    return 0;
-
-  for (i = start; i < end; i++)
-    {
-      int comp_offset = (i == start) ? startrest : 0;
-      int comp_length = (i == end) ? endrest : elsize;
-
-      if (!value_bits_valid (c->val, c->indices[i] * elsize + comp_offset,
-			     comp_length))
-	return 0;
-    }
-
-  return 1;
-}
-
-/* Return nonzero if any bit in V is valid.  */
-
-static int
-lval_func_check_any_valid (const struct value *v)
-{
-  struct lval_closure *c = (struct lval_closure *) value_computed_closure (v);
-  /* Size of the target type in bits.  */
-  int elsize =
-      TYPE_LENGTH (TYPE_TARGET_TYPE (check_typedef (value_type (c->val)))) * 8;
-  int i;
-
-  for (i = 0; i < c->n; i++)
-    if (value_bits_valid (c->val, c->indices[i] * elsize, elsize))
-      return 1;
-
-  return 0;
-}
-
 /* Return nonzero if bits in V from OFFSET and LENGTH represent a
    synthetic pointer.  */
 
@@ -358,8 +306,6 @@ static const struct lval_funcs opencl_value_funcs =
   {
     lval_func_read,
     lval_func_write,
-    lval_func_check_validity,
-    lval_func_check_any_valid,
     NULL,	/* indirect */
     NULL,	/* coerce_ref */
     lval_func_check_synthetic_pointer,
diff --git a/gdb/p-valprint.c b/gdb/p-valprint.c
index 70eb3a8..c796218 100644
--- a/gdb/p-valprint.c
+++ b/gdb/p-valprint.c
@@ -627,11 +627,6 @@ pascal_object_print_value_fields (struct type *type, const gdb_byte *valaddr,
 		{
 		  fputs_filtered (_("<synthetic pointer>"), stream);
 		}
-	      else if (!value_bits_valid (val, TYPE_FIELD_BITPOS (type, i),
-					  TYPE_FIELD_BITSIZE (type, i)))
-		{
-		  val_print_optimized_out (val, stream);
-		}
 	      else
 		{
 		  struct value_print_options opts = *options;
diff --git a/gdb/stack.c b/gdb/stack.c
index 4db5df5..346ce29 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -385,9 +385,12 @@ read_frame_arg (struct symbol *sym, struct frame_info *frame,
 	    {
 	      struct type *type = value_type (val);
 
-	      if (!value_optimized_out (val)
-		  && value_available_contents_eq (val, 0, entryval, 0,
-						  TYPE_LENGTH (type)))
+	      if (value_lazy (val))
+		value_fetch_lazy (val);
+	      if (value_lazy (entryval))
+		value_fetch_lazy (entryval);
+
+	      if (value_contents_eq (val, 0, entryval, 0, TYPE_LENGTH (type)))
 		{
 		  /* Initialize it just to avoid a GCC false warning.  */
 		  struct value *val_deref = NULL, *entryval_deref;
@@ -413,11 +416,9 @@ read_frame_arg (struct symbol *sym, struct frame_info *frame,
 		      /* If the reference addresses match but dereferenced
 			 content does not match print them.  */
 		      if (val != val_deref
-		          && !value_optimized_out (val_deref)
-		          && !value_optimized_out (entryval_deref)
-			  && value_available_contents_eq (val_deref, 0,
-							  entryval_deref, 0,
-						      TYPE_LENGTH (type_deref)))
+			  && value_contents_eq (val_deref, 0,
+						entryval_deref, 0,
+						TYPE_LENGTH (type_deref)))
 			val_equal = 1;
 		    }
 
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp b/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp
index 5ab5817..d245951 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp
@@ -50,36 +50,12 @@ gdb_test "bt" "#0  ($hex in )?breakpt \\(\\)\r\n#1  ($hex in )?int_param_single_
 
 # (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 $" {
-	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 $" {
-	kfail "symtab/14604" $test
-    }
-}
+gdb_test "bt" "#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 \\(\\)" "Backtrace for test struct_param_single_reg_loc"
 
 # (3) struct_param_two_reg_pieces
 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 $" {
-	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 $" {
-	kfail "symtab/14605" $test
-    }
-}
+gdb_test "bt" "#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 \\(\\)" "Backtrace for test struct_param_two_reg_pieces"
 
 # (4) int_param_two_reg_pieces
 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 $" {
-	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 $" {
-	kfail "symtab/14605" $test
-    }
-}
+gdb_test "bt" "#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 \\(\\)" "Backtrace for test int_param_two_reg_pieces"
diff --git a/gdb/valprint.c b/gdb/valprint.c
index 8600b34..981ef9b 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -311,8 +311,9 @@ valprint_check_validity (struct ui_file *stream,
       && TYPE_CODE (type) != TYPE_CODE_STRUCT
       && TYPE_CODE (type) != TYPE_CODE_ARRAY)
     {
-      if (!value_bits_valid (val, TARGET_CHAR_BIT * embedded_offset,
-			     TARGET_CHAR_BIT * TYPE_LENGTH (type)))
+      if (value_bits_any_optimized_out (val,
+					TARGET_CHAR_BIT * embedded_offset,
+					TARGET_CHAR_BIT * TYPE_LENGTH (type)))
 	{
 	  val_print_optimized_out (val, stream);
 	  return 0;
@@ -983,8 +984,9 @@ val_print_scalar_formatted (struct type *type,
 
   /* A scalar object that does not have all bits available can't be
      printed, because all bits contribute to its representation.  */
-  if (!value_bits_valid (val, TARGET_CHAR_BIT * embedded_offset,
-			      TARGET_CHAR_BIT * TYPE_LENGTH (type)))
+  if (value_bits_any_optimized_out (val,
+				    TARGET_CHAR_BIT * embedded_offset,
+				    TARGET_CHAR_BIT * TYPE_LENGTH (type)))
     val_print_optimized_out (val, stream);
   else if (!value_bytes_available (val, embedded_offset, TYPE_LENGTH (type)))
     val_print_unavailable (stream);
@@ -1685,12 +1687,12 @@ val_print_array_elements (struct type *type,
       if (options->repeat_count_threshold < UINT_MAX)
 	{
 	  while (rep1 < len
-		 && value_available_contents_eq (val,
-						 embedded_offset + i * eltlen,
-						 val,
-						 (embedded_offset
-						  + rep1 * eltlen),
-						 eltlen))
+		 && value_contents_eq (val,
+				       embedded_offset + i * eltlen,
+				       val,
+				       (embedded_offset
+					+ rep1 * eltlen),
+				       eltlen))
 	    {
 	      ++reps;
 	      ++rep1;
diff --git a/gdb/value.c b/gdb/value.c
index 8b44a6d..01e9409 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -197,15 +197,6 @@ struct value
      reset, be sure to consider this use as well!  */
   unsigned int lazy : 1;
 
-  /* 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.  */
   unsigned int initialized : 1;
 
@@ -336,9 +327,20 @@ struct value
 
   /* Unavailable ranges in CONTENTS.  We mark unavailable ranges,
      rather than available, since the common and default case is for a
-     value to be available.  This is filled in at value read time.  The
-     unavailable ranges are tracked in bits.  */
+     value to be available.  This is filled in at value read time.
+     The unavailable ranges are tracked in bits.  Note that a contents
+     bit that has been optimized out doesn't really exist in the
+     program, so it can't be marked unavailable either.  */
   VEC(range_s) *unavailable;
+
+  /* Likewise, but for optimized out contents (a chunk of the value of
+     a variable that does not actually exist in the program).  If LVAL
+     is lval_register, this is a register ($pc, $sp, etc., never a
+     program variable) that has not been saved in the frame.  Not
+     saved registers and optimized-out program variables values are
+     treated pretty much the same, except not-saved registers have a
+     different string representation and related error strings.  */
+  VEC(range_s) *optimized_out;
 };
 
 int
@@ -358,6 +360,14 @@ value_bytes_available (const struct value *value, int offset, int length)
 }
 
 int
+value_bits_any_optimized_out (const struct value *value, int bit_offset, int bit_length)
+{
+  gdb_assert (!value->lazy);
+
+  return ranges_contain (value->optimized_out, bit_offset, bit_length);
+}
+
+int
 value_entirely_available (struct value *value)
 {
   /* We can only tell whether the whole value is available when we try
@@ -370,17 +380,22 @@ value_entirely_available (struct value *value)
   return 0;
 }
 
-int
-value_entirely_unavailable (struct value *value)
+/* Returns true if VALUE is entirely covered by RANGES.  If the value
+   is lazy, it'll be read now.  Note that RANGE is a pointer to
+   pointer because reading the value might change *RANGE.  */
+
+static int
+value_entirely_covered_by_range_vector (struct value *value,
+					VEC(range_s) **ranges)
 {
-  /* We can only tell whether the whole value is available when we try
-     to read it.  */
+  /* We can only tell whether the whole value is optimized out /
+     unavailable when we try to read it.  */
   if (value->lazy)
     value_fetch_lazy (value);
 
-  if (VEC_length (range_s, value->unavailable) == 1)
+  if (VEC_length (range_s, *ranges) == 1)
     {
-      struct range *t = VEC_index (range_s, value->unavailable, 0);
+      struct range *t = VEC_index (range_s, *ranges, 0);
 
       if (t->offset == 0
 	  && t->length == (TARGET_CHAR_BIT
@@ -391,8 +406,23 @@ value_entirely_unavailable (struct value *value)
   return 0;
 }
 
-void
-mark_value_bits_unavailable (struct value *value, int offset, int length)
+int
+value_entirely_unavailable (struct value *value)
+{
+  return value_entirely_covered_by_range_vector (value, &value->unavailable);
+}
+
+int
+value_entirely_optimized_out (struct value *value)
+{
+  return value_entirely_covered_by_range_vector (value, &value->optimized_out);
+}
+
+/* Insert into the vector pointed to by VECTORP the bit range starting of
+   OFFSET bits, and extending for the next LENGTH bits.  */
+
+static void
+insert_into_bit_range_vector (VEC(range_s) **vectorp, int offset, int length)
 {
   range_s newr;
   int i;
@@ -483,10 +513,10 @@ mark_value_bits_unavailable (struct value *value, int offset, int length)
 
   */
 
-  i = VEC_lower_bound (range_s, value->unavailable, &newr, range_lessthan);
+  i = VEC_lower_bound (range_s, *vectorp, &newr, range_lessthan);
   if (i > 0)
     {
-      struct range *bef = VEC_index (range_s, value->unavailable, i - 1);
+      struct range *bef = VEC_index (range_s, *vectorp, i - 1);
 
       if (ranges_overlap (bef->offset, bef->length, offset, length))
 	{
@@ -507,18 +537,18 @@ mark_value_bits_unavailable (struct value *value, int offset, int length)
       else
 	{
 	  /* #3 */
-	  VEC_safe_insert (range_s, value->unavailable, i, &newr);
+	  VEC_safe_insert (range_s, *vectorp, i, &newr);
 	}
     }
   else
     {
       /* #4 */
-      VEC_safe_insert (range_s, value->unavailable, i, &newr);
+      VEC_safe_insert (range_s, *vectorp, i, &newr);
     }
 
   /* Check whether the ranges following the one we've just added or
      touched can be folded in (#5 above).  */
-  if (i + 1 < VEC_length (range_s, value->unavailable))
+  if (i + 1 < VEC_length (range_s, *vectorp))
     {
       struct range *t;
       struct range *r;
@@ -526,11 +556,11 @@ mark_value_bits_unavailable (struct value *value, int offset, int length)
       int next = i + 1;
 
       /* Get the range we just touched.  */
-      t = VEC_index (range_s, value->unavailable, i);
+      t = VEC_index (range_s, *vectorp, i);
       removed = 0;
 
       i = next;
-      for (; VEC_iterate (range_s, value->unavailable, i, r); i++)
+      for (; VEC_iterate (range_s, *vectorp, i, r); i++)
 	if (r->offset <= t->offset + t->length)
 	  {
 	    ULONGEST l, h;
@@ -552,11 +582,17 @@ mark_value_bits_unavailable (struct value *value, int offset, int length)
 	  }
 
       if (removed != 0)
-	VEC_block_remove (range_s, value->unavailable, next, removed);
+	VEC_block_remove (range_s, *vectorp, next, removed);
     }
 }
 
 void
+mark_value_bits_unavailable (struct value *value, int offset, int length)
+{
+  insert_into_bit_range_vector (&value->unavailable, offset, length);
+}
+
+void
 mark_value_bytes_unavailable (struct value *value, int offset, int length)
 {
   mark_value_bits_unavailable (value,
@@ -684,48 +720,53 @@ memcmp_with_bit_offsets (const gdb_byte *ptr1, size_t offset1_bits,
   return 0;
 }
 
-/* Helper function for value_available_contents_eq. The only difference is
-   that this function is bit rather than byte based.
+/* Helper struct for find_first_range_overlap_and_match and
+   value_contents_bits_eq.  Keep track of which slot of a given ranges
+   vector have we last looked at.  */
 
-   Compare LENGTH bits of VAL1's contents starting at OFFSET1 bits with
-   LENGTH bits of VAL2's contents starting at OFFSET2 bits.  Return true
-   if the available bits match.  */
+struct ranges_and_idx
+{
+  /* The ranges.  */
+  VEC(range_s) *ranges;
+
+  /* The range we've last found in RANGES.  Given ranges are sorted,
+     we can start the next lookup here.  */
+  int idx;
+};
+
+/* Helper function for value_contents_bits_eq.  Compare LENGTH bits of
+   RP1's ranges starting at OFFSET1 bits with LENGTH bits of RP2's
+   ranges starting at OFFSET2 bits.  Return true if the ranges match
+   and fill in *L and *H with the overlapping window relative to
+   (both) OFFSET1 or OFFSET2.  */
 
 static int
-value_available_contents_bits_eq (const struct value *val1, int offset1,
-				  const struct value *val2, int offset2,
-				  int length)
+find_first_range_overlap_and_match (struct ranges_and_idx *rp1,
+				    struct ranges_and_idx *rp2,
+				    int offset1, int offset2,
+				    int length, ULONGEST *l, ULONGEST *h)
 {
-  int idx1 = 0, idx2 = 0;
-
-  /* See function description in value.h.  */
-  gdb_assert (!val1->lazy && !val2->lazy);
+  rp1->idx = find_first_range_overlap (rp1->ranges, rp1->idx,
+				       offset1, length);
+  rp2->idx = find_first_range_overlap (rp2->ranges, rp2->idx,
+				       offset2, length);
 
-  while (length > 0)
+  if (rp1->idx == -1 && rp2->idx == -1)
+    {
+      *l = length;
+      *h = length;
+      return 1;
+    }
+  else if (rp1->idx == -1 || rp2->idx == -1)
+    return 0;
+  else
     {
       range_s *r1, *r2;
       ULONGEST l1, h1;
       ULONGEST l2, h2;
 
-      idx1 = find_first_range_overlap (val1->unavailable, idx1,
-				       offset1, length);
-      idx2 = find_first_range_overlap (val2->unavailable, idx2,
-				       offset2, length);
-
-      /* The usual case is for both values to be completely available.  */
-      if (idx1 == -1 && idx2 == -1)
-	return (memcmp_with_bit_offsets (val1->contents, offset1,
-					 val2->contents, offset2,
-					 length) == 0);
-      /* The contents only match equal if the available set matches as
-	 well.  */
-      else if (idx1 == -1 || idx2 == -1)
-	return 0;
-
-      gdb_assert (idx1 != -1 && idx2 != -1);
-
-      r1 = VEC_index (range_s, val1->unavailable, idx1);
-      r2 = VEC_index (range_s, val2->unavailable, idx2);
+      r1 = VEC_index (range_s, rp1->ranges, rp1->idx);
+      r2 = VEC_index (range_s, rp2->ranges, rp2->idx);
 
       /* Get the unavailable windows intersected by the incoming
 	 ranges.  The first and last ranges that overlap the argument
@@ -734,7 +775,7 @@ value_available_contents_bits_eq (const struct value *val1, int offset1,
       h1 = min (offset1 + length, r1->offset + r1->length);
 
       l2 = max (offset2, r2->offset);
-      h2 = min (offset2 + length, r2->offset + r2->length);
+      h2 = min (offset2 + length, offset2 + r2->length);
 
       /* Make them relative to the respective start offsets, so we can
 	 compare them for equality.  */
@@ -744,31 +785,93 @@ value_available_contents_bits_eq (const struct value *val1, int offset1,
       l2 -= offset2;
       h2 -= offset2;
 
-      /* Different availability, no match.  */
+      /* Different ranges, no match.  */
       if (l1 != l2 || h1 != h2)
 	return 0;
 
-      /* Compare the _available_ contents.  */
+      *h = h1;
+      *l = l1;
+      return 1;
+    }
+}
+
+/* Helper function for value_contents_eq.  The only difference is that
+   this function is bit rather than byte based.
+
+   Compare LENGTH bits of VAL1's contents starting at OFFSET1 bits
+   with LENGTH bits of VAL2's contents starting at OFFSET2 bits.
+   Return true if the available bits match.  */
+
+static int
+value_contents_bits_eq (const struct value *val1, int offset1,
+			const struct value *val2, int offset2,
+			int length)
+{
+  /* Each array element corresponds to a ranges source (unavailable,
+     optimized out).  '1' is for VAL1, '2' for VAL2.  */
+  struct ranges_and_idx rp1[2], rp2[2];
+
+  /* See function description in value.h.  */
+  gdb_assert (!val1->lazy && !val2->lazy);
+
+  /* We shouldn't be trying to compare past the end of the values.  */
+  gdb_assert (offset1 + length
+	      <= TYPE_LENGTH (val1->enclosing_type) * TARGET_CHAR_BIT);
+  gdb_assert (offset2 + length
+	      <= TYPE_LENGTH (val2->enclosing_type) * TARGET_CHAR_BIT);
+
+  memset (&rp1, 0, sizeof (rp1));
+  memset (&rp2, 0, sizeof (rp2));
+  rp1[0].ranges = val1->unavailable;
+  rp2[0].ranges = val2->unavailable;
+  rp1[1].ranges = val1->optimized_out;
+  rp2[1].ranges = val2->optimized_out;
+
+  while (length > 0)
+    {
+      ULONGEST l, h;
+      int i;
+
+      for (i = 0; i < 2; i++)
+	{
+	  ULONGEST l_tmp, h_tmp;
+
+	  /* The contents only match equal if the invalid/unavailable
+	     contents ranges match as well.  */
+	  if (!find_first_range_overlap_and_match (&rp1[i], &rp2[i],
+						   offset1, offset2, length,
+						   &l_tmp, &h_tmp))
+	    return 0;
+
+	  /* We're interested in the lowest/first range found.  */
+	  if (i == 0 || l_tmp < l)
+	    {
+	      l = l_tmp;
+	      h = h_tmp;
+	    }
+	}
+
+      /* Compare the available/valid contents.  */
       if (memcmp_with_bit_offsets (val1->contents, offset1,
-				   val2->contents, offset2, l1) != 0)
+				   val2->contents, offset2, l) != 0)
 	return 0;
 
-      length -= h1;
-      offset1 += h1;
-      offset2 += h1;
+      length -= h;
+      offset1 += h;
+      offset2 += h;
     }
 
   return 1;
 }
 
 int
-value_available_contents_eq (const struct value *val1, int offset1,
-			     const struct value *val2, int offset2,
-			     int length)
+value_contents_eq (const struct value *val1, int offset1,
+		   const struct value *val2, int offset2,
+		   int length)
 {
-  return value_available_contents_bits_eq (val1, offset1 * TARGET_CHAR_BIT,
-					   val2, offset2 * TARGET_CHAR_BIT,
-					   length * TARGET_CHAR_BIT);
+  return value_contents_bits_eq (val1, offset1 * TARGET_CHAR_BIT,
+				 val2, offset2 * TARGET_CHAR_BIT,
+				 length * TARGET_CHAR_BIT);
 }
 
 /* Prototypes for local functions.  */
@@ -836,7 +939,6 @@ allocate_value_lazy (struct type *type)
   val->bitsize = 0;
   VALUE_REGNUM (val) = -1;
   val->lazy = 1;
-  val->optimized_out = 0;
   val->embedded_offset = 0;
   val->pointed_to_offset = 0;
   val->modifiable = 1;
@@ -905,11 +1007,8 @@ allocate_optimized_out_value (struct type *type)
 {
   struct value *retval = allocate_value_lazy (type);
 
-  set_value_optimized_out (retval, 1);
-  /* FIXME: we should be able to avoid allocating the value's contents
-     buffer, but value_available_contents_bits_eq can't handle
-     that.  */
-  /* set_value_lazy (retval, 0); */
+  mark_value_bytes_optimized_out (retval, 0, TYPE_LENGTH (type));
+  set_value_lazy (retval, 0);
   return retval;
 }
 
@@ -1057,7 +1156,7 @@ error_value_optimized_out (void)
 static void
 require_not_optimized_out (const struct value *value)
 {
-  if (value->optimized_out)
+  if (!VEC_empty (range_s, value->optimized_out))
     {
       if (value->lval == lval_register)
 	error (_("register has not been saved in frame"));
@@ -1097,6 +1196,31 @@ value_contents_all (struct value *value)
   return result;
 }
 
+/* Copy ranges in SRC_RANGE that overlap [SRC_BIT_OFFSET,
+   SRC_BIT_OFFSET+BIT_LENGTH) ranges into *DST_RANGE, adjusted.  */
+
+static void
+ranges_copy_adjusted (VEC (range_s) **dst_range, int dst_bit_offset,
+		      VEC (range_s) *src_range, int src_bit_offset,
+		      int bit_length)
+{
+  range_s *r;
+  int i;
+
+  for (i = 0; VEC_iterate (range_s, src_range, i, r); i++)
+    {
+      ULONGEST h, l;
+
+      l = max (r->offset, src_bit_offset);
+      h = min (r->offset + r->length, src_bit_offset + bit_length);
+
+      if (l < h)
+	insert_into_bit_range_vector (dst_range,
+				      dst_bit_offset + (l - src_bit_offset),
+				      h - l);
+    }
+}
+
 /* Copy LENGTH bytes of SRC value's (all) contents
    (value_contents_all) starting at SRC_OFFSET, into DST value's (all)
    contents, starting at DST_OFFSET.  If unavailable contents are
@@ -1125,6 +1249,9 @@ value_contents_copy_raw (struct value *dst, int dst_offset,
      replaced.  Make sure to remember to implement replacing if it
      turns out actually necessary.  */
   gdb_assert (value_bytes_available (dst, dst_offset, length));
+  gdb_assert (!value_bits_any_optimized_out (dst,
+					     TARGET_CHAR_BIT * dst_offset,
+					     TARGET_CHAR_BIT * length));
 
   /* Copy the data.  */
   memcpy (value_contents_all_raw (dst) + dst_offset,
@@ -1135,18 +1262,14 @@ value_contents_copy_raw (struct value *dst, int dst_offset,
   src_bit_offset = src_offset * TARGET_CHAR_BIT;
   dst_bit_offset = dst_offset * TARGET_CHAR_BIT;
   bit_length = length * TARGET_CHAR_BIT;
-  for (i = 0; VEC_iterate (range_s, src->unavailable, i, r); i++)
-    {
-      ULONGEST h, l;
 
-      l = max (r->offset, src_bit_offset);
-      h = min (r->offset + r->length, src_bit_offset + bit_length);
+  ranges_copy_adjusted (&dst->unavailable, dst_bit_offset,
+			src->unavailable, src_bit_offset,
+			bit_length);
 
-      if (l < h)
-	mark_value_bits_unavailable (dst,
-				     dst_bit_offset + (l - src_bit_offset),
-				     h - l);
-    }
+  ranges_copy_adjusted (&dst->optimized_out, dst_bit_offset,
+			src->optimized_out, src_bit_offset,
+			bit_length);
 }
 
 /* Copy LENGTH bytes of SRC value's (all) contents
@@ -1154,8 +1277,7 @@ value_contents_copy_raw (struct value *dst, int dst_offset,
    (all) contents, starting at DST_OFFSET.  If unavailable contents
    are being copied from SRC, the corresponding DST contents are
    marked unavailable accordingly.  DST must not be lazy.  If SRC is
-   lazy, it will be fetched now.  If SRC is not valid (is optimized
-   out), an error is thrown.
+   lazy, it will be fetched now.
 
    It is assumed the contents of DST in the [DST_OFFSET,
    DST_OFFSET+LENGTH) range are wholly available.  */
@@ -1164,8 +1286,6 @@ void
 value_contents_copy (struct value *dst, int dst_offset,
 		     struct value *src, int src_offset, int length)
 {
-  require_not_optimized_out (src);
-
   if (src->lazy)
     value_fetch_lazy (src);
 
@@ -1218,45 +1338,29 @@ value_optimized_out (struct value *value)
 {
   /* We can only know if a value is optimized out once we have tried to
      fetch it.  */
-  if (!value->optimized_out && value->lazy)
+  if (VEC_empty (range_s, value->optimized_out) && value->lazy)
     value_fetch_lazy (value);
 
-  return value->optimized_out;
+  return !VEC_empty (range_s, value->optimized_out);
 }
 
-int
-value_optimized_out_const (const struct value *value)
-{
-  return value->optimized_out;
-}
+/* Mark contents of VALUE as optimized out, starting at OFFSET bytes, and
+   the following LENGTH bytes.  */
 
 void
-set_value_optimized_out (struct value *value, int val)
+mark_value_bytes_optimized_out (struct value *value, int offset, int length)
 {
-  value->optimized_out = val;
+  mark_value_bits_optimized_out (value,
+				 offset * TARGET_CHAR_BIT,
+				 length * TARGET_CHAR_BIT);
 }
 
-int
-value_entirely_optimized_out (const struct value *value)
-{
-  if (!value->optimized_out)
-    return 0;
-  if (value->lval != lval_computed
-      || !value->location.computed.funcs->check_any_valid)
-    return 1;
-  return !value->location.computed.funcs->check_any_valid (value);
-}
+/* See value.h.  */
 
-int
-value_bits_valid (const struct value *value, int offset, int length)
+void
+mark_value_bits_optimized_out (struct value *value, int offset, int length)
 {
-  if (!value->optimized_out)
-    return 1;
-  if (value->lval != lval_computed
-      || !value->location.computed.funcs->check_validity)
-    return 0;
-  return value->location.computed.funcs->check_validity (value, offset,
-							 length);
+  insert_into_bit_range_vector (&value->optimized_out, offset, length);
 }
 
 int
@@ -1569,7 +1673,6 @@ value_copy (struct value *arg)
   VALUE_FRAME_ID (val) = VALUE_FRAME_ID (arg);
   VALUE_REGNUM (val) = VALUE_REGNUM (arg);
   val->lazy = arg->lazy;
-  val->optimized_out = arg->optimized_out;
   val->embedded_offset = value_embedded_offset (arg);
   val->pointed_to_offset = arg->pointed_to_offset;
   val->modifiable = arg->modifiable;
@@ -1580,6 +1683,7 @@ value_copy (struct value *arg)
 
     }
   val->unavailable = VEC_copy (range_s, arg->unavailable);
+  val->optimized_out = VEC_copy (range_s, arg->optimized_out);
   set_value_parent (val, arg->parent);
   if (VALUE_LVAL (val) == lval_computed)
     {
@@ -2854,24 +2958,19 @@ value_primitive_field (struct value *arg1, int offset,
       int bitpos = TYPE_FIELD_BITPOS (arg_type, fieldno);
       int container_bitsize = TYPE_LENGTH (type) * 8;
 
-      if (arg1->optimized_out)
-	v = allocate_optimized_out_value (type);
+      v = allocate_value_lazy (type);
+      v->bitsize = TYPE_FIELD_BITSIZE (arg_type, fieldno);
+      if ((bitpos % container_bitsize) + v->bitsize <= container_bitsize
+	  && TYPE_LENGTH (type) <= (int) sizeof (LONGEST))
+	v->bitpos = bitpos % container_bitsize;
       else
-	{
-	  v = allocate_value_lazy (type);
-	  v->bitsize = TYPE_FIELD_BITSIZE (arg_type, fieldno);
-	  if ((bitpos % container_bitsize) + v->bitsize <= container_bitsize
-	      && TYPE_LENGTH (type) <= (int) sizeof (LONGEST))
-	    v->bitpos = bitpos % container_bitsize;
-	  else
-	    v->bitpos = bitpos % 8;
-	  v->offset = (value_embedded_offset (arg1)
-		       + offset
-		       + (bitpos - v->bitpos) / 8);
-	  set_value_parent (v, arg1);
-	  if (!value_lazy (arg1))
-	    value_fetch_lazy (v);
-	}
+	v->bitpos = bitpos % 8;
+      v->offset = (value_embedded_offset (arg1)
+		   + offset
+		   + (bitpos - v->bitpos) / 8);
+      set_value_parent (v, arg1);
+      if (!value_lazy (arg1))
+	value_fetch_lazy (v);
     }
   else if (fieldno < TYPE_N_BASECLASSES (arg_type))
     {
@@ -2884,37 +2983,29 @@ value_primitive_field (struct value *arg1, int offset,
       if (VALUE_LVAL (arg1) == lval_register && value_lazy (arg1))
 	value_fetch_lazy (arg1);
 
-      /* The optimized_out flag is only set correctly once a lazy value is
-         loaded, having just loaded some lazy values we should check the
-         optimized out case now.  */
-      if (arg1->optimized_out)
-	v = allocate_optimized_out_value (type);
+      /* We special case virtual inheritance here because this
+	 requires access to the contents, which we would rather avoid
+	 for references to ordinary fields of unavailable values.  */
+      if (BASETYPE_VIA_VIRTUAL (arg_type, fieldno))
+	boffset = baseclass_offset (arg_type, fieldno,
+				    value_contents (arg1),
+				    value_embedded_offset (arg1),
+				    value_address (arg1),
+				    arg1);
       else
-	{
-	  /* We special case virtual inheritance here because this
-	     requires access to the contents, which we would rather avoid
-	     for references to ordinary fields of unavailable values.  */
-	  if (BASETYPE_VIA_VIRTUAL (arg_type, fieldno))
-	    boffset = baseclass_offset (arg_type, fieldno,
-					value_contents (arg1),
-					value_embedded_offset (arg1),
-					value_address (arg1),
-					arg1);
-	  else
-	    boffset = TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
+	boffset = TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
 
-	  if (value_lazy (arg1))
-	    v = allocate_value_lazy (value_enclosing_type (arg1));
-	  else
-	    {
-	      v = allocate_value (value_enclosing_type (arg1));
-	      value_contents_copy_raw (v, 0, arg1, 0,
-				       TYPE_LENGTH (value_enclosing_type (arg1)));
-	    }
-	  v->type = type;
-	  v->offset = value_offset (arg1);
-	  v->embedded_offset = offset + value_embedded_offset (arg1) + boffset;
+      if (value_lazy (arg1))
+	v = allocate_value_lazy (value_enclosing_type (arg1));
+      else
+	{
+	  v = allocate_value (value_enclosing_type (arg1));
+	  value_contents_copy_raw (v, 0, arg1, 0,
+				   TYPE_LENGTH (value_enclosing_type (arg1)));
 	}
+      v->type = type;
+      v->offset = value_offset (arg1);
+      v->embedded_offset = offset + value_embedded_offset (arg1) + boffset;
     }
   else
     {
@@ -2925,12 +3016,7 @@ value_primitive_field (struct value *arg1, int offset,
       if (VALUE_LVAL (arg1) == lval_register && value_lazy (arg1))
 	value_fetch_lazy (arg1);
 
-      /* The optimized_out flag is only set correctly once a lazy value is
-         loaded, having just loaded some lazy values we should check for
-         the optimized out case now.  */
-      if (arg1->optimized_out)
-	v = allocate_optimized_out_value (type);
-      else if (value_lazy (arg1))
+      if (value_lazy (arg1))
 	v = allocate_value_lazy (type);
       else
 	{
@@ -3649,6 +3735,11 @@ value_fetch_lazy (struct value *val)
 {
   gdb_assert (value_lazy (val));
   allocate_value_contents (val);
+  /* A value is either lazy, or fully fetched.  The
+     availability/validity is only established as we try to fetch a
+     value.  */
+  gdb_assert (VEC_empty (range_s, val->optimized_out));
+  gdb_assert (VEC_empty (range_s, val->unavailable));
   if (value_bitsize (val))
     {
       /* To read a lazy bitfield, read the entire enclosing value.  This
@@ -3665,10 +3756,11 @@ value_fetch_lazy (struct value *val)
       if (value_lazy (parent))
 	value_fetch_lazy (parent);
 
-      if (!value_bits_valid (parent,
-			     TARGET_CHAR_BIT * offset + value_bitpos (val),
-			     value_bitsize (val)))
-	set_value_optimized_out (val, 1);
+      if (value_bits_any_optimized_out (parent,
+					TARGET_CHAR_BIT * offset + value_bitpos (val),
+					value_bitsize (val)))
+	mark_value_bytes_optimized_out (val, value_embedded_offset (val),
+					TYPE_LENGTH (type));
       else if (!unpack_value_bits_as_long (value_type (val),
 				      value_contents_for_printing (parent),
 				      offset,
@@ -3743,16 +3835,12 @@ value_fetch_lazy (struct value *val)
       if (value_lazy (new_val))
 	value_fetch_lazy (new_val);
 
-      /* If the register was not saved, mark it optimized out.  */
-      if (value_optimized_out (new_val))
-	set_value_optimized_out (val, 1);
-      else
-	{
-	  set_value_lazy (val, 0);
-	  value_contents_copy (val, value_embedded_offset (val),
-			       new_val, value_embedded_offset (new_val),
-			       TYPE_LENGTH (type));
-	}
+      /* Copy the contents and the unavailability/optimized-out
+	 meta-data from NEW_VAL to VAL.  */
+      set_value_lazy (val, 0);
+      value_contents_copy (val, value_embedded_offset (val),
+			   new_val, value_embedded_offset (new_val),
+			   TYPE_LENGTH (type));
 
       if (frame_debug)
 	{
@@ -3805,11 +3893,6 @@ value_fetch_lazy (struct value *val)
   else if (VALUE_LVAL (val) == lval_computed
 	   && value_computed_funcs (val)->read != NULL)
     value_computed_funcs (val)->read (val);
-  /* Don't call value_optimized_out on val, doing so would result in a
-     recursive call back to value_fetch_lazy, instead check the
-     optimized_out flag directly.  */
-  else if (val->optimized_out)
-    /* Keep it optimized out.  */;
   else
     internal_error (__FILE__, __LINE__, _("Unexpected lazy value type."));
 
diff --git a/gdb/value.h b/gdb/value.h
index 86ebd70..bff5220 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -33,6 +33,54 @@ struct language_defn;
 struct value_print_options;
 struct xmethod_worker;
 
+/* Values can be partially 'optimized out' and/or 'unavailable'.
+   These are distinct states and have different string representations
+   and related error strings.
+
+   'unavailable' has a specific meaning in this context.  It means the
+   value exists in the program (at the machine level), but GDB has no
+   means to get to it.  Such a value is normally printed as
+   <unavailable>.  Examples of how to end up with an unavailable value
+   would be:
+
+    - We're inspecting a traceframe, and the memory or registers the
+      debug information says the value lives on haven't been collected.
+
+    - We're inspecting a core dump, the memory or registers the debug
+      information says the value lives aren't present in the dump
+      (that is, we have a partial/trimmed core dump, or we don't fully
+      understand/handle the core dump's format).
+
+    - We're doing live debugging, but the debug API has no means to
+      get at where the value lives in the machine, like e.g., ptrace
+      not having access to some register or register set.
+
+    - Any other similar scenario.
+
+  OTOH, "optimized out" is about what the compiler decided to generate
+  (or not generate).  A chunk of a value that was optimized out does
+  not actually exist in the program.  There's no way to get at it
+  short of compiling the program differently.
+
+  A register that has not been saved in a frame is likewise considered
+  optimized out, except not-saved registers have a different string
+  representation and related error strings.  E.g., we'll print them as
+  <not-saved> instead of <optimized out>, as in:
+
+    (gdb) p/x $rax
+    $1 = <not saved>
+    (gdb) info registers rax
+    rax            <not saved>
+
+  If the debug info describes a variable as being in such a register,
+  we'll still print the variable as <optimized out>.  IOW, <not saved>
+  is reserved for inspecting registers at the machine level.
+
+  When comparing value contents, optimized out chunks, unavailable
+  chunks, and valid contents data are all considered different.  See
+  value_contents_eq for more info.
+*/
+
 /* The structure which defines the type of a value.  It should never
    be possible for a program lval value to survive over a call to the
    inferior (i.e. to be put into the history list or an internal
@@ -181,14 +229,6 @@ struct lval_funcs
      TOVAL is not considered as an lvalue.  */
   void (*write) (struct value *toval, struct value *fromval);
 
-  /* Check the validity of some bits in VALUE.  This should return 1
-     if all the bits starting at OFFSET and extending for LENGTH bits
-     are valid, or 0 if any bit is invalid.  */
-  int (*check_validity) (const struct value *value, int offset, int length);
-
-  /* Return 1 if any bit in VALUE is valid, 0 if they are all invalid.  */
-  int (*check_any_valid) (const struct value *value);
-
   /* If non-NULL, this is used to implement pointer indirection for
      this value.  This method may return NULL, in which case value_ind
      will fall back to ordinary indirection.  */
@@ -327,16 +367,29 @@ extern int value_fetch_lazy (struct value *val);
    exist in the program, at least partially.  If the value is lazy,
    this may fetch it now.  */
 extern int value_optimized_out (struct value *value);
-extern void set_value_optimized_out (struct value *value, int val);
 
-/* Like value_optimized_out, but don't fetch the value even if it is
-   lazy.  Mainly useful for constructing other values using VALUE as
-   template.  */
-extern int value_optimized_out_const (const struct value *value);
+/* Given a value, return true if any of the contents bits starting at
+   OFFSET and extending for LENGTH bits is optimized out, false
+   otherwise.  */
+
+extern int value_bits_any_optimized_out (const struct value *value,
+					 int bit_offset, int bit_length);
+
+/* Like value_optimized_out, but return true iff the whole value is
+   optimized out.  */
+extern int value_entirely_optimized_out (struct value *value);
+
+/* Mark VALUE's content bytes starting at OFFSET and extending for
+   LENGTH bytes as optimized out.  */
+
+extern void mark_value_bytes_optimized_out (struct value *value,
+					    int offset, int length);
+
+/* Mark VALUE's content bits starting at OFFSET and extending for
+   LENGTH bits as optimized out.  */
 
-/* Like value_optimized_out, but return false if any bit in the object
-   is valid.  */
-extern int value_entirely_optimized_out (const struct value *value);
+extern void mark_value_bits_optimized_out (struct value *value,
+					   int offset, int length);
 
 /* Set or return field indicating whether a variable is initialized or
    not, based on debugging information supplied by the compiler.
@@ -416,13 +469,6 @@ extern struct value *coerce_ref (struct value *value);
 extern struct value *coerce_array (struct value *value);
 
 /* Given a value, determine whether the bits starting at OFFSET and
-   extending for LENGTH bits are valid.  This returns nonzero if all
-   bits in the given range are valid, zero if any bit is invalid.  */
-
-extern int value_bits_valid (const struct value *value,
-			     int offset, int length);
-
-/* Given a value, determine whether the bits starting at OFFSET and
    extending for LENGTH bits are a synthetic pointer.  */
 
 extern int value_bits_synthetic_pointer (const struct value *value,
@@ -473,35 +519,53 @@ extern void mark_value_bits_unavailable (struct value *value,
    its enclosing type chunk, you'd do:
 
      int len = TYPE_LENGTH (check_typedef (value_enclosing_type (val)));
-     value_available_contents (val, 0, val, 0, len);
+     value_contents_eq (val, 0, val, 0, len);
+
+   Returns true iff the set of available/valid contents match.
+
+   Optimized-out contents are equal to optimized-out contents, and are
+   not equal to non-optimized-out contents.
 
-   Returns true iff the set of available contents match.  Unavailable
-   contents compare equal with unavailable contents, and different
-   with any available byte.  For example, if 'x's represent an
-   unavailable byte, and 'V' and 'Z' represent different available
-   bytes, in a value with length 16:
+   Unavailable contente are equal to unavailable contents, and are not
+   equal to non-unavailable contents.
 
-   offset:   0   4   8   12  16
-   contents: xxxxVVVVxxxxVVZZ
+   For example, if 'x's represent an unavailable byte, and 'V' and 'Z'
+   represent different available/valid bytes, in a value with length
+   16:
+
+     offset:   0   4   8   12  16
+     contents: xxxxVVVVxxxxVVZZ
 
    then:
 
-   value_available_contents_eq(val, 0, val, 8, 6) => 1
-   value_available_contents_eq(val, 0, val, 4, 4) => 1
-   value_available_contents_eq(val, 0, val, 8, 8) => 0
-   value_available_contents_eq(val, 4, val, 12, 2) => 1
-   value_available_contents_eq(val, 4, val, 12, 4) => 0
-   value_available_contents_eq(val, 3, val, 4, 4) => 0
-
-   We only know whether a value chunk is available if we've tried to
-   read it.  As this routine is used by printing routines, which may
-   be printing values in the value history, long after the inferior is
-   gone, it works with const values.  Therefore, this routine must not
-   be called with lazy values.  */
-
-extern int value_available_contents_eq (const struct value *val1, int offset1,
-					const struct value *val2, int offset2,
-					int length);
+     value_contents_eq(val, 0, val, 8, 6) => 1
+     value_contents_eq(val, 0, val, 4, 4) => 0
+     value_contents_eq(val, 0, val, 8, 8) => 0
+     value_contents_eq(val, 4, val, 12, 2) => 1
+     value_contents_eq(val, 4, val, 12, 4) => 0
+     value_contents_eq(val, 3, val, 4, 4) => 0
+
+   If 'x's represent an unavailable byte, 'o' represents an optimized
+   out byte, in a value with length 8:
+
+     offset:   0   4   8
+     contents: xxxxoooo
+
+   then:
+
+     value_contents_eq(val, 0, val, 2, 2) => 1
+     value_contents_eq(val, 4, val, 6, 2) => 1
+     value_contents_eq(val, 0, val, 4, 4) => 0
+
+   We only know whether a value chunk is unavailable or optimized out
+   if we've tried to read it.  As this routine is used by printing
+   routines, which may be printing values in the value history, long
+   after the inferior is gone, it works with const values.  Therefore,
+   this routine must not be called with lazy values.  */
+
+extern int value_contents_eq (const struct value *val1, int offset1,
+			      const struct value *val2, int offset2,
+			      int length);
 
 /* Read LENGTH bytes of memory starting at MEMADDR into BUFFER, which
    is (or will be copied to) VAL's contents buffer offset by
-- 
1.9.3


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [commit+7.8] [read_frame_arg patch] Handle partially optimized out values similarly to unavailable values
  2014-07-22 20:21               ` [commit+7.8] [read_frame_arg patch] Handle partially optimized out values similarly to unavailable values Jan Kratochvil
@ 2014-08-05 17:16                 ` Doug Evans
  2014-08-14 18:25                   ` Jan Kratochvil
  0 siblings, 1 reply; 28+ messages in thread
From: Doug Evans @ 2014-08-05 17:16 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: Pedro Alves, gdb-patches

Jan Kratochvil writes:
 > On Tue, 22 Jul 2014 21:19:22 +0200, Pedro Alves wrote:
 > > OK, I've pushed the reversion (without the #if 0 bit) to both master
 > > and 7.8.
 > 
 > Therefore pushed in the fix of read_frame_arg together with the testcase.
 > 	e214cf6c2e05bcfc85dc6f335d8ffdc3629cf0cf
 > and also for 7.8:
 > 	0f9e1204f3de3cbe46a2b9e54049c1df9a5df305
 > 
 > 
 > Jan
 > commit e214cf6c2e05bcfc85dc6f335d8ffdc3629cf0cf
 > Author: Jan Kratochvil <jan.kratochvil@redhat.com>
 > Date:   Tue Jul 22 22:09:35 2014 +0200
 > 
 >     Fix read_frame_arg for optimized-out entry values.
 >     
 >     gdb/
 >     2014-07-22  Jan Kratochvil  <jan.kratochvil@redhat.com>
 >     
 >     	* stack.c (read_frame_arg): Verify value_optimized_out before calling
 >     	value_available_contents_eq.
 >     
 >     gdb/testsuite/
 >     2014-07-22  Jan Kratochvil  <jan.kratochvil@redhat.com>
 >     
 >     	* gdb.arch/amd64-entry-value-paramref.S: New file.
 >     	* gdb.arch/amd64-entry-value-paramref.cc: New file.
 >     	* gdb.arch/amd64-entry-value-paramref.exp: New file.
 >     	* gdb.arch/amd64-optimout-repeat.S: New file.
 >     	* gdb.arch/amd64-optimout-repeat.c: New file.
 >     	* gdb.arch/amd64-optimout-repeat.exp: New file.
 >     
 >     Message-ID: <20140720150727.GA18488@host2.jankratochvil.net>
 >     Message-ID: <20140711153757.GA452@host2.jankratochvil.net>

Hi.

In trunk I'm seeing amd64-entry-value-paramref.exp fail with a
gdb internal error.  I can debug this further if you need me to.

(gdb) file testsuite/gdb.arch/amd64-entry-value-paramref
[...]
(top-gdb) bt
#0  internal_error (file=0xa249e8 "../../entry-value/gdb/dwarf2read.c", line=15776, string=0xa28050 "could not find partial DIE 0x%x in cache [from module %s]\n") at ../../entry-value/gdb/utils.c:823
#1  0x00000000006a89cb in find_partial_die (offset=..., offset_in_dwz=0, cu=0x1029370) at ../../entry-value/gdb/dwarf2read.c:15776
#2  0x00000000006a8c9d in fixup_partial_die (part_die=0x103a6f0, cu=0x1029370) at ../../entry-value/gdb/dwarf2read.c:15855
#3  0x0000000000692b49 in scan_partial_symbols (first_die=0x103a690, lowpc=0x7fffffffdb78, highpc=0x7fffffffdb70, need_pc=0, cu=0x1029370) at ../../entry-value/gdb/dwarf2read.c:6567
#4  0x000000000069132a in process_psymtab_comp_unit_reader (reader=0x7fffffffdcc0, info_ptr=0xf6c78c "\002bar", comp_unit_die=0x103a480, has_children=1, data=0x7fffffffdd90) at ../../entry-value/gdb/dwarf2read.c:5913
#5  0x0000000000690662 in init_cutu_and_read_dies (this_cu=0xf5d770, abbrev_table=0x0, use_existing_cu=0, keep=0, die_reader_func=0x690fe2 <process_psymtab_comp_unit_reader>, data=0x7fffffffdd90) at ../../entry-value/gdb/dwarf2read.c:5529
#6  0x00000000006917d0 in process_psymtab_comp_unit (this_cu=0xf5d770, want_partial_unit=0, pretend_language=language_minimal) at ../../entry-value/gdb/dwarf2read.c:5998
#7  0x0000000000692456 in dwarf2_build_psymtabs_hard (objfile=0x101eab0) at ../../entry-value/gdb/dwarf2read.c:6397
#8  0x000000000068d225 in dwarf2_build_psymtabs (objfile=0x101eab0) at ../../entry-value/gdb/dwarf2read.c:4173
#9  0x0000000000554e9d in read_psyms (objfile=0x101eab0) at ../../entry-value/gdb/elfread.c:1363
[...]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [commit+7.8] [read_frame_arg patch] Handle partially optimized out values similarly to unavailable values
  2014-08-05 17:16                 ` Doug Evans
@ 2014-08-14 18:25                   ` Jan Kratochvil
  0 siblings, 0 replies; 28+ messages in thread
From: Jan Kratochvil @ 2014-08-14 18:25 UTC (permalink / raw)
  To: Doug Evans; +Cc: Pedro Alves, gdb-patches

On Tue, 05 Aug 2014 19:16:17 +0200, Doug Evans wrote:
> In trunk I'm seeing amd64-entry-value-paramref.exp fail with a
> gdb internal error.  I can debug this further if you need me to.

Yes, please.  We probably agree it should be sufficient to send me binaries
built by the testcase.


Thanks,
Jan

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v2] Handle partially optimized out values similarly to unavailable values
  2014-07-24 12:51         ` [PATCH v2] Handle partially optimized out values similarly to unavailable values Pedro Alves
@ 2014-08-15 20:13           ` Jan Kratochvil
  2014-08-19 23:36             ` Pedro Alves
  0 siblings, 1 reply; 28+ messages in thread
From: Jan Kratochvil @ 2014-08-15 20:13 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On Thu, 24 Jul 2014 14:08:13 +0200, Pedro Alves wrote:
> New patch below.  Let me know what you think.

My comments have been addressed, I find it OK.


Thanks,
Jan

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v2] Handle partially optimized out values similarly to unavailable values
  2014-08-15 20:13           ` Jan Kratochvil
@ 2014-08-19 23:36             ` Pedro Alves
  2014-08-20  0:55               ` Andrew Pinski
  2014-08-21 19:57               ` Regression for i686 gdb.dwarf2/pieces-optimized-out.exp [Re: [PATCH v2] Handle partially optimized out values similarly to unavailable values] Jan Kratochvil
  0 siblings, 2 replies; 28+ messages in thread
From: Pedro Alves @ 2014-08-19 23:36 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

On 08/15/2014 09:13 PM, Jan Kratochvil wrote:
> On Thu, 24 Jul 2014 14:08:13 +0200, Pedro Alves wrote:
>> New patch below.  Let me know what you think.
> 
> My comments have been addressed, I find it OK.

Great, I pushed this in then.

Thanks!

Pedro Alves

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v2] Handle partially optimized out values similarly to unavailable values
  2014-08-19 23:36             ` Pedro Alves
@ 2014-08-20  0:55               ` Andrew Pinski
  2014-08-20  9:46                 ` Pedro Alves
  2014-08-21 19:57               ` Regression for i686 gdb.dwarf2/pieces-optimized-out.exp [Re: [PATCH v2] Handle partially optimized out values similarly to unavailable values] Jan Kratochvil
  1 sibling, 1 reply; 28+ messages in thread
From: Andrew Pinski @ 2014-08-20  0:55 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Jan Kratochvil, gdb-patches

On Tue, Aug 19, 2014 at 4:36 PM, Pedro Alves <palves@redhat.com> wrote:
> On 08/15/2014 09:13 PM, Jan Kratochvil wrote:
>> On Thu, 24 Jul 2014 14:08:13 +0200, Pedro Alves wrote:
>>> New patch below.  Let me know what you think.
>>
>> My comments have been addressed, I find it OK.
>
> Great, I pushed this in then.

This caused a build error for me:

cc1: warnings being treated as errors
../../gdb/value.c: In function ‘value_contents_eq’:
../../gdb/value.c:830: error: ‘l’ may be used uninitialized in this function
../../gdb/value.c:830: note: ‘l’ was declared here
../../gdb/value.c:830: error: ‘h’ may be used uninitialized in this function
../../gdb/value.c:830: note: ‘h’ was declared here
make[2]: *** [value.o] Error 1

Thanks,
Andrew Pinski



>
> Thanks!
>
> Pedro Alves
>

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v2] Handle partially optimized out values similarly to unavailable values
  2014-08-20  0:55               ` Andrew Pinski
@ 2014-08-20  9:46                 ` Pedro Alves
  2014-08-20 10:32                   ` [PUSHED] value.c (value_contents_bits_eq): Initialize l,h for gcc, -Wall. (was: Re: [PATCH v2] Handle partially optimized out values similarly to unavailable values) Pedro Alves
  0 siblings, 1 reply; 28+ messages in thread
From: Pedro Alves @ 2014-08-20  9:46 UTC (permalink / raw)
  To: Andrew Pinski; +Cc: Jan Kratochvil, gdb-patches

On 08/20/2014 01:54 AM, Andrew Pinski wrote:
> On Tue, Aug 19, 2014 at 4:36 PM, Pedro Alves <palves@redhat.com> wrote:


>> Great, I pushed this in then.
> 
> This caused a build error for me:
> 
> cc1: warnings being treated as errors
> ../../gdb/value.c: In function ‘value_contents_eq’:
> ../../gdb/value.c:830: error: ‘l’ may be used uninitialized in this function
> ../../gdb/value.c:830: note: ‘l’ was declared here
> ../../gdb/value.c:830: error: ‘h’ may be used uninitialized in this function
> ../../gdb/value.c:830: note: ‘h’ was declared here
> make[2]: *** [value.o] Error 1
> 
> Thanks,
> Andrew Pinski

Thanks Andrew.  I'm looking.

-- 
Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PUSHED] value.c (value_contents_bits_eq): Initialize l,h for gcc, -Wall.  (was: Re: [PATCH v2] Handle partially optimized out values similarly to unavailable values)
  2014-08-20  9:46                 ` Pedro Alves
@ 2014-08-20 10:32                   ` Pedro Alves
  2014-08-20 16:28                     ` Andrew Pinski
  0 siblings, 1 reply; 28+ messages in thread
From: Pedro Alves @ 2014-08-20 10:32 UTC (permalink / raw)
  To: Andrew Pinski; +Cc: Jan Kratochvil, gdb-patches

On 08/20/2014 10:46 AM, Pedro Alves wrote:
> On 08/20/2014 01:54 AM, Andrew Pinski wrote:
>> On Tue, Aug 19, 2014 at 4:36 PM, Pedro Alves <palves@redhat.com> wrote:
> 
> 
>>> Great, I pushed this in then.
>>
>> This caused a build error for me:
>>
>> cc1: warnings being treated as errors
>> ../../gdb/value.c: In function ‘value_contents_eq’:
>> ../../gdb/value.c:830: error: ‘l’ may be used uninitialized in this function
>> ../../gdb/value.c:830: note: ‘l’ was declared here
>> ../../gdb/value.c:830: error: ‘h’ may be used uninitialized in this function
>> ../../gdb/value.c:830: note: ‘h’ was declared here
>> make[2]: *** [value.o] Error 1
>>
>> Thanks,
>> Andrew Pinski
> 
> Thanks Andrew.  I'm looking.
> 

I can't trigger that, but should be fixed now.

Thanks.

------------
value.c (value_contents_bits_eq): Initialize l,h for gcc -Wall.

	gdb/
	* value.c (value_contents_bits_eq): Initialize l,h for gcc -Wall.
---
 gdb/ChangeLog | 4 ++++
 gdb/value.c   | 2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 55cc92c..c0b4f82 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,7 @@
+2014-08-20  Pedro Alves  <palves@redhat.com>
+
+	* value.c (value_contents_bits_eq): Initialize l,h for gcc -Wall.
+
 2014-08-20  Yao Qi  <yao@codesourcery.com>
 
 	* amd64-tdep.c (amd64_classify): Add a blank line after the
diff --git a/gdb/value.c b/gdb/value.c
index b74f23a..09ee1ca 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -827,7 +827,7 @@ value_contents_bits_eq (const struct value *val1, int offset1,
 
   while (length > 0)
     {
-      ULONGEST l, h;
+      ULONGEST l = 0, h = 0; /* init for gcc -Wall */
       int i;
 
       for (i = 0; i < 2; i++)
-- 
1.9.3



-- 
Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PUSHED] value.c (value_contents_bits_eq): Initialize l,h for gcc, -Wall. (was: Re: [PATCH v2] Handle partially optimized out values similarly to unavailable values)
  2014-08-20 10:32                   ` [PUSHED] value.c (value_contents_bits_eq): Initialize l,h for gcc, -Wall. (was: Re: [PATCH v2] Handle partially optimized out values similarly to unavailable values) Pedro Alves
@ 2014-08-20 16:28                     ` Andrew Pinski
  0 siblings, 0 replies; 28+ messages in thread
From: Andrew Pinski @ 2014-08-20 16:28 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Jan Kratochvil, gdb-patches

On Wed, Aug 20, 2014 at 3:32 AM, Pedro Alves <palves@redhat.com> wrote:
> On 08/20/2014 10:46 AM, Pedro Alves wrote:
>> On 08/20/2014 01:54 AM, Andrew Pinski wrote:
>>> On Tue, Aug 19, 2014 at 4:36 PM, Pedro Alves <palves@redhat.com> wrote:
>>
>>
>>>> Great, I pushed this in then.
>>>
>>> This caused a build error for me:
>>>
>>> cc1: warnings being treated as errors
>>> ../../gdb/value.c: In function ‘value_contents_eq’:
>>> ../../gdb/value.c:830: error: ‘l’ may be used uninitialized in this function
>>> ../../gdb/value.c:830: note: ‘l’ was declared here
>>> ../../gdb/value.c:830: error: ‘h’ may be used uninitialized in this function
>>> ../../gdb/value.c:830: note: ‘h’ was declared here
>>> make[2]: *** [value.o] Error 1
>>>
>>> Thanks,
>>> Andrew Pinski
>>
>> Thanks Andrew.  I'm looking.
>>
>
> I can't trigger that, but should be fixed now.


Yes this fixes the issue for me.

Thanks,
Andrew

>
> Thanks.
>
> ------------
> value.c (value_contents_bits_eq): Initialize l,h for gcc -Wall.
>
>         gdb/
>         * value.c (value_contents_bits_eq): Initialize l,h for gcc -Wall.
> ---
>  gdb/ChangeLog | 4 ++++
>  gdb/value.c   | 2 +-
>  2 files changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
> index 55cc92c..c0b4f82 100644
> --- a/gdb/ChangeLog
> +++ b/gdb/ChangeLog
> @@ -1,3 +1,7 @@
> +2014-08-20  Pedro Alves  <palves@redhat.com>
> +
> +       * value.c (value_contents_bits_eq): Initialize l,h for gcc -Wall.
> +
>  2014-08-20  Yao Qi  <yao@codesourcery.com>
>
>         * amd64-tdep.c (amd64_classify): Add a blank line after the
> diff --git a/gdb/value.c b/gdb/value.c
> index b74f23a..09ee1ca 100644
> --- a/gdb/value.c
> +++ b/gdb/value.c
> @@ -827,7 +827,7 @@ value_contents_bits_eq (const struct value *val1, int offset1,
>
>    while (length > 0)
>      {
> -      ULONGEST l, h;
> +      ULONGEST l = 0, h = 0; /* init for gcc -Wall */
>        int i;
>
>        for (i = 0; i < 2; i++)
> --
> 1.9.3
>
>
>
> --
> Thanks,
> Pedro Alves

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Regression for i686 gdb.dwarf2/pieces-optimized-out.exp  [Re: [PATCH v2] Handle partially optimized out values similarly to unavailable values]
  2014-08-19 23:36             ` Pedro Alves
  2014-08-20  0:55               ` Andrew Pinski
@ 2014-08-21 19:57               ` Jan Kratochvil
  2014-08-22 16:20                 ` Pedro Alves
  1 sibling, 1 reply; 28+ messages in thread
From: Jan Kratochvil @ 2014-08-21 19:57 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On Wed, 20 Aug 2014 01:36:35 +0200, Pedro Alves wrote:
> Great, I pushed this in then.

-PASS: gdb.dwarf2/pieces-optimized-out.exp: print s
+FAIL: gdb.dwarf2/pieces-optimized-out.exp: print s

for i686 and x86_64-m32 configurations on all known platforms:

9a0dc9e3699018b15980bb6a39eb33dea8fefa34 is the first bad commit
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
    

Jan

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Regression for i686 gdb.dwarf2/pieces-optimized-out.exp  [Re: [PATCH v2] Handle partially optimized out values similarly to unavailable values]
  2014-08-21 19:57               ` Regression for i686 gdb.dwarf2/pieces-optimized-out.exp [Re: [PATCH v2] Handle partially optimized out values similarly to unavailable values] Jan Kratochvil
@ 2014-08-22 16:20                 ` Pedro Alves
  2014-08-24 19:56                   ` Jan Kratochvil
  2014-09-04 11:36                   ` [pushed] " Pedro Alves
  0 siblings, 2 replies; 28+ messages in thread
From: Pedro Alves @ 2014-08-22 16:20 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

On 08/21/2014 08:57 PM, Jan Kratochvil wrote:
> On Wed, 20 Aug 2014 01:36:35 +0200, Pedro Alves wrote:
>> Great, I pushed this in then.
> 
> -PASS: gdb.dwarf2/pieces-optimized-out.exp: print s
> +FAIL: gdb.dwarf2/pieces-optimized-out.exp: print s
> 
> for i686 and x86_64-m32 configurations on all known platforms:
> 
> 9a0dc9e3699018b15980bb6a39eb33dea8fefa34 is the first bad commit
> 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
>     

Thanks Jan.

So it didn't take that long to get back to handling partially
optimized out bitfields after all...  I think I found an easy way.
We don't currently print partially optimized out scalars, though
we could print the valid/invalid bits with p/t, for example,
and I think the code ends up clearer anyway.

----------
Subject: [PATCH] Regression for i686 gdb.dwarf2/pieces-optimized-out.exp

Git 9a0dc9e3 regressed gdb.dwarf2/pieces-optimized-out.exp, visible on
i686 (the test doesn't run on x86_64):

 (gdb) p s
 -$1 = {a = 5, b = <optimized out>, c = <optimized out>, d = <optimized out>}
 +$1 = {a = 5, b = <optimized out>, c = 0, d = 0}
 -(gdb) PASS: gdb.dwarf2/pieces-optimized-out.exp: print s
 +(gdb) FAIL: gdb.dwarf2/pieces-optimized-out.exp: print s

The regression was caused by this removal in cp-valprint.c:

  @@ -293,12 +293,6 @@ cp_print_value_fields (struct type *type, struct type *real_type,
		  {
		    fputs_filtered (_("<synthetic pointer>"), stream);
		  }
  -             else if (!value_bits_valid (val,
  -                                         TYPE_FIELD_BITPOS (type, i),
  -                                         TYPE_FIELD_BITSIZE (type, i)))
  -               {
  -                 val_print_optimized_out (val, stream);
  -               }
		else
		  {
		    struct value_print_options opts = *options;

The idea was that we'd just fallback to calling value_field_bitfield,
which handles unavailable values (in unpack_value_bits_as_long_1) so
should be able to handle optimized out values too.  Alas, it doesn't.
This is currently a bit too messy.  Instead of teaching
unpack_value_bits_as_long_1 about optimized out bits, let's bite the
bullet and teach the value code to handle partially optimized out
bitfield, by having it unpack a bitfield and then propagate the range
metadata.  Turns out the resulting code looks simpler and clearer.

Tested on x86_64 Fedora 20, -m64/-m32.

gdb/ChangeLog:
2014-08-22  Pedro Alves  <palves@redhat.com>

	* value.c (value_ranges_copy_adjusted): New function, factored out
	from ...
	(value_contents_copy_raw): ... here.
	(unpack_value_bits_as_long_1): Rename back to ...
	(unpack_bits_as_long): ... this.  Remove 'original_value' and
	'result' parameters.  Change return type to LONGEST.
	(unpack_value_bits_as_long): Delete.
	(unpack_value_field_as_long_1): Delete.
	(unpack_value_field_as_long, unpack_field_as_long): Reimplement.
	(unpack_value_bitfield): New function.
	(value_field_bitfield): Reimplement using unpack_value_bitfield.
	(value_fetch_lazy): Use unpack_value_bitfield.
	* value.h (unpack_value_bits_as_long): Delete declaration.
---
 gdb/value.c | 227 +++++++++++++++++++++++++++++-------------------------------
 gdb/value.h |   7 --
 2 files changed, 109 insertions(+), 125 deletions(-)

diff --git a/gdb/value.c b/gdb/value.c
index 077d234..6620f96 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -1219,6 +1219,22 @@ ranges_copy_adjusted (VEC (range_s) **dst_range, int dst_bit_offset,
     }
 }
 
+/* Copy the ranges metadata in SRC that overlaps [SRC_BIT_OFFSET,
+   SRC_BIT_OFFSET+BIT_LENGTH) into DST, adjusted.  */
+
+static void
+value_ranges_copy_adjusted (struct value *dst, int dst_bit_offset,
+			    const struct value *src, int src_bit_offset,
+			    int bit_length)
+{
+  ranges_copy_adjusted (&dst->unavailable, dst_bit_offset,
+			src->unavailable, src_bit_offset,
+			bit_length);
+  ranges_copy_adjusted (&dst->optimized_out, dst_bit_offset,
+			src->optimized_out, src_bit_offset,
+			bit_length);
+}
+
 /* Copy LENGTH bytes of SRC value's (all) contents
    (value_contents_all) starting at SRC_OFFSET, into DST value's (all)
    contents, starting at DST_OFFSET.  If unavailable contents are
@@ -1261,13 +1277,9 @@ value_contents_copy_raw (struct value *dst, int dst_offset,
   dst_bit_offset = dst_offset * TARGET_CHAR_BIT;
   bit_length = length * TARGET_CHAR_BIT;
 
-  ranges_copy_adjusted (&dst->unavailable, dst_bit_offset,
-			src->unavailable, src_bit_offset,
-			bit_length);
-
-  ranges_copy_adjusted (&dst->optimized_out, dst_bit_offset,
-			src->optimized_out, src_bit_offset,
-			bit_length);
+  value_ranges_copy_adjusted (dst, dst_bit_offset,
+			      src, src_bit_offset,
+			      bit_length);
 }
 
 /* Copy LENGTH bytes of SRC value's (all) contents
@@ -3105,16 +3117,24 @@ value_fn_field (struct value **arg1p, struct fn_field *f,
 
 \f
 
-/* Helper function for both unpack_value_bits_as_long and
-   unpack_bits_as_long.  See those functions for more details on the
-   interface; the only difference is that this function accepts either
-   a NULL or a non-NULL ORIGINAL_VALUE.  */
+/* Unpack a bitfield of the specified FIELD_TYPE, from the object at
+   VALADDR, and store the result in *RESULT.
+   The bitfield starts at BITPOS bits and contains BITSIZE bits.
 
-static int
-unpack_value_bits_as_long_1 (struct type *field_type, const gdb_byte *valaddr,
-			     int embedded_offset, int bitpos, int bitsize,
-			     const struct value *original_value,
-			     LONGEST *result)
+   Extracting bits depends on endianness of the machine.  Compute the
+   number of least significant bits to discard.  For big endian machines,
+   we compute the total number of bits in the anonymous object, subtract
+   off the bit count from the MSB of the object to the MSB of the
+   bitfield, then the size of the bitfield, which leaves the LSB discard
+   count.  For little endian machines, the discard count is simply the
+   number of bits from the LSB of the anonymous object to the LSB of the
+   bitfield.
+
+   If the field is signed, we also do sign extension.  */
+
+static LONGEST
+unpack_bits_as_long (struct type *field_type, const gdb_byte *valaddr,
+		     int bitpos, int bitsize)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (field_type));
   ULONGEST val;
@@ -3133,12 +3153,7 @@ unpack_value_bits_as_long_1 (struct type *field_type, const gdb_byte *valaddr,
 
   read_offset = bitpos / 8;
 
-  if (original_value != NULL
-      && !value_bits_available (original_value, embedded_offset + bitpos,
-				bitsize))
-    return 0;
-
-  val = extract_unsigned_integer (valaddr + embedded_offset + read_offset,
+  val = extract_unsigned_integer (valaddr + read_offset,
 				  bytes_read, byte_order);
 
   /* Extract bits.  See comment above.  */
@@ -3165,60 +3180,7 @@ unpack_value_bits_as_long_1 (struct type *field_type, const gdb_byte *valaddr,
 	}
     }
 
-  *result = val;
-  return 1;
-}
-
-/* Unpack a bitfield of the specified FIELD_TYPE, from the object at
-   VALADDR + EMBEDDED_OFFSET, and store the result in *RESULT.
-   VALADDR points to the contents of ORIGINAL_VALUE, which must not be
-   NULL.  The bitfield starts at BITPOS bits and contains BITSIZE
-   bits.
-
-   Returns false if the value contents are unavailable, otherwise
-   returns true, indicating a valid value has been stored in *RESULT.
-
-   Extracting bits depends on endianness of the machine.  Compute the
-   number of least significant bits to discard.  For big endian machines,
-   we compute the total number of bits in the anonymous object, subtract
-   off the bit count from the MSB of the object to the MSB of the
-   bitfield, then the size of the bitfield, which leaves the LSB discard
-   count.  For little endian machines, the discard count is simply the
-   number of bits from the LSB of the anonymous object to the LSB of the
-   bitfield.
-
-   If the field is signed, we also do sign extension.  */
-
-int
-unpack_value_bits_as_long (struct type *field_type, const gdb_byte *valaddr,
-			   int embedded_offset, int bitpos, int bitsize,
-			   const struct value *original_value,
-			   LONGEST *result)
-{
-  gdb_assert (original_value != NULL);
-
-  return unpack_value_bits_as_long_1 (field_type, valaddr, embedded_offset,
-				      bitpos, bitsize, original_value, result);
-
-}
-
-/* Unpack a field FIELDNO of the specified TYPE, from the object at
-   VALADDR + EMBEDDED_OFFSET.  VALADDR points to the contents of
-   ORIGINAL_VALUE.  See unpack_value_bits_as_long for more
-   details.  */
-
-static int
-unpack_value_field_as_long_1 (struct type *type, const gdb_byte *valaddr,
-			      int embedded_offset, int fieldno,
-			      const struct value *val, LONGEST *result)
-{
-  int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
-  int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
-  struct type *field_type = TYPE_FIELD_TYPE (type, fieldno);
-
-  return unpack_value_bits_as_long_1 (field_type, valaddr, embedded_offset,
-				      bitpos, bitsize, val,
-				      result);
+  return val;
 }
 
 /* Unpack a field FIELDNO of the specified TYPE, from the object at
@@ -3231,51 +3193,95 @@ unpack_value_field_as_long (struct type *type, const gdb_byte *valaddr,
 			    int embedded_offset, int fieldno,
 			    const struct value *val, LONGEST *result)
 {
+  int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
+  int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
+  struct type *field_type = TYPE_FIELD_TYPE (type, fieldno);
+  int bit_offset;
+
   gdb_assert (val != NULL);
 
-  return unpack_value_field_as_long_1 (type, valaddr, embedded_offset,
-				       fieldno, val, result);
+  bit_offset = embedded_offset * TARGET_CHAR_BIT + bitpos;
+  if (value_bits_any_optimized_out (val, bit_offset, bitsize)
+      || !value_bits_available (val, bit_offset, bitsize))
+    return 0;
+
+  *result = unpack_bits_as_long (field_type, valaddr + embedded_offset,
+				 bitpos, bitsize);
+  return 1;
 }
 
 /* Unpack a field FIELDNO of the specified TYPE, from the anonymous
-   object at VALADDR.  See unpack_value_bits_as_long for more details.
-   This function differs from unpack_value_field_as_long in that it
-   operates without a struct value object.  */
+   object at VALADDR.  See unpack_bits_as_long for more details.  */
 
 LONGEST
 unpack_field_as_long (struct type *type, const gdb_byte *valaddr, int fieldno)
 {
-  LONGEST result;
+  int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
+  int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
+  struct type *field_type = TYPE_FIELD_TYPE (type, fieldno);
 
-  unpack_value_field_as_long_1 (type, valaddr, 0, fieldno, NULL, &result);
-  return result;
+  return unpack_bits_as_long (field_type, valaddr, bitpos, bitsize);
+}
+
+/* Unpack a bitfield of BITSIZE bits found at BITPOS in the object at
+   VALADDR + EMBEDDEDOFFSET that has the type of DEST_VAL and store
+   the contents in DEST_VAL, zero or sign extending if the type of
+   DEST_VAL is wider than BITSIZE.  VALADDR points to the contents of
+   VAL.  If the VAL's contents required to extract the bitfield from
+   are unavailable/optimized out, DEST_VAL is correspondingly
+   marked unavailable/optimized out.  */
+
+static void
+unpack_value_bitfield (struct value *dest_val,
+		       int bitpos, int bitsize,
+		       const gdb_byte *valaddr, int embedded_offset,
+		       const struct value *val)
+{
+  enum bfd_endian byte_order;
+  int src_bit_offset;
+  int dst_bit_offset;
+  LONGEST num;
+  struct type *field_type = value_type (dest_val);
+
+  /* First, unpack and sign extend the bitfield as if it was wholly
+     available.  Invalid/unavailable bits are read as zero, but that's
+     OK, as they'll end up marked below.  */
+  byte_order = gdbarch_byte_order (get_type_arch (field_type));
+  num = unpack_bits_as_long (field_type, valaddr + embedded_offset,
+			     bitpos, bitsize);
+  store_signed_integer (value_contents_raw (dest_val),
+			TYPE_LENGTH (field_type), byte_order, num);
+
+  /* Now copy the optimized out / unavailability ranges to the right
+     bits.  */
+  src_bit_offset = embedded_offset * TARGET_CHAR_BIT + bitpos;
+  if (byte_order == BFD_ENDIAN_BIG)
+    dst_bit_offset = TYPE_LENGTH (field_type) * TARGET_CHAR_BIT - bitsize;
+  else
+    dst_bit_offset = 0;
+  value_ranges_copy_adjusted (dest_val, dst_bit_offset,
+			      val, src_bit_offset, bitsize);
 }
 
 /* Return a new value with type TYPE, which is FIELDNO field of the
    object at VALADDR + EMBEDDEDOFFSET.  VALADDR points to the contents
    of VAL.  If the VAL's contents required to extract the bitfield
-   from are unavailable, the new value is correspondingly marked as
-   unavailable.  */
+   from are unavailable/optimized out, the new value is
+   correspondingly marked unavailable/optimized out.  */
 
 struct value *
 value_field_bitfield (struct type *type, int fieldno,
 		      const gdb_byte *valaddr,
 		      int embedded_offset, const struct value *val)
 {
-  LONGEST l;
+  int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
+  int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
+  struct value *res_val = allocate_value (TYPE_FIELD_TYPE (type, fieldno));
 
-  if (!unpack_value_field_as_long (type, valaddr, embedded_offset, fieldno,
-				   val, &l))
-    {
-      struct type *field_type = TYPE_FIELD_TYPE (type, fieldno);
-      struct value *retval = allocate_value (field_type);
-      mark_value_bytes_unavailable (retval, 0, TYPE_LENGTH (field_type));
-      return retval;
-    }
-  else
-    {
-      return value_from_longest (TYPE_FIELD_TYPE (type, fieldno), l);
-    }
+  unpack_value_bitfield (res_val, bitpos, bitsize,
+			 valaddr, embedded_offset, val);
+
+  return res_val;
 }
 
 /* Modify the value of a bitfield.  ADDR points to a block of memory in
@@ -3757,30 +3763,15 @@ value_fetch_lazy (struct value *val)
          word, but we have no way to record that just specific bits of a
          value have been fetched.  */
       struct type *type = check_typedef (value_type (val));
-      enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
       struct value *parent = value_parent (val);
-      LONGEST offset = value_offset (val);
-      LONGEST num;
 
       if (value_lazy (parent))
 	value_fetch_lazy (parent);
 
-      if (value_bits_any_optimized_out (parent,
-					TARGET_CHAR_BIT * offset + value_bitpos (val),
-					value_bitsize (val)))
-	mark_value_bytes_optimized_out (val, value_embedded_offset (val),
-					TYPE_LENGTH (type));
-      else if (!unpack_value_bits_as_long (value_type (val),
-				      value_contents_for_printing (parent),
-				      offset,
-				      value_bitpos (val),
-				      value_bitsize (val), parent, &num))
-	mark_value_bytes_unavailable (val,
-				      value_embedded_offset (val),
-				      TYPE_LENGTH (type));
-      else
-	store_signed_integer (value_contents_raw (val), TYPE_LENGTH (type),
-			      byte_order, num);
+      unpack_value_bitfield (val,
+			     value_bitpos (val), value_bitsize (val),
+			     value_contents_for_printing (parent),
+			     value_offset (val), parent);
     }
   else if (VALUE_LVAL (val) == lval_memory)
     {
diff --git a/gdb/value.h b/gdb/value.h
index 5d4949c..4cdbf21 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -606,13 +606,6 @@ extern DOUBLEST unpack_double (struct type *type, const gdb_byte *valaddr,
 			       int *invp);
 extern CORE_ADDR unpack_pointer (struct type *type, const gdb_byte *valaddr);
 
-extern int unpack_value_bits_as_long (struct type *field_type,
-				      const gdb_byte *valaddr,
-				      int embedded_offset, int bitpos,
-				      int bitsize,
-				      const struct value *original_value,
-				      LONGEST *result);
-
 extern LONGEST unpack_field_as_long (struct type *type,
 				     const gdb_byte *valaddr,
 				     int fieldno);
-- 
1.9.3


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: Regression for i686 gdb.dwarf2/pieces-optimized-out.exp  [Re: [PATCH v2] Handle partially optimized out values similarly to unavailable values]
  2014-08-22 16:20                 ` Pedro Alves
@ 2014-08-24 19:56                   ` Jan Kratochvil
  2014-09-04 11:36                   ` [pushed] " Pedro Alves
  1 sibling, 0 replies; 28+ messages in thread
From: Jan Kratochvil @ 2014-08-24 19:56 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On Fri, 22 Aug 2014 18:20:38 +0200, Pedro Alves wrote:
> So it didn't take that long to get back to handling partially
> optimized out bitfields after all...  I think I found an easy way.
> We don't currently print partially optimized out scalars, though
> we could print the valid/invalid bits with p/t, for example,
> and I think the code ends up clearer anyway.

If you waited for my reply you can check it in as I do not think I can
reliably review this code.


Thanks,
Jan

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [pushed] Re: Regression for i686 gdb.dwarf2/pieces-optimized-out.exp  [Re: [PATCH v2] Handle partially optimized out values similarly to unavailable values]
  2014-08-22 16:20                 ` Pedro Alves
  2014-08-24 19:56                   ` Jan Kratochvil
@ 2014-09-04 11:36                   ` Pedro Alves
  1 sibling, 0 replies; 28+ messages in thread
From: Pedro Alves @ 2014-09-04 11:36 UTC (permalink / raw)
  To: gdb-patches; +Cc: Jan Kratochvil

I've pushed this in now.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2014-09-04 11:36 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-09 10:33 [patchv2] Fix crash on optimized-out entry data values Jan Kratochvil
2014-07-09 11:52 ` Pedro Alves
2014-07-09 15:31   ` Jan Kratochvil
2014-07-11 16:07     ` [patchv3] " Jan Kratochvil
2014-07-14  7:02       ` Yao Qi
2014-07-14  8:32         ` Jan Kratochvil
2014-07-14 18:12       ` Pedro Alves
2014-07-14 18:47     ` [PATCH] Handle partially optimized out values similarly to unavailable values (Re: [patchv2] Fix crash on optimized-out entry data values) Pedro Alves
2014-07-17  8:04       ` Jan Kratochvil
2014-07-17  8:35         ` Jan Kratochvil
2014-07-17 13:38         ` Pedro Alves
2014-07-20 15:33           ` [read_frame_arg patch] " Jan Kratochvil
2014-07-22 19:33             ` Pedro Alves
2014-07-22 20:21               ` [commit+7.8] [read_frame_arg patch] Handle partially optimized out values similarly to unavailable values Jan Kratochvil
2014-08-05 17:16                 ` Doug Evans
2014-08-14 18:25                   ` Jan Kratochvil
2014-07-23 14:26               ` [commit] Remove setting value address for reference entry value target data value Jan Kratochvil
2014-07-24 12:51         ` [PATCH v2] Handle partially optimized out values similarly to unavailable values Pedro Alves
2014-08-15 20:13           ` Jan Kratochvil
2014-08-19 23:36             ` Pedro Alves
2014-08-20  0:55               ` Andrew Pinski
2014-08-20  9:46                 ` Pedro Alves
2014-08-20 10:32                   ` [PUSHED] value.c (value_contents_bits_eq): Initialize l,h for gcc, -Wall. (was: Re: [PATCH v2] Handle partially optimized out values similarly to unavailable values) Pedro Alves
2014-08-20 16:28                     ` Andrew Pinski
2014-08-21 19:57               ` Regression for i686 gdb.dwarf2/pieces-optimized-out.exp [Re: [PATCH v2] Handle partially optimized out values similarly to unavailable values] Jan Kratochvil
2014-08-22 16:20                 ` Pedro Alves
2014-08-24 19:56                   ` Jan Kratochvil
2014-09-04 11:36                   ` [pushed] " Pedro Alves

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).