|
List Info
Thread: Questions about MI variable objects
|
|
| Questions about MI variable objects |
  United States |
2007-05-24 17:17:26 |
I have some questions for GUI implementors. Suppose I have
the
following program:
void
foo (int x)
{
if (x > 0)
foo (x - 1);
}
void
bar (int x)
{
foo (x - 1);
}
int
main (int argc, char **argv)
{
foo (2);
bar (10);
return 0;
}
Suppose I'm stopped where the stack is like this:
main -> foo (2) -> foo (1) -> foo (0)
Suppose the top frame is selected, and the user adds a
display for
'x'. Clearly, it should show '0'.
These are questions about what the GUI should display ---
not what GDB
or MI or varobjs should do. They're about what you want the
user to
see.
1) If the user selects the 'foo (1)' frame, what should
happen to the
display of 'x'? Should it grey out? Should it now show
1? (I'd
say it should show 1.)
2) If the user lets the 'foo (0)' call run to completion (as
with a
GDB CLI 'finish' command), what should happen to the
display of
'x'? Should it disappear altogether? Should it grey
out? Should
it show 1? (I'd say it should show 1.)
3) If the user lets control go all the way back to main,
what should
happen to the display? (I'd say it should grey out.)
4) If the user lets control run to 'foo' again, so the stack
now looks
like:
main -> bar (10) -> foo (9)
what should happen to the display of 'x'? (I'd say it
should show
'9'.)
If there's some general agreement on how these ought to
behave (not
necessarily my guesses, just any agreement) then maybe we
could make
MI varobjs match that behavior, so that each GUI variable
display
could be backed by exactly one varobj, and GDB's reports on
changes to
the varobj's state would correspond closely to changes in
the GUI's
display. Varobjs exist to help GUIs, and GDB shouldn't be
making GUIs
jump through hoops to get the behavior they want.
The principle behind my guesses is that a display should
refer to a
particular variable in the source code --- a particular
declaration
--- and should show its value whenever that declaration is
in scope in
the selected frame. This is less specific than having the
display
refer to a particular frame's instance of that variable, and
more
specific than having it refer to any variable that happens
to be in
scope under that name. But it's what I'd expect from a
GUI.
At the moment, GDB tries to associate each varobj with a
specific
function invocation. It's so easy to concoct a case where
frame ID's
collide that in casual testing, the varobj code may appear
to
implement something more like my suggested behavior. But it
doesn't.
|
|
| Re: Questions about MI variable objects |

|
2007-05-24 22:35:01 |
> Suppose I'm stopped where the stack is like this:
>
> main -> foo (2) -> foo (1) -> foo (0)
>
> Suppose the top frame is selected, and the user adds a
display for
> 'x'. Clearly, it should show '0'.
>
> These are questions about what the GUI should display
--- not what GDB
> or MI or varobjs should do. They're about what you
want the user to
> see.
>
> 1) If the user selects the 'foo (1)' frame, what
should happen to the
> display of 'x'? Should it grey out? Should it now
show 1? (I'd
> say it should show 1.)
I think "-var-create - var1" does this i.e.
follows the selected frame but I
currently only use "-var-create - * var1" to
generate watch expressions for
Emacs. I only grey expressions out when the frame they are
created in
disappears.
> 2) If the user lets the 'foo (0)' call run to
completion (as with a
> GDB CLI 'finish' command), what should happen to
the display of
> 'x'? Should it disappear altogether? Should it
grey out? Should
> it show 1? (I'd say it should show 1.)
There's a case for both behaviours. Emacs greys it out, but
it could offer
an option to show 1. This would only be an issue with
recursion, and since
iteration is generally better, I've not offered it for Emacs
yet.
> 3) If the user lets control go all the way back to
main, what should
> happen to the display? (I'd say it should grey
out.)
>
> 4) If the user lets control run to 'foo' again, so the
stack now looks
> like:
>
> main -> bar (10) -> foo (9)
>
> what should happen to the display of 'x'? (I'd say
it should show
> '9'.)
That's what Emacs currently does and what the default GDB
behaviour gives,
although Daniel J doesn't seem to think it's useful.
> If there's some general agreement on how these ought
to behave (not
> necessarily my guesses, just any agreement) then maybe
we could make
> MI varobjs match that behavior, so that each GUI
variable display
> could be backed by exactly one varobj, and GDB's
reports on changes to
> the varobj's state would correspond closely to changes
in the GUI's
> display. Varobjs exist to help GUIs, and GDB
shouldn't be making GUIs
> jump through hoops to get the behavior they want.
I'm not sure how you intend to change GDB's behaviour but I
think it should
provide options rather than define the policy.
> The principle behind my guesses is that a display
should refer to a
> particular variable in the source code --- a
particular declaration
> --- and should show its value whenever that
declaration is in scope in
> the selected frame. This is less specific than having
the display
> refer to a particular frame's instance of that
variable, and more
> specific than having it refer to any variable that
happens to be in
> scope under that name. But it's what I'd expect from
a GUI.
I don't know what to expect. I've always intended to base
the display
behavior on user feedback, but until Emacs is released I
guess I won't get
much.
> At the moment, GDB tries to associate each varobj with
a specific
> function invocation. It's so easy to concoct a case
where frame ID's
> collide that in casual testing, the varobj code may
appear to
> implement something more like my suggested behavior.
But it doesn't.
I don't really follow. Can you give an real example where
frame IDs collide?
--
Nick http://www.inet.net.n
z/~nickrob
|
|
| Re: Questions about MI variable objects |
  United States |
