public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [RFC 00/12] Merge value optimized_out and unavailable
@ 2013-08-12 12:15 Andrew Burgess
  2013-08-12 12:16 ` [PATCH 01/12] Introduce is_unavailable_error Andrew Burgess
                   ` (13 more replies)
  0 siblings, 14 replies; 27+ messages in thread
From: Andrew Burgess @ 2013-08-12 12:15 UTC (permalink / raw)
  To: gdb-patches

This patch set merges together how gdb handles values that are
optimized out and values that are unavailable.

I think that in most cases gdb should not care why the contents of
a value are not fetch-able, it is only when we need to display
something to the user that we should have to figure out was this
optimized-out or unavailable?

After this patch set there will be a single unified interface to ask
if a value is available (either fully, partially, or for a range of
bit/bytes), this will answer in terms of both optimized out and
unavailable state.

A second method will fetch the set of flags for the value
optimized/unavailable, this will be used for printing the correct string.

For the implementation I've moved away from the code we currently have
for supporting partially optimized out values and consolidated on the
unavailable vector.

Currently within gdb there are places where we handle optimized out and
unavailable differently, resulting in different style of output, and there
are places where we handle one of optimized out or unavailable, but not the
other.  After this patch set it should (I hope) be much harder for either
of these situations to arise.

Looking forward to your feedback.

Thanks,
Andrew

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

* [PATCH 01/12] Introduce is_unavailable_error
  2013-08-12 12:15 [RFC 00/12] Merge value optimized_out and unavailable Andrew Burgess
@ 2013-08-12 12:16 ` Andrew Burgess
  2013-08-12 12:18 ` [PATCH 02/12]: Remove set_value_optimized_out Andrew Burgess
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Andrew Burgess @ 2013-08-12 12:16 UTC (permalink / raw)
  To: gdb-patches

Is some places we specifically check for the NOT_AVAILABLE_ERROR error
code, in a later patch I'll be adding a new error for optimized out
values and I'll want to detect both error codes at the same time.

In preparation for this upcoming change I add a new function for
detecting the NOT_AVAILABLE_ERROR code, this is just a refactor.

OK to apply?

Thanks,
Andrew

gdb/ChangeLog

2013-08-08  Andrew Burgess  <aburgess@broadcom.com>

	* exceptions.c (is_unavailable_error): New function definition.
	* exceptions.h (is_unavailable_error): New function declaration.
	* cp-abi.c (baseclass_offset): Switch to use
	is_unavailable_error, and rethrow whatever error we recieved
	rather than a specific error code.
	* amd64-tdep.c (amd64_frame_cache, amd64_sigtramp_frame_cache)
	(amd64_epilogue_frame_cache): Switch to use
	is_unavailable_error.
	* cp-valprint.c (cp_print_value): Likewise.
	* dwarf2-frame.c (dwarf2_frame_cache): Likewise.
	* dwarf2loc.c (dwarf2_evaluate_loc_desc_full): Likewise.
	* frame-unwind.c (frame_unwind_find_by_frame): Likewise.
	* frame.c (frame_unwind_pc_if_available)
	(get_frame_address_in_block_if_available): Likewise.
	* i386-tdep.c (i386_frame_cache, i386_epilogue_frame_cache)
	(i386_sigtramp_frame_cache): Likewise.
	* infcmd.c (post_create_inferior): Likewise.
	* p-valprint.c (pascal_object_print_value): Likewise.
	* stack.c (get_frame_language): Likewise.

diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index 3ab74f0..71525b8 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -2366,7 +2366,7 @@ amd64_frame_cache (struct frame_info *this_frame,
void **this_cache)
     {
       amd64_frame_cache_1 (this_frame, cache);
     }
-  if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
+  if (ex.reason < 0 && !is_unavailable_error (ex.error))
     throw_exception (ex);
    return cache;
@@ -2490,7 +2490,7 @@ amd64_sigtramp_frame_cache (struct frame_info
*this_frame, void **this_cache)
        cache->base_p = 1;
     }
-  if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
+  if (ex.reason < 0 && !is_unavailable_error (ex.error))
     throw_exception (ex);
    *this_cache = cache;
@@ -2658,10 +2658,9 @@ amd64_epilogue_frame_cache (struct frame_info
*this_frame, void **this_cache)
        /* The saved %eip will be at cache->base plus 8.  */
       cache->saved_regs[AMD64_RIP_REGNUM] = cache->base + 8;
-
       cache->base_p = 1;
     }
-  if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
+  if (ex.reason < 0 && !is_unavailable_error (ex.error))
     throw_exception (ex);
    return cache;
diff --git a/gdb/cp-abi.c b/gdb/cp-abi.c
index 2540eca..fbc68a4 100644
--- a/gdb/cp-abi.c
+++ b/gdb/cp-abi.c
@@ -85,8 +85,8 @@ baseclass_offset (struct type *type, int index, const
gdb_byte *valaddr,
 						address, val);
     }
 -  if (ex.reason < 0 && ex.error == NOT_AVAILABLE_ERROR)
-    throw_error (NOT_AVAILABLE_ERROR,
+  if (ex.reason < 0 && is_unavailable_error (ex.error))
+    throw_error (ex.error,
 		 _("Cannot determine virtual baseclass offset "
 		   "of incomplete object"));
   else if (ex.reason < 0)
diff --git a/gdb/cp-valprint.c b/gdb/cp-valprint.c
index e83d979..795b7b0 100644
--- a/gdb/cp-valprint.c
+++ b/gdb/cp-valprint.c
@@ -519,7 +519,7 @@ cp_print_value (struct type *type, struct type
*real_type,
 	{
 	  boffset = baseclass_offset (type, i, valaddr, offset, address, val);
 	}
-      if (ex.reason < 0 && ex.error == NOT_AVAILABLE_ERROR)
+      if (ex.reason < 0 && is_unavailable_error (ex.error))
 	skip = -1;
       else if (ex.reason < 0)
 	skip = 1;
diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
index 5c88b03..b709d3b 100644
--- a/gdb/dwarf2-frame.c
+++ b/gdb/dwarf2-frame.c
@@ -1117,7 +1117,7 @@ dwarf2_frame_cache (struct frame_info *this_frame,
void **this_cache)
     }
   if (ex.reason < 0)
     {
-      if (ex.error == NOT_AVAILABLE_ERROR)
+      if (is_unavailable_error (ex.error))
 	{
 	  cache->unavailable_retaddr = 1;
 	  do_cleanups (old_chain);
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 02afcdf..3b843fa 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -2237,7 +2237,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type,
struct frame_info *frame,
     }
   if (ex.reason < 0)
     {
-      if (ex.error == NOT_AVAILABLE_ERROR)
+      if (is_unavailable_error (ex.error))
 	{
 	  do_cleanups (old_chain);
 	  retval = allocate_value (type);
diff --git a/gdb/exceptions.c b/gdb/exceptions.c
index c4c1e57..134d918 100644
--- a/gdb/exceptions.c
+++ b/gdb/exceptions.c
@@ -571,3 +571,11 @@ catch_command_errors_const
(catch_command_errors_const_ftype *command,
     return 0;
   return 1;
 }
+
+/* Return true if this is an error indicating a value was unavailable.  */
+
+int
+is_unavailable_error (const enum errors error)
+{
+  return error == NOT_AVAILABLE_ERROR;
+}
diff --git a/gdb/exceptions.h b/gdb/exceptions.h
index bf41860..1baecf4 100644
--- a/gdb/exceptions.h
+++ b/gdb/exceptions.h
@@ -101,6 +101,10 @@ struct gdb_exception
   const char *message;
 };
 +/* Return true for those errors relating to value unavailability.  */
+
+extern int is_unavailable_error (enum errors error);
+
 /* A pre-defined non-exception.  */
 extern const struct gdb_exception exception_none;
 diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c
index ce2f6da..25b1e08 100644
--- a/gdb/frame-unwind.c
+++ b/gdb/frame-unwind.c
@@ -112,7 +112,7 @@ frame_unwind_find_by_frame (struct frame_info
*this_frame, void **this_cache)
 	  res = entry->unwinder->sniffer (entry->unwinder, this_frame,
 					  this_cache);
 	}
-      if (ex.reason < 0 && ex.error == NOT_AVAILABLE_ERROR)
+      if (ex.reason < 0 && is_unavailable_error (ex.error))
 	{
 	  /* This usually means that not even the PC is available,
 	     thus most unwinders aren't able to determine if they're
diff --git a/gdb/frame.c b/gdb/frame.c
index d52c26a..54f828c 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -721,7 +721,7 @@ frame_unwind_pc_if_available (struct frame_info
*this_frame, CORE_ADDR *pc)
 	    {
 	      pc = gdbarch_unwind_pc (prev_gdbarch, this_frame);
 	    }
-	  if (ex.reason < 0 && ex.error == NOT_AVAILABLE_ERROR)
+	  if (ex.reason < 0 && is_unavailable_error (ex.error))
 	    {
 	      this_frame->prev_pc.p = -1;
 @@ -2064,7 +2064,7 @@ get_frame_pc_if_available (struct frame_info
*frame, CORE_ADDR *pc)
     }
   if (ex.reason < 0)
     {
-      if (ex.error == NOT_AVAILABLE_ERROR)
+      if (is_unavailable_error (ex.error))
 	return 0;
       else
 	throw_exception (ex);
@@ -2145,7 +2145,7 @@ get_frame_address_in_block_if_available (struct
frame_info *this_frame,
     {
       *pc = get_frame_address_in_block (this_frame);
     }
-  if (ex.reason < 0 && ex.error == NOT_AVAILABLE_ERROR)
+  if (ex.reason < 0 && is_unavailable_error (ex.error))
     return 0;
   else if (ex.reason < 0)
     throw_exception (ex);
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index b159b49..1c9fa68 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -1834,7 +1834,7 @@ i386_frame_cache (struct frame_info *this_frame,
void **this_cache)
     {
       i386_frame_cache_1 (this_frame, cache);
     }
-  if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
+  if (ex.reason < 0 && !is_unavailable_error (ex.error))
     throw_exception (ex);
    return cache;
@@ -2004,7 +2004,7 @@ i386_epilogue_frame_cache (struct frame_info
*this_frame, void **this_cache)
        cache->base_p = 1;
     }
-  if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
+  if (ex.reason < 0 && !is_unavailable_error (ex.error))
     throw_exception (ex);
    return cache;
@@ -2197,7 +2197,7 @@ i386_sigtramp_frame_cache (struct frame_info
*this_frame, void **this_cache)
        cache->base_p = 1;
     }
-  if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
+  if (ex.reason < 0 && !is_unavailable_error (ex.error))
     throw_exception (ex);
    *this_cache = cache;
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 154cde2..ed9ec5e 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -422,7 +422,7 @@ post_create_inferior (struct target_ops *target, int
from_tty)
     {
       stop_pc = regcache_read_pc (get_current_regcache ());
     }
-  if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
+  if (ex.reason < 0 && !is_unavailable_error (ex.error))
     throw_exception (ex);
    if (exec_bfd)
diff --git a/gdb/p-valprint.c b/gdb/p-valprint.c
index 05d4c6f..cfafe99 100644
--- a/gdb/p-valprint.c
+++ b/gdb/p-valprint.c
@@ -754,7 +754,7 @@ pascal_object_print_value (struct type *type, const
gdb_byte *valaddr,
 	{
 	  boffset = baseclass_offset (type, i, valaddr, offset, address, val);
 	}
-      if (ex.reason < 0 && ex.error == NOT_AVAILABLE_ERROR)
+      if (ex.reason < 0 && is_unavailable_error (ex.error))
 	skip = -1;
       else if (ex.reason < 0)
 	skip = 1;
diff --git a/gdb/stack.c b/gdb/stack.c
index 7d97dc8..af05f84 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -2558,7 +2558,7 @@ get_frame_language (void)
 	}
       if (ex.reason < 0)
 	{
-	  if (ex.error != NOT_AVAILABLE_ERROR)
+	  if (!is_unavailable_error (ex.error))
 	    throw_exception (ex);
 	}
       else


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

* [PATCH 02/12]: Remove set_value_optimized_out
  2013-08-12 12:15 [RFC 00/12] Merge value optimized_out and unavailable Andrew Burgess
  2013-08-12 12:16 ` [PATCH 01/12] Introduce is_unavailable_error Andrew Burgess
@ 2013-08-12 12:18 ` Andrew Burgess
  2013-08-12 12:20 ` [PATCH 03/12] Mark optimized out values as non-lazy Andrew Burgess
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Andrew Burgess @ 2013-08-12 12:18 UTC (permalink / raw)
  To: gdb-patches

In this patch I change the API used to mark a value as optimized
out, the API now matches that used for marking a value unavailable.

This patch does revert a recent change by Pedro:
  http://sourceware.org/ml/gdb-patches/2013-07/msg00178.html

however, later patches will change the code to be more acceptable.

OK to apply?

Thanks,
Andrew


gdb/ChangeLog

2013-08-08  Andrew Burgess  <aburgess@broadcom.com>

	* ada-lang.c (coerce_unspec_val_to_type): Switch to
	mark_value_bytes_optimized_out, and only mark non-lazy values as
	optimized out.
	* dwarf2loc.c (read_pieced_value): Switch to use
	mark_value_bytes_optimized_out, or mark_value_bits_optimized_out.
	(write_pieced_value): Switch to use
	mark_value_bytes_optimized_out.
	* findvar.c (read_frame_register_value): Switch to use
	mark_value_bytes_optimized_out.
	(value_from_register): Likewise.
	* value.c (allocate_optimized_out_value, value_fetch_lazy): Switch
	to use mark_value_bytes_optimized_out.
	(value_optimized_out_const, set_value_optimized_out): Remove.
	(mark_value_bytes_optimized_out, mark_value_bits_optimized_out):
	New function definition.
	* value.h (value_optimized_out_const, set_value_optimized_out):
	Remove.
	(mark_value_bytes_optimized_out, mark_value_bits_optimized_out):
	Add new declaration.

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index ba59913..20a0f02 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -576,12 +576,13 @@ coerce_unspec_val_to_type (struct value *val,
struct type *type)
 	  result = allocate_value (type);
 	  memcpy (value_contents_raw (result), value_contents (val),
 		  TYPE_LENGTH (type));
+	  if (value_optimized_out (val))
+	    mark_value_bytes_optimized_out (result, 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/dwarf2loc.c b/gdb/dwarf2loc.c
index 3b843fa..36b80fb 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -1694,7 +1694,7 @@ read_pieced_value (struct value *v)
 		    memset (buffer, 0, this_size);
  		    if (optim)
-		      set_value_optimized_out (v, 1);
+		      mark_value_bytes_optimized_out (v, offset, this_size);
 		    if (unavail)
 		      mark_value_bytes_unavailable (v, offset, this_size);
 		  }
@@ -1754,7 +1754,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:
@@ -1792,7 +1792,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;
     }
 @@ -1923,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;
diff --git a/gdb/findvar.c b/gdb/findvar.c
index f586ce2..f2bb247 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -713,7 +713,11 @@ read_frame_register_value (struct value *value,
struct frame_info *frame)
        if (value_optimized_out (regval))
 	{
-	  set_value_optimized_out (value, 1);
+	  /* If any one of the component registers is marked optimized out
+	     then we just mark the whole composite register as optimized
+	     out.  We could do better, but this style of composite register
+	     passing is not standard, and is only used on a few targets.  */
+	  mark_value_bytes_optimized_out (value, 0, TYPE_LENGTH (value_type
(value)));
 	  break;
 	}
 @@ -762,7 +766,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/value.c b/gdb/value.c
index 09ab1bb..462244e 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -742,7 +742,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));
    return retval;
 }
@@ -1062,16 +1062,28 @@ value_optimized_out (struct value *value)
   return value->optimized_out;
 }
 -int
-value_optimized_out_const (const struct value *value)
+/* Mark contents of VALUE as optimized out, starting at OFFSET bytes, and
+   the following LENGTH bytes.  */
+
+void
+mark_value_bytes_optimized_out (struct value *value, int offset, int
length)
 {
-  return value->optimized_out;
+  mark_value_bits_optimized_out (value,
+				 offset * TARGET_CHAR_BIT,
+				 length * TARGET_CHAR_BIT);
 }
 +/* Mark contents of VALUE as optimized out, starting at OFFSET bits, and
+   the following LENGTH bits.  */
+
 void
-set_value_optimized_out (struct value *value, int val)
+mark_value_bits_optimized_out (struct value *value,
+			       int offset ATTRIBUTE_UNUSED,
+			       int length ATTRIBUTE_UNUSED)
 {
-  value->optimized_out = val;
+  /* For now just set the optimized out flag to indicate that part of the
+     value is optimized out, this will be expanded upon in later
patches.  */
+  value->optimized_out = 1;   }
  int
@@ -3439,7 +3451,8 @@ value_fetch_lazy (struct value *val)
       if (!value_bits_valid (parent,
 			     TARGET_CHAR_BIT * offset + value_bitpos (val),
 			     value_bitsize (val)))
-	set_value_optimized_out (val, 1);
+	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,
@@ -3498,7 +3511,7 @@ value_fetch_lazy (struct value *val)
        /* If the register was not saved, mark it optimized out.  */
       if (value_optimized_out (new_val))
-	set_value_optimized_out (val, 1);
+	mark_value_bytes_optimized_out (val, 0, TYPE_LENGTH (value_type (val)));
       else
 	{
 	  set_value_lazy (val, 0);
diff --git a/gdb/value.h b/gdb/value.h
index 599850e..dd8a0c1 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -322,12 +322,18 @@ extern int value_contents_equal (struct value
*val1, struct value *val2);
    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);
+/* 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.  */
+
+extern void mark_value_bits_optimized_out (struct value *value,
+					   int offset, int length);
  /* Like value_optimized_out, but return false if any bit in the object
    is valid.  */


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

* [PATCH 03/12] Mark optimized out values as non-lazy.
  2013-08-12 12:15 [RFC 00/12] Merge value optimized_out and unavailable Andrew Burgess
  2013-08-12 12:16 ` [PATCH 01/12] Introduce is_unavailable_error Andrew Burgess
  2013-08-12 12:18 ` [PATCH 02/12]: Remove set_value_optimized_out Andrew Burgess
