]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb: add new helpers for retrieving a type's fully qualified name
authorMatthieu Longo <matthieu.longo@arm.com>
Wed, 28 Jan 2026 13:09:51 +0000 (13:09 +0000)
committerMatthieu Longo <matthieu.longo@arm.com>
Wed, 8 Apr 2026 10:49:30 +0000 (11:49 +0100)
Py_TYPE (self)->tp_name is the traditional idiomatic way to get a Python
type's fully qualified name. However, in the context of the Python
limited API, PyTypeObject is opaque, so the 'tp_name' attribute is no
longer accessible. Additionally, retrieving the type of a Python object
requires Py_TYPE, which is only available as part of the stable API
starting with Python 3.14.

This patch increases minimal Python limited API version from 3.11 to 3.14.
It also introduces two new helpers to retrieve a type's fully qualified
name: gdb_py_tp_name() and gdbpy_py_obj_tp_name(), which extract the fully
qualified name from a PyTypeObject and a PyObject, respectively. Ifdefery
allows these wrappers to select the appropriate API depending on the Python
version and whether the Python limited API is enabled. For any Python
version less than 3.13, gdb_py_tp_name() fallbacks using __qualname__
instead. However, the result may differ slightly in some cases, e.g. the
module name may be missing.

Finally, this patch adapts the existing code to use these wrappers, and
adjusts some test expectations to use the fully qualified name (or
__qualname__ for versions <= 3.13) where it was not previously used.
Note that the corner case where the module name would be missing does not
appear in the testsuite.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23830

Approved-By: Tom Tromey <tom@tromey.com>
24 files changed:
gdb/Makefile.in
gdb/configure
gdb/configure.ac
gdb/python/py-arch.c
gdb/python/py-block.c
gdb/python/py-breakpoint.c
gdb/python/py-connection.c
gdb/python/py-corefile.c
gdb/python/py-disasm.c
gdb/python/py-frame.c
gdb/python/py-infthread.c
gdb/python/py-mi.c
gdb/python/py-micmd.c
gdb/python/py-obj-type.c [new file with mode: 0644]
gdb/python/py-obj-type.h [new file with mode: 0644]
gdb/python/py-style.c
gdb/python/py-symbol.c
gdb/python/py-type.c
gdb/python/py-unwind.c
gdb/python/py-utils.c
gdb/python/python-internal.h
gdb/python/python.c
gdb/testsuite/gdb.python/py-disasm.exp.tcl
gdb/testsuite/gdb.python/py-unwind.exp

index 2488d78958038f46fd3aac530a57683371321e40..81a601dc448b5ec637f8b3a32ffe8b0d48fdb817 100644 (file)
@@ -422,6 +422,7 @@ SUBDIR_PYTHON_SRCS = \
        python/py-micmd.c \
        python/py-newobjfileevent.c \
        python/py-objfile.c \
+       python/py-obj-type.c \
        python/py-param.c \
        python/py-prettyprint.c \
        python/py-progspace.c \
index 14d0848a2271eeafa7f141165ea322d36703df76..abac48b92b25d9fb612d4388e7fa559cfb1c5b82 100755 (executable)
@@ -28765,8 +28765,8 @@ fi
 
 
 if test "$enable_py_limited_api" = yes; then
-  # The minimal Python limited API version is currently set to 3.11 for the
-  # support of PyBuffer_FillInfo and PyBuffer_Release.
+  # The minimal Python limited API version is currently set to 3.14 for the
+  # support of Py_TYPE().
   # The choice of the minimal version for the Python limited API won't be
   # frozen until the end of the migration.
   old_CFLAGS="$CFLAGS"
@@ -28781,8 +28781,8 @@ if test "$enable_py_limited_api" = yes; then
 #ifndef PY_VERSION_HEX
 #error "PY_VERSION_HEX is not defined"
 #endif
-#if PY_VERSION_HEX < 0x030b0000
-#error "Python limited API support requires at least Python version 3.11"
+#if PY_VERSION_HEX < 0x030e0000
+#error "Python limited API support requires at least Python version 3.14"
 #endif
 
 int
