|
List Info
Thread: Understanding GDB frames
|
|
| Understanding GDB frames |

|
2007-05-21 17:24:04 |
I experience some difficulties in finding a precise
definition
of gdb frames.
Any help on choosing the right answer among the list
provided
by me at the end of this message will be highly
appreciated.
QUESTION
========
The program (frame.c) is
#include <stdio.h>
int frame_number = 1;
int f11(int b)
{
int a;
printf("f11() frame number %dn",
frame_number++);
a = b + 1;
b--;
if (b != 0)
{
printf("f11() will be called
recursivelyn");
f11(b);
}
return a; /* <-- BP set here. */
}
int f1(int a)
{
return f11(a);
}
int main()
{
int a = 1;
int i;
for (i = 0; i <2; i++)
a = f11(a);
a = f11(1);
a = f1(1);
return 0;
}
The gdb command file "CMD":
break frame.c:18
run
continue
continue
continue
continue
kill
quit
was used to run a gdb session like this :
gdb <executable> --command=CMD
Let's define that "frames A and B are the same"
if
frame_id_eq ( A->this_id, B->this_id ) == true
The breakpoit has been set at line 18 and hit 5 times.
Execution control has been subsequently taken by
gdb in five frames numbered 1, 2, 3, 4, and 5.
According to the definition of GDB frames,
which statement is correct ?
ANSWERS
=======
1) All frames 1, 2, 3, 4, and 5 are the same;
2) All frames 1, 2, 3, 4, and 5 are different from each
other;
3) Frames 1,2, and 4 are the same. Frames 3 and 5 are
different from 1, 2, 4 and from each other;
4) It's implementation-dependent. While doing architecture
ports,
people decide how to implement frame_id-related
functions
to compare frames;
5) Other ( explanation would be appreciated ).
-- Maxim
|
|
| Re: Understanding GDB frames |

|
2007-05-21 18:28:16 |
There is another interesting case where I think GDB might
have
an issue, and that is best illustrated using Maxim's
previous
test case with a modified version of f11(), say f12().
int f11(int b)
{
int a;
a = b + 1;
return a; /* <- BP set here. */
}
int f12(int b)
{
int a;
while (b < 3)
{
a = b + 1;
b = a; /* <- BP set here. */
}
return a;
}
int main()
{
int a = 1;
a = f11(a);
a = f11(a);
a = f12(1);
return a;
}
Best compile with -O0 to ensure the loop isn't optimized
out.
Compare the two iterations of the loop in f12() with the
two
calls to f11(). For the calls to f11(), each has a separate
instantiation of the frame and thus (strictly speaking) has
a
separate frame and a separate instance of var 'a'. In the
two
iterations of f12(), the frame is the same one set up at
the
beginning of the single call, and 'a' is the same variable.
In both cases, the PC and SP are the same.
How can GDB tell the difference? (using the return address
instead of the PC in identifying the frame is one way, but
then one only needs to go one level deeper to defeat it).
Does GDB need to tell the difference?
GDB confronts a similar issue with watchpoints on local
vars.
It uses a special scope breakpoint to detect the return of
the
function and thus detect the watched variable going out of
scope. That mechanism is not used for MI variables. Is that
because the extra overhead is tolerable if a watchpoint is
set but not otherwise?
Should scoping of MI vars be treated the same as watched
vars?
Ross
Maxim Grigoriev wrote:
> I experience some difficulties in finding a precise
definition
> of gdb frames.
>
> Any help on choosing the right answer among the list
provided
> by me at the end of this message will be highly
appreciated.
>
> QUESTION
> ========
>
> The program (frame.c) is
>
> #include <stdio.h>
>
> int frame_number = 1;
>
> int f11(int b)
> {
> int a;
>
> printf("f11() frame number %dn",
frame_number++);
>
> a = b + 1;
> b--;
> if (b != 0)
> {
> printf("f11() will be called
recursivelyn");
> f11(b);
> }
> return a; /* <-- BP set here. */
> }
>
> int f1(int a)
> {
> return f11(a);
> }
>
> int main()
> {
> int a = 1;
> int i;
>
> for (i = 0; i <2; i++)
> a = f11(a);
>
> a = f11(1);
> a = f1(1);
>
> return 0;
> }
>
> The gdb command file "CMD":
>
> break frame.c:18
> run
> continue
> continue
> continue
> continue
> kill
> quit
>
> was used to run a gdb session like this :
> gdb <executable> --command=CMD
>
> Let's define that "frames A and B are the
same" if
>
> frame_id_eq ( A->this_id, B->this_id ) ==
true
>
> The breakpoit has been set at line 18 and hit 5 times.
> Execution control has been subsequently taken by
> gdb in five frames numbered 1, 2, 3, 4, and 5.
>
> According to the definition of GDB frames,
> which statement is correct ?
>
> ANSWERS
> =======
>
> 1) All frames 1, 2, 3, 4, and 5 are the same;
> 2) All frames 1, 2, 3, 4, and 5 are different from each
other;
> 3) Frames 1,2, and 4 are the same. Frames 3 and 5 are
> different from 1, 2, 4 and from each other;
> 4) It's implementation-dependent. While doing
architecture ports,
> people decide how to implement frame_id-related
functions
> to compare frames;
> 5) Other ( explanation would be appreciated ).
>
> -- Maxim
>
>
>
>
>
>
>
>
>
>
|
|
| Re: Understanding GDB frames |
  United States |
