From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7907 invoked by alias); 26 Jan 2006 23:16:25 -0000 Received: (qmail 7897 invoked by uid 22791); 26 Jan 2006 23:16:23 -0000 X-Spam-Check-By: sourceware.org Received: from zproxy.gmail.com (HELO zproxy.gmail.com) (64.233.162.207) by sourceware.org (qpsmtpd/0.31) with ESMTP; Thu, 26 Jan 2006 23:16:21 +0000 Received: by zproxy.gmail.com with SMTP id x3so537161nzd for ; Thu, 26 Jan 2006 15:16:19 -0800 (PST) Received: by 10.36.251.8 with SMTP id y8mr1970651nzh; Thu, 26 Jan 2006 15:16:19 -0800 (PST) Received: by 10.37.2.5 with HTTP; Thu, 26 Jan 2006 15:16:19 -0800 (PST) Message-ID: <8f2776cb0601261516l51b150c3u8720b2816f7b624a@mail.gmail.com> Date: Thu, 26 Jan 2006 23:16:00 -0000 From: Jim Blandy To: NZG Subject: Re: frame theory, was pointer madness Cc: gdb-patches@sourceware.org, Daniel Jacobowitz In-Reply-To: <200601261354.12256.ngustavson@emacinc.com> MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Content-Disposition: inline References: <200601231438.26040.ngustavson@emacinc.com> <200601261017.41108.ngustavson@emacinc.com> <20060126164315.GA7821@nevyn.them.org> <200601261354.12256.ngustavson@emacinc.com> X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2006-01/txt/msg00436.txt.bz2 I've read the conversation with Daniel, but I'm going to pick at your use of terminology even more carefully, because I think that's actually a central source of confusion. As you've worked out, "the next frame" in GDB-speak means "the next younger frame". The "next frame" of some frame F is the frame for the function F called. There is no standard terminology for this that I know of, which is one source of the confusion. It's worth pointing out that 1) I got the terminology backwards the first time I typed this paragraph, and 2) Daniel got it backwards too when he said: >The innermost frame is always #0; it is the first frame "unwound" >from the sentinel frame. Then the next frame is unwound from frame 0. He should have said "the PREVIOUS frame is unwound from frame 0". The frame chain in GDB is a doubly-linked list. Every frame points to the next and previous frame. When you write things like this: > prev->frame->next that's not meaningful, because it isn't clear whether you're talking about the chain as defined by the "next" pointers, or by the "prev" pointers. Don't talk about what points to what; use the terms "next" and "previous". (And check what you type. :) ) > level description > -1 sentinal frame(virtual) > 0 youngest frame (the deepest function call and current fra= me) > 1 older > 2 even older > 3 oldest > > And the list should look like this > > prev->frame->next > > NULL->3->2->1->0->-1->-1->-1........ > > I think, and I have yet to successfully verify this, that the highest lev= el > frame should have an id of zero, or at least should. Don't confuse "level" with "id". The level is generally what the user uses to identify frames when using the "frame" command; it's what follows the # mark in "where" output. The frame ID, on the other hand, is a pair (or on the IA-64, a triplet) of addresses that is meant to identify a frame throughout its lifetime. They're usually a code address and a stack address. Every time the inferior runs, even for a single-step, GDB throws away all its frame structures, and reconstructs them when the inferior stops next. It constructs its own frame_info structures starting with the *youngest* frame, at the top of the stack, and works its way towards the bottom of the stack. GDB constructs frame_info structures lazily; it doesn't bother to figure them out until you actually refer to them (via "up" or "where"). So a NULL "prev" link in a frame_info structure does not mean that the stack has ended; it simply means that GDB hasn't produced the next frame yet. What *does* indicate that the stack has ended is if frame_unwind_id returns the null_frame_id. Note that, since 'struct frame_id' is a structure, it doesn't make sense to talk about a "frame id of zero". It's not a number. It's very good that GDB reconstructs the frame chain from scratch every time the inferior stops. This avoids bugs caused by out-of-date information. But it does mean that 'struct frame' objects are useless for referring to a particular frame while the program runs. For example, when we 'next' over a function call, we single-step into the call, and then set a breakpoint at the return address and let the program continue until we hit it. However, if there's recursion going on, we might hit that breakpoint when we return to some recursive invocation of the calling function --- but we're not through with the call the user asked us to 'next' over. So in addition to setting the breakpoint at the return address, we need to remember which *frame* we're looking for a return to. Struct frame objects don't work here; we throw them away while the inferior runs. A frame ID is supposed to be a robust, lightweight way to refer to a particular frame. It's usually the address of the base of the frame (often, the value the SP had when we entered the function), and the address of the function itself. When we produce frame_info structures, we record a frame ID for each one. Then, commands like "next" compare frame ID's to see whether they've found the frame they need. These comparisons can be fooled, of course. If you record a frame's ID, and then the frame gets popped but the caller calls the same function again, you're liable to get a new frame with the same ID as the old frame. It's very difficult to avoid this, and GDB doesn't bother. So frame levels (user interface), frame id's (long-term frame identification), and frame_info structures (detailed but transient records) are all distinct things to keep track of. > Normal gdb appears to work by caching the frame of the highest level to a= NULL > prev value, I'm not sure what this means. GDB starts with the youngest (current) frame, and then works towards the older frames, producing caller from callee, until (if it's lucky) it reaches the oldest frame on the stack. > When frame 0 is the highest and lowest real > level it will "unwind" frame zero by accessing -1. which should in turn > actually read the registers from remote device. Then ->black magic - bla= ck > magic -> gdb realizes there is no higher level frame and caches a NULL th= ere. You'll see GDB calling the "frame_unwind_register" functions all the time, not just the first time it constructs the frame_info object. A NULL "prev" pointer in a frame_info structure simply indicates that GDB hasn't (yet) produced any older frames. This could be because there are no older frames, or it could simply be that GDB hasn't bothered to find them yet. There isn't any master document defining all this, but I'll see if I can pirate some of what's been written into this thread for gdbint.texinfo.