gdb/python: New method to access list of register groups

Add a new method gdb.Architecture.register_groups which returns a new
object of type gdb.RegisterGroupsIterator.  This new iterator then
returns objects of type gdb.RegisterGroup.

Each gdb.RegisterGroup object just wraps a single reggroup pointer,
and (currently) has just one read-only property 'name' that is a
string, the name of the register group.

As with the previous commit (adding gdb.RegisterDescriptor) I made
gdb.RegisterGroup an object rather than just a string in case we want
to add additional properties in the future.

gdb/ChangeLog:

	* NEWS: Mention additions to Python API.
	* python/py-arch.c (archpy_register_groups): New function.
	(arch_object_methods): Add 'register_groups' method.
	* python/py-registers.c (reggroup_iterator_object): New struct.
	(reggroup_object): New struct.
	(gdbpy_new_reggroup): New function.
	(gdbpy_reggroup_to_string): New function.
	(gdbpy_reggroup_name): New function.
	(gdbpy_reggroup_iter): New function.
	(gdbpy_reggroup_iter_next): New function.
	(gdbpy_new_reggroup_iterator): New function
	(gdbpy_initialize_registers): Register new types.
	(reggroup_iterator_object_type): Define new Python type.
	(gdbpy_reggroup_getset): New static global.
	(reggroup_object_type): Define new Python type.
	* python/python-internal.h

gdb/testsuite/ChangeLog:

	* gdb.python/py-arch-reg-groups.exp: New file.

gdb/doc/ChangeLog:

	* gdb.texi (Registers): Add @anchor for 'info registers
	<reggroup>' command.
	* python.texi (Architectures In Python): Document new
	register_groups method.
	(Registers In Python): Document two new object types related to
	register groups.
This commit is contained in:
Andrew Burgess
2020-06-07 10:08:01 +01:00
parent 0f767f942b
commit 64cb3757a9
10 changed files with 371 additions and 0 deletions

View File

