]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb: cast all Python extension objects passed to gdbpy_ref_policy to PyObject*
authorMatthieu Longo <matthieu.longo@arm.com>
Sat, 25 Oct 2025 22:55:29 +0000 (23:55 +0100)
committerMatthieu Longo <matthieu.longo@arm.com>
Thu, 29 Jan 2026 16:46:14 +0000 (16:46 +0000)
When enabling the Python limited API, pointers to Python C extension
objects can no longer be implicitly converted to 'PyObject *' by the
compiler.

gdbpy_ref_policy is a templated class that provides a generic interface
for incrementing and decrementing the reference counter on the given
object. It is used as a specialisation of the policy parameter in
gdb::ref_ptr, together with PyObject as the parameter type. As a result,
gdbpy_ref_policy always expects an argument derived from PyObject.

This patch fixes the resulting compilation issue by adding an explicit
static_cast to 'PyObject *' before passing the value to Py_INCREF and
Py_DECREF. As a side effect, these casts enforce, at compile time, that
the template type passed to gdbpy_ref_policy is a subclass of PyObject.
To provide a clearer diagnostic when an incorrect type is used, a
static_assert is added to gdbpy_ref_policy, avoiding obscure errors
originating from the static_cast. Finally, all C Python extension types
passed to gdbpy_ref_policy are updated to inherit from PyObject.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23830
Approved-By: Tom Tromey <tom@tromey.com>
14 files changed:
gdb/python/py-breakpoint.c
gdb/python/py-cmd.c
gdb/python/py-color.c
gdb/python/py-connection.c
gdb/python/py-corefile.c
gdb/python/py-disasm.c
gdb/python/py-events.h
gdb/python/py-frame.c
gdb/python/py-membuf.c
gdb/python/py-micmd.c
gdb/python/py-ref.h
gdb/python/py-registers.c
gdb/python/py-tui.c
gdb/python/python-internal.h

index fc53213966a9eaa22367b7bf1e7652dee2b1a75e..408d4b9d857b9da65dd227f2ebe39b0e0baa8d66 100644 (file)
 
 extern PyTypeObject breakpoint_location_object_type;
 
