* [RFC][patch 5/9] permit GDB commands implemented in Python
2008-04-29 15:59 [RFC][patch 0/9] Python support in GDB Thiago Jung Bauermann
` (3 preceding siblings ...)
2008-04-29 15:59 ` [RFC][patch 3/9] export hooks mechanism " Thiago Jung Bauermann
@ 2008-04-29 15:59 ` Thiago Jung Bauermann
2008-04-29 16:08 ` [RFC][patch 7/9] export block and symbol mechanism to Python Thiago Jung Bauermann
` (5 subsequent siblings)
10 siblings, 0 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-04-29 15:59 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: python-commands.diff --]
[-- Type: text/plain, Size: 15002 bytes --]
2008-04-29 Tom Tromey <tromey@redhat.com>
* Makefile.in (SUBDIR_PYTHON_OBS): Add python-cmd.o.
(SUBDIR_PYTHON_SRCS): Add python/cmd.c.
(python-cmd.o): New target.
* cli/cli-cmds.c (edit_command): Delete log10 code.
* cli/cli-decode.c (delete_cmd): Rewrote. Handle 'destroyer'
field.
(add_cmd): Initialize 'destroyer'.
* cli/cli-decode.h (struct cmd_list_element): Added 'destroyer'
field.
* python/cmd.c: New file.
* python/python-internal.h (gdbpy_initialize_commands): Declare.
* python/python.c (demand_python): Call gdbpy_initialize_commands.
Index: tromey.git/gdb/Makefile.in
===================================================================
--- tromey.git.orig/gdb/Makefile.in 2008-04-29 11:05:15.000000000 -0300
+++ tromey.git/gdb/Makefile.in 2008-04-29 11:05:20.000000000 -0300
@@ -263,11 +263,13 @@ SUBDIR_TUI_CFLAGS= \
SUBDIR_PYTHON_OBS = \
python.o \
python-breakpoint.o \
+ python-cmd.o \
python-hooks.o \
python-value.o
SUBDIR_PYTHON_SRCS = \
python/python.c \
python/breakpoint.c \
+ python/cmd.c \
python/hooks.c \
python/value.c
SUBDIR_PYTHON_DEPS =
@@ -3422,6 +3424,11 @@ python-breakpoint.o: $(srcdir)/python/br
$(breakpoint_h) $(gdbcmd_h)
$(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
$(srcdir)/python/breakpoint.c -o python-breakpoint.o
+python-cmd.o: $(srcdir)/python/cmd.c $(defs_h) $(python_h) $(value_h) \
+ $(exceptions_h) $(python_internal_h) $(charset_h) \
+ $(gdbcmd_h) $(cli_decode_h)
+ $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
+ $(srcdir)/python/cmd.c -o python-cmd.o
python-hooks.o: $(srcdir)/python/hooks.c $(defs_h) $(cli_decode_h) \
$(charset_h) $(gdb_events_h) $(python_h) $(python_internal_h)
$(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
Index: tromey.git/gdb/cli/cli-cmds.c
===================================================================
--- tromey.git.orig/gdb/cli/cli-cmds.c 2008-04-29 10:57:39.000000000 -0300
+++ tromey.git/gdb/cli/cli-cmds.c 2008-04-29 11:05:20.000000000 -0300
@@ -615,8 +615,7 @@ edit_command (char *arg, int from_tty)
struct symtab_and_line sal;
struct symbol *sym;
char *arg1;
- int cmdlen, log10;
- unsigned m;
+ int cmdlen;
char *editor;
char *p, *fn;
@@ -692,10 +691,6 @@ edit_command (char *arg, int from_tty)
if ((editor = (char *) getenv ("EDITOR")) == NULL)
editor = "/bin/ex";
- /* Approximate base-10 log of line to 1 unit for digit count */
- for(log10=32, m=0x80000000; !(sal.line & m) && log10>0; log10--, m=m>>1);
- log10 = 1 + (int)((log10 + (0 == ((m-1) & sal.line)))/3.32192809);
-
/* If we don't already know the full absolute file name of the
source file, find it now. */
if (!sal.symtab->fullname)
Index: tromey.git/gdb/cli/cli-decode.c
===================================================================
--- tromey.git.orig/gdb/cli/cli-decode.c 2008-04-29 10:57:39.000000000 -0300
+++ tromey.git/gdb/cli/cli-decode.c 2008-04-29 11:05:20.000000000 -0300
@@ -190,6 +190,7 @@ add_cmd (char *name, enum command_class
c->allow_unknown = 0;
c->abbrev_flag = 0;
set_cmd_completer (c, make_symbol_completion_list);
+ c->destroyer = NULL;
c->type = not_set_cmd;
c->var = NULL;
c->var_type = var_boolean;
@@ -614,37 +615,32 @@ add_setshow_zinteger_cmd (char *name, en
void
delete_cmd (char *name, struct cmd_list_element **list)
{
- struct cmd_list_element *c;
- struct cmd_list_element *p;
+ struct cmd_list_element *iter;
+ struct cmd_list_element **previous_chain_ptr;
+
+ previous_chain_ptr = list;
- while (*list && strcmp ((*list)->name, name) == 0)
+ for (iter = *previous_chain_ptr; iter; iter = *previous_chain_ptr)
{
- if ((*list)->hookee_pre)
- (*list)->hookee_pre->hook_pre = 0; /* Hook slips out of its mouth */
- if ((*list)->hookee_post)
- (*list)->hookee_post->hook_post = 0; /* Hook slips out of its bottom */
- p = (*list)->next;
- xfree (* list);
- *list = p;
- }
+ if (strcmp (iter->name, name) == 0)
+ {
+ if (iter->destroyer)
+ iter->destroyer (iter, iter->context);
+ if (iter->hookee_pre)
+ iter->hookee_pre->hook_pre = 0;
+ if (iter->hookee_post)
+ iter->hookee_post->hook_post = 0;
+
+ /* Update the link. Note that we don't change
+ previous_chain_ptr; next time through the loop this must
+ stay the same. */
+ *previous_chain_ptr = iter->next;
- if (*list)
- for (c = *list; c->next;)
- {
- if (strcmp (c->next->name, name) == 0)
- {
- if (c->next->hookee_pre)
- c->next->hookee_pre->hook_pre = 0; /* hooked cmd gets away. */
- if (c->next->hookee_post)
- c->next->hookee_post->hook_post = 0; /* remove post hook */
- /* :( no fishing metaphore */
- p = c->next->next;
- xfree (c->next);
- c->next = p;
- }
- else
- c = c->next;
- }
+ xfree (iter);
+ }
+ else
+ previous_chain_ptr = &iter->next;
+ }
}
\f
/* Shorthands to the commands above. */
Index: tromey.git/gdb/cli/cli-decode.h
===================================================================
--- tromey.git.orig/gdb/cli/cli-decode.h 2008-04-29 10:57:39.000000000 -0300
+++ tromey.git/gdb/cli/cli-decode.h 2008-04-29 11:05:20.000000000 -0300
@@ -168,6 +168,11 @@ struct cmd_list_element
"oobar"; if WORD is "baz/foo", return "baz/foobar". */
char **(*completer) (char *text, char *word);
+ /* Destruction routine for this command. If non-NULL, this is
+ called when this command instance is destroyed. This may be
+ used to finalize the CONTEXT field, if needed. */
+ void (*destroyer) (struct cmd_list_element *self, void *context);
+
/* Type of "set" or "show" command (or SET_NOT_SET if not "set"
or "show"). */
cmd_types type;
Index: tromey.git/gdb/python/cmd.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ tromey.git/gdb/python/cmd.c 2008-04-29 11:05:40.000000000 -0300
@@ -0,0 +1,255 @@
+/* gdb commands implemented in Python
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+
+#include "defs.h"
+#include "value.h"
+#include "exceptions.h"
+#include "python-internal.h"
+#include "charset.h"
+#include "gdbcmd.h"
+#include "cli/cli-decode.h"
+
+/* A gdb command. For the time being only ordinary commands (not
+ set/show commands) are allowed. */
+struct cmdpy_object
+{
+ PyObject_HEAD
+
+ /* The corresponding gdb command object, or NULL if the command is
+ no longer installed. */
+ /* It isn't clear if we will ever care about this. */
+ struct cmd_list_element *command;
+};
+
+typedef struct cmdpy_object cmdpy_object;
+
+static PyObject *cmdpy_dont_repeat (PyObject *self, PyObject *args);
+
+static PyMethodDef cmdpy_object_methods[] =
+{
+ { "dont_repeat", cmdpy_dont_repeat, METH_NOARGS,
+ "Prevent command repetition when user enters empty line." },
+
+ { 0 }
+};
+
+static PyTypeObject cmdpy_object_type =
+{
+ PyObject_HEAD_INIT (NULL)
+ 0, /*ob_size*/
+ "gdb.Command", /*tp_name*/
+ sizeof (cmdpy_object), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ "GDB command object", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ cmdpy_object_methods /* tp_methods */
+};
+
+\f
+
+static PyObject *
+cmdpy_dont_repeat (PyObject *self, PyObject *args)
+{
+ dont_repeat ();
+ Py_RETURN_NONE;
+}
+
+
+\f
+
+/* Called if the gdb cmd_list_element is destroyed. */
+static void
+cmdpy_destroyer (struct cmd_list_element *self, void *context)
+{
+ /* Release our hold on the command object. */
+ cmdpy_object *cmd = (cmdpy_object *) context;
+ cmd->command = NULL;
+ Py_DECREF (cmd);
+
+ /* We allocated the name and doc string. */
+ xfree (self->name);
+ xfree (self->doc);
+}
+
+/* Called by gdb to invoke the command. */
+static void
+cmdpy_function (struct cmd_list_element *command, char *args, int from_tty)
+{
+ cmdpy_object *obj = (cmdpy_object *) get_cmd_context (command);
+ PyObject *method, *argobj, *ttyobj, *result;
+
+ if (! obj)
+ error ("Invalid invocation of Python command object");
+ if (! PyObject_HasAttrString ((PyObject *) obj, "invoke"))
+ error ("Python command object missing 'invoke' method");
+
+ method = PyString_FromString ("invoke");
+ if (! args)
+ {
+ argobj = Py_None;
+ Py_INCREF (argobj);
+ }
+ else
+ {
+ argobj = PyString_FromString (args);
+ if (! argobj)
+ error ("Couldn't convert arguments to Python string");
+ }
+ ttyobj = from_tty ? Py_True : Py_False;
+ Py_INCREF (ttyobj);
+ result = PyObject_CallMethodObjArgs ((PyObject *) obj, method, argobj,
+ ttyobj, NULL);
+ Py_DECREF (method);
+ Py_DECREF (argobj);
+ Py_DECREF (ttyobj);
+ if (! result)
+ {
+ /* FIXME: pretty lame. */
+ PyErr_Print ();
+ error ("Error occurred in Python command");
+ }
+ Py_DECREF (result);
+}
+
+/* Object initializer; sets up gdb-side structures for command.
+
+ Use: __init__(NAME, CMDCLASS).
+
+ NAME is the name of the command; spaces in the name mean to look up
+ initial segments as prefixes.
+
+ CMDCLASS is the kind of command. It should be one of the COMMAND_*
+ constants defined in the gdb module.
+
+ The documentation for the command is taken from the doc string for
+ the python class.
+
+*/
+static int
+cmdpy_init (PyObject *self, PyObject *args, PyObject *kwds)
+{
+ cmdpy_object *obj = (cmdpy_object *) self;
+ char *name;
+ int cmdtype;
+ volatile struct gdb_exception except;
+
+ if (obj->command)
+ {
+ /* Note: this is apparently not documented in Python. We return
+ 0 for success, -1 for failure. */
+ PyErr_Format (PyExc_RuntimeError, "Command object already initialized");
+ return -1;
+ }
+
+ if (! PyArg_ParseTuple (args, "si", &name, &cmdtype))
+ return -1;
+
+ if (cmdtype != no_class && cmdtype != class_run
+ && cmdtype != class_vars && cmdtype != class_stack
+ && cmdtype != class_files && cmdtype != class_support
+ && cmdtype != class_info && cmdtype != class_breakpoint
+ && cmdtype != class_trace && cmdtype != class_obscure
+ && cmdtype != class_maintenance)
+ {
+ PyErr_Format (PyExc_RuntimeError, "invalid command class argument");
+ return -1;
+ }
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ /* FIXME: decoding NAME if it has spaces. Also, how to add new
+ prefix commands? */
+ struct cmd_list_element *cmd = add_cmd (xstrdup (name),
+ (enum command_class) cmdtype,
+ NULL,
+ xstrdup ("FIXME: docstring"),
+ &cmdlist /* FIXME */);
+ /* There appears to be no API to set this. */
+ cmd->func = cmdpy_function;
+ /* FIXME: route completion requests through user object. */
+
+ obj->command = cmd;
+ Py_INCREF (self);
+ set_cmd_context (cmd, self);
+ }
+ if (except.reason < 0)
+ {
+ PyErr_Format (except.reason == RETURN_QUIT
+ ? PyExc_KeyboardInterrupt : PyExc_RuntimeError,
+ "%s", except.message);
+ return -1;
+ }
+ return 0;
+}
+
+\f
+
+void
+gdbpy_initialize_commands (void)
+{
+ cmdpy_object_type.tp_new = PyType_GenericNew;
+ cmdpy_object_type.tp_init = cmdpy_init;
+ if (PyType_Ready (&cmdpy_object_type) < 0)
+ return;
+
+ /* Note: alias and user seem to be special; pseudo appears to be
+ unused, and there is no reason to expose tui or xdb, I think. */
+ if (PyModule_AddIntConstant (gdb_module, "COMMAND_NONE", no_class) < 0
+ || PyModule_AddIntConstant (gdb_module, "COMMAND_RUN", class_run) < 0
+ || PyModule_AddIntConstant (gdb_module, "COMMAND_VARS", class_vars) < 0
+ || PyModule_AddIntConstant (gdb_module, "COMMAND_STACK", class_stack) < 0
+ || PyModule_AddIntConstant (gdb_module, "COMMAND_FILES", class_files) < 0
+ || PyModule_AddIntConstant (gdb_module, "COMMAND_SUPPORT",
+ class_support) < 0
+ || PyModule_AddIntConstant (gdb_module, "COMMAND_INFO", class_info) < 0
+ || PyModule_AddIntConstant (gdb_module, "COMMAND_BREAKPOINT",
+ class_breakpoint) < 0
+ || PyModule_AddIntConstant (gdb_module, "COMMAND_TRACE", class_trace) < 0
+ || PyModule_AddIntConstant (gdb_module, "COMMAND_OBSCURE",
+ class_obscure) < 0
+ || PyModule_AddIntConstant (gdb_module, "COMMAND_MAINTENANCE",
+ class_maintenance) < 0)
+ return;
+
+ Py_INCREF (&cmdpy_object_type);
+ PyModule_AddObject (gdb_module, "Command",
+ (PyObject *) &cmdpy_object_type);
+}
Index: tromey.git/gdb/python/python-internal.h
===================================================================
--- tromey.git.orig/gdb/python/python-internal.h 2008-04-29 11:05:15.000000000 -0300
+++ tromey.git/gdb/python/python-internal.h 2008-04-29 11:05:20.000000000 -0300
@@ -44,6 +44,7 @@ PyObject *gdbpy_get_hook_function (const
void gdbpy_initialize_values (void);
void gdbpy_initialize_hooks (void);
void gdbpy_initialize_breakpoints (void);
+void gdbpy_initialize_commands (void);
/* Use this after a TRY_EXCEPT to throw the appropriate Python
exception. FIXME: throw different errors depending on
Index: tromey.git/gdb/python/python.c
===================================================================
--- tromey.git.orig/gdb/python/python.c 2008-04-29 11:05:15.000000000 -0300
+++ tromey.git/gdb/python/python.c 2008-04-29 11:05:20.000000000 -0300
@@ -70,6 +70,7 @@ demand_python ()
gdbpy_initialize_hooks ();
gdbpy_initialize_values ();
gdbpy_initialize_breakpoints ();
+ gdbpy_initialize_commands ();
PyRun_SimpleString ("import gdb");
--
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* [RFC][patch 3/9] export hooks mechanism to Python
2008-04-29 15:59 [RFC][patch 0/9] Python support in GDB Thiago Jung Bauermann
` (2 preceding siblings ...)
2008-04-29 15:59 ` [RFC][patch 9/9] export threads " Thiago Jung Bauermann
@ 2008-04-29 15:59 ` Thiago Jung Bauermann
2008-04-29 21:29 ` Tom Tromey
2008-05-29 7:55 ` Daniel Jacobowitz
2008-04-29 15:59 ` [RFC][patch 5/9] permit GDB commands implemented in Python Thiago Jung Bauermann
` (6 subsequent siblings)
10 siblings, 2 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-04-29 15:59 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: python-hooks.diff --]
[-- Type: text/plain, Size: 7443 bytes --]
2008-04-29 Tom Tromey <tromey@redhat.com>
* Makefile.in (SUBDIR_PYTHON_OBS): Add python-hooks.o.
(SUBDIR_PYTHON_SRCS): Add python/hooks.c.
(python-hooks.o): New target.
* interps.c (interp_set): Don't call clear_interpreter_hooks.
[Temporary hack].
* python/hooks.c: New file.
* python/python-internal.h (variable_to_python,
gdbpy_get_hook_function, gdbpy_initialize_hooks): Declare.
* python/python.c (demand_python): Call gdbpy_initialize_hooks.
Index: tromey.git/gdb/Makefile.in
===================================================================
--- tromey.git.orig/gdb/Makefile.in 2008-04-29 11:04:11.000000000 -0300
+++ tromey.git/gdb/Makefile.in 2008-04-29 11:05:09.000000000 -0300
@@ -262,9 +262,11 @@ SUBDIR_TUI_CFLAGS= \
#
SUBDIR_PYTHON_OBS = \
python.o \
+ python-hooks.o \
python-value.o
SUBDIR_PYTHON_SRCS = \
python/python.c \
+ python/hooks.c \
python/value.c
SUBDIR_PYTHON_DEPS =
SUBDIR_PYTHON_LDFLAGS=
@@ -3413,6 +3415,10 @@ python.o: $(srcdir)/python/python.c $(de
$(command_h) $(libiberty_h) $(cli_decode_h) $(charset_h) $(top_h) \
$(exceptions_h) $(python_internal_h) $(version_h)
$(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) $(srcdir)/python/python.c
+python-hooks.o: $(srcdir)/python/hooks.c $(defs_h) $(cli_decode_h) \
+ $(charset_h) $(gdb_events_h) $(python_h) $(python_internal_h)
+ $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
+ $(srcdir)/python/hooks.c -o python-hooks.o
python-value.o: $(srcdir)/python/value.c $(defs_h) $(exceptions_h) \
$(python_internal_h) $(value_h)
$(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
Index: tromey.git/gdb/interps.c
===================================================================
--- tromey.git.orig/gdb/interps.c 2008-04-29 10:57:39.000000000 -0300
+++ tromey.git/gdb/interps.c 2008-04-29 11:05:09.000000000 -0300
@@ -191,7 +191,11 @@ interp_set (struct interp *interp, int t
}
/* Clear out any installed interpreter hooks/event handlers. */
- clear_interpreter_hooks ();
+ /* FIXME - we don't want python to be a normal interpreter, but we
+ do want to be able to hook in everywhere. Not sure what to do
+ about this -- maybe allow events to be delivered to multiple
+ handlers. */
+/* clear_interpreter_hooks (); */
if (interp->procs->resume_proc != NULL
&& (!interp->procs->resume_proc (interp->data)))
Index: tromey.git/gdb/python/hooks.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ tromey.git/gdb/python/hooks.c 2008-04-29 11:05:09.000000000 -0300
@@ -0,0 +1,120 @@
+/* Notifications from gdb to Python
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "cli/cli-decode.h"
+#include "charset.h"
+#include "gdb-events.h"
+#include "python.h"
+#include "python-internal.h"
+
+static struct gdb_events handlers;
+
+PyObject *
+gdbpy_get_hook_function (const char *name)
+{
+ PyObject *hooks;
+
+ if (! PyObject_HasAttrString (gdb_module, "hooks"))
+ return NULL;
+ hooks = PyObject_GetAttrString (gdb_module, "hooks");
+ if (! hooks)
+ return NULL;
+ /* The cast is because the Python function doesn't declare const argument.
+ This is a problem in Python version 2.4, but not in 2.5. */
+ if (! PyObject_HasAttrString (hooks, (char *) name))
+ return NULL;
+ /* The cast is because the Python function doesn't declare const argument.
+ This is a problem in Python version 2.4, but not in 2.5. */
+ return PyObject_GetAttrString (hooks, (char *) name);
+}
+
+static void
+gdbpy_set_hook (struct cmd_list_element *cmd)
+{
+ char *name;
+ PyObject *nameobj, *valobj, *func;
+
+ func = gdbpy_get_hook_function ("post_set");
+ if (! func)
+ return;
+
+ valobj = variable_to_python (cmd);
+ if (! valobj)
+ return;
+
+ name = concat (cmd->prefixname ? cmd->prefixname : "", " ", cmd->name, NULL);
+ nameobj = PyString_Decode (name, strlen (name), host_charset (),
+ NULL /* FIXME */);
+ xfree (name);
+
+ PyObject_CallFunctionObjArgs (func, nameobj, valobj, NULL);
+ if (PyErr_Occurred ())
+ PyErr_Print ();
+}
+
+static void
+gdbpy_attach (void)
+{
+ PyObject *func;
+ func = gdbpy_get_hook_function ("post_attach");
+ if (func)
+ {
+ PyObject_CallFunctionObjArgs (func, NULL);
+ if (PyErr_Occurred ())
+ PyErr_Print ();
+ }
+}
+
+static void
+gdbpy_detach (void)
+{
+ PyObject *func;
+ func = gdbpy_get_hook_function ("post_detach");
+ if (func)
+ {
+ PyObject_CallFunctionObjArgs (func, NULL);
+ if (PyErr_Occurred ())
+ PyErr_Print ();
+ }
+}
+
+static void
+gdbpy_architecture_changed (void)
+{
+ PyObject *func;
+ func = gdbpy_get_hook_function ("post_architecture_change");
+ if (func)
+ {
+ PyObject_CallFunctionObjArgs (func, NULL);
+ if (PyErr_Occurred ())
+ PyErr_Print ();
+ }
+}
+
+void
+gdbpy_initialize_hooks (void)
+{
+ handlers.architecture_changed = gdbpy_architecture_changed;
+ deprecated_set_gdb_event_hooks (&handlers);
+
+ deprecated_set_hook = gdbpy_set_hook;
+ deprecated_attach_hook = gdbpy_attach;
+ deprecated_detach_hook = gdbpy_detach;
+}
Index: tromey.git/gdb/python/python-internal.h
===================================================================
--- tromey.git.orig/gdb/python/python-internal.h 2008-04-29 11:04:11.000000000 -0300
+++ tromey.git/gdb/python/python-internal.h 2008-04-29 11:05:09.000000000 -0300
@@ -32,12 +32,16 @@ extern PyTypeObject value_object_type;
PyObject *gdbpy_make_value_from_int (PyObject *self, PyObject *args);
PyObject *gdbpy_get_value_from_history (PyObject *self, PyObject *args);
+PyObject *variable_to_python (struct cmd_list_element *);
PyObject *value_to_value_object (struct value *v);
PyObject *gdb_owned_value_to_value_object (struct value *v);
struct value *value_object_to_value (PyObject *self);
+PyObject *gdbpy_get_hook_function (const char *);
+
void gdbpy_initialize_values (void);
+void gdbpy_initialize_hooks (void);
/* Use this after a TRY_EXCEPT to throw the appropriate Python
exception. FIXME: throw different errors depending on
Index: tromey.git/gdb/python/python.c
===================================================================
--- tromey.git.orig/gdb/python/python.c 2008-04-29 11:04:11.000000000 -0300
+++ tromey.git/gdb/python/python.c 2008-04-29 11:05:09.000000000 -0300
@@ -64,6 +64,7 @@ demand_python ()
PyModule_AddStringConstant (gdb_module, "HOST_CONFIG", host_name);
PyModule_AddStringConstant (gdb_module, "TARGET_CONFIG", target_name);
+ gdbpy_initialize_hooks ();
gdbpy_initialize_values ();
PyRun_SimpleString ("import gdb");
--
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* [RFC][patch 8/9] export symtab mechanism to Python
2008-04-29 15:59 [RFC][patch 0/9] Python support in GDB Thiago Jung Bauermann
@ 2008-04-29 15:59 ` Thiago Jung Bauermann
2008-04-29 15:59 ` [RFC][patch 6/9] export frames " Thiago Jung Bauermann
` (9 subsequent siblings)
10 siblings, 0 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-04-29 15:59 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: python-symtab.diff --]
[-- Type: text/plain, Size: 22369 bytes --]
2008-04-29 Thiago Jung Bauermann <bauerman@br.ibm.com>
* Makefile.in (SUBDIR_PYTHON_OBS): Add python-symtab.o.
(SUBDIR_PYTHON_SRCS): Add python/symtab.c.
(python-symtab.o): New target.
* python/frame.c (frame_object_methods): Add find_sal and
read_var_value Python methods.
(frapy_find_sal, frapy_read_var_value): New functions.
* python/python-internal.h (gdbpy_lookup_symbol,
symtab_and_line_to_sal_object, symtab_to_symtab_object,
gdbpy_initialize_symtabs): Declare.
* python/python.c (demand_python): Add lookup_symbol and
decode_line Python functions. Call gdb_initialize_symtabs.
(gdbpy_decode_line): New function.
Include linespec.h, symtab.h and source.c.
* python/symbol.c (symtab_object_methods): Add get_symtab
Python method.
(sympy_get_symtab, gdbpy_lookup_symbol): New functions.
* python/symtab.c: New file.
Index: python-tromey.git/gdb/Makefile.in
===================================================================
--- python-tromey.git.orig/gdb/Makefile.in 2008-04-29 11:47:49.000000000 -0300
+++ python-tromey.git/gdb/Makefile.in 2008-04-29 11:49:51.000000000 -0300
@@ -267,6 +267,7 @@ SUBDIR_PYTHON_OBS = \
python-cmd.o \
python-frame.o \
python-hooks.o \
+ python-symtab.o \
python-symbol.o \
python-value.o
SUBDIR_PYTHON_SRCS = \
@@ -276,6 +277,7 @@ SUBDIR_PYTHON_SRCS = \
python/cmd.c \
python/frame.c \
python/hooks.c \
+ python/symtab.c \
python/symbol.c \
python/value.c
SUBDIR_PYTHON_DEPS =
@@ -3423,7 +3425,8 @@ PYTHON_CFLAGS=-fno-strict-aliasing
python.o: $(srcdir)/python/python.c $(defs_h) $(python_h) \
$(command_h) $(libiberty_h) $(cli_decode_h) $(charset_h) $(top_h) \
- $(exceptions_h) $(python_internal_h) $(version_h) $(solib_h)
+ $(exceptions_h) $(python_internal_h) $(version_h) $(solib_h) \
+ $(linespec_h) $(symtab_h) $(source_h)
$(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) $(srcdir)/python/python.c
python-block.o: $(srcdir)/python/block.c $(defs_h) $(block_h) $(dictionary_h) \
$(symtab_h) $(python_h) $(python_internal_h)
@@ -3452,6 +3455,10 @@ python-symbol.o: $(srcdir)/python/symbol
$(python_internal_h)
$(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
$(srcdir)/python/symbol.c -o python-symbol.o
+python-symtab.o: $(srcdir)/python/symtab.c $(defs_h) $(charset_h) $(source_h) \
+ $(symtab_h) $(python_h) $(python_internal_h)
+ $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
+ $(srcdir)/python/symtab.c -o python-symtab.o
python-value.o: $(srcdir)/python/value.c $(defs_h) $(exceptions_h) \
$(python_internal_h) $(value_h)
$(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
Index: python-tromey.git/gdb/python/frame.c
===================================================================
--- python-tromey.git.orig/gdb/python/frame.c 2008-04-29 11:47:49.000000000 -0300
+++ python-tromey.git/gdb/python/frame.c 2008-04-29 11:47:56.000000000 -0300
@@ -56,6 +56,8 @@ static PyObject *frapy_get_pc (PyObject
static PyObject *frapy_get_address_in_block (PyObject *self, PyObject *args);
static PyObject *frapy_get_prev (PyObject *self, PyObject *args);
static PyObject *frapy_get_next (PyObject *self, PyObject *args);
+static PyObject *frapy_find_sal (PyObject *self, PyObject *args);
+static PyObject *frapy_read_var_value (PyObject *self, PyObject *args);
#define FRAPY_REQUIRE_VALID(frame_obj, frame) \
do { \
@@ -84,6 +86,10 @@ static PyMethodDef frame_object_methods[
{ "get_prev", frapy_get_prev, METH_NOARGS,
"Return the previous (outer) frame." },
{ "get_next", frapy_get_next, METH_NOARGS, "Return the next (inner) frame." },
+ { "find_sal", frapy_find_sal, METH_NOARGS,
+ "Return the frame's symtab and line." },
+ { "read_var_value", frapy_read_var_value, METH_VARARGS,
+ "Return the value of the variable in this frame." },
{NULL} /* Sentinel */
};
@@ -403,6 +409,54 @@ frapy_get_next (PyObject *self, PyObject
return next_obj;
}
+static PyObject *
+frapy_find_sal (PyObject *self, PyObject *args)
+{
+ struct frame_info *frame;
+ struct symtab_and_line sal;
+ volatile struct gdb_exception except;
+ PyObject *sal_obj = NULL; /* Initialize to appease gcc warning. */
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
+
+ find_frame_sal (frame, &sal);
+ sal_obj = symtab_and_line_to_sal_object (sal);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return sal_obj;
+}
+
+static PyObject *
+frapy_read_var_value (PyObject *self, PyObject *args)
+{
+ struct frame_info *frame;
+ PyObject *sym_obj;
+ struct symbol *var;
+ struct value *val = NULL;
+ volatile struct gdb_exception except;
+
+ if (!PyArg_ParseTuple (args, "O!", &symbol_object_type, &sym_obj))
+ return NULL;
+
+ var = symbol_object_to_symbol (sym_obj);
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
+
+ val = read_var_value (var, frame);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ if (val)
+ return value_to_value_object (val);
+
+ Py_RETURN_NONE;
+}
+
PyObject *
gdbpy_get_frames (PyObject *self, PyObject *args)
{
Index: python-tromey.git/gdb/python/python-internal.h
===================================================================
--- python-tromey.git.orig/gdb/python/python-internal.h 2008-04-29 11:47:49.000000000 -0300
+++ python-tromey.git/gdb/python/python-internal.h 2008-04-29 11:47:56.000000000 -0300
@@ -37,9 +37,12 @@ PyObject *gdbpy_get_breakpoints (PyObjec
PyObject *gdbpy_get_frames (PyObject *, PyObject *);
PyObject *gdbpy_get_current_frame (PyObject *, PyObject *);
PyObject *gdbpy_frame_stop_reason_string (PyObject *, PyObject *);
+PyObject *gdbpy_lookup_symbol (PyObject *self, PyObject *args);
PyObject *gdbpy_get_selected_frame (PyObject *self, PyObject *args);
PyObject *variable_to_python (struct cmd_list_element *);
+PyObject *symtab_and_line_to_sal_object (struct symtab_and_line sal);
+PyObject *symtab_to_symtab_object (struct symtab *symtab);
PyObject *symbol_to_symbol_object (struct symbol *sym);
PyObject *block_to_block_object (struct block *block);
PyObject *value_to_value_object (struct value *v);
@@ -55,6 +58,7 @@ void gdbpy_initialize_values (void);
void gdbpy_initialize_hooks (void);
void gdbpy_initialize_breakpoints (void);
void gdbpy_initialize_frames (void);
+void gdbpy_initialize_symtabs (void);
void gdbpy_initialize_commands (void);
void gdbpy_initialize_symbols (void);
void gdbpy_initialize_blocks (void);
Index: python-tromey.git/gdb/python/python.c
===================================================================
--- python-tromey.git.orig/gdb/python/python.c 2008-04-29 11:47:49.000000000 -0300
+++ python-tromey.git/gdb/python/python.c 2008-04-29 11:47:56.000000000 -0300
@@ -27,6 +27,9 @@
#include "solib.h"
#include "exceptions.h"
#include "python-internal.h"
+#include "linespec.h"
+#include "symtab.h"
+#include "source.h"
#include "version.h"
#include <ctype.h>
@@ -36,6 +39,7 @@ PyObject *gdb_module;
static PyObject *get_show_variable (PyObject *, PyObject *);
static PyObject *execute_gdb_command (PyObject *, PyObject *);
static PyObject *gdbpy_solib_address (PyObject *, PyObject *);
+static PyObject *gdbpy_decode_line (PyObject *, PyObject *);
static PyObject *gdbpy_find_pc_function (PyObject *, PyObject *);
@@ -68,12 +72,19 @@ demand_python ()
{ "frame_stop_reason_string", gdbpy_frame_stop_reason_string,
METH_VARARGS, "Return a string explaining unwind stop reason" },
+ { "lookup_symbol", gdbpy_lookup_symbol, METH_VARARGS,
+ "Return the symbol corresponding to the given name, or None." },
{ "solib_address", gdbpy_solib_address, METH_VARARGS,
"Return shared library holding a given address, or None." },
{ "find_pc_function", gdbpy_find_pc_function, METH_VARARGS,
"Return the function containing the given pc value, or None." },
+ { "decode_line", gdbpy_decode_line, METH_VARARGS,
+ "Decode a string argument the way that 'break' or 'edit' does.\n\
+Return a tuple holding the file name (or None) and line number (or None).\n\
+Note: may later change to return an object." },
+
{NULL, NULL, 0, NULL}
};
@@ -89,6 +100,7 @@ demand_python ()
gdbpy_initialize_values ();
gdbpy_initialize_breakpoints ();
gdbpy_initialize_frames ();
+ gdbpy_initialize_symtabs ();
gdbpy_initialize_commands ();
gdbpy_initialize_symbols ();
gdbpy_initialize_blocks ();
@@ -388,6 +400,78 @@ gdbpy_find_pc_function (PyObject *self,
Py_RETURN_NONE;
}
+PyObject *
+gdbpy_decode_line (PyObject *self, PyObject *args)
+{
+ struct symtabs_and_lines sals = { NULL, 0 }; /* Initialize to appease gcc. */
+ struct symtab_and_line sal;
+ char *arg = NULL;
+ int free_sals = 0, i;
+ PyObject *result = NULL;
+ volatile struct gdb_exception except;
+
+ if (! PyArg_ParseTuple (args, "|s", &arg))
+ return NULL;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ if (arg)
+ {
+ char *copy;
+
+ arg = strdup (arg);
+ copy = arg;
+
+ sals = decode_line_1 (©, 0, 0, 0, 0, 0);
+ free_sals = 1;
+ }
+ else
+ {
+ set_default_source_symtab_and_line ();
+ sal = get_current_source_symtab_and_line ();
+ sals.sals = &sal;
+ sals.nelts = 1;
+ }
+ }
+ if (arg)
+ xfree (arg);
+
+ if (except.reason < 0)
+ {
+ if (free_sals)
+ xfree (sals.sals);
+ /* We know this will always throw. */
+ GDB_PY_HANDLE_EXCEPTION (except);
+ }
+
+ if (sals.nelts)
+ {
+ result = PyTuple_New (sals.nelts);
+ for (i = 0; i < sals.nelts; ++i)
+ {
+ PyObject *obj;
+ char *str;
+
+ obj = symtab_and_line_to_sal_object (sals.sals[i]);
+ if (! obj)
+ {
+ Py_DECREF (result);
+ result = NULL;
+ break;
+ }
+
+ PyTuple_SetItem (result, i, obj);
+ }
+ }
+
+ if (free_sals)
+ xfree (sals.sals);
+
+ if (result)
+ return result;
+ Py_RETURN_NONE;
+}
+
\f
void
Index: python-tromey.git/gdb/python/symbol.c
===================================================================
--- python-tromey.git.orig/gdb/python/symbol.c 2008-04-29 11:47:49.000000000 -0300
+++ python-tromey.git/gdb/python/symbol.c 2008-04-29 11:47:56.000000000 -0300
@@ -28,6 +28,7 @@ typedef struct {
static PyObject *sympy_str (PyObject *self);
static PyObject *sympy_get_value (PyObject *self, PyObject *args);
+static PyObject *sympy_get_symtab (PyObject *self, PyObject *args);
static PyObject *sympy_get_natural_name (PyObject *self, PyObject *args);
static PyObject *sympy_get_linkage_name (PyObject *self, PyObject *args);
static PyObject *sympy_get_print_name (PyObject *self, PyObject *args);
@@ -36,6 +37,8 @@ static PyObject *sympy_get_class (PyObje
static PyMethodDef symbol_object_methods[] = {
{ "get_value", sympy_get_value, METH_NOARGS,
"Return the value of the symbol." },
+ { "get_symtab", sympy_get_symtab, METH_NOARGS,
+ "Return the value of the symbol." },
{ "get_natural_name", sympy_get_natural_name, METH_NOARGS,
"Return the \"natural\" name of the symbol." },
{ "get_linkage_name", sympy_get_linkage_name, METH_NOARGS,
@@ -115,6 +118,14 @@ sympy_get_value (PyObject *self, PyObjec
}
static PyObject *
+sympy_get_symtab (PyObject *self, PyObject *args)
+{
+ symbol_object *self_sym = (symbol_object *) self;
+
+ return symtab_to_symtab_object (SYMBOL_SYMTAB (self_sym->symbol));
+}
+
+static PyObject *
sympy_get_natural_name (PyObject *self, PyObject *args)
{
symbol_object *self_sym = (symbol_object *) self;
@@ -169,6 +180,73 @@ symbol_object_to_symbol (PyObject *obj)
return ((symbol_object *) obj)->symbol;
}
+/* This function has less arguments than its C counterpart, to simplify the
+ Python interface: name, block and domain. The other two arguments are always
+ assumed to be set, and a tuple with 3 elements is always returned. The first
+ is the symbol object or None, the second is a boolean with the value of
+ is_a_field_of_this, and the third is the symbol object or None. */
+PyObject *gdbpy_lookup_symbol (PyObject *self, PyObject *args)
+{
+ int domain, is_a_field_of_this = 0;
+ const char *name;
+ struct symbol *symbol;
+ struct symtab *symtab;
+ PyObject *block_obj, *ret_tuple, *sym_obj, *symtab_obj, *bool_obj;
+
+ PyArg_ParseTuple (args, "sO!i", &name, &block_object_type, &block_obj,
+ &domain);
+
+ symbol = lookup_symbol (name, block_object_to_block (block_obj), domain,
+ &is_a_field_of_this, &symtab);
+
+ ret_tuple = PyTuple_New (3);
+ if (!ret_tuple)
+ {
+ PyErr_SetString (PyExc_MemoryError, "Could not allocate tuple object.");
+ return NULL;
+ }
+
+ if (symbol)
+ {
+ sym_obj = symbol_to_symbol_object (symbol);
+ if (!sym_obj)
+ {
+ Py_DECREF (ret_tuple);
+ return NULL;
+ }
+ }
+ else
+ {
+ sym_obj = Py_None;
+ Py_INCREF (Py_None);
+ }
+ PyTuple_SET_ITEM (ret_tuple, 0, sym_obj);
+
+ bool_obj = is_a_field_of_this? Py_True : Py_False;
+ Py_INCREF (bool_obj);
+ PyTuple_SET_ITEM (ret_tuple, 1, bool_obj);
+
+ if (symtab)
+ {
+ symtab_obj = symtab_to_symtab_object (symtab);
+ if (!symtab_obj)
+ {
+ /* I *think* this will take care of decref'ing sym_obj and
+ bool_obj. */
+ Py_DECREF (ret_tuple);
+ return NULL;
+ }
+ }
+ else
+ {
+ symtab_obj = Py_None;
+ Py_INCREF (Py_None);
+ }
+ PyTuple_SET_ITEM (ret_tuple, 2, symtab_obj);
+
+ return ret_tuple;
+}
+
void
gdbpy_initialize_symbols (void)
{
Index: python-tromey.git/gdb/python/symtab.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ python-tromey.git/gdb/python/symtab.c 2008-04-29 11:47:56.000000000 -0300
@@ -0,0 +1,325 @@
+/* Python interface to symbol tables.
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "charset.h"
+#include "symtab.h"
+#include "source.h"
+#include "python-internal.h"
+
+typedef struct {
+ PyObject_HEAD
+ struct symtab *symtab;
+} symtab_object;
+
+static PyObject *stpy_str (PyObject *self);
+static PyObject *stpy_filename (PyObject *self, PyObject *args);
+static PyObject *stpy_to_fullname (PyObject *self, PyObject *args);
+
+static PyMethodDef symtab_object_methods[] = {
+ { "get_filename", stpy_filename, METH_NOARGS,
+ "Return the symtab's source filename." },
+ { "to_fullname", stpy_to_fullname, METH_NOARGS,
+ "Return the symtab's full source filename." },
+ {NULL} /* Sentinel */
+};
+
+static PyTypeObject symtab_object_type = {
+ PyObject_HEAD_INIT (NULL)
+ 0, /*ob_size*/
+ "gdb.Symtab", /*tp_name*/
+ sizeof (symtab_object), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ stpy_str, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "GDB symtab object", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ symtab_object_methods /* tp_methods */
+};
+
+typedef struct {
+ PyObject_HEAD
+ symtab_object *symtab;
+ struct symtab_and_line *sal;
+} sal_object;
+
+static void salpy_dealloc (PyObject *self);
+static int salpy_setsymtab (PyObject *self, PyObject *value, void *closure);
+static PyObject *salpy_str (PyObject *self);
+static PyObject *salpy_getsymtab (PyObject *self, void *closure);
+static PyObject *salpy_pc (PyObject *self, PyObject *args);
+static PyObject *salpy_line (PyObject *self, PyObject *args);
+
+static PyGetSetDef sal_object_getseters[] = {
+ { "symtab", salpy_getsymtab, salpy_setsymtab, "Symtab object.", NULL },
+ {NULL} /* Sentinel */
+};
+
+static PyMethodDef sal_object_methods[] = {
+ { "get_pc", salpy_pc, METH_NOARGS,
+ "Return the symtab_and_line's pc." },
+ { "get_line", salpy_line, METH_NOARGS,
+ "Return the symtab_and_line's line." },
+ {NULL} /* Sentinel */
+};
+
+static PyTypeObject sal_object_type = {
+ PyObject_HEAD_INIT (NULL)
+ 0, /*ob_size*/
+ "gdb.Symtab_and_line", /*tp_name*/
+ sizeof (sal_object), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ salpy_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ salpy_str, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "GDB symtab_and_line object", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ sal_object_methods, /* tp_methods */
+ 0, /* tp_members */
+ sal_object_getseters /* tp_getset */
+};
+
+
+static PyObject *
+stpy_str (PyObject *self)
+{
+ int ret;
+ char *s;
+ PyObject *result;
+
+ ret = asprintf (&s, "symbol table for %s",
+ ((symtab_object *) self)->symtab->filename);
+ if (ret < 0)
+ Py_RETURN_NONE;
+
+ result = PyString_FromString (s);
+ xfree (s);
+
+ return result;
+}
+
+/* FIXME: maybe this should be an attribute instead of a method? */
+static PyObject *
+stpy_filename (PyObject *self, PyObject *args)
+{
+ symtab_object *self_symtab = (symtab_object *) self;
+ PyObject *str_obj;
+
+ /* FIXME: Can symtab->filename really be NULL? */
+ if (self_symtab->symtab->filename)
+ str_obj = PyString_Decode (self_symtab->symtab->filename,
+ strlen (self_symtab->symtab->filename),
+ host_charset (), NULL /* FIXME */);
+ else
+ {
+ str_obj = Py_None;
+ Py_INCREF (Py_None);
+ }
+
+ return str_obj;
+}
+
+static PyObject *
+stpy_to_fullname (PyObject *self, PyObject *args)
+{
+ char *fullname;
+
+ fullname = symtab_to_fullname (((symtab_object *) self)->symtab);
+ if (fullname)
+ return PyString_Decode (fullname, strlen (fullname), host_charset (),
+ NULL /* FIXME */);
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+salpy_str (PyObject *self)
+{
+ int ret;
+ char *s, *filename;
+ sal_object *sal_obj;
+ PyObject *result;
+
+ sal_obj = (sal_object *) self;
+ filename = (sal_obj->symtab == (symtab_object *) Py_None)? "<unknown>" :
+ sal_obj->symtab->symtab->filename;
+ ret = asprintf (&s, "symbol and line for %s, line %d", filename,
+ sal_obj->sal->line);
+ if (ret < 0)
+ Py_RETURN_NONE;
+
+ result = PyString_FromString (s);
+ xfree (s);
+
+ return result;
+}
+
+static PyObject *
+salpy_pc (PyObject *self, PyObject *args)
+{
+ return PyLong_FromUnsignedLongLong (((sal_object *) self)->sal->pc);
+}
+
+static PyObject *
+salpy_line (PyObject *self, PyObject *args)
+{
+ return PyLong_FromUnsignedLongLong (((sal_object *) self)->sal->line);
+}
+
+static PyObject *
+salpy_getsymtab (PyObject *self, void *closure)
+{
+ sal_object *self_sal = (sal_object *) self;
+
+ Py_INCREF (self_sal->symtab);
+
+ return (PyObject *) self_sal->symtab;
+}
+
+static int
+salpy_setsymtab (PyObject *self, PyObject *value, void *closure)
+{
+ PyErr_SetString (PyExc_TypeError, "The symtab attribute can't be modified.");
+
+ return -1;
+}
+
+static void
+salpy_dealloc (PyObject *self)
+{
+ sal_object *self_sal = (sal_object *) self;
+
+ Py_DECREF (self_sal->symtab);
+ xfree (self_sal->sal);
+ self_sal->ob_type->tp_free (self);
+}
+
+PyObject *
+symtab_and_line_to_sal_object (struct symtab_and_line sal)
+{
+ sal_object *sal_obj;
+ symtab_object *symtab_obj;
+
+ sal_obj = PyObject_New (sal_object, &sal_object_type);
+ if (sal_obj == NULL)
+ {
+ PyErr_SetString (PyExc_MemoryError,
+ "Could not allocate Symtab_and_line object.");
+ return NULL;
+ }
+
+ if (sal.symtab)
+ {
+ symtab_obj = (symtab_object *) symtab_to_symtab_object (sal.symtab);
+ if (symtab_obj == NULL)
+ {
+ Py_DECREF (sal_obj);
+ return NULL;
+ }
+
+ symtab_obj->symtab = sal.symtab;
+ }
+ else
+ {
+ symtab_obj = (symtab_object *) Py_None;
+ Py_INCREF (Py_None);
+ }
+
+ sal_obj->sal = (struct symtab_and_line *)
+ xmalloc (sizeof (struct symtab_and_line));
+ *(sal_obj->sal) = sal;
+ sal_obj->symtab = symtab_obj;
+
+ return (PyObject *) sal_obj;
+}
+
+PyObject *
+symtab_to_symtab_object (struct symtab *symtab)
+{
+ symtab_object *symtab_obj;
+
+ symtab_obj = PyObject_New (symtab_object, &symtab_object_type);
+ if (symtab_obj == NULL)
+ {
+ PyErr_SetString (PyExc_MemoryError,
+ "Could not allocate Symtab object.");
+
+ return NULL;
+ }
+
+ symtab_obj->symtab = symtab;
+
+ return (PyObject *) symtab_obj;
+}
+
+void
+gdbpy_initialize_symtabs (void)
+{
+ symtab_object_type.tp_new = PyType_GenericNew;
+ if (PyType_Ready (&symtab_object_type) < 0)
+ return;
+
+ sal_object_type.tp_new = PyType_GenericNew;
+ if (PyType_Ready (&sal_object_type) < 0)
+ return;
+
+ Py_INCREF (&symtab_object_type);
+ PyModule_AddObject (gdb_module, "Symtab", (PyObject *) &symtab_object_type);
+
+ Py_INCREF (&sal_object_type);
+ PyModule_AddObject (gdb_module, "Symtab_and_line",
+ (PyObject *) &sal_object_type);
+}
--
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* [RFC][patch 9/9] export threads to Python
2008-04-29 15:59 [RFC][patch 0/9] Python support in GDB Thiago Jung Bauermann
2008-04-29 15:59 ` [RFC][patch 8/9] export symtab mechanism to Python Thiago Jung Bauermann
2008-04-29 15:59 ` [RFC][patch 6/9] export frames " Thiago Jung Bauermann
@ 2008-04-29 15:59 ` Thiago Jung Bauermann
2008-04-29 15:59 ` [RFC][patch 3/9] export hooks mechanism " Thiago Jung Bauermann
` (7 subsequent siblings)
10 siblings, 0 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-04-29 15:59 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: python-threads.diff --]
[-- Type: text/plain, Size: 6339 bytes --]
2008-04-29 Tom Tromey <tromey@redhat.com>
* Makefile.in (python.o): Depend on inferior.h and gdbthread.h.
* gdbthread.h (prune_threads): Declare.
* python/python.c: Include inferior.h, gdbthread.h.
(demand_python): Register new functions.
(count_callback): New function.
(struct set_thread_info): New struct.
(update_tuple_callback): New function.
(gdbpy_get_threads): Likewise.
(gdbpy_get_current_thread): Likewise.
(gdbpy_switch_to_thread): Likewise.
* thread.c (prune_threads): No longer 'static'. Rewrote.
Index: python-tromey.git/gdb/Makefile.in
===================================================================
--- python-tromey.git.orig/gdb/Makefile.in 2008-04-29 11:49:51.000000000 -0300
+++ python-tromey.git/gdb/Makefile.in 2008-04-29 11:55:27.000000000 -0300
@@ -3426,7 +3426,7 @@ PYTHON_CFLAGS=-fno-strict-aliasing
python.o: $(srcdir)/python/python.c $(defs_h) $(python_h) \
$(command_h) $(libiberty_h) $(cli_decode_h) $(charset_h) $(top_h) \
$(exceptions_h) $(python_internal_h) $(version_h) $(solib_h) \
- $(linespec_h) $(symtab_h) $(source_h)
+ $(linespec_h) $(symtab_h) $(source_h) $(inferior_h) $(gdbthread_h)
$(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) $(srcdir)/python/python.c
python-block.o: $(srcdir)/python/block.c $(defs_h) $(block_h) $(dictionary_h) \
$(symtab_h) $(python_h) $(python_internal_h)
Index: python-tromey.git/gdb/gdbthread.h
===================================================================
--- python-tromey.git.orig/gdb/gdbthread.h 2008-04-29 11:47:48.000000000 -0300
+++ python-tromey.git/gdb/gdbthread.h 2008-04-29 11:54:06.000000000 -0300
@@ -110,6 +110,9 @@ extern int valid_thread_id (int thread);
/* Search function to lookup a thread by 'pid'. */
extern struct thread_info *find_thread_pid (ptid_t ptid);
+/* Prune dead threads from the list of threads. */
+extern void prune_threads (void);
+
/* Iterator function to call a user-provided callback function
once for each known thread. */
typedef int (*thread_callback_func) (struct thread_info *, void *);
Index: python-tromey.git/gdb/python/python.c
===================================================================
--- python-tromey.git.orig/gdb/python/python.c 2008-04-29 11:47:56.000000000 -0300
+++ python-tromey.git/gdb/python/python.c 2008-04-29 11:54:06.000000000 -0300
@@ -31,6 +31,8 @@
#include "symtab.h"
#include "source.h"
#include "version.h"
+#include "inferior.h"
+#include "gdbthread.h"
#include <ctype.h>
@@ -41,6 +43,9 @@ static PyObject *execute_gdb_command (Py
static PyObject *gdbpy_solib_address (PyObject *, PyObject *);
static PyObject *gdbpy_decode_line (PyObject *, PyObject *);
static PyObject *gdbpy_find_pc_function (PyObject *, PyObject *);
+static PyObject *gdbpy_get_threads (PyObject *, PyObject *);
+static PyObject *gdbpy_get_current_thread (PyObject *, PyObject *);
+static PyObject *gdbpy_switch_to_thread (PyObject *, PyObject *);
void
@@ -85,6 +90,13 @@ demand_python ()
Return a tuple holding the file name (or None) and line number (or None).\n\
Note: may later change to return an object." },
+ { "get_threads", gdbpy_get_threads, METH_NOARGS,
+ "Return a tuple holding all the valid thread IDs." },
+ { "get_current_thread", gdbpy_get_current_thread, METH_NOARGS,
+ "Return the thread ID of the current thread." },
+ { "switch_to_thread", gdbpy_switch_to_thread, METH_VARARGS,
+ "Switch to a thread, given the thread ID." },
+
{NULL, NULL, 0, NULL}
};
@@ -474,6 +486,75 @@ gdbpy_decode_line (PyObject *self, PyObj
\f
+/* Threads. */
+
+static int
+count_callback (struct thread_info *info, void *user_data)
+{
+ int *count = (int *) user_data;
+ ++*count;
+ return 0;
+}
+
+struct set_thread_info
+{
+ PyObject *tuple;
+ int index;
+};
+
+static int
+update_tuple_callback (struct thread_info *info, void *user_data)
+{
+ struct set_thread_info *tinfo = (struct set_thread_info *) user_data;
+ PyTuple_SetItem (tinfo->tuple, tinfo->index, PyInt_FromLong (info->num));
+ ++tinfo->index;
+ return 0;
+}
+
+static PyObject *
+gdbpy_get_threads (PyObject *unused1, PyObject *unused2)
+{
+ int thread_count = 0;
+ struct set_thread_info info;
+ PyObject *result;
+
+ prune_threads ();
+ target_find_new_threads ();
+
+ iterate_over_threads (count_callback, &thread_count);
+
+ if (!thread_count)
+ Py_RETURN_NONE;
+
+ result = PyTuple_New (thread_count);
+ info.tuple = result;
+ info.index = 0;
+ iterate_over_threads (update_tuple_callback, &info);
+ return result;
+}
+
+static PyObject *
+gdbpy_get_current_thread (PyObject *unused1, PyObject *unused2)
+{
+ if (PIDGET (inferior_ptid) == 0)
+ Py_RETURN_NONE;
+ return PyInt_FromLong (pid_to_thread_id (inferior_ptid));
+}
+
+static PyObject *
+gdbpy_switch_to_thread (PyObject *self, PyObject *args)
+{
+ int id;
+ if (! PyArg_ParseTuple (args, "i", &id))
+ return NULL;
+ if (! valid_thread_id (id))
+ return PyErr_Format (PyExc_RuntimeError, "invalid thread id");
+ switch_to_thread (thread_id_to_pid (id));
+ Py_RETURN_NONE;
+}
+
+\f
+
void
_initialize_python (void)
{
Index: python-tromey.git/gdb/thread.c
===================================================================
--- python-tromey.git.orig/gdb/thread.c 2008-04-29 11:47:48.000000000 -0300
+++ python-tromey.git/gdb/thread.c 2008-04-29 11:54:06.000000000 -0300
@@ -60,7 +60,6 @@ static int thread_alive (struct thread_i
static void info_threads_command (char *, int);
static void thread_apply_command (char *, int);
static void restore_current_thread (ptid_t);
-static void prune_threads (void);
void
delete_step_resume_breakpoint (void *arg)
@@ -400,16 +399,23 @@ thread_alive (struct thread_info *tp)
return 1;
}
-static void
+void
prune_threads (void)
{
- struct thread_info *tp, *next;
+ struct thread_info *tp;
+ struct thread_info **prevp = &thread_list;
- for (tp = thread_list; tp; tp = next)
+ for (tp = *prevp; tp; tp = *prevp)
{
- next = tp->next;
+ /* If the thread has died, free it and unlink it from the list.
+ Otherwise, advance to the next thread. */
if (!thread_alive (tp))
- delete_thread (tp->ptid);
+ {
+ (*prevp)->next = tp->next;
+ free_thread (tp);
+ }
+ else
+ prevp = &tp->next;
}
}
--
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* [RFC][patch 6/9] export frames to Python
2008-04-29 15:59 [RFC][patch 0/9] Python support in GDB Thiago Jung Bauermann
2008-04-29 15:59 ` [RFC][patch 8/9] export symtab mechanism to Python Thiago Jung Bauermann
@ 2008-04-29 15:59 ` Thiago Jung Bauermann
2008-04-29 15:59 ` [RFC][patch 9/9] export threads " Thiago Jung Bauermann
` (8 subsequent siblings)
10 siblings, 0 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-04-29 15:59 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: python-frames.diff --]
[-- Type: text/plain, Size: 26227 bytes --]
2008-04-29 Thiago Jung Bauermann <bauerman@br.ibm.com>
Tom Tromey <tromey@redhat.com>
* Makefile.in (SUBDIR_PYTHON_OBS): Add python-frame.o.
(SUBDIR_PYTHON_SRCS): Add python/frame.c.
(python.o): Depend on solib.h.
(python-frame.o): New target.
* python/frame.c: New file.
* python/python-internal.h (gdbpy_get_frames,
gdbpy_get_current_frame, gdbpy_frame_stop_reason_string,
gdbpy_get_selected_frame, gdbpy_initialize_frames): Declare.
* python/python.c (demand_python): Add frame functions. Call
gdbpy_initialize_frames.
(gdbpy_solib_address): New function.
Include solib.h
* stack.c (print_frame): Factor out code to find function name
and language into ...
(find_frame_funname): ... this new function.
* stack.h (find_frame_funname): Declare.
Index: tromey.git/gdb/Makefile.in
===================================================================
--- tromey.git.orig/gdb/Makefile.in 2008-04-29 11:05:20.000000000 -0300
+++ tromey.git/gdb/Makefile.in 2008-04-29 11:05:45.000000000 -0300
@@ -264,12 +264,14 @@ SUBDIR_PYTHON_OBS = \
python.o \
python-breakpoint.o \
python-cmd.o \
+ python-frame.o \
python-hooks.o \
python-value.o
SUBDIR_PYTHON_SRCS = \
python/python.c \
python/breakpoint.c \
python/cmd.c \
+ python/frame.c \
python/hooks.c \
python/value.c
SUBDIR_PYTHON_DEPS =
@@ -3417,7 +3419,7 @@ PYTHON_CFLAGS=-fno-strict-aliasing
python.o: $(srcdir)/python/python.c $(defs_h) $(python_h) \
$(command_h) $(libiberty_h) $(cli_decode_h) $(charset_h) $(top_h) \
- $(exceptions_h) $(python_internal_h) $(version_h)
+ $(exceptions_h) $(python_internal_h) $(version_h) $(solib_h)
$(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) $(srcdir)/python/python.c
python-breakpoint.o: $(srcdir)/python/breakpoint.c $(defs_h) $(python_h) \
$(value_h) $(exceptions_h) $(python_internal_h) $(charset_h) \
@@ -3429,6 +3431,11 @@ python-cmd.o: $(srcdir)/python/cmd.c $(d
$(gdbcmd_h) $(cli_decode_h)
$(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
$(srcdir)/python/cmd.c -o python-cmd.o
+python-frame.o: $(srcdir)/python/frame.c $(defs_h) $(python_h) \
+ $(python_internal_h) $(frame_h) $(exceptions_h) $(symtab_h) \
+ $(charset_h) $(stack_h) $(value_h)
+ $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
+ $(srcdir)/python/frame.c -o python-frame.o
python-hooks.o: $(srcdir)/python/hooks.c $(defs_h) $(cli_decode_h) \
$(charset_h) $(gdb_events_h) $(python_h) $(python_internal_h)
$(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
Index: tromey.git/gdb/python/frame.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ tromey.git/gdb/python/frame.c 2008-04-29 11:05:54.000000000 -0300
@@ -0,0 +1,536 @@
+/* Python interface to stack frames
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "charset.h"
+#include "frame.h"
+#include "exceptions.h"
+#include "symtab.h"
+#include "stack.h"
+#include "value.h"
+#include "python-internal.h"
+
+typedef struct {
+ PyObject_HEAD
+ struct frame_id frame_id;
+ struct gdbarch *gdbarch;
+
+ /* Marks that the FRAME_ID member actually holds the ID of the frame next
+ to this, and not this frames' ID itself. This is a hack to permit Python
+ frame objects which represent invalid frames (i.e., the last frame_info
+ in a corrupt stack). The problem arises from the fact that this code
+ relies on FRAME_ID to uniquely identify a frame, which is not always true
+ for the last "frame" in a corrupt stack (it can have a null ID, or the same
+ ID as the previous frame). Whenever get_prev_frame returns NULL, we
+ record the frame_id of the next frame and set FRAME_ID_IS_NEXT to 1. */
+ int frame_id_is_next;
+} frame_object;
+
+static frame_object *frame_info_to_frame_object (struct frame_info *frame);
+static struct frame_info *frame_object_to_frame_info (frame_object *frame_obj);
+
+static PyObject *frapy_str (PyObject *self);
+static PyObject *frapy_equal_p (PyObject *self, PyObject *args);
+static PyObject *frapy_inner_p (PyObject *self, PyObject *args);
+static PyObject *frapy_is_valid (PyObject *self, PyObject *args);
+static PyObject *frapy_get_name (PyObject *self, PyObject *args);
+static PyObject *frapy_get_type (PyObject *self, PyObject *args);
+static PyObject *frapy_get_unwind_stop_reason (PyObject *self, PyObject *args);
+static PyObject *frapy_get_pc (PyObject *self, PyObject *args);
+static PyObject *frapy_get_address_in_block (PyObject *self, PyObject *args);
+static PyObject *frapy_get_prev (PyObject *self, PyObject *args);
+static PyObject *frapy_get_next (PyObject *self, PyObject *args);
+
+#define FRAPY_REQUIRE_VALID(frame_obj, frame) \
+ do { \
+ frame = frame_object_to_frame_info (frame_obj); \
+ if (frame == NULL) \
+ { \
+ PyErr_SetString (PyExc_RuntimeError, "Frame is invalid."); \
+ return NULL; \
+ } \
+ } while (0)
+
+static PyMethodDef frame_object_methods[] = {
+ { "equals", frapy_equal_p, METH_VARARGS, "Compare frames." },
+ { "is_inner_than", frapy_inner_p, METH_VARARGS,
+ "Return true if this frame is strictly inner than the other frame." },
+ { "is_valid", frapy_is_valid, METH_NOARGS,
+ "Return true if this frame is valid, false if not." },
+ { "get_name", frapy_get_name, METH_NOARGS,
+ "Return the function name of the frame." },
+ { "get_type", frapy_get_type, METH_NOARGS, "Return the type of the frame." },
+ { "get_unwind_stop_reason", frapy_get_unwind_stop_reason,
+ METH_NOARGS, "Return the function name of the frame." },
+ { "get_pc", frapy_get_pc, METH_NOARGS, "Return the frame's resume address." },
+ { "get_address_in_block", frapy_get_address_in_block, METH_NOARGS,
+ "Return an address which falls within the frame's code block." },
+ { "get_prev", frapy_get_prev, METH_NOARGS,
+ "Return the previous (outer) frame." },
+ { "get_next", frapy_get_next, METH_NOARGS, "Return the next (inner) frame." },
+ {NULL} /* Sentinel */
+};
+
+static PyTypeObject frame_object_type = {
+ PyObject_HEAD_INIT (NULL)
+ 0, /*ob_size*/
+ "gdb.Frame", /*tp_name*/
+ sizeof (frame_object), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ frapy_str, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "GDB frame object", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ frame_object_methods /* tp_methods */
+};
+
+
+static PyObject *
+frapy_str (PyObject *self)
+{
+ char *s;
+ long len;
+ PyObject *result;
+ struct ui_file *strfile;
+
+ strfile = mem_fileopen ();
+ fprint_frame_id (strfile, ((frame_object *) self)->frame_id);
+ s = ui_file_xstrdup (strfile, &len);
+ result = PyString_FromString (s);
+ xfree (s);
+
+ return result;
+}
+
+static PyObject *
+frapy_is_valid (PyObject *self, PyObject *args)
+{
+ struct frame_info *frame;
+
+ frame = frame_object_to_frame_info ((frame_object *) self);
+ if (frame == NULL)
+ Py_RETURN_FALSE;
+
+ Py_RETURN_TRUE;
+}
+
+static PyObject *
+frapy_equal_p (PyObject *self, PyObject *args)
+{
+ int equalp = 0; /* Initialize to appease gcc warning. */
+ frame_object *self_frame = (frame_object *) self;
+ frame_object *other;
+ volatile struct gdb_exception except;
+
+ if (!PyArg_ParseTuple (args, "O!", &frame_object_type, &other))
+ return NULL;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ equalp = frame_id_eq (self_frame->frame_id, other->frame_id);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ if (equalp)
+ Py_RETURN_TRUE;
+
+ Py_RETURN_FALSE;
+}
+
+static PyObject *
+frapy_inner_p (PyObject *self, PyObject *args)
+{
+ int innerp = 0; /* Initialize to appease gcc warning. */
+ frame_object *self_frame = (frame_object *) self;
+ frame_object *other;
+ volatile struct gdb_exception except;
+
+ if (!PyArg_ParseTuple (args, "O!", &frame_object_type, &other))
+ return NULL;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ /* It doesn't make sense to compare frames from different arches. */
+ if (self_frame->gdbarch != other->gdbarch)
+ {
+ PyErr_SetString (PyExc_ValueError,
+ "Frames are from different architectures.");
+ return NULL;
+ }
+
+ innerp = frame_id_inner (self_frame->gdbarch,
+ self_frame->frame_id, other->frame_id);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ if (innerp)
+ Py_RETURN_TRUE;
+
+ Py_RETURN_FALSE;
+}
+
+static PyObject *
+frapy_get_name (PyObject *self, PyObject *args)
+{
+ struct frame_info *frame;
+ char *name;
+ enum language lang;
+ PyObject *result;
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
+
+ find_frame_funname (frame, &name, &lang);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ if (name)
+ result = PyString_Decode (name, strlen (name), host_charset (),
+ NULL /* FIXME */);
+ else
+ {
+ result = Py_None;
+ Py_INCREF (Py_None);
+ }
+
+ return result;
+}
+
+static PyObject *
+frapy_get_type (PyObject *self, PyObject *args)
+{
+ struct frame_info *frame;
+ enum frame_type type = NORMAL_FRAME;/* Initialize to appease gcc warning. */
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
+
+ type = get_frame_type (frame);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return PyInt_FromLong (type);
+}
+
+static PyObject *
+frapy_get_unwind_stop_reason (PyObject *self, PyObject *args)
+{
+ struct frame_info *frame = NULL; /* Initialize to appease gcc warning. */
+ volatile struct gdb_exception except;
+ enum unwind_stop_reason stop_reason;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ stop_reason = get_frame_unwind_stop_reason (frame);
+
+ return PyInt_FromLong (stop_reason);
+}
+
+static PyObject *
+frapy_get_pc (PyObject *self, PyObject *args)
+{
+ CORE_ADDR pc = 0; /* Initialize to appease gcc warning. */
+ struct frame_info *frame;
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
+
+ pc = get_frame_pc (frame);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return PyLong_FromUnsignedLongLong (pc);
+}
+
+static PyObject *
+frapy_get_address_in_block (PyObject *self, PyObject *args)
+{
+ CORE_ADDR pc = 0; /* Initialize to appease gcc warning. */
+ struct frame_info *frame;
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
+
+ pc = get_frame_address_in_block (frame);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return PyLong_FromUnsignedLongLong (pc);
+}
+
+static frame_object *
+frame_info_to_frame_object (struct frame_info *frame)
+{
+ frame_object *frame_obj;
+
+ frame_obj = PyObject_New (frame_object, &frame_object_type);
+ if (frame_obj == NULL)
+ {
+ PyErr_SetString (PyExc_MemoryError, "Could not allocate frame object.");
+ return NULL;
+ }
+
+ /* Try to get the previous frame, to determine if this is the last frame
+ in a corrupt stack. If so, we need to store the frame_id of the next
+ frame and not of this one (which is possibly invalid). */
+ if (get_prev_frame (frame) == NULL
+ && get_frame_unwind_stop_reason (frame) != UNWIND_NO_REASON
+ && get_next_frame (frame) != NULL)
+ {
+ frame_obj->frame_id = get_frame_id (get_next_frame (frame));
+ frame_obj->frame_id_is_next = 1;
+ }
+ else
+ {
+ frame_obj->frame_id = get_frame_id (frame);
+ frame_obj->frame_id_is_next = 0;
+ }
+
+ frame_obj->gdbarch = get_frame_arch (frame);
+
+ return frame_obj;
+}
+
+static struct frame_info *
+frame_object_to_frame_info (frame_object *frame_obj)
+{
+ struct frame_info *frame;
+
+ frame = frame_find_by_id (frame_obj->frame_id);
+ if (frame == NULL)
+ return NULL;
+
+ if (frame_obj->frame_id_is_next)
+ frame = get_prev_frame (frame);
+
+ return frame;
+}
+
+static PyObject *
+frapy_get_prev (PyObject *self, PyObject *args)
+{
+ struct frame_info *frame, *prev;
+ volatile struct gdb_exception except;
+ PyObject *prev_obj = NULL; /* Initialize to appease gcc warning. */
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
+
+ prev = get_prev_frame (frame);
+ if (prev)
+ prev_obj = (PyObject *) frame_info_to_frame_object (prev);
+ else
+ {
+ Py_INCREF (Py_None);
+ prev_obj = Py_None;
+ }
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return prev_obj;
+}
+
+static PyObject *
+frapy_get_next (PyObject *self, PyObject *args)
+{
+ struct frame_info *frame, *next;
+ volatile struct gdb_exception except;
+ PyObject *next_obj = NULL; /* Initialize to appease gcc warning. */
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
+
+ next = get_next_frame (frame);
+ if (next)
+ next_obj = (PyObject *) frame_info_to_frame_object (next);
+ else
+ {
+ Py_INCREF (Py_None);
+ next_obj = Py_None;
+ }
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return next_obj;
+}
+
+PyObject *
+gdbpy_get_frames (PyObject *self, PyObject *args)
+{
+ int result = 0;
+ struct frame_info *frame;
+ frame_object *frame_obj;
+ PyObject *list, *tuple;
+ volatile struct gdb_exception except;
+
+ list = PyList_New (0);
+ if (list == NULL)
+ {
+ PyErr_SetString (PyExc_MemoryError, "Could not allocate frames list.");
+ return NULL;
+ }
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ for (frame = get_current_frame (); frame; frame = get_prev_frame (frame))
+ {
+ frame_obj = frame_info_to_frame_object (frame);
+ if (frame_obj == NULL)
+ {
+ Py_DECREF (list);
+ return NULL;
+ }
+
+ PyList_Append (list, (PyObject *) frame_obj);
+ }
+ }
+ if (except.reason < 0)
+ {
+ Py_DECREF (list);
+ return PyErr_Format (except.reason == RETURN_QUIT
+ ? PyExc_KeyboardInterrupt : PyExc_RuntimeError,
+ "%s", except.message);
+ }
+
+ tuple = PyList_AsTuple (list);
+ Py_DECREF (list);
+
+ return tuple;
+}
+
+PyObject *
+gdbpy_get_current_frame (PyObject *self, PyObject *args)
+{
+ struct frame_info *frame;
+ frame_object *frame_obj = NULL; /* Initialize to appease gcc warning. */
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ frame = get_current_frame ();
+ frame_obj = frame_info_to_frame_object (frame);
+ if (frame_obj == NULL)
+ return NULL;
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return (PyObject *) frame_obj;
+}
+
+PyObject *
+gdbpy_get_selected_frame (PyObject *self, PyObject *args)
+{
+ struct frame_info *frame;
+ frame_object *frame_obj = NULL; /* Initialize to appease gcc warning. */
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ frame = get_selected_frame ("No frame is currently selected.");
+ frame_obj = frame_info_to_frame_object (frame);
+ if (frame_obj == NULL)
+ return NULL;
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ return (PyObject *) frame_obj;
+}
+
+PyObject *
+gdbpy_frame_stop_reason_string (PyObject *self, PyObject *args)
+{
+ int reason;
+ const char *str;
+
+ if (!PyArg_ParseTuple (args, "i", &reason))
+ return NULL;
+
+ if (reason < 0 || reason > UNWIND_NO_SAVED_PC)
+ {
+ PyErr_SetString (PyExc_ValueError, "Invalid frame stop reason.");
+ return NULL;
+ }
+
+ str = frame_stop_reason_string (reason);
+ return PyString_Decode (str, strlen (str), host_charset (), NULL /* FIXME */);
+}
+
+void
+gdbpy_initialize_frames (void)
+{
+ frame_object_type.tp_new = PyType_GenericNew;
+ if (PyType_Ready (&frame_object_type) < 0)
+ return;
+
+ /* FIXME: These would probably be best exposed as class attributes of Frame,
+ but I don't know how to do it except by messing with the type's dictionary.
+ That seems too messy. */
+ PyModule_AddIntConstant (gdb_module, "NORMAL_FRAME", NORMAL_FRAME);
+ PyModule_AddIntConstant (gdb_module, "DUMMY_FRAME", DUMMY_FRAME);
+ PyModule_AddIntConstant (gdb_module, "SIGTRAMP_FRAME", SIGTRAMP_FRAME);
+ PyModule_AddIntConstant (gdb_module, "SENTINEL_FRAME", SENTINEL_FRAME);
+ PyModule_AddIntConstant (gdb_module,
+ "FRAME_UNWIND_NO_REASON", UNWIND_NO_REASON);
+ PyModule_AddIntConstant (gdb_module,
+ "FRAME_UNWIND_NULL_ID", UNWIND_NULL_ID);
+ PyModule_AddIntConstant (gdb_module,
+ "FRAME_UNWIND_FIRST_ERROR", UNWIND_FIRST_ERROR);
+ PyModule_AddIntConstant (gdb_module,
+ "FRAME_UNWIND_INNER_ID", UNWIND_INNER_ID);
+ PyModule_AddIntConstant (gdb_module,
+ "FRAME_UNWIND_SAME_ID", UNWIND_SAME_ID);
+ PyModule_AddIntConstant (gdb_module,
+ "FRAME_UNWIND_NO_SAVED_PC", UNWIND_NO_SAVED_PC);
+
+ Py_INCREF (&frame_object_type);
+ PyModule_AddObject (gdb_module, "Frame", (PyObject *) &frame_object_type);
+}
Index: tromey.git/gdb/python/python-internal.h
===================================================================
--- tromey.git.orig/gdb/python/python-internal.h 2008-04-29 11:05:20.000000000 -0300
+++ tromey.git/gdb/python/python-internal.h 2008-04-29 11:05:45.000000000 -0300
@@ -32,6 +32,10 @@ extern PyTypeObject value_object_type;
PyObject *gdbpy_make_value_from_int (PyObject *self, PyObject *args);
PyObject *gdbpy_get_value_from_history (PyObject *self, PyObject *args);
PyObject *gdbpy_get_breakpoints (PyObject *, PyObject *);
+PyObject *gdbpy_get_frames (PyObject *, PyObject *);
+PyObject *gdbpy_get_current_frame (PyObject *, PyObject *);
+PyObject *gdbpy_frame_stop_reason_string (PyObject *, PyObject *);
+PyObject *gdbpy_get_selected_frame (PyObject *self, PyObject *args);
PyObject *variable_to_python (struct cmd_list_element *);
PyObject *value_to_value_object (struct value *v);
@@ -44,6 +48,7 @@ PyObject *gdbpy_get_hook_function (const
void gdbpy_initialize_values (void);
void gdbpy_initialize_hooks (void);
void gdbpy_initialize_breakpoints (void);
+void gdbpy_initialize_frames (void);
void gdbpy_initialize_commands (void);
/* Use this after a TRY_EXCEPT to throw the appropriate Python
Index: tromey.git/gdb/python/python.c
===================================================================
--- tromey.git.orig/gdb/python/python.c 2008-04-29 11:05:20.000000000 -0300
+++ tromey.git/gdb/python/python.c 2008-04-29 11:05:45.000000000 -0300
@@ -24,6 +24,7 @@
#include "cli/cli-decode.h"
#include "charset.h"
#include "top.h"
+#include "solib.h"
#include "exceptions.h"
#include "python-internal.h"
#include "version.h"
@@ -34,6 +35,7 @@ PyObject *gdb_module;
static PyObject *get_show_variable (PyObject *, PyObject *);
static PyObject *execute_gdb_command (PyObject *, PyObject *);
+static PyObject *gdbpy_solib_address (PyObject *, PyObject *);
void
@@ -56,6 +58,18 @@ demand_python ()
{ "get_breakpoints", gdbpy_get_breakpoints, METH_NOARGS,
"Return a tuple of all breakpoint objects" },
+ { "get_frames", gdbpy_get_frames, METH_NOARGS,
+ "Return a tuple of all frame objects" },
+ { "get_current_frame", gdbpy_get_current_frame, METH_NOARGS,
+ "Return the current frame object" },
+ { "get_selected_frame", gdbpy_get_selected_frame, METH_NOARGS,
+ "Return the selected frame object" },
+ { "frame_stop_reason_string", gdbpy_frame_stop_reason_string,
+ METH_VARARGS, "Return a string explaining unwind stop reason" },
+
+ { "solib_address", gdbpy_solib_address, METH_VARARGS,
+ "Return shared library holding a given address, or None." },
+
{NULL, NULL, 0, NULL}
};
@@ -70,6 +84,7 @@ demand_python ()
gdbpy_initialize_hooks ();
gdbpy_initialize_values ();
gdbpy_initialize_breakpoints ();
+ gdbpy_initialize_frames ();
gdbpy_initialize_commands ();
PyRun_SimpleString ("import gdb");
@@ -327,6 +342,29 @@ value_of_python (char *expr, int length)
return value;
}
+PyObject *
+gdbpy_solib_address (PyObject *self, PyObject *args)
+{
+ unsigned long long pc;
+ char *soname;
+ PyObject *str_obj;
+
+ if (!PyArg_ParseTuple (args, "K", &pc))
+ return NULL;
+
+ soname = solib_address (pc);
+ if (soname)
+ str_obj = PyString_Decode (soname, strlen (soname), host_charset (),
+ NULL /* FIXME */);
+ else
+ {
+ str_obj = Py_None;
+ Py_INCREF (Py_None);
+ }
+
+ return str_obj;
+}
+
\f
void
Index: tromey.git/gdb/stack.c
===================================================================
--- tromey.git.orig/gdb/stack.c 2008-04-29 10:57:39.000000000 -0300
+++ tromey.git/gdb/stack.c 2008-04-29 11:05:45.000000000 -0300
@@ -562,19 +562,16 @@ print_frame_info (struct frame_info *fra
gdb_flush (gdb_stdout);
}
-static void
-print_frame (struct frame_info *frame, int print_level,
- enum print_what print_what, int print_args,
- struct symtab_and_line sal)
+/* Attempt to obtain the FUNNAME and FUNLANG of the function corresponding
+ to FRAME. */
+void
+find_frame_funname (struct frame_info *frame, char **funname,
+ enum language *funlang)
{
struct symbol *func;
- char *funname = NULL;
- enum language funlang = language_unknown;
- struct ui_stream *stb;
- struct cleanup *old_chain, *list_chain;
- stb = ui_out_stream_new (uiout);
- old_chain = make_cleanup_ui_out_stream_delete (stb);
+ *funname = NULL;
+ *funlang = language_unknown;
func = find_pc_function (get_frame_address_in_block (frame));
if (func)
@@ -607,14 +604,14 @@ print_frame (struct frame_info *frame, i
/* We also don't know anything about the function besides
its address and name. */
func = 0;
- funname = DEPRECATED_SYMBOL_NAME (msymbol);
- funlang = SYMBOL_LANGUAGE (msymbol);
+ *funname = DEPRECATED_SYMBOL_NAME (msymbol);
+ *funlang = SYMBOL_LANGUAGE (msymbol);
}
else
{
- funname = DEPRECATED_SYMBOL_NAME (func);
- funlang = SYMBOL_LANGUAGE (func);
- if (funlang == language_cplus)
+ *funname = DEPRECATED_SYMBOL_NAME (func);
+ *funlang = SYMBOL_LANGUAGE (func);
+ if (*funlang == language_cplus)
{
/* It seems appropriate to use SYMBOL_PRINT_NAME() here,
to display the demangled name that we already have
@@ -629,12 +626,12 @@ print_frame (struct frame_info *frame, i
too. So we want to catch the failure (where DEMANGLED
is NULL below) here, while we still have our hands on
the function symbol.) */
- char *demangled = cplus_demangle (funname, DMGL_ANSI);
+ char *demangled = cplus_demangle (*funname, DMGL_ANSI);
if (demangled == NULL)
/* If the demangler fails, try the demangled name from
the symbol table. That'll have parameters, but
that's preferable to displaying a mangled name. */
- funname = SYMBOL_PRINT_NAME (func);
+ *funname = SYMBOL_PRINT_NAME (func);
else
xfree (demangled);
}
@@ -647,10 +644,26 @@ print_frame (struct frame_info *frame, i
if (msymbol != NULL)
{
- funname = DEPRECATED_SYMBOL_NAME (msymbol);
- funlang = SYMBOL_LANGUAGE (msymbol);
+ *funname = DEPRECATED_SYMBOL_NAME (msymbol);
+ *funlang = SYMBOL_LANGUAGE (msymbol);
}
}
+}
+
+static void
+print_frame (struct frame_info *frame, int print_level,
+ enum print_what print_what, int print_args,
+ struct symtab_and_line sal)
+{
+ char *funname = NULL;
+ enum language funlang = language_unknown;
+ struct ui_stream *stb;
+ struct cleanup *old_chain, *list_chain;
+
+ stb = ui_out_stream_new (uiout);
+ old_chain = make_cleanup_ui_out_stream_delete (stb);
+
+ find_frame_funname (frame, &funname, &funlang);
annotate_frame_begin (print_level ? frame_relative_level (frame) : 0,
get_frame_pc (frame));
@@ -685,7 +698,7 @@ print_frame (struct frame_info *frame, i
struct print_args_args args;
struct cleanup *args_list_chain;
args.frame = frame;
- args.func = func;
+ args.func = find_pc_function (get_frame_address_in_block (frame));
args.stream = gdb_stdout;
args_list_chain = make_cleanup_ui_out_list_begin_end (uiout, "args");
catch_errors (print_args_stub, &args, "", RETURN_MASK_ERROR);
Index: tromey.git/gdb/stack.h
===================================================================
--- tromey.git.orig/gdb/stack.h 2008-04-29 10:57:39.000000000 -0300
+++ tromey.git/gdb/stack.h 2008-04-29 11:05:45.000000000 -0300
@@ -22,4 +22,9 @@
void select_frame_command (char *level_exp, int from_tty);
+/* Attempt to obtain the FUNNAME and FUNLANG of the function corresponding
+ to FRAME. */
+void find_frame_funname (struct frame_info *frame, char **funname,
+ enum language *funlang);
+
#endif /* #ifndef STACK_H */
--
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* [RFC][patch 0/9] Python support in GDB
@ 2008-04-29 15:59 Thiago Jung Bauermann
2008-04-29 15:59 ` [RFC][patch 8/9] export symtab mechanism to Python Thiago Jung Bauermann
` (10 more replies)
0 siblings, 11 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-04-29 15:59 UTC (permalink / raw)
To: gdb-patches
Hi everybody,
This patch series adds Python scripting support to GDB, and exposes
some of its subsystems hopefully in a "pythonic" way. These patches
correspond to the contents of the git repository at gitorious.org,
rebased to apply cleanly on top of CVS HEAD as of 04/27.
Unfortunately I wasn't able to resolve the conflicts on the MI code
when I did the rebase, so I had to leave the MI part out. Sorry about
this, Vladimir. I pushed to gitorious the branch containig the HEAD
version I used as base for the patches (it is the patches-base branch),
so I believe it will be easy for you to generate the missing patch.
Let me know if you would like me to help with this.
Regarding the ChangeLogs, I tried to put the right authors for each
patch. If I didn't attribute blame correctly, please let me know.
We now would like your opinion and input, especially regarding what
is/should be exposed to Python and how. We implemented what we thought
was useful, and covered the use cases we had in mind. Please point out
if the current implementation doesn't cover your use case, or a use
case that would be useful to support.
And, of course, if you think this is all well and good and the greatest
thing since sliced bread, consider this an RFA. :-)
By the way, here is a Python implementation of the backtrace command
which shows its output in reverse (correct, actually!) order. It is
relatively complex so it shows well how Python scripting currently
looks like in GDB (but it doesn't use all of what is exposed):
python
import sys
def argument_symbol (sym):
sym_class = sym.get_class ()
if (sym_class == gdb.SYMBOL_LOC_ARG or
sym_class == gdb.SYMBOL_LOC_REF_ARG or
sym_class == gdb.SYMBOL_LOC_REGPARM or
sym_class == gdb.SYMBOL_LOC_REGPARM_ADDR or
sym_class == gdb.SYMBOL_LOC_LOCAL_ARG or
sym_class == gdb.SYMBOL_LOC_BASEREG_ARG or
sym_class == gdb.SYMBOL_LOC_COMPUTED_ARG):
return True
return False
def print_frame_args (func, frame):
if not func:
return
first = True
block = func.get_value ()
for sym in block:
if not argument_symbol (sym):
continue;
if len(sym.get_linkage_name ()):
nsym, is_field_of_this, symtab = gdb.lookup_symbol (sym.get_linkage_name (), block, gdb.SYMBOL_VAR_DOMAIN)
if nsym.get_class () != gdb.SYMBOL_LOC_REGISTER:
sym = nsym
if not first:
sys.stdout.write (", ")
sys.stdout.write (sym.get_print_name () + "=")
val = frame.read_var_value (sym)
if val:
val.common_print (None, False, 2, 0)
else:
sys.stdout.write ("???")
first = False
def gdb_rbacktrace ():
frames = gdb.get_frames ()
num_frames = len (frames)
if num_frames > 0 and frames[num_frames - 1].get_unwind_stop_reason() > gdb.FRAME_UNWIND_FIRST_ERROR:
print "Backtrace stopped: " + gdb.frame_stop_reason_string (frames[num_frames - 1].get_unwind_stop_reason())
for i in reversed (range (len (frames))):
sys.stdout.write ("#%-2d" % i)
if frames[i].get_type () == gdb.DUMMY_FRAME:
sys.stdout.write (" <function called from gdb>\n")
continue
elif frames[i].get_type () == gdb.SIGTRAMP_FRAME:
sys.stdout.write (" <signal handler called>\n")
continue
sal = frames[i].find_sal ()
pc = frames[i].get_pc ()
name = frames[i].get_name ()
if not name:
name = "??"
if pc != sal.get_pc () or not sal.symtab:
sys.stdout.write (" 0x%08x in" % pc)
sys.stdout.write (" " + name + " (")
func = gdb.find_pc_function (frames[i].get_address_in_block ())
print_frame_args (func, frames[i])
sys.stdout.write (")")
if sal.symtab and sal.symtab.get_filename ():
sys.stdout.write (" at " + sal.symtab.get_filename ())
sys.stdout.write (":" + str (sal.get_line ()))
if not frames[i].get_name () or (not sal.symtab or not sal.symtab.get_filename ()):
lib = gdb.solib_address (pc)
if lib:
sys.stdout.write (" from " + lib)
sys.stdout.write ("\n")
end
define rbt
python gdb_rbacktrace ()
end
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* [RFC][patch 7/9] export block and symbol mechanism to Python
2008-04-29 15:59 [RFC][patch 0/9] Python support in GDB Thiago Jung Bauermann
` (4 preceding siblings ...)
2008-04-29 15:59 ` [RFC][patch 5/9] permit GDB commands implemented in Python Thiago Jung Bauermann
@ 2008-04-29 16:08 ` Thiago Jung Bauermann
2008-04-29 18:11 ` [RFC][patch 4/9] export breakpoints " Thiago Jung Bauermann
` (4 subsequent siblings)
10 siblings, 0 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-04-29 16:08 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: python-block.diff --]
[-- Type: text/plain, Size: 21491 bytes --]
2008-04-29 Thiago Jung Bauermann <bauerman@br.ibm.com>
* Makefile.in (SUBDIR_PYTHON_OBS): Add python-block.o and
python-symbol.o.
(SUBDIR_PYTHON_SRCS): Add python/block.c and python/symbol.c.
(python-block.o, python-symbol.o): New targets.
* python/block.c: New file.
* python/python-internal.h (block_object_type,
symbol_object_type, symbol_to_symbol_object,
block_to_block_object, block_object_to_block,
symbol_object_to_symbol, gdbpy_initialize_symbols,
gdbpy_initialize_blocks): Declare.
* python/python.c (demand_python): Add find_pc_function function.
Call gdbpy_initialize_symbols and gdbpy_initialize_blocks.
(gdbpy_find_pc_function): New function.
* python/symbol.c: New file.
Index: tromey.git/gdb/Makefile.in
===================================================================
--- tromey.git.orig/gdb/Makefile.in 2008-04-29 11:05:45.000000000 -0300
+++ tromey.git/gdb/Makefile.in 2008-04-29 11:06:02.000000000 -0300
@@ -262,17 +262,21 @@ SUBDIR_TUI_CFLAGS= \
#
SUBDIR_PYTHON_OBS = \
python.o \
+ python-block.o \
python-breakpoint.o \
python-cmd.o \
python-frame.o \
python-hooks.o \
+ python-symbol.o \
python-value.o
SUBDIR_PYTHON_SRCS = \
python/python.c \
+ python/block.c \
python/breakpoint.c \
python/cmd.c \
python/frame.c \
python/hooks.c \
+ python/symbol.c \
python/value.c
SUBDIR_PYTHON_DEPS =
SUBDIR_PYTHON_LDFLAGS=
@@ -3421,6 +3425,10 @@ python.o: $(srcdir)/python/python.c $(de
$(command_h) $(libiberty_h) $(cli_decode_h) $(charset_h) $(top_h) \
$(exceptions_h) $(python_internal_h) $(version_h) $(solib_h)
$(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) $(srcdir)/python/python.c
+python-block.o: $(srcdir)/python/block.c $(defs_h) $(block_h) $(dictionary_h) \
+ $(symtab_h) $(python_h) $(python_internal_h)
+ $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
+ $(srcdir)/python/block.c -o python-block.o
python-breakpoint.o: $(srcdir)/python/breakpoint.c $(defs_h) $(python_h) \
$(value_h) $(exceptions_h) $(python_internal_h) $(charset_h) \
$(breakpoint_h) $(gdbcmd_h)
@@ -3440,6 +3448,10 @@ python-hooks.o: $(srcdir)/python/hooks.c
$(charset_h) $(gdb_events_h) $(python_h) $(python_internal_h)
$(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
$(srcdir)/python/hooks.c -o python-hooks.o
+python-symbol.o: $(srcdir)/python/symbol.c $(defs_h) $(symtab_h) $(python_h) \
+ $(python_internal_h)
+ $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
+ $(srcdir)/python/symbol.c -o python-symbol.o
python-value.o: $(srcdir)/python/value.c $(defs_h) $(exceptions_h) \
$(python_internal_h) $(value_h)
$(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
Index: tromey.git/gdb/python/block.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ tromey.git/gdb/python/block.c 2008-04-29 11:06:02.000000000 -0300
@@ -0,0 +1,258 @@
+/* Python interface to blocks.
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "block.h"
+#include "dictionary.h"
+#include "symtab.h"
+#include "python-internal.h"
+
+typedef struct {
+ PyObject_HEAD
+ struct block *block;
+} block_object;
+
+static PyObject *blpy_iter (PyObject *self);
+static PyObject *blpy_itersymbols (PyObject *self, PyObject *args);
+static PyObject *blpy_get_start (PyObject *self, PyObject *args);
+static PyObject *blpy_get_end (PyObject *self, PyObject *args);
+static PyObject *blpy_get_function (PyObject *self, PyObject *args);
+static PyObject *blpy_get_superblock (PyObject *self, PyObject *args);
+
+static PyMethodDef block_object_methods[] = {
+ { "itersymbols", blpy_itersymbols, METH_NOARGS,
+ "Return an iterator to walk through the symbols in the block." },
+ { "get_start", blpy_get_start, METH_NOARGS,
+ "Return the start address of this block." },
+ { "get_end", blpy_get_end, METH_NOARGS,
+ "Return the end address of this block." },
+ { "get_function", blpy_get_function, METH_NOARGS,
+ "Return the symbol that names this block, or None." },
+ { "get_superblock", blpy_get_end, METH_NOARGS,
+ "Return the block containing this block, or None." },
+ {NULL} /* Sentinel */
+};
+
+PyTypeObject block_object_type = {
+ PyObject_HEAD_INIT (NULL)
+ 0, /*ob_size*/
+ "gdb.Block", /*tp_name*/
+ sizeof (block_object), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/
+ "GDB block object", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ blpy_iter, /* tp_iter */
+ 0, /* tp_iternext */
+ block_object_methods /* tp_methods */
+};
+
+typedef struct {
+ PyObject_HEAD
+ struct dictionary *dict;
+ struct dict_iterator iter;
+ int initialized_p;
+} block_syms_iterator_object;
+
+static PyObject *blpy_block_syms_iter (PyObject *self);
+static PyObject *blpy_block_syms_iternext (PyObject *self);
+
+static PyTypeObject block_syms_iterator_object_type = {
+ PyObject_HEAD_INIT (NULL)
+ 0, /*ob_size*/
+ "gdb.BlockIterator", /*tp_name*/
+ sizeof (block_syms_iterator_object), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/
+ "GDB block syms iterator object", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ blpy_block_syms_iter, /* tp_iter */
+ blpy_block_syms_iternext, /* tp_iternext */
+ 0 /* tp_methods */
+};
+
+
+static PyObject *
+blpy_iter (PyObject *self)
+{
+ block_syms_iterator_object *block_iter_obj;
+
+ block_iter_obj = PyObject_New (block_syms_iterator_object,
+ &block_syms_iterator_object_type);
+ if (block_iter_obj == NULL)
+ {
+ PyErr_SetString (PyExc_MemoryError,
+ "Could not allocate iterator object.");
+ return NULL;
+ }
+
+ block_iter_obj->dict = BLOCK_DICT (((block_object *) self)->block);
+ block_iter_obj->initialized_p = 0;
+
+ return (PyObject *) block_iter_obj;
+}
+
+static PyObject *
+blpy_itersymbols (PyObject *self, PyObject *args)
+{
+ return blpy_iter (self);
+}
+
+static PyObject *
+blpy_get_start (PyObject *self, PyObject *args)
+{
+ block_object *self_block = (block_object *) self;
+
+ return PyLong_FromUnsignedLongLong (BLOCK_START (self_block->block));
+}
+
+static PyObject *
+blpy_get_end (PyObject *self, PyObject *args)
+{
+ block_object *self_block = (block_object *) self;
+
+ return PyLong_FromUnsignedLongLong (BLOCK_END (self_block->block));
+}
+
+static PyObject *
+blpy_get_function (PyObject *self, PyObject *args)
+{
+ block_object *self_block = (block_object *) self;
+ struct symbol *sym;
+
+ sym = BLOCK_FUNCTION (self_block->block);
+ if (sym)
+ return symbol_to_symbol_object (sym);
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+blpy_get_superblock (PyObject *self, PyObject *args)
+{
+ block_object *self_block = (block_object *) self;
+ struct block *block;
+
+ block = BLOCK_SUPERBLOCK (self_block->block);
+ if (block)
+ return block_to_block_object (block);
+
+ Py_RETURN_NONE;
+}
+
+PyObject *
+block_to_block_object (struct block *block)
+{
+ block_object *block_obj;
+
+ block_obj = PyObject_New (block_object, &block_object_type);
+ if (block_obj == NULL)
+ {
+ PyErr_SetString (PyExc_MemoryError, "Could not allocate block object.");
+ return NULL;
+ }
+
+ block_obj->block = block;
+
+ return (PyObject *) block_obj;
+}
+
+struct block *
+block_object_to_block (PyObject *obj)
+{
+ return ((block_object *) obj)->block;
+}
+
+static PyObject *
+blpy_block_syms_iter (PyObject *self)
+{
+ return self;
+}
+
+static PyObject *
+blpy_block_syms_iternext (PyObject *self)
+{
+ block_syms_iterator_object *iter_obj = (block_syms_iterator_object *) self;
+ struct symbol *sym;
+
+ if (!iter_obj->initialized_p)
+ {
+ sym = dict_iterator_first (iter_obj->dict, &(iter_obj->iter));
+ iter_obj->initialized_p = 1;
+ }
+ else
+ sym = dict_iterator_next (&(iter_obj->iter));
+
+ return (sym == NULL)? NULL : symbol_to_symbol_object (sym);
+}
+
+void
+gdbpy_initialize_blocks (void)
+{
+ block_object_type.tp_new = PyType_GenericNew;
+ if (PyType_Ready (&block_object_type) < 0)
+ return;
+
+ block_syms_iterator_object_type.tp_new = PyType_GenericNew;
+ if (PyType_Ready (&block_syms_iterator_object_type) < 0)
+ return;
+
+ Py_INCREF (&block_object_type);
+ PyModule_AddObject (gdb_module, "Block", (PyObject *) &block_object_type);
+
+ Py_INCREF (&block_syms_iterator_object_type);
+ PyModule_AddObject (gdb_module, "BlockIterator",
+ (PyObject *) &block_syms_iterator_object_type);
+}
Index: tromey.git/gdb/python/python-internal.h
===================================================================
--- tromey.git.orig/gdb/python/python-internal.h 2008-04-29 11:05:45.000000000 -0300
+++ tromey.git/gdb/python/python-internal.h 2008-04-29 11:06:02.000000000 -0300
@@ -27,7 +27,9 @@
#endif
extern PyObject *gdb_module;
+extern PyTypeObject block_object_type;
extern PyTypeObject value_object_type;
+extern PyTypeObject symbol_object_type;
PyObject *gdbpy_make_value_from_int (PyObject *self, PyObject *args);
PyObject *gdbpy_get_value_from_history (PyObject *self, PyObject *args);
@@ -38,9 +40,13 @@ PyObject *gdbpy_frame_stop_reason_string
PyObject *gdbpy_get_selected_frame (PyObject *self, PyObject *args);
PyObject *variable_to_python (struct cmd_list_element *);
+PyObject *symbol_to_symbol_object (struct symbol *sym);
+PyObject *block_to_block_object (struct block *block);
PyObject *value_to_value_object (struct value *v);
PyObject *gdb_owned_value_to_value_object (struct value *v);
+struct block *block_object_to_block (PyObject *obj);
+struct symbol *symbol_object_to_symbol (PyObject *obj);
struct value *value_object_to_value (PyObject *self);
PyObject *gdbpy_get_hook_function (const char *);
@@ -50,6 +56,8 @@ void gdbpy_initialize_hooks (void);
void gdbpy_initialize_breakpoints (void);
void gdbpy_initialize_frames (void);
void gdbpy_initialize_commands (void);
+void gdbpy_initialize_symbols (void);
+void gdbpy_initialize_blocks (void);
/* Use this after a TRY_EXCEPT to throw the appropriate Python
exception. FIXME: throw different errors depending on
Index: tromey.git/gdb/python/python.c
===================================================================
--- tromey.git.orig/gdb/python/python.c 2008-04-29 11:05:45.000000000 -0300
+++ tromey.git/gdb/python/python.c 2008-04-29 11:06:02.000000000 -0300
@@ -36,6 +36,7 @@ PyObject *gdb_module;
static PyObject *get_show_variable (PyObject *, PyObject *);
static PyObject *execute_gdb_command (PyObject *, PyObject *);
static PyObject *gdbpy_solib_address (PyObject *, PyObject *);
+static PyObject *gdbpy_find_pc_function (PyObject *, PyObject *);
void
@@ -70,6 +71,9 @@ demand_python ()
{ "solib_address", gdbpy_solib_address, METH_VARARGS,
"Return shared library holding a given address, or None." },
+ { "find_pc_function", gdbpy_find_pc_function, METH_VARARGS,
+ "Return the function containing the given pc value, or None." },
+
{NULL, NULL, 0, NULL}
};
@@ -86,6 +90,8 @@ demand_python ()
gdbpy_initialize_breakpoints ();
gdbpy_initialize_frames ();
gdbpy_initialize_commands ();
+ gdbpy_initialize_symbols ();
+ gdbpy_initialize_blocks ();
PyRun_SimpleString ("import gdb");
@@ -365,6 +371,23 @@ gdbpy_solib_address (PyObject *self, PyO
return str_obj;
}
+PyObject *
+gdbpy_find_pc_function (PyObject *self, PyObject *args)
+{
+ unsigned long long pc;
+ struct symbol *sym;
+ PyObject *sym_obj;
+
+ if (!PyArg_ParseTuple (args, "K", &pc))
+ return NULL;
+
+ sym = find_pc_function (pc);
+ if (sym)
+ return symbol_to_symbol_object (sym);
+
+ Py_RETURN_NONE;
+}
+
\f
void
Index: tromey.git/gdb/python/symbol.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ tromey.git/gdb/python/symbol.c 2008-04-29 11:06:02.000000000 -0300
@@ -0,0 +1,224 @@
+/* Python interface to symbols.
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "python-internal.h"
+
+typedef struct {
+ PyObject_HEAD
+ struct symbol *symbol;
+} symbol_object;
+
+static PyObject *sympy_str (PyObject *self);
+static PyObject *sympy_get_value (PyObject *self, PyObject *args);
+static PyObject *sympy_get_natural_name (PyObject *self, PyObject *args);
+static PyObject *sympy_get_linkage_name (PyObject *self, PyObject *args);
+static PyObject *sympy_get_print_name (PyObject *self, PyObject *args);
+static PyObject *sympy_get_class (PyObject *self, PyObject *args);
+
+static PyMethodDef symbol_object_methods[] = {
+ { "get_value", sympy_get_value, METH_NOARGS,
+ "Return the value of the symbol." },
+ { "get_natural_name", sympy_get_natural_name, METH_NOARGS,
+ "Return the \"natural\" name of the symbol." },
+ { "get_linkage_name", sympy_get_linkage_name, METH_NOARGS,
+ "Return the name of the symbol as used by the linker." },
+ { "get_print_name", sympy_get_print_name, METH_NOARGS,
+ "Return the name of the symbol in a form suitable for output." },
+ { "get_class", sympy_get_class, METH_NOARGS,
+ "Return the class of the symbol." },
+ {NULL} /* Sentinel */
+};
+
+PyTypeObject symbol_object_type = {
+ PyObject_HEAD_INIT (NULL)
+ 0, /*ob_size*/
+ "gdb.Symbol", /*tp_name*/
+ sizeof (symbol_object), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ sympy_str, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "GDB symbol object", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ symbol_object_methods /* tp_methods */
+};
+
+
+static PyObject *
+sympy_str (PyObject *self)
+{
+ int ret;
+ char *s;
+ PyObject *result;
+
+ ret = asprintf (&s, "symbol for %s",
+ SYMBOL_PRINT_NAME (((symbol_object *) self)->symbol));
+ if (ret < 0)
+ Py_RETURN_NONE;
+
+ result = PyString_FromString (s);
+ xfree (s);
+
+ return result;
+}
+
+static PyObject *
+sympy_get_value (PyObject *self, PyObject *args)
+{
+ symbol_object *self_sym = (symbol_object *) self;
+
+ switch (SYMBOL_CLASS (self_sym->symbol))
+ {
+ case LOC_BLOCK:
+ return block_to_block_object (SYMBOL_BLOCK_VALUE (self_sym->symbol));
+ }
+
+ PyErr_SetString (PyExc_NotImplementedError,
+ "Symbol type not yet supported in Python scripts.");
+ return NULL;
+}
+
+static PyObject *
+sympy_get_natural_name (PyObject *self, PyObject *args)
+{
+ symbol_object *self_sym = (symbol_object *) self;
+
+ return PyString_FromString (SYMBOL_NATURAL_NAME (self_sym->symbol));
+}
+
+static PyObject *
+sympy_get_linkage_name (PyObject *self, PyObject *args)
+{
+ symbol_object *self_sym = (symbol_object *) self;
+
+ return PyString_FromString (SYMBOL_LINKAGE_NAME (self_sym->symbol));
+}
+
+static PyObject *
+sympy_get_print_name (PyObject *self, PyObject *args)
+{
+ symbol_object *self_sym = (symbol_object *) self;
+
+ return PyString_FromString (SYMBOL_PRINT_NAME (self_sym->symbol));
+}
+
+static PyObject *
+sympy_get_class (PyObject *self, PyObject *args)
+{
+ symbol_object *self_sym = (symbol_object *) self;
+
+ return PyInt_FromLong (SYMBOL_CLASS (self_sym->symbol));
+}
+
+PyObject *
+symbol_to_symbol_object (struct symbol *sym)
+{
+ symbol_object *sym_obj;
+
+ sym_obj = PyObject_New (symbol_object, &symbol_object_type);
+ if (sym_obj == NULL)
+ {
+ PyErr_SetString (PyExc_MemoryError, "Could not allocate symbol object.");
+ return NULL;
+ }
+
+ sym_obj->symbol = sym;
+
+ return (PyObject *) sym_obj;
+}
+
+struct symbol *
+symbol_object_to_symbol (PyObject *obj)
+{
+ return ((symbol_object *) obj)->symbol;
+}
+
+void
+gdbpy_initialize_symbols (void)
+{
+ symbol_object_type.tp_new = PyType_GenericNew;
+ if (PyType_Ready (&symbol_object_type) < 0)
+ return;
+
+ /* FIXME: These would probably be best exposed as class attributes of Symbol,
+ but I don't know how to do it except by messing with the type's dictionary.
+ That seems too messy. */
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_UNDEF", LOC_UNDEF);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_CONST", LOC_CONST);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_STATIC", LOC_STATIC);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_REGISTER", LOC_REGISTER);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_ARG", LOC_ARG);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_REF_ARG", LOC_REF_ARG);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_REGPARM", LOC_REGPARM);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_REGPARM_ADDR",
+ LOC_REGPARM_ADDR);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_LOCAL", LOC_LOCAL);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_TYPEDEF", LOC_TYPEDEF);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_LABEL", LOC_LABEL);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_BLOCK", LOC_BLOCK);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_CONST_BYTES",
+ LOC_CONST_BYTES);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_LOCAL_ARG", LOC_LOCAL_ARG);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_BASEREG", LOC_BASEREG);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_BASEREG_ARG",
+ LOC_BASEREG_ARG);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_UNRESOLVED", LOC_UNRESOLVED);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_HP_THREAD_LOCAL_STATIC",
+ LOC_HP_THREAD_LOCAL_STATIC);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_OPTIMIZED_OUT",
+ LOC_OPTIMIZED_OUT);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_INDIRECT", LOC_INDIRECT);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_COMPUTED", LOC_COMPUTED);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_COMPUTED_ARG",
+ LOC_COMPUTED_ARG);
+
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_UNDEF_DOMAIN", UNDEF_DOMAIN);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_VAR_DOMAIN", VAR_DOMAIN);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_STRUCT_DOMAIN", STRUCT_DOMAIN);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_LABEL_DOMAIN", LABEL_DOMAIN);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_VARIABLES_DOMAIN",
+ VARIABLES_DOMAIN);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_FUNCTIONS_DOMAIN",
+ FUNCTIONS_DOMAIN);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_TYPES_DOMAIN", TYPES_DOMAIN);
+ PyModule_AddIntConstant (gdb_module, "SYMBOL_METHODS_DOMAIN", METHODS_DOMAIN);
+
+ Py_INCREF (&symbol_object_type);
+ PyModule_AddObject (gdb_module, "Symbol", (PyObject *) &symbol_object_type);
+}
--
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* [RFC][patch 4/9] export breakpoints to Python
2008-04-29 15:59 [RFC][patch 0/9] Python support in GDB Thiago Jung Bauermann
` (5 preceding siblings ...)
2008-04-29 16:08 ` [RFC][patch 7/9] export block and symbol mechanism to Python Thiago Jung Bauermann
@ 2008-04-29 18:11 ` Thiago Jung Bauermann
2008-04-29 18:15 ` [RFC][patch 1/9] initial Python support Thiago Jung Bauermann
` (3 subsequent siblings)
10 siblings, 0 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-04-29 18:11 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: python-breakpoints.diff --]
[-- Type: text/plain, Size: 15709 bytes --]
2008-04-29 Tom Tromey <tromey@redhat.com>
* Makefile.in (SUBDIR_PYTHON_OBS): Add python-breakpoint.o.
(SUBDIR_PYTHON_SRCS): Add python/breakpoint.c.
(python-breakpoint.o): New target.
* python/breakpoint.c: New file.
* python/hooks.c (gdbpy_initialize_hooks): Register breakpoint
event callback functions.
* python/python-internal.h (gdbpy_get_breakpoints,
gdbpy_initialize_breakpoints, gdbpy_breakpoint_created,
gdbpy_breakpoint_deleted): Declare.
* python/python.c (demand_python): Add "get_breakpoints"
function. Call gdbpy_initialize_breakpoints.
Index: tromey.git/gdb/Makefile.in
===================================================================
--- tromey.git.orig/gdb/Makefile.in 2008-04-29 11:05:09.000000000 -0300
+++ tromey.git/gdb/Makefile.in 2008-04-29 11:05:15.000000000 -0300
@@ -262,10 +262,12 @@ SUBDIR_TUI_CFLAGS= \
#
SUBDIR_PYTHON_OBS = \
python.o \
+ python-breakpoint.o \
python-hooks.o \
python-value.o
SUBDIR_PYTHON_SRCS = \
python/python.c \
+ python/breakpoint.c \
python/hooks.c \
python/value.c
SUBDIR_PYTHON_DEPS =
@@ -3415,6 +3417,11 @@ python.o: $(srcdir)/python/python.c $(de
$(command_h) $(libiberty_h) $(cli_decode_h) $(charset_h) $(top_h) \
$(exceptions_h) $(python_internal_h) $(version_h)
$(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) $(srcdir)/python/python.c
+python-breakpoint.o: $(srcdir)/python/breakpoint.c $(defs_h) $(python_h) \
+ $(value_h) $(exceptions_h) $(python_internal_h) $(charset_h) \
+ $(breakpoint_h) $(gdbcmd_h)
+ $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
+ $(srcdir)/python/breakpoint.c -o python-breakpoint.o
python-hooks.o: $(srcdir)/python/hooks.c $(defs_h) $(cli_decode_h) \
$(charset_h) $(gdb_events_h) $(python_h) $(python_internal_h)
$(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
Index: tromey.git/gdb/python/breakpoint.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ tromey.git/gdb/python/breakpoint.c 2008-04-29 11:05:15.000000000 -0300
@@ -0,0 +1,408 @@
+/* Python interface to breakpoints
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "value.h"
+#include "exceptions.h"
+#include "python-internal.h"
+#include "charset.h"
+#include "breakpoint.h"
+#include "gdbcmd.h"
+
+
+/* From breakpoint.c. */
+extern struct breakpoint *breakpoint_chain;
+
+
+typedef struct breakpoint_object breakpoint_object;
+
+static PyObject *bppy_is_valid (PyObject *, PyObject *);
+static PyObject *bppy_is_enabled (PyObject *, PyObject *);
+static PyObject *bppy_is_silent (PyObject *, PyObject *);
+static PyObject *bppy_set_enabled (PyObject *, PyObject *);
+static PyObject *bppy_set_silent (PyObject *, PyObject *);
+static PyObject *bppy_get_location (PyObject *, PyObject *);
+static PyObject *bppy_get_condition (PyObject *, PyObject *);
+static PyObject *bppy_get_commands (PyObject *, PyObject *);
+
+
+/* A dynamically allocated vector of breakpoint objects. Each
+ breakpoint has a number. A breakpoint is valid if its slot in this
+ vector is non-null. When a breakpoint is deleted, we drop our
+ reference to it and zero its slot; this is how we let the Python
+ object have a lifetime which is independent from that of the gdb
+ breakpoint. */
+static breakpoint_object **bppy_breakpoints;
+
+/* Number of slots in bppy_breakpoints. */
+static int bppy_slots;
+
+/* Number of live breakpoints. */
+static int bppy_live;
+
+/* Variables used to pass information between the Breakpoint
+ constructor and the breakpoint-created hook function. */
+static breakpoint_object *bppy_pending_object;
+
+struct breakpoint_object
+{
+ PyObject_HEAD
+
+ /* The breakpoint number according to gdb. */
+ int number;
+
+ /* The gdb breakpoint object, or NULL if the breakpoint has been
+ deleted. */
+ struct breakpoint *bp;
+};
+
+#define BPPY_VALID_P(Num) \
+ ((Num) >= 0 \
+ && (Num) < bppy_slots \
+ && bppy_breakpoints[Num] != NULL)
+
+#define BPPY_REQUIRE_VALID(Breakpoint) \
+ do { \
+ if (! BPPY_VALID_P ((Breakpoint)->number)) \
+ return PyErr_Format (PyExc_RuntimeError, "breakpoint %d is invalid", \
+ (Breakpoint)->number); \
+ } while (0)
+
+static PyMethodDef breakpoint_object_methods[] =
+{
+ { "is_valid", bppy_is_valid, METH_NOARGS,
+ "Return true if this breakpoint is valid, false if not." },
+ { "is_enabled", bppy_is_enabled, METH_NOARGS,
+ "Return true if this breakpoint is enabled, false if disabled." },
+ { "is_silent", bppy_is_silent, METH_NOARGS,
+ "Return true if this breakpoint is silent, false if verbose." },
+
+ { "set_enabled", bppy_set_enabled, METH_O,
+ "Enable or disable this breakpoint" },
+ { "set_silent", bppy_set_silent, METH_O,
+ "Make this breakpoint quiet or verbose" },
+
+ { "get_location", bppy_get_location, METH_NOARGS,
+ "Return the location of this breakpoint, as specified by the user"},
+ { "get_condition", bppy_get_condition, METH_NOARGS,
+ "Return the condition of this breakpoint, as specified by the user.\n\
+Returns None if no condition set."},
+ { "get_commands", bppy_get_commands, METH_NOARGS,
+ "Return the commands of this breakpoint, as specified by the user"},
+
+ { 0 }
+};
+
+static PyTypeObject breakpoint_object_type =
+{
+ PyObject_HEAD_INIT (NULL)
+ 0, /*ob_size*/
+ "gdb.Breakpoint", /*tp_name*/
+ sizeof (breakpoint_object), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "GDB breakpoint object", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ breakpoint_object_methods /* tp_methods */
+};
+
+static PyObject *
+bppy_is_valid (PyObject *self, PyObject *args)
+{
+ if (((breakpoint_object *) self)->bp)
+ Py_RETURN_TRUE;
+ Py_RETURN_FALSE;
+}
+
+static PyObject *
+bppy_is_enabled (PyObject *self, PyObject *args)
+{
+ if (! ((breakpoint_object *) self)->bp)
+ Py_RETURN_FALSE;
+ /* Not clear what we really want here. */
+ if (((breakpoint_object *) self)->bp->enable_state == bp_enabled)
+ Py_RETURN_TRUE;
+ Py_RETURN_FALSE;
+}
+
+static PyObject *
+bppy_is_silent (PyObject *self, PyObject *args)
+{
+ BPPY_REQUIRE_VALID ((breakpoint_object *) self);
+ if (((breakpoint_object *) self)->bp->silent)
+ Py_RETURN_TRUE;
+ Py_RETURN_FALSE;
+}
+
+static PyObject *
+bppy_set_enabled (PyObject *self, PyObject *newvalue)
+{
+ breakpoint_object *self_bp = (breakpoint_object *) self;
+
+ BPPY_REQUIRE_VALID (self_bp);
+ if (! PyBool_Check (newvalue))
+ return PyErr_Format (PyExc_RuntimeError, "argument must be boolean");
+
+ if (newvalue == Py_True)
+ enable_breakpoint (self_bp->bp);
+ else
+ disable_breakpoint (self_bp->bp);
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+bppy_set_silent (PyObject *self, PyObject *newvalue)
+{
+ breakpoint_object *self_bp = (breakpoint_object *) self;
+
+ BPPY_REQUIRE_VALID (self_bp);
+ if (! PyBool_Check (newvalue))
+ return PyErr_Format (PyExc_RuntimeError, "argument must be boolean");
+
+ self_bp->bp->silent = (newvalue == Py_True);
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+bppy_get_location (PyObject *self, PyObject *args)
+{
+ char *str;
+
+ BPPY_REQUIRE_VALID ((breakpoint_object *) self);
+ str = ((breakpoint_object *) self)->bp->addr_string;
+ /* FIXME: watchpoints? tracepoints? */
+ if (! str)
+ str = "";
+ return PyString_Decode (str, strlen (str), host_charset (),
+ NULL /* FIXME */);
+}
+
+static PyObject *
+bppy_get_condition (PyObject *self, PyObject *args)
+{
+ char *str;
+ BPPY_REQUIRE_VALID ((breakpoint_object *) self);
+
+ str = ((breakpoint_object *) self)->bp->cond_string;
+ if (! str)
+ Py_RETURN_NONE;
+ return PyString_Decode (str, strlen (str), host_charset (),
+ NULL /* FIXME */);
+}
+
+static PyObject *
+bppy_get_commands (PyObject *self, PyObject *args)
+{
+ breakpoint_object *self_bp = (breakpoint_object *) self;
+ long length;
+ volatile struct gdb_exception except;
+ struct ui_file *string_file;
+ struct cleanup *chain;
+ PyObject *result;
+ char *cmdstr;
+
+ BPPY_REQUIRE_VALID (self_bp);
+
+ if (! self_bp->bp->commands)
+ Py_RETURN_NONE;
+
+ string_file = mem_fileopen ();
+ chain = make_cleanup_ui_file_delete (string_file);
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ /* FIXME: this can fail. Maybe we need to be making a new
+ ui_out object here? */
+ ui_out_redirect (uiout, string_file);
+ print_command_lines (uiout, self_bp->bp->commands, 0);
+ ui_out_redirect (uiout, NULL);
+ }
+ cmdstr = ui_file_xstrdup (string_file, &length);
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ result = PyString_Decode (cmdstr, strlen (cmdstr), host_charset (),
+ NULL /* FIXME */);
+ do_cleanups (chain);
+ xfree (cmdstr);
+ return result;
+}
+
+static PyObject *
+bppy_new (PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
+{
+ PyObject *result;
+ char *spec;
+ volatile struct gdb_exception except;
+
+ /* FIXME: allow condition, thread, temporary, ... ? */
+ if (! PyArg_ParseTuple (args, "s", &spec))
+ return NULL;
+ result = subtype->tp_alloc (subtype, 0);
+ if (! result)
+ return NULL;
+ bppy_pending_object = (breakpoint_object *) result;
+ bppy_pending_object->number = -1;
+ bppy_pending_object->bp = NULL;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ set_breakpoint (spec, NULL, 0, 0, -1, 0, AUTO_BOOLEAN_TRUE);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ BPPY_REQUIRE_VALID ((breakpoint_object *) result);
+ return result;
+}
+
+\f
+
+/* Static function to return a tuple holding all breakpoints. */
+
+PyObject *
+gdbpy_get_breakpoints (PyObject *self, PyObject *args)
+{
+ PyObject *result;
+
+ if (bppy_live == 0)
+ Py_RETURN_NONE;
+
+ result = PyTuple_New (bppy_live);
+ if (result)
+ {
+ int i, out = 0;
+ for (i = 0; out < bppy_live; ++i)
+ {
+ if (! bppy_breakpoints[i])
+ continue;
+ Py_INCREF (bppy_breakpoints[i]);
+ PyTuple_SetItem (result, out, (PyObject *) bppy_breakpoints[i]);
+ ++out;
+ }
+ }
+ return result;
+}
+
+\f
+
+/* Event callback functions. */
+
+void
+gdbpy_breakpoint_created (int num)
+{
+ breakpoint_object *newbp;
+ struct breakpoint *bp;
+
+ if (num < 0)
+ return;
+
+ for (bp = breakpoint_chain; bp; bp = bp->next)
+ if (bp->number == num)
+ break;
+ if (! bp)
+ return;
+
+ if (num >= bppy_slots)
+ {
+ int old = bppy_slots;
+ bppy_slots = bppy_slots * 2 + 10;
+ bppy_breakpoints
+ = (breakpoint_object **) xrealloc (bppy_breakpoints,
+ (bppy_slots
+ * sizeof (breakpoint_object *)));
+ memset (&bppy_breakpoints[old], 0,
+ (bppy_slots - old) * sizeof (PyObject *));
+ }
+
+ ++bppy_live;
+
+ if (bppy_pending_object)
+ {
+ newbp = bppy_pending_object;
+ bppy_pending_object = NULL;
+ }
+ else
+ newbp = PyObject_New (breakpoint_object, &breakpoint_object_type);
+ if (newbp)
+ {
+ PyObject *hookfn;
+
+ newbp->number = num;
+ newbp->bp = bp;
+ bppy_breakpoints[num] = newbp;
+
+ hookfn = gdbpy_get_hook_function ("new_breakpoint");
+ if (hookfn)
+ {
+ /* FIXME: refc? */
+ PyObject_CallFunctionObjArgs (hookfn, newbp, NULL);
+ }
+ }
+
+ if (PyErr_Occurred ())
+ {
+ /* FIXME -- what to do? */
+ PyErr_Print ();
+ }
+}
+
+void
+gdbpy_breakpoint_deleted (int num)
+{
+ if (BPPY_VALID_P (num))
+ {
+ bppy_breakpoints[num]->bp = NULL;
+ Py_DECREF (bppy_breakpoints[num]);
+ bppy_breakpoints[num] = NULL;
+ --bppy_live;
+ }
+}
+
+void
+gdbpy_initialize_breakpoints (void)
+{
+ breakpoint_object_type.tp_new = bppy_new;
+ if (PyType_Ready (&breakpoint_object_type) < 0)
+ return;
+
+ Py_INCREF (&breakpoint_object_type);
+ PyModule_AddObject (gdb_module, "Breakpoint",
+ (PyObject *) &breakpoint_object_type);
+}
Index: tromey.git/gdb/python/hooks.c
===================================================================
--- tromey.git.orig/gdb/python/hooks.c 2008-04-29 11:05:09.000000000 -0300
+++ tromey.git/gdb/python/hooks.c 2008-04-29 11:05:15.000000000 -0300
@@ -112,6 +112,8 @@ void
gdbpy_initialize_hooks (void)
{
handlers.architecture_changed = gdbpy_architecture_changed;
+ handlers.breakpoint_create = gdbpy_breakpoint_created;
+ handlers.breakpoint_delete = gdbpy_breakpoint_deleted;
deprecated_set_gdb_event_hooks (&handlers);
deprecated_set_hook = gdbpy_set_hook;
Index: tromey.git/gdb/python/python-internal.h
===================================================================
--- tromey.git.orig/gdb/python/python-internal.h 2008-04-29 11:05:09.000000000 -0300
+++ tromey.git/gdb/python/python-internal.h 2008-04-29 11:05:15.000000000 -0300
@@ -31,6 +31,7 @@ extern PyTypeObject value_object_type;
PyObject *gdbpy_make_value_from_int (PyObject *self, PyObject *args);
PyObject *gdbpy_get_value_from_history (PyObject *self, PyObject *args);
+PyObject *gdbpy_get_breakpoints (PyObject *, PyObject *);
PyObject *variable_to_python (struct cmd_list_element *);
PyObject *value_to_value_object (struct value *v);
@@ -42,6 +43,7 @@ PyObject *gdbpy_get_hook_function (const
void gdbpy_initialize_values (void);
void gdbpy_initialize_hooks (void);
+void gdbpy_initialize_breakpoints (void);
/* Use this after a TRY_EXCEPT to throw the appropriate Python
exception. FIXME: throw different errors depending on
@@ -54,4 +56,8 @@ void gdbpy_initialize_hooks (void);
"%s", Exception.message); \
} while (0)
+/* Breakpoint hook functions. */
+void gdbpy_breakpoint_created (int);
+void gdbpy_breakpoint_deleted (int);
+
#endif /* GDB_PYTHON_INTERNAL_H */
Index: tromey.git/gdb/python/python.c
===================================================================
--- tromey.git.orig/gdb/python/python.c 2008-04-29 11:05:09.000000000 -0300
+++ tromey.git/gdb/python/python.c 2008-04-29 11:05:15.000000000 -0300
@@ -53,6 +53,9 @@ demand_python ()
{ "show", get_show_variable, METH_VARARGS,
"Return a gdb setting's value" },
+ { "get_breakpoints", gdbpy_get_breakpoints, METH_NOARGS,
+ "Return a tuple of all breakpoint objects" },
+
{NULL, NULL, 0, NULL}
};
@@ -66,6 +69,7 @@ demand_python ()
gdbpy_initialize_hooks ();
gdbpy_initialize_values ();
+ gdbpy_initialize_breakpoints ();
PyRun_SimpleString ("import gdb");
--
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* [RFC][patch 1/9] initial Python support
2008-04-29 15:59 [RFC][patch 0/9] Python support in GDB Thiago Jung Bauermann
` (6 preceding siblings ...)
2008-04-29 18:11 ` [RFC][patch 4/9] export breakpoints " Thiago Jung Bauermann
@ 2008-04-29 18:15 ` Thiago Jung Bauermann
2008-05-05 8:12 ` Thiago Jung Bauermann
2008-05-29 0:29 ` Daniel Jacobowitz
2008-04-29 18:17 ` [RFC][patch 2/9] export values mechanism to Python Thiago Jung Bauermann
` (2 subsequent siblings)
10 siblings, 2 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-04-29 18:15 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: python-basic.diff --]
[-- Type: text/plain, Size: 37752 bytes --]
This patch adds the initial code for Python scripting support in GDB,
and adapts the build system accordingly.
The Python support included in this patch was explained by Tromey thusly:
> You can evaluate python, either as a block, as a one-liner, or as an
> expression. I cleaned up the code so that it works properly in other
> block structures, like commands or loops. The expression evaluation
> code makes an attempt to convert python values to gdb values as
> appropriate (strings, ints, and floating-point types). Some contrived
> examples...
>
> Block form:
>
> python
> print 23
> end
>
> One liner:
>
> python print 23
>
> Expression:
>
> break foo if $(23 > 5)
>
> There's also a Python command to pass any string to the gdb CLI, and
> another one to get the value of any "set/show" variable.
Regarding changes to the building system, the patch adds the
--with-python option to configure. With the option set to yes or auto
(which is the default), configure will first search for -lpython2.5 and
failing that, -lpython2.4. If no Python library is found, or if the
--without-python option is given, GDB will be compiled without Python
scripting support.
There are two caveats with the configure.ac changes: one is that they
trigger a bug in autoconf 2.59 when library names contain a dot
(e.g., libpython2.5). I regenerated the configure script using
autoconf 2.61, but the proper way to fix this at the moment (since we
must use version 2.59) is to backport the fix using the
config/override.m4 mechanism. I didn't look into that yet.
The other caveat is that I had trouble with gnulib configure script
when using this patch. I didn't investigate the issue yet, and to test
this code I removed gnulib from the compilation. Maybe I didn't
regenerate the configure scripts properly.
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
2008-04-29 Vladimir Prus <vladimir@codesourcery.com>
Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
* Makefile.in (LIBPYTHON, SUBDIR_PYTHON_OBS, SUBDIR_PYTHON_SRCS,
SUBDIR_PYTHON_DEPS, SUBDIR_PYTHON_LDFLAGS, SUBDIR_PYTHON_CFLAGS,
PYTHON_CFLAGS): New.
(CLIBS): Add dependency on Python library.
(python_h, python_internal_h): New.
(cli-script.o): Depend on python.h
(python.o): New.
* ax-gdb.c (gen_expr): Handle OP_INTERNALFUNC.
* c-exp.y (yylex): Recognize $(...).
* cli/cli-script.c (print_command_lines): Handle python_control.
(execute_control_command): Handle python_control.
(read_next_line): Add new special_processing parameter. Update all
callers. Handle "python".
(recurse_read_control_structure): Handle python_control.
(read_command_lines): Add new special_processing parameter. Update
all callers. Handle python_control.
Include python.h.
* configure.ac: Add --with-python.
* defs.h (enum command_control_type) <python_control>: New
constant.
* eval.c (evaluate_subexp_standard): Handle OP_INTERNALFUNC.
* expprint.c (print_subexp_standard): Handle OP_INTERNALFUNC.
(op_name_standard): Likewise.
(dump_subexp_body_standard): Likewise.
* expression.h (enum exp_opcode): Add OP_INTERNALFUNC.
* parse.c (write_dollar_funcall): New function.
(operator_length_standard): Handle OP_INTERNALFUNC.
* parser-defs.h (write_dollar_funcall): Declare.
* python/python-internal.h: New file.
* python/python.c: New file.
* python/python.h: New file.
* value.h (value_of_python): Declare.
Index: tromey.git/gdb/Makefile.in
===================================================================
--- tromey.git.orig/gdb/Makefile.in 2008-04-29 10:57:39.000000000 -0300
+++ tromey.git/gdb/Makefile.in 2008-04-29 11:00:35.000000000 -0300
@@ -141,6 +141,9 @@ READLINE_CFLAGS = @READLINE_CFLAGS@
# Where is expat? This will be empty if expat was not available.
LIBEXPAT = @LIBEXPAT@
+# Where is python? This will be empty if python was not available.
+LIBPYTHON = @LIBPYTHON2_4@ @LIBPYTHON2_5@
+
WARN_CFLAGS = @WARN_CFLAGS@
WERROR_CFLAGS = @WERROR_CFLAGS@
GDB_WARN_CFLAGS = $(WARN_CFLAGS)
@@ -254,6 +257,17 @@ SUBDIR_TUI_LDFLAGS=
SUBDIR_TUI_CFLAGS= \
-DTUI=1
+#
+# python sub directory definitons
+#
+SUBDIR_PYTHON_OBS = \
+ python.o
+SUBDIR_PYTHON_SRCS = \
+ python/python.c
+SUBDIR_PYTHON_DEPS =
+SUBDIR_PYTHON_LDFLAGS=
+SUBDIR_PYTHON_CFLAGS=
+
# Opcodes currently live in one of two places. Either they are in the
# opcode library, typically ../opcodes, or they are in a header file
@@ -399,7 +413,7 @@ INSTALLED_LIBS=-lbfd -lreadline -lopcode
-lintl -liberty $(LIBGNU)
CLIBS = $(SIM) $(READLINE) $(OPCODES) $(BFD) $(INTL) $(LIBIBERTY) $(LIBDECNUMBER) \
$(XM_CLIBS) $(TM_CLIBS) $(NAT_CLIBS) $(GDBTKLIBS) @LIBS@ \
- $(LIBICONV) $(LIBEXPAT) \
+ $(LIBICONV) $(LIBEXPAT) $(LIBPYTHON) \
$(LIBIBERTY) $(WIN32LIBS) $(LIBGNU)
CDEPS = $(XM_CDEPS) $(TM_CDEPS) $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE_DEPS) \
$(OPCODES) $(INTL_DEPS) $(LIBIBERTY) $(CONFIG_DEPS) $(LIBGNU)
@@ -963,6 +977,13 @@ tui_wingeneral_h = $(srcdir)/tui/tui-win
tui_win_h = $(srcdir)/tui/tui-win.h $(tui_data_h)
tui_winsource_h = $(srcdir)/tui/tui-winsource.h $(tui_data_h)
+#
+# gdb/python/ headers
+#
+
+python_h = $(srcdir)/python/python.h $(defs_h) $(value_h)
+python_internal_h = $(srcdir)/python/python-internal.h
+
# gdb/features preparsed descriptions
features_headers = $(defs_h) $(gdbtypes_h) $(target_descriptions_h)
arm_with_iwmmxt_c = $(srcdir)/features/arm-with-iwmmxt.c $(features_headers)
@@ -3051,7 +3072,8 @@ cli-logging.o: $(srcdir)/cli/cli-logging
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-logging.c
cli-script.o: $(srcdir)/cli/cli-script.c $(defs_h) $(value_h) $(language_h) \
$(ui_out_h) $(gdb_string_h) $(exceptions_h) $(top_h) $(cli_cmds_h) \
- $(cli_decode_h) $(cli_script_h) $(gdb_assert_h) $(breakpoint_h)
+ $(cli_decode_h) $(cli_script_h) $(gdb_assert_h) $(breakpoint_h) \
+ $(python_h)
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-script.c
cli-setshow.o: $(srcdir)/cli/cli-setshow.c $(defs_h) $(readline_tilde_h) \
$(value_h) $(gdb_string_h) $(ui_out_h) $(cli_decode_h) $(cli_cmds_h) \
@@ -3375,4 +3397,19 @@ tui-winsource.o: $(srcdir)/tui/tui-winso
$(gdb_curses_h) $(gdb_assert_h)
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tui-winsource.c
+#
+# gdb/python/ dependencies
+#
+# Need to explicitly specify the compile rule as make will do nothing
+# or try to compile the object file into the sub-directory.
+
+# Flags needed to compile Python code (taken from python-config --cflags)
+# FIXME: should we add -DNDEBUG? See CAUTION comment in Python.h.
+PYTHON_CFLAGS=-fno-strict-aliasing
+
+python.o: $(srcdir)/python/python.c $(defs_h) $(python_h) \
+ $(command_h) $(libiberty_h) $(cli_decode_h) $(charset_h) $(top_h) \
+ $(exceptions_h) $(python_internal_h) $(version_h)
+ $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) $(srcdir)/python/python.c
+
### end of the gdb Makefile.in.
Index: tromey.git/gdb/ax-gdb.c
===================================================================
--- tromey.git.orig/gdb/ax-gdb.c 2008-04-29 10:57:39.000000000 -0300
+++ tromey.git/gdb/ax-gdb.c 2008-04-29 10:58:06.000000000 -0300
@@ -1620,6 +1620,9 @@ gen_expr (union exp_element **pc, struct
case OP_INTERNALVAR:
error (_("GDB agent expressions cannot use convenience variables."));
+ case OP_INTERNALFUNC:
+ error (_("GDB agent expressions cannot use convenience functions."));
+
/* Weirdo operator: see comments for gen_repeat for details. */
case BINOP_REPEAT:
/* Note that gen_repeat handles its own argument evaluation. */
Index: tromey.git/gdb/breakpoint.c
===================================================================
--- tromey.git.orig/gdb/breakpoint.c 2008-04-29 10:57:39.000000000 -0300
+++ tromey.git/gdb/breakpoint.c 2008-04-29 10:58:06.000000000 -0300
@@ -671,7 +671,7 @@ commands_command (char *arg, int from_tt
char *tmpbuf = xstrprintf ("Type commands for when breakpoint %d is hit, one per line.",
bnum);
struct cleanup *cleanups = make_cleanup (xfree, tmpbuf);
- l = read_command_lines (tmpbuf, from_tty);
+ l = read_command_lines (tmpbuf, from_tty, 1);
do_cleanups (cleanups);
free_command_lines (&b->commands);
b->commands = l;
Index: tromey.git/gdb/c-exp.y
===================================================================
--- tromey.git.orig/gdb/c-exp.y 2008-04-29 10:57:39.000000000 -0300
+++ tromey.git/gdb/c-exp.y 2008-04-29 10:58:06.000000000 -0300
@@ -1636,6 +1636,31 @@ yylex ()
/* We must have come across a bad character (e.g. ';'). */
error ("Invalid character '%c' in expression.", c);
+ if (c == '$' && tokstart[1] == '(')
+ {
+ /* Convenience function call. */
+ int cparen_depth = 0;
+ int i;
+ for (i = 1; tokstart[i]; ++i)
+ {
+ if (tokstart[i] == '(')
+ ++cparen_depth;
+ else if (tokstart[i] == ')')
+ {
+ if (--cparen_depth == 0)
+ break;
+ }
+ }
+ if (cparen_depth != 0)
+ error ("Unmatched parentheses in convenience function invocation.");
+ yylval.sval.ptr = &tokstart[2];
+ yylval.sval.length = i - 2;
+ write_dollar_funcall (yylval.sval);
+ lexptr = &tokstart[i + 1];
+ /* FIXME: not exactly right. */
+ return VARIABLE;
+ }
+
/* It's a name. See how long it is. */
namelen = 0;
for (c = tokstart[namelen];
Index: tromey.git/gdb/cli/cli-script.c
===================================================================
--- tromey.git.orig/gdb/cli/cli-script.c 2008-04-29 10:57:39.000000000 -0300
+++ tromey.git/gdb/cli/cli-script.c 2008-04-29 11:03:58.000000000 -0300
@@ -34,6 +34,10 @@
#include "cli/cli-script.h"
#include "gdb_assert.h"
+#ifdef HAVE_PYTHON
+#include "python/python.h"
+#endif
+
/* Prototypes for local functions */
static enum command_control_type
@@ -225,6 +229,20 @@ print_command_lines (struct ui_out *uiou
continue;
}
+#ifdef HAVE_PYTHON
+ if (list->control_type == python_control)
+ {
+ ui_out_field_string (uiout, NULL, "python");
+ print_command_lines (uiout, *list->body_list, depth + 1);
+ if (depth)
+ ui_out_spaces (uiout, 2 * depth);
+ ui_out_field_string (uiout, NULL, "end");
+ ui_out_text (uiout, "\n");
+ list = list->next;
+ continue;
+ }
+#endif
+
/* ignore illegal command type and try next */
list = list->next;
} /* while (list) */
@@ -527,6 +545,17 @@ execute_control_command (struct command_
ret = commands_from_control_command (new_line, cmd);
break;
}
+ case python_control:
+#ifdef HAVE_PYTHON
+ {
+ eval_python_from_control_command (cmd);
+ ret = simple_control;
+ break;
+ }
+#else
+ warning (_("Python scripting is not supported in this copy of GDB."));
+ break;
+#endif
default:
warning (_("Invalid control type in canned commands structure."));
@@ -812,10 +841,11 @@ realloc_body_list (struct command_line *
"end", return such an indication to the caller. */
static enum misc_command_type
-read_next_line (struct command_line **command)
+read_next_line (struct command_line **command, int special_processing)
{
char *p, *p1, *prompt_ptr, control_prompt[256];
int i = 0;
+ int not_handled = 0;
if (control_level >= 254)
error (_("Control nesting too deep!"));
@@ -838,13 +868,20 @@ read_next_line (struct command_line **co
if (p == NULL)
return end_command;
- /* Strip leading and trailing whitespace. */
- while (*p == ' ' || *p == '\t')
- p++;
-
- p1 = p + strlen (p);
- while (p1 != p && (p1[-1] == ' ' || p1[-1] == '\t'))
- p1--;
+ if (special_processing)
+ {
+ /* Strip leading and trailing whitespace. */
+ while (*p == ' ' || *p == '\t')
+ p++;
+
+ p1 = p + strlen (p);
+ while (p1 != p && (p1[-1] == ' ' || p1[-1] == '\t'))
+ p1--;
+ }
+ else
+ {
+ p1 = p + strlen (p);
+ }
/* Blanks and comments don't really do anything, but we need to
distinguish them from else, end and other commands which can be
@@ -856,57 +893,71 @@ read_next_line (struct command_line **co
if (p1 - p == 3 && !strncmp (p, "end", 3))
return end_command;
- /* Is the else clause of an if control structure? */
- if (p1 - p == 4 && !strncmp (p, "else", 4))
- return else_command;
-
- /* Check for while, if, break, continue, etc and build a new command
- line structure for them. */
- if (p1 - p > 5 && !strncmp (p, "while", 5))
- {
- char *first_arg;
- first_arg = p + 5;
- while (first_arg < p1 && isspace (*first_arg))
- first_arg++;
- *command = build_command_line (while_control, first_arg);
- }
- else if (p1 - p > 2 && !strncmp (p, "if", 2))
- {
- char *first_arg;
- first_arg = p + 2;
- while (first_arg < p1 && isspace (*first_arg))
- first_arg++;
- *command = build_command_line (if_control, first_arg);
- }
- else if (p1 - p >= 8 && !strncmp (p, "commands", 8))
- {
- char *first_arg;
- first_arg = p + 8;
- while (first_arg < p1 && isspace (*first_arg))
- first_arg++;
- *command = build_command_line (commands_control, first_arg);
- }
- else if (p1 - p == 10 && !strncmp (p, "loop_break", 10))
- {
- *command = (struct command_line *)
- xmalloc (sizeof (struct command_line));
- (*command)->next = NULL;
- (*command)->line = NULL;
- (*command)->control_type = break_control;
- (*command)->body_count = 0;
- (*command)->body_list = NULL;
- }
- else if (p1 - p == 13 && !strncmp (p, "loop_continue", 13))
+ if (special_processing)
{
- *command = (struct command_line *)
- xmalloc (sizeof (struct command_line));
- (*command)->next = NULL;
- (*command)->line = NULL;
- (*command)->control_type = continue_control;
- (*command)->body_count = 0;
- (*command)->body_list = NULL;
+ /* Is the else clause of an if control structure? */
+ if (p1 - p == 4 && !strncmp (p, "else", 4))
+ return else_command;
+
+ /* Check for while, if, break, continue, etc and build a new command
+ line structure for them. */
+ if (p1 - p > 5 && !strncmp (p, "while", 5))
+ {
+ char *first_arg;
+ first_arg = p + 5;
+ while (first_arg < p1 && isspace (*first_arg))
+ first_arg++;
+ *command = build_command_line (while_control, first_arg);
+ }
+ else if (p1 - p > 2 && !strncmp (p, "if", 2))
+ {
+ char *first_arg;
+ first_arg = p + 2;
+ while (first_arg < p1 && isspace (*first_arg))
+ first_arg++;
+ *command = build_command_line (if_control, first_arg);
+ }
+ else if (p1 - p >= 8 && !strncmp (p, "commands", 8))
+ {
+ char *first_arg;
+ first_arg = p + 8;
+ while (first_arg < p1 && isspace (*first_arg))
+ first_arg++;
+ *command = build_command_line (commands_control, first_arg);
+ }
+#ifdef HAVE_PYTHON
+ else if (p1 - p == 6 && !strncmp (p, "python", 6))
+ {
+ /* Note that we ignore the inline "python command" form
+ here. */
+ *command = build_command_line (python_control, "");
+ }
+#endif
+ else if (p1 - p == 10 && !strncmp (p, "loop_break", 10))
+ {
+ *command = (struct command_line *)
+ xmalloc (sizeof (struct command_line));
+ (*command)->next = NULL;
+ (*command)->line = NULL;
+ (*command)->control_type = break_control;
+ (*command)->body_count = 0;
+ (*command)->body_list = NULL;
+ }
+ else if (p1 - p == 13 && !strncmp (p, "loop_continue", 13))
+ {
+ *command = (struct command_line *)
+ xmalloc (sizeof (struct command_line));
+ (*command)->next = NULL;
+ (*command)->line = NULL;
+ (*command)->control_type = continue_control;
+ (*command)->body_count = 0;
+ (*command)->body_list = NULL;
+ }
+ else
+ not_handled = 1;
}
- else
+
+ if (!special_processing || not_handled)
{
/* A normal command. */
*command = (struct command_line *)
@@ -952,7 +1003,7 @@ recurse_read_control_structure (struct c
dont_repeat ();
next = NULL;
- val = read_next_line (&next);
+ val = read_next_line (&next, 1);
/* Just skip blanks and comments. */
if (val == nop_command)
@@ -962,6 +1013,9 @@ recurse_read_control_structure (struct c
{
if (current_cmd->control_type == while_control
|| current_cmd->control_type == if_control
+#ifdef HAVE_PYTHON
+ || current_cmd->control_type == python_control
+#endif
|| current_cmd->control_type == commands_control)
{
/* Success reading an entire canned sequence of commands. */
@@ -1013,6 +1067,9 @@ recurse_read_control_structure (struct c
on it. */
if (next->control_type == while_control
|| next->control_type == if_control
+#ifdef HAVE_PYTHON
+ || next->control_type == python_control
+#endif
|| next->control_type == commands_control)
{
control_level++;
@@ -1037,7 +1094,7 @@ recurse_read_control_structure (struct c
#define END_MESSAGE "End with a line saying just \"end\"."
struct command_line *
-read_command_lines (char *prompt_arg, int from_tty)
+read_command_lines (char *prompt_arg, int from_tty, int special_processing)
{
struct command_line *head, *tail, *next;
struct cleanup *old_chain;
@@ -1066,7 +1123,7 @@ read_command_lines (char *prompt_arg, in
while (1)
{
dont_repeat ();
- val = read_next_line (&next);
+ val = read_next_line (&next, special_processing);
/* Ignore blank lines or comments. */
if (val == nop_command)
@@ -1086,6 +1143,9 @@ read_command_lines (char *prompt_arg, in
if (next->control_type == while_control
|| next->control_type == if_control
+#ifdef HAVE_PYTHON
+ || next->control_type == python_control
+#endif
|| next->control_type == commands_control)
{
control_level++;
@@ -1299,7 +1359,7 @@ define_command (char *comname, int from_
*tem = tolower (*tem);
sprintf (tmpbuf, "Type commands for definition of \"%s\".", comname);
- cmds = read_command_lines (tmpbuf, from_tty);
+ cmds = read_command_lines (tmpbuf, from_tty, 1);
if (c && c->class == class_user)
free_command_lines (&c->user_commands);
@@ -1346,7 +1406,7 @@ document_command (char *comname, int fro
error (_("Command \"%s\" is built-in."), comname);
sprintf (tmpbuf, "Type documentation for \"%s\".", comname);
- doclines = read_command_lines (tmpbuf, from_tty);
+ doclines = read_command_lines (tmpbuf, from_tty, 0);
if (c->doc)
xfree (c->doc);
Index: tromey.git/gdb/configure.ac
===================================================================
--- tromey.git.orig/gdb/configure.ac 2008-04-29 10:57:39.000000000 -0300
+++ tromey.git/gdb/configure.ac 2008-04-29 10:58:06.000000000 -0300
@@ -485,6 +485,41 @@ else
fi
fi
+AC_ARG_WITH(python,
+ AS_HELP_STRING([--with-python], [include python support (auto/yes/no)]),
+ [], [with_python=auto])
+AC_MSG_CHECKING([whether to use python])
+AC_MSG_RESULT([$with_python])
+
+if test "${with_python}" = no; then
+ AC_MSG_WARN([python support disabled; some features may be unavailable.])
+ HAVE_LIBPYTHON2_5=no
+ HAVE_LIBPYTHON2_4=no
+else
+ AC_LIB_HAVE_LINKFLAGS([python2.5], [], [#include "python2.5/Python.h"],
+ [Py_Initialize ();])
+ if test "$HAVE_LIBPYTHON2_5" != yes; then
+ AC_LIB_HAVE_LINKFLAGS([python2.4], [], [#include "python2.4/Python.h"],
+ [Py_Initialize ();])
+ if test "$HAVE_LIBPYTHON2_4" != yes; then
+ if test "$with_python" = yes; then
+ AC_MSG_ERROR([python is missing or unusable])
+ else
+ AC_MSG_WARN([python is missing or unusable; some features may be unavailable.])
+ fi
+ fi
+ fi
+fi
+
+if test "$HAVE_LIBPYTHON2_4" = yes || test "$HAVE_LIBPYTHON2_5" == yes; then
+ AC_DEFINE(HAVE_PYTHON, 1, [Define if Python interpreter is being linked in.])
+ CONFIG_OBS="$CONFIG_OBS \$(SUBDIR_PYTHON_OBS)"
+ CONFIG_DEPS="$CONFIG_DEPS \$(SUBDIR_PYTHON_DEPS)"
+ CONFIG_SRCS="$CONFIG_SRCS \$(SUBDIR_PYTHON_SRCS)"
+ CONFIG_INITS="$CONFIG_INITS \$(SUBDIR_PYTHON_INITS)"
+ ENABLE_CFLAGS="$ENABLE_CFLAGS \$(SUBDIR_PYTHON_CFLAGS)"
+fi
+
# ------------------------- #
# Checks for header files. #
# ------------------------- #
Index: tromey.git/gdb/defs.h
===================================================================
--- tromey.git.orig/gdb/defs.h 2008-04-29 10:57:39.000000000 -0300
+++ tromey.git/gdb/defs.h 2008-04-29 10:58:06.000000000 -0300
@@ -642,6 +642,7 @@ enum command_control_type
while_control,
if_control,
commands_control,
+ python_control,
invalid_control
};
@@ -657,7 +658,7 @@ struct command_line
struct command_line **body_list;
};
-extern struct command_line *read_command_lines (char *, int);
+extern struct command_line *read_command_lines (char *, int, int);
extern void free_command_lines (struct command_line **);
Index: tromey.git/gdb/eval.c
===================================================================
--- tromey.git.orig/gdb/eval.c 2008-04-29 10:57:39.000000000 -0300
+++ tromey.git/gdb/eval.c 2008-04-29 10:58:06.000000000 -0300
@@ -538,6 +538,18 @@ evaluate_subexp_standard (struct type *e
(*pos) += 2;
return value_of_internalvar (exp->elts[pc + 1].internalvar);
+ case OP_INTERNALFUNC:
+#ifdef HAVE_PYTHON
+ tem = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
+ /* FIXME: handling noside == EVAL_AVOID_SIDE_EFFECTS? */
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ return value_of_python (&exp->elts[pc + 2].string, tem);
+#else
+ error (_("Python scripting is not supported in this copy of GDB."));
+#endif
+
case OP_STRING:
tem = longest_to_int (exp->elts[pc + 1].longconst);
(*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
Index: tromey.git/gdb/expprint.c
===================================================================
--- tromey.git.orig/gdb/expprint.c 2008-04-29 10:57:39.000000000 -0300
+++ tromey.git/gdb/expprint.c 2008-04-29 10:58:06.000000000 -0300
@@ -148,6 +148,14 @@ print_subexp_standard (struct expression
internalvar_name (exp->elts[pc + 1].internalvar));
return;
+ case OP_INTERNALFUNC:
+ {
+ const char *name = &exp->elts[pc + 2].string;
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (exp->elts[pc + 1].longconst + 1);
+ fprintf_filtered (stream, "$(%s)", name);
+ return;
+ }
+
case OP_FUNCALL:
(*pos) += 2;
nargs = longest_to_int (exp->elts[pc + 1].longconst);
@@ -692,6 +700,8 @@ op_name_standard (enum exp_opcode opcode
return "OP_REGISTER";
case OP_INTERNALVAR:
return "OP_INTERNALVAR";
+ case OP_INTERNALFUNC:
+ return "OP_INTERNALFUNC";
case OP_FUNCALL:
return "OP_FUNCALL";
case OP_STRING:
@@ -973,6 +983,11 @@ dump_subexp_body_standard (struct expres
exp->elts[elt].internalvar->name);
elt += 2;
break;
+ case OP_INTERNALFUNC:
+ fprintf_filtered (stream, "Internal function call $(%s)",
+ &exp->elts[elt + 1].string);
+ elt += 3 + BYTES_TO_EXP_ELEM (exp->elts[elt].longconst + 1);
+ break;
case OP_FUNCALL:
{
int i, nargs;
Index: tromey.git/gdb/expression.h
===================================================================
--- tromey.git.orig/gdb/expression.h 2008-04-29 10:57:39.000000000 -0300
+++ tromey.git/gdb/expression.h 2008-04-29 10:58:06.000000000 -0300
@@ -172,6 +172,12 @@ enum exp_opcode
With another OP_INTERNALVAR at the end, this makes three exp_elements. */
OP_INTERNALVAR,
+ /* OP_INTERNALFUNC represents a call to a gdb-internal
+ "convenience function". Its format is the same as that of a
+ STRUCTOP, but the string data is evaluated as a call to a
+ gdb-provided function. */
+ OP_INTERNALFUNC,
+
/* OP_FUNCALL is followed by an integer in the next exp_element.
The integer is the number of args to the function call.
That many plus one values from following subexpressions
Index: tromey.git/gdb/parse.c
===================================================================
--- tromey.git.orig/gdb/parse.c 2008-04-29 10:57:39.000000000 -0300
+++ tromey.git/gdb/parse.c 2008-04-29 10:58:06.000000000 -0300
@@ -295,7 +295,7 @@ write_exp_elt_intern (struct internalvar
strings with embedded null bytes, as is required for some languages.
Don't be fooled by the fact that the string is null byte terminated,
- this is strictly for the convenience of debugging gdb itself. Gdb
+ this is strictly for the convenience of debugging gdb itself.
Gdb does not depend up the string being null terminated, since the
actual length is recorded in expression elements at each end of the
string. The null byte is taken into consideration when computing how
@@ -574,6 +574,14 @@ handle_register:
return;
}
+void
+write_dollar_funcall (struct stoken str)
+{
+ write_exp_elt_opcode (OP_INTERNALFUNC);
+ write_exp_string (str);
+ write_exp_elt_opcode (OP_INTERNALFUNC);
+}
+
char *
find_template_name_end (char *p)
@@ -798,6 +806,7 @@ operator_length_standard (struct express
case OP_OBJC_NSSTRING: /* Objective C Foundation Class NSString constant */
case OP_OBJC_SELECTOR: /* Objective C "@selector" pseudo-op */
case OP_NAME:
+ case OP_INTERNALFUNC:
oplen = longest_to_int (expr->elts[endpos - 2].longconst);
oplen = 4 + BYTES_TO_EXP_ELEM (oplen + 1);
break;
Index: tromey.git/gdb/parser-defs.h
===================================================================
--- tromey.git.orig/gdb/parser-defs.h 2008-04-29 10:57:39.000000000 -0300
+++ tromey.git/gdb/parser-defs.h 2008-04-29 10:58:06.000000000 -0300
@@ -136,6 +136,8 @@ extern void write_exp_elt_objfile (struc
extern void write_exp_msymbol (struct minimal_symbol *,
struct type *, struct type *);
+extern void write_dollar_funcall (struct stoken str);
+
extern void write_dollar_variable (struct stoken str);
extern char *find_template_name_end (char *);
Index: tromey.git/gdb/python/python-internal.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ tromey.git/gdb/python/python-internal.h 2008-04-29 10:58:06.000000000 -0300
@@ -0,0 +1,42 @@
+/* Gdb/Python header for private use by Python module.
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDB_PYTHON_INTERNAL_H
+#define GDB_PYTHON_INTERNAL_H
+
+#if HAVE_LIBPYTHON2_4
+#include "python2.4/Python.h"
+#elif HAVE_LIBPYTHON2_5
+#include "python2.5/Python.h"
+#endif
+
+extern PyObject *gdb_module;
+
+/* Use this after a TRY_EXCEPT to throw the appropriate Python
+ exception. FIXME: throw different errors depending on
+ Exception.error? */
+#define GDB_PY_HANDLE_EXCEPTION(Exception) \
+ do { \
+ if (Exception.reason < 0) \
+ return PyErr_Format (Exception.reason == RETURN_QUIT \
+ ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, \
+ "%s", Exception.message); \
+ } while (0)
+
+#endif /* GDB_PYTHON_INTERNAL_H */
Index: tromey.git/gdb/python/python.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ tromey.git/gdb/python/python.c 2008-04-29 11:03:46.000000000 -0300
@@ -0,0 +1,327 @@
+/* General python/gdb code
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "python.h"
+#include "command.h"
+#include "libiberty.h"
+#include "cli/cli-decode.h"
+#include "charset.h"
+#include "top.h"
+#include "exceptions.h"
+#include "python-internal.h"
+#include "version.h"
+
+#include <ctype.h>
+
+PyObject *gdb_module;
+
+static PyObject *get_show_variable (PyObject *, PyObject *);
+static PyObject *execute_gdb_command (PyObject *, PyObject *);
+
+
+void
+demand_python ()
+{
+ static int initialized = 0;
+
+ if (!initialized)
+ {
+ static PyMethodDef GdbMethods[] = {
+ { "execute", execute_gdb_command, METH_VARARGS,
+ "Execute a gdb command" },
+ { "show", get_show_variable, METH_VARARGS,
+ "Return a gdb setting's value" },
+
+ {NULL, NULL, 0, NULL}
+ };
+
+ Py_Initialize ();
+
+ gdb_module = Py_InitModule ("gdb", GdbMethods);
+
+ PyModule_AddStringConstant (gdb_module, "VERSION", version);
+ PyModule_AddStringConstant (gdb_module, "HOST_CONFIG", host_name);
+ PyModule_AddStringConstant (gdb_module, "TARGET_CONFIG", target_name);
+
+ PyRun_SimpleString ("import gdb");
+
+ initialized = 1;
+ }
+}
+
+static char *
+compute_python_string (struct command_line *l)
+{
+ char *script = NULL;
+ for (;l; l = l->next)
+ {
+ /* FIXME: inefficient. */
+ if (script)
+ {
+ char *save = script;
+ script = concat (script, l->line, "\n", NULL);
+ xfree (save);
+ }
+ else
+ script = concat (l->line, "\n", NULL);
+ }
+ return script;
+}
+
+void
+eval_python_from_control_command (struct command_line *cmd)
+{
+ char *script;
+
+ if (cmd->body_count != 1)
+ error (_("Invalid \"python\" block structure."));
+
+ demand_python ();
+
+ script = compute_python_string (cmd->body_list[0]);
+ PyRun_SimpleString (script);
+ xfree (script);
+ if (PyErr_Occurred ())
+ {
+ PyErr_Print ();
+ error ("error while executing Python code");
+ }
+}
+
+static void
+python_command (char *arg, int from_tty)
+{
+ char *script;
+ struct cleanup *cleanups = NULL;
+
+ while (arg && *arg && isspace (*arg))
+ ++arg;
+ if (arg && *arg)
+ script = arg;
+ else
+ {
+ struct command_line *l;
+ char *tmpbuf = xstrprintf ("Type python script");
+ cleanups = make_cleanup (xfree, tmpbuf);
+ l = read_command_lines (tmpbuf, from_tty, 0);
+ script = compute_python_string (l);
+ free_command_lines (&l);
+ }
+
+ /* This was observed on the following code in .gdbinit:
+ python
+ #
+ */
+ if (!script)
+ error ("empty Python script specified");
+
+ demand_python ();
+
+ PyRun_SimpleString (script);
+ if (script != arg)
+ xfree (script);
+ if (PyErr_Occurred ())
+ {
+ PyErr_Print ();
+ error ("error while executing Python code");
+ }
+
+ if (cleanups)
+ do_cleanups (cleanups);
+}
+
+\f
+
+/* Transform a gdb variable's value into a Python value. May return
+ NULL (and set a Python exception) on error. */
+
+PyObject *
+variable_to_python (struct cmd_list_element *cmd)
+{
+ switch (cmd->var_type)
+ {
+ case var_string:
+ case var_string_noescape:
+ case var_optional_filename:
+ case var_filename:
+ case var_enum:
+ {
+ char *str = * (char **) cmd->var;
+ if (! str)
+ str = "";
+ return PyString_Decode (str, strlen (str), host_charset (),
+ NULL /* FIXME */);
+ }
+
+ case var_boolean:
+ {
+ if (* (int *) cmd->var)
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
+ }
+
+ case var_auto_boolean:
+ {
+ enum auto_boolean ab = * (enum auto_boolean *) cmd->var;
+ if (ab == AUTO_BOOLEAN_TRUE)
+ Py_RETURN_TRUE;
+ else if (ab == AUTO_BOOLEAN_FALSE)
+ Py_RETURN_FALSE;
+ else
+ Py_RETURN_NONE;
+ }
+
+ case var_integer:
+ case var_zinteger:
+ return PyLong_FromLong (* (int *) cmd->var);
+
+ case var_uinteger:
+ return PyLong_FromUnsignedLong (* (unsigned int *) cmd->var);
+ }
+
+ return PyErr_Format (PyExc_RuntimeError, "programmer error: unhandled type");
+}
+
+static PyObject *
+get_show_variable (PyObject *self, PyObject *args)
+{
+ struct cmd_list_element *alias, *prefix, *cmd;
+ char *arg, *newarg;
+ volatile struct gdb_exception except;
+
+ if (! PyArg_ParseTuple (args, "s", &arg))
+ return NULL;
+
+ newarg = concat ("show ", arg, (char *) NULL);
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ if (! lookup_cmd_composition (newarg, &alias, &prefix, &cmd))
+ {
+ xfree (newarg);
+ return PyErr_Format (PyExc_RuntimeError,
+ "could not find variable `%s'", arg);
+ }
+ }
+ xfree (newarg);
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ if (! cmd->var)
+ return PyErr_Format (PyExc_RuntimeError, "`%s' is not a variable", arg);
+ return variable_to_python (cmd);
+}
+
+static PyObject *
+execute_gdb_command (PyObject *self, PyObject *args)
+{
+ struct cmd_list_element *alias, *prefix, *cmd;
+ char *arg, *newarg;
+ volatile struct gdb_exception except;
+
+ if (! PyArg_ParseTuple (args, "s", &arg))
+ return NULL;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ execute_command (arg, 0);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ /* gdbtk does bpstat_do_actions here... */
+
+ Py_RETURN_NONE;
+}
+
+/* Call a python function and return the result. EXPR is the command
+ string. LENGTH is the length of the string. */
+
+struct value *
+value_of_python (char *expr, int length)
+{
+ PyObject *result, *python_main, *global;
+ struct value *value = NULL;
+
+ demand_python ();
+
+ expr = xstrndup (expr, length);
+ make_cleanup (xfree, expr);
+
+ python_main = PyImport_ImportModule ("__main__");
+ global = PyModule_GetDict (python_main);
+
+ result = PyRun_String (expr, Py_eval_input, global, NULL);
+ /* FIXME: do we need a decref here? */
+ if (PyErr_Occurred ())
+ {
+ /* FIXME -- probably should not do this. */
+ PyErr_Print ();
+ error ("python error while evaluating expression");
+ }
+
+ if (PyBool_Check (result))
+ value = value_from_longest (builtin_type_bool, result == Py_True);
+ else if (PyInt_Check (result))
+ {
+ /* FIXME: type mapping. */
+ value = value_from_longest (builtin_type_int, PyInt_AsLong (result));
+ }
+ else if (PyLong_Check (result))
+ {
+ /* FIXME: longest -vs- long long. */
+ LONGEST l = PyLong_AsLongLong (result);
+ if (! PyErr_Occurred ())
+ value = value_from_longest (builtin_type_long, l);
+ }
+ else if (PyFloat_Check (result))
+ {
+ double d = PyFloat_AsDouble (result);
+ if (! PyErr_Occurred ())
+ value = value_from_double (builtin_type_double, d);
+ }
+ else if (PyString_Check (result))
+ {
+ /* FIXME: encoding */
+ char *s = PyString_AsString (result);
+ return value_from_string (s);
+ }
+ else
+ error ("could not convert python result: %s",
+ PyString_AsString (PyObject_Str (result)));
+
+ if (PyErr_Occurred ())
+ {
+ PyErr_Print ();
+ error ("error converting python value");
+ }
+
+ return value;
+}
+
+\f
+
+void
+_initialize_python (void)
+{
+ add_com ("python", class_obscure, python_command, _("\
+Blah, blah, blah."));
+
+ demand_python ();
+}
Index: tromey.git/gdb/python/python.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ tromey.git/gdb/python/python.h 2008-04-29 10:58:06.000000000 -0300
@@ -0,0 +1,29 @@
+/* Python/gdb header for generic use in gdb
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDB_PYTHON_H
+#define GDB_PYTHON_H
+
+#include "defs.h"
+#include "value.h"
+#include "python-internal.h"
+
+void eval_python_from_control_command (struct command_line *);
+
+#endif /* GDB_PYTHON_H */
Index: tromey.git/gdb/value.h
===================================================================
--- tromey.git.orig/gdb/value.h 2008-04-29 10:57:39.000000000 -0300
+++ tromey.git/gdb/value.h 2008-04-29 10:58:06.000000000 -0300
@@ -434,6 +434,8 @@ extern LONGEST parse_and_eval_long (char
extern struct value *access_value_history (int num);
+extern struct value *value_of_python (char *exp, int length);
+
extern struct value *value_of_internalvar (struct internalvar *var);
extern void set_internalvar (struct internalvar *var, struct value *val);
--
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* [RFC][patch 2/9] export values mechanism to Python
2008-04-29 15:59 [RFC][patch 0/9] Python support in GDB Thiago Jung Bauermann
` (7 preceding siblings ...)
2008-04-29 18:15 ` [RFC][patch 1/9] initial Python support Thiago Jung Bauermann
@ 2008-04-29 18:17 ` Thiago Jung Bauermann
2008-05-29 1:23 ` Daniel Jacobowitz
2008-04-29 18:38 ` [RFC][patch 0/9] Python support in GDB Eli Zaretskii
2008-05-02 18:30 ` Vladimir Prus
10 siblings, 1 reply; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-04-29 18:17 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: python-values.diff --]
[-- Type: text/plain, Size: 19311 bytes --]
2008-04-29 Vladimir Prus <vladimir@codesourcery.com>
Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
* Makefile.in (SUBDIR_PYTHON_OBS): Add python-value.o.
(SUBDIR_PYTHON_SRCS): Add python/value.c.
(value.o): Depend on python.h.
(python-value.o): New target.
* python/python-internal.h (value_object_type,
gdbpy_make_value_from_int, gdbpy_get_value_from_history,
value_to_value_object, gdb_owned_value_to_value_object,
value_object_to_value, gdbpy_initialize_values): Declare.
* python/python.c (demand_python): Add new functions for values.
Call gdbpy_initialize_values.
* python/python.h (values_in_python): Declare.
* python/value.c: New file.
* value.c (value_prepend_to_list, value_remove_from_list): New
functions.
(preserve_values): Process elements in values_in_python list.
Include python.h.
* value.h (value_prepend_to_list,
value_remove_from_list): Declare.
Index: tromey.git/gdb/Makefile.in
===================================================================
--- tromey.git.orig/gdb/Makefile.in 2008-04-29 11:00:35.000000000 -0300
+++ tromey.git/gdb/Makefile.in 2008-04-29 11:04:11.000000000 -0300
@@ -261,9 +261,11 @@ SUBDIR_TUI_CFLAGS= \
# python sub directory definitons
#
SUBDIR_PYTHON_OBS = \
- python.o
+ python.o \
+ python-value.o
SUBDIR_PYTHON_SRCS = \
- python/python.c
+ python/python.c \
+ python/value.c
SUBDIR_PYTHON_DEPS =
SUBDIR_PYTHON_LDFLAGS=
SUBDIR_PYTHON_CFLAGS=
@@ -2982,7 +2984,7 @@ valprint.o: valprint.c $(defs_h) $(gdb_s
value.o: value.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
$(value_h) $(gdbcore_h) $(command_h) $(gdbcmd_h) $(target_h) \
$(language_h) $(demangle_h) $(doublest_h) \
- $(gdb_assert_h) $(regcache_h) $(block_h) $(dfp_h)
+ $(gdb_assert_h) $(regcache_h) $(block_h) $(dfp_h) $(python_h)
varobj.o: varobj.c $(defs_h) $(exceptions_h) $(value_h) $(expression_h) \
$(frame_h) $(language_h) $(wrapper_h) $(gdbcmd_h) $(block_h) \
$(gdb_assert_h) $(gdb_string_h) $(varobj_h) $(vec_h) $(gdbthread_h) \
@@ -3411,5 +3413,9 @@ python.o: $(srcdir)/python/python.c $(de
$(command_h) $(libiberty_h) $(cli_decode_h) $(charset_h) $(top_h) \
$(exceptions_h) $(python_internal_h) $(version_h)
$(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) $(srcdir)/python/python.c
+python-value.o: $(srcdir)/python/value.c $(defs_h) $(exceptions_h) \
+ $(python_internal_h) $(value_h)
+ $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
+ $(srcdir)/python/value.c -o python-value.o
### end of the gdb Makefile.in.
Index: tromey.git/gdb/python/python-internal.h
===================================================================
--- tromey.git.orig/gdb/python/python-internal.h 2008-04-29 10:58:06.000000000 -0300
+++ tromey.git/gdb/python/python-internal.h 2008-04-29 11:04:11.000000000 -0300
@@ -27,6 +27,17 @@
#endif
extern PyObject *gdb_module;
+extern PyTypeObject value_object_type;
+
+PyObject *gdbpy_make_value_from_int (PyObject *self, PyObject *args);
+PyObject *gdbpy_get_value_from_history (PyObject *self, PyObject *args);
+
+PyObject *value_to_value_object (struct value *v);
+PyObject *gdb_owned_value_to_value_object (struct value *v);
+
+struct value *value_object_to_value (PyObject *self);
+
+void gdbpy_initialize_values (void);
/* Use this after a TRY_EXCEPT to throw the appropriate Python
exception. FIXME: throw different errors depending on
Index: tromey.git/gdb/python/python.c
===================================================================
--- tromey.git.orig/gdb/python/python.c 2008-04-29 11:03:46.000000000 -0300
+++ tromey.git/gdb/python/python.c 2008-04-29 11:04:11.000000000 -0300
@@ -44,6 +44,10 @@ demand_python ()
if (!initialized)
{
static PyMethodDef GdbMethods[] = {
+ { "make_value_from_int", gdbpy_make_value_from_int, METH_VARARGS,
+ "Make a value from int" },
+ { "get_value_from_history", gdbpy_get_value_from_history, METH_VARARGS,
+ "Get a value from history" },
{ "execute", execute_gdb_command, METH_VARARGS,
"Execute a gdb command" },
{ "show", get_show_variable, METH_VARARGS,
@@ -60,6 +64,8 @@ demand_python ()
PyModule_AddStringConstant (gdb_module, "HOST_CONFIG", host_name);
PyModule_AddStringConstant (gdb_module, "TARGET_CONFIG", target_name);
+ gdbpy_initialize_values ();
+
PyRun_SimpleString ("import gdb");
initialized = 1;
Index: tromey.git/gdb/python/python.h
===================================================================
--- tromey.git.orig/gdb/python/python.h 2008-04-29 10:58:06.000000000 -0300
+++ tromey.git/gdb/python/python.h 2008-04-29 11:04:11.000000000 -0300
@@ -24,6 +24,8 @@
#include "value.h"
#include "python-internal.h"
+extern struct value *values_in_python;
+
void eval_python_from_control_command (struct command_line *);
#endif /* GDB_PYTHON_H */
Index: tromey.git/gdb/python/value.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ tromey.git/gdb/python/value.c 2008-04-29 11:04:56.000000000 -0300
@@ -0,0 +1,392 @@
+/* Python interface to values.
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "value.h"
+#include "exceptions.h"
+#include "python-internal.h"
+
+typedef struct {
+ PyObject_HEAD
+ struct value *value;
+ int owned_by_gdb;
+} value_object;
+
+/* List of all values which are currently exposed to Python. It is maintained
+ so that when an objfile is discarded, preserve_values can copy the values'
+ types if needed. */
+struct value *values_in_python;
+
+static void valpy_dealloc (PyObject *obj);
+static PyObject *valpy_dereference (PyObject *self, PyObject *args);
+static PyObject *valpy_get_element (PyObject *self, PyObject *args);
+static PyObject *valpy_str (PyObject *self);
+static PyObject *valpy_increment (PyObject *self, PyObject *args);
+static PyObject *valpy_equal_p (PyObject *self, PyObject *args);
+static PyObject * valpy_lazy_p (PyObject *self, PyObject *args);
+static PyObject * valpy_fetch_lazy (PyObject *self, PyObject *args);
+static PyObject * valpy_common_print (PyObject *self, PyObject *args);
+
+static PyMethodDef value_object_methods[] = {
+ { "dereference", valpy_dereference, METH_NOARGS, "Dereferences the value." },
+ { "get_element", valpy_get_element, METH_VARARGS,
+ "Obtains element inside value." },
+ { "increment", valpy_increment, METH_VARARGS,
+ "Increment value by the given amount." },
+ { "equals", valpy_equal_p, METH_VARARGS, "Compare values." },
+ { "is_lazy", valpy_lazy_p, METH_NOARGS,
+ "Returns True if the value is lazy, False if not." },
+ { "fetch_lazy", valpy_fetch_lazy, METH_NOARGS,
+ "Fetches value from inferior memory." },
+ { "common_print", valpy_common_print, METH_VARARGS, "Prints value." },
+ {NULL} /* Sentinel */
+};
+
+PyTypeObject value_object_type = {
+ PyObject_HEAD_INIT (NULL)
+ 0, /*ob_size*/
+ "gdb.Value", /*tp_name*/
+ sizeof (value_object), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ valpy_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ valpy_str, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "GDB value object", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ value_object_methods /* tp_methods */
+};
+
+/* Mantra used to return value object wrapping value struct. */
+#define VALPY_RETURN_VALUE(valpy_obj, value_st) \
+ do { \
+ valpy_obj = PyObject_New (value_object, &value_object_type); \
+ if (valpy_obj != NULL) \
+ { \
+ valpy_obj->value = value_st; \
+ release_value (value_st); \
+ value_prepend_to_list (&values_in_python, value_st); \
+ } \
+ return (PyObject *) valpy_obj; \
+ } while (0)
+
+
+static void
+valpy_dealloc (PyObject *obj)
+{
+ value_object *self = (value_object *) obj;
+
+ value_remove_from_list (&values_in_python, self->value);
+
+ if (!self->owned_by_gdb)
+ value_free (self->value);
+ self->ob_type->tp_free (self);
+}
+
+static PyObject *
+valpy_dereference (PyObject *self, PyObject *args)
+{
+ struct value *res_val = NULL; /* Initialize to appease gcc warning. */
+ value_object *result;
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ res_val = value_ind (((value_object *) self)->value);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ VALPY_RETURN_VALUE (result, res_val);
+}
+
+/* Takes value and string name of element inside that value. */
+static PyObject *
+valpy_get_element (PyObject *self, PyObject *args)
+{
+ value_object *self_value = (value_object *) self;
+ char *field;
+ struct value *res_val = NULL; /* Initialize to appease gcc warning. */
+ value_object *result;
+ volatile struct gdb_exception except;
+
+ if (!PyArg_ParseTuple (args, "s", &field))
+ return NULL;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ res_val = value_struct_elt (&self_value->value, NULL, field, 0, NULL);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ VALPY_RETURN_VALUE (result, res_val);
+}
+
+/* FIXME: copy paste from varobj.c */
+static char *
+value_get_print_value (struct value *value)
+{
+ long dummy;
+ struct ui_file *stb;
+ struct cleanup *old_chain;
+ char *thevalue;
+
+ if (value == NULL)
+ return NULL;
+
+ stb = mem_fileopen ();
+ old_chain = make_cleanup_ui_file_delete (stb);
+
+ common_val_print (value, stb, 0, 1, 0, 0);
+ thevalue = ui_file_xstrdup (stb, &dummy);
+
+ do_cleanups (old_chain);
+ return thevalue;
+}
+
+static PyObject *
+valpy_str (PyObject *self)
+{
+ char *s;
+ PyObject *result;
+
+ s = value_get_print_value (((value_object *) self)->value);
+ result = PyString_FromString (s);
+ xfree (s);
+
+ return result;
+}
+
+static PyObject *
+valpy_increment (PyObject *self, PyObject *args)
+{
+ int i;
+ struct value *res_val = NULL; /* Initialize to appease gcc warning. */
+ struct value *inc;
+ value_object *result;
+ volatile struct gdb_exception except;
+
+ if (!PyArg_ParseTuple (args, "i", &i))
+ return NULL;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ /* FIXME: clear everything. */
+ inc = value_from_longest (builtin_type_int, i);
+ res_val = value_add (((value_object *) self)->value, inc);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ VALPY_RETURN_VALUE (result, res_val);
+}
+
+static PyObject *
+valpy_equal_p (PyObject *self, PyObject *args)
+{
+ int equalp = 0; /* Initialize to appease gcc warning. */
+ value_object *other;
+ volatile struct gdb_exception except;
+
+ if (!PyArg_ParseTuple (args, "O!", &value_object_type, &other))
+ return NULL;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ equalp = value_equal (((value_object *) self)->value, other->value);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ if (equalp == 1)
+ Py_RETURN_TRUE;
+
+ Py_RETURN_FALSE;
+}
+
+static PyObject *
+valpy_lazy_p (PyObject *self, PyObject *args)
+{
+ if (value_lazy (((value_object *) self)->value))
+ Py_RETURN_TRUE;
+
+ Py_RETURN_FALSE;
+}
+
+static PyObject *
+valpy_fetch_lazy (PyObject *self, PyObject *args)
+{
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ value_fetch_lazy (((value_object *) self)->value);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+valpy_common_print (PyObject *self, PyObject *args)
+{
+ value_object *self_value = (value_object *) self;
+ int ret = 0, format, recurse, pretty;
+ PyObject *format_obj, *deref_obj;
+ struct ui_stream *stb;
+ struct cleanup *chain;
+ volatile struct gdb_exception except;
+
+ if (!PyArg_ParseTuple (args, "OO!ii", &format_obj, &PyBool_Type, &deref_obj,
+ &recurse, &pretty))
+ return NULL;
+
+ if (format_obj == Py_None)
+ format = 0;
+ else
+ {
+ if (!PyString_Check (format_obj) || PyString_Size (format_obj) != 1)
+ {
+ PyErr_SetString (PyExc_TypeError, "Argument 1 must be char or None.");
+ return NULL;
+ }
+
+ format = *PyString_AsString (format_obj);
+ }
+
+ stb = ui_out_stream_new (uiout);
+ chain = make_cleanup_ui_out_stream_delete (stb);
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ ret = common_val_print (self_value->value, stb->stream, format,
+ deref_obj == Py_True, recurse, pretty);
+ /* FIXME: should I really use ui_out_field_stream? */
+ ui_out_field_stream (uiout, "value", stb);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ do_cleanups (chain);
+
+ return PyInt_FromLong (ret);
+}
+
+/* A value owned by GDB is in the all_values chain, so it will be freed
+ automatically when not needed anymore (i.e., before the current command
+ completes). */
+PyObject *
+gdb_owned_value_to_value_object (struct value *v)
+{
+ value_object *result = PyObject_New (value_object, &value_object_type);
+ if (result != NULL)
+ {
+ result->value = v;
+ result->owned_by_gdb = 1;
+ /* FIXME: should we do it? What is it? */
+ /* I don't think it is needed, since a GDB owned value has a very short
+ lifetime. The purpose of the list is explained in the comment above
+ its declaration. -- bauermann */
+ value_prepend_to_list (&values_in_python, v);
+ }
+ return (PyObject *)result;
+}
+
+/* Returns an object for a value which is released from the all_values chain,
+ so its lifetime is not bound to the execution of a command. */
+PyObject *
+value_to_value_object (struct value *v)
+{
+ value_object *val_obj;
+
+ VALPY_RETURN_VALUE (val_obj, v);
+}
+
+struct value *
+value_object_to_value (PyObject *self)
+{
+ value_object *real = (value_object *)self;
+ return real->value;
+}
+
+PyObject *
+gdbpy_make_value_from_int (PyObject *self, PyObject *args)
+{
+ int i;
+ struct value *res_val = NULL; /* Initialize to appease gcc warning. */
+ value_object *result;
+ volatile struct gdb_exception except;
+
+ if (!PyArg_ParseTuple (args, "i", &i))
+ return NULL;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ res_val = value_from_longest (builtin_type_int, i);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ VALPY_RETURN_VALUE (result, res_val);
+}
+
+PyObject *
+gdbpy_get_value_from_history (PyObject *self, PyObject *args)
+{
+ int i;
+ struct value *res_val = NULL; /* Initialize to appease gcc warning. */
+ value_object *result;
+ volatile struct gdb_exception except;
+
+ if (!PyArg_ParseTuple (args, "i", &i))
+ return NULL;
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ res_val = access_value_history (i);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ VALPY_RETURN_VALUE (result, res_val);
+}
+
+void
+gdbpy_initialize_values (void)
+{
+ value_object_type.tp_new = PyType_GenericNew;
+ if (PyType_Ready (&value_object_type) < 0)
+ return;
+
+ Py_INCREF (&value_object_type);
+ PyModule_AddObject (gdb_module, "Value", (PyObject *) &value_object_type);
+
+ values_in_python = NULL;
+}
Index: tromey.git/gdb/value.c
===================================================================
--- tromey.git.orig/gdb/value.c 2008-04-29 10:57:39.000000000 -0300
+++ tromey.git/gdb/value.c 2008-04-29 11:04:11.000000000 -0300
@@ -36,6 +36,10 @@
#include "block.h"
#include "dfp.h"
+#ifdef HAVE_PYTHON
+#include "python/python.h"
+#endif
+
/* Prototypes for exported functions. */
void _initialize_values (void);
@@ -129,8 +133,8 @@ struct value
/* Values are stored in a chain, so that they can be deleted easily
over calls to the inferior. Values assigned to internal
- variables or put into the value history are taken off this
- list. */
+ variables, put into the value history or exposed to Python are
+ taken off this list. */
struct value *next;
/* Register number if the value is from a register. */
@@ -256,6 +260,31 @@ allocate_repeat_value (struct type *type
type, range_type));
}
+/* Needed if another module needs to maintain its on list of values. */
+void
+value_prepend_to_list (struct value **head, struct value *val)
+{
+ val->next = *head;
+ *head = val;
+}
+
+/* Needed if another module needs to maintain its on list of values. */
+void
+value_remove_from_list (struct value **head, struct value *val)
+{
+ struct value *prev;
+
+ if (*head == val)
+ *head = (*head)->next;
+ else
+ for (prev = *head; prev->next; prev = prev->next)
+ if (prev->next == val)
+ {
+ prev->next = val->next;
+ break;
+ }
+}
+
/* Accessor methods. */
struct value *
@@ -915,6 +944,7 @@ preserve_values (struct objfile *objfile
htab_t copied_types;
struct value_history_chunk *cur;
struct internalvar *var;
+ struct value *val;
int i;
/* Create the hash table. We allocate on the objfile's obstack, since
@@ -929,6 +959,11 @@ preserve_values (struct objfile *objfile
for (var = internalvars; var; var = var->next)
preserve_one_value (var->value, objfile, copied_types);
+#ifdef HAVE_PYTHON
+ for (val = values_in_python; val; val = val->next)
+ preserve_one_value (val, objfile, copied_types);
+#endif
+
htab_delete (copied_types);
}
Index: tromey.git/gdb/value.h
===================================================================
--- tromey.git.orig/gdb/value.h 2008-04-29 10:58:06.000000000 -0300
+++ tromey.git/gdb/value.h 2008-04-29 11:04:11.000000000 -0300
@@ -39,9 +39,15 @@ struct ui_file;
struct value;
+/* Needed if another module needs to maintain its on list of values. */
+
+void value_prepend_to_list (struct value **head, struct value *val);
+void value_remove_from_list (struct value **head, struct value *val);
+
/* Values are stored in a chain, so that they can be deleted easily
- over calls to the inferior. Values assigned to internal variables
- or put into the value history are taken off this list. */
+ over calls to the inferior. Values assigned to internal variables,
+ put into the value history or exposed to Python are taken off this
+ list. */
struct value *value_next (struct value *);
--
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 0/9] Python support in GDB
2008-04-29 15:59 [RFC][patch 0/9] Python support in GDB Thiago Jung Bauermann
` (8 preceding siblings ...)
2008-04-29 18:17 ` [RFC][patch 2/9] export values mechanism to Python Thiago Jung Bauermann
@ 2008-04-29 18:38 ` Eli Zaretskii
2008-04-29 20:37 ` Thiago Jung Bauermann
2008-05-02 18:30 ` Vladimir Prus
10 siblings, 1 reply; 147+ messages in thread
From: Eli Zaretskii @ 2008-04-29 18:38 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
> Date: Tue, 29 Apr 2008 12:52:12 -0300
> From: Thiago Jung Bauermann <bauerman@br.ibm.com>
>
> This patch series adds Python scripting support to GDB, and exposes
> some of its subsystems hopefully in a "pythonic" way.
Thanks a lot!
I presume that you are suggesting these patches for the GDB CVS trunk,
right? That is, it isn't gonna live on some specialized branch,
right? If so, it must be accompanied by some minimal documentation.
We cannot have such a major feature go undocumented.
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 0/9] Python support in GDB
2008-04-29 18:38 ` [RFC][patch 0/9] Python support in GDB Eli Zaretskii
@ 2008-04-29 20:37 ` Thiago Jung Bauermann
2008-04-29 21:22 ` Tom Tromey
0 siblings, 1 reply; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-04-29 20:37 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gdb-patches
On Tue, 2008-04-29 at 21:14 +0300, Eli Zaretskii wrote:
> > Date: Tue, 29 Apr 2008 12:52:12 -0300
> > From: Thiago Jung Bauermann <bauerman@br.ibm.com>
> >
> > This patch series adds Python scripting support to GDB, and exposes
> > some of its subsystems hopefully in a "pythonic" way.
>
> Thanks a lot!
>
> I presume that you are suggesting these patches for the GDB CVS trunk,
> right? That is, it isn't gonna live on some specialized branch,
> right? If so, it must be accompanied by some minimal documentation.
> We cannot have such a major feature go undocumented.
You are right of course, I forgot to talk about this in the e-mail,
sorry. The reason there is no documentation right now is that we want to
do it after it is clear what will be the final form fo python support.
It could be what is in these patches, but it can change based on further
discussion.
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 0/9] Python support in GDB
2008-04-29 20:37 ` Thiago Jung Bauermann
@ 2008-04-29 21:22 ` Tom Tromey
2008-04-30 7:54 ` Eli Zaretskii
0 siblings, 1 reply; 147+ messages in thread
From: Tom Tromey @ 2008-04-29 21:22 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: Eli Zaretskii, gdb-patches
>>>>> "Thiago" == Thiago Jung Bauermann <bauerman@br.ibm.com> writes:
Thiago> You are right of course, I forgot to talk about this in the e-mail,
Thiago> sorry. The reason there is no documentation right now is that we want to
Thiago> do it after it is clear what will be the final form fo python support.
Thiago> It could be what is in these patches, but it can change based on further
Thiago> discussion.
I completely agree with Thiago here. Also, a similar consideration
applies to the test suite.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 3/9] export hooks mechanism to Python
2008-04-29 15:59 ` [RFC][patch 3/9] export hooks mechanism " Thiago Jung Bauermann
@ 2008-04-29 21:29 ` Tom Tromey
2008-04-30 18:27 ` Joel Brobecker
2008-04-30 18:29 ` Daniel Jacobowitz
2008-05-29 7:55 ` Daniel Jacobowitz
1 sibling, 2 replies; 147+ messages in thread
From: Tom Tromey @ 2008-04-29 21:29 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
>>>>> "Thiago" == Thiago Jung Bauermann <bauerman@br.ibm.com> writes:
>> 2008-04-29 Tom Tromey <tromey@redhat.com>
>> * interps.c (interp_set): Don't call clear_interpreter_hooks.
>> [Temporary hack].
This is one particular thing I wanted to highlight and ask for help on.
>> + /* FIXME - we don't want python to be a normal interpreter, but we
>> + do want to be able to hook in everywhere. Not sure what to do
>> + about this -- maybe allow events to be delivered to multiple
>> + handlers. */
>> +/* clear_interpreter_hooks (); */
The Python code installs hooks so that users can write Python that
reacts to gdb events. I wasn't sure what would be an acceptable
approach here, and for the short term I just disabled this code. But,
this is not a good solution.
A lot of this stuff is marked deprecated. Why is that? Is there some
other approach the Python code should use instead?
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 0/9] Python support in GDB
2008-04-29 21:22 ` Tom Tromey
@ 2008-04-30 7:54 ` Eli Zaretskii
2008-04-30 19:38 ` Thiago Jung Bauermann
0 siblings, 1 reply; 147+ messages in thread
From: Eli Zaretskii @ 2008-04-30 7:54 UTC (permalink / raw)
To: tromey; +Cc: bauerman, gdb-patches
> X-Spam-Status: No, score=-2.5 required=5.0 tests=AWL,BAYES_00 autolearn=ham
> version=3.1.0
> Cc: Eli Zaretskii <eliz@gnu.org>, gdb-patches@sourceware.org
> From: Tom Tromey <tromey@redhat.com>
> Date: Tue, 29 Apr 2008 12:37:35 -0600
>
> >>>>> "Thiago" == Thiago Jung Bauermann <bauerman@br.ibm.com> writes:
>
> Thiago> You are right of course, I forgot to talk about this in the e-mail,
> Thiago> sorry. The reason there is no documentation right now is that we want to
> Thiago> do it after it is clear what will be the final form fo python support.
> Thiago> It could be what is in these patches, but it can change based on further
> Thiago> discussion.
>
> I completely agree with Thiago here. Also, a similar consideration
> applies to the test suite.
I understand the urge to avoid unnecessary work. That is why I said
_minimal_ documentation. I find it hard to believe that nothing can
be said about this feature that will not change based on further
discussion. Unless all that discussion happens before the patches are
committed to the GDB CVS, in which case I have no problems waiting
till then. But whenever the patches are actually committed, I will
object to doing so without some minimal documentation that describes
its usage.
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 3/9] export hooks mechanism to Python
2008-04-29 21:29 ` Tom Tromey
@ 2008-04-30 18:27 ` Joel Brobecker
2008-04-30 21:30 ` Tom Tromey
2008-04-30 18:29 ` Daniel Jacobowitz
1 sibling, 1 reply; 147+ messages in thread
From: Joel Brobecker @ 2008-04-30 18:27 UTC (permalink / raw)
To: Tom Tromey; +Cc: Thiago Jung Bauermann, gdb-patches
> The Python code installs hooks so that users can write Python that
> reacts to gdb events. I wasn't sure what would be an acceptable
> approach here, and for the short term I just disabled this code. But,
> this is not a good solution.
>
> A lot of this stuff is marked deprecated. Why is that? Is there some
> other approach the Python code should use instead?
I am not 100% sure why these hooks were marked as deprecated, I haven't
checked the exact history, but if these are meant to be called when
something specific happens, we prefer now to use "observers". With
hooks, you can have only one user of the hook - although we did manage
to get around this limitation with a little tap dance but that was
hardly satisfactory.
Observers are a relatively recent addition to our code compared to these
hooks - see doc/observer.texi, and the generated file observer.h (and
observer-inc.c I think). The generation is performed by observer.sh.
Since you need to be able to write some python code that "reacts to
*GDB events*", I think that observers are exactly what you are looking
for.
--
Joel
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 3/9] export hooks mechanism to Python
2008-04-29 21:29 ` Tom Tromey
2008-04-30 18:27 ` Joel Brobecker
@ 2008-04-30 18:29 ` Daniel Jacobowitz
2008-04-30 23:00 ` Tom Tromey
1 sibling, 1 reply; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-04-30 18:29 UTC (permalink / raw)
To: Tom Tromey; +Cc: Thiago Jung Bauermann, gdb-patches
On Tue, Apr 29, 2008 at 02:07:21PM -0600, Tom Tromey wrote:
> A lot of this stuff is marked deprecated. Why is that? Is there some
> other approach the Python code should use instead?
Basically, because the main user of hooks is Insight. Without
Insight, most of the code could go away. Note "User Interface Events"
as the description in gdb-events.h; they're for a GUI.
What sort of events are you hooking usefully? Can we share e.g. the
CLI "hook-" mechanism?
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 0/9] Python support in GDB
2008-04-30 7:54 ` Eli Zaretskii
@ 2008-04-30 19:38 ` Thiago Jung Bauermann
2008-04-30 19:52 ` Eli Zaretskii
0 siblings, 1 reply; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-04-30 19:38 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: tromey, gdb-patches
On Wed, 2008-04-30 at 06:21 +0300, Eli Zaretskii wrote:
> I understand the urge to avoid unnecessary work. That is why I said
> _minimal_ documentation. I find it hard to believe that nothing can
> be said about this feature that will not change based on further
> discussion.
Oh, I see. Yes, it's perfectly reasonable.
> Unless all that discussion happens before the patches are
> committed to the GDB CVS, in which case I have no problems waiting
> till then. But whenever the patches are actually committed, I will
> object to doing so without some minimal documentation that describes
> its usage.
I'm inclined to take this approach. At the moment I prefer to see what
folks will say about the current implementation, and when at least one
of these patches is ready to be committed I'll include documentation to
go with it.
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 0/9] Python support in GDB
2008-04-30 19:38 ` Thiago Jung Bauermann
@ 2008-04-30 19:52 ` Eli Zaretskii
0 siblings, 0 replies; 147+ messages in thread
From: Eli Zaretskii @ 2008-04-30 19:52 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: tromey, gdb-patches
> From: Thiago Jung Bauermann <bauerman@br.ibm.com>
> Cc: tromey@redhat.com, gdb-patches@sourceware.org
> Date: Wed, 30 Apr 2008 13:38:15 -0300
>
> > Unless all that discussion happens before the patches are
> > committed to the GDB CVS, in which case I have no problems waiting
> > till then. But whenever the patches are actually committed, I will
> > object to doing so without some minimal documentation that describes
> > its usage.
>
> I'm inclined to take this approach. At the moment I prefer to see what
> folks will say about the current implementation, and when at least one
> of these patches is ready to be committed I'll include documentation to
> go with it.
Fine with me, and thanks.
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 3/9] export hooks mechanism to Python
2008-04-30 18:27 ` Joel Brobecker
@ 2008-04-30 21:30 ` Tom Tromey
2008-05-27 18:22 ` Tom Tromey
0 siblings, 1 reply; 147+ messages in thread
From: Tom Tromey @ 2008-04-30 21:30 UTC (permalink / raw)
To: Joel Brobecker; +Cc: Thiago Jung Bauermann, gdb-patches
>>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:
Joel> Since you need to be able to write some python code that "reacts to
Joel> *GDB events*", I think that observers are exactly what you are looking
Joel> for.
Thanks, I will look at that.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 3/9] export hooks mechanism to Python
2008-04-30 18:29 ` Daniel Jacobowitz
@ 2008-04-30 23:00 ` Tom Tromey
0 siblings, 0 replies; 147+ messages in thread
From: Tom Tromey @ 2008-04-30 23:00 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
>>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
Daniel> What sort of events are you hooking usefully? Can we share e.g. the
Daniel> CLI "hook-" mechanism?
A lot of this code is just speculative -- based on the idea that it
would be nice to be able to write Python scripts which do things
reactively; say for instance take some action after an "attach".
(A lot of this has never even been tried.)
However internally the Python code uses events to track breakpoint
creation and destruction. I suppose I could try to add new observers
to let me do that.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 0/9] Python support in GDB
2008-04-29 15:59 [RFC][patch 0/9] Python support in GDB Thiago Jung Bauermann
` (9 preceding siblings ...)
2008-04-29 18:38 ` [RFC][patch 0/9] Python support in GDB Eli Zaretskii
@ 2008-05-02 18:30 ` Vladimir Prus
10 siblings, 0 replies; 147+ messages in thread
From: Vladimir Prus @ 2008-05-02 18:30 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1282 bytes --]
Thiago Jung Bauermann wrote:
> Hi everybody,
>
> This patch series adds Python scripting support to GDB, and exposes
> some of its subsystems hopefully in a "pythonic" way. These patches
> correspond to the contents of the git repository at gitorious.org,
> rebased to apply cleanly on top of CVS HEAD as of 04/27.
The attached two patches are rebased MI ones. The first is cleanup,
and I'll commit it shortly. The second one is the real one. Since both
patches touch just MI code, this is RFC, not RFA. The second patch
has a couple fixmes that I'll address later, and needs doc that I'll
also write as the other Python patches are in.
Here's an example session:
(gdb)
-var-set-type-visualizer std::vector.* VectorVisualizer
^done
....
~"11\t std::vector<int> v;\n"
....
~"12\t v.push_back (7);\n"
^done
(gdb)
-var-create V * v
^done,name="V",numchild="1",value="{...}",type="std::vector<int,std::allocator<int> >",thread-id="1"
(gdb)
-var-list-children V
^done,numchild="0"
(gdb)
next
&"next\n"
~"13\t v[0] = 11;\n"
^done
(gdb)
-var-update --all-values V
^done,changelist=[{name="V",value="{...}",in_scope="true",type_changed="false",children=[{name="V.0",exp="0",numchild="0",value="7",type="int",thread-id="1"}]}]
(gdb)
The .gdbinit I use is also attached.
- Volodya
[-- Attachment #2: 0001-Refactor-varobj_update-interface.patch --]
[-- Type: application/mbox, Size: 12073 bytes --]
[-- Attachment #3: 0002-Implement-Python-based-computation-of-varobj-childre.patch --]
[-- Type: application/mbox, Size: 29338 bytes --]
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #4: .gdbinit --]
[-- Type: text/x-java; name=".gdbinit", Size: 740 bytes --]
python
class StringVisualizer:
def to_string (self, v):
# FIXME: catch any exceptions accessing bogus memory
data = v.get_element ("_M_dataplus")
return str (data.get_element ("_M_p"))
class VectorVisualizer:
def children (self, v):
result = []
impl = v.get_element ('_M_impl')
start = impl.get_element ('_M_start')
finish = impl.get_element ('_M_finish')
current = start
index = 0
while not current.equals(finish):
result.append((str(index), current.dereference()))
current = current.increment(1)
index = index + 1
return result
end
#interpreter-exec mi2 "-var-set-type-visualizer string StringVisualizer"
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 1/9] initial Python support
2008-04-29 18:15 ` [RFC][patch 1/9] initial Python support Thiago Jung Bauermann
@ 2008-05-05 8:12 ` Thiago Jung Bauermann
2008-05-05 14:39 ` Daniel Jacobowitz
2008-05-29 0:29 ` Daniel Jacobowitz
1 sibling, 1 reply; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-05-05 8:12 UTC (permalink / raw)
To: gdb-patches
On Tue, 2008-04-29 at 12:52 -0300, Thiago Jung Bauermann wrote:
> There are two caveats with the configure.ac changes: one is that they
> trigger a bug in autoconf 2.59 when library names contain a dot
> (e.g., libpython2.5). I regenerated the configure script using
> autoconf 2.61, but the proper way to fix this at the moment (since we
> must use version 2.59) is to backport the fix using the
> config/override.m4 mechanism. I didn't look into that yet.
With the patch below I was able to work around the bug. It adds a
version of autoconf 2.59's AC_ARG_WITH to config/override.m4, with the
following fix:
# Check whether --with-$1 or --without-$1 was given.
-if test "[${with_]m4_bpatsubst([$1], -, _)+set}" = set; then
- withval="[$with_]m4_bpatsubst([$1], -, _)"
+if test "[${with_]m4_translit([$1], [.-], [__])+set}" = set; then
+ withval="[$with_]m4_translit([$1], [.-], [__])"
The problem affects only the --with-libpython2.5-prefix configure
option. Without the fix, configure won't even run to completion because
it contains a syntax error (variable name with dot in it). With the fix,
configure works, but said configure option doesn't:
% ../configure --with-libpython2.5-prefix=/blah
configure: error: invalid package name: libpython2.5-prefix
I looked into fixing that problem, but this would require overriding
_AC_INIT_PARSE_ARGS which is a very big macro in autoconf 2.59. Is it
worth doing that?
Note that --with-python and --without-python work as expected.
> The other caveat is that I had trouble with gnulib configure script
> when using this patch. I didn't investigate the issue yet, and to test
> this code I removed gnulib from the compilation. Maybe I didn't
> regenerate the configure scripts properly.
The fix to that is running aclocal with -I gnulib/m4, as Daniel noted on
the IRC channel.
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
diff --git a/config/override.m4 b/config/override.m4
index 592f641..38fc101 100644
--- a/config/override.m4
+++ b/config/override.m4
@@ -189,3 +189,23 @@ if $ac_cache_corrupted; then
fi
])# _AC_ARG_VAR_VALIDATE
])])
+
+ifelse(m4_PACKAGE_VERSION, [2.59], [
+
+# AC_ARG_WITH(PACKAGE, HELP-STRING, ACTION-IF-TRUE, [ACTION-IF-FALSE])
+# --------------------------------------------------------------------
+AC_DEFUN([AC_ARG_WITH],
+[m4_divert_once([HELP_WITH], [[
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)]])
+m4_divert_once([HELP_WITH], [$2])dnl
+# Check whether --with-$1 or --without-$1 was given.
+if test "[${with_]m4_translit([$1], [.-], [__])+set}" = set; then
+ withval="[$with_]m4_translit([$1], [.-], [__])"
+ $3
+m4_ifvaln([$4], [else
+ $4])dnl
+fi; dnl
+])# AC_ARG_WITH
+])
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 1/9] initial Python support
2008-05-05 8:12 ` Thiago Jung Bauermann
@ 2008-05-05 14:39 ` Daniel Jacobowitz
2008-05-05 14:46 ` Thiago Jung Bauermann
0 siblings, 1 reply; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-05-05 14:39 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
On Mon, May 05, 2008 at 01:50:38AM -0300, Thiago Jung Bauermann wrote:
> % ../configure --with-libpython2.5-prefix=/blah
> configure: error: invalid package name: libpython2.5-prefix
Do we even want this option? The macro it comes from has been
surprisingly troublesome and is very complicated. Maybe we just want
--with-python, --without-python, and --with-python=/path.
BTW, could you do me a favor... make GDB fail to build if
--with-python is specified on the command line but Python could not be
found. This is something I learned from working on Debian package
builds and our own Sourcery G++ product builds. Autoconf
configuration is not so good at producing consistent packages
build after build. IMO the default should be "use python if
we find it", but with --with-python it should be "use python or go
boom".
Anyway, </soapbox>.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 1/9] initial Python support
2008-05-05 14:39 ` Daniel Jacobowitz
@ 2008-05-05 14:46 ` Thiago Jung Bauermann
2008-05-05 16:50 ` Daniel Jacobowitz
0 siblings, 1 reply; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-05-05 14:46 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb-patches
On Mon, 2008-05-05 at 09:10 -0400, Daniel Jacobowitz wrote:
> On Mon, May 05, 2008 at 01:50:38AM -0300, Thiago Jung Bauermann wrote:
> > % ../configure --with-libpython2.5-prefix=/blah
> > configure: error: invalid package name: libpython2.5-prefix
>
> Do we even want this option?
I don't care much about it...
> Maybe we just want
> --with-python, --without-python, and --with-python=/path.
The last one isn't implemented by the AC_ARG_WITH option, IIUC. I'd have
to explicitly implement it. Would it work work just like
--with-libpython2.5-prefix? Why would it be less problematic and less
complicated?
> BTW, could you do me a favor... make GDB fail to build if
> --with-python is specified on the command line but Python could not be
> found.
That's how I made it.
> IMO the default should be "use python if
> we find it", but with --with-python it should be "use python or go
> boom".
% ../src/configure --with-python
[big snip]
checking whether to use python... yes
checking for libpython2.5... no
checking for libpython2.4... no
configure: error: python is missing or unusable
make[1]: *** [configure-gdb] Error 1
make[1]: Leaving directory `/tmp/master-build'
make: *** [all] Error 2
Boom.
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 1/9] initial Python support
2008-05-05 14:46 ` Thiago Jung Bauermann
@ 2008-05-05 16:50 ` Daniel Jacobowitz
2008-05-06 2:38 ` Thiago Jung Bauermann
2008-05-11 22:24 ` Thiago Jung Bauermann
0 siblings, 2 replies; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-05-05 16:50 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
On Mon, May 05, 2008 at 11:06:20AM -0300, Thiago Jung Bauermann wrote:
> > Maybe we just want
> > --with-python, --without-python, and --with-python=/path.
>
> The last one isn't implemented by the AC_ARG_WITH option, IIUC. I'd have
> to explicitly implement it.
Right.
> Would it work work just like --with-libpython2.5-prefix? Why would
> it be less problematic and less complicated?
Take a look at config/lib-link.m4 and config/lib-prefix.m4. Then
compare to --with-mpfr and --with-mpfr-lib in the top level
configure.ac. Notice that they're about a hundredth of the size.
The top level also chose to use multiple options so maybe that's
wise after all. But anyway that lets us have --with-python-lib
and --with-python-include, avoiding the version-specific options.
The versions in config handle all sorts of complicated extra
scenarios. But they're pretty rare and there's others that aren't
handled. One which adds -L${withval}/lib and -I${withval}/include
works 99% of the time, and the user can fiddle CFLAGS/LDFLAGS for
the other cases.
I may rip out the existing uses, though we'll have to keep the long
option names for compatibility.
> That's how I made it.
Thanks!
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 1/9] initial Python support
2008-05-05 16:50 ` Daniel Jacobowitz
@ 2008-05-06 2:38 ` Thiago Jung Bauermann
2008-05-11 22:24 ` Thiago Jung Bauermann
1 sibling, 0 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-05-06 2:38 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb-patches
On Mon, 2008-05-05 at 10:46 -0400, Daniel Jacobowitz wrote:
> On Mon, May 05, 2008 at 11:06:20AM -0300, Thiago Jung Bauermann wrote:
> > Would it work work just like --with-libpython2.5-prefix? Why would
> > it be less problematic and less complicated?
>
> Take a look at config/lib-link.m4 and config/lib-prefix.m4. Then
> compare to --with-mpfr and --with-mpfr-lib in the top level
> configure.ac.
Thanks for the pointers. I'll take a look at those and try to come up
with something.
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 1/9] initial Python support
2008-05-05 16:50 ` Daniel Jacobowitz
2008-05-06 2:38 ` Thiago Jung Bauermann
@ 2008-05-11 22:24 ` Thiago Jung Bauermann
2008-05-11 22:26 ` Daniel Jacobowitz
1 sibling, 1 reply; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-05-11 22:24 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb-patches
On Mon, 2008-05-05 at 10:46 -0400, Daniel Jacobowitz wrote:
> On Mon, May 05, 2008 at 11:06:20AM -0300, Thiago Jung Bauermann wrote:
> > > Maybe we just want
> > > --with-python, --without-python, and --with-python=/path.
> >
> > The last one isn't implemented by the AC_ARG_WITH option, IIUC. I'd have
> > to explicitly implement it.
>
> Right.
I just noticed that configure doesn't offer -prefix, -include or -lib
options to any of the libraries GDB currently uses, including recently
added ones. Does it have to be different for the Python library?
> One which adds -L${withval}/lib and -I${withval}/include
> works 99% of the time, and the user can fiddle CFLAGS/LDFLAGS for
> the other cases.
Perhaps fiddling with CFLAGS/LDFLAGS is enough anyway?
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 1/9] initial Python support
2008-05-11 22:24 ` Thiago Jung Bauermann
@ 2008-05-11 22:26 ` Daniel Jacobowitz
2008-05-12 20:33 ` Thiago Jung Bauermann
0 siblings, 1 reply; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-05-11 22:26 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
On Sun, May 11, 2008 at 06:46:01PM -0300, Thiago Jung Bauermann wrote:
> I just noticed that configure doesn't offer -prefix, -include or -lib
> options to any of the libraries GDB currently uses, including recently
> added ones. Does it have to be different for the Python library?
No. Add whichever is most convenient, I think.
> Perhaps fiddling with CFLAGS/LDFLAGS is enough anyway?
I've no opinion.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 1/9] initial Python support
2008-05-11 22:26 ` Daniel Jacobowitz
@ 2008-05-12 20:33 ` Thiago Jung Bauermann
2008-05-12 20:39 ` Daniel Jacobowitz
0 siblings, 1 reply; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-05-12 20:33 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb-patches
On Sun, 2008-05-11 at 17:51 -0400, Daniel Jacobowitz wrote:
> > Perhaps fiddling with CFLAGS/LDFLAGS is enough anyway?
>
> I've no opinion.
Well, if nobody has a good enough reason, I'll leave it at that, then.
The patch 1 in the python series plus the config/override.m4 patch I
posted in this thread are all that should be needed configure-wise,
IMHO.
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 1/9] initial Python support
2008-05-12 20:33 ` Thiago Jung Bauermann
@ 2008-05-12 20:39 ` Daniel Jacobowitz
2008-05-12 21:00 ` Thiago Jung Bauermann
0 siblings, 1 reply; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-05-12 20:39 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
On Mon, May 12, 2008 at 01:00:33PM -0300, Thiago Jung Bauermann wrote:
> The patch 1 in the python series plus the config/override.m4 patch I
> posted in this thread are all that should be needed configure-wise,
> IMHO.
Sorry, but I was just talking about how to specify paths :-(
I don't think the --with-python2.5, --with-python2.4 options are a
good idea. How about --with-python=2.5 and search CPPFLAGS/LDFLAGS
for that version?
--with-python unspecified: use it if we find it
--with-python: use it if we find it, else fail. Try 2.5 then 2.4.
--without-python: no python
--with-python=2.5: only try 2.5; else fail
How does that sound?
No need to rework the patch right now if you don't want; I need to
look at the rest of it still :-)
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 1/9] initial Python support
2008-05-12 20:39 ` Daniel Jacobowitz
@ 2008-05-12 21:00 ` Thiago Jung Bauermann
0 siblings, 0 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-05-12 21:00 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb-patches
On Mon, 2008-05-12 at 12:11 -0400, Daniel Jacobowitz wrote:
> On Mon, May 12, 2008 at 01:00:33PM -0300, Thiago Jung Bauermann wrote:
> > The patch 1 in the python series plus the config/override.m4 patch I
> > posted in this thread are all that should be needed configure-wise,
> > IMHO.
>
> Sorry, but I was just talking about how to specify paths :-(
Ah, ok. I had misunderstood.
> I don't think the --with-python2.5, --with-python2.4 options are a
> good idea.
Me neither, but they will be there as a byproduct of the AC_ macros
being used... Can we just pretend they don't exist?
> How about --with-python=2.5 and search CPPFLAGS/LDFLAGS
> for that version?
>
>
> --with-python unspecified: use it if we find it
> --with-python: use it if we find it, else fail. Try 2.5 then 2.4.
> --without-python: no python
> --with-python=2.5: only try 2.5; else fail
>
> How does that sound?
I liked that, because if you have both installed in the standard places,
you can still control which one the build will pick up. In the previous
scheme you had to have (say) 2.4 installed in a separate prefix if you
wanted to use that.
> No need to rework the patch right now if you don't want; I need to
> look at the rest of it still :-)
Nice. I'll wait the next slot in my copious free time then. :-)
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 3/9] export hooks mechanism to Python
2008-04-30 21:30 ` Tom Tromey
@ 2008-05-27 18:22 ` Tom Tromey
0 siblings, 0 replies; 147+ messages in thread
From: Tom Tromey @ 2008-05-27 18:22 UTC (permalink / raw)
To: Thiago Jung Bauermann, gdb-patches
>>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:
Joel> Since you need to be able to write some python code that "reacts to
Joel> *GDB events*", I think that observers are exactly what you are looking
Joel> for.
Tom> Thanks, I will look at that.
In case anybody is wondering about the status of this, today I changed
the Python support to use observers rather than events. I deleted
some old event-based stuff that I think was not in use, and added a
couple observers.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 1/9] initial Python support
2008-04-29 18:15 ` [RFC][patch 1/9] initial Python support Thiago Jung Bauermann
2008-05-05 8:12 ` Thiago Jung Bauermann
@ 2008-05-29 0:29 ` Daniel Jacobowitz
2008-05-30 13:07 ` Function syntax (Was: [RFC][patch 1/9] initial Python support) Tom Tromey
` (2 more replies)
1 sibling, 3 replies; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-05-29 0:29 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
Looks generally good.
For the general syntax: Should we allow $() to always mean Python, or
are there other useful potential scripting interfaces or environment
variable access or anything, in which case we want $(python ) or $(P )
or $python( )? There are only so many nice grouping specifiers. $<>
is not so good but we still have $[] and ${}, plus $env(). I don't
remember if we discussed this before, but we may have.
On Tue, Apr 29, 2008 at 12:52:13PM -0300, Thiago Jung Bauermann wrote:
> There are two caveats with the configure.ac changes: one is that they
> trigger a bug in autoconf 2.59 when library names contain a dot
> (e.g., libpython2.5). I regenerated the configure script using
> autoconf 2.61, but the proper way to fix this at the moment (since we
> must use version 2.59) is to backport the fix using the
> config/override.m4 mechanism. I didn't look into that yet.
We've discussed already the configure options - I'd prefer to avoid
this issue and only have --with-python and maybe
--with-python-lib/--with-python-include. Parallel to the top level
gmp/mpfr handling, for instance.
I didn't know about python-config. Is that new? Could we specify a
path to python-config instead of messing with cflags/ldflags directly?
> The other caveat is that I had trouble with gnulib configure script
> when using this patch. I didn't investigate the issue yet, and to test
> this code I removed gnulib from the compilation. Maybe I didn't
> regenerate the configure scripts properly.
And we sorted this out on IRC.
The special_processing argument to read_next_line / read_command_lines
is not commented and the name doesn't say much of anything about what
it's for. It looks like this changes the behavior of document versus
define, probably deliberately if it does what I think it does. So
this would be a good patch to split out separately. In general, any
bits that can go in separately should; it makes the whole pile easier
to manage :-)
> Index: tromey.git/gdb/c-exp.y
> ===================================================================
> --- tromey.git.orig/gdb/c-exp.y 2008-04-29 10:57:39.000000000 -0300
> +++ tromey.git/gdb/c-exp.y 2008-04-29 10:58:06.000000000 -0300
> @@ -1636,6 +1636,31 @@ yylex ()
> /* We must have come across a bad character (e.g. ';'). */
> error ("Invalid character '%c' in expression.", c);
>
> + if (c == '$' && tokstart[1] == '(')
> + {
> + /* Convenience function call. */
> + int cparen_depth = 0;
> + int i;
> + for (i = 1; tokstart[i]; ++i)
> + {
> + if (tokstart[i] == '(')
> + ++cparen_depth;
> + else if (tokstart[i] == ')')
> + {
> + if (--cparen_depth == 0)
> + break;
> + }
> + }
> + if (cparen_depth != 0)
> + error ("Unmatched parentheses in convenience function invocation.");
> + yylval.sval.ptr = &tokstart[2];
> + yylval.sval.length = i - 2;
> + write_dollar_funcall (yylval.sval);
> + lexptr = &tokstart[i + 1];
> + /* FIXME: not exactly right. */
> + return VARIABLE;
> + }
> +
VARIABLE seems fine. The parenthesis handling is a little hokey
because we do not lex the body of the scripting expression; you can't
use ')' or '(' unmatched in the expression... I'm not sure we can do
better.
> Index: tromey.git/gdb/cli/cli-script.c
> ===================================================================
> --- tromey.git.orig/gdb/cli/cli-script.c 2008-04-29 10:57:39.000000000 -0300
> +++ tromey.git/gdb/cli/cli-script.c 2008-04-29 11:03:58.000000000 -0300
> @@ -34,6 +34,10 @@
> #include "cli/cli-script.h"
> #include "gdb_assert.h"
>
> +#ifdef HAVE_PYTHON
> +#include "python/python.h"
> +#endif
> +
There are too many #ifdef's in the rest of GDB in this patch, IMO.
Can python/python.h be included unconditionally, not include
python-internal.h, and have the exposed interfaces error() when Python
support is not compiled in? That's the approach I took for
xml-support.h.
Similarly we should recognize python_control regardless of
HAVE_PYTHON. That way we can parse a .gdbinit which defines Python
commands and give a sensible error only if they are invoked.
> +#ifdef HAVE_PYTHON
> + {
> + eval_python_from_control_command (cmd);
> + ret = simple_control;
> + break;
> + }
> +#else
> + warning (_("Python scripting is not supported in this copy of GDB."));
> + break;
> +#endif
So, e.g., this would be error() but it would be pushed into
eval_python_from_control_command.
> + /* FIXME: handling noside == EVAL_AVOID_SIDE_EFFECTS? */
> + if (noside == EVAL_SKIP)
> + goto nosideret;
> + return value_of_python (&exp->elts[pc + 2].string, tem);
I think either a void value, or an error, for EVAL_AVOID_SIDE_EFFECTS.
If we need more we can return to it later.
> +/* Use this after a TRY_EXCEPT to throw the appropriate Python
> + exception. FIXME: throw different errors depending on
> + Exception.error? */
> +#define GDB_PY_HANDLE_EXCEPTION(Exception)
Yes, at some point it seems like we will want some Python exceptions
corresponding to memory read errors and so forth... no need for that
now, though.
In general I would prefer we not commit any FIXMEs. We can decide now
what the right thing to do is and if there is room for future
enhancement, that's not a FIXME any more :-)
> +
> +void
> +demand_python ()
Most functions need a comment. Also, please (void) instead of ().
> +static char *
> +compute_python_string (struct command_line *l)
> +{
> + char *script = NULL;
> + for (;l; l = l->next)
> + {
> + /* FIXME: inefficient. */
> + if (script)
> + {
> + char *save = script;
> + script = concat (script, l->line, "\n", NULL);
> + xfree (save);
> + }
> + else
> + script = concat (l->line, "\n", NULL);
> + }
> + return script;
> +}
So, fix it... :-)
> +
> +void
> +eval_python_from_control_command (struct command_line *cmd)
> +{
> + char *script;
> +
> + if (cmd->body_count != 1)
> + error (_("Invalid \"python\" block structure."));
> +
> + demand_python ();
> +
> + script = compute_python_string (cmd->body_list[0]);
> + PyRun_SimpleString (script);
> + xfree (script);
> + if (PyErr_Occurred ())
> + {
> + PyErr_Print ();
> + error ("error while executing Python code");
> + }
> +}
_() around arguments to error. Also, in general PyErr_Print is
probably dumping to stderr? Output should go through GDB's error
mechanisms, and in this case probably be part of the argument to
error. Can you get it to return an error string instead?
python_command can share the code in execute_control_command; see
if_command for a similar case.
> + return PyString_Decode (str, strlen (str), host_charset (),
> + NULL /* FIXME */);
Yes, do fix it :-)
> + case var_integer:
> + case var_zinteger:
> + return PyLong_FromLong (* (int *) cmd->var);
> +
> + case var_uinteger:
> + return PyLong_FromUnsignedLong (* (unsigned int *) cmd->var);
uinteger and integer both have sentinel values; you used None for auto
booleans so it is probably appropriate here too.
> +static PyObject *
> +execute_gdb_command (PyObject *self, PyObject *args)
> +{
> + struct cmd_list_element *alias, *prefix, *cmd;
> + char *arg, *newarg;
> + volatile struct gdb_exception except;
> +
> + if (! PyArg_ParseTuple (args, "s", &arg))
> + return NULL;
> +
> + TRY_CATCH (except, RETURN_MASK_ALL)
> + {
> + execute_command (arg, 0);
> + }
> + GDB_PY_HANDLE_EXCEPTION (except);
> +
> + /* gdbtk does bpstat_do_actions here... */
Please figure out if we need to or not. It looks like we do; running
the command "continue" to a breakpoint with actions will test it.
Speaking of which... a testsuite? :-)
> + result = PyRun_String (expr, Py_eval_input, global, NULL);
> + /* FIXME: do we need a decref here? */
> + if (PyErr_Occurred ())
> + {
> + /* FIXME -- probably should not do this. */
> + PyErr_Print ();
> + error ("python error while evaluating expression");
> + }
Fix? And various other things in this function.
> + add_com ("python", class_obscure, python_command, _("\
> +Blah, blah, blah."));
...
> +#include "defs.h"
> +#include "value.h"
No need for defs.h in a header; it's always included already and every
source file should include it explicitly.
> Index: tromey.git/gdb/value.h
> ===================================================================
> --- tromey.git.orig/gdb/value.h 2008-04-29 10:57:39.000000000 -0300
> +++ tromey.git/gdb/value.h 2008-04-29 10:58:06.000000000 -0300
> @@ -434,6 +434,8 @@ extern LONGEST parse_and_eval_long (char
>
> extern struct value *access_value_history (int num);
>
> +extern struct value *value_of_python (char *exp, int length);
> +
> extern struct value *value_of_internalvar (struct internalvar *var);
>
> extern void set_internalvar (struct internalvar *var, struct value *val);
All considered, probably belongs in python.h.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 2/9] export values mechanism to Python
2008-04-29 18:17 ` [RFC][patch 2/9] export values mechanism to Python Thiago Jung Bauermann
@ 2008-05-29 1:23 ` Daniel Jacobowitz
2008-06-03 0:19 ` Tom Tromey
0 siblings, 1 reply; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-05-29 1:23 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
On Tue, Apr 29, 2008 at 12:52:14PM -0300, Thiago Jung Bauermann wrote:
> +python-value.o: $(srcdir)/python/value.c $(defs_h) $(exceptions_h) \
> + $(python_internal_h) $(value_h)
> + $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
> + $(srcdir)/python/value.c -o python-value.o
A little indentation (extra two spaces?) on that last line.
Comments for the new functions / variables. Either in the header or
at the definition or both, as you prefer, but there need to be more
comments in this code.
> + { "make_value_from_int", gdbpy_make_value_from_int, METH_VARARGS,
> + "Make a value from int" },
Do we need make_value_from_int or just make_value (that could also
handle e.g. a string)?
> +static PyObject * valpy_lazy_p (PyObject *self, PyObject *args);
> +static PyObject * valpy_fetch_lazy (PyObject *self, PyObject *args);
> +static PyObject * valpy_common_print (PyObject *self, PyObject *args);
Stray spaces after *.
> +
> +static PyMethodDef value_object_methods[] = {
> + { "dereference", valpy_dereference, METH_NOARGS, "Dereferences the value." },
> + { "get_element", valpy_get_element, METH_VARARGS,
> + "Obtains element inside value." },
Would it be helpful or confusing to automatically expose this as [] in
Python, __getitem__?
> + { "increment", valpy_increment, METH_VARARGS,
> + "Increment value by the given amount." },
Since the amount is specified, this is add rather than increment.
Same question as above; it could be __add__.
> + { "equals", valpy_equal_p, METH_VARARGS, "Compare values." },
Similarly, __eq__.
> + { "is_lazy", valpy_lazy_p, METH_NOARGS,
> + "Returns True if the value is lazy, False if not." },
> + { "fetch_lazy", valpy_fetch_lazy, METH_NOARGS,
> + "Fetches value from inferior memory." },
Do you have an example where these are useful? I think of them as an
implementation detail of values.
> + { "common_print", valpy_common_print, METH_VARARGS, "Prints
> value." },
__str__? And maybe we want __repr__. If any of the options to
common_print are useful, we can have "print"; I think that's better
than common_print which is an artifact of GDB's history.
> +
> +/* FIXME: copy paste from varobj.c */
> +static char *
> +value_get_print_value (struct value *value)
Yes, do fix :-) Does it need to move to a value-related file instead
of varobj.c?
> +/* A value owned by GDB is in the all_values chain, so it will be freed
> + automatically when not needed anymore (i.e., before the current command
> + completes). */
> +PyObject *
> +gdb_owned_value_to_value_object (struct value *v)
> +{
> + value_object *result = PyObject_New (value_object, &value_object_type);
> + if (result != NULL)
> + {
> + result->value = v;
> + result->owned_by_gdb = 1;
> + /* FIXME: should we do it? What is it? */
> + /* I don't think it is needed, since a GDB owned value has a very short
> + lifetime. The purpose of the list is explained in the comment above
> + its declaration. -- bauermann */
> + value_prepend_to_list (&values_in_python, v);
> + }
> + return (PyObject *)result;
> +}
What is this function used for in later patches? It seems dangerous
to me. GDB is going to discard the value and Python might still have
a reference to it after it's free'd. If this is really necessary, we
can reference-count values.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 3/9] export hooks mechanism to Python
2008-04-29 15:59 ` [RFC][patch 3/9] export hooks mechanism " Thiago Jung Bauermann
2008-04-29 21:29 ` Tom Tromey
@ 2008-05-29 7:55 ` Daniel Jacobowitz
2008-05-30 14:59 ` Tom Tromey
1 sibling, 1 reply; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-05-29 7:55 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
On Tue, Apr 29, 2008 at 12:52:15PM -0300, Thiago Jung Bauermann wrote:
> 2008-04-29 Tom Tromey <tromey@redhat.com>
>
> * Makefile.in (SUBDIR_PYTHON_OBS): Add python-hooks.o.
> (SUBDIR_PYTHON_SRCS): Add python/hooks.c.
> (python-hooks.o): New target.
> * interps.c (interp_set): Don't call clear_interpreter_hooks.
> [Temporary hack].
> * python/hooks.c: New file.
> * python/python-internal.h (variable_to_python,
> gdbpy_get_hook_function, gdbpy_initialize_hooks): Declare.
> * python/python.c (demand_python): Call gdbpy_initialize_hooks.
I won't look at this one, as I believe Tom's rewritten it to use
observers instead.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Function syntax (Was: [RFC][patch 1/9] initial Python support)
2008-05-29 0:29 ` Daniel Jacobowitz
@ 2008-05-30 13:07 ` Tom Tromey
2008-06-08 15:24 ` Doug Evans
2008-06-08 18:21 ` Function syntax (Was: [RFC][patch 1/9] initial Python support) Daniel Jacobowitz
2008-05-30 14:47 ` [RFC][patch 1/9] initial Python support Tom Tromey
2008-06-15 22:35 ` thiagoju
2 siblings, 2 replies; 147+ messages in thread
From: Tom Tromey @ 2008-05-30 13:07 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
I think this response should be its own thread.
Daniel> For the general syntax: Should we allow $() to always mean Python, or
Daniel> are there other useful potential scripting interfaces or environment
Daniel> variable access or anything, in which case we want $(python ) or $(P )
Daniel> or $python( )? There are only so many nice grouping specifiers. $<>
Daniel> is not so good but we still have $[] and ${}, plus $env(). I don't
Daniel> remember if we discussed this before, but we may have.
Recently I've been thinking that $(...) should not simply eval the
'...' as a python expression. Instead, I'm leaning more toward a
function registry approach. I have two reasons for this.
First, pure Python syntax is somewhat clunky for the gdb user. E.g.,
I used this to make a breakpoint conditional on the calling function:
cond 1 $(gdb.current_frame().get_prev().get_name() == "declspecs_add_type")
That's a lot of "()" for a pretty simple action.
Instead, we could provide little helper functions and get:
cond 1 $(caller-is "declspecs_add_type")
The second reason is that with explicit registration and function
objects (like the existing command objects) we could allow nicer
completion inside the $(...).
We can always provide a function named "python" to eval its argument.
As to some of the other things you mentioned:
* I agree with the lexing point. I think we could specify some
standardized quoting and dequote before passing the argument to the
underlying code.
* I don't want to use $python(...) -- but I was wondering, doesn't
this already have a meaning if 'python' happens to be a
function-pointer-valued convenience variable?
* I don't think we should worry about supporting any scripting
language other than Python. Stuff like getenv access or reflective
access to gdb 'set' variables can all be done via the python code.
Anyway, the explicit-function-registration approach leaves open the
possibility of built-in functions written in other ways.
I suppose my basic proposal is that all functions be derived from
something like:
class Function:
# ARG is a string, already de-quoted and whitespace-stripped.
def invoke(self, arg):
do something
def complete(self, text, word):
complete the argument
This is basically exactly what we do for commands, only in the
Function case we could expect invoke to return a value.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 1/9] initial Python support
2008-05-29 0:29 ` Daniel Jacobowitz
2008-05-30 13:07 ` Function syntax (Was: [RFC][patch 1/9] initial Python support) Tom Tromey
@ 2008-05-30 14:47 ` Tom Tromey
2008-06-15 22:35 ` thiagoju
2 siblings, 0 replies; 147+ messages in thread
From: Tom Tromey @ 2008-05-30 14:47 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
>>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
I've checked in fixes for a lot of the comments you've made. Thanks
for taking the time. It is clear we still have a lot to do.
Here, I've only commented on specific things requiring comment.
>> +#ifdef HAVE_PYTHON
>> +#include "python/python.h"
>> +#endif
Daniel> There are too many #ifdef's in the rest of GDB in this patch,
Daniel> IMO. Can python/python.h be included unconditionally, not
Daniel> include python-internal.h, and have the exposed interfaces
Daniel> error() when Python support is not compiled in?
I didn't touch Volodya's MI/varobj code, but I did the rest of this.
Daniel> In general I would prefer we not commit any FIXMEs. We can
Daniel> decide now what the right thing to do is and if there is room
Daniel> for future enhancement, that's not a FIXME any more :-)
Ok. I'm working my way through the new ones. Thiago, Volodya --
please look through the code you've written on the branch :-)
Daniel> Also, in general PyErr_Print is probably dumping to stderr?
Daniel> Output should go through GDB's error mechanisms, and in this
Daniel> case probably be part of the argument to error. Can you get
Daniel> it to return an error string instead?
Good question. I looked at the implementation of PyErr_Print, but it
is ~100 lines of C. That's kind of a lot to copy.
We can probably get just the exception's text -- without the entire
stack trace -- fairly easily. I will have to look into this.
Or, I think we can set sys.stderr and dump the exception, including
the whole trace, wherever we like. This may be more fragile. And, it
isn't clear to me that we want or need the whole trace.
Daniel> Speaking of which... a testsuite? :-)
Yeah -- we definitely need both a testsuite and documentation.
I'd guess we are all avoiding this.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 3/9] export hooks mechanism to Python
2008-05-29 7:55 ` Daniel Jacobowitz
@ 2008-05-30 14:59 ` Tom Tromey
2008-06-15 22:53 ` Thiago Jung Bauermann
0 siblings, 1 reply; 147+ messages in thread
From: Tom Tromey @ 2008-05-30 14:59 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
>>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
Daniel> I won't look at this one, as I believe Tom's rewritten it to use
Daniel> observers instead.
Yeah, that's right.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 2/9] export values mechanism to Python
2008-05-29 1:23 ` Daniel Jacobowitz
@ 2008-06-03 0:19 ` Tom Tromey
2008-06-03 13:04 ` Daniel Jacobowitz
2008-07-07 6:03 ` Thiago Jung Bauermann
0 siblings, 2 replies; 147+ messages in thread
From: Tom Tromey @ 2008-06-03 0:19 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
>>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
Daniel> Would it be helpful or confusing to automatically expose this
Daniel> as [] in Python, __getitem__?
Good question.
In general I've been using explicit method names, like get_* and
set_*. But perhaps we should be using attributes and various
"intrinsic" names... I'm not enough of a Python expert to know what is
preferred.
Also, about the varobj patch in particular: I notice that it is
MI-specific. At least for type visualizers I think I would like
something that works with 'print' as well. I'm thinking:
* A way to register a type->object mapping from Python
* A new method on the Python object (if needed -- I'm not an expert in
this area) to return the 'print' form of the value. (If a new
method is needed this, I think, implies that we should not use
__str__ here.)
* Modifications to 'print' and friends
* A new 'raw' format to print to let us bypass the custom printer and
just show whatever the language defaults to.
Let me know what you think of this general plan.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 2/9] export values mechanism to Python
2008-06-03 0:19 ` Tom Tromey
@ 2008-06-03 13:04 ` Daniel Jacobowitz
2008-06-03 14:52 ` Tom Tromey
2008-07-07 6:03 ` Thiago Jung Bauermann
1 sibling, 1 reply; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-06-03 13:04 UTC (permalink / raw)
To: gdb-patches
On Mon, Jun 02, 2008 at 06:18:59PM -0600, Tom Tromey wrote:
> >>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
>
> Daniel> Would it be helpful or confusing to automatically expose this
> Daniel> as [] in Python, __getitem__?
>
> Good question.
>
> In general I've been using explicit method names, like get_* and
> set_*. But perhaps we should be using attributes and various
> "intrinsic" names... I'm not enough of a Python expert to know what is
> preferred.
Anyone else got a preference?
> Also, about the varobj patch in particular: I notice that it is
> MI-specific. At least for type visualizers I think I would like
> something that works with 'print' as well. I'm thinking:
>
> * A way to register a type->object mapping from Python
I'm not sure what you mean. Type to what object?
An interesting question is how to access sub-pieces of a value from
the CLI. If we pretty-print something as a map, how should the user
get (A) the values, and (B) the fields of the raw representation of
the map?
I think we need a UI before we worry about the innards.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 2/9] export values mechanism to Python
2008-06-03 13:04 ` Daniel Jacobowitz
@ 2008-06-03 14:52 ` Tom Tromey
0 siblings, 0 replies; 147+ messages in thread
From: Tom Tromey @ 2008-06-03 14:52 UTC (permalink / raw)
To: gdb-patches
>>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
>> * A way to register a type->object mapping from Python
Daniel> I'm not sure what you mean. Type to what object?
Sorry -- I mean a way to map a gdb 'struct type *' to the Python
object which will handle printing objects of that type.
Daniel> An interesting question is how to access sub-pieces of a value from
Daniel> the CLI. If we pretty-print something as a map, how should the user
Daniel> get (A) the values, and (B) the fields of the raw representation of
Daniel> the map?
Yeah, good question.
Daniel> I think we need a UI before we worry about the innards.
Ok.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: Function syntax (Was: [RFC][patch 1/9] initial Python support)
2008-05-30 13:07 ` Function syntax (Was: [RFC][patch 1/9] initial Python support) Tom Tromey
@ 2008-06-08 15:24 ` Doug Evans
2008-06-08 15:32 ` Function syntax Tom Tromey
2008-06-08 18:21 ` Function syntax (Was: [RFC][patch 1/9] initial Python support) Daniel Jacobowitz
1 sibling, 1 reply; 147+ messages in thread
From: Doug Evans @ 2008-06-08 15:24 UTC (permalink / raw)
To: tromey; +Cc: Thiago Jung Bauermann, gdb-patches
On Thu, May 29, 2008 at 1:29 PM, Tom Tromey <tromey@redhat.com> wrote:
> I suppose my basic proposal is that all functions be derived from
> something like:
>
> class Function:
> # ARG is a string, already de-quoted and whitespace-stripped.
> def invoke(self, arg):
> do something
>
> def complete(self, text, word):
> complete the argument
>
> This is basically exactly what we do for commands, only in the
> Function case we could expect invoke to return a value.
IWBN if this also included some help text that was somehow hooked into
help/apropos. [maybe as fhelp, fapropos, or some such]
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: Function syntax
2008-06-08 15:24 ` Doug Evans
@ 2008-06-08 15:32 ` Tom Tromey
0 siblings, 0 replies; 147+ messages in thread
From: Tom Tromey @ 2008-06-08 15:32 UTC (permalink / raw)
To: Doug Evans; +Cc: Thiago Jung Bauermann, gdb-patches
>>>>> "Doug" == Doug Evans <dje@google.com> writes:
Doug> IWBN if this also included some help text that was somehow hooked into
Doug> help/apropos. [maybe as fhelp, fapropos, or some such]
Yeah, good idea.
For Commands we already extract the Python docstring and present it
to the user as the help for the command.
Doing something similar for registered functions should be pretty easy.
FWIW I went ahead and changed the function syntax in the python
repository last week or so. There is just a single built-in function
named "python" which evaluates its argument.
I did not try to change lexing of the text in $(...). It would be
nice to have a consensus on that.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: Function syntax (Was: [RFC][patch 1/9] initial Python support)
2008-05-30 13:07 ` Function syntax (Was: [RFC][patch 1/9] initial Python support) Tom Tromey
2008-06-08 15:24 ` Doug Evans
@ 2008-06-08 18:21 ` Daniel Jacobowitz
2008-06-09 13:48 ` Thiago Jung Bauermann
2008-06-10 0:00 ` Tom Tromey
1 sibling, 2 replies; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-06-08 18:21 UTC (permalink / raw)
To: Tom Tromey; +Cc: Thiago Jung Bauermann, gdb-patches
On Thu, May 29, 2008 at 02:29:32PM -0600, Tom Tromey wrote:
> Recently I've been thinking that $(...) should not simply eval the
> '...' as a python expression. Instead, I'm leaning more toward a
> function registry approach. I have two reasons for this.
This sounds good to me.
> * I agree with the lexing point. I think we could specify some
> standardized quoting and dequote before passing the argument to the
> underlying code.
I don't think this is really necessary. It's not like the user would
be up a creek if they had an arbitrary character that interfered with
the lexer.
Except we do need to define what the arguments to specified functions
are, and I want a clear answer on that point before anything goes in.
They could be Python syntax, or some other well-defined syntax which
happens to be similar to Python. Would GDB convenience variables
work? As values or as textual substitution?
As long as we pick something and document it, I think the choice of
what to pick is not too significant.
> * I don't want to use $python(...) -- but I was wondering, doesn't
> this already have a meaning if 'python' happens to be a
> function-pointer-valued convenience variable?
Yes, but this is always an issue defining new predefined convenience
variables since they share a namespace with user variables.
> I suppose my basic proposal is that all functions be derived from
> something like:
>
> class Function:
> # ARG is a string, already de-quoted and whitespace-stripped.
> def invoke(self, arg):
> do something
>
> def complete(self, text, word):
> complete the argument
>
> This is basically exactly what we do for commands, only in the
> Function case we could expect invoke to return a value.
Making them complete on a string seems too awkward when writing such
things. At function-writing time it would be easier (but less
flexible) to specify a list of arguments and have GDB handle the
breaking up into words... I know we discussed this before but I can't
remember the details now.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: Function syntax (Was: [RFC][patch 1/9] initial Python support)
2008-06-08 18:21 ` Function syntax (Was: [RFC][patch 1/9] initial Python support) Daniel Jacobowitz
@ 2008-06-09 13:48 ` Thiago Jung Bauermann
2008-06-09 18:43 ` Daniel Jacobowitz
2008-06-10 0:04 ` Tom Tromey
2008-06-10 0:00 ` Tom Tromey
1 sibling, 2 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-06-09 13:48 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Tom Tromey, gdb-patches
On Sun, 2008-06-08 at 14:21 -0400, Daniel Jacobowitz wrote:
> Except we do need to define what the arguments to specified functions
> are, and I want a clear answer on that point before anything goes in.
> They could be Python syntax, or some other well-defined syntax which
> happens to be similar to Python. Would GDB convenience variables
> work? As values or as textual substitution?
What about separating argument by commas, and treating each CSV as an
expression to be evaluated? The Python function would then receive
arguments as value objects.
This also means that convenience variables (and variables in the
inferior) would work.
The Python function would also return a value object.
> > * I don't want to use $python(...) -- but I was wondering, doesn't
> > this already have a meaning if 'python' happens to be a
> > function-pointer-valued convenience variable?
>
> Yes, but this is always an issue defining new predefined convenience
> variables since they share a namespace with user variables.
I actually prefer the $func(...) syntax. Using $(func args) doesn't feel
natural for non-LISP hackers. The former approach IMHO fits better with
the current GDB syntax, and also with the imperative language used in
the inferior.
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: Function syntax (Was: [RFC][patch 1/9] initial Python support)
2008-06-09 13:48 ` Thiago Jung Bauermann
@ 2008-06-09 18:43 ` Daniel Jacobowitz
2008-06-10 0:24 ` Function syntax Tom Tromey
2008-06-10 0:04 ` Tom Tromey
1 sibling, 1 reply; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-06-09 18:43 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: Tom Tromey, gdb-patches
On Mon, Jun 09, 2008 at 10:36:21AM -0300, Thiago Jung Bauermann wrote:
> What about separating argument by commas, and treating each CSV as an
> expression to be evaluated? The Python function would then receive
> arguments as value objects.
>
> This also means that convenience variables (and variables in the
> inferior) would work.
>
> The Python function would also return a value object.
I've no objection to this; it sounds almost foolproof, though it would
be nice to have some examples and see how well it fits in practice.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: Function syntax
2008-06-08 18:21 ` Function syntax (Was: [RFC][patch 1/9] initial Python support) Daniel Jacobowitz
2008-06-09 13:48 ` Thiago Jung Bauermann
@ 2008-06-10 0:00 ` Tom Tromey
1 sibling, 0 replies; 147+ messages in thread
From: Tom Tromey @ 2008-06-10 0:00 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
>>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
Tom> Recently I've been thinking that $(...) should not simply eval the
Tom> '...' as a python expression. Instead, I'm leaning more toward a
Tom> function registry approach. I have two reasons for this.
Daniel> This sounds good to me.
Good :) I actually went ahead and implemented this a little while
back.
Daniel> Except we do need to define what the arguments to specified functions
Daniel> are, and I want a clear answer on that point before anything goes in.
Yes, I totally agree. IMO this is much more important than the
various implementation details -- those can be changed much more
easily than user-facing behavior.
Daniel> They could be Python syntax, or some other well-defined syntax which
Daniel> happens to be similar to Python. Would GDB convenience variables
Daniel> work? As values or as textual substitution?
Daniel> As long as we pick something and document it, I think the choice of
Daniel> what to pick is not too significant.
[...]
Daniel> Making them complete on a string seems too awkward when writing such
Daniel> things. At function-writing time it would be easier (but less
Daniel> flexible) to specify a list of arguments and have GDB handle the
Daniel> breaking up into words... I know we discussed this before but I can't
Daniel> remember the details now.
The way this works right now is that the first word is stripped from
the text between the parens. This is the function name and is looked
up in an internal table. The rest is passed, untranslated, as an
argument.
We talked about doing more parsing here for commands, and I guess by
extension functions. But I have kind of come around to the other
point of view -- leave the argument as a string and let the callee
deal with it.
One reason I prefer this is that it lets new functions require less
syntax. For instance, consider my canonical example of a function
that looks to see if the caller's stack frame matches the argument:
break somewhere if $(caller-is somewhere_else)
If we were dealing with sub-expressions or the like, this would have
to be a string. That just seems less gdb-ish to me -- though of
course this argument is somewhat weak in that other folks may have a
different idea about the nature of gdb's grammar.
I see your point about convenience variables. They would not be
automatically interpolated. On the other hand, nothing prevents a
python function from evalling an argument as a gdb expression.
Another reason I prefer this approach is that in general it is simpler
to write stuff in Python rather than C. I already plan to ship a
library of useful Python functions with this gdb -- adding more
utility code to handle parsing, completion, etc, is no big deal.
Tom> * I don't want to use $python(...) -- but I was wondering, doesn't
Tom> this already have a meaning if 'python' happens to be a
Tom> function-pointer-valued convenience variable?
Daniel> Yes, but this is always an issue defining new predefined convenience
Daniel> variables since they share a namespace with user variables.
I think this is an argument to keep the $(fn) syntax -- it would be
nice if these functions had a separate namespace. One reason in
particular I would like that is that I think we ought to ship a lot of
built-in ones, and it would be nice not to trample all over the user
namespace.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: Function syntax
2008-06-09 13:48 ` Thiago Jung Bauermann
2008-06-09 18:43 ` Daniel Jacobowitz
@ 2008-06-10 0:04 ` Tom Tromey
2008-06-11 0:04 ` Thiago Jung Bauermann
1 sibling, 1 reply; 147+ messages in thread
From: Tom Tromey @ 2008-06-10 0:04 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: Daniel Jacobowitz, gdb-patches
>>>>> "Thiago" == Thiago Jung Bauermann <bauerman@br.ibm.com> writes:
Thiago> I actually prefer the $func(...) syntax. Using $(func args) doesn't feel
Thiago> natural for non-LISP hackers. The former approach IMHO fits better with
Thiago> the current GDB syntax, and also with the imperative language used in
Thiago> the inferior.
Perhaps we can find a third syntax. As I said in my previous note, I
would prefer not to share the namespace with convenience variables.
I was thinking maybe some puncutation other than "$" -- but it is hard
to see what would work.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: Function syntax
2008-06-09 18:43 ` Daniel Jacobowitz
@ 2008-06-10 0:24 ` Tom Tromey
0 siblings, 0 replies; 147+ messages in thread
From: Tom Tromey @ 2008-06-10 0:24 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
>>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
>> The Python function would also return a value object.
... or just any Python value. We have this completely dynamic
language here, we might as well take advantage :-)
Actually, now it only allows a Python value. We should modify it to
automatically unbox a gdb.Value result.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: Function syntax
2008-06-10 0:04 ` Tom Tromey
@ 2008-06-11 0:04 ` Thiago Jung Bauermann
0 siblings, 0 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-06-11 0:04 UTC (permalink / raw)
To: Tom Tromey; +Cc: Daniel Jacobowitz, gdb-patches
On Mon, 2008-06-09 at 17:55 -0600, Tom Tromey wrote:
> >>>>> "Thiago" == Thiago Jung Bauermann <bauerman@br.ibm.com> writes:
> Thiago> I actually prefer the $func(...) syntax. Using $(func args) doesn't feel
> Thiago> natural for non-LISP hackers. The former approach IMHO fits better with
> Thiago> the current GDB syntax, and also with the imperative language used in
> Thiago> the inferior.
> Perhaps we can find a third syntax. As I said in my previous note, I
> would prefer not to share the namespace with convenience variables.
I'm ok with that.
> I was thinking maybe some puncutation other than "$" -- but it is hard
> to see what would work.
We can ask some Perl folks. I'm sure they'll have lots of ideas. :-)
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 1/9] initial Python support
2008-05-29 0:29 ` Daniel Jacobowitz
2008-05-30 13:07 ` Function syntax (Was: [RFC][patch 1/9] initial Python support) Tom Tromey
2008-05-30 14:47 ` [RFC][patch 1/9] initial Python support Tom Tromey
@ 2008-06-15 22:35 ` thiagoju
2008-06-23 17:36 ` Tom Tromey
2008-07-15 7:38 ` [RFA] " Thiago Jung Bauermann
2 siblings, 2 replies; 147+ messages in thread
From: thiagoju @ 2008-06-15 22:35 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Thiago Jung Bauermann, gdb-patches
[-- Attachment #1: Type: text/plain, Size: 4989 bytes --]
Zitat von Daniel Jacobowitz <drow@false.org>:
> Looks generally good.
Good, I'm generally happy then. :-)
> For the general syntax: Should we allow $() to always mean Python, or
> are there other useful potential scripting interfaces or environment
> variable access or anything, in which case we want $(python ) or $(P )
> or $python( )? There are only so many nice grouping specifiers. $<>
> is not so good but we still have $[] and ${}, plus $env(). I don't
> remember if we discussed this before, but we may have.
This discussion is still being carried out. In the interest of having
at least the very basic committed soon, I removed support for Python
evalution inside expressions for this patch. This is now in a separate
patch in the python-patches branch. There, you will also find another
patch which Tromey is developing implementing his other proposal
(i.e., registering functions and then using $(func args) syntax).
The downside is that this patch adds near zero value to the user.
But all other patches build on this one.
> We've discussed already the configure options - I'd prefer to avoid
> this issue and only have --with-python and maybe
> --with-python-lib/--with-python-include. Parallel to the top level
> gmp/mpfr handling, for instance.
This patch now sports the shiny new --with-python code brought to you
by Doug Evans.
> I didn't know about python-config. Is that new? Could we specify a
> path to python-config instead of messing with cflags/ldflags directly?
Yes we could, but I didn't experiment with the idea...
> And we sorted this out on IRC.
Hooray for IRC. :-)
> The special_processing argument to read_next_line / read_command_lines
> is not commented and the name doesn't say much of anything about what
> it's for. It looks like this changes the behavior of document versus
> define, probably deliberately if it does what I think it does. So
> this would be a good patch to split out separately. In general, any
> bits that can go in separately should; it makes the whole pile easier
> to manage :-)
You are right, I didn't know why these changes were there as well but at
the time I kept them in the patch anyway. They seem to be useful only to
varobj/MI Python bindings by Vladimir, and I separated them in another
patch (found in the python-patches branch).
> There are too many #ifdef's in the rest of GDB in this patch, IMO.
> Can python/python.h be included unconditionally, not include
> python-internal.h, and have the exposed interfaces error() when Python
> support is not compiled in? That's the approach I took for
> xml-support.h.
>
> Similarly we should recognize python_control regardless of
> HAVE_PYTHON. That way we can parse a .gdbinit which defines Python
> commands and give a sensible error only if they are invoked.
Done, courtesy of Tom Tromey.
> In general I would prefer we not commit any FIXMEs. We can decide now
> what the right thing to do is and if there is room for future
> enhancement, that's not a FIXME any more :-)
All FIXMEs in this patch are now gone (also by Tromey).
> > +
> > +void
> > +eval_python_from_control_command (struct command_line *cmd)
> > +{
> > + char *script;
> > +
> > + if (cmd->body_count != 1)
> > + error (_("Invalid \"python\" block structure."));
> > +
> > + demand_python ();
> > +
> > + script = compute_python_string (cmd->body_list[0]);
> > + PyRun_SimpleString (script);
> > + xfree (script);
> > + if (PyErr_Occurred ())
> > + {
> > + PyErr_Print ();
> > + error ("error while executing Python code");
> > + }
> > +}
>
> _() around arguments to error. Also, in general PyErr_Print is
> probably dumping to stderr? Output should go through GDB's error
> mechanisms, and in this case probably be part of the argument to
> error. Can you get it to return an error string instead?
This is stillpending, I think.
> > +static PyObject *
> > +execute_gdb_command (PyObject *self, PyObject *args)
> > +{
> > + struct cmd_list_element *alias, *prefix, *cmd;
> > + char *arg, *newarg;
> > + volatile struct gdb_exception except;
> > +
> > + if (! PyArg_ParseTuple (args, "s", &arg))
> > + return NULL;
> > +
> > + TRY_CATCH (except, RETURN_MASK_ALL)
> > + {
> > + execute_command (arg, 0);
> > + }
> > + GDB_PY_HANDLE_EXCEPTION (except);
> > +
> > + /* gdbtk does bpstat_do_actions here... */
>
> Please figure out if we need to or not. It looks like we do; running
> the command "continue" to a breakpoint with actions will test it.
I don't know much about bpstat_do_actions, and didn't do the experiment
you mention (not sure I understood it), so I made a crude try at adding
a call to bpstat_do_actions just to get this patch out.
> Speaking of which... a testsuite? :-)
Next in my list!
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
[-- Attachment #2: python-basic.diff --]
[-- Type: text/x-patch, Size: 25600 bytes --]
2008-06-15 Vladimir Prus <vladimir@codesourcery.com>
Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
Doug Evans <dje@google.com>
* Makefile.in (SUBDIR_PYTHON_OBS, SUBDIR_PYTHON_SRCS,
SUBDIR_PYTHON_DEPS, SUBDIR_PYTHON_LDFLAGS, SUBDIR_PYTHON_CFLAGS,
PYTHON_CFLAGS): New.
(python_h, python_internal_h): New.
(COMMON_OBS): Add python.o.
(INIT_FILES): Add python/python.c.
(cli-script.o): Depend on python.h
(python.o): New.
* cli/cli-script.c (print_command_lines): Handle python_control.
(execute_control_command): Handle python_control.
(execute_control_command_suppressed): New function.
(while_command): Call execute_control_command_suppressed.
(if_command): Likewise.
(get_command_line): Remove static attribute.
(read_next_line): Handle "python".
(recurse_read_control_structure): Handle python_control.
(read_command_lines): Handle python_control.
Include python.h.
* cli/cli-script.h (get_command_line): Add prototype.
(execute_control_command_suppressed): Likewise.
* configure.ac: Add --with-python.
* defs.h (enum command_control_type) <python_control>: New
constant.
* python/python-internal.h: New file.
* python/python.c: New file.
* python/python.h: New file.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 9304bc2..09fdc34 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -254,6 +254,16 @@ SUBDIR_TUI_LDFLAGS=
SUBDIR_TUI_CFLAGS= \
-DTUI=1
+#
+# python sub directory definitons
+#
+SUBDIR_PYTHON_OBS =
+SUBDIR_PYTHON_SRCS = \
+ python/python.c
+SUBDIR_PYTHON_DEPS =
+SUBDIR_PYTHON_LDFLAGS=
+SUBDIR_PYTHON_CFLAGS=
+
# Opcodes currently live in one of two places. Either they are in the
# opcode library, typically ../opcodes, or they are in a header file
@@ -963,6 +973,13 @@ tui_wingeneral_h = $(srcdir)/tui/tui-wingeneral.h
tui_win_h = $(srcdir)/tui/tui-win.h $(tui_data_h)
tui_winsource_h = $(srcdir)/tui/tui-winsource.h $(tui_data_h)
+#
+# gdb/python/ headers
+#
+
+python_h = $(srcdir)/python/python.h $(value_h)
+python_internal_h = $(srcdir)/python/python-internal.h
+
# gdb/features preparsed descriptions
features_headers = $(defs_h) $(gdbtypes_h) $(target_descriptions_h)
arm_with_iwmmxt_c = $(srcdir)/features/arm-with-iwmmxt.c $(features_headers)
@@ -1081,7 +1098,8 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
tramp-frame.o \
solib.o solib-null.o \
prologue-value.o memory-map.o xml-support.o \
- target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o
+ target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \
+ python.o
TSOBS = inflow.o
@@ -1275,7 +1293,11 @@ test-cp-name-parser$(EXEEXT): test-cp-name-parser.o $(LIBIBERTY)
# duplicates. Files in the gdb/ directory can end up appearing in
# COMMON_OBS (as a .o file) and CONFIG_SRCS (as a .c file).
-INIT_FILES = $(COMMON_OBS) $(TSOBS) $(CONFIG_SRCS)
+# NOTE: bauermann/2008-06-15: python.c needs to be explicitly included
+# because the generation of init.c does not work for .c files which
+# result in differently named objects (i.e., python/python -> python.o).
+
+INIT_FILES = $(COMMON_OBS) $(TSOBS) $(CONFIG_SRCS) python/python.c
init.c: $(INIT_FILES)
@echo Making init.c
@rm -f init.c-tmp init.l-tmp
@@ -3051,7 +3073,8 @@ cli-logging.o: $(srcdir)/cli/cli-logging.c $(defs_h) $(gdbcmd_h) $(ui_out_h) \
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-logging.c
cli-script.o: $(srcdir)/cli/cli-script.c $(defs_h) $(value_h) $(language_h) \
$(ui_out_h) $(gdb_string_h) $(exceptions_h) $(top_h) $(cli_cmds_h) \
- $(cli_decode_h) $(cli_script_h) $(gdb_assert_h) $(breakpoint_h)
+ $(cli_decode_h) $(cli_script_h) $(gdb_assert_h) $(breakpoint_h) \
+ $(python_h)
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-script.c
cli-setshow.o: $(srcdir)/cli/cli-setshow.c $(defs_h) $(readline_tilde_h) \
$(value_h) $(gdb_string_h) $(ui_out_h) $(cli_decode_h) $(cli_cmds_h) \
@@ -3375,4 +3398,19 @@ tui-winsource.o: $(srcdir)/tui/tui-winsource.c $(defs_h) $(symtab_h) \
$(gdb_curses_h) $(gdb_assert_h)
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tui-winsource.c
+#
+# gdb/python/ dependencies
+#
+# Need to explicitly specify the compile rule as make will do nothing
+# or try to compile the object file into the sub-directory.
+
+# Flags needed to compile Python code (taken from python-config --cflags)
+PYTHON_CFLAGS=-fno-strict-aliasing -DNDEBUG -fwrapv
+
+python.o: $(srcdir)/python/python.c $(defs_h) $(python_h) \
+ $(command_h) $(libiberty_h) $(cli_decode_h) $(charset_h) $(top_h) \
+ $(exceptions_h) $(python_internal_h) $(version_h) $(cli_script_h) \
+ $(ui_out_h)
+ $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) $(srcdir)/python/python.c
+
### end of the gdb Makefile.in.
diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c
index e6fbe3f..69fd3c7 100644
--- a/gdb/cli/cli-script.c
+++ b/gdb/cli/cli-script.c
@@ -34,6 +34,8 @@
#include "cli/cli-script.h"
#include "gdb_assert.h"
+#include "python/python.h"
+
/* Prototypes for local functions */
static enum command_control_type
@@ -102,7 +104,7 @@ build_command_line (enum command_control_type type, char *args)
/* Build and return a new command structure for the control commands
such as "if" and "while". */
-static struct command_line *
+struct command_line *
get_command_line (enum command_control_type type, char *arg)
{
struct command_line *cmd;
@@ -225,6 +227,18 @@ print_command_lines (struct ui_out *uiout, struct command_line *cmd,
continue;
}
+ if (list->control_type == python_control)
+ {
+ ui_out_field_string (uiout, NULL, "python");
+ print_command_lines (uiout, *list->body_list, depth + 1);
+ if (depth)
+ ui_out_spaces (uiout, 2 * depth);
+ ui_out_field_string (uiout, NULL, "end");
+ ui_out_text (uiout, "\n");
+ list = list->next;
+ continue;
+ }
+
/* ignore illegal command type and try next */
list = list->next;
} /* while (list) */
@@ -527,6 +541,12 @@ execute_control_command (struct command_line *cmd)
ret = commands_from_control_command (new_line, cmd);
break;
}
+ case python_control:
+ {
+ eval_python_from_control_command (cmd);
+ ret = simple_control;
+ break;
+ }
default:
warning (_("Invalid control type in canned commands structure."));
@@ -538,6 +558,17 @@ execute_control_command (struct command_line *cmd)
return ret;
}
+/* Like execute_control_command, but first set
+ suppress_next_print_command_trace. */
+
+enum command_control_type
+execute_control_command_suppressed (struct command_line *cmd)
+{
+ suppress_next_print_command_trace = 1;
+ return execute_control_command (cmd);
+}
+
+
/* "while" command support. Executes a body of statements while the
loop condition is nonzero. */
@@ -552,8 +583,7 @@ while_command (char *arg, int from_tty)
if (command == NULL)
return;
- suppress_next_print_command_trace = 1;
- execute_control_command (command);
+ execute_control_command_suppressed (command);
free_command_lines (&command);
}
@@ -571,8 +601,7 @@ if_command (char *arg, int from_tty)
if (command == NULL)
return;
- suppress_next_print_command_trace = 1;
- execute_control_command (command);
+ execute_control_command_suppressed (command);
free_command_lines (&command);
}
@@ -886,6 +915,12 @@ read_next_line (struct command_line **command)
first_arg++;
*command = build_command_line (commands_control, first_arg);
}
+ else if (p1 - p == 6 && !strncmp (p, "python", 6))
+ {
+ /* Note that we ignore the inline "python command" form
+ here. */
+ *command = build_command_line (python_control, "");
+ }
else if (p1 - p == 10 && !strncmp (p, "loop_break", 10))
{
*command = (struct command_line *)
@@ -962,6 +997,7 @@ recurse_read_control_structure (struct command_line *current_cmd)
{
if (current_cmd->control_type == while_control
|| current_cmd->control_type == if_control
+ || current_cmd->control_type == python_control
|| current_cmd->control_type == commands_control)
{
/* Success reading an entire canned sequence of commands. */
@@ -1013,6 +1049,7 @@ recurse_read_control_structure (struct command_line *current_cmd)
on it. */
if (next->control_type == while_control
|| next->control_type == if_control
+ || next->control_type == python_control
|| next->control_type == commands_control)
{
control_level++;
@@ -1086,6 +1123,7 @@ read_command_lines (char *prompt_arg, int from_tty)
if (next->control_type == while_control
|| next->control_type == if_control
+ || next->control_type == python_control
|| next->control_type == commands_control)
{
control_level++;
diff --git a/gdb/cli/cli-script.h b/gdb/cli/cli-script.h
index 42663dd..7416e1c 100644
--- a/gdb/cli/cli-script.h
+++ b/gdb/cli/cli-script.h
@@ -40,6 +40,12 @@ extern void show_user_1 (struct cmd_list_element *c, struct ui_file *stream);
extern enum command_control_type
execute_control_command (struct command_line *cmd);
+extern enum command_control_type
+ execute_control_command_suppressed (struct command_line *cmd);
+
+extern struct command_line *get_command_line (enum command_control_type,
+ char *);
+
extern void print_command_lines (struct ui_out *,
struct command_line *, unsigned int);
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 101dedf..0adc9fd 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -485,6 +485,99 @@ else
fi
fi
+dnl Utility to simplify finding libpython.
+AC_DEFUN([AC_TRY_LIBPYTHON],
+[
+ version=$1
+ define([have_libpython_var],$2)
+ define([VERSION],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+ [HAVE_LIB]VERSION=no
+ AC_MSG_CHECKING([for ${version}])
+ save_LIBS=$LIBS
+ LIBS="$LIBS -l${version}"
+ AC_LINK_IFELSE(AC_LANG_PROGRAM([[#include "${version}/Python.h"]],
+ [[Py_Initialize ();]]),
+ [[HAVE_LIB]VERSION=yes
+ have_libpython_var=yes],
+ [LIBS=$save_LIBS])
+ AC_MSG_RESULT([$[HAVE_LIB]VERSION])
+])
+
+AC_ARG_WITH(python,
+ AS_HELP_STRING([--with-python], [include python support (auto/yes/no/<path>)]),
+ [], [with_python=auto])
+AC_MSG_CHECKING([whether to use python])
+AC_MSG_RESULT([$with_python])
+
+if test "${with_python}" = no; then
+ AC_MSG_WARN([python support disabled; some features may be unavailable.])
+ have_libpython=no
+else
+ case "${with_python}" in
+ yes | auto)
+ # Leave as empty, use defaults.
+ python_includes=
+ python_libs=
+ ;;
+ /*)
+ python_includes="-I${with_python}/include"
+ python_libs="-L${with_python}/lib"
+ ;;
+ *)
+ AC_ERROR(invalid value for --with-python)
+ ;;
+ esac
+
+ save_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS ${python_includes}"
+ save_LIBS=$LIBS
+ LIBS="$LIBS ${python_libs}"
+ have_libpython=no
+ if test "${have_libpython}" = no; then
+ AC_TRY_LIBPYTHON(python2.6, have_libpython)
+ if test "${HAVE_LIBPYTHON2_6}" = yes; then
+ AC_DEFINE(HAVE_LIBPYTHON2_6, 1, [Define if Python 2.6 is being used.])
+ fi
+ fi
+ if test ${have_libpython} = no; then
+ AC_TRY_LIBPYTHON(python2.5, have_libpython)
+ if test "${HAVE_LIBPYTHON2_5}" = yes; then
+ AC_DEFINE(HAVE_LIBPYTHON2_5, 1, [Define if Python 2.5 is being used.])
+ fi
+ fi
+ if test ${have_libpython} = no; then
+ AC_TRY_LIBPYTHON(python2.4, have_libpython)
+ if test "${HAVE_LIBPYTHON2_4}" = yes; then
+ AC_DEFINE(HAVE_LIBPYTHON2_4, 1, [Define if Python 2.4 is being used.])
+ fi
+ fi
+ if test ${have_libpython} = no; then
+ case "${with_python}" in
+ yes)
+ AC_MSG_ERROR([python is missing or unusable])
+ ;;
+ auto)
+ AC_MSG_WARN([python is missing or unusable; some features may be unavailable.])
+ ;;
+ *)
+ AC_MSG_ERROR([no usable python found at ${with_python}])
+ ;;
+ esac
+ CPPFLAGS=$save_CPPFLAGS
+ LIBS=$save_LIBS
+ fi
+fi
+
+if test "${have_libpython}" = yes; then
+ AC_DEFINE(HAVE_PYTHON, 1, [Define if Python interpreter is being linked in.])
+ CONFIG_OBS="$CONFIG_OBS \$(SUBDIR_PYTHON_OBS)"
+ CONFIG_DEPS="$CONFIG_DEPS \$(SUBDIR_PYTHON_DEPS)"
+ CONFIG_SRCS="$CONFIG_SRCS \$(SUBDIR_PYTHON_SRCS)"
+ CONFIG_INITS="$CONFIG_INITS \$(SUBDIR_PYTHON_INITS)"
+ ENABLE_CFLAGS="$ENABLE_CFLAGS \$(SUBDIR_PYTHON_CFLAGS)"
+fi
+
# ------------------------- #
# Checks for header files. #
# ------------------------- #
diff --git a/gdb/defs.h b/gdb/defs.h
index 2af40ab..98d3f7c 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -642,6 +642,7 @@ enum command_control_type
while_control,
if_control,
commands_control,
+ python_control,
invalid_control
};
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
new file mode 100644
index 0000000..d39724c
--- /dev/null
+++ b/gdb/python/python-internal.h
@@ -0,0 +1,60 @@
+/* Gdb/Python header for private use by Python module.
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDB_PYTHON_INTERNAL_H
+#define GDB_PYTHON_INTERNAL_H
+
+/* Python 2.4 doesn't include stdint.h soon enough to get {u,}intptr_t
+ needed by pyport.h. */
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+/* /usr/include/features.h on linux systems will define _POSIX_C_SOURCE
+ if it sees _GNU_SOURCE (which config.h will define).
+ pyconfig.h defines _POSIX_C_SOURCE to a different value than
+ /usr/include/features.h does causing compilation to fail.
+ To work around this, undef _POSIX_C_SOURCE before we include Python.h. */
+#undef _POSIX_C_SOURCE
+
+#if HAVE_LIBPYTHON2_4
+#include "python2.4/Python.h"
+/* Py_ssize_t is not defined until 2.5. */
+typedef Py_intptr_t Py_ssize_t;
+#elif HAVE_LIBPYTHON2_5
+#include "python2.5/Python.h"
+#elif HAVE_LIBPYTHON2_6
+#include "python2.6/Python.h"
+#else
+#error "Unable to find usable Python.h"
+#endif
+
+extern PyObject *gdb_module;
+
+/* Use this after a TRY_EXCEPT to throw the appropriate Python
+ exception. */
+#define GDB_PY_HANDLE_EXCEPTION(Exception) \
+ do { \
+ if (Exception.reason < 0) \
+ return PyErr_Format (Exception.reason == RETURN_QUIT \
+ ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, \
+ "%s", Exception.message); \
+ } while (0)
+
+#endif /* GDB_PYTHON_INTERNAL_H */
diff --git a/gdb/python/python.c b/gdb/python/python.c
new file mode 100644
index 0000000..89e136c
--- /dev/null
+++ b/gdb/python/python.c
@@ -0,0 +1,324 @@
+/* General python/gdb code
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "command.h"
+#include "ui-out.h"
+#include "cli/cli-script.h"
+
+#include <ctype.h>
+
+#ifdef HAVE_PYTHON
+
+#include "python.h"
+#include "libiberty.h"
+#include "cli/cli-decode.h"
+#include "charset.h"
+#include "top.h"
+#include "exceptions.h"
+#include "python-internal.h"
+#include "version.h"
+
+
+PyObject *gdb_module;
+
+static PyObject *get_show_variable (PyObject *, PyObject *);
+static PyObject *execute_gdb_command (PyObject *, PyObject *);
+
+static PyMethodDef GdbMethods[] =
+{
+ { "execute", execute_gdb_command, METH_VARARGS,
+ "Execute a gdb command" },
+ { "show", get_show_variable, METH_VARARGS,
+ "Return a gdb setting's value" },
+
+ {NULL, NULL, 0, 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
+ responsible for freeing it. */
+
+static char *
+compute_python_string (struct command_line *l)
+{
+ struct command_line *iter;
+ char *script = NULL;
+ int size = 0;
+ int here;
+
+ for (iter = l; iter; iter = iter->next)
+ size += strlen (iter->line) + 1;
+
+ script = xmalloc (size + 1);
+ here = 0;
+ for (iter = l; iter; iter = iter->next)
+ {
+ int len = strlen (iter->line) + 1;
+ strcpy (&script[here], iter->line);
+ here += len;
+ script[here++] = '\n';
+ }
+ script[here] = '\0';
+ return script;
+}
+
+void
+eval_python_from_control_command (struct command_line *cmd)
+{
+ char *script;
+
+ if (cmd->body_count != 1)
+ error (_("Invalid \"python\" block structure."));
+
+ script = compute_python_string (cmd->body_list[0]);
+ PyRun_SimpleString (script);
+ xfree (script);
+ if (PyErr_Occurred ())
+ {
+ PyErr_Print ();
+ error (_("error while executing Python code"));
+ }
+}
+
+/* Implementation of the gdb "python" command. */
+
+static void
+python_command (char *arg, int from_tty)
+{
+ while (arg && *arg && isspace (*arg))
+ ++arg;
+ if (arg && *arg)
+ {
+ PyRun_SimpleString (arg);
+ if (PyErr_Occurred ())
+ {
+ PyErr_Print ();
+ error (_("error while executing Python code"));
+ }
+ }
+ else
+ {
+ char *tmpbuf = xstrprintf ("Type python script");
+ struct cleanup *cleanups = make_cleanup (xfree, tmpbuf);
+ struct command_line *l = get_command_line (python_control, "");
+ cleanups = make_cleanup_free_command_lines (&l);
+ execute_control_command_suppressed (l);
+ do_cleanups (cleanups);
+ }
+}
+
+\f
+
+/* Transform a gdb variable's value into a Python value. May return
+ NULL (and set a Python exception) on error. Helper function for
+ get_show_variable. */
+
+static PyObject *
+variable_to_python (struct cmd_list_element *cmd)
+{
+ switch (cmd->var_type)
+ {
+ case var_string:
+ case var_string_noescape:
+ case var_optional_filename:
+ case var_filename:
+ case var_enum:
+ {
+ char *str = * (char **) cmd->var;
+ if (! str)
+ str = "";
+ return PyString_Decode (str, strlen (str), host_charset (), NULL);
+ }
+
+ case var_boolean:
+ {
+ if (* (int *) cmd->var)
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
+ }
+
+ case var_auto_boolean:
+ {
+ enum auto_boolean ab = * (enum auto_boolean *) cmd->var;
+ if (ab == AUTO_BOOLEAN_TRUE)
+ Py_RETURN_TRUE;
+ else if (ab == AUTO_BOOLEAN_FALSE)
+ Py_RETURN_FALSE;
+ else
+ Py_RETURN_NONE;
+ }
+
+ case var_integer:
+ if ((* (int *) cmd->var) == INT_MAX)
+ Py_RETURN_NONE;
+ /* Fall through. */
+ case var_zinteger:
+ return PyLong_FromLong (* (int *) cmd->var);
+
+ case var_uinteger:
+ {
+ unsigned int val = * (unsigned int *) cmd->var;
+ if (val == UINT_MAX)
+ Py_RETURN_NONE;
+ return PyLong_FromUnsignedLong (val);
+ }
+ }
+
+ return PyErr_Format (PyExc_RuntimeError, "programmer error: unhandled type");
+}
+
+/* A Python function which returns a gdb variable's value as a Python
+ value. */
+
+static PyObject *
+get_show_variable (PyObject *self, PyObject *args)
+{
+ struct cmd_list_element *alias, *prefix, *cmd;
+ char *arg, *newarg;
+ volatile struct gdb_exception except;
+
+ if (! PyArg_ParseTuple (args, "s", &arg))
+ return NULL;
+
+ newarg = concat ("show ", arg, (char *) NULL);
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ if (! lookup_cmd_composition (newarg, &alias, &prefix, &cmd))
+ {
+ xfree (newarg);
+ return PyErr_Format (PyExc_RuntimeError,
+ "could not find variable `%s'", arg);
+ }
+ }
+ xfree (newarg);
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ if (! cmd->var)
+ return PyErr_Format (PyExc_RuntimeError, "`%s' is not a variable", arg);
+ return variable_to_python (cmd);
+}
+
+/* A Python function which evaluates a string using the gdb CLI. */
+
+static PyObject *
+execute_gdb_command (PyObject *self, PyObject *args)
+{
+ struct cmd_list_element *alias, *prefix, *cmd;
+ char *arg, *newarg;
+ volatile struct gdb_exception except;
+ struct cleanup *old_chain;
+
+ if (! PyArg_ParseTuple (args, "s", &arg))
+ return NULL;
+
+ old_chain = make_cleanup (null_cleanup, 0);
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ execute_command (arg, 0);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ /* Do any commands attached to breakpoint we stopped at. Only if we
+ are always running synchronously. Or if we have just executed a
+ command that doesn't start the target. */
+ if (!target_can_async_p () || !target_executing)
+ {
+ bpstat_do_actions (&stop_bpstat);
+ do_cleanups (old_chain);
+ }
+
+ Py_RETURN_NONE;
+}
+
+\f
+
+/* Initialize the Python code. */
+
+void
+_initialize_python (void)
+{
+ add_com ("python", class_obscure, python_command, _("\
+Evaluate a Python command.\n\
+\n\
+The command can be given as an argument, for instance:\n\
+\n\
+ python print 23\n\
+\n\
+If no argument is given, the following lines are read and used\n\
+as the Python commands. Type a line containing \"end\" to indicate\n\
+the end of the command."));
+
+ Py_Initialize ();
+
+ gdb_module = Py_InitModule ("gdb", GdbMethods);
+
+ /* The casts to (char*) are for python 2.4. */
+ PyModule_AddStringConstant (gdb_module, "VERSION", (char*) version);
+ PyModule_AddStringConstant (gdb_module, "HOST_CONFIG", (char*) host_name);
+ PyModule_AddStringConstant (gdb_module, "TARGET_CONFIG", (char*) target_name);
+
+ PyRun_SimpleString ("import gdb");
+}
+
+#else /* HAVE_PYTHON */
+
+/* Dummy implementation of the gdb "python" command. */
+
+static void
+python_command (char *arg, int from_tty)
+{
+ while (arg && *arg && isspace (*arg))
+ ++arg;
+ if (arg && *arg)
+ error (_("Python scripting is not supported in this copy of GDB."));
+ else
+ {
+ char *tmpbuf = xstrprintf ("Type python script");
+ struct cleanup *cleanups = make_cleanup (xfree, tmpbuf);
+ struct command_line *l = get_command_line (python_control, "");
+ cleanups = make_cleanup_free_command_lines (&l);
+ execute_control_command_suppressed (l);
+ do_cleanups (cleanups);
+ }
+}
+
+void
+eval_python_from_control_command (struct command_line *cmd)
+{
+ error (_("Python scripting is not supported in this copy of GDB."));
+}
+
+/* Initialize dummy Python code. */
+
+void
+_initialize_python (void)
+{
+ add_com ("python", class_obscure, python_command, _("\
+Evaluate a Python command.\n\
+\n\
+Python scripting is not supported in this copy of GDB.\n\
+This command is only a placeholder."));
+}
+
+#endif /* HAVE_PYTHON */
diff --git a/gdb/python/python.h b/gdb/python/python.h
new file mode 100644
index 0000000..00ff159
--- /dev/null
+++ b/gdb/python/python.h
@@ -0,0 +1,27 @@
+/* Python/gdb header for generic use in gdb
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDB_PYTHON_H
+#define GDB_PYTHON_H
+
+#include "value.h"
+
+void eval_python_from_control_command (struct command_line *);
+
+#endif /* GDB_PYTHON_H */
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 3/9] export hooks mechanism to Python
2008-05-30 14:59 ` Tom Tromey
@ 2008-06-15 22:53 ` Thiago Jung Bauermann
2008-06-15 22:58 ` Tom Tromey
0 siblings, 1 reply; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-06-15 22:53 UTC (permalink / raw)
To: tromey; +Cc: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 323 bytes --]
Zitat von Tom Tromey <tromey@redhat.com>:
>>>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
>
> Daniel> I won't look at this one, as I believe Tom's rewritten it to use
> Daniel> observers instead.
>
> Yeah, that's right.
>
Here's the new version.
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
[-- Attachment #2: python-hooks.diff --]
[-- Type: text/x-patch, Size: 6803 bytes --]
gdb/
2008-06-15 Tom Tromey <tromey@redhat.com>
* Makefile.in (SUBDIR_PYTHON_OBS): Add python-hooks.o.
(SUBDIR_PYTHON_SRCS): Add python/hooks.c.
(python-hooks.o): New target.
* breakpoint.c (mention): Notify observers of created
breakpoint.
(delete_breakpoint): Notify observers of deleted
breakpoint.
* python/hooks.c: New file.
* python/python-internal.h (gdbpy_get_hook_function,
gdbpy_initialize_hooks): Declare.
* python/python.c (_initialize_python): Call gdbpy_initialize_hooks.
doc/
2008-06-15 Tom Tromey <tromey@redhat.com>
* observer.texi (Notifications): Document breakpoint_created
and breakpoint_deleted.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index b15fa61..45ecfbd 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -257,9 +257,11 @@ SUBDIR_TUI_CFLAGS= \
#
# python sub directory definitons
#
-SUBDIR_PYTHON_OBS =
+SUBDIR_PYTHON_OBS = \
+ python-hooks.o
SUBDIR_PYTHON_SRCS = \
python/python.c \
+ python/hooks.c \
python/value.c
SUBDIR_PYTHON_DEPS =
SUBDIR_PYTHON_LDFLAGS=
@@ -3413,6 +3415,11 @@ python.o: $(srcdir)/python/python.c $(defs_h) $(python_h) \
$(exceptions_h) $(python_internal_h) $(version_h) $(cli_script_h) \
$(ui_out_h)
$(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) $(srcdir)/python/python.c
+python-hooks.o: $(srcdir)/python/hooks.c $(defs_h) $(cli_decode_h) \
+ $(charset_h) $(gdb_events_h) $(python_h) $(python_internal_h) \
+ $(observer_h)
+ $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
+ $(srcdir)/python/hooks.c -o python-hooks.o
python-value.o: $(srcdir)/python/value.c $(defs_h) $(exceptions_h) \
$(python_internal_h) $(value_h)
$(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 24ef7bf..4c2b1eb 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -4913,6 +4913,7 @@ mention (struct breakpoint *b)
if (deprecated_create_breakpoint_hook)
deprecated_create_breakpoint_hook (b);
breakpoint_create_event (b->number);
+ observer_notify_breakpoint_created (b->number);
if (b->ops != NULL && b->ops->print_mention != NULL)
b->ops->print_mention (b);
@@ -7141,6 +7142,7 @@ delete_breakpoint (struct breakpoint *bpt)
if (deprecated_delete_breakpoint_hook)
deprecated_delete_breakpoint_hook (bpt);
breakpoint_delete_event (bpt->number);
+ observer_notify_breakpoint_deleted (bpt->number);
if (breakpoint_chain == bpt)
breakpoint_chain = bpt->next;
diff --git a/gdb/doc/observer.texi b/gdb/doc/observer.texi
index 5bcc76c..b6aefab 100644
--- a/gdb/doc/observer.texi
+++ b/gdb/doc/observer.texi
@@ -2,7 +2,7 @@
@c This file is part of the GDB manual.
@c
-@c Copyright (C) 2003, 2004, 2005, 2006
+@c Copyright (C) 2003, 2004, 2005, 2006, 2008
@c Free Software Foundation, Inc.
@c
@c See the file gdbint.texinfo for copying conditions.
@@ -133,3 +133,13 @@ previously loaded symbol table data has now been invalidated.
The thread specified by @var{t} has been created.
@end deftypefun
+@deftypefun void breakpoint_created (int @var{bpnum})
+A new breakpoint has been created. The argument @var{bpnum} is the
+number of the newly-created breakpoint.
+@end deftypefun
+
+@deftypefun void breakpoint_deleted (int @var{bpnum})
+A breakpoint has been destroyed. The argument @var{bpnum} is the
+number of the newly-destroyed breakpoint.
+@end deftypefun
+
diff --git a/gdb/python/hooks.c b/gdb/python/hooks.c
new file mode 100644
index 0000000..21f3a28
--- /dev/null
+++ b/gdb/python/hooks.c
@@ -0,0 +1,62 @@
+/* Notifications from gdb to Python
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "cli/cli-decode.h"
+#include "charset.h"
+#include "gdb-events.h"
+#include "python.h"
+#include "python-internal.h"
+#include "observer.h"
+
+PyObject *
+gdbpy_get_hook_function (const char *name)
+{
+ PyObject *hooks;
+ PyObject *result;
+
+ if (! PyObject_HasAttrString (gdb_module, "hooks"))
+ return NULL;
+ hooks = PyObject_GetAttrString (gdb_module, "hooks");
+ if (! hooks)
+ return NULL;
+ /* The cast is because the Python function doesn't declare const argument.
+ This is a problem in Python version 2.4, but not in 2.5. */
+ if (! PyObject_HasAttrString (hooks, (char *) name))
+ {
+ Py_DECREF (hooks);
+ return NULL;
+ }
+ /* The cast is because the Python function doesn't declare const argument.
+ This is a problem in Python version 2.4, but not in 2.5. */
+ result = PyObject_GetAttrString (hooks, (char *) name);
+ Py_DECREF (hooks);
+ return result;
+}
+
+void
+gdbpy_initialize_hooks (void)
+{
+ /* If you need to hook into any sort of state change in gdb, do so
+ by adding a new observer to observer.texi, attach to the new
+ observer here, and notify the new observer at the appropriate
+ place. */
+ observer_attach_breakpoint_created (gdbpy_breakpoint_created);
+ observer_attach_breakpoint_deleted (gdbpy_breakpoint_deleted);
+}
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 0abdfde..1bb2422 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -56,7 +56,10 @@ PyObject *gdb_owned_value_to_value_object (struct value *v);
struct value *value_object_to_value (PyObject *self);
+PyObject *gdbpy_get_hook_function (const char *);
+
void gdbpy_initialize_values (void);
+void gdbpy_initialize_hooks (void);
/* Use this after a TRY_EXCEPT to throw the appropriate Python
exception. */
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 5b8b975..2e8db56 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -282,6 +282,7 @@ the end of the command."));
PyModule_AddStringConstant (gdb_module, "HOST_CONFIG", (char*) host_name);
PyModule_AddStringConstant (gdb_module, "TARGET_CONFIG", (char*) target_name);
+ gdbpy_initialize_hooks ();
gdbpy_initialize_values ();
PyRun_SimpleString ("import gdb");
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 3/9] export hooks mechanism to Python
2008-06-15 22:53 ` Thiago Jung Bauermann
@ 2008-06-15 22:58 ` Tom Tromey
2008-06-16 3:22 ` Daniel Jacobowitz
0 siblings, 1 reply; 147+ messages in thread
From: Tom Tromey @ 2008-06-15 22:58 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
>>>>> "Thiago" == Thiago Jung Bauermann <bauerman@br.ibm.com> writes:
>> Yeah, that's right.
Thiago> Here's the new version.
Funnily enough I was just thinking about this code today.
In particular I was wondering if we ought to expose observers to
Python more directly -- say by having a generic way for a Python
object to register with a given observer.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 3/9] export hooks mechanism to Python
2008-06-15 22:58 ` Tom Tromey
@ 2008-06-16 3:22 ` Daniel Jacobowitz
2008-06-17 18:13 ` Thiago Jung Bauermann
0 siblings, 1 reply; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-06-16 3:22 UTC (permalink / raw)
To: Tom Tromey; +Cc: Thiago Jung Bauermann, gdb-patches
On Sun, Jun 15, 2008 at 04:35:19PM -0600, Tom Tromey wrote:
> Funnily enough I was just thinking about this code today.
> In particular I was wondering if we ought to expose observers to
> Python more directly -- say by having a generic way for a Python
> object to register with a given observer.
I don't think that's a good idea; it ties the Python exposed
interfaces too closely to GDB's internal interfaces. I don't want
hacking on GDB to break Python programs unexpectedly.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 3/9] export hooks mechanism to Python
2008-06-16 3:22 ` Daniel Jacobowitz
@ 2008-06-17 18:13 ` Thiago Jung Bauermann
2008-06-17 22:20 ` Joel Brobecker
0 siblings, 1 reply; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-06-17 18:13 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Tom Tromey, gdb-patches
Zitat von Daniel Jacobowitz <drow@false.org>:
> On Sun, Jun 15, 2008 at 04:35:19PM -0600, Tom Tromey wrote:
>> Funnily enough I was just thinking about this code today.
>> In particular I was wondering if we ought to expose observers to
>> Python more directly -- say by having a generic way for a Python
>> object to register with a given observer.
>
> I don't think that's a good idea; it ties the Python exposed
> interfaces too closely to GDB's internal interfaces. I don't want
> hacking on GDB to break Python programs unexpectedly.
Observers look like a useful feature in GDB to be used by scripts,
IMHO we should think about ways to make it available to python, and consider
turning it into a stable exported interface...
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 3/9] export hooks mechanism to Python
2008-06-17 18:13 ` Thiago Jung Bauermann
@ 2008-06-17 22:20 ` Joel Brobecker
2008-06-23 17:58 ` Tom Tromey
0 siblings, 1 reply; 147+ messages in thread
From: Joel Brobecker @ 2008-06-17 22:20 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: Daniel Jacobowitz, Tom Tromey, gdb-patches
> Observers look like a useful feature in GDB to be used by scripts,
> IMHO we should think about ways to make it available to python, and consider
> turning it into a stable exported interface...
Exposing some events to Python sounds pretty reasonable, but I also
prefer if we did not expose the observers directly, for the reasons
that Daniel explained. The event at the Python would be very well
defined and (hopefully) stable while we are free to modify the observers.
--
Joel
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 1/9] initial Python support
2008-06-15 22:35 ` thiagoju
@ 2008-06-23 17:36 ` Tom Tromey
2008-07-06 17:28 ` Tom Tromey
2008-07-15 7:38 ` [RFA] " Thiago Jung Bauermann
1 sibling, 1 reply; 147+ messages in thread
From: Tom Tromey @ 2008-06-23 17:36 UTC (permalink / raw)
To: thiagoju; +Cc: Daniel Jacobowitz, Thiago Jung Bauermann, gdb-patches
>>>>> "Thiago" == thiagoju <thiagoju@linux.ibm.com> writes:
>> > + if (PyErr_Occurred ())
>> > + {
>> > + PyErr_Print ();
>> > + error ("error while executing Python code");
>> > + }
>> > +}
>> _() around arguments to error. Also, in general PyErr_Print is
>> probably dumping to stderr? Output should go through GDB's error
>> mechanisms, and in this case probably be part of the argument to
>> error. Can you get it to return an error string instead?
Thiago> This is stillpending, I think.
Yeah, this one is still pending.
I haven't dug into what to do here yet... feel free to take it if you
want :). Otherwise I will get to it when I'm a bit more caught up.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 3/9] export hooks mechanism to Python
2008-06-17 22:20 ` Joel Brobecker
@ 2008-06-23 17:58 ` Tom Tromey
0 siblings, 0 replies; 147+ messages in thread
From: Tom Tromey @ 2008-06-23 17:58 UTC (permalink / raw)
To: Joel Brobecker; +Cc: Thiago Jung Bauermann, Daniel Jacobowitz, gdb-patches
>>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:
>> Observers look like a useful feature in GDB to be used by scripts,
>> IMHO we should think about ways to make it available to python, and consider
>> turning it into a stable exported interface...
Joel> Exposing some events to Python sounds pretty reasonable, but I also
Joel> prefer if we did not expose the observers directly, for the reasons
Joel> that Daniel explained. The event at the Python would be very well
Joel> defined and (hopefully) stable while we are free to modify the observers.
FWIW we talked about this at the Summit and my understanding is that
we agreed there should be some "buffering" between raw observers and
Python code.
BTW, Thiago, this patch is a bit obsolete since I moved breakpoint
observer registration directly into python/breakpoint.c.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 1/9] initial Python support
2008-06-23 17:36 ` Tom Tromey
@ 2008-07-06 17:28 ` Tom Tromey
2008-07-08 4:12 ` Thiago Jung Bauermann
0 siblings, 1 reply; 147+ messages in thread
From: Tom Tromey @ 2008-07-06 17:28 UTC (permalink / raw)
To: thiagoju; +Cc: Daniel Jacobowitz, Thiago Jung Bauermann, gdb-patches
>>>>> "Tom" == Tom Tromey <tromey@redhat.com> writes:
>>> > + if (PyErr_Occurred ())
>>> > + {
>>> > + PyErr_Print ();
>>> > + error ("error while executing Python code");
>>> > + }
>>> > +}
Thiago> This is stillpending, I think.
FYI -- I fixed this today. I added a new 'maint set python-stack'
variable that controls whether Python stack traces are printed. By
default they are. I changed all the new code to use a new
gdbpy_print_stack which checks this variable. Finally, I set things
up so that gdb overrides Python's sys.stdout and sys.stderr to print
things using printf_filtered.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 2/9] export values mechanism to Python
2008-06-03 0:19 ` Tom Tromey
2008-06-03 13:04 ` Daniel Jacobowitz
@ 2008-07-07 6:03 ` Thiago Jung Bauermann
2008-07-07 23:44 ` Tom Tromey
2008-08-13 6:45 ` [python] acessing struct elements Thiago Jung Bauermann
1 sibling, 2 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-07-07 6:03 UTC (permalink / raw)
To: tromey; +Cc: gdb-patches
On Mon, 2008-06-02 at 18:18 -0600, Tom Tromey wrote:
> >>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
>
> Daniel> Would it be helpful or confusing to automatically expose this
> Daniel> as [] in Python, __getitem__?
>
> Good question.
>
> In general I've been using explicit method names, like get_* and
> set_*. But perhaps we should be using attributes and various
> "intrinsic" names... I'm not enough of a Python expert to know what is
> preferred.
In the GDB BoF we decided to use Python __magic__ for gdb.Values, so I
started working on it. My idea is to make them behave as much as the
corresponding native Python types as possible, so a gdb.Value with an
int type would behave like a Python int.
There's one case which I'd like to discuss, and about which I talked to
Tromey on IRC:
In the case of valpy_get_element (which is used to access an element in
a value representing a struct or class), using __getitem__ means that in
Python one would use a_struct["element"] to access a_struct.element.
This looks a bit strange at least. It would be possible to make this
case work more like a real struct, by intercepting python object
accesses to attributes. Then one could have a_struct.element work for
gdb.Values.
The downside is that it means that value objects couldn't have methods
since they would be interpreted as struct elements. If Python supports
class methods (I'm not sure of that, but I think it does), then we could
have things like gdb.Values.some_method (value_object, other, args).
Also, Python's own attributes and methods (like __doc__) would clash
with structure elements.
What do you prefer?
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 2/9] export values mechanism to Python
2008-07-07 6:03 ` Thiago Jung Bauermann
@ 2008-07-07 23:44 ` Tom Tromey
2008-07-26 2:55 ` Daniel Jacobowitz
2008-08-13 6:45 ` [python] acessing struct elements Thiago Jung Bauermann
1 sibling, 1 reply; 147+ messages in thread
From: Tom Tromey @ 2008-07-07 23:44 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
>>>>> "Thiago" == Thiago Jung Bauermann <bauerman@br.ibm.com> writes:
Thiago> In the GDB BoF we decided to use Python __magic__ for gdb.Values, so I
Thiago> started working on it. My idea is to make them behave as much as the
Thiago> corresponding native Python types as possible, so a gdb.Value with an
Thiago> int type would behave like a Python int.
BTW -- there is some redundancy between gdbpy_make_value and
convert_value_from_python. It seems to me that we should have a
single function to convert a PyObject* to a 'struct value *',
and then a separate function to box a 'struct value *' in a
gdb.Value.
Also, I think we don't need gdb.make_value. It seems to me that this
should instead be a gdb.Value constructor. What do you think?
(Really this constructor needs a Type argument, but we haven't
implemented that yet...)
FWIW, gdb.Function does default conversions of python objects to gdb
values. I.e., if the python function does 'return 5', that is turned
into a struct value whose type is some default int type. So, in most
cases I think we won't need to make new Value objects at all -- any
place one is needed I think we can easily accept ordinary Python
objects as well.
Thiago> In the case of valpy_get_element (which is used to access an element in
Thiago> a value representing a struct or class), using __getitem__ means that in
Thiago> Python one would use a_struct["element"] to access a_struct.element.
Thiago> This looks a bit strange at least.
I don't mind this, my reasoning is:
* I suspect it will be more common to use a string-valued expression
here than it will be to use a string constant.
* This approach also works nicely for arrays.
* This approach does not mix the Value namespace with the
debuggee's field names.
Thiago> If Python supports class methods (I'm not sure of that, but I
Thiago> think it does), then we could have things like
Thiago> gdb.Values.some_method (value_object, other, args).
I definitely do not like the idea of class methods that are really
instance methods in disguise.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 1/9] initial Python support
2008-07-06 17:28 ` Tom Tromey
@ 2008-07-08 4:12 ` Thiago Jung Bauermann
0 siblings, 0 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-07-08 4:12 UTC (permalink / raw)
To: tromey; +Cc: thiagoju, Daniel Jacobowitz, gdb-patches
On Sun, 2008-07-06 at 11:27 -0600, Tom Tromey wrote:
> >>>>> "Tom" == Tom Tromey <tromey@redhat.com> writes:
>
> >>> > + if (PyErr_Occurred ())
> >>> > + {
> >>> > + PyErr_Print ();
> >>> > + error ("error while executing Python code");
> >>> > + }
> >>> > +}
>
> Thiago> This is stillpending, I think.
>
> FYI -- I fixed this today. I added a new 'maint set python-stack'
> variable that controls whether Python stack traces are printed. By
> default they are. I changed all the new code to use a new
> gdbpy_print_stack which checks this variable. Finally, I set things
> up so that gdb overrides Python's sys.stdout and sys.stderr to print
> things using printf_filtered.
Awesome!
This means that there are only three things pending for this patch to go
in:
1. I'd like someone to verify if my call to bpstat_do_actions in
execute_gdb_command is needed and if I implemented it correctly (I'm not
sure I knew what I was doing, I just wanted something there so I could
post the patch).
2. Testcases
3. Documentation (both user and internal)
I can work on the last two items, but I'd like input on the first. After
these are resolved I'll post a refreshed patch to the list.
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* [RFA] Re: [RFC][patch 1/9] initial Python support
2008-06-15 22:35 ` thiagoju
2008-06-23 17:36 ` Tom Tromey
@ 2008-07-15 7:38 ` Thiago Jung Bauermann
2008-07-15 17:19 ` Tom Tromey
2008-07-15 18:01 ` [RFA] Re: [RFC][patch 1/9] " Thiago Jung Bauermann
1 sibling, 2 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-07-15 7:38 UTC (permalink / raw)
To: gdb-patches ml
Hi,
This is the latest version of the patch adding initial Python support.
AFAIK it fixes all concerns that were raised regarding it, and has
documentation and a testcase. The only caveat is...
On Sun, 2008-06-15 at 18:18 -0400, thiagoju@linux.ibm.com wrote:
> Zitat von Daniel Jacobowitz <drow@false.org>:
> > > +static PyObject *
> > > +execute_gdb_command (PyObject *self, PyObject *args)
> > > +{
> > > + struct cmd_list_element *alias, *prefix, *cmd;
> > > + char *arg, *newarg;
> > > + volatile struct gdb_exception except;
> > > +
> > > + if (! PyArg_ParseTuple (args, "s", &arg))
> > > + return NULL;
> > > +
> > > + TRY_CATCH (except, RETURN_MASK_ALL)
> > > + {
> > > + execute_command (arg, 0);
> > > + }
> > > + GDB_PY_HANDLE_EXCEPTION (except);
> > > +
> > > + /* gdbtk does bpstat_do_actions here... */
> >
> > Please figure out if we need to or not. It looks like we do; running
> > the command "continue" to a breakpoint with actions will test it.
>
> I don't know much about bpstat_do_actions, and didn't do the experiment
> you mention (not sure I understood it), so I made a crude try at adding
> a call to bpstat_do_actions just to get this patch out.
... the fix I implemented for this. I still would like someone to check
it for sanity.
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
gdb/
2008-07-15 Vladimir Prus <vladimir@codesourcery.com>
Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
Doug Evans <dje@google.com>
* Makefile.in (SUBDIR_PYTHON_OBS, SUBDIR_PYTHON_SRCS,
SUBDIR_PYTHON_DEPS, SUBDIR_PYTHON_LDFLAGS, SUBDIR_PYTHON_CFLAGS,
PYTHON_CFLAGS): New.
(python_h, python_internal_h): New.
(COMMON_OBS): Add python.o.
(INIT_FILES): Add python/python.c.
(cli-script.o): Depend on python.h
(python.o, python-utils.o): New.
* cli/cli-script.c (print_command_lines): Handle python_control.
(execute_control_command): Handle python_control.
(execute_control_command_suppressed): New function.
(while_command): Call execute_control_command_suppressed.
(if_command): Likewise.
(get_command_line): Remove static attribute.
(read_next_line): Handle "python".
(recurse_read_control_structure): Handle python_control.
(read_command_lines): Handle python_control.
Include python.h.
* cli/cli-script.h (get_command_line): Add prototype.
(execute_control_command_suppressed): Likewise.
* configure.ac: Add --with-python.
* defs.h (enum command_control_type) <python_control>: New
constant.
* python/python-internal.h: New file.
* python/python.c: New file.
* python/python.h: New file.
* python/utils.c: New file.
gdb/doc/
2008-07-15 Tom Tromey <tromey@redhat.com>
* gdb.texinfo (Python): New chapter.
gdb/testsuite/
2008-07-15 Tom Tromey <tromey@redhat.com>
* gdb.python/python.exp: New file.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 9304bc2..9007bc8 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -254,6 +254,18 @@ SUBDIR_TUI_LDFLAGS=
SUBDIR_TUI_CFLAGS= \
-DTUI=1
+#
+# python sub directory definitons
+#
+SUBDIR_PYTHON_OBS = \
+ python-utils.o
+SUBDIR_PYTHON_SRCS = \
+ python/python.c \
+ python/utils.c
+SUBDIR_PYTHON_DEPS =
+SUBDIR_PYTHON_LDFLAGS=
+SUBDIR_PYTHON_CFLAGS=
+
# Opcodes currently live in one of two places. Either they are in the
# opcode library, typically ../opcodes, or they are in a header file
@@ -963,6 +975,13 @@ tui_wingeneral_h = $(srcdir)/tui/tui-wingeneral.h
tui_win_h = $(srcdir)/tui/tui-win.h $(tui_data_h)
tui_winsource_h = $(srcdir)/tui/tui-winsource.h $(tui_data_h)
+#
+# gdb/python/ headers
+#
+
+python_h = $(srcdir)/python/python.h $(value_h)
+python_internal_h = $(srcdir)/python/python-internal.h
+
# gdb/features preparsed descriptions
features_headers = $(defs_h) $(gdbtypes_h) $(target_descriptions_h)
arm_with_iwmmxt_c = $(srcdir)/features/arm-with-iwmmxt.c $(features_headers)
@@ -1081,7 +1100,8 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
tramp-frame.o \
solib.o solib-null.o \
prologue-value.o memory-map.o xml-support.o \
- target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o
+ target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \
+ python.o
TSOBS = inflow.o
@@ -1275,7 +1295,11 @@ test-cp-name-parser$(EXEEXT): test-cp-name-parser.o $(LIBIBERTY)
# duplicates. Files in the gdb/ directory can end up appearing in
# COMMON_OBS (as a .o file) and CONFIG_SRCS (as a .c file).
-INIT_FILES = $(COMMON_OBS) $(TSOBS) $(CONFIG_SRCS)
+# NOTE: bauermann/2008-06-15: python.c needs to be explicitly included
+# because the generation of init.c does not work for .c files which
+# result in differently named objects (i.e., python/python -> python.o).
+
+INIT_FILES = $(COMMON_OBS) $(TSOBS) $(CONFIG_SRCS) python/python.c
init.c: $(INIT_FILES)
@echo Making init.c
@rm -f init.c-tmp init.l-tmp
@@ -3051,7 +3075,8 @@ cli-logging.o: $(srcdir)/cli/cli-logging.c $(defs_h) $(gdbcmd_h) $(ui_out_h) \
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-logging.c
cli-script.o: $(srcdir)/cli/cli-script.c $(defs_h) $(value_h) $(language_h) \
$(ui_out_h) $(gdb_string_h) $(exceptions_h) $(top_h) $(cli_cmds_h) \
- $(cli_decode_h) $(cli_script_h) $(gdb_assert_h) $(breakpoint_h)
+ $(cli_decode_h) $(cli_script_h) $(gdb_assert_h) $(breakpoint_h) \
+ $(python_h)
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-script.c
cli-setshow.o: $(srcdir)/cli/cli-setshow.c $(defs_h) $(readline_tilde_h) \
$(value_h) $(gdb_string_h) $(ui_out_h) $(cli_decode_h) $(cli_cmds_h) \
@@ -3375,4 +3400,22 @@ tui-winsource.o: $(srcdir)/tui/tui-winsource.c $(defs_h) $(symtab_h) \
$(gdb_curses_h) $(gdb_assert_h)
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tui-winsource.c
+#
+# gdb/python/ dependencies
+#
+# Need to explicitly specify the compile rule as make will do nothing
+# or try to compile the object file into the sub-directory.
+
+# Flags needed to compile Python code (taken from python-config --cflags)
+PYTHON_CFLAGS=-fno-strict-aliasing -DNDEBUG -fwrapv
+
+python.o: $(srcdir)/python/python.c $(defs_h) $(python_h) \
+ $(command_h) $(libiberty_h) $(cli_decode_h) $(charset_h) $(top_h) \
+ $(exceptions_h) $(python_internal_h) $(version_h) $(cli_script_h) \
+ $(ui_out_h)
+ $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) $(srcdir)/python/python.c
+python-utils.o: $(srcdir)/python/utils.c $(defs_h) $(python_internal_h)
+ $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
+ $(srcdir)/python/utils.c -o python-utils.o
+
### end of the gdb Makefile.in.
diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c
index e6fbe3f..69fd3c7 100644
--- a/gdb/cli/cli-script.c
+++ b/gdb/cli/cli-script.c
@@ -34,6 +34,8 @@
#include "cli/cli-script.h"
#include "gdb_assert.h"
+#include "python/python.h"
+
/* Prototypes for local functions */
static enum command_control_type
@@ -102,7 +104,7 @@ build_command_line (enum command_control_type type, char *args)
/* Build and return a new command structure for the control commands
such as "if" and "while". */
-static struct command_line *
+struct command_line *
get_command_line (enum command_control_type type, char *arg)
{
struct command_line *cmd;
@@ -225,6 +227,18 @@ print_command_lines (struct ui_out *uiout, struct command_line *cmd,
continue;
}
+ if (list->control_type == python_control)
+ {
+ ui_out_field_string (uiout, NULL, "python");
+ print_command_lines (uiout, *list->body_list, depth + 1);
+ if (depth)
+ ui_out_spaces (uiout, 2 * depth);
+ ui_out_field_string (uiout, NULL, "end");
+ ui_out_text (uiout, "\n");
+ list = list->next;
+ continue;
+ }
+
/* ignore illegal command type and try next */
list = list->next;
} /* while (list) */
@@ -527,6 +541,12 @@ execute_control_command (struct command_line *cmd)
ret = commands_from_control_command (new_line, cmd);
break;
}
+ case python_control:
+ {
+ eval_python_from_control_command (cmd);
+ ret = simple_control;
+ break;
+ }
default:
warning (_("Invalid control type in canned commands structure."));
@@ -538,6 +558,17 @@ execute_control_command (struct command_line *cmd)
return ret;
}
+/* Like execute_control_command, but first set
+ suppress_next_print_command_trace. */
+
+enum command_control_type
+execute_control_command_suppressed (struct command_line *cmd)
+{
+ suppress_next_print_command_trace = 1;
+ return execute_control_command (cmd);
+}
+
+
/* "while" command support. Executes a body of statements while the
loop condition is nonzero. */
@@ -552,8 +583,7 @@ while_command (char *arg, int from_tty)
if (command == NULL)
return;
- suppress_next_print_command_trace = 1;
- execute_control_command (command);
+ execute_control_command_suppressed (command);
free_command_lines (&command);
}
@@ -571,8 +601,7 @@ if_command (char *arg, int from_tty)
if (command == NULL)
return;
- suppress_next_print_command_trace = 1;
- execute_control_command (command);
+ execute_control_command_suppressed (command);
free_command_lines (&command);
}
@@ -886,6 +915,12 @@ read_next_line (struct command_line **command)
first_arg++;
*command = build_command_line (commands_control, first_arg);
}
+ else if (p1 - p == 6 && !strncmp (p, "python", 6))
+ {
+ /* Note that we ignore the inline "python command" form
+ here. */
+ *command = build_command_line (python_control, "");
+ }
else if (p1 - p == 10 && !strncmp (p, "loop_break", 10))
{
*command = (struct command_line *)
@@ -962,6 +997,7 @@ recurse_read_control_structure (struct command_line *current_cmd)
{
if (current_cmd->control_type == while_control
|| current_cmd->control_type == if_control
+ || current_cmd->control_type == python_control
|| current_cmd->control_type == commands_control)
{
/* Success reading an entire canned sequence of commands. */
@@ -1013,6 +1049,7 @@ recurse_read_control_structure (struct command_line *current_cmd)
on it. */
if (next->control_type == while_control
|| next->control_type == if_control
+ || next->control_type == python_control
|| next->control_type == commands_control)
{
control_level++;
@@ -1086,6 +1123,7 @@ read_command_lines (char *prompt_arg, int from_tty)
if (next->control_type == while_control
|| next->control_type == if_control
+ || next->control_type == python_control
|| next->control_type == commands_control)
{
control_level++;
diff --git a/gdb/cli/cli-script.h b/gdb/cli/cli-script.h
index 42663dd..7416e1c 100644
--- a/gdb/cli/cli-script.h
+++ b/gdb/cli/cli-script.h
@@ -40,6 +40,12 @@ extern void show_user_1 (struct cmd_list_element *c, struct ui_file *stream);
extern enum command_control_type
execute_control_command (struct command_line *cmd);
+extern enum command_control_type
+ execute_control_command_suppressed (struct command_line *cmd);
+
+extern struct command_line *get_command_line (enum command_control_type,
+ char *);
+
extern void print_command_lines (struct ui_out *,
struct command_line *, unsigned int);
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 101dedf..0adc9fd 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -485,6 +485,99 @@ else
fi
fi
+dnl Utility to simplify finding libpython.
+AC_DEFUN([AC_TRY_LIBPYTHON],
+[
+ version=$1
+ define([have_libpython_var],$2)
+ define([VERSION],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+ [HAVE_LIB]VERSION=no
+ AC_MSG_CHECKING([for ${version}])
+ save_LIBS=$LIBS
+ LIBS="$LIBS -l${version}"
+ AC_LINK_IFELSE(AC_LANG_PROGRAM([[#include "${version}/Python.h"]],
+ [[Py_Initialize ();]]),
+ [[HAVE_LIB]VERSION=yes
+ have_libpython_var=yes],
+ [LIBS=$save_LIBS])
+ AC_MSG_RESULT([$[HAVE_LIB]VERSION])
+])
+
+AC_ARG_WITH(python,
+ AS_HELP_STRING([--with-python], [include python support (auto/yes/no/<path>)]),
+ [], [with_python=auto])
+AC_MSG_CHECKING([whether to use python])
+AC_MSG_RESULT([$with_python])
+
+if test "${with_python}" = no; then
+ AC_MSG_WARN([python support disabled; some features may be unavailable.])
+ have_libpython=no
+else
+ case "${with_python}" in
+ yes | auto)
+ # Leave as empty, use defaults.
+ python_includes=
+ python_libs=
+ ;;
+ /*)
+ python_includes="-I${with_python}/include"
+ python_libs="-L${with_python}/lib"
+ ;;
+ *)
+ AC_ERROR(invalid value for --with-python)
+ ;;
+ esac
+
+ save_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS ${python_includes}"
+ save_LIBS=$LIBS
+ LIBS="$LIBS ${python_libs}"
+ have_libpython=no
+ if test "${have_libpython}" = no; then
+ AC_TRY_LIBPYTHON(python2.6, have_libpython)
+ if test "${HAVE_LIBPYTHON2_6}" = yes; then
+ AC_DEFINE(HAVE_LIBPYTHON2_6, 1, [Define if Python 2.6 is being used.])
+ fi
+ fi
+ if test ${have_libpython} = no; then
+ AC_TRY_LIBPYTHON(python2.5, have_libpython)
+ if test "${HAVE_LIBPYTHON2_5}" = yes; then
+ AC_DEFINE(HAVE_LIBPYTHON2_5, 1, [Define if Python 2.5 is being used.])
+ fi
+ fi
+ if test ${have_libpython} = no; then
+ AC_TRY_LIBPYTHON(python2.4, have_libpython)
+ if test "${HAVE_LIBPYTHON2_4}" = yes; then
+ AC_DEFINE(HAVE_LIBPYTHON2_4, 1, [Define if Python 2.4 is being used.])
+ fi
+ fi
+ if test ${have_libpython} = no; then
+ case "${with_python}" in
+ yes)
+ AC_MSG_ERROR([python is missing or unusable])
+ ;;
+ auto)
+ AC_MSG_WARN([python is missing or unusable; some features may be unavailable.])
+ ;;
+ *)
+ AC_MSG_ERROR([no usable python found at ${with_python}])
+ ;;
+ esac
+ CPPFLAGS=$save_CPPFLAGS
+ LIBS=$save_LIBS
+ fi
+fi
+
+if test "${have_libpython}" = yes; then
+ AC_DEFINE(HAVE_PYTHON, 1, [Define if Python interpreter is being linked in.])
+ CONFIG_OBS="$CONFIG_OBS \$(SUBDIR_PYTHON_OBS)"
+ CONFIG_DEPS="$CONFIG_DEPS \$(SUBDIR_PYTHON_DEPS)"
+ CONFIG_SRCS="$CONFIG_SRCS \$(SUBDIR_PYTHON_SRCS)"
+ CONFIG_INITS="$CONFIG_INITS \$(SUBDIR_PYTHON_INITS)"
+ ENABLE_CFLAGS="$ENABLE_CFLAGS \$(SUBDIR_PYTHON_CFLAGS)"
+fi
+
# ------------------------- #
# Checks for header files. #
# ------------------------- #
diff --git a/gdb/defs.h b/gdb/defs.h
index 2af40ab..98d3f7c 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -642,6 +642,7 @@ enum command_control_type
while_control,
if_control,
commands_control,
+ python_control,
invalid_control
};
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 46d5904..ef7985a 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -1,6 +1,6 @@
\input texinfo @c -*-texinfo-*-
@c Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998,
-@c 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+@c 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008
@c Free Software Foundation, Inc.
@c
@c %**start of header
@@ -155,6 +155,7 @@ software in general. We will miss him.
* Emacs:: Using @value{GDBN} under @sc{gnu} Emacs
* GDB/MI:: @value{GDBN}'s Machine Interface.
* Annotations:: @value{GDBN}'s annotation interface.
+* Python:: Scripting @value{GDBN} using Python.
* GDB Bugs:: Reporting bugs in @value{GDBN}
@@ -22406,6 +22407,41 @@ source which is being displayed. @var{addr} is in the form @samp{0x}
followed by one or more lowercase hex digits (note that this does not
depend on the language).
+@node Python
+@chapter Scripting @value{GDBN} using Python
+@cindex Python
+
+You can script @value{GDBN} using the @url{http://www.python.org/,
+Python} programming language. This feature is available only if
+@value{GDBN} was configured using @code{--with-python}.
+
+@kindex python
+The @code{python} command can be used to evaluate Python code.
+
+If given an argument, the @code{python} command will evaluate the
+argument as a Python command. For example:
+
+@smallexample
+(@value{GDBP}) python print 23
+23
+@end smallexample
+
+If you do not provide an argument to @code{python}, it will act as a
+multi-line command, like @code{define}. In this case, the Python
+script is made up of subsequent command lines, given after the
+@code{python} command. This command list is terminated using a line
+containing @code{end}. For example:
+
+@smallexample
+(@value{GDBP}) python
+Type python script
+End with a line saying just "end".
+>print 23
+>end
+23
+@end smallexample
+
+
@node GDB Bugs
@chapter Reporting Bugs in @value{GDBN}
@cindex bugs in @value{GDBN}
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
new file mode 100644
index 0000000..da2e7e1
--- /dev/null
+++ b/gdb/python/python-internal.h
@@ -0,0 +1,73 @@
+/* Gdb/Python header for private use by Python module.
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDB_PYTHON_INTERNAL_H
+#define GDB_PYTHON_INTERNAL_H
+
+/* Python 2.4 doesn't include stdint.h soon enough to get {u,}intptr_t
+ needed by pyport.h. */
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+/* /usr/include/features.h on linux systems will define _POSIX_C_SOURCE
+ if it sees _GNU_SOURCE (which config.h will define).
+ pyconfig.h defines _POSIX_C_SOURCE to a different value than
+ /usr/include/features.h does causing compilation to fail.
+ To work around this, undef _POSIX_C_SOURCE before we include Python.h. */
+#undef _POSIX_C_SOURCE
+
+#if HAVE_LIBPYTHON2_4
+#include "python2.4/Python.h"
+/* Py_ssize_t is not defined until 2.5. */
+typedef Py_intptr_t Py_ssize_t;
+#elif HAVE_LIBPYTHON2_5
+#include "python2.5/Python.h"
+#elif HAVE_LIBPYTHON2_6
+#include "python2.6/Python.h"
+#else
+#error "Unable to find usable Python.h"
+#endif
+
+struct block;
+struct symbol;
+struct symtab_and_line;
+
+extern PyObject *gdb_module;
+
+struct cleanup *make_cleanup_py_decref (PyObject *py);
+
+/* Use this after a TRY_EXCEPT to throw the appropriate Python
+ exception. */
+#define GDB_PY_HANDLE_EXCEPTION(Exception) \
+ do { \
+ if (Exception.reason < 0) \
+ return PyErr_Format (Exception.reason == RETURN_QUIT \
+ ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, \
+ "%s", Exception.message); \
+ } while (0)
+
+
+void gdbpy_print_stack (void);
+
+PyObject *python_string_to_unicode (PyObject *obj);
+char *unicode_to_target_string (PyObject *unicode_str);
+char *python_string_to_target_string (PyObject *obj);
+
+#endif /* GDB_PYTHON_INTERNAL_H */
diff --git a/gdb/python/python.c b/gdb/python/python.c
new file mode 100644
index 0000000..a492bd3
--- /dev/null
+++ b/gdb/python/python.c
@@ -0,0 +1,431 @@
+/* General python/gdb code
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "command.h"
+#include "ui-out.h"
+#include "cli/cli-script.h"
+
+#include <ctype.h>
+
+#ifdef HAVE_PYTHON
+
+#include "python.h"
+#include "libiberty.h"
+#include "cli/cli-decode.h"
+#include "charset.h"
+#include "top.h"
+#include "exceptions.h"
+#include "python-internal.h"
+#include "version.h"
+#include "gdbcmd.h"
+
+
+PyObject *gdb_module;
+
+static PyObject *get_show_variable (PyObject *, PyObject *);
+static PyObject *execute_gdb_command (PyObject *, PyObject *);
+static PyObject *gdbpy_write (PyObject *, PyObject *);
+static PyObject *gdbpy_flush (PyObject *, PyObject *);
+
+static PyMethodDef GdbMethods[] =
+{
+ { "execute", execute_gdb_command, METH_VARARGS,
+ "Execute a gdb command" },
+ { "show", get_show_variable, METH_VARARGS,
+ "Return a gdb setting's value" },
+
+ { "write", gdbpy_write, METH_VARARGS,
+ "Write a string using gdb's filtered stream." },
+ { "flush", gdbpy_flush, METH_NOARGS,
+ "Flush gdb's filtered stdout stream." },
+
+ {NULL, NULL, 0, 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
+ responsible for freeing it. */
+
+static char *
+compute_python_string (struct command_line *l)
+{
+ struct command_line *iter;
+ char *script = NULL;
+ int size = 0;
+ int here;
+
+ for (iter = l; iter; iter = iter->next)
+ size += strlen (iter->line) + 1;
+
+ script = xmalloc (size + 1);
+ here = 0;
+ for (iter = l; iter; iter = iter->next)
+ {
+ int len = strlen (iter->line);
+ strcpy (&script[here], iter->line);
+ here += len;
+ script[here++] = '\n';
+ }
+ script[here] = '\0';
+ return script;
+}
+
+void
+eval_python_from_control_command (struct command_line *cmd)
+{
+ char *script;
+
+ if (cmd->body_count != 1)
+ error (_("Invalid \"python\" block structure."));
+
+ script = compute_python_string (cmd->body_list[0]);
+ PyRun_SimpleString (script);
+ xfree (script);
+ if (PyErr_Occurred ())
+ {
+ gdbpy_print_stack ();
+ error (_("error while executing Python code"));
+ }
+}
+
+/* Implementation of the gdb "python" command. */
+
+static void
+python_command (char *arg, int from_tty)
+{
+ while (arg && *arg && isspace (*arg))
+ ++arg;
+ if (arg && *arg)
+ {
+ PyRun_SimpleString (arg);
+ if (PyErr_Occurred ())
+ {
+ gdbpy_print_stack ();
+ error (_("error while executing Python code"));
+ }
+ }
+ else
+ {
+ char *tmpbuf = xstrprintf ("Type python script");
+ struct cleanup *cleanups = make_cleanup (xfree, tmpbuf);
+ struct command_line *l = get_command_line (python_control, "");
+ cleanups = make_cleanup_free_command_lines (&l);
+ execute_control_command_suppressed (l);
+ do_cleanups (cleanups);
+ }
+}
+
+\f
+
+/* Transform a gdb variable's value into a Python value. May return
+ NULL (and set a Python exception) on error. Helper function for
+ get_show_variable. */
+
+static PyObject *
+variable_to_python (struct cmd_list_element *cmd)
+{
+ switch (cmd->var_type)
+ {
+ case var_string:
+ case var_string_noescape:
+ case var_optional_filename:
+ case var_filename:
+ case var_enum:
+ {
+ char *str = * (char **) cmd->var;
+ if (! str)
+ str = "";
+ return PyString_Decode (str, strlen (str), host_charset (), NULL);
+ }
+
+ case var_boolean:
+ {
+ if (* (int *) cmd->var)
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
+ }
+
+ case var_auto_boolean:
+ {
+ enum auto_boolean ab = * (enum auto_boolean *) cmd->var;
+ if (ab == AUTO_BOOLEAN_TRUE)
+ Py_RETURN_TRUE;
+ else if (ab == AUTO_BOOLEAN_FALSE)
+ Py_RETURN_FALSE;
+ else
+ Py_RETURN_NONE;
+ }
+
+ case var_integer:
+ if ((* (int *) cmd->var) == INT_MAX)
+ Py_RETURN_NONE;
+ /* Fall through. */
+ case var_zinteger:
+ return PyLong_FromLong (* (int *) cmd->var);
+
+ case var_uinteger:
+ {
+ unsigned int val = * (unsigned int *) cmd->var;
+ if (val == UINT_MAX)
+ Py_RETURN_NONE;
+ return PyLong_FromUnsignedLong (val);
+ }
+ }
+
+ return PyErr_Format (PyExc_RuntimeError, "programmer error: unhandled type");
+}
+
+/* A Python function which returns a gdb variable's value as a Python
+ value. */
+
+static PyObject *
+get_show_variable (PyObject *self, PyObject *args)
+{
+ struct cmd_list_element *alias, *prefix, *cmd;
+ char *arg, *newarg;
+ volatile struct gdb_exception except;
+
+ if (! PyArg_ParseTuple (args, "s", &arg))
+ return NULL;
+
+ newarg = concat ("show ", arg, (char *) NULL);
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ if (! lookup_cmd_composition (newarg, &alias, &prefix, &cmd))
+ {
+ xfree (newarg);
+ return PyErr_Format (PyExc_RuntimeError,
+ "could not find variable `%s'", arg);
+ }
+ }
+ xfree (newarg);
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ if (! cmd->var)
+ return PyErr_Format (PyExc_RuntimeError, "`%s' is not a variable", arg);
+ return variable_to_python (cmd);
+}
+
+/* A Python function which evaluates a string using the gdb CLI. */
+
+static PyObject *
+execute_gdb_command (PyObject *self, PyObject *args)
+{
+ struct cmd_list_element *alias, *prefix, *cmd;
+ char *arg, *newarg;
+ volatile struct gdb_exception except;
+ struct cleanup *old_chain;
+
+ if (! PyArg_ParseTuple (args, "s", &arg))
+ return NULL;
+
+ old_chain = make_cleanup (null_cleanup, 0);
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ execute_command (arg, 0);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ /* Do any commands attached to breakpoint we stopped at. Only if we
+ are always running synchronously. Or if we have just executed a
+ command that doesn't start the target. */
+ if (!target_can_async_p () || !target_executing)
+ {
+ bpstat_do_actions (&stop_bpstat);
+ do_cleanups (old_chain);
+ }
+
+ Py_RETURN_NONE;
+}
+
+/* This is a cleanup function which decrements the refcount on a
+ Python object. */
+
+static void
+py_decref (void *p)
+{
+ PyObject *py = p;
+ /* Note that we need the extra braces in this 'if' to avoid a
+ warning from gcc. */
+ if (py)
+ {
+ Py_DECREF (py);
+ }
+}
+
+/* Return a new cleanup which will decrement the Python object's
+ refcount when run. */
+
+struct cleanup *
+make_cleanup_py_decref (PyObject *py)
+{
+ return make_cleanup (py_decref, (void *) py);
+}
+
+\f
+
+/* Printing. */
+
+/* A python function to write a single string using gdb's filtered
+ output stream. */
+static PyObject *
+gdbpy_write (PyObject *self, PyObject *args)
+{
+ char *arg;
+ if (! PyArg_ParseTuple (args, "s", &arg))
+ return NULL;
+ printf_filtered ("%s", arg);
+ Py_RETURN_NONE;
+}
+
+/* A python function to flush gdb's filtered output stream. */
+static PyObject *
+gdbpy_flush (PyObject *self, PyObject *args)
+{
+ gdb_flush (gdb_stdout);
+ Py_RETURN_NONE;
+}
+
+/* True if we should print the stack when catching a Python error,
+ false otherwise. */
+static int gdbpy_should_print_stack = 1;
+
+/* Print a python exception trace, or print nothing and clear the
+ python exception, depending on gdbpy_should_print_stack. Only call
+ this if a python exception is set. */
+void
+gdbpy_print_stack (void)
+{
+ if (gdbpy_should_print_stack)
+ PyErr_Print ();
+ else
+ PyErr_Clear ();
+}
+
+\f
+
+/* Initialize the Python code. */
+
+void
+_initialize_python (void)
+{
+ add_com ("python", class_obscure, python_command, _("\
+Evaluate a Python command.\n\
+\n\
+The command can be given as an argument, for instance:\n\
+\n\
+ python print 23\n\
+\n\
+If no argument is given, the following lines are read and used\n\
+as the Python commands. Type a line containing \"end\" to indicate\n\
+the end of the command."));
+
+ add_setshow_boolean_cmd ("python-stack", class_maintenance,
+ &gdbpy_should_print_stack, _("\
+Set Python stack printing."), _("\
+Show Python stack printing."), _("\
+Enables printing of Python stack traces."),
+ NULL, NULL,
+ &maintenance_set_cmdlist,
+ &maintenance_show_cmdlist);
+
+ Py_Initialize ();
+
+ gdb_module = Py_InitModule ("gdb", GdbMethods);
+
+ /* The casts to (char*) are for python 2.4. */
+ PyModule_AddStringConstant (gdb_module, "VERSION", (char*) version);
+ PyModule_AddStringConstant (gdb_module, "HOST_CONFIG", (char*) host_name);
+ PyModule_AddStringConstant (gdb_module, "TARGET_CONFIG", (char*) target_name);
+
+ PyRun_SimpleString ("import gdb");
+
+ /* Create a couple objects which are used for Python's stdout and
+ stderr. */
+ PyRun_SimpleString ("\
+import sys\n\
+class GdbOutputFile:\n\
+ def close(self):\n\
+ # Do nothing.\n\
+ return None\n\
+\n\
+ def isatty(self):\n\
+ return False\n\
+\n\
+ def write(self, s):\n\
+ gdb.write(s)\n\
+\n\
+ def writelines(self, iterable):\n\
+ for line in iterable:\n\
+ self.write(line)\n\
+\n\
+ def flush(self):\n\
+ gdb.flush()\n\
+\n\
+sys.stderr = GdbOutputFile()\n\
+sys.stdout = GdbOutputFile()\n\
+");
+}
+
+#else /* HAVE_PYTHON */
+
+/* Dummy implementation of the gdb "python" command. */
+
+static void
+python_command (char *arg, int from_tty)
+{
+ while (arg && *arg && isspace (*arg))
+ ++arg;
+ if (arg && *arg)
+ error (_("Python scripting is not supported in this copy of GDB."));
+ else
+ {
+ char *tmpbuf = xstrprintf ("Type python script");
+ struct cleanup *cleanups = make_cleanup (xfree, tmpbuf);
+ struct command_line *l = get_command_line (python_control, "");
+ cleanups = make_cleanup_free_command_lines (&l);
+ execute_control_command_suppressed (l);
+ do_cleanups (cleanups);
+ }
+}
+
+void
+eval_python_from_control_command (struct command_line *cmd)
+{
+ error (_("Python scripting is not supported in this copy of GDB."));
+}
+
+/* Initialize dummy Python code. */
+
+void
+_initialize_python (void)
+{
+ add_com ("python", class_obscure, python_command, _("\
+Evaluate a Python command.\n\
+\n\
+Python scripting is not supported in this copy of GDB.\n\
+This command is only a placeholder."));
+}
+
+#endif /* HAVE_PYTHON */
diff --git a/gdb/python/python.h b/gdb/python/python.h
new file mode 100644
index 0000000..00ff159
--- /dev/null
+++ b/gdb/python/python.h
@@ -0,0 +1,27 @@
+/* Python/gdb header for generic use in gdb
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDB_PYTHON_H
+#define GDB_PYTHON_H
+
+#include "value.h"
+
+void eval_python_from_control_command (struct command_line *);
+
+#endif /* GDB_PYTHON_H */
diff --git a/gdb/python/utils.c b/gdb/python/utils.c
new file mode 100644
index 0000000..9883cc5
--- /dev/null
+++ b/gdb/python/utils.c
@@ -0,0 +1,117 @@
+/* General utility routines for GDB/Python.
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "charset.h"
+#include "python-internal.h"
+
+
+/* This is a cleanup function which decrements the refcount on a
+ Python object. */
+
+static void
+py_decref (void *p)
+{
+ PyObject *py = p;
+ /* Note that we need the extra braces in this 'if' to avoid a
+ warning from gcc. */
+ if (py)
+ {
+ Py_DECREF (py);
+ }
+}
+
+/* Return a new cleanup which will decrement the Python object's
+ refcount when run. */
+
+struct cleanup *
+make_cleanup_py_decref (PyObject *py)
+{
+ return make_cleanup (py_decref, (void *) py);
+}
+
+/* Converts a Python 8-bit string to a unicode string object. Assumes the
+ 8-bit string is in the host charset. If an error occurs during conversion,
+ returns NULL with a python exception set.
+
+ As an added bonus, the functions accepts a unicode string and returns it
+ right away, so callers don't need to check which kind of string they've
+ got.
+
+ If the given object is not one of the mentioned string types, NULL is
+ returned, with the TypeError python exception set. */
+PyObject *
+python_string_to_unicode (PyObject *obj)
+{
+ PyObject *unicode_str;
+
+ /* If obj is already a unicode string, just return it.
+ I wish life was always that simple... */
+ if (PyUnicode_Check (obj))
+ unicode_str = obj;
+ else if (PyString_Check (obj))
+ unicode_str = PyUnicode_FromEncodedObject (obj, host_charset (), NULL);
+ else
+ {
+ PyErr_SetString (PyExc_TypeError,
+ _("Expected a string or unicode object."));
+ unicode_str = NULL;
+ }
+
+ return unicode_str;
+}
+
+/* Returns a newly allocated string with the contents of the given unicode
+ string object converted to the target's charset. If an error occurs during
+ the conversion, NULL will be returned and a python exception will be set.
+
+ The caller is responsible for xfree'ing the string. */
+char *
+unicode_to_target_string (PyObject *unicode_str)
+{
+ char *target_string;
+ PyObject *string;
+
+ /* Translate string to target's charset. */
+ string = PyUnicode_AsEncodedString (unicode_str, target_charset (), NULL);
+ if (string == NULL)
+ return NULL;
+
+ target_string = xstrdup (PyString_AsString (string));
+
+ Py_DECREF (string);
+
+ return target_string;
+}
+
+/* Converts a python string (8-bit or unicode) to a target string in
+ the target's charset. Returns NULL on error, with a python exception set.
+
+ The caller is responsible for xfree'ing the string. */
+char *
+python_string_to_target_string (PyObject *obj)
+{
+ PyObject *str;
+
+ str = python_string_to_unicode (obj);
+ if (str == NULL)
+ return NULL;
+
+ return unicode_to_target_string (str);
+}
diff --git a/gdb/testsuite/gdb.python/python.exp b/gdb/testsuite/gdb.python/python.exp
new file mode 100644
index 0000000..adc79f3
--- /dev/null
+++ b/gdb/testsuite/gdb.python/python.exp
@@ -0,0 +1,40 @@
+# Copyright (C) 2008 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite. It tests the mechanism
+# exposing values to Python.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test_multiple "python print 23" "verify python support" {
+ -re "not supported.*$gdb_prompt $" {
+ unsupported "python support is disabled"
+ return -1
+ }
+ -re "$gdb_prompt $" {}
+}
+
+gdb_test_multiple "python\nprint 23\nend\n" "multi-line python command" {
+ -re "23.*$gdb_prompt $" { pass "multi-line python command" }
+ -re "$gdb_prompt $" { fail "multi-line python command" }
+}
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA] Re: [RFC][patch 1/9] initial Python support
2008-07-15 7:38 ` [RFA] " Thiago Jung Bauermann
@ 2008-07-15 17:19 ` Tom Tromey
2008-07-15 18:33 ` Thiago Jung Bauermann
2008-07-16 14:39 ` Tom Tromey
2008-07-15 18:01 ` [RFA] Re: [RFC][patch 1/9] " Thiago Jung Bauermann
1 sibling, 2 replies; 147+ messages in thread
From: Tom Tromey @ 2008-07-15 17:19 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches ml
>>>>> "Thiago" == Thiago Jung Bauermann <bauerman@br.ibm.com> writes:
This patch had a couple of problems I didn't have time to fix up
yesterday. I'm sorry about this ... I knew of them but didn't get the
message out on time.
Thiago> + if (list->control_type == python_control)
Thiago> + {
Thiago> + ui_out_field_string (uiout, NULL, "python");
Thiago> + print_command_lines (uiout, *list->body_list, depth + 1);
Thiago> + if (depth)
Thiago> + ui_out_spaces (uiout, 2 * depth);
Thiago> + ui_out_field_string (uiout, NULL, "end");
Thiago> + ui_out_text (uiout, "\n");
Thiago> + list = list->next;
Thiago> + continue;
We should probably explicitly *not* indent python command bodies
somehow.
Thiago> +@node Python
Thiago> +@chapter Scripting @value{GDBN} using Python
Thiago> +@cindex Python
I forgot to document the new 'python-stack' variable. (This one I
just realized this morning...)
Thiago> +
Thiago> +void
Thiago> +eval_python_from_control_command (struct command_line *cmd)
Thiago> +{
This function needs a comment.
Thiago> + char *tmpbuf = xstrprintf ("Type python script");
Thiago> + struct cleanup *cleanups = make_cleanup (xfree, tmpbuf);
Thiago> + struct command_line *l = get_command_line (python_control, "");
Thiago> + cleanups = make_cleanup_free_command_lines (&l);
Thiago> + execute_control_command_suppressed (l);
Thiago> + do_cleanups (cleanups);
Here we allocate a temporary string for no good reason (we can just
use a string constant afaik); then we don't actually print it as a
prompt. Whoops. I think I didn't quite finish a change
here... though I don't really remember.
How can we change our development process in git to make this work
simpler for you?
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA] Re: [RFC][patch 1/9] initial Python support
2008-07-15 7:38 ` [RFA] " Thiago Jung Bauermann
2008-07-15 17:19 ` Tom Tromey
@ 2008-07-15 18:01 ` Thiago Jung Bauermann
1 sibling, 0 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-07-15 18:01 UTC (permalink / raw)
To: gdb-patches ml
Hi,
Sorry folks, the patch I just posted failed to apply the gdb.texinfo
changes, and wouldn't compile on CVS HEAD (turns out the base we were
using for the python branch is not as clean as I thought).
This version applies cleanly, compiles and passes the smoke test.
/me puts on brownbag
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
gdb/
2008-07-15 Vladimir Prus <vladimir@codesourcery.com>
Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
Doug Evans <dje@google.com>
* Makefile.in (SUBDIR_PYTHON_OBS, SUBDIR_PYTHON_SRCS,
SUBDIR_PYTHON_DEPS, SUBDIR_PYTHON_LDFLAGS, SUBDIR_PYTHON_CFLAGS,
PYTHON_CFLAGS): New.
(python_h, python_internal_h): New.
(COMMON_OBS): Add python.o.
(INIT_FILES): Add python/python.c.
(cli-script.o): Depend on python.h
(python.o, python-utils.o): New.
* cli/cli-script.c (print_command_lines): Handle python_control.
(execute_control_command): Handle python_control.
(execute_control_command_suppressed): New function.
(while_command): Call execute_control_command_suppressed.
(if_command): Likewise.
(get_command_line): Remove static attribute.
(read_next_line): Handle "python".
(recurse_read_control_structure): Handle python_control.
(read_command_lines): Handle python_control.
Include python.h.
* cli/cli-script.h (get_command_line): Add prototype.
(execute_control_command_suppressed): Likewise.
* configure.ac: Add --with-python.
* defs.h (enum command_control_type) <python_control>: New
constant.
* python/python-internal.h: New file.
* python/python.c: New file.
* python/python.h: New file.
* python/utils.c: New file.
gdb/doc/
2008-07-15 Tom Tromey <tromey@redhat.com>
* gdb.texinfo (Python): New chapter.
gdb/testsuite/
2008-07-15 Tom Tromey <tromey@redhat.com>
* gdb.python/python.exp: New file.
Index: typos/gdb/Makefile.in
===================================================================
--- typos.orig/gdb/Makefile.in 2008-07-15 14:04:10.000000000 -0300
+++ typos/gdb/Makefile.in 2008-07-15 14:48:58.000000000 -0300
@@ -254,6 +254,18 @@ SUBDIR_TUI_LDFLAGS=
SUBDIR_TUI_CFLAGS= \
-DTUI=1
+#
+# python sub directory definitons
+#
+SUBDIR_PYTHON_OBS = \
+ python-utils.o
+SUBDIR_PYTHON_SRCS = \
+ python/python.c \
+ python/utils.c
+SUBDIR_PYTHON_DEPS =
+SUBDIR_PYTHON_LDFLAGS=
+SUBDIR_PYTHON_CFLAGS=
+
# Opcodes currently live in one of two places. Either they are in the
# opcode library, typically ../opcodes, or they are in a header file
@@ -963,6 +975,13 @@ tui_wingeneral_h = $(srcdir)/tui/tui-win
tui_win_h = $(srcdir)/tui/tui-win.h $(tui_data_h)
tui_winsource_h = $(srcdir)/tui/tui-winsource.h $(tui_data_h)
+#
+# gdb/python/ headers
+#
+
+python_h = $(srcdir)/python/python.h $(value_h)
+python_internal_h = $(srcdir)/python/python-internal.h
+
# gdb/features preparsed descriptions
features_headers = $(defs_h) $(gdbtypes_h) $(target_descriptions_h)
arm_with_iwmmxt_c = $(srcdir)/features/arm-with-iwmmxt.c $(features_headers)
@@ -1089,7 +1108,8 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $
tramp-frame.o \
solib.o solib-null.o \
prologue-value.o memory-map.o xml-support.o \
- target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o
+ target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \
+ python.o
TSOBS = inflow.o
@@ -1283,7 +1303,11 @@ test-cp-name-parser$(EXEEXT): test-cp-na
# duplicates. Files in the gdb/ directory can end up appearing in
# COMMON_OBS (as a .o file) and CONFIG_SRCS (as a .c file).
-INIT_FILES = $(COMMON_OBS) $(TSOBS) $(CONFIG_SRCS)
+# NOTE: bauermann/2008-06-15: python.c needs to be explicitly included
+# because the generation of init.c does not work for .c files which
+# result in differently named objects (i.e., python/python -> python.o).
+
+INIT_FILES = $(COMMON_OBS) $(TSOBS) $(CONFIG_SRCS) python/python.c
init.c: $(INIT_FILES)
@echo Making init.c
@rm -f init.c-tmp init.l-tmp
@@ -3064,7 +3088,8 @@ cli-logging.o: $(srcdir)/cli/cli-logging
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-logging.c
cli-script.o: $(srcdir)/cli/cli-script.c $(defs_h) $(value_h) $(language_h) \
$(ui_out_h) $(gdb_string_h) $(exceptions_h) $(top_h) $(cli_cmds_h) \
- $(cli_decode_h) $(cli_script_h) $(gdb_assert_h) $(breakpoint_h)
+ $(cli_decode_h) $(cli_script_h) $(gdb_assert_h) $(breakpoint_h) \
+ $(python_h)
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-script.c
cli-setshow.o: $(srcdir)/cli/cli-setshow.c $(defs_h) $(readline_tilde_h) \
$(value_h) $(gdb_string_h) $(ui_out_h) $(cli_decode_h) $(cli_cmds_h) \
@@ -3389,4 +3414,22 @@ tui-winsource.o: $(srcdir)/tui/tui-winso
$(gdb_curses_h) $(gdb_assert_h)
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tui-winsource.c
+#
+# gdb/python/ dependencies
+#
+# Need to explicitly specify the compile rule as make will do nothing
+# or try to compile the object file into the sub-directory.
+
+# Flags needed to compile Python code (taken from python-config --cflags)
+PYTHON_CFLAGS=-fno-strict-aliasing -DNDEBUG -fwrapv
+
+python.o: $(srcdir)/python/python.c $(defs_h) $(python_h) \
+ $(command_h) $(libiberty_h) $(cli_decode_h) $(charset_h) $(top_h) \
+ $(exceptions_h) $(python_internal_h) $(version_h) $(cli_script_h) \
+ $(ui_out_h) $(target_h) $(gdbthread_h)
+ $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) $(srcdir)/python/python.c
+python-utils.o: $(srcdir)/python/utils.c $(defs_h) $(python_internal_h)
+ $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
+ $(srcdir)/python/utils.c -o python-utils.o
+
### end of the gdb Makefile.in.
Index: typos/gdb/cli/cli-script.c
===================================================================
--- typos.orig/gdb/cli/cli-script.c 2008-07-15 14:04:10.000000000 -0300
+++ typos/gdb/cli/cli-script.c 2008-07-15 14:09:52.000000000 -0300
@@ -34,6 +34,8 @@
#include "cli/cli-script.h"
#include "gdb_assert.h"
+#include "python/python.h"
+
/* Prototypes for local functions */
static enum command_control_type
@@ -102,7 +104,7 @@ build_command_line (enum command_control
/* Build and return a new command structure for the control commands
such as "if" and "while". */
-static struct command_line *
+struct command_line *
get_command_line (enum command_control_type type, char *arg)
{
struct command_line *cmd;
@@ -225,6 +227,18 @@ print_command_lines (struct ui_out *uiou
continue;
}
+ if (list->control_type == python_control)
+ {
+ ui_out_field_string (uiout, NULL, "python");
+ print_command_lines (uiout, *list->body_list, depth + 1);
+ if (depth)
+ ui_out_spaces (uiout, 2 * depth);
+ ui_out_field_string (uiout, NULL, "end");
+ ui_out_text (uiout, "\n");
+ list = list->next;
+ continue;
+ }
+
/* ignore illegal command type and try next */
list = list->next;
} /* while (list) */
@@ -527,6 +541,12 @@ execute_control_command (struct command_
ret = commands_from_control_command (new_line, cmd);
break;
}
+ case python_control:
+ {
+ eval_python_from_control_command (cmd);
+ ret = simple_control;
+ break;
+ }
default:
warning (_("Invalid control type in canned commands structure."));
@@ -538,6 +558,17 @@ execute_control_command (struct command_
return ret;
}
+/* Like execute_control_command, but first set
+ suppress_next_print_command_trace. */
+
+enum command_control_type
+execute_control_command_suppressed (struct command_line *cmd)
+{
+ suppress_next_print_command_trace = 1;
+ return execute_control_command (cmd);
+}
+
+
/* "while" command support. Executes a body of statements while the
loop condition is nonzero. */
@@ -552,8 +583,7 @@ while_command (char *arg, int from_tty)
if (command == NULL)
return;
- suppress_next_print_command_trace = 1;
- execute_control_command (command);
+ execute_control_command_suppressed (command);
free_command_lines (&command);
}
@@ -571,8 +601,7 @@ if_command (char *arg, int from_tty)
if (command == NULL)
return;
- suppress_next_print_command_trace = 1;
- execute_control_command (command);
+ execute_control_command_suppressed (command);
free_command_lines (&command);
}
@@ -886,6 +915,12 @@ read_next_line (struct command_line **co
first_arg++;
*command = build_command_line (commands_control, first_arg);
}
+ else if (p1 - p == 6 && !strncmp (p, "python", 6))
+ {
+ /* Note that we ignore the inline "python command" form
+ here. */
+ *command = build_command_line (python_control, "");
+ }
else if (p1 - p == 10 && !strncmp (p, "loop_break", 10))
{
*command = (struct command_line *)
@@ -962,6 +997,7 @@ recurse_read_control_structure (struct c
{
if (current_cmd->control_type == while_control
|| current_cmd->control_type == if_control
+ || current_cmd->control_type == python_control
|| current_cmd->control_type == commands_control)
{
/* Success reading an entire canned sequence of commands. */
@@ -1013,6 +1049,7 @@ recurse_read_control_structure (struct c
on it. */
if (next->control_type == while_control
|| next->control_type == if_control
+ || next->control_type == python_control
|| next->control_type == commands_control)
{
control_level++;
@@ -1086,6 +1123,7 @@ read_command_lines (char *prompt_arg, in
if (next->control_type == while_control
|| next->control_type == if_control
+ || next->control_type == python_control
|| next->control_type == commands_control)
{
control_level++;
Index: typos/gdb/cli/cli-script.h
===================================================================
--- typos.orig/gdb/cli/cli-script.h 2008-07-15 14:04:10.000000000 -0300
+++ typos/gdb/cli/cli-script.h 2008-07-15 14:09:52.000000000 -0300
@@ -40,6 +40,12 @@ extern void show_user_1 (struct cmd_list
extern enum command_control_type
execute_control_command (struct command_line *cmd);
+extern enum command_control_type
+ execute_control_command_suppressed (struct command_line *cmd);
+
+extern struct command_line *get_command_line (enum command_control_type,
+ char *);
+
extern void print_command_lines (struct ui_out *,
struct command_line *, unsigned int);
Index: typos/gdb/configure.ac
===================================================================
--- typos.orig/gdb/configure.ac 2008-07-15 14:04:10.000000000 -0300
+++ typos/gdb/configure.ac 2008-07-15 14:09:52.000000000 -0300
@@ -497,6 +497,99 @@ else
fi
fi
+dnl Utility to simplify finding libpython.
+AC_DEFUN([AC_TRY_LIBPYTHON],
+[
+ version=$1
+ define([have_libpython_var],$2)
+ define([VERSION],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+ [HAVE_LIB]VERSION=no
+ AC_MSG_CHECKING([for ${version}])
+ save_LIBS=$LIBS
+ LIBS="$LIBS -l${version}"
+ AC_LINK_IFELSE(AC_LANG_PROGRAM([[#include "${version}/Python.h"]],
+ [[Py_Initialize ();]]),
+ [[HAVE_LIB]VERSION=yes
+ have_libpython_var=yes],
+ [LIBS=$save_LIBS])
+ AC_MSG_RESULT([$[HAVE_LIB]VERSION])
+])
+
+AC_ARG_WITH(python,
+ AS_HELP_STRING([--with-python], [include python support (auto/yes/no/<path>)]),
+ [], [with_python=auto])
+AC_MSG_CHECKING([whether to use python])
+AC_MSG_RESULT([$with_python])
+
+if test "${with_python}" = no; then
+ AC_MSG_WARN([python support disabled; some features may be unavailable.])
+ have_libpython=no
+else
+ case "${with_python}" in
+ yes | auto)
+ # Leave as empty, use defaults.
+ python_includes=
+ python_libs=
+ ;;
+ /*)
+ python_includes="-I${with_python}/include"
+ python_libs="-L${with_python}/lib"
+ ;;
+ *)
+ AC_ERROR(invalid value for --with-python)
+ ;;
+ esac
+
+ save_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS ${python_includes}"
+ save_LIBS=$LIBS
+ LIBS="$LIBS ${python_libs}"
+ have_libpython=no
+ if test "${have_libpython}" = no; then
+ AC_TRY_LIBPYTHON(python2.6, have_libpython)
+ if test "${HAVE_LIBPYTHON2_6}" = yes; then
+ AC_DEFINE(HAVE_LIBPYTHON2_6, 1, [Define if Python 2.6 is being used.])
+ fi
+ fi
+ if test ${have_libpython} = no; then
+ AC_TRY_LIBPYTHON(python2.5, have_libpython)
+ if test "${HAVE_LIBPYTHON2_5}" = yes; then
+ AC_DEFINE(HAVE_LIBPYTHON2_5, 1, [Define if Python 2.5 is being used.])
+ fi
+ fi
+ if test ${have_libpython} = no; then
+ AC_TRY_LIBPYTHON(python2.4, have_libpython)
+ if test "${HAVE_LIBPYTHON2_4}" = yes; then
+ AC_DEFINE(HAVE_LIBPYTHON2_4, 1, [Define if Python 2.4 is being used.])
+ fi
+ fi
+ if test ${have_libpython} = no; then
+ case "${with_python}" in
+ yes)
+ AC_MSG_ERROR([python is missing or unusable])
+ ;;
+ auto)
+ AC_MSG_WARN([python is missing or unusable; some features may be unavailable.])
+ ;;
+ *)
+ AC_MSG_ERROR([no usable python found at ${with_python}])
+ ;;
+ esac
+ CPPFLAGS=$save_CPPFLAGS
+ LIBS=$save_LIBS
+ fi
+fi
+
+if test "${have_libpython}" = yes; then
+ AC_DEFINE(HAVE_PYTHON, 1, [Define if Python interpreter is being linked in.])
+ CONFIG_OBS="$CONFIG_OBS \$(SUBDIR_PYTHON_OBS)"
+ CONFIG_DEPS="$CONFIG_DEPS \$(SUBDIR_PYTHON_DEPS)"
+ CONFIG_SRCS="$CONFIG_SRCS \$(SUBDIR_PYTHON_SRCS)"
+ CONFIG_INITS="$CONFIG_INITS \$(SUBDIR_PYTHON_INITS)"
+ ENABLE_CFLAGS="$ENABLE_CFLAGS \$(SUBDIR_PYTHON_CFLAGS)"
+fi
+
# ------------------------- #
# Checks for header files. #
# ------------------------- #
Index: typos/gdb/defs.h
===================================================================
--- typos.orig/gdb/defs.h 2008-07-15 14:04:10.000000000 -0300
+++ typos/gdb/defs.h 2008-07-15 14:09:52.000000000 -0300
@@ -652,6 +652,7 @@ enum command_control_type
while_control,
if_control,
commands_control,
+ python_control,
invalid_control
};
Index: typos/gdb/doc/gdb.texinfo
===================================================================
--- typos.orig/gdb/doc/gdb.texinfo 2008-07-15 14:04:10.000000000 -0300
+++ typos/gdb/doc/gdb.texinfo 2008-07-15 14:09:52.000000000 -0300
@@ -165,6 +165,7 @@ software in general. We will miss him.
* Emacs:: Using @value{GDBN} under @sc{gnu} Emacs
* GDB/MI:: @value{GDBN}'s Machine Interface.
* Annotations:: @value{GDBN}'s annotation interface.
+* Python:: Scripting @value{GDBN} using Python.
* GDB Bugs:: Reporting bugs in @value{GDBN}
@@ -22704,6 +22705,41 @@ source which is being displayed. @var{a
followed by one or more lowercase hex digits (note that this does not
depend on the language).
+@node Python
+@chapter Scripting @value{GDBN} using Python
+@cindex Python
+
+You can script @value{GDBN} using the @url{http://www.python.org/,
+Python} programming language. This feature is available only if
+@value{GDBN} was configured using @code{--with-python}.
+
+@kindex python
+The @code{python} command can be used to evaluate Python code.
+
+If given an argument, the @code{python} command will evaluate the
+argument as a Python command. For example:
+
+@smallexample
+(@value{GDBP}) python print 23
+23
+@end smallexample
+
+If you do not provide an argument to @code{python}, it will act as a
+multi-line command, like @code{define}. In this case, the Python
+script is made up of subsequent command lines, given after the
+@code{python} command. This command list is terminated using a line
+containing @code{end}. For example:
+
+@smallexample
+(@value{GDBP}) python
+Type python script
+End with a line saying just "end".
+>print 23
+>end
+23
+@end smallexample
+
+
@node GDB Bugs
@chapter Reporting Bugs in @value{GDBN}
@cindex bugs in @value{GDBN}
Index: typos/gdb/python/python-internal.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ typos/gdb/python/python-internal.h 2008-07-15 14:09:52.000000000 -0300
@@ -0,0 +1,73 @@
+/* Gdb/Python header for private use by Python module.
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDB_PYTHON_INTERNAL_H
+#define GDB_PYTHON_INTERNAL_H
+
+/* Python 2.4 doesn't include stdint.h soon enough to get {u,}intptr_t
+ needed by pyport.h. */
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+/* /usr/include/features.h on linux systems will define _POSIX_C_SOURCE
+ if it sees _GNU_SOURCE (which config.h will define).
+ pyconfig.h defines _POSIX_C_SOURCE to a different value than
+ /usr/include/features.h does causing compilation to fail.
+ To work around this, undef _POSIX_C_SOURCE before we include Python.h. */
+#undef _POSIX_C_SOURCE
+
+#if HAVE_LIBPYTHON2_4
+#include "python2.4/Python.h"
+/* Py_ssize_t is not defined until 2.5. */
+typedef Py_intptr_t Py_ssize_t;
+#elif HAVE_LIBPYTHON2_5
+#include "python2.5/Python.h"
+#elif HAVE_LIBPYTHON2_6
+#include "python2.6/Python.h"
+#else
+#error "Unable to find usable Python.h"
+#endif
+
+struct block;
+struct symbol;
+struct symtab_and_line;
+
+extern PyObject *gdb_module;
+
+struct cleanup *make_cleanup_py_decref (PyObject *py);
+
+/* Use this after a TRY_EXCEPT to throw the appropriate Python
+ exception. */
+#define GDB_PY_HANDLE_EXCEPTION(Exception) \
+ do { \
+ if (Exception.reason < 0) \
+ return PyErr_Format (Exception.reason == RETURN_QUIT \
+ ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, \
+ "%s", Exception.message); \
+ } while (0)
+
+
+void gdbpy_print_stack (void);
+
+PyObject *python_string_to_unicode (PyObject *obj);
+char *unicode_to_target_string (PyObject *unicode_str);
+char *python_string_to_target_string (PyObject *obj);
+
+#endif /* GDB_PYTHON_INTERNAL_H */
Index: typos/gdb/python/python.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ typos/gdb/python/python.c 2008-07-15 14:48:36.000000000 -0300
@@ -0,0 +1,409 @@
+/* General python/gdb code
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "command.h"
+#include "ui-out.h"
+#include "cli/cli-script.h"
+
+#include <ctype.h>
+
+#ifdef HAVE_PYTHON
+
+#include "python.h"
+#include "libiberty.h"
+#include "cli/cli-decode.h"
+#include "charset.h"
+#include "top.h"
+#include "exceptions.h"
+#include "python-internal.h"
+#include "version.h"
+#include "gdbcmd.h"
+#include "target.h"
+#include "gdbthread.h"
+
+
+PyObject *gdb_module;
+
+static PyObject *get_show_variable (PyObject *, PyObject *);
+static PyObject *execute_gdb_command (PyObject *, PyObject *);
+static PyObject *gdbpy_write (PyObject *, PyObject *);
+static PyObject *gdbpy_flush (PyObject *, PyObject *);
+
+static PyMethodDef GdbMethods[] =
+{
+ { "execute", execute_gdb_command, METH_VARARGS,
+ "Execute a gdb command" },
+ { "show", get_show_variable, METH_VARARGS,
+ "Return a gdb setting's value" },
+
+ { "write", gdbpy_write, METH_VARARGS,
+ "Write a string using gdb's filtered stream." },
+ { "flush", gdbpy_flush, METH_NOARGS,
+ "Flush gdb's filtered stdout stream." },
+
+ {NULL, NULL, 0, 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
+ responsible for freeing it. */
+
+static char *
+compute_python_string (struct command_line *l)
+{
+ struct command_line *iter;
+ char *script = NULL;
+ int size = 0;
+ int here;
+
+ for (iter = l; iter; iter = iter->next)
+ size += strlen (iter->line) + 1;
+
+ script = xmalloc (size + 1);
+ here = 0;
+ for (iter = l; iter; iter = iter->next)
+ {
+ int len = strlen (iter->line);
+ strcpy (&script[here], iter->line);
+ here += len;
+ script[here++] = '\n';
+ }
+ script[here] = '\0';
+ return script;
+}
+
+void
+eval_python_from_control_command (struct command_line *cmd)
+{
+ char *script;
+
+ if (cmd->body_count != 1)
+ error (_("Invalid \"python\" block structure."));
+
+ script = compute_python_string (cmd->body_list[0]);
+ PyRun_SimpleString (script);
+ xfree (script);
+ if (PyErr_Occurred ())
+ {
+ gdbpy_print_stack ();
+ error (_("error while executing Python code"));
+ }
+}
+
+/* Implementation of the gdb "python" command. */
+
+static void
+python_command (char *arg, int from_tty)
+{
+ while (arg && *arg && isspace (*arg))
+ ++arg;
+ if (arg && *arg)
+ {
+ PyRun_SimpleString (arg);
+ if (PyErr_Occurred ())
+ {
+ gdbpy_print_stack ();
+ error (_("error while executing Python code"));
+ }
+ }
+ else
+ {
+ char *tmpbuf = xstrprintf ("Type python script");
+ struct cleanup *cleanups = make_cleanup (xfree, tmpbuf);
+ struct command_line *l = get_command_line (python_control, "");
+ cleanups = make_cleanup_free_command_lines (&l);
+ execute_control_command_suppressed (l);
+ do_cleanups (cleanups);
+ }
+}
+
+\f
+
+/* Transform a gdb variable's value into a Python value. May return
+ NULL (and set a Python exception) on error. Helper function for
+ get_show_variable. */
+
+static PyObject *
+variable_to_python (struct cmd_list_element *cmd)
+{
+ switch (cmd->var_type)
+ {
+ case var_string:
+ case var_string_noescape:
+ case var_optional_filename:
+ case var_filename:
+ case var_enum:
+ {
+ char *str = * (char **) cmd->var;
+ if (! str)
+ str = "";
+ return PyString_Decode (str, strlen (str), host_charset (), NULL);
+ }
+
+ case var_boolean:
+ {
+ if (* (int *) cmd->var)
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
+ }
+
+ case var_auto_boolean:
+ {
+ enum auto_boolean ab = * (enum auto_boolean *) cmd->var;
+ if (ab == AUTO_BOOLEAN_TRUE)
+ Py_RETURN_TRUE;
+ else if (ab == AUTO_BOOLEAN_FALSE)
+ Py_RETURN_FALSE;
+ else
+ Py_RETURN_NONE;
+ }
+
+ case var_integer:
+ if ((* (int *) cmd->var) == INT_MAX)
+ Py_RETURN_NONE;
+ /* Fall through. */
+ case var_zinteger:
+ return PyLong_FromLong (* (int *) cmd->var);
+
+ case var_uinteger:
+ {
+ unsigned int val = * (unsigned int *) cmd->var;
+ if (val == UINT_MAX)
+ Py_RETURN_NONE;
+ return PyLong_FromUnsignedLong (val);
+ }
+ }
+
+ return PyErr_Format (PyExc_RuntimeError, "programmer error: unhandled type");
+}
+
+/* A Python function which returns a gdb variable's value as a Python
+ value. */
+
+static PyObject *
+get_show_variable (PyObject *self, PyObject *args)
+{
+ struct cmd_list_element *alias, *prefix, *cmd;
+ char *arg, *newarg;
+ volatile struct gdb_exception except;
+
+ if (! PyArg_ParseTuple (args, "s", &arg))
+ return NULL;
+
+ newarg = concat ("show ", arg, (char *) NULL);
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ if (! lookup_cmd_composition (newarg, &alias, &prefix, &cmd))
+ {
+ xfree (newarg);
+ return PyErr_Format (PyExc_RuntimeError,
+ "could not find variable `%s'", arg);
+ }
+ }
+ xfree (newarg);
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ if (! cmd->var)
+ return PyErr_Format (PyExc_RuntimeError, "`%s' is not a variable", arg);
+ return variable_to_python (cmd);
+}
+
+/* A Python function which evaluates a string using the gdb CLI. */
+
+static PyObject *
+execute_gdb_command (PyObject *self, PyObject *args)
+{
+ struct cmd_list_element *alias, *prefix, *cmd;
+ char *arg, *newarg;
+ volatile struct gdb_exception except;
+ struct cleanup *old_chain;
+
+ if (! PyArg_ParseTuple (args, "s", &arg))
+ return NULL;
+
+ old_chain = make_cleanup (null_cleanup, 0);
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ execute_command (arg, 0);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ /* Do any commands attached to breakpoint we stopped at. Only if we
+ are always running synchronously. Or if we have just executed a
+ command that doesn't start the target. */
+ if (!target_can_async_p () || !is_running (inferior_ptid))
+ {
+ bpstat_do_actions (&stop_bpstat);
+ do_cleanups (old_chain);
+ }
+
+ Py_RETURN_NONE;
+}
+
+\f
+
+/* Printing. */
+
+/* A python function to write a single string using gdb's filtered
+ output stream. */
+static PyObject *
+gdbpy_write (PyObject *self, PyObject *args)
+{
+ char *arg;
+ if (! PyArg_ParseTuple (args, "s", &arg))
+ return NULL;
+ printf_filtered ("%s", arg);
+ Py_RETURN_NONE;
+}
+
+/* A python function to flush gdb's filtered output stream. */
+static PyObject *
+gdbpy_flush (PyObject *self, PyObject *args)
+{
+ gdb_flush (gdb_stdout);
+ Py_RETURN_NONE;
+}
+
+/* True if we should print the stack when catching a Python error,
+ false otherwise. */
+static int gdbpy_should_print_stack = 1;
+
+/* Print a python exception trace, or print nothing and clear the
+ python exception, depending on gdbpy_should_print_stack. Only call
+ this if a python exception is set. */
+void
+gdbpy_print_stack (void)
+{
+ if (gdbpy_should_print_stack)
+ PyErr_Print ();
+ else
+ PyErr_Clear ();
+}
+
+\f
+
+/* Initialize the Python code. */
+
+void
+_initialize_python (void)
+{
+ add_com ("python", class_obscure, python_command, _("\
+Evaluate a Python command.\n\
+\n\
+The command can be given as an argument, for instance:\n\
+\n\
+ python print 23\n\
+\n\
+If no argument is given, the following lines are read and used\n\
+as the Python commands. Type a line containing \"end\" to indicate\n\
+the end of the command."));
+
+ add_setshow_boolean_cmd ("python-stack", class_maintenance,
+ &gdbpy_should_print_stack, _("\
+Set Python stack printing."), _("\
+Show Python stack printing."), _("\
+Enables printing of Python stack traces."),
+ NULL, NULL,
+ &maintenance_set_cmdlist,
+ &maintenance_show_cmdlist);
+
+ Py_Initialize ();
+
+ gdb_module = Py_InitModule ("gdb", GdbMethods);
+
+ /* The casts to (char*) are for python 2.4. */
+ PyModule_AddStringConstant (gdb_module, "VERSION", (char*) version);
+ PyModule_AddStringConstant (gdb_module, "HOST_CONFIG", (char*) host_name);
+ PyModule_AddStringConstant (gdb_module, "TARGET_CONFIG", (char*) target_name);
+
+ PyRun_SimpleString ("import gdb");
+
+ /* Create a couple objects which are used for Python's stdout and
+ stderr. */
+ PyRun_SimpleString ("\
+import sys\n\
+class GdbOutputFile:\n\
+ def close(self):\n\
+ # Do nothing.\n\
+ return None\n\
+\n\
+ def isatty(self):\n\
+ return False\n\
+\n\
+ def write(self, s):\n\
+ gdb.write(s)\n\
+\n\
+ def writelines(self, iterable):\n\
+ for line in iterable:\n\
+ self.write(line)\n\
+\n\
+ def flush(self):\n\
+ gdb.flush()\n\
+\n\
+sys.stderr = GdbOutputFile()\n\
+sys.stdout = GdbOutputFile()\n\
+");
+}
+
+#else /* HAVE_PYTHON */
+
+/* Dummy implementation of the gdb "python" command. */
+
+static void
+python_command (char *arg, int from_tty)
+{
+ while (arg && *arg && isspace (*arg))
+ ++arg;
+ if (arg && *arg)
+ error (_("Python scripting is not supported in this copy of GDB."));
+ else
+ {
+ char *tmpbuf = xstrprintf ("Type python script");
+ struct cleanup *cleanups = make_cleanup (xfree, tmpbuf);
+ struct command_line *l = get_command_line (python_control, "");
+ cleanups = make_cleanup_free_command_lines (&l);
+ execute_control_command_suppressed (l);
+ do_cleanups (cleanups);
+ }
+}
+
+void
+eval_python_from_control_command (struct command_line *cmd)
+{
+ error (_("Python scripting is not supported in this copy of GDB."));
+}
+
+/* Initialize dummy Python code. */
+
+void
+_initialize_python (void)
+{
+ add_com ("python", class_obscure, python_command, _("\
+Evaluate a Python command.\n\
+\n\
+Python scripting is not supported in this copy of GDB.\n\
+This command is only a placeholder."));
+}
+
+#endif /* HAVE_PYTHON */
Index: typos/gdb/python/python.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ typos/gdb/python/python.h 2008-07-15 14:09:52.000000000 -0300
@@ -0,0 +1,27 @@
+/* Python/gdb header for generic use in gdb
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDB_PYTHON_H
+#define GDB_PYTHON_H
+
+#include "value.h"
+
+void eval_python_from_control_command (struct command_line *);
+
+#endif /* GDB_PYTHON_H */
Index: typos/gdb/python/utils.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ typos/gdb/python/utils.c 2008-07-15 14:20:22.000000000 -0300
@@ -0,0 +1,117 @@
+/* General utility routines for GDB/Python.
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "charset.h"
+#include "python-internal.h"
+
+
+/* This is a cleanup function which decrements the refcount on a
+ Python object. */
+
+static void
+py_decref (void *p)
+{
+ PyObject *py = p;
+ /* Note that we need the extra braces in this 'if' to avoid a
+ warning from gcc. */
+ if (py)
+ {
+ Py_DECREF (py);
+ }
+}
+
+/* Return a new cleanup which will decrement the Python object's
+ refcount when run. */
+
+struct cleanup *
+make_cleanup_py_decref (PyObject *py)
+{
+ return make_cleanup (py_decref, (void *) py);
+}
+
+/* Converts a Python 8-bit string to a unicode string object. Assumes the
+ 8-bit string is in the host charset. If an error occurs during conversion,
+ returns NULL with a python exception set.
+
+ As an added bonus, the functions accepts a unicode string and returns it
+ right away, so callers don't need to check which kind of string they've
+ got.
+
+ If the given object is not one of the mentioned string types, NULL is
+ returned, with the TypeError python exception set. */
+PyObject *
+python_string_to_unicode (PyObject *obj)
+{
+ PyObject *unicode_str;
+
+ /* If obj is already a unicode string, just return it.
+ I wish life was always that simple... */
+ if (PyUnicode_Check (obj))
+ unicode_str = obj;
+ else if (PyString_Check (obj))
+ unicode_str = PyUnicode_FromEncodedObject (obj, host_charset (), NULL);
+ else
+ {
+ PyErr_SetString (PyExc_TypeError,
+ _("Expected a string or unicode object."));
+ unicode_str = NULL;
+ }
+
+ return unicode_str;
+}
+
+/* Returns a newly allocated string with the contents of the given unicode
+ string object converted to the target's charset. If an error occurs during
+ the conversion, NULL will be returned and a python exception will be set.
+
+ The caller is responsible for xfree'ing the string. */
+char *
+unicode_to_target_string (PyObject *unicode_str)
+{
+ char *target_string;
+ PyObject *string;
+
+ /* Translate string to target's charset. */
+ string = PyUnicode_AsEncodedString (unicode_str, target_charset (), NULL);
+ if (string == NULL)
+ return NULL;
+
+ target_string = xstrdup (PyString_AsString (string));
+
+ Py_DECREF (string);
+
+ return target_string;
+}
+
+/* Converts a python string (8-bit or unicode) to a target string in
+ the target's charset. Returns NULL on error, with a python exception set.
+
+ The caller is responsible for xfree'ing the string. */
+char *
+python_string_to_target_string (PyObject *obj)
+{
+ PyObject *str;
+
+ str = python_string_to_unicode (obj);
+ if (str == NULL)
+ return NULL;
+
+ return unicode_to_target_string (str);
+}
Index: typos/gdb/testsuite/gdb.python/python.exp
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ typos/gdb/testsuite/gdb.python/python.exp 2008-07-15 14:09:52.000000000 -0300
@@ -0,0 +1,40 @@
+# Copyright (C) 2008 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite. It tests the mechanism
+# exposing values to Python.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test_multiple "python print 23" "verify python support" {
+ -re "not supported.*$gdb_prompt $" {
+ unsupported "python support is disabled"
+ return -1
+ }
+ -re "$gdb_prompt $" {}
+}
+
+gdb_test_multiple "python\nprint 23\nend\n" "multi-line python command" {
+ -re "23.*$gdb_prompt $" { pass "multi-line python command" }
+ -re "$gdb_prompt $" { fail "multi-line python command" }
+}
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA] Re: [RFC][patch 1/9] initial Python support
2008-07-15 17:19 ` Tom Tromey
@ 2008-07-15 18:33 ` Thiago Jung Bauermann
2008-07-15 19:03 ` Tom Tromey
2008-07-16 14:39 ` Tom Tromey
1 sibling, 1 reply; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-07-15 18:33 UTC (permalink / raw)
To: tromey; +Cc: gdb-patches ml
On Tue, 2008-07-15 at 11:19 -0600, Tom Tromey wrote:
> How can we change our development process in git to make this work
> simpler for you?
Thanks for asking. :-)
Well, my suggestion is to stop using the git repo and move everything
here to the mailing list. After the 1st (initial python support) and 2nd
(export values) patches are accepted (and they seem to be close), I
don't see a reason to keep working in a separate branch. But if you
prefer to continue to use it, we can think of improvements to the
process (like rebasing to a clean CVS HEAD, for instance).
My current idea is to produce a refreshed version of each of the patches
that I posted in the original python series, with all the changes that
went into the python-revisited branch since they were first posted (I
already have that, with commits up to yesterday in my local
python-patches branch).
Then I can either post the patches here to the list, or (since I'm not
sure if they are ready to be approved) send you a patches/ directory
suitable for use with quilt, and from there each of us drive his own
patches to acceptance (there are one or two which have both our names in
the changelog. We can have a duel at sunset to decide about those).
WDYT?
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA] Re: [RFC][patch 1/9] initial Python support
2008-07-15 18:33 ` Thiago Jung Bauermann
@ 2008-07-15 19:03 ` Tom Tromey
2008-07-16 7:14 ` Thiago Jung Bauermann
0 siblings, 1 reply; 147+ messages in thread
From: Tom Tromey @ 2008-07-15 19:03 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches ml
>>>>> "Thiago" == Thiago Jung Bauermann <bauerman@br.ibm.com> writes:
Tom> How can we change our development process in git to make this
Tom> work simpler for you?
Thiago> Well, my suggestion is to stop using the git repo and move
Thiago> everything here to the mailing list. After the 1st (initial
Thiago> python support) and 2nd (export values) patches are accepted
Thiago> (and they seem to be close), I don't see a reason to keep
Thiago> working in a separate branch. But if you prefer to continue to
Thiago> use it, we can think of improvements to the process (like
Thiago> rebasing to a clean CVS HEAD, for instance).
I'm a bit reluctant to move purely to working from CVS. This will
make it harder for us to work on things in concert, and will require a
lot of administrative overhead as well. One thing that has been nice
about this project, so far, is that we can be fairly experimental and
we don't have to spend much time waiting... whereas my
cvs-head-hacking experience has been pretty much the opposite.
Thiago> sure if they are ready to be approved) send you a patches/
Thiago> directory suitable for use with quilt, and from there each of
Thiago> us drive his own patches to acceptance (there are one or two
Thiago> which have both our names in the changelog. We can have a duel
Thiago> at sunset to decide about those).
What if we used 'guilt' or 'StGIT' instead? I have never tried these,
but they both seem to basically be git+quilt, where the patches can
easily be shared. (Am I wrong about this?)
This would require anyone working on the git repository to use this
tool and to be careful about managing the patches. But, that would
take the work off you and spread it around -- exactly what we want.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA] Re: [RFC][patch 1/9] initial Python support
2008-07-15 19:03 ` Tom Tromey
@ 2008-07-16 7:14 ` Thiago Jung Bauermann
0 siblings, 0 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-07-16 7:14 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches ml
On Tue, 2008-07-15 at 13:03 -0600, Tom Tromey wrote:
> >>>>> "Thiago" == Thiago Jung Bauermann <bauerman@br.ibm.com> writes:
> Thiago> Well, my suggestion is to stop using the git repo and move
> Thiago> everything here to the mailing list. After the 1st (initial
> Thiago> python support) and 2nd (export values) patches are accepted
> Thiago> (and they seem to be close), I don't see a reason to keep
> Thiago> working in a separate branch. But if you prefer to continue to
> Thiago> use it, we can think of improvements to the process (like
> Thiago> rebasing to a clean CVS HEAD, for instance).
>
> I'm a bit reluctant to move purely to working from CVS. This will
> make it harder for us to work on things in concert, and will require a
> lot of administrative overhead as well. One thing that has been nice
> about this project, so far, is that we can be fairly experimental and
> we don't have to spend much time waiting... whereas my
> cvs-head-hacking experience has been pretty much the opposite.
Ok, makes sense. We can keep working in the branch.
> Thiago> sure if they are ready to be approved) send you a patches/
> Thiago> directory suitable for use with quilt, and from there each of
> Thiago> us drive his own patches to acceptance (there are one or two
> Thiago> which have both our names in the changelog. We can have a duel
> Thiago> at sunset to decide about those).
>
> What if we used 'guilt' or 'StGIT' instead? I have never tried these,
> but they both seem to basically be git+quilt, where the patches can
> easily be shared. (Am I wrong about this?)
I never used any of those, but from the cursory reading I just had about
them, it seems you are wrong about the "patches can easily be shared"
part. These tools seem designed to keep a private set of patches updated
against some remote branch, not intended to push and pull patches
around.
> This would require anyone working on the git repository to use this
> tool and to be careful about managing the patches. But, that would
> take the work off you and spread it around -- exactly what we want.
Well, I think we can make some small improvements to the current process
so that the work of keeping the patches should be lighter:
I just updated the patches-base branch to a pristine CVS HEAD from today
(by the way, the git repo was almost pristine already, the problem I had
was with some change from upstream. My bad.), and I rebased the
python-patches branch against it. So the patches are all refreshed to
today's HEAD.
I also resolved some minor differences between the code in the
python-patches and python-revisited branches, which inflicted some
unnecessary merge conflicts. These must have crept in while I was
initially dividing the code in patches. The python-patches and the
python-revisited trees are now exactly equal (as they should have always
been). I didn't push the latter yet because there's a build problem that
I need to sort out...
And to keep things that way, my idea is to update the patches-base
branch from time to time (every two weeks? one month?) and merge it into
python-revisited.
I think this will bring down the number of conflicts, which is the
biggest time sink here. (Also keeping the commits focused helps a lot
since then there's rarely the need to break the commit in two or three
parts, but we've been doing that already).
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA] Re: [RFC][patch 1/9] initial Python support
2008-07-15 17:19 ` Tom Tromey
2008-07-15 18:33 ` Thiago Jung Bauermann
@ 2008-07-16 14:39 ` Tom Tromey
2008-07-16 22:02 ` Thiago Jung Bauermann
1 sibling, 1 reply; 147+ messages in thread
From: Tom Tromey @ 2008-07-16 14:39 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches ml
Tom> This patch had a couple of problems I didn't have time to fix up
Tom> yesterday. I'm sorry about this ... I knew of them but didn't get the
Tom> message out on time.
I've pushed fixes for all these problems, plus one more I found --
"python" commands were not printing properly, due to a missing
newline. I added a regression test for this one.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA] Re: [RFC][patch 1/9] initial Python support
2008-07-16 14:39 ` Tom Tromey
@ 2008-07-16 22:02 ` Thiago Jung Bauermann
2008-07-18 19:50 ` Daniel Jacobowitz
0 siblings, 1 reply; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-07-16 22:02 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches ml
On Wed, 2008-07-16 at 08:38 -0600, Tom Tromey wrote:
> Tom> This patch had a couple of problems I didn't have time to fix up
> Tom> yesterday. I'm sorry about this ... I knew of them but didn't get the
> Tom> message out on time.
>
> I've pushed fixes for all these problems, plus one more I found --
> "python" commands were not printing properly, due to a missing
> newline. I added a regression test for this one.
This patch incorporates these fixes, and contains no problem that we are
aware of. It also cleanly applies on yesterday's CVS HEAD, passes the
included python.exp test and introduces no regression on the teststuite
(tested on ppc-linux).
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
gdb/
2008-07-16 Vladimir Prus <vladimir@codesourcery.com>
Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
Doug Evans <dje@google.com>
* Makefile.in (SUBDIR_PYTHON_OBS, SUBDIR_PYTHON_SRCS,
SUBDIR_PYTHON_DEPS, SUBDIR_PYTHON_LDFLAGS, SUBDIR_PYTHON_CFLAGS,
PYTHON_CFLAGS): New.
(python_h, python_internal_h): New.
(COMMON_OBS): Add python.o.
(INIT_FILES): Add python/python.c.
(cli-script.o): Depend on python.h
(python.o, python-utils.o): New.
* cli/cli-script.c (print_command_lines): Handle python_control.
(execute_control_command): Handle python_control.
(execute_control_command_suppressed): New function.
(while_command): Call execute_control_command_suppressed.
(if_command): Likewise.
(get_command_line): Remove static attribute.
(read_next_line): Handle "python".
(recurse_read_control_structure): Handle python_control.
(read_command_lines): Handle python_control.
Include python.h.
* cli/cli-script.h (get_command_line): Add prototype.
(execute_control_command_suppressed): Likewise.
* configure.ac: Add --with-python.
* defs.h (enum command_control_type) <python_control>: New
constant.
* python/python-internal.h: New file.
* python/python.c: New file.
* python/python.h: New file.
* python/utils.c: New file.
gdb/doc/
2008-07-16 Tom Tromey <tromey@redhat.com>
* gdb.texinfo (Python): New chapter.
gdb/testsuite/
2008-07-16 Tom Tromey <tromey@redhat.com>
* gdb.python/python.exp: New file.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 3e82b92..087453a 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -254,6 +254,18 @@ SUBDIR_TUI_LDFLAGS=
SUBDIR_TUI_CFLAGS= \
-DTUI=1
+#
+# python sub directory definitons
+#
+SUBDIR_PYTHON_OBS = \
+ python-utils.o
+SUBDIR_PYTHON_SRCS = \
+ python/python.c \
+ python/utils.c
+SUBDIR_PYTHON_DEPS =
+SUBDIR_PYTHON_LDFLAGS=
+SUBDIR_PYTHON_CFLAGS=
+
# Opcodes currently live in one of two places. Either they are in the
# opcode library, typically ../opcodes, or they are in a header file
@@ -963,6 +975,13 @@ tui_wingeneral_h = $(srcdir)/tui/tui-wingeneral.h
tui_win_h = $(srcdir)/tui/tui-win.h $(tui_data_h)
tui_winsource_h = $(srcdir)/tui/tui-winsource.h $(tui_data_h)
+#
+# gdb/python/ headers
+#
+
+python_h = $(srcdir)/python/python.h $(value_h)
+python_internal_h = $(srcdir)/python/python-internal.h
+
# gdb/features preparsed descriptions
features_headers = $(defs_h) $(gdbtypes_h) $(target_descriptions_h)
arm_with_iwmmxt_c = $(srcdir)/features/arm-with-iwmmxt.c $(features_headers)
@@ -1089,7 +1108,8 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
tramp-frame.o \
solib.o solib-null.o \
prologue-value.o memory-map.o xml-support.o \
- target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o
+ target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \
+ python.o
TSOBS = inflow.o
@@ -1283,7 +1303,11 @@ test-cp-name-parser$(EXEEXT): test-cp-name-parser.o $(LIBIBERTY)
# duplicates. Files in the gdb/ directory can end up appearing in
# COMMON_OBS (as a .o file) and CONFIG_SRCS (as a .c file).
-INIT_FILES = $(COMMON_OBS) $(TSOBS) $(CONFIG_SRCS)
+# NOTE: bauermann/2008-06-15: python.c needs to be explicitly included
+# because the generation of init.c does not work for .c files which
+# result in differently named objects (i.e., python/python -> python.o).
+
+INIT_FILES = $(COMMON_OBS) $(TSOBS) $(CONFIG_SRCS) python/python.c
init.c: $(INIT_FILES)
@echo Making init.c
@rm -f init.c-tmp init.l-tmp
@@ -3064,7 +3088,8 @@ cli-logging.o: $(srcdir)/cli/cli-logging.c $(defs_h) $(gdbcmd_h) $(ui_out_h) \
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-logging.c
cli-script.o: $(srcdir)/cli/cli-script.c $(defs_h) $(value_h) $(language_h) \
$(ui_out_h) $(gdb_string_h) $(exceptions_h) $(top_h) $(cli_cmds_h) \
- $(cli_decode_h) $(cli_script_h) $(gdb_assert_h) $(breakpoint_h)
+ $(cli_decode_h) $(cli_script_h) $(gdb_assert_h) $(breakpoint_h) \
+ $(python_h)
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-script.c
cli-setshow.o: $(srcdir)/cli/cli-setshow.c $(defs_h) $(readline_tilde_h) \
$(value_h) $(gdb_string_h) $(ui_out_h) $(cli_decode_h) $(cli_cmds_h) \
@@ -3389,4 +3414,22 @@ tui-winsource.o: $(srcdir)/tui/tui-winsource.c $(defs_h) $(symtab_h) \
$(gdb_curses_h) $(gdb_assert_h)
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tui-winsource.c
+#
+# gdb/python/ dependencies
+#
+# Need to explicitly specify the compile rule as make will do nothing
+# or try to compile the object file into the sub-directory.
+
+# Flags needed to compile Python code (taken from python-config --cflags)
+PYTHON_CFLAGS=-fno-strict-aliasing -DNDEBUG -fwrapv
+
+python.o: $(srcdir)/python/python.c $(defs_h) $(python_h) \
+ $(command_h) $(libiberty_h) $(cli_decode_h) $(charset_h) $(top_h) \
+ $(exceptions_h) $(python_internal_h) $(version_h) $(cli_script_h) \
+ $(ui_out_h) $(target_h) $(gdbthread_h)
+ $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) $(srcdir)/python/python.c
+python-utils.o: $(srcdir)/python/utils.c $(defs_h) $(python_internal_h)
+ $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
+ $(srcdir)/python/utils.c -o python-utils.o
+
### end of the gdb Makefile.in.
diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c
index e6fbe3f..00199a7 100644
--- a/gdb/cli/cli-script.c
+++ b/gdb/cli/cli-script.c
@@ -34,6 +34,8 @@
#include "cli/cli-script.h"
#include "gdb_assert.h"
+#include "python/python.h"
+
/* Prototypes for local functions */
static enum command_control_type
@@ -102,7 +104,7 @@ build_command_line (enum command_control_type type, char *args)
/* Build and return a new command structure for the control commands
such as "if" and "while". */
-static struct command_line *
+struct command_line *
get_command_line (enum command_control_type type, char *arg)
{
struct command_line *cmd;
@@ -225,6 +227,20 @@ print_command_lines (struct ui_out *uiout, struct command_line *cmd,
continue;
}
+ if (list->control_type == python_control)
+ {
+ ui_out_field_string (uiout, NULL, "python");
+ ui_out_text (uiout, "\n");
+ /* Don't indent python code at all. */
+ print_command_lines (uiout, *list->body_list, 0);
+ if (depth)
+ ui_out_spaces (uiout, 2 * depth);
+ ui_out_field_string (uiout, NULL, "end");
+ ui_out_text (uiout, "\n");
+ list = list->next;
+ continue;
+ }
+
/* ignore illegal command type and try next */
list = list->next;
} /* while (list) */
@@ -527,6 +543,12 @@ execute_control_command (struct command_line *cmd)
ret = commands_from_control_command (new_line, cmd);
break;
}
+ case python_control:
+ {
+ eval_python_from_control_command (cmd);
+ ret = simple_control;
+ break;
+ }
default:
warning (_("Invalid control type in canned commands structure."));
@@ -538,6 +560,17 @@ execute_control_command (struct command_line *cmd)
return ret;
}
+/* Like execute_control_command, but first set
+ suppress_next_print_command_trace. */
+
+enum command_control_type
+execute_control_command_suppressed (struct command_line *cmd)
+{
+ suppress_next_print_command_trace = 1;
+ return execute_control_command (cmd);
+}
+
+
/* "while" command support. Executes a body of statements while the
loop condition is nonzero. */
@@ -552,8 +585,7 @@ while_command (char *arg, int from_tty)
if (command == NULL)
return;
- suppress_next_print_command_trace = 1;
- execute_control_command (command);
+ execute_control_command_suppressed (command);
free_command_lines (&command);
}
@@ -571,8 +603,7 @@ if_command (char *arg, int from_tty)
if (command == NULL)
return;
- suppress_next_print_command_trace = 1;
- execute_control_command (command);
+ execute_control_command_suppressed (command);
free_command_lines (&command);
}
@@ -886,6 +917,12 @@ read_next_line (struct command_line **command)
first_arg++;
*command = build_command_line (commands_control, first_arg);
}
+ else if (p1 - p == 6 && !strncmp (p, "python", 6))
+ {
+ /* Note that we ignore the inline "python command" form
+ here. */
+ *command = build_command_line (python_control, "");
+ }
else if (p1 - p == 10 && !strncmp (p, "loop_break", 10))
{
*command = (struct command_line *)
@@ -962,6 +999,7 @@ recurse_read_control_structure (struct command_line *current_cmd)
{
if (current_cmd->control_type == while_control
|| current_cmd->control_type == if_control
+ || current_cmd->control_type == python_control
|| current_cmd->control_type == commands_control)
{
/* Success reading an entire canned sequence of commands. */
@@ -1013,6 +1051,7 @@ recurse_read_control_structure (struct command_line *current_cmd)
on it. */
if (next->control_type == while_control
|| next->control_type == if_control
+ || next->control_type == python_control
|| next->control_type == commands_control)
{
control_level++;
@@ -1086,6 +1125,7 @@ read_command_lines (char *prompt_arg, int from_tty)
if (next->control_type == while_control
|| next->control_type == if_control
+ || next->control_type == python_control
|| next->control_type == commands_control)
{
control_level++;
diff --git a/gdb/cli/cli-script.h b/gdb/cli/cli-script.h
index 42663dd..7416e1c 100644
--- a/gdb/cli/cli-script.h
+++ b/gdb/cli/cli-script.h
@@ -40,6 +40,12 @@ extern void show_user_1 (struct cmd_list_element *c, struct ui_file *stream);
extern enum command_control_type
execute_control_command (struct command_line *cmd);
+extern enum command_control_type
+ execute_control_command_suppressed (struct command_line *cmd);
+
+extern struct command_line *get_command_line (enum command_control_type,
+ char *);
+
extern void print_command_lines (struct ui_out *,
struct command_line *, unsigned int);
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 0a92812..e943dd1 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -497,6 +497,99 @@ else
fi
fi
+dnl Utility to simplify finding libpython.
+AC_DEFUN([AC_TRY_LIBPYTHON],
+[
+ version=$1
+ define([have_libpython_var],$2)
+ define([VERSION],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+ [HAVE_LIB]VERSION=no
+ AC_MSG_CHECKING([for ${version}])
+ save_LIBS=$LIBS
+ LIBS="$LIBS -l${version}"
+ AC_LINK_IFELSE(AC_LANG_PROGRAM([[#include "${version}/Python.h"]],
+ [[Py_Initialize ();]]),
+ [[HAVE_LIB]VERSION=yes
+ have_libpython_var=yes],
+ [LIBS=$save_LIBS])
+ AC_MSG_RESULT([$[HAVE_LIB]VERSION])
+])
+
+AC_ARG_WITH(python,
+ AS_HELP_STRING([--with-python], [include python support (auto/yes/no/<path>)]),
+ [], [with_python=auto])
+AC_MSG_CHECKING([whether to use python])
+AC_MSG_RESULT([$with_python])
+
+if test "${with_python}" = no; then
+ AC_MSG_WARN([python support disabled; some features may be unavailable.])
+ have_libpython=no
+else
+ case "${with_python}" in
+ yes | auto)
+ # Leave as empty, use defaults.
+ python_includes=
+ python_libs=
+ ;;
+ /*)
+ python_includes="-I${with_python}/include"
+ python_libs="-L${with_python}/lib"
+ ;;
+ *)
+ AC_ERROR(invalid value for --with-python)
+ ;;
+ esac
+
+ save_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS ${python_includes}"
+ save_LIBS=$LIBS
+ LIBS="$LIBS ${python_libs}"
+ have_libpython=no
+ if test "${have_libpython}" = no; then
+ AC_TRY_LIBPYTHON(python2.6, have_libpython)
+ if test "${HAVE_LIBPYTHON2_6}" = yes; then
+ AC_DEFINE(HAVE_LIBPYTHON2_6, 1, [Define if Python 2.6 is being used.])
+ fi
+ fi
+ if test ${have_libpython} = no; then
+ AC_TRY_LIBPYTHON(python2.5, have_libpython)
+ if test "${HAVE_LIBPYTHON2_5}" = yes; then
+ AC_DEFINE(HAVE_LIBPYTHON2_5, 1, [Define if Python 2.5 is being used.])
+ fi
+ fi
+ if test ${have_libpython} = no; then
+ AC_TRY_LIBPYTHON(python2.4, have_libpython)
+ if test "${HAVE_LIBPYTHON2_4}" = yes; then
+ AC_DEFINE(HAVE_LIBPYTHON2_4, 1, [Define if Python 2.4 is being used.])
+ fi
+ fi
+ if test ${have_libpython} = no; then
+ case "${with_python}" in
+ yes)
+ AC_MSG_ERROR([python is missing or unusable])
+ ;;
+ auto)
+ AC_MSG_WARN([python is missing or unusable; some features may be unavailable.])
+ ;;
+ *)
+ AC_MSG_ERROR([no usable python found at ${with_python}])
+ ;;
+ esac
+ CPPFLAGS=$save_CPPFLAGS
+ LIBS=$save_LIBS
+ fi
+fi
+
+if test "${have_libpython}" = yes; then
+ AC_DEFINE(HAVE_PYTHON, 1, [Define if Python interpreter is being linked in.])
+ CONFIG_OBS="$CONFIG_OBS \$(SUBDIR_PYTHON_OBS)"
+ CONFIG_DEPS="$CONFIG_DEPS \$(SUBDIR_PYTHON_DEPS)"
+ CONFIG_SRCS="$CONFIG_SRCS \$(SUBDIR_PYTHON_SRCS)"
+ CONFIG_INITS="$CONFIG_INITS \$(SUBDIR_PYTHON_INITS)"
+ ENABLE_CFLAGS="$ENABLE_CFLAGS \$(SUBDIR_PYTHON_CFLAGS)"
+fi
+
# ------------------------- #
# Checks for header files. #
# ------------------------- #
diff --git a/gdb/defs.h b/gdb/defs.h
index 6e6aa80..7fe5934 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -652,6 +652,7 @@ enum command_control_type
while_control,
if_control,
commands_control,
+ python_control,
invalid_control
};
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 2920179..b1419a7 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -165,6 +165,7 @@ software in general. We will miss him.
* Emacs:: Using @value{GDBN} under @sc{gnu} Emacs
* GDB/MI:: @value{GDBN}'s Machine Interface.
* Annotations:: @value{GDBN}'s annotation interface.
+* Python:: Scripting @value{GDBN} using Python.
* GDB Bugs:: Reporting bugs in @value{GDBN}
@@ -22704,6 +22705,45 @@ source which is being displayed. @var{addr} is in the form @samp{0x}
followed by one or more lowercase hex digits (note that this does not
depend on the language).
+@node Python
+@chapter Scripting @value{GDBN} using Python
+@cindex Python
+
+You can script @value{GDBN} using the @url{http://www.python.org/,
+Python} programming language. This feature is available only if
+@value{GDBN} was configured using @code{--with-python}.
+
+@kindex python
+The @code{python} command can be used to evaluate Python code.
+
+If given an argument, the @code{python} command will evaluate the
+argument as a Python command. For example:
+
+@smallexample
+(@value{GDBP}) python print 23
+23
+@end smallexample
+
+If you do not provide an argument to @code{python}, it will act as a
+multi-line command, like @code{define}. In this case, the Python
+script is made up of subsequent command lines, given after the
+@code{python} command. This command list is terminated using a line
+containing @code{end}. For example:
+
+@smallexample
+(@value{GDBP}) python
+Type python script
+End with a line saying just "end".
+>print 23
+>end
+23
+@end smallexample
+
+@kindex set python-stack
+By default, @value{GDBN} will print a stack trace when an error occurs
+in a Python script. This can be controlled using @code{set python-stack}.
+
+
@node GDB Bugs
@chapter Reporting Bugs in @value{GDBN}
@cindex bugs in @value{GDBN}
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
new file mode 100644
index 0000000..da2e7e1
--- /dev/null
+++ b/gdb/python/python-internal.h
@@ -0,0 +1,73 @@
+/* Gdb/Python header for private use by Python module.
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDB_PYTHON_INTERNAL_H
+#define GDB_PYTHON_INTERNAL_H
+
+/* Python 2.4 doesn't include stdint.h soon enough to get {u,}intptr_t
+ needed by pyport.h. */
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+/* /usr/include/features.h on linux systems will define _POSIX_C_SOURCE
+ if it sees _GNU_SOURCE (which config.h will define).
+ pyconfig.h defines _POSIX_C_SOURCE to a different value than
+ /usr/include/features.h does causing compilation to fail.
+ To work around this, undef _POSIX_C_SOURCE before we include Python.h. */
+#undef _POSIX_C_SOURCE
+
+#if HAVE_LIBPYTHON2_4
+#include "python2.4/Python.h"
+/* Py_ssize_t is not defined until 2.5. */
+typedef Py_intptr_t Py_ssize_t;
+#elif HAVE_LIBPYTHON2_5
+#include "python2.5/Python.h"
+#elif HAVE_LIBPYTHON2_6
+#include "python2.6/Python.h"
+#else
+#error "Unable to find usable Python.h"
+#endif
+
+struct block;
+struct symbol;
+struct symtab_and_line;
+
+extern PyObject *gdb_module;
+
+struct cleanup *make_cleanup_py_decref (PyObject *py);
+
+/* Use this after a TRY_EXCEPT to throw the appropriate Python
+ exception. */
+#define GDB_PY_HANDLE_EXCEPTION(Exception) \
+ do { \
+ if (Exception.reason < 0) \
+ return PyErr_Format (Exception.reason == RETURN_QUIT \
+ ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, \
+ "%s", Exception.message); \
+ } while (0)
+
+
+void gdbpy_print_stack (void);
+
+PyObject *python_string_to_unicode (PyObject *obj);
+char *unicode_to_target_string (PyObject *unicode_str);
+char *python_string_to_target_string (PyObject *obj);
+
+#endif /* GDB_PYTHON_INTERNAL_H */
diff --git a/gdb/python/python.c b/gdb/python/python.c
new file mode 100644
index 0000000..3035138
--- /dev/null
+++ b/gdb/python/python.c
@@ -0,0 +1,420 @@
+/* General python/gdb code
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "command.h"
+#include "ui-out.h"
+#include "cli/cli-script.h"
+
+#include <ctype.h>
+
+/* True if we should print the stack when catching a Python error,
+ false otherwise. */
+static int gdbpy_should_print_stack = 1;
+
+#ifdef HAVE_PYTHON
+
+#include "python.h"
+#include "libiberty.h"
+#include "cli/cli-decode.h"
+#include "charset.h"
+#include "top.h"
+#include "exceptions.h"
+#include "python-internal.h"
+#include "version.h"
+#include "gdbcmd.h"
+#include "target.h"
+#include "gdbthread.h"
+
+
+PyObject *gdb_module;
+
+static PyObject *get_show_variable (PyObject *, PyObject *);
+static PyObject *execute_gdb_command (PyObject *, PyObject *);
+static PyObject *gdbpy_write (PyObject *, PyObject *);
+static PyObject *gdbpy_flush (PyObject *, PyObject *);
+
+static PyMethodDef GdbMethods[] =
+{
+ { "execute", execute_gdb_command, METH_VARARGS,
+ "Execute a gdb command" },
+ { "show", get_show_variable, METH_VARARGS,
+ "Return a gdb setting's value" },
+
+ { "write", gdbpy_write, METH_VARARGS,
+ "Write a string using gdb's filtered stream." },
+ { "flush", gdbpy_flush, METH_NOARGS,
+ "Flush gdb's filtered stdout stream." },
+
+ {NULL, NULL, 0, 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
+ responsible for freeing it. */
+
+static char *
+compute_python_string (struct command_line *l)
+{
+ struct command_line *iter;
+ char *script = NULL;
+ int size = 0;
+ int here;
+
+ for (iter = l; iter; iter = iter->next)
+ size += strlen (iter->line) + 1;
+
+ script = xmalloc (size + 1);
+ here = 0;
+ for (iter = l; iter; iter = iter->next)
+ {
+ int len = strlen (iter->line);
+ strcpy (&script[here], iter->line);
+ here += len;
+ script[here++] = '\n';
+ }
+ script[here] = '\0';
+ return script;
+}
+
+/* Take a command line structure representing a 'python' command, and
+ evaluate its body using the Python interpreter. */
+
+void
+eval_python_from_control_command (struct command_line *cmd)
+{
+ char *script;
+
+ if (cmd->body_count != 1)
+ error (_("Invalid \"python\" block structure."));
+
+ script = compute_python_string (cmd->body_list[0]);
+ PyRun_SimpleString (script);
+ xfree (script);
+ if (PyErr_Occurred ())
+ {
+ gdbpy_print_stack ();
+ error (_("error while executing Python code"));
+ }
+}
+
+/* Implementation of the gdb "python" command. */
+
+static void
+python_command (char *arg, int from_tty)
+{
+ while (arg && *arg && isspace (*arg))
+ ++arg;
+ if (arg && *arg)
+ {
+ PyRun_SimpleString (arg);
+ if (PyErr_Occurred ())
+ {
+ gdbpy_print_stack ();
+ error (_("error while executing Python code"));
+ }
+ }
+ else
+ {
+ char *tmpbuf = xstrprintf ("Type python script");
+ struct cleanup *cleanups = make_cleanup (xfree, tmpbuf);
+ struct command_line *l = get_command_line (python_control, "");
+ cleanups = make_cleanup_free_command_lines (&l);
+ execute_control_command_suppressed (l);
+ do_cleanups (cleanups);
+ }
+}
+
+\f
+
+/* Transform a gdb variable's value into a Python value. May return
+ NULL (and set a Python exception) on error. Helper function for
+ get_show_variable. */
+
+static PyObject *
+variable_to_python (struct cmd_list_element *cmd)
+{
+ switch (cmd->var_type)
+ {
+ case var_string:
+ case var_string_noescape:
+ case var_optional_filename:
+ case var_filename:
+ case var_enum:
+ {
+ char *str = * (char **) cmd->var;
+ if (! str)
+ str = "";
+ return PyString_Decode (str, strlen (str), host_charset (), NULL);
+ }
+
+ case var_boolean:
+ {
+ if (* (int *) cmd->var)
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
+ }
+
+ case var_auto_boolean:
+ {
+ enum auto_boolean ab = * (enum auto_boolean *) cmd->var;
+ if (ab == AUTO_BOOLEAN_TRUE)
+ Py_RETURN_TRUE;
+ else if (ab == AUTO_BOOLEAN_FALSE)
+ Py_RETURN_FALSE;
+ else
+ Py_RETURN_NONE;
+ }
+
+ case var_integer:
+ if ((* (int *) cmd->var) == INT_MAX)
+ Py_RETURN_NONE;
+ /* Fall through. */
+ case var_zinteger:
+ return PyLong_FromLong (* (int *) cmd->var);
+
+ case var_uinteger:
+ {
+ unsigned int val = * (unsigned int *) cmd->var;
+ if (val == UINT_MAX)
+ Py_RETURN_NONE;
+ return PyLong_FromUnsignedLong (val);
+ }
+ }
+
+ return PyErr_Format (PyExc_RuntimeError, "programmer error: unhandled type");
+}
+
+/* A Python function which returns a gdb variable's value as a Python
+ value. */
+
+static PyObject *
+get_show_variable (PyObject *self, PyObject *args)
+{
+ struct cmd_list_element *alias, *prefix, *cmd;
+ char *arg, *newarg;
+ volatile struct gdb_exception except;
+
+ if (! PyArg_ParseTuple (args, "s", &arg))
+ return NULL;
+
+ newarg = concat ("show ", arg, (char *) NULL);
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ if (! lookup_cmd_composition (newarg, &alias, &prefix, &cmd))
+ {
+ xfree (newarg);
+ return PyErr_Format (PyExc_RuntimeError,
+ "could not find variable `%s'", arg);
+ }
+ }
+ xfree (newarg);
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ if (! cmd->var)
+ return PyErr_Format (PyExc_RuntimeError, "`%s' is not a variable", arg);
+ return variable_to_python (cmd);
+}
+
+/* A Python function which evaluates a string using the gdb CLI. */
+
+static PyObject *
+execute_gdb_command (PyObject *self, PyObject *args)
+{
+ struct cmd_list_element *alias, *prefix, *cmd;
+ char *arg, *newarg;
+ volatile struct gdb_exception except;
+ struct cleanup *old_chain;
+
+ if (! PyArg_ParseTuple (args, "s", &arg))
+ return NULL;
+
+ old_chain = make_cleanup (null_cleanup, 0);
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ execute_command (arg, 0);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ /* Do any commands attached to breakpoint we stopped at. Only if we
+ are always running synchronously. Or if we have just executed a
+ command that doesn't start the target. */
+ if (!target_can_async_p () || !is_running (inferior_ptid))
+ {
+ bpstat_do_actions (&stop_bpstat);
+ do_cleanups (old_chain);
+ }
+
+ Py_RETURN_NONE;
+}
+
+\f
+
+/* Printing. */
+
+/* A python function to write a single string using gdb's filtered
+ output stream. */
+static PyObject *
+gdbpy_write (PyObject *self, PyObject *args)
+{
+ char *arg;
+ if (! PyArg_ParseTuple (args, "s", &arg))
+ return NULL;
+ printf_filtered ("%s", arg);
+ Py_RETURN_NONE;
+}
+
+/* A python function to flush gdb's filtered output stream. */
+static PyObject *
+gdbpy_flush (PyObject *self, PyObject *args)
+{
+ gdb_flush (gdb_stdout);
+ Py_RETURN_NONE;
+}
+
+/* Print a python exception trace, or print nothing and clear the
+ python exception, depending on gdbpy_should_print_stack. Only call
+ this if a python exception is set. */
+void
+gdbpy_print_stack (void)
+{
+ if (gdbpy_should_print_stack)
+ PyErr_Print ();
+ else
+ PyErr_Clear ();
+}
+
+\f
+
+/* Initialize the Python code. */
+
+void
+_initialize_python (void)
+{
+ add_com ("python", class_obscure, python_command, _("\
+Evaluate a Python command.\n\
+\n\
+The command can be given as an argument, for instance:\n\
+\n\
+ python print 23\n\
+\n\
+If no argument is given, the following lines are read and used\n\
+as the Python commands. Type a line containing \"end\" to indicate\n\
+the end of the command."));
+
+ add_setshow_boolean_cmd ("python-stack", class_maintenance,
+ &gdbpy_should_print_stack, _("\
+Set Python stack printing."), _("\
+Show Python stack printing."), _("\
+Enables printing of Python stack traces."),
+ NULL, NULL,
+ &maintenance_set_cmdlist,
+ &maintenance_show_cmdlist);
+
+ Py_Initialize ();
+
+ gdb_module = Py_InitModule ("gdb", GdbMethods);
+
+ /* The casts to (char*) are for python 2.4. */
+ PyModule_AddStringConstant (gdb_module, "VERSION", (char*) version);
+ PyModule_AddStringConstant (gdb_module, "HOST_CONFIG", (char*) host_name);
+ PyModule_AddStringConstant (gdb_module, "TARGET_CONFIG", (char*) target_name);
+
+ PyRun_SimpleString ("import gdb");
+
+ /* Create a couple objects which are used for Python's stdout and
+ stderr. */
+ PyRun_SimpleString ("\
+import sys\n\
+class GdbOutputFile:\n\
+ def close(self):\n\
+ # Do nothing.\n\
+ return None\n\
+\n\
+ def isatty(self):\n\
+ return False\n\
+\n\
+ def write(self, s):\n\
+ gdb.write(s)\n\
+\n\
+ def writelines(self, iterable):\n\
+ for line in iterable:\n\
+ self.write(line)\n\
+\n\
+ def flush(self):\n\
+ gdb.flush()\n\
+\n\
+sys.stderr = GdbOutputFile()\n\
+sys.stdout = GdbOutputFile()\n\
+");
+}
+
+#else /* HAVE_PYTHON */
+
+/* Dummy implementation of the gdb "python" command. */
+
+static void
+python_command (char *arg, int from_tty)
+{
+ while (arg && *arg && isspace (*arg))
+ ++arg;
+ if (arg && *arg)
+ error (_("Python scripting is not supported in this copy of GDB."));
+ else
+ {
+ struct command_line *l = get_command_line (python_control, "");
+ struct cleanup *cleanups = make_cleanup_free_command_lines (&l);
+ execute_control_command_suppressed (l);
+ do_cleanups (cleanups);
+ }
+}
+
+void
+eval_python_from_control_command (struct command_line *cmd)
+{
+ error (_("Python scripting is not supported in this copy of GDB."));
+}
+
+/* Initialize dummy Python code. */
+
+void
+_initialize_python (void)
+{
+ add_com ("python", class_obscure, python_command, _("\
+Evaluate a Python command.\n\
+\n\
+Python scripting is not supported in this copy of GDB.\n\
+This command is only a placeholder."));
+
+ add_setshow_boolean_cmd ("python-stack", class_maintenance,
+ &gdbpy_should_print_stack, _("\
+Set Python stack printing."), _("\
+Show Python stack printing."), _("\
+Enables printing of Python stack traces."),
+ NULL, NULL,
+ &maintenance_set_cmdlist,
+ &maintenance_show_cmdlist);
+
+}
+
+#endif /* HAVE_PYTHON */
diff --git a/gdb/python/python.h b/gdb/python/python.h
new file mode 100644
index 0000000..00ff159
--- /dev/null
+++ b/gdb/python/python.h
@@ -0,0 +1,27 @@
+/* Python/gdb header for generic use in gdb
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDB_PYTHON_H
+#define GDB_PYTHON_H
+
+#include "value.h"
+
+void eval_python_from_control_command (struct command_line *);
+
+#endif /* GDB_PYTHON_H */
diff --git a/gdb/python/utils.c b/gdb/python/utils.c
new file mode 100644
index 0000000..912845f
--- /dev/null
+++ b/gdb/python/utils.c
@@ -0,0 +1,117 @@
+/* General utility routines for GDB/Python.
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "charset.h"
+#include "python-internal.h"
+
+
+/* This is a cleanup function which decrements the refcount on a
+ Python object. */
+
+static void
+py_decref (void *p)
+{
+ PyObject *py = p;
+ /* Note that we need the extra braces in this 'if' to avoid a
+ warning from gcc. */
+ if (py)
+ {
+ Py_DECREF (py);
+ }
+}
+
+/* Return a new cleanup which will decrement the Python object's
+ refcount when run. */
+
+struct cleanup *
+make_cleanup_py_decref (PyObject *py)
+{
+ return make_cleanup (py_decref, (void *) py);
+}
+
+/* Converts a Python 8-bit string to a unicode string object. Assumes the
+ 8-bit string is in the host charset. If an error occurs during conversion,
+ returns NULL with a python exception set.
+
+ As an added bonus, the functions accepts a unicode string and returns it
+ right away, so callers don't need to check which kind of string they've
+ got.
+
+ If the given object is not one of the mentioned string types, NULL is
+ returned, with the TypeError python exception set. */
+PyObject *
+python_string_to_unicode (PyObject *obj)
+{
+ PyObject *unicode_str;
+
+ /* If obj is already a unicode string, just return it.
+ I wish life was always that simple... */
+ if (PyUnicode_Check (obj))
+ unicode_str = obj;
+ else if (PyString_Check (obj))
+ unicode_str = PyUnicode_FromEncodedObject (obj, host_charset (), NULL);
+ else
+ {
+ PyErr_SetString (PyExc_TypeError,
+ _("Expected a string or unicode object."));
+ unicode_str = NULL;
+ }
+
+ return unicode_str;
+}
+
+/* Returns a newly allocated string with the contents of the given unicode
+ string object converted to the target's charset. If an error occurs during
+ the conversion, NULL will be returned and a python exception will be set.
+
+ The caller is responsible for xfree'ing the string. */
+char *
+unicode_to_target_string (PyObject *unicode_str)
+{
+ char *target_string;
+ PyObject *string;
+
+ /* Translate string to target's charset. */
+ string = PyUnicode_AsEncodedString (unicode_str, target_charset (), NULL);
+ if (string == NULL)
+ return NULL;
+
+ target_string = xstrdup (PyString_AsString (string));
+
+ Py_DECREF (string);
+
+ return target_string;
+}
+
+/* Converts a python string (8-bit or unicode) to a target string in
+ the target's charset. Returns NULL on error, with a python exception set.
+
+ The caller is responsible for xfree'ing the string. */
+char *
+python_string_to_target_string (PyObject *obj)
+{
+ PyObject *str;
+
+ str = python_string_to_unicode (obj);
+ if (str == NULL)
+ return NULL;
+
+ return unicode_to_target_string (str);
+}
diff --git a/gdb/testsuite/gdb.python/python.exp b/gdb/testsuite/gdb.python/python.exp
new file mode 100644
index 0000000..44037f2
--- /dev/null
+++ b/gdb/testsuite/gdb.python/python.exp
@@ -0,0 +1,66 @@
+# Copyright (C) 2008 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite. It tests the mechanism
+# exposing values to Python.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test_multiple "python print 23" "verify python support" {
+ -re "not supported.*$gdb_prompt $" {
+ unsupported "python support is disabled"
+ return -1
+ }
+ -re "$gdb_prompt $" {}
+}
+
+# Usage: gdb_py_test_multiple NAME INPUT RESULT {INPUT RESULT}...
+# Run a test named NAME, consisting of multiple lines of input.
+# After each input line INPUT, search for result line RESULT.
+# Succeed if all results are seen; fail otherwise.
+proc gdb_py_test_multiple {name args} {
+ global gdb_prompt
+ foreach {input result} $args {
+ if {[gdb_test_multiple $input "$name - $input" {
+ -re "\[\r\n\]*($result)\[\r\n\]+($gdb_prompt | *>)$" {
+ pass "$name - $input"
+ }
+ }]} {
+ return 1
+ }
+ }
+ return 0
+}
+
+gdb_py_test_multiple "multi-line python command" \
+ "python" "" \
+ "print 23" "" \
+ "end" "23"
+
+gdb_py_test_multiple "show python command" \
+ "define zzq" "Type commands for definition of .* just \"end\"\\.*" \
+ "python" "" \
+ "print 23" "" \
+ "end" "" \
+ "end" "" \
+ "show user zzq" "User command zzq:.* python.*print 23.* end"
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA] Re: [RFC][patch 1/9] initial Python support
2008-07-16 22:02 ` Thiago Jung Bauermann
@ 2008-07-18 19:50 ` Daniel Jacobowitz
2008-07-18 23:24 ` Tom Tromey
` (3 more replies)
0 siblings, 4 replies; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-07-18 19:50 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: Tom Tromey, gdb-patches ml
On Wed, Jul 16, 2008 at 07:00:20PM -0300, Thiago Jung Bauermann wrote:
> +#
> +# python sub directory definitons
> +#
> +SUBDIR_PYTHON_OBS = \
> + python-utils.o
> +SUBDIR_PYTHON_SRCS = \
> + python/python.c \
> + python/utils.c
Can we call it python-utils.c or something else, instead? IMO having
different naming for the source file and object is very confusing.
> @@ -1283,7 +1303,11 @@ test-cp-name-parser$(EXEEXT): test-cp-name-parser.o $(LIBIBERTY)
> # duplicates. Files in the gdb/ directory can end up appearing in
> # COMMON_OBS (as a .o file) and CONFIG_SRCS (as a .c file).
>
> -INIT_FILES = $(COMMON_OBS) $(TSOBS) $(CONFIG_SRCS)
> +# NOTE: bauermann/2008-06-15: python.c needs to be explicitly included
> +# because the generation of init.c does not work for .c files which
> +# result in differently named objects (i.e., python/python -> python.o).
> +
> +INIT_FILES = $(COMMON_OBS) $(TSOBS) $(CONFIG_SRCS) python/python.c
This comment doesn't make sense. python/python.c is already included
in INIT_FILES, because of CONFIG_SRCS.
> +# Flags needed to compile Python code (taken from python-config --cflags)
> +PYTHON_CFLAGS=-fno-strict-aliasing -DNDEBUG -fwrapv
The output of python-config will vary by platform (that's the point of
having a helper program). So, I'm afraid we have to run python-config
if we need the cflags. Or else we could add these flags
unconditionally, if they work with the current compiler. Consider
non-GCC.
> @@ -538,6 +560,17 @@ execute_control_command (struct command_line *cmd)
> return ret;
> }
>
> +/* Like execute_control_command, but first set
> + suppress_next_print_command_trace. */
> +
> +enum command_control_type
> +execute_control_command_suppressed (struct command_line *cmd)
> +{
> + suppress_next_print_command_trace = 1;
> + return execute_control_command (cmd);
> +}
> +
> +
> /* "while" command support. Executes a body of statements while the
> loop condition is nonzero. */
>
This is an unclear name - suppressed what? Maybe
execute_control_command_untraced is more accurate.
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index 2920179..b1419a7 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -165,6 +165,7 @@ software in general. We will miss him.
> * Emacs:: Using @value{GDBN} under @sc{gnu} Emacs
> * GDB/MI:: @value{GDBN}'s Machine Interface.
> * Annotations:: @value{GDBN}'s annotation interface.
> +* Python:: Scripting @value{GDBN} using Python.
>
> * GDB Bugs:: Reporting bugs in @value{GDBN}
>
We should ask Eli to look at the manual.
> +@kindex set python-stack
> +By default, @value{GDBN} will print a stack trace when an error occurs
> +in a Python script. This can be controlled using @code{set python-stack}.
Please expand this; see e.g. Print Settings for the usual way we
document commands. In particular it should say what the values
are/mean.
Also, perhaps this should use a prefix command, like "set python
print-stack"?
There should probably be an explicit table item for the "python"
command, too.
> +/* Python 2.4 doesn't include stdint.h soon enough to get {u,}intptr_t
> + needed by pyport.h. */
> +#ifdef HAVE_STDINT_H
> +#include <stdint.h>
> +#endif
You can include stdint.h unconditionally now; gnulib provides it.
> +/* /usr/include/features.h on linux systems will define _POSIX_C_SOURCE
> + if it sees _GNU_SOURCE (which config.h will define).
> + pyconfig.h defines _POSIX_C_SOURCE to a different value than
> + /usr/include/features.h does causing compilation to fail.
> + To work around this, undef _POSIX_C_SOURCE before we include Python.h. */
> +#undef _POSIX_C_SOURCE
Odd. For me, pyconfig.h and features.h define it to the same thing.
Anyway, this is gross but acceptable.
> +static PyMethodDef GdbMethods[] =
> +{
> + { "execute", execute_gdb_command, METH_VARARGS,
> + "Execute a gdb command" },
> + { "show", get_show_variable, METH_VARARGS,
> + "Return a gdb setting's value" },
> +
> + { "write", gdbpy_write, METH_VARARGS,
> + "Write a string using gdb's filtered stream." },
> + { "flush", gdbpy_flush, METH_NOARGS,
> + "Flush gdb's filtered stdout stream." },
> +
> + {NULL, NULL, 0, NULL}
> +};
I think that these are now "gdb commands", effectively. So, sorry,
but there's a bit more documentation you get to write :-) No new
undocumented public interfaces.
> + /* Create a couple objects which are used for Python's stdout and
> + stderr. */
> + PyRun_SimpleString ("\
> +import sys\n\
> +class GdbOutputFile:\n\
> + def close(self):\n\
> + # Do nothing.\n\
> + return None\n\
> +\n\
> + def isatty(self):\n\
> + return False\n\
> +\n\
> + def write(self, s):\n\
> + gdb.write(s)\n\
> +\n\
> + def writelines(self, iterable):\n\
> + for line in iterable:\n\
> + self.write(line)\n\
> +\n\
> + def flush(self):\n\
> + gdb.flush()\n\
> +\n\
> +sys.stderr = GdbOutputFile()\n\
> +sys.stdout = GdbOutputFile()\n\
This is OK for now, but it is likely to grow. There's code to convert
a text file into a C string, in features/ (used for XML files); maybe
we should internalize a couple of Python source files that way?
Alternatively we could install Python source files to a known path in
the build / install directories; that lets vendors precompile the
files for faster startup.
Anyway, that's a future note, not a current problem.
> +/* Initialize dummy Python code. */
> +
> +void
> +_initialize_python (void)
> +{
> + add_com ("python", class_obscure, python_command, _("\
> +Evaluate a Python command.\n\
> +\n\
> +Python scripting is not supported in this copy of GDB.\n\
> +This command is only a placeholder."));
> +
> + add_setshow_boolean_cmd ("python-stack", class_maintenance,
> + &gdbpy_should_print_stack, _("\
> +Set Python stack printing."), _("\
> +Show Python stack printing."), _("\
> +Enables printing of Python stack traces."),
> + NULL, NULL,
> + &maintenance_set_cmdlist,
> + &maintenance_show_cmdlist);
> +
> +}
If the list of python configuration variables grows, this will get out
of hand; I suggest sharing the init code regardless of HAVE_PYTHON.
This patch is enough for a first NEWS entry.
Otherwise OK :-)
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA] Re: [RFC][patch 1/9] initial Python support
2008-07-18 19:50 ` Daniel Jacobowitz
@ 2008-07-18 23:24 ` Tom Tromey
2008-07-19 0:45 ` Daniel Jacobowitz
2008-07-19 19:50 ` [RFA] iRe: " Thiago Jung Bauermann
` (2 subsequent siblings)
3 siblings, 1 reply; 147+ messages in thread
From: Tom Tromey @ 2008-07-18 23:24 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches ml
>>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
Just a quick note to comment on a couple things in the review.
Daniel> Also, perhaps this should use a prefix command, like "set python
Daniel> print-stack"?
No problem.
Daniel> There should probably be an explicit table item for the "python"
Daniel> command, too.
I saw tables elsewhere but it seemed odd to have one with just a
single entry. No big deal, though, I'll do it.
>> +#undef _POSIX_C_SOURCE
Daniel> Odd. For me, pyconfig.h and features.h define it to the same thing.
Daniel> Anyway, this is gross but acceptable.
I think Doug had a case where this was needed.
>> + { "write", gdbpy_write, METH_VARARGS,
>> + "Write a string using gdb's filtered stream." },
>> + { "flush", gdbpy_flush, METH_NOARGS,
>> + "Flush gdb's filtered stdout stream." },
Daniel> I think that these are now "gdb commands", effectively. So, sorry,
Daniel> but there's a bit more documentation you get to write :-) No new
Daniel> undocumented public interfaces.
So, you mean, document the Python API in the manual? Or more info in
the doc strings here? (I assume the former.)
>> + PyRun_SimpleString ("\
>> +import sys\n\
>> +class GdbOutputFile:\n\
[...]
Daniel> This is OK for now, but it is likely to grow. There's code to convert
Daniel> a text file into a C string, in features/ (used for XML files); maybe
Daniel> we should internalize a couple of Python source files that way?
Daniel> Alternatively we could install Python source files to a known path in
Daniel> the build / install directories; that lets vendors precompile the
Daniel> files for faster startup.
Daniel> Anyway, that's a future note, not a current problem.
Just to be clear, I have thought about this, and I think we will want
a library of Python code that is distributed with gdb and installed by
'make install'.
However, I think this particular snippet should remain in the source
(or be compiled in -- I don't care either way about that). My
reasoning is that it would be nice, if at all possible, if gdb would
still properly start up even if someone deleted the python library by
mistake.
So, truly critical python code should just be included directly; but
at the same time the amount of critical code should be kept to a
minimum.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA] Re: [RFC][patch 1/9] initial Python support
2008-07-18 23:24 ` Tom Tromey
@ 2008-07-19 0:45 ` Daniel Jacobowitz
0 siblings, 0 replies; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-07-19 0:45 UTC (permalink / raw)
To: Tom Tromey; +Cc: Thiago Jung Bauermann, gdb-patches ml
On Fri, Jul 18, 2008 at 05:24:30PM -0600, Tom Tromey wrote:
> Daniel> I think that these are now "gdb commands", effectively. So, sorry,
> Daniel> but there's a bit more documentation you get to write :-) No new
> Daniel> undocumented public interfaces.
>
> So, you mean, document the Python API in the manual? Or more info in
> the doc strings here? (I assume the former.)
The former. I don't know how much technical complexity it's worth to
keep the doc strings and manual in sync, but the manual is pretty
important.
> So, truly critical python code should just be included directly; but
> at the same time the amount of critical code should be kept to a
> minimum.
I agree.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA] iRe: [RFC][patch 1/9] initial Python support
2008-07-18 19:50 ` Daniel Jacobowitz
2008-07-18 23:24 ` Tom Tromey
@ 2008-07-19 19:50 ` Thiago Jung Bauermann
2008-07-19 21:13 ` Daniel Jacobowitz
2008-07-20 23:47 ` Thiago Jung Bauermann
2008-07-20 22:43 ` [RFA] Re: [RFC][patch 1/9] initial Python support Tom Tromey
2008-07-21 15:29 ` [RFA][patch 1/9] Yet another respin of the patch with " Thiago Jung Bauermann
3 siblings, 2 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-07-19 19:50 UTC (permalink / raw)
To: gdb-patches
Daniel Jacobowitz wrote:
> On Wed, Jul 16, 2008 at 07:00:20PM -0300, Thiago Jung Bauermann wrote:
>> +#
>> +# python sub directory definitons
>> +#
>> +SUBDIR_PYTHON_OBS = \
>> + python-utils.o
>> +SUBDIR_PYTHON_SRCS = \
>> + python/python.c \
>> + python/utils.c
>
> Can we call it python-utils.c or something else, instead? IMO having
> different naming for the source file and object is very confusing.
Actually I prefer to keep it this way. I am following the existing
convention used to build other GDB components which live in their own
subdirectories (cli/, mi/ and tui/).
Since by the end of this patch series there will be 13 Python-related .c
and .h files, I prefer to put them in their own subdirectory. IMHO having a
flat source tree, with all source files lumped together, is more confusing
than an object file named differently (but not much) than its source file.
>> @@ -1283,7 +1303,11 @@ test-cp-name-parser$(EXEEXT):
>> test-cp-name-parser.o $(LIBIBERTY)
>> # duplicates. Files in the gdb/ directory can end up appearing in
>> # COMMON_OBS (as a .o file) and CONFIG_SRCS (as a .c file).
>>
>> -INIT_FILES = $(COMMON_OBS) $(TSOBS) $(CONFIG_SRCS)
>> +# NOTE: bauermann/2008-06-15: python.c needs to be explicitly included
>> +# because the generation of init.c does not work for .c files which
>> +# result in differently named objects (i.e., python/python -> python.o).
>> +
>> +INIT_FILES = $(COMMON_OBS) $(TSOBS) $(CONFIG_SRCS) python/python.c
>
> This comment doesn't make sense. python/python.c is already included
> in INIT_FILES, because of CONFIG_SRCS.
Indeed. I just tried saving face by reproducing the problem which prompted
me to add python/python.c there in the first place, but couldn't. I don't
remember why I needed it at the time.
>> +# Flags needed to compile Python code (taken from python-config
>> --cflags) +PYTHON_CFLAGS=-fno-strict-aliasing -DNDEBUG -fwrapv
>
> The output of python-config will vary by platform (that's the point of
> having a helper program). So, I'm afraid we have to run python-config
> if we need the cflags. Or else we could add these flags
> unconditionally, if they work with the current compiler. Consider
> non-GCC.
I looked into using python-config, and found a problem: the CFLAGS it
provides is just a copy of all the CFLAGS used when building the Python
interpreter itself, including options which would make the python-related
objects be compiled differently from the rest of GDB. For instance, in my
system it includes -O2 (what if want to compile GDB with -O0?). In another
system it also includes -fPIC.
There's an open python ticket about this: http://bugs.python.org/issue3290
So I don't know yet how to solve the problem. :-/
Even if they fix it upstream, we want to support the broken systems out
there.
Perhaps get the python-config output and filter out options from a
blacklist?
>> + /* Create a couple objects which are used for Python's stdout and
>> + stderr. */
>> + PyRun_SimpleString ("\
>> +import sys\n\
>> +class GdbOutputFile:\n\
>> + def close(self):\n\
>> + # Do nothing.\n\
>> + return None\n\
>> +\n\
>> + def isatty(self):\n\
>> + return False\n\
>> +\n\
>> + def write(self, s):\n\
>> + gdb.write(s)\n\
>> +\n\
>> + def writelines(self, iterable):\n\
>> + for line in iterable:\n\
>> + self.write(line)\n\
>> +\n\
>> + def flush(self):\n\
>> + gdb.flush()\n\
>> +\n\
>> +sys.stderr = GdbOutputFile()\n\
>> +sys.stdout = GdbOutputFile()\n\
>
> This is OK for now, but it is likely to grow. There's code to convert
> a text file into a C string, in features/ (used for XML files); maybe
> we should internalize a couple of Python source files that way?
I like the idea, will play with it...
> Anyway, that's a future note, not a current problem.
... and provide a separate patch later.
>> +/* Initialize dummy Python code. */
>> +
>> +void
>> +_initialize_python (void)
>> +{
>> + add_com ("python", class_obscure, python_command, _("\
>> +Evaluate a Python command.\n\
>> +\n\
>> +Python scripting is not supported in this copy of GDB.\n\
>> +This command is only a placeholder."));
>> +
>> + add_setshow_boolean_cmd ("python-stack", class_maintenance,
>> + &gdbpy_should_print_stack, _("\
>> +Set Python stack printing."), _("\
>> +Show Python stack printing."), _("\
>> +Enables printing of Python stack traces."),
>> + NULL, NULL,
>> + &maintenance_set_cmdlist,
>> + &maintenance_show_cmdlist);
>> +
>> +}
>
> If the list of python configuration variables grows, this will get out
> of hand; I suggest sharing the init code regardless of HAVE_PYTHON.
You mean having #ifdefs inside _initialize_python itself?
> This patch is enough for a first NEWS entry.
>
> Otherwise OK :-)
Awesome. Now working in a respin of the patch...
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA] iRe: [RFC][patch 1/9] initial Python support
2008-07-19 19:50 ` [RFA] iRe: " Thiago Jung Bauermann
@ 2008-07-19 21:13 ` Daniel Jacobowitz
2008-07-19 22:13 ` Thiago Jung Bauermann
2008-07-20 23:47 ` Thiago Jung Bauermann
1 sibling, 1 reply; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-07-19 21:13 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
On Sat, Jul 19, 2008 at 04:36:47PM -0300, Thiago Jung Bauermann wrote:
> > Can we call it python-utils.c or something else, instead? IMO having
> > different naming for the source file and object is very confusing.
>
> Actually I prefer to keep it this way. I am following the existing
> convention used to build other GDB components which live in their own
> subdirectories (cli/, mi/ and tui/).
>
> Since by the end of this patch series there will be 13 Python-related .c
> and .h files, I prefer to put them in their own subdirectory. IMHO having a
> flat source tree, with all source files lumped together, is more confusing
> than an object file named differently (but not much) than its source file.
That's not what I meant. Leaving it in python/ is fine. But call it
python/python-utils.c. All the cli/ sources are prefixed, ditto the
mi/ sources.
> Perhaps get the python-config output and filter out options from a
> blacklist?
Use your hardcoded options, but check using autoconf that they're
valid for the current compiler. IIRC we do something similar for
warning flags already.
> > If the list of python configuration variables grows, this will get out
> > of hand; I suggest sharing the init code regardless of HAVE_PYTHON.
>
> You mean having #ifdefs inside _initialize_python itself?
Right.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA] iRe: [RFC][patch 1/9] initial Python support
2008-07-19 21:13 ` Daniel Jacobowitz
@ 2008-07-19 22:13 ` Thiago Jung Bauermann
0 siblings, 0 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-07-19 22:13 UTC (permalink / raw)
To: gdb-patches
Daniel Jacobowitz wrote:
> On Sat, Jul 19, 2008 at 04:36:47PM -0300, Thiago Jung Bauermann wrote:
>> > Can we call it python-utils.c or something else, instead? IMO having
>> > different naming for the source file and object is very confusing.
>>
>> Actually I prefer to keep it this way. I am following the existing
>> convention used to build other GDB components which live in their own
>> subdirectories (cli/, mi/ and tui/).
>>
>> Since by the end of this patch series there will be 13 Python-related .c
>> and .h files, I prefer to put them in their own subdirectory. IMHO having
>> a flat source tree, with all source files lumped together, is more
>> confusing than an object file named differently (but not much) than its
>> source file.
>
> That's not what I meant. Leaving it in python/ is fine. But call it
> python/python-utils.c. All the cli/ sources are prefixed, ditto the
> mi/ sources.
Ah, got it. Fine by me.
Thanks for your suggestions.
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA] Re: [RFC][patch 1/9] initial Python support
2008-07-18 19:50 ` Daniel Jacobowitz
2008-07-18 23:24 ` Tom Tromey
2008-07-19 19:50 ` [RFA] iRe: " Thiago Jung Bauermann
@ 2008-07-20 22:43 ` Tom Tromey
2008-07-21 1:59 ` Daniel Jacobowitz
2008-07-21 15:29 ` [RFA][patch 1/9] Yet another respin of the patch with " Thiago Jung Bauermann
3 siblings, 1 reply; 147+ messages in thread
From: Tom Tromey @ 2008-07-20 22:43 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches ml
>>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
>> +# Flags needed to compile Python code (taken from python-config --cflags)
>> +PYTHON_CFLAGS=-fno-strict-aliasing -DNDEBUG -fwrapv
I wonder whether we really need -fwrapv. I can understand it being
needed by the python interpreter... but does this need leak out to
user code via macros?
Daniel> Also, perhaps this should use a prefix command, like "set python
Daniel> print-stack"?
While fixing the manual I realized I had put this under "maint".
I left it there in my recent fixes, but I thought I'd make this
explicit... would you rather "maint set python print-stack", or the
same without "maint"?
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA] iRe: [RFC][patch 1/9] initial Python support
2008-07-19 19:50 ` [RFA] iRe: " Thiago Jung Bauermann
2008-07-19 21:13 ` Daniel Jacobowitz
@ 2008-07-20 23:47 ` Thiago Jung Bauermann
2008-07-21 2:03 ` Daniel Jacobowitz
1 sibling, 1 reply; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-07-20 23:47 UTC (permalink / raw)
To: gdb-patches
Thiago Jung Bauermann wrote:
> Daniel Jacobowitz wrote:
>> On Wed, Jul 16, 2008 at 07:00:20PM -0300, Thiago Jung Bauermann wrote:
>>> @@ -1283,7 +1303,11 @@ test-cp-name-parser$(EXEEXT):
>>> test-cp-name-parser.o $(LIBIBERTY)
>>> # duplicates. Files in the gdb/ directory can end up appearing in
>>> # COMMON_OBS (as a .o file) and CONFIG_SRCS (as a .c file).
>>>
>>> -INIT_FILES = $(COMMON_OBS) $(TSOBS) $(CONFIG_SRCS)
>>> +# NOTE: bauermann/2008-06-15: python.c needs to be explicitly included
>>> +# because the generation of init.c does not work for .c files which
>>> +# result in differently named objects (i.e., python/python ->
>>> python.o). +
>>> +INIT_FILES = $(COMMON_OBS) $(TSOBS) $(CONFIG_SRCS) python/python.c
>>
>> This comment doesn't make sense. python/python.c is already included
>> in INIT_FILES, because of CONFIG_SRCS.
>
> Indeed. I just tried saving face by reproducing the problem which prompted
> me to add python/python.c there in the first place, but couldn't. I don't
> remember why I needed it at the time.
Actually, I just found the problem. If Python support is not being
compiled in, python/python.c will not be included in INIT_FILES. And the
fact that python.o is in COMMON_OBS will not help because of the reason
outlined in my comment. That's why I added python/python.c explicitly in
INIT_FILES.
Another way to solve the problem, which I am using this time, is to add
the following else clause to configure.ac:
if test "${have_libpython}" = yes; then
AC_DEFINE(HAVE_PYTHON, 1, [Define if Python interpreter is being linked in.])
CONFIG_OBS="$CONFIG_OBS \$(SUBDIR_PYTHON_OBS)"
CONFIG_DEPS="$CONFIG_DEPS \$(SUBDIR_PYTHON_DEPS)"
CONFIG_SRCS="$CONFIG_SRCS \$(SUBDIR_PYTHON_SRCS)"
CONFIG_INITS="$CONFIG_INITS \$(SUBDIR_PYTHON_INITS)"
ENABLE_CFLAGS="$ENABLE_CFLAGS \$(SUBDIR_PYTHON_CFLAGS)"
else
# Even if Python support is not compiled in, we need to have python/python.c
# included, in order to recognize the python command. Even though python.o is
# in Makefile.in's COMMON_OBS, the code generating init.c won't include a
# call to _initialize_python unless python/python.c is explicitly added to
# INIT_FILES.
CONFIG_SRCS="$CONFIG_SRCS python/python.c"
fi
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA] Re: [RFC][patch 1/9] initial Python support
2008-07-20 22:43 ` [RFA] Re: [RFC][patch 1/9] initial Python support Tom Tromey
@ 2008-07-21 1:59 ` Daniel Jacobowitz
0 siblings, 0 replies; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-07-21 1:59 UTC (permalink / raw)
To: Tom Tromey; +Cc: Thiago Jung Bauermann, gdb-patches ml
On Sun, Jul 20, 2008 at 04:43:06PM -0600, Tom Tromey wrote:
> >>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
>
> >> +# Flags needed to compile Python code (taken from python-config --cflags)
> >> +PYTHON_CFLAGS=-fno-strict-aliasing -DNDEBUG -fwrapv
>
> I wonder whether we really need -fwrapv. I can understand it being
> needed by the python interpreter... but does this need leak out to
> user code via macros?
I don't know, but wouldn't be surprised... Python's got an awful lot
of macros.
> Daniel> Also, perhaps this should use a prefix command, like "set python
> Daniel> print-stack"?
>
> While fixing the manual I realized I had put this under "maint".
> I left it there in my recent fixes, but I thought I'd make this
> explicit... would you rather "maint set python print-stack", or the
> same without "maint"?
I've no preference.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA] iRe: [RFC][patch 1/9] initial Python support
2008-07-20 23:47 ` Thiago Jung Bauermann
@ 2008-07-21 2:03 ` Daniel Jacobowitz
2008-07-23 17:46 ` [obvious] Wipe out CONFIG_INITS Thiago Jung Bauermann
0 siblings, 1 reply; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-07-21 2:03 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
On Sun, Jul 20, 2008 at 08:47:08PM -0300, Thiago Jung Bauermann wrote:
> Actually, I just found the problem. If Python support is not being
> compiled in, python/python.c will not be included in INIT_FILES. And the
> fact that python.o is in COMMON_OBS will not help because of the reason
> outlined in my comment. That's why I added python/python.c explicitly in
> INIT_FILES.
>
> Another way to solve the problem, which I am using this time, is to add
> the following else clause to configure.ac:
Is it in both COMMON_OBS and CONFIG_OBS? Sounds like it should be in
CONFIG_OBS all the time, never in COMMON_OBS. Which means CONFIG_OBS,
CONFIG_DEPS, CONFIG_SRCS also.
> if test "${have_libpython}" = yes; then
> AC_DEFINE(HAVE_PYTHON, 1, [Define if Python interpreter is being linked in.])
> CONFIG_OBS="$CONFIG_OBS \$(SUBDIR_PYTHON_OBS)"
> CONFIG_DEPS="$CONFIG_DEPS \$(SUBDIR_PYTHON_DEPS)"
> CONFIG_SRCS="$CONFIG_SRCS \$(SUBDIR_PYTHON_SRCS)"
> CONFIG_INITS="$CONFIG_INITS \$(SUBDIR_PYTHON_INITS)"
> ENABLE_CFLAGS="$ENABLE_CFLAGS \$(SUBDIR_PYTHON_CFLAGS)"
CONFIG_INITS appears to be obsolete.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-18 19:50 ` Daniel Jacobowitz
` (2 preceding siblings ...)
2008-07-20 22:43 ` [RFA] Re: [RFC][patch 1/9] initial Python support Tom Tromey
@ 2008-07-21 15:29 ` Thiago Jung Bauermann
2008-07-21 16:47 ` Thiago Jung Bauermann
` (2 more replies)
3 siblings, 3 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-07-21 15:29 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Tom Tromey, gdb-patches ml, Eli Zaretskii
Hi people,
This is today's version of the patch. :-)
It addresses the latest review comments, and is good to go AFAIK.
Eli,
What do you think of this documentation?
I'm aware you are not currently able to review it. I'd appreciate your
input when you have time.
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
gdb/
2008-07-16 Vladimir Prus <vladimir@codesourcery.com>
Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
Doug Evans <dje@google.com>
* Makefile.in (SUBDIR_PYTHON_OBS, SUBDIR_PYTHON_SRCS,
SUBDIR_PYTHON_DEPS, SUBDIR_PYTHON_LDFLAGS, SUBDIR_PYTHON_CFLAGS,
PYTHON_CFLAGS): New.
(python_h, python_internal_h): New.
(cli-script.o): Depend on python.h
(python.o, python-utils.o): New.
* cli/cli-script.c (print_command_lines): Handle python_control.
(execute_control_command): Handle python_control.
(execute_control_command_untraced): New function.
(while_command): Call execute_control_command_untraced.
(if_command): Likewise.
(get_command_line): Remove static attribute.
(read_next_line): Handle "python".
(recurse_read_control_structure): Handle python_control.
(read_command_lines): Handle python_control.
Include python.h.
* cli/cli-script.h (get_command_line): Add prototype.
(execute_control_command_untraced): Likewise.
* configure.ac: Add --with-python.
* defs.h (enum command_control_type) <python_control>: New
constant.
* python/python-internal.h: New file.
* python/python.c: New file.
* python/python.h: New file.
* python/python-utils.c: New file.
* NEWS: Mention Python scripting support and its new commands.
gdb/doc/
2008-07-16 Tom Tromey <tromey@redhat.com>
* gdb.texinfo (Python): New chapter.
gdb/testsuite/
2008-07-16 Tom Tromey <tromey@redhat.com>
* gdb.python/python.exp: New file.
Index: typos/gdb/Makefile.in
===================================================================
--- typos.orig/gdb/Makefile.in 2008-07-16 13:20:47.000000000 -0300
+++ typos/gdb/Makefile.in 2008-07-21 12:16:16.000000000 -0300
@@ -254,6 +254,19 @@ SUBDIR_TUI_LDFLAGS=
SUBDIR_TUI_CFLAGS= \
-DTUI=1
+#
+# python sub directory definitons
+#
+SUBDIR_PYTHON_OBS = \
+ python.o \
+ python-utils.o
+SUBDIR_PYTHON_SRCS = \
+ python/python.c \
+ python/python-utils.c
+SUBDIR_PYTHON_DEPS =
+SUBDIR_PYTHON_LDFLAGS=
+SUBDIR_PYTHON_CFLAGS=
+
# Opcodes currently live in one of two places. Either they are in the
# opcode library, typically ../opcodes, or they are in a header file
@@ -963,6 +976,13 @@ tui_wingeneral_h = $(srcdir)/tui/tui-win
tui_win_h = $(srcdir)/tui/tui-win.h $(tui_data_h)
tui_winsource_h = $(srcdir)/tui/tui-winsource.h $(tui_data_h)
+#
+# gdb/python/ headers
+#
+
+python_h = $(srcdir)/python/python.h $(value_h)
+python_internal_h = $(srcdir)/python/python-internal.h
+
# gdb/features preparsed descriptions
features_headers = $(defs_h) $(gdbtypes_h) $(target_descriptions_h)
arm_with_iwmmxt_c = $(srcdir)/features/arm-with-iwmmxt.c $(features_headers)
@@ -1283,7 +1303,11 @@ test-cp-name-parser$(EXEEXT): test-cp-na
# duplicates. Files in the gdb/ directory can end up appearing in
# COMMON_OBS (as a .o file) and CONFIG_SRCS (as a .c file).
-INIT_FILES = $(COMMON_OBS) $(TSOBS) $(CONFIG_SRCS)
+# NOTE: bauermann/2008-06-15: python.c needs to be explicitly included
+# because the generation of init.c does not work for .c files which
+# result in differently named objects (i.e., python/python -> python.o).
+
+INIT_FILES = $(COMMON_OBS) $(TSOBS) $(CONFIG_SRCS) python/python.c
init.c: $(INIT_FILES)
@echo Making init.c
@rm -f init.c-tmp init.l-tmp
@@ -3064,7 +3088,8 @@ cli-logging.o: $(srcdir)/cli/cli-logging
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-logging.c
cli-script.o: $(srcdir)/cli/cli-script.c $(defs_h) $(value_h) $(language_h) \
$(ui_out_h) $(gdb_string_h) $(exceptions_h) $(top_h) $(cli_cmds_h) \
- $(cli_decode_h) $(cli_script_h) $(gdb_assert_h) $(breakpoint_h)
+ $(cli_decode_h) $(cli_script_h) $(gdb_assert_h) $(breakpoint_h) \
+ $(python_h)
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-script.c
cli-setshow.o: $(srcdir)/cli/cli-setshow.c $(defs_h) $(readline_tilde_h) \
$(value_h) $(gdb_string_h) $(ui_out_h) $(cli_decode_h) $(cli_cmds_h) \
@@ -3389,4 +3414,22 @@ tui-winsource.o: $(srcdir)/tui/tui-winso
$(gdb_curses_h) $(gdb_assert_h)
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tui-winsource.c
+#
+# gdb/python/ dependencies
+#
+# Need to explicitly specify the compile rule as make will do nothing
+# or try to compile the object file into the sub-directory.
+
+# Flags needed to compile Python code
+PYTHON_CFLAGS=@PYTHON_CFLAGS@
+
+python.o: $(srcdir)/python/python.c $(defs_h) $(python_h) \
+ $(command_h) $(libiberty_h) $(cli_decode_h) $(charset_h) $(top_h) \
+ $(exceptions_h) $(python_internal_h) $(version_h) $(cli_script_h) \
+ $(ui_out_h) $(target_h) $(gdbthread_h)
+ $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) $(srcdir)/python/python.c
+python-utils.o: $(srcdir)/python/python-utils.c $(defs_h) $(python_internal_h)
+ $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
+ $(srcdir)/python/python-utils.c -o python-utils.o
+
### end of the gdb Makefile.in.
Index: typos/gdb/NEWS
===================================================================
--- typos.orig/gdb/NEWS 2008-07-15 04:44:06.000000000 -0300
+++ typos/gdb/NEWS 2008-07-21 12:16:16.000000000 -0300
@@ -62,12 +62,25 @@ have also been fixed.
gdbserver executable to debug both 32-bit and 64-bit programs.
(This requires gdbserver itself to be built as a 64-bit executable.)
+* Python scripting
+
+ GDB now has support for scripting using Python. Whether this is
+ available is determined at configure time; you can explicitly
+ disable the support using --without-python.
+
* New commands
find [/size-char] [/max-count] start-address, end-address|+search-space-size,
val1 [, val2, ...]
Search memory for a sequence of bytes.
+maint set python print-stack
+maint show python print-stack
+ Show a stack trace when an error is encountered in a Python script.
+
+python [code]
+ Invoke python code.
+
set print symbol-loading
show print symbol-loading
Control printing of symbol loading messages.
Index: typos/gdb/cli/cli-script.c
===================================================================
--- typos.orig/gdb/cli/cli-script.c 2008-07-16 13:20:47.000000000 -0300
+++ typos/gdb/cli/cli-script.c 2008-07-21 12:16:16.000000000 -0300
@@ -34,6 +34,8 @@
#include "cli/cli-script.h"
#include "gdb_assert.h"
+#include "python/python.h"
+
/* Prototypes for local functions */
static enum command_control_type
@@ -102,7 +104,7 @@ build_command_line (enum command_control
/* Build and return a new command structure for the control commands
such as "if" and "while". */
-static struct command_line *
+struct command_line *
get_command_line (enum command_control_type type, char *arg)
{
struct command_line *cmd;
@@ -225,6 +227,20 @@ print_command_lines (struct ui_out *uiou
continue;
}
+ if (list->control_type == python_control)
+ {
+ ui_out_field_string (uiout, NULL, "python");
+ ui_out_text (uiout, "\n");
+ /* Don't indent python code at all. */
+ print_command_lines (uiout, *list->body_list, 0);
+ if (depth)
+ ui_out_spaces (uiout, 2 * depth);
+ ui_out_field_string (uiout, NULL, "end");
+ ui_out_text (uiout, "\n");
+ list = list->next;
+ continue;
+ }
+
/* ignore illegal command type and try next */
list = list->next;
} /* while (list) */
@@ -527,6 +543,12 @@ execute_control_command (struct command_
ret = commands_from_control_command (new_line, cmd);
break;
}
+ case python_control:
+ {
+ eval_python_from_control_command (cmd);
+ ret = simple_control;
+ break;
+ }
default:
warning (_("Invalid control type in canned commands structure."));
@@ -538,6 +560,17 @@ execute_control_command (struct command_
return ret;
}
+/* Like execute_control_command, but first set
+ suppress_next_print_command_trace. */
+
+enum command_control_type
+execute_control_command_untraced (struct command_line *cmd)
+{
+ suppress_next_print_command_trace = 1;
+ return execute_control_command (cmd);
+}
+
+
/* "while" command support. Executes a body of statements while the
loop condition is nonzero. */
@@ -552,8 +585,7 @@ while_command (char *arg, int from_tty)
if (command == NULL)
return;
- suppress_next_print_command_trace = 1;
- execute_control_command (command);
+ execute_control_command_untraced (command);
free_command_lines (&command);
}
@@ -571,8 +603,7 @@ if_command (char *arg, int from_tty)
if (command == NULL)
return;
- suppress_next_print_command_trace = 1;
- execute_control_command (command);
+ execute_control_command_untraced (command);
free_command_lines (&command);
}
@@ -886,6 +917,12 @@ read_next_line (struct command_line **co
first_arg++;
*command = build_command_line (commands_control, first_arg);
}
+ else if (p1 - p == 6 && !strncmp (p, "python", 6))
+ {
+ /* Note that we ignore the inline "python command" form
+ here. */
+ *command = build_command_line (python_control, "");
+ }
else if (p1 - p == 10 && !strncmp (p, "loop_break", 10))
{
*command = (struct command_line *)
@@ -962,6 +999,7 @@ recurse_read_control_structure (struct c
{
if (current_cmd->control_type == while_control
|| current_cmd->control_type == if_control
+ || current_cmd->control_type == python_control
|| current_cmd->control_type == commands_control)
{
/* Success reading an entire canned sequence of commands. */
@@ -1013,6 +1051,7 @@ recurse_read_control_structure (struct c
on it. */
if (next->control_type == while_control
|| next->control_type == if_control
+ || next->control_type == python_control
|| next->control_type == commands_control)
{
control_level++;
@@ -1086,6 +1125,7 @@ read_command_lines (char *prompt_arg, in
if (next->control_type == while_control
|| next->control_type == if_control
+ || next->control_type == python_control
|| next->control_type == commands_control)
{
control_level++;
Index: typos/gdb/cli/cli-script.h
===================================================================
--- typos.orig/gdb/cli/cli-script.h 2008-07-16 13:20:47.000000000 -0300
+++ typos/gdb/cli/cli-script.h 2008-07-21 12:16:16.000000000 -0300
@@ -40,6 +40,12 @@ extern void show_user_1 (struct cmd_list
extern enum command_control_type
execute_control_command (struct command_line *cmd);
+extern enum command_control_type
+ execute_control_command_untraced (struct command_line *cmd);
+
+extern struct command_line *get_command_line (enum command_control_type,
+ char *);
+
extern void print_command_lines (struct ui_out *,
struct command_line *, unsigned int);
Index: typos/gdb/configure.ac
===================================================================
--- typos.orig/gdb/configure.ac 2008-07-16 13:20:47.000000000 -0300
+++ typos/gdb/configure.ac 2008-07-21 12:16:39.000000000 -0300
@@ -497,6 +497,125 @@ else
fi
fi
+dnl Utility to simplify finding libpython.
+AC_DEFUN([AC_TRY_LIBPYTHON],
+[
+ version=$1
+ define([have_libpython_var],$2)
+ define([VERSION],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+ [HAVE_LIB]VERSION=no
+ AC_MSG_CHECKING([for ${version}])
+ save_LIBS=$LIBS
+ LIBS="$LIBS -l${version}"
+ AC_LINK_IFELSE(AC_LANG_PROGRAM([[#include "${version}/Python.h"]],
+ [[Py_Initialize ();]]),
+ [[HAVE_LIB]VERSION=yes
+ have_libpython_var=yes],
+ [LIBS=$save_LIBS])
+ AC_MSG_RESULT([$[HAVE_LIB]VERSION])
+])
+
+AC_ARG_WITH(python,
+ AS_HELP_STRING([--with-python], [include python support (auto/yes/no/<path>)]),
+ [], [with_python=auto])
+AC_MSG_CHECKING([whether to use python])
+AC_MSG_RESULT([$with_python])
+
+if test "${with_python}" = no; then
+ AC_MSG_WARN([python support disabled; some features may be unavailable.])
+ have_libpython=no
+else
+ case "${with_python}" in
+ yes | auto)
+ # Leave as empty, use defaults.
+ python_includes=
+ python_libs=
+ ;;
+ /*)
+ python_includes="-I${with_python}/include"
+ python_libs="-L${with_python}/lib"
+ ;;
+ *)
+ AC_ERROR(invalid value for --with-python)
+ ;;
+ esac
+
+ save_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS ${python_includes}"
+ save_LIBS=$LIBS
+ LIBS="$LIBS ${python_libs}"
+ have_libpython=no
+ if test "${have_libpython}" = no; then
+ AC_TRY_LIBPYTHON(python2.6, have_libpython)
+ if test "${HAVE_LIBPYTHON2_6}" = yes; then
+ AC_DEFINE(HAVE_LIBPYTHON2_6, 1, [Define if Python 2.6 is being used.])
+ fi
+ fi
+ if test ${have_libpython} = no; then
+ AC_TRY_LIBPYTHON(python2.5, have_libpython)
+ if test "${HAVE_LIBPYTHON2_5}" = yes; then
+ AC_DEFINE(HAVE_LIBPYTHON2_5, 1, [Define if Python 2.5 is being used.])
+ fi
+ fi
+ if test ${have_libpython} = no; then
+ AC_TRY_LIBPYTHON(python2.4, have_libpython)
+ if test "${HAVE_LIBPYTHON2_4}" = yes; then
+ AC_DEFINE(HAVE_LIBPYTHON2_4, 1, [Define if Python 2.4 is being used.])
+ fi
+ fi
+ if test ${have_libpython} = no; then
+ case "${with_python}" in
+ yes)
+ AC_MSG_ERROR([python is missing or unusable])
+ ;;
+ auto)
+ AC_MSG_WARN([python is missing or unusable; some features may be unavailable.])
+ ;;
+ *)
+ AC_MSG_ERROR([no usable python found at ${with_python}])
+ ;;
+ esac
+ CPPFLAGS=$save_CPPFLAGS
+ LIBS=$save_LIBS
+ fi
+fi
+
+if test "${have_libpython}" = yes; then
+ AC_DEFINE(HAVE_PYTHON, 1, [Define if Python interpreter is being linked in.])
+ CONFIG_OBS="$CONFIG_OBS \$(SUBDIR_PYTHON_OBS)"
+ CONFIG_DEPS="$CONFIG_DEPS \$(SUBDIR_PYTHON_DEPS)"
+ CONFIG_SRCS="$CONFIG_SRCS \$(SUBDIR_PYTHON_SRCS)"
+ ENABLE_CFLAGS="$ENABLE_CFLAGS \$(SUBDIR_PYTHON_CFLAGS)"
+
+ # Flags needed to compile Python code (taken from python-config --cflags).
+ # We cannot call python-config directly because it will output whatever was
+ # used when compiling the Python interpreter itself, including flags which
+ # would make the python-related objects be compiled differently from the
+ # rest of GDB (e.g., -O2 and -fPIC).
+ if test "${GCC}" = yes; then
+ tentative_python_cflags="-fno-strict-aliasing -DNDEBUG -fwrapv"
+ fi
+
+ if test "x${tentative_python_cflags}" != x; then
+ AC_MSG_CHECKING(compiler flags for python code)
+ for flag in ${tentative_python_cflags}; do
+ # Check that the compiler accepts it
+ saved_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $flag"
+ AC_TRY_COMPILE([],[],PYTHON_CFLAGS="${PYTHON_CFLAGS} $flag",)
+ CFLAGS="$saved_CFLAGS"
+ done
+ AC_MSG_RESULT(${PYTHON_CFLAGS})
+ fi
+else
+ # Even if Python support is not compiled in, we need to have this file
+ # included in order to recognize the GDB command "python".
+ CONFIG_OBS="$CONFIG_OBS python.o"
+ CONFIG_SRCS="$CONFIG_SRCS python/python.c"
+fi
+AC_SUBST(PYTHON_CFLAGS)
+
# ------------------------- #
# Checks for header files. #
# ------------------------- #
Index: typos/gdb/defs.h
===================================================================
--- typos.orig/gdb/defs.h 2008-07-16 13:20:47.000000000 -0300
+++ typos/gdb/defs.h 2008-07-21 12:16:16.000000000 -0300
@@ -652,6 +652,7 @@ enum command_control_type
while_control,
if_control,
commands_control,
+ python_control,
invalid_control
};
Index: typos/gdb/doc/gdb.texinfo
===================================================================
--- typos.orig/gdb/doc/gdb.texinfo 2008-07-16 13:20:47.000000000 -0300
+++ typos/gdb/doc/gdb.texinfo 2008-07-21 12:16:16.000000000 -0300
@@ -165,6 +165,7 @@ software in general. We will miss him.
* Emacs:: Using @value{GDBN} under @sc{gnu} Emacs
* GDB/MI:: @value{GDBN}'s Machine Interface.
* Annotations:: @value{GDBN}'s annotation interface.
+* Python:: Scripting @value{GDBN} using Python.
* GDB Bugs:: Reporting bugs in @value{GDBN}
@@ -22704,6 +22705,124 @@ source which is being displayed. @var{a
followed by one or more lowercase hex digits (note that this does not
depend on the language).
+@node Python
+@chapter Scripting @value{GDBN} using Python
+@cindex Python
+
+You can script @value{GDBN} using the @url{http://www.python.org/,
+Python programming language}. This feature is available only if
+@value{GDBN} was configured using @code{--with-python}.
+
+@menu
+* Python Commands:: Accessing Python from @value{GDBN}.
+* Python API:: Accessing @value{GDBN} from Python.
+@end menu
+
+@node Python Commands
+@section Python Commands
+
+@value{GDBN} provides one command for accessing the Python interpreter,
+and one related setting:
+
+@table @code
+@kindex python
+@item python @r{[}@var{code}@r{]}
+The @code{python} command can be used to evaluate Python code.
+
+If given an argument, the @code{python} command will evaluate the
+argument as a Python command. For example:
+
+@smallexample
+(@value{GDBP}) python print 23
+23
+@end smallexample
+
+If you do not provide an argument to @code{python}, it will act as a
+multi-line command, like @code{define}. In this case, the Python
+script is made up of subsequent command lines, given after the
+@code{python} command. This command list is terminated using a line
+containing @code{end}. For example:
+
+@smallexample
+(@value{GDBP}) python
+Type python script
+End with a line saying just "end".
+>print 23
+>end
+23
+@end smallexample
+
+@kindex maint set python print-stack
+@item maint set python print-stack
+By default, @value{GDBN} will print a stack trace when an error occurs
+in a Python script. This can be controlled using @code{maint set python
+print-stack}. This variable takes a boolean value; if @code{on}, the
+default, then Python stack printing is enabled; if @code{off}, then
+Python stack printing is disabled.
+@end table
+
+@node Python API
+@section Python API
+
+@value{GDBN} exposes a number of features to Python scripts.
+
+@cindex python exceptions
+@cindex exceptions, python
+When executing a @code{python} command, uncaught Python exceptions are
+translated to calls to @value{GDBN}'s @code{error} function.
+Conversely, @value{GDBN} exceptions are converted to Python exceptions.
+In particular, a @value{GDBN} @code{QUIT} exception is translated to a
+Python @code{KeyboardInterrupt} exception, and other @value{GDBN}
+exceptions are translated to Python @code{RuntimeError}s.
+
+@cindex python stdout
+@cindex python pagination
+At startup, @value{GDBN} overrides Python's @code{sys.stdout} and
+@code{sys.stderr} to print using @value{GDBN}'s output-paging streams.
+A Python program which outputs to one of these streams may have its
+output interrupted by the user (@pxref{Screen Size}). In this
+situation, a Python @code{KeyboardInterrupt} exception is thrown.
+
+@cindex python functions
+@cindex python module
+@cindex gdb module
+@value{GDBN} introduces a new Python module, named @code{gdb}. All
+methods and classes added by @value{GDBN} are placed in this module.
+
+@findex gdb.execute
+@defun execute @var{command}
+Evaluate @var{command}, a string, as a @value{GDBN} CLI command.
+Exceptions are translated as noted above. If no error occurs, this
+function will return @code{None}.
+@end defun
+
+@findex gdb.show
+@defun show @var{variable}
+Find the value of a @value{GDBN} setting. @var{variable} is a string
+naming the setting to look up; @var{variable} may contain spaces if the
+variable has a multi-part name. For example, @samp{print object} is a
+valid variable name.
+
+If the named variable does not exist, this function throws an exception.
+Otherwise, the variable's value is converted to a Python value of the
+appropriate type, and returned.
+@end defun
+
+@findex gdb.write
+@defun write @var{string}
+Print a string to @value{GDBN}'s paginated standard output stream.
+Ordinarily your program should not call this function directly; simply
+print to @code{sys.stdout} as usual.
+@end defun
+
+@findex gdb.flush
+@defun flush
+Flush @value{GDBN}'s paginated standard output stream. Ordinarily your
+program should not call this function directly; simply flush
+@code{sys.stdout} as usual.
+@end defun
+
+
@node GDB Bugs
@chapter Reporting Bugs in @value{GDBN}
@cindex bugs in @value{GDBN}
Index: typos/gdb/python/python-internal.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ typos/gdb/python/python-internal.h 2008-07-21 12:16:16.000000000 -0300
@@ -0,0 +1,71 @@
+/* Gdb/Python header for private use by Python module.
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDB_PYTHON_INTERNAL_H
+#define GDB_PYTHON_INTERNAL_H
+
+/* Python 2.4 doesn't include stdint.h soon enough to get {u,}intptr_t
+ needed by pyport.h. */
+#include <stdint.h>
+
+/* /usr/include/features.h on linux systems will define _POSIX_C_SOURCE
+ if it sees _GNU_SOURCE (which config.h will define).
+ pyconfig.h defines _POSIX_C_SOURCE to a different value than
+ /usr/include/features.h does causing compilation to fail.
+ To work around this, undef _POSIX_C_SOURCE before we include Python.h. */
+#undef _POSIX_C_SOURCE
+
+#if HAVE_LIBPYTHON2_4
+#include "python2.4/Python.h"
+/* Py_ssize_t is not defined until 2.5. */
+typedef Py_intptr_t Py_ssize_t;
+#elif HAVE_LIBPYTHON2_5
+#include "python2.5/Python.h"
+#elif HAVE_LIBPYTHON2_6
+#include "python2.6/Python.h"
+#else
+#error "Unable to find usable Python.h"
+#endif
+
+struct block;
+struct symbol;
+struct symtab_and_line;
+
+extern PyObject *gdb_module;
+
+struct cleanup *make_cleanup_py_decref (PyObject *py);
+
+/* Use this after a TRY_EXCEPT to throw the appropriate Python
+ exception. */
+#define GDB_PY_HANDLE_EXCEPTION(Exception) \
+ do { \
+ if (Exception.reason < 0) \
+ return PyErr_Format (Exception.reason == RETURN_QUIT \
+ ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, \
+ "%s", Exception.message); \
+ } while (0)
+
+
+void gdbpy_print_stack (void);
+
+PyObject *python_string_to_unicode (PyObject *obj);
+char *unicode_to_target_string (PyObject *unicode_str);
+char *python_string_to_target_string (PyObject *obj);
+
+#endif /* GDB_PYTHON_INTERNAL_H */
Index: typos/gdb/python/python-utils.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ typos/gdb/python/python-utils.c 2008-07-21 12:16:16.000000000 -0300
@@ -0,0 +1,117 @@
+/* General utility routines for GDB/Python.
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "charset.h"
+#include "python-internal.h"
+
+
+/* This is a cleanup function which decrements the refcount on a
+ Python object. */
+
+static void
+py_decref (void *p)
+{
+ PyObject *py = p;
+ /* Note that we need the extra braces in this 'if' to avoid a
+ warning from gcc. */
+ if (py)
+ {
+ Py_DECREF (py);
+ }
+}
+
+/* Return a new cleanup which will decrement the Python object's
+ refcount when run. */
+
+struct cleanup *
+make_cleanup_py_decref (PyObject *py)
+{
+ return make_cleanup (py_decref, (void *) py);
+}
+
+/* Converts a Python 8-bit string to a unicode string object. Assumes the
+ 8-bit string is in the host charset. If an error occurs during conversion,
+ returns NULL with a python exception set.
+
+ As an added bonus, the functions accepts a unicode string and returns it
+ right away, so callers don't need to check which kind of string they've
+ got.
+
+ If the given object is not one of the mentioned string types, NULL is
+ returned, with the TypeError python exception set. */
+PyObject *
+python_string_to_unicode (PyObject *obj)
+{
+ PyObject *unicode_str;
+
+ /* If obj is already a unicode string, just return it.
+ I wish life was always that simple... */
+ if (PyUnicode_Check (obj))
+ unicode_str = obj;
+ else if (PyString_Check (obj))
+ unicode_str = PyUnicode_FromEncodedObject (obj, host_charset (), NULL);
+ else
+ {
+ PyErr_SetString (PyExc_TypeError,
+ _("Expected a string or unicode object."));
+ unicode_str = NULL;
+ }
+
+ return unicode_str;
+}
+
+/* Returns a newly allocated string with the contents of the given unicode
+ string object converted to the target's charset. If an error occurs during
+ the conversion, NULL will be returned and a python exception will be set.
+
+ The caller is responsible for xfree'ing the string. */
+char *
+unicode_to_target_string (PyObject *unicode_str)
+{
+ char *target_string;
+ PyObject *string;
+
+ /* Translate string to target's charset. */
+ string = PyUnicode_AsEncodedString (unicode_str, target_charset (), NULL);
+ if (string == NULL)
+ return NULL;
+
+ target_string = xstrdup (PyString_AsString (string));
+
+ Py_DECREF (string);
+
+ return target_string;
+}
+
+/* Converts a python string (8-bit or unicode) to a target string in
+ the target's charset. Returns NULL on error, with a python exception set.
+
+ The caller is responsible for xfree'ing the string. */
+char *
+python_string_to_target_string (PyObject *obj)
+{
+ PyObject *str;
+
+ str = python_string_to_unicode (obj);
+ if (str == NULL)
+ return NULL;
+
+ return unicode_to_target_string (str);
+}
Index: typos/gdb/python/python.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ typos/gdb/python/python.c 2008-07-21 12:16:16.000000000 -0300
@@ -0,0 +1,438 @@
+/* General python/gdb code
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "command.h"
+#include "ui-out.h"
+#include "cli/cli-script.h"
+#include "gdbcmd.h"
+
+#include <ctype.h>
+
+/* True if we should print the stack when catching a Python error,
+ false otherwise. */
+static int gdbpy_should_print_stack = 1;
+
+#ifdef HAVE_PYTHON
+
+#include "python.h"
+#include "libiberty.h"
+#include "cli/cli-decode.h"
+#include "charset.h"
+#include "top.h"
+#include "exceptions.h"
+#include "python-internal.h"
+#include "version.h"
+#include "target.h"
+#include "gdbthread.h"
+
+
+PyObject *gdb_module;
+
+static PyObject *get_show_variable (PyObject *, PyObject *);
+static PyObject *execute_gdb_command (PyObject *, PyObject *);
+static PyObject *gdbpy_write (PyObject *, PyObject *);
+static PyObject *gdbpy_flush (PyObject *, PyObject *);
+
+static PyMethodDef GdbMethods[] =
+{
+ { "execute", execute_gdb_command, METH_VARARGS,
+ "Execute a gdb command" },
+ { "show", get_show_variable, METH_VARARGS,
+ "Return a gdb setting's value" },
+
+ { "write", gdbpy_write, METH_VARARGS,
+ "Write a string using gdb's filtered stream." },
+ { "flush", gdbpy_flush, METH_NOARGS,
+ "Flush gdb's filtered stdout stream." },
+
+ {NULL, NULL, 0, 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
+ responsible for freeing it. */
+
+static char *
+compute_python_string (struct command_line *l)
+{
+ struct command_line *iter;
+ char *script = NULL;
+ int size = 0;
+ int here;
+
+ for (iter = l; iter; iter = iter->next)
+ size += strlen (iter->line) + 1;
+
+ script = xmalloc (size + 1);
+ here = 0;
+ for (iter = l; iter; iter = iter->next)
+ {
+ int len = strlen (iter->line);
+ strcpy (&script[here], iter->line);
+ here += len;
+ script[here++] = '\n';
+ }
+ script[here] = '\0';
+ return script;
+}
+
+/* Take a command line structure representing a 'python' command, and
+ evaluate its body using the Python interpreter. */
+
+void
+eval_python_from_control_command (struct command_line *cmd)
+{
+ char *script;
+
+ if (cmd->body_count != 1)
+ error (_("Invalid \"python\" block structure."));
+
+ script = compute_python_string (cmd->body_list[0]);
+ PyRun_SimpleString (script);
+ xfree (script);
+ if (PyErr_Occurred ())
+ {
+ gdbpy_print_stack ();
+ error (_("error while executing Python code"));
+ }
+}
+
+/* Implementation of the gdb "python" command. */
+
+static void
+python_command (char *arg, int from_tty)
+{
+ while (arg && *arg && isspace (*arg))
+ ++arg;
+ if (arg && *arg)
+ {
+ PyRun_SimpleString (arg);
+ if (PyErr_Occurred ())
+ {
+ gdbpy_print_stack ();
+ error (_("error while executing Python code"));
+ }
+ }
+ else
+ {
+ struct command_line *l = get_command_line (python_control, "");
+ struct cleanup *cleanups = make_cleanup_free_command_lines (&l);
+ execute_control_command_untraced (l);
+ do_cleanups (cleanups);
+ }
+}
+
+\f
+
+/* Transform a gdb variable's value into a Python value. May return
+ NULL (and set a Python exception) on error. Helper function for
+ get_show_variable. */
+
+static PyObject *
+variable_to_python (struct cmd_list_element *cmd)
+{
+ switch (cmd->var_type)
+ {
+ case var_string:
+ case var_string_noescape:
+ case var_optional_filename:
+ case var_filename:
+ case var_enum:
+ {
+ char *str = * (char **) cmd->var;
+ if (! str)
+ str = "";
+ return PyString_Decode (str, strlen (str), host_charset (), NULL);
+ }
+
+ case var_boolean:
+ {
+ if (* (int *) cmd->var)
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
+ }
+
+ case var_auto_boolean:
+ {
+ enum auto_boolean ab = * (enum auto_boolean *) cmd->var;
+ if (ab == AUTO_BOOLEAN_TRUE)
+ Py_RETURN_TRUE;
+ else if (ab == AUTO_BOOLEAN_FALSE)
+ Py_RETURN_FALSE;
+ else
+ Py_RETURN_NONE;
+ }
+
+ case var_integer:
+ if ((* (int *) cmd->var) == INT_MAX)
+ Py_RETURN_NONE;
+ /* Fall through. */
+ case var_zinteger:
+ return PyLong_FromLong (* (int *) cmd->var);
+
+ case var_uinteger:
+ {
+ unsigned int val = * (unsigned int *) cmd->var;
+ if (val == UINT_MAX)
+ Py_RETURN_NONE;
+ return PyLong_FromUnsignedLong (val);
+ }
+ }
+
+ return PyErr_Format (PyExc_RuntimeError, "programmer error: unhandled type");
+}
+
+/* A Python function which returns a gdb variable's value as a Python
+ value. */
+
+static PyObject *
+get_show_variable (PyObject *self, PyObject *args)
+{
+ struct cmd_list_element *alias, *prefix, *cmd;
+ char *arg, *newarg;
+ volatile struct gdb_exception except;
+
+ if (! PyArg_ParseTuple (args, "s", &arg))
+ return NULL;
+
+ newarg = concat ("show ", arg, (char *) NULL);
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ if (! lookup_cmd_composition (newarg, &alias, &prefix, &cmd))
+ {
+ xfree (newarg);
+ return PyErr_Format (PyExc_RuntimeError,
+ "could not find variable `%s'", arg);
+ }
+ }
+ xfree (newarg);
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ if (! cmd->var)
+ return PyErr_Format (PyExc_RuntimeError, "`%s' is not a variable", arg);
+ return variable_to_python (cmd);
+}
+
+/* A Python function which evaluates a string using the gdb CLI. */
+
+static PyObject *
+execute_gdb_command (PyObject *self, PyObject *args)
+{
+ struct cmd_list_element *alias, *prefix, *cmd;
+ char *arg, *newarg;
+ volatile struct gdb_exception except;
+ struct cleanup *old_chain;
+
+ if (! PyArg_ParseTuple (args, "s", &arg))
+ return NULL;
+
+ old_chain = make_cleanup (null_cleanup, 0);
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ execute_command (arg, 0);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ /* Do any commands attached to breakpoint we stopped at. Only if we
+ are always running synchronously. Or if we have just executed a
+ command that doesn't start the target. */
+ if (!target_can_async_p () || !is_running (inferior_ptid))
+ {
+ bpstat_do_actions (&stop_bpstat);
+ do_cleanups (old_chain);
+ }
+
+ Py_RETURN_NONE;
+}
+
+\f
+
+/* Printing. */
+
+/* A python function to write a single string using gdb's filtered
+ output stream. */
+static PyObject *
+gdbpy_write (PyObject *self, PyObject *args)
+{
+ char *arg;
+ if (! PyArg_ParseTuple (args, "s", &arg))
+ return NULL;
+ printf_filtered ("%s", arg);
+ Py_RETURN_NONE;
+}
+
+/* A python function to flush gdb's filtered output stream. */
+static PyObject *
+gdbpy_flush (PyObject *self, PyObject *args)
+{
+ gdb_flush (gdb_stdout);
+ Py_RETURN_NONE;
+}
+
+/* Print a python exception trace, or print nothing and clear the
+ python exception, depending on gdbpy_should_print_stack. Only call
+ this if a python exception is set. */
+void
+gdbpy_print_stack (void)
+{
+ if (gdbpy_should_print_stack)
+ PyErr_Print ();
+ else
+ PyErr_Clear ();
+}
+
+#else /* HAVE_PYTHON */
+
+/* Dummy implementation of the gdb "python" command. */
+
+static void
+python_command (char *arg, int from_tty)
+{
+ while (arg && *arg && isspace (*arg))
+ ++arg;
+ if (arg && *arg)
+ error (_("Python scripting is not supported in this copy of GDB."));
+ else
+ {
+ struct command_line *l = get_command_line (python_control, "");
+ struct cleanup *cleanups = make_cleanup_free_command_lines (&l);
+ execute_control_command_untraced (l);
+ do_cleanups (cleanups);
+ }
+}
+
+void
+eval_python_from_control_command (struct command_line *cmd)
+{
+ error (_("Python scripting is not supported in this copy of GDB."));
+}
+
+#endif /* HAVE_PYTHON */
+
+\f
+
+/* Lists for 'maint set python' commands. */
+
+static struct cmd_list_element *set_python_list;
+static struct cmd_list_element *show_python_list;
+
+/* Function for use by 'maint set python' prefix command. */
+
+static void
+set_python (char *args, int from_tty)
+{
+ help_list (set_python_list, "maintenance set python ", -1, gdb_stdout);
+}
+
+/* Function for use by 'maint show python' prefix command. */
+
+static void
+show_python (char *args, int from_tty)
+{
+ cmd_show_list (show_python_list, from_tty, "");
+}
+
+/* Initialize the Python code. */
+
+void
+_initialize_python (void)
+{
+ add_com ("python", class_obscure, python_command,
+#ifdef HAVE_PYTHON
+ _("\
+Evaluate a Python command.\n\
+\n\
+The command can be given as an argument, for instance:\n\
+\n\
+ python print 23\n\
+\n\
+If no argument is given, the following lines are read and used\n\
+as the Python commands. Type a line containing \"end\" to indicate\n\
+the end of the command.")
+#else /* HAVE_PYTHON */
+ _("\
+Evaluate a Python command.\n\
+\n\
+Python scripting is not supported in this copy of GDB.\n\
+This command is only a placeholder.")
+#endif /* HAVE_PYTHON */
+ );
+
+ add_prefix_cmd ("python", no_class, show_python,
+ _("Prefix command for python maintenance settings."),
+ &show_python_list, "maint show python ", 0,
+ &maintenance_show_cmdlist);
+ add_prefix_cmd ("python", no_class, set_python,
+ _("Prefix command for python maintenance settings."),
+ &set_python_list, "maint set python ", 0,
+ &maintenance_set_cmdlist);
+
+ add_setshow_boolean_cmd ("print-stack", class_maintenance,
+ &gdbpy_should_print_stack, _("\
+Enable or disable printing of Python stack dump on error."), _("\
+Show whether Python stack will be printed on error."), _("\
+Enables or disables printing of Python stack traces."),
+ NULL, NULL,
+ &set_python_list,
+ &show_python_list);
+
+#ifdef HAVE_PYTHON
+ Py_Initialize ();
+
+ gdb_module = Py_InitModule ("gdb", GdbMethods);
+
+ /* The casts to (char*) are for python 2.4. */
+ PyModule_AddStringConstant (gdb_module, "VERSION", (char*) version);
+ PyModule_AddStringConstant (gdb_module, "HOST_CONFIG", (char*) host_name);
+ PyModule_AddStringConstant (gdb_module, "TARGET_CONFIG", (char*) target_name);
+
+ PyRun_SimpleString ("import gdb");
+
+ /* Create a couple objects which are used for Python's stdout and
+ stderr. */
+ PyRun_SimpleString ("\
+import sys\n\
+class GdbOutputFile:\n\
+ def close(self):\n\
+ # Do nothing.\n\
+ return None\n\
+\n\
+ def isatty(self):\n\
+ return False\n\
+\n\
+ def write(self, s):\n\
+ gdb.write(s)\n\
+\n\
+ def writelines(self, iterable):\n\
+ for line in iterable:\n\
+ self.write(line)\n\
+\n\
+ def flush(self):\n\
+ gdb.flush()\n\
+\n\
+sys.stderr = GdbOutputFile()\n\
+sys.stdout = GdbOutputFile()\n\
+");
+#endif /* HAVE_PYTHON */
+}
Index: typos/gdb/python/python.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ typos/gdb/python/python.h 2008-07-21 12:16:16.000000000 -0300
@@ -0,0 +1,27 @@
+/* Python/gdb header for generic use in gdb
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDB_PYTHON_H
+#define GDB_PYTHON_H
+
+#include "value.h"
+
+void eval_python_from_control_command (struct command_line *);
+
+#endif /* GDB_PYTHON_H */
Index: typos/gdb/testsuite/gdb.python/python.exp
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ typos/gdb/testsuite/gdb.python/python.exp 2008-07-21 12:16:16.000000000 -0300
@@ -0,0 +1,66 @@
+# Copyright (C) 2008 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite. It tests the mechanism
+# exposing values to Python.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test_multiple "python print 23" "verify python support" {
+ -re "not supported.*$gdb_prompt $" {
+ unsupported "python support is disabled"
+ return -1
+ }
+ -re "$gdb_prompt $" {}
+}
+
+# Usage: gdb_py_test_multiple NAME INPUT RESULT {INPUT RESULT}...
+# Run a test named NAME, consisting of multiple lines of input.
+# After each input line INPUT, search for result line RESULT.
+# Succeed if all results are seen; fail otherwise.
+proc gdb_py_test_multiple {name args} {
+ global gdb_prompt
+ foreach {input result} $args {
+ if {[gdb_test_multiple $input "$name - $input" {
+ -re "\[\r\n\]*($result)\[\r\n\]+($gdb_prompt | *>)$" {
+ pass "$name - $input"
+ }
+ }]} {
+ return 1
+ }
+ }
+ return 0
+}
+
+gdb_py_test_multiple "multi-line python command" \
+ "python" "" \
+ "print 23" "" \
+ "end" "23"
+
+gdb_py_test_multiple "show python command" \
+ "define zzq" "Type commands for definition of .* just \"end\"\\.*" \
+ "python" "" \
+ "print 23" "" \
+ "end" "" \
+ "end" "" \
+ "show user zzq" "User command zzq:.* python.*print 23.* end"
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-21 15:29 ` [RFA][patch 1/9] Yet another respin of the patch with " Thiago Jung Bauermann
@ 2008-07-21 16:47 ` Thiago Jung Bauermann
2008-07-26 13:07 ` Eli Zaretskii
2008-08-02 17:41 ` Daniel Jacobowitz
2 siblings, 0 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-07-21 16:47 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Tom Tromey, gdb-patches ml, Eli Zaretskii
On Mon, 2008-07-21 at 12:26 -0300, Thiago Jung Bauermann wrote:
> @@ -1283,7 +1303,11 @@ test-cp-name-parser$(EXEEXT): test-cp-na
> # duplicates. Files in the gdb/ directory can end up appearing in
> # COMMON_OBS (as a .o file) and CONFIG_SRCS (as a .c file).
>
> -INIT_FILES = $(COMMON_OBS) $(TSOBS) $(CONFIG_SRCS)
> +# NOTE: bauermann/2008-06-15: python.c needs to be explicitly included
> +# because the generation of init.c does not work for .c files which
> +# result in differently named objects (i.e., python/python -> python.o).
> +
> +INIT_FILES = $(COMMON_OBS) $(TSOBS) $(CONFIG_SRCS) python/python.c
> init.c: $(INIT_FILES)
> @echo Making init.c
> @rm -f init.c-tmp init.l-tmp
Please ignore this hunk, it shouldn't be there and won't be committed
(*sigh*). The rest of the patch is ok.
Thanks, Tromey, for sanity checking this post and spotting this.
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* [obvious] Wipe out CONFIG_INITS.
2008-07-21 2:03 ` Daniel Jacobowitz
@ 2008-07-23 17:46 ` Thiago Jung Bauermann
0 siblings, 0 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-07-23 17:46 UTC (permalink / raw)
To: gdb-patches ml
On Sun, 2008-07-20 at 22:03 -0400, Daniel Jacobowitz wrote:
> CONFIG_INITS appears to be obsolete.
Indeed, ChangeLog-2004 shows that it's long been deleted.
Commited this patch to remove last instance of it.
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
2008-07-23 Thiago Jung Bauermann <bauerman@br.ibm.com>
* configure.ac (CONFIG_INITS): Delete long obsoleted variable.
* configure: Regenerate.
diff -u -r1.254 configure
--- configure 18 Jul 2008 13:38:13 -0000 1.254
+++ configure 23 Jul 2008 16:08:18 -0000
@@ -25480,7 +25480,6 @@
CONFIG_OBS="$CONFIG_OBS \$(SUBDIR_TUI_OBS)"
CONFIG_DEPS="$CONFIG_DEPS \$(SUBDIR_TUI_DEPS)"
CONFIG_SRCS="$CONFIG_SRCS \$(SUBDIR_TUI_SRCS)"
- CONFIG_INITS="$CONFIG_INITS \$(SUBDIR_TUI_INITS)"
ENABLE_CFLAGS="$ENABLE_CFLAGS \$(SUBDIR_TUI_CFLAGS)"
CONFIG_ALL="${CONFIG_ALL} all-tui"
CONFIG_CLEAN="${CONFIG_CLEAN} clean-tui"
Index: configure.ac
===================================================================
RCS file: /cvs/src/src/gdb/configure.ac,v
retrieving revision 1.74
diff -u -r1.74 configure.ac
--- configure.ac 18 Jul 2008 13:38:14 -0000 1.74
+++ configure.ac 23 Jul 2008 16:08:18 -0000
@@ -1607,7 +1607,6 @@
CONFIG_OBS="$CONFIG_OBS \$(SUBDIR_TUI_OBS)"
CONFIG_DEPS="$CONFIG_DEPS \$(SUBDIR_TUI_DEPS)"
CONFIG_SRCS="$CONFIG_SRCS \$(SUBDIR_TUI_SRCS)"
- CONFIG_INITS="$CONFIG_INITS \$(SUBDIR_TUI_INITS)"
ENABLE_CFLAGS="$ENABLE_CFLAGS \$(SUBDIR_TUI_CFLAGS)"
CONFIG_ALL="${CONFIG_ALL} all-tui"
CONFIG_CLEAN="${CONFIG_CLEAN} clean-tui"
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 2/9] export values mechanism to Python
2008-07-07 23:44 ` Tom Tromey
@ 2008-07-26 2:55 ` Daniel Jacobowitz
2008-07-26 17:17 ` Tom Tromey
0 siblings, 1 reply; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-07-26 2:55 UTC (permalink / raw)
To: Tom Tromey; +Cc: Thiago Jung Bauermann, gdb-patches
On Mon, Jul 07, 2008 at 05:44:23PM -0600, Tom Tromey wrote:
> Thiago> In the case of valpy_get_element (which is used to access an element in
> Thiago> a value representing a struct or class), using __getitem__ means that in
> Thiago> Python one would use a_struct["element"] to access a_struct.element.
> Thiago> This looks a bit strange at least.
>
> I don't mind this, my reasoning is:
>
> * I suspect it will be more common to use a string-valued expression
> here than it will be to use a string constant.
I don't know about that... If we have a foo and want to
determine what sort of foo it is, we'll want foo.type and foo.subtype;
in other words I expect pretty-printers to use lots of fixed-name
members.
> * This approach also works nicely for arrays.
> * This approach does not mix the Value namespace with the
> debuggee's field names.
I thought about making both approaches work. It is tecnically easy;
if we use __getattr__, then foo.field will work - unless field is
ambiguous with a value method, which will take priority. foo["field"]
will always work. But if we provide this then script writers will use
it which will be a problem if we ever added methods.
So, it only makes sense if we plan to have no instance methods for
values. You'd know better than I do whether instance methods are
likely to be useful here.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-21 15:29 ` [RFA][patch 1/9] Yet another respin of the patch with " Thiago Jung Bauermann
2008-07-21 16:47 ` Thiago Jung Bauermann
@ 2008-07-26 13:07 ` Eli Zaretskii
2008-07-26 13:43 ` Daniel Jacobowitz
` (2 more replies)
2008-08-02 17:41 ` Daniel Jacobowitz
2 siblings, 3 replies; 147+ messages in thread
From: Eli Zaretskii @ 2008-07-26 13:07 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: drow, tromey, gdb-patches
> From: Thiago Jung Bauermann <bauerman@br.ibm.com>
> Cc: Tom Tromey <tromey@redhat.com>,
> gdb-patches ml <gdb-patches@sourceware.org>,
> Eli Zaretskii <eliz@gnu.org>
> Date: Mon, 21 Jul 2008 12:26:09 -0300
>
> This is today's version of the patch. :-)
> It addresses the latest review comments, and is good to go AFAIK.
>
> Eli,
>
> What do you think of this documentation?
Thanks; comments below.
Do I understand correctly that I need not review the doco patches you
posted prior to this? If there's something else I should review,
please point to the corresponding messages.
> +* Python scripting
> +
> + GDB now has support for scripting using Python. Whether this is
> + available is determined at configure time; you can explicitly
> + disable the support using --without-python.
Is --without-python a configure-time switch or a run-time switch? If
the former, I don't think it should be mentioned here. If the latter,
we should explicitly say it's a run-time switch.
> +python [code]
> + Invoke python code.
Please say a few word about the form of [code]. Is it a string? if
so, should it be in quotes? Or maybe it's the name of a file with
Python code? Or something else? These all are questions that went
through my head when I was reading this NEWS entry.
> + else if (p1 - p == 6 && !strncmp (p, "python", 6))
Can we avoid literal constants such as 6 here, and instead make it
dependent on the string "python"?
> else if (p1 - p == 10 && !strncmp (p, "loop_break", 10))
Ditto.
> * Emacs:: Using @value{GDBN} under @sc{gnu} Emacs
> * GDB/MI:: @value{GDBN}'s Machine Interface.
> * Annotations:: @value{GDBN}'s annotation interface.
> +* Python:: Scripting @value{GDBN} using Python.
I think this should not be a separate chapter, but rather a section of
the "Canned Sequences of Commands" chapter.
> +@node Python
> +@chapter Scripting @value{GDBN} using Python
> +@cindex Python
First, @cindex entries should begin with lower-case letters, to
produce deterministic results when index entries are sorted.
Second, I think "python scripting" will be a better index entry here,
especially since the GDB manual joins all indices into one, and you
define later an index entry "python" for `python' the command..
Third, I'd add another @cindex entry "scripting with Python".
> +You can script @value{GDBN} using the @url{http://www.python.org/,
> +Python programming language}.
Please use @uref, not @url here. The latter has become a synonym of
the former only in the latest versions of Texinfo, so let's not force
users upgrade their Texinfo just for that.
>+ This feature is available only if
> +@value{GDBN} was configured using @code{--with-python}.
Please use @option for switches, not @code.
> +@node Python Commands
> +@section Python Commands
This needs index entries; please add them.
> +By default, @value{GDBN} will print a stack trace when an error occurs
> +in a Python script. This can be controlled using @code{maint set python
> +print-stack}. This variable takes a boolean value; if @code{on}, the
> +default, then Python stack printing is enabled; if @code{off}, then
> +Python stack printing is disabled.
I'd rephrase this slightly ("set python print-stack" is not a
variable):
By default, @value{GDBN} prints a stack trace when an error occurs
in a Python script. This can be controlled using @code{maint set
python print-stack}: if @code{on}, the default, Python stack
printing is enabled; if @code{off}, it is disabled.
> +@node Python API
> +@section Python API
This also needs index entries.
> +@value{GDBN} exposes a number of features to Python scripts.
This should end with a colon, and the list of the features should be a
@table.
> +When executing a @code{python} command, uncaught Python exceptions are
^^^
"the @code{python} command"
> +In particular, a @value{GDBN} @code{QUIT} exception is translated to a
> +Python @code{KeyboardInterrupt} exception, and other @value{GDBN}
> +exceptions are translated to Python @code{RuntimeError}s.
I think this is nowhere nearly as clear as it should be. Even to a C
hacker, "QUIT exception" is not sufficiently self-explanatory. Do you
mean SIGQUIT? then please say so. Will Python RuntimeError clear
enough to casual GDB users who want to use Python scripting, but are
not experienced Python programmers? I'm not sure. And what about
stating explicitly which exceptions map to which Python RuntimeError.
Finally, "GDB exception" is itself a term that is not defined anywhere
in the manual. Strictly speaking, GDB being a C program does not have
any exception at all.
This all needs to be explained, if we want Python scripting to be
useful for writing complex GDB extensions (which is the raison d'être
of this feature in the first place).
> +At startup, @value{GDBN} overrides Python's @code{sys.stdout} and
> +@code{sys.stderr} to print using @value{GDBN}'s output-paging streams.
> +A Python program which outputs to one of these streams may have its
> +output interrupted by the user (@pxref{Screen Size}). In this
> +situation, a Python @code{KeyboardInterrupt} exception is thrown.
Is there something here that whoever writes the Python program should
know to behave correctly? Does she need, for example, catch
KeyboardInterrupt and do something in the handler? If so, we should
state here what's needed.
> +@value{GDBN} introduces a new Python module, named @code{gdb}. All
> +methods and classes added by @value{GDBN} are placed in this module.
OK, but what does this mean for whoever writes Python extensions for
GDB? While at that, how about explaining why a command FOO is indexed
as gdb.FOO?
> +@defun execute @var{command}
You should not give a @var markup to arguments in @defun; @defun does
that itself.
> +Evaluate @var{command}, a string, as a @value{GDBN} CLI command.
> +Exceptions are translated as noted above. If no error occurs, this
> +function will return @code{None}.
The last sentence begs a question: what happens if errors _do_ occur?
> +@defun show @var{variable}
Please remove @var.
> +Find the value of a @value{GDBN} setting.
"find" or "display"? If the former, why the name is "show"?
> + @var{variable} is a string
> +naming the setting to look up; @var{variable} may contain spaces if the
> +variable has a multi-part name. For example, @samp{print object} is a
> +valid variable name.
So what signals the end of the name? Also, what exactly is a
"multi-part name"?
> +If the named variable does not exist, this function throws an exception.
Any specific exception? if so, please name it.
> +Otherwise, the variable's value is converted to a Python value of the
> +appropriate type, and returned.
Sounds like it's indeed "find the value" or "return the value", not
"show". How about renaming the command to be more mnemonic?
> +@defun write @var{string}
@var again.
> +Print a string to @value{GDBN}'s paginated standard output stream.
> +Ordinarily your program should not call this function directly; simply
> +print to @code{sys.stdout} as usual.
So why is this command available, and why document it?
> +@defun flush
> +Flush @value{GDBN}'s paginated standard output stream. Ordinarily your
> +program should not call this function directly; simply flush
> +@code{sys.stdout} as usual.
Ditto.
Thanks again for working on this.
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-26 13:07 ` Eli Zaretskii
@ 2008-07-26 13:43 ` Daniel Jacobowitz
2008-07-26 14:02 ` Eli Zaretskii
2008-07-26 17:04 ` Tom Tromey
2008-08-04 4:44 ` [RFA][patch 1/9] Yet another respin of the patch with initial Python support Thiago Jung Bauermann
2 siblings, 1 reply; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-07-26 13:43 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: Thiago Jung Bauermann, tromey, gdb-patches
On Sat, Jul 26, 2008 at 04:06:30PM +0300, Eli Zaretskii wrote:
> > * Emacs:: Using @value{GDBN} under @sc{gnu} Emacs
> > * GDB/MI:: @value{GDBN}'s Machine Interface.
> > * Annotations:: @value{GDBN}'s annotation interface.
> > +* Python:: Scripting @value{GDBN} using Python.
>
> I think this should not be a separate chapter, but rather a section of
> the "Canned Sequences of Commands" chapter.
Can I suggest leaving it in the top level menu? The bits added by
this patch are similar to canned sequences of commands ("define"), but
this is the first patch of hopefully many; you'll be able to use it
for more than just macros.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-26 13:43 ` Daniel Jacobowitz
@ 2008-07-26 14:02 ` Eli Zaretskii
2008-07-26 14:42 ` Daniel Jacobowitz
0 siblings, 1 reply; 147+ messages in thread
From: Eli Zaretskii @ 2008-07-26 14:02 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: bauerman, tromey, gdb-patches
> Date: Sat, 26 Jul 2008 09:42:52 -0400
> From: Daniel Jacobowitz <drow@false.org>
> Cc: Thiago Jung Bauermann <bauerman@br.ibm.com>, tromey@redhat.com,
> gdb-patches@sourceware.org
>
> On Sat, Jul 26, 2008 at 04:06:30PM +0300, Eli Zaretskii wrote:
> > > * Emacs:: Using @value{GDBN} under @sc{gnu} Emacs
> > > * GDB/MI:: @value{GDBN}'s Machine Interface.
> > > * Annotations:: @value{GDBN}'s annotation interface.
> > > +* Python:: Scripting @value{GDBN} using Python.
> >
> > I think this should not be a separate chapter, but rather a section of
> > the "Canned Sequences of Commands" chapter.
>
> Can I suggest leaving it in the top level menu?
Of course, you can suggest it.
> The bits added by
> this patch are similar to canned sequences of commands ("define"), but
> this is the first patch of hopefully many; you'll be able to use it
> for more than just macros.
Sorry, I don't understand this rationale (and what does it have to do
with macros? what macros?). Please elaborate.
My rationale is simple: we should have a single chapter for scripting,
because that's where a reader would look for information on how to
write GDB scripts. If there's sense to distributing this information
between separate chapters, please explain what that is.
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-26 14:02 ` Eli Zaretskii
@ 2008-07-26 14:42 ` Daniel Jacobowitz
2008-07-26 17:06 ` Eli Zaretskii
2008-07-26 17:10 ` Tom Tromey
0 siblings, 2 replies; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-07-26 14:42 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: bauerman, tromey, gdb-patches
On Sat, Jul 26, 2008 at 05:01:14PM +0300, Eli Zaretskii wrote:
> > The bits added by
> > this patch are similar to canned sequences of commands ("define"), but
> > this is the first patch of hopefully many; you'll be able to use it
> > for more than just macros.
>
> Sorry, I don't understand this rationale (and what does it have to do
> with macros? what macros?). Please elaborate.
Sorry, I'm used to thinking of user-defined commands as macros.
Sloppy choice of terminology.
> My rationale is simple: we should have a single chapter for scripting,
> because that's where a reader would look for information on how to
> write GDB scripts. If there's sense to distributing this information
> between separate chapters, please explain what that is.
Ok, in that case I have an alternative suggestion: how about renaming
the combined scripting chapter, and putting both Python scripting and
the existing information in the new chapter?
I don't think Python makes sense as a section of "Canned Sequences of
Commands", because Python scripts don't contain GDB commands. And
they will be able to respond to events that CLI scripts can not
respond to, because we can pass structured information to Python
scripts and retrieve structured results. For example, we can pass a
value or type and get back a friendlier display value or type; the
long-requested C++/STL pretty-printing support.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-26 13:07 ` Eli Zaretskii
2008-07-26 13:43 ` Daniel Jacobowitz
@ 2008-07-26 17:04 ` Tom Tromey
2008-07-26 17:35 ` Daniel Jacobowitz
2008-07-26 18:11 ` Eli Zaretskii
2008-08-04 4:44 ` [RFA][patch 1/9] Yet another respin of the patch with initial Python support Thiago Jung Bauermann
2 siblings, 2 replies; 147+ messages in thread
From: Tom Tromey @ 2008-07-26 17:04 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: Thiago Jung Bauermann, drow, gdb-patches
>>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:
Eli> Do I understand correctly that I need not review the doco patches you
Eli> posted prior to this? If there's something else I should review,
Eli> please point to the corresponding messages.
This is it.
>> + GDB now has support for scripting using Python. Whether this is
>> + available is determined at configure time; you can explicitly
>> + disable the support using --without-python.
Eli> Is --without-python a configure-time switch or a run-time switch? If
Eli> the former, I don't think it should be mentioned here. If the latter,
Eli> we should explicitly say it's a run-time switch.
Configure time. I changed the text to read:
* Python scripting
GDB now has support for scripting using Python. Whether this is
available is determined at configure time.
>> +python [code]
>> + Invoke python code.
Eli> Please say a few word about the form of [code]. Is it a string? if
Eli> so, should it be in quotes?
How about:
python [CODE]
Invoke CODE by passing it to the Python interpreter.
I can be as specific as you like here. I thought, though, that NEWS
was just a teaser and that users should read the manual for details.
>> + else if (p1 - p == 6 && !strncmp (p, "python", 6))
Eli> Can we avoid literal constants such as 6 here, and instead make it
Eli> dependent on the string "python"?
Here I just followed the existing code in that file.
>> else if (p1 - p == 10 && !strncmp (p, "loop_break", 10))
Eli> Ditto.
This is existing code. Please read that file, you'll see there are a
dozen cases like this. I don't mind fixing this, but I think it is
generally preferable to do cleanups in a separate patch. If you
disagree, let me know and I will go ahead and mash them together.
>> +* Python:: Scripting @value{GDBN} using Python.
Eli> I think this should not be a separate chapter, but rather a section of
Eli> the "Canned Sequences of Commands" chapter.
This is a drawback of the one-patch-at-a-time submission method.
Later patches, which we have not yet submitted, greatly expand this
chapter. In particular we add a bunch of subsections describing the
Python API.
>> +@node Python
>> +@chapter Scripting @value{GDBN} using Python
>> +@cindex Python
Eli> First, @cindex entries should begin with lower-case letters, to
Eli> produce deterministic results when index entries are sorted.
Ok. I fixed this. You might want to fix the other 121 occurrences ;)
>> + This feature is available only if
>> +@value{GDBN} was configured using @code{--with-python}.
Eli> Please use @option for switches, not @code.
Note there's another use of @code in this situation. I keep copying
the wrong examples :-(
>> +@value{GDBN} exposes a number of features to Python scripts.
Eli> This should end with a colon, and the list of the features should be a
Eli> @table.
I guess those aren't really features, they are more like generic
things that the python-in-gdb programmer ought to know.
So, I don't think a table makes sense, but I suppose the current text
is also misleading. What do you suggest?
>> +In particular, a @value{GDBN} @code{QUIT} exception is translated to a
>> +Python @code{KeyboardInterrupt} exception, and other @value{GDBN}
>> +exceptions are translated to Python @code{RuntimeError}s.
Eli> I think this is nowhere nearly as clear as it should be. Even to a C
Eli> hacker, "QUIT exception" is not sufficiently self-explanatory. Do you
Eli> mean SIGQUIT? then please say so.
Daniel or some other gdb maintainer will have to suggest something.
I don't know what else to call this. exceptions.h refers to "QUIT
event", but also the enum value is "RETURN_QUIT"... maybe the latter?
Eli> Will Python RuntimeError clear enough to casual GDB users who
Eli> want to use Python scripting, but are not experienced Python
Eli> programmers? I'm not sure.
People expecting to do this will have to read a Python manual.
There is no way around that.
Eli> And what about stating explicitly
Eli> which exceptions map to which Python RuntimeError.
It does say -- all the rest of them.
AFAICT gdb really only has quit exceptions and "the other kind".
Eli> Finally, "GDB exception" is itself a term that is not defined anywhere
Eli> in the manual. Strictly speaking, GDB being a C program does not have
Eli> any exception at all.
I guess that is true in some pedantic way, if you assume that only
languages that explicitly have a "throw" statement can have
exceptions. But, in practice it is manifestly untrue for gdb. gdb
uses exceptions everywhere, and discusses them in just those terms.
>> +At startup, @value{GDBN} overrides Python's @code{sys.stdout} and
>> +@code{sys.stderr} to print using @value{GDBN}'s output-paging streams.
>> +A Python program which outputs to one of these streams may have its
>> +output interrupted by the user (@pxref{Screen Size}). In this
>> +situation, a Python @code{KeyboardInterrupt} exception is thrown.
Eli> Is there something here that whoever writes the Python program should
Eli> know to behave correctly? Does she need, for example, catch
Eli> KeyboardInterrupt and do something in the handler? If so, we should
Eli> state here what's needed.
Yes, Python programmers might want to know about this in some
circumstances. It just depends on what they are trying to accomplish.
I don't agree that we need to explain this. I don't think we should
try to explain Python programming in general. Instead, I think we
should explain the Python API and refer users to already existing
Python manuals.
>> +@value{GDBN} introduces a new Python module, named @code{gdb}. All
>> +methods and classes added by @value{GDBN} are placed in this module.
Eli> OK, but what does this mean for whoever writes Python extensions for
Eli> GDB? While at that, how about explaining why a command FOO is indexed
Eli> as gdb.FOO?
I thought it would be nice to index them both ways. Do you disagree?
Python programmers know what the module stuff means. We don't have to
explain that.
>> +Find the value of a @value{GDBN} setting.
Eli> "find" or "display"? If the former, why the name is "show"?
It mimics the CLI command name.
"find" would be weird, IMO. I'm open to other names.
>> + @var{variable} is a string
>> +naming the setting to look up; @var{variable} may contain spaces if the
>> +variable has a multi-part name. For example, @samp{print object} is a
>> +valid variable name.
Eli> So what signals the end of the name? Also, what exactly is a
Eli> "multi-part name"?
The point of this text is to say that you can invoke:
gdb.show("print object")
and get a sensible answer.
If you want to rephrase this somehow, that is fine by me.
>> +Print a string to @value{GDBN}'s paginated standard output stream.
>> +Ordinarily your program should not call this function directly; simply
>> +print to @code{sys.stdout} as usual.
Eli> So why is this command available, and why document it?
Completeness. It is visible in the module.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-26 14:42 ` Daniel Jacobowitz
@ 2008-07-26 17:06 ` Eli Zaretskii
2008-07-26 17:26 ` Tom Tromey
2008-07-26 17:40 ` Daniel Jacobowitz
2008-07-26 17:10 ` Tom Tromey
1 sibling, 2 replies; 147+ messages in thread
From: Eli Zaretskii @ 2008-07-26 17:06 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: bauerman, tromey, gdb-patches
> Date: Sat, 26 Jul 2008 10:41:38 -0400
> From: Daniel Jacobowitz <drow@false.org>
> Cc: bauerman@br.ibm.com, tromey@redhat.com, gdb-patches@sourceware.org
>
> On Sat, Jul 26, 2008 at 05:01:14PM +0300, Eli Zaretskii wrote:
> > > The bits added by
> > > this patch are similar to canned sequences of commands ("define"), but
> > > this is the first patch of hopefully many; you'll be able to use it
> > > for more than just macros.
> >
> > Sorry, I don't understand this rationale (and what does it have to do
> > with macros? what macros?). Please elaborate.
>
> Sorry, I'm used to thinking of user-defined commands as macros.
> Sloppy choice of terminology.
So are you saying that adding Python will enable features that are
beyond user-defined commands (a.k.a. scripting)? If so, what are
those features?
> > My rationale is simple: we should have a single chapter for scripting,
> > because that's where a reader would look for information on how to
> > write GDB scripts. If there's sense to distributing this information
> > between separate chapters, please explain what that is.
>
> Ok, in that case I have an alternative suggestion: how about renaming
> the combined scripting chapter, and putting both Python scripting and
> the existing information in the new chapter?
I have no objections to renaming that chapter.
> I don't think Python makes sense as a section of "Canned Sequences of
> Commands", because Python scripts don't contain GDB commands.
The chapter name doesn't say "GDB Commands", it says just "Commands".
But let's not argue about that on which we agree ;-)
> For example, we can pass a value or type and get back a friendlier
> display value or type; the long-requested C++/STL pretty-printing
> support.
Maybe I'm missing something, because I don't see how this is different
from what we have now. For example, the .gdbinit file distributed
with Emacs already pretty-prints Emacs Lisp data types, as do the
various GDB extensions for printing Qt data types that float around.
They are all written in the current scripting CLI language. How will
Python be different in this department?
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-26 14:42 ` Daniel Jacobowitz
2008-07-26 17:06 ` Eli Zaretskii
@ 2008-07-26 17:10 ` Tom Tromey
2008-07-26 17:40 ` Eli Zaretskii
1 sibling, 1 reply; 147+ messages in thread
From: Tom Tromey @ 2008-07-26 17:10 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: bauerman, gdb-patches
>>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
>> My rationale is simple: we should have a single chapter for scripting,
>> because that's where a reader would look for information on how to
>> write GDB scripts. If there's sense to distributing this information
>> between separate chapters, please explain what that is.
Daniel> Ok, in that case I have an alternative suggestion: how about renaming
Daniel> the combined scripting chapter, and putting both Python scripting and
Daniel> the existing information in the new chapter?
I don't really want to merge them. I don't think it provides much
benefit to the reader of the manual.
It might make sense to document the "python" command alongside
"define" or what have you -- but I think only barely, since the
"python" command is kinda pointless without the rest of the API.
In the long run the Python chapter is going to be 99% documentation of
the Python API, something that will hold little interest to the casual
gdb user.
I guess we could even go so far as to make a separate python API
manual. That seemed like more of a pain though; I wasn't sure what
the benefit of that would be either.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 2/9] export values mechanism to Python
2008-07-26 2:55 ` Daniel Jacobowitz
@ 2008-07-26 17:17 ` Tom Tromey
2008-07-26 17:41 ` Daniel Jacobowitz
0 siblings, 1 reply; 147+ messages in thread
From: Tom Tromey @ 2008-07-26 17:17 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
>>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
>> * I suspect it will be more common to use a string-valued expression
>> here than it will be to use a string constant.
Daniel> I don't know about that... If we have a foo and want to
Daniel> determine what sort of foo it is, we'll want foo.type and
Daniel> foo.subtype; in other words I expect pretty-printers to use
Daniel> lots of fixed-name members.
Good point.
>> * This approach also works nicely for arrays.
>> * This approach does not mix the Value namespace with the
>> debuggee's field names.
Daniel> I thought about making both approaches work.
[...]
Daniel> So, it only makes sense if we plan to have no instance methods for
Daniel> values. You'd know better than I do whether instance methods are
Daniel> likely to be useful here.
I don't really know. I was just thinking we should be a bit
conservative so that if we find out we need methods later, we can add
them without worry.
There do seem to be a number of methods defined in value.h. I don't
know whether it makes sense to expose most of these to python, though.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-26 17:06 ` Eli Zaretskii
@ 2008-07-26 17:26 ` Tom Tromey
2008-07-26 19:21 ` Eli Zaretskii
2008-07-26 17:40 ` Daniel Jacobowitz
1 sibling, 1 reply; 147+ messages in thread
From: Tom Tromey @ 2008-07-26 17:26 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: Daniel Jacobowitz, bauerman, gdb-patches
>>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:
Eli> So are you saying that adding Python will enable features that are
Eli> beyond user-defined commands (a.k.a. scripting)? If so, what are
Eli> those features?
The python programmer will be able to access nearly everything. We
already have (on the branch) representations for threads, breakpoints,
commands, internal functions (a new feature), blocks, frames, symbols,
symbol tables, and values. We'll add more, too (at least types) --
but we're going through a round of cleanup-and-submit first.
>> For example, we can pass a value or type and get back a friendlier
>> display value or type; the long-requested C++/STL pretty-printing
>> support.
Eli> Maybe I'm missing something, because I don't see how this is different
Eli> from what we have now. For example, the .gdbinit file distributed
Eli> with Emacs already pretty-prints Emacs Lisp data types, as do the
Eli> various GDB extensions for printing Qt data types that float around.
Eli> They are all written in the current scripting CLI language. How will
Eli> Python be different in this department?
It will be integrated into "print" and will work with MI as well.
Lots of projects distribute .gdbinit-style files like this. They all
are lacking in various ways, due to shortcomings of gdb's command
language. The Python approach will fix all of this.
Pretty-printing is just one feature though. I want to push things
much farther.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-26 17:04 ` Tom Tromey
@ 2008-07-26 17:35 ` Daniel Jacobowitz
2008-07-26 17:42 ` Tom Tromey
2008-07-26 19:20 ` Eli Zaretskii
2008-07-26 18:11 ` Eli Zaretskii
1 sibling, 2 replies; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-07-26 17:35 UTC (permalink / raw)
To: Tom Tromey; +Cc: Eli Zaretskii, Thiago Jung Bauermann, gdb-patches
On Sat, Jul 26, 2008 at 11:04:24AM -0600, Tom Tromey wrote:
> >> +In particular, a @value{GDBN} @code{QUIT} exception is translated to a
> >> +Python @code{KeyboardInterrupt} exception, and other @value{GDBN}
> >> +exceptions are translated to Python @code{RuntimeError}s.
>
> Eli> I think this is nowhere nearly as clear as it should be. Even to a C
> Eli> hacker, "QUIT exception" is not sufficiently self-explanatory. Do you
> Eli> mean SIGQUIT? then please say so.
>
> Daniel or some other gdb maintainer will have to suggest something.
> I don't know what else to call this. exceptions.h refers to "QUIT
> event", but also the enum value is "RETURN_QUIT"... maybe the latter?
For clarification, Tom's talking about "QUIT;" in the GDB sources.
No need to talk about the internal meaning for that part - we can just
talk about interrupting operations with Control-C. I'm not sure how
to explain "other exceptions"; just "other error conditions"?
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-26 17:10 ` Tom Tromey
@ 2008-07-26 17:40 ` Eli Zaretskii
2008-07-26 18:00 ` Tom Tromey
0 siblings, 1 reply; 147+ messages in thread
From: Eli Zaretskii @ 2008-07-26 17:40 UTC (permalink / raw)
To: tromey; +Cc: bauerman, gdb-patches
> Cc: bauerman@br.ibm.com, gdb-patches@sourceware.org
> From: Tom Tromey <tromey@redhat.com>
> Date: Sat, 26 Jul 2008 11:09:59 -0600
>
> Daniel> Ok, in that case I have an alternative suggestion: how about renaming
> Daniel> the combined scripting chapter, and putting both Python scripting and
> Daniel> the existing information in the new chapter?
>
> I don't really want to merge them. I don't think it provides much
> benefit to the reader of the manual.
The benefit is more structure. Both Python support and the old way of
defining user-defined commands is about the same thing: extending GDB.
> It might make sense to document the "python" command alongside
> "define" or what have you -- but I think only barely, since the
> "python" command is kinda pointless without the rest of the API.
I don't see why this invalidates the merge. Please explain.
> In the long run the Python chapter is going to be 99% documentation of
> the Python API, something that will hold little interest to the casual
> gdb user.
That's why it will be in a different section.
> I guess we could even go so far as to make a separate python API
> manual. That seemed like more of a pain though; I wasn't sure what
> the benefit of that would be either.
I agree: there's no sense of having such a separate manual.
Determining where we stop describing Python in the GDB manual will be
a challenge, but it shouldn't IMO prevent us from trying to have some
reasonable structure on the top level. Having too many chapters is
not a good sign.
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-26 17:06 ` Eli Zaretskii
2008-07-26 17:26 ` Tom Tromey
@ 2008-07-26 17:40 ` Daniel Jacobowitz
1 sibling, 0 replies; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-07-26 17:40 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: bauerman, tromey, gdb-patches
On Sat, Jul 26, 2008 at 08:05:31PM +0300, Eli Zaretskii wrote:
> So are you saying that adding Python will enable features that are
> beyond user-defined commands (a.k.a. scripting)? If so, what are
> those features?
I don't know what any of them are yet. Some examples we've discussed
are support for transparent pretty-printing (much more flexible than
the existing print macros which just produce text - it will allow you
to explore nested objects using gdb's normal value operations, for
instance); support for new formats of shared libraries and core files;
custom backtracing support for interrupts; and new callable functions
in GDB's expression evaluator which produce typed values as if they
were inferior function calls.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 2/9] export values mechanism to Python
2008-07-26 17:17 ` Tom Tromey
@ 2008-07-26 17:41 ` Daniel Jacobowitz
2008-07-30 3:01 ` Tom Tromey
0 siblings, 1 reply; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-07-26 17:41 UTC (permalink / raw)
To: Tom Tromey; +Cc: Thiago Jung Bauermann, gdb-patches
On Sat, Jul 26, 2008 at 11:17:04AM -0600, Tom Tromey wrote:
> There do seem to be a number of methods defined in value.h. I don't
> know whether it makes sense to expose most of these to python, though.
Oh, I think it does - I'm just not sure how many of them will make
sense as instance methods rather than less object-oriented functions.
The operators we've already got covered.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-26 17:35 ` Daniel Jacobowitz
@ 2008-07-26 17:42 ` Tom Tromey
2008-07-26 19:18 ` Eli Zaretskii
2008-07-26 19:20 ` Eli Zaretskii
1 sibling, 1 reply; 147+ messages in thread
From: Tom Tromey @ 2008-07-26 17:42 UTC (permalink / raw)
To: gdb-patches
>>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
Daniel> No need to talk about the internal meaning for that part - we can just
Daniel> talk about interrupting operations with Control-C. I'm not sure how
Daniel> to explain "other exceptions"; just "other error conditions"?
How about this?
When executing the @code{python} command, uncaught Python exceptions
are translated to calls to @value{GDBN}'s @code{error} function.
Conversely, @value{GDBN} exceptions are converted to Python
exceptions. In particular, a user interrupt (via @kbd{C-c} or by
typing @kbd{q} at a pagination prompt) is translated to a Python
@code{KeyboardInterrupt} exception, and other @value{GDBN} exceptions
-- calls to @code{error} in the C code -- are translated to Python
@code{RuntimeError}s.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-26 17:40 ` Eli Zaretskii
@ 2008-07-26 18:00 ` Tom Tromey
2008-07-26 18:29 ` Eli Zaretskii
0 siblings, 1 reply; 147+ messages in thread
From: Tom Tromey @ 2008-07-26 18:00 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: bauerman, gdb-patches
>>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:
>> I don't really want to merge them. I don't think it provides much
>> benefit to the reader of the manual.
Eli> The benefit is more structure. Both Python support and the old way of
Eli> defining user-defined commands is about the same thing: extending GDB.
That is one way to look at it. But really they don't have that much
in common.
The "define" command creates new user-defined commands, which are
sequences of gdb commands.
The python command accesses the python interpreter. It is not really
useful unless you already know python and want to use gdb's python
api. So, it has a much narrower audience.
>> It might make sense to document the "python" command alongside
>> "define" or what have you -- but I think only barely, since the
>> "python" command is kinda pointless without the rest of the API.
Eli> I don't see why this invalidates the merge. Please explain.
Well, there are two cases.
In one case, we put the python command and all the python API
documentation together in the "Commands" section. This means that if
you read the manual straight through, you will get a lot of
information about the CLI, then a very long diversion into the details
of the Python API, and then more information about the CLI.
In the other case, we can document the python command in one place,
but then the API elsewhere. However, this will also be a pain to
read. The python command is not useful unless you can also read about
the API. So, readers will have to flip between two parts of the
manual.
Eli> Having too many chapters is not a good sign.
This does not seem like a strong argument given that there are already
27 chapters.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-26 17:04 ` Tom Tromey
2008-07-26 17:35 ` Daniel Jacobowitz
@ 2008-07-26 18:11 ` Eli Zaretskii
2008-07-26 18:30 ` Daniel Jacobowitz
2008-08-05 4:19 ` Thiago Jung Bauermann
1 sibling, 2 replies; 147+ messages in thread
From: Eli Zaretskii @ 2008-07-26 18:11 UTC (permalink / raw)
To: tromey; +Cc: bauerman, drow, gdb-patches
> Cc: Thiago Jung Bauermann <bauerman@br.ibm.com>, drow@false.org,
> gdb-patches@sourceware.org
> From: Tom Tromey <tromey@redhat.com>
> Date: Sat, 26 Jul 2008 11:04:24 -0600
>
> >> +python [code]
> >> + Invoke python code.
>
> Eli> Please say a few word about the form of [code]. Is it a string? if
> Eli> so, should it be in quotes?
>
> How about:
>
> python [CODE]
> Invoke CODE by passing it to the Python interpreter.
>
> I can be as specific as you like here. I thought, though, that NEWS
> was just a teaser and that users should read the manual for details.
If that's the best we can do, let's at least name the relevant section
of the manual.
> >> + else if (p1 - p == 6 && !strncmp (p, "python", 6))
>
> Eli> Can we avoid literal constants such as 6 here, and instead make it
> Eli> dependent on the string "python"?
>
> Here I just followed the existing code in that file.
>
> >> else if (p1 - p == 10 && !strncmp (p, "loop_break", 10))
>
> Eli> Ditto.
>
> This is existing code. Please read that file, you'll see there are a
> dozen cases like this. I don't mind fixing this, but I think it is
> generally preferable to do cleanups in a separate patch. If you
> disagree, let me know and I will go ahead and mash them together.
I don't mind to fix this as a separate patch. It's up to you. I just
want it fixed.
> >> +* Python:: Scripting @value{GDBN} using Python.
>
> Eli> I think this should not be a separate chapter, but rather a section of
> Eli> the "Canned Sequences of Commands" chapter.
>
> This is a drawback of the one-patch-at-a-time submission method.
> Later patches, which we have not yet submitted, greatly expand this
> chapter. In particular we add a bunch of subsections describing the
> Python API.
As I wrote elsewhere in this thread, I don't see why this should
prevent us from having both CLI and Python scripting in the same
chapter.
> >> +@value{GDBN} exposes a number of features to Python scripts.
>
> Eli> This should end with a colon, and the list of the features should be a
> Eli> @table.
>
> I guess those aren't really features, they are more like generic
> things that the python-in-gdb programmer ought to know.
>
> So, I don't think a table makes sense, but I suppose the current text
> is also misleading. What do you suggest?
My problem is with the form, not with the content. By default, each
paragraph in a Texinfo document starts with an indentation, like in a
book. @table prevents that, producing paragraphs whose all lines line
up. This section presents a list of features; having each feature's
description begin with an indented line is simply ugly.
You seem to think that @table produces a table, but it doesn't.
> >> +In particular, a @value{GDBN} @code{QUIT} exception is translated to a
> >> +Python @code{KeyboardInterrupt} exception, and other @value{GDBN}
> >> +exceptions are translated to Python @code{RuntimeError}s.
>
> Eli> I think this is nowhere nearly as clear as it should be. Even to a C
> Eli> hacker, "QUIT exception" is not sufficiently self-explanatory. Do you
> Eli> mean SIGQUIT? then please say so.
>
> Daniel or some other gdb maintainer will have to suggest something.
> I don't know what else to call this. exceptions.h refers to "QUIT
> event", but also the enum value is "RETURN_QUIT"... maybe the latter?
Now I'm totally confused. If you are saying that we are now exposing
to user-defined commands some new kind of event, we should at least
document that event. Just calling it "QUIT exception" doesn't fit
that bill, IMO.
> Eli> Will Python RuntimeError clear enough to casual GDB users who
> Eli> want to use Python scripting, but are not experienced Python
> Eli> programmers? I'm not sure.
>
> People expecting to do this will have to read a Python manual.
> There is no way around that.
Let's at least mention the name of the section in the Python manual
where the details can be found.
> Eli> And what about stating explicitly
> Eli> which exceptions map to which Python RuntimeError.
>
> It does say -- all the rest of them.
> AFAICT gdb really only has quit exceptions and "the other kind".
>
> Eli> Finally, "GDB exception" is itself a term that is not defined anywhere
> Eli> in the manual. Strictly speaking, GDB being a C program does not have
> Eli> any exception at all.
>
> I guess that is true in some pedantic way, if you assume that only
> languages that explicitly have a "throw" statement can have
> exceptions. But, in practice it is manifestly untrue for gdb. gdb
> uses exceptions everywhere, and discusses them in just those terms.
We are talking about the user manual. Readers of the user manual were
up until now ignorant about the internal structure of GDB top-level
code, including how it throws to top level. If we want users of
Python scripting to take advantage of the mapping between the GDB C
code and Python, we cannot side-step the need to document those GDB
exceptions in some way that is understandable by readers of the user
manual. Otherwise, only GDB hackers such as you and me will be able
to ever write powerful user-defined commands using Python.
> >> +At startup, @value{GDBN} overrides Python's @code{sys.stdout} and
> >> +@code{sys.stderr} to print using @value{GDBN}'s output-paging streams.
> >> +A Python program which outputs to one of these streams may have its
> >> +output interrupted by the user (@pxref{Screen Size}). In this
> >> +situation, a Python @code{KeyboardInterrupt} exception is thrown.
>
> Eli> Is there something here that whoever writes the Python program should
> Eli> know to behave correctly? Does she need, for example, catch
> Eli> KeyboardInterrupt and do something in the handler? If so, we should
> Eli> state here what's needed.
>
> Yes, Python programmers might want to know about this in some
> circumstances. It just depends on what they are trying to accomplish.
>
> I don't agree that we need to explain this. I don't think we should
> try to explain Python programming in general. Instead, I think we
> should explain the Python API and refer users to already existing
> Python manuals.
The Python manual is a large document. Saying something about what
needs to be done on the Python side will go a long way towards helping
the reader find the relevant details in the Python manual quickly and
efficiently. You don't need to describe everything, just hint on it
and use a few relevant keywords.
> >> +@value{GDBN} introduces a new Python module, named @code{gdb}. All
> >> +methods and classes added by @value{GDBN} are placed in this module.
>
> Eli> OK, but what does this mean for whoever writes Python extensions for
> Eli> GDB? While at that, how about explaining why a command FOO is indexed
> Eli> as gdb.FOO?
>
> I thought it would be nice to index them both ways. Do you disagree?
>
> Python programmers know what the module stuff means. We don't have to
> explain that.
Sorry, I disagree.
> >> +Find the value of a @value{GDBN} setting.
>
> Eli> "find" or "display"? If the former, why the name is "show"?
>
> It mimics the CLI command name.
??? CLI commands that begin with "show" actually display the values.
This one does not, right?
> >> + @var{variable} is a string
> >> +naming the setting to look up; @var{variable} may contain spaces if the
> >> +variable has a multi-part name. For example, @samp{print object} is a
> >> +valid variable name.
>
> Eli> So what signals the end of the name? Also, what exactly is a
> Eli> "multi-part name"?
>
> The point of this text is to say that you can invoke:
>
> gdb.show("print object")
>
> and get a sensible answer.
Then the text should mention the parens and the quotes. Specifically,
this:
> >> +@defun show @var{variable}
should have been written like this:
+@deftypefun show ("@var{variable}")
> >> +Print a string to @value{GDBN}'s paginated standard output stream.
> >> +Ordinarily your program should not call this function directly; simply
> >> +print to @code{sys.stdout} as usual.
>
> Eli> So why is this command available, and why document it?
>
> Completeness. It is visible in the module.
Doesn't sound like a good enough reason to me.
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-26 18:00 ` Tom Tromey
@ 2008-07-26 18:29 ` Eli Zaretskii
2008-07-26 18:45 ` Tom Tromey
0 siblings, 1 reply; 147+ messages in thread
From: Eli Zaretskii @ 2008-07-26 18:29 UTC (permalink / raw)
To: Tom Tromey; +Cc: bauerman, gdb-patches
> Cc: bauerman@br.ibm.com, gdb-patches@sourceware.org
> From: Tom Tromey <tromey@redhat.com>
> Date: Sat, 26 Jul 2008 12:00:24 -0600
>
> >>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:
>
> >> I don't really want to merge them. I don't think it provides much
> >> benefit to the reader of the manual.
>
> Eli> The benefit is more structure. Both Python support and the old way of
> Eli> defining user-defined commands is about the same thing: extending GDB.
>
> That is one way to look at it. But really they don't have that much
> in common.
>
> The "define" command creates new user-defined commands, which are
> sequences of gdb commands.
>
> The python command accesses the python interpreter. It is not really
> useful unless you already know python and want to use gdb's python
> api. So, it has a much narrower audience.
But the goal is the same: create user-defined commands, isn't it? Or
is there something else?
> >> It might make sense to document the "python" command alongside
> >> "define" or what have you -- but I think only barely, since the
> >> "python" command is kinda pointless without the rest of the API.
>
> Eli> I don't see why this invalidates the merge. Please explain.
>
> Well, there are two cases.
>
> In one case, we put the python command and all the python API
> documentation together in the "Commands" section. This means that if
> you read the manual straight through, you will get a lot of
> information about the CLI, then a very long diversion into the details
> of the Python API, and then more information about the CLI.
>
> In the other case, we can document the python command in one place,
> but then the API elsewhere. However, this will also be a pain to
> read. The python command is not useful unless you can also read about
> the API. So, readers will have to flip between two parts of the
> manual.
Sounds like we agree that API should be together with the "python"
command.
> Eli> Having too many chapters is not a good sign.
>
> This does not seem like a strong argument given that there are already
> 27 chapters.
It would have been 47 if I hadn't resisted the trend.
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-26 18:11 ` Eli Zaretskii
@ 2008-07-26 18:30 ` Daniel Jacobowitz
2008-07-26 19:26 ` Eli Zaretskii
2008-08-01 20:04 ` Tom Tromey
2008-08-05 4:19 ` Thiago Jung Bauermann
1 sibling, 2 replies; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-07-26 18:30 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: tromey, bauerman, gdb-patches
On Sat, Jul 26, 2008 at 09:10:18PM +0300, Eli Zaretskii wrote:
> > >> +@value{GDBN} introduces a new Python module, named @code{gdb}. All
> > >> +methods and classes added by @value{GDBN} are placed in this module.
> >
> > Eli> OK, but what does this mean for whoever writes Python extensions for
> > Eli> GDB? While at that, how about explaining why a command FOO is indexed
> > Eli> as gdb.FOO?
> >
> > I thought it would be nice to index them both ways. Do you disagree?
> >
> > Python programmers know what the module stuff means. We don't have to
> > explain that.
>
> Sorry, I disagree.
What would you like explained? I'm a bit confused - as a Python
programmer, albeit novice, what Tom wrote makes sense to me.
> > >> +Find the value of a @value{GDBN} setting.
> >
> > Eli> "find" or "display"? If the former, why the name is "show"?
> >
> > It mimics the CLI command name.
>
> ??? CLI commands that begin with "show" actually display the values.
> This one does not, right?
I suggest "get" parallel to "set", then.
> > >> +Print a string to @value{GDBN}'s paginated standard output stream.
> > >> +Ordinarily your program should not call this function directly; simply
> > >> +print to @code{sys.stdout} as usual.
> >
> > Eli> So why is this command available, and why document it?
> >
> > Completeness. It is visible in the module.
>
> Doesn't sound like a good enough reason to me.
Maybe we should move it to a new module gdb._internal then. Tom, what
do you think?
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-26 18:29 ` Eli Zaretskii
@ 2008-07-26 18:45 ` Tom Tromey
2008-07-26 19:34 ` Eli Zaretskii
0 siblings, 1 reply; 147+ messages in thread
From: Tom Tromey @ 2008-07-26 18:45 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: bauerman, gdb-patches
>>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:
>> The "define" command creates new user-defined commands, which are
>> sequences of gdb commands.
>>
>> The python command accesses the python interpreter. It is not really
>> useful unless you already know python and want to use gdb's python
>> api. So, it has a much narrower audience.
Eli> But the goal is the same: create user-defined commands, isn't it? Or
Eli> is there something else?
There's a distinction to be aware of here ... what we have and what is
planned are not identical. So, for instance, with the current patch
under consideration, you really cannot do much at all with python.
Future (existing ones in this series) patches add a lot of different
features. Adding new commands is one of them. However, there is a
lot more. For instance, you will be able to write new "gdb-side"
functions in Python; this is related to exprsseion evaluation, not new
commands. And, you will be able to script gdb in any number of ways.
Some of the immediate things will not be visible as user commands.
For example, pretty-printing will not be exposed that way. It will be
part of the "print" command (or just automatic in the MI case).
However, library authors and the like will be able to write new
pretty-printers; for this they will need to read gdb's python api
documentation.
Long term I want to make it possible to fully script gdb. In
particular I want to be able to start a python script with
"#!/usr/bin/gdb" and have it completely control execution.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-26 17:42 ` Tom Tromey
@ 2008-07-26 19:18 ` Eli Zaretskii
2008-08-04 2:52 ` Thiago Jung Bauermann
0 siblings, 1 reply; 147+ messages in thread
From: Eli Zaretskii @ 2008-07-26 19:18 UTC (permalink / raw)
To: tromey; +Cc: gdb-patches
> From: Tom Tromey <tromey@redhat.com>
> Date: Sat, 26 Jul 2008 11:42:12 -0600
>
> >>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
>
> Daniel> No need to talk about the internal meaning for that part - we can just
> Daniel> talk about interrupting operations with Control-C. I'm not sure how
> Daniel> to explain "other exceptions"; just "other error conditions"?
>
> How about this?
>
> When executing the @code{python} command, uncaught Python exceptions
> are translated to calls to @value{GDBN}'s @code{error} function.
> Conversely, @value{GDBN} exceptions are converted to Python
> exceptions. In particular, a user interrupt (via @kbd{C-c} or by
> typing @kbd{q} at a pagination prompt) is translated to a Python
> @code{KeyboardInterrupt} exception, and other @value{GDBN} exceptions
> -- calls to @code{error} in the C code -- are translated to Python
> @code{RuntimeError}s.
That's a step in the right direction, but only one step; more is
needed to make this palatable to the manual readers who are not GDB
hackers. We cannot mention the `error' function, for example, since
we don't want the reader to read GDB sources to understand what that
means.
Here's something that should explain what I have in mind (details
might be factually incorrect):
When executing the @code{python} command, Python exceptions uncaught
within the Python code are translated to calls to @value{GDBN}
error-reporting mechanism, which terminates the currently executing
command and prints an error message containing the Python exception
name, the associated value, and the Python call stack backtrace at
the point where the exception was raised. Example:
@smallexample
...
@end smallexample
@value{GDBN} errors that happen in GDB commands invoked by Python
code are converted to Python @code{RuntimeError} exceptions. User
interrupts (via @kbd{C-c} or by typing @kbd{q} at a pagination
prompt) is translated to a Python @code{KeyboardInterrupt}
exception. If you catch these exceptions in your Python code, your
exception handler will see @code{RuntimeError} or
@code{KeyboardInterrupt} as the exception type, @code{None} as its
value, and @value{GDBN} backtrace as the traceback.
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-26 17:35 ` Daniel Jacobowitz
2008-07-26 17:42 ` Tom Tromey
@ 2008-07-26 19:20 ` Eli Zaretskii
1 sibling, 0 replies; 147+ messages in thread
From: Eli Zaretskii @ 2008-07-26 19:20 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: tromey, bauerman, gdb-patches
> Date: Sat, 26 Jul 2008 13:35:08 -0400
> From: Daniel Jacobowitz <drow@false.org>
> Cc: Eli Zaretskii <eliz@gnu.org>,
> Thiago Jung Bauermann <bauerman@br.ibm.com>,
> gdb-patches@sourceware.org
>
> On Sat, Jul 26, 2008 at 11:04:24AM -0600, Tom Tromey wrote:
> > >> +In particular, a @value{GDBN} @code{QUIT} exception is translated to a
> > >> +Python @code{KeyboardInterrupt} exception, and other @value{GDBN}
> > >> +exceptions are translated to Python @code{RuntimeError}s.
> >
> > Eli> I think this is nowhere nearly as clear as it should be. Even to a C
> > Eli> hacker, "QUIT exception" is not sufficiently self-explanatory. Do you
> > Eli> mean SIGQUIT? then please say so.
> >
> > Daniel or some other gdb maintainer will have to suggest something.
> > I don't know what else to call this. exceptions.h refers to "QUIT
> > event", but also the enum value is "RETURN_QUIT"... maybe the latter?
>
> For clarification, Tom's talking about "QUIT;" in the GDB sources.
Yes, I know. But we cannot mention symbols from GDB sources in the
user manual. The readers of the manual are not supposed to search the
sources to understand what these symbols mean.
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-26 17:26 ` Tom Tromey
@ 2008-07-26 19:21 ` Eli Zaretskii
0 siblings, 0 replies; 147+ messages in thread
From: Eli Zaretskii @ 2008-07-26 19:21 UTC (permalink / raw)
To: Tom Tromey; +Cc: drow, bauerman, gdb-patches
> Cc: Daniel Jacobowitz <drow@false.org>, bauerman@br.ibm.com,
> gdb-patches@sourceware.org
> From: Tom Tromey <tromey@redhat.com>
> Date: Sat, 26 Jul 2008 11:25:48 -0600
>
> >>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:
>
> Eli> So are you saying that adding Python will enable features that are
> Eli> beyond user-defined commands (a.k.a. scripting)? If so, what are
> Eli> those features?
>
> The python programmer will be able to access nearly everything. We
> already have (on the branch) representations for threads, breakpoints,
> commands, internal functions (a new feature), blocks, frames, symbols,
> symbol tables, and values.
Yes, but is there some _purpose_ of accessing these internals, except
for writing user-defined commands?
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-26 18:30 ` Daniel Jacobowitz
@ 2008-07-26 19:26 ` Eli Zaretskii
2008-08-01 20:04 ` Tom Tromey
1 sibling, 0 replies; 147+ messages in thread
From: Eli Zaretskii @ 2008-07-26 19:26 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: tromey, bauerman, gdb-patches
> Date: Sat, 26 Jul 2008 14:29:57 -0400
> From: Daniel Jacobowitz <drow@false.org>
> Cc: tromey@redhat.com, bauerman@br.ibm.com, gdb-patches@sourceware.org
>
> On Sat, Jul 26, 2008 at 09:10:18PM +0300, Eli Zaretskii wrote:
> > > >> +@value{GDBN} introduces a new Python module, named @code{gdb}. All
> > > >> +methods and classes added by @value{GDBN} are placed in this module.
> > >
> > > Eli> OK, but what does this mean for whoever writes Python extensions for
> > > Eli> GDB? While at that, how about explaining why a command FOO is indexed
> > > Eli> as gdb.FOO?
> > >
> > > I thought it would be nice to index them both ways. Do you disagree?
> > >
> > > Python programmers know what the module stuff means. We don't have to
> > > explain that.
> >
> > Sorry, I disagree.
>
> What would you like explained?
Why it is important to the manual reader to know that there's a module
called `gdb', and that all methods and classes added by GDB are placed
in that module. Suppose I didn't know that--what would I be missing
as result, and what code would I get wrong?
> > > >> +Find the value of a @value{GDBN} setting.
> > >
> > > Eli> "find" or "display"? If the former, why the name is "show"?
> > >
> > > It mimics the CLI command name.
> >
> > ??? CLI commands that begin with "show" actually display the values.
> > This one does not, right?
>
> I suggest "get" parallel to "set", then.
Fine with me.
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-26 18:45 ` Tom Tromey
@ 2008-07-26 19:34 ` Eli Zaretskii
2008-07-30 14:59 ` Thiago Jung Bauermann
0 siblings, 1 reply; 147+ messages in thread
From: Eli Zaretskii @ 2008-07-26 19:34 UTC (permalink / raw)
To: Tom Tromey; +Cc: bauerman, gdb-patches
> Cc: bauerman@br.ibm.com, gdb-patches@sourceware.org
> From: Tom Tromey <tromey@redhat.com>
> Date: Sat, 26 Jul 2008 12:44:33 -0600
>
> >>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:
>
> >> The "define" command creates new user-defined commands, which are
> >> sequences of gdb commands.
> >>
> >> The python command accesses the python interpreter. It is not really
> >> useful unless you already know python and want to use gdb's python
> >> api. So, it has a much narrower audience.
>
> Eli> But the goal is the same: create user-defined commands, isn't it? Or
> Eli> is there something else?
>
> There's a distinction to be aware of here ... what we have and what is
> planned are not identical.
I was talking about what was planned.
> For instance, you will be able to write new "gdb-side" functions in
> Python; this is related to exprsseion evaluation, not new commands.
Sorry, I don't understand. Can you give an example, please?
> And, you will be able to script gdb in any number of ways.
What do you mean by "script gdb"?
> Some of the immediate things will not be visible as user commands.
> For example, pretty-printing will not be exposed that way. It will be
> part of the "print" command (or just automatic in the MI case).
If it's automatic, it's part of GDB and there's no need to mention it
in the manual. For non-MI cases, are you talking about some kind of
hooks into which user-defined Python code can be plugged to modify how
certain objects are printed?
> However, library authors and the like will be able to write new
> pretty-printers
How will those pretty-printers be invoked by GDB?
> Long term I want to make it possible to fully script gdb. In
> particular I want to be able to start a python script with
> "#!/usr/bin/gdb" and have it completely control execution.
For what purpose?
Bottom line, unless I'm again missing something, we are talking about
extending GDB. CLI scripting is also a way of extending GDB, albeit
very limited one. So I still think having these two in the same
chapter is OK.
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 2/9] export values mechanism to Python
2008-07-26 17:41 ` Daniel Jacobowitz
@ 2008-07-30 3:01 ` Tom Tromey
2008-07-30 14:26 ` Thiago Jung Bauermann
0 siblings, 1 reply; 147+ messages in thread
From: Tom Tromey @ 2008-07-30 3:01 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
>>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
Daniel> Oh, I think it does - I'm just not sure how many of them will make
Daniel> sense as instance methods rather than less object-oriented functions.
I think we don't know what we might want to do in the future, since we
have not finished attaching Python to gdb. It is easy to add
"invisible"-style treatment of inferior field names later -- but it
would be much harder to remove them.
So, currently I lean toward conservatism on this issue.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFC][patch 2/9] export values mechanism to Python
2008-07-30 3:01 ` Tom Tromey
@ 2008-07-30 14:26 ` Thiago Jung Bauermann
0 siblings, 0 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-07-30 14:26 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
On Tue, 2008-07-29 at 21:00 -0600, Tom Tromey wrote:
> >>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
>
> Daniel> Oh, I think it does - I'm just not sure how many of them will make
> Daniel> sense as instance methods rather than less object-oriented functions.
>
> I think we don't know what we might want to do in the future, since we
> have not finished attaching Python to gdb. It is easy to add
> "invisible"-style treatment of inferior field names later -- but it
> would be much harder to remove them.
>
> So, currently I lean toward conservatism on this issue.
Makes sense to me. We can decide after we have some of the Python
functionality committed (including this values patch), and hopefuly with
some people already using it to give some feedback of what they
want/expect.
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-26 19:34 ` Eli Zaretskii
@ 2008-07-30 14:59 ` Thiago Jung Bauermann
2008-07-30 17:57 ` Eli Zaretskii
0 siblings, 1 reply; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-07-30 14:59 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: Tom Tromey, gdb-patches
On Sat, 2008-07-26 at 22:34 +0300, Eli Zaretskii wrote:
> Bottom line, unless I'm again missing something, we are talking about
> extending GDB. CLI scripting is also a way of extending GDB, albeit
> very limited one. So I still think having these two in the same
> chapter is OK.
It seems to me that the confusion comes from the fact that Python
scripting support can be viewed by two angles: a much more powerful
version of the current GDB scripting capability, and a way to develop
new features and functionality (even eligible to be shipped with GDB
itself) without having to mess around with GDB internals, by doing them
completely in Python.
In the first sense, it makes sense to put the Python-related
documentation in the "Canned Sequence of Commands" chapter. In the
other, it doesn't because it's something different. And the audience of
each of those is different.
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-30 14:59 ` Thiago Jung Bauermann
@ 2008-07-30 17:57 ` Eli Zaretskii
2008-08-04 4:44 ` Thiago Jung Bauermann
0 siblings, 1 reply; 147+ messages in thread
From: Eli Zaretskii @ 2008-07-30 17:57 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: tromey, gdb-patches
> From: Thiago Jung Bauermann <bauerman@br.ibm.com>
> Cc: Tom Tromey <tromey@redhat.com>, gdb-patches@sourceware.org
> Date: Wed, 30 Jul 2008 11:58:56 -0300
>
> On Sat, 2008-07-26 at 22:34 +0300, Eli Zaretskii wrote:
> > Bottom line, unless I'm again missing something, we are talking about
> > extending GDB. CLI scripting is also a way of extending GDB, albeit
> > very limited one. So I still think having these two in the same
> > chapter is OK.
>
> It seems to me that the confusion comes from the fact that Python
> scripting support can be viewed by two angles: a much more powerful
> version of the current GDB scripting capability, and a way to develop
> new features and functionality (even eligible to be shipped with GDB
> itself) without having to mess around with GDB internals, by doing them
> completely in Python.
>
> In the first sense, it makes sense to put the Python-related
> documentation in the "Canned Sequence of Commands" chapter. In the
> other, it doesn't because it's something different. And the audience of
> each of those is different.
Sorry, I'm unconvinced. Both features belong to a broader category of
means of extending GDB.
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-26 18:30 ` Daniel Jacobowitz
2008-07-26 19:26 ` Eli Zaretskii
@ 2008-08-01 20:04 ` Tom Tromey
2008-08-02 17:38 ` Daniel Jacobowitz
1 sibling, 1 reply; 147+ messages in thread
From: Tom Tromey @ 2008-08-01 20:04 UTC (permalink / raw)
To: gdb-patches
>>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
[ gdb.show ]
Daniel> I suggest "get" parallel to "set", then.
I've been thinking about this, and on further reflection I think both
"show" and "get" are too generic. How about "get_parameter"? I
picked this because the manual refers to these entities as parameters
at one point:
@kindex info set
To display all the settable parameters and their current
values, you can use @code{show} with no arguments; you may also use
[ flush and write ]
Daniel> Maybe we should move it to a new module gdb._internal then.
Daniel> Tom, what do you think?
I'm ambivalent about it. I don't see much harm in exposing and
documenting these primitives. If it is what you want, though, I will
do it. I suppose the wrapper class ought to go in _internal as well.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-08-01 20:04 ` Tom Tromey
@ 2008-08-02 17:38 ` Daniel Jacobowitz
2008-08-02 17:50 ` Tom Tromey
2008-08-02 19:00 ` Eli Zaretskii
0 siblings, 2 replies; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-08-02 17:38 UTC (permalink / raw)
To: Eli Zaretskii, Tom Tromey; +Cc: bauerman, gdb-patches
On Sat, Jul 26, 2008 at 10:24:49PM +0300, Eli Zaretskii wrote:
> > What would you like explained?
>
> Why it is important to the manual reader to know that there's a module
> called `gdb', and that all methods and classes added by GDB are placed
> in that module. Suppose I didn't know that--what would I be missing
> as result, and what code would I get wrong?
You would not know that you had to 'import gdb' in any new modules you
wrote, that's all. This is obvious to a Python programmer from the
existence of the module.
Tom, the gdb module is automatically imported in executed Python
fragments, right? That may be worth an explicit mention.
On Fri, Aug 01, 2008 at 02:04:19PM -0600, Tom Tromey wrote:
> >>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
>
> [ gdb.show ]
> Daniel> I suggest "get" parallel to "set", then.
>
> I've been thinking about this, and on further reflection I think both
> "show" and "get" are too generic. How about "get_parameter"? I
> picked this because the manual refers to these entities as parameters
> at one point:
>
> @kindex info set
> To display all the settable parameters and their current
> values, you can use @code{show} with no arguments; you may also use
This sounds good.
> [ flush and write ]
> Daniel> Maybe we should move it to a new module gdb._internal then.
> Daniel> Tom, what do you think?
>
> I'm ambivalent about it. I don't see much harm in exposing and
> documenting these primitives. If it is what you want, though, I will
> do it. I suppose the wrapper class ought to go in _internal as well.
I'm happy to leave them where they are and document them.
How about replacing this:
> +Print a string to @value{GDBN}'s paginated standard output stream.
> +Ordinarily your program should not call this function directly; simply
> +print to @code{sys.stdout} as usual.
with:
Print a string to @value{GDBN}'s paginated standard output stream.
Writing to @code{sys.stdout} will automatically call this method.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-21 15:29 ` [RFA][patch 1/9] Yet another respin of the patch with " Thiago Jung Bauermann
2008-07-21 16:47 ` Thiago Jung Bauermann
2008-07-26 13:07 ` Eli Zaretskii
@ 2008-08-02 17:41 ` Daniel Jacobowitz
2008-08-02 19:02 ` Eli Zaretskii
2 siblings, 1 reply; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-08-02 17:41 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: Tom Tromey, gdb-patches ml, Eli Zaretskii
On Mon, Jul 21, 2008 at 12:26:09PM -0300, Thiago Jung Bauermann wrote:
> Hi people,
>
> This is today's version of the patch. :-)
> It addresses the latest review comments, and is good to go AFAIK.
This patch is OK once the documentation is approved.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-08-02 17:38 ` Daniel Jacobowitz
@ 2008-08-02 17:50 ` Tom Tromey
2008-08-02 19:00 ` Eli Zaretskii
1 sibling, 0 replies; 147+ messages in thread
From: Tom Tromey @ 2008-08-02 17:50 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: bauerman, gdb-patches
>>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes:
Daniel> Tom, the gdb module is automatically imported in executed Python
Daniel> fragments, right? That may be worth an explicit mention.
Yes. Fixed.
>> How about "get_parameter"?
Daniel> This sounds good.
Done.
Daniel> Print a string to @value{GDBN}'s paginated standard output stream.
Daniel> Writing to @code{sys.stdout} will automatically call this method.
Done.
thanks,
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-08-02 17:38 ` Daniel Jacobowitz
2008-08-02 17:50 ` Tom Tromey
@ 2008-08-02 19:00 ` Eli Zaretskii
1 sibling, 0 replies; 147+ messages in thread
From: Eli Zaretskii @ 2008-08-02 19:00 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: tromey, bauerman, gdb-patches
> Date: Sat, 2 Aug 2008 13:37:44 -0400
> From: Daniel Jacobowitz <drow@false.org>
> Cc: bauerman@br.ibm.com, gdb-patches@sourceware.org
>
> On Sat, Jul 26, 2008 at 10:24:49PM +0300, Eli Zaretskii wrote:
> > > What would you like explained?
> >
> > Why it is important to the manual reader to know that there's a module
> > called `gdb', and that all methods and classes added by GDB are placed
> > in that module. Suppose I didn't know that--what would I be missing
> > as result, and what code would I get wrong?
>
> You would not know that you had to 'import gdb' in any new modules you
> wrote, that's all. This is obvious to a Python programmer from the
> existence of the module.
Might as well say explicitly that new modules need to 'import gdb'.
Most Python programmers will still understand that the methods and
classes added by GDB are placed in the `gdb' module, but the
instruction to 'import gdb' is IMO more friendly to those who won't.
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-08-02 17:41 ` Daniel Jacobowitz
@ 2008-08-02 19:02 ` Eli Zaretskii
2008-08-02 19:07 ` Daniel Jacobowitz
0 siblings, 1 reply; 147+ messages in thread
From: Eli Zaretskii @ 2008-08-02 19:02 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: bauerman, tromey, gdb-patches
> Date: Sat, 2 Aug 2008 13:41:14 -0400
> From: Daniel Jacobowitz <drow@false.org>
> Cc: Tom Tromey <tromey@redhat.com>,
> gdb-patches ml <gdb-patches@sourceware.org>,
> Eli Zaretskii <eliz@gnu.org>
>
> On Mon, Jul 21, 2008 at 12:26:09PM -0300, Thiago Jung Bauermann wrote:
> > Hi people,
> >
> > This is today's version of the patch. :-)
> > It addresses the latest review comments, and is good to go AFAIK.
>
> This patch is OK once the documentation is approved.
I hope no one is waiting for me to approve something. Unless I missed
some messages, the last thing I remember is that I reviewed the
documentation and had several comments on it. If I did miss some
messages, please point me to them.
Thanks.
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-08-02 19:02 ` Eli Zaretskii
@ 2008-08-02 19:07 ` Daniel Jacobowitz
0 siblings, 0 replies; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-08-02 19:07 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: bauerman, tromey, gdb-patches
On Sat, Aug 02, 2008 at 10:01:50PM +0300, Eli Zaretskii wrote:
> I hope no one is waiting for me to approve something. Unless I missed
> some messages, the last thing I remember is that I reviewed the
> documentation and had several comments on it. If I did miss some
> messages, please point me to them.
No, you're correct. I just spoke to Tom; they're planning to make a
few more fixes in response to your comments and repost.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-26 19:18 ` Eli Zaretskii
@ 2008-08-04 2:52 ` Thiago Jung Bauermann
2008-08-04 3:22 ` Eli Zaretskii
0 siblings, 1 reply; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-08-04 2:52 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: tromey, gdb-patches
On Sat, 2008-07-26 at 22:17 +0300, Eli Zaretskii wrote:
> Here's something that should explain what I have in mind (details
> might be factually incorrect):
Thanks for this text. I think it can be mostly used, except...
>
> When executing the @code{python} command, Python exceptions uncaught
> within the Python code are translated to calls to @value{GDBN}
> error-reporting mechanism, which terminates the currently executing
> command and prints an error message containing the Python exception
> name, the associated value, and the Python call stack backtrace at
> the point where the exception was raised. Example:
... it is not necessarily true that GDB will terminate the currently
executing command when the Python exception is converted to a GDB
exception. If the Python script is extending some GDB subsystem (one of
our goals), that subsystem can catch the exception and deal with it in
another way. So for this part I suggest:
... are translated to calls to @value{GDBN} error-handling mechanism,
which depending on the context of the Python script can either deal
with the error in a subsystem-specific way, or terminate the currently
executing command ...
What do you think?
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-08-04 2:52 ` Thiago Jung Bauermann
@ 2008-08-04 3:22 ` Eli Zaretskii
2008-08-04 12:15 ` Daniel Jacobowitz
0 siblings, 1 reply; 147+ messages in thread
From: Eli Zaretskii @ 2008-08-04 3:22 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: tromey, gdb-patches
> From: Thiago Jung Bauermann <bauerman@br.ibm.com>
> Cc: tromey@redhat.com, gdb-patches@sources.redhat.com
> Date: Sun, 03 Aug 2008 23:50:43 -0300
>
> > When executing the @code{python} command, Python exceptions uncaught
> > within the Python code are translated to calls to @value{GDBN}
> > error-reporting mechanism, which terminates the currently executing
> > command and prints an error message containing the Python exception
> > name, the associated value, and the Python call stack backtrace at
> > the point where the exception was raised. Example:
>
> ... it is not necessarily true that GDB will terminate the currently
> executing command when the Python exception is converted to a GDB
> exception. If the Python script is extending some GDB subsystem (one of
> our goals), that subsystem can catch the exception and deal with it in
> another way. So for this part I suggest:
>
> ... are translated to calls to @value{GDBN} error-handling mechanism,
> which depending on the context of the Python script can either deal
> with the error in a subsystem-specific way, or terminate the currently
> executing command ...
>
> What do you think?
I think what I suggested is still valid: no matter how the exception
is caught, it will still terminate the current command, won't it?
And, btw, do we actually have examples of such non-default exception
handling in GDB?
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-26 13:07 ` Eli Zaretskii
2008-07-26 13:43 ` Daniel Jacobowitz
2008-07-26 17:04 ` Tom Tromey
@ 2008-08-04 4:44 ` Thiago Jung Bauermann
2008-08-04 19:22 ` Eli Zaretskii
2 siblings, 1 reply; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-08-04 4:44 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: drow, tromey, gdb-patches
On Sat, 2008-07-26 at 16:06 +0300, Eli Zaretskii wrote:
> > +Evaluate @var{command}, a string, as a @value{GDBN} CLI command.
> > +Exceptions are translated as noted above. If no error occurs, this
> > +function will return @code{None}.
>
> The last sentence begs a question: what happens if errors _do_ occur?
I suggest rewording this as:
Evaluate @var{command}, a string, as a @value{GDBN} CLI command.
If no error occurs, this function will return @code{None}. Otherwise,
GDB exceptions are translated as noted above.
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-30 17:57 ` Eli Zaretskii
@ 2008-08-04 4:44 ` Thiago Jung Bauermann
2008-08-04 19:18 ` Eli Zaretskii
0 siblings, 1 reply; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-08-04 4:44 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: tromey, gdb-patches
On Wed, 2008-07-30 at 20:56 +0300, Eli Zaretskii wrote:
> > From: Thiago Jung Bauermann <bauerman@br.ibm.com>
> > In the first sense, it makes sense to put the Python-related
> > documentation in the "Canned Sequence of Commands" chapter. In the
> > other, it doesn't because it's something different. And the audience of
> > each of those is different.
>
> Sorry, I'm unconvinced. Both features belong to a broader category of
> means of extending GDB.
In that case, my opinion is that the current "Canned Sequences of
Commands" chapter should be demoted to a section (and its sections would
then be demoted to subsubsections), and both this section and Python's
section should be under a chapter called "Extending GDB".
Rereading this thread, I think this is what Daniel suggested in the
first place.
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-08-04 3:22 ` Eli Zaretskii
@ 2008-08-04 12:15 ` Daniel Jacobowitz
2008-08-04 19:50 ` Eli Zaretskii
0 siblings, 1 reply; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-08-04 12:15 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: Thiago Jung Bauermann, tromey, gdb-patches
On Mon, Aug 04, 2008 at 06:20:47AM +0300, Eli Zaretskii wrote:
> I think what I suggested is still valid: no matter how the exception
> is caught, it will still terminate the current command, won't it?
> And, btw, do we actually have examples of such non-default exception
> handling in GDB?
About half the times that TRY_CATCH or catch_exception / catch_error
are used, we handle an exception in a more specific way. Some are for
cleanups, but many continue after e.g. a memory read error. The
current action is terminated, but the action may be just part of
a command.
For example, if we have a Python implementation of a shared library
list and the equivalent of current_sos throws an exception, that
should not abort a "continue" command.
For an example currently in GDB,
TRY_CATCH (e, RETURN_MASK_ALL)
{
bpstat_do_actions (&stop_bpstat);
}
The actions associated with a breakpoint may terminate themselves, but
not the surrounding command.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-08-04 4:44 ` Thiago Jung Bauermann
@ 2008-08-04 19:18 ` Eli Zaretskii
2008-08-05 3:42 ` Thiago Jung Bauermann
0 siblings, 1 reply; 147+ messages in thread
From: Eli Zaretskii @ 2008-08-04 19:18 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: tromey, gdb-patches
> From: Thiago Jung Bauermann <bauerman@br.ibm.com>
> Cc: tromey@redhat.com, gdb-patches@sourceware.org
> Date: Mon, 04 Aug 2008 01:41:53 -0300
>
> > Sorry, I'm unconvinced. Both features belong to a broader category of
> > means of extending GDB.
>
> In that case, my opinion is that the current "Canned Sequences of
> Commands" chapter should be demoted to a section (and its sections would
> then be demoted to subsubsections), and both this section and Python's
> section should be under a chapter called "Extending GDB".
Agreed.
> Rereading this thread, I think this is what Daniel suggested in the
> first place.
And I agreed:
>> Ok, in that case I have an alternative suggestion: how about renaming
>> the combined scripting chapter, and putting both Python scripting and
>> the existing information in the new chapter?
>
> I have no objections to renaming that chapter.
>
>> I don't think Python makes sense as a section of "Canned Sequences of
>> Commands", because Python scripts don't contain GDB commands.
>
> The chapter name doesn't say "GDB Commands", it says just "Commands".
> But let's not argue about that on which we agree ;-)
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-08-04 4:44 ` [RFA][patch 1/9] Yet another respin of the patch with initial Python support Thiago Jung Bauermann
@ 2008-08-04 19:22 ` Eli Zaretskii
2008-08-05 1:24 ` Thiago Jung Bauermann
0 siblings, 1 reply; 147+ messages in thread
From: Eli Zaretskii @ 2008-08-04 19:22 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: drow, tromey, gdb-patches
> From: Thiago Jung Bauermann <bauerman@br.ibm.com>
> Cc: drow@false.org, tromey@redhat.com, gdb-patches@sourceware.org
> Date: Mon, 04 Aug 2008 01:31:07 -0300
>
> On Sat, 2008-07-26 at 16:06 +0300, Eli Zaretskii wrote:
> > > +Evaluate @var{command}, a string, as a @value{GDBN} CLI command.
> > > +Exceptions are translated as noted above. If no error occurs, this
> > > +function will return @code{None}.
> >
> > The last sentence begs a question: what happens if errors _do_ occur?
>
> I suggest rewording this as:
>
> Evaluate @var{command}, a string, as a @value{GDBN} CLI command.
> If no error occurs, this function will return @code{None}. Otherwise,
> GDB exceptions are translated as noted above.
Oh, I didn't realize that error == exception here. In that case,
let's use the same term:
Evaluate @var{command}, a string, as a @value{GDBN} CLI command.
If a GDB exception happens while @var{command} runs, it is
translated as described above. If no exceptions occur, this
function returns @code{None}.
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-08-04 12:15 ` Daniel Jacobowitz
@ 2008-08-04 19:50 ` Eli Zaretskii
2008-08-05 2:08 ` Daniel Jacobowitz
0 siblings, 1 reply; 147+ messages in thread
From: Eli Zaretskii @ 2008-08-04 19:50 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: bauerman, tromey, gdb-patches
> Date: Mon, 4 Aug 2008 08:14:52 -0400
> From: Daniel Jacobowitz <drow@false.org>
> Cc: Thiago Jung Bauermann <bauerman@br.ibm.com>, tromey@redhat.com, gdb-patches@sources.redhat.com
>
> On Mon, Aug 04, 2008 at 06:20:47AM +0300, Eli Zaretskii wrote:
> > I think what I suggested is still valid: no matter how the exception
> > is caught, it will still terminate the current command, won't it?
> > And, btw, do we actually have examples of such non-default exception
> > handling in GDB?
>
> About half the times that TRY_CATCH or catch_exception / catch_error
> are used, we handle an exception in a more specific way. Some are for
> cleanups, but many continue after e.g. a memory read error. The
> current action is terminated, but the action may be just part of
> a command.
Okay, how about this, then:
When executing the @code{python} command, Python exceptions
uncaught within the Python code are translated to calls to
@value{GDBN} error-reporting mechanism. If the command that called
@code{python} does not handle the error, @value{GDBN} will
terminate it and print an error message containing the Python
exception name, the associated value, and the Python call stack
backtrace at the point where the exception was raised. Example:
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-08-04 19:22 ` Eli Zaretskii
@ 2008-08-05 1:24 ` Thiago Jung Bauermann
0 siblings, 0 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-08-05 1:24 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: drow, tromey, gdb-patches
On Mon, 2008-08-04 at 22:22 +0300, Eli Zaretskii wrote:
> Oh, I didn't realize that error == exception here. In that case,
> let's use the same term:
>
> Evaluate @var{command}, a string, as a @value{GDBN} CLI command.
> If a GDB exception happens while @var{command} runs, it is
> translated as described above. If no exceptions occur, this
> function returns @code{None}.
Thanks, used this text then.
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-08-04 19:50 ` Eli Zaretskii
@ 2008-08-05 2:08 ` Daniel Jacobowitz
2008-08-05 2:41 ` Thiago Jung Bauermann
2008-08-05 3:32 ` Eli Zaretskii
0 siblings, 2 replies; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-08-05 2:08 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: bauerman, tromey, gdb-patches
On Mon, Aug 04, 2008 at 10:48:46PM +0300, Eli Zaretskii wrote:
> When executing the @code{python} command, Python exceptions
> uncaught within the Python code are translated to calls to
> @value{GDBN} error-reporting mechanism. If the command that called
> @code{python} does not handle the error, @value{GDBN} will
> terminate it and print an error message containing the Python
> exception name, the associated value, and the Python call stack
> backtrace at the point where the exception was raised. Example:
I think we've almost got it. The only problem I see with the above
text is that it's focused on user commands, both "python" and others.
This fits with the "Canned Sequences of Commands" usage which is what
the first patch implements, but if we can say it more generally it may
continue to be true as more patches go in. Here's some other
scenarios I heard mentioned in conversation today:
- Tab completion. Python code might be invoked when the user hits Tab
in the middle of an expression.
- "gdb --python", which Tom has implemented on the branch - no CLI
interpreter involved, GDB just executes a Python script.
- If Python code is used to discover some information about a stack
frame, it might be invoked every time the program stops.
So that gives me a paragraph like this, which I think is accurate.
Does this look OK to you?
When executing Python code, uncaught Python exceptions are translated
to calls to the @value{GDBN} error-reporting mechanism. If
@value{GDBN} does not handle the error, it will terminate the current
command and print an error message containing the Python exception
name, the associated value, and the Python call stack backtrace at the
point where the exception was raised. Example:
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-08-05 2:08 ` Daniel Jacobowitz
@ 2008-08-05 2:41 ` Thiago Jung Bauermann
2008-08-05 3:32 ` Eli Zaretskii
1 sibling, 0 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-08-05 2:41 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Eli Zaretskii, tromey, gdb-patches
On Mon, 2008-08-04 at 22:07 -0400, Daniel Jacobowitz wrote:
> So that gives me a paragraph like this, which I think is accurate.
> Does this look OK to you?
I liked it. So this is the complete version of this text that I have for
now. I changed the last sentence a bit, to reflect what you actually get
from the Python exception:
@cindex python exceptions
@cindex exceptions, python
When executing Python code, uncaught Python exceptions are translated
to calls to the @value{GDBN} error-reporting mechanism. If
@value{GDBN} does not handle the error, it will terminate the current
command and print an error message containing the Python exception
name, the associated value, and the Python call stack backtrace at the
point where the exception was raised. Example:
@smallexample
(@value{GDBP}) python print foo
Traceback (most recent call last):
File "<string>", line 1, in <module>
NameError: name 'foo' is not defined
@end smallexample
@value{GDBN} errors that happen in @value{GDBN} commands invoked by Python
code are converted to Python @code{RuntimeError} exceptions. User
interrupt (via @kbd{C-c} or by typing @kbd{q} at a pagination
prompt) is translated to a Python @code{KeyboardInterrupt}
exception. If you catch these exceptions in your Python code, your
exception handler will see @code{RuntimeError} or
@code{KeyboardInterrupt} as the exception type, the @value{GDBN} error
message as its value, and the Python call stack backtrace at the
Python statement closest to where the @value{GDB} error occured as the
traceback.
It this ok?
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-08-05 2:08 ` Daniel Jacobowitz
2008-08-05 2:41 ` Thiago Jung Bauermann
@ 2008-08-05 3:32 ` Eli Zaretskii
2008-08-05 12:19 ` Daniel Jacobowitz
1 sibling, 1 reply; 147+ messages in thread
From: Eli Zaretskii @ 2008-08-05 3:32 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: bauerman, tromey, gdb-patches
> Date: Mon, 4 Aug 2008 22:07:54 -0400
> From: Daniel Jacobowitz <drow@false.org>
> Cc: bauerman@br.ibm.com, tromey@redhat.com, gdb-patches@sources.redhat.com
>
> On Mon, Aug 04, 2008 at 10:48:46PM +0300, Eli Zaretskii wrote:
> > When executing the @code{python} command, Python exceptions
> > uncaught within the Python code are translated to calls to
> > @value{GDBN} error-reporting mechanism. If the command that called
> > @code{python} does not handle the error, @value{GDBN} will
> > terminate it and print an error message containing the Python
> > exception name, the associated value, and the Python call stack
> > backtrace at the point where the exception was raised. Example:
>
> I think we've almost got it. The only problem I see with the above
> text is that it's focused on user commands, both "python" and others.
> This fits with the "Canned Sequences of Commands" usage which is what
> the first patch implements, but if we can say it more generally it may
> continue to be true as more patches go in. Here's some other
> scenarios I heard mentioned in conversation today:
>
> - Tab completion. Python code might be invoked when the user hits Tab
> in the middle of an expression.
>
> - "gdb --python", which Tom has implemented on the branch - no CLI
> interpreter involved, GDB just executes a Python script.
>
> - If Python code is used to discover some information about a stack
> frame, it might be invoked every time the program stops.
>
> So that gives me a paragraph like this, which I think is accurate.
> Does this look OK to you?
>
> When executing Python code, uncaught Python exceptions are translated
> to calls to the @value{GDBN} error-reporting mechanism. If
> @value{GDBN} does not handle the error, it will terminate the current
> command and print an error message containing the Python exception
> name, the associated value, and the Python call stack backtrace at the
> point where the exception was raised. Example:
I'm not sure this change is for the best: you've eliminated only one
of the two uses of "command" in this text, which just obfuscates the
text a little (what is it exactly in GDB that does not handle the
error, and if it isn't a command that invoked "python", why do we
terminate a command?).
I think trying to say the truth, all the truth, and nothing but the
truth is not the right attitude when writing software documentation.
So, on balance, I like my text better.
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-08-04 19:18 ` Eli Zaretskii
@ 2008-08-05 3:42 ` Thiago Jung Bauermann
0 siblings, 0 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-08-05 3:42 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: tromey, gdb-patches
On Mon, 2008-08-04 at 22:17 +0300, Eli Zaretskii wrote:
> > From: Thiago Jung Bauermann <bauerman@br.ibm.com>
> > In that case, my opinion is that the current "Canned Sequences of
> > Commands" chapter should be demoted to a section (and its sections would
> > then be demoted to subsubsections), and both this section and Python's
> > section should be under a chapter called "Extending GDB".
>
> Agreed.
>
> > Rereading this thread, I think this is what Daniel suggested in the
> > first place.
>
> And I agreed:
>
> >> Ok, in that case I have an alternative suggestion: how about renaming
> >> the combined scripting chapter, and putting both Python scripting and
> >> the existing information in the new chapter?
> >
> > I have no objections to renaming that chapter.
Great, I wasn't sure about the demotion part. I guess I was just dazed
and confused. I made that change, then.
Now we have a chapter describing both canned commands, and the fresh
python scripts.
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-07-26 18:11 ` Eli Zaretskii
2008-07-26 18:30 ` Daniel Jacobowitz
@ 2008-08-05 4:19 ` Thiago Jung Bauermann
2008-08-05 18:14 ` Eli Zaretskii
1 sibling, 1 reply; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-08-05 4:19 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: tromey, drow, gdb-patches
On Sat, 2008-07-26 at 21:10 +0300, Eli Zaretskii wrote:
> > From: Tom Tromey <tromey@redhat.com>
> > >> +@value{GDBN} exposes a number of features to Python scripts.
> >
> > Eli> This should end with a colon, and the list of the features should be a
> > Eli> @table.
> >
> > I guess those aren't really features, they are more like generic
> > things that the python-in-gdb programmer ought to know.
> >
> > So, I don't think a table makes sense, but I suppose the current text
> > is also misleading. What do you suggest?
>
> My problem is with the form, not with the content. By default, each
> paragraph in a Texinfo document starts with an indentation, like in a
> book. @table prevents that, producing paragraphs whose all lines line
> up. This section presents a list of features; having each feature's
> description begin with an indented line is simply ugly.
We can sidestep the issue and actually get a better result in the end:
The two paragraphs talking about exception handling should go to a new
subsubsection, and the paragraph stdout and pagination should go to the
"Basic Python" subsubsection.
Then we can whack the "GDB exposes a number of features to Python
scripts." sentence.
IMO it is the best option.
> You seem to think that @table produces a table, but it doesn't.
Heh. :-)
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-08-05 3:32 ` Eli Zaretskii
@ 2008-08-05 12:19 ` Daniel Jacobowitz
2008-08-05 18:10 ` Eli Zaretskii
0 siblings, 1 reply; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-08-05 12:19 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: bauerman, tromey, gdb-patches
On Tue, Aug 05, 2008 at 06:30:51AM +0300, Eli Zaretskii wrote:
> > So that gives me a paragraph like this, which I think is accurate.
> > Does this look OK to you?
> >
> > When executing Python code, uncaught Python exceptions are translated
> > to calls to the @value{GDBN} error-reporting mechanism. If
> > @value{GDBN} does not handle the error, it will terminate the current
> > command and print an error message containing the Python exception
> > name, the associated value, and the Python call stack backtrace at the
> > point where the exception was raised. Example:
>
> I'm not sure this change is for the best: you've eliminated only one
> of the two uses of "command" in this text, which just obfuscates the
> text a little (what is it exactly in GDB that does not handle the
> error, and if it isn't a command that invoked "python", why do we
> terminate a command?).
Is s/command/operation/ acceptable?
If any part of GDB handles the error, the error is swallowed.
Otherwise it drifts upwards through the call stack, terminating
function calls as it goes. It's always caught if it reaches the main
command loop, but there are lots of other places too.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-08-05 12:19 ` Daniel Jacobowitz
@ 2008-08-05 18:10 ` Eli Zaretskii
2008-08-05 18:23 ` Daniel Jacobowitz
0 siblings, 1 reply; 147+ messages in thread
From: Eli Zaretskii @ 2008-08-05 18:10 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: bauerman, tromey, gdb-patches
> Date: Tue, 5 Aug 2008 08:19:08 -0400
> From: Daniel Jacobowitz <drow@false.org>
> Cc: bauerman@br.ibm.com, tromey@redhat.com, gdb-patches@sources.redhat.com
>
> On Tue, Aug 05, 2008 at 06:30:51AM +0300, Eli Zaretskii wrote:
> > > So that gives me a paragraph like this, which I think is accurate.
> > > Does this look OK to you?
> > >
> > > When executing Python code, uncaught Python exceptions are translated
> > > to calls to the @value{GDBN} error-reporting mechanism. If
> > > @value{GDBN} does not handle the error, it will terminate the current
> > > command and print an error message containing the Python exception
> > > name, the associated value, and the Python call stack backtrace at the
> > > point where the exception was raised. Example:
> >
> > I'm not sure this change is for the best: you've eliminated only one
> > of the two uses of "command" in this text, which just obfuscates the
> > text a little (what is it exactly in GDB that does not handle the
> > error, and if it isn't a command that invoked "python", why do we
> > terminate a command?).
>
> Is s/command/operation/ acceptable?
No objections, but what problem would that solve?
> If any part of GDB handles the error, the error is swallowed.
> Otherwise it drifts upwards through the call stack, terminating
> function calls as it goes. It's always caught if it reaches the main
> command loop, but there are lots of other places too.
Yes, I know, but again: how does this help to make the above passage
right?
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-08-05 4:19 ` Thiago Jung Bauermann
@ 2008-08-05 18:14 ` Eli Zaretskii
2008-08-06 5:35 ` [RFA][patch 1/9] Initial Python support, patch du jour Thiago Jung Bauermann
0 siblings, 1 reply; 147+ messages in thread
From: Eli Zaretskii @ 2008-08-05 18:14 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: tromey, drow, gdb-patches
> From: Thiago Jung Bauermann <bauerman@br.ibm.com>
> Cc: tromey@redhat.com, drow@false.org, gdb-patches@sourceware.org
> Date: Tue, 05 Aug 2008 01:18:47 -0300
>
> > My problem is with the form, not with the content. By default, each
> > paragraph in a Texinfo document starts with an indentation, like in a
> > book. @table prevents that, producing paragraphs whose all lines line
> > up. This section presents a list of features; having each feature's
> > description begin with an indented line is simply ugly.
>
> We can sidestep the issue and actually get a better result in the end:
>
> The two paragraphs talking about exception handling should go to a new
> subsubsection, and the paragraph stdout and pagination should go to the
> "Basic Python" subsubsection.
>
> Then we can whack the "GDB exposes a number of features to Python
> scripts." sentence.
>
> IMO it is the best option.
Can you show me the patch along those lines?
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-08-05 18:10 ` Eli Zaretskii
@ 2008-08-05 18:23 ` Daniel Jacobowitz
2008-08-05 18:50 ` Eli Zaretskii
0 siblings, 1 reply; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-08-05 18:23 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: bauerman, tromey, gdb-patches
On Tue, Aug 05, 2008 at 09:10:04PM +0300, Eli Zaretskii wrote:
> > Date: Tue, 5 Aug 2008 08:19:08 -0400
> > From: Daniel Jacobowitz <drow@false.org>
> > Cc: bauerman@br.ibm.com, tromey@redhat.com, gdb-patches@sources.redhat.com
> > > I'm not sure this change is for the best: you've eliminated only one
> > > of the two uses of "command" in this text, which just obfuscates the
> > > text a little (what is it exactly in GDB that does not handle the
> > > error, and if it isn't a command that invoked "python", why do we
> > > terminate a command?).
> >
> > Is s/command/operation/ acceptable?
>
> No objections, but what problem would that solve?
Your comment about terminating a command if something other than a
command invoked Python. We terminate whatever it was that invoked
Python. Operation is a general term ("we're doing something"), which
does not have the risk associated with "command" which has a specific
meaning in GDB. None of this is restricted to the context of
commands.
> > If any part of GDB handles the error, the error is swallowed.
> > Otherwise it drifts upwards through the call stack, terminating
> > function calls as it goes. It's always caught if it reaches the main
> > command loop, but there are lots of other places too.
>
> Yes, I know, but again: how does this help to make the above passage
> right?
I'm afraid you've lost me :-( I need a little help - what's not
right about it? You said it was confusing, not that it was wrong,
so I tried to make it clearer.
To the best of my technical and writing ability, the version above
accurately describes GDB's behavior. And I think it's clear, too.
To reduce quoting depth (I have trouble following discussion when it
gets too deep), here it is again.
When executing Python code, uncaught Python exceptions are translated
to calls to the @value{GDBN} error-reporting mechanism. If
@value{GDBN} does not handle the error, it will terminate the current
operation and print an error message containing the Python exception
name, the associated value, and the Python call stack backtrace at the
point where the exception was raised. Example:
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-08-05 18:23 ` Daniel Jacobowitz
@ 2008-08-05 18:50 ` Eli Zaretskii
2008-08-05 18:58 ` Daniel Jacobowitz
0 siblings, 1 reply; 147+ messages in thread
From: Eli Zaretskii @ 2008-08-05 18:50 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: bauerman, tromey, gdb-patches
> Date: Tue, 5 Aug 2008 14:23:05 -0400
> From: Daniel Jacobowitz <drow@false.org>
> Cc: bauerman@br.ibm.com, tromey@redhat.com, gdb-patches@sources.redhat.com
>
> When executing Python code, uncaught Python exceptions are translated
> to calls to the @value{GDBN} error-reporting mechanism. If
> @value{GDBN} does not handle the error, it will terminate the current
> operation and print an error message containing the Python exception
> name, the associated value, and the Python call stack backtrace at the
> point where the exception was raised. Example:
As I said, I don't see the (marginal, IMO) case of Python invoked by
something other than a command worth obscuring this already quite
complicated description. So I suggest to reinstate "command" in the
second sentence, since this is the most frequent situation users will
see.
But if you really want to be rigorous, I will claim that "GDB does not
handle the error" is inaccurate as well because what is described
afterwards _is_ handling the error. So we would need to make that
sentence even more complicated, etc. etc. All this for a situation
that most users will never care about. I think it's a wrong balance,
but if you still insist on doing it, go ahead and install your
version; I don't see a sense in arguing about this nit any longer.
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Yet another respin of the patch with initial Python support
2008-08-05 18:50 ` Eli Zaretskii
@ 2008-08-05 18:58 ` Daniel Jacobowitz
0 siblings, 0 replies; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-08-05 18:58 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: bauerman, tromey, gdb-patches
On Tue, Aug 05, 2008 at 09:49:18PM +0300, Eli Zaretskii wrote:
> > Date: Tue, 5 Aug 2008 14:23:05 -0400
> > From: Daniel Jacobowitz <drow@false.org>
> > Cc: bauerman@br.ibm.com, tromey@redhat.com, gdb-patches@sources.redhat.com
> >
> > When executing Python code, uncaught Python exceptions are translated
> > to calls to the @value{GDBN} error-reporting mechanism. If
> > @value{GDBN} does not handle the error, it will terminate the current
> > operation and print an error message containing the Python exception
> > name, the associated value, and the Python call stack backtrace at the
> > point where the exception was raised. Example:
>
> As I said, I don't see the (marginal, IMO) case of Python invoked by
> something other than a command worth obscuring this already quite
> complicated description. So I suggest to reinstate "command" in the
> second sentence, since this is the most frequent situation users will
> see.
OK, let's use command then.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* [RFA][patch 1/9] Initial Python support, patch du jour
2008-08-05 18:14 ` Eli Zaretskii
@ 2008-08-06 5:35 ` Thiago Jung Bauermann
2008-08-06 18:24 ` Eli Zaretskii
0 siblings, 1 reply; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-08-06 5:35 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: tromey, drow, gdb-patches
On Tue, 2008-08-05 at 21:13 +0300, Eli Zaretskii wrote:
> > From: Thiago Jung Bauermann <bauerman@br.ibm.com>
> > The two paragraphs talking about exception handling should go to a new
> > subsubsection, and the paragraph stdout and pagination should go to the
> > "Basic Python" subsubsection.
> >
> > Then we can whack the "GDB exposes a number of features to Python
> > scripts." sentence.
> >
> > IMO it is the best option.
>
> Can you show me the patch along those lines?
Sure. I'm sending everything I have so far, actually. In the end I
preferred to keep the paragraph about stdout and pagination in the
Python API subsection, instead of moving it to Basic Python.
The code part is the same as the last submission and is already
approved. The documentation part reflects everything we've discussed
until now. I hope I didn't miss anything, it was a long thread. :-)
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
gdb/
2008-08-06 Vladimir Prus <vladimir@codesourcery.com>
Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
Doug Evans <dje@google.com>
* Makefile.in (SUBDIR_PYTHON_OBS, SUBDIR_PYTHON_SRCS,
SUBDIR_PYTHON_DEPS, SUBDIR_PYTHON_LDFLAGS, SUBDIR_PYTHON_CFLAGS,
PYTHON_CFLAGS): New.
(python_h, python_internal_h): New.
(cli-script.o): Depend on python.h
(python.o, python-utils.o): New.
* cli/cli-script.c (print_command_lines): Handle python_control.
(execute_control_command): Handle python_control.
(execute_control_command_untraced): New function.
(while_command): Call execute_control_command_untraced.
(if_command): Likewise.
(get_command_line): Remove static attribute.
(read_next_line): Handle "python".
(recurse_read_control_structure): Handle python_control.
(read_command_lines): Handle python_control.
Include python.h.
* cli/cli-script.h (get_command_line): Add prototype.
(execute_control_command_untraced): Likewise.
* configure.ac: Add --with-python.
* defs.h (enum command_control_type) <python_control>: New
constant.
* python/python-internal.h: New file.
* python/python.c: New file.
* python/python.h: New file.
* python/python-utils.c: New file.
* NEWS: Mention Python scripting support and its new commands.
gdb/doc/
2008-08-06 Tom Tromey <tromey@redhat.com>
* gdb.texinfo (Extending GDB): New chapter.
(Sequences): Demoted chapter, now a section under the new
Extending GDB chapter.
(Python): New section.
gdb/testsuite/
2008-08-06 Tom Tromey <tromey@redhat.com>
* gdb.python/python.exp: New file.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 3e82b92..615be3f 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -254,6 +254,19 @@ SUBDIR_TUI_LDFLAGS=
SUBDIR_TUI_CFLAGS= \
-DTUI=1
+#
+# python sub directory definitons
+#
+SUBDIR_PYTHON_OBS = \
+ python.o \
+ python-utils.o
+SUBDIR_PYTHON_SRCS = \
+ python/python.c \
+ python/python-utils.c
+SUBDIR_PYTHON_DEPS =
+SUBDIR_PYTHON_LDFLAGS=
+SUBDIR_PYTHON_CFLAGS=
+
# Opcodes currently live in one of two places. Either they are in the
# opcode library, typically ../opcodes, or they are in a header file
@@ -963,6 +976,13 @@ tui_wingeneral_h = $(srcdir)/tui/tui-wingeneral.h
tui_win_h = $(srcdir)/tui/tui-win.h $(tui_data_h)
tui_winsource_h = $(srcdir)/tui/tui-winsource.h $(tui_data_h)
+#
+# gdb/python/ headers
+#
+
+python_h = $(srcdir)/python/python.h $(value_h)
+python_internal_h = $(srcdir)/python/python-internal.h
+
# gdb/features preparsed descriptions
features_headers = $(defs_h) $(gdbtypes_h) $(target_descriptions_h)
arm_with_iwmmxt_c = $(srcdir)/features/arm-with-iwmmxt.c $(features_headers)
@@ -3064,7 +3084,8 @@ cli-logging.o: $(srcdir)/cli/cli-logging.c $(defs_h) $(gdbcmd_h) $(ui_out_h) \
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-logging.c
cli-script.o: $(srcdir)/cli/cli-script.c $(defs_h) $(value_h) $(language_h) \
$(ui_out_h) $(gdb_string_h) $(exceptions_h) $(top_h) $(cli_cmds_h) \
- $(cli_decode_h) $(cli_script_h) $(gdb_assert_h) $(breakpoint_h)
+ $(cli_decode_h) $(cli_script_h) $(gdb_assert_h) $(breakpoint_h) \
+ $(python_h)
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-script.c
cli-setshow.o: $(srcdir)/cli/cli-setshow.c $(defs_h) $(readline_tilde_h) \
$(value_h) $(gdb_string_h) $(ui_out_h) $(cli_decode_h) $(cli_cmds_h) \
@@ -3389,4 +3410,22 @@ tui-winsource.o: $(srcdir)/tui/tui-winsource.c $(defs_h) $(symtab_h) \
$(gdb_curses_h) $(gdb_assert_h)
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tui-winsource.c
+#
+# gdb/python/ dependencies
+#
+# Need to explicitly specify the compile rule as make will do nothing
+# or try to compile the object file into the sub-directory.
+
+# Flags needed to compile Python code
+PYTHON_CFLAGS=@PYTHON_CFLAGS@
+
+python.o: $(srcdir)/python/python.c $(defs_h) $(python_h) \
+ $(command_h) $(libiberty_h) $(cli_decode_h) $(charset_h) $(top_h) \
+ $(exceptions_h) $(python_internal_h) $(version_h) $(cli_script_h) \
+ $(ui_out_h) $(target_h) $(gdbthread_h)
+ $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) $(srcdir)/python/python.c
+python-utils.o: $(srcdir)/python/python-utils.c $(defs_h) $(python_internal_h)
+ $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
+ $(srcdir)/python/python-utils.c -o python-utils.o
+
### end of the gdb Makefile.in.
diff --git a/gdb/NEWS b/gdb/NEWS
index e783259..82dbfe6 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -62,12 +62,24 @@ have also been fixed.
gdbserver executable to debug both 32-bit and 64-bit programs.
(This requires gdbserver itself to be built as a 64-bit executable.)
+* Python scripting
+
+ GDB now has support for scripting using Python. Whether this is
+ available is determined at configure time.
+
* New commands
find [/size-char] [/max-count] start-address, end-address|+search-space-size,
val1 [, val2, ...]
Search memory for a sequence of bytes.
+maint set python print-stack
+maint show python print-stack
+ Show a stack trace when an error is encountered in a Python script.
+
+python [CODE]
+ Invoke CODE by passing it to the Python interpreter.
+
set print symbol-loading
show print symbol-loading
Control printing of symbol loading messages.
diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c
index e6fbe3f..5aafc75 100644
--- a/gdb/cli/cli-script.c
+++ b/gdb/cli/cli-script.c
@@ -34,6 +34,8 @@
#include "cli/cli-script.h"
#include "gdb_assert.h"
+#include "python/python.h"
+
/* Prototypes for local functions */
static enum command_control_type
@@ -102,7 +104,7 @@ build_command_line (enum command_control_type type, char *args)
/* Build and return a new command structure for the control commands
such as "if" and "while". */
-static struct command_line *
+struct command_line *
get_command_line (enum command_control_type type, char *arg)
{
struct command_line *cmd;
@@ -225,6 +227,20 @@ print_command_lines (struct ui_out *uiout, struct command_line *cmd,
continue;
}
+ if (list->control_type == python_control)
+ {
+ ui_out_field_string (uiout, NULL, "python");
+ ui_out_text (uiout, "\n");
+ /* Don't indent python code at all. */
+ print_command_lines (uiout, *list->body_list, 0);
+ if (depth)
+ ui_out_spaces (uiout, 2 * depth);
+ ui_out_field_string (uiout, NULL, "end");
+ ui_out_text (uiout, "\n");
+ list = list->next;
+ continue;
+ }
+
/* ignore illegal command type and try next */
list = list->next;
} /* while (list) */
@@ -527,6 +543,12 @@ execute_control_command (struct command_line *cmd)
ret = commands_from_control_command (new_line, cmd);
break;
}
+ case python_control:
+ {
+ eval_python_from_control_command (cmd);
+ ret = simple_control;
+ break;
+ }
default:
warning (_("Invalid control type in canned commands structure."));
@@ -538,6 +560,17 @@ execute_control_command (struct command_line *cmd)
return ret;
}
+/* Like execute_control_command, but first set
+ suppress_next_print_command_trace. */
+
+enum command_control_type
+execute_control_command_untraced (struct command_line *cmd)
+{
+ suppress_next_print_command_trace = 1;
+ return execute_control_command (cmd);
+}
+
+
/* "while" command support. Executes a body of statements while the
loop condition is nonzero. */
@@ -552,8 +585,7 @@ while_command (char *arg, int from_tty)
if (command == NULL)
return;
- suppress_next_print_command_trace = 1;
- execute_control_command (command);
+ execute_control_command_untraced (command);
free_command_lines (&command);
}
@@ -571,8 +603,7 @@ if_command (char *arg, int from_tty)
if (command == NULL)
return;
- suppress_next_print_command_trace = 1;
- execute_control_command (command);
+ execute_control_command_untraced (command);
free_command_lines (&command);
}
@@ -886,6 +917,12 @@ read_next_line (struct command_line **command)
first_arg++;
*command = build_command_line (commands_control, first_arg);
}
+ else if (p1 - p == 6 && !strncmp (p, "python", 6))
+ {
+ /* Note that we ignore the inline "python command" form
+ here. */
+ *command = build_command_line (python_control, "");
+ }
else if (p1 - p == 10 && !strncmp (p, "loop_break", 10))
{
*command = (struct command_line *)
@@ -962,6 +999,7 @@ recurse_read_control_structure (struct command_line *current_cmd)
{
if (current_cmd->control_type == while_control
|| current_cmd->control_type == if_control
+ || current_cmd->control_type == python_control
|| current_cmd->control_type == commands_control)
{
/* Success reading an entire canned sequence of commands. */
@@ -1013,6 +1051,7 @@ recurse_read_control_structure (struct command_line *current_cmd)
on it. */
if (next->control_type == while_control
|| next->control_type == if_control
+ || next->control_type == python_control
|| next->control_type == commands_control)
{
control_level++;
@@ -1086,6 +1125,7 @@ read_command_lines (char *prompt_arg, int from_tty)
if (next->control_type == while_control
|| next->control_type == if_control
+ || next->control_type == python_control
|| next->control_type == commands_control)
{
control_level++;
diff --git a/gdb/cli/cli-script.h b/gdb/cli/cli-script.h
index 42663dd..50ec1e1 100644
--- a/gdb/cli/cli-script.h
+++ b/gdb/cli/cli-script.h
@@ -40,6 +40,12 @@ extern void show_user_1 (struct cmd_list_element *c, struct ui_file *stream);
extern enum command_control_type
execute_control_command (struct command_line *cmd);
+extern enum command_control_type
+ execute_control_command_untraced (struct command_line *cmd);
+
+extern struct command_line *get_command_line (enum command_control_type,
+ char *);
+
extern void print_command_lines (struct ui_out *,
struct command_line *, unsigned int);
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 0a92812..370c21b 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -497,6 +497,125 @@ else
fi
fi
+dnl Utility to simplify finding libpython.
+AC_DEFUN([AC_TRY_LIBPYTHON],
+[
+ version=$1
+ define([have_libpython_var],$2)
+ define([VERSION],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+ [HAVE_LIB]VERSION=no
+ AC_MSG_CHECKING([for ${version}])
+ save_LIBS=$LIBS
+ LIBS="$LIBS -l${version}"
+ AC_LINK_IFELSE(AC_LANG_PROGRAM([[#include "${version}/Python.h"]],
+ [[Py_Initialize ();]]),
+ [[HAVE_LIB]VERSION=yes
+ have_libpython_var=yes],
+ [LIBS=$save_LIBS])
+ AC_MSG_RESULT([$[HAVE_LIB]VERSION])
+])
+
+AC_ARG_WITH(python,
+ AS_HELP_STRING([--with-python], [include python support (auto/yes/no/<path>)]),
+ [], [with_python=auto])
+AC_MSG_CHECKING([whether to use python])
+AC_MSG_RESULT([$with_python])
+
+if test "${with_python}" = no; then
+ AC_MSG_WARN([python support disabled; some features may be unavailable.])
+ have_libpython=no
+else
+ case "${with_python}" in
+ yes | auto)
+ # Leave as empty, use defaults.
+ python_includes=
+ python_libs=
+ ;;
+ /*)
+ python_includes="-I${with_python}/include"
+ python_libs="-L${with_python}/lib"
+ ;;
+ *)
+ AC_ERROR(invalid value for --with-python)
+ ;;
+ esac
+
+ save_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS ${python_includes}"
+ save_LIBS=$LIBS
+ LIBS="$LIBS ${python_libs}"
+ have_libpython=no
+ if test "${have_libpython}" = no; then
+ AC_TRY_LIBPYTHON(python2.6, have_libpython)
+ if test "${HAVE_LIBPYTHON2_6}" = yes; then
+ AC_DEFINE(HAVE_LIBPYTHON2_6, 1, [Define if Python 2.6 is being used.])
+ fi
+ fi
+ if test ${have_libpython} = no; then
+ AC_TRY_LIBPYTHON(python2.5, have_libpython)
+ if test "${HAVE_LIBPYTHON2_5}" = yes; then
+ AC_DEFINE(HAVE_LIBPYTHON2_5, 1, [Define if Python 2.5 is being used.])
+ fi
+ fi
+ if test ${have_libpython} = no; then
+ AC_TRY_LIBPYTHON(python2.4, have_libpython)
+ if test "${HAVE_LIBPYTHON2_4}" = yes; then
+ AC_DEFINE(HAVE_LIBPYTHON2_4, 1, [Define if Python 2.4 is being used.])
+ fi
+ fi
+ if test ${have_libpython} = no; then
+ case "${with_python}" in
+ yes)
+ AC_MSG_ERROR([python is missing or unusable])
+ ;;
+ auto)
+ AC_MSG_WARN([python is missing or unusable; some features may be unavailable.])
+ ;;
+ *)
+ AC_MSG_ERROR([no usable python found at ${with_python}])
+ ;;
+ esac
+ CPPFLAGS=$save_CPPFLAGS
+ LIBS=$save_LIBS
+ fi
+fi
+
+if test "${have_libpython}" = yes; then
+ AC_DEFINE(HAVE_PYTHON, 1, [Define if Python interpreter is being linked in.])
+ CONFIG_OBS="$CONFIG_OBS \$(SUBDIR_PYTHON_OBS)"
+ CONFIG_DEPS="$CONFIG_DEPS \$(SUBDIR_PYTHON_DEPS)"
+ CONFIG_SRCS="$CONFIG_SRCS \$(SUBDIR_PYTHON_SRCS)"
+ ENABLE_CFLAGS="$ENABLE_CFLAGS \$(SUBDIR_PYTHON_CFLAGS)"
+
+ # Flags needed to compile Python code (taken from python-config --cflags).
+ # We cannot call python-config directly because it will output whatever was
+ # used when compiling the Python interpreter itself, including flags which
+ # would make the python-related objects be compiled differently from the
+ # rest of GDB (e.g., -O2 and -fPIC).
+ if test "${GCC}" = yes; then
+ tentative_python_cflags="-fno-strict-aliasing -DNDEBUG -fwrapv"
+ fi
+
+ if test "x${tentative_python_cflags}" != x; then
+ AC_MSG_CHECKING(compiler flags for python code)
+ for flag in ${tentative_python_cflags}; do
+ # Check that the compiler accepts it
+ saved_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $flag"
+ AC_TRY_COMPILE([],[],PYTHON_CFLAGS="${PYTHON_CFLAGS} $flag",)
+ CFLAGS="$saved_CFLAGS"
+ done
+ AC_MSG_RESULT(${PYTHON_CFLAGS})
+ fi
+else
+ # Even if Python support is not compiled in, we need to have this file
+ # included in order to recognize the GDB command "python".
+ CONFIG_OBS="$CONFIG_OBS python.o"
+ CONFIG_SRCS="$CONFIG_SRCS python/python.c"
+fi
+AC_SUBST(PYTHON_CFLAGS)
+
# ------------------------- #
# Checks for header files. #
# ------------------------- #
diff --git a/gdb/defs.h b/gdb/defs.h
index 6e6aa80..7fe5934 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -652,6 +652,7 @@ enum command_control_type
while_control,
if_control,
commands_control,
+ python_control,
invalid_control
};
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 2920179..543dea8 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -159,7 +159,7 @@ software in general. We will miss him.
* Remote Debugging:: Debugging remote programs
* Configurations:: Configuration-specific information
* Controlling GDB:: Controlling @value{GDBN}
-* Sequences:: Canned sequences of commands
+* Extending GDB:: Extending @value{GDBN}
* Interpreters:: Command Interpreters
* TUI:: @value{GDBN} Text User Interface
* Emacs:: Using @value{GDBN} under @sc{gnu} Emacs
@@ -16847,8 +16847,21 @@ Turns on or off debugging messages for built-in XML parsers.
Displays the current state of XML debugging messages.
@end table
+@node Extending GDB
+@chapter Extending @value{GDBN}
+@cindex extending GDB
+
+@value{GDBN} provides two mechanisms for extension. The first is based
+on composition of @value{GDBN} commands, and the second is based on the
+Python scripting language.
+
+@menu
+* Sequences:: Canned Sequences of Commands
+* Python:: Scripting @value{GDBN} using Python
+@end menu
+
@node Sequences
-@chapter Canned Sequences of Commands
+@section Canned Sequences of Commands
Aside from breakpoint commands (@pxref{Break Commands, ,Breakpoint
Command Lists}), @value{GDBN} provides two ways to store sequences of
@@ -16863,7 +16876,7 @@ files.
@end menu
@node Define
-@section User-defined Commands
+@subsection User-defined Commands
@cindex user-defined command
@cindex arguments, to user-defined commands
@@ -16975,7 +16988,7 @@ commands that normally print messages to say what they are doing omit the
messages when used in a user-defined command.
@node Hooks
-@section User-defined Command Hooks
+@subsection User-defined Command Hooks
@cindex command hooks
@cindex hooks, for commands
@cindex hooks, pre-command
@@ -17056,7 +17069,7 @@ If you try to define a hook which does not match any known command, you
get a warning from the @code{define} command.
@node Command Files
-@section Command Files
+@subsection Command Files
@cindex command files
@cindex scripting commands
@@ -17160,7 +17173,7 @@ Terminate the block of commands that are the body of @code{if},
@node Output
-@section Commands for Controlled Output
+@subsection Commands for Controlled Output
During the execution of a command file or a user-defined command, normal
@value{GDBN} output is suppressed; the only output that appears is what is
@@ -17307,6 +17320,159 @@ printf "D32: %Hf - D64: %Df - D128: %DDf\n",1.2345df,1.2E10dd,1.2E1dl
@end table
+@node Python
+@section Scripting @value{GDBN} using Python
+@cindex python scripting
+@cindex scripting with python
+
+You can script @value{GDBN} using the @uref{http://www.python.org/,
+Python programming language}. This feature is available only if
+@value{GDBN} was configured using @option{--with-python}.
+
+@menu
+* Python Commands:: Accessing Python from @value{GDBN}.
+* Python API:: Accessing @value{GDBN} from Python.
+@end menu
+
+@node Python Commands
+@subsection Python Commands
+@cindex python commands
+@cindex commands to access python
+
+@value{GDBN} provides one command for accessing the Python interpreter,
+and one related setting:
+
+@table @code
+@kindex python
+@item python @r{[}@var{code}@r{]}
+The @code{python} command can be used to evaluate Python code.
+
+If given an argument, the @code{python} command will evaluate the
+argument as a Python command. For example:
+
+@smallexample
+(@value{GDBP}) python print 23
+23
+@end smallexample
+
+If you do not provide an argument to @code{python}, it will act as a
+multi-line command, like @code{define}. In this case, the Python
+script is made up of subsequent command lines, given after the
+@code{python} command. This command list is terminated using a line
+containing @code{end}. For example:
+
+@smallexample
+(@value{GDBP}) python
+Type python script
+End with a line saying just "end".
+>print 23
+>end
+23
+@end smallexample
+
+@kindex maint set python print-stack
+@item maint set python print-stack
+By default, @value{GDBN} will print a stack trace when an error occurs
+in a Python script. This can be controlled using @code{maint set
+python print-stack}: if @code{on}, the default, then Python stack
+printing is enabled; if @code{off}, then Python stack printing is
+disabled.
+@end table
+
+@node Python API
+@subsection Python API
+@cindex python api
+@cindex programming in python
+
+@cindex python stdout
+@cindex python pagination
+At startup, @value{GDBN} overrides Python's @code{sys.stdout} and
+@code{sys.stderr} to print using @value{GDBN}'s output-paging streams.
+A Python program which outputs to one of these streams may have its
+output interrupted by the user (@pxref{Screen Size}). In this
+situation, a Python @code{KeyboardInterrupt} exception is thrown.
+
+@menu
+* Basic Python:: Basic Python Functions.
+* Exception Handling::
+@end menu
+
+@node Basic Python
+@subsubsection Basic Python
+
+@cindex python functions
+@cindex python module
+@cindex gdb module
+@value{GDBN} introduces a new Python module, named @code{gdb}. All
+methods and classes added by @value{GDBN} are placed in this module.
+@value{GDBN} automatically @code{import}s the @code{gdb} module for
+use in all scripts evaluated by the @code{python} command.
+
+@findex gdb.execute
+@defun execute command
+Evaluate @var{command}, a string, as a @value{GDBN} CLI command.
+If a GDB exception happens while @var{command} runs, it is
+translated as described above. If no exceptions occur, this
+function returns @code{None}.
+@end defun
+
+@findex gdb.get_parameter
+@defun get_parameter parameter
+Find the value of a @value{GDBN} parameter. @var{parameter} is a
+string naming the parameter to look up; @var{parameter} may contain
+spaces if the parameter has a multi-part name. For example,
+@samp{print object} is a valid parameter name.
+
+If the named parameter does not exist, this function throws a
+@code{RuntimeError}. Otherwise, the parameter's value is converted to
+a Python value of the appropriate type, and returned.
+@end defun
+
+@findex gdb.write
+@defun write string
+Print a string to @value{GDBN}'s paginated standard output stream.
+Writing to @code{sys.stdout} or @code{sys.stderr} will automatically
+call this function.
+@end defun
+
+@findex gdb.flush
+@defun flush
+Flush @value{GDBN}'s paginated standard output stream. Flushing
+@code{sys.stdout} or @code{sys.stderr} will automatically call this
+function.
+@end defun
+
+@node Exception Handling
+@subsubsection Exception Handling
+@cindex python exceptions
+@cindex exceptions, python
+
+When executing the @code{python} command, Python exceptions
+uncaught within the Python code are translated to calls to
+@value{GDBN} error-reporting mechanism. If the command that called
+@code{python} does not handle the error, @value{GDBN} will
+terminate it and print an error message containing the Python
+exception name, the associated value, and the Python call stack
+backtrace at the point where the exception was raised. Example:
+
+@smallexample
+(@value{GDBP}) python print foo
+Traceback (most recent call last):
+ File "<string>", line 1, in <module>
+NameError: name 'foo' is not defined
+@end smallexample
+
+@value{GDBN} errors that happen in @value{GDBN} commands invoked by Python
+code are converted to Python @code{RuntimeError} exceptions. User
+interrupt (via @kbd{C-c} or by typing @kbd{q} at a pagination
+prompt) is translated to a Python @code{KeyboardInterrupt}
+exception. If you catch these exceptions in your Python code, your
+exception handler will see @code{RuntimeError} or
+@code{KeyboardInterrupt} as the exception type, the @value{GDBN} error
+message as its value, and the Python call stack backtrace at the
+Python statement closest to where the @value{GDBN} error occured as the
+traceback.
+
@node Interpreters
@chapter Command Interpreters
@cindex command interpreters
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
new file mode 100644
index 0000000..f850448
--- /dev/null
+++ b/gdb/python/python-internal.h
@@ -0,0 +1,71 @@
+/* Gdb/Python header for private use by Python module.
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDB_PYTHON_INTERNAL_H
+#define GDB_PYTHON_INTERNAL_H
+
+/* Python 2.4 doesn't include stdint.h soon enough to get {u,}intptr_t
+ needed by pyport.h. */
+#include <stdint.h>
+
+/* /usr/include/features.h on linux systems will define _POSIX_C_SOURCE
+ if it sees _GNU_SOURCE (which config.h will define).
+ pyconfig.h defines _POSIX_C_SOURCE to a different value than
+ /usr/include/features.h does causing compilation to fail.
+ To work around this, undef _POSIX_C_SOURCE before we include Python.h. */
+#undef _POSIX_C_SOURCE
+
+#if HAVE_LIBPYTHON2_4
+#include "python2.4/Python.h"
+/* Py_ssize_t is not defined until 2.5. */
+typedef Py_intptr_t Py_ssize_t;
+#elif HAVE_LIBPYTHON2_5
+#include "python2.5/Python.h"
+#elif HAVE_LIBPYTHON2_6
+#include "python2.6/Python.h"
+#else
+#error "Unable to find usable Python.h"
+#endif
+
+struct block;
+struct symbol;
+struct symtab_and_line;
+
+extern PyObject *gdb_module;
+
+struct cleanup *make_cleanup_py_decref (PyObject *py);
+
+/* Use this after a TRY_EXCEPT to throw the appropriate Python
+ exception. */
+#define GDB_PY_HANDLE_EXCEPTION(Exception) \
+ do { \
+ if (Exception.reason < 0) \
+ return PyErr_Format (Exception.reason == RETURN_QUIT \
+ ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, \
+ "%s", Exception.message); \
+ } while (0)
+
+
+void gdbpy_print_stack (void);
+
+PyObject *python_string_to_unicode (PyObject *obj);
+char *unicode_to_target_string (PyObject *unicode_str);
+char *python_string_to_target_string (PyObject *obj);
+
+#endif /* GDB_PYTHON_INTERNAL_H */
diff --git a/gdb/python/python-utils.c b/gdb/python/python-utils.c
new file mode 100644
index 0000000..912845f
--- /dev/null
+++ b/gdb/python/python-utils.c
@@ -0,0 +1,117 @@
+/* General utility routines for GDB/Python.
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "charset.h"
+#include "python-internal.h"
+
+
+/* This is a cleanup function which decrements the refcount on a
+ Python object. */
+
+static void
+py_decref (void *p)
+{
+ PyObject *py = p;
+ /* Note that we need the extra braces in this 'if' to avoid a
+ warning from gcc. */
+ if (py)
+ {
+ Py_DECREF (py);
+ }
+}
+
+/* Return a new cleanup which will decrement the Python object's
+ refcount when run. */
+
+struct cleanup *
+make_cleanup_py_decref (PyObject *py)
+{
+ return make_cleanup (py_decref, (void *) py);
+}
+
+/* Converts a Python 8-bit string to a unicode string object. Assumes the
+ 8-bit string is in the host charset. If an error occurs during conversion,
+ returns NULL with a python exception set.
+
+ As an added bonus, the functions accepts a unicode string and returns it
+ right away, so callers don't need to check which kind of string they've
+ got.
+
+ If the given object is not one of the mentioned string types, NULL is
+ returned, with the TypeError python exception set. */
+PyObject *
+python_string_to_unicode (PyObject *obj)
+{
+ PyObject *unicode_str;
+
+ /* If obj is already a unicode string, just return it.
+ I wish life was always that simple... */
+ if (PyUnicode_Check (obj))
+ unicode_str = obj;
+ else if (PyString_Check (obj))
+ unicode_str = PyUnicode_FromEncodedObject (obj, host_charset (), NULL);
+ else
+ {
+ PyErr_SetString (PyExc_TypeError,
+ _("Expected a string or unicode object."));
+ unicode_str = NULL;
+ }
+
+ return unicode_str;
+}
+
+/* Returns a newly allocated string with the contents of the given unicode
+ string object converted to the target's charset. If an error occurs during
+ the conversion, NULL will be returned and a python exception will be set.
+
+ The caller is responsible for xfree'ing the string. */
+char *
+unicode_to_target_string (PyObject *unicode_str)
+{
+ char *target_string;
+ PyObject *string;
+
+ /* Translate string to target's charset. */
+ string = PyUnicode_AsEncodedString (unicode_str, target_charset (), NULL);
+ if (string == NULL)
+ return NULL;
+
+ target_string = xstrdup (PyString_AsString (string));
+
+ Py_DECREF (string);
+
+ return target_string;
+}
+
+/* Converts a python string (8-bit or unicode) to a target string in
+ the target's charset. Returns NULL on error, with a python exception set.
+
+ The caller is responsible for xfree'ing the string. */
+char *
+python_string_to_target_string (PyObject *obj)
+{
+ PyObject *str;
+
+ str = python_string_to_unicode (obj);
+ if (str == NULL)
+ return NULL;
+
+ return unicode_to_target_string (str);
+}
diff --git a/gdb/python/python.c b/gdb/python/python.c
new file mode 100644
index 0000000..a560290
--- /dev/null
+++ b/gdb/python/python.c
@@ -0,0 +1,438 @@
+/* General python/gdb code
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "command.h"
+#include "ui-out.h"
+#include "cli/cli-script.h"
+#include "gdbcmd.h"
+
+#include <ctype.h>
+
+/* True if we should print the stack when catching a Python error,
+ false otherwise. */
+static int gdbpy_should_print_stack = 1;
+
+#ifdef HAVE_PYTHON
+
+#include "python.h"
+#include "libiberty.h"
+#include "cli/cli-decode.h"
+#include "charset.h"
+#include "top.h"
+#include "exceptions.h"
+#include "python-internal.h"
+#include "version.h"
+#include "target.h"
+#include "gdbthread.h"
+
+
+PyObject *gdb_module;
+
+static PyObject *get_parameter (PyObject *, PyObject *);
+static PyObject *execute_gdb_command (PyObject *, PyObject *);
+static PyObject *gdbpy_write (PyObject *, PyObject *);
+static PyObject *gdbpy_flush (PyObject *, PyObject *);
+
+static PyMethodDef GdbMethods[] =
+{
+ { "execute", execute_gdb_command, METH_VARARGS,
+ "Execute a gdb command" },
+ { "get_parameter", get_parameter, METH_VARARGS,
+ "Return a gdb parameter's value" },
+
+ { "write", gdbpy_write, METH_VARARGS,
+ "Write a string using gdb's filtered stream." },
+ { "flush", gdbpy_flush, METH_NOARGS,
+ "Flush gdb's filtered stdout stream." },
+
+ {NULL, NULL, 0, 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
+ responsible for freeing it. */
+
+static char *
+compute_python_string (struct command_line *l)
+{
+ struct command_line *iter;
+ char *script = NULL;
+ int size = 0;
+ int here;
+
+ for (iter = l; iter; iter = iter->next)
+ size += strlen (iter->line) + 1;
+
+ script = xmalloc (size + 1);
+ here = 0;
+ for (iter = l; iter; iter = iter->next)
+ {
+ int len = strlen (iter->line);
+ strcpy (&script[here], iter->line);
+ here += len;
+ script[here++] = '\n';
+ }
+ script[here] = '\0';
+ return script;
+}
+
+/* Take a command line structure representing a 'python' command, and
+ evaluate its body using the Python interpreter. */
+
+void
+eval_python_from_control_command (struct command_line *cmd)
+{
+ char *script;
+
+ if (cmd->body_count != 1)
+ error (_("Invalid \"python\" block structure."));
+
+ script = compute_python_string (cmd->body_list[0]);
+ PyRun_SimpleString (script);
+ xfree (script);
+ if (PyErr_Occurred ())
+ {
+ gdbpy_print_stack ();
+ error (_("error while executing Python code"));
+ }
+}
+
+/* Implementation of the gdb "python" command. */
+
+static void
+python_command (char *arg, int from_tty)
+{
+ while (arg && *arg && isspace (*arg))
+ ++arg;
+ if (arg && *arg)
+ {
+ PyRun_SimpleString (arg);
+ if (PyErr_Occurred ())
+ {
+ gdbpy_print_stack ();
+ error (_("error while executing Python code"));
+ }
+ }
+ else
+ {
+ struct command_line *l = get_command_line (python_control, "");
+ struct cleanup *cleanups = make_cleanup_free_command_lines (&l);
+ execute_control_command_untraced (l);
+ do_cleanups (cleanups);
+ }
+}
+
+\f
+
+/* Transform a gdb parameters's value into a Python value. May return
+ NULL (and set a Python exception) on error. Helper function for
+ get_parameter. */
+
+static PyObject *
+parameter_to_python (struct cmd_list_element *cmd)
+{
+ switch (cmd->var_type)
+ {
+ case var_string:
+ case var_string_noescape:
+ case var_optional_filename:
+ case var_filename:
+ case var_enum:
+ {
+ char *str = * (char **) cmd->var;
+ if (! str)
+ str = "";
+ return PyString_Decode (str, strlen (str), host_charset (), NULL);
+ }
+
+ case var_boolean:
+ {
+ if (* (int *) cmd->var)
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
+ }
+
+ case var_auto_boolean:
+ {
+ enum auto_boolean ab = * (enum auto_boolean *) cmd->var;
+ if (ab == AUTO_BOOLEAN_TRUE)
+ Py_RETURN_TRUE;
+ else if (ab == AUTO_BOOLEAN_FALSE)
+ Py_RETURN_FALSE;
+ else
+ Py_RETURN_NONE;
+ }
+
+ case var_integer:
+ if ((* (int *) cmd->var) == INT_MAX)
+ Py_RETURN_NONE;
+ /* Fall through. */
+ case var_zinteger:
+ return PyLong_FromLong (* (int *) cmd->var);
+
+ case var_uinteger:
+ {
+ unsigned int val = * (unsigned int *) cmd->var;
+ if (val == UINT_MAX)
+ Py_RETURN_NONE;
+ return PyLong_FromUnsignedLong (val);
+ }
+ }
+
+ return PyErr_Format (PyExc_RuntimeError, "programmer error: unhandled type");
+}
+
+/* A Python function which returns a gdb parameter's value as a Python
+ value. */
+
+static PyObject *
+get_parameter (PyObject *self, PyObject *args)
+{
+ struct cmd_list_element *alias, *prefix, *cmd;
+ char *arg, *newarg;
+ volatile struct gdb_exception except;
+
+ if (! PyArg_ParseTuple (args, "s", &arg))
+ return NULL;
+
+ newarg = concat ("show ", arg, (char *) NULL);
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ if (! lookup_cmd_composition (newarg, &alias, &prefix, &cmd))
+ {
+ xfree (newarg);
+ return PyErr_Format (PyExc_RuntimeError,
+ "could not find variable `%s'", arg);
+ }
+ }
+ xfree (newarg);
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ if (! cmd->var)
+ return PyErr_Format (PyExc_RuntimeError, "`%s' is not a variable", arg);
+ return parameter_to_python (cmd);
+}
+
+/* A Python function which evaluates a string using the gdb CLI. */
+
+static PyObject *
+execute_gdb_command (PyObject *self, PyObject *args)
+{
+ struct cmd_list_element *alias, *prefix, *cmd;
+ char *arg, *newarg;
+ volatile struct gdb_exception except;
+ struct cleanup *old_chain;
+
+ if (! PyArg_ParseTuple (args, "s", &arg))
+ return NULL;
+
+ old_chain = make_cleanup (null_cleanup, 0);
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ execute_command (arg, 0);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ /* Do any commands attached to breakpoint we stopped at. Only if we
+ are always running synchronously. Or if we have just executed a
+ command that doesn't start the target. */
+ if (!target_can_async_p () || !is_running (inferior_ptid))
+ {
+ bpstat_do_actions (&stop_bpstat);
+ do_cleanups (old_chain);
+ }
+
+ Py_RETURN_NONE;
+}
+
+\f
+
+/* Printing. */
+
+/* A python function to write a single string using gdb's filtered
+ output stream. */
+static PyObject *
+gdbpy_write (PyObject *self, PyObject *args)
+{
+ char *arg;
+ if (! PyArg_ParseTuple (args, "s", &arg))
+ return NULL;
+ printf_filtered ("%s", arg);
+ Py_RETURN_NONE;
+}
+
+/* A python function to flush gdb's filtered output stream. */
+static PyObject *
+gdbpy_flush (PyObject *self, PyObject *args)
+{
+ gdb_flush (gdb_stdout);
+ Py_RETURN_NONE;
+}
+
+/* Print a python exception trace, or print nothing and clear the
+ python exception, depending on gdbpy_should_print_stack. Only call
+ this if a python exception is set. */
+void
+gdbpy_print_stack (void)
+{
+ if (gdbpy_should_print_stack)
+ PyErr_Print ();
+ else
+ PyErr_Clear ();
+}
+
+#else /* HAVE_PYTHON */
+
+/* Dummy implementation of the gdb "python" command. */
+
+static void
+python_command (char *arg, int from_tty)
+{
+ while (arg && *arg && isspace (*arg))
+ ++arg;
+ if (arg && *arg)
+ error (_("Python scripting is not supported in this copy of GDB."));
+ else
+ {
+ struct command_line *l = get_command_line (python_control, "");
+ struct cleanup *cleanups = make_cleanup_free_command_lines (&l);
+ execute_control_command_untraced (l);
+ do_cleanups (cleanups);
+ }
+}
+
+void
+eval_python_from_control_command (struct command_line *cmd)
+{
+ error (_("Python scripting is not supported in this copy of GDB."));
+}
+
+#endif /* HAVE_PYTHON */
+
+\f
+
+/* Lists for 'maint set python' commands. */
+
+static struct cmd_list_element *set_python_list;
+static struct cmd_list_element *show_python_list;
+
+/* Function for use by 'maint set python' prefix command. */
+
+static void
+set_python (char *args, int from_tty)
+{
+ help_list (set_python_list, "maintenance set python ", -1, gdb_stdout);
+}
+
+/* Function for use by 'maint show python' prefix command. */
+
+static void
+show_python (char *args, int from_tty)
+{
+ cmd_show_list (show_python_list, from_tty, "");
+}
+
+/* Initialize the Python code. */
+
+void
+_initialize_python (void)
+{
+ add_com ("python", class_obscure, python_command,
+#ifdef HAVE_PYTHON
+ _("\
+Evaluate a Python command.\n\
+\n\
+The command can be given as an argument, for instance:\n\
+\n\
+ python print 23\n\
+\n\
+If no argument is given, the following lines are read and used\n\
+as the Python commands. Type a line containing \"end\" to indicate\n\
+the end of the command.")
+#else /* HAVE_PYTHON */
+ _("\
+Evaluate a Python command.\n\
+\n\
+Python scripting is not supported in this copy of GDB.\n\
+This command is only a placeholder.")
+#endif /* HAVE_PYTHON */
+ );
+
+ add_prefix_cmd ("python", no_class, show_python,
+ _("Prefix command for python maintenance settings."),
+ &show_python_list, "maint show python ", 0,
+ &maintenance_show_cmdlist);
+ add_prefix_cmd ("python", no_class, set_python,
+ _("Prefix command for python maintenance settings."),
+ &set_python_list, "maint set python ", 0,
+ &maintenance_set_cmdlist);
+
+ add_setshow_boolean_cmd ("print-stack", class_maintenance,
+ &gdbpy_should_print_stack, _("\
+Enable or disable printing of Python stack dump on error."), _("\
+Show whether Python stack will be printed on error."), _("\
+Enables or disables printing of Python stack traces."),
+ NULL, NULL,
+ &set_python_list,
+ &show_python_list);
+
+#ifdef HAVE_PYTHON
+ Py_Initialize ();
+
+ gdb_module = Py_InitModule ("gdb", GdbMethods);
+
+ /* The casts to (char*) are for python 2.4. */
+ PyModule_AddStringConstant (gdb_module, "VERSION", (char*) version);
+ PyModule_AddStringConstant (gdb_module, "HOST_CONFIG", (char*) host_name);
+ PyModule_AddStringConstant (gdb_module, "TARGET_CONFIG", (char*) target_name);
+
+ PyRun_SimpleString ("import gdb");
+
+ /* Create a couple objects which are used for Python's stdout and
+ stderr. */
+ PyRun_SimpleString ("\
+import sys\n\
+class GdbOutputFile:\n\
+ def close(self):\n\
+ # Do nothing.\n\
+ return None\n\
+\n\
+ def isatty(self):\n\
+ return False\n\
+\n\
+ def write(self, s):\n\
+ gdb.write(s)\n\
+\n\
+ def writelines(self, iterable):\n\
+ for line in iterable:\n\
+ self.write(line)\n\
+\n\
+ def flush(self):\n\
+ gdb.flush()\n\
+\n\
+sys.stderr = GdbOutputFile()\n\
+sys.stdout = GdbOutputFile()\n\
+");
+#endif /* HAVE_PYTHON */
+}
diff --git a/gdb/python/python.h b/gdb/python/python.h
new file mode 100644
index 0000000..00ff159
--- /dev/null
+++ b/gdb/python/python.h
@@ -0,0 +1,27 @@
+/* Python/gdb header for generic use in gdb
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDB_PYTHON_H
+#define GDB_PYTHON_H
+
+#include "value.h"
+
+void eval_python_from_control_command (struct command_line *);
+
+#endif /* GDB_PYTHON_H */
diff --git a/gdb/testsuite/gdb.python/python.exp b/gdb/testsuite/gdb.python/python.exp
new file mode 100644
index 0000000..44037f2
--- /dev/null
+++ b/gdb/testsuite/gdb.python/python.exp
@@ -0,0 +1,66 @@
+# Copyright (C) 2008 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite. It tests the mechanism
+# exposing values to Python.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test_multiple "python print 23" "verify python support" {
+ -re "not supported.*$gdb_prompt $" {
+ unsupported "python support is disabled"
+ return -1
+ }
+ -re "$gdb_prompt $" {}
+}
+
+# Usage: gdb_py_test_multiple NAME INPUT RESULT {INPUT RESULT}...
+# Run a test named NAME, consisting of multiple lines of input.
+# After each input line INPUT, search for result line RESULT.
+# Succeed if all results are seen; fail otherwise.
+proc gdb_py_test_multiple {name args} {
+ global gdb_prompt
+ foreach {input result} $args {
+ if {[gdb_test_multiple $input "$name - $input" {
+ -re "\[\r\n\]*($result)\[\r\n\]+($gdb_prompt | *>)$" {
+ pass "$name - $input"
+ }
+ }]} {
+ return 1
+ }
+ }
+ return 0
+}
+
+gdb_py_test_multiple "multi-line python command" \
+ "python" "" \
+ "print 23" "" \
+ "end" "23"
+
+gdb_py_test_multiple "show python command" \
+ "define zzq" "Type commands for definition of .* just \"end\"\\.*" \
+ "python" "" \
+ "print 23" "" \
+ "end" "" \
+ "end" "" \
+ "show user zzq" "User command zzq:.* python.*print 23.* end"
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Initial Python support, patch du jour
2008-08-06 5:35 ` [RFA][patch 1/9] Initial Python support, patch du jour Thiago Jung Bauermann
@ 2008-08-06 18:24 ` Eli Zaretskii
2008-08-06 19:53 ` Thiago Jung Bauermann
0 siblings, 1 reply; 147+ messages in thread
From: Eli Zaretskii @ 2008-08-06 18:24 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: tromey, drow, gdb-patches
> From: Thiago Jung Bauermann <bauerman@br.ibm.com>
> Cc: tromey@redhat.com, drow@false.org, gdb-patches@sourceware.org
> Date: Wed, 06 Aug 2008 02:34:27 -0300
>
> +Evaluate @var{command}, a string, as a @value{GDBN} CLI command.
> +If a GDB exception happens while @var{command} runs, it is
> +translated as described above.
There's no description of exceptions translation in this node, so
"above" is not really true. If the description is in another node,
please use a cross-reference to point there.
> +@defun get_parameter parameter
> +Find the value of a @value{GDBN} parameter. @var{parameter} is a
^^^^^^^^^^^^^^
I think "return the value" is better here.
Otherwise, the patches for the manual are okay with me; thanks.
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [RFA][patch 1/9] Initial Python support, patch du jour
2008-08-06 18:24 ` Eli Zaretskii
@ 2008-08-06 19:53 ` Thiago Jung Bauermann
0 siblings, 0 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-08-06 19:53 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: tromey, drow, gdb-patches
On Wed, 2008-08-06 at 21:21 +0300, Eli Zaretskii wrote:
> Otherwise, the patches for the manual are okay with me; thanks.
Thanks! I made the changes and committed the version below.
Now to the next Python patches. :-)
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
gdb/
2008-08-06 Vladimir Prus <vladimir@codesourcery.com>
Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
Doug Evans <dje@google.com>
* Makefile.in (SUBDIR_PYTHON_OBS, SUBDIR_PYTHON_SRCS,
SUBDIR_PYTHON_DEPS, SUBDIR_PYTHON_LDFLAGS, SUBDIR_PYTHON_CFLAGS,
PYTHON_CFLAGS): New.
(python_h, python_internal_h): New.
(cli-script.o): Depend on python.h
(python.o, python-utils.o): New.
* cli/cli-script.c (print_command_lines): Handle python_control.
(execute_control_command): Handle python_control.
(execute_control_command_untraced): New function.
(while_command): Call execute_control_command_untraced.
(if_command): Likewise.
(get_command_line): Remove static attribute.
(read_next_line): Handle "python".
(recurse_read_control_structure): Handle python_control.
(read_command_lines): Handle python_control.
Include python.h.
* cli/cli-script.h (get_command_line): Add prototype.
(execute_control_command_untraced): Likewise.
* configure.ac: Add --with-python.
* defs.h (enum command_control_type) <python_control>: New
constant.
* python/python-internal.h: New file.
* python/python.c: New file.
* python/python.h: New file.
* python/python-utils.c: New file.
* NEWS: Mention Python scripting support and its new commands.
gdb/doc/
2008-08-06 Tom Tromey <tromey@redhat.com>
* gdb.texinfo (Extending GDB): New chapter.
(Sequences): Demoted chapter, now a section under the new
Extending GDB chapter.
(Python): New section.
gdb/testsuite/
2008-08-06 Tom Tromey <tromey@redhat.com>
* gdb.python/python.exp: New file.
Index: gdb.git/gdb/Makefile.in
===================================================================
--- gdb.git.orig/gdb/Makefile.in 2008-08-05 18:39:32.000000000 -0300
+++ gdb.git/gdb/Makefile.in 2008-08-06 16:04:36.000000000 -0300
@@ -254,6 +254,19 @@ SUBDIR_TUI_LDFLAGS=
SUBDIR_TUI_CFLAGS= \
-DTUI=1
+#
+# python sub directory definitons
+#
+SUBDIR_PYTHON_OBS = \
+ python.o \
+ python-utils.o
+SUBDIR_PYTHON_SRCS = \
+ python/python.c \
+ python/python-utils.c
+SUBDIR_PYTHON_DEPS =
+SUBDIR_PYTHON_LDFLAGS=
+SUBDIR_PYTHON_CFLAGS=
+
# Opcodes currently live in one of two places. Either they are in the
# opcode library, typically ../opcodes, or they are in a header file
@@ -951,6 +964,13 @@ tui_wingeneral_h = $(srcdir)/tui/tui-win
tui_win_h = $(srcdir)/tui/tui-win.h $(tui_data_h)
tui_winsource_h = $(srcdir)/tui/tui-winsource.h $(tui_data_h)
+#
+# gdb/python/ headers
+#
+
+python_h = $(srcdir)/python/python.h $(value_h)
+python_internal_h = $(srcdir)/python/python-internal.h
+
# gdb/features preparsed descriptions
features_headers = $(defs_h) $(gdbtypes_h) $(target_descriptions_h)
arm_with_iwmmxt_c = $(srcdir)/features/arm-with-iwmmxt.c $(features_headers)
@@ -3044,7 +3064,8 @@ cli-logging.o: $(srcdir)/cli/cli-logging
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-logging.c
cli-script.o: $(srcdir)/cli/cli-script.c $(defs_h) $(value_h) $(language_h) \
$(ui_out_h) $(gdb_string_h) $(exceptions_h) $(top_h) $(cli_cmds_h) \
- $(cli_decode_h) $(cli_script_h) $(gdb_assert_h) $(breakpoint_h)
+ $(cli_decode_h) $(cli_script_h) $(gdb_assert_h) $(breakpoint_h) \
+ $(python_h)
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-script.c
cli-setshow.o: $(srcdir)/cli/cli-setshow.c $(defs_h) $(readline_tilde_h) \
$(value_h) $(gdb_string_h) $(ui_out_h) $(cli_decode_h) $(cli_cmds_h) \
@@ -3372,4 +3393,22 @@ tui-winsource.o: $(srcdir)/tui/tui-winso
$(gdb_curses_h) $(gdb_assert_h)
$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/tui/tui-winsource.c
+#
+# gdb/python/ dependencies
+#
+# Need to explicitly specify the compile rule as make will do nothing
+# or try to compile the object file into the sub-directory.
+
+# Flags needed to compile Python code
+PYTHON_CFLAGS=@PYTHON_CFLAGS@
+
+python.o: $(srcdir)/python/python.c $(defs_h) $(python_h) \
+ $(command_h) $(libiberty_h) $(cli_decode_h) $(charset_h) $(top_h) \
+ $(exceptions_h) $(python_internal_h) $(version_h) $(cli_script_h) \
+ $(ui_out_h) $(target_h) $(gdbthread_h)
+ $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) $(srcdir)/python/python.c
+python-utils.o: $(srcdir)/python/python-utils.c $(defs_h) $(python_internal_h)
+ $(CC) -c $(INTERNAL_CFLAGS) $(PYTHON_CFLAGS) \
+ $(srcdir)/python/python-utils.c -o python-utils.o
+
### end of the gdb Makefile.in.
Index: gdb.git/gdb/NEWS
===================================================================
--- gdb.git.orig/gdb/NEWS 2008-08-05 18:39:32.000000000 -0300
+++ gdb.git/gdb/NEWS 2008-08-06 16:04:36.000000000 -0300
@@ -62,12 +62,24 @@ have also been fixed.
gdbserver executable to debug both 32-bit and 64-bit programs.
(This requires gdbserver itself to be built as a 64-bit executable.)
+* Python scripting
+
+ GDB now has support for scripting using Python. Whether this is
+ available is determined at configure time.
+
* New commands
find [/size-char] [/max-count] start-address, end-address|+search-space-size,
val1 [, val2, ...]
Search memory for a sequence of bytes.
+maint set python print-stack
+maint show python print-stack
+ Show a stack trace when an error is encountered in a Python script.
+
+python [CODE]
+ Invoke CODE by passing it to the Python interpreter.
+
set print symbol-loading
show print symbol-loading
Control printing of symbol loading messages.
Index: gdb.git/gdb/cli/cli-script.c
===================================================================
--- gdb.git.orig/gdb/cli/cli-script.c 2008-08-05 18:39:32.000000000 -0300
+++ gdb.git/gdb/cli/cli-script.c 2008-08-06 16:04:36.000000000 -0300
@@ -34,6 +34,8 @@
#include "cli/cli-script.h"
#include "gdb_assert.h"
+#include "python/python.h"
+
/* Prototypes for local functions */
static enum command_control_type
@@ -102,7 +104,7 @@ build_command_line (enum command_control
/* Build and return a new command structure for the control commands
such as "if" and "while". */
-static struct command_line *
+struct command_line *
get_command_line (enum command_control_type type, char *arg)
{
struct command_line *cmd;
@@ -225,6 +227,20 @@ print_command_lines (struct ui_out *uiou
continue;
}
+ if (list->control_type == python_control)
+ {
+ ui_out_field_string (uiout, NULL, "python");
+ ui_out_text (uiout, "\n");
+ /* Don't indent python code at all. */
+ print_command_lines (uiout, *list->body_list, 0);
+ if (depth)
+ ui_out_spaces (uiout, 2 * depth);
+ ui_out_field_string (uiout, NULL, "end");
+ ui_out_text (uiout, "\n");
+ list = list->next;
+ continue;
+ }
+
/* ignore illegal command type and try next */
list = list->next;
} /* while (list) */
@@ -527,6 +543,12 @@ execute_control_command (struct command_
ret = commands_from_control_command (new_line, cmd);
break;
}
+ case python_control:
+ {
+ eval_python_from_control_command (cmd);
+ ret = simple_control;
+ break;
+ }
default:
warning (_("Invalid control type in canned commands structure."));
@@ -538,6 +560,17 @@ execute_control_command (struct command_
return ret;
}
+/* Like execute_control_command, but first set
+ suppress_next_print_command_trace. */
+
+enum command_control_type
+execute_control_command_untraced (struct command_line *cmd)
+{
+ suppress_next_print_command_trace = 1;
+ return execute_control_command (cmd);
+}
+
+
/* "while" command support. Executes a body of statements while the
loop condition is nonzero. */
@@ -552,8 +585,7 @@ while_command (char *arg, int from_tty)
if (command == NULL)
return;
- suppress_next_print_command_trace = 1;
- execute_control_command (command);
+ execute_control_command_untraced (command);
free_command_lines (&command);
}
@@ -571,8 +603,7 @@ if_command (char *arg, int from_tty)
if (command == NULL)
return;
- suppress_next_print_command_trace = 1;
- execute_control_command (command);
+ execute_control_command_untraced (command);
free_command_lines (&command);
}
@@ -886,6 +917,12 @@ read_next_line (struct command_line **co
first_arg++;
*command = build_command_line (commands_control, first_arg);
}
+ else if (p1 - p == 6 && !strncmp (p, "python", 6))
+ {
+ /* Note that we ignore the inline "python command" form
+ here. */
+ *command = build_command_line (python_control, "");
+ }
else if (p1 - p == 10 && !strncmp (p, "loop_break", 10))
{
*command = (struct command_line *)
@@ -962,6 +999,7 @@ recurse_read_control_structure (struct c
{
if (current_cmd->control_type == while_control
|| current_cmd->control_type == if_control
+ || current_cmd->control_type == python_control
|| current_cmd->control_type == commands_control)
{
/* Success reading an entire canned sequence of commands. */
@@ -1013,6 +1051,7 @@ recurse_read_control_structure (struct c
on it. */
if (next->control_type == while_control
|| next->control_type == if_control
+ || next->control_type == python_control
|| next->control_type == commands_control)
{
control_level++;
@@ -1086,6 +1125,7 @@ read_command_lines (char *prompt_arg, in
if (next->control_type == while_control
|| next->control_type == if_control
+ || next->control_type == python_control
|| next->control_type == commands_control)
{
control_level++;
Index: gdb.git/gdb/cli/cli-script.h
===================================================================
--- gdb.git.orig/gdb/cli/cli-script.h 2008-08-05 18:39:32.000000000 -0300
+++ gdb.git/gdb/cli/cli-script.h 2008-08-06 16:04:36.000000000 -0300
@@ -40,6 +40,12 @@ extern void show_user_1 (struct cmd_list
extern enum command_control_type
execute_control_command (struct command_line *cmd);
+extern enum command_control_type
+ execute_control_command_untraced (struct command_line *cmd);
+
+extern struct command_line *get_command_line (enum command_control_type,
+ char *);
+
extern void print_command_lines (struct ui_out *,
struct command_line *, unsigned int);
Index: gdb.git/gdb/configure.ac
===================================================================
--- gdb.git.orig/gdb/configure.ac 2008-08-05 18:39:32.000000000 -0300
+++ gdb.git/gdb/configure.ac 2008-08-06 16:04:36.000000000 -0300
@@ -497,6 +497,125 @@ else
fi
fi
+dnl Utility to simplify finding libpython.
+AC_DEFUN([AC_TRY_LIBPYTHON],
+[
+ version=$1
+ define([have_libpython_var],$2)
+ define([VERSION],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+ [HAVE_LIB]VERSION=no
+ AC_MSG_CHECKING([for ${version}])
+ save_LIBS=$LIBS
+ LIBS="$LIBS -l${version}"
+ AC_LINK_IFELSE(AC_LANG_PROGRAM([[#include "${version}/Python.h"]],
+ [[Py_Initialize ();]]),
+ [[HAVE_LIB]VERSION=yes
+ have_libpython_var=yes],
+ [LIBS=$save_LIBS])
+ AC_MSG_RESULT([$[HAVE_LIB]VERSION])
+])
+
+AC_ARG_WITH(python,
+ AS_HELP_STRING([--with-python], [include python support (auto/yes/no/<path>)]),
+ [], [with_python=auto])
+AC_MSG_CHECKING([whether to use python])
+AC_MSG_RESULT([$with_python])
+
+if test "${with_python}" = no; then
+ AC_MSG_WARN([python support disabled; some features may be unavailable.])
+ have_libpython=no
+else
+ case "${with_python}" in
+ yes | auto)
+ # Leave as empty, use defaults.
+ python_includes=
+ python_libs=
+ ;;
+ /*)
+ python_includes="-I${with_python}/include"
+ python_libs="-L${with_python}/lib"
+ ;;
+ *)
+ AC_ERROR(invalid value for --with-python)
+ ;;
+ esac
+
+ save_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS ${python_includes}"
+ save_LIBS=$LIBS
+ LIBS="$LIBS ${python_libs}"
+ have_libpython=no
+ if test "${have_libpython}" = no; then
+ AC_TRY_LIBPYTHON(python2.6, have_libpython)
+ if test "${HAVE_LIBPYTHON2_6}" = yes; then
+ AC_DEFINE(HAVE_LIBPYTHON2_6, 1, [Define if Python 2.6 is being used.])
+ fi
+ fi
+ if test ${have_libpython} = no; then
+ AC_TRY_LIBPYTHON(python2.5, have_libpython)
+ if test "${HAVE_LIBPYTHON2_5}" = yes; then
+ AC_DEFINE(HAVE_LIBPYTHON2_5, 1, [Define if Python 2.5 is being used.])
+ fi
+ fi
+ if test ${have_libpython} = no; then
+ AC_TRY_LIBPYTHON(python2.4, have_libpython)
+ if test "${HAVE_LIBPYTHON2_4}" = yes; then
+ AC_DEFINE(HAVE_LIBPYTHON2_4, 1, [Define if Python 2.4 is being used.])
+ fi
+ fi
+ if test ${have_libpython} = no; then
+ case "${with_python}" in
+ yes)
+ AC_MSG_ERROR([python is missing or unusable])
+ ;;
+ auto)
+ AC_MSG_WARN([python is missing or unusable; some features may be unavailable.])
+ ;;
+ *)
+ AC_MSG_ERROR([no usable python found at ${with_python}])
+ ;;
+ esac
+ CPPFLAGS=$save_CPPFLAGS
+ LIBS=$save_LIBS
+ fi
+fi
+
+if test "${have_libpython}" = yes; then
+ AC_DEFINE(HAVE_PYTHON, 1, [Define if Python interpreter is being linked in.])
+ CONFIG_OBS="$CONFIG_OBS \$(SUBDIR_PYTHON_OBS)"
+ CONFIG_DEPS="$CONFIG_DEPS \$(SUBDIR_PYTHON_DEPS)"
+ CONFIG_SRCS="$CONFIG_SRCS \$(SUBDIR_PYTHON_SRCS)"
+ ENABLE_CFLAGS="$ENABLE_CFLAGS \$(SUBDIR_PYTHON_CFLAGS)"
+
+ # Flags needed to compile Python code (taken from python-config --cflags).
+ # We cannot call python-config directly because it will output whatever was
+ # used when compiling the Python interpreter itself, including flags which
+ # would make the python-related objects be compiled differently from the
+ # rest of GDB (e.g., -O2 and -fPIC).
+ if test "${GCC}" = yes; then
+ tentative_python_cflags="-fno-strict-aliasing -DNDEBUG -fwrapv"
+ fi
+
+ if test "x${tentative_python_cflags}" != x; then
+ AC_MSG_CHECKING(compiler flags for python code)
+ for flag in ${tentative_python_cflags}; do
+ # Check that the compiler accepts it
+ saved_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $flag"
+ AC_TRY_COMPILE([],[],PYTHON_CFLAGS="${PYTHON_CFLAGS} $flag",)
+ CFLAGS="$saved_CFLAGS"
+ done
+ AC_MSG_RESULT(${PYTHON_CFLAGS})
+ fi
+else
+ # Even if Python support is not compiled in, we need to have this file
+ # included in order to recognize the GDB command "python".
+ CONFIG_OBS="$CONFIG_OBS python.o"
+ CONFIG_SRCS="$CONFIG_SRCS python/python.c"
+fi
+AC_SUBST(PYTHON_CFLAGS)
+
# ------------------------- #
# Checks for header files. #
# ------------------------- #
Index: gdb.git/gdb/defs.h
===================================================================
--- gdb.git.orig/gdb/defs.h 2008-08-05 18:39:32.000000000 -0300
+++ gdb.git/gdb/defs.h 2008-08-06 16:04:36.000000000 -0300
@@ -652,6 +652,7 @@ enum command_control_type
while_control,
if_control,
commands_control,
+ python_control,
invalid_control
};
Index: gdb.git/gdb/doc/gdb.texinfo
===================================================================
--- gdb.git.orig/gdb/doc/gdb.texinfo 2008-08-05 18:39:32.000000000 -0300
+++ gdb.git/gdb/doc/gdb.texinfo 2008-08-06 16:09:34.000000000 -0300
@@ -159,7 +159,7 @@ software in general. We will miss him.
* Remote Debugging:: Debugging remote programs
* Configurations:: Configuration-specific information
* Controlling GDB:: Controlling @value{GDBN}
-* Sequences:: Canned sequences of commands
+* Extending GDB:: Extending @value{GDBN}
* Interpreters:: Command Interpreters
* TUI:: @value{GDBN} Text User Interface
* Emacs:: Using @value{GDBN} under @sc{gnu} Emacs
@@ -16845,8 +16845,21 @@ Turns on or off debugging messages for b
Displays the current state of XML debugging messages.
@end table
+@node Extending GDB
+@chapter Extending @value{GDBN}
+@cindex extending GDB
+
+@value{GDBN} provides two mechanisms for extension. The first is based
+on composition of @value{GDBN} commands, and the second is based on the
+Python scripting language.
+
+@menu
+* Sequences:: Canned Sequences of Commands
+* Python:: Scripting @value{GDBN} using Python
+@end menu
+
@node Sequences
-@chapter Canned Sequences of Commands
+@section Canned Sequences of Commands
Aside from breakpoint commands (@pxref{Break Commands, ,Breakpoint
Command Lists}), @value{GDBN} provides two ways to store sequences of
@@ -16861,7 +16874,7 @@ files.
@end menu
@node Define
-@section User-defined Commands
+@subsection User-defined Commands
@cindex user-defined command
@cindex arguments, to user-defined commands
@@ -16973,7 +16986,7 @@ commands that normally print messages to
messages when used in a user-defined command.
@node Hooks
-@section User-defined Command Hooks
+@subsection User-defined Command Hooks
@cindex command hooks
@cindex hooks, for commands
@cindex hooks, pre-command
@@ -17054,7 +17067,7 @@ If you try to define a hook which does n
get a warning from the @code{define} command.
@node Command Files
-@section Command Files
+@subsection Command Files
@cindex command files
@cindex scripting commands
@@ -17158,7 +17171,7 @@ Terminate the block of commands that are
@node Output
-@section Commands for Controlled Output
+@subsection Commands for Controlled Output
During the execution of a command file or a user-defined command, normal
@value{GDBN} output is suppressed; the only output that appears is what is
@@ -17305,6 +17318,159 @@ printf "D32: %Hf - D64: %Df - D128: %DDf
@end table
+@node Python
+@section Scripting @value{GDBN} using Python
+@cindex python scripting
+@cindex scripting with python
+
+You can script @value{GDBN} using the @uref{http://www.python.org/,
+Python programming language}. This feature is available only if
+@value{GDBN} was configured using @option{--with-python}.
+
+@menu
+* Python Commands:: Accessing Python from @value{GDBN}.
+* Python API:: Accessing @value{GDBN} from Python.
+@end menu
+
+@node Python Commands
+@subsection Python Commands
+@cindex python commands
+@cindex commands to access python
+
+@value{GDBN} provides one command for accessing the Python interpreter,
+and one related setting:
+
+@table @code
+@kindex python
+@item python @r{[}@var{code}@r{]}
+The @code{python} command can be used to evaluate Python code.
+
+If given an argument, the @code{python} command will evaluate the
+argument as a Python command. For example:
+
+@smallexample
+(@value{GDBP}) python print 23
+23
+@end smallexample
+
+If you do not provide an argument to @code{python}, it will act as a
+multi-line command, like @code{define}. In this case, the Python
+script is made up of subsequent command lines, given after the
+@code{python} command. This command list is terminated using a line
+containing @code{end}. For example:
+
+@smallexample
+(@value{GDBP}) python
+Type python script
+End with a line saying just "end".
+>print 23
+>end
+23
+@end smallexample
+
+@kindex maint set python print-stack
+@item maint set python print-stack
+By default, @value{GDBN} will print a stack trace when an error occurs
+in a Python script. This can be controlled using @code{maint set
+python print-stack}: if @code{on}, the default, then Python stack
+printing is enabled; if @code{off}, then Python stack printing is
+disabled.
+@end table
+
+@node Python API
+@subsection Python API
+@cindex python api
+@cindex programming in python
+
+@cindex python stdout
+@cindex python pagination
+At startup, @value{GDBN} overrides Python's @code{sys.stdout} and
+@code{sys.stderr} to print using @value{GDBN}'s output-paging streams.
+A Python program which outputs to one of these streams may have its
+output interrupted by the user (@pxref{Screen Size}). In this
+situation, a Python @code{KeyboardInterrupt} exception is thrown.
+
+@menu
+* Basic Python:: Basic Python Functions.
+* Exception Handling::
+@end menu
+
+@node Basic Python
+@subsubsection Basic Python
+
+@cindex python functions
+@cindex python module
+@cindex gdb module
+@value{GDBN} introduces a new Python module, named @code{gdb}. All
+methods and classes added by @value{GDBN} are placed in this module.
+@value{GDBN} automatically @code{import}s the @code{gdb} module for
+use in all scripts evaluated by the @code{python} command.
+
+@findex gdb.execute
+@defun execute command
+Evaluate @var{command}, a string, as a @value{GDBN} CLI command.
+If a GDB exception happens while @var{command} runs, it is
+translated as described in @ref{Exception Handling,,Exception Handling}.
+If no exceptions occur, this function returns @code{None}.
+@end defun
+
+@findex gdb.get_parameter
+@defun get_parameter parameter
+Return the value of a @value{GDBN} parameter. @var{parameter} is a
+string naming the parameter to look up; @var{parameter} may contain
+spaces if the parameter has a multi-part name. For example,
+@samp{print object} is a valid parameter name.
+
+If the named parameter does not exist, this function throws a
+@code{RuntimeError}. Otherwise, the parameter's value is converted to
+a Python value of the appropriate type, and returned.
+@end defun
+
+@findex gdb.write
+@defun write string
+Print a string to @value{GDBN}'s paginated standard output stream.
+Writing to @code{sys.stdout} or @code{sys.stderr} will automatically
+call this function.
+@end defun
+
+@findex gdb.flush
+@defun flush
+Flush @value{GDBN}'s paginated standard output stream. Flushing
+@code{sys.stdout} or @code{sys.stderr} will automatically call this
+function.
+@end defun
+
+@node Exception Handling
+@subsubsection Exception Handling
+@cindex python exceptions
+@cindex exceptions, python
+
+When executing the @code{python} command, Python exceptions
+uncaught within the Python code are translated to calls to
+@value{GDBN} error-reporting mechanism. If the command that called
+@code{python} does not handle the error, @value{GDBN} will
+terminate it and print an error message containing the Python
+exception name, the associated value, and the Python call stack
+backtrace at the point where the exception was raised. Example:
+
+@smallexample
+(@value{GDBP}) python print foo
+Traceback (most recent call last):
+ File "<string>", line 1, in <module>
+NameError: name 'foo' is not defined
+@end smallexample
+
+@value{GDBN} errors that happen in @value{GDBN} commands invoked by Python
+code are converted to Python @code{RuntimeError} exceptions. User
+interrupt (via @kbd{C-c} or by typing @kbd{q} at a pagination
+prompt) is translated to a Python @code{KeyboardInterrupt}
+exception. If you catch these exceptions in your Python code, your
+exception handler will see @code{RuntimeError} or
+@code{KeyboardInterrupt} as the exception type, the @value{GDBN} error
+message as its value, and the Python call stack backtrace at the
+Python statement closest to where the @value{GDBN} error occured as the
+traceback.
+
@node Interpreters
@chapter Command Interpreters
@cindex command interpreters
Index: gdb.git/gdb/python/python-internal.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gdb.git/gdb/python/python-internal.h 2008-08-06 16:04:36.000000000 -0300
@@ -0,0 +1,71 @@
+/* Gdb/Python header for private use by Python module.
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDB_PYTHON_INTERNAL_H
+#define GDB_PYTHON_INTERNAL_H
+
+/* Python 2.4 doesn't include stdint.h soon enough to get {u,}intptr_t
+ needed by pyport.h. */
+#include <stdint.h>
+
+/* /usr/include/features.h on linux systems will define _POSIX_C_SOURCE
+ if it sees _GNU_SOURCE (which config.h will define).
+ pyconfig.h defines _POSIX_C_SOURCE to a different value than
+ /usr/include/features.h does causing compilation to fail.
+ To work around this, undef _POSIX_C_SOURCE before we include Python.h. */
+#undef _POSIX_C_SOURCE
+
+#if HAVE_LIBPYTHON2_4
+#include "python2.4/Python.h"
+/* Py_ssize_t is not defined until 2.5. */
+typedef Py_intptr_t Py_ssize_t;
+#elif HAVE_LIBPYTHON2_5
+#include "python2.5/Python.h"
+#elif HAVE_LIBPYTHON2_6
+#include "python2.6/Python.h"
+#else
+#error "Unable to find usable Python.h"
+#endif
+
+struct block;
+struct symbol;
+struct symtab_and_line;
+
+extern PyObject *gdb_module;
+
+struct cleanup *make_cleanup_py_decref (PyObject *py);
+
+/* Use this after a TRY_EXCEPT to throw the appropriate Python
+ exception. */
+#define GDB_PY_HANDLE_EXCEPTION(Exception) \
+ do { \
+ if (Exception.reason < 0) \
+ return PyErr_Format (Exception.reason == RETURN_QUIT \
+ ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, \
+ "%s", Exception.message); \
+ } while (0)
+
+
+void gdbpy_print_stack (void);
+
+PyObject *python_string_to_unicode (PyObject *obj);
+char *unicode_to_target_string (PyObject *unicode_str);
+char *python_string_to_target_string (PyObject *obj);
+
+#endif /* GDB_PYTHON_INTERNAL_H */
Index: gdb.git/gdb/python/python-utils.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gdb.git/gdb/python/python-utils.c 2008-08-06 16:04:36.000000000 -0300
@@ -0,0 +1,117 @@
+/* General utility routines for GDB/Python.
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "charset.h"
+#include "python-internal.h"
+
+
+/* This is a cleanup function which decrements the refcount on a
+ Python object. */
+
+static void
+py_decref (void *p)
+{
+ PyObject *py = p;
+ /* Note that we need the extra braces in this 'if' to avoid a
+ warning from gcc. */
+ if (py)
+ {
+ Py_DECREF (py);
+ }
+}
+
+/* Return a new cleanup which will decrement the Python object's
+ refcount when run. */
+
+struct cleanup *
+make_cleanup_py_decref (PyObject *py)
+{
+ return make_cleanup (py_decref, (void *) py);
+}
+
+/* Converts a Python 8-bit string to a unicode string object. Assumes the
+ 8-bit string is in the host charset. If an error occurs during conversion,
+ returns NULL with a python exception set.
+
+ As an added bonus, the functions accepts a unicode string and returns it
+ right away, so callers don't need to check which kind of string they've
+ got.
+
+ If the given object is not one of the mentioned string types, NULL is
+ returned, with the TypeError python exception set. */
+PyObject *
+python_string_to_unicode (PyObject *obj)
+{
+ PyObject *unicode_str;
+
+ /* If obj is already a unicode string, just return it.
+ I wish life was always that simple... */
+ if (PyUnicode_Check (obj))
+ unicode_str = obj;
+ else if (PyString_Check (obj))
+ unicode_str = PyUnicode_FromEncodedObject (obj, host_charset (), NULL);
+ else
+ {
+ PyErr_SetString (PyExc_TypeError,
+ _("Expected a string or unicode object."));
+ unicode_str = NULL;
+ }
+
+ return unicode_str;
+}
+
+/* Returns a newly allocated string with the contents of the given unicode
+ string object converted to the target's charset. If an error occurs during
+ the conversion, NULL will be returned and a python exception will be set.
+
+ The caller is responsible for xfree'ing the string. */
+char *
+unicode_to_target_string (PyObject *unicode_str)
+{
+ char *target_string;
+ PyObject *string;
+
+ /* Translate string to target's charset. */
+ string = PyUnicode_AsEncodedString (unicode_str, target_charset (), NULL);
+ if (string == NULL)
+ return NULL;
+
+ target_string = xstrdup (PyString_AsString (string));
+
+ Py_DECREF (string);
+
+ return target_string;
+}
+
+/* Converts a python string (8-bit or unicode) to a target string in
+ the target's charset. Returns NULL on error, with a python exception set.
+
+ The caller is responsible for xfree'ing the string. */
+char *
+python_string_to_target_string (PyObject *obj)
+{
+ PyObject *str;
+
+ str = python_string_to_unicode (obj);
+ if (str == NULL)
+ return NULL;
+
+ return unicode_to_target_string (str);
+}
Index: gdb.git/gdb/python/python.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gdb.git/gdb/python/python.c 2008-08-06 16:04:36.000000000 -0300
@@ -0,0 +1,438 @@
+/* General python/gdb code
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "command.h"
+#include "ui-out.h"
+#include "cli/cli-script.h"
+#include "gdbcmd.h"
+
+#include <ctype.h>
+
+/* True if we should print the stack when catching a Python error,
+ false otherwise. */
+static int gdbpy_should_print_stack = 1;
+
+#ifdef HAVE_PYTHON
+
+#include "python.h"
+#include "libiberty.h"
+#include "cli/cli-decode.h"
+#include "charset.h"
+#include "top.h"
+#include "exceptions.h"
+#include "python-internal.h"
+#include "version.h"
+#include "target.h"
+#include "gdbthread.h"
+
+
+PyObject *gdb_module;
+
+static PyObject *get_parameter (PyObject *, PyObject *);
+static PyObject *execute_gdb_command (PyObject *, PyObject *);
+static PyObject *gdbpy_write (PyObject *, PyObject *);
+static PyObject *gdbpy_flush (PyObject *, PyObject *);
+
+static PyMethodDef GdbMethods[] =
+{
+ { "execute", execute_gdb_command, METH_VARARGS,
+ "Execute a gdb command" },
+ { "get_parameter", get_parameter, METH_VARARGS,
+ "Return a gdb parameter's value" },
+
+ { "write", gdbpy_write, METH_VARARGS,
+ "Write a string using gdb's filtered stream." },
+ { "flush", gdbpy_flush, METH_NOARGS,
+ "Flush gdb's filtered stdout stream." },
+
+ {NULL, NULL, 0, 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
+ responsible for freeing it. */
+
+static char *
+compute_python_string (struct command_line *l)
+{
+ struct command_line *iter;
+ char *script = NULL;
+ int size = 0;
+ int here;
+
+ for (iter = l; iter; iter = iter->next)
+ size += strlen (iter->line) + 1;
+
+ script = xmalloc (size + 1);
+ here = 0;
+ for (iter = l; iter; iter = iter->next)
+ {
+ int len = strlen (iter->line);
+ strcpy (&script[here], iter->line);
+ here += len;
+ script[here++] = '\n';
+ }
+ script[here] = '\0';
+ return script;
+}
+
+/* Take a command line structure representing a 'python' command, and
+ evaluate its body using the Python interpreter. */
+
+void
+eval_python_from_control_command (struct command_line *cmd)
+{
+ char *script;
+
+ if (cmd->body_count != 1)
+ error (_("Invalid \"python\" block structure."));
+
+ script = compute_python_string (cmd->body_list[0]);
+ PyRun_SimpleString (script);
+ xfree (script);
+ if (PyErr_Occurred ())
+ {
+ gdbpy_print_stack ();
+ error (_("error while executing Python code"));
+ }
+}
+
+/* Implementation of the gdb "python" command. */
+
+static void
+python_command (char *arg, int from_tty)
+{
+ while (arg && *arg && isspace (*arg))
+ ++arg;
+ if (arg && *arg)
+ {
+ PyRun_SimpleString (arg);
+ if (PyErr_Occurred ())
+ {
+ gdbpy_print_stack ();
+ error (_("error while executing Python code"));
+ }
+ }
+ else
+ {
+ struct command_line *l = get_command_line (python_control, "");
+ struct cleanup *cleanups = make_cleanup_free_command_lines (&l);
+ execute_control_command_untraced (l);
+ do_cleanups (cleanups);
+ }
+}
+
+\f
+
+/* Transform a gdb parameters's value into a Python value. May return
+ NULL (and set a Python exception) on error. Helper function for
+ get_parameter. */
+
+static PyObject *
+parameter_to_python (struct cmd_list_element *cmd)
+{
+ switch (cmd->var_type)
+ {
+ case var_string:
+ case var_string_noescape:
+ case var_optional_filename:
+ case var_filename:
+ case var_enum:
+ {
+ char *str = * (char **) cmd->var;
+ if (! str)
+ str = "";
+ return PyString_Decode (str, strlen (str), host_charset (), NULL);
+ }
+
+ case var_boolean:
+ {
+ if (* (int *) cmd->var)
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
+ }
+
+ case var_auto_boolean:
+ {
+ enum auto_boolean ab = * (enum auto_boolean *) cmd->var;
+ if (ab == AUTO_BOOLEAN_TRUE)
+ Py_RETURN_TRUE;
+ else if (ab == AUTO_BOOLEAN_FALSE)
+ Py_RETURN_FALSE;
+ else
+ Py_RETURN_NONE;
+ }
+
+ case var_integer:
+ if ((* (int *) cmd->var) == INT_MAX)
+ Py_RETURN_NONE;
+ /* Fall through. */
+ case var_zinteger:
+ return PyLong_FromLong (* (int *) cmd->var);
+
+ case var_uinteger:
+ {
+ unsigned int val = * (unsigned int *) cmd->var;
+ if (val == UINT_MAX)
+ Py_RETURN_NONE;
+ return PyLong_FromUnsignedLong (val);
+ }
+ }
+
+ return PyErr_Format (PyExc_RuntimeError, "programmer error: unhandled type");
+}
+
+/* A Python function which returns a gdb parameter's value as a Python
+ value. */
+
+static PyObject *
+get_parameter (PyObject *self, PyObject *args)
+{
+ struct cmd_list_element *alias, *prefix, *cmd;
+ char *arg, *newarg;
+ volatile struct gdb_exception except;
+
+ if (! PyArg_ParseTuple (args, "s", &arg))
+ return NULL;
+
+ newarg = concat ("show ", arg, (char *) NULL);
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ if (! lookup_cmd_composition (newarg, &alias, &prefix, &cmd))
+ {
+ xfree (newarg);
+ return PyErr_Format (PyExc_RuntimeError,
+ "could not find variable `%s'", arg);
+ }
+ }
+ xfree (newarg);
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ if (! cmd->var)
+ return PyErr_Format (PyExc_RuntimeError, "`%s' is not a variable", arg);
+ return parameter_to_python (cmd);
+}
+
+/* A Python function which evaluates a string using the gdb CLI. */
+
+static PyObject *
+execute_gdb_command (PyObject *self, PyObject *args)
+{
+ struct cmd_list_element *alias, *prefix, *cmd;
+ char *arg, *newarg;
+ volatile struct gdb_exception except;
+ struct cleanup *old_chain;
+
+ if (! PyArg_ParseTuple (args, "s", &arg))
+ return NULL;
+
+ old_chain = make_cleanup (null_cleanup, 0);
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ execute_command (arg, 0);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+
+ /* Do any commands attached to breakpoint we stopped at. Only if we
+ are always running synchronously. Or if we have just executed a
+ command that doesn't start the target. */
+ if (!target_can_async_p () || !is_running (inferior_ptid))
+ {
+ bpstat_do_actions (&stop_bpstat);
+ do_cleanups (old_chain);
+ }
+
+ Py_RETURN_NONE;
+}
+
+\f
+
+/* Printing. */
+
+/* A python function to write a single string using gdb's filtered
+ output stream. */
+static PyObject *
+gdbpy_write (PyObject *self, PyObject *args)
+{
+ char *arg;
+ if (! PyArg_ParseTuple (args, "s", &arg))
+ return NULL;
+ printf_filtered ("%s", arg);
+ Py_RETURN_NONE;
+}
+
+/* A python function to flush gdb's filtered output stream. */
+static PyObject *
+gdbpy_flush (PyObject *self, PyObject *args)
+{
+ gdb_flush (gdb_stdout);
+ Py_RETURN_NONE;
+}
+
+/* Print a python exception trace, or print nothing and clear the
+ python exception, depending on gdbpy_should_print_stack. Only call
+ this if a python exception is set. */
+void
+gdbpy_print_stack (void)
+{
+ if (gdbpy_should_print_stack)
+ PyErr_Print ();
+ else
+ PyErr_Clear ();
+}
+
+#else /* HAVE_PYTHON */
+
+/* Dummy implementation of the gdb "python" command. */
+
+static void
+python_command (char *arg, int from_tty)
+{
+ while (arg && *arg && isspace (*arg))
+ ++arg;
+ if (arg && *arg)
+ error (_("Python scripting is not supported in this copy of GDB."));
+ else
+ {
+ struct command_line *l = get_command_line (python_control, "");
+ struct cleanup *cleanups = make_cleanup_free_command_lines (&l);
+ execute_control_command_untraced (l);
+ do_cleanups (cleanups);
+ }
+}
+
+void
+eval_python_from_control_command (struct command_line *cmd)
+{
+ error (_("Python scripting is not supported in this copy of GDB."));
+}
+
+#endif /* HAVE_PYTHON */
+
+\f
+
+/* Lists for 'maint set python' commands. */
+
+static struct cmd_list_element *set_python_list;
+static struct cmd_list_element *show_python_list;
+
+/* Function for use by 'maint set python' prefix command. */
+
+static void
+set_python (char *args, int from_tty)
+{
+ help_list (set_python_list, "maintenance set python ", -1, gdb_stdout);
+}
+
+/* Function for use by 'maint show python' prefix command. */
+
+static void
+show_python (char *args, int from_tty)
+{
+ cmd_show_list (show_python_list, from_tty, "");
+}
+
+/* Initialize the Python code. */
+
+void
+_initialize_python (void)
+{
+ add_com ("python", class_obscure, python_command,
+#ifdef HAVE_PYTHON
+ _("\
+Evaluate a Python command.\n\
+\n\
+The command can be given as an argument, for instance:\n\
+\n\
+ python print 23\n\
+\n\
+If no argument is given, the following lines are read and used\n\
+as the Python commands. Type a line containing \"end\" to indicate\n\
+the end of the command.")
+#else /* HAVE_PYTHON */
+ _("\
+Evaluate a Python command.\n\
+\n\
+Python scripting is not supported in this copy of GDB.\n\
+This command is only a placeholder.")
+#endif /* HAVE_PYTHON */
+ );
+
+ add_prefix_cmd ("python", no_class, show_python,
+ _("Prefix command for python maintenance settings."),
+ &show_python_list, "maint show python ", 0,
+ &maintenance_show_cmdlist);
+ add_prefix_cmd ("python", no_class, set_python,
+ _("Prefix command for python maintenance settings."),
+ &set_python_list, "maint set python ", 0,
+ &maintenance_set_cmdlist);
+
+ add_setshow_boolean_cmd ("print-stack", class_maintenance,
+ &gdbpy_should_print_stack, _("\
+Enable or disable printing of Python stack dump on error."), _("\
+Show whether Python stack will be printed on error."), _("\
+Enables or disables printing of Python stack traces."),
+ NULL, NULL,
+ &set_python_list,
+ &show_python_list);
+
+#ifdef HAVE_PYTHON
+ Py_Initialize ();
+
+ gdb_module = Py_InitModule ("gdb", GdbMethods);
+
+ /* The casts to (char*) are for python 2.4. */
+ PyModule_AddStringConstant (gdb_module, "VERSION", (char*) version);
+ PyModule_AddStringConstant (gdb_module, "HOST_CONFIG", (char*) host_name);
+ PyModule_AddStringConstant (gdb_module, "TARGET_CONFIG", (char*) target_name);
+
+ PyRun_SimpleString ("import gdb");
+
+ /* Create a couple objects which are used for Python's stdout and
+ stderr. */
+ PyRun_SimpleString ("\
+import sys\n\
+class GdbOutputFile:\n\
+ def close(self):\n\
+ # Do nothing.\n\
+ return None\n\
+\n\
+ def isatty(self):\n\
+ return False\n\
+\n\
+ def write(self, s):\n\
+ gdb.write(s)\n\
+\n\
+ def writelines(self, iterable):\n\
+ for line in iterable:\n\
+ self.write(line)\n\
+\n\
+ def flush(self):\n\
+ gdb.flush()\n\
+\n\
+sys.stderr = GdbOutputFile()\n\
+sys.stdout = GdbOutputFile()\n\
+");
+#endif /* HAVE_PYTHON */
+}
Index: gdb.git/gdb/python/python.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gdb.git/gdb/python/python.h 2008-08-06 16:04:36.000000000 -0300
@@ -0,0 +1,27 @@
+/* Python/gdb header for generic use in gdb
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDB_PYTHON_H
+#define GDB_PYTHON_H
+
+#include "value.h"
+
+void eval_python_from_control_command (struct command_line *);
+
+#endif /* GDB_PYTHON_H */
Index: gdb.git/gdb/testsuite/gdb.python/python.exp
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gdb.git/gdb/testsuite/gdb.python/python.exp 2008-08-06 16:04:36.000000000 -0300
@@ -0,0 +1,66 @@
+# Copyright (C) 2008 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite. It tests the mechanism
+# exposing values to Python.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+gdb_test_multiple "python print 23" "verify python support" {
+ -re "not supported.*$gdb_prompt $" {
+ unsupported "python support is disabled"
+ return -1
+ }
+ -re "$gdb_prompt $" {}
+}
+
+# Usage: gdb_py_test_multiple NAME INPUT RESULT {INPUT RESULT}...
+# Run a test named NAME, consisting of multiple lines of input.
+# After each input line INPUT, search for result line RESULT.
+# Succeed if all results are seen; fail otherwise.
+proc gdb_py_test_multiple {name args} {
+ global gdb_prompt
+ foreach {input result} $args {
+ if {[gdb_test_multiple $input "$name - $input" {
+ -re "\[\r\n\]*($result)\[\r\n\]+($gdb_prompt | *>)$" {
+ pass "$name - $input"
+ }
+ }]} {
+ return 1
+ }
+ }
+ return 0
+}
+
+gdb_py_test_multiple "multi-line python command" \
+ "python" "" \
+ "print 23" "" \
+ "end" "23"
+
+gdb_py_test_multiple "show python command" \
+ "define zzq" "Type commands for definition of .* just \"end\"\\.*" \
+ "python" "" \
+ "print 23" "" \
+ "end" "" \
+ "end" "" \
+ "show user zzq" "User command zzq:.* python.*print 23.* end"
Index: gdb.git/gdb/config.in
===================================================================
--- gdb.git.orig/gdb/config.in 2008-08-06 16:16:01.000000000 -0300
+++ gdb.git/gdb/config.in 2008-08-06 16:23:30.000000000 -0300
@@ -184,6 +184,15 @@
/* Define to 1 if you have the `m' library (-lm). */
#undef HAVE_LIBM
+/* Define if Python 2.4 is being used. */
+#undef HAVE_LIBPYTHON2_4
+
+/* Define if Python 2.5 is being used. */
+#undef HAVE_LIBPYTHON2_5
+
+/* Define if Python 2.6 is being used. */
+#undef HAVE_LIBPYTHON2_6
+
/* Define if libunwind library is being used. */
#undef HAVE_LIBUNWIND
@@ -307,6 +316,9 @@
/* Define if sys/ptrace.h defines the PT_GETXMMREGS request. */
#undef HAVE_PT_GETXMMREGS
+/* Define if Python interpreter is being linked in. */
+#undef HAVE_PYTHON
+
/* Define to 1 if you have the `realpath' function. */
#undef HAVE_REALPATH
Index: gdb.git/gdb/configure
===================================================================
--- gdb.git.orig/gdb/configure 2008-08-06 16:15:58.000000000 -0300
+++ gdb.git/gdb/configure 2008-08-06 16:23:26.000000000 -0300
@@ -314,7 +314,7 @@ ac_subdirs_all="$ac_subdirs_all doc test
ac_subdirs_all="$ac_subdirs_all gdbtk"
ac_subdirs_all="$ac_subdirs_all multi-ice"
ac_subdirs_all="$ac_subdirs_all gdbserver"
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP RANLIB ac_ct_RANLIB build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT localedir GL_COND_LIBTOOL_TRUE GL_COND_LIBTOOL_FALSE GNULIB_MEMMEM GNULIB_MEMPCPY GNULIB_MEMRCHR GNULIB_STPCPY GNULIB_STPNCPY GNULIB_STRCHRNUL GNULIB_STRDUP GNULIB_STRNDUP GNULIB_STRNLEN GNULIB_STRPBRK GNULIB_STRSEP GNULIB_STRSTR GNULIB_STRCASESTR GNULIB_STRTOK_R GNULIB_MBSLEN GNULIB_MBSNLEN GNULIB_MBSCHR GNULIB_MBSRCHR GNULIB_MBSSTR GNULIB_MBSCASECMP GNULIB_MBSNCASECMP GNULIB_MBSPCASECMP GNULIB_MBSCASESTR GNULIB_MBSCSPN GNULIB_MBSPBRK GNULIB_MBSSPN GNULIB_MBSSEP GNULIB_MBSTOK_R GNULIB_STRERROR GNULIB_STRSIGNAL HAVE_DECL_MEMMEM HAVE_MEMPCPY HAVE_DECL_MEMRCHR HAVE_STPCPY HAVE_STPNCPY HAVE_STRCHRNUL HAVE_DECL_STRDUP HAVE_STRNDUP HAVE_DECL_STRNDUP HAVE_DECL_STRNLEN HAVE_STRPBRK HAVE_STRSEP HAVE_STRCASESTR HAVE_DECL_STRTOK_R HAVE_DECL_STRERROR HAVE_DECL_STRSIGNAL REPLACE_STRERROR REPLACE_STRSIGNAL REPLACE_MEMMEM REPLACE_STRCASESTR REPLACE_STRSTR HAVE_LONG_LONG_INT HAVE_UNSIGNED_LONG_LONG_INT HAVE_INTTYPES_H HAVE_SYS_TYPES_H INCLUDE_NEXT NEXT_STDINT_H HAVE_STDINT_H HAVE_SYS_INTTYPES_H HAVE_SYS_BITYPES_H BITSIZEOF_PTRDIFF_T BITSIZEOF_SIG_ATOMIC_T BITSIZEOF_SIZE_T BITSIZEOF_WCHAR_T BITSIZEOF_WINT_T HAVE_SIGNED_SIG_ATOMIC_T HAVE_SIGNED_WCHAR_T HAVE_SIGNED_WINT_T PTRDIFF_T_SUFFIX SIG_ATOMIC_T_SUFFIX SIZE_T_SUFFIX WCHAR_T_SUFFIX WINT_T_SUFFIX STDINT_H NEXT_STRING_H GNULIB_WCWIDTH HAVE_DECL_WCWIDTH REPLACE_WCWIDTH WCHAR_H HAVE_WCHAR_H NEXT_WCHAR_H LIBGNU_LIBDEPS LIBGNU_LTLIBDEPS GNULIB_STDINT_H PACKAGE INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE subdirs TARGET_OBS PKGVERSION REPORT_BUGS_TO REPORT_BUGS_TEXI LN_S YACC AR ac_ct_AR DLLTOOL ac_ct_DLLTOOL WINDRES ac_ct_WINDRES MIG ac_ct_MIG READLINE READLINE_DEPS READLINE_CFLAGS HAVE_LIBEXPAT LIBEXPAT LTLIBEXPAT ALLOCA CONFIG_LDFLAGS TARGET_SYSTEM_ROOT TARGET_SYSTEM_ROOT_DEFINE WARN_CFLAGS WERROR_CFLAGS SER_HARDWIRE WIN32LIBS LIBGUI GUI_CFLAGS_X WIN32LDAPP TCL_VERSION TCL_PATCH_LEVEL TCL_BIN_DIR TCL_SRC_DIR TCL_LIB_FILE TCL_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC TCL_INCLUDE TCL_LIBRARY TCL_DEPS TK_VERSION TK_BIN_DIR TK_SRC_DIR TK_LIB_FILE TK_LIB_FLAG TK_LIB_SPEC TK_STUB_LIB_FILE TK_STUB_LIB_FLAG TK_STUB_LIB_SPEC TK_INCLUDE TK_LIBRARY TK_DEPS TK_XINCLUDES X_CFLAGS X_LDFLAGS X_LIBS GDBTKLIBS GDBTK_CFLAGS GDBTK_SRC_DIR SIM SIM_OBS ENABLE_CFLAGS PROFILE_CFLAGS CONFIG_OBS CONFIG_DEPS CONFIG_SRCS CONFIG_ALL CONFIG_CLEAN CONFIG_INSTALL CONFIG_UNINSTALL target_subdir frags nm_h LIBICONV LIBOBJS LTLIBOBJS gl_LIBOBJS gl_LTLIBOBJS gltests_LIBOBJS gltests_LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP RANLIB ac_ct_RANLIB build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT localedir GL_COND_LIBTOOL_TRUE GL_COND_LIBTOOL_FALSE GNULIB_MEMMEM GNULIB_MEMPCPY GNULIB_MEMRCHR GNULIB_STPCPY GNULIB_STPNCPY GNULIB_STRCHRNUL GNULIB_STRDUP GNULIB_STRNDUP GNULIB_STRNLEN GNULIB_STRPBRK GNULIB_STRSEP GNULIB_STRSTR GNULIB_STRCASESTR GNULIB_STRTOK_R GNULIB_MBSLEN GNULIB_MBSNLEN GNULIB_MBSCHR GNULIB_MBSRCHR GNULIB_MBSSTR GNULIB_MBSCASECMP GNULIB_MBSNCASECMP GNULIB_MBSPCASECMP GNULIB_MBSCASESTR GNULIB_MBSCSPN GNULIB_MBSPBRK GNULIB_MBSSPN GNULIB_MBSSEP GNULIB_MBSTOK_R GNULIB_STRERROR GNULIB_STRSIGNAL HAVE_DECL_MEMMEM HAVE_MEMPCPY HAVE_DECL_MEMRCHR HAVE_STPCPY HAVE_STPNCPY HAVE_STRCHRNUL HAVE_DECL_STRDUP HAVE_STRNDUP HAVE_DECL_STRNDUP HAVE_DECL_STRNLEN HAVE_STRPBRK HAVE_STRSEP HAVE_STRCASESTR HAVE_DECL_STRTOK_R HAVE_DECL_STRERROR HAVE_DECL_STRSIGNAL REPLACE_STRERROR REPLACE_STRSIGNAL REPLACE_MEMMEM REPLACE_STRCASESTR REPLACE_STRSTR HAVE_LONG_LONG_INT HAVE_UNSIGNED_LONG_LONG_INT HAVE_INTTYPES_H HAVE_SYS_TYPES_H INCLUDE_NEXT NEXT_STDINT_H HAVE_STDINT_H HAVE_SYS_INTTYPES_H HAVE_SYS_BITYPES_H BITSIZEOF_PTRDIFF_T BITSIZEOF_SIG_ATOMIC_T BITSIZEOF_SIZE_T BITSIZEOF_WCHAR_T BITSIZEOF_WINT_T HAVE_SIGNED_SIG_ATOMIC_T HAVE_SIGNED_WCHAR_T HAVE_SIGNED_WINT_T PTRDIFF_T_SUFFIX SIG_ATOMIC_T_SUFFIX SIZE_T_SUFFIX WCHAR_T_SUFFIX WINT_T_SUFFIX STDINT_H NEXT_STRING_H GNULIB_WCWIDTH HAVE_DECL_WCWIDTH REPLACE_WCWIDTH WCHAR_H HAVE_WCHAR_H NEXT_WCHAR_H LIBGNU_LIBDEPS LIBGNU_LTLIBDEPS GNULIB_STDINT_H PACKAGE INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE subdirs TARGET_OBS PKGVERSION REPORT_BUGS_TO REPORT_BUGS_TEXI LN_S YACC AR ac_ct_AR DLLTOOL ac_ct_DLLTOOL WINDRES ac_ct_WINDRES MIG ac_ct_MIG READLINE READLINE_DEPS READLINE_CFLAGS HAVE_LIBEXPAT LIBEXPAT LTLIBEXPAT PYTHON_CFLAGS ALLOCA CONFIG_LDFLAGS TARGET_SYSTEM_ROOT TARGET_SYSTEM_ROOT_DEFINE WARN_CFLAGS WERROR_CFLAGS SER_HARDWIRE WIN32LIBS LIBGUI GUI_CFLAGS_X WIN32LDAPP TCL_VERSION TCL_PATCH_LEVEL TCL_BIN_DIR TCL_SRC_DIR TCL_LIB_FILE TCL_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC TCL_INCLUDE TCL_LIBRARY TCL_DEPS TK_VERSION TK_BIN_DIR TK_SRC_DIR TK_LIB_FILE TK_LIB_FLAG TK_LIB_SPEC TK_STUB_LIB_FILE TK_STUB_LIB_FLAG TK_STUB_LIB_SPEC TK_INCLUDE TK_LIBRARY TK_DEPS TK_XINCLUDES X_CFLAGS X_LDFLAGS X_LIBS GDBTKLIBS GDBTK_CFLAGS GDBTK_SRC_DIR SIM SIM_OBS ENABLE_CFLAGS PROFILE_CFLAGS CONFIG_OBS CONFIG_DEPS CONFIG_SRCS CONFIG_ALL CONFIG_CLEAN CONFIG_INSTALL CONFIG_UNINSTALL target_subdir frags nm_h LIBICONV LIBOBJS LTLIBOBJS gl_LIBOBJS gl_LTLIBOBJS gltests_LIBOBJS gltests_LTLIBOBJS'
ac_subst_files='host_makefile_frag'
ac_pwd=`pwd`
@@ -890,6 +890,7 @@ Optional Packages:
--with-gnu-ld assume the C compiler uses GNU ld default=no
--with-libexpat-prefix[=DIR] search for libexpat in DIR/include and DIR/lib
--without-libexpat-prefix don't search for libexpat in includedir and libdir
+ --with-python include python support (auto/yes/no/<path>)
--without-included-regex don't use included regex; this is the default
on systems with version 2 of the GNU C library
(use with caution on other system)
@@ -11197,6 +11198,358 @@ done
fi
fi
+
+
+
+# Check whether --with-python or --without-python was given.
+if test "${with_python+set}" = set; then
+ withval="$with_python"
+
+else
+ with_python=auto
+fi;
+echo "$as_me:$LINENO: checking whether to use python" >&5
+echo $ECHO_N "checking whether to use python... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $with_python" >&5
+echo "${ECHO_T}$with_python" >&6
+
+if test "${with_python}" = no; then
+ { echo "$as_me:$LINENO: WARNING: python support disabled; some features may be unavailable." >&5
+echo "$as_me: WARNING: python support disabled; some features may be unavailable." >&2;}
+ have_libpython=no
+else
+ case "${with_python}" in
+ yes | auto)
+ # Leave as empty, use defaults.
+ python_includes=
+ python_libs=
+ ;;
+ /*)
+ python_includes="-I${with_python}/include"
+ python_libs="-L${with_python}/lib"
+ ;;
+ *)
+ { { echo "$as_me:$LINENO: error: invalid value for --with-python" >&5
+echo "$as_me: error: invalid value for --with-python" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ esac
+
+ save_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS ${python_includes}"
+ save_LIBS=$LIBS
+ LIBS="$LIBS ${python_libs}"
+ have_libpython=no
+ if test "${have_libpython}" = no; then
+
+ version=python2.6
+
+
+ HAVE_LIBPYTHON2_6=no
+ echo "$as_me:$LINENO: checking for ${version}" >&5
+echo $ECHO_N "checking for ${version}... $ECHO_C" >&6
+ save_LIBS=$LIBS
+ LIBS="$LIBS -l${version}"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include "${version}/Python.h"
+int
+main ()
+{
+Py_Initialize ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ HAVE_LIBPYTHON2_6=yes
+ have_libpython=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+LIBS=$save_LIBS
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ echo "$as_me:$LINENO: result: $HAVE_LIBPYTHON2_6" >&5
+echo "${ECHO_T}$HAVE_LIBPYTHON2_6" >&6
+
+ if test "${HAVE_LIBPYTHON2_6}" = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBPYTHON2_6 1
+_ACEOF
+
+ fi
+ fi
+ if test ${have_libpython} = no; then
+
+ version=python2.5
+
+
+ HAVE_LIBPYTHON2_5=no
+ echo "$as_me:$LINENO: checking for ${version}" >&5
+echo $ECHO_N "checking for ${version}... $ECHO_C" >&6
+ save_LIBS=$LIBS
+ LIBS="$LIBS -l${version}"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include "${version}/Python.h"
+int
+main ()
+{
+Py_Initialize ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ HAVE_LIBPYTHON2_5=yes
+ have_libpython=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+LIBS=$save_LIBS
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ echo "$as_me:$LINENO: result: $HAVE_LIBPYTHON2_5" >&5
+echo "${ECHO_T}$HAVE_LIBPYTHON2_5" >&6
+
+ if test "${HAVE_LIBPYTHON2_5}" = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBPYTHON2_5 1
+_ACEOF
+
+ fi
+ fi
+ if test ${have_libpython} = no; then
+
+ version=python2.4
+
+
+ HAVE_LIBPYTHON2_4=no
+ echo "$as_me:$LINENO: checking for ${version}" >&5
+echo $ECHO_N "checking for ${version}... $ECHO_C" >&6
+ save_LIBS=$LIBS
+ LIBS="$LIBS -l${version}"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include "${version}/Python.h"
+int
+main ()
+{
+Py_Initialize ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ HAVE_LIBPYTHON2_4=yes
+ have_libpython=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+LIBS=$save_LIBS
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ echo "$as_me:$LINENO: result: $HAVE_LIBPYTHON2_4" >&5
+echo "${ECHO_T}$HAVE_LIBPYTHON2_4" >&6
+
+ if test "${HAVE_LIBPYTHON2_4}" = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBPYTHON2_4 1
+_ACEOF
+
+ fi
+ fi
+ if test ${have_libpython} = no; then
+ case "${with_python}" in
+ yes)
+ { { echo "$as_me:$LINENO: error: python is missing or unusable" >&5
+echo "$as_me: error: python is missing or unusable" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ auto)
+ { echo "$as_me:$LINENO: WARNING: python is missing or unusable; some features may be unavailable." >&5
+echo "$as_me: WARNING: python is missing or unusable; some features may be unavailable." >&2;}
+ ;;
+ *)
+ { { echo "$as_me:$LINENO: error: no usable python found at ${with_python}" >&5
+echo "$as_me: error: no usable python found at ${with_python}" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ esac
+ CPPFLAGS=$save_CPPFLAGS
+ LIBS=$save_LIBS
+ fi
+fi
+
+if test "${have_libpython}" = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_PYTHON 1
+_ACEOF
+
+ CONFIG_OBS="$CONFIG_OBS \$(SUBDIR_PYTHON_OBS)"
+ CONFIG_DEPS="$CONFIG_DEPS \$(SUBDIR_PYTHON_DEPS)"
+ CONFIG_SRCS="$CONFIG_SRCS \$(SUBDIR_PYTHON_SRCS)"
+ ENABLE_CFLAGS="$ENABLE_CFLAGS \$(SUBDIR_PYTHON_CFLAGS)"
+
+ # Flags needed to compile Python code (taken from python-config --cflags).
+ # We cannot call python-config directly because it will output whatever was
+ # used when compiling the Python interpreter itself, including flags which
+ # would make the python-related objects be compiled differently from the
+ # rest of GDB (e.g., -O2 and -fPIC).
+ if test "${GCC}" = yes; then
+ tentative_python_cflags="-fno-strict-aliasing -DNDEBUG -fwrapv"
+ fi
+
+ if test "x${tentative_python_cflags}" != x; then
+ echo "$as_me:$LINENO: checking compiler flags for python code" >&5
+echo $ECHO_N "checking compiler flags for python code... $ECHO_C" >&6
+ for flag in ${tentative_python_cflags}; do
+ # Check that the compiler accepts it
+ saved_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $flag"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ PYTHON_CFLAGS="${PYTHON_CFLAGS} $flag"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$saved_CFLAGS"
+ done
+ echo "$as_me:$LINENO: result: ${PYTHON_CFLAGS}" >&5
+echo "${ECHO_T}${PYTHON_CFLAGS}" >&6
+ fi
+else
+ # Even if Python support is not compiled in, we need to have this file
+ # included in order to recognize the GDB command "python".
+ CONFIG_OBS="$CONFIG_OBS python.o"
+ CONFIG_SRCS="$CONFIG_SRCS python/python.c"
+fi
+
+
# ------------------------- #
# Checks for header files. #
# ------------------------- #
@@ -26284,7 +26637,7 @@ s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t
s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
s,@INSTALL_DATA@,$INSTALL_DATA,;t t
s,@CYGPATH_W@,$CYGPATH_W,;t t
-s,@VERSION@,$VERSION,;t t
+s,@PYTHON2_4@,$PYTHON2_4,;t t
s,@ACLOCAL@,$ACLOCAL,;t t
s,@AUTOCONF@,$AUTOCONF,;t t
s,@AUTOMAKE@,$AUTOMAKE,;t t
@@ -26331,6 +26684,7 @@ s,@READLINE_CFLAGS@,$READLINE_CFLAGS,;t
s,@HAVE_LIBEXPAT@,$HAVE_LIBEXPAT,;t t
s,@LIBEXPAT@,$LIBEXPAT,;t t
s,@LTLIBEXPAT@,$LTLIBEXPAT,;t t
+s,@PYTHON_CFLAGS@,$PYTHON_CFLAGS,;t t
s,@ALLOCA@,$ALLOCA,;t t
s,@CONFIG_LDFLAGS@,$CONFIG_LDFLAGS,;t t
s,@TARGET_SYSTEM_ROOT@,$TARGET_SYSTEM_ROOT,;t t
^ permalink raw reply [flat|nested] 147+ messages in thread
* [python] acessing struct elements
2008-07-07 6:03 ` Thiago Jung Bauermann
2008-07-07 23:44 ` Tom Tromey
@ 2008-08-13 6:45 ` Thiago Jung Bauermann
2008-08-13 12:38 ` Daniel Jacobowitz
2008-08-17 20:16 ` Tom Tromey
1 sibling, 2 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-08-13 6:45 UTC (permalink / raw)
To: gdb-patches
Thiago Jung Bauermann wrote:
> In the case of valpy_get_element (which is used to access an element in
> a value representing a struct or class), using __getitem__ means that in
> Python one would use a_struct["element"] to access a_struct.element.
There's one unexpected consequence of this: to enable the syntax above, all
gdb.Value objects need to implement the map methods, and Python considers
empty maps to be False in contexts which expect a boolean. Because of this,
the following will not generally work:
val = frame.read_var_value (sym)
if val:
print "Variable value is: " + str (val)
else:
print "Variable not found."
Instead, one needs to explicitly compare with None:
val = frame.read_var_value (sym)
if val != None:
print "Variable value is: " + str (val)
else:
print "Variable not found."
I believe the same problem can happen with values representing numbers,
since Python also considers 0 to be False. I didn't test that, though.
We can keep going with this approach, and warn users that they need to
explicitly compare gdb.Value with None instead of relying on Python
implicit rules for boolean evaluation. Is this acceptable?
Or we can create an element of gdb.Value which would provide access to the
actual value, so one would say something like a_struct.val["element"] (or
do math using a_number.val, in the case of numeric values). While we are at
it ...
> It would be possible to make this
> case work more like a real struct, by intercepting python object
> accesses to attributes. Then one could have a_struct.element work for
> gdb.Values.
... we can implement this alternative (e.g., a_struct.val.element), since we
wouldn't have to worry anymore about confusing struct elements with
gdb.Value methods.
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [python] acessing struct elements
2008-08-13 6:45 ` [python] acessing struct elements Thiago Jung Bauermann
@ 2008-08-13 12:38 ` Daniel Jacobowitz
2008-08-13 20:38 ` Thiago Jung Bauermann
2008-08-17 20:16 ` Tom Tromey
1 sibling, 1 reply; 147+ messages in thread
From: Daniel Jacobowitz @ 2008-08-13 12:38 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
On Wed, Aug 13, 2008 at 01:46:53AM -0300, Thiago Jung Bauermann wrote:
> There's one unexpected consequence of this: to enable the syntax above, all
> gdb.Value objects need to implement the map methods, and Python considers
> empty maps to be False in contexts which expect a boolean. Because of this,
> the following will not generally work:
>
> val = frame.read_var_value (sym)
> if val:
> print "Variable value is: " + str (val)
> else:
> print "Variable not found."
It took me a while to find it, but I knew there was an operator for
this. Take a look at __nonzero__:
http://docs.python.org/ref/customization.html
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [python] acessing struct elements
2008-08-13 12:38 ` Daniel Jacobowitz
@ 2008-08-13 20:38 ` Thiago Jung Bauermann
0 siblings, 0 replies; 147+ messages in thread
From: Thiago Jung Bauermann @ 2008-08-13 20:38 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb-patches
On Wed, 2008-08-13 at 08:37 -0400, Daniel Jacobowitz wrote:
> It took me a while to find it, but I knew there was an operator for
> this. Take a look at __nonzero__:
>
> http://docs.python.org/ref/customization.html
Thanks for the tip! I'll try it out.
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 147+ messages in thread
* Re: [python] acessing struct elements
2008-08-13 6:45 ` [python] acessing struct elements Thiago Jung Bauermann
2008-08-13 12:38 ` Daniel Jacobowitz
@ 2008-08-17 20:16 ` Tom Tromey
1 sibling, 0 replies; 147+ messages in thread
From: Tom Tromey @ 2008-08-17 20:16 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
>>>>> "Thiago" == Thiago Jung Bauermann <bauerman@br.ibm.com> writes:
Thiago> There's one unexpected consequence of this: to enable the
Thiago> syntax above, all gdb.Value objects need to implement the map
Thiago> methods, and Python considers empty maps to be False in
Thiago> contexts which expect a boolean. Because of this, the
Thiago> following will not generally work:
Thiago> val = frame.read_var_value (sym)
Thiago> if val:
Thiago> print "Variable value is: " + str (val)
I think read_var_value should throw an exception if the symbol is not
found. My reason is that this is an error condition -- the caller has
asked for a symbol that does not exist. (Actually, I was assuming
this is what we'd do, but I realize now that this was just an
assumption :)
This would bypass this particular problem here. I have a feeling
there might be other similar problems lurking, but I'm not sure what.
Tom
^ permalink raw reply [flat|nested] 147+ messages in thread
end of thread, other threads:[~2008-08-17 20:16 UTC | newest]
Thread overview: 147+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-04-29 15:59 [RFC][patch 0/9] Python support in GDB Thiago Jung Bauermann
2008-04-29 15:59 ` [RFC][patch 8/9] export symtab mechanism to Python Thiago Jung Bauermann
2008-04-29 15:59 ` [RFC][patch 6/9] export frames " Thiago Jung Bauermann
2008-04-29 15:59 ` [RFC][patch 9/9] export threads " Thiago Jung Bauermann
2008-04-29 15:59 ` [RFC][patch 3/9] export hooks mechanism " Thiago Jung Bauermann
2008-04-29 21:29 ` Tom Tromey
2008-04-30 18:27 ` Joel Brobecker
2008-04-30 21:30 ` Tom Tromey
2008-05-27 18:22 ` Tom Tromey
2008-04-30 18:29 ` Daniel Jacobowitz
2008-04-30 23:00 ` Tom Tromey
2008-05-29 7:55 ` Daniel Jacobowitz
2008-05-30 14:59 ` Tom Tromey
2008-06-15 22:53 ` Thiago Jung Bauermann
2008-06-15 22:58 ` Tom Tromey
2008-06-16 3:22 ` Daniel Jacobowitz
2008-06-17 18:13 ` Thiago Jung Bauermann
2008-06-17 22:20 ` Joel Brobecker
2008-06-23 17:58 ` Tom Tromey
2008-04-29 15:59 ` [RFC][patch 5/9] permit GDB commands implemented in Python Thiago Jung Bauermann
2008-04-29 16:08 ` [RFC][patch 7/9] export block and symbol mechanism to Python Thiago Jung Bauermann
2008-04-29 18:11 ` [RFC][patch 4/9] export breakpoints " Thiago Jung Bauermann
2008-04-29 18:15 ` [RFC][patch 1/9] initial Python support Thiago Jung Bauermann
2008-05-05 8:12 ` Thiago Jung Bauermann
2008-05-05 14:39 ` Daniel Jacobowitz
2008-05-05 14:46 ` Thiago Jung Bauermann
2008-05-05 16:50 ` Daniel Jacobowitz
2008-05-06 2:38 ` Thiago Jung Bauermann
2008-05-11 22:24 ` Thiago Jung Bauermann
2008-05-11 22:26 ` Daniel Jacobowitz
2008-05-12 20:33 ` Thiago Jung Bauermann
2008-05-12 20:39 ` Daniel Jacobowitz
2008-05-12 21:00 ` Thiago Jung Bauermann
2008-05-29 0:29 ` Daniel Jacobowitz
2008-05-30 13:07 ` Function syntax (Was: [RFC][patch 1/9] initial Python support) Tom Tromey
2008-06-08 15:24 ` Doug Evans
2008-06-08 15:32 ` Function syntax Tom Tromey
2008-06-08 18:21 ` Function syntax (Was: [RFC][patch 1/9] initial Python support) Daniel Jacobowitz
2008-06-09 13:48 ` Thiago Jung Bauermann
2008-06-09 18:43 ` Daniel Jacobowitz
2008-06-10 0:24 ` Function syntax Tom Tromey
2008-06-10 0:04 ` Tom Tromey
2008-06-11 0:04 ` Thiago Jung Bauermann
2008-06-10 0:00 ` Tom Tromey
2008-05-30 14:47 ` [RFC][patch 1/9] initial Python support Tom Tromey
2008-06-15 22:35 ` thiagoju
2008-06-23 17:36 ` Tom Tromey
2008-07-06 17:28 ` Tom Tromey
2008-07-08 4:12 ` Thiago Jung Bauermann
2008-07-15 7:38 ` [RFA] " Thiago Jung Bauermann
2008-07-15 17:19 ` Tom Tromey
2008-07-15 18:33 ` Thiago Jung Bauermann
2008-07-15 19:03 ` Tom Tromey
2008-07-16 7:14 ` Thiago Jung Bauermann
2008-07-16 14:39 ` Tom Tromey
2008-07-16 22:02 ` Thiago Jung Bauermann
2008-07-18 19:50 ` Daniel Jacobowitz
2008-07-18 23:24 ` Tom Tromey
2008-07-19 0:45 ` Daniel Jacobowitz
2008-07-19 19:50 ` [RFA] iRe: " Thiago Jung Bauermann
2008-07-19 21:13 ` Daniel Jacobowitz
2008-07-19 22:13 ` Thiago Jung Bauermann
2008-07-20 23:47 ` Thiago Jung Bauermann
2008-07-21 2:03 ` Daniel Jacobowitz
2008-07-23 17:46 ` [obvious] Wipe out CONFIG_INITS Thiago Jung Bauermann
2008-07-20 22:43 ` [RFA] Re: [RFC][patch 1/9] initial Python support Tom Tromey
2008-07-21 1:59 ` Daniel Jacobowitz
2008-07-21 15:29 ` [RFA][patch 1/9] Yet another respin of the patch with " Thiago Jung Bauermann
2008-07-21 16:47 ` Thiago Jung Bauermann
2008-07-26 13:07 ` Eli Zaretskii
2008-07-26 13:43 ` Daniel Jacobowitz
2008-07-26 14:02 ` Eli Zaretskii
2008-07-26 14:42 ` Daniel Jacobowitz
2008-07-26 17:06 ` Eli Zaretskii
2008-07-26 17:26 ` Tom Tromey
2008-07-26 19:21 ` Eli Zaretskii
2008-07-26 17:40 ` Daniel Jacobowitz
2008-07-26 17:10 ` Tom Tromey
2008-07-26 17:40 ` Eli Zaretskii
2008-07-26 18:00 ` Tom Tromey
2008-07-26 18:29 ` Eli Zaretskii
2008-07-26 18:45 ` Tom Tromey
2008-07-26 19:34 ` Eli Zaretskii
2008-07-30 14:59 ` Thiago Jung Bauermann
2008-07-30 17:57 ` Eli Zaretskii
2008-08-04 4:44 ` Thiago Jung Bauermann
2008-08-04 19:18 ` Eli Zaretskii
2008-08-05 3:42 ` Thiago Jung Bauermann
2008-07-26 17:04 ` Tom Tromey
2008-07-26 17:35 ` Daniel Jacobowitz
2008-07-26 17:42 ` Tom Tromey
2008-07-26 19:18 ` Eli Zaretskii
2008-08-04 2:52 ` Thiago Jung Bauermann
2008-08-04 3:22 ` Eli Zaretskii
2008-08-04 12:15 ` Daniel Jacobowitz
2008-08-04 19:50 ` Eli Zaretskii
2008-08-05 2:08 ` Daniel Jacobowitz
2008-08-05 2:41 ` Thiago Jung Bauermann
2008-08-05 3:32 ` Eli Zaretskii
2008-08-05 12:19 ` Daniel Jacobowitz
2008-08-05 18:10 ` Eli Zaretskii
2008-08-05 18:23 ` Daniel Jacobowitz
2008-08-05 18:50 ` Eli Zaretskii
2008-08-05 18:58 ` Daniel Jacobowitz
2008-07-26 19:20 ` Eli Zaretskii
2008-07-26 18:11 ` Eli Zaretskii
2008-07-26 18:30 ` Daniel Jacobowitz
2008-07-26 19:26 ` Eli Zaretskii
2008-08-01 20:04 ` Tom Tromey
2008-08-02 17:38 ` Daniel Jacobowitz
2008-08-02 17:50 ` Tom Tromey
2008-08-02 19:00 ` Eli Zaretskii
2008-08-05 4:19 ` Thiago Jung Bauermann
2008-08-05 18:14 ` Eli Zaretskii
2008-08-06 5:35 ` [RFA][patch 1/9] Initial Python support, patch du jour Thiago Jung Bauermann
2008-08-06 18:24 ` Eli Zaretskii
2008-08-06 19:53 ` Thiago Jung Bauermann
2008-08-04 4:44 ` [RFA][patch 1/9] Yet another respin of the patch with initial Python support Thiago Jung Bauermann
2008-08-04 19:22 ` Eli Zaretskii
2008-08-05 1:24 ` Thiago Jung Bauermann
2008-08-02 17:41 ` Daniel Jacobowitz
2008-08-02 19:02 ` Eli Zaretskii
2008-08-02 19:07 ` Daniel Jacobowitz
2008-07-15 18:01 ` [RFA] Re: [RFC][patch 1/9] " Thiago Jung Bauermann
2008-04-29 18:17 ` [RFC][patch 2/9] export values mechanism to Python Thiago Jung Bauermann
2008-05-29 1:23 ` Daniel Jacobowitz
2008-06-03 0:19 ` Tom Tromey
2008-06-03 13:04 ` Daniel Jacobowitz
2008-06-03 14:52 ` Tom Tromey
2008-07-07 6:03 ` Thiago Jung Bauermann
2008-07-07 23:44 ` Tom Tromey
2008-07-26 2:55 ` Daniel Jacobowitz
2008-07-26 17:17 ` Tom Tromey
2008-07-26 17:41 ` Daniel Jacobowitz
2008-07-30 3:01 ` Tom Tromey
2008-07-30 14:26 ` Thiago Jung Bauermann
2008-08-13 6:45 ` [python] acessing struct elements Thiago Jung Bauermann
2008-08-13 12:38 ` Daniel Jacobowitz
2008-08-13 20:38 ` Thiago Jung Bauermann
2008-08-17 20:16 ` Tom Tromey
2008-04-29 18:38 ` [RFC][patch 0/9] Python support in GDB Eli Zaretskii
2008-04-29 20:37 ` Thiago Jung Bauermann
2008-04-29 21:22 ` Tom Tromey
2008-04-30 7:54 ` Eli Zaretskii
2008-04-30 19:38 ` Thiago Jung Bauermann
2008-04-30 19:52 ` Eli Zaretskii
2008-05-02 18:30 ` Vladimir Prus
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox