Automatically add types to Python modules

Message ID 20240911163741.3130271-1-tromey@adacore.com
State New
Headers
Series Automatically add types to Python modules |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gdb_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 fail Test failed
linaro-tcwg-bot/tcwg_gdb_check--master-arm fail Test failed

Commit Message

Tom Tromey Sept. 11, 2024, 4:37 p.m. UTC
  PR python/32163 points out that various types provided by gdb are not
added to the gdb module, so they aren't available for interactive
inspection.  I think this is just an oversight.

This patch fixes the problem by introducing a new helper function that
both readies the type and then adds it to the appropriate module.  The
patch also poisons PyType_Ready, the idea being to avoid this bug in
the future.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32163
---
 gdb/python/py-arch.c             |  7 +------
 gdb/python/py-block.c            | 11 +++--------
 gdb/python/py-breakpoint.c       | 15 ++-------------
 gdb/python/py-cmd.c              |  6 +-----
 gdb/python/py-connection.c       | 12 ++----------
 gdb/python/py-disasm.c           | 32 +++++---------------------------
 gdb/python/py-event.c            | 18 +-----------------
 gdb/python/py-event.h            |  2 --
 gdb/python/py-evtregistry.c      |  6 +-----
 gdb/python/py-finishbreakpoint.c |  6 +-----
 gdb/python/py-frame.c            |  5 ++---
 gdb/python/py-function.c         |  6 +-----
 gdb/python/py-inferior.c         |  6 +-----
 gdb/python/py-infthread.c        |  6 +-----
 gdb/python/py-instruction.c      |  2 +-
 gdb/python/py-lazy-string.c      |  6 +-----
 gdb/python/py-linetable.c        | 22 +++-------------------
 gdb/python/py-membuf.c           |  6 +-----
 gdb/python/py-micmd.c            |  7 +------
 gdb/python/py-objfile.c          |  6 +-----
 gdb/python/py-param.c            |  5 ++---
 gdb/python/py-prettyprint.c      |  5 +----
 gdb/python/py-progspace.c        |  5 ++---
 gdb/python/py-record-btrace.c    |  2 +-
 gdb/python/py-record.c           | 10 +++++-----
 gdb/python/py-registers.c        | 25 ++++++-------------------
 gdb/python/py-symbol.c           |  5 ++---
 gdb/python/py-symtab.c           | 11 +++--------
 gdb/python/py-tui.c              |  2 +-
 gdb/python/py-type.c             | 17 ++++-------------
 gdb/python/py-unwind.c           | 12 ++++--------
 gdb/python/py-value.c            |  6 +-----
 gdb/python/python-internal.h     | 30 ++++++++++++++++++++++++++++++
 gdb/python/python.c              |  2 +-
 34 files changed, 93 insertions(+), 231 deletions(-)
  

Comments

Alexandra Hájková Sept. 16, 2024, 12:33 p.m. UTC | #1
Hi Tom,

after applying this patch on aarch64, Fedora Rawhide, I can see this
regression:
FAIL: gdb.python/py-arch.exp: Test empty achitecture __repr__ does not
trigger an assert
FAIL: gdb.python/py-arch.exp: Test empty architecture.name does not trigger
an assert
FAIL: gdb.python/py-arch.exp: Test empty architecture.disassemble does not
trigger an assert

=== gdb Summary ===

# of expected passes 122
# of unexpected failures 3

Why have you decided not to write the test for this fix?

Thank you,
Alexandra
  
Tom Tromey Sept. 16, 2024, 2:06 p.m. UTC | #2
>>>>> "Alexandra" == Alexandra Petlanova Hajkova <ahajkova@redhat.com> writes:

Alexandra> Why have you decided not to write the test for this fix?

I don't think the main point of the patch -- preventing the bug in the
future -- can be tested.  But I suppose the immediate bug could be.

Tom
  
Tom Tromey Sept. 16, 2024, 2:25 p.m. UTC | #3
Alexandra> after applying this patch on aarch64, Fedora Rawhide, I can see this regression:
Alexandra> FAIL: gdb.python/py-arch.exp: Test empty achitecture __repr__ does not trigger an assert
Alexandra> FAIL: gdb.python/py-arch.exp: Test empty architecture.name does not trigger an assert
Alexandra> FAIL: gdb.python/py-arch.exp: Test empty architecture.disassemble does not trigger an assert

Sorry about that.  I've fixed it in v2.

I also added a regression test.

Tom
  

Patch