@ 2013-08-12 12:20 ` Andrew Burgess
  2013-11-26 16:38   ` Pedro Alves
  2013-08-12 12:22 ` [PATCH 04/12] Introduce OPTIMIZED_OUT_ERROR Andrew Burgess
                   ` (10 subsequent siblings)
  13 siblings, 1 reply; 27+ messages in thread
From: Andrew Burgess @ 2013-08-12 12:20 UTC (permalink / raw)
  To: gdb-patches

This is a re-posting of this patch:
  http://sourceware.org/ml/gdb-patches/2013-07/msg00058.html

The patch was never rejected, it just ran out of steam.  Pedro noticed
that we could go beyond this patch and do more, even releasing the
value contents when we spot values are fully optimized out.  I agree,
but believe that is a separate idea, that can always be added later,
for this case we've not even allocated any value contents yet.

OK to apply?

Cheers,
Andrew


gdb/ChangeLog

2013-08-12  Andrew Burgess  <aburgess@broadcom.com>

	* value.c (allocate_optimized_out_value): Mark fully optimized out
	values as non-lazy.

diff --git a/gdb/value.c b/gdb/value.c
index 462244e..64c9d78 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -744,6 +744,8 @@ allocate_optimized_out_value (struct type *type)
    mark_value_bytes_optimized_out (retval, 0, TYPE_LENGTH (type));
+  set_value_lazy (retval, 0);
+
   return retval;
 }


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

* [PATCH 04/12] Introduce OPTIMIZED_OUT_ERROR.
  2013-08-12 12:15 [RFC 00/12] Merge value optimized_out and unavailable Andrew Burgess
                   ` (2 preceding siblings ...)
  2013-08-12 12:20 ` [PATCH 03/12] Mark optimized out values as non-lazy Andrew Burgess
@ 2013-08-12 12:22 ` Andrew Burgess
  2013-08-12 12:24 ` [PATCH 05/12] Convert the unavailable to be bit based Andrew Burgess
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Andrew Burgess @ 2013-08-12 12:22 UTC (permalink / raw)
  To: gdb-patches

We already have a NOT_AVAILABLE_ERROR, this patch adds
an OPTIMIZED_OUT_ERROR.

It is not clear to me if the original intention of the
NOT_AVAILABLE_ERROR was to cover all reasons why a value
is missing, but from how it is currently used the
NOT_AVAILABLE_ERROR is for specifically the case where
a value is unavailable.   So, in order to catch the
optimized out errors just like we catch the unavailable
errors, I've added a new error code, and throw it in
various places.

OK to apply?

Thanks,
Andrew

gdb/ChangeLog

2013-08-08  Andrew Burgess  <aburgess@broadcom.com>

	* exceptions.h (errors): Add OPTIMIZED_OUT_ERROR.
	* exceptions.c (is_unavailable_error): Check for
	OPTIMIZED_OUT_ERROR.
	* dwarf2loc.c (write_pieced_value): Throw OPTIMIZED_OUT_ERROR.
	* frame.c (frame_unwind_pc_if_available): Display correct string
	for optimized out or unavailable values.
	(frame_unwind_register): Throw OPTIMIZED_OUT_ERROR.
	* spu-tdep.c (spu_software_single_step): Throw
	OPTIMIZED_OUT_ERROR.
	* valops.c (value_assign): Throw OPTIMIZED_OUT_ERROR.

diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 36b80fb..bae425a 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -1880,9 +1880,10 @@ write_pieced_value (struct value *to, struct
value *from)
 						   &optim, &unavail))
 		      {
 			if (optim)
-			  error (_("Can't do read-modify-write to "
-				   "update bitfield; containing word has been "
-				   "optimized out"));
+			  throw_error (OPTIMIZED_OUT_ERROR,
+				       _("Can't do read-modify-write to "
+					 "update bitfield; containing word "
+					 "has been optimized out"));
 			if (unavail)
 			  throw_error (NOT_AVAILABLE_ERROR,
 				       _("Can't do read-modify-write to update "
diff --git a/gdb/exceptions.c b/gdb/exceptions.c
index 134d918..c6248bc 100644
--- a/gdb/exceptions.c
+++ b/gdb/exceptions.c
@@ -577,5 +577,6 @@ catch_command_errors_const
(catch_command_errors_const_ftype *command,
 int
 is_unavailable_error (const enum errors error)
 {
-  return error == NOT_AVAILABLE_ERROR;
+  return (error == NOT_AVAILABLE_ERROR
+	  || error == OPTIMIZED_OUT_ERROR);
 }
diff --git a/gdb/exceptions.h b/gdb/exceptions.h
index 1baecf4..f2cc528 100644
--- a/gdb/exceptions.h
+++ b/gdb/exceptions.h
@@ -79,9 +79,9 @@ enum errors {
   /* Feature is not supported in this copy of GDB.  */
   UNSUPPORTED_ERROR,
 -  /* Value not available.  E.g., a register was not collected in a
-     traceframe.  */
-  NOT_AVAILABLE_ERROR,
+  /* Value not available.  */
+  NOT_AVAILABLE_ERROR, /* Not collected, e.g. in a traceframe.  */
+  OPTIMIZED_OUT_ERROR, /* Optimized out by compiler or ABI.  */
    /* DW_OP_GNU_entry_value resolving failed.  */
   NO_ENTRY_VALUE_ERROR,
diff --git a/gdb/frame.c b/gdb/frame.c
index 54f828c..f825f96 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -728,8 +728,11 @@ frame_unwind_pc_if_available (struct frame_info
*this_frame, CORE_ADDR *pc)
 	      if (frame_debug)
 		fprintf_unfiltered (gdb_stdlog,
 				    "{ frame_unwind_pc (this_frame=%d)"
-				    " -> <unavailable> }\n",
-				    this_frame->level);
+				    " -> %s }\n",
+				    this_frame->level,
+				    (ex.error == NOT_AVAILABLE_ERROR
+				     ? "<unavailable>"
+				     : "<optimized out>"));
 	    }
 	  else if (ex.reason < 0)
 	    {
@@ -988,7 +991,8 @@ frame_unwind_register (struct frame_info *frame, int
regnum, gdb_byte *buf)
 			 &lval, &addr, &realnum, buf);
    if (optimized)
-    error (_("Register %d was optimized out"), regnum);
+    throw_error (OPTIMIZED_OUT_ERROR,
+		 _("Register %d was optimized out"), regnum);
   if (unavailable)
     throw_error (NOT_AVAILABLE_ERROR,
 		 _("Register %d is not available"), regnum);
diff --git a/gdb/spu-tdep.c b/gdb/spu-tdep.c
index 46f3e2c..6fa3e7e 100644
--- a/gdb/spu-tdep.c
+++ b/gdb/spu-tdep.c
@@ -1614,8 +1614,9 @@ spu_software_single_step (struct frame_info *frame)
 	  else
 	    {
 	      if (optim)
-		error (_("Could not determine address of "
-			 "single-step breakpoint."));
+		throw_error (OPTIMIZED_OUT_ERROR,
+			     _("Could not determine address of "
+			       "single-step breakpoint."));
 	      if (unavail)
 		throw_error (NOT_AVAILABLE_ERROR,
 			     _("Could not determine address of "
diff --git a/gdb/valops.c b/gdb/valops.c
index f86b283..48dbeaa 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -1188,7 +1188,8 @@ value_assign (struct value *toval, struct value
*fromval)
 					       &optim, &unavail))
 		  {
 		    if (optim)
-		      error (_("value has been optimized out"));
+		      throw_error (OPTIMIZED_OUT_ERROR,
+				   _("value has been optimized out"));
 		    if (unavail)
 		      throw_error (NOT_AVAILABLE_ERROR,
 				   _("value is not available"));


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

* [PATCH 05/12] Convert the unavailable to be bit based.
  2013-08-12 12:15 [RFC 00/12] Merge value optimized_out and unavailable Andrew Burgess
                   ` (3 preceding siblings ...)
  2013-08-12 12:22 ` [PATCH 04/12] Introduce OPTIMIZED_OUT_ERROR Andrew Burgess
@ 2013-08-12 12:24 ` Andrew Burgess
  2013-08-12 12:27 ` [PATCH 06/12] Delete value_bits_valid Andrew Burgess
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Andrew Burgess @ 2013-08-12 12:24 UTC (permalink / raw)
  To: gdb-patches

The unavailable vector currently stores byte ranges within the value.
However, the optimized out interface allows for bit ranges to be
optimized out.

This patch changes the unavailable vector to be bit based, and at the
same time moves the code that actually inserts into the vector into a
helper function.

OK to apply?

Thanks,
Andrew

gdb/ChangeLog

2013-08-12  Andrew Burgess  <aburgess@broadcom.com>

	* value.c (insert_into_bit_range_vector): New function for
	inserting into the vector.
	(mark_value_bytes_unavailable): Use new function to build
	the unavailable vector in bits rather than bytes.
	(value_available_contents_eq): Take account of parameters being
	bytes, but the unavailable range now being in bits.
	(value_contents_copy_raw): Likewise, change to accommodate the
	unavailable vector being in bits.
	(value_bytes_available): Convert byte values to bits.

diff --git a/gdb/value.c b/gdb/value.c
index 64c9d78..e28c213 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -337,7 +337,9 @@ value_bytes_available (const struct value *value,
int offset
 {
   gdb_assert (!value->lazy);
 -  return !ranges_contain (value->unavailable, offset, length);
+  return !ranges_contain (value->unavailable,
+                         offset * TARGET_CHAR_BIT,
+                         length * TARGET_CHAR_BIT);
 }
  int
@@ -353,8 +353,11 @@ value_entirely_available (struct value *value)
   return 0;
 }
 -void
-mark_value_bytes_unavailable (struct value *value, int offset, int length)
+/* 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;
@@ -445,10 +448,10 @@ mark_value_bytes_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))
 	{
@@ -469,18 +472,18 @@ mark_value_bytes_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;
@@ -488,11 +491,11 @@ mark_value_bytes_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;
@@ -514,10 +517,18 @@ mark_value_bytes_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_bytes_unavailable (struct value *value, int offset, int length)
+{
+  insert_into_bit_range_vector (&value->unavailable,
+				offset * TARGET_CHAR_BIT,
+				length * TARGET_CHAR_BIT);
+}
+
 /* Find the first range in RANGES that overlaps the range defined by
    OFFSET and LENGTH, starting at element POS in the RANGES vector,
    Returns the index into RANGES where such overlapping range was
@@ -547,6 +558,12 @@ value_available_contents_eq (const struct value
*val1, int offset1,
   /* See function description in value.h.  */
   gdb_assert (!val1->lazy && !val2->lazy);
 +  /* The offsets and length parameters are all byte based, but we
store the
+     unavailable data in a bit based list.  */
+  offset1 *= TARGET_CHAR_BIT;
+  offset2 *= TARGET_CHAR_BIT;
+  length *= TARGET_CHAR_BIT;
+
   while (length > 0)
     {
       range_s *r1, *r2;
@@ -560,9 +577,9 @@ value_available_contents_eq (const struct value
*val1, int offset1,
        /* The usual case is for both values to be completely available.  */
       if (idx1 == -1 && idx2 == -1)
-	return (memcmp (val1->contents + offset1,
-			val2->contents + offset2,
-			length) == 0);
+	return (memcmp (val1->contents + (offset1 / TARGET_CHAR_BIT),
+			val2->contents + (offset2 / TARGET_CHAR_BIT),
+			(length / TARGET_CHAR_BIT)) == 0);
       /* The contents only match equal if the available set matches as
 	 well.  */
       else if (idx1 == -1 || idx2 == -1)
@@ -595,9 +612,9 @@ value_available_contents_eq (const struct value
*val1, int offset1,
 	return 0;
        /* Compare the _available_ contents.  */
-      if (memcmp (val1->contents + offset1,
-		  val2->contents + offset2,
-		  l1) != 0)
+      if (memcmp (val1->contents + (offset1 / TARGET_CHAR_BIT),
+		  val2->contents + (offset2 / TARGET_CHAR_BIT),
+		  (l1 / TARGET_CHAR_BIT)) != 0)
 	return 0;
        length -= h1;
@@ -938,6 +955,7 @@ value_contents_copy_raw (struct value *dst, int
dst_offset,
 {
   range_s *r;
   int i;
+  int src_bit_offset, dst_bit_offset, bit_length;
    /* A lazy DST would make that this copy operation useless, since as
      soon as DST's contents were un-lazied (by a later value_contents
@@ -956,16 +974,19 @@ value_contents_copy_raw (struct value *dst, int
dst_offset,
 	  length);
    /* Copy the meta-data, adjusted.  */
+  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_offset);
-      h = min (r->offset + r->length, src_offset + length);
+      l = max (r->offset, src_bit_offset);
+      h = min (r->offset + r->length, src_bit_offset + bit_length);
        if (l < h)
-	mark_value_bytes_unavailable (dst,
-				      dst_offset + (l - src_offset),
+	insert_into_bit_range_vector (&dst->unavailable,
+				      dst_bit_offset + (l - src_bit_offset),
 				      h - l);
     }
 }


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

* [PATCH 06/12] Delete value_bits_valid.
  2013-08-12 12:15 [RFC 00/12] Merge value optimized_out and unavailable Andrew Burgess
                   ` (4 preceding siblings ...)
  2013-08-12 12:24 ` [PATCH 05/12] Convert the unavailable to be bit based Andrew Burgess
@ 2013-08-12 12:27 ` Andrew Burgess
  2013-11-25 21:41   ` [PATCH] Print entirely unavailable struct/union values as a single <unavailable>. (Re: [PATCH 06/12] Delete value_bits_valid.) Pedro Alves
  2013-08-12 12:28 ` [PATCH 07/12] Generic print unavailable or optimized out function Andrew Burgess
                   ` (7 subsequent siblings)
  13 siblings, 1 reply; 27+ messages in thread
From: Andrew Burgess @ 2013-08-12 12:27 UTC (permalink / raw)
  To: gdb-patches

In this patch I remove value_bits_valid and merge the functionality
into value_bytes_available and a new value_bits_available.

At this point the optimized out and unavailable state are still
stored separately, the optimized out as a single bit flag, and
unavailable in the vector, but the query functions are now merged.

There are a few updates required to the expected results of the
gdb.trace/unavailable.exp test, the output is now more like the output
you would get if the values were optimized out.  I personally think this
is a good thing, but if most people disagree then we could change the
output for optimized out to be unavailable like, I do think the style of
output should match.  The reason I prefer this style is that a fully
unavailable structure is displayed with a single "<unavailable>" rather
than the full structure with lots of unavailables throughout.

OK to apply?

Thanks,
Andrew

gdb/ChangeLog

2013-08-08  Andrew Burgess  <aburgess@broadcom.com>

	* c-valprint.c (c_val_print): Remove call to value_bits_valid.
	* cp-valprint.c (cp_print_value_fields): Remove call to
	value_bits_valid, and print correct unavailability reason.
	(cp_print_value_fields_rtti): Use value_bytes_available instead of
	value_bits_valid.
	* d-valprint.c (dynamic_array_type): Likewise.
	* frame.c (frame_register_unwind): Use value_availability_flags.
	(read_frame_register_unsigned): Remove call to value_optimized_out.
	* jv-valprint.c (java_print_value_fields): Use
	value_bits_available rather than value_bits_valid.
	* opencl-lang.c (lval_func_check_validity): Likewise.
	(lval_func_check_any_valid): Likewise.
	* p-valprint.c (pascal_object_print_value_fields): Use
	value_bits_available rather than value_bits_valid, and print the
	correct unavailability reason.
	* valprint.c (valprint_check_validity): Use value_bits_available
	rather than value_bits_valid, and print the correct unavailability
	reason.  Remove additional call to value_bytes_available.
	(value_check_printable): Replace value_entirely_optimized_out with
	value_entirely_unavailable., print the corrct unavailability reason.
	(val_print_scalar_formatted): Use value_bytes_available rather
	than value_bits_valid, and print the correct unavailability
	reason.
	* value.c (value_bits_available): New function, includes old
	value_bits_valid.
	(value_bytes_available): Use value_bits_available.
	(value_entirely_available): Take account of optimized_out.
	(value_entirely_unavailable): New function, includes old
	value_entirely_optimized_out code.
	(value_availability_flags): New function.
	(value_entirely_optimized_out): Deleted, code forms part of
	value_entirely_unavailable.
	(value_bits_valid): Deleted, code forms part of
	value_bits_available.
	(value_fetch_lazy): Use value_bits_available rather than
	value_bits_valid.  If parent is unavailable, mark child value
	either opttimized out or unavailable.  Remove duplicate call to set
	chid value unavailable.
	* value.h (value_entirely_optimized_out): Deleted.
	(value_bits_valid): Deleted.
	(value_bits_available): New function.
	(value_entirely_available): Add comment.
	(value_entirely_unavailable): New function.
	(value_availability_flags): New function.

gdb/testsuite/ChangeLog

2013-08-08  Andrew Burgess  <aburgess@broadcom.com>

	* gdb.trace/unavailable.exp(gdb_collect_args_test): Update
	expected results.
	(gdb_collect_locals_test): Likewise.
	(gdb_collect_globals_test): Likewise.

diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c
index 3466df0..551080a 100644
--- a/gdb/c-valprint.c
+++ b/gdb/c-valprint.c
@@ -171,10 +171,7 @@ c_val_print (struct type *type, const gdb_byte
*valaddr,
           if (c_textual_element_type (unresolved_elttype,
 				      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)))
+					TYPE_LENGTH (type)))
 	    {
 	      int force_ellipses = 0;
 diff --git a/gdb/cp-valprint.c b/gdb/cp-valprint.c
index 795b7b0..5dd98b0 100644
--- a/gdb/cp-valprint.c
+++ b/gdb/cp-valprint.c
@@ -294,11 +294,17 @@ 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)))
+	      else if (!value_bits_available (val,
+					      TYPE_FIELD_BITPOS (type, i),
+					      TYPE_FIELD_BITSIZE (type, i)))
 		{
-		  val_print_optimized_out (stream);
+		  int optimizedp, unavailablep;
+
+		  value_availability_flags (val, &optimizedp, &unavailablep);
+		  if (optimizedp)
+		    val_print_optimized_out (stream);
+		  else
+		    val_print_unavailable (stream);
 		}
 	      else
 		{
@@ -437,8 +443,7 @@ 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_bytes_available (val, offset, TYPE_LENGTH (type)))
     {
       struct value *value;
       int full, top, using_enc;
diff --git a/gdb/d-valprint.c b/gdb/d-valprint.c
index 6e9c28d..499c0e3 100644
--- a/gdb/d-valprint.c
+++ b/gdb/d-valprint.c
@@ -38,8 +38,7 @@ 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_bytes_available (val, embedded_offset, TYPE_LENGTH (type)))
     {
       CORE_ADDR addr;
       struct type *elttype;
diff --git a/gdb/frame.c b/gdb/frame.c
index f825f96..c5d85b4 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -937,8 +937,10 @@ frame_register_unwind (struct frame_info *frame,
int regnum,
    gdb_assert (value != NULL);
 -  *optimizedp = value_optimized_out (value);
-  *unavailablep = !value_entirely_available (value);
+  if (!value_entirely_available (value))
+    value_availability_flags (value, optimizedp, unavailablep);
+  else
+    *optimizedp = *unavailablep = 0;
   *lvalp = VALUE_LVAL (value);
   *addrp = value_address (value);
   *realnump = VALUE_REGNUM (value);
@@ -1116,8 +1118,7 @@ read_frame_register_unsigned (struct frame_info
*frame, int regnum,
 {
   struct value *regval = get_frame_register_value (frame, regnum);
 -  if (!value_optimized_out (regval)
-      && value_entirely_available (regval))
+  if (value_entirely_available (regval))
     {
       struct gdbarch *gdbarch = get_frame_arch (frame);
       enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
diff --git a/gdb/jv-valprint.c b/gdb/jv-valprint.c
index 3b90e54..edcd769 100644
--- a/gdb/jv-valprint.c
+++ b/gdb/jv-valprint.c
@@ -392,10 +392,16 @@ 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)))
+	      else if (!value_bits_available (val, TYPE_FIELD_BITPOS (type, i),
+					      TYPE_FIELD_BITSIZE (type, i)))
 		{
-		  val_print_optimized_out (stream);
+		  int optimizedp, unavailablep;
+
+		  value_availability_flags (val, &optimizedp, &unavailablep);
+		  if (optimizedp)
+		    val_print_optimized_out (stream);
+		  else
+		    val_print_unavailable (stream);
 		}
 	      else
 		{
diff --git a/gdb/opencl-lang.c b/gdb/opencl-lang.c
index 4720e2b..4da2c9d 100644
--- a/gdb/opencl-lang.c
+++ b/gdb/opencl-lang.c
@@ -266,8 +266,8 @@ lval_func_check_validity (const struct value *v, int
offset, int length)
       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))
+      if (!value_bits_available (c->val, c->indices[i] * elsize +
comp_offset,
+				 comp_length))
 	return 0;
     }
 @@ -286,7 +286,7 @@ lval_func_check_any_valid (const struct value *v)
   int i;
    for (i = 0; i < c->n; i++)
-    if (value_bits_valid (c->val, c->indices[i] * elsize, elsize))
+    if (value_bits_available (c->val, c->indices[i] * elsize, elsize))
       return 1;
    return 0;
diff --git a/gdb/p-valprint.c b/gdb/p-valprint.c
index cfafe99..bc57541 100644
--- a/gdb/p-valprint.c
+++ b/gdb/p-valprint.c
@@ -626,10 +626,16 @@ 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)))
+	      else if (!value_bits_available (val, TYPE_FIELD_BITPOS (type, i),
+					      TYPE_FIELD_BITSIZE (type, i)))
 		{
-		  val_print_optimized_out (stream);
+		  int optimizedp, unavailablep;
+		  +		  value_availability_flags (val, &optimizedp, &unavailablep);
+		  if (optimizedp)
+		    val_print_optimized_out (stream);
+		  else
+		    val_print_unavailable (stream);
 		}
 	      else
 		{
diff --git a/gdb/testsuite/gdb.trace/unavailable.exp
b/gdb/testsuite/gdb.trace/unavailable.exp
index 8e2e105..304f1ef 100644
--- a/gdb/testsuite/gdb.trace/unavailable.exp
+++ b/gdb/testsuite/gdb.trace/unavailable.exp
@@ -170,14 +170,14 @@ proc gdb_collect_args_test {} {
 	# struct arg as one of several args (near end of list)
  	gdb_test "print argstruct" \
-	    " = \{memberc = <unavailable>, memberi = <unavailable>, memberf =
<unavailable>, memberd = <unavailable>\}"
+	    " = <unavailable>"
  	gdb_test "print argstruct.memberc" " = <unavailable>"
 	gdb_test "print argstruct.memberi" " = <unavailable>"
 	gdb_test "print argstruct.memberf" " = <unavailable>"
 	gdb_test "print argstruct.memberd" " = <unavailable>"
 -	gdb_test "print argarray" " = \\(int \\*\\) <unavailable>"
+	gdb_test "print argarray" " = <unavailable>"
  	gdb_test "print &argarray" \
 	    "Can't take address of \"argarray\" which isn't an lvalue\."
@@ -190,7 +190,7 @@ proc gdb_collect_args_test {} {
 	set r "${r}argi = <unavailable>${cr}"
 	set r "${r}argf = <unavailable>${cr}"
 	set r "${r}argd = <unavailable>${cr}"
-	set r "${r}argstruct = {memberc = <unavailable>, memberi =
<unavailable>, memberf = <unavailable>, memberd = <unavailable>}${cr}"
+	set r "${r}argstruct = <unavailable>${cr}"
 	set r "${r}argarray = <unavailable>${cr}"
 	gdb_test "info args" "$r" "info args"
 @@ -237,11 +237,11 @@ proc gdb_collect_locals_test { func msg } {
 	set r ""
 	set r "${r}locf = <unavailable>${cr}"
 	set r "${r}locd = <unavailable>${cr}"
-	set r "${r}locst = {memberc = <unavailable>, memberi = <unavailable>,
memberf = <unavailable>, memberd = <unavailable>}${cr}"
-	set r "${r}locar = {<unavailable>, <unavailable>, <unavailable>,
<unavailable>}${cr}"
+	set r "${r}locst = <unavailable>${cr}"
+	set r "${r}locar = <unavailable>${cr}"
 	set r "${r}i = <unavailable>${cr}"
 	if { $func == "local_test_func" } {
-	    set r "${r}locdefst = {<No data fields>}${cr}"
+	    set r "${r}locdefst = <unavailable>${cr}"
 	}
 	set r "${r}locc = <unavailable>${cr}"
 	set r "${r}loci = <unavailable>${cr}"
@@ -399,7 +399,7 @@ proc gdb_collect_globals_test { } {
 	gdb_test "print globalstruct.memberd" " = <unavailable>"
  	gdb_test "print globalstruct" \
-	    " = {memberc = <unavailable>, memberi = <unavailable>, memberf =
<unavailable>, memberd = <unavailable>}"
+	    " = <unavailable>"
  	gdb_test "print globalp == &globalstruct" \
 	    "value is not available" \
@@ -450,7 +450,7 @@ proc gdb_collect_globals_test { } {
 	# Static fields
  	gdb_test "print struct_b.static_struct_a" \
-	    " = {a = <unavailable>, b = <unavailable>, array = {<unavailable>
<repeats 10000 times>}, ptr = <unavailable>, bitfield = <unavailable>}"
+	    " = <unavailable>"
  	# Bitfields
 @@ -469,7 +469,7 @@ proc gdb_collect_globals_test { } {
 	    "referenced integer was not collected (taking address of reference)"
  	gdb_test "print *g_structref_p" \
-	    " = {d = <unavailable>, ref = <unavailable>}"
+	    " = <unavailable>"
  	# Strings
 @@ -483,7 +483,7 @@ proc gdb_collect_globals_test { } {
 	    "printing constant string through collected pointer"
  	gdb_test "print g_string_unavail" \
-	    " = \{<unavailable> <repeats 12 times>\}" \
+	    " = <unavailable>" \
 	    "printing non collected string"
  	# Incomplete strings print as an array.
@@ -521,15 +521,15 @@ proc gdb_collect_globals_test { } {
 	# unavailable-ness is propagated.  History values are easy
 	# non-lazy values, so use those.  The first test just sets up for
 	# the second.
-	gdb_test "print g_smallstruct" " = \\{member = <unavailable>\\}"
+	gdb_test "print g_smallstruct" " = <unavailable>"
 	gdb_test "print \$.member" " = <unavailable>"
  	# Cast to baseclass, checking the unavailable-ness is propagated.
-	gdb_test "print (small_struct) g_smallstruct_b" " = \\{member =
<unavailable>\\}"
+	gdb_test "print (small_struct) g_smallstruct_b" " = <unavailable>"
  	# Same cast, but starting from a non-lazy, value.
-	gdb_test "print g_smallstruct_b" " = \\{<small_struct> = \\{member =
<unavailable>\\}, <No data fields>\\}"
-	gdb_test "print (small_struct) \$" " = \\{member = <unavailable>\\}"
+	gdb_test "print g_smallstruct_b" " = <unavailable>"
+	gdb_test "print (small_struct) \$" " = <unavailable>"
  	gdb_test_no_output "set print object on"
 @@ -538,11 +538,11 @@ proc gdb_collect_globals_test { } {
 	    # the pointed-to object, to check its run-time type.  Make
 	    # sure that fails gracefully and transparently when the
 	    # pointer itself is unavailable.
-	    gdb_test "print virtualp" " = \\(Virtual \\*\\) <unavailable>"
+	    gdb_test "print virtualp" " = <unavailable>"
  	    # no vtable pointer available
 	    gdb_test "print derived_unavail" \
-		" = {<Middle> = <unavailable>, _vptr.Derived = <unavailable>, z =
<unavailable>}"
+		" = <unavailable>"
  	    # vtable pointer available, but nothing else
 	    gdb_test "print derived_partial" \
