This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFA: fix PR python/12027


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  <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-01-31  Tom Tromey  <tromey@redhat.com>

	* gdb.texinfo (Symbols In Python): Document Symbol.needs_frame and
	Symbol.value.

2012-01-31  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.

>From b64469667736ae9876cdb131514d634715dfbe59 Mon Sep 17 00:00:00 2001
From: Tom Tromey <tromey@redhat.com>
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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]