Message ID | 20161215173917.GA12231@redhat.com |
---|---|
State | New |
Headers | show |
On 15 December 2016 at 19:39, Jonathan Wakely <jwakely@redhat.com> wrote: > This patch tries to improve the user experience when debugging > container iterators, for cases where some of the typedefs used by the > printers are not in the debuginfo, so gdb.lookup_type() calls fail. > That happens if the iterator's operator*() and operator->() haven't > been instantiated, or if they've been inlined. > > Currently this results in an exception: > > $1 = Python Exception <class 'ValueError'> Cannot find type > std::_List_iterator<int>::_Node: > If the iterator being printed is part of some other object the whole > thing fails due to the exception. > > With this patch the iterator instead prints: > > $1 = <insufficient debuginfo for std::list iterator> > > and if it's a subobject the rest of the object is printed, with that > as the value of the iterator. > > * python/libstdcxx/v6/printers.py > (StdListIteratorPrinter.to_string): > Handle exception from failed type lookup and return user-friendly > string. > (StdRbtreeIteratorPrinter.__init__): Handle exception from failed > type lookup. > (StdRbtreeIteratorPrinter.to_string): Return user-friendly string. > > Seem reasonable? Yes, looks like a good improvement. > I consider this a stop-gap until we have Xmethods for all our iterator > types, then we'll be able to "print *iter" even without debuginfo for > all the iterator's members, and we can disable these printers. +1.
On Thu, 2016-12-15 at 17:39 +0000, Jonathan Wakely wrote: > This patch tries to improve the user experience when debugging > container iterators, for cases where some of the typedefs used by the > printers are not in the debuginfo, so gdb.lookup_type() calls fail. > That happens if the iterator's operator*() and operator->() haven't > been instantiated, or if they've been inlined. > > Currently this results in an exception: > > $1 = Python Exception <class 'ValueError'> Cannot find type > std::_List_iterator<int>::_Node: > > If the iterator being printed is part of some other object the whole > thing fails due to the exception. > > With this patch the iterator instead prints: > > $1 = <insufficient debuginfo for std::list iterator> > > and if it's a subobject the rest of the object is printed, with that > as the value of the iterator. > > * python/libstdcxx/v6/printers.py > (StdListIteratorPrinter.to_string): > Handle exception from failed type lookup and return user > -friendly > string. > (StdRbtreeIteratorPrinter.__init__): Handle exception from > failed > type lookup. > (StdRbtreeIteratorPrinter.to_string): Return user-friendly > string. > > Seem reasonable? > > I consider this a stop-gap until we have Xmethods for all our > iterator > types, then we'll be able to "print *iter" even without debuginfo for > all the iterator's members, and we can disable these printers. BTW, is it always a ValueError exception? (I'm a little wary of naked "except:" in Python, as it can catch *anything*, including syntax errors in the try/except-guarded code).
On 15/12/16 13:11 -0500, David Malcolm wrote: >On Thu, 2016-12-15 at 17:39 +0000, Jonathan Wakely wrote: >> This patch tries to improve the user experience when debugging >> container iterators, for cases where some of the typedefs used by the >> printers are not in the debuginfo, so gdb.lookup_type() calls fail. >> That happens if the iterator's operator*() and operator->() haven't >> been instantiated, or if they've been inlined. >> >> Currently this results in an exception: >> >> $1 = Python Exception <class 'ValueError'> Cannot find type >> std::_List_iterator<int>::_Node: >> >> If the iterator being printed is part of some other object the whole >> thing fails due to the exception. >> >> With this patch the iterator instead prints: >> >> $1 = <insufficient debuginfo for std::list iterator> >> >> and if it's a subobject the rest of the object is printed, with that >> as the value of the iterator. >> >> * python/libstdcxx/v6/printers.py >> (StdListIteratorPrinter.to_string): >> Handle exception from failed type lookup and return user >> -friendly >> string. >> (StdRbtreeIteratorPrinter.__init__): Handle exception from >> failed >> type lookup. >> (StdRbtreeIteratorPrinter.to_string): Return user-friendly >> string. >> >> Seem reasonable? >> >> I consider this a stop-gap until we have Xmethods for all our >> iterator >> types, then we'll be able to "print *iter" even without debuginfo for >> all the iterator's members, and we can disable these printers. > >BTW, is it always a ValueError exception? > >(I'm a little wary of naked "except:" in Python, as it can catch >*anything*, including syntax errors in the try/except-guarded code). Good point. As far as I know, the gdb.lookup_type method will throw a ValueError in the case I'm trying to fix. If it can throw other things we can deal with them later by adding other handlers.
diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py index 86de1ca..60afb52 100644 --- a/libstdc++-v3/python/libstdcxx/v6/printers.py +++ b/libstdc++-v3/python/libstdcxx/v6/printers.py @@ -202,10 +202,13 @@ class StdListIteratorPrinter: def to_string(self): if not self.val['_M_node']: return 'non-dereferenceable iterator for std::list' - nodetype = find_type(self.val.type, '_Node') - nodetype = nodetype.strip_typedefs().pointer() - node = self.val['_M_node'].cast(nodetype).dereference() - return str(get_value_from_list_node(node)) + try: + nodetype = find_type(self.val.type, '_Node') + nodetype = nodetype.strip_typedefs().pointer() + node = self.val['_M_node'].cast(nodetype).dereference() + return str(get_value_from_list_node(node)) + except: + return '<insufficient debuginfo for std::list iterator>' class StdSlistPrinter: "Print a __gnu_cxx::slist" @@ -496,12 +499,17 @@ class StdRbtreeIteratorPrinter: def __init__ (self, typename, val): self.val = val valtype = self.val.type.template_argument(0).strip_typedefs() - nodetype = gdb.lookup_type('std::_Rb_tree_node<' + str(valtype) + '>') - self.link_type = nodetype.strip_typedefs().pointer() + try: + nodetype = gdb.lookup_type('std::_Rb_tree_node<' + str(valtype) + '>') + self.link_type = nodetype.strip_typedefs().pointer() + except: + self.link_type = None def to_string (self): if not self.val['_M_node']: return 'non-dereferenceable iterator for associative container' + if self.link_type is None: + return "<insufficient debuginfo for associative container iterator>" node = self.val['_M_node'].cast(self.link_type).dereference() return str(get_value_from_Rb_tree_node(node))