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]

RFA: add python exception subclasses (Was: gdb with python support still get crash on showing uninitialized local variables)


>>>>> ">" == Asm gmail <asmwarrior@gmail.com> writes:

This needs a doc review.

>>> stdStrRef =
>>> s = std::stack wrapping: std::deque with -521291805 elements = {<error
>>> reading variable s (Cannot access memory at address 0x80)>

Tom> I am working on a fix for this.

Tom> Currently all gdb exceptions are convert to a Python RuntimeError.  But,
Tom> I think we should differentiate a little more.  In particular, I think a
Tom> gdb MEMORY_ERROR should be a separate class, and should be handled
Tom> specially by the pretty-printing code (basically by omitting the stack
Tom> trace).

This patch implements this idea.  It adds some new subclasses of
RuntimeError, including one specifically for MEMORY_ERROR.  Then it
arranges for the memory error exception to be treated specially by the
pretty-printing code.

Built and regtested on x86-64 (compile farm).
Some new test cases are included.

asmwarrior, it would be helpful if you could try this out.

Ok?

Tom

2010-10-19  Tom Tromey  <tromey@redhat.com>

	* varobj.c (value_get_print_value): Rearrange.  Pass stream to
	apply_varobj_pretty_printer.
	* c-lang.c: Include exceptions.h.
	(c_get_string): Throw MEMORY_ERROR when appropriate.
	* python/py-prettyprint.c (enum string_repr_result): New.
	(print_stack_unless_memory_error): New function.
	(print_string_repr): Change return type.  Use
	print_stack_unless_memory_error.
	(print_children): Use print_stack_unless_memory_error.
	(apply_val_pretty_printer): Update.  Don't print children if
	string representation threw an exception.
	(apply_varobj_pretty_printer): Add 'stream' argument.  Use
	print_stack_unless_memory_error.
	* python/python.c (gdbpy_gdb_error, gdbpy_gdb_memory_error): New
	globals.
	(_initialize_python): Initialize them.
	* python/python-internal.h (GDB_PY_HANDLE_EXCEPTION): Use
	gdbpy_convert_exception.
	(GDB_PY_SET_HANDLE_EXCEPTION): Likewise.
	(gdbpy_gdb_error, gdbpy_gdb_memory_error): Declare.
	(gdbpy_convert_exception): Declare.
	(apply_varobj_pretty_printer): Update.
	* python/py-utils.c (gdbpy_convert_exception): New function.

2010-10-19  Tom Tromey  <tromey@redhat.com>

	* gdb.texinfo (Basic Python): Update.  Add xref.
	(Exception Handling): Document new exception classes.
	(Types In Python): Update.
	(Frames In Python): Update.

2010-10-19  Tom Tromey  <tromey@redhat.com>

	* gdb.python/py-prettyprint.c (main): Add new 'ns2' local.
	* gdb.python/py-prettyprint.exp (run_lang_tests): Add test for
	MemoryError.
	* gdb.python/python.exp (gdb_py_test_multiple): Update exception
	type.
	* gdb.python/py-value.exp (test_value_in_inferior): Add test for
	MemoryError.
	(test_subscript_regression): Update exception type.

diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index 40c4172..2e80595 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -35,6 +35,7 @@
 #include "cp-support.h"
 #include "gdb_obstack.h"
 #include <ctype.h>
+#include "exceptions.h"
 
 extern void _initialize_c_language (void);
 
@@ -698,13 +699,19 @@ c_get_string (struct value *value, gdb_byte **buffer, int *length,
     }
   else
     {
-      err = read_string (value_as_address (value), *length, width, fetchlimit,
-  			 byte_order, buffer, length);
+      CORE_ADDR addr = value_as_address (value);
+
+      err = read_string (addr, *length, width, fetchlimit,
+			 byte_order, buffer, length);
       if (err)
 	{
 	  xfree (*buffer);
-	  error (_("Error reading string from inferior: %s"),
-		 safe_strerror (err));
+	  if (err == EIO)
+	    throw_error (MEMORY_ERROR, "Address %s out of bounds",
+			 paddress (get_type_arch (type), addr));
+	  else
+	    error (_("Error reading string from inferior: %s"),
+		   safe_strerror (err));
 	}
     }
 
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 9446932..a8f81c4 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -20548,8 +20548,9 @@ spaces if the parameter has a multi-part name.  For example,
 @samp{print object} is a valid parameter name.
 
 If the named parameter does not exist, this function throws a
-@code{RuntimeError}.  Otherwise, the parameter's value is converted to
-a Python value of the appropriate type, and returned.
+@code{gdb.error} (@pxref{Exception Handling}).  Otherwise, the
+parameter's value is converted to a Python value of the appropriate
+type, and returned.
 @end defun
 
 @findex gdb.history
@@ -20560,7 +20561,7 @@ If @var{number} is negative, then @value{GDBN} will take its absolute value
 and count backward from the last element (i.e., the most recent element) to
 find the value to return.  If @var{number} is zero, then @value{GDBN} will
 return the most recent element.  If the element specified by @var{number}
-doesn't exist in the value history, a @code{RuntimeError} exception will be
+doesn't exist in the value history, a @code{gdb.error} exception will be
 raised.
 
 If no exception is raised, the return value is always an instance of
@@ -20688,15 +20689,31 @@ Traceback (most recent call last):
 NameError: name 'foo' is not defined
 @end smallexample
 
-@value{GDBN} errors that happen in @value{GDBN} commands invoked by Python
-code are converted to Python @code{RuntimeError} exceptions.  User
-interrupt (via @kbd{C-c} or by typing @kbd{q} at a pagination
-prompt) is translated to a Python @code{KeyboardInterrupt}
-exception.  If you catch these exceptions in your Python code, your
-exception handler will see @code{RuntimeError} or
-@code{KeyboardInterrupt} as the exception type, the @value{GDBN} error
-message as its value, and the Python call stack backtrace at the
-Python statement closest to where the @value{GDBN} error occured as the
+@value{GDBN} errors that happen in @value{GDBN} commands invoked by
+Python code are converted to Python exceptions.  The type of the
+Python exception depends on the error.
+
+@ftable @code
+@item gdb.error
+This is the base class for most exceptions generated by @value{GDBN}.
+It is derived from @code{RuntimeError}, for compatibility with earlier
+versions of @value{GDBN}.
+
+If an error occurring in @value{GDBN} does not fit into some more
+specific category, then the generated exception will have this type.
+
+@item gdb.MemoryError
+This is a subclass of @code{gdb.error} which is thrown when an
+operation tried to access invalid memory in the inferior.
+
+@item KeyboardInterrupt
+User interrupt (via @kbd{C-c} or by typing @kbd{q} at a pagination
+prompt) is translated to a Python @code{KeyboardInterrupt} exception.
+@end ftable
+
+In all cases, your exception handler will see the @value{GDBN} error
+message as its value and the Python call stack backtrace at the Python
+statement closest to where the @value{GDBN} error occured as the
 traceback.
 
 @findex gdb.GdbError
@@ -21061,7 +21078,7 @@ variant of this type.  That is, the result is neither @code{const} nor
 Return a Python @code{Tuple} object that contains two elements: the
 low bound of the argument type and the high bound of that type.  If
 the type does not have a range, @value{GDBN} will raise a
-@code{RuntimeError} exception.
+@code{gdb.error} exception (@pxref{Exception Handling}).
 @end defmethod
 
 @defmethod Type reference
@@ -22166,8 +22183,8 @@ When the debugged program stops, @value{GDBN} is able to analyze its call
 stack (@pxref{Frames,,Stack frames}).  The @code{gdb.Frame} class
 represents a frame in the stack.  A @code{gdb.Frame} object is only valid
 while its corresponding frame exists in the inferior's stack.  If you try
-to use an invalid frame object, @value{GDBN} will throw a @code{RuntimeError}
-exception.
+to use an invalid frame object, @value{GDBN} will throw a @code{gdb.error}
+exception (@pxref{Exception Handling}).
 
 Two @code{gdb.Frame} objects can be compared for equality with the @code{==}
 operator, like:
diff --git a/gdb/python/py-prettyprint.c b/gdb/python/py-prettyprint.c
index 37c4078..e6a13c1 100644
--- a/gdb/python/py-prettyprint.c
+++ b/gdb/python/py-prettyprint.c
@@ -29,6 +29,18 @@
 #ifdef HAVE_PYTHON
 #include "python-internal.h"
 
+/* Return type of print_string_repr.  */
+
+enum string_repr_result
+  {
+    /* The string method returned None.  */
+    string_repr_none,
+    /* The string method had an error.  */
+    string_repr_error,
+    /* Everything ok.  */
+    string_repr_ok
+  };
+
 /* Helper function for find_pretty_printer which iterates over a list,
    calls each function and inspects output.  This will return a
    printer object if one recognizes VALUE.  If no printer is found, it
@@ -256,12 +268,40 @@ gdbpy_get_display_hint (PyObject *printer)
   return result;
 }
 
+/* A wrapper for gdbpy_print_stack that ignores MemoryError.  */
+
+static void
+print_stack_unless_memory_error (struct ui_file *stream)
+{
+  if (PyErr_ExceptionMatches (gdbpy_gdb_memory_error))
+    {
+      struct cleanup *cleanup;
+      PyObject *type, *value, *trace;
+      char *msg;
+
+      PyErr_Fetch (&type, &value, &trace);
+      cleanup = make_cleanup_py_decref (type);
+      make_cleanup_py_decref (value);
+      make_cleanup_py_decref (trace);
+
+      msg = gdbpy_exception_to_string (type, value);
+      make_cleanup (xfree, msg);
+
+      if (msg == NULL || *msg == '\0')
+	fprintf_filtered (stream, _("<error reading variable"));
+      else
+	fprintf_filtered (stream, _("<error reading variable: %s>"), msg);
+
+      do_cleanups (cleanup);
+    }
+  else
+    gdbpy_print_stack ();
+}
+
 /* Helper for apply_val_pretty_printer which calls to_string and
-   formats the result.  If the value returnd is Py_None, nothing is
-   printed and the function returns a 1; in all other cases data is
-   printed as given by the pretty printer and the function returns 0.
-*/
-static int
+   formats the result.  */
+
+static enum string_repr_result
 print_string_repr (PyObject *printer, const char *hint,
 		   struct ui_file *stream, int recurse,
 		   const struct value_print_options *options,
@@ -270,7 +310,7 @@ print_string_repr (PyObject *printer, const char *hint,
 {
   struct value *replacement = NULL;
   PyObject *py_str = NULL;
-  int is_py_none = 0;
+  enum string_repr_result result = string_repr_ok;
 
   py_str = pretty_print_one_value (printer, &replacement);
   if (py_str)
@@ -278,7 +318,7 @@ print_string_repr (PyObject *printer, const char *hint,
       struct cleanup *cleanup = make_cleanup_py_decref (py_str);
 
       if (py_str == Py_None)
-	is_py_none = 1;
+	result = string_repr_none;
       else if (gdbpy_is_lazy_string (py_str))
 	{
 	  CORE_ADDR addr;
@@ -316,7 +356,10 @@ print_string_repr (PyObject *printer, const char *hint,
 		fputs_filtered (output, stream);
 	    }
 	  else
-	    gdbpy_print_stack ();
+	    {
+	      result = string_repr_error;
+	      print_stack_unless_memory_error (stream);
+	    }
 	}
 
       do_cleanups (cleanup);
@@ -329,9 +372,12 @@ print_string_repr (PyObject *printer, const char *hint,
       common_val_print (replacement, stream, recurse, &opts, language);
     }
   else
-    gdbpy_print_stack ();
+    {
+      result = string_repr_error;
+      print_stack_unless_memory_error (stream);
+    }
 
-  return is_py_none;
+  return result;
 }
 
 static void
@@ -437,7 +483,7 @@ print_children (PyObject *printer, const char *hint,
 					 NULL);
   if (! children)
     {
-      gdbpy_print_stack ();
+      print_stack_unless_memory_error (stream);
       return;
     }
 
@@ -446,7 +492,7 @@ print_children (PyObject *printer, const char *hint,
   iter = PyObject_GetIter (children);
   if (!iter)
     {
-      gdbpy_print_stack ();
+      print_stack_unless_memory_error (stream);
       goto done;
     }
   make_cleanup_py_decref (iter);
@@ -476,7 +522,7 @@ print_children (PyObject *printer, const char *hint,
       if (! item)
 	{
 	  if (PyErr_Occurred ())
-	    gdbpy_print_stack ();
+	    print_stack_unless_memory_error (stream);
 	  /* Set a flag so we can know whether we printed all the
 	     available elements.  */
 	  else	  
@@ -631,7 +677,7 @@ apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr,
   char *hint = NULL;
   struct cleanup *cleanups;
   int result = 0;
-  int is_py_none = 0;
+  enum string_repr_result print_result;
   cleanups = ensure_python_env (gdbarch, language);
 
   /* Instantiate the printer.  */
@@ -666,17 +712,18 @@ apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr,
   make_cleanup (free_current_contents, &hint);
 
   /* Print the section */
-  is_py_none = print_string_repr (printer, hint, stream, recurse,
-				  options, language, gdbarch);
-  print_children (printer, hint, stream, recurse, options, language,
-		  is_py_none);
+  print_result = print_string_repr (printer, hint, stream, recurse,
+				    options, language, gdbarch);
+  if (print_result != string_repr_error)
+    print_children (printer, hint, stream, recurse, options, language,
+		    print_result == string_repr_none);
 
   result = 1;
 
 
  done:
   if (PyErr_Occurred ())
-    gdbpy_print_stack ();
+    print_stack_unless_memory_error (stream);
   do_cleanups (cleanups);
   return result;
 }
@@ -693,7 +740,8 @@ apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr,
    NULL.  */
 PyObject *
 apply_varobj_pretty_printer (PyObject *printer_obj,
-			     struct value **replacement)
+			     struct value **replacement,
+			     struct ui_file *stream)
 {
   PyObject *py_str = NULL;
 
@@ -701,7 +749,7 @@ apply_varobj_pretty_printer (PyObject *printer_obj,
   py_str = pretty_print_one_value (printer_obj, replacement);
 
   if (*replacement == NULL && py_str == NULL)
-    gdbpy_print_stack ();
+    print_stack_unless_memory_error (stream);
 
   return py_str;
 }
diff --git a/gdb/python/py-utils.c b/gdb/python/py-utils.c
index 90609fa..2f0aac4 100644
--- a/gdb/python/py-utils.c
+++ b/gdb/python/py-utils.c
@@ -274,6 +274,25 @@ gdbpy_exception_to_string (PyObject *ptype, PyObject *pvalue)
   return str;
 }
 
+/* Convert a GDB exception to the appropriate Python exception.
+   
+   This sets the Python error indicator, and returns NULL.  */
+
+PyObject *
+gdbpy_convert_exception (struct gdb_exception exception)
+{
+  PyObject *exc_class;
+
+  if (exception.reason == RETURN_QUIT)
+    exc_class = PyExc_KeyboardInterrupt;
+  else if (exception.error == MEMORY_ERROR)
+    exc_class = gdbpy_gdb_memory_error;
+  else
+    exc_class = gdbpy_gdb_error;
+
+  return PyErr_Format (exc_class, "%s", exception.message);
+}
+
 /* Converts OBJ to a CORE_ADDR value.
 
    Returns 1 on success or 0 on failure, with a Python exception set.  This
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index d00c23e..c196a30 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -76,6 +76,8 @@ typedef int Py_ssize_t;
 /* Also needed to parse enum var_types. */
 #include "command.h"
 
+#include "exceptions.h"
+
 struct block;
 struct value;
 struct language_defn;
@@ -175,9 +177,7 @@ extern const struct language_defn *python_language;
 #define GDB_PY_HANDLE_EXCEPTION(Exception)				\
     do {								\
       if (Exception.reason < 0)						\
-	return PyErr_Format (Exception.reason == RETURN_QUIT		\
-			     ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, \
-			     "%s", Exception.message);			\
+	return gdbpy_convert_exception (Exception);			\
     } while (0)
 
 /* Use this after a TRY_EXCEPT to throw the appropriate Python
@@ -186,9 +186,7 @@ extern const struct language_defn *python_language;
     do {								\
       if (Exception.reason < 0)						\
         {								\
-	  PyErr_Format (Exception.reason == RETURN_QUIT			\
-			? PyExc_KeyboardInterrupt : PyExc_RuntimeError, \
-			"%s", Exception.message);			\
+	  gdbpy_convert_exception (Exception);				\
 	  return -1;							\
 	}								\
     } while (0)
@@ -218,7 +216,8 @@ int gdbpy_is_value_object (PyObject *obj);
 /* Note that these are declared here, and not in python.h with the
    other pretty-printer functions, because they refer to PyObject.  */
 PyObject *apply_varobj_pretty_printer (PyObject *print_obj,
-				       struct value **replacement);
+				       struct value **replacement,
+				       struct ui_file *stream);
 PyObject *gdbpy_get_varobj_pretty_printer (struct value *value);
 char *gdbpy_get_display_hint (PyObject *printer);
 PyObject *gdbpy_default_visualizer (PyObject *self, PyObject *args);
@@ -229,8 +228,13 @@ extern PyObject *gdbpy_to_string_cst;
 extern PyObject *gdbpy_display_hint_cst;
 extern PyObject *gdbpy_enabled_cst;
 
+/* Exception types.  */
+extern PyObject *gdbpy_gdb_error;
+extern PyObject *gdbpy_gdb_memory_error;
 extern PyObject *gdbpy_gdberror_exc;
 
+extern PyObject *gdbpy_convert_exception (struct gdb_exception);
+
 int get_addr_from_python (PyObject *obj, CORE_ADDR *addr);
 
 #endif /* GDB_PYTHON_INTERNAL_H */
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 78410c6..1eef8ce 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -66,6 +66,12 @@ PyObject *gdbpy_enabled_cst;
 /* The GdbError exception.  */
 PyObject *gdbpy_gdberror_exc;
 
+/* The `gdb.error' base class.  */
+PyObject *gdbpy_gdb_error;
+
+/* The `gdb.MemoryError' exception.  */
+PyObject *gdbpy_gdb_memory_error;
+
 /* Architecture and language to be used in callbacks from
    the Python interpreter.  */
 struct gdbarch *python_gdbarch;
@@ -967,6 +973,13 @@ Enables or disables printing of Python stack traces."),
     xfree (gdb_pythondir);
   }
 
+  gdbpy_gdb_error = PyErr_NewException ("gdb.error", PyExc_RuntimeError, NULL);
+  PyModule_AddObject (gdb_module, "error", gdbpy_gdb_error);
+
+  gdbpy_gdb_memory_error = PyErr_NewException ("gdb.MemoryError",
+					       gdbpy_gdb_error, NULL);
+  PyModule_AddObject (gdb_module, "MemoryError", gdbpy_gdb_memory_error);
+
   gdbpy_gdberror_exc = PyErr_NewException ("gdb.GdbError", NULL, NULL);
   PyModule_AddObject (gdb_module, "GdbError", gdbpy_gdberror_exc);
 
diff --git a/gdb/testsuite/gdb.python/py-prettyprint.c b/gdb/testsuite/gdb.python/py-prettyprint.c
index b633111..23e3ff9 100644
--- a/gdb/testsuite/gdb.python/py-prettyprint.c
+++ b/gdb/testsuite/gdb.python/py-prettyprint.c
@@ -213,7 +213,7 @@ main ()
   /* Clearing by being `static' could invoke an other GDB C++ bug.  */
   struct nullstr nullstr;
   nostring_type nstype;
-  struct ns  ns;
+  struct ns ns, ns2;
   struct lazystring estring, estring2;
 
   nstype.elements = narray;
@@ -231,6 +231,10 @@ main ()
   ns.null_str = "embedded\0null\0string";
   ns.length = 20;
 
+  /* Make a "corrupted" string.  */
+  ns2.null_str = NULL;
+  ns2.length = 20;
+
   estring.lazy_str = "embedded x\201\202\203\204" ;
 
   /* Incomplete UTF-8, but ok Latin-1.  */
diff --git a/gdb/testsuite/gdb.python/py-prettyprint.exp b/gdb/testsuite/gdb.python/py-prettyprint.exp
index b8f37d3..7eda415 100644
--- a/gdb/testsuite/gdb.python/py-prettyprint.exp
+++ b/gdb/testsuite/gdb.python/py-prettyprint.exp
@@ -87,6 +87,8 @@ proc run_lang_tests {lang} {
 	gdb_py_test_silent_cmd "set print elements 200" "" 1
     }
 
+    gdb_test "print ns2" ".error reading variable: Address 0x0 out of bounds."
+
     gdb_test "print x" " = \"this is x\""
     gdb_test "print cstring" " = \"const string\""
 
diff --git a/gdb/testsuite/gdb.python/py-value.exp b/gdb/testsuite/gdb.python/py-value.exp
index 895969b..9bee1c0 100644
--- a/gdb/testsuite/gdb.python/py-value.exp
+++ b/gdb/testsuite/gdb.python/py-value.exp
@@ -210,6 +210,9 @@ proc test_value_in_inferior {} {
   # Test address attribute
   gdb_test "python print 'result =', arg0.address" "= 0x\[\[:xdigit:\]\]+" "Test address attribute"
 
+  # Test memory error.
+  gdb_test "python print gdb.parse_and_eval('*(int*)0')" "gdb.MemoryError: Cannot access memory at address 0x0.*"
+
   # Test string fetches,  both partial and whole.
   gdb_test "print st" "\"divide et impera\""
   gdb_py_test_silent_cmd "python st = gdb.history (0)" "get value from history" 1
@@ -371,7 +374,7 @@ proc test_subscript_regression {lang} {
 
  # Try to access an int with a subscript.  This should fail.
  gdb_test "python print intv" "1" "Baseline print of a Python value"
- gdb_test "python print intv\[0\]" "RuntimeError: Cannot subscript requested type.*" \
+ gdb_test "python print intv\[0\]" "gdb.error: Cannot subscript requested type.*" \
      "Attempt to access an integer with a subscript"
 
  # Try to access a string with a subscript.  This should pass.
@@ -386,7 +389,7 @@ proc test_subscript_regression {lang} {
 
  # Try to access a single dimension array with a subscript to the
  # result.  This should fail.
- gdb_test "python print pointer\[intv\]\[0\]" "RuntimeError: Cannot subscript requested type.*" \
+ gdb_test "python print pointer\[intv\]\[0\]" "gdb.error: Cannot subscript requested type.*" \
      "Attempt to access an integer with a subscript"
 
  # Lastly, test subscript access to an array with multiple
diff --git a/gdb/testsuite/gdb.python/python.exp b/gdb/testsuite/gdb.python/python.exp
index 301245b..dd9175a 100644
--- a/gdb/testsuite/gdb.python/python.exp
+++ b/gdb/testsuite/gdb.python/python.exp
@@ -160,7 +160,7 @@ runto [gdb_get_line_number "Break to end."]
 
 # Test gdb.decode_line.
 gdb_test "python gdb.decode_line(\"main.c:43\")" \
-    "RuntimeError: No source file named main.c.*" "test decode_line no source named main"
+    "gdb.error: No source file named main.c.*" "test decode_line no source named main"
 
 gdb_py_test_silent_cmd "python symtab = gdb.decode_line()" "test decode_line current location" 1
 gdb_test "python print len(symtab)" "2" "Test decode_line current location"
@@ -177,7 +177,7 @@ gdb_test "python print symtab\[1\]\[0\].symtab" "gdb/testsuite/gdb.python/python
 gdb_test "python print symtab\[1\]\[0\].line" "26" "Test decode_line python.c:26 line number"
 
 gdb_test "python gdb.decode_line(\"randomfunc\")" \
-    "RuntimeError: Function \"randomfunc\" not defined.*" "test decode_line randomfunc"
+    "gdb.error: Function \"randomfunc\" not defined.*" "test decode_line randomfunc"
 gdb_py_test_silent_cmd "python symtab = gdb.decode_line(\"func1\")" "test decode_line func1()" 1
 gdb_test "python print len(symtab)" "2" "Test decode_line func1 length"
 gdb_test "python print len(symtab\[1\])" "1" "Test decode_line func1 length"
diff --git a/gdb/varobj.c b/gdb/varobj.c
index 09f91eb..e87d399 100644
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -2479,7 +2479,7 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
 		       struct varobj *var)
 {
   struct ui_file *stb;
-  struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
+  struct cleanup *old_chain;
   gdb_byte *thevalue = NULL;
   struct value_print_options opts;
   struct type *type = NULL;
@@ -2493,6 +2493,9 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
   if (value == NULL)
     return NULL;
 
+  stb = mem_fileopen ();
+  old_chain = make_cleanup_ui_file_delete (stb);
+
   gdbarch = get_type_arch (value_type (value));
 #if HAVE_PYTHON
   {
@@ -2505,7 +2508,10 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
 	/* First check to see if we have any children at all.  If so,
 	   we simply return {...}.  */
 	if (dynamic_varobj_has_child_method (var))
-	  return xstrdup ("{...}");
+	  {
+	    do_cleanups (old_chain);
+	    return xstrdup ("{...}");
+	  }
 
 	if (PyObject_HasAttr (value_formatter, gdbpy_to_string_cst))
 	  {
@@ -2522,7 +2528,8 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
 	      }
 
 	    output = apply_varobj_pretty_printer (value_formatter,
-						  &replacement);
+						  &replacement,
+						  stb);
 	    if (output)
 	      {
 		make_cleanup_py_decref (output);
@@ -2567,9 +2574,6 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
   }
 #endif
 
-  stb = mem_fileopen ();
-  make_cleanup_ui_file_delete (stb);
-
   get_formatted_print_options (&opts, format_code[(int) format]);
   opts.deref_ref = 0;
   opts.raw = 1;


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