This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Fix frozen variable objects laziness


I've just noticed that gdb mainline has grown some
subtle bugs in the handling of frozen variable objects.

1. The install_new_value always calls value_get_print_value,
which fetches the value. It means that it's not possible
to have read-sensitive variable object that are read only
on user request.

2. In the case where a value for variable object is not
yet fetched, and we -var-update it, we enter install_new_value
and go via this path:

  if (initial && changeable)
	...
  else if (changeable)
    {
      if (var->updated)
	{
	  .....
	}
      else 
	{
	  if (var->not_fetched && value_lazy (var->value))
	    {
	      /* This is a frozen varobj and the value was never read.
		 Presumably, UI shows some "never read" indicator.
		 Now that we've fetched the real value, we need to report
		 this varobj as changed so that UI can show the real
		 value.  */
	      changed = 1;
	    }

And the var->print_value is never updated.

The attached patch, fixes that by:

1. Updating var->print_value in a single place at the end of
install_new_value.

2. Not getting print_value at all for lazy value.

The attached patch fixes that.  Approved by Daniel Jacobowitz and
checked in.

- Volodya


Index: ChangeLog
===================================================================
RCS file: /cvs/src/src/gdb/ChangeLog,v
retrieving revision 1.8719
diff -u -p -r1.8719 ChangeLog
--- ChangeLog	26 Sep 2007 18:44:55 -0000	1.8719
+++ ChangeLog	27 Sep 2007 18:03:03 -0000
@@ -1,5 +1,12 @@
 2007-09-26  Vladimir Prus  <vladimir@codesourcery.com>
 
+	* varobj.c (install_new_value): Don't
+	call value_get_print_value when a value is
+	lazy.  Update the print_value member in a
+	single place.
+
+2007-09-26  Vladimir Prus  <vladimir@codesourcery.com>
+
 	* breakpoint.c (create_breakpoint): Set
 	condition on each location, not on the first
 	location of breakpoint.
Index: varobj.c
===================================================================
RCS file: /cvs/src/src/gdb/varobj.c,v
retrieving revision 1.95
diff -u -p -r1.95 varobj.c
--- varobj.c	31 Aug 2007 19:01:17 -0000	1.95
+++ varobj.c	27 Sep 2007 18:03:04 -0000
@@ -985,6 +985,7 @@ install_new_value (struct varobj *var, s
   int need_to_fetch;
   int changed = 0;
   int intentionally_not_fetched = 0;
+  char *print_value = NULL;
 
   /* We need to know the varobj's type to decide if the value should
      be fetched or not.  C++ fake children (public/protected/private) don't have
@@ -1042,12 +1043,17 @@ install_new_value (struct varobj *var, s
 	}
     }
 
+  /* Below, we'll be comparing string rendering of old and new
+     values.  Don't get string rendering if the value is
+     lazy -- if it is, the code above has decided that the value
+     should not be fetched.  */
+  if (value && !value_lazy (value))
+      print_value = value_get_print_value (value, var->format);
+
   /* If the type is changeable, compare the old and the new values.
      If this is the initial assignment, we don't have any old value
      to compare with.  */
-  if (initial && changeable)
-    var->print_value = value_get_print_value (value, var->format);
-  else if (changeable)
+  if (!initial && changeable)
     {
       /* If the value of the varobj was changed by -var-set-value, then the 
 	 value in the varobj and in the target is the same.  However, that value
@@ -1055,8 +1061,6 @@ install_new_value (struct varobj *var, s
 	 -var-update. So need to the varobj as changed.  */
       if (var->updated)
 	{
-	  xfree (var->print_value);
-	  var->print_value = value_get_print_value (value, var->format);
 	  changed = 1;
 	}
       else 
@@ -1077,26 +1081,16 @@ install_new_value (struct varobj *var, s
 	    ;
 	  else if (var->value == NULL || value == NULL)
 	    {
-	      xfree (var->print_value);
-	      var->print_value = value_get_print_value (value, var->format);
 	      changed = 1;
 	    }
 	  else
 	    {
-	      char *print_value;
 	      gdb_assert (!value_lazy (var->value));
 	      gdb_assert (!value_lazy (value));
-	      print_value = value_get_print_value (value, var->format);
 
 	      gdb_assert (var->print_value != NULL && print_value != NULL);
 	      if (strcmp (var->print_value, print_value) != 0)
-		{
-		  xfree (var->print_value);
-		  var->print_value = print_value;
-		  changed = 1;
-		}
-	      else
-		xfree (print_value);
+		changed = 1;
 	    }
 	}
     }
@@ -1105,6 +1099,9 @@ install_new_value (struct varobj *var, s
   if (var->value != NULL && var->value != value)
     value_free (var->value);
   var->value = value;
+  if (var->print_value)
+    xfree (var->print_value);
+  var->print_value = print_value;
   if (value && value_lazy (value) && intentionally_not_fetched)
     var->not_fetched = 1;
   else

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]