diff --git a/gdb/python/py-arch.c b/gdb/python/py-arch.c
index 178efab4cee..ac9b2bb586e 100644
--- a/gdb/python/py-arch.c
+++ b/gdb/python/py-arch.c
@@ -360,12 +360,7 @@  gdbpy_all_architecture_names (PyObject *self, PyObject *args)
 static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_arch (void)
 {
-  arch_object_type.tp_new = PyType_GenericNew;
-  if (PyType_Ready (&arch_object_type) < 0)
-    return -1;
-
-  return gdb_pymodule_addobject (gdb_module, "Architecture",
-				 (PyObject *) &arch_object_type);
+  return gdbpy_type_ready (&arch_object_type);
 }
 
 GDBPY_INITIALIZE_FILE (gdbpy_initialize_arch);
diff --git a/gdb/python/py-block.c b/gdb/python/py-block.c
index 62e93d55072..aeb9acb7260 100644
--- a/gdb/python/py-block.c
+++ b/gdb/python/py-block.c
@@ -493,19 +493,14 @@  static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_blocks (void)
 {
   block_object_type.tp_new = PyType_GenericNew;
-  if (PyType_Ready (&block_object_type) < 0)
+  if (gdbpy_type_ready (&block_object_type) < 0)
     return -1;
 
   block_syms_iterator_object_type.tp_new = PyType_GenericNew;
-  if (PyType_Ready (&block_syms_iterator_object_type) < 0)
+  if (gdbpy_type_ready (&block_syms_iterator_object_type) < 0)
     return -1;
 
-  if (gdb_pymodule_addobject (gdb_module, "Block",
-			      (PyObject *) &block_object_type) < 0)
-    return -1;
-
-  return gdb_pymodule_addobject (gdb_module, "BlockIterator",
-				 (PyObject *) &block_syms_iterator_object_type);
+  return 0;
 }
 
 GDBPY_INITIALIZE_FILE (gdbpy_initialize_blocks);
diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
index 013c3fadabf..a21ffac8392 100644
--- a/gdb/python/py-breakpoint.c
+++ b/gdb/python/py-breakpoint.c
@@ -1114,7 +1114,7 @@  gdbpy_breakpoint_init_breakpoint_type ()
   if (breakpoint_object_type.tp_new == nullptr)
     {
       breakpoint_object_type.tp_new = PyType_GenericNew;
-      if (PyType_Ready (&breakpoint_object_type) < 0)
+      if (gdbpy_type_ready (&breakpoint_object_type) < 0)
 	{
 	  /* Reset tp_new back to nullptr so future calls to this function
 	     will try calling PyType_Ready again.  */
@@ -1359,10 +1359,6 @@  gdbpy_initialize_breakpoints (void)
   if (!gdbpy_breakpoint_init_breakpoint_type ())
     return -1;
 
-  if (gdb_pymodule_addobject (gdb_module, "Breakpoint",
-			      (PyObject *) &breakpoint_object_type) < 0)
-    return -1;
-
   gdb::observers::breakpoint_created.attach (gdbpy_breakpoint_created,
 					     "py-breakpoint");
   gdb::observers::breakpoint_deleted.attach (gdbpy_breakpoint_deleted,
@@ -1394,14 +1390,7 @@  gdbpy_initialize_breakpoints (void)
 static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_breakpoint_locations ()
 {
-  if (PyType_Ready (&breakpoint_location_object_type) < 0)
-    return -1;
-
-  if (gdb_pymodule_addobject (gdb_module, "BreakpointLocation",
-			      (PyObject *) &breakpoint_location_object_type)
-      < 0)
-    return -1;
-  return 0;
+  return gdbpy_type_ready (&breakpoint_location_object_type);
 }
 
 
diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c
index e042f20fa0d..731a94d9655 100644
--- a/gdb/python/py-cmd.c
+++ b/gdb/python/py-cmd.c
@@ -557,7 +557,7 @@  gdbpy_initialize_commands (void)
   int i;
 
   cmdpy_object_type.tp_new = PyType_GenericNew;
-  if (PyType_Ready (&cmdpy_object_type) < 0)
+  if (gdbpy_type_ready (&cmdpy_object_type) < 0)
     return -1;
 
   /* Note: alias and user are special.  */
@@ -587,10 +587,6 @@  gdbpy_initialize_commands (void)
 	return -1;
     }
 
-  if (gdb_pymodule_addobject (gdb_module, "Command",
-			      (PyObject *) &cmdpy_object_type) < 0)
-    return -1;
-
   invoke_cst = PyUnicode_FromString ("invoke");
   if (invoke_cst == NULL)
     return -1;
diff --git a/gdb/python/py-connection.c b/gdb/python/py-connection.c
index 79e27677442..7f5cce3d483 100644
--- a/gdb/python/py-connection.c
+++ b/gdb/python/py-connection.c
@@ -287,18 +287,10 @@  connpy_get_connection_details (PyObject *self, void *closure)
 static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_connection (void)
 {
-  if (PyType_Ready (&connection_object_type) < 0)
+  if (gdbpy_type_ready (&connection_object_type) < 0)
     return -1;
 
-  if (gdb_pymodule_addobject (gdb_module, "TargetConnection",
-			      (PyObject *) &connection_object_type) < 0)
-    return -1;
-
-  if (PyType_Ready (&remote_connection_object_type) < 0)
-    return -1;
-
-  if (gdb_pymodule_addobject (gdb_module, "RemoteTargetConnection",
-			      (PyObject *) &remote_connection_object_type) < 0)
+  if (gdbpy_type_ready (&remote_connection_object_type) < 0)
     return -1;
 
   return 0;
diff --git a/gdb/python/py-disasm.c b/gdb/python/py-disasm.c
index 9b9b509748d..8adf28ca025 100644
--- a/gdb/python/py-disasm.c
+++ b/gdb/python/py-disasm.c
@@ -1665,45 +1665,23 @@  gdbpy_initialize_disasm ()
     }
 
   disasm_info_object_type.tp_new = PyType_GenericNew;
-  if (PyType_Ready (&disasm_info_object_type) < 0)
-    return -1;
-
-  if (gdb_pymodule_addobject (gdb_disassembler_module, "DisassembleInfo",
-			      (PyObject *) &disasm_info_object_type) < 0)
+  if (gdbpy_type_ready (&disasm_info_object_type, gdb_disassembler_module) < 0)
     return -1;
 
   disasm_result_object_type.tp_new = PyType_GenericNew;
-  if (PyType_Ready (&disasm_result_object_type) < 0)
-    return -1;
-
-  if (gdb_pymodule_addobject (gdb_disassembler_module, "DisassemblerResult",
-			      (PyObject *) &disasm_result_object_type) < 0)
+  if (gdbpy_type_ready (&disasm_result_object_type, gdb_disassembler_module) < 0)
     return -1;
 
   disasm_part_object_type.tp_new = PyType_GenericNew;
-  if (PyType_Ready (&disasm_part_object_type) < 0)
-    return -1;
-
-  if (gdb_pymodule_addobject (gdb_disassembler_module, "DisassemblerPart",
-			      (PyObject *) &disasm_part_object_type) < 0)
+  if (gdbpy_type_ready (&disasm_part_object_type, gdb_disassembler_module) < 0)
     return -1;
 
   disasm_addr_part_object_type.tp_new = PyType_GenericNew;
-  if (PyType_Ready (&disasm_addr_part_object_type) < 0)
-    return -1;
-
-  if (gdb_pymodule_addobject (gdb_disassembler_module,
-			      "DisassemblerAddressPart",
-			      (PyObject *) &disasm_addr_part_object_type) < 0)
+  if (gdbpy_type_ready (&disasm_addr_part_object_type, gdb_disassembler_module) < 0)
     return -1;
 
   disasm_text_part_object_type.tp_new = PyType_GenericNew;
-  if (PyType_Ready (&disasm_text_part_object_type) < 0)
-    return -1;
-
-  if (gdb_pymodule_addobject (gdb_disassembler_module,
-			      "DisassemblerTextPart",
-			      (PyObject *) &disasm_text_part_object_type) < 0)
+  if (gdbpy_type_ready (&disasm_text_part_object_type, gdb_disassembler_module) < 0)
     return -1;
 
   return 0;
diff --git a/gdb/python/py-event.c b/gdb/python/py-event.c
index 47a2997a09a..a918136ccca 100644
--- a/gdb/python/py-event.c
+++ b/gdb/python/py-event.c
@@ -56,25 +56,9 @@  evpy_add_attribute (PyObject *event, const char *name, PyObject *attr)
 static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_event (void)
 {
-  return gdbpy_initialize_event_generic (&event_object_type,
-					 "Event");
+  return gdbpy_type_ready (&event_object_type);
 }
 
-/* Initialize the given event type.  If BASE is not NULL it will
-  be set as the types base.
-  Returns 0 if initialization was successful -1 otherwise.  */
-
-int
-gdbpy_initialize_event_generic (PyTypeObject *type,
-				const char *name)
-{
-  if (PyType_Ready (type) < 0)
-    return -1;
-
-  return gdb_pymodule_addobject (gdb_module, name, (PyObject *) type);
-}
-
-
 /* Notify the list of listens that the given EVENT has occurred.
    returns 0 if emit is successful -1 otherwise.  */
 
diff --git a/gdb/python/py-event.h b/gdb/python/py-event.h
index 388c513e5e9..a7238241f68 100644
--- a/gdb/python/py-event.h
+++ b/gdb/python/py-event.h
@@ -84,7 +84,5 @@  extern void evpy_dealloc (PyObject *self);
 extern int evpy_add_attribute (PyObject *event,
 			       const char *name, PyObject *attr)
   CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
-int gdbpy_initialize_event_generic (PyTypeObject *type, const char *name)
-  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
 
 #endif /* PYTHON_PY_EVENT_H */
diff --git a/gdb/python/py-evtregistry.c b/gdb/python/py-evtregistry.c
index 1f486e28c92..7ae3997ec9e 100644
--- a/gdb/python/py-evtregistry.c
+++ b/gdb/python/py-evtregistry.c
@@ -104,11 +104,7 @@  evregpy_dealloc (PyObject *self)
 static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_eventregistry (void)
 {
-  if (PyType_Ready (&eventregistry_object_type) < 0)
-    return -1;
-
-  return gdb_pymodule_addobject (gdb_module, "EventRegistry",
-				 (PyObject *) &eventregistry_object_type);
+  return gdbpy_type_ready (&eventregistry_object_type);
 }
 
 /* Return the number of listeners currently connected to this
diff --git a/gdb/python/py-finishbreakpoint.c b/gdb/python/py-finishbreakpoint.c
index ed3c4a5d90e..d9f7c895fe7 100644
--- a/gdb/python/py-finishbreakpoint.c
+++ b/gdb/python/py-finishbreakpoint.c
@@ -439,11 +439,7 @@  gdbpy_initialize_finishbreakpoints (void)
   if (!gdbpy_breakpoint_init_breakpoint_type ())
     return -1;
 
-  if (PyType_Ready (&finish_breakpoint_object_type) < 0)
-    return -1;
-
-  if (gdb_pymodule_addobject (gdb_module, "FinishBreakpoint",
-			      (PyObject *) &finish_breakpoint_object_type) < 0)
+  if (gdbpy_type_ready (&finish_breakpoint_object_type) < 0)
     return -1;
 
   gdb::observers::normal_stop.attach (bpfinishpy_handle_stop,
diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c
index 7f617fa5cea..fef4640d4ed 100644
--- a/gdb/python/py-frame.c
+++ b/gdb/python/py-frame.c
@@ -761,7 +761,7 @@  static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_frames (void)
 {
   frame_object_type.tp_new = PyType_GenericNew;
-  if (PyType_Ready (&frame_object_type) < 0)
+  if (gdbpy_type_ready (&frame_object_type) < 0)
     return -1;
 
   /* Note: These would probably be best exposed as class attributes of
@@ -785,8 +785,7 @@  gdbpy_initialize_frames (void)
 #include "unwind_stop_reasons.def"
 #undef SET
 
-  return gdb_pymodule_addobject (gdb_module, "Frame",
-				 (PyObject *) &frame_object_type);
+  return 0;
 }
 
 GDBPY_INITIALIZE_FILE (gdbpy_initialize_frames);
diff --git a/gdb/python/py-function.c b/gdb/python/py-function.c
index 2bbfb9d3a6d..58ae0d058e2 100644
--- a/gdb/python/py-function.c
+++ b/gdb/python/py-function.c
@@ -137,11 +137,7 @@  static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_functions (void)
 {
   fnpy_object_type.tp_new = PyType_GenericNew;
-  if (PyType_Ready (&fnpy_object_type) < 0)
-    return -1;
-
-  return gdb_pymodule_addobject (gdb_module, "Function",
-				 (PyObject *) &fnpy_object_type);
+  return gdbpy_type_ready (&fnpy_object_type);
 }
 
 GDBPY_INITIALIZE_FILE (gdbpy_initialize_functions);
diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c
index ccc3e881702..e5a74c153a8 100644
--- a/gdb/python/py-inferior.c
+++ b/gdb/python/py-inferior.c
@@ -1009,11 +1009,7 @@  gdbpy_selected_inferior (PyObject *self, PyObject *args)
 static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_inferior (void)
 {
-  if (PyType_Ready (&inferior_object_type) < 0)
-    return -1;
-
-  if (gdb_pymodule_addobject (gdb_module, "Inferior",
-			      (PyObject *) &inferior_object_type) < 0)
+  if (gdbpy_type_ready (&inferior_object_type) < 0)
     return -1;
 
   gdb::observers::new_thread.attach (add_thread_object, "py-inferior");
diff --git a/gdb/python/py-infthread.c b/gdb/python/py-infthread.c
index a17f25ed498..09f493abeec 100644
--- a/gdb/python/py-infthread.c
+++ b/gdb/python/py-infthread.c
@@ -412,11 +412,7 @@  gdbpy_selected_thread (PyObject *self, PyObject *args)
 static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_thread (void)
 {
-  if (PyType_Ready (&thread_object_type) < 0)
-    return -1;
-
-  return gdb_pymodule_addobject (gdb_module, "InferiorThread",
-				 (PyObject *) &thread_object_type);
+  return gdbpy_type_ready (&thread_object_type);
 }
 
 GDBPY_INITIALIZE_FILE (gdbpy_initialize_thread);
diff --git a/gdb/python/py-instruction.c b/gdb/python/py-instruction.c
index bc3945af2cf..7d775721ad6 100644
--- a/gdb/python/py-instruction.c
+++ b/gdb/python/py-instruction.c
@@ -66,7 +66,7 @@  py_insn_get_insn_type ()
       py_insn_type.tp_doc = "GDB instruction object";
       py_insn_type.tp_getset = py_insn_getset;
 
-      if (PyType_Ready (&py_insn_type) < 0)
+      if (gdbpy_type_ready (&py_insn_type) < 0)
 	{
 	  /* Reset the tp_new field so any subsequent calls to this
 	     function will retry to make the type ready.  */
diff --git a/gdb/python/py-lazy-string.c b/gdb/python/py-lazy-string.c
index 8779716c4b9..67b7a33dab2 100644
--- a/gdb/python/py-lazy-string.c
+++ b/gdb/python/py-lazy-string.c
@@ -236,11 +236,7 @@  gdbpy_create_lazy_string_object (CORE_ADDR address, long length,
 static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_lazy_string (void)
 {
-  if (PyType_Ready (&lazy_string_object_type) < 0)
-    return -1;
-
-  Py_INCREF (&lazy_string_object_type);
-  return 0;
+  return gdbpy_type_ready (&lazy_string_object_type);
 }
 
 /* Determine whether the printer object pointed to by OBJ is a
diff --git a/gdb/python/py-linetable.c b/gdb/python/py-linetable.c
index e3e71f9e436..8c0a6cc91fc 100644
--- a/gdb/python/py-linetable.c
+++ b/gdb/python/py-linetable.c
@@ -287,27 +287,11 @@  ltpy_dealloc (PyObject *self)
 static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_linetable (void)
 {
-  if (PyType_Ready (&linetable_object_type) < 0)
+  if (gdbpy_type_ready (&linetable_object_type) < 0)
     return -1;
-  if (PyType_Ready (&linetable_entry_object_type) < 0)
+  if (gdbpy_type_ready (&linetable_entry_object_type) < 0)
     return -1;
-  if (PyType_Ready (&ltpy_iterator_object_type) < 0)
-    return -1;
-
-  Py_INCREF (&linetable_object_type);
-  Py_INCREF (&linetable_entry_object_type);
-  Py_INCREF (&ltpy_iterator_object_type);
-
-  if (gdb_pymodule_addobject (gdb_module, "LineTable",
-			      (PyObject *) &linetable_object_type) < 0)
-    return -1;
-
-  if (gdb_pymodule_addobject (gdb_module, "LineTableEntry",
-			      (PyObject *) &linetable_entry_object_type) < 0)
-    return -1;
-
-  if (gdb_pymodule_addobject (gdb_module, "LineTableIterator",
-			      (PyObject *) &ltpy_iterator_object_type) < 0)
+  if (gdbpy_type_ready (&ltpy_iterator_object_type) < 0)
     return -1;
 
   return 0;
diff --git a/gdb/python/py-membuf.c b/gdb/python/py-membuf.c
index af48d01b9ed..25ebc99bb22 100644
--- a/gdb/python/py-membuf.c
+++ b/gdb/python/py-membuf.c
@@ -102,11 +102,7 @@  static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_membuf (void)
 {
   membuf_object_type.tp_new = PyType_GenericNew;
-  if (PyType_Ready (&membuf_object_type) < 0)
-    return -1;
-
-  return gdb_pymodule_addobject (gdb_module, "Membuf",
-				 (PyObject *) &membuf_object_type);
+  return gdbpy_type_ready (&membuf_object_type);
 }
 
 GDBPY_INITIALIZE_FILE (gdbpy_initialize_membuf);
diff --git a/gdb/python/py-micmd.c b/gdb/python/py-micmd.c
index 54427d4633b..f4abf2b1cd0 100644
--- a/gdb/python/py-micmd.c
+++ b/gdb/python/py-micmd.c
@@ -447,12 +447,7 @@  static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_micommands ()
 {
   micmdpy_object_type.tp_new = PyType_GenericNew;
-  if (PyType_Ready (&micmdpy_object_type) < 0)
-    return -1;
-
-  if (gdb_pymodule_addobject (gdb_module, "MICommand",
-			      (PyObject *) &micmdpy_object_type)
-      < 0)
+  if (gdbpy_type_ready (&micmdpy_object_type) < 0)
     return -1;
 
   invoke_cst = PyUnicode_FromString ("invoke");
diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c
index 6e8d5b57692..d8c7631ee15 100644
--- a/gdb/python/py-objfile.c
+++ b/gdb/python/py-objfile.c
@@ -709,11 +709,7 @@  objfile_to_objfile_object (struct objfile *objfile)
 static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_objfile (void)
 {
-  if (PyType_Ready (&objfile_object_type) < 0)
-    return -1;
-
-  return gdb_pymodule_addobject (gdb_module, "Objfile",
-				 (PyObject *) &objfile_object_type);
+  return gdbpy_type_ready (&objfile_object_type);
 }
 
 GDBPY_INITIALIZE_FILE (gdbpy_initialize_objfile);
diff --git a/gdb/python/py-param.c b/gdb/python/py-param.c
index e7032f7758c..2567061cad2 100644
--- a/gdb/python/py-param.c
+++ b/gdb/python/py-param.c
@@ -909,7 +909,7 @@  gdbpy_initialize_parameters (void)
   int i;
 
   parmpy_object_type.tp_new = PyType_GenericNew;
-  if (PyType_Ready (&parmpy_object_type) < 0)
+  if (gdbpy_type_ready (&parmpy_object_type) < 0)
     return -1;
 
   set_doc_cst = PyUnicode_FromString ("set_doc");
@@ -927,8 +927,7 @@  gdbpy_initialize_parameters (void)
 	return -1;
     }
 
-  return gdb_pymodule_addobject (gdb_module, "Parameter",
-				 (PyObject *) &parmpy_object_type);
+  return 0;
 }
 
 GDBPY_INITIALIZE_FILE (gdbpy_initialize_parameters);
diff --git a/gdb/python/py-prettyprint.c b/gdb/python/py-prettyprint.c
index 368b3a3c793..e061ea1b361 100644
--- a/gdb/python/py-prettyprint.c
+++ b/gdb/python/py-prettyprint.c
@@ -836,10 +836,7 @@  PyTypeObject printer_object_type =
 static int
 gdbpy_initialize_prettyprint ()
 {
-  if (PyType_Ready (&printer_object_type) < 0)
-    return -1;
-  return gdb_pymodule_addobject (gdb_module, "ValuePrinter",
-				 (PyObject *) &printer_object_type);
+  return gdbpy_type_ready (&printer_object_type);
 }
 
 GDBPY_INITIALIZE_FILE (gdbpy_initialize_prettyprint);
diff --git a/gdb/python/py-progspace.c b/gdb/python/py-progspace.c
index 5bc0015d728..081d6320cc1 100644
--- a/gdb/python/py-progspace.c
+++ b/gdb/python/py-progspace.c
@@ -747,11 +747,10 @@  gdbpy_initialize_pspace (void)
   gdb::observers::free_program_space.attach (gdbpy_free_program_space_event,
 					     "py-progspace");
 
-  if (PyType_Ready (&pspace_object_type) < 0)
+  if (gdbpy_type_ready (&pspace_object_type) < 0)
     return -1;
 
-  return gdb_pymodule_addobject (gdb_module, "Progspace",
-				 (PyObject *) &pspace_object_type);
+  return 0;
 }
 
 GDBPY_INITIALIZE_FILE (gdbpy_initialize_pspace);
diff --git a/gdb/python/py-record-btrace.c b/gdb/python/py-record-btrace.c
index 30d0e8305db..55ee67efd81 100644
--- a/gdb/python/py-record-btrace.c
+++ b/gdb/python/py-record-btrace.c
@@ -1006,7 +1006,7 @@  gdbpy_initialize_btrace (void)
 
   btpy_list_mapping_methods.mp_subscript = btpy_list_slice;
 
-  return PyType_Ready (&btpy_list_type);
+  return gdbpy_type_ready (&btpy_list_type);
 }
 
 GDBPY_INITIALIZE_FILE (gdbpy_initialize_btrace);
diff --git a/gdb/python/py-record.c b/gdb/python/py-record.c
index 759bf3049cb..83cfa66ad66 100644
--- a/gdb/python/py-record.c
+++ b/gdb/python/py-record.c
@@ -653,11 +653,11 @@  gdbpy_initialize_record (void)
   recpy_aux_type.tp_richcompare = recpy_element_richcompare;
   recpy_aux_type.tp_hash = recpy_element_hash;
 
-  if (PyType_Ready (&recpy_record_type) < 0
-      || PyType_Ready (&recpy_insn_type) < 0
-      || PyType_Ready (&recpy_func_type) < 0
-      || PyType_Ready (&recpy_gap_type) < 0
-      || PyType_Ready (&recpy_aux_type) < 0)
+  if (gdbpy_type_ready (&recpy_record_type) < 0
+      || gdbpy_type_ready (&recpy_insn_type) < 0
+      || gdbpy_type_ready (&recpy_func_type) < 0
+      || gdbpy_type_ready (&recpy_gap_type) < 0
+      || gdbpy_type_ready (&recpy_aux_type) < 0)
     return -1;
   else
     return 0;
diff --git a/gdb/python/py-registers.c b/gdb/python/py-registers.c
index f03274c308a..229dd62a826 100644
--- a/gdb/python/py-registers.c
+++ b/gdb/python/py-registers.c
@@ -430,35 +430,22 @@  static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_registers ()
 {
   register_descriptor_object_type.tp_new = PyType_GenericNew;
-  if (PyType_Ready (&register_descriptor_object_type) < 0)
-    return -1;
-  if (gdb_pymodule_addobject
-      (gdb_module, "RegisterDescriptor",
-       (PyObject *) &register_descriptor_object_type) < 0)
+  if (gdbpy_type_ready (&register_descriptor_object_type) < 0)
     return -1;
 
   reggroup_iterator_object_type.tp_new = PyType_GenericNew;
-  if (PyType_Ready (&reggroup_iterator_object_type) < 0)
-    return -1;
-  if (gdb_pymodule_addobject
-      (gdb_module, "RegisterGroupsIterator",
-       (PyObject *) &reggroup_iterator_object_type) < 0)
+  if (gdbpy_type_ready (&reggroup_iterator_object_type) < 0)
     return -1;
 
   reggroup_object_type.tp_new = PyType_GenericNew;
-  if (PyType_Ready (&reggroup_object_type) < 0)
-    return -1;
-  if (gdb_pymodule_addobject
-      (gdb_module, "RegisterGroup",
-       (PyObject *) &reggroup_object_type) < 0)
+  if (gdbpy_type_ready (&reggroup_object_type) < 0)
     return -1;
 
   register_descriptor_iterator_object_type.tp_new = PyType_GenericNew;
-  if (PyType_Ready (&register_descriptor_iterator_object_type) < 0)
+  if (gdbpy_type_ready (&register_descriptor_iterator_object_type) < 0)
     return -1;
-  return (gdb_pymodule_addobject
-	  (gdb_module, "RegisterDescriptorIterator",
-	   (PyObject *) &register_descriptor_iterator_object_type));
+
+  return 0;
 }
 
 GDBPY_INITIALIZE_FILE (gdbpy_initialize_registers);
diff --git a/gdb/python/py-symbol.c b/gdb/python/py-symbol.c
index 754420f3b56..1c3a67546b5 100644
--- a/gdb/python/py-symbol.c
+++ b/gdb/python/py-symbol.c
@@ -640,7 +640,7 @@  gdbpy_lookup_static_symbols (PyObject *self, PyObject *args, PyObject *kw)
 static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_symbols (void)
 {
-  if (PyType_Ready (&symbol_object_type) < 0)
+  if (gdbpy_type_ready (&symbol_object_type) < 0)
     return -1;
 
   if (PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_UNDEF", LOC_UNDEF) < 0
@@ -685,8 +685,7 @@  gdbpy_initialize_symbols (void)
 #include "sym-domains.def"
 #undef SYM_DOMAIN
 
-  return gdb_pymodule_addobject (gdb_module, "Symbol",
-				 (PyObject *) &symbol_object_type);
+  return 0;
 }
 
 GDBPY_INITIALIZE_FILE (gdbpy_initialize_symbols);
diff --git a/gdb/python/py-symtab.c b/gdb/python/py-symtab.c
index 7290b856478..99a5094ba60 100644
--- a/gdb/python/py-symtab.c
+++ b/gdb/python/py-symtab.c
@@ -512,19 +512,14 @@  static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_symtabs (void)
 {
   symtab_object_type.tp_new = PyType_GenericNew;
-  if (PyType_Ready (&symtab_object_type) < 0)
+  if (gdbpy_type_ready (&symtab_object_type) < 0)
     return -1;
 
   sal_object_type.tp_new = PyType_GenericNew;
-  if (PyType_Ready (&sal_object_type) < 0)
+  if (gdbpy_type_ready (&sal_object_type) < 0)
     return -1;
 
-  if (gdb_pymodule_addobject (gdb_module, "Symtab",
-			      (PyObject *) &symtab_object_type) < 0)
-    return -1;
-
-  return gdb_pymodule_addobject (gdb_module, "Symtab_and_line",
-				 (PyObject *) &sal_object_type);
+  return 0;
 }
 
 GDBPY_INITIALIZE_FILE (gdbpy_initialize_symtabs);
diff --git a/gdb/python/py-tui.c b/gdb/python/py-tui.c
index 8ad2b7d9733..3be0fb12d9c 100644
--- a/gdb/python/py-tui.c
+++ b/gdb/python/py-tui.c
@@ -625,7 +625,7 @@  gdbpy_initialize_tui ()
 {
 #ifdef TUI
   gdbpy_tui_window_object_type.tp_new = PyType_GenericNew;
-  if (PyType_Ready (&gdbpy_tui_window_object_type) < 0)
+  if (gdbpy_type_ready (&gdbpy_tui_window_object_type) < 0)
     return -1;
 #endif	/* TUI */
 
diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index c13b8610d37..5e00b947e56 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -1526,11 +1526,11 @@  gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw)
 static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_types (void)
 {
-  if (PyType_Ready (&type_object_type) < 0)
+  if (gdbpy_type_ready (&type_object_type) < 0)
     return -1;
-  if (PyType_Ready (&field_object_type) < 0)
+  if (gdbpy_type_ready (&field_object_type) < 0)
     return -1;
-  if (PyType_Ready (&type_iterator_object_type) < 0)
+  if (gdbpy_type_ready (&type_iterator_object_type) < 0)
     return -1;
 
   for (const auto &item : pyty_codes)
@@ -1539,16 +1539,7 @@  gdbpy_initialize_types (void)
 	return -1;
     }
 
-  if (gdb_pymodule_addobject (gdb_module, "Type",
-			      (PyObject *) &type_object_type) < 0)
-    return -1;
-
-  if (gdb_pymodule_addobject (gdb_module, "TypeIterator",
-			      (PyObject *) &type_iterator_object_type) < 0)
-    return -1;
-
-  return gdb_pymodule_addobject (gdb_module, "Field",
-				 (PyObject *) &field_object_type);
+  return 0;
 }
 
 GDBPY_INITIALIZE_FILE (gdbpy_initialize_types);
diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c
index e36768ecd12..a10a7585cd7 100644
--- a/gdb/python/py-unwind.c
+++ b/gdb/python/py-unwind.c
@@ -1002,17 +1002,13 @@  gdbpy_initialize_unwind (void)
 {
   gdb::observers::new_architecture.attach (pyuw_on_new_gdbarch, "py-unwind");
 
-  if (PyType_Ready (&pending_frame_object_type) < 0)
+  if (gdbpy_type_ready (&pending_frame_object_type) < 0)
     return -1;
-  int rc = gdb_pymodule_addobject (gdb_module, "PendingFrame",
-				   (PyObject *) &pending_frame_object_type);
-  if (rc != 0)
-    return rc;
 
-  if (PyType_Ready (&unwind_info_object_type) < 0)
+  if (gdbpy_type_ready (&unwind_info_object_type) < 0)
     return -1;
-  return gdb_pymodule_addobject (gdb_module, "UnwindInfo",
-      (PyObject *) &unwind_info_object_type);
+
+  return 0;
 }
 
 void _initialize_py_unwind ();
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index 37d5716b6d8..98b82a9d295 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -2215,11 +2215,7 @@  gdbpy_is_value_object (PyObject *obj)
 static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
 gdbpy_initialize_values (void)
 {
-  if (PyType_Ready (&value_object_type) < 0)
-    return -1;
-
-  return gdb_pymodule_addobject (gdb_module, "Value",
-				 (PyObject *) &value_object_type);
+  return gdbpy_type_ready (&value_object_type);
 }
 
 GDBPY_INITIALIZE_FILE (gdbpy_initialize_values);
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index bf3ab67ea74..82680cdac0a 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -1119,4 +1119,34 @@  extern std::optional<int> gdbpy_print_insn (struct gdbarch *gdbarch,
 					    CORE_ADDR address,
 					    disassemble_info *info);
 
+/* A wrapper for PyType_Ready that also automatically registers the
+   type in the appropriate module.  Returns 0 on success, -1 on error.
+   If MOD is supplied, then the type is added to that module.  If MOD
+   is not supplied, the type name (tp_name field) must be of the form
+   "gdb.Mumble", and the type will be added to the gdb module.  */
+
+static inline int
+gdbpy_type_ready (PyTypeObject *type, PyObject *mod = nullptr)
+{
+  if (PyType_Ready (type) < 0)
+    return -1;
+  if (mod == nullptr)
+    {
+      gdb_assert (startswith (type->tp_name, "gdb."));
+      mod = gdb_module;
+    }
+  const char *dot = strrchr (type->tp_name, '.');
+  gdb_assert (dot != nullptr);
+  return gdb_pymodule_addobject (mod, dot + 1, (PyObject *) type);
+}
+
+/* Poison PyType_Ready.  Only gdbpy_type_ready should be used, to
+   avoid forgetting to register the type.  See PR python/32163.  */
+#undef PyType_Ready
+#ifdef __GNUC__
+# pragma GCC poison PyType_Ready
+#else
+# define PyType_Ready POISONED_PyType_Ready
+#endif
+
 #endif /* PYTHON_PYTHON_INTERNAL_H */
diff --git a/gdb/python/python.c b/gdb/python/python.c
index a2ce1f6545a..405dc8281a9 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -2316,7 +2316,7 @@  do_start_initialization ()
     return false;
 
 #define GDB_PY_DEFINE_EVENT_TYPE(name, py_name, doc, base)	\
-  if (gdbpy_initialize_event_generic (&name##_event_object_type, py_name) < 0) \
+  if (gdbpy_type_ready (&name##_event_object_type) < 0) \
     return false;
 #include "py-event-types.def"
 #undef GDB_PY_DEFINE_EVENT_TYPE