@@ -28795,12 +28795,12 @@ main ()
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
 
-$as_echo "#define Py_LIMITED_API 0x030b0000" >>confdefs.h
+$as_echo "#define Py_LIMITED_API 0x030e0000" >>confdefs.h
 
 
 else
 
-      as_fn_error $? "Python limited API support requires at least Python version 3.11" "$LINENO" 5
+      as_fn_error $? "Python limited API support requires at least Python version 3.14" "$LINENO" 5
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
index a6da4ac7b24bb073913a238ecb5f09ce68653cca..cad343ebe8be46959a8a8bfa4fb5e00289b3edb1 100644 (file)
@@ -1078,8 +1078,8 @@ AC_ARG_ENABLE([py-limited-api],
              [enable_py_limited_api=no])
 
 if test "$enable_py_limited_api" = yes; then
-  # The minimal Python limited API version is currently set to 3.11 for the
-  # support of PyBuffer_FillInfo and PyBuffer_Release.
+  # The minimal Python limited API version is currently set to 3.14 for the
+  # support of Py_TYPE().
   # The choice of the minimal version for the Python limited API won't be
   # frozen until the end of the migration.
   old_CFLAGS="$CFLAGS"
@@ -1093,14 +1093,14 @@ if test "$enable_py_limited_api" = yes; then
 #ifndef PY_VERSION_HEX
 #error "PY_VERSION_HEX is not defined"
 #endif
-#if PY_VERSION_HEX < 0x030b0000
-#error "Python limited API support requires at least Python version 3.11"
+#if PY_VERSION_HEX < 0x030e0000
+#error "Python limited API support requires at least Python version 3.14"
 #endif
     ]],[[]])],
-    [AC_DEFINE(Py_LIMITED_API, 0x030b0000,
+    [AC_DEFINE(Py_LIMITED_API, 0x030e0000,
       [Define if GDB should be built against the Python limited C API.])
     ],[
-      AC_MSG_ERROR([Python limited API support requires at least Python version 3.11])
+      AC_MSG_ERROR([Python limited API support requires at least Python version 3.14])
     ])
   CFLAGS="$old_CFLAGS"
   CPPFLAGS="$old_CPPFLAGS"
index 4031f925b04d7b4d940addb4f897ae7369607007..ac0c40dcf45c7075dcde1f20043e55688ab8e134 100644 (file)
@@ -341,7 +341,8 @@ archpy_repr (PyObject *self)
 
   auto arch_info = gdbarch_bfd_arch_info (gdbarch);
   return PyUnicode_FromFormat ("<%s arch_name=%s printable_name=%s>",
-                              Py_TYPE (self)->tp_name, arch_info->arch_name,
+                              gdbpy_py_obj_tp_name (self),
+                              arch_info->arch_name,
                               arch_info->printable_name);
 }
 
index 6e4b662cc513d9a7cfaaa816e4f595d8db24adc0..d9751d26378a253ac4a982c0fbb29e5c6128185f 100644 (file)
@@ -522,7 +522,8 @@ blpy_repr (PyObject *self)
       if (++written_symbols < len)
        str += ", ";
     }
-  return PyUnicode_FromFormat ("<%s %s {%s}>", Py_TYPE (self)->tp_name,
+  return PyUnicode_FromFormat ("<%s %s {%s}>",
+                              gdbpy_py_obj_tp_name (self),
                               name, str.c_str ());
 }
 
