[PATCH v2 8/9] gdb/python: add gdbpy_dict_wrapper:allocate_dict helper

Matthieu Longo
2026-03-03T16:28:03Z

Python extension objects that support __dict__ must inherit from
gdbpy_dict_wrapper, a wrapper class that stores the PyObject
corresponding to the __dict__ attribute.

Currently, management of this dictionary is not centralized, and
each Python extension object implements its own logic to create,
access, and destroy it.

This patch focuses on the allocation of the dictionary, introduces
a new helper function, gdbpy_dict_wrapper::allocate_dict(), and
adapts the existing code to use the helper.
---
gdb/python/py-corefile.c | 3 +--
gdb/python/py-event.c | 7 +++----
gdb/python/py-inferior.c | 3 +--
gdb/python/py-infthread.c | 7 +++----
gdb/python/py-objfile.c | 7 +++----
gdb/python/py-progspace.c | 3 +--
gdb/python/py-ref.h | 11 +++++++++++
gdb/python/py-type.c | 9 +++------
8 files changed, 26 insertions(+), 24 deletions(-)

diff --git a/gdb/python/py-corefile.c b/gdb/python/py-corefile.c
index de88a964efb..5aefd2092c8 100644
--- a/gdb/python/py-corefile.c
+++ b/gdb/python/py-corefile.c
@@ -132,8 +132,7 @@ gdbpy_core_file_from_inferior (inferior *inf)
which requires that the 'inferior' be set to NULL. */
object->inferior = nullptr;
object->mapped_files = nullptr;
- object->dict = PyDict_New ();
- if (object->dict == nullptr)
+ if (! gdbpy_dict_wrapper::allocate_dict (object))
return nullptr;

/* Now that the gdb.Corefile has been successfully initialised and we know
diff --git a/gdb/python/py-event.c b/gdb/python/py-event.c
index 8fb21b7fdad..47c2ba4c84d 100644
--- a/gdb/python/py-event.c
+++ b/gdb/python/py-event.c
@@ -31,11 +31,10 @@ create_event_object (PyTypeObject *py_type)
{
gdbpy_ref<event_object> event_obj (PyObject_New (event_object, py_type));
if (event_obj == NULL)
- return NULL;
+ return nullptr;

- event_obj->dict = PyDict_New ();
- if (!event_obj->dict)
- return NULL;
+ if (! gdbpy_dict_wrapper::allocate_dict (event_obj))
+ return nullptr;

return gdbpy_ref<> ((PyObject *) event_obj.release ());
}
diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c
index dbf3a536255..e1cd1b8f9dd 100644
--- a/gdb/python/py-inferior.c
+++ b/gdb/python/py-inferior.c
@@ -224,8 +224,7 @@ inferior_to_inferior_object (struct inferior *inferior)

inf_obj->inferior = inferior;
inf_obj->threads = new thread_map_t ();
- inf_obj->dict = PyDict_New ();
- if (inf_obj->dict == nullptr)
+ if (! gdbpy_dict_wrapper::allocate_dict (inf_obj))
return nullptr;

/* PyObject_New initializes the new object with a refcount of 1. This counts
diff --git a/gdb/python/py-infthread.c b/gdb/python/py-infthread.c
index 0f29e9fb7a4..ca9a34632d6 100644
--- a/gdb/python/py-infthread.c
+++ b/gdb/python/py-infthread.c
@@ -41,16 +41,15 @@ create_thread_object (struct thread_info *tp)

gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (tp->inf);
if (inf_obj == NULL)
- return NULL;
+ return nullptr;

thread_obj.reset (PyObject_New (thread_object, &thread_object_type));
if (thread_obj == NULL)
- return NULL;
+ return nullptr;

thread_obj->thread = tp;
thread_obj->inf_obj = (PyObject *) inf_obj.release ();
- thread_obj->dict = PyDict_New ();
- if (thread_obj->dict == nullptr)
+ if (! gdbpy_dict_wrapper::allocate_dict (thread_obj))
return nullptr;

return thread_obj;
diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c
index feae62c32a8..289182c794d 100644
--- a/gdb/python/py-objfile.c
+++ b/gdb/python/py-objfile.c
@@ -201,12 +201,11 @@ objfpy_dealloc (PyObject *o)
static bool
objfpy_initialize (gdbpy_ref<objfile_object> &self)
{
- self->objfile = NULL;
-
- self->dict = PyDict_New ();
- if (self->dict == NULL)
+ if (! gdbpy_dict_wrapper::allocate_dict (self))
return false;

+ self->objfile = NULL;
+
self->printers = PyList_New (0);
if (self->printers == NULL)
return false;
diff --git a/gdb/python/py-progspace.c b/gdb/python/py-progspace.c
index 15f7fbead65..c38fd740286 100644
--- a/gdb/python/py-progspace.c
+++ b/gdb/python/py-progspace.c
@@ -171,8 +171,7 @@ pspy_initialize (gdbpy_ref<pspace_object> &self)
{
self->pspace = NULL;

- self->dict = PyDict_New ();
- if (self->dict == NULL)
+ if (! gdbpy_dict_wrapper::allocate_dict (self))
return false;

self->printers = PyList_New (0);
diff --git a/gdb/python/py-ref.h b/gdb/python/py-ref.h
index 4ce7e29357d..f67e247cc98 100644
--- a/gdb/python/py-ref.h
+++ b/gdb/python/py-ref.h
@@ -81,6 +81,17 @@ struct gdbpy_dict_wrapper : public PyObject
auto *wrapper = reinterpret_cast<gdbpy_dict_wrapper *> (self);
return &wrapper->dict;
}
+
+ template <class T>
+ static bool
+ allocate_dict (gdbpy_ref<T>& self)
+ {
+ static_assert (std::is_base_of_v<gdbpy_dict_wrapper, T>
+ || std::is_same_v<PyObject, T>);
+ auto *obj = static_cast<gdbpy_dict_wrapper *> (self.get ());
+ obj->dict = PyDict_New ();
+ return obj->dict != nullptr;
+ }
};

#endif /* GDB_PYTHON_PY_REF_H */
diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index ec4126d0589..a4b046be1ad 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -93,12 +93,9 @@ field_new (void)
gdbpy_ref<field_object> result (PyObject_New (field_object,
&field_object_type));

- if (result != NULL)
- {
- result->dict = PyDict_New ();
- if (!result->dict)
- return NULL;
- }
+ if (result != nullptr && ! gdbpy_dict_wrapper::allocate_dict (result))
+ return nullptr;
+
return (PyObject *) result.release ();
}

--
2.53.0