@ -56,6 +56,67 @@ typedef struct {
extern PyTypeObject register_descriptor_object_type
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("register_descriptor_object");
/* Structure for iterator over register groups. */
typedef struct {
PyObject_HEAD
/* The last register group returned. Initially this will be NULL. */
struct reggroup *reggroup;
/* Pointer back to the architecture we're finding registers for. */
struct gdbarch *gdbarch;
} reggroup_iterator_object;
extern PyTypeObject reggroup_iterator_object_type
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("reggroup_iterator_object");
/* A register group object. */
typedef struct {
PyObject_HEAD
/* The register group being described. */
struct reggroup *reggroup;
} reggroup_object;
extern PyTypeObject reggroup_object_type
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("reggroup_object");
/* Create a new gdb.RegisterGroup object wrapping REGGROUP. */
static PyObject *
gdbpy_new_reggroup (struct reggroup *reggroup)
{
/* Create a new object and fill in its details. */
reggroup_object *group
= PyObject_New (reggroup_object, &reggroup_object_type);
if (group == NULL)
return NULL;
group->reggroup = reggroup;
return (PyObject *) group;
}
/* Convert a gdb.RegisterGroup to a string, it just returns the name of
the register group. */
static PyObject *
gdbpy_reggroup_to_string (PyObject *self)
{
reggroup_object *group = (reggroup_object *) self;
struct reggroup *reggroup = group->reggroup;
const char *name = reggroup_name (reggroup);
return PyString_FromString (name);
}
/* Implement gdb.RegisterGroup.name (self) -> String.
Return a string that is the name of this register group. */
static PyObject *
gdbpy_reggroup_name (PyObject *self, void *closure)
{
return gdbpy_reggroup_to_string (self);
}
/* Create an return a new gdb.RegisterDescriptor object. */
static PyObject *
gdbpy_new_register_descriptor (struct gdbarch *gdbarch,
@ -96,6 +157,54 @@ gdbpy_register_descriptor_name (PyObject *self, void *closure)
return gdbpy_register_descriptor_to_string (self);
}
/* Return a reference to the gdb.RegisterGroupsIterator object. */
static PyObject *
gdbpy_reggroup_iter (PyObject *self)
{
Py_INCREF (self);
return self;
}
/* Return the next gdb.RegisterGroup object from the iterator. */
static PyObject *
gdbpy_reggroup_iter_next (PyObject *self)
{
reggroup_iterator_object *iter_obj
= (reggroup_iterator_object *) self;
struct gdbarch *gdbarch = iter_obj->gdbarch;
struct reggroup *next_group = reggroup_next (gdbarch, iter_obj->reggroup);
if (next_group == NULL)
{
PyErr_SetString (PyExc_StopIteration, _("No more groups"));
return NULL;
}
iter_obj->reggroup = next_group;
return gdbpy_new_reggroup (iter_obj->reggroup);
}
/* Return a new gdb.RegisterGroupsIterator over all the register groups in
GDBARCH. */
PyObject *
gdbpy_new_reggroup_iterator (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != nullptr);
/* Create a new object and fill in its internal state. */
reggroup_iterator_object *iter
= PyObject_New (reggroup_iterator_object,
&reggroup_iterator_object_type);
if (iter == NULL)
return NULL;
iter->reggroup = NULL;
iter->gdbarch = gdbarch;
return (PyObject *) iter;
}
/* Create and return a new gdb.RegisterDescriptorIterator object which
will iterate over all registers in GROUP_NAME for GDBARCH. If
GROUP_NAME is either NULL or the empty string then the ALL_REGGROUP is
@ -190,6 +299,22 @@ gdbpy_initialize_registers ()
(PyObject *) &register_descriptor_object_type) < 0)
return -1;
reggroup_iterator_object_type.tp_new = PyType_GenericNew;
if (PyType_Ready (&reggroup_iterator_object_type) < 0)
return -1;
if (gdb_pymodule_addobject
(gdb_module, "RegisterGroupsIterator",
(PyObject *) &reggroup_iterator_object_type) < 0)
return -1;
reggroup_object_type.tp_new = PyType_GenericNew;
if (PyType_Ready (&reggroup_object_type) < 0)
return -1;
if (gdb_pymodule_addobject
(gdb_module, "RegisterGroup",
(PyObject *) &reggroup_object_type) < 0)
return -1;
register_descriptor_iterator_object_type.tp_new = PyType_GenericNew;
if (PyType_Ready (&register_descriptor_iterator_object_type) < 0)
return -1;
@ -267,3 +392,73 @@ PyTypeObject register_descriptor_object_type = {
0, /*tp_members */
gdbpy_register_descriptor_getset /*tp_getset */
};
PyTypeObject reggroup_iterator_object_type = {
PyVarObject_HEAD_INIT (NULL, 0)
"gdb.RegisterGroupsIterator", /*tp_name*/
sizeof (reggroup_iterator_object), /*tp_basicsize*/
0, /*tp_itemsize*/
0, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/
"GDB register groups iterator object", /*tp_doc */
0, /*tp_traverse */
0, /*tp_clear */
0, /*tp_richcompare */
0, /*tp_weaklistoffset */
gdbpy_reggroup_iter, /*tp_iter */
gdbpy_reggroup_iter_next, /*tp_iternext */
0 /*tp_methods */
};
static gdb_PyGetSetDef gdbpy_reggroup_getset[] = {
{ "name", gdbpy_reggroup_name, NULL,
"The name of this register group.", NULL },
{ NULL } /* Sentinel */
};
PyTypeObject reggroup_object_type = {
PyVarObject_HEAD_INIT (NULL, 0)
"gdb.RegisterGroup", /*tp_name*/
sizeof (reggroup_object), /*tp_basicsize*/
0, /*tp_itemsize*/
0, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
gdbpy_reggroup_to_string, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
"GDB register group object", /*tp_doc */
0, /*tp_traverse */
0, /*tp_clear */
0, /*tp_richcompare */
0, /*tp_weaklistoffset */
0, /*tp_iter */
0, /*tp_iternext */
0, /*tp_methods */
0, /*tp_members */
gdbpy_reggroup_getset /*tp_getset */
};