@@ -556,11 +556,11 @@ proc gdb_collect_globals_test { } {
 	gdb_test_no_output "set print object off"
  	with_test_prefix "print object off" {
-	    gdb_test "print virtualp" " = \\(Virtual \\*\\) <unavailable>"
+	    gdb_test "print virtualp" " = <unavailable>"
  	    # no vtable pointer available
 	    gdb_test "print derived_unavail" \
-		" = {<Middle> = <unavailable>, _vptr.Derived = <unavailable>, z =
<unavailable>}"
+		" = <unavailable>"
  	    # vtable pointer available, but nothing else
 	    gdb_test "print derived_partial" \
diff --git a/gdb/valprint.c b/gdb/valprint.c
index 753ae34..4e165b4 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -311,10 +311,16 @@ 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_available (val, TARGET_CHAR_BIT * embedded_offset,
+				 TARGET_CHAR_BIT * TYPE_LENGTH (type)))
 	{
-	  val_print_optimized_out (stream);
+	  int optimizedp, unavailablep;
+	  +	  value_availability_flags (val, &optimizedp, &unavailablep);
+	  if (optimizedp)
+	    val_print_optimized_out (stream);
+	  else
+	    val_print_unavailable (stream);
 	  return 0;
 	}
 @@ -324,12 +330,6 @@ valprint_check_validity (struct ui_file *stream,
 	  fputs_filtered (_("<synthetic pointer>"), stream);
 	  return 0;
 	}
-
-      if (!value_bytes_available (val, embedded_offset, TYPE_LENGTH
(type)))
-	{
-	  val_print_unavailable (stream);
-	  return 0;
-	}
     }
    return 1;
@@ -800,12 +800,20 @@ value_check_printable (struct value *val, struct
ui_file *stream,
       return 0;
     }
 -  if (value_entirely_optimized_out (val))
+  if (value_entirely_unavailable (val))
     {
       if (options->summary && !scalar_type_p (value_type (val)))
 	fprintf_filtered (stream, "...");
       else
-	val_print_optimized_out (stream);
+	{
+	  int optimizedp, unavailablep;
+
+	  value_availability_flags (val, &optimizedp, &unavailablep);
+	  if (optimizedp)
+	    val_print_optimized_out (stream);
+	  else
+	    val_print_unavailable (stream);
+	}
       return 0;
     }
 @@ -964,11 +972,16 @@ 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)))
-    val_print_optimized_out (stream);
-  else if (!value_bytes_available (val, embedded_offset, TYPE_LENGTH
(type)))
-    val_print_unavailable (stream);
+  if (!value_bytes_available (val, embedded_offset, TYPE_LENGTH (type)))
+    {
+      int optimizedp, unavailablep;
+      +      value_availability_flags (val, &optimizedp, &unavailablep);
+      if (optimizedp)
+	val_print_optimized_out (stream);
+      else
+	val_print_unavailable (stream);
+    }
   else
     print_scalar_formatted (valaddr + embedded_offset, type,
 			    options, size, stream);
diff --git a/gdb/value.c b/gdb/value.c
index 49af876..b9f5709 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -335,11 +335,25 @@ struct value
 int
 value_bytes_available (const struct value *value, int offset, int length)
 {
+  return value_bits_available (value,
+			       offset * TARGET_CHAR_BIT,
+			       length * TARGET_CHAR_BIT);
+}
+
+int
+value_bits_available (const struct value *value, int offset, int length)
+{
   gdb_assert (!value->lazy);
 -  return !ranges_contain (value->unavailable,
-			  offset * TARGET_CHAR_BIT,
-			  length * TARGET_CHAR_BIT);
+  if (ranges_contain (value->unavailable, offset, length))
+    return 0;
+  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);
 }
  int
@@ -350,11 +364,43 @@ value_entirely_available (struct value *value)
   if (value->lazy)
     value_fetch_lazy (value);
 -  if (VEC_empty (range_s, value->unavailable))
+  if (VEC_empty (range_s, value->unavailable)
+      && !value->optimized_out)
     return 1;
   return 0;
 }
 +int
+value_entirely_unavailable (struct value *value)
+{
+  if (value->lazy)
+    value_fetch_lazy (value);
+
+  /* Check if the unavailable vector covers the entire value.  As we merge
+     entries in the vector, if the entire value is covered then we'll
+     have a single entry starting at offset 0 and length as long as the
+     type.  */
+  if (VEC_length (range_s, value->unavailable) == 1)
+    {
+      const range_s *r;
+      struct type *type;
+
+      type = check_typedef (value_type (value));
+      r = VEC_index (range_s, value->unavailable, 0);
+      if (r->offset == 0 && r->length >= TARGET_CHAR_BIT * TYPE_LENGTH
(type))
+	return 1;
+    }
+
+  /* At least some of the value contents are NOT covered by the unavailable
+     vector, fall back to the optimized out heuristic.  */
+  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);
+}
+
 /* Insert into the vector pointed to by VECTORP the bit range starting of
    OFFSET bits, and extending for the next LENGTH bits.  */
 @@ -531,6 +577,15 @@ mark_value_bytes_unavailable (struct value *value,
int offset, int length)
 				length * TARGET_CHAR_BIT);
 }
 +void
+value_availability_flags (const struct value *value,
+			  int *optimizedp,
+			  int *unavailablep)
+{
+  *optimizedp = value->optimized_out;
+  *unavailablep = !VEC_empty (range_s, value->unavailable);
+}
+
 /* Find the first range in RANGES that overlaps the range defined by
    OFFSET and LENGTH, starting at element POS in the RANGES vector,
    Returns the index into RANGES where such overlapping range was
@@ -1112,29 +1167,6 @@ mark_value_bits_optimized_out (struct value *value,
 }
  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);
-}
-
-int
-value_bits_valid (const 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);
-}
-
-int
 value_bits_synthetic_pointer (const struct value *value,
 			      int offset, int length)
 {
@@ -3473,19 +3505,26 @@ 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)))
-	mark_value_bytes_optimized_out (val, value_embedded_offset (val),
-					TYPE_LENGTH (type));
+      if (!value_bits_available (parent,
+				 TARGET_CHAR_BIT * offset + value_bitpos (val),
+				 value_bitsize (val)))
+	{
+	  int optimizedp, unavailablep;
+
+	  value_availability_flags (parent, &optimizedp, &unavailablep);
+	  if (optimizedp)
+	    mark_value_bytes_optimized_out (val, value_embedded_offset (val),
+					    TYPE_LENGTH (type));
+	  else
+	    mark_value_bytes_unavailable (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));
+	error (_("unable to unpack bitfield"));
       else
 	store_signed_integer (value_contents_raw (val), TYPE_LENGTH (type),
 			      byte_order, num);
diff --git a/gdb/value.h b/gdb/value.h
index dd8a0c1..81c1cc5 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -335,10 +335,6 @@ extern void mark_value_bytes_optimized_out (struct
value *value,
 extern void mark_value_bits_optimized_out (struct value *value,
 					   int offset, int length);
 -/* 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);
-
 /* Set or return field indicating whether a variable is initialized or
    not, based on debugging information supplied by the compiler.
    1 = initialized; 0 = uninitialized.  */
