+2010-11-12 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-11-12 Marc Khouzam <marc.khouzam@ericsson.com>
* mi/mi-main.c (mi_cmd_target_detach): Accept new
#include "cp-support.h"
#include "gdb_obstack.h"
#include <ctype.h>
+#include "exceptions.h"
extern void _initialize_c_language (void);
}
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));
}
}
+2010-11-12 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-11-11 Phil Muldoon <pmuldoon@redhat.com>
* gdb.texinfo (Breakpoints In Python): Document "internal"
@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
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
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
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
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:
#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
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,
{
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)
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;
fputs_filtered (output, stream);
}
else
- gdbpy_print_stack ();
+ {
+ result = string_repr_error;
+ print_stack_unless_memory_error (stream);
+ }
}
do_cleanups (cleanup);
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
NULL);
if (! children)
{
- gdbpy_print_stack ();
+ print_stack_unless_memory_error (stream);
return;
}
iter = PyObject_GetIter (children);
if (!iter)
{
- gdbpy_print_stack ();
+ print_stack_unless_memory_error (stream);
goto done;
}
make_cleanup_py_decref (iter);
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
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. */
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;
}
NULL. */
PyObject *
apply_varobj_pretty_printer (PyObject *printer_obj,
- struct value **replacement)
+ struct value **replacement,
+ struct ui_file *stream)
{
PyObject *py_str = NULL;
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;
}
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
/* Also needed to parse enum var_types. */
#include "command.h"
+#include "exceptions.h"
+
struct block;
struct value;
struct language_defn;
#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
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)
/* 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);
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 */
/* 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;
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);
+2010-11-12 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.
+
2010-11-11 Phil Muldoon <pmuldoon@redhat.com>
* gdb.python/py-breakpoint.exp: Add internal watchpoint and
/* 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;
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. */
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\""
# 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
# 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.
# 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
# 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"
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"
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;
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
{
/* 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))
{
}
output = apply_varobj_pretty_printer (value_formatter,
- &replacement);
+ &replacement,
+ stb);
if (output)
{
make_cleanup_py_decref (output);
}
#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;