diff --git a/gdb/ChangeLog b/gdb/ChangeLog index fc2d0b130c5..106dfcdac81 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,12 @@ +2020-07-28 Andrew Burgess + + * python/py-registers.c: Add 'user-regs.h' include. + (register_descriptor_iter_find): New function. + (register_descriptor_iterator_object_methods): New static global + methods array. + (register_descriptor_iterator_object_type): Add pointer to methods + array. + 2020-07-27 John Baldwin * fbsd-nat.h: Include . Define USE_SIGTRAP_SIGINFO diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 7e530c04475..1074511bcbb 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,7 @@ +2020-07-28 Andrew Burgess + + * python.texi (Registers In Python): Document new find function. + 2020-07-22 Kevin Buettner * gdb.texinfo (Maintenance Commands): Add documentation for diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index 4fb994ca6d9..c9dc1ff3b71 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -5755,6 +5755,15 @@ A @code{gdb.RegisterDescriptor} has the following read-only properties: The name of this register. @end defvar +It is also possible to lookup a register descriptor based on its name +using the following @code{gdb.RegisterDescriptorIterator} function: + +@defun RegisterDescriptorIterator.find (@var{name}) +Takes @var{name} as an argument, which must be a string, and returns a +@code{gdb.RegisterDescriptor} for the register with that name, or +@code{None} if there is no register with that name. +@end defun + Python code can also request from a @code{gdb.Architecture} information about the set of register groups available on a given architecture diff --git a/gdb/python/py-registers.c b/gdb/python/py-registers.c index f64ca3c401b..fffe3ecb1e6 100644 --- a/gdb/python/py-registers.c +++ b/gdb/python/py-registers.c @@ -23,6 +23,7 @@ #include "disasm.h" #include "reggroups.h" #include "python-internal.h" +#include "user-regs.h" #include /* Token to access per-gdbarch data related to register descriptors. */ @@ -337,6 +338,38 @@ gdbpy_register_descriptor_iter_next (PyObject *self) while (true); } +/* Implement: + + gdb.RegisterDescriptorIterator.find (self, name) -> gdb.RegisterDescriptor + + Look up a descriptor for register with NAME. If no matching register is + found then return None. */ + +static PyObject * +register_descriptor_iter_find (PyObject *self, PyObject *args, PyObject *kw) +{ + static const char *keywords[] = { "name", NULL }; + const char *register_name = NULL; + + register_descriptor_iterator_object *iter_obj + = (register_descriptor_iterator_object *) self; + struct gdbarch *gdbarch = iter_obj->gdbarch; + + if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s", keywords, + ®ister_name)) + return NULL; + + if (register_name != NULL && *register_name != '\0') + { + int regnum = user_reg_map_name_to_regnum (gdbarch, register_name, + strlen (register_name)); + if (regnum >= 0) + return gdbpy_get_register_descriptor (gdbarch, regnum).release (); + } + + Py_RETURN_NONE; +} + /* Initializes the new Python classes from this file in the gdb module. */ int @@ -377,6 +410,15 @@ gdbpy_initialize_registers () (PyObject *) ®ister_descriptor_iterator_object_type)); } +static PyMethodDef register_descriptor_iterator_object_methods [] = { + { "find", (PyCFunction) register_descriptor_iter_find, + METH_VARARGS | METH_KEYWORDS, + "registers (name) -> gdb.RegisterDescriptor.\n\ +Return a register descriptor for the register NAME, or None if no register\n\ +with that name exists in this iterator." }, + {NULL} /* Sentinel */ +}; + PyTypeObject register_descriptor_iterator_object_type = { PyVarObject_HEAD_INIT (NULL, 0) "gdb.RegisterDescriptorIterator", /*tp_name*/ @@ -405,7 +447,7 @@ PyTypeObject register_descriptor_iterator_object_type = { 0, /*tp_weaklistoffset */ gdbpy_register_descriptor_iter, /*tp_iter */ gdbpy_register_descriptor_iter_next, /*tp_iternext */ - 0 /*tp_methods */ + register_descriptor_iterator_object_methods /*tp_methods */ }; static gdb_PyGetSetDef gdbpy_register_descriptor_getset[] = { diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 98a35cf3b90..a4b8dfeb8da 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2020-07-28 Andrew Burgess + + * gdb.python/py-arch-reg-names.exp: Add additional tests. + 2020-07-25 Andrew Burgess PR fortran/23051 diff --git a/gdb/testsuite/gdb.python/py-arch-reg-names.exp b/gdb/testsuite/gdb.python/py-arch-reg-names.exp index 8dd34ef5fd2..891da1b6af5 100644 --- a/gdb/testsuite/gdb.python/py-arch-reg-names.exp +++ b/gdb/testsuite/gdb.python/py-arch-reg-names.exp @@ -104,3 +104,18 @@ gdb_py_test_silent_cmd \ " raise gdb.GdbError (\"miss-matched objects\")" \ "\004" ] \ "check names and objects match" 1 + +# Ensure that the '.find' method on the iterator returns the same +# Python object as we got from the iterator's list of descriptors. +gdb_py_test_silent_cmd \ + [multi_line \ + "python" \ + "def check_regs (arch, regs):" \ + " for r in (regs):" \ + " if (arch.registers ().find (r.name) != r):" \ + " raise gdb.GdbError (\"object miss-match\")" \ + "end" ] \ + "build check_obj function" 0 +gdb_py_test_silent_cmd \ + "python check_regs (arch, arch.registers (\"general\"))" \ + "ensure find gets expected descriptors" 1