2007-05-25 12:11:32 |
Vladimir Prus <ghost cs.msu.su> writes:
>> Suppose I'm stopped where the stack is like this:
>>
>> main -> foo (2) -> foo (1) -> foo (0)
>>
>> Suppose the top frame is selected, and the user
adds a display for
>> 'x'. Clearly, it should show '0'.
>
> You're using an ill-defined term "adds a
display".
Well, sure. I'm asking people to tell me about all the GUIs
they work
on, so I can't use specific language.
>> 4) If the user lets control run to 'foo' again, so
the stack now looks
>> like:
>>
>> main -> bar (10) -> foo (9)
>>
>> what should happen to the display of 'x'? (I'd
say it should show
>> '9'.)
>
> I agree.
>
> I think that -variable-object should behave as
described above.
Right; I wasn't aware of ' '-frame varobjs when I
originally wrote,
since they're not documented.
> Note also that it's possible to imagine GUI commands
that show a
> value of some expression in particular
"scope", and became
> forever grayed out when that scope dies. It raises
numerous
> questions how to identify scopes. It should be noted
that KDevelop
> does not have such UI command, and it was never
requested.
Yeah, it doesn't seem too useful.
>> The principle behind my guesses is that a display
should refer to a
>> particular variable in the source code --- a
particular declaration
>> --- and should show its value whenever that
declaration is in scope in
>> the selected frame. This is less specific than
having the display
>> refer to a particular frame's instance of that
variable, and more
>> specific than having it refer to any variable that
happens to be in
>> scope under that name. But it's what I'd expect
from a GUI.
>
> This seem to contradict your claim that in 'bar', we
should show '9'
> for 'x' -- it's different 'x', after all.
You misread --- I said we should show '9' in the first call
to foo
from bar.
> Assume user asked to show value of "x+y".
There are three alternatives:
>
> 1. Show value of that expression in specific frame,
gray it out
> otherwise.
> 2. Show value of that expression in current frame,
provided "x" and "y"
> refer to the same language declaration.
> 3. Show value of that expression in current frame.
>
> (3) is what implemented by -varobjs. You seem to
propose (2),
> which will only differ from (2) by the fact that
sometimes (3) will show
> a value and (2) will have value greyed. Is this big
enough deal to
> worry about?
Yes, that is the distinction. If it's not important to GUI
implementors, then it's certainly not a big enough deal to
worry
about.
> As for (1), it's implemented by ordinary varobjs.
Except for the frame collision behavior which I
demonstrated, yes.
|
|
| Re: Questions about MI variable objects |
  United States |