index 03388812ff89fde5bc4f27a170b78693881716da..d96c67694b3e96053503b3b1f22b0f4249081497 100644 (file)
@@ -1065,9 +1065,11 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
 static PyObject *
 bppy_repr (PyObject *self)
 {
+  const char *tp_name = gdbpy_py_obj_tp_name (self);
+
   const auto bp = (struct gdbpy_breakpoint_object*) self;
   if (bp->bp == nullptr)
-    return PyUnicode_FromFormat ("<%s (invalid)>", Py_TYPE (self)->tp_name);
+    return PyUnicode_FromFormat ("<%s (invalid)>", tp_name);
 
   std::string str = " ";
   if (bp->bp->thread != -1)
@@ -1079,7 +1081,7 @@ bppy_repr (PyObject *self)
   str.pop_back ();
 
   return PyUnicode_FromFormat ("<%s%s number=%d hits=%d%s>",
-                              Py_TYPE (self)->tp_name,
+                              tp_name,
                               (bp->bp->enable_state == bp_enabled
                                ? "" : " disabled"), bp->bp->number,
                               bp->bp->hit_count, str.c_str ());
@@ -1771,7 +1773,8 @@ bplocpy_repr (PyObject *py_self)
       str += fn_name;
     }
 
-  return PyUnicode_FromFormat ("<%s %s>", Py_TYPE (self)->tp_name,
+  return PyUnicode_FromFormat ("<%s %s>",
+                              gdbpy_py_obj_tp_name (py_self),
                               str.c_str ());
 }
 
index 26cb6cdde57f29ae73f68bf4873f5cf20622d224..a8bea4d832fe91382478282742483529cf0123a9 100644 (file)
@@ -201,7 +201,7 @@ connpy_repr (PyObject *obj)
     return gdb_py_invalid_object_repr (obj);
 
   return PyUnicode_FromFormat ("<%s num=%d, what=\"%s\">",
-                              Py_TYPE (obj)->tp_name,
+                              gdbpy_py_obj_tp_name (obj),
                               target->connection_number,
                               make_target_connection_string (target).c_str ());
 }
index d35838c75237e8f9ae3172f2276cad57720544c3..1daeabb59155af677a520309714d004449e392ad 100644 (file)
@@ -361,7 +361,7 @@ cfpy_repr (PyObject *self)
   bfd *core_bfd = get_inferior_core_bfd (obj->inferior);
   gdb_assert (core_bfd != nullptr);
   return PyUnicode_FromFormat ("<%s inferior=%d filename='%s'>",
-                              Py_TYPE (self)->tp_name,
+                              gdbpy_py_obj_tp_name (self),
                               obj->inferior->num,
                               bfd_get_filename (core_bfd));
 }
index 7635e45db56e08cbccd4e326a273c845beeae51b..1c5661dd307814c3c8c2b67e0932a708bc01f853 100644 (file)
@@ -304,7 +304,7 @@ disasmpy_info_repr (PyObject *self)
   const char *arch_name
     = (gdbarch_bfd_arch_info (obj->gdbarch))->printable_name;
   return PyUnicode_FromFormat ("<%s address=%s architecture=%s>",
-                              Py_TYPE (obj)->tp_name,
+                              gdbpy_py_obj_tp_name (self),
                               core_addr_to_string_nz (obj->address),
                               arch_name);
 }
@@ -995,7 +995,7 @@ disasmpy_result_init (PyObject *self, PyObject *args, PyObject *kwargs)
     {
       PyErr_Format (PyExc_ValueError,
                    _("Cannot use 'string' and 'parts' when creating %s."),
-                   Py_TYPE (self)->tp_name);
+                   gdbpy_py_obj_tp_name (self));
       return -1;
     }
 
@@ -1079,7 +1079,7 @@ disasmpy_result_repr (PyObject *self)
   gdb_assert (obj->parts != nullptr);
 
   return PyUnicode_FromFormat ("<%s length=%d string=\"%U\">",
-                              Py_TYPE (obj)->tp_name,
+                              gdbpy_py_obj_tp_name (self),
                               obj->length,
                               disasmpy_result_str (self));
 }
@@ -1294,7 +1294,7 @@ gdbpy_print_insn (struct gdbarch *gdbarch, CORE_ADDR memaddr,
       PyErr_Format
        (PyExc_TypeError,
         _("Result from Disassembler must be gdb.DisassemblerResult, not %s."),
-        Py_TYPE (result.get ())->tp_name);
+        gdbpy_py_obj_tp_name (result.get ()));
       gdbpy_print_stack ();
       return std::optional<int> (-1);
     }
@@ -1381,8 +1381,9 @@ disasmpy_dealloc_result (PyObject *self)
 static int
 disasmpy_part_init (PyObject *self, PyObject *args, PyObject *kwargs)
 {
-  PyErr_SetString (PyExc_RuntimeError,
-                  _("Cannot create instances of DisassemblerPart."));
+  PyErr_Format (PyExc_RuntimeError,
+               _("Cannot create instances of %s."),
+               gdbpy_py_obj_tp_name (self));
   return -1;
 }
 
@@ -1419,7 +1420,7 @@ disasmpy_text_part_repr (PyObject *self)
   gdb_assert (obj->string != nullptr);
 
   return PyUnicode_FromFormat ("<%s string='%s', style='%s'>",
-                              Py_TYPE (obj)->tp_name,
+                              gdbpy_py_obj_tp_name (self),
                               obj->string->c_str (),
                               get_style_name (obj->style));
 }
@@ -1462,7 +1463,7 @@ disasmpy_addr_part_repr (PyObject *self)
   disasm_addr_part_object *obj = (disasm_addr_part_object *) self;
 
   return PyUnicode_FromFormat ("<%s address='%s'>",
-                              Py_TYPE (obj)->tp_name,
+                              gdbpy_py_obj_tp_name (self),
                               core_addr_to_string_nz (obj->address));
 }
 
index 23d8eff661f0b75e5d15bafc184cfe7aa161fef4..1420d2ac5b9fbe29542b023bf4bf99698c504d23 100644 (file)
@@ -95,7 +95,7 @@ frapy_repr (PyObject *self)
 
   const frame_id &fid = frame_obj->frame_id;
   return PyUnicode_FromFormat ("<%s level=%d frame-id=%s>",
-                              Py_TYPE (self)->tp_name,
+                              gdbpy_py_obj_tp_name (self),
                               frame_relative_level (f_info),
                               fid.to_string ().c_str ());
 }
@@ -544,7 +544,7 @@ frapy_read_var (PyObject *self, PyObject *args, PyObject *kw)
     {
       PyErr_Format (PyExc_TypeError,
                    _("argument 1 must be gdb.Symbol or str, not %s"),
-                   Py_TYPE (sym_obj)->tp_name);
+                   gdbpy_py_obj_tp_name (sym_obj));
       return NULL;
     }
 
index 4adfaa71ae2e3ced6bddf4d85e4c4d5fc7bf80c6..672546e106d1b631d04a18942aa77d64cafb8089 100644 (file)
@@ -354,7 +354,7 @@ thpy_repr (PyObject *self)
 
   thread_info *thr = thread_obj->thread;
   return PyUnicode_FromFormat ("<%s id=%s target-id=\"%s\">",
-                              Py_TYPE (self)->tp_name,
+                              gdbpy_py_obj_tp_name (self),
                               print_full_thread_id (thr),
                               target_pid_to_str (thr->ptid).c_str ());
 }
index 5189bda944ecddd45bd4924553ceb7bdc49ce730..27c79d6063681df6c78a2c057ff19f83df8b9af1 100644 (file)
@@ -379,7 +379,7 @@ gdbpy_notify_mi (PyObject *self, PyObject *args, PyObject *kwargs)
       PyErr_Format
        (PyExc_ValueError,
         _("MI notification data must be either None or a dictionary, not %s"),
-        Py_TYPE (data)->tp_name);
+        gdbpy_py_obj_tp_name (data));
       return nullptr;
     }
 
index ab06e197d84120350e8aa7b069448b4955af180e..6edea04ccb5fb31a28c22978ca84b2ead292302c 100644 (file)
@@ -509,7 +509,7 @@ micmdpy_set_installed (PyObject *self, PyObject *newvalue, void *closure)
     {
       PyErr_Format (PyExc_TypeError,
                    _("gdb.MICommand.installed must be set to a bool, not %s"),
-                   newvalue == Py_None ? "None" : Py_TYPE(newvalue)->tp_name);
+                   newvalue == Py_None ? "None" : gdbpy_py_obj_tp_name (newvalue));
       return -1;
     }
 
