From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14487 invoked by alias); 26 Feb 2010 12:38:04 -0000 Received: (qmail 14459 invoked by uid 22791); 26 Feb 2010 12:38:01 -0000 X-SWARE-Spam-Status: No, hits=-6.1 required=5.0 tests=AWL,BAYES_00,KAM_STOCKGEN,RCVD_IN_DNSWL_HI,SPF_HELO_PASS X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 26 Feb 2010 12:37:56 +0000 Received: from int-mx03.intmail.prod.int.phx2.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.16]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o1QCbsI1013965 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 26 Feb 2010 07:37:54 -0500 Received: from localhost.localdomain (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx03.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o1QCboFt018581 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NO); Fri, 26 Feb 2010 07:37:53 -0500 Date: Fri, 26 Feb 2010 12:38:00 -0000 From: Phil Muldoon To: Tom Tromey Cc: gdb-patches@sourceware.org Subject: Re: [python][patch] Fix 11036 Message-ID: <20100226123749.GA16942@localhost.localdomain> References: <20100225142823.GA10175@localhost.localdomain> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.20 (2009-08-17) X-IsSubscribed: yes 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 X-SW-Source: 2010-02/txt/msg00648.txt.bz2 On Thu, Feb 25, 2010 at 11:33:49AM -0700, Tom Tromey wrote: > >>>>> "Phil" == Phil Muldoon writes: > Phil> + argument must be an instance of gdb.Block. Returns None if GDB > Phil> + can't find the specified variable. */ > > This last sentence in this comment seems to be wrong. > Sometimes the function returns None, sometimes it throws an exception. > I think the function should behave more predictably somehow. I took a look at the code that lies beneath the instance where this function could return None. It seems that read_var_value can (according to the comments heading that function) return NULL. I'm stumped when this can happen, as it deals with each LOC_* scenario, throwing the relevant errors when needed. We talked a little about this on irc last night, and even in the case of symbols where the value have been optimized away, read_var still returns non-null: (gdb) py f = gdb.selected_frame() (gdb) py print f.read_var("optimize_me") If you examine the runtime, the return here is a valid value, not a NULL. In any case, I think that if read_var returns NULL, then this is an error case. If anyone knows this to be different let me know and I can go back to returning None in this case. To reflect this, if the result of read_var is NULL, I raise an exception. What do you think? > Phil> + block = block_object_to_block (block_obj); > Phil> + if (block == NULL) > Phil> + return NULL; Ok, fixed. I have also updated the comments and the documentation to reflect the new decisions. Cheers, Phil -- diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index f6105b7..23aca55 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -20799,9 +20799,13 @@ Return the frame's symtab and line object. @xref{Symbol Tables In Python}. @end defmethod -@defmethod Frame read_var variable -Return the value of the given variable in this frame. @var{variable} must -be a string. +@defmethod Frame read_var variable @r{[}block@r{]} +Return the value of the given variable in this frame. If the optional +block argument is provided, search for the variable from that current +block; otherwise start at the frame's current block (which is +determined by the frame's current program counter). @var{variable} +must be a string or a @code{gdb.Symbol} object. @var{block} must be +a @code{gdb.Block} object. @end defmethod @defmethod Frame select diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c index 94211db..3b5320c 100644 --- a/gdb/python/py-frame.c +++ b/gdb/python/py-frame.c @@ -380,20 +380,22 @@ frapy_find_sal (PyObject *self, PyObject *args) return sal_obj; } -/* Implementation of gdb.Frame.read_var_value (self, variable) -> gdb.Value. - Returns the value of the given variable in this frame. The argument must be - a string. Returns None if GDB can't find the specified variable. */ - +/* Implementation of gdb.Frame.read_var_value (self, variable, + [block]) -> gdb.Value. If the optional block argument is provided + start the search from that block, otherwise search from the frame's + current block (determined by examining the resume address of the + frame). The variable argument must be a string or an instance of a + gdb.Symbol. The block argument must be an instance of gdb.Block. */ static PyObject * frapy_read_var (PyObject *self, PyObject *args) { struct frame_info *frame; - PyObject *sym_obj; + PyObject *sym_obj, *block_obj = NULL; struct symbol *var = NULL; /* gcc-4.3.2 false warning. */ struct value *val = NULL; volatile struct gdb_exception except; - if (!PyArg_ParseTuple (args, "O", &sym_obj)) + if (!PyArg_ParseTuple (args, "O|O", &sym_obj, &block_obj)) return NULL; if (PyObject_TypeCheck (sym_obj, &symbol_object_type)) @@ -410,11 +412,23 @@ frapy_read_var (PyObject *self, PyObject *args) return NULL; cleanup = make_cleanup (xfree, var_name); + if (block_obj) + { + block = block_object_to_block (block_obj); + if (!block) + { + PyErr_SetString (PyExc_RuntimeError, + _("Second argument must be block.")); + return NULL; + } + } + TRY_CATCH (except, RETURN_MASK_ALL) { FRAPY_REQUIRE_VALID ((frame_object *) self, frame); - block = block_for_pc (get_frame_address_in_block (frame)); + if (!block) + block = block_for_pc (get_frame_address_in_block (frame)); var = lookup_symbol (var_name, block, VAR_DOMAIN, NULL); } GDB_PY_HANDLE_EXCEPTION (except); @@ -445,10 +459,15 @@ frapy_read_var (PyObject *self, PyObject *args) } GDB_PY_HANDLE_EXCEPTION (except); - if (val) - return value_to_value_object (val); + if (!val) + { + PyErr_Format (PyExc_ValueError, + _("Variable cannot be found for symbol '%s'."), + SYMBOL_NATURAL_NAME (var)); + return NULL; + } - Py_RETURN_NONE; + return value_to_value_object (val); } /* Select this frame. */ diff --git a/gdb/testsuite/gdb.python/py-frame.c b/gdb/testsuite/gdb.python/py-frame.c index 22eb9f2..82db341 100644 --- a/gdb/testsuite/gdb.python/py-frame.c +++ b/gdb/testsuite/gdb.python/py-frame.c @@ -8,7 +8,23 @@ int f1 (int a, int b) return f2(a) + b; } +int block (void) +{ + int i = 99; + { + double i = 1.1; + double f = 2.2; + { + const char *i = "stuff"; + const char *f = "foo"; + const char *b = "bar"; + return 0; /* Block break here. */ + } + } +} + int main (int argc, char *argv[]) { + block (); return f1 (1, 2); } diff --git a/gdb/testsuite/gdb.python/py-frame.exp b/gdb/testsuite/gdb.python/py-frame.exp index 6989207..150e737 100644 --- a/gdb/testsuite/gdb.python/py-frame.exp +++ b/gdb/testsuite/gdb.python/py-frame.exp @@ -56,6 +56,30 @@ if ![runto_main] then { return 0 } +gdb_breakpoint [gdb_get_line_number "Block break here."] +gdb_continue_to_breakpoint "Block break here." +gdb_py_test_silent_cmd "python bf1 = gdb.selected_frame ()" "get frame" 0 + +# First test that read_var is unaffected by PR 11036 changes. +gdb_test "python print bf1.read_var(\"i\")" "\"stuff\"" "test i" +gdb_test "python print bf1.read_var(\"f\")" "\"foo\"" "test f" +gdb_test "python print bf1.read_var(\"b\")" "\"bar\"" "test b" + +# Test the read_var function in another block other than the current +# block (in this case, the super block). Test thar read_var is reading +# the correct variables of i and f but they are the correct value and type. +gdb_py_test_silent_cmd "python sb = bf1.block().superblock" "get superblock" 0 +gdb_test "python print bf1.read_var(\"i\", sb)" "1.1.*" "test i = 1.1" +gdb_test "python print bf1.read_var(\"i\", sb).type" "double" "test double i" +gdb_test "python print bf1.read_var(\"f\", sb)" "2.2.*" "test f = 2.2" +gdb_test "python print bf1.read_var(\"f\", sb).type" "double" "test double f" + +# And again test another outerblock, this time testing "i" is the +# correct value and type. +gdb_py_test_silent_cmd "python sb = sb.superblock" "get superblock" 0 +gdb_test "python print bf1.read_var(\"i\", sb)" "99" "test i = 99" +gdb_test "python print bf1.read_var(\"i\", sb).type" "int" "test int i" + gdb_breakpoint "f2" gdb_continue_to_breakpoint "breakpoint at f2" gdb_test "up" "" ""