2007-05-25 11:26:53 |
Nick Roberts <nickrob snap.net.nz> writes:
> > Suppose I'm stopped where the stack is like
this:
> >
> > main -> foo (2) -> foo (1) -> foo
(0)
> >
> > Suppose the top frame is selected, and the user
adds a display for
> > 'x'. Clearly, it should show '0'.
> >
> > These are questions about what the GUI should
display --- not what GDB
> > or MI or varobjs should do. They're about what
you want the user to
> > see.
> >
> > 1) If the user selects the 'foo (1)' frame, what
should happen to the
> > display of 'x'? Should it grey out? Should
it now show 1? (I'd
> > say it should show 1.)
>
> I think "-var-create - var1" does this i.e.
follows the selected frame but I
> currently only use "-var-create - * var1" to
generate watch expressions for
> Emacs. I only grey expressions out when the frame they
are created in
> disappears.
Oh, I see --- USE_SELECTED_FRAME. That's not documented; we
should
fix that.
So, if Emacs wants displays to grey out when the frame
disappears,
does it ever expect those expressions to become ungrey
again? After
all, that frame is gone forever. Under what conditions
should the
display become ungrey?
> > 4) If the user lets control run to 'foo' again,
so the stack now looks
> > like:
> >
> > main -> bar (10) -> foo (9)
> >
> > what should happen to the display of 'x'?
(I'd say it should show
> > '9'.)
>
> That's what Emacs currently does and what the default
GDB behaviour gives,
> although Daniel J doesn't seem to think it's useful.
Actually, I don't believe you. Would you
humor me and try this
out?
- Start with the program I posted.
- Set a breakpoint on foo.
- Run to the third hit (that is, foo (0))
- Display 'x'.
- finish three times, so that we're back in main. We all
agree the
display should be 'greyed' out at this point.
- continue to the next hit of foo.
When I do this with what I assume are the corresponding MI
commands,
the varobj I made for x in foo (0) is still out of scope.
If I continue again, I happen to get a frame whose address
matches the
original foo (0) address, and the varobj comes back in
scope, but this
is, again, a spurious frame ID match. It happens only
because the
frames sizes on the stack happen to line up. The compiler
could
generate different, correct, code and the varobj behavior
would stop
working.
So, at the moment, your displays based on '*'-frame varobjs
ungrey at
times that appear reasonable in simple test programs, but
are actually
dependent on flukes of your compiler's stack management.
Setting aside MI and GDB and varobjs, from your users' point
of view,
when should that display come alive again?
> > If there's some general agreement on how these
ought to behave (not
> > necessarily my guesses, just any agreement) then
maybe we could make
> > MI varobjs match that behavior, so that each GUI
variable display
> > could be backed by exactly one varobj, and GDB's
reports on changes to
> > the varobj's state would correspond closely to
changes in the GUI's
> > display. Varobjs exist to help GUIs, and GDB
shouldn't be making GUIs
> > jump through hoops to get the behavior they
want.
>
> I'm not sure how you intend to change GDB's behaviour
but I think it should
> provide options rather than define the policy.
MI is a protocol; I don't want to break backwards
compatibility. But
there's no point in retaining backwards compatibility with a
bug ---
when that bug's behavior is unpredictable.
> > The principle behind my guesses is that a display
should refer to a
> > particular variable in the source code --- a
particular declaration
> > --- and should show its value whenever that
declaration is in scope in
> > the selected frame. This is less specific than
having the display
> > refer to a particular frame's instance of that
variable, and more
> > specific than having it refer to any variable
that happens to be in
> > scope under that name. But it's what I'd expect
from a GUI.
>
> I don't know what to expect. I've always intended to
base the display
> behavior on user feedback, but until Emacs is released
I guess I won't get
> much.
>
> > At the moment, GDB tries to associate each varobj
with a specific
> > function invocation. It's so easy to concoct a
case where frame ID's
> > collide that in casual testing, the varobj code
may appear to
> > implement something more like my suggested
behavior. But it doesn't.
>
> I don't really follow. Can you give an real example
where frame IDs collide?
Well, since it depends on the stack management code the
compiler
emits, it's compiler-specific. But on a Fedora Core 6 x86
machine:
$ cat vo.c
void
foo (int x)
{
if (x > 0)
foo (x - 1);
}
void
bar (int x)
{
foo (x - 1);
}
int
main (int argc, char **argv)
{
foo (2);
bar (2);
return 0;
}
$ gcc -g vo.c -o vo
$ ~/uberbaum/build-cvs-out/gdb/gdb vo
GNU gdb 6.6.50.20070516-cvs
Copyright (C) 2007 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public
License, and you are
welcome to change it and/or distribute copies of it under
certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show
warranty" for details.
This GDB was configured as
"i686-pc-linux-gnu"...
Using host libthread_db library
"/lib/libthread_db.so.1".
(gdb) break foo if x == 0
Breakpoint 1 at 0x804832a: file vo.c, line 4.
(gdb) run
Starting program: /home/jimb/play/vo
Breakpoint 1, foo (x=0) at vo.c:4
4 if (x > 0)
(gdb) info frame
Stack level 0, frame at 0xbf9c98d8:
eip = 0x804832a in foo (vo.c:4); saved eip 0x804833e
called by frame at 0xbf9c98e4
source language c.
Arglist at 0xbf9c98d0, args: x=0
Locals at 0xbf9c98d0, Previous frame's sp is 0xbf9c98d8
Saved registers:
ebp at 0xbf9c98d0, eip at 0xbf9c98d4
Since the breakpoint was conditional on x being zero, the
stack now
looks like this:
main -> foo (2) -> foo (1) -> foo (0)
Note the "frame at" address. The frame ID is that
address, along with
the entry point of foo. We'll create a varobj looking at x,
just for
fun:
(gdb) interpreter mi3 "-var-create a * x"
^done,name="a",numchild="0",value="
0",type="int"
(gdb)
(gdb) finish
Run till exit from #0 foo (x=0) at vo.c:4
foo (x=1) at vo.c:6
6 }
(gdb) interpreter mi3 "-var-update *"
^done,changelist=[{name="a",in_scope="false&q
uot;}]
(gdb)
So, we're in a different call to foo, but it's got a
different frame
ID, and MI considers our varobj to be out of scope. Which
is fine: we
created it with '*', so it's attached to the now-popped 'foo
(0)'
frame.
(gdb) finish
Run till exit from #0 foo (x=1) at vo.c:6
foo (x=2) at vo.c:6
6 }
(gdb) finish
#0 fooRun till exit from (x=2) at vo.c:6
main () at vo.c:18
18 bar (2);
(gdb) info frame
Stack level 0, frame at 0xbf9c9900:
eip = 0x8048373 in main (vo.c:18); saved eip 0x98cf2c
source language c.
Arglist at 0xbf9c98f8, args:
Locals at 0xbf9c98f8, Previous frame's sp at 0xbf9c98f4
Saved registers:
ebp at 0xbf9c98f8, eip at 0xbf9c98fc
(gdb) interpreter mi3 "-var-update *"
^done,changelist=[{name="a",in_scope="false&q
uot;}]
(gdb)
This is all as we'd expect: the frame address for 'main' is
greater
(the stack grows towards lower addresses), and the varobj is
out of
scope.
We'll run until the next hit of the breakpoint --- which is
conditional on x == 0, remember, so the stack will look like
this:
main -> bar (2) -> foo (1) -> foo (0)
(gdb) continue
Continuing.
Breakpoint 1, foo (x=0) at vo.c:4
4 if (x > 0)
(gdb) info frame
Stack level 0, frame at 0xbf9c98d8:
eip = 0x804832a in foo (vo.c:4); saved eip 0x804833e
called by frame at 0xbf9c98e4
source language c.
Arglist at 0xbf9c98d0, args: x=0
Locals at 0xbf9c98d0, Previous frame's sp is 0xbf9c98d8
Saved registers:
ebp at 0xbf9c98d0, eip at 0xbf9c98d4
Here is the spurious frame ID collision. This call to foo
is entirely
distict from the one in which we created the varobj, but
because 1)
main didn't change its stack size, 2) bar (2) happens to
have the same
frame size as foo (2), and 3) foo happens to use consistent
frame
sizes each time it's called, the frame address is the same
for the
second foo (0) as it was for the first. And indeed, MI
considers the
varobj to be back in scope:
(gdb) interpreter mi3 "-var-update *"
^done,changelist=[{name="a",in_scope="true&qu
ot;,type_changed="false"}]
(gdb)
(gdb)
Now, if I add a local variable 'int a[1];' to bar, and
compile again
without optimization, that changes bar's frame size, and the
exact
same series of commands plays out differently: the varobj
won't come
back into scope.
Any GUI which relies on '*'-frame varobjs coming back into
scope has
behavior dependent on internal details of the compiler's
behavior, and
is buggy.
|
|
| Re: Questions about MI variable objects |
  United States |
