aboutsummaryrefslogtreecommitdiff
path: root/gdb/python
diff options
context:
space:
mode:
authorJan Vrany <jan.vrany@labware.com>2025-03-19 21:12:53 +0000
committerJan Vrany <jan.vrany@labware.com>2025-03-19 21:12:53 +0000
commit974c8ea576353d58fc024898dbc349da3c13984b (patch)
tree9a6aceac2c0d8892169c2b989eb93c66b53a4010 /gdb/python
parentaaefa9023e6c7835c37ad62a4542b7171651479e (diff)
downloadbinutils-974c8ea576353d58fc024898dbc349da3c13984b.zip
binutils-974c8ea576353d58fc024898dbc349da3c13984b.tar.gz
binutils-974c8ea576353d58fc024898dbc349da3c13984b.tar.bz2
gdb/python: preserve identity for gdb.Type objects
This commit changes type_to_type_object() so that each it is called with a particular struct type * it returns the very same gdb.Type object. This is done in the same way as for gdb.Symtab objects in earlier commit ("gdb/python: preserve identity for gdb.Symtab objects") except that types may be either objfile-owned or arch-owned. Prior this commit, arch-owned objects we not put into any list (like objfile-owned ones) so they could not be easily looked up. This commit changes the code so arch-owned list are put into per-architecture list which is then used (solely) for looking up arch-owned gdb.Type. Another complication comes from the fact that when objfile is about to be freed, associated gdb.Type instances are not merely invalidated (like it is done with gdb.Symtab or gdb.Symbol objects) but instead the type is copied and the copy is arch-owned. So we need two different "deleters", one for objfile-owned types that copies the type (as before) and then insert the object to per-architecture list and another one for arch-owned types. Approved-By: Tom Tromey <tom@tromey.com>
Diffstat (limited to 'gdb/python')
-rw-r--r--gdb/python/py-type.c91
1 files changed, 76 insertions, 15 deletions
diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index 11a96d5..dbc355c 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -1162,8 +1162,11 @@ typy_richcompare (PyObject *self, PyObject *other, int op)
+/* Forward declaration, see below. */
+static void set_type (type_object *obj, struct type *type);
+
/* Deleter that saves types when an objfile is being destroyed. */
-struct typy_deleter
+struct typy_deleter_for_objfile_owned
{
void operator() (type_object *obj)
{
@@ -1181,25 +1184,54 @@ struct typy_deleter
type_object *next = obj->next;
copied_types.clear ();
- obj->type = copy_type_recursive (obj->type, copied_types);
- obj->next = NULL;
- obj->prev = NULL;
+ /* Set a copied (now arch-owned) type. As a side-effect this
+ adds OBJ to per-arch list. We do not need to remove it from
+ per-objfile list since the objfile is going to go completely
+ anyway. */
+ set_type (obj, copy_type_recursive (obj->type, copied_types));
obj = next;
}
}
};
-static const registry<objfile>::key<type_object, typy_deleter>
+/* Deleter that is used when an arch is is about to be freed. */
+struct typy_deleter_for_arch_owned
+{
+ void operator() (type_object *obj)
+ {
+ while (obj)
+ {
+ type_object *next = obj->next;
+
+ obj->type = nullptr;
+
+ obj->next = nullptr;
+ obj->prev = nullptr;
+
+ obj = next;
+ }
+ }
+};
+
+
+
+static const registry<objfile>::key<type_object, typy_deleter_for_objfile_owned>
typy_objfile_data_key;
+static const registry<gdbarch>::key<type_object, typy_deleter_for_arch_owned>
+ typy_gdbarch_data_key;
static void
set_type (type_object *obj, struct type *type)
{
+ gdb_assert (type != nullptr);
+
obj->type = type;
- obj->prev = NULL;
- if (type != nullptr && type->objfile_owner () != nullptr)
+ obj->prev = nullptr;
+
+ /* Can it really happen that type is NULL? */
+ if (type->objfile_owner () != nullptr)
{
struct objfile *objfile = type->objfile_owner ();
@@ -1209,9 +1241,15 @@ set_type (type_object *obj, struct type *type)
typy_objfile_data_key.set (objfile, obj);
}
else
- obj->next = NULL;
-}
+ {
+ struct gdbarch *arch = type->arch_owner ();
+ obj->next = typy_gdbarch_data_key.get (arch);
+ if (obj->next)
+ obj->next->prev = obj;
+ typy_gdbarch_data_key.set (arch, obj);
+ }
+}
static void
typy_dealloc (PyObject *obj)
{
@@ -1219,13 +1257,19 @@ typy_dealloc (PyObject *obj)
if (type->prev)
type->prev->next = type->next;
- else if (type->type != nullptr && type->type->objfile_owner () != nullptr)
+ else if (type->type != nullptr)
{
- /* Must reset head of list. */
- struct objfile *objfile = type->type->objfile_owner ();
-
- if (objfile)
- typy_objfile_data_key.set (objfile, type->next);
+ if (type->type->is_objfile_owned ())
+ {
+ /* Must reset head of list. */
+ struct objfile *objfile = type->type->objfile_owner ();
+ typy_objfile_data_key.set (objfile, type->next);
+ }
+ else
+ {
+ struct gdbarch *arch = type->type->arch_owner ();
+ typy_gdbarch_data_key.set (arch, type->next);
+ }
}
if (type->next)
type->next->prev = type->prev;
@@ -1473,6 +1517,23 @@ type_to_type_object (struct type *type)
return gdbpy_handle_gdb_exception (nullptr, except);
}
+ /* Look if there's already a gdb.Type object for given TYPE
+ and if so, return it. */
+ if (type->is_objfile_owned ())
+ type_obj = typy_objfile_data_key.get (type->objfile_owner ());
+ else
+ type_obj = typy_gdbarch_data_key.get (type->arch_owner ());
+
+ while (type_obj != nullptr)
+ {
+ if (type_obj->type == type)
+ {
+ Py_INCREF (type_obj);
+ return (PyObject*)type_obj;
+ }
+ type_obj = type_obj->next;
+ }
+
type_obj = PyObject_New (type_object, &type_object_type);
if (type_obj)
set_type (type_obj, type);