From f0823d2ce8e4cb8b64176872a372d8147804fb10 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Tue, 7 Feb 2012 19:47:16 +0000 Subject: [PATCH] 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. gdb/doc * gdb.texinfo (Symbols In Python): Document Symbol.needs_frame and Symbol.value. gdb/testsuite * gdb.python/py-symbol.exp: Test Symbol.needs_frame and Symbol.value. * gdb.python/py-symbol.c (qq): Set default 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 | 8 +++- gdb/testsuite/gdb.python/py-symbol.c | 2 +- gdb/testsuite/gdb.python/py-symbol.exp | 18 ++++++++ 10 files changed, 137 insertions(+), 5 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index bc8b7d4..60c5833 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,15 @@ 2012-02-07 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-02-07 Tom Tromey + PR python/13599: * python/py-symbol.c (sympy_line): New function. (symbol_object_getset): Add "line". 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/ChangeLog b/gdb/doc/ChangeLog index 8dd113e..19b61be 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,5 +1,10 @@ 2012-02-07 Tom Tromey + * gdb.texinfo (Symbols In Python): Document Symbol.needs_frame and + Symbol.value. + +2012-02-07 Tom Tromey + * gdb.texinfo (Symbols In Python): Document Symbol.line. 2012-01-27 Thomas Schwinge diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 052820b..02beed7 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -23993,6 +23993,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 @@ -24020,6 +24025,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 12cedc3..12a54e8 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 d44014c..1c00b48 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 @@ -473,6 +543,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 */ @@ -482,6 +554,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/ChangeLog b/gdb/testsuite/ChangeLog index 39a952c..4fd340c 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,4 +1,10 @@ -2012-01-31 Tom Tromey +2012-02-07 Tom Tromey + + * gdb.python/py-symbol.exp: Test Symbol.needs_frame and + Symbol.value. + * gdb.python/py-symbol.c (qq): Set default value. + +2012-02-07 Tom Tromey * gdb.python/py-symbol.c (qq): New global. * gdb.python/py-symbol.exp: Add test for frame-less 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 154eb37..0f5eb3c 100644 --- a/gdb/testsuite/gdb.python/py-symbol.exp +++ b/gdb/testsuite/gdb.python/py-symbol.exp @@ -42,10 +42,20 @@ gdb_py_test_silent_cmd "python main_func = gdb.lookup_global_symbol(\"main\")" " gdb_test "python print main_func.is_function" "True" "Test main_func.is_function" gdb_test "python print gdb.lookup_global_symbol(\"junk\")" "None" "Test lookup_global_symbol(\"junk\")" +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 @@ -88,6 +98,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" -- 2.7.4