/* General utility routines for GDB/Python.
- Copyright (C) 2008-2012 Free Software Foundation, Inc.
+ Copyright (C) 2008-2018 Free Software Foundation, Inc.
This file is part of GDB.
#include "charset.h"
#include "value.h"
#include "python-internal.h"
-
-
-/* This is a cleanup function which decrements the refcount on a
- Python object. */
-
-static void
-py_decref (void *p)
-{
- PyObject *py = p;
-
- /* Note that we need the extra braces in this 'if' to avoid a
- warning from gcc. */
- if (py)
- {
- Py_DECREF (py);
- }
-}
-
-/* Return a new cleanup which will decrement the Python object's
- refcount when run. */
-
-struct cleanup *
-make_cleanup_py_decref (PyObject *py)
-{
- return make_cleanup (py_decref, (void *) py);
-}
+#include "py-ref.h"
/* Converts a Python 8-bit string to a unicode string object. Assumes the
8-bit string is in the host charset. If an error occurs during conversion,
As an added bonus, the functions accepts a unicode string and returns it
right away, so callers don't need to check which kind of string they've
- got. In Python 3, all strings are Unicode so this case is always the
+ got. In Python 3, all strings are Unicode so this case is always the
one that applies.
If the given object is not one of the mentioned string types, NULL is
conversion, NULL will be returned and a python exception will be set.
The caller is responsible for xfree'ing the string. */
-static char *
+static gdb::unique_xmalloc_ptr<char>
unicode_to_encoded_string (PyObject *unicode_str, const char *charset)
{
- char *result;
- PyObject *string;
+ gdb::unique_xmalloc_ptr<char> result;
/* Translate string to named charset. */
- string = PyUnicode_AsEncodedString (unicode_str, charset, NULL);
+ gdbpy_ref<> string (PyUnicode_AsEncodedString (unicode_str, charset, NULL));
if (string == NULL)
return NULL;
#ifdef IS_PY3K
- result = xstrdup (PyBytes_AsString (string));
+ result.reset (xstrdup (PyBytes_AsString (string.get ())));
#else
- result = xstrdup (PyString_AsString (string));
+ result.reset (xstrdup (PyString_AsString (string.get ())));
#endif
- Py_DECREF (string);
-
return result;
}
return PyUnicode_AsEncodedString (unicode_str, charset, NULL);
}
-/* Returns a newly allocated string with the contents of the given unicode
- string object converted to the target's charset. If an error occurs during
- the conversion, NULL will be returned and a python exception will be set.
-
- The caller is responsible for xfree'ing the string. */
-char *
+/* Returns a newly allocated string with the contents of the given
+ unicode string object converted to the target's charset. If an
+ error occurs during the conversion, NULL will be returned and a
+ python exception will be set. */
+gdb::unique_xmalloc_ptr<char>
unicode_to_target_string (PyObject *unicode_str)
{
return unicode_to_encoded_string (unicode_str,
}
/* Converts a python string (8-bit or unicode) to a target string in
- the target's charset. Returns NULL on error, with a python exception set.
-
- The caller is responsible for xfree'ing the string. */
-char *
+ the target's charset. Returns NULL on error, with a python
+ exception set. */
+gdb::unique_xmalloc_ptr<char>
python_string_to_target_string (PyObject *obj)
{
- PyObject *str;
- char *result;
-
- str = python_string_to_unicode (obj);
+ gdbpy_ref<> str (python_string_to_unicode (obj));
if (str == NULL)
return NULL;
- result = unicode_to_target_string (str);
- Py_DECREF (str);
- return result;
+ return unicode_to_target_string (str.get ());
}
/* Converts a python string (8-bit or unicode) to a target string in the
PyObject *
python_string_to_target_python_string (PyObject *obj)
{
- PyObject *str;
- PyObject *result;
-
- str = python_string_to_unicode (obj);
+ gdbpy_ref<> str (python_string_to_unicode (obj));
if (str == NULL)
return NULL;
- result = unicode_to_target_python_string (str);
- Py_DECREF (str);
- return result;
+ return unicode_to_target_python_string (str.get ());
}
/* Converts a python string (8-bit or unicode) to a target string in
- the host's charset. Returns NULL on error, with a python exception set.
-
- The caller is responsible for xfree'ing the string. */
-char *
+ the host's charset. Returns NULL on error, with a python exception
+ set. */
+gdb::unique_xmalloc_ptr<char>
python_string_to_host_string (PyObject *obj)
{
- PyObject *str;
- char *result;
-
- str = python_string_to_unicode (obj);
+ gdbpy_ref<> str (python_string_to_unicode (obj));
if (str == NULL)
return NULL;
- result = unicode_to_encoded_string (str, host_charset ());
- Py_DECREF (str);
- return result;
+ return unicode_to_encoded_string (str.get (), host_charset ());
}
-/* Converts a target string of LENGTH bytes in the target's charset to a
- Python Unicode string. If LENGTH is -1, convert until a null byte is found.
+/* Convert a host string to a python string. */
- Returns NULL on error, with a python exception set. */
PyObject *
-target_string_to_unicode (const gdb_byte *str, int length)
+host_string_to_python_string (const char *str)
{
- if (length == -1)
- length = strlen (str);
-
- return PyUnicode_Decode (str, length, target_charset (python_gdbarch), NULL);
+ return PyString_Decode (str, strlen (str), host_charset (), NULL);
}
/* Return true if OBJ is a Python string or unicode object, false
}
/* Return the string representation of OBJ, i.e., str (obj).
- Space for the result is malloc'd, the caller must free.
If the result is NULL a python error occurred, the caller must clear it. */
-char *
+gdb::unique_xmalloc_ptr<char>
gdbpy_obj_to_string (PyObject *obj)
{
- PyObject *str_obj = PyObject_Str (obj);
+ gdbpy_ref<> str_obj (PyObject_Str (obj));
if (str_obj != NULL)
{
+ gdb::unique_xmalloc_ptr<char> msg;
+
#ifdef IS_PY3K
- char *msg = python_string_to_host_string (str_obj);
+ msg = python_string_to_host_string (str_obj.get ());
#else
- char *msg = xstrdup (PyString_AsString (str_obj));
+ msg.reset (xstrdup (PyString_AsString (str_obj.get ())));
#endif
- Py_DECREF (str_obj);
return msg;
}
/* Return the string representation of the exception represented by
TYPE, VALUE which is assumed to have been obtained with PyErr_Fetch,
i.e., the error indicator is currently clear.
- Space for the result is malloc'd, the caller must free.
If the result is NULL a python error occurred, the caller must clear it. */
-char *
+gdb::unique_xmalloc_ptr<char>
gdbpy_exception_to_string (PyObject *ptype, PyObject *pvalue)
{
- char *str;
-
/* There are a few cases to consider.
For example:
pvalue is a string when PyErr_SetString is used.
gdb.GdbError ("message"). */
if (pvalue && pvalue != Py_None)
- str = gdbpy_obj_to_string (pvalue);
+ return gdbpy_obj_to_string (pvalue);
else
- str = gdbpy_obj_to_string (ptype);
-
- return str;
+ return gdbpy_obj_to_string (ptype);
}
/* Convert a GDB exception to the appropriate Python exception.
-
- This sets the Python error indicator, and returns NULL. */
-PyObject *
+ This sets the Python error indicator. */
+
+void
gdbpy_convert_exception (struct gdb_exception exception)
{
PyObject *exc_class;
else
exc_class = gdbpy_gdb_error;
- return PyErr_Format (exc_class, "%s", exception.message);
+ 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
- function can also throw GDB exceptions.
+ Returns 0 on success or -1 on failure, with a Python exception set.
*/
int
get_addr_from_python (PyObject *obj, CORE_ADDR *addr)
{
if (gdbpy_is_value_object (obj))
- *addr = value_as_address (value_object_to_value (obj));
+ {
+
+ TRY
+ {
+ *addr = value_as_address (value_object_to_value (obj));
+ }
+ CATCH (except, RETURN_MASK_ALL)
+ {
+ GDB_PY_SET_HANDLE_EXCEPTION (except);
+ }
+ END_CATCH
+ }
else
{
- PyObject *num = PyNumber_Long (obj);
+ gdbpy_ref<> num (PyNumber_Long (obj));
gdb_py_ulongest val;
if (num == NULL)
- return 0;
+ return -1;
- val = gdb_py_long_as_ulongest (num);
- Py_XDECREF (num);
+ val = gdb_py_long_as_ulongest (num.get ());
if (PyErr_Occurred ())
- return 0;
+ return -1;
if (sizeof (val) > sizeof (CORE_ADDR) && ((CORE_ADDR) val) != val)
{
PyErr_SetString (PyExc_ValueError,
_("Overflow converting to address."));
- return 0;
+ return -1;
}
*addr = val;
}
- return 1;
+ return 0;
}
/* Convert a LONGEST to the appropriate Python object -- either an
gdb_py_generic_dict (PyObject *self, void *closure)
{
PyObject *result;
- PyTypeObject *type_obj = closure;
+ PyTypeObject *type_obj = (PyTypeObject *) closure;
char *raw_ptr;
raw_ptr = (char *) self + type_obj->tp_dictoffset;
Py_INCREF (result);
return result;
}
+
+/* Like PyModule_AddObject, but does not steal a reference to
+ OBJECT. */
+
+int
+gdb_pymodule_addobject (PyObject *module, const char *name, PyObject *object)
+{
+ int result;
+
+ Py_INCREF (object);
+ /* Python 2.4 did not have a 'const' here. */
+ result = PyModule_AddObject (module, (char *) name, object);
+ if (result < 0)
+ Py_DECREF (object);
+ return result;
+}
+
+/* Handle a Python exception when the special gdb.GdbError treatment
+ is desired. This should only be called when an exception is set.
+ If the exception is a gdb.GdbError, throw a gdb exception with the
+ exception text. For other exceptions, print the Python stack and
+ then throw a gdb exception. */
+
+void
+gdbpy_handle_exception ()
+{
+ PyObject *ptype, *pvalue, *ptraceback;
+
+ PyErr_Fetch (&ptype, &pvalue, &ptraceback);
+
+ /* Try to fetch an error message contained within ptype, pvalue.
+ When fetching the error message we need to make our own copy,
+ we no longer own ptype, pvalue after the call to PyErr_Restore. */
+
+ gdb::unique_xmalloc_ptr<char>
+ msg (gdbpy_exception_to_string (ptype, pvalue));
+
+ if (msg == NULL)
+ {
+ /* An error occurred computing the string representation of the
+ error message. This is rare, but we should inform the user. */
+ printf_filtered (_("An error occurred in Python "
+ "and then another occurred computing the "
+ "error message.\n"));
+ gdbpy_print_stack ();
+ }
+
+ /* Don't print the stack for gdb.GdbError exceptions.
+ It is generally used to flag user errors.
+
+ We also don't want to print "Error occurred in Python command"
+ for user errors. However, a missing message for gdb.GdbError
+ exceptions is arguably a bug, so we flag it as such. */
+
+ if (! PyErr_GivenExceptionMatches (ptype, gdbpy_gdberror_exc)
+ || msg == NULL || *msg == '\0')
+ {
+ PyErr_Restore (ptype, pvalue, ptraceback);
+ gdbpy_print_stack ();
+ if (msg != NULL && *msg != '\0')
+ error (_("Error occurred in Python: %s"), msg.get ());
+ else
+ error (_("Error occurred in Python."));
+ }
+ else
+ {
+ Py_XDECREF (ptype);
+ Py_XDECREF (pvalue);
+ Py_XDECREF (ptraceback);
+ error ("%s", msg.get ());
+ }
+}