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.
This commit is contained in:
Tom Tromey 2012-02-07 19:47:16 +00:00
parent 64e7d9dddc
commit f0823d2ce8
10 changed files with 137 additions and 5 deletions

View file

@ -1,3 +1,13 @@
2012-02-07 Tom Tromey <tromey@redhat.com>
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 <tromey@redhat.com> 2012-02-07 Tom Tromey <tromey@redhat.com>
PR python/13599: PR python/13599:

View file

@ -15,6 +15,11 @@
** gdb.Symbol now has a 'line' attribute, holding the line number in ** gdb.Symbol now has a 'line' attribute, holding the line number in
the source at which the symbol was defined. 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. * GDBserver now supports stdio connections.
E.g. (gdb) target remote | ssh myhost gdbserver - hello E.g. (gdb) target remote | ssh myhost gdbserver - hello

View file

@ -1,3 +1,8 @@
2012-02-07 Tom Tromey <tromey@redhat.com>
* gdb.texinfo (Symbols In Python): Document Symbol.needs_frame and
Symbol.value.
2012-02-07 Tom Tromey <tromey@redhat.com> 2012-02-07 Tom Tromey <tromey@redhat.com>
* gdb.texinfo (Symbols In Python): Document Symbol.line. * gdb.texinfo (Symbols In Python): Document Symbol.line.

View file

@ -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. @code{gdb} module and described later in this chapter.
@end defvar @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 @defvar Symbol.is_argument
@code{True} if the symbol is an argument of a function. @code{True} if the symbol is an argument of a function.
@end defvar @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 All other @code{gdb.Symbol} methods will throw an exception if it is
invalid at the time the method is called. invalid at the time the method is called.
@end defun @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 @end table
The available domain categories in @code{gdb.Symbol} are represented The available domain categories in @code{gdb.Symbol} are represented

View file

@ -54,8 +54,6 @@ typedef struct {
error (_("Frame is invalid.")); \ error (_("Frame is invalid.")); \
} while (0) } while (0)
static PyTypeObject frame_object_type;
/* Returns the frame_info object corresponding to the given Python Frame /* Returns the frame_info object corresponding to the given Python Frame
object. If the frame doesn't exist anymore (the frame id doesn't object. If the frame doesn't exist anymore (the frame id doesn't
correspond to any frame in the inferior), returns NULL. */ correspond to any frame in the inferior), returns NULL. */
@ -663,7 +661,7 @@ Return the value of the variable in this frame." },
{NULL} /* Sentinel */ {NULL} /* Sentinel */
}; };
static PyTypeObject frame_object_type = { PyTypeObject frame_object_type = {
PyObject_HEAD_INIT (NULL) PyObject_HEAD_INIT (NULL)
0, /* ob_size */ 0, /* ob_size */
"gdb.Frame", /* tp_name */ "gdb.Frame", /* tp_name */

View file

@ -183,6 +183,29 @@ sympy_is_variable (PyObject *self, void *closure)
|| class == LOC_OPTIMIZED_OUT)); || 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. /* Implementation of gdb.Symbol.line -> int.
Returns the line number at which the symbol was defined. */ Returns the line number at which the symbol was defined. */
@ -211,6 +234,53 @@ sympy_is_valid (PyObject *self, PyObject *args)
Py_RETURN_TRUE; 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 /* Given a symbol, and a symbol_object that has previously been
allocated and initialized, populate the symbol_object with the allocated and initialized, populate the symbol_object with the
struct symbol data. Also, register the symbol_object life-cycle 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." }, "True if the symbol is a function or method." },
{ "is_variable", sympy_is_variable, NULL, { "is_variable", sympy_is_variable, NULL,
"True if the symbol is a variable." }, "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, { "line", sympy_line, NULL,
"The source line number at which the symbol was defined." }, "The source line number at which the symbol was defined." },
{ NULL } /* Sentinel */ { NULL } /* Sentinel */
@ -482,6 +554,9 @@ static PyMethodDef symbol_object_methods[] = {
{ "is_valid", sympy_is_valid, METH_NOARGS, { "is_valid", sympy_is_valid, METH_NOARGS,
"is_valid () -> Boolean.\n\ "is_valid () -> Boolean.\n\
Return true if this symbol is valid, false if not." }, 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 */ {NULL} /* Sentinel */
}; };

View file

@ -121,6 +121,7 @@ extern PyTypeObject event_object_type;
extern PyTypeObject events_object_type; extern PyTypeObject events_object_type;
extern PyTypeObject stop_event_object_type; extern PyTypeObject stop_event_object_type;
extern PyTypeObject breakpoint_object_type; extern PyTypeObject breakpoint_object_type;
extern PyTypeObject frame_object_type;
typedef struct breakpoint_object typedef struct breakpoint_object
{ {

View file

@ -1,4 +1,10 @@
2012-01-31 Tom Tromey <tromey@redhat.com> 2012-02-07 Tom Tromey <tromey@redhat.com>
* 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 <tromey@redhat.com>
* gdb.python/py-symbol.c (qq): New global. * gdb.python/py-symbol.c (qq): New global.
* gdb.python/py-symbol.exp: Add test for frame-less * gdb.python/py-symbol.exp: Add test for frame-less

View file

@ -35,7 +35,7 @@ class SimpleClass
}; };
#endif #endif
int qq; /* line of qq */ int qq = 72; /* line of qq */
int func (int arg) int func (int arg)
{ {

View file

@ -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 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_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"] set qq_line [gdb_get_line_number "line of qq"]
gdb_test "python print gdb.lookup_symbol('qq')\[0\].line" "$qq_line" \ gdb_test "python print gdb.lookup_symbol('qq')\[0\].line" "$qq_line" \
"print line number of qq" "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 { if ![runto_main] then {
fail "Can't run to main" fail "Can't run to main"
return 0 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\].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\].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 # Test is_constant attribute
gdb_py_test_silent_cmd "python t = gdb.lookup_symbol(\"one\")" "Get variable a" 0 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" gdb_test "python print t\[0\].is_variable" "False" "Test t.is_variable"