@@ -417,13 +413,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,
@@ -437,16 +426,37 @@ extern int value_bits_synthetic_pointer (const
struct value *value,
 extern int value_bytes_available (const struct value *value,
 				  int offset, int length);
 -/* Like value_bytes_available, but return false if any byte in the
-   whole object is unavailable.  */
+/* Given a value, determine whether the bits starting at OFFSET and
+   extending for LENGTH bits are available.  This returns nonzero if all
+   bits in the given range are available, zero if any bit is
unavailable.  */
+
+extern int value_bits_available (const struct value *value,
+				 int offset, int length);
+
+/* Return true if the entire contents of VALUE are available, if any part
+   of VALUE is not available then return false.  */
+
 extern int value_entirely_available (struct value *value);
 +/* Return true if the entire contents of VALUE are unavailable.  If any
+   part of VALUE is available then return false.  */
+
+extern int value_entirely_unavailable (struct value *value);
+
 /* Mark VALUE's content bytes starting at OFFSET and extending for
    LENGTH bytes as unavailable.  */
  extern void mark_value_bytes_unavailable (struct value *value,
 					  int offset, int length);
 +/* Set contents of OPTIMIZEDP to nonzero if any part of VALUE is optimized
+   out, otherwise set to zero.  Set contents of UNAVAILABLEP to nonzero if
+   any part of VALUE is unavailable, otherwise set to zero.  */
+
+extern void value_availability_flags (const struct value *value,
+				      int *optimizedp,
+				      int *unavailablep);
+
 /* Compare LENGTH bytes of VAL1's contents starting at OFFSET1 with
    LENGTH bytes of VAL2's contents starting at OFFSET2.



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

* [PATCH 07/12] Generic print unavailable or optimized out function.
  2013-08-12 12:15 [RFC 00/12] Merge value optimized_out and unavailable Andrew Burgess
                   ` (5 preceding siblings ...)
  2013-08-12 12:27 ` [PATCH 06/12] Delete value_bits_valid Andrew Burgess
@ 2013-08-12 12:28 ` Andrew Burgess
  2013-08-12 12:29 ` [PATCH 08/12] Replace some value_optimized_out with value_entirely_available Andrew Burgess
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Andrew Burgess @ 2013-08-12 12:28 UTC (permalink / raw)
  To: gdb-patches

Following on from the patch #6, this factors out a common pattern:
given a value print either <optimized-out> or <unavailable>.

OK to apply?

Thanks,
Andrew



gdb/ChangeLog

2013-08-08  Andrew Burgess  <aburgess@broadcom.com>

	* cp-valprint.c (cp_print_value_fields): Use
	val_print_unavailability_reason.
	* jv-valprint.c (java_print_value_fields): Use
	val_print_unavailability_reason.
	* p-valprint.c (pascal_object_print_value_fields): Use
	val_print_unavailability_reason.
	* valprint.c (valprint_check_validity, value_check_printable)
	(val_print_scalar_formatted): Use val_print_unavailability_reason.
	(val_print_unavailability_reason): New function.
	* valprint.h (val_print_unavailability_reason): New function.

diff --git a/gdb/cp-valprint.c b/gdb/cp-valprint.c
index 5dd98b0..6b66092 100644
--- a/gdb/cp-valprint.c
+++ b/gdb/cp-valprint.c
@@ -298,13 +298,7 @@ cp_print_value_fields (struct type *type, struct
type *real_type,
 					      TYPE_FIELD_BITPOS (type, i),
 					      TYPE_FIELD_BITSIZE (type, i)))
 		{
-		  int optimizedp, unavailablep;
-
-		  value_availability_flags (val, &optimizedp, &unavailablep);
-		  if (optimizedp)
-		    val_print_optimized_out (stream);
-		  else
-		    val_print_unavailable (stream);
+		  val_print_unavailability_reason (val, stream);
 		}
 	      else
 		{
diff --git a/gdb/jv-valprint.c b/gdb/jv-valprint.c
index edcd769..dfa2d38 100644
--- a/gdb/jv-valprint.c
+++ b/gdb/jv-valprint.c
@@ -394,15 +394,7 @@ java_print_value_fields (struct type *type, const
gdb_byte *valaddr,
 		}
 	      else if (!value_bits_available (val, TYPE_FIELD_BITPOS (type, i),
 					      TYPE_FIELD_BITSIZE (type, i)))
-		{
-		  int optimizedp, unavailablep;
-
-		  value_availability_flags (val, &optimizedp, &unavailablep);
-		  if (optimizedp)
-		    val_print_optimized_out (stream);
-		  else
-		    val_print_unavailable (stream);
-		}
+		val_print_unavailability_reason (val, stream);
 	      else
 		{
 		  struct value_print_options opts;
diff --git a/gdb/p-valprint.c b/gdb/p-valprint.c
index bc57541..0bd0022 100644
--- a/gdb/p-valprint.c
+++ b/gdb/p-valprint.c
@@ -628,15 +628,7 @@ pascal_object_print_value_fields (struct type
*type, const gdb_byte *valaddr,
 		}
 	      else if (!value_bits_available (val, TYPE_FIELD_BITPOS (type, i),
 					      TYPE_FIELD_BITSIZE (type, i)))
-		{
-		  int optimizedp, unavailablep;
-		  -		  value_availability_flags (val, &optimizedp, &unavailablep);
-		  if (optimizedp)
-		    val_print_optimized_out (stream);
-		  else
-		    val_print_unavailable (stream);
-		}
+		val_print_unavailability_reason (val, stream);
 	      else
 		{
 		  struct value_print_options opts = *options;
diff --git a/gdb/valprint.c b/gdb/valprint.c
index 4e165b4..0443737 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -314,13 +314,7 @@ valprint_check_validity (struct ui_file *stream,
       if (!value_bits_available (val, TARGET_CHAR_BIT * embedded_offset,
 				 TARGET_CHAR_BIT * TYPE_LENGTH (type)))
 	{
-	  int optimizedp, unavailablep;
-	  -	  value_availability_flags (val, &optimizedp, &unavailablep);
-	  if (optimizedp)
-	    val_print_optimized_out (stream);
-	  else
-	    val_print_unavailable (stream);
+	  val_print_unavailability_reason (val, stream);
 	  return 0;
 	}
 @@ -353,6 +347,19 @@ val_print_invalid_address (struct ui_file *stream)
   fprintf_filtered (stream, _("<invalid address>"));
 }
 +void
+val_print_unavailability_reason (const struct value *value,
+				 struct ui_file *stream)
+{
+  int optimizedp, unavailablep;
+
+  value_availability_flags (value, &optimizedp, &unavailablep);
+  if (optimizedp)
+    val_print_optimized_out (stream);
+  else
+    val_print_unavailable (stream);
+}
+
 /* A generic val_print that is suitable for use by language
    implementations of the la_val_print method.  This function can
    handle most type codes, though not all, notably exception
@@ -805,15 +812,7 @@ value_check_printable (struct value *val, struct
ui_file *stream,
       if (options->summary && !scalar_type_p (value_type (val)))
 	fprintf_filtered (stream, "...");
       else
-	{
-	  int optimizedp, unavailablep;
-
-	  value_availability_flags (val, &optimizedp, &unavailablep);
-	  if (optimizedp)
-	    val_print_optimized_out (stream);
-	  else
-	    val_print_unavailable (stream);
-	}
+	val_print_unavailability_reason (val, stream);
       return 0;
     }
 @@ -973,15 +972,7 @@ 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_bytes_available (val, embedded_offset, TYPE_LENGTH (type)))
-    {
-      int optimizedp, unavailablep;
-      -      value_availability_flags (val, &optimizedp, &unavailablep);
-      if (optimizedp)
-	val_print_optimized_out (stream);
-      else
-	val_print_unavailable (stream);
-    }
+    val_print_unavailability_reason (val, stream);
   else
     print_scalar_formatted (valaddr + embedded_offset, type,
 			    options, size, stream);
diff --git a/gdb/valprint.h b/gdb/valprint.h
index 2959098..5d7f211 100644
--- a/gdb/valprint.h
+++ b/gdb/valprint.h
@@ -166,6 +166,12 @@ extern void val_print_unavailable (struct ui_file
*stream);
  extern void val_print_invalid_address (struct ui_file *stream);
 +/* For VALUE call the most appropriate of val_print_optimized_out or
+   val_print_unavailable on STREAM.  */
+
+void val_print_unavailability_reason (const struct value *value,
+				      struct ui_file *stream);
+
 /* An instance of this is passed to generic_val_print and describes
    some language-specific ways to print things.  */


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

* [PATCH 08/12] Replace some value_optimized_out with value_entirely_available
  2013-08-12 12:15 [RFC 00/12] Merge value optimized_out and unavailable Andrew Burgess
                   ` (6 preceding siblings ...)
  2013-08-12 12:28 ` [PATCH 07/12] Generic print unavailable or optimized out function Andrew Burgess
@ 2013-08-12 12:29 ` Andrew Burgess
  2013-11-27 17:52   ` [COMMITTED PATCH 0/2] "set debug frame 1" and not saved registers (was: Re: [PATCH 08/12] Replace some value_optimized_out with value_entirely_available) Pedro Alves
  2013-08-12 12:30 ` [PATCH 09/12] DWARF value, mark unavailable in bits not bytes Andrew Burgess
                   ` (5 subsequent siblings)
  13 siblings, 1 reply; 27+ messages in thread
From: Andrew Burgess @ 2013-08-12 12:29 UTC (permalink / raw)
  To: gdb-patches

A few places where we use value_optimized_out to check that
the value is entirely available, this fails to take into
account the unavailable status of the value.

Fix by using value_entirely_available instead.

OK to apply?

thanks,
Andrew

gdb/ChangeLog

2013-08-09  Andrew Burgess  <aburgess@broadcom.com>

	* frame.c (frame_unwind_register_value): Use
	value_entirely_available rather than value_optimized_out.
	* infrun.c (insert_exception_resume_breakpoint): Likewise.
	* mips-tdep.c (mips_print_register): Likewise.
	* s390-tdep.c (s390_unwind_pseudo_register): Likewise.
	* stack.c (read_frame_arg): Likewise.
	* value.c (value_fetch_lazy): Likewise.

diff --git a/gdb/frame.c b/gdb/frame.c
index c5d85b4..edac6e7 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -44,6 +44,7 @@
 #include "inline-frame.h"
 #include "tracepoint.h"
 #include "hashtab.h"
+#include "valprint.h"
  static struct frame_info *get_prev_frame_1 (struct frame_info
*this_frame);
 static struct frame_info *get_prev_frame_raw (struct frame_info
*this_frame);
@@ -1035,8 +1036,11 @@ frame_unwind_register_value (struct frame_info
*frame, int regnum)
   if (frame_debug)
     {
       fprintf_unfiltered (gdb_stdlog, "->");
-      if (value_optimized_out (value))
-	fprintf_unfiltered (gdb_stdlog, " optimized out");
+      if (!value_entirely_available (value))
+	{
+	  fprintf_unfiltered (gdb_stdlog, " ");
+	  val_print_unavailability_reason (value, gdb_stdlog);
+	}
       else
 	{
 	  if (VALUE_LVAL (value) == lval_register)
diff --git a/gdb/infrun.c b/gdb/infrun.c
index dc1036d..eaa85b5 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -5547,7 +5547,7 @@ insert_exception_resume_breakpoint (struct
thread_info *tp,
       vsym = lookup_symbol (SYMBOL_LINKAGE_NAME (sym), b, VAR_DOMAIN,
NULL);
       value = read_var_value (vsym, frame);
       /* If the value was optimized out, revert to the old behavior.  */
-      if (! value_optimized_out (value))
+      if (value_entirely_available (value))
 	{
 	  handler = value_as_address (value);
 diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index bcbdcc5..ba73501 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -6196,7 +6196,7 @@ mips_print_register (struct ui_file *file, struct
frame_info *frame,
     }
    val = get_frame_register_value (frame, regnum);
-  if (value_optimized_out (val))
+  if (!value_entirely_available (val))
     {
       fprintf_filtered (file, "%s: [Invalid]",
 			gdbarch_register_name (gdbarch, regnum));
diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c
index 72d5545..16b1779 100644
--- a/gdb/s390-tdep.c
+++ b/gdb/s390-tdep.c
@@ -1689,7 +1689,7 @@ s390_unwind_pseudo_register (struct frame_info
*this_frame, int regnum)
       struct value *val;
        val = frame_unwind_register_value (this_frame, S390_PSWA_REGNUM);
-      if (!value_optimized_out (val))
+      if (value_entirely_available (val))
 	{
 	  LONGEST pswa = value_as_long (val);
 @@ -1706,7 +1706,7 @@ s390_unwind_pseudo_register (struct frame_info
*this_frame, int regnum)
       struct value *val;
        val = frame_unwind_register_value (this_frame, S390_PSWM_REGNUM);
-      if (!value_optimized_out (val))
+      if (value_entirely_available (val))
 	{
 	  LONGEST pswm = value_as_long (val);
 @@ -1727,7 +1727,7 @@ s390_unwind_pseudo_register (struct frame_info
*this_frame, int regnum)
       struct value *val;
        val = frame_unwind_register_value (this_frame, S390_R0_REGNUM +
reg);
-      if (!value_optimized_out (val))
+      if (value_entirely_available (val))
 	return value_cast (type, val);
     }
 diff --git a/gdb/stack.c b/gdb/stack.c
index af05f84..cec5df5 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -353,7 +353,7 @@ read_frame_arg (struct symbol *sym, struct
frame_info *frame,
       && SYMBOL_COMPUTED_OPS (sym)->read_variable_at_entry != NULL
       && print_entry_values != print_entry_values_no
       && (print_entry_values != print_entry_values_if_needed
-	  || !val || value_optimized_out (val)))
+	  || !val || !value_entirely_available (val)))
     {
       TRY_CATCH (except, RETURN_MASK_ERROR)
 	{
@@ -369,7 +369,7 @@ read_frame_arg (struct symbol *sym, struct
frame_info *frame,
 	}
        if (except.error == NO_ENTRY_VALUE_ERROR
-	  || (entryval && value_optimized_out (entryval)))
+	  || (entryval && !value_entirely_available (entryval)))
 	{
 	  entryval = NULL;
 	  entryval_error = NULL;
@@ -468,13 +468,13 @@ read_frame_arg (struct symbol *sym, struct
frame_info *frame,
       if (print_entry_values == print_entry_values_only
 	  || print_entry_values == print_entry_values_both
 	  || (print_entry_values == print_entry_values_preferred
-	      && (!val || value_optimized_out (val))))
+	      && (!val || !value_entirely_available (val))))
 	entryval = allocate_optimized_out_value (SYMBOL_TYPE (sym));
     }
   if ((print_entry_values == print_entry_values_compact
        || print_entry_values == print_entry_values_if_needed
        || print_entry_values == print_entry_values_preferred)
-      && (!val || value_optimized_out (val)) && entryval != NULL)
+      && (!val || !value_entirely_available (val)) && entryval != NULL)
     {
       val = NULL;
       val_error = NULL;
diff --git a/gdb/value.c b/gdb/value.c
index b9f5709..19ba16c 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -3598,8 +3598,11 @@ value_fetch_lazy (struct value *val)
 			      user_reg_map_regnum_to_name (gdbarch, regnum));
  	  fprintf_unfiltered (gdb_stdlog, "->");
-	  if (value_optimized_out (new_val))
-	    fprintf_unfiltered (gdb_stdlog, " optimized out");
+	  if (!value_entirely_available (new_val))
+	    {
+	      fprintf_unfiltered (gdb_stdlog, " ");
+	      val_print_unavailability_reason (new_val, gdb_stdlog);
+	    }
 	  else
 	    {
 	      int i;


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

* [PATCH 09/12] DWARF value, mark unavailable in bits not bytes.
  2013-08-12 12:15 [RFC 00/12] Merge value optimized_out and unavailable Andrew Burgess
                   ` (7 preceding siblings ...)
  2013-08-12 12:29 ` [PATCH 08/12] Replace some value_optimized_out with value_entirely_available Andrew Burgess
@ 2013-08-12 12:30 ` Andrew Burgess
  2013-08-12 12:31 ` [PATCH 10/12] Merge optimized_out into unavailable vector Andrew Burgess
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Andrew Burgess @ 2013-08-12 12:30 UTC (permalink / raw)
  To: gdb-patches

A later patch revealed that in the dwarf code we're marking
a value unavailable in bytes using a bit based offset and a
byte based size.

Here I switch to using just bits to do the job.

OK to apply?

Thanks,
Andrew

gdb/ChangeLog

2013-08-08  Andrew Burgess <aburgess@broadcom.com>

	* dwarf2loc.c (read_pieced_value): Mark optimized out and
	unavailable in bits not bytes.
	* value.c (mark_value_bits_unavailable): New function.
	(mark_value_bytes_unavailable): Use mark_value_bits_unavailable.
	* value.h (mark_value_bits_unavailable): New function.

diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index bae425a..553f720 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -1694,9 +1694,9 @@ read_pieced_value (struct value *v)
 		    memset (buffer, 0, this_size);
  		    if (optim)
-		      mark_value_bytes_optimized_out (v, offset, this_size);
+		      mark_value_bits_optimized_out (v, offset, this_size_bits);
 		    if (unavail)
-		      mark_value_bytes_unavailable (v, offset, this_size);
+		      mark_value_bits_unavailable (v, offset, this_size_bits);
 		  }
 	      }
 	    else
diff --git a/gdb/value.c b/gdb/value.c
index 19ba16c..c41e6e1 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -572,9 +572,17 @@ insert_into_bit_range_vector (VEC(range_s)
**vectorp, int offset, int length)
 void
 mark_value_bytes_unavailable (struct value *value, int offset, int length)
 {
+  mark_value_bits_unavailable (value, offset * TARGET_CHAR_BIT,
+			       length * TARGET_CHAR_BIT);
+}
+
+void
+mark_value_bits_unavailable (struct value *value, int offset, int length)
+{
   insert_into_bit_range_vector (&value->unavailable,
-				offset * TARGET_CHAR_BIT,
-				length * TARGET_CHAR_BIT);
+				offset,
+				length,
+				bit_range_unavailable);
 }
  void
diff --git a/gdb/value.h b/gdb/value.h
index 81c1cc5..8226a0d 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -449,6 +449,12 @@ extern int value_entirely_unavailable (struct value
*value);
 extern void mark_value_bytes_unavailable (struct value *value,
 					  int offset, int length);
 +/* Mark VALUE's content bits starting at OFFSET and extending for
+   LENGTH bits as unavailable.  */
+
+extern void mark_value_bits_unavailable (struct value *value,
+					 int offset, int length);
+
 /* Set contents of OPTIMIZEDP to nonzero if any part of VALUE is optimized
    out, otherwise set to zero.  Set contents of UNAVAILABLEP to nonzero if
    any part of VALUE is unavailable, otherwise set to zero.  */



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

* [PATCH 10/12] Merge optimized_out into unavailable vector.
  2013-08-12 12:15 [RFC 00/12] Merge value optimized_out and unavailable Andrew Burgess
                   ` (8 preceding siblings ...)
  2013-08-12 12:30 ` [PATCH 09/12] DWARF value, mark unavailable in bits not bytes Andrew Burgess
@ 2013-08-12 12:31 ` Andrew Burgess
  2013-08-12 12:32 ` [PATCH 11/12] Add test mechanism for value " Andrew Burgess
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Andrew Burgess @ 2013-08-12 12:31 UTC (permalink / raw)
  To: gdb-patches

Finally!  Store the optimized out state in to the unavailable vector.
Removes the separate value_optimized_out interface and the last few
uses of it.  Update the code within value.c to just use the unavailable
vector.

The code to maintain the unavailable vector has had to change a bit and
patch #12 adds a new mechanism for unit testing this code, as it's not
required for functionality I split it into a separate patch.

OK to apply?

Thanks,
Andrew

gdb/ChangeLog

2013-08-08  Andrew Burgess  <aburgess@broadcom.com>

	* ada-lang.c (coerce_unspec_val_to_type): Switch to using
	value_contents_copy_raw.
	* findvar.c (read_frame_register_value): Remove special handling
	of optimized out registers.
	* python/py-value.c (valpy_get_is_optimized_out): Update mechanism
	to get optimized out flag.
	* stack.c (read_frame_reg): Remove optimized out check, ensure
	values are not lazy.
	* tui/tui-regs.c (tui_get_register): Remove special check for
	optimized out registers.
	* value.c (enum unavailability_reason): Add.
	(struct range): Add reason field.
	(struct value): Remove optimized_out field.
	(value_bits_available): Remove optimized_out checks, just check
	unavailable vector.
	(value_entirely_available): Likewise.
	(value_entirely_unavailable): Likewise.
	(insert_into_bit_range_vector): Add reason parameter, rewrite to
	deal with reason field.
	(value_availability_flags): Look in unavailability vector for
	answer.
	(allocate_value_lazy): Remove setting of optimized_out.
	(require_not_optimized_out): Remove.
	(require_available): Check both available and optimized out.
	(value_contents_all): Remove call to require_not_optimized_out.
	(value_contents_copy_raw): Maintain unavailability reason.
	(value_contents_copy): Update comment, remove call to
	require_not_optimized_out.
	(value_contents): Remove call to require_not_optimized_out.
	(value_optimized_out): Remove.
	(mark_value_bit_optimized_out): Store optimized out state in
	unavailability vector.
	(value_copy): Remove use of optimized_out.
	(value_primitive_field): Remove special handling of optimized out.
	(value_fetch_lazy): Add assert that lazy values should have no
	unavailable regions.  Remove some special handling for optimized
	out values.
	* value.h (value_optimized_out): Remove.

gdb/testsuite/ChangeLog

2013-08-08  Andrew Burgess  <aburgess@broadcom.com>

	* gdb.dwarf2/dw2-op-out-param.exp: Tests now pass.

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 20a0f02..b0b310d 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -574,10 +574,7 @@ 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));
-	  if (value_optimized_out (val))
-	    mark_value_bytes_optimized_out (result, 0, 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));
diff --git a/gdb/findvar.c b/gdb/findvar.c
index f2bb247..c92915c 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -711,16 +711,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))
-	{
-	  /* If any one of the component registers is marked optimized out
-	     then we just mark the whole composite register as optimized
-	     out.  We could do better, but this style of composite register
-	     passing is not standard, and is only used on a few targets.  */
-	  mark_value_bytes_optimized_out (value, 0, TYPE_LENGTH (value_type
(value)));
-	  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)
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index 0d87219..426ac0c 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -674,7 +674,12 @@ valpy_get_is_optimized_out (PyObject *self, void
*closure)
    TRY_CATCH (except, RETURN_MASK_ALL)
     {
-      opt = value_optimized_out (value);
+      if (!value_entirely_available (value))
+	{
+	  int unavailablep;
+
+	  value_availability_flags (value, &opt, &unavailablep);
+	}
     }
   GDB_PY_HANDLE_EXCEPTION (except);
 diff --git a/gdb/stack.c b/gdb/stack.c