-struct gdbpy_breakpoint_location_object
+struct gdbpy_breakpoint_location_object : public PyObject
 {
-  PyObject_HEAD
-
   /* An owning reference to the gdb breakpoint location object.  */
   bp_location *bp_loc;
 
index 6b40b1796c666e4897475cce12b5552e04061392..3fbc26b0cdec5c752083a894abc5181c0269485a 100644 (file)
@@ -50,10 +50,8 @@ static const struct cmdpy_completer completers[] =
 
 /* A gdb command.  For the time being only ordinary commands (not
    set/show commands) are allowed.  */
-struct cmdpy_object
+struct cmdpy_object : public PyObject
 {
-  PyObject_HEAD
-
   /* The corresponding gdb command object, or NULL if the command is
      no longer installed.  */
   struct cmd_list_element *command;
index b41dff2edd70fac22d6c6c81854c59d1fa715d46..0bec51b1e52b6489bd82198bab4d446aa88212c9 100644 (file)
@@ -37,10 +37,8 @@ static struct {
 };
 
 /* A color.  */
-struct colorpy_object
+struct colorpy_object : public PyObject
 {
-  PyObject_HEAD
-
   /* Underlying value.  */
   ui_file_style::color color;
 };
index bef50b07f183c9ca45b7e503dc33d647d0e17d67..e2c29f6f180d4107ebadf7e186212d5e89a4e283 100644 (file)
 
 /* The Python object that represents a connection.  */
 
-struct connection_object
+struct connection_object : public PyObject
 {
-  PyObject_HEAD
-
   /* The process target that represents this connection.   When a
      connection_object is created this field will always point at a valid
      target.  Later, if GDB stops using this target (the target is popped
index 24b573b2dbde61dae06efcca9269cd7450ecf126..88fedbd718ce884243d4455202b305873686ce96 100644 (file)
@@ -45,10 +45,8 @@ extern PyTypeObject corefile_object_type;
 
 /* A gdb.CorefileMapped object.  */
 
-struct corefile_mapped_file_object
+struct corefile_mapped_file_object : public PyObject
 {
-  PyObject_HEAD
-
   /* The name of a file that was mapped when the core file was created.
      This is a 'str' object.  */
   PyObject *filename;
@@ -70,10 +68,8 @@ extern PyTypeObject corefile_mapped_file_object_type;
 
 /* A gdb.CorefileMappedFileRegion object.  */
 
-struct corefile_mapped_file_region_object
+struct corefile_mapped_file_region_object : public PyObject
 {
-  PyObject_HEAD
-
   /* The start and end addresses for this mapping, these are addresses
      within the inferior's address space.  */
   CORE_ADDR start;
index c1aa4d0586ab2f1920b347099e223623b5413605..a125907948c9ef08570a0443ef4041ee3550c80c 100644 (file)
 /* Implement gdb.disassembler.DisassembleInfo type.  An object of this type
    represents a single disassembler request from GDB.  */
 
-struct disasm_info_object
+struct disasm_info_object : public PyObject
 {
-  PyObject_HEAD
-
   /* The architecture in which we are disassembling.  */
   struct gdbarch *gdbarch;
 
@@ -99,10 +97,8 @@ extern PyTypeObject disasm_part_object_type;
    the disassembled instruction (in bytes), and the string representing the
    disassembled instruction.  */
 
-struct disasm_result_object
+struct disasm_result_object : public PyObject
 {
-  PyObject_HEAD
-
   /* The length of the disassembled instruction in bytes.  */
   int length;
 
index 9fc7a86920e9cd95e6a36e7621bdb2460651dc52..e44b4b4a7616427dd057482038385cf88e9f1c29 100644 (file)
 /* Stores a list of objects to be notified when the event for which this
    registry tracks occurs.  */
 
-struct eventregistry_object
+struct eventregistry_object : public PyObject
 {
-  PyObject_HEAD
-
   PyObject *callbacks;
 };
 
index 027ccb4112dd6f907c632024baa6b446b62a0d7f..ab7883b4e73b1e63e50ffc966ad3806e6a7a549a 100644 (file)
@@ -28,8 +28,8 @@
 #include "symfile.h"
 #include "objfiles.h"
 
-struct frame_object {
-  PyObject_HEAD
+struct frame_object : public PyObject
+{
   struct frame_id frame_id;
   struct gdbarch *gdbarch;
 
index 832ab62cf52a78ac4f7fbbf718c06cfa21b1f1bc..e3bf5e2ceabdf5235885824282da7ba94dd57779 100644 (file)
@@ -19,9 +19,8 @@
 
 #include "python-internal.h"
 
-struct membuf_object {
-  PyObject_HEAD
-
+struct membuf_object : public PyObject
+{
   /* Pointer to the raw data, and array of gdb_bytes.  */
   void *buffer;
 
index c6a96dc3ad536f842dd910cb74453fe55044a74c..0c820751c5679a1b133b7138244be0f4a89ad843 100644 (file)
@@ -55,10 +55,8 @@ struct mi_command_py;
 
 /* Representation of a Python gdb.MICommand object.  */
 
-struct micmdpy_object
+struct micmdpy_object : public PyObject
 {
-  PyObject_HEAD
-
   /* The object representing this command in the MI command table.  This
      pointer can be nullptr if the command is not currently installed into
      the MI command table (see gdb.MICommand.installed property).  */
index 4d44ca90e210e779a36283f93089866265a7749c..1d07eeb3dc95319321187d9c027aa2d5c21369fe 100644 (file)
 template<typename T>
 struct gdbpy_ref_policy
 {
+  static_assert(std::is_base_of<PyObject, T>::value,
+               "T must be a subclass of PyObject");
+
   static void incref (T *ptr)
   {
-    Py_INCREF (ptr);
+    Py_INCREF (static_cast<PyObject *> (ptr));
   }
 
   static void decref (T *ptr)
   {
-    Py_DECREF (ptr);
+    Py_DECREF (static_cast<PyObject *> (ptr));
   }
 };
 
index ac7480caea9b5822bb6fceefbf12fcdec282f4df..3d1683805d1ff378a8f8a7f9a0ea350114fea0e9 100644 (file)
@@ -49,9 +49,8 @@ struct register_descriptor_iterator_object {
 extern PyTypeObject register_descriptor_iterator_object_type;
 
 /* A register descriptor.  */
-struct register_descriptor_object {
-  PyObject_HEAD
-
+struct register_descriptor_object : public PyObject
+{
   /* The register this is a descriptor for.  */
   int regnum;
 
@@ -75,9 +74,8 @@ struct reggroup_iterator_object {
 extern PyTypeObject reggroup_iterator_object_type;
 
 /* A register group object.  */
-struct reggroup_object {
-  PyObject_HEAD
-
+struct reggroup_object : public PyObject
+{
   /* The register group being described.  */
   const struct reggroup *reggroup;
 };
index 578ddfbcc67b01fc00df9ae7138f47df14f2534a..be19193770fde17a8be34d1cc7702cb593bf339f 100644 (file)
@@ -44,10 +44,8 @@ class tui_py_window;
 
 /* A PyObject representing a TUI window.  */
 
-struct gdbpy_tui_window
+struct gdbpy_tui_window: public PyObject
 {
-  PyObject_HEAD
-
   /* The TUI window, or nullptr if the window has been deleted.  */
   tui_py_window *window;
 
index f6915a62b7a57ce6268531c305ecf548e30ceb12..722edbd1a1cff763086f3d4e3e293fe7b58e8701 100644 (file)
@@ -350,10 +350,8 @@ extern PyTypeObject thread_object_type;
 
 extern bool gdbpy_breakpoint_init_breakpoint_type ();
 
-struct gdbpy_breakpoint_object
+struct gdbpy_breakpoint_object : public PyObject
 {
-  PyObject_HEAD
-
   /* The breakpoint number according to gdb.  */
   int number;