diff --git a/gdb/python/py-obj-type.c b/gdb/python/py-obj-type.c
new file mode 100644 (file)
index 0000000..ea0b59a
--- /dev/null
@@ -0,0 +1,74 @@
+/* Helpers related to Python object type
+
+   Copyright (C) 2026 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "python-internal.h"
+#include "py-obj-type.h"
+
+/* Return the type's fully qualified name from a PyTypeObject.  */
+const char *
+gdb_py_tp_name (PyTypeObject *py_type) noexcept
+{
+#if PY_VERSION_HEX >= 0x030d0000
+  /* Note: PyType_GetFullyQualifiedName() was added in version 3.13, and is
+     part of the stable ABI since version 3.13.  */
+  PyObject *fully_qualified_name = PyType_GetFullyQualifiedName (py_type);
+  if (fully_qualified_name == nullptr)
+    return nullptr;
+
+  return PyUnicode_AsUTF8AndSize (fully_qualified_name, nullptr);
+
+#else /* PY_VERSION_HEX < 0x030d0000 && ! defined (Py_LIMITED_API)  */
+  /* For non-heap types, the fully qualified name corresponds to tp_name.  */
+  if (! (PyType_GetFlags (py_type) & Py_TPFLAGS_HEAPTYPE))
+    return py_type->tp_name;
+
+  /* In the absence of PyType_GetFullyQualifiedName(), we fallback using
+     __qualname__ instead. However, the result may differ slightly in some
+     cases, e.g. the module name may be missing.  */
+
+# if PY_VERSION_HEX >= 0x030b0000
+  /* Note: PyType_GetQualName() was added in version 3.11.  */
+  PyObject *qualname = PyType_GetQualName (py_type);
+  if (qualname == nullptr)
+    return nullptr;
+
+  return PyUnicode_AsUTF8AndSize (qualname, nullptr);
+
+# else
+  /* In the absence of PyType_GetQualName(), fallback on using PyHeapTypeObject
+     which is not part of the public API.
+     Tested on 3.10 which is the oldest supported version at the time of this
+     writing, i.e. February 2026.  Hopefully, this workaround should go away
+     when the minimum supported Python version is increased above 3.10.  */
+  PyHeapTypeObject *ht = (PyHeapTypeObject *) py_type;
+  if (ht->ht_qualname == nullptr)
+    return nullptr;
+
+  return PyUnicode_AsUTF8AndSize (ht->ht_qualname, nullptr);
+# endif
+#endif
+}
+
+/* Return the type's fully qualified name from a PyObject.  */
+const char *
+gdbpy_py_obj_tp_name (PyObject *self) noexcept
+{
+  /* Note: Py_TYPE () is part of the stable ABI since version 3.14.  */
+  return gdb_py_tp_name (Py_TYPE (self));
+}
diff --git a/gdb/python/py-obj-type.h b/gdb/python/py-obj-type.h
new file mode 100644 (file)
index 0000000..293647f
--- /dev/null
@@ -0,0 +1,29 @@
+/* Helpers related to Python object type
+
+   Copyright (C) 2026 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef GDB_PYTHON_PY_OBJ_TYPE_H
+#define GDB_PYTHON_PY_OBJ_TYPE_H
+
+/* Return the type's fully qualified name from a PyTypeObject.  */
+extern const char *gdb_py_tp_name (PyTypeObject *py_type) noexcept;
+
+/* Return the type's fully qualified name from a PyObject.  */
+extern const char *gdbpy_py_obj_tp_name (PyObject *self) noexcept;
+
+#endif /* GDB_PYTHON_PY_OBJ_TYPE_H */
index d149d90aaa9f1b1d1e4fc0892802796bb04599e3..60a9ea4792ffaef67d52929496b60e4ead425a4d 100644 (file)
@@ -267,7 +267,7 @@ stylepy_init_from_parts (PyObject *self, PyObject *fg, PyObject *bg,
       PyErr_Format
        (PyExc_TypeError,
         _("'foreground' argument must be gdb.Color or None, not %s."),
-        Py_TYPE (fg)->tp_name);
+        gdbpy_py_obj_tp_name (fg));
       return -1;
     }
 
