diff options
author | Andrew Burgess <andrew.burgess@embecosm.com> | 2020-06-07 10:08:01 +0100 |
---|---|---|
committer | Andrew Burgess <andrew.burgess@embecosm.com> | 2020-07-06 15:06:06 +0100 |
commit | 64cb3757a9df273b990adf4f28333324edc3cae8 (patch) | |
tree | bd2f7edb9b8da04b018d532afa24b489f020499d /gdb/python | |
parent | 0f767f942b027df6de60c42ed0e4a1dac7d0fd4b (diff) | |
download | fsf-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.c | 18 | ||||
-rw-r--r-- | gdb/python/py-registers.c | 195 | ||||
-rw-r--r-- | gdb/python/python-internal.h | 1 |
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, ®group_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, + ®group_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 *) ®ister_descriptor_object_type) < 0) return -1; + reggroup_iterator_object_type.tp_new = PyType_GenericNew; + if (PyType_Ready (®group_iterator_object_type) < 0) + return -1; + if (gdb_pymodule_addobject + (gdb_module, "RegisterGroupsIterator", + (PyObject *) ®group_iterator_object_type) < 0) + return -1; + + reggroup_object_type.tp_new = PyType_GenericNew; + if (PyType_Ready (®group_object_type) < 0) + return -1; + if (gdb_pymodule_addobject + (gdb_module, "RegisterGroup", + (PyObject *) ®group_object_type) < 0) + return -1; + register_descriptor_iterator_object_type.tp_new = PyType_GenericNew; if (PyType_Ready (®ister_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);; |