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]

[02/15] Python interpreter callback functions


Hello,

Python support has re-introduced a number of reference to current_gdbarch
(and current_language) that are somewhat hard to eliminate as they happen
from within callback routines called by the Pyhton interpreter.

My solution to this problem is to use a set of global variables called
python_gdbarch and python_langague that are initialized whenever we are
about to call into the Python interpreter, and which are used from within
those callbacks.

We're using
- "current" architecture/language for top-level CLI calls
- expression architecture/language when evaluating an internal function
- varobj architecture/language when pretty-printing a varobj

If there's a more elegant way of passing this sort of environmental
information through the Python interpreter, I'd appreciate any hints
from the Python experts ;-)


ChangeLog:

	* python/python-internal.h (struct language_defn): Declare.
	(python_gdbarch, python_language): Likewise.
	(make_cleanup_python_env): Add prototype.

	* python/python.c: Include "arch-utils.h", "value.h" and "language.h".
	(python_gdbarch, python_language): New global variables.
	(make_cleanup_python_env, clear_python_env): New functions.
	(eval_python_from_control_command): Call make_cleanup_python_env to
	install current architecture and language.
	(python_command): Likewise.
	* python/python-command.c: Include "arch-utils.h" and "language.h".
	(cmdpy_function, cmdpy_completer): Call make_cleanup_python_env.
	* python/python-prettyprint.c (apply_val_pretty_printer): Likewise.
	* varobj.c (update_dynamic_varobj_children, install_default_visualizer,
	varobj_set_visualizer, value_get_print_value): Likewise.

	* value.h (internal_function_fn): Add GDBARCH and LANGUAGE argument.
	(call_internal_function): Likewise.
	* value.c (call_internal_function): Likewise.  Pass to handler.
	* eval.c (evaluate_subexp_standard): Update call.
	* python/python-function.c: Include "language.h".
	(fnpy_call): Add GDBARCH and LANGAUAGE arguments and call
	make_cleanup_python_env.

	* python/python-value.c (builtin_type_pyint, builtin_type_pyfloat,
	builtin_type_pylong, builtin_type_pybool, builtin_type_pychar,
	valpy_str): Use python_gdbarch and python_language instead of
	current_gdbarch and current_language.
	* python/python-type.c (typy_lookup_typename): Likewise.


Index: gdb-head/gdb/python/python.c
===================================================================
--- gdb-head.orig/gdb/python/python.c
+++ gdb-head/gdb/python/python.c
@@ -18,12 +18,15 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
+#include "arch-utils.h"
 #include "command.h"
 #include "ui-out.h"
 #include "cli/cli-script.h"
 #include "gdbcmd.h"
 #include "objfiles.h"
 #include "observer.h"
+#include "value.h"
+#include "language.h"
 
 #include <ctype.h>
 
@@ -58,6 +61,45 @@ PyObject *gdbpy_children_cst;
 PyObject *gdbpy_display_hint_cst;
 PyObject *gdbpy_doc_cst;
 