@@ -276,7 +276,7 @@ stylepy_init_from_parts (PyObject *self, PyObject *fg, PyObject *bg,
       PyErr_Format
        (PyExc_TypeError,
         _("'background' argument must be gdb.Color or None, not %s."),
-        Py_TYPE (bg)->tp_name);
+        gdbpy_py_obj_tp_name (bg));
       return -1;
     }
 
@@ -483,7 +483,7 @@ stylepy_set_foreground (PyObject *self, PyObject *newvalue, void *closure)
   if (!gdbpy_is_color (newvalue))
     {
       PyErr_Format (PyExc_TypeError, _("value must be gdb.Color, not %s"),
-                   Py_TYPE (newvalue)->tp_name);
+                   gdbpy_py_obj_tp_name (newvalue));
       return -1;
     }
 
@@ -541,7 +541,7 @@ stylepy_set_background (PyObject *self, PyObject *newvalue, void *closure)
   if (!gdbpy_is_color (newvalue))
     {
       PyErr_Format (PyExc_TypeError, _("value must be gdb.Color, not %s"),
-                   Py_TYPE (newvalue)->tp_name);
+                   gdbpy_py_obj_tp_name (newvalue));
       return -1;
     }
 
@@ -623,7 +623,7 @@ stylepy_set_intensity (PyObject *self, PyObject *newvalue, void *closure)
       PyErr_Format
        (PyExc_TypeError,
         _("value must be a Long (a gdb.INTENSITY constant), not %s"),
-        Py_TYPE (newvalue)->tp_name);
+        gdbpy_py_obj_tp_name (newvalue));
       return -1;
     }
 
@@ -733,12 +733,12 @@ stylepy_repr (PyObject *self)
 
   if (style_obj->style_name == nullptr)
     return PyUnicode_FromFormat ("<%s fg=%s, bg=%s, intensity=%s>",
-                                Py_TYPE (self)->tp_name,
+                                gdbpy_py_obj_tp_name (self),
                                 fg_str.get (), bg_str.get (),
                                 intensity_str);
   else
     return PyUnicode_FromFormat ("<%s name='%s', fg=%s, bg=%s, intensity=%s>",
-                                Py_TYPE (self)->tp_name,
+                                gdbpy_py_obj_tp_name (self),
                                 style_obj->style_name, fg_str.get (),
                                 bg_str.get (), intensity_str);
 }
index fe4d6dac000806995cfbcf2a074a609cae891b82..e74c8e4b3680b51e7916ca429d48c97264160d40 100644 (file)
@@ -384,7 +384,8 @@ sympy_repr (PyObject *self)
   if (symbol == nullptr)
     return gdb_py_invalid_object_repr (self);
 
-  return PyUnicode_FromFormat ("<%s print_name=%s>", Py_TYPE (self)->tp_name,
+  return PyUnicode_FromFormat ("<%s print_name=%s>",
+                              gdbpy_py_obj_tp_name (self),
                               symbol->print_name ());
 }
 
index e1c57928b08c9354f058cdfd86c617e668f58c7e..263d48a93650a9cc935d24623598f1ce7ab3ee14 100644 (file)
@@ -1081,7 +1081,8 @@ typy_repr (PyObject *self)
   auto py_typename = PyUnicode_Decode (type_name.c_str (), type_name.size (),
                                       host_charset (), NULL);
 
-  return PyUnicode_FromFormat ("<%s code=%s name=%U>", Py_TYPE (self)->tp_name,
+  return PyUnicode_FromFormat ("<%s code=%s name=%U>",
+                              gdbpy_py_obj_tp_name (self),
                               code, py_typename);
 }
 
