From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 93203 invoked by alias); 3 Mar 2015 08:46:35 -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 93192 invoked by uid 89); 3 Mar 2015 08:46:35 -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; Tue, 03 Mar 2015 08:46:33 +0000 Received: from sasl.smtp.pobox.com (unknown [127.0.0.1]) by pb-sasl1.pobox.com (Postfix) with ESMTP id 631DC3455A; Tue, 3 Mar 2015 03:46:31 -0500 (EST) Received: from pb-sasl1.int.icgroup.com (unknown [127.0.0.1]) by pb-sasl1.pobox.com (Postfix) with ESMTP id 5B1C634558; Tue, 3 Mar 2015 03:46:31 -0500 (EST) 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 5EDD334557; Tue, 3 Mar 2015 03:46:30 -0500 (EST) 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: Tue, 03 Mar 2015 08:46:00 -0000 In-Reply-To: (Alexander Smundak's message of "Mon, 2 Mar 2015 14:56:00 -0800") Message-ID: <87ioei31uj.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: C99F78FE-C181-11E4-B017-B058D0B8C469-02397024!pb-sasl1.pobox.com X-IsSubscribed: yes X-SW-Source: 2015-03/txt/msg00058.txt.bz2 Hi Alexander, Thanks for the reply! On Mon 02 Mar 2015 23:56, Alexander Smundak writes: > So here's the new proposal for the Python API, hopefully in > line with what you have in mind for Guile: > > If a sniffer is able to unwind a frame, it should return an instance of > gdb.sniffer.UnwindInfo class, which has the following methods: > * UnwindInfo(registers) > Constructor. `registers' is a tuple of (register_number, register_value) > 2-tuples for the registers that can be unwound. > * frame_id_build_wild(SP) > frame_id_build(SP, PC) > frame_id_build_special(SP, PC, SPECIAL) > Sets frame ID by calling the corresponding GDB function. It is an error > to return UnwindInfo object before one of these methods is called (a > sniffer should return None if it cannot unwind a frame) > * set_register(register_number, register_value) > Adds a 2-tuple to the list of unwound registers. Not sure this is needed. You'll need a link to the sniffer_info in order to be able to give good errors for set_register, to check that the register exists and that the value is of the correct type and size. For that reason, in my first draft of a Guile interface, the "ephemeral frame" is like your sniffer_info and unwind_info together. Perhaps this is a bad idea though. I would note as a meta-point that there are going to be some differences between a Python and a Scheme interface, just for linguistic reasons. Please consider my feedback as merely a friendly review and not an obligation in any way :) In particular, I'm not a GDB developer and don't have a finely tuned nose for the tao of GDB :) >> [W]hy not specify registers as strings, as elsewhere >> (e.g. gdb.Frame.read_register)? > My concern is that name lookups are expensive Are they? I wouldn't think so, no more than anything that happens in Python. > I am proposing a tradeoff: add > `gdb.Architecture.register_name_to_number' method. > On the Python side, register number values can then be initialized > during architecture-specific sniffer state initialization. If it were Guile I would leave off the numbers, but hey that's me :) I'll leave this one to Doug. >> The sniffer_info object is unfortunate -- it's a frame, but without >> frame methods. You can't get its architecture from python, for >> example, or get the next frame. More about that later. > I guess you know by now that it is not a frame. The interface > reflects that. Well. I mean, it's not a frame to Python, but its only state is a "struct frame_info" pointer, and its only method is also present on gdb.Frame, so it looks a lot like a frame to me :) >> In the read_register() function, I believe you can use >> get_frame_register_value instead of deprecated_frame_register_read. > You can't, get frame_register_value wiil assert because the frame > has no frame ID yet. The comment in the source says: /* Call `deprecated_frame_register_read' -- calling `value_of_register' would an assert in `get_frame_id' because our frame is incomplete. */ Whereas get_frame_register_value looks something like this: struct value * frame_unwind_register_value (struct frame_info *frame, int regnum) { /* Find the unwinder. */ if (frame->unwind == NULL) frame_unwind_find_by_frame (frame, &frame->prologue_cache); /* Ask this frame to unwind its register. */ return frame->unwind->prev_register (frame, &frame->prologue_cache, regnum); } struct value * get_frame_register_value (struct frame_info *frame, int regnum) { return frame_unwind_register_value (frame->next, regnum); } So it doesn't touch THIS_FRAME. Alexander, did you not run into nasty crashes while doing random Python things inside your unwind handler? For completeness, here's a draft of the unwinder I was working on, with a bunch of helpers elided: (define (unwind-v8-frame frame) (let* ((isolate (cached-current-isolate)) (prev-pc (ephemeral-frame-read-register frame "rip")) (code (and isolate (lookup-code-for-pc prev-pc isolate)))) (when code (let* ((fp (ephemeral-frame-read-register frame "rbp")) (type (if (code-optimized? code) (v8-constant "StackFrame::OPTIMIZED") (v8-constant "StackFrame::JAVA_SCRIPT"))) (pc-address (compute-standard-frame-pc-address fp)) (pc (value-dereference pc-address)) (start-pc (code-instruction-start code)) (sp (compute-frame-older-sp fp type)) (fp (compute-standard-frame-older-fp fp))) (set-ephemeral-frame-id! frame fp start-pc) (ephemeral-frame-write-register! frame "rsp" sp) (ephemeral-frame-write-register! frame "rbp" fp) (ephemeral-frame-write-register! frame "rip" pc))))) As you can see it's the set-ephemeral-frame-id! that marks the frame as unwound. A pretty weird interface, maybe I'd do better to separate them again. Andy