index cec5df5..084ed7a 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -384,9 +384,13 @@ 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_available_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;
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp
b/gdb/testsuite/gdb.dwarf2/dw2-op-out-param.exp
index 5e4ca01..9c60236 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/tui/tui-regs.c b/gdb/tui/tui-regs.c
index bb72340..102beb6 100644
--- a/gdb/tui/tui-regs.c
+++ b/gdb/tui/tui-regs.c
@@ -737,9 +737,8 @@ tui_get_register (struct frame_info *frame,
 	  if (value_lazy (old_val))
 	    value_fetch_lazy (old_val);
 -	  if (value_optimized_out (data->value) != value_optimized_out (old_val)
-	      || !value_available_contents_eq (data->value, 0,
-					       old_val, 0, size))
+	  if (!value_available_contents_eq (data->value, 0,
+					    old_val, 0, size))
 	    *changedp = TRUE;
 	}
 diff --git a/gdb/value.c b/gdb/value.c
index c41e6e1..ec46863 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -63,6 +63,16 @@ struct internal_function
   void *cookie;
 };
 +/* Used to describe the different reasons part of a value
+   might not be available to gdb.  */
+
+enum unavailability_reason
+{
+  /* Leave value 0 as invalid.  */
+  bit_range_unavailable = 1,
+  bit_range_optimized_out = 2
+};
+
 /* Defines an [OFFSET, OFFSET + LENGTH) range.  */
  struct range
@@ -72,6 +79,9 @@ struct range
    /* Length of the range.  */
   int length;
+
+  /* The reason this range is unavailable.  */
+  enum unavailability_reason reason;
 };
  typedef struct range range_s;
@@ -197,10 +207,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 which does not
-     actually exist in the program.  */
-  unsigned int optimized_out : 1;
-
   /* If value is a variable, is it initialized or not.  */
   unsigned int initialized : 1;
 @@ -345,15 +351,7 @@ value_bits_available (const struct value *value,
int offset, int length)
 {
   gdb_assert (!value->lazy);
 -  if (ranges_contain (value->unavailable, offset, length))
-    return 0;
-  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);
+  return (!ranges_contain (value->unavailable, offset, length));
 }
  int
@@ -364,65 +362,80 @@ value_entirely_available (struct value *value)
   if (value->lazy)
     value_fetch_lazy (value);
 -  if (VEC_empty (range_s, value->unavailable)
-      && !value->optimized_out)
-    return 1;
-  return 0;
+  return VEC_empty (range_s, value->unavailable);
 }
  int
 value_entirely_unavailable (struct value *value)
 {
+  struct range *r;
+  int i, expected_offset;
+  struct type *type;
+
   if (value->lazy)
     value_fetch_lazy (value);
 -  /* Check if the unavailable vector covers the entire value.  As we merge
-     entries in the vector, if the entire value is covered then we'll
-     have a single entry starting at offset 0 and length as long as the
-     type.  */
-  if (VEC_length (range_s, value->unavailable) == 1)
+  /* Short cut the common case, no bits are marked unavailable.  */
+  if (VEC_empty (range_s, value->unavailable))
+    return 0;
+
+  expected_offset = 0;
+  for (i = 0; VEC_iterate (range_s, value->unavailable, i, r); i++)
     {
-      const range_s *r;
-      struct type *type;
+      if (r->offset != expected_offset)
+        return 0; /* Not completely optimized out.  */
 -      type = check_typedef (value_type (value));
-      r = VEC_index (range_s, value->unavailable, 0);
-      if (r->offset == 0 && r->length >= TARGET_CHAR_BIT * TYPE_LENGTH
(type))
-	return 1;
+      expected_offset += r->length;
     }
 -  /* At least some of the value contents are NOT covered by the
unavailable
-     vector, fall back to the optimized out heuristic.  */
-  if (!value->optimized_out)
-    return 0;
-  if (value->lval != lval_computed
-      || !value->location.computed.funcs->check_any_valid)
+  /* We've now looked at every entry in the vector of unavailable bits
+     and not found any gaps.  If the EXPECTED_OFFSET is the same as the
+     type length then the whole value is no longer available.  */
+  type = check_typedef (value_type (value));
+  if (expected_offset >= TYPE_LENGTH (type) * TARGET_CHAR_BIT)
     return 1;
-  return !value->location.computed.funcs->check_any_valid (value);
+
+  /* There's a few bits available at the very end of the value.  */
+  return 0;
 }
  /* 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)
+insert_into_bit_range_vector (VEC(range_s) **vectorp,
+			      int offset, int length,
+			      enum unavailability_reason reason)
 {
-  range_s newr;
-  int i;
+  gdb_assert (vectorp != NULL);
+
+  while (length > 0)
+    {
+      int i;
+      range_s newr;
+
+      /* All the ranges of unavailable bits are stored in order of
+	 increasing offset within the value.  Contiguous or overlapping
+	 ranges with the same unavailability reason will be merged, while
+	 ranges with different unavailability reasons that overlap will
+	 result in one of the ranges being truncated to accommodate the
+	 other; no two ranges in the vector may overlap.  */
 -  /* Insert the range sorted.  If there's overlap or the new range
-     would be contiguous with an existing range, merge.  */
+      newr.offset = offset;
+      newr.length = length;
+      newr.reason = reason;
 -  newr.offset = offset;
-  newr.length = length;
+      /* If we only consider the insertion of ranges with the same
+	 unavailability reason then the following logic is used to manges
+	 the ranges in the vector:
 -  /* Do a binary search for the position the given range would be
-     inserted if we only considered the starting OFFSET of ranges.
-     Call that position I.  Since we also have LENGTH to care for
-     (this is a range afterall), we need to check if the _previous_
-     range overlaps the I range.  E.g., calling R the new range:
+	 Do a binary search for the position the given range would be
+	 inserted if we only considered the starting OFFSET of ranges.
+	 Call that position I.  Since we also have LENGTH to care for
+	 (this is a range afterall), we need to check if the _previous_
+	 range overlaps the I range.  E.g., calling R the new range:
 -       #1 - overlaps with previous
+	 #1 - overlaps with previous
  	   R
 	   |-...-|
@@ -431,15 +444,15 @@ insert_into_bit_range_vector (VEC(range_s)
**vectorp, int offset, int length)
  	 I=1
 -     In the case #1 above, the binary search would return `I=1',
-     meaning, this OFFSET should be inserted at position 1, and the
-     current position 1 should be pushed further (and become 2).  But,
-     note that `0' overlaps with R, so we want to merge them.
+	 In the case #1 above, the binary search would return `I=1',
+	 meaning, this OFFSET should be inserted at position 1, and the
+	 current position 1 should be pushed further (and become 2).  But,
+	 note that `0' overlaps with R, so we want to merge them.
 -     A similar consideration needs to be taken if the new range would
-     be contiguous with the previous range:
+	 A similar consideration needs to be taken if the new range would
+	 be contiguous with the previous range:
 -       #2 - contiguous with previous
+	 #2 - contiguous with previous
  	    R
 	    |-...-|
@@ -448,44 +461,44 @@ insert_into_bit_range_vector (VEC(range_s)
**vectorp, int offset, int length)
  	 I=1
 -     If there's no overlap with the previous range, as in:
+	 If there's no overlap with the previous range, as in:
 -       #3 - not overlapping and not contiguous
+	 #3 - not overlapping and not contiguous
 -	       R
-	       |-...-|
-	  |--|         |---|  |------| ... |--|
-	  0            1      2            N
+	      R
+	      |-...-|
+	 |--|         |---|  |------| ... |--|
+	 0            1      2            N
  	 I=1
 -     or if I is 0:
+	 or if I is 0:
 -       #4 - R is the range with lowest offset
+	 #4 - R is the range with lowest offset
 -	  R
+	 R
 	 |-...-|
 	         |--|       |---|  |------| ... |--|
 	         0          1      2            N
  	 I=0
 -     ... we just push the new range to I.
+	 ... we just push the new range to I.
 -     All the 4 cases above need to consider that the new range may
-     also overlap several of the ranges that follow, or that R may be
-     contiguous with the following range, and merge.  E.g.,
+	 All the 4 cases above need to consider that the new range may
+	 also overlap several of the ranges that follow, or that R may be
+	 contiguous with the following range, and merge.  E.g.,
 -       #5 - overlapping following ranges
+	 #5 - overlapping following ranges
 -	  R
+	 R
 	 |------------------------|
 	         |--|       |---|  |------| ... |--|
 	         0          1      2            N
  	 I=0
 -       or:
+	 or:
  	    R
 	    |-------|
@@ -494,79 +507,173 @@ insert_into_bit_range_vector (VEC(range_s)
**vectorp, int offset, int length)
  	 I=1
 -  */
+	 When we consider ranges with different availability reasons the
+	 following additional rules are used.
 -  i = VEC_lower_bound (range_s, *vectorp, &newr, range_lessthan);
-  if (i > 0)
-    {
-      struct range *bef = VEC_index (range_s, *vectorp, i - 1);
+	 Each unavailability reason has a value, see the enum
+	 unavailability_reason.  The higher value reasons have greater
+	 precedence, they are considered a "better" reason to explain why
+	 some bits of a value are not available.
 -      if (ranges_overlap (bef->offset, bef->length, offset, length))
-	{
-	  /* #1 */
-	  ULONGEST l = min (bef->offset, offset);
-	  ULONGEST h = max (bef->offset + bef->length, offset + length);
+	 When two ranges overlap, as in case #1 above, the range with the
+	 lowest precedence is shortened, possibly to the point of
+	 non-existence, to accommodate the range with greater precedence.
 -	  bef->offset = l;
-	  bef->length = h - l;
-	  i--;
-	}
-      else if (offset == bef->offset + bef->length)
-	{
-	  /* #2 */
-	  bef->length += length;
-	  i--;
-	}
-      else
-	{
-	  /* #3 */
-	  VEC_safe_insert (range_s, *vectorp, i, &newr);
-	}
-    }
-  else
-    {
-      /* #4 */
-      VEC_safe_insert (range_s, *vectorp, i, &newr);
-    }
+	 Two contiguous ranges, as in case #2 above will not be merged if
+	 they have different reasons.
 -  /* 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, *vectorp))
-    {
-      struct range *t;
-      struct range *r;
-      int removed = 0;
-      int next = i + 1;
+	 Case #3 and #4 above are unchanged.
 -      /* Get the range we just touched.  */
-      t = VEC_index (range_s, *vectorp, i);
-      removed = 0;
+	 When inserting a range that overlaps many existing ranges, and in
+	 case #5 above, all overlapped ranges with a lower precedence
+	 reason will be deleted, effectively replaced by the new range.  A
+	 range of higher precedence will cause the newly inserted range to
+	 fragment around the existing, higher precedence range.
+      */
 -      i = next;
-      for (; VEC_iterate (range_s, *vectorp, i, r); i++)
-	if (r->offset <= t->offset + t->length)
-	  {
-	    ULONGEST l, h;
+      i = VEC_lower_bound (range_s, *vectorp, &newr, range_lessthan);
+      if (i > 0)
+	{
+	  struct range *bef = VEC_index (range_s, *vectorp, i - 1);
 -	    l = min (t->offset, r->offset);
-	    h = max (t->offset + t->length, r->offset + r->length);
+	  if (ranges_overlap (bef->offset, bef->length, offset, length))
+	    {
+	      /* #1 */
+	      if (bef->reason == reason)
+		{
+		  ULONGEST l = min (bef->offset, offset);
+		  ULONGEST h = max (bef->offset + bef->length, offset + length);
+
+		  bef->offset = l;
+		  bef->length = h - l;
+		  i--;
+		}
+	      else if (bef->reason < reason)
+		{
+		  /* Reduce the previous range.  */
+		  bef->length -= (bef->offset + bef->length) - offset;
+
+		  if (bef->length == 0)
+		    VEC_block_remove (range_s, *vectorp, (i - 1), 1);
+
+		  VEC_safe_insert (range_s, *vectorp, i, &newr);
+		}
+	      else
+		{
+		  /* Reduce the new range.  */
+		  if ((bef->offset + bef->length) >= offset + length)
+		    return; /* We're completely within previous range.  */
 -	    t->offset = l;
-	    t->length = h - l;
+		  newr.offset = bef->offset + bef->length;
+		  newr.length -= (bef->offset + bef->length) - newr.offset;
 -	    removed++;
-	  }
-	else
-	  {
-	    /* If we couldn't merge this one, we won't be able to
-	       merge following ones either, since the ranges are
-	       always sorted by OFFSET.  */
-	    break;
-	  }
+		  VEC_safe_insert (range_s, *vectorp, i, &newr);
+		}
+	    }
+	  else if (offset == bef->offset + bef->length)
+	    {
+	      /* #2 */
+	      if (bef->reason == reason)
+		{
+		  bef->length += length;
+		  i--;
+		}
+	      else
+		VEC_safe_insert (range_s, *vectorp, i, &newr);
+	    }
+	  else
+	    {
+	      /* #3 */
+	      VEC_safe_insert (range_s, *vectorp, i, &newr);
+	    }
+	}
+      else
+	{
+	  /* #4 */
+	  VEC_safe_insert (range_s, *vectorp, i, &newr);
+	}
 -      if (removed != 0)
-	VEC_block_remove (range_s, *vectorp, next, removed);
+      /* 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, *vectorp))
+	{
+	  struct range *t;
+	  struct range *r;
+	  int removed = 0;
+	  int next = i + 1;
+
+	  /* Get the range we just touched.  */
+	  t = VEC_index (range_s, *vectorp, i);
+	  removed = 0;
+
+	  i = next;
+	  for (; VEC_iterate (range_s, *vectorp, i, r); i++)
+	    if (r->offset <= t->offset + t->length
+		&& r->reason <= t->reason)
+	      {
+		ULONGEST h;
+
+		gdb_assert (t->offset <= r->offset);
+
+		if (r->offset + r->length >= t->offset + t->length)
+		  {
+		    if (r->reason == t->reason)
+		      {
+			t->length += ((r->offset + r->length)
+				      - (t->offset + t->length));
+			removed++;
+		      }
+		    else
+		      {
+			r->length = ((r->offset + r->length)
+				     - (t->offset + t->length));
+			r->offset = t->offset + t->length;
+		      }
+		  }
+		else
+		  {
+		    removed++;
+		  }
+	      }
+	    else
+	      {
+		/* If we couldn't merge this one, we won't be able to
+		   merge following ones either, since the ranges are
+		   always sorted by OFFSET.  */
+		break;
+	      }
+
+	  if (removed != 0)
+	    VEC_block_remove (range_s, *vectorp, next, removed);
+
+	  /* If the next range overlaps with the range we just touched, but has
+	     a more important reason then we need to skip over the existing
+	     range and create a new range on the other side.  */
+	  if (r && r->offset <= t->offset + t->length)
+	    {
+	      /* If the next one overlaps its reason should be greater than
+		 ours, otherwise we should have folded it in above.  */
+	      gdb_assert (r->reason > t->reason);
+
+	      if (r->offset + r->length >= t->offset + t->length)
+		{
+		  t->length -= (t->offset + t->length) - r->offset;
+		  return;
+		}
+
+	      offset = r->offset + r->length;
+	      length = (t->offset + t->length) - (r->offset + r->length);
+	      t->length = r->offset - t->offset;
+	    }
+	  else
+	    return; /* All inserted.  */
+	}
+      else
+	return; /* All inserted.  */
     }
