public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
From: Jonathan Wakely <jwakely.gcc@gmail.com>
To: Paul Smith <paul@mad-scientist.net>
Cc: "gcc-help@gcc.gnu.org" <gcc-help@gcc.gnu.org>
Subject: Re: Help using the GDB C++ STL pretty-printers / xmethods
Date: Sat, 7 May 2022 20:51:12 +0100	[thread overview]
Message-ID: <CAH6eHdSK0cX65cMUfF+Ub2n2_WmxHKKedQKxE09zvNn7Fv7CPw@mail.gmail.com> (raw)
In-Reply-To: <222e7c9b9ac74aa886c1501792e677a0dfa1f268.camel@mad-scientist.net>

On Sat, 7 May 2022 at 20:07, Paul Smith <paul@mad-scientist.net> wrote:
>
> On Sat, 2022-05-07 at 16:35 +0100, Jonathan Wakely wrote:
> > On Sat, 7 May 2022 at 16:08, Paul Smith <paul@mad-scientist.net>
> > wrote:
> > > Thanks for the reply.  I should have mentioned this; what I do is:
> > >
> > >   python
> > >   from libstdcxx.v6 import register_libstdcxx_printers
> > >   register_libstdcxx_printers(None)
> > >   end
> >
> > Why are you doing this by hand? That should not be necessary.
>
> Well I have this in my init file so I don't really enter it by hand.
> But are you implying that it should somehow happen without having to do
> anything at all... how does that work?  Do you mean, that my
> distribution should have set things up so that it happens
> automatically?

Yes.

> Or that somehow GDB should "find" these macros on its
> own?
>
> Note I am building/installing my own GCC and GDB so maybe I just
> haven't put everything in the right places.

GCC's 'make install' should do everything needed. That installs
$prefix/lib64/libstdc++.so.6.0.30-gdb.py alongside the .so file, and
gdb auto-loads that when debugging a process linked to the
libstdc++.so.6.0.30 library. That python script imports the
register_libstdcxx_printers function and runs it.

Maybe you're only linking statically to libstdc++.a?

>
> > > Just to clarify are you saying that one or both of the methods I've
> > > tried (using * or -> operators) _should_ work, and that they do
> > > work for you when you try them?
> >
> > Yes.
>
> OK, I've discovered what's going on.  Apparently for some reason the
> ability to show the values doesn't happen immediately.  When I attach
> to a process and it's sitting in a sleep somewhere in the C runtime
> like this:
>
>   (gdb) bt
>   #0  0x00007f804634e26f in clock_nanosleep () from /lib/x86_64-linux-
> gnu/libc.so.6
>   #1  0x00007f8046353ef7 in nanosleep () from /lib/x86_64-linux-
> gnu/libc.so.6
>   #2  0x000000000097a3c9 in SignalHandler::sleepUntilSignal
> (this=<optimized out>, response=..., timeoutMs=<optimized out>) at
> SignalHandler.cpp:205
>   #3  0x0000000000960e64 in Engine::main (this=0x7f8045f0f000) at
> Engine.cpp:1374
>   #4  0x000000000098fbdf in Engine::runMain (this=0x7f8045f0f000) at
> Engine.cpp:793
>   #5  0x000000000095f907 in main (argc=<optimized out>, argv=<optimized
> out>) at main.cpp:59
>
> so my current frame is #0, then I run a python function I wrote that
> shows a bunch of info about this process and sets a convenience
> variable for the main pointer $mp, then I try to use it I get the
> errors I showed earlier:
>
>   (gdb) p $mp->mgr->initialized
>   One of the arguments you tried to pass to operator-> could not be
>   converted to what the function wants.
>
> but, now if I change my frame (to one of my frames... it doesn't help
> to go to frame #1 above) it works fine:
>
>   (gdb) fr 2
>   #2  0x000000000097a3c9 in SignalHandler::sleepUntilSignal
> (this=<optimized out>, response=..., timeoutMs=<optimized out>) at
> SignalHandler.cpp:205
>   205         ::nanosleep(&interval, NULL);
>
>   (gdb) p $mp->mgr->initialized
>   $1 = true
>
> Now I can go back down to frame 0 and it still works:
>
>   (gdb) fr 0
>   #0  0x00007f804634e26f in clock_nanosleep () from /lib/x86_64-linux-
> gnu/libc.so.6
>
>   (gdb) p $mp->mgr->initialized
>   $2 = true
>
> I can't find anything in the GDB docs about this but I guess it's a
> question for them, as to what's happening here.

Hmm, that's reminiscent of https://sourceware.org/bugzilla/show_bug.cgi?id=25234

> > > I'm not talking about printing things per se, I'm talking about
> > > writing my own python macros that help me examine my own data
> > > structures, which are built with STL types.
> > >
> > > For example I have a complex structure that uses std::vector,
> > > std::list, std:unordered_map, unique_ptr, etc. and I want to write
> > > my own methods that examine these structures, either to print them
> > > in a different way (not just the standard pretty-printer output) or
> > > whatever.
> >
> > That sounds useful, but it's unlikely anybody else is going to
> > provide it. If you want it, you get to build it :-)
>
> (sorry please replace "macro" with "Python function" everywhere in my
> email... I will try to do better)
>
> I'm pretty sure that's the same answer I got last time I asked :).
>
> I just don't have the time or, probably, the knowledge of the STL
> implementation I would need to do this well.  But I would be happy to
> work with someone, including writing some code, designing some
> features, etc., if anyone else were interested.
>
> What I would really like to have are two things:
>
> (a) iterator classes that I could instantiate from my python functions
> when I need to iterate through an STL type.  So if in my class I have
> "std::list<Foo> fooList" and in my python functions I have a python
> variable "fooList" which refers to this object, I would like a way to
> write something like:
>
>     for elt in StdForwardIterator(fooList):
>         <do something with elt>
>
> Map iterators could return a tuple, etc.
>
> I don't know if it makes more sense to create individual iterator
> classes like above, or to implement Python classes that wrap types and
> provides Pythonic access by implementing Python special methods (so
> that an std::unordered_map object could be treated like a dict or
> whatever).

All the logic to do that in Python is already present in the printers,
it's just that the iterators are GDB pretty-print iterators so have a
different API from general purpose Python iterables. They do exactly
what the printers want, which means the iterator returns ('[n]',
value) for each n in [0,cont.size()). And the StdMapPrinter._iter type
iterators over key,value,key,value,key,value because that's what a
printer with display_hint() = 'map' expects. For your purposes you
probably want (key,value),(key,value),(key,value). But starting from
the existing code and making it do that would take about five minutes
per container, I reckon. I don't think you need any knowledge of the
C++ implementation, because that's already been captured in Python
code.


> (b) Ways to access the contents of containers like unique_ptr,
> shared_ptr, etc. from python functions.  So if in my class I have
> "std::unique_ptr<Foo> fooPtr" and in my python functions I have a
> variable "fooPtr" which refers to this object, I would like a way to
> retrieve a gdb.Value containing its pointer.

The UniquePtrGetWorker Xmethod already does that. You should be able to just do:

 py ptr = gdb.parse_and_eval('uniqptr.get()')

Xmethods seems like the right way to do much of this, because they can
be used at the normal GDB prompt as well as within Python scripts
working in GDB. We could certainly add more Xmethods, but nobody is
asking for them or telling us which ones are missing. Adding things
nobody wants is a waste of time, there are dozens of other things we
can work on instead that people are actually asking for.

If we had a Python type to access a std::unique_ptr maybe it would
make sense to reuse that in both the printer and xmethods for
unique_ptr, and similarly for each other std type that was exposed via
some Python lookalike type. But somebody would have to do the work.

  reply	other threads:[~2022-05-07 19:51 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-07  1:23 Paul Smith
2022-05-07 11:19 ` Hannes Domani
2022-05-07 15:07   ` Paul Smith
2022-05-07 15:35     ` Jonathan Wakely
2022-05-07 19:07       ` Paul Smith
2022-05-07 19:51         ` Jonathan Wakely [this message]
2022-05-07 23:08           ` Paul Smith
2022-05-08  8:13             ` Jonathan Wakely
2022-05-08  8:16               ` Jonathan Wakely
2022-05-08 14:09                 ` Paul Smith
2022-05-08 14:36                   ` Jonathan Wakely
2022-05-08 19:44                 ` Paul Smith
2022-05-08 20:26                   ` Paul Smith
2022-05-09 10:47                     ` Hannes Domani
2022-05-09 10:52                       ` Hannes Domani
2022-05-09  9:32                   ` Jonathan Wakely
2022-05-09 11:23                     ` Jonathan Wakely
2022-05-09 14:05                       ` Paul Smith
2022-05-09 14:40                         ` Paul Smith
2022-05-07 15:44     ` Hannes Domani
2022-05-07 15:25 ` Jonathan Wakely

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAH6eHdSK0cX65cMUfF+Ub2n2_WmxHKKedQKxE09zvNn7Fv7CPw@mail.gmail.com \
    --to=jwakely.gcc@gmail.com \
    --cc=gcc-help@gcc.gnu.org \
    --cc=paul@mad-scientist.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).