/* Python interface to program spaces.
- Copyright (C) 2010-2013 Free Software Foundation, Inc.
+ Copyright (C) 2010-2018 Free Software Foundation, Inc.
This file is part of GDB.
#include "objfiles.h"
#include "language.h"
#include "arch-utils.h"
+#include "py-ref.h"
typedef struct
{
/* The corresponding pspace. */
struct program_space *pspace;
+ /* Dictionary holding user-added attributes.
+ This is the __dict__ attribute of the object. */
+ PyObject *dict;
+
/* The pretty-printer list of functions. */
PyObject *printers;
/* The frame filter list of functions. */
PyObject *frame_filters;
+
+ /* The frame unwinder list. */
+ PyObject *frame_unwinders;
+
/* The type-printer list. */
PyObject *type_printers;
+
+ /* The debug method list. */
+ PyObject *xmethods;
} pspace_object;
-static PyTypeObject pspace_object_type;
+extern PyTypeObject pspace_object_type
+ CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("pspace_object");
static const struct program_space_data *pspy_pspace_data_key;
struct objfile *objfile = obj->pspace->symfile_object_file;
if (objfile)
- return PyString_Decode (objfile->name, strlen (objfile->name),
- host_charset (), NULL);
+ return host_string_to_python_string (objfile_name (objfile));
}
Py_RETURN_NONE;
}
{
pspace_object *ps_self = (pspace_object *) self;
+ Py_XDECREF (ps_self->dict);
Py_XDECREF (ps_self->printers);
Py_XDECREF (ps_self->frame_filters);
+ Py_XDECREF (ps_self->frame_unwinders);
Py_XDECREF (ps_self->type_printers);
+ Py_XDECREF (ps_self->xmethods);
Py_TYPE (self)->tp_free (self);
}
-static PyObject *
-pspy_new (PyTypeObject *type, PyObject *args, PyObject *keywords)
+/* Initialize a pspace_object.
+ The result is a boolean indicating success. */
+
+static int
+pspy_initialize (pspace_object *self)
{
- pspace_object *self = (pspace_object *) type->tp_alloc (type, 0);
+ self->pspace = NULL;
- if (self)
- {
- self->pspace = NULL;
+ self->dict = PyDict_New ();
+ if (self->dict == NULL)
+ return 0;
- self->printers = PyList_New (0);
- if (!self->printers)
- {
- Py_DECREF (self);
- return NULL;
- }
+ self->printers = PyList_New (0);
+ if (self->printers == NULL)
+ return 0;
- self->frame_filters = PyDict_New ();
- if (!self->frame_filters)
- {
- Py_DECREF (self);
- return NULL;
- }
+ self->frame_filters = PyDict_New ();
+ if (self->frame_filters == NULL)
+ return 0;
- self->type_printers = PyList_New (0);
- if (!self->type_printers)
- {
- Py_DECREF (self);
- return NULL;
- }
+ self->frame_unwinders = PyList_New (0);
+ if (self->frame_unwinders == NULL)
+ return 0;
+
+ self->type_printers = PyList_New (0);
+ if (self->type_printers == NULL)
+ return 0;
+
+ self->xmethods = PyList_New (0);
+ if (self->xmethods == NULL)
+ return 0;
+
+ return 1;
+}
+
+static PyObject *
+pspy_new (PyTypeObject *type, PyObject *args, PyObject *keywords)
+{
+ gdbpy_ref<pspace_object> self ((pspace_object *) type->tp_alloc (type, 0));
+
+ if (self != NULL)
+ {
+ if (!pspy_initialize (self.get ()))
+ return NULL;
}
- return (PyObject *) self;
+
+ return (PyObject *) self.release ();
}
PyObject *
return 0;
}
+/* Return the list of the frame unwinders for this program space. */
+
+PyObject *
+pspy_get_frame_unwinders (PyObject *o, void *ignore)
+{
+ pspace_object *self = (pspace_object *) o;
+
+ Py_INCREF (self->frame_unwinders);
+ return self->frame_unwinders;
+}
+
+/* Set this program space's list of the unwinders to UNWINDERS. */
+
+static int
+pspy_set_frame_unwinders (PyObject *o, PyObject *unwinders, void *ignore)
+{
+ PyObject *tmp;
+ pspace_object *self = (pspace_object *) o;
+
+ if (!unwinders)
+ {
+ PyErr_SetString (PyExc_TypeError,
+ "cannot delete the frame unwinders list");
+ return -1;
+ }
+
+ if (!PyList_Check (unwinders))
+ {
+ PyErr_SetString (PyExc_TypeError,
+ "the frame unwinders attribute must be a list");
+ return -1;
+ }
+
+ /* Take care in case the LHS and RHS are related somehow. */
+ tmp = self->frame_unwinders;
+ Py_INCREF (unwinders);
+ self->frame_unwinders = unwinders;
+ Py_XDECREF (tmp);
+
+ return 0;
+}
+
/* Get the 'type_printers' attribute. */
static PyObject *
return self->type_printers;
}
+/* Get the 'xmethods' attribute. */
+
+PyObject *
+pspy_get_xmethods (PyObject *o, void *ignore)
+{
+ pspace_object *self = (pspace_object *) o;
+
+ Py_INCREF (self->xmethods);
+ return self->xmethods;
+}
+
/* Set the 'type_printers' attribute. */
static int
static void
py_free_pspace (struct program_space *pspace, void *datum)
{
- struct cleanup *cleanup;
- pspace_object *object = datum;
- struct gdbarch *arch = get_current_arch ();
-
- cleanup = ensure_python_env (arch, current_language);
+ /* This is a fiction, but we're in a nasty spot: The pspace is in the
+ process of being deleted, we can't rely on anything in it. Plus
+ this is one time when the current program space and current inferior
+ are not in sync: All inferiors that use PSPACE may no longer exist.
+ We don't need to do much here, and since "there is always an inferior"
+ using target_gdbarch suffices.
+ Note: We cannot call get_current_arch because it may try to access
+ the target, which may involve accessing data in the pspace currently
+ being deleted. */
+ struct gdbarch *arch = target_gdbarch ();
+
+ gdbpy_enter enter_py (arch, current_language);
+ gdbpy_ref<pspace_object> object ((pspace_object *) datum);
object->pspace = NULL;
- Py_DECREF ((PyObject *) object);
- do_cleanups (cleanup);
}
/* Return a borrowed reference to the Python object of type Pspace
PyObject *
pspace_to_pspace_object (struct program_space *pspace)
{
- pspace_object *object;
-
- object = program_space_data (pspace, pspy_pspace_data_key);
- if (!object)
+ gdbpy_ref<pspace_object> object
+ ((pspace_object *) program_space_data (pspace, pspy_pspace_data_key));
+ if (object == NULL)
{
- object = PyObject_New (pspace_object, &pspace_object_type);
- if (object)
+ object.reset (PyObject_New (pspace_object, &pspace_object_type));
+ if (object != NULL)
{
- object->pspace = pspace;
+ if (!pspy_initialize (object.get ()))
+ return NULL;
- object->printers = PyList_New (0);
- if (!object->printers)
- {
- Py_DECREF (object);
- return NULL;
- }
-
- object->frame_filters = PyDict_New ();
- if (!object->frame_filters)
- {
- Py_DECREF (object);
- return NULL;
- }
-
- object->type_printers = PyList_New (0);
- if (!object->type_printers)
- {
- Py_DECREF (object);
- return NULL;
- }
-
- set_program_space_data (pspace, pspy_pspace_data_key, object);
+ object->pspace = pspace;
+ set_program_space_data (pspace, pspy_pspace_data_key, object.get ());
}
}
- return (PyObject *) object;
+ return (PyObject *) object.release ();
}
-void
+int
gdbpy_initialize_pspace (void)
{
pspy_pspace_data_key
= register_program_space_data_with_cleanup (NULL, py_free_pspace);
if (PyType_Ready (&pspace_object_type) < 0)
- return;
+ return -1;
- Py_INCREF (&pspace_object_type);
- PyModule_AddObject (gdb_module, "Progspace",
- (PyObject *) &pspace_object_type);
+ return gdb_pymodule_addobject (gdb_module, "Progspace",
+ (PyObject *) &pspace_object_type);
}
\f
-static PyGetSetDef pspace_getset[] =
+static gdb_PyGetSetDef pspace_getset[] =
{
+ { "__dict__", gdb_py_generic_dict, NULL,
+ "The __dict__ for this progspace.", &pspace_object_type },
{ "filename", pspy_get_filename, NULL,
"The progspace's main filename, or None.", NULL },
{ "pretty_printers", pspy_get_printers, pspy_set_printers,
"Pretty printers.", NULL },
{ "frame_filters", pspy_get_frame_filters, pspy_set_frame_filters,
"Frame filters.", NULL },
+ { "frame_unwinders", pspy_get_frame_unwinders, pspy_set_frame_unwinders,
+ "Frame unwinders.", NULL },
{ "type_printers", pspy_get_type_printers, pspy_set_type_printers,
"Type printers.", NULL },
+ { "xmethods", pspy_get_xmethods, NULL,
+ "Debug methods.", NULL },
{ NULL }
};
-static PyTypeObject pspace_object_type =
+PyTypeObject pspace_object_type =
{
PyVarObject_HEAD_INIT (NULL, 0)
"gdb.Progspace", /*tp_name*/
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
- 0, /* tp_dictoffset */
+ offsetof (pspace_object, dict), /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
pspy_new, /* tp_new */