+
+  /* Strange, was not expecting to get here.  */
+  internal_error (__FILE__, __LINE__, "error during vector insert");
 }
  void
@@ -590,8 +697,21 @@ value_availability_flags (const struct value *value,
 			  int *optimizedp,
 			  int *unavailablep)
 {
-  *optimizedp = value->optimized_out;
-  *unavailablep = !VEC_empty (range_s, value->unavailable);
+  int i;
+  struct range *r;
+
+  gdb_assert (!value->lazy);
+
+  *optimizedp = *unavailablep = 0;
+
+  /* Look through every entry in the unavailable vector.  */
+  for (i = 0; VEC_iterate (range_s, value->unavailable, i, r); i++)
+    {
+      if (r->reason == bit_range_optimized_out)
+        *optimizedp = 1;
+      else if (r->reason == bit_range_unavailable)
+        *unavailablep = 1;
+    }
 }
  /* Find the first range in RANGES that overlaps the range defined by
@@ -755,7 +875,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;
@@ -967,17 +1086,18 @@ value_actual_type (struct value *value, int
resolve_simple_types,
 }
  static void
-require_not_optimized_out (const struct value *value)
-{
-  if (value->optimized_out)
-    error (_("value has been optimized out"));
-}
-
-static void
 require_available (const struct value *value)
 {
   if (!VEC_empty (range_s, value->unavailable))
-    throw_error (NOT_AVAILABLE_ERROR, _("value is not available"));
+    {
+      int optimizedp, unavailablep;
+
+      value_availability_flags (value, &optimizedp, &unavailablep);
+      if (optimizedp)
+	throw_error (OPTIMIZED_OUT_ERROR, _("value has been optimized out"));
+      else
+	throw_error (NOT_AVAILABLE_ERROR, _("value is not available"));
+    }
 }
  const gdb_byte *
@@ -999,7 +1119,6 @@ const gdb_byte *
 value_contents_all (struct value *value)
 {
   const gdb_byte *result = value_contents_for_printing (value);
-  require_not_optimized_out (value);
   require_available (value);
   return result;
 }
@@ -1052,7 +1171,7 @@ value_contents_copy_raw (struct value *dst, int
dst_offset,
       if (l < h)
 	insert_into_bit_range_vector (&dst->unavailable,
 				      dst_bit_offset + (l - src_bit_offset),
-				      h - l);
+				      h - l, r->reason);
     }
 }
 @@ -1061,8 +1180,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.  */
@@ -1071,8 +1189,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);
 @@ -1107,7 +1223,6 @@ const gdb_byte *
 value_contents (struct value *value)
 {
   const gdb_byte *result = value_contents_writeable (value);
-  require_not_optimized_out (value);
   require_available (value);
   return result;
 }
@@ -1139,17 +1254,6 @@ value_contents_equal (struct value *val1, struct
value *val2)
 		  TYPE_LENGTH (type1)) == 0);
 }
 -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)
-    value_fetch_lazy (value);
-
-  return value->optimized_out;
-}
-
 /* Mark contents of VALUE as optimized out, starting at OFFSET bytes, and
    the following LENGTH bytes.  */
 @@ -1166,12 +1270,12 @@ mark_value_bytes_optimized_out (struct value
*value, int offset, int length)
  void
 mark_value_bits_optimized_out (struct value *value,
-			       int offset ATTRIBUTE_UNUSED,
-			       int length ATTRIBUTE_UNUSED)
+			       int offset,
+			       int length)
 {
-  /* For now just set the optimized out flag to indicate that part of the
-     value is optimized out, this will be expanded upon in later
patches.  */
-  value->optimized_out = 1;  +  insert_into_bit_range_vector
(&value->unavailable,
+				offset, length,
+				bit_range_optimized_out);
 }
  int
@@ -1479,7 +1583,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;
@@ -2730,24 +2833,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))
     {
@@ -2760,37 +2858,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
     {
@@ -2804,9 +2894,7 @@ value_primitive_field (struct value *arg1, int offset,
       /* 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
 	{
@@ -3497,6 +3585,9 @@ value_fetch_lazy (struct value *val)
 {
   gdb_assert (value_lazy (val));
   allocate_value_contents (val);
+  /* Right now a value is either lazy, or fully fetched.  The availability
+     is only established as we try to fetch a value.  */
+  gdb_assert (VEC_empty (range_s, val->unavailable));
   if (value_bitsize (val))
     {
       /* To read a lazy bitfield, read the entire enclosing value.  This
@@ -3581,16 +3672,11 @@ 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))
-	mark_value_bytes_optimized_out (val, 0, TYPE_LENGTH (value_type (val)));
-      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 any unavailability 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)
 	{
@@ -3643,11 +3729,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 8226a0d..d2b7f18 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -318,11 +318,6 @@ extern const gdb_byte *
 extern int value_fetch_lazy (struct value *val);
 extern int value_contents_equal (struct value *val1, struct value *val2);
 -/* If nonzero, this is the value of a variable which does not actually
-   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);
-
 /* Mark VALUE's content bytes starting at OFFSET and extending for
    LENGTH bytes as optimized out.  */



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

* [PATCH 11/12] Add test mechanism for value unavailable vector.
  2013-08-12 12:15 [RFC 00/12] Merge value optimized_out and unavailable Andrew Burgess
                   ` (9 preceding siblings ...)
  2013-08-12 12:31 ` [PATCH 10/12] Merge optimized_out into unavailable vector Andrew Burgess
@ 2013-08-12 12:32 ` Andrew Burgess
  2013-08-12 12:33 ` [PATCH 12/12] Remove old lval check valid functions Andrew Burgess
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Andrew Burgess @ 2013-08-12 12:32 UTC (permalink / raw)
  To: gdb-patches


This patch it optional, and is really just an idea.  More work
might be required.

This adds a unit test like command for the value unavailable vector.
This let me build vectors and see how they were merged and ordered to
help get the code right.

Given that the amount of extra code is pretty small it might be nice to
keep this in.... what do you think?

Some possible changes would be, adding a new "unit-test" sub-command
under which this could be placed, currently the test command lives
under maintenance, but we could have "maintenance unit-test <blah>".
We could also guard the unit tests with a build flag so compiling
them in was optional.

What do folk think?

Cheers,
Andrew

gdb/ChangeLog

2013-08-09  Andrew Burgess  <aburgess@broadcom.com>

	* value.c (vector_test_show): New function.
	(vector_test_parse_range): New function.
	(vector_test_command): New function.
	(_initialize_values): Add value-vector-test command.

gdb/testsuite/ChangeLog

2013-08-09  Andrew Burgess  <aburgess@broadcom.com>

	* gdb.base/value-unavailable-vector.exp: New file.

diff --git a/gdb/testsuite/gdb.base/value-unavailable-vector.exp
b/gdb/testsuite/gdb.base/value-unavailable-vector.exp
new file mode 100644
index 0000000..2a602eb
--- /dev/null
+++ b/gdb/testsuite/gdb.base/value-unavailable-vector.exp
@@ -0,0 +1,32 @@
+# Copyright 2013 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/>.
+
+# Test the behaviour of the gdb value unavailable bits vector.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test "maintenance value-vector-test (2,2,unavailable)
(4,2,unavailable) (2,6,optimized-out)" \
+    "VECTOR: \\(2, 6, optimized-out\\)"
+
+gdb_test "maintenance value-vector-test ( 4, 2,unavailable) ( 8,
2,unavailable) (12, 2,unavailable) ( 2,11,optimized-out)" \
+    "VECTOR: \\(2, 11, optimized-out\\) \\(13, 1, unavailable\\)"
+
+gdb_test "maintenance value-vector-test ( 4, 2,unavailable) ( 8,
2,unavailable) (12, 2,optimized-out) ( 2,13,unavailable)" \
+    "VECTOR: \\(2, 10, unavailable\\) \\(12, 2, optimized-out\\) \\(14,
1, unavailable\\)"
+
+gdb_test "maintenance value-vector-test ( 4, 2,optimized-out) ( 8,
2,optimized-out) (12, 2,optimized-out) ( 2,13,unavailable)" \
+    "VECTOR: \\(2, 2, unavailable\\) \\(4, 2, optimized-out\\) \\(6, 2,
unavailable\\) \\(8, 2, optimized-out\\) \\(10, 2, unavailable\\) \\(12,
2, optimized-out\\) \\(14, 1, unavailable\\)"
diff --git a/gdb/value.c b/gdb/value.c
index ec46863..7151b61 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -43,6 +43,7 @@
 #include "tracepoint.h"
 #include "cp-abi.h"
 #include "user-regs.h"
+#include "cli/cli-utils.h"
  /* Prototypes for exported functions.  */
 @@ -3736,6 +3737,122 @@ value_fetch_lazy (struct value *val)
   return 0;
 }
 +/* Internal debugging function.  Used to display a vector containing the
+   unavailable and optimized out information.  This is currently only used
+   by the maintenance command value-vector-test.  */
+
+static void
+vector_test_show (VEC(range_s) *vector)
+{
+  if (VEC_empty (range_s, vector))
+    printf_filtered ("VECTOR is empty.\n");
+  else
+    {
+      range_s *r;
+      int i;
+
+      printf_filtered ("VECTOR:");
+      for (i = 0; VEC_iterate (range_s, vector, i, r); i++)
+	{
+	  printf_filtered (" (%d, %d, %s)",
+			   r->offset, r->length,
+			   (r->reason == bit_range_optimized_out
+			    ? "optimized-out"
+			    : (r->reason == bit_range_unavailable
+			       ? "unavailable"
+			       : "unknown")));
+
+	  if (i > 0)
+	    {
+	      range_s *prev = VEC_index (range_s, vector, (i - 1));
+
+	      if (prev->offset + prev->length > r->offset)
+		internal_error (__FILE__, __LINE__,
+				"Inconsistent vector configuration: overlap");
+
+	      if (prev->offset + prev->length == r->offset
+		  && prev->reason == r->reason)
+		internal_error (__FILE__, __LINE__,
+				"Inconsistent vector configuration: unmerged");
+	    }
+	}
+      printf_filtered ("\n");
+    }
+}
+
+/* Parse vector entries of the form "(START, LENGTH, TYPE)", where START
+   and LENGTH are numbers, START >= 0 && LENGTH > 0.  The TYPE is a string
+   either "optimized-out", or "unavailable".  */
+
+static char *
+vector_test_parse_range (char *exp, range_s *rng)
+{
+  char *tmp;
+
+  gdb_assert (exp);
+  exp = skip_spaces (exp);
+
+  memset (rng, 0, sizeof (*rng));
+
+  if (*exp != '(')
+    error ("Invalid range specification in `%s'", exp);
+  exp++;
+  /* Find the next "," character (error if non found).	*/
+  tmp = strchr (exp, ',');
+  if (!tmp)
+    error ("Missing `,' in `%s'", exp);
+  *tmp = '\0';
+  rng->offset = parse_and_eval_long (exp);
+  *tmp = ',';
+  exp = skip_spaces (tmp + 1);
+
+  tmp = strchr (exp, ',');
+  if (!tmp)
+    error ("Missing `,' in `%s'", exp);
+  *tmp = '\0';
+  rng->length = parse_and_eval_long (exp);
+  *tmp = ',';
+  exp = skip_spaces (tmp + 1);
+
+  tmp = strchr (exp, ')');
+  if (!tmp)
+    error ("Missing `)' in `%s'", exp);
+  *tmp = '\0';
+  if (strcasecmp (exp, "unavailable") == 0)
+    rng->reason = bit_range_unavailable;
+  else if (strcasecmp (exp, "optimized-out") == 0)
+    rng->reason = bit_range_optimized_out;
+  else
+    error ("unknown reason field in `%s'", exp);
+  *tmp = ')';
+  exp = skip_spaces (tmp + 1);
+
+  return exp;
+}
+
+/* Parse sequence of range descriptions from EXP into a vector then display
+   the resulting vector.  This allows us to test the vector construction
+   algorithm.  */
+
+static void
+vector_test_command (char *exp, int from_tty)
+{
+  VEC(range_s) *vector = NULL;
+
+  (void) from_tty;
+
+  while (exp && *exp != '\0')
+    {
+      range_s r;
+
+      exp = vector_test_parse_range (exp, &r);
+      insert_into_bit_range_vector (&vector, r.offset, r.length, r.reason);
+    }
+
+  vector_test_show (vector);
+  VEC_free (range_s, vector);
+}
+
 void
 _initialize_values (void)
 {
@@ -3768,4 +3885,8 @@ VARIABLE is already initialized."));
   add_prefix_cmd ("function", no_class, function_command, _("\
 Placeholder command for showing help on convenience functions."),
 		  &functionlist, "function ", 0, &cmdlist);
+
+  add_cmd ("value-vector-test", class_maintenance, vector_test_command,
+	   _("Allows for testing of internal gdb unavailability vector."),
+	   &maintenancelist);
 }


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

* [PATCH 12/12] Remove old lval check valid functions.
  2013-08-12 12:15 [RFC 00/12] Merge value optimized_out and unavailable Andrew Burgess
                   ` (10 preceding siblings ...)
  2013-08-12 12:32 ` [PATCH 11/12] Add test mechanism for value " Andrew Burgess
@ 2013-08-12 12:33 ` Andrew Burgess
  2013-08-29 17:21 ` PING: Re: [RFC 00/12] Merge value optimized_out and unavailable Andrew Burgess
  2013-11-29 22:31 ` Pedro Alves
  13 siblings, 0 replies; 27+ messages in thread
From: Andrew Burgess @ 2013-08-12 12:33 UTC (permalink / raw)
  To: gdb-patches


This was the old way we supported checking for partially optimized out
values, this is no longer needed given this patch set.

Just remove unused code.

OK to apply?

Thanks,
Andrew

gdb/ChangeLog

2013-08-11  Andrew Burgess  <aburgess@broadcom.com>

	* dwarf2loc.c (entry_data_value_funcs): Remove check_validity and
	check_any_valid fields.
	(check_pieced_value_validity): Delete.
	(check_pieced_value_invalid): Delete.
	(pieced_value_funcs): Remove check_validity and check_any_valid
	fields.
	* 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.
	* value.h (struct lval_funcs): Remove check_validity and
	check_any_valid fields.

diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 553f720..1ddf841 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -1275,8 +1275,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 */
@@ -1996,22 +1994,6 @@ check_pieced_value_bits (const struct value
*value, int bit_offset,
   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.  */
 @@ -2169,8 +2151,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,
diff --git a/gdb/opencl-lang.c b/gdb/opencl-lang.c
index 4da2c9d..100295b 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_available (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_available (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/value.h b/gdb/value.h
index d2b7f18..c848338 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -180,14 +180,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.  */


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

* PING: Re: [RFC 00/12] Merge value optimized_out and unavailable
  2013-08-12 12:15 [RFC 00/12] Merge value optimized_out and unavailable Andrew Burgess
                   ` (11 preceding siblings ...)
  2013-08-12 12:33 ` [PATCH 12/12] Remove old lval check valid functions Andrew Burgess
@ 2013-08-29 17:21 ` Andrew Burgess
  2013-11-12  9:37   ` Andrew Burgess
  2013-11-29 22:31 ` Pedro Alves
  13 siblings, 1 reply; 27+ messages in thread
From: Andrew Burgess @ 2013-08-29 17:21 UTC (permalink / raw)
  To: gdb-patches

Ping!

Thanks,
Andrew

On 12/08/2013 1:15 PM, Andrew Burgess wrote:
> This patch set merges together how gdb handles values that are
> optimized out and values that are unavailable.
> 
> I think that in most cases gdb should not care why the contents of
> a value are not fetch-able, it is only when we need to display
> something to the user that we should have to figure out was this
> optimized-out or unavailable?
> 
> After this patch set there will be a single unified interface to ask
> if a value is available (either fully, partially, or for a range of
> bit/bytes), this will answer in terms of both optimized out and
> unavailable state.
> 
> A second method will fetch the set of flags for the value
> optimized/unavailable, this will be used for printing the correct string.
> 
> For the implementation I've moved away from the code we currently have
> for supporting partially optimized out values and consolidated on the
> unavailable vector.
> 
> Currently within gdb there are places where we handle optimized out and
> unavailable differently, resulting in different style of output, and there
> are places where we handle one of optimized out or unavailable, but not the
> other.  After this patch set it should (I hope) be much harder for either
> of these situations to arise.
> 
> Looking forward to your feedback.
> 
> Thanks,
> Andrew
> 
> 
> 
> 


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

* Re: PING: Re: [RFC 00/12] Merge value optimized_out and unavailable
  2013-08-29 17:21 ` PING: Re: [RFC 00/12] Merge value optimized_out and unavailable Andrew Burgess
@ 2013-11-12  9:37   ` Andrew Burgess
  0 siblings, 0 replies; 27+ messages in thread
From: Andrew Burgess @ 2013-11-12  9:37 UTC (permalink / raw)
  To: gdb-patches

On 29/08/2013 6:20 PM, Andrew Burgess wrote:
> Ping!

Ping #2!

It's been a while, but I still have interest in merging this work.

I've not checked to see if the patches still apply, if there's anyone
who's willing to review this work then let me know and I'll refresh the
patch series.

I know I'm still a fairly new / small time contributor to gdb, and this
patch set is a refactor, not a bug fix, so I might be getting ahead of
myself trying to have something like this merged :)  That's OK, if you
let me know then I'll not spend any more time on this work.

Thanks,
Andrew