+
+/* Architecture and language to be used in callbacks from
+   the Python interpreter.  */
+struct gdbarch *python_gdbarch;
+const struct language_defn *python_language;
+
+/* Clear out global language and architecture when leaving the
+   Python interpreter.  */
+static void
+clear_python_env (void *p)
+{
+  python_gdbarch = NULL;
+  python_language = NULL;
+}
+
+/* Called before entering the Python interpreter to install the
+   current language and architecture to be used for Python values.  */
+struct cleanup *
+make_cleanup_python_env (struct gdbarch *gdbarch,
+                         const struct language_defn *language)
+{
+  /* Allow recursive calls, e.g. via valpy_str calling common_val_print
+     calling back into the Python pretty-printer, but only if gdbarch
+     and language match.  Do *not* install a cleanup for the recursive
+     case.  */
+  if (python_gdbarch || python_language)
+    {
+      gdb_assert (python_gdbarch == gdbarch);
+      gdb_assert (python_language == language);
+      return NULL;
+    }
+
+  python_gdbarch = gdbarch;
+  python_language = language;
+
+  return make_cleanup (clear_python_env, NULL);
+}
+
+
 /* Given a command_line, return a command string suitable for passing
    to Python.  Lines in the string are separated by newlines.  The
    return value is allocated using xmalloc and the caller is
@@ -104,6 +146,8 @@ eval_python_from_control_command (struct
   state = PyGILState_Ensure ();
   cleanup = make_cleanup_py_restore_gil (&state);
 
+  make_cleanup_python_env (get_current_arch (), current_language);
+
   script = compute_python_string (cmd->body_list[0]);
   ret = PyRun_SimpleString (script);
   xfree (script);
@@ -131,6 +175,8 @@ python_command (char *arg, int from_tty)
     ++arg;
   if (arg && *arg)
     {
+      make_cleanup_python_env (get_current_arch (), current_language);
+
       if (PyRun_SimpleString (arg))
 	{
 	  gdbpy_print_stack ();
Index: gdb-head/gdb/python/python-internal.h
===================================================================
--- gdb-head.orig/gdb/python/python-internal.h
+++ gdb-head/gdb/python/python-internal.h
@@ -62,6 +62,7 @@ typedef int Py_ssize_t;
 #endif
 
 struct value;
+struct language_defn;
 
 extern PyObject *gdb_module;
 extern PyTypeObject value_object_type;
@@ -91,6 +92,12 @@ void gdbpy_initialize_objfile (void);
 struct cleanup *make_cleanup_py_decref (PyObject *py);
 struct cleanup *make_cleanup_py_restore_gil (PyGILState_STATE *state);
 
+struct cleanup *make_cleanup_python_env (struct gdbarch *gdbarch,
+					 const struct language_defn *language);
+
+extern struct gdbarch *python_gdbarch;
+extern const struct language_defn *python_language;
+
 /* Use this after a TRY_EXCEPT to throw the appropriate Python
    exception.  */
 #define GDB_PY_HANDLE_EXCEPTION(Exception)				\
Index: gdb-head/gdb/python/python-value.c
===================================================================
--- gdb-head.orig/gdb/python/python-value.c
+++ gdb-head/gdb/python/python-value.c
@@ -44,19 +44,19 @@ struct value *values_in_python = NULL;
    GDB (which uses target arithmetic).  */
 
 /* Python's integer type corresponds to C's long type.  */
-#define builtin_type_pyint builtin_type (current_gdbarch)->builtin_long
+#define builtin_type_pyint builtin_type (python_gdbarch)->builtin_long
 
 /* Python's float type corresponds to C's double type.  */
-#define builtin_type_pyfloat builtin_type (current_gdbarch)->builtin_double
+#define builtin_type_pyfloat builtin_type (python_gdbarch)->builtin_double
 
 /* Python's long type corresponds to C's long long type.  */
-#define builtin_type_pylong builtin_type (current_gdbarch)->builtin_long_long
+#define builtin_type_pylong builtin_type (python_gdbarch)->builtin_long_long
 
 #define builtin_type_pybool \
-  language_bool_type (current_language, current_gdbarch)
+  language_bool_type (python_language, python_gdbarch)
 
 #define builtin_type_pychar \
-  language_string_char_type (current_language, current_gdbarch)
+  language_string_char_type (python_language, python_gdbarch)
 
 typedef struct {
   PyObject_HEAD
@@ -333,7 +333,7 @@ valpy_str (PyObject *self)
   TRY_CATCH (except, RETURN_MASK_ALL)
     {
       common_val_print (((value_object *) self)->value, stb, 0,
-			&opts, current_language);
+			&opts, python_language);
       s = ui_file_xstrdup (stb, &dummy);
     }
   GDB_PY_HANDLE_EXCEPTION (except);
Index: gdb-head/gdb/value.c
===================================================================
--- gdb-head.orig/gdb/value.c
+++ gdb-head/gdb/value.c
@@ -1243,7 +1243,9 @@ value_internal_function_name (struct val
 }
 
 struct value *
