From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 63477 invoked by alias); 9 Mar 2015 09:42:38 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 63468 invoked by uid 89); 9 Mar 2015 09:42:38 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.3 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_LOW,SPF_NEUTRAL autolearn=ham version=3.3.2 X-HELO: sasl.smtp.pobox.com Received: from pb-sasl1.int.icgroup.com (HELO sasl.smtp.pobox.com) (208.72.237.25) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 09 Mar 2015 09:42:36 +0000 Received: from sasl.smtp.pobox.com (unknown [127.0.0.1]) by pb-sasl1.pobox.com (Postfix) with ESMTP id 5C52D337DC; Mon, 9 Mar 2015 05:42:34 -0400 (EDT) Received: from pb-sasl1.int.icgroup.com (unknown [127.0.0.1]) by pb-sasl1.pobox.com (Postfix) with ESMTP id 5288E337DA; Mon, 9 Mar 2015 05:42:34 -0400 (EDT) Received: from rusty (unknown [88.160.190.192]) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by pb-sasl1.pobox.com (Postfix) with ESMTPSA id 94D0D337D8; Mon, 9 Mar 2015 05:42:33 -0400 (EDT) From: Andy Wingo To: Alexander Smundak Cc: Phil Muldoon , Doug Evans , gdb-patches Subject: Re: [RFC] [PATCH] Provide the ability to write the frame unwinder in Python References: <21714.40641.510825.30998@ruffy2.mtv.corp.google.com> <54E71694.1080304@redhat.com> Date: Mon, 09 Mar 2015 09:42:00 -0000 In-Reply-To: (Alexander Smundak's message of "Mon, 2 Mar 2015 14:56:00 -0800") Message-ID: <8761aatsl5.fsf@igalia.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.4 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Pobox-Relay-ID: 9CB78CB4-C640-11E4-8903-B058D0B8C469-02397024!pb-sasl1.pobox.com X-IsSubscribed: yes X-SW-Source: 2015-03/txt/msg00209.txt.bz2 Greets Alexander, One thing I found in your docs: > +@subheading Returning Previous Frame > + > +If sniffer's @code{__call__} method recognizes the frame, it should > +return a (@var{registers}, @var{frame_id_register_numbers}) tuple. > + > +@var{registers} describe the registers that can be unwound (i.e., the > +registers from the previous frame that have been saved in the current > +frame described by @var{sniffer_info}). It is a tuple where each > +element is a (@var{regnum}, @var{regdata}) 2-tuple. @var{regnum} is > +a register number, and @var{regdata} is register contents (a > +@code{gdb.Value} object). > + > +@var{frame_id_register_numbers} is a tuple specifying the registers > +used to construct frame ID of the returned frame. It is a (@var{sp}), > +(@var{sp}, @var{pc}) or (@var{sp}, @var{pc}, @var{special}) tuple, > +where @var{sp}, @var{pc}, @var{special} are register numbers. The > +referenced registers should be present in @var{registers} tuple. The > +frame ID is constructed by calling > +@code{frame_id_build_wild}(@var{value}(@var{sp})), > +@code{frame_id_build}(@var{value}(@var{sp}), @var{value}(@var{pc})), > +or @code{frame_id_build}(@var{value}(@var{sp}), @var{value}(@var{pc}), > +@var{value}(@var{special})) respectively. The frame_id that the unwinder computes is for THIS, not for PREVIOUS, so the interface is incorrect if it works as documented. Here is a section of the docs that I wrote for the Guile side. Before getting into the API, we should discuss how unwinders work in @value{GDBN}. As an example, consider a stack in which we have already computed frame 0 and we want to compute frame 1. We say that frame 0 is the ``inner'' frame, and frame 1 will be the ``outer'' frame. Unwinding starts with a model of the state of all registers in an inner, already unwound frame. In our case, we start with frame 0. @value{GDBN} then constructs a ephemeral frame object for the outer frame that is being built (frame 1) and links it to the inner frame (frame 0). @value{GDBN} then goes through its list of registered unwinders, searching for one that knows how to unwind the frame. When it finds one, @value{GDBN} will ask the unwinder to compute a frame identifier for the outer frame. Once the unwinder has done so, the frame is marked as ``valid'' and can be accessed using the normal frame API. A frame identifier (frame ID) consists of code and data pointers associated with a frame which will remain valid as long as the frame is still alive. Usually a frame ID is a pair of the code and stack pointers as they were when control entered the function associated with the frame, though as described below there are other ways to build a frame ID@. However as you can see, computing the frame ID requires some input from the unwinder to determine the start code address (PC) and the frame pointer (FP), especially on platforms that don't dedicate a register to the FP. (Given this description, you might wonder how the frame ID for the innermost frame (frame 0) is unwound, given that unwinding requires an inner frame. The answer is that internally, @value{GDBN} always has a ``sentinel'' frame that is inner to the innermost frame, and which has a pre-computed unwinder that just returns the registers as they are, without unwinding.) The Guile frame unwinder API loosely follows this protocol as described above. Guile will build a special ``ephemeral frame object'' corresponding the frame being unwound (in our example, frame 1). It allows the user to read registers from that ephemeral frame, which in reality are unwound from the already-existing frame 0. If the unwinder decides that it can handle the frame in question, it then sets the frame ID on the ephemeral frame. It also records the values of any registers saved in the frame, for use when unwinding its outer frame (frame 2). Regards, Andy