From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7021 invoked by alias); 22 May 2007 18:37:30 -0000 Received: (qmail 7010 invoked by uid 22791); 22 May 2007 18:37:28 -0000 X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.4) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 22 May 2007 18:37:23 +0000 Received: (qmail 29670 invoked from network); 22 May 2007 18:37:21 -0000 Received: from unknown (HELO localhost) (jimb@127.0.0.2) by mail.codesourcery.com with ESMTPA; 22 May 2007 18:37:21 -0000 To: Maxim Grigoriev Cc: gdb@sourceware.org, Marc Gauthier , Pete MacLiesh , Ross Morley Subject: Re: Understanding GDB frames References: <46521C04.7040405@hq.tensilica.com> From: Jim Blandy Date: Tue, 22 May 2007 18:37:00 -0000 In-Reply-To: <46521C04.7040405@hq.tensilica.com> (Maxim Grigoriev's message of "Mon, 21 May 2007 15:24:04 -0700") Message-ID: User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-IsSubscribed: yes Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org X-SW-Source: 2007-05/txt/msg00117.txt.bz2 Maxim Grigoriev writes: > QUESTION > ======== > > The program (frame.c) is > > #include > > 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 --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.