> On 12/08/2013 1:15 PM, Andrew Burgess wrote:
>> This patch set merges together how gdb handles values that are
>> optimized out and values that are unavailable.
>>
>> I think that in most cases gdb should not care why the contents of
>> a value are not fetch-able, it is only when we need to display
>> something to the user that we should have to figure out was this
>> optimized-out or unavailable?
>>
>> After this patch set there will be a single unified interface to ask
>> if a value is available (either fully, partially, or for a range of
>> bit/bytes), this will answer in terms of both optimized out and
>> unavailable state.
>>
>> A second method will fetch the set of flags for the value
>> optimized/unavailable, this will be used for printing the correct string.
>>
>> For the implementation I've moved away from the code we currently have
>> for supporting partially optimized out values and consolidated on the
>> unavailable vector.
>>
>> Currently within gdb there are places where we handle optimized out and
>> unavailable differently, resulting in different style of output, and there
>> are places where we handle one of optimized out or unavailable, but not the
>> other.  After this patch set it should (I hope) be much harder for either
>> of these situations to arise.
>>
>> Looking forward to your feedback.
>>
>> Thanks,
>> Andrew
>>


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

* [PATCH] Print entirely unavailable struct/union values as a single <unavailable>. (Re: [PATCH 06/12] Delete value_bits_valid.)
  2013-08-12 12:27 ` [PATCH 06/12] Delete value_bits_valid Andrew Burgess
@ 2013-11-25 21:41   ` Pedro Alves
  2013-11-26 10:13     ` Andrew Burgess
  0 siblings, 1 reply; 27+ messages in thread
From: Pedro Alves @ 2013-11-25 21:41 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches

On 08/12/2013 01:27 PM, Andrew Burgess wrote:
> There are a few updates required to the expected results of the
> gdb.trace/unavailable.exp test, the output is now more like the output
> you would get if the values were optimized out.  I personally think this
> is a good thing, but if most people disagree then we could change the
> output for optimized out to be unavailable like, I do think the style of
> output should match.  The reason I prefer this style is that a fully
> unavailable structure is displayed with a single "<unavailable>" rather
> than the full structure with lots of unavailables throughout.

I'd like to get this part out of the way; I don't have a problem with
it.

We don't really need the whole series for this though.  Any
objections?

-------
Print entirely unavailable struct/union values as a single <unavailable>.

When printing an entirely optimized out structure/class/union, we
print a single <optimized out> instead of printing <optimized out> for
each field.

This patch makes an entirely unavailable structure/class/union be
likewise displayed with a single "<unavailable>" rather than the whole
object with all fields <unavailable>.

This seems good because this way the user can quickly tell whether the
whole value is unavailable, rather than having to skim all fields.
Consistency with optimized out values also seems to be a good thing to
have.

A new check is added to value_check_printable, where we already do
the equivalent check for entirely optimized out values.

A few updates to gdb.trace/unavailable.exp where required.

Tested on x86_64 Fedora 17, native gdbserver.

gdb/
2013-11-25  Andrew Burgess  <aburgess@broadcom.com>
	    Pedro Alves  <palves@redhat.com>

	* valprint.c (value_check_printable): If the value is entirely
	unavailable, print a single "<unavailable>" instead of printing
	all subfields.

gdb/testsuite/
2013-11-25  Andrew Burgess  <aburgess@broadcom.com>

	* gdb.trace/unavailable.exp(gdb_collect_args_test): Update
	expected results.
	(gdb_collect_locals_test): Likewise.
	(gdb_collect_globals_test): Likewise.

---

 gdb/testsuite/gdb.trace/unavailable.exp |   41 ++++++++++++++-----------------
 gdb/valprint.c                          |    9 +++++++
 2 files changed, 27 insertions(+), 23 deletions(-)

diff --git a/gdb/testsuite/gdb.trace/unavailable.exp b/gdb/testsuite/gdb.trace/unavailable.exp
index ed14798..40319d5 100644
--- a/gdb/testsuite/gdb.trace/unavailable.exp
+++ b/gdb/testsuite/gdb.trace/unavailable.exp
@@ -169,15 +169,14 @@ proc gdb_collect_args_test {} {
 
 	# struct arg as one of several args (near end of list)
 
-	gdb_test "print argstruct" \
-	    " = \{memberc = <unavailable>, memberi = <unavailable>, memberf = <unavailable>, memberd = <unavailable>\}"
+	gdb_test "print argstruct" " = <unavailable>"
 
 	gdb_test "print argstruct.memberc" " = <unavailable>"
 	gdb_test "print argstruct.memberi" " = <unavailable>"
 	gdb_test "print argstruct.memberf" " = <unavailable>"
 	gdb_test "print argstruct.memberd" " = <unavailable>"
 
-	gdb_test "print argarray" " = \\(int \\*\\) <unavailable>"
+	gdb_test "print argarray" " = <unavailable>"
 
 	gdb_test "print &argarray" \
 	    "Can't take address of \"argarray\" which isn't an lvalue\."
@@ -190,7 +189,7 @@ proc gdb_collect_args_test {} {
 	set r "${r}argi = <unavailable>${cr}"
 	set r "${r}argf = <unavailable>${cr}"
 	set r "${r}argd = <unavailable>${cr}"
-	set r "${r}argstruct = {memberc = <unavailable>, memberi = <unavailable>, memberf = <unavailable>, memberd = <unavailable>}${cr}"
+	set r "${r}argstruct = <unavailable>${cr}"
 	set r "${r}argarray = <unavailable>${cr}"
 	gdb_test "info args" "$r" "info args"
 
@@ -237,11 +236,11 @@ proc gdb_collect_locals_test { func msg } {
 	set r ""
 	set r "${r}locf = <unavailable>${cr}"
 	set r "${r}locd = <unavailable>${cr}"
-	set r "${r}locst = {memberc = <unavailable>, memberi = <unavailable>, memberf = <unavailable>, memberd = <unavailable>}${cr}"
-	set r "${r}locar = {<unavailable>, <unavailable>, <unavailable>, <unavailable>}${cr}"
+	set r "${r}locst = <unavailable>${cr}"
+	set r "${r}locar = <unavailable>${cr}"
 	set r "${r}i = <unavailable>${cr}"
 	if { $func == "local_test_func" } {
-	    set r "${r}locdefst = {<No data fields>}${cr}"
+	    set r "${r}locdefst = <unavailable>${cr}"
 	}
 	set r "${r}locc = <unavailable>${cr}"
 	set r "${r}loci = <unavailable>${cr}"
@@ -398,8 +397,7 @@ proc gdb_collect_globals_test { } {
 	gdb_test "print globalstruct.memberf" " = <unavailable>"
 	gdb_test "print globalstruct.memberd" " = <unavailable>"
 
-	gdb_test "print globalstruct" \
-	    " = {memberc = <unavailable>, memberi = <unavailable>, memberf = <unavailable>, memberd = <unavailable>}"
+	gdb_test "print globalstruct" " = <unavailable>"
 
 	gdb_test "print globalp == &globalstruct" \
 	    "value is not available" \
@@ -449,8 +447,7 @@ proc gdb_collect_globals_test { } {
 
 	# Static fields
 
-	gdb_test "print struct_b.static_struct_a" \
-	    " = {a = <unavailable>, b = <unavailable>, array = {<unavailable> <repeats 10000 times>}, ptr = <unavailable>, bitfield = <unavailable>}"
+	gdb_test "print struct_b.static_struct_a" " = <unavailable>"
 
 	# Bitfields
 
@@ -468,8 +465,7 @@ proc gdb_collect_globals_test { } {
 	    "\\$\[0-9\]+ = <unavailable>$cr" \
 	    "referenced integer was not collected (taking address of reference)"
 
-	gdb_test "print *g_structref_p" \
-	    " = {d = <unavailable>, ref = <unavailable>}"
+	gdb_test "print *g_structref_p" " = <unavailable>"
 
 	# Strings
 
@@ -483,7 +479,7 @@ proc gdb_collect_globals_test { } {
 	    "printing constant string through collected pointer"
 
 	gdb_test "print g_string_unavail" \
-	    " = \{<unavailable> <repeats 12 times>\}" \
+	    " = <unavailable>" \
 	    "printing non collected string"
 
 	# Incomplete strings print as an array.
@@ -521,15 +517,15 @@ proc gdb_collect_globals_test { } {
 	# unavailable-ness is propagated.  History values are easy
 	# non-lazy values, so use those.  The first test just sets up for
 	# the second.
-	gdb_test "print g_smallstruct" " = \\{member = <unavailable>\\}"
+	gdb_test "print g_smallstruct" " = <unavailable>"
 	gdb_test "print \$.member" " = <unavailable>"
 
 	# Cast to baseclass, checking the unavailable-ness is propagated.
-	gdb_test "print (small_struct) g_smallstruct_b" " = \\{member = <unavailable>\\}"
+	gdb_test "print (small_struct) g_smallstruct_b" " = <unavailable>"
 
 	# Same cast, but starting from a non-lazy, value.
-	gdb_test "print g_smallstruct_b" " = \\{<small_struct> = \\{member = <unavailable>\\}, <No data fields>\\}"
-	gdb_test "print (small_struct) \$" " = \\{member = <unavailable>\\}"
+	gdb_test "print g_smallstruct_b" " = <unavailable>"
+	gdb_test "print (small_struct) \$" " = <unavailable>"
 
 	gdb_test_no_output "set print object on"
 
@@ -538,11 +534,10 @@ proc gdb_collect_globals_test { } {
 	    # the pointed-to object, to check its run-time type.  Make
 	    # sure that fails gracefully and transparently when the
 	    # pointer itself is unavailable.
-	    gdb_test "print virtualp" " = \\(Virtual \\*\\) <unavailable>"
+	    gdb_test "print virtualp" " = <unavailable>"
 
 	    # no vtable pointer available
-	    gdb_test "print derived_unavail" \
-		" = {<Middle> = <unavailable>, _vptr.Derived = <unavailable>, z = <unavailable>}"
+	    gdb_test "print derived_unavail" " = <unavailable>"
 
 	    # vtable pointer available, but nothing else
 	    gdb_test "print derived_partial" \
@@ -556,11 +551,11 @@ proc gdb_collect_globals_test { } {
 	gdb_test_no_output "set print object off"
 
 	with_test_prefix "print object off" {
-	    gdb_test "print virtualp" " = \\(Virtual \\*\\) <unavailable>"
+	    gdb_test "print virtualp" " = <unavailable>"
 
 	    # no vtable pointer available
 	    gdb_test "print derived_unavail" \
-		" = {<Middle> = <unavailable>, _vptr.Derived = <unavailable>, z = <unavailable>}"
+		" = <unavailable>"
 
 	    # vtable pointer available, but nothing else
 	    gdb_test "print derived_partial" \
diff --git a/gdb/valprint.c b/gdb/valprint.c
index ecc3411..0124934 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -812,6 +812,15 @@ value_check_printable (struct value *val, struct ui_file *stream,
       return 0;
     }
 
+  if (value_entirely_unavailable (val))
+    {
+      if (options->summary && !val_print_scalar_type_p (value_type (val)))
+	fprintf_filtered (stream, "...");
+      else
+	val_print_unavailable (stream);
+      return 0;
+    }
+
   if (TYPE_CODE (value_type (val)) == TYPE_CODE_INTERNAL_FUNCTION)
     {
       fprintf_filtered (stream, _("<internal function %s>"),

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

* Re: [PATCH] Print entirely unavailable struct/union values as a single <unavailable>. (Re: [PATCH 06/12] Delete value_bits_valid.)
  2013-11-25 21:41   ` [PATCH] Print entirely unavailable struct/union values as a single <unavailable>. (Re: [PATCH 06/12] Delete value_bits_valid.) Pedro Alves
@ 2013-11-26 10:13     ` Andrew Burgess
  2013-11-28 20:14       ` Pedro Alves
  0 siblings, 1 reply; 27+ messages in thread
From: Andrew Burgess @ 2013-11-26 10:13 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On 25/11/2013 6:49 PM, Pedro Alves wrote:
> 
> I'd like to get this part out of the way; I don't have a problem with
> it.
> 
> We don't really need the whole series for this though.  Any
> objections?

Sounds reasonable to me.

> gdb/
> 2013-11-25  Andrew Burgess  <aburgess@broadcom.com>
> 	    Pedro Alves  <palves@redhat.com>
> 
> 	* valprint.c (value_check_printable): If the value is entirely
> 	unavailable, print a single "<unavailable>" instead of printing
> 	all subfields.
> 
> gdb/testsuite/
> 2013-11-25  Andrew Burgess  <aburgess@broadcom.com>
> 
> 	* gdb.trace/unavailable.exp(gdb_collect_args_test): Update
> 	expected results.
> 	(gdb_collect_locals_test): Likewise.
> 	(gdb_collect_globals_test): Likewise.

Looks fine to me.

Thanks,
Andrew


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

* Re: [PATCH 03/12] Mark optimized out values as non-lazy.
  2013-08-12 12:20 ` [PATCH 03/12] Mark optimized out values as non-lazy Andrew Burgess
@ 2013-11-26 16:38   ` Pedro Alves
  2013-11-26 19:19     ` Andrew Burgess
  0 siblings, 1 reply; 27+ messages in thread
From: Pedro Alves @ 2013-11-26 16:38 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches

On 08/12/2013 01:20 PM, Andrew Burgess wrote:
> This is a re-posting of this patch:
>   http://sourceware.org/ml/gdb-patches/2013-07/msg00058.html
> 
> The patch was never rejected, it just ran out of steam.  Pedro noticed
> that we could go beyond this patch and do more, even releasing the
> value contents when we spot values are fully optimized out.  I agree,
> but believe that is a separate idea, that can always be added later,
> for this case we've not even allocated any value contents yet.
> 
> OK to apply?

OK.  I've pushed it (with you as author), with the commit log
below.

Thanks.

-----------
From: Andrew Burgess <aburgess@broadcom.com>

Mark entirely optimized out value as non-lazy.

If a value is entirely optimized out, then there's nothing for
value_fetch_lazy to fetch.  Sequences like:

 if (value_lazy (retval))
   value_fetch_lazy (retval);

End up allocating the value contents buffer, wasting memory, for no
use.

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

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

 gdb/ChangeLog |    4 ++++
 gdb/value.c   |    2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 7e28436..c144565 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,7 @@
+2013-11-26  Andrew Burgess  <aburgess@broadcom.com>
+
+	* value.c (allocate_optimized_out_value): Mark value as non-lazy.
+
 2013-11-26  Tom Tromey  <tromey@redhat.com>
 
 	* dwarf2-frame.c (dwarf2_frame_cache): Revert patch from
diff --git a/gdb/value.c b/gdb/value.c
index da7778f..8052f52 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -768,7 +768,7 @@ 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);
   return retval;
 }
 

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

* Re: [PATCH 03/12] Mark optimized out values as non-lazy.
  2013-11-26 16:38   ` Pedro Alves
@ 2013-11-26 19:19     ` Andrew Burgess
  0 siblings, 0 replies; 27+ messages in thread
From: Andrew Burgess @ 2013-11-26 19:19 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On 26/11/2013 4:28 PM, Pedro Alves wrote:
> On 08/12/2013 01:20 PM, Andrew Burgess wrote:
>> This is a re-posting of this patch:
>>   http://sourceware.org/ml/gdb-patches/2013-07/msg00058.html
>>
>> The patch was never rejected, it just ran out of steam.  Pedro noticed
>> that we could go beyond this patch and do more, even releasing the
>> value contents when we spot values are fully optimized out.  I agree,
>> but believe that is a separate idea, that can always be added later,
>> for this case we've not even allocated any value contents yet.
>>
>> OK to apply?
> 
> OK.  I've pushed it (with you as author), with the commit log
> below.
> 

Thank you.

Andrew


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

* [COMMITTED PATCH 0/2] "set debug frame 1" and not saved registers (was: Re: [PATCH 08/12] Replace some value_optimized_out with value_entirely_available)
  2013-08-12 12:29 ` [PATCH 08/12] Replace some value_optimized_out with value_entirely_available Andrew Burgess
@ 2013-11-27 17:52   ` Pedro Alves
  2013-11-27 18:14     ` [PATCH 1/2] Make "set debug frame 1" use the standard print routine for optimized out values Pedro Alves
  2013-11-27 18:35     ` [PATCH 2/2] Make "set debug frame 1" output print <not saved> instead of <optimized out> Pedro Alves
  0 siblings, 2 replies; 27+ messages in thread
From: Pedro Alves @ 2013-11-27 17:52 UTC (permalink / raw)
  To: gdb-patches

On 08/12/2013 01:29 PM, Andrew Burgess wrote:
> @@ -1035,8 +1036,11 @@ frame_unwind_register_value (struct frame_info
> *frame, int regnum)
>    if (frame_debug)
>      {
>        fprintf_unfiltered (gdb_stdlog, "->");
> -      if (value_optimized_out (value))
> -	fprintf_unfiltered (gdb_stdlog, " optimized out");
> +      if (!value_entirely_available (value))
> +	{
> +	  fprintf_unfiltered (gdb_stdlog, " ");
> +	  val_print_unavailability_reason (value, gdb_stdlog);
> +	}
>        else

I'm splitting this output change into its separate patch,
and then applying a follow up.

Tested on x86_64 Fedora 17.

Thanks.

Andrew Burgess (1):
  Make "set debug frame 1" use the standard print routine for optimized
    out values.

Pedro Alves (1):
  Make "set debug frame 1" output print <not saved> instead of
    <optimized out>.

 gdb/frame-unwind.c | 8 +++++---
 gdb/frame.c        | 6 +++++-
 gdb/value.c        | 5 ++++-
 3 files changed, 14 insertions(+), 5 deletions(-)

-- 
1.7.11.7

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

* [PATCH 1/2] Make "set debug frame 1" use the standard print routine for optimized out values.
  2013-11-27 17:52   ` [COMMITTED PATCH 0/2] "set debug frame 1" and not saved registers (was: Re: [PATCH 08/12] Replace some value_optimized_out with value_entirely_available) Pedro Alves
@ 2013-11-27 18:14     ` Pedro Alves
  2013-11-27 18:35     ` [PATCH 2/2] Make "set debug frame 1" output print <not saved> instead of <optimized out> Pedro Alves
  1 sibling, 0 replies; 27+ messages in thread
From: Pedro Alves @ 2013-11-27 18:14 UTC (permalink / raw)
  To: gdb-patches; +Cc: Andrew Burgess

From: Andrew Burgess <aburgess@broadcom.com>

 ...
 - { frame_unwind_register_value (frame=0,regnum=7(rsp),...) -> optimized out }
 + { frame_unwind_register_value (frame=0,regnum=7(rsp),...) -> <optimized out> }
 ...

