From 621c83642d17cf523c20f55f2ed945a7ec95ea6a Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Fri, 12 Nov 2010 20:49:43 +0000 Subject: [PATCH] gdb * 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. gdb/doc * gdb.texinfo (Basic Python): Update. Add xref. (Exception Handling): Document new exception classes. (Types In Python): Update. (Frames In Python): Update. gdb/testsuite * 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. --- gdb/ChangeLog | 26 ++++++ gdb/c-lang.c | 15 +++- gdb/doc/ChangeLog | 7 ++ gdb/doc/gdb.texinfo | 47 +++++++---- gdb/python/py-prettyprint.c | 90 ++++++++++++++++----- gdb/python/py-utils.c | 19 +++++ gdb/python/python-internal.h | 18 +++-- gdb/python/python.c | 13 +++ gdb/testsuite/ChangeLog | 11 +++ gdb/testsuite/gdb.python/py-prettyprint.c | 6 +- gdb/testsuite/gdb.python/py-prettyprint.exp | 2 + gdb/testsuite/gdb.python/py-value.exp | 7 +- gdb/testsuite/gdb.python/python.exp | 4 +- gdb/varobj.c | 16 ++-- 14 files changed, 223 insertions(+), 58 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 567b54bfc4..58ce121d58 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,29 @@ +2010-11-12 Tom Tromey + + * 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-11-12 Marc Khouzam * mi/mi-main.c (mi_cmd_target_detach): Accept new diff --git a/gdb/c-lang.c b/gdb/c-lang.c index 015ba16308..775a6f83e8 100644 --- a/gdb/c-lang.c +++ b/gdb/c-lang.c @@ -35,6 +35,7 @@ #include "cp-support.h" #include "gdb_obstack.h" #include +#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/ChangeLog b/gdb/doc/ChangeLog index d999772c26..75f6f704b3 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,10 @@ +2010-11-12 Tom Tromey + + * gdb.texinfo (Basic Python): Update. Add xref. + (Exception Handling): Document new exception classes. + (Types In Python): Update. + (Frames In Python): Update. + 2010-11-11 Phil Muldoon * gdb.texinfo (Breakpoints In Python): Document "internal" diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index cf70ce43ef..ddc711b12e 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -20729,8 +20729,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 @@ -20741,7 +20742,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 @@ -20869,15 +20870,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 @@ -21242,7 +21259,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 @@ -22433,8 +22450,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 afe2b40045..7be1409e68 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, _(""), 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 90609fa85d..2f0aac44cb 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 67de6223a1..30d75336a4 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -80,6 +80,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; @@ -179,9 +181,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 @@ -190,9 +190,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) @@ -222,7 +220,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); @@ -233,8 +232,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 d4f8c3dfd1..d009be94ed 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/ChangeLog b/gdb/testsuite/ChangeLog index 11b86ad387..3c62b9d005 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2010-11-12 Tom Tromey + + * 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. + 2010-11-11 Phil Muldoon * gdb.python/py-breakpoint.exp: Add internal watchpoint and diff --git a/gdb/testsuite/gdb.python/py-prettyprint.c b/gdb/testsuite/gdb.python/py-prettyprint.c index b6331115dc..23e3ff9991 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 b8f37d335c..7eda415a2d 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 895969be53..9bee1c08f0 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 301245bf11..dd9175ae4c 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 9cff971403..25518d4daf 100644 --- a/gdb/varobj.c +++ b/gdb/varobj.c @@ -2477,7 +2477,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; @@ -2491,6 +2491,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 { @@ -2503,7 +2506,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)) { @@ -2520,7 +2526,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); @@ -2565,9 +2572,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; -- 2.34.1