2007-05-21 20:40:44 |
If my understanding of the frame code is correct, then the
only
thing that is really guaranteed is that the frame ID
remains
constant throughout the lifetime of its associated frame,
or
function call. The rest is implementation-dependent.
In practice, I think most targets implement the frame ID as
a tuple
that contains one stack address (usually the address on the
stack
of the function frame), and one code address (usually the
address
of the first instruction for that function). So two
consecutive
calls to the same function from the same caller would
usually
result in the same frame ID being computed for these two
calls.
But this is not guaranteed, for instance if the compiler
elected
to adjust the stack for whatever reason between the two
function
calls.
IA64 is slighly more complicated, because it also has to
take
into account the fact that it has a register stack. So the
frame
ID tuple also includes a non-zero "special addr".
Hope this helps. Others will correct me if I'm wrong.
--
Joel
|
|
| Re: Understanding GDB frames |

|
2007-05-21 21:05:35 |
> Compare the two iterations of the loop in f12() with
the two
> calls to f11(). For the calls to f11(), each has a
separate
> instantiation of the frame and thus (strictly
speaking) has a
> separate frame and a separate instance of var 'a'. In
the two
> iterations of f12(), the frame is the same one set up
at the
> beginning of the single call, and 'a' is the same
variable.
> In both cases, the PC and SP are the same.
>
> How can GDB tell the difference? (using the return
address
> instead of the PC in identifying the frame is one way,
but
> then one only needs to go one level deeper to defeat
it).
>
> Does GDB need to tell the difference?
>
> GDB confronts a similar issue with watchpoints on
local vars.
> It uses a special scope breakpoint to detect the
return of the
> function and thus detect the watched variable going
out of
> scope. That mechanism is not used for MI variables. Is
that
> because the extra overhead is tolerable if a
watchpoint is
> set but not otherwise?
Watchpoints are different to variable objects in that they
stop execution,
when their value changes, for example. Presumably when the
vlaue is being
monitored, so too can the scope. Variable objects are only
updated (if
requested) after execution has already stopped.
> Should scoping of MI vars be treated the same as
watched vars?
As watchpoints? I don't think so. A closer analogy to
variable objects
is the "display" command. There, GDB allows
expressions to come back into
scope.
--
Nick http://www.inet.net.n
z/~nickrob
|
|
| Re: Understanding GDB frames |
  United States |