-call_internal_function (struct value *func, int argc, struct value **argv)
+call_internal_function (struct gdbarch *gdbarch,
+			const struct language_defn *language,
+			struct value *func, int argc, struct value **argv)
 {
   struct internal_function *ifn;
   int result;
@@ -1252,7 +1254,7 @@ call_internal_function (struct value *fu
   result = get_internalvar_function (VALUE_INTERNALVAR (func), &ifn);
   gdb_assert (result);
 
-  return (*ifn->handler) (ifn->cookie, argc, argv);
+  return (*ifn->handler) (gdbarch, language, ifn->cookie, argc, argv);
 }
 
 /* The 'function' command.  This does nothing -- it is just a
Index: gdb-head/gdb/python/python-cmd.c
===================================================================
--- gdb-head.orig/gdb/python/python-cmd.c
+++ gdb-head/gdb/python/python-cmd.c
@@ -19,6 +19,7 @@
 
 
 #include "defs.h"
+#include "arch-utils.h"
 #include "value.h"
 #include "exceptions.h"
 #include "python-internal.h"
@@ -26,6 +27,7 @@
 #include "gdbcmd.h"
 #include "cli/cli-decode.h"
 #include "completer.h"
+#include "language.h"
 
 /* Struct representing built-in completion types.  */
 struct cmdpy_completer
@@ -120,6 +122,8 @@ cmdpy_function (struct cmd_list_element 
   state = PyGILState_Ensure ();
   cleanup = make_cleanup_py_restore_gil (&state);
 
+  make_cleanup_python_env (get_current_arch (), current_language);
+
   if (! obj)
     error (_("Invalid invocation of Python command object."));
   if (! PyObject_HasAttr ((PyObject *) obj, invoke_cst))
@@ -187,6 +191,8 @@ cmdpy_completer (struct cmd_list_element
   state = PyGILState_Ensure ();
   cleanup = make_cleanup_py_restore_gil (&state);
 
+  make_cleanup_python_env (get_current_arch (), current_language);
+
   if (! obj)
     error (_("Invalid invocation of Python command object."));
   if (! PyObject_HasAttr ((PyObject *) obj, complete_cst))
Index: gdb-head/gdb/python/python-function.c
===================================================================
--- gdb-head.orig/gdb/python/python-function.c
+++ gdb-head/gdb/python/python-function.c
@@ -27,6 +27,7 @@
 #include "cli/cli-decode.h"
 #include "completer.h"
 #include "expression.h"
+#include "language.h"
 
 static PyTypeObject fnpy_object_type;
 
@@ -53,7 +54,8 @@ convert_values_to_python (int argc, stru
 /* Call a Python function object's invoke method.  */
 
 static struct value *
-fnpy_call (void *cookie, int argc, struct value **argv)
+fnpy_call (struct gdbarch *gdbarch, const struct language_defn *language,
+	   void *cookie, int argc, struct value **argv)
 {
   int i;
   struct value *value = NULL;
@@ -66,6 +68,8 @@ fnpy_call (void *cookie, int argc, struc
 
   args = convert_values_to_python (argc, argv);
 
+  make_cleanup_python_env (gdbarch, language);
+
   callable = PyObject_GetAttrString ((PyObject *) cookie, "invoke");
   if (! callable)
     {
Index: gdb-head/gdb/value.h
===================================================================
--- gdb-head.orig/gdb/value.h
+++ gdb-head/gdb/value.h
@@ -666,7 +666,9 @@ extern struct value * value_subscripted_
 
 /* User function handler.  */
 
-typedef struct value *(*internal_function_fn) (void *cookie,
+typedef struct value *(*internal_function_fn) (struct gdbarch *gdbarch,
+					       const struct language_defn *language,
+					       void *cookie,
 					       int argc,
 					       struct value **argv);
 
@@ -674,7 +676,9 @@ void add_internal_function (const char *
 			    internal_function_fn handler,
 			    void *cookie);
 
-struct value *call_internal_function (struct value *function,
+struct value *call_internal_function (struct gdbarch *gdbarch,
+				      const struct language_defn *language,
+				      struct value *function,
 				      int argc, struct value **argv);
 
 char *value_internal_function_name (struct value *);
Index: gdb-head/gdb/eval.c
===================================================================
--- gdb-head.orig/gdb/eval.c
+++ gdb-head/gdb/eval.c
@@ -1523,7 +1523,8 @@ evaluate_subexp_standard (struct type *e
 	    error (_("Expression of type other than \"Function returning ...\" used as function"));
 	}
       if (TYPE_CODE (value_type (argvec[0])) == TYPE_CODE_INTERNAL_FUNCTION)
-	return call_internal_function (argvec[0], nargs, argvec + 1);
+	return call_internal_function (exp->gdbarch, exp->language_defn,
+				       argvec[0], nargs, argvec + 1);
 
       return call_function_by_hand (argvec[0], nargs, argvec + 1);
       /* pai: FIXME save value from call_function_by_hand, then adjust pc by adjust_fn_pc if +ve  */
Index: gdb-head/gdb/python/python-type.c
===================================================================
--- gdb-head.orig/gdb/python/python-type.c
+++ gdb-head/gdb/python/python-type.c
@@ -374,7 +374,7 @@ typy_lookup_typename (char *type_name)
       else if (!strncmp (type_name, "enum ", 5))
 	type = lookup_enum (type_name + 5, NULL);
       else
-	type = lookup_typename (current_language, current_gdbarch,
+	type = lookup_typename (python_language, python_gdbarch,
 				type_name, NULL, 0);
     }
   if (except.reason < 0)
Index: gdb-head/gdb/python/python-prettyprint.c
===================================================================
--- gdb-head.orig/gdb/python/python-prettyprint.c
+++ gdb-head/gdb/python/python-prettyprint.c
@@ -477,6 +477,8 @@ apply_val_pretty_printer (struct type *t
   state = PyGILState_Ensure ();
   cleanups = make_cleanup_py_restore_gil (&state);
 
+  make_cleanup_python_env (current_gdbarch, language);
+
   /* Instantiate the printer.  */
   if (valaddr)
     valaddr += embedded_offset;
Index: gdb-head/gdb/varobj.c
===================================================================
--- gdb-head.orig/gdb/varobj.c
+++ gdb-head/gdb/varobj.c
@@ -846,6 +846,9 @@ update_dynamic_varobj_children (struct v
   state = PyGILState_Ensure ();
   back_to = make_cleanup_py_restore_gil (&state);
 
+  make_cleanup_python_env (var->root->exp->gdbarch,
+			   var->root->exp->language_defn);
+
   *cchanged = 0;
   if (!PyObject_HasAttr (printer, gdbpy_children_cst))
     {
@@ -1407,6 +1410,9 @@ install_default_visualizer (struct varob
   state = PyGILState_Ensure ();
   cleanup = make_cleanup_py_restore_gil (&state);
 
+  make_cleanup_python_env (var->root->exp->gdbarch,
+			   var->root->exp->language_defn);
+
   if (var->value)
     {
       pretty_printer = gdbpy_get_varobj_pretty_printer (var->value);
@@ -1442,6 +1448,9 @@ varobj_set_visualizer (struct varobj *va
   state = PyGILState_Ensure ();
   back_to = make_cleanup_py_restore_gil (&state);
 
+  make_cleanup_python_env (var->root->exp->gdbarch,
+			   var->root->exp->language_defn);
+
   mainmod = PyImport_AddModule ("__main__");
   globals = PyModule_GetDict (mainmod);
   Py_INCREF (globals);
@@ -2240,6 +2249,10 @@ value_get_print_value (struct value *val
 #if HAVE_PYTHON
   {
     PyGILState_STATE state = PyGILState_Ensure ();
+    struct cleanup *back_to = make_cleanup_py_restore_gil (&state);
+
+    make_cleanup_python_env (current_gdbarch, current_language);
+
     if (value_formatter && PyObject_HasAttr (value_formatter,
 					     gdbpy_to_string_cst))
       {
@@ -2259,13 +2272,13 @@ value_get_print_value (struct value *val
 						&replacement);
 	if (thevalue && !string_print)
 	  {
-	    PyGILState_Release (state);
+	    do_cleanups (back_to);
 	    return thevalue;
 	  }
 	if (replacement)
 	  value = replacement;
       }
-    PyGILState_Release (state);
+    do_cleanups (back_to);
   }
 #endif
 
-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


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