diff mbox series

libstdc++: gdb pretty printer fails from c frame

Message ID 20201222083229.2309147-1-rae.kim@gmail.com
State New
Headers show
Series libstdc++: gdb pretty printer fails from c frame | expand

Commit Message

Rae Kim Dec. 22, 2020, 8:32 a.m. UTC
Pretty prining c++ object from c frame fails with python exception. The
bug filed in gdb bugzilla shows very simple example.

- https://sourceware.org/bugzilla/show_bug.cgi?id=27021

  main.cc:
      #include <stdlib.h>
      #include <map>

      std::map<int, int> foo_map;

      int main()
      {
        foo_map[1] = 10;
        foo_map[2] = 20;
        abort();
      }

  repros:
      > g++ -g main.cc
      > gdb a.out
      (gdb) run
      (gdb) print foo_map
  !!  Python Exception <class 'AttributeError'> 'NoneType' object has no attribute 'pointer':
      $4 = std::map with 2 elements

      (gdb) frame 2
      (gdb) print foo_map
      $5 = std::map with 2 elements = {[1] = 10, [2] = 20}

When str(gdb.Type) is called(implicitly or explicitly) gdb returns type
name differently depending on currently selected frame's language. In
c++ frame, it will return just type name. But in c frame, the type name
will be prepended with "class ", "union ", "enum ", and etc.

e.g)
    # c frame
    (gdb) frame 0
    (gdb) python print(gdb.lookup_symbol('foo_map')[0].value().type)
    class std::map<int, int, std::less<int>, std::allocator<std::pair<int const, int> > >
    ^

    # c++ frame
    (gdb) frame 2
    (gdb) python print(gdb.lookup_symbol('foo_map')[0].value().type)
    std::map<int, int, std::less<int>, std::allocator<std::pair<int const, int> > >
    ^

The prepended "class " is the root causes problem. But this can be
easily mitigated by getting the type name explicitly by using
gdb.Type.name or gdb.Type.tag. I think gdb.Type.tag is prefered because
according to gdb documentation:

    "...The tag name is the name after struct, union, or enum in C and C++..."

e.g.)
    # c frame
    (gdb) frame 0
    (gdb) python print(gdb.lookup_symbol('foo_map')[0].value().type.tag)
    std::map<int, int, std::less<int>, std::allocator<std::pair<int const, int> > >
    ^

libstdc++-v3/ChangeLog:

2020-12-22  Rae Kim  <rae.kim@gmail.com>

	* python/libstdcxx/v6/printers.py (find_type): Use Type.tag.
	(lookup_templ_spec): likewise.
---
 libstdc++-v3/python/libstdcxx/v6/printers.py | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index 9c6393712a0..9f7a16174a8 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -86,7 +86,7 @@  def find_type(orig, name):
     typ = orig.strip_typedefs()
     while True:
         # Strip cv-qualifiers.  PR 67440.
-        search = '%s::%s' % (typ.unqualified(), name)
+        search = '%s::%s' % (typ.unqualified().tag, name)
         try:
             return gdb.lookup_type(search)
         except RuntimeError:
@@ -106,7 +106,14 @@  def lookup_templ_spec(templ, *args):
     """
     Lookup template specialization templ<args...>
     """
-    t = '{}<{}>'.format(templ, ', '.join([str(a) for a in args]))
+    args_str = []
+    for a in args:
+        if isinstance(a, gdb.Type):
+            args_str.append(a.tag)
+        else:
+            args_str.append(str(a))
+
+    t = '{}<{}>'.format(templ, ', '.join(args_str))
     try:
         return gdb.lookup_type(t)
     except gdb.error as e: