aboutsummaryrefslogtreecommitdiff
path: root/gdb/python
diff options
context:
space:
mode:
authorTom Tromey <tromey@redhat.com>2010-11-12 20:49:43 +0000
committerTom Tromey <tromey@redhat.com>2010-11-12 20:49:43 +0000
commit621c83642d17cf523c20f55f2ed945a7ec95ea6a (patch)
tree231cb6bb882e72fb68d6a5eb189060af43bb0dad /gdb/python
parentf1b9e6e7ee6f55dd82194417e8f4d1713783ef39 (diff)
downloadgdb-621c83642d17cf523c20f55f2ed945a7ec95ea6a.zip
gdb-621c83642d17cf523c20f55f2ed945a7ec95ea6a.tar.gz
gdb-621c83642d17cf523c20f55f2ed945a7ec95ea6a.tar.bz2
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.
Diffstat (limited to 'gdb/python')
-rw-r--r--gdb/python/py-prettyprint.c90
-rw-r--r--gdb/python/py-utils.c19
-rw-r--r--gdb/python/python-internal.h18
-rw-r--r--gdb/python/python.c13
4 files changed, 112 insertions, 28 deletions
diff --git a/gdb/python/py-prettyprint.c b/gdb/python/py-prettyprint.c
index afe2b40..7be1409 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 67de622..30d7533 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 d4f8c3d..d009be9 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);