gdb: Add a find method for RegisterDescriptorIterator
authorAndrew Burgess <andrew.burgess@embecosm.com>
Wed, 22 Jul 2020 13:02:30 +0000 (14:02 +0100)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Tue, 28 Jul 2020 09:27:53 +0000 (10:27 +0100)
Adds a new method 'find' to the gdb.RegisterDescriptorIterator class,
this allows gdb.RegisterDescriptor objects to be looked up directly by
register name rather than having to iterate over all registers.

This will be of use for a later commit.

I've documented the new function in the manual, but I don't think a
NEWS entry is required here, as, since the last release, the whole
register descriptor mechanism is new, and is already mentioned in the
NEWS file.

gdb/ChangeLog:

* 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.

gdb/testsuite/ChangeLog:

* gdb.python/py-arch-reg-names.exp: Add additional tests.

gdb/doc/ChangeLog:

* python.texi (Registers In Python): Document new find function.

gdb/ChangeLog
gdb/doc/ChangeLog
gdb/doc/python.texi
gdb/python/py-registers.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.python/py-arch-reg-names.exp

index fc2d0b130c5755c4950da208640d1a5cc42858da..106dfcdac816d58969e07d4e40c571b7c1458cf3 100644 (file)
@@ -1,3 +1,12 @@
+2020-07-28  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * 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  <jhb@FreeBSD.org>
 
        * fbsd-nat.h: Include <osreldate.h>.  Define USE_SIGTRAP_SIGINFO
index 7e530c044754069a5df6996f95577f40c0d55b87..1074511bcbb4e99bcb40180b9edb2cd9105299d0 100644 (file)
@@ -1,3 +1,7 @@
+2020-07-28  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * python.texi (Registers In Python): Document new find function.
+
 2020-07-22  Kevin Buettner  <kevinb@redhat.com>
 
        * gdb.texinfo (Maintenance Commands): Add documentation for
index 4fb994ca6d95d17dbdc7bbd708a4be7ed5aeb824..c9dc1ff3b7145c181143ffb2d3215a9698c80309 100644 (file)
@@ -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
index f64ca3c401b010d00fa71d52fca8d7a361a4e9de..fffe3ecb1e6476232596326f678b9093e30abd0a 100644 (file)
@@ -23,6 +23,7 @@
 #include "disasm.h"
 #include "reggroups.h"
 #include "python-internal.h"
+#include "user-regs.h"
 #include <unordered_map>
 
 /* 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,
+                                       &register_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 *) &register_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[] = {
index 98a35cf3b90267d79dd87d859335497d98fd00de..a4b8dfeb8da2d5ba72a19048ad22f07de989ca87 100644 (file)
@@ -1,3 +1,7 @@
+2020-07-28  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * gdb.python/py-arch-reg-names.exp: Add additional tests.
+
 2020-07-25  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        PR fortran/23051
index 8dd34ef5fd24f41bdf498873676613bf822865bd..891da1b6af5ebaf85ce800807e3a77532afca4e4 100644 (file)
@@ -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