2007-05-25 13:42:08 |
Adding a little complexity to the issue... We implemented
flyover
variables using the varobj system. In that case, you can't
just say
"show me variable "x" in the current scope,
because if you have:
void foo ()
{
int x = 5;
printf ("Here I got %dn", x);
{
int x = 6;
printf ("Here I got %dn", x); /* Break here
*/
}
}
and the pc is at the second printf, but the user points at
"x" in the
first printf, you want to show "5" and not
"6". We extended this by
adding a "+" form of the varobj that accepts
either an address or a
file:line specification, and looks up the varobj in the
current frame,
restricted to the block surrounding that address.
We also had a problem showing global & static variables
with this
frame stuff. Suppose you want to make a varobj for a global
variable. Obviously you can't use the * form - you don't
want the
global to go out of scope ever... You could try to use the
form,
but then when you went to update it, if the frame you were
currently
in had a variable of the same name it would shadow the
global, and the
wrong value would get printed. You could cons up some
"function:varname" or "file:varname"
form, but that is a RPITA. So we
added another varobj type "NO_FRAME_NEEDED". When
we make one of the
"+" style varobj's we use the NO_FRAME_NEEDED if
we find the match in
the static or global block.
Turns out we didn't need to add an explicit character for
the
NO_FRAME_NEEDED, however. Instead, we added commands to
list the
statics & globals from a given function or file or
shlib. That's the
way Xcode usually gets it's hands on this sort of thing.
BTW, even though we use the " " form for our
"expressions" window in
general, one case where it would be useful to use the
"*" form instead
is if you had a deep recursive stack with gnarly big
structures (that
you have to turn out pretty far to inspect the good parts)
in the
recurring functions.
Then it would be useful to put the version of one of the
gnarly
variables from frame 35 in the expressions window, another
from frame
0, and then compare them at leisure. If you've ever tried
to do this
by flipping back & forth in the stack, you will see the
benefit of
this. To do this well you'd have to add some UI to the
expressions
window to identify the scope each variable was tacked to.
This
wouldn't be too hard, and could be handy in some cases.
Jim
On May 25, 2007, at 10:11 AM, Jim Blandy wrote:
>
> Vladimir Prus <ghost cs.msu.su> writes:
>>> Suppose I'm stopped where the stack is like
this:
>>>
>>> main -> foo (2) -> foo (1) -> foo
(0)
>>>
>>> Suppose the top frame is selected, and the user
adds a display for
>>> 'x'. Clearly, it should show '0'.
>>
>> You're using an ill-defined term "adds a
display".
>
> Well, sure. I'm asking people to tell me about all the
GUIs they work
> on, so I can't use specific language.
>
>>> 4) If the user lets control run to 'foo' again,
so the stack now
>>> looks
>>> like:
>>>
>>> main -> bar (10) -> foo (9)
>>>
>>> what should happen to the display of 'x'?
(I'd say it should show
>>> '9'.)
>>
>> I agree.
>>
>> I think that -variable-object should behave as
described above.
>
> Right; I wasn't aware of ' '-frame varobjs when I
originally wrote,
> since they're not documented.
>
>> Note also that it's possible to imagine GUI
commands that show a
>> value of some expression in particular
"scope", and became
>> forever grayed out when that scope dies. It raises
numerous
>> questions how to identify scopes. It should be
noted that KDevelop
>> does not have such UI command, and it was never
requested.
>
> Yeah, it doesn't seem too useful.
>
>>> The principle behind my guesses is that a
display should refer to a
>>> particular variable in the source code --- a
particular declaration
>>> --- and should show its value whenever that
declaration is in
>>> scope in
>>> the selected frame. This is less specific than
having the display
>>> refer to a particular frame's instance of that
variable, and more
>>> specific than having it refer to any variable
that happens to be in
>>> scope under that name. But it's what I'd
expect from a GUI.
>>
>> This seem to contradict your claim that in 'bar',
we should show '9'
>> for 'x' -- it's different 'x', after all.
>
> You misread --- I said we should show '9' in the first
call to foo
> from bar.
>
>> Assume user asked to show value of "x+y".
There are three
>> alternatives:
>>
>> 1. Show value of that expression in specific frame,
gray it out
>> otherwise.
>> 2. Show value of that expression in current frame,
provided "x" and
>> "y"
>> refer to the same language declaration.
>> 3. Show value of that expression in current frame.
>>
>> (3) is what implemented by -varobjs. You seem to
propose (2),
>> which will only differ from (2) by the fact that
sometimes (3) will
>> show
>> a value and (2) will have value greyed. Is this big
enough deal to
>> worry about?
>
> Yes, that is the distinction. If it's not important to
GUI
> implementors, then it's certainly not a big enough deal
to worry
> about.
>
>> As for (1), it's implemented by ordinary varobjs.
>
> Except for the frame collision behavior which I
demonstrated, yes.
|
|
| Re: Questions about MI variable objects |