index 9ffa382d0931f3cc0b95343e1467d60b239ecd7a..dcf86f7db3d7331849e7245c5f4cb1d566b30493 100644 (file)
@@ -247,7 +247,7 @@ unwind_infopy_repr (PyObject *self)
 
   if (frame == nullptr)
     return PyUnicode_FromFormat ("<%s for an invalid frame>",
-                                Py_TYPE (self)->tp_name);
+                                gdbpy_py_obj_tp_name (self));
 
   std::string saved_reg_names;
   struct gdbarch *gdbarch = pending_frame->gdbarch;
@@ -262,7 +262,7 @@ unwind_infopy_repr (PyObject *self)
     }
 
   return PyUnicode_FromFormat ("<%s frame #%d, saved_regs=(%s)>",
-                              Py_TYPE (self)->tp_name,
+                              gdbpy_py_obj_tp_name (self),
                               frame_relative_level (frame),
                               saved_reg_names.c_str ());
 }
@@ -456,7 +456,7 @@ pending_framepy_repr (PyObject *self)
     }
 
   return PyUnicode_FromFormat ("<%s level=%d, sp=%s, pc=%s>",
-                              Py_TYPE (self)->tp_name,
+                              gdbpy_py_obj_tp_name (self),
                               frame_relative_level (frame),
                               sp_str,
                               pc_str);
@@ -924,7 +924,7 @@ frame_unwind_python::sniff (const frame_info_ptr &this_frame,
   gdb_assert (pyo_unwind_info != nullptr);
   if (!PyObject_TypeCheck (pyo_unwind_info, &unwind_info_object_type))
     error (_("an Unwinder should return gdb.UnwindInfo, not %s."),
-          Py_TYPE (pyo_unwind_info)->tp_name);
+          gdbpy_py_obj_tp_name (pyo_unwind_info));
 
   {
     unwind_info_object *unwind_info =
index 484fc4611b719365e23fd9eea7bfb63e1104afcd..96f1cb1ee3158de661efaee3fa4e31c511cb8ccb 100644 (file)
@@ -362,7 +362,7 @@ gdb_py_generic_getattro (PyObject *self, PyObject *attr)
      Therefore, we must explicitly raise an AttributeError in this case.  */
   PyErr_Format (PyExc_AttributeError,
                "'%s' object has no attribute '%s'",
-               Py_TYPE (self)->tp_name,
+               gdbpy_py_obj_tp_name (self),
                PyUnicode_AsUTF8AndSize (attr, nullptr));
   return nullptr;
 }
@@ -700,5 +700,5 @@ gdbpy_fix_doc_string_indentation (gdb::unique_xmalloc_ptr<char> doc)
 PyObject *
 gdb_py_invalid_object_repr (PyObject *self)
 {
-  return PyUnicode_FromFormat ("<%s (invalid)>", Py_TYPE (self)->tp_name);
+  return PyUnicode_FromFormat ("<%s (invalid)>", gdbpy_py_obj_tp_name (self));
 }
index b24b9314994b0cbfd027348825a5350c125a334f..37bc37691fe41b351c560ebd3a6c46c8735e21b3 100644 (file)
@@ -59,6 +59,7 @@
 #include <Python.h>
 #include <frameobject.h>
 #include "py-ref.h"
+#include "py-obj-type.h"
 
 static_assert (PY_VERSION_HEX >= 0x03040000);
 
@@ -1126,12 +1127,13 @@ gdbpy_type_ready (PyTypeObject *type, PyObject *mod = nullptr)
 {
   if (PyType_Ready (type) < 0)
     return -1;
+  const char *tp_name = gdb_py_tp_name (type);
   if (mod == nullptr)
     {
-      gdb_assert (startswith (type->tp_name, "gdb."));
+      gdb_assert (startswith (tp_name, "gdb."));
       mod = gdb_module;
     }
-  const char *dot = strrchr (type->tp_name, '.');
+  const char *dot = strrchr (tp_name, '.');
   gdb_assert (dot != nullptr);
   return gdb_pymodule_addobject (mod, dot + 1, (PyObject *) type);
 }
