From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 6338 invoked by alias); 9 Jun 2009 15:15:43 -0000 Received: (qmail 6325 invoked by uid 22791); 9 Jun 2009 15:15:41 -0000 X-SWARE-Spam-Status: No, hits=-1.4 required=5.0 tests=AWL,BAYES_00,MSGID_FROM_MTA_HEADER,SPF_SOFTFAIL X-Spam-Check-By: sourceware.org Received: from mtagate4.de.ibm.com (HELO mtagate4.de.ibm.com) (195.212.29.153) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 09 Jun 2009 15:15:35 +0000 Received: from d12nrmr1607.megacenter.de.ibm.com (d12nrmr1607.megacenter.de.ibm.com [9.149.167.49]) by mtagate4.de.ibm.com (8.14.3/8.13.8) with ESMTP id n59FFWwQ227458 for ; Tue, 9 Jun 2009 15:15:32 GMT Received: from d12av02.megacenter.de.ibm.com (d12av02.megacenter.de.ibm.com [9.149.165.228]) by d12nrmr1607.megacenter.de.ibm.com (8.13.8/8.13.8/NCO v9.2) with ESMTP id n59FFWIg1605700 for ; Tue, 9 Jun 2009 17:15:32 +0200 Received: from d12av02.megacenter.de.ibm.com (loopback [127.0.0.1]) by d12av02.megacenter.de.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id n59FFV5c027663 for ; Tue, 9 Jun 2009 17:15:31 +0200 Received: from tuxmaker.boeblingen.de.ibm.com (tuxmaker.boeblingen.de.ibm.com [9.152.85.9]) by d12av02.megacenter.de.ibm.com (8.12.11.20060308/8.12.11) with SMTP id n59FFU04027588 for ; Tue, 9 Jun 2009 17:15:30 +0200 Message-Id: <200906091515.n59FFU04027588@d12av02.megacenter.de.ibm.com> Received: by tuxmaker.boeblingen.de.ibm.com (sSMTP sendmail emulation); Tue, 09 Jun 2009 17:15:30 +0200 Subject: [02/15] Python interpreter callback functions To: gdb-patches@sourceware.org Date: Tue, 09 Jun 2009 15:15:00 -0000 From: "Ulrich Weigand" MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit 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: 2009-06/txt/msg00212.txt.bz2 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 . */ #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 @@ -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