aboutsummaryrefslogtreecommitdiff
path: root/gdb/python
diff options
context:
space:
mode:
authorAndrew Burgess <andrew.burgess@embecosm.com>2020-06-07 10:08:01 +0100
committerAndrew Burgess <andrew.burgess@embecosm.com>2020-07-06 15:06:06 +0100
commit64cb3757a9df273b990adf4f28333324edc3cae8 (patch)
treebd2f7edb9b8da04b018d532afa24b489f020499d /gdb/python
parent0f767f942b027df6de60c42ed0e4a1dac7d0fd4b (diff)
downloadfsf-binutils-gdb-64cb3757a9df273b990adf4f28333324edc3cae8.zip
fsf-binutils-gdb-64cb3757a9df273b990adf4f28333324edc3cae8.tar.gz
fsf-binutils-gdb-64cb3757a9df273b990adf4f28333324edc3cae8.tar.bz2
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.
Diffstat (limited to 'gdb/python')
-rw-r--r--gdb/python/py-arch.c18
-rw-r--r--gdb/python/py-registers.c195
-rw-r--r--gdb/python/python-internal.h1
3 files changed, 214 insertions, 0 deletions
diff --git a/gdb/python/py-arch.c b/gdb/python/py-arch.c
index 15f9f50..d9eaf81 100644
--- a/gdb/python/py-arch.c
+++ b/gdb/python/py-arch.c
@@ -248,6 +248,20 @@ archpy_registers (PyObject *self, PyObject *args, PyObject *kw)
return gdbpy_new_register_descriptor_iterator (gdbarch, group_name);
}
+/* Implementation of gdb.Architecture.register_groups (self) -> Iterator.
+ Returns an iterator that will give up all valid register groups in the
+ architecture SELF. */
+
+static PyObject *
+archpy_register_groups (PyObject *self, PyObject *args)
+{
+ struct gdbarch *gdbarch = NULL;
+
+ /* Extract the gdbarch from the self object. */
+ ARCHPY_REQUIRE_VALID (self, gdbarch);
+ return gdbpy_new_reggroup_iterator (gdbarch);
+}
+
/* Initializes the Architecture class in the gdb module. */
int
@@ -276,6 +290,10 @@ END_PC." },
"registers ([ group-name ]) -> Iterator.\n\
Return an iterator of register descriptors for the registers in register\n\
group GROUP-NAME." },
+ { "register_groups", archpy_register_groups,
+ METH_NOARGS,
+ "register_groups () -> Iterator.\n\
+Return an iterator over all of the register groups in this architecture." },
{NULL} /* Sentinel */
};
diff --git a/gdb/python/py-registers.c b/gdb/python/py-registers.c
index 6ccd17e..db0fe37 100644
--- a/gdb/python/py-registers.c
+++ b/gdb/python/py-registers.c
@@ -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 */
+};
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 758dc55..1e6dcf3 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -475,6 +475,7 @@ PyObject *gdbarch_to_arch_object (struct gdbarch *gdbarch);
PyObject *gdbpy_new_register_descriptor_iterator (struct gdbarch *gdbarch,
const char *group_name);
+PyObject *gdbpy_new_reggroup_iterator (struct gdbarch *gdbarch);
gdbpy_ref<thread_object> create_thread_object (struct thread_info *tp);
gdbpy_ref<> thread_to_thread_object (thread_info *thr);;