index 6e13ab5bb3f76693b719d17ebf4fde91ca1d431e..4182c699cb5d193582221278110bd7f2417f0c24 100644 (file)
@@ -1579,7 +1579,7 @@ gdbpy_write (PyObject *self, PyObject *args, PyObject *kw)
       PyErr_Format
        (PyExc_TypeError,
         _("'style' argument must be gdb.Style or None, not %s."),
-        Py_TYPE (style_obj)->tp_name);
+        gdbpy_py_obj_tp_name (style_obj));
       return nullptr;
     }
 
index 07131a44bff8b2b12a905683dbd5777e3be98f73..e4391fa59ced996087bdfbee65cf822a1fa76d00 100644 (file)
@@ -124,7 +124,7 @@ set test_plans \
         [list "" "${base_pattern}\r\n.*"] \
         [list "GlobalNullDisassembler" "${base_pattern}\r\n.*"] \
         [list "ShowInfoRepr" "${base_pattern}\\s+## <gdb.disassembler.DisassembleInfo address=$hex architecture=\[^>\]+>\r\n.*"] \
-        [list "ShowInfoSubClassRepr" "${base_pattern}\\s+## <MyInfo address=$hex architecture=\[^>\]+>\r\n.*"] \
+        [list "ShowInfoSubClassRepr" "${base_pattern}\\s+## <ShowInfoSubClassRepr.MyInfo address=$hex architecture=\[^>\]+>\r\n.*"] \
         [list "ShowResultRepr" "${base_pattern}\\s+## <gdb.disassembler.DisassemblerResult length=$decimal string=\"\[^\r\n\]+\">\r\n.*"] \
         [list "ShowResultStr" "${base_pattern}\\s+## ${nop}\r\n.*"] \
         [list "GlobalPreInfoDisassembler" "${base_pattern}\\s+## ad = $hex, ar = ${curr_arch}\r\n.*"] \
@@ -154,10 +154,10 @@ set test_plans \
                   "Buffer returned from read_memory is sized $decimal instead of the expected $decimal"]] \
         [list "ResultOfWrongType" \
              [make_exception_pattern "TypeError" \
-                  "Result from Disassembler must be gdb.DisassemblerResult, not Blah."]] \
+                  "Result from Disassembler must be gdb.DisassemblerResult, not ResultOfWrongType.Blah."]] \
         [list "ResultOfVeryWrongType" \
              [make_exception_pattern "TypeError" \
-                  "Result from Disassembler must be gdb.DisassemblerResult, not Blah."]] \
+                  "Result from Disassembler must be gdb.DisassemblerResult, not ResultOfVeryWrongType.Blah."]] \
         [list "ErrorCreatingTextPart_NoArgs" \
              [make_exception_pattern "TypeError" \
                   [missing_arg_pattern "style" 1]]] \
@@ -337,7 +337,7 @@ foreach len {0 -1} {
 foreach type {DisassemblerTextPart DisassemblerAddressPart} {
     gdb_test "python result = gdb.disassembler.${type}()" \
        [multi_line \
-            "RuntimeError.*: Cannot create instances of DisassemblerPart\\." \
+            "RuntimeError.*: Cannot create instances of gdb.disassembler.${type}\\." \
             "Error occurred in Python.*"] \
         "try to create an instance of ${type}"
 }
index 8c90da50a1d8d866e28cdb293657e61a32c7c146..784d9dfcb64d33e6bbfd869a456891051ce9471d 100644 (file)
@@ -249,7 +249,7 @@ with_test_prefix "bad object unwinder" {
     gdb_test_no_output "python obj = bad_object_unwinder(\"bad-object\")"
     gdb_test_no_output "python gdb.unwinder.register_unwinder(None, obj, replace=True)"
     gdb_test "backtrace" \
-       "Python Exception <class 'gdb.error'>: an Unwinder should return gdb.UnwindInfo, not Blah\\.\r\n.*"
+       "Python Exception <class 'gdb.error'>: an Unwinder should return gdb.UnwindInfo, not bad_object_unwinder.+Blah\\.\r\n.*"
 }
 
 # Gather information about every frame.