From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 29442 invoked by alias); 31 Jan 2012 22:04:45 -0000 Received: (qmail 29402 invoked by uid 22791); 31 Jan 2012 22:04:39 -0000 X-SWARE-Spam-Status: No, hits=-6.2 required=5.0 tests=AWL,BAYES_00,KAM_STOCKGEN,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,T_RP_MATCHES_RCVD 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; Tue, 31 Jan 2012 22:04:25 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q0VM4PpF031849 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 31 Jan 2012 17:04:25 -0500 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q0VM4OEp027484; Tue, 31 Jan 2012 17:04:25 -0500 Received: from barimba (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id q0VM4NUf015556; Tue, 31 Jan 2012 17:04:23 -0500 From: Tom Tromey To: gdb-patches@sourceware.org Subject: RFA: fix PR python/12027 Date: Tue, 31 Jan 2012 23:14:00 -0000 Message-ID: MIME-Version: 1.0 Content-Type: text/plain 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: 2012-01/txt/msg01022.txt.bz2 This fixes PR python/12027. The bug is that there is no way to get the value of a gdb.Symbol. This adds a new 'value' method to Symbol to make this easier. This method accepts an option frame argument. This patch also adds a new 'needs_frame' attribute so that it is easy to tell whether or not computing the symbol's value requires a frame. This needs a doc review. Built and regtested on x86-64 Fedora 15. Tom 2012-01-31 Tom Tromey PR python/12027: * python/python-internal.h (frame_object_type): Declare. * python/py-symbol.c (sympy_needs_frame): New function. (sympy_value): New function. (symbol_object_getset): Add "needs_frame". (symbol_object_methods): Add "value". * python/py-frame.c (frame_object_type): No longer static. 2012-01-31 Tom Tromey * gdb.texinfo (Symbols In Python): Document Symbol.needs_frame and Symbol.value. 2012-01-31 Tom Tromey * gdb.python/py-symbol.exp: Test Symbol.needs_frame and Symbol.value. * gdb.python/py-symbol.c (qq): Set default value. >From b64469667736ae9876cdb131514d634715dfbe59 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Tue, 31 Jan 2012 14:47:28 -0700 Subject: [PATCH 3/3] fix PR 12027 - no way to get a symbol value --- gdb/ChangeLog | 10 ++++ gdb/NEWS | 5 ++ gdb/doc/ChangeLog | 5 ++ gdb/doc/gdb.texinfo | 14 ++++++ gdb/python/py-frame.c | 4 +- gdb/python/py-symbol.c | 75 ++++++++++++++++++++++++++++++++ gdb/python/python-internal.h | 1 + gdb/testsuite/ChangeLog | 6 +++ gdb/testsuite/gdb.python/py-symbol.c | 2 +- gdb/testsuite/gdb.python/py-symbol.exp | 18 ++++++++ 10 files changed, 136 insertions(+), 4 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index bb9429f..46ef6d8 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -15,6 +15,11 @@ ** gdb.Symbol now has a 'line' attribute, holding the line number in the source at which the symbol was defined. + ** gdb.Symbol now has the new attribute 'needs_frame' and the new + method 'value'. The former indicates whether the symbol needs a + frame in order to compute its value, and the latter computes the + symbol's value. + * GDBserver now supports stdio connections. E.g. (gdb) target remote | ssh myhost gdbserver - hello diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 9fa4b4e..fafecb7 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -23994,6 +23994,11 @@ of a symbol. Each address class is a constant defined in the @code{gdb} module and described later in this chapter. @end defvar +@defvar Symbol.needs_frame +This is @code{True} if evaluating this symbol's value requires a frame +(@pxref{Frames In Python}) and @code{False} otherwise. Typically, +local variables will require a frame, but other symbols will not. + @defvar Symbol.is_argument @code{True} if the symbol is an argument of a function. @end defvar @@ -24021,6 +24026,15 @@ the symbol it refers to does not exist in @value{GDBN} any longer. All other @code{gdb.Symbol} methods will throw an exception if it is invalid at the time the method is called. @end defun + +@defun Symbol.value (@r{[}frame@r{]}) +Compute the value of the symbol, as a @code{gdb.Value}. For +functions, this computes the address of the function, cast to the +appropriate type. If the symbol requires a frame in order to compute +its value, then @var{frame} must be given. If @var{frame} is not +given, or if @var{frame} is invalid, then this method will throw an +exception. +@end defun @end table The available domain categories in @code{gdb.Symbol} are represented diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c index a8ce598..76fe06d 100644 --- a/gdb/python/py-frame.c +++ b/gdb/python/py-frame.c @@ -54,8 +54,6 @@ typedef struct { error (_("Frame is invalid.")); \ } while (0) -static PyTypeObject frame_object_type; - /* Returns the frame_info object corresponding to the given Python Frame object. If the frame doesn't exist anymore (the frame id doesn't correspond to any frame in the inferior), returns NULL. */ @@ -663,7 +661,7 @@ Return the value of the variable in this frame." }, {NULL} /* Sentinel */ }; -static PyTypeObject frame_object_type = { +PyTypeObject frame_object_type = { PyObject_HEAD_INIT (NULL) 0, /* ob_size */ "gdb.Frame", /* tp_name */ diff --git a/gdb/python/py-symbol.c b/gdb/python/py-symbol.c index d9dae47..9a29191 100644 --- a/gdb/python/py-symbol.c +++ b/gdb/python/py-symbol.c @@ -183,6 +183,29 @@ sympy_is_variable (PyObject *self, void *closure) || class == LOC_OPTIMIZED_OUT)); } +/* Implementation of gdb.Symbol.needs_frame -> Boolean. + Returns true iff the symbol needs a frame for evaluation. */ + +static PyObject * +sympy_needs_frame (PyObject *self, void *closure) +{ + struct symbol *symbol = NULL; + volatile struct gdb_exception except; + int result = 0; + + SYMPY_REQUIRE_VALID (self, symbol); + + TRY_CATCH (except, RETURN_MASK_ALL) + { + result = symbol_read_needs_frame (symbol); + } + GDB_PY_HANDLE_EXCEPTION (except); + + if (result) + Py_RETURN_TRUE; + Py_RETURN_FALSE; +} + /* Implementation of gdb.Symbol.line -> int. Returns the line number at which the symbol was defined. */ @@ -211,6 +234,53 @@ sympy_is_valid (PyObject *self, PyObject *args) Py_RETURN_TRUE; } +/* Implementation of gdb.Symbol.value (self[, frame]) -> gdb.Value. Returns + the value of the symbol, or an error in various circumstances. */ + +static PyObject * +sympy_value (PyObject *self, PyObject *args) +{ + struct symbol *symbol = NULL; + struct frame_info *frame_info = NULL; + PyObject *frame_obj = NULL; + struct value *value = NULL; + volatile struct gdb_exception except; + + if (!PyArg_ParseTuple (args, "|O", &frame_obj)) + return NULL; + + if (frame_obj != NULL && !PyObject_TypeCheck (frame_obj, &frame_object_type)) + { + PyErr_SetString (PyExc_TypeError, "argument is not a frame"); + return NULL; + } + + SYMPY_REQUIRE_VALID (self, symbol); + if (SYMBOL_CLASS (symbol) == LOC_TYPEDEF) + { + PyErr_SetString (PyExc_TypeError, "cannot get the value of a typedef"); + return NULL; + } + + TRY_CATCH (except, RETURN_MASK_ALL) + { + if (frame_obj != NULL) + { + frame_info = frame_object_to_frame_info (frame_obj); + if (frame_info == NULL) + error ("invalid frame"); + } + + if (symbol_read_needs_frame (symbol) && frame_info == NULL) + error ("symbol requires a frame to compute its value"); + + value = read_var_value (symbol, frame_info); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return value_to_value_object (value); +} + /* Given a symbol, and a symbol_object that has previously been allocated and initialized, populate the symbol_object with the struct symbol data. Also, register the symbol_object life-cycle @@ -474,6 +544,8 @@ to display demangled or mangled names.", NULL }, "True if the symbol is a function or method." }, { "is_variable", sympy_is_variable, NULL, "True if the symbol is a variable." }, + { "needs_frame", sympy_needs_frame, NULL, + "True if the symbol requires a frame for evaluation." }, { "line", sympy_line, NULL, "The source line number at which the symbol was defined." }, { NULL } /* Sentinel */ @@ -483,6 +555,9 @@ static PyMethodDef symbol_object_methods[] = { { "is_valid", sympy_is_valid, METH_NOARGS, "is_valid () -> Boolean.\n\ Return true if this symbol is valid, false if not." }, + { "value", sympy_value, METH_VARARGS, + "value ([frame]) -> gdb.Value\n\ +Return the value of the symbol." }, {NULL} /* Sentinel */ }; diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index 22e6b41..1d6247d 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -121,6 +121,7 @@ extern PyTypeObject event_object_type; extern PyTypeObject events_object_type; extern PyTypeObject stop_event_object_type; extern PyTypeObject breakpoint_object_type; +extern PyTypeObject frame_object_type; typedef struct breakpoint_object { diff --git a/gdb/testsuite/gdb.python/py-symbol.c b/gdb/testsuite/gdb.python/py-symbol.c index d29849b..4c1c26d 100644 --- a/gdb/testsuite/gdb.python/py-symbol.c +++ b/gdb/testsuite/gdb.python/py-symbol.c @@ -35,7 +35,7 @@ class SimpleClass }; #endif -int qq; /* line of qq */ +int qq = 72; /* line of qq */ int func (int arg) { diff --git a/gdb/testsuite/gdb.python/py-symbol.exp b/gdb/testsuite/gdb.python/py-symbol.exp index 36d7bfd..5eed6e9 100644 --- a/gdb/testsuite/gdb.python/py-symbol.exp +++ b/gdb/testsuite/gdb.python/py-symbol.exp @@ -45,10 +45,20 @@ gdb_test "python print gdb.lookup_global_symbol(\"junk\")" "None" "Test lookup_g gdb_test "python print gdb.lookup_symbol('main')\[0\].is_function" "True" \ "Lookup main using lookup_symbol" +gdb_test "python print gdb.lookup_symbol('main')\[0\].value()" "$hex .main." \ + "print value of main" + set qq_line [gdb_get_line_number "line of qq"] gdb_test "python print gdb.lookup_symbol('qq')\[0\].line" "$qq_line" \ "print line number of qq" +gdb_test "python print gdb.lookup_symbol('qq')\[0\].value()" "72" \ + "print value of qq" + +gdb_test "python print gdb.lookup_symbol('qq')\[0\].needs_frame" "False" \ + "print whether qq needs a frame" + + if ![runto_main] then { fail "Can't run to main" return 0 @@ -91,6 +101,14 @@ gdb_test "python print a\[0\].is_argument" "False" "Test a.is_argument" gdb_test "python print a\[0\].is_function" "False" "Test a.is_function" gdb_test "python print a\[0\].addr_class == gdb.SYMBOL_LOC_COMPUTED" "True" "Test a.addr_class" +gdb_test "python print a\[0\].value()" \ + "symbol requires a frame to compute its value.*"\ + "try to print value of a without a frame" +gdb_test "python print a\[0\].value(frame)" "0" \ + "print value of a" +gdb_test "python print a\[0\].needs_frame" "True" \ + "print whether a needs a frame" + # Test is_constant attribute gdb_py_test_silent_cmd "python t = gdb.lookup_symbol(\"one\")" "Get variable a" 0 gdb_test "python print t\[0\].is_variable" "False" "Test t.is_variable" -- 1.7.6.5