|
2007-05-25 21:29:08 |
> So, if Emacs wants displays to grey out when the frame
disappears,
> does it ever expect those expressions to become ungrey
again? After
> all, that frame is gone forever. Under what
conditions should the
> display become ungrey?
If the frame_id matches again.
> > > 4) If the user lets control run to 'foo'
again, so the stack now looks
> > > like:
> > >
> > > main -> bar (10) -> foo (9)
> > >
> > > what should happen to the display of
'x'? (I'd say it should show
> > > '9'.)
> >
> > That's what Emacs currently does and what the
default GDB behaviour gives,
> > although Daniel J doesn't seem to think it's
useful.
>
> Actually, I don't believe you. Would you
humor me and try this
> out?
My mistake, I read too quickly. I was thinking it was going
straight back into
foo, having just come out. (I don't know why - ypu were
quite clear.)
> - Start with the program I posted.
> - Set a breakpoint on foo.
> - Run to the third hit (that is, foo (0))
> - Display 'x'.
> - finish three times, so that we're back in main. We
all agree the
> display should be 'greyed' out at this point.
> - continue to the next hit of foo.
>
> When I do this with what I assume are the
corresponding MI commands,
> the varobj I made for x in foo (0) is still out of
scope.
>
> If I continue again, I happen to get a frame whose
address matches the
> original foo (0) address, and the varobj comes back in
scope, but this
> is, again, a spurious frame ID match. It happens only
because the
> frames sizes on the stack happen to line up. The
compiler could
> generate different, correct, code and the varobj
behavior would stop
> working.
I have tried in the past to do something similar but could
never get them to
line up. (I tried to get two functions use the same amount
of stack as
one function.)
> So, at the moment, your displays based on '*'-frame
varobjs ungrey at
> times that appear reasonable in simple test programs,
but are actually
> dependent on flukes of your compiler's stack
management.
>
> Setting aside MI and GDB and varobjs, from your users'
point of view,
> when should that display come alive again?
When the function and stack trace matches again. I
generally use GDB in Emacs
just to debug GDB and Emacs (yeah, I know, it's all a bit
circular) and there
the the frame_id only seems match again under these
conditions
However I can't really speak for others, as, currently,
there aren't many
people using GDB in Emacs 22.
> > > If there's some general agreement on how
these ought to behave (not
> > > necessarily my guesses, just any agreement)
then maybe we could make
> > > MI varobjs match that behavior, so that
each GUI variable display
> > > could be backed by exactly one varobj, and
GDB's reports on changes to
> > > the varobj's state would correspond closely
to changes in the GUI's
> > > display. Varobjs exist to help GUIs, and
GDB shouldn't be making GUIs
> > > jump through hoops to get the behavior they
want.
> >
> > I'm not sure how you intend to change GDB's
behaviour but I think it should
> > provide options rather than define the policy.
>
> MI is a protocol; I don't want to break backwards
compatibility. But
> there's no point in retaining backwards compatibility
with a bug ---
> when that bug's behavior is unpredictable.
Well, you call it a fluke when it works, but I would call it
an (unlucky) fluke
when it fails. My view is unacceptable, of course, when
delivering to
customers.
> > I don't really follow. Can you give an real
example where frame IDs
> > collide?
>
> Well, since it depends on the stack management code
the compiler
> emits, it's compiler-specific. But on a Fedora Core 6
x86 machine:
Sure. Sorry, I should have followed through your first
example.
--
Nick http://www.inet.net.n
z/~nickrob
|
|
[1-6]
|
|