At least when compiling with optimizations with gcc (GCC) 8.3.1 20190223 (Red Hat 8.3.1-2) the debug info doesn't include the type alias using __node_type = __detail::_Hash_node<_Value, __hash_cached::value> Which causes the pretty printer to fail with ----------------------------------------------------- Traceback (most recent call last): File "/home/espindola/scylla/gdb-printers/libstdcxx/v6/printers.py", line 966, in children data = self.flatten (imap (self.format_one, StdHashtableIterator (self.hashtable()))) File "/home/espindola/scylla/gdb-printers/libstdcxx/v6/printers.py", line 889, in __init__ self.node_type = find_type(hash.type, '__node_type').pointer() File "/home/espindola/scylla/gdb-printers/libstdcxx/v6/printers.py", line 97, in find_type field = typ.fields()[0] IndexError: list index out of range ----------------------------------------------------- To work around that the pretty printer should reconstruct the type. The best I was able to come up with was - self.node_type = find_type(hash.type, '__node_type').pointer() + pair_name = hash.type.template_argument(1).name + traits_type = hash.type.template_argument(9) + cached = str(traits_type.template_argument(0)).lower() + node_name = '::std::__detail::_Hash_node<%s,%s>' % (pair_name, cached) + self.node_type = gdb.lookup_type(node_name).pointer()
From https://bugzilla.redhat.com/show_bug.cgi?id=1053438 this also happens with std::list #include <stdio.h> #include <list> #include <string> int main() { std::list<std::string> list; list.push_back("a"); std::list<std::string>::iterator it=list.begin(); return 0; } $ gdb -q -ex "br 8" -ex r -ex "p it" a.out Reading symbols from a.out... Breakpoint 1 at 0x401237: file 91997.cc, line 8. Starting program: /tmp/a.out Breakpoint 1, main () at 91997.cc:8 8 return 0; Python Exception <class 'ValueError'> Cannot find type std::__cxx11::list<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::iterator::_Node: $1 = (gdb)
Rafael, I'm unable to reproduce this with unordered containers. Do you have a testcase?
(In reply to Jonathan Wakely from comment #2) > Rafael, I'm unable to reproduce this with unordered containers. Do you have > a testcase? I was able to reproduce it with 2 files: $ cat test.cc #include <unordered_map> void foo(std::unordered_map<int, int> &map); int main() { std::unordered_map<int, int> map; map[42] = 1; foo(map); return 0; } $ cat test2.cc #include <unordered_map> #include <stdio.h> void foo(std::unordered_map<int, int> &map) { auto it = map.begin(); printf("%d\n", *it); } $ g++ test.cc test2.cc -o t -g $ /usr/bin/gdb -q -ex "b printf" -ex r -ex bt ./t Reading symbols from ./t... Breakpoint 1 at 0x204b10 Starting program: /home/espindola/scylla/t warning: Loadable section ".note.gnu.property" outside of ELF segments warning: Loadable section ".note.gnu.property" outside of ELF segments warning: Loadable section ".note.gnu.property" outside of ELF segments Breakpoint 1, __printf (format=0x20081b "%d\n") at printf.c:28 28 { #0 __printf (format=0x20081b "%d\n") at printf.c:28 #1 0x000000000020494a in foo (Traceback (most recent call last): File "/lib64/../share/gcc-9/python/libstdcxx/v6/printers.py", line 957, in children data = self.flatten (imap (self.format_one, StdHashtableIterator (self.hashtable()))) File "/lib64/../share/gcc-9/python/libstdcxx/v6/printers.py", line 880, in __init__ self.node_type = find_type(hash.type, '__node_type').pointer() File "/lib64/../share/gcc-9/python/libstdcxx/v6/printers.py", line 97, in find_type field = typ.fields()[0] IndexError: list index out of range map= std::unordered_map with 1 element) at test2.cc:5 #2 0x0000000000203017 in main () at test.cc:6
Thanks, I can confirm that error. Oddly, it works fine when printing the variable within its own stack frame: $ gdb -q -ex "br printf" -ex r -ex up -ex bt -ex down -ex bt -ex cont -ex q map Reading symbols from map... Breakpoint 1 at 0x401030 Starting program: /tmp/map Breakpoint 1, __printf (format=0x403007 "%d\n") at printf.c:28 28 { #1 0x0000000000401272 in foo (map=std::unordered_map with 1 element = {...}) at map.cc:16 16 __builtin_printf("%d\n", *it); #0 __printf (format=0x403007 "%d\n") at printf.c:28 #1 0x0000000000401272 in foo (map=std::unordered_map with 1 element = {...}) at map.cc:16 #2 0x0000000000401203 in main () at map.cc:9 #0 __printf (format=0x403007 "%d\n") at printf.c:28 28 { #0 __printf (format=0x403007 "%d\n") at printf.c:28 #1 0x0000000000401272 in foo (Python Exception <class 'gdb.error'> No type named std::__detail::_Hash_node<struct std::pair<int const, int>, false>.: map=std::unordered_map with 1 element) at map.cc:16 #2 0x0000000000401203 in main () at map.cc:9 Continuing. 42 [Inferior 1 (process 679052) exited normally] It fails when it's not at the top of the stack.
(In reply to Jonathan Wakely from comment #4) > #1 0x0000000000401272 in foo (Python Exception <class 'gdb.error'> No type > named std::__detail::_Hash_node<struct std::pair<int const, int>, false>.: N.B. That's a different error because I'm testing a fix. Apparently it doesn't fix it.
The problem is not missing debuginfo, it's a GDB bug: https://sourceware.org/bugzilla/show_bug.cgi?id=25234 I have a workaround for libstdc++ though.
Author: redi Date: Fri Nov 29 14:47:03 2019 New Revision: 278846 URL: https://gcc.gnu.org/viewcvs?rev=278846&root=gcc&view=rev Log: libstdc++:: improve how pretty printers find node types (PR 91997) This fixes two related problems. The iterators for node-based containers use nested typedefs such as std::list<T>::iterator::_Node to denote their node types. As reported in https://bugzilla.redhat.com/show_bug.cgi?id=1053438 those typedefs are not always present in the debug info. That means the pretty printers cannot find them using gdb.lookup_type (via the find_type helper). Instead of looking up the nested typedefs this patch makes the printers look up the actual class templates directly. A related problem (and the original topic of PR 91997) is that GDB fails to find types via gdb.lookup_type when printing a backtrace from a non-C++ functiion: https://sourceware.org/bugzilla/show_bug.cgi?id=25234 That is also solved by not looking up the nested typedef. PR libstdc++/91997 * python/libstdcxx/v6/printers.py (find_type): Fail more gracefully if we run out of base classes to look at. (llokup_templ_spec, lookup_node_type): New utilities to find node types for node-based containers. (StdListPrinter.children, NodeIteratorPrinter.__init__) (NodeIteratorPrinter.to_string, StdSlistPrinter.children) (StdSlistIteratorPrinter.to_string, StdRbtreeIteratorPrinter.__init__) (StdMapPrinter.children, StdSetPrinter.children) (StdForwardListPrinter.children): Use lookup_node_type instead of find_type. (StdListIteratorPrinter.__init__, StdFwdListIteratorPrinter.__init__): Pass name of node type to NodeIteratorPrinter constructor. (Tr1HashtableIterator.__init__): Rename argument. (StdHashtableIterator.__init__): Likewise. Use lookup_templ_spec instead of find_type. * testsuite/libstdc++-prettyprinters/59161.cc: Remove workaround for _Node typedef not being present in debuginfo. * testsuite/libstdc++-prettyprinters/91997.cc: New test. Added: trunk/libstdc++-v3/testsuite/libstdc++-prettyprinters/91997.cc Modified: trunk/libstdc++-v3/ChangeLog trunk/libstdc++-v3/python/libstdcxx/v6/printers.py trunk/libstdc++-v3/testsuite/libstdc++-prettyprinters/59161.cc
Fixed on trunk, backports to follow.
GCC 8.4.0 has been released, adjusting target milestone.
The releases/gcc-9 branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>: https://gcc.gnu.org/g:b1dba8a228e7d9497d2ddbd012b4343f99b87823 commit r9-9168-gb1dba8a228e7d9497d2ddbd012b4343f99b87823 Author: Jonathan Wakely <jwakely@redhat.com> Date: Fri Nov 29 14:47:03 2019 +0000 libstdc++: improve how pretty printers find node types (PR 91997) This fixes two related problems. The iterators for node-based containers use nested typedefs such as std::list<T>::iterator::_Node to denote their node types. As reported in https://bugzilla.redhat.com/show_bug.cgi?id=1053438 those typedefs are not always present in the debug info. That means the pretty printers cannot find them using gdb.lookup_type (via the find_type helper). Instead of looking up the nested typedefs this patch makes the printers look up the actual class templates directly. A related problem (and the original topic of PR 91997) is that GDB fails to find types via gdb.lookup_type when printing a backtrace from a non-C++ functiion: https://sourceware.org/bugzilla/show_bug.cgi?id=25234 That is also solved by not looking up the nested typedef. PR libstdc++/91997 * python/libstdcxx/v6/printers.py (find_type): Fail more gracefully if we run out of base classes to look at. (llokup_templ_spec, lookup_node_type): New utilities to find node types for node-based containers. (StdListPrinter.children, NodeIteratorPrinter.__init__) (NodeIteratorPrinter.to_string, StdSlistPrinter.children) (StdSlistIteratorPrinter.to_string, StdRbtreeIteratorPrinter.__init__) (StdMapPrinter.children, StdSetPrinter.children) (StdForwardListPrinter.children): Use lookup_node_type instead of find_type. (StdListIteratorPrinter.__init__, StdFwdListIteratorPrinter.__init__): Pass name of node type to NodeIteratorPrinter constructor. (Tr1HashtableIterator.__init__): Rename argument. (StdHashtableIterator.__init__): Likewise. Use lookup_templ_spec instead of find_type. * testsuite/libstdc++-prettyprinters/59161.cc: Remove workaround for _Node typedef not being present in debuginfo. * testsuite/libstdc++-prettyprinters/91997.cc: New test. (cherry picked from commit 9d50a6a78509b42b3c2b2264da1a0d2c4b151d66)
Fixed for 9.4, but I do not plan to backport it to gcc-8.