diff options
author | Tom Tromey <tromey@redhat.com> | 2009-05-28 00:40:24 +0000 |
---|---|---|
committer | Tom Tromey <tromey@redhat.com> | 2009-05-28 00:40:24 +0000 |
commit | 89c73adef9f9fac7e1efeb6961a867f46e54e24b (patch) | |
tree | a1023e41bebc2f1ce3cf04909ee2cce0a3a6f706 /gdb/python | |
parent | 58683880f52b1ae4b0233ea1565e7ee39a36b9b0 (diff) | |
download | fsf-binutils-gdb-89c73adef9f9fac7e1efeb6961a867f46e54e24b.zip fsf-binutils-gdb-89c73adef9f9fac7e1efeb6961a867f46e54e24b.tar.gz fsf-binutils-gdb-89c73adef9f9fac7e1efeb6961a867f46e54e24b.tar.bz2 |
gdb
2009-04-01 Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
Phil Muldoon <pmuldoon@redhat.com>
* python/python.c: Include objfiles.h, observer.h.
(gdbpy_auto_load): New global.
(gdbpy_current_objfile): Likewise.
(GDBPY_AUTO_FILENAME): New define.
(gdbpy_new_objfile): New function.
(gdbpy_get_current_objfile): Likewise.
(gdbpy_objfiles): Likewise.
(_initialize_python): Add "maint set auto-load". Call
gdbpy_initialize_objfile. Attach objfile observer.
(GdbMethods): New methods current_objfile, objfiles.
* python/python-objfile.c: New file.
* python/python-internal.h (objfile_to_objfile_object): Declare.
(objfpy_get_printers): Likewise.
(gdbpy_initialize_objfile): Likewise.
* Makefile.in (SUBDIR_PYTHON_OBS): Add python-objfile.o.
(SUBDIR_PYTHON_SRCS): Add python-objfile.c.
(python-objfile.o): New target.
gdb/doc
2009-04-01 Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
* gdb.texinfo (Python API): Update.
(Auto-loading): New node.
(Objfiles In Python): New node.
gdb/testsuite
2009-04-06 Tom Tromey <tromey@redhat.com>
* gdb.python/python.exp (gdb_py_test_multiple): Add two objfile
tests.
* gdb.python/python-value.exp (py_objfile_tests): New proc.
Call it.
Diffstat (limited to 'gdb/python')
-rw-r--r-- | gdb/python/python-internal.h | 4 | ||||
-rw-r--r-- | gdb/python/python-objfile.c | 229 | ||||
-rw-r--r-- | gdb/python/python.c | 146 |
3 files changed, 379 insertions, 0 deletions
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index f8d0896..f16b509 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -68,6 +68,9 @@ PyObject *gdbpy_frame_stop_reason_string (PyObject *, PyObject *); PyObject *gdbpy_selected_frame (PyObject *self, PyObject *args); PyObject *value_to_value_object (struct value *v); +PyObject *objfile_to_objfile_object (struct objfile *); + +PyObject *objfpy_get_printers (PyObject *, void *); struct value *convert_value_from_python (PyObject *obj); @@ -75,6 +78,7 @@ void gdbpy_initialize_values (void); void gdbpy_initialize_frames (void); void gdbpy_initialize_commands (void); void gdbpy_initialize_functions (void); +void gdbpy_initialize_objfile (void); struct cleanup *make_cleanup_py_decref (PyObject *py); struct cleanup *make_cleanup_py_restore_gil (PyGILState_STATE *state); diff --git a/gdb/python/python-objfile.c b/gdb/python/python-objfile.c new file mode 100644 index 0000000..b70a006 --- /dev/null +++ b/gdb/python/python-objfile.c @@ -0,0 +1,229 @@ +/* Python interface to objfiles. + + Copyright (C) 2008, 2009 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-internal.h" +#include "charset.h" +#include "objfiles.h" + +typedef struct +{ + PyObject_HEAD + + /* The corresponding objfile. */ + struct objfile *objfile; + + /* The pretty-printer list of functions. */ + PyObject *printers; +} objfile_object; + +static PyTypeObject objfile_object_type; + +static const struct objfile_data *objfpy_objfile_data_key; + + + +/* An Objfile method which returns the objfile's file name, or None. */ +static PyObject * +objfpy_get_filename (PyObject *self, void *closure) +{ + objfile_object *obj = (objfile_object *) self; + if (obj->objfile && obj->objfile->name) + return PyString_Decode (obj->objfile->name, strlen (obj->objfile->name), + host_charset (), NULL); + Py_RETURN_NONE; +} + +static void +objfpy_dealloc (PyObject *o) +{ + objfile_object *self = (objfile_object *) o; + Py_XDECREF (self->printers); + self->ob_type->tp_free ((PyObject *) self); +} + +static PyObject * +objfpy_new (PyTypeObject *type, PyObject *args, PyObject *keywords) +{ + objfile_object *self = (objfile_object *) type->tp_alloc (type, 0); + if (self) + { + self->objfile = NULL; + + self->printers = PyList_New (0); + if (!self->printers) + { + Py_DECREF (self); + return NULL; + } + } + return (PyObject *) self; +} + +PyObject * +objfpy_get_printers (PyObject *o, void *ignore) +{ + objfile_object *self = (objfile_object *) o; + Py_INCREF (self->printers); + return self->printers; +} + +static int +objfpy_set_printers (PyObject *o, PyObject *value, void *ignore) +{ + PyObject *tmp; + objfile_object *self = (objfile_object *) o; + if (! value) + { + PyErr_SetString (PyExc_TypeError, + "cannot delete the pretty_printers attribute"); + return -1; + } + + if (! PyList_Check (value)) + { + PyErr_SetString (PyExc_TypeError, + "the pretty_printers attribute must be a list"); + return -1; + } + + /* Take care in case the LHS and RHS are related somehow. */ + tmp = self->printers; + Py_INCREF (value); + self->printers = value; + Py_XDECREF (tmp); + + return 0; +} + + + +/* Clear the OBJFILE pointer in an Objfile object and remove the + reference. */ +static void +clean_up_objfile (struct objfile *objfile, void *datum) +{ + PyGILState_STATE state; + objfile_object *object = datum; + + state = PyGILState_Ensure (); + object->objfile = NULL; + Py_DECREF ((PyObject *) object); + PyGILState_Release (state); +} + +/* Return a borrowed reference to the Python object of type Objfile + representing OBJFILE. If the object has already been created, + return it. Otherwise, create it. Return NULL and set the Python + error on failure. */ +PyObject * +objfile_to_objfile_object (struct objfile *objfile) +{ + objfile_object *object; + + object = objfile_data (objfile, objfpy_objfile_data_key); + if (!object) + { + object = PyObject_New (objfile_object, &objfile_object_type); + if (object) + { + PyObject *dict; + + object->objfile = objfile; + + object->printers = PyList_New (0); + if (!object->printers) + { + Py_DECREF (object); + return NULL; + } + + set_objfile_data (objfile, objfpy_objfile_data_key, object); + } + } + + return (PyObject *) object; +} + +void +gdbpy_initialize_objfile (void) +{ + objfpy_objfile_data_key + = register_objfile_data_with_cleanup (clean_up_objfile); + + if (PyType_Ready (&objfile_object_type) < 0) + return; + + Py_INCREF (&objfile_object_type); + PyModule_AddObject (gdb_module, "Objfile", (PyObject *) &objfile_object_type); +} + + + +static PyGetSetDef objfile_getset[] = +{ + { "filename", objfpy_get_filename, NULL, + "The objfile's filename, or None.", NULL }, + { "pretty_printers", objfpy_get_printers, objfpy_set_printers, + "Pretty printers.", NULL }, + { NULL } +}; + +static PyTypeObject objfile_object_type = +{ + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.Objfile", /*tp_name*/ + sizeof (objfile_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + objfpy_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*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "GDB objfile object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + objfile_getset, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + objfpy_new, /* tp_new */ +}; diff --git a/gdb/python/python.c b/gdb/python/python.c index 52fc780..78a23c7 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -22,6 +22,8 @@ #include "ui-out.h" #include "cli/cli-script.h" #include "gdbcmd.h" +#include "objfiles.h" +#include "observer.h" #include <ctype.h> @@ -29,6 +31,10 @@ false otherwise. */ static int gdbpy_should_print_stack = 1; +/* This is true if we should auto-load python code when an objfile is + opened, false otherwise. */ +static int gdbpy_auto_load = 1; + #ifdef HAVE_PYTHON #include "python.h" @@ -301,6 +307,129 @@ gdbpy_print_stack (void) PyErr_Clear (); } + + +/* The "current" objfile. This is set when gdb detects that a new + objfile has been loaded. It is only set for the duration of a call + to gdbpy_new_objfile; it is NULL at other times. */ +static struct objfile *gdbpy_current_objfile; + +/* The file name we attempt to read. */ +#define GDBPY_AUTO_FILENAME "-gdb.py" + +/* This is a new_objfile observer callback which loads python code + based on the path to the objfile. */ +static void +gdbpy_new_objfile (struct objfile *objfile) +{ + char *realname; + char *filename, *debugfile; + int len; + FILE *input; + PyGILState_STATE state; + struct cleanup *cleanups; + + if (!gdbpy_auto_load || !objfile || !objfile->name) + return; + + state = PyGILState_Ensure (); + + gdbpy_current_objfile = objfile; + + realname = gdb_realpath (objfile->name); + len = strlen (realname); + filename = xmalloc (len + sizeof (GDBPY_AUTO_FILENAME)); + memcpy (filename, realname, len); + strcpy (filename + len, GDBPY_AUTO_FILENAME); + + input = fopen (filename, "r"); + debugfile = filename; + + cleanups = make_cleanup (xfree, filename); + make_cleanup (xfree, realname); + + if (!input && debug_file_directory) + { + /* Also try the same file in the separate debug info directory. */ + debugfile = xmalloc (strlen (filename) + + strlen (debug_file_directory) + 1); + strcpy (debugfile, debug_file_directory); + /* FILENAME is absolute, so we don't need a "/" here. */ + strcat (debugfile, filename); + + make_cleanup (xfree, debugfile); + input = fopen (debugfile, "r"); + } + + if (!input && gdb_datadir) + { + /* Also try the same file in a subdirectory of gdb's data + directory. */ + debugfile = xmalloc (strlen (gdb_datadir) + strlen (filename) + + strlen ("/auto-load") + 1); + strcpy (debugfile, gdb_datadir); + strcat (debugfile, "/auto-load"); + /* FILENAME is absolute, so we don't need a "/" here. */ + strcat (debugfile, filename); + + make_cleanup (xfree, debugfile); + input = fopen (debugfile, "r"); + } + + if (input) + { + /* We don't want to throw an exception here -- but the user + would like to know that something went wrong. */ + if (PyRun_SimpleFile (input, debugfile)) + gdbpy_print_stack (); + fclose (input); + } + + do_cleanups (cleanups); + gdbpy_current_objfile = NULL; + + PyGILState_Release (state); +} + +/* Return the current Objfile, or None if there isn't one. */ +static PyObject * +gdbpy_get_current_objfile (PyObject *unused1, PyObject *unused2) +{ + PyObject *result; + + if (! gdbpy_current_objfile) + Py_RETURN_NONE; + + result = objfile_to_objfile_object (gdbpy_current_objfile); + if (result) + Py_INCREF (result); + return result; +} + +/* Return a sequence holding all the Objfiles. */ +static PyObject * +gdbpy_objfiles (PyObject *unused1, PyObject *unused2) +{ + struct objfile *objf; + PyObject *list; + + list = PyList_New (0); + if (!list) + return NULL; + + ALL_OBJFILES (objf) + { + PyObject *item = objfile_to_objfile_object (objf); + if (!item || PyList_Append (list, item) == -1) + { + Py_DECREF (list); + return NULL; + } + } + + return list; +} + #else /* HAVE_PYTHON */ /* Dummy implementation of the gdb "python" command. */ @@ -399,6 +528,15 @@ Enables or disables printing of Python stack traces."), &set_python_list, &show_python_list); + add_setshow_boolean_cmd ("auto-load", class_maintenance, + &gdbpy_auto_load, _("\ +Enable or disable auto-loading of Python code when an object is opened."), _("\ +Show whether Python code will be auto-loaded when an object is opened."), _("\ +Enables or disables auto-loading of Python code when an object is opened."), + NULL, NULL, + &set_python_list, + &show_python_list); + #ifdef HAVE_PYTHON Py_Initialize (); PyEval_InitThreads (); @@ -414,9 +552,12 @@ Enables or disables printing of Python stack traces."), gdbpy_initialize_frames (); gdbpy_initialize_commands (); gdbpy_initialize_functions (); + gdbpy_initialize_objfile (); PyRun_SimpleString ("import gdb"); + observer_attach_new_objfile (gdbpy_new_objfile); + gdbpy_doc_cst = PyString_FromString ("__doc__"); /* Create a couple objects which are used for Python's stdout and @@ -465,6 +606,11 @@ static PyMethodDef GdbMethods[] = { "get_parameter", get_parameter, METH_VARARGS, "Return a gdb parameter's value" }, + { "current_objfile", gdbpy_get_current_objfile, METH_NOARGS, + "Return the current Objfile being loaded, or None." }, + { "objfiles", gdbpy_objfiles, METH_NOARGS, + "Return a sequence of all loaded objfiles." }, + { "selected_frame", gdbpy_selected_frame, METH_NOARGS, "selected_frame () -> gdb.Frame.\n\ Return the selected frame object." }, |