Re: Understanding GDB frames

Maxim Grigoriev
2007-05-22T19:17:27Z

> 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.

We've been using a function return address instead of
the PC of the function's entry, and it works just fine.

The good part of our approach is it allowed to expose some
problems with MI variable objects :-)

> All those frames ought to be different, but GDB will treat
> some of them as the same.

I think distinguishing frames can be improved by using the third
argument of frame_id, which is a "special address". Most of the
implementations don't use it.

-- Maxim

Jim Blandy wrote:
> 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 %d\n", frame_number++);
>>
>> a = b + 1;
>> b--;
>> if (b != 0)
>> {
>> printf("f11() will be called recursively\n");
>> 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.
>
>