Tested on x86_64 Fedora 17.

2013-11-27  Andrew Burgess  <aburgess@broadcom.com>

	* frame.c: Include "valprint.h".
	(frame_unwind_register_value): Use value_optimized_out.
	* value.c (value_fetch_lazy): Likewise.
---
 gdb/frame.c | 6 +++++-
 gdb/value.c | 5 ++++-
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/gdb/frame.c b/gdb/frame.c
index f77ce75..4e6e06c 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -44,6 +44,7 @@
 #include "inline-frame.h"
 #include "tracepoint.h"
 #include "hashtab.h"
+#include "valprint.h"
 
 static struct frame_info *get_prev_frame_1 (struct frame_info *this_frame);
 static struct frame_info *get_prev_frame_raw (struct frame_info *this_frame);
@@ -1047,7 +1048,10 @@ frame_unwind_register_value (struct frame_info *frame, int regnum)
     {
       fprintf_unfiltered (gdb_stdlog, "->");
       if (value_optimized_out (value))
-	fprintf_unfiltered (gdb_stdlog, " optimized out");
+	{
+	  fprintf_unfiltered (gdb_stdlog, " ");
+	  val_print_optimized_out (value, gdb_stdlog);
+	}
       else
 	{
 	  if (VALUE_LVAL (value) == lval_register)
diff --git a/gdb/value.c b/gdb/value.c
index 8052f52..a64e7e1 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -3572,7 +3572,10 @@ value_fetch_lazy (struct value *val)
 
 	  fprintf_unfiltered (gdb_stdlog, "->");
 	  if (value_optimized_out (new_val))
-	    fprintf_unfiltered (gdb_stdlog, " optimized out");
+	    {
+	      fprintf_unfiltered (gdb_stdlog, " ");
+	      val_print_optimized_out (new_val, gdb_stdlog);
+	    }
 	  else
 	    {
 	      int i;
-- 
1.7.11.7

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

* [PATCH 2/2] Make "set debug frame 1" output print <not saved> instead of <optimized out>.
  2013-11-27 17:52   ` [COMMITTED PATCH 0/2] "set debug frame 1" and not saved registers (was: Re: [PATCH 08/12] Replace some value_optimized_out with value_entirely_available) Pedro Alves
  2013-11-27 18:14     ` [PATCH 1/2] Make "set debug frame 1" use the standard print routine for optimized out values Pedro Alves
@ 2013-11-27 18:35     ` Pedro Alves
  2013-11-27 18:41       ` Pedro Alves
  1 sibling, 1 reply; 27+ messages in thread
From: Pedro Alves @ 2013-11-27 18:35 UTC (permalink / raw)
  To: gdb-patches

"set debug frame 1" is printing "<optimized out>" for not saved
registers.  That's because the unwinders are returning optimized out
not_lval values instead of optimized out lval_register values.  "<not
saved>" is how val_print_optimized_out prints lval_register values.

  ...
  - { frame_unwind_register_value (frame=0,regnum=7(rsp),...) -> <optimized out> }
  + { frame_unwind_register_value (frame=0,regnum=7(rsp),...) -> <not saved> }
  ...

Tested on x86_64 Fedora 17.

2013-11-27  Pedro Alves  <palves@redhat.com>

	* frame-unwind.c (frame_unwind_got_optimized): Return
	an lval_register value instead of a not_lval value.
---
 gdb/frame-unwind.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c
index ce2f6da..68879f3 100644
--- a/gdb/frame-unwind.c
+++ b/gdb/frame-unwind.c
@@ -161,10 +161,12 @@ default_frame_unwind_stop_reason (struct frame_info *this_frame,
 struct value *
 frame_unwind_got_optimized (struct frame_info *frame, int regnum)
 {
-  struct gdbarch *gdbarch = frame_unwind_arch (frame);
-  struct type *reg_type = register_type (gdbarch, regnum);
+  struct value *val;
 
-  return allocate_optimized_out_value (reg_type);
+  val = value_of_register_lazy (frame, regnum);
+  set_value_lazy (val, 0);
+  set_value_optimized_out (val, 1);
+  return val;
 }
 
 /* Return a value which indicates that FRAME copied REGNUM into
-- 
1.7.11.7

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

* Re: [PATCH 2/2] Make "set debug frame 1" output print <not saved> instead of <optimized out>.
  2013-11-27 18:35     ` [PATCH 2/2] Make "set debug frame 1" output print <not saved> instead of <optimized out> Pedro Alves
@ 2013-11-27 18:41       ` Pedro Alves
  2013-11-27 18:53         ` [pushed] Fix type of not saved registers. (was: Re: [PATCH 2/2] Make "set debug frame 1" output print <not saved> instead of <optimized out>.) Pedro Alves
  0 siblings, 1 reply; 27+ messages in thread
From: Pedro Alves @ 2013-11-27 18:41 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On 11/27/2013 05:52 PM, Pedro Alves wrote:
>  struct value *
>  frame_unwind_got_optimized (struct frame_info *frame, int regnum)
>  {
> -  struct gdbarch *gdbarch = frame_unwind_arch (frame);
> -  struct type *reg_type = register_type (gdbarch, regnum);

Oh, wait.  Given multi-arch, the arch of FRAME might be different
from the prev frame's arch, and therefore the type of register
REGNUM should be retrieved from the unwound arch.

> +  struct value *val;
>  
> -  return allocate_optimized_out_value (reg_type);
> +  val = value_of_register_lazy (frame, regnum);

This is using the type of REGNUM in FRAME.  I'll fix this
in a moment...

> +  set_value_lazy (val, 0);
> +  set_value_optimized_out (val, 1);
> +  return val;

-- 
Pedro Alves

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

* [pushed] Fix type of not saved registers.  (was: Re: [PATCH 2/2] Make "set debug frame 1" output print <not saved> instead of <optimized out>.)
  2013-11-27 18:41       ` Pedro Alves
@ 2013-11-27 18:53         ` Pedro Alves
  0 siblings, 0 replies; 27+ messages in thread
From: Pedro Alves @ 2013-11-27 18:53 UTC (permalink / raw)
  To: gdb-patches

On 11/27/2013 06:13 PM, Pedro Alves wrote:
> On 11/27/2013 05:52 PM, Pedro Alves wrote:
>>  struct value *
>>  frame_unwind_got_optimized (struct frame_info *frame, int regnum)
>>  {
>> -  struct gdbarch *gdbarch = frame_unwind_arch (frame);
>> -  struct type *reg_type = register_type (gdbarch, regnum);
> 
> Oh, wait.  Given multi-arch, the arch of FRAME might be different
> from the prev frame's arch, and therefore the type of register
> REGNUM should be retrieved from the unwound arch.
> 
>> +  struct value *val;
>>  
>> -  return allocate_optimized_out_value (reg_type);
>> +  val = value_of_register_lazy (frame, regnum);
> 
> This is using the type of REGNUM in FRAME.  I'll fix this
> in a moment...

Done.

-----------
Fix type of not saved registers.

value_of_register_lazy uses the type of REGNUM in FRAME, but given
multi-arch, the arch of FRAME might be different from the previous
frame's arch, and therefore the type of register REGNUM should be
retrieved from the unwound arch.  This used to be correct before the
previous change.

Tested on x86_64 Fedora 17.

gdb/
2013-11-27  Pedro Alves  <palves@redhat.com>

	* frame-unwind.c (frame_unwind_got_optimized): Use the type of the
	register in the previous frame's arch.
---

 gdb/ChangeLog      |    5 +++++
 gdb/frame-unwind.c |    9 ++++++++-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a2da98f..00369e9 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,10 @@
 2013-11-27  Pedro Alves  <palves@redhat.com>
 
+	* frame-unwind.c (frame_unwind_got_optimized): Use the type of the
+	register in the previous frame's arch.
+
+2013-11-27  Pedro Alves  <palves@redhat.com>
+
 	* frame-unwind.c (frame_unwind_got_optimized): Return
 	an lval_register value instead of a not_lval value.
 
diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c
index 68879f3..a731b33 100644
--- a/gdb/frame-unwind.c
+++ b/gdb/frame-unwind.c
@@ -161,11 +161,18 @@ default_frame_unwind_stop_reason (struct frame_info *this_frame,
 struct value *
 frame_unwind_got_optimized (struct frame_info *frame, int regnum)
 {
+  struct gdbarch *gdbarch = frame_unwind_arch (frame);
+  struct type *type = register_type (gdbarch, regnum);
   struct value *val;
 
-  val = value_of_register_lazy (frame, regnum);
+  /* Return an lval_register value, so that we print it as
+     "<not saved>".  */
+  val = allocate_value_lazy (type);
   set_value_lazy (val, 0);
   set_value_optimized_out (val, 1);
+  VALUE_LVAL (val) = lval_register;
+  VALUE_REGNUM (val) = regnum;
+  VALUE_FRAME_ID (val) = get_frame_id (frame);
   return val;
 }
 

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

* Re: [PATCH] Print entirely unavailable struct/union values as a single <unavailable>. (Re: [PATCH 06/12] Delete value_bits_valid.)
  2013-11-26 10:13     ` Andrew Burgess
@ 2013-11-28 20:14       ` Pedro Alves
  0 siblings, 0 replies; 27+ messages in thread
From: Pedro Alves @ 2013-11-28 20:14 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches

On 11/26/2013 09:39 AM, Andrew Burgess wrote:
> On 25/11/2013 6:49 PM, Pedro Alves wrote:
>>
>> I'd like to get this part out of the way; I don't have a problem with
>> it.
>>
>> We don't really need the whole series for this though.  Any
>> objections?
> 
> Sounds reasonable to me.

Thanks.  Now pushed.

-- 
Pedro Alves

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

* Re: [RFC 00/12] Merge value optimized_out and unavailable
  2013-08-12 12:15 [RFC 00/12] Merge value optimized_out and unavailable Andrew Burgess
                   ` (12 preceding siblings ...)
  2013-08-29 17:21 ` PING: Re: [RFC 00/12] Merge value optimized_out and unavailable Andrew Burgess
@ 2013-11-29 22:31 ` Pedro Alves
  2013-12-04 14:54   ` Andrew Burgess
  13 siblings, 1 reply; 27+ messages in thread
From: Pedro Alves @ 2013-11-29 22:31 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: gdb-patches

On 08/12/2013 01:15 PM, Andrew Burgess wrote:
> This patch set merges together how gdb handles values that are
> optimized out and values that are unavailable.
> 
> I think that in most cases gdb should not care why the contents of
> a value are not fetch-able, it is only when we need to display
> something to the user that we should have to figure out was this
> optimized-out or unavailable?

Kind of, but not quite.  Going through the series, and thinking about
it a lot, I'm not convinced the parts that handle unavailable and
optimized out errors the same way are right.  The frame machinery
handles unavailable registers especially, with the _if_available
wrappers, because it's possible to have a traceframe with no
collected PC, or trimmed core file with no registers info,
and consequently, a frame #0 with an <unavailable> PC / function.
I'm not seeing how it's possible to end up with a frame_info that
has an optimized out PC.  If unwinding the PC results in a not
saved PC, we use that as indication that we've reached the
outermost frame, so we stop the backtrace before that could happen.

So all the _if_available functions that _don't_ try to unwind the
prev frame (which are most, except frame_unwind_caller_pc_if_available),
shouldn't ever throw an optimized error for PC/function.

Since frame_unwind_caller_pc_if_available is the only
_if_available wrapper that unwinds, that's the case where the
caller would need to likewise handle optimized out / not saved
PCs.  But then, after the series, "info frame", the only caller
of frame_unwind_caller_pc_if_available, ends printing <unavailable>
instead of <not saved>, because these different errors passed
through the same sieve hole:

  if (frame_unwind_caller_pc_if_available (fi, &caller_pc))
    fputs_filtered (paddress (gdbarch, caller_pc), gdb_stdout);
  else
    fputs_filtered ("<unavailable>", gdb_stdout);

(gdb) info frame
Stack level 2, frame at 0x0:
 rip = 0x323d4f168d in clone (../sysdeps/unix/sysv/linux/x86_64/clone.S:115); saved rip <unavailable>
 Outermost frame: outermost
 caller of frame at 0x7ffff7fcafc0
 source language asm.
 Arglist at 0x7ffff7fcafb8, args:
 Locals at 0x7ffff7fcafb8, Previous frame's sp is 0x7ffff7fcafc8
(gdb)

Another place showing the issue with "merging" the errors
is here:

 static CORE_ADDR
 frame_unwind_pc (struct frame_info *this_frame)
 {
   CORE_ADDR pc;

   if (!frame_unwind_pc_if_available (this_frame, &pc))
     throw_error (NOT_AVAILABLE_ERROR, _("PC not available"));
   else
     return pc;
 }

This throws the wrong error with the wrong string if
frame_unwind_pc_if_available returned false due to
OPTIMIZED_OUT_ERROR.

So for that part of the series, I'd rather not go around and
sprinkle the is_unavailable_error wrapper function wherever
we use catch NOT_AVAILABLE_ERROR, but instead handle
OPTIMIZED_OUT_ERROR as needed.

I've posted a mini series that fixes the "info frame" case
above:

  https://sourceware.org/ml/gdb-patches/2013-11/msg00943.html

(I had actually tried to fix that before by making
frame_unwind_caller_pc return struct value, and gave up as that
grew quite messy quick.  Making use of your new OPTIMIZED_OUT_ERROR
ends up much simpler.)

> After this patch set there will be a single unified interface to ask
> if a value is available (either fully, partially, or for a range of
> bit/bytes), this will answer in terms of both optimized out and
> unavailable state.

On terminology: I'd much rather not overload the "available/unavailable"
words for this. It'll end up confusing, like "This value is
not available, because it was unavailable?  No, because it
was optimized out.".  Etc.

Thanks,
-- 
Pedro Alves

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

* Re: [RFC 00/12] Merge value optimized_out and unavailable
  2013-11-29 22:31 ` Pedro Alves
@ 2013-12-04 14:54   ` Andrew Burgess
  0 siblings, 0 replies; 27+ messages in thread
From: Andrew Burgess @ 2013-12-04 14:54 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On 29/11/2013 8:20 PM, Pedro Alves wrote:
> On 08/12/2013 01:15 PM, Andrew Burgess wrote:
>> This patch set merges together how gdb handles values that are
>> optimized out and values that are unavailable.

Thanks for taking the time to review these patches. I'll go through your
comments and see if there's a way that this could be moved forward, I
already have one small patch to post that can be split from this series.

>> After this patch set there will be a single unified interface to ask
>> if a value is available (either fully, partially, or for a range of
>> bit/bytes), this will answer in terms of both optimized out and
>> unavailable state.
> 
> On terminology: I'd much rather not overload the "available/unavailable"
> words for this. It'll end up confusing, like "This value is
> not available, because it was unavailable?  No, because it
> was optimized out.".  Etc.

I agree, and I should have mentioned this.  To avoid excessive churn I
had not tried to resolve this issue, but the way I currently see it we
have two current reasons for unavailability, "optimized-out" and
"not-collected" (not-collected covers not collected by a trace frame, or
not collected in a core file).

For a consistent user experience we'd probably always print
"optimized-out" or "unavailable" to the user, but within gdb I had
imagined transitioning to an API that reflected that above naming scheme.

Thanks,
Andrew

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

end of thread, other threads:[~2013-12-04 14:54 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-08-12 12:15 [RFC 00/12] Merge value optimized_out and unavailable Andrew Burgess
2013-08-12 12:16 ` [PATCH 01/12] Introduce is_unavailable_error Andrew Burgess
2013-08-12 12:18 ` [PATCH 02/12]: Remove set_value_optimized_out Andrew Burgess
2013-08-12 12:20 ` [PATCH 03/12] Mark optimized out values as non-lazy Andrew Burgess
2013-11-26 16:38   ` Pedro Alves
2013-11-26 19:19     ` Andrew Burgess
2013-08-12 12:22 ` [PATCH 04/12] Introduce OPTIMIZED_OUT_ERROR Andrew Burgess
2013-08-12 12:24 ` [PATCH 05/12] Convert the unavailable to be bit based Andrew Burgess
2013-08-12 12:27 ` [PATCH 06/12] Delete value_bits_valid Andrew Burgess
2013-11-25 21:41   ` [PATCH] Print entirely unavailable struct/union values as a single <unavailable>. (Re: [PATCH 06/12] Delete value_bits_valid.) Pedro Alves
2013-11-26 10:13     ` Andrew Burgess
2013-11-28 20:14       ` Pedro Alves
2013-08-12 12:28 ` [PATCH 07/12] Generic print unavailable or optimized out function Andrew Burgess
2013-08-12 12:29 ` [PATCH 08/12] Replace some value_optimized_out with value_entirely_available Andrew Burgess
2013-11-27 17:52   ` [COMMITTED PATCH 0/2] "set debug frame 1" and not saved registers (was: Re: [PATCH 08/12] Replace some value_optimized_out with value_entirely_available) Pedro Alves
2013-11-27 18:14     ` [PATCH 1/2] Make "set debug frame 1" use the standard print routine for optimized out values Pedro Alves
2013-11-27 18:35     ` [PATCH 2/2] Make "set debug frame 1" output print <not saved> instead of <optimized out> Pedro Alves
2013-11-27 18:41       ` Pedro Alves
2013-11-27 18:53         ` [pushed] Fix type of not saved registers. (was: Re: [PATCH 2/2] Make "set debug frame 1" output print <not saved> instead of <optimized out>.) Pedro Alves
2013-08-12 12:30 ` [PATCH 09/12] DWARF value, mark unavailable in bits not bytes Andrew Burgess
2013-08-12 12:31 ` [PATCH 10/12] Merge optimized_out into unavailable vector Andrew Burgess
2013-08-12 12:32 ` [PATCH 11/12] Add test mechanism for value " Andrew Burgess
2013-08-12 12:33 ` [PATCH 12/12] Remove old lval check valid functions Andrew Burgess
2013-08-29 17:21 ` PING: Re: [RFC 00/12] Merge value optimized_out and unavailable Andrew Burgess
2013-11-12  9:37   ` Andrew Burgess
2013-11-29 22:31 ` Pedro Alves
2013-12-04 14:54   ` Andrew Burgess

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).