2007-05-21 21:29:33 |
On Mon, May 21, 2007 at 03:24:04PM -0700, Maxim Grigoriev
wrote:
> Let's define that "frames A and B are the
same" if
>
> frame_id_eq ( A->this_id, B->this_id ) ==
true
>
> The breakpoit has been set at line 18 and hit 5 times.
> Execution control has been subsequently taken by
> gdb in five frames numbered 1, 2, 3, 4, and 5.
>
> According to the definition of GDB frames,
> which statement is correct ?
>
> ANSWERS
> =======
>
> 1) All frames 1, 2, 3, 4, and 5 are the same;
> 2) All frames 1, 2, 3, 4, and 5 are different from each
other;
> 3) Frames 1,2, and 4 are the same. Frames 3 and 5 are
> different from 1, 2, 4 and from each other;
> 4) It's implementation-dependent. While doing
architecture ports,
> people decide how to implement frame_id-related
functions
> to compare frames;
> 5) Other ( explanation would be appreciated ).
The correct answer, in my opinion, is that all of these
frames are
different. It is likely that when you compare their frame
IDs, all of
those representing a call of f11 from main will have the
same frame
ID - you can't always compare two arbitrary frame IDs if you
don't
know where they came from, and it's impossible to get this
100%
correct without slowing down the execution of the program,
so some of
them may be indistinguishable.
The frame ID is supposed to indicate which one of a set of
currently
running frames you're looking at. Maybe if we have varobjs
for a
specified frame ID, we should insert a scope breakpoint at
the exit of
that frame to mark those varobjs as invalid.
--
Daniel Jacobowitz
CodeSourcery
|
|
| Re: Understanding GDB frames |
  United States |
2007-05-21 21:31:25 |
On Tue, May 22, 2007 at 02:05:35PM +1200, Nick Roberts
wrote:
> As watchpoints? I don't think so. A closer analogy
to variable objects
> is the "display" command. There, GDB allows
expressions to come back into
> scope.
I don't think that allowing varobjs to come back into scope
this way
is really useful.
There's a different sort of scope that does make sense - a
varobj
might come in and out of lexical scope while its frame is
live, due to
optimization. But once the frame has gone we should
recreate the
varobjs, or else we should associate them with the function
instead of
the frame.
--
Daniel Jacobowitz
CodeSourcery
|
|
| Re: Understanding GDB frames |

|
2007-05-21 21:49:41 |
> > As watchpoints? I don't think so. A closer
analogy to variable objects
> > is the "display" command. There, GDB
allows expressions to come back into
> > scope.
>
> I don't think that allowing varobjs to come back into
scope this way
> is really useful.
I can't say how useful it is generally because Emacs 22 is
still stuck in CVS.
>From personal use, however, I've sometimes found
watchpoints deleting
themselves to be a nuisance. Sometimes I've got around by
specifying an adress
rather than a variable name.
> ...But once the frame has gone we
should recreate the
> varobjs, or else we should associate them with the
function instead of
> the frame.
Would this be straightforward to implement? Isn't there
anything in their
nature that makes this easier to do for watchpoints?
--
Nick http://www.inet.net.n
z/~nickrob
|
|
| Re: Understanding GDB frames |

|
2007-05-22 03:40:20 |
Daniel Jacobowitz wrote:
>On Tue, May 22, 2007 at 02:05:35PM +1200, Nick Roberts
wrote:
>
>
>>As watchpoints? I don't think so. A closer
analogy to variable objects
>>is the "display" command. There, GDB
allows expressions to come back into
>>scope.
>>
>>
>
>I don't think that allowing varobjs to come back into
scope this way
>is really useful.
>
>
I agree, since there's no way of knowing it's really the
same variable.
Using a C language definition of scope (and most languages
are similar)
a variable with the same name in a different scope is a
different variable.
>There's a different sort of scope that does make sense -
a varobj
>might come in and out of lexical scope while its frame
is live, due to
>optimization. But once the frame has gone we should
recreate the
>varobjs, or else we should associate them with the
function instead of
>the frame.
>
>
Associating them with the function has problems with
recursion. It seems to
me the ideal is to recreate vars that have gone out of scope
(they really
are new vars). Use of a scope breakpoint can better detect
that than the
current methods. However, are there implementation or
performance issues?
Ross
|
|
| Re: Understanding GDB frames |
  United States |
2007-05-22 05:57:49 |
On Tue, May 22, 2007 at 02:49:41PM +1200, Nick Roberts
wrote:
> > ...But once the frame has gone we
should recreate the
> > varobjs, or else we should associate them with
the function instead of
> > the frame.
>
> Would this be straightforward to implement? Isn't
there anything in their
> nature that makes this easier to do for watchpoints?
Nope. We could do it in basically the same way for varobjs
that we do
for watchpoints, if we decide it's useful.
--
Daniel Jacobowitz
CodeSourcery
|
|
| Re: Understanding GDB frames |
  United States |
2007-05-22 13:37:20 |
Maxim Grigoriev <maxim tensilica.com> writes:
> QUESTION
> ========
>
> The program (frame.c) is
>
> #include <stdio.h>
>
> int frame_number = 1;
>
> int f11(int b)
> {
> int a;
>
> printf("f11() frame number %dn",
frame_number++);
>
> a = b + 1;
> b--;
> if (b != 0)
> {
> printf("f11() will be called
recursivelyn");
> f11(b);
> }
> return a; /* <-- BP set here. */
> }
>
> int f1(int a)
> {
> return f11(a);
> }
>
> int main()
> {
> int a = 1;
> int i;
>
> for (i = 0; i <2; i++)
> a = f11(a);
>
> a = f11(1);
> a = f1(1);
>
> return 0;
> }
>
> The gdb command file "CMD":
>
> break frame.c:18
> run
> continue
> continue
> continue
> continue
> kill
> quit
>
> was used to run a gdb session like this :
> gdb <executable> --command=CMD
>
> Let's define that "frames A and B are the
same" if
>
> frame_id_eq ( A->this_id, B->this_id ) ==
true
>
> The breakpoit has been set at line 18 and hit 5 times.
> Execution control has been subsequently taken by
> gdb in five frames numbered 1, 2, 3, 4, and 5.
>
> According to the definition of GDB frames,
> which statement is correct ?
>
> ANSWERS
> =======
>
> 1) All frames 1, 2, 3, 4, and 5 are the same;
> 2) All frames 1, 2, 3, 4, and 5 are different from each
other;
> 3) Frames 1,2, and 4 are the same. Frames 3 and 5 are
> different from 1, 2, 4 and from each other;
> 4) It's implementation-dependent. While doing
architecture ports,
> people decide how to implement frame_id-related
functions
> to compare frames;
> 5) Other ( explanation would be appreciated ).
All those frames ought to be different, but GDB will treat
some of
them as the same.
Ideally, a frame is allocated each time a function is
entered, and
destroyed when a function returns, or when we longjmp out of
it, or
throw an exception out of it, or when the thread exits or
is
cancelled. So every one of those frames is distinct. This
is the
programmer's view of frames.
The first source of difficulty is optimization. The
compiler may
choose to inline a function call, and thus not allocate a
distinct
frame for it. Or, the compiler may choose to implement the
final call
in a function as a jump, effectively freeing the caller's
frame before
allocating its callee's frame. So optimization can affect
which
frames actually exist in memory. GDB could 'fabricate'
frames for
inlined functions, but for tail calls there's no easy
solution --- the
state which would describe the caller's frame is just gone.
The second source of difficulty is that GDB doesn't get any
notification when a frame is popped. (It could arrange to
get this
notification, but as Daniel says, that would slow things
down.) Thus,
if a function returns, and then is called again with exactly
the same
incoming stack pointer --- which is quite possible if it's
the same
frame underneath making both calls --- then it's impossible
for GDB to
look in on the first call, and then look in on the second
call, and
know that the two frames are distinct. The PC may be the
same; the SP
may be the same; the values of the arguments might be the
same. If
the calls are in a loop, the PC in the caller might well be
the same.
So GDB's frame ID's are a best-effort, but still faulty,
approximation
to what we really want. If two ID's are *unequal*, then you
can trust
that result, as far as I know. But if they're *equal*, you
can't
trust that.
Joel is right when he says:
> If my understanding of the frame code is correct, then
the only
> thing that is really guaranteed is that the frame ID
remains
> constant throughout the lifetime of its associated
frame, or
> function call. The rest is implementation-dependent.
It's worth pointing out that the 'PC' in a frame ID isn't
the current
PC within the function. It's always the PC of the
function's entry
point, so that stepping within a function doesn't cause the
frame ID
to change. Usually it's a PC value returned by
'frame_func_unwind',
which takes care of calling get_pc_function_start for you.
|
|
|
|