gdb/
* python/py-breakpoint.c (bppy_set_condition): New comment. * python/py-cmd.c (cmdpy_function): Call also gdbpy_print_stack for failed PyUnicode_Decode. (cmdpy_completer): Skip element for failed python_string_to_host_string. (cmdpy_init): Return -1 on failed python_string_to_host_string. * python/py-frame.c (frapy_read_var): Extend the function comment. * python/py-function.c (fnpy_init): Return -1 on failed python_string_to_host_string. * python/py-inferior.c (infpy_read_memory, infpy_write_memory): Extend the function comment. (infpy_search_memory): Extend the function comment. Remove the PyErr_SetString call on already set error state. * python/py-param.c (set_parameter_value): Extend the function comment. Return -1 on failed python_string_to_host_string, twice. (set_attr): Extend the function comment. (compute_enum_values): Extend the function comment. New variable back_to. Protect self->enumeration by BACK_TO cleanups. Return 0 on failed python_string_to_host_string. (get_doc_string): Call gdbpy_print_stack on failed python_string_to_host_string. (parmpy_init): Extend the function comment. * python/py-prettyprint.c (pretty_print_one_value): Likewise. (gdbpy_get_display_hint, print_children): Call gdbpy_print_stack on failed python_string_to_host_string. * python/py-value.c (valpy_new, valpy_getitem, valpy_call) (valpy_binop, valpy_richcompare): Extend the function comment. * python/python.c (struct python_env) <error_type, error_value, error_traceback>: New fields. (restore_python_env): Handle PyErr_Occurred. Call PyErr_Restore. (ensure_python_env): Call PyErr_Fetch. * varobj.c (update_dynamic_varobj_children): Call gdbpy_print_stack on failed convert_value_from_python. (value_get_print_value): Call gdbpy_print_stack on failed python_string_to_target_python_string. gdb/testsuite/ * gdb.python/py-error.exp: New file. * gdb.python/py-error.py: New file.
This commit is contained in:
parent
a071456ba8
commit
8dc785338e
14 changed files with 241 additions and 34 deletions
|
@ -420,6 +420,9 @@ bppy_get_condition (PyObject *self, void *closure)
|
|||
return PyString_Decode (str, strlen (str), host_charset (), NULL);
|
||||
}
|
||||
|
||||
/* Returns 0 on success. Returns -1 on error, with a python exception set.
|
||||
*/
|
||||
|
||||
static int
|
||||
bppy_set_condition (PyObject *self, PyObject *newvalue, void *closure)
|
||||
{
|
||||
|
|
|
@ -139,7 +139,10 @@ cmdpy_function (struct cmd_list_element *command, char *args, int from_tty)
|
|||
args = "";
|
||||
argobj = PyUnicode_Decode (args, strlen (args), host_charset (), NULL);
|
||||
if (! argobj)
|
||||
error (_("Could not convert arguments to Python string."));
|
||||
{
|
||||
gdbpy_print_stack ();
|
||||
error (_("Could not convert arguments to Python string."));
|
||||
}
|
||||
|
||||
ttyobj = from_tty ? Py_True : Py_False;
|
||||
Py_INCREF (ttyobj);
|
||||
|
@ -256,6 +259,12 @@ cmdpy_completer (struct cmd_list_element *command, char *text, char *word)
|
|||
continue;
|
||||
}
|
||||
result[out] = python_string_to_host_string (elt);
|
||||
if (result[out] == NULL)
|
||||
{
|
||||
/* Skip problem elements. */
|
||||
PyErr_Clear ();
|
||||
continue;
|
||||
}
|
||||
++out;
|
||||
}
|
||||
result[out] = NULL;
|
||||
|
@ -466,7 +475,15 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
|
|||
PyObject *ds_obj = PyObject_GetAttr (self, gdbpy_doc_cst);
|
||||
|
||||
if (ds_obj && gdbpy_is_string (ds_obj))
|
||||
docstring = python_string_to_host_string (ds_obj);
|
||||
{
|
||||
docstring = python_string_to_host_string (ds_obj);
|
||||
if (docstring == NULL)
|
||||
{
|
||||
xfree (cmd_name);
|
||||
xfree (pfx_name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (! docstring)
|
||||
docstring = xstrdup (_("This command is not documented."));
|
||||
|
|
|
@ -385,7 +385,8 @@ frapy_find_sal (PyObject *self, PyObject *args)
|
|||
start the search from that block, otherwise search from the frame's
|
||||
current block (determined by examining the resume address of the
|
||||
frame). The variable argument must be a string or an instance of a
|
||||
gdb.Symbol. The block argument must be an instance of gdb.Block. */
|
||||
gdb.Symbol. The block argument must be an instance of gdb.Block. Returns
|
||||
NULL on error, with a python exception set. */
|
||||
static PyObject *
|
||||
frapy_read_var (PyObject *self, PyObject *args)
|
||||
{
|
||||
|
|
|
@ -113,7 +113,14 @@ fnpy_init (PyObject *self, PyObject *args, PyObject *kwds)
|
|||
{
|
||||
PyObject *ds_obj = PyObject_GetAttrString (self, "__doc__");
|
||||
if (ds_obj && gdbpy_is_string (ds_obj))
|
||||
docstring = python_string_to_host_string (ds_obj);
|
||||
{
|
||||
docstring = python_string_to_host_string (ds_obj);
|
||||
if (docstring == NULL)
|
||||
{
|
||||
Py_DECREF (self);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (! docstring)
|
||||
docstring = xstrdup (_("This function is not documented."));
|
||||
|
|
|
@ -293,7 +293,8 @@ gdbpy_inferiors (PyObject *unused, PyObject *unused2)
|
|||
|
||||
/* Implementation of gdb.read_memory (address, length).
|
||||
Returns a Python buffer object with LENGTH bytes of the inferior's
|
||||
memory at ADDRESS. Both arguments are integers. */
|
||||
memory at ADDRESS. Both arguments are integers. Returns NULL on error,
|
||||
with a python exception set. */
|
||||
static PyObject *
|
||||
infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
|
@ -361,7 +362,8 @@ infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw)
|
|||
Writes the contents of BUFFER (a Python object supporting the read
|
||||
buffer protocol) at ADDRESS in the inferior's memory. Write LENGTH
|
||||
bytes from BUFFER, or its entire contents if the argument is not
|
||||
provided. The function returns nothing. */
|
||||
provided. The function returns nothing. Returns NULL on error, with
|
||||
a python exception set. */
|
||||
static PyObject *
|
||||
infpy_write_memory (PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
|
@ -473,7 +475,8 @@ get_char_buffer (PyObject *self, Py_ssize_t segment, char **ptrptr)
|
|||
search from ADDRESS. PATTERN is the pattern to search for (and
|
||||
must be a Python object supporting the buffer protocol).
|
||||
Returns a Python Long object holding the address where the pattern
|
||||
was located, or if the pattern was not found, returns None. */
|
||||
was located, or if the pattern was not found, returns None. Returns NULL
|
||||
on error, with a python exception set. */
|
||||
static PyObject *
|
||||
infpy_search_memory (PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
|
@ -511,12 +514,7 @@ infpy_search_memory (PyObject *self, PyObject *args, PyObject *kw)
|
|||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString (PyExc_RuntimeError,
|
||||
_("Cannot get search address/range from Python."));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
if (!PyObject_CheckReadBuffer (pattern))
|
||||
{
|
||||
|
|
|
@ -110,8 +110,8 @@ get_attr (PyObject *obj, PyObject *attr_name)
|
|||
return PyObject_GenericGetAttr (obj, attr_name);
|
||||
}
|
||||
|
||||
/* Set a parameter value from a Python value. Return 0 on success, -1
|
||||
on failure. */
|
||||
/* Set a parameter value from a Python value. Return 0 on success. Returns
|
||||
-1 on error, with a python exception set. */
|
||||
static int
|
||||
set_parameter_value (parmpy_object *self, PyObject *value)
|
||||
{
|
||||
|
@ -132,17 +132,25 @@ set_parameter_value (parmpy_object *self, PyObject *value)
|
|||
|
||||
return -1;
|
||||
}
|
||||
if (self->value.stringval)
|
||||
xfree (self->value.stringval);
|
||||
if (value == Py_None)
|
||||
{
|
||||
xfree (self->value.stringval);
|
||||
if (self->type == var_optional_filename)
|
||||
self->value.stringval = xstrdup ("");
|
||||
else
|
||||
self->value.stringval = NULL;
|
||||
}
|
||||
else
|
||||
self->value.stringval = python_string_to_host_string (value);
|
||||
{
|
||||
char *string;
|
||||
|
||||
string = python_string_to_host_string (value);
|
||||
if (string == NULL)
|
||||
return -1;
|
||||
|
||||
xfree (self->value.stringval);
|
||||
self->value.stringval = string;
|
||||
}
|
||||
break;
|
||||
|
||||
case var_enum:
|
||||
|
@ -158,6 +166,8 @@ set_parameter_value (parmpy_object *self, PyObject *value)
|
|||
}
|
||||
|
||||
str = python_string_to_host_string (value);
|
||||
if (str == NULL)
|
||||
return -1;
|
||||
for (i = 0; self->enumeration[i]; ++i)
|
||||
if (! strcmp (self->enumeration[i], str))
|
||||
break;
|
||||
|
@ -258,7 +268,7 @@ set_parameter_value (parmpy_object *self, PyObject *value)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Set an attribute. */
|
||||
/* Set an attribute. Returns -1 on error, with a python exception set. */
|
||||
static int
|
||||
set_attr (PyObject *obj, PyObject *attr_name, PyObject *val)
|
||||
{
|
||||
|
@ -358,12 +368,13 @@ add_setshow_generic (int parmclass, enum command_class cmdclass,
|
|||
}
|
||||
}
|
||||
|
||||
/* A helper which computes enum values. Returns 1 on success, 0 on
|
||||
error. */
|
||||
/* A helper which computes enum values. Returns 1 on success. Returns 0 on
|
||||
error, with a python exception set. */
|
||||
static int
|
||||
compute_enum_values (parmpy_object *self, PyObject *enum_values)
|
||||
{
|
||||
Py_ssize_t size, i;
|
||||
struct cleanup *back_to;
|
||||
|
||||
if (! enum_values)
|
||||
{
|
||||
|
@ -390,6 +401,7 @@ compute_enum_values (parmpy_object *self, PyObject *enum_values)
|
|||
}
|
||||
|
||||
self->enumeration = xmalloc ((size + 1) * sizeof (char *));
|
||||
back_to = make_cleanup (free_current_contents, &self->enumeration);
|
||||
memset (self->enumeration, 0, (size + 1) * sizeof (char *));
|
||||
|
||||
for (i = 0; i < size; ++i)
|
||||
|
@ -397,16 +409,27 @@ compute_enum_values (parmpy_object *self, PyObject *enum_values)
|
|||
PyObject *item = PySequence_GetItem (enum_values, i);
|
||||
|
||||
if (! item)
|
||||
return 0;
|
||||
{
|
||||
do_cleanups (back_to);
|
||||
return 0;
|
||||
}
|
||||
if (! gdbpy_is_string (item))
|
||||
{
|
||||
do_cleanups (back_to);
|
||||
PyErr_SetString (PyExc_RuntimeError,
|
||||
_("The enumeration item not a string."));
|
||||
return 0;
|
||||
}
|
||||
self->enumeration[i] = python_string_to_host_string (item);
|
||||
if (self->enumeration[i] == NULL)
|
||||
{
|
||||
do_cleanups (back_to);
|
||||
return 0;
|
||||
}
|
||||
make_cleanup (xfree, (char *) self->enumeration[i]);
|
||||
}
|
||||
|
||||
discard_cleanups (back_to);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -422,7 +445,11 @@ get_doc_string (PyObject *object, PyObject *attr)
|
|||
PyObject *ds_obj = PyObject_GetAttr (object, attr);
|
||||
|
||||
if (ds_obj && gdbpy_is_string (ds_obj))
|
||||
result = python_string_to_host_string (ds_obj);
|
||||
{
|
||||
result = python_string_to_host_string (ds_obj);
|
||||
if (result == NULL)
|
||||
gdbpy_print_stack ();
|
||||
}
|
||||
}
|
||||
if (! result)
|
||||
result = xstrdup (_("This command is not documented."));
|
||||
|
@ -449,8 +476,9 @@ get_doc_string (PyObject *object, PyObject *attr)
|
|||
|
||||
The documentation for the parameter is taken from the doc string
|
||||
for the python class.
|
||||
|
||||
*/
|
||||
|
||||
Returns -1 on error, with a python exception set. */
|
||||
|
||||
static int
|
||||
parmpy_init (PyObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
|
|
|
@ -196,8 +196,8 @@ find_pretty_printer (PyObject *value)
|
|||
is returned. If the function returns Py_NONE that means the pretty
|
||||
printer returned the Python None as a value. Otherwise, if the
|
||||
function returns a value, *OUT_VALUE is set to the value, and NULL
|
||||
is returned. On error, *OUT_VALUE is set to NULL, and NULL is
|
||||
returned. */
|
||||
is returned. On error, *OUT_VALUE is set to NULL, NULL is
|
||||
returned, with a python exception set. */
|
||||
|
||||
static PyObject *
|
||||
pretty_print_one_value (PyObject *printer, struct value **out_value)
|
||||
|
@ -243,7 +243,11 @@ gdbpy_get_display_hint (PyObject *printer)
|
|||
if (hint)
|
||||
{
|
||||
if (gdbpy_is_string (hint))
|
||||
result = python_string_to_host_string (hint);
|
||||
{
|
||||
result = python_string_to_host_string (hint);
|
||||
if (result == NULL)
|
||||
gdbpy_print_stack ();
|
||||
}
|
||||
Py_DECREF (hint);
|
||||
}
|
||||
else
|
||||
|
@ -566,7 +570,10 @@ print_children (PyObject *printer, const char *hint,
|
|||
else
|
||||
{
|
||||
output = python_string_to_host_string (py_v);
|
||||
fputs_filtered (output, stream);
|
||||
if (!output)
|
||||
gdbpy_print_stack ();
|
||||
else
|
||||
fputs_filtered (output, stream);
|
||||
xfree (output);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,7 +119,8 @@ note_value (value_object *value_obj)
|
|||
values_in_python = value_obj;
|
||||
}
|
||||
|
||||
/* Called when a new gdb.Value object needs to be allocated. */
|
||||
/* Called when a new gdb.Value object needs to be allocated. Returns NULL on
|
||||
error, with a python exception set. */
|
||||
static PyObject *
|
||||
valpy_new (PyTypeObject *subtype, PyObject *args, PyObject *keywords)
|
||||
{
|
||||
|
@ -438,7 +439,7 @@ valpy_length (PyObject *self)
|
|||
}
|
||||
|
||||
/* Given string name of an element inside structure, return its value
|
||||
object. */
|
||||
object. Returns NULL on error, with a python exception set. */
|
||||
static PyObject *
|
||||
valpy_getitem (PyObject *self, PyObject *key)
|
||||
{
|
||||
|
@ -499,7 +500,7 @@ valpy_setitem (PyObject *self, PyObject *key, PyObject *value)
|
|||
}
|
||||
|
||||
/* Called by the Python interpreter to perform an inferior function
|
||||
call on the value. */
|
||||
call on the value. Returns NULL on error, with a python exception set. */
|
||||
static PyObject *
|
||||
valpy_call (PyObject *self, PyObject *args, PyObject *keywords)
|
||||
{
|
||||
|
@ -619,7 +620,8 @@ enum valpy_opcode
|
|||
((TYPE_CODE (TYPE) == TYPE_CODE_REF) ? (TYPE_TARGET_TYPE (TYPE)) : (TYPE))
|
||||
|
||||
/* Returns a value object which is the result of applying the operation
|
||||
specified by OPCODE to the given arguments. */
|
||||
specified by OPCODE to the given arguments. Returns NULL on error, with
|
||||
a python exception set. */
|
||||
static PyObject *
|
||||
valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other)
|
||||
{
|
||||
|
@ -871,7 +873,8 @@ valpy_xor (PyObject *self, PyObject *other)
|
|||
return valpy_binop (VALPY_BITXOR, self, other);
|
||||
}
|
||||
|
||||
/* Implements comparison operations for value objects. */
|
||||
/* Implements comparison operations for value objects. Returns NULL on error,
|
||||
with a python exception set. */
|
||||
static PyObject *
|
||||
valpy_richcompare (PyObject *self, PyObject *other, int op)
|
||||
{
|
||||
|
|
|
@ -79,6 +79,7 @@ struct python_env
|
|||
PyGILState_STATE state;
|
||||
struct gdbarch *gdbarch;
|
||||
const struct language_defn *language;
|
||||
PyObject *error_type, *error_value, *error_traceback;
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -86,6 +87,16 @@ restore_python_env (void *p)
|
|||
{
|
||||
struct python_env *env = (struct python_env *)p;
|
||||
|
||||
/* Leftover Python error is forbidden by Python Exception Handling. */
|
||||
if (PyErr_Occurred ())
|
||||
{
|
||||
/* This order is similar to the one calling error afterwards. */
|
||||
gdbpy_print_stack ();
|
||||
warning (_("internal error: Unhandled Python exception"));
|
||||
}
|
||||
|
||||
PyErr_Restore (env->error_type, env->error_value, env->error_traceback);
|
||||
|
||||
PyGILState_Release (env->state);
|
||||
python_gdbarch = env->gdbarch;
|
||||
python_language = env->language;
|
||||
|
@ -108,6 +119,9 @@ ensure_python_env (struct gdbarch *gdbarch,
|
|||
python_gdbarch = gdbarch;
|
||||
python_language = language;
|
||||
|
||||
/* Save it and ensure ! PyErr_Occurred () afterwards. */
|
||||
PyErr_Fetch (&env->error_type, &env->error_value, &env->error_traceback);
|
||||
|
||||
return make_cleanup (restore_python_env, env);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue