aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog11
-rw-r--r--gdb/python/py-registers.c61
-rw-r--r--gdb/testsuite/ChangeLog4
-rw-r--r--gdb/testsuite/gdb.python/py-arch-reg-names.exp19
4 files changed, 82 insertions, 13 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index b15a3a4..e2d2e15 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,14 @@
+2020-07-21 Andrew Burgess <andrew.burgess@embecosm.com>
+
+ * python/py-registers.c (gdbpy_register_object_data): New static
+ global.
+ (gdbpy_register_object_data_init): New function.
+ (gdbpy_new_register_descriptor): Renamed to...
+ (gdbpy_get_register_descriptor): ...this, and update to reuse
+ existing register descriptors where possible.
+ (gdbpy_register_descriptor_iter_next): Update.
+ (gdbpy_initialize_registers): Register new gdbarch data.
+
2020-07-21 Simon Marchi <simon.marchi@efficios.com>
* linux-nat.c (stopped_pids): Make static.
diff --git a/gdb/python/py-registers.c b/gdb/python/py-registers.c
index db0fe37..8e22a919 100644
--- a/gdb/python/py-registers.c
+++ b/gdb/python/py-registers.c
@@ -24,6 +24,9 @@
#include "reggroups.h"
#include "python-internal.h"
+/* Token to access per-gdbarch data related to register descriptors. */
+static struct gdbarch_data *gdbpy_register_object_data = NULL;
+
/* Structure for iterator over register descriptors. */
typedef struct {
PyObject_HEAD
@@ -81,6 +84,17 @@ typedef struct {
extern PyTypeObject reggroup_object_type
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("reggroup_object");
+/* Associates a vector of gdb.RegisterDescriptor objects with GDBARCH as
+ gdbarch_data via the gdbarch post init registration mechanism
+ (gdbarch_data_register_post_init). */
+
+static void *
+gdbpy_register_object_data_init (struct gdbarch *gdbarch)
+{
+ std::vector<gdbpy_ref<>> *vec = new (std::vector<gdbpy_ref<>>);
+ return (void *) vec;
+}
+
/* Create a new gdb.RegisterGroup object wrapping REGGROUP. */
static PyObject *
@@ -117,20 +131,38 @@ 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,
+/* Return a gdb.RegisterDescriptor object for REGNUM from GDBARCH. For
+ each REGNUM (in GDBARCH) only one descriptor is ever created, which is
+ then cached on the GDBARCH. */
+
+static gdbpy_ref<>
+gdbpy_get_register_descriptor (struct gdbarch *gdbarch,
int regnum)
{
- /* Create a new object and fill in its details. */
- register_descriptor_object *reg
- = PyObject_New (register_descriptor_object,
- &register_descriptor_object_type);
- if (reg == NULL)
- return NULL;
- reg->regnum = regnum;
- reg->gdbarch = gdbarch;
- return (PyObject *) reg;
+ auto vec = (std::vector<gdbpy_ref<>> *) gdbarch_data
+ (gdbarch, gdbpy_register_object_data);
+
+ /* Ensure that we have enough entries in the vector. */
+ if (vec->size () <= regnum)
+ vec->resize ((regnum + 1), nullptr);
+
+ /* If we don't already have a descriptor for REGNUM in GDBARCH then
+ create one now. */
+ if (vec->at (regnum) == nullptr)
+ {
+ gdbpy_ref <register_descriptor_object> reg
+ (PyObject_New (register_descriptor_object,
+ &register_descriptor_object_type));
+ if (reg == NULL)
+ return NULL;
+ reg->regnum = regnum;
+ reg->gdbarch = gdbarch;
+ vec->at (regnum) = gdbpy_ref<> ((PyObject *) reg.release ());
+ }
+
+ /* Grab the register descriptor from the vector, the reference count is
+ automatically incremented thanks to gdbpy_ref. */
+ return vec->at (regnum);
}
/* Convert the register descriptor to a string. */
@@ -281,7 +313,7 @@ gdbpy_register_descriptor_iter_next (PyObject *self)
iter_obj->regnum++;
if (name != nullptr && *name != '\0')
- return gdbpy_new_register_descriptor (gdbarch, regnum);
+ return gdbpy_get_register_descriptor (gdbarch, regnum).release ();
}
while (true);
}
@@ -291,6 +323,9 @@ gdbpy_register_descriptor_iter_next (PyObject *self)
int
gdbpy_initialize_registers ()
{
+ gdbpy_register_object_data
+ = gdbarch_data_register_post_init (gdbpy_register_object_data_init);
+
register_descriptor_object_type.tp_new = PyType_GenericNew;
if (PyType_Ready (&register_descriptor_object_type) < 0)
return -1;
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 804df02..6b13e92 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2020-07-21 Andrew Burgess <andrew.burgess@embecosm.com>
+
+ * gdb.python/py-arch-reg-names.exp: Additional tests.
+
2020-07-21 Tom de Vries <tdevries@suse.de>
* gdb.reverse/solib-precsave.exp: Handle additional "recommended
diff --git a/gdb/testsuite/gdb.python/py-arch-reg-names.exp b/gdb/testsuite/gdb.python/py-arch-reg-names.exp
index 14bc0a8..8dd34ef 100644
--- a/gdb/testsuite/gdb.python/py-arch-reg-names.exp
+++ b/gdb/testsuite/gdb.python/py-arch-reg-names.exp
@@ -85,3 +85,22 @@ for { set i 0 } { $i < [llength $regs] } { incr i } {
}
}
gdb_assert { $found_non_match == 0 } "all registers match"
+
+# Check that we get the same register descriptors from two different
+# iterators.
+gdb_py_test_silent_cmd \
+ "python iter1 = arch.registers ()" \
+ "get first all register iterator" 0
+gdb_py_test_silent_cmd \
+ "python iter2 = arch.registers ()" \
+ "get second all register iterator" 0
+gdb_py_test_silent_cmd \
+ [multi_line_input \
+ "python" \
+ "for r1, r2 in zip(iter1, iter2):" \
+ " if (r1.name != r2.name):"\
+ " raise gdb.GdbError (\"miss-matched names\")" \
+ " if (r1 != r2):" \
+ " raise gdb.GdbError (\"miss-matched objects\")" \
+ "\004" ] \
+ "check names and objects match" 1