Re: Python API - nested pretty printers MI implications

Andrew Oakley
2011-08-16T22:12:07Z

On Mon, 15 Aug 2011 15:30:08 +0100
Pedro Alves <pedro@codesourcery.com> wrote:
> On Monday 15 August 2011 15:06:10, Andrew Oakley wrote:
> > I assume the idea is to create a gdb.Value (with some data it
> > doesn't really matter what) and then detect that it is that
> > particular gdb.Value when the pretty printers list is searched?
> > Perhaps you could do something like this:
> >
> > def fake_value_printer(val):
> > if hasattr(val, "prettyprinter"):
> > return val.prettyprinter
> > else:
> > return None
> >
> > gdb.pretty_printers.insert(0, fake_value_printer)
> >
> > Then you could just return any old gdb.Value and as long as it had a
> > prettyprinter attribute then that would be called instead of the
> > "normal" version.
> >
> > Is this what you were thinking of?
>
> I was actually thinking more like:
>
> gdb.pretty_printers.insert(0, fake_value_printer)
>
> def fake_value_printer(val):
> isinstance(o, MyFakeValue)
> return FakeValuePrinter(val, or whatever args needed)
> else:
> return None
>
> instead of duck typing, but yes, that sounds similar.
>
> > That's quite a nice trick but I'm not sure its a good long-term
> > solution. It relies on the same python gdb.Value being passed back
> > to the pretty printer selection function
>
> I don't understand.

Imagine for a minute that a "struct value" didn't have a reference to a
gdb.Value. Instead a gdb.Value is created every time we want to pass
a value to python. The result of this is that the pretty-printer could
return one gdb.Value and the pretty printer selection function would
get a completely different gdb.Value that represented the same thing
(breaking any code that worked like the examples above).

Given that GDB is quite happy giving you different gdb.Value objects
for exactly the same thing it doesn't seem unreasonable to expect it to
happen with pretty printers too (and the documentation doesn't say that
it can't happen).

As a random example of GDB returning different gdb.Values for the same
thing:

> $ gdb --quiet `which cat`
> Reading symbols from /bin/cat...Reading symbols from /usr/lib64/debug/bin/cat.debug...done.
> done.
> (gdb) start
> Temporary breakpoint 1 at 0x401d7b: file cat.c, line 502.
> Starting program: /bin/cat
>
> Temporary breakpoint 1, main (argc=1, argv=0x7fffffffe068) at cat.c:5
> 502 cat.c: No such file or directory.
> in cat.c
> (gdb) python print gdb.selected_frame().read_var('argc') is gdb.selected_frame().read_var('argc')
> False
> (gdb)

Given some changes to the MI I can envisage this actually happening in
reality, Daniel Jacobowitz was talking about allowing non-root object
updates which might lead to this kind of behaviour.

I hope this makes more sense now because I don't think I can explain it
any better :(.

> > and probably causes exactly the same problems for the MI.
>
> There'd be no NULL values this way. Wasn't that the problem?

Kind of. Unfortunately this could well confuse front ends. They see
something that looks like a real value, it even has a type they can
"helpfully" display. That's not good because this isn't a real value so
we shouldn't make the FE (and by extension varobj) think that it is.

> > Back to my initial question I guess for MI this is also creating a
> > "dummy" varobj with some type and value chosen by the python
> > script. Do you know if this works in practice with MI frontends?
>
> I'm not sure what you mean. You'd always need a "dummy" varobj
> for each of the "fake values", wouldn't you? (I'm not sure you've
> seen my reply to André though).

Again, it's a question of whether the varobj knows it is fake or not.
I'd prefer it if the varobj did know (even if this isn't exposed over
MI for now).

--
Andrew Oakley