diff options
author | Doug Evans <dje@google.com> | 2010-04-15 19:54:13 +0000 |
---|---|---|
committer | Doug Evans <dje@google.com> | 2010-04-15 19:54:13 +0000 |
commit | fa33c3cd050c9f8a33ab0826479fd3e0f26a3da6 (patch) | |
tree | 8aa1bd5a3237ffff09f051cad7544427a67ed81e /gdb/python | |
parent | 3f7b2faa4bb3f35f6c88687b6943cdbe6003b615 (diff) | |
download | gdb-fa33c3cd050c9f8a33ab0826479fd3e0f26a3da6.zip gdb-fa33c3cd050c9f8a33ab0826479fd3e0f26a3da6.tar.gz gdb-fa33c3cd050c9f8a33ab0826479fd3e0f26a3da6.tar.bz2 |
* NEWS: Add entry for python program space support.
* Makefile.in (SUBDIR_PYTHON_OBS): Add py-progspace.o.
(SUBDIR_PYTHON_SRCS): Add py-progspace.c.
(py-progspace.o): New rule.
* python/py-prettyprint.c (find_pretty_printer_from_objfiles): New
function.
(find_pretty_printer_from_progspace): New function.
(find_pretty_printer_from_gdb): New function.
(find_pretty_printer): Rewrite.
* python/py-progspace.c: New file.
* python/python-internal.h (program_space): Add forward decl.
(pspace_to_pspace_object, pspy_get_printers): Declare.
(gdbpy_initialize_pspace): Declare.
* python/python.c: #include "progspace.h".
(gdbpy_get_current_progspace, gdbpy_progspaces): New functions.
(_initialize_python): Call gdbpy_initialize_pspace.
(GdbMethods): Add current_progspace, progspaces.
doc/
* gdb.texinfo (Python API): Add progspaces section.
(Selecting Pretty-Printers): Progspace pretty-printers are
searched too.
(Progspaces In Python): New section.
testsuite/
* gdb.python/py-progspace.c: New file.
* gdb.python/py-progspace.exp: New file.
Diffstat (limited to 'gdb/python')
-rw-r--r-- | gdb/python/py-prettyprint.c | 110 | ||||
-rw-r--r-- | gdb/python/py-progspace.c | 240 | ||||
-rw-r--r-- | gdb/python/python-internal.h | 7 | ||||
-rw-r--r-- | gdb/python/python.c | 49 |
4 files changed, 376 insertions, 30 deletions
diff --git a/gdb/python/py-prettyprint.c b/gdb/python/py-prettyprint.c index 9f9fea1..d26ed58 100644 --- a/gdb/python/py-prettyprint.c +++ b/gdb/python/py-prettyprint.c @@ -29,12 +29,12 @@ #ifdef HAVE_PYTHON #include "python-internal.h" - /* Helper function for find_pretty_printer which iterates over a list, calls each function and inspects output. This will return a printer object if one recognizes VALUE. If no printer is found, it will return None. On error, it will set the Python error and return NULL. */ + static PyObject * search_pp_list (PyObject *list, PyObject *value) { @@ -60,18 +60,19 @@ search_pp_list (PyObject *list, PyObject *value) Py_RETURN_NONE; } -/* Find the pretty-printing constructor function for VALUE. If no - pretty-printer exists, return None. If one exists, return a new - reference. On error, set the Python error and return NULL. */ +/* Subroutine of find_pretty_printer to simplify it. + Look for a pretty-printer to print VALUE in all objfiles. + The result is NULL if there's an error and the search should be terminated. + The result is Py_None, suitably inc-ref'd, if no pretty-printer was found. + Otherwise the result is the pretty-printer function, suitably inc-ref'd. */ + static PyObject * -find_pretty_printer (PyObject *value) +find_pretty_printer_from_objfiles (PyObject *value) { - PyObject *pp_list = NULL; - PyObject *function = NULL; + PyObject *pp_list; + PyObject *function; struct objfile *obj; - volatile struct gdb_exception except; - /* Look at the pretty-printer dictionary for each objfile. */ ALL_OBJFILES (obj) { PyObject *objf = objfile_to_objfile_object (obj); @@ -84,44 +85,95 @@ find_pretty_printer (PyObject *value) pp_list = objfpy_get_printers (objf, NULL); function = search_pp_list (pp_list, value); + Py_XDECREF (pp_list); - /* If there is an error in any objfile list, abort the search and - exit. */ + /* If there is an error in any objfile list, abort the search and exit. */ if (! function) - { - Py_XDECREF (pp_list); - return NULL; - } + return NULL; if (function != Py_None) - goto done; + return function; Py_DECREF (function); - Py_XDECREF (pp_list); } - pp_list = NULL; + Py_RETURN_NONE; +} + +/* Subroutine of find_pretty_printer to simplify it. + Look for a pretty-printer to print VALUE in the current program space. + The result is NULL if there's an error and the search should be terminated. + The result is Py_None, suitably inc-ref'd, if no pretty-printer was found. + Otherwise the result is the pretty-printer function, suitably inc-ref'd. */ + +static PyObject * +find_pretty_printer_from_progspace (PyObject *value) +{ + PyObject *pp_list; + PyObject *function; + PyObject *obj = pspace_to_pspace_object (current_program_space); + + if (!obj) + return NULL; + pp_list = pspy_get_printers (obj, NULL); + function = search_pp_list (pp_list, value); + Py_XDECREF (pp_list); + return function; +} + +/* Subroutine of find_pretty_printer to simplify it. + Look for a pretty-printer to print VALUE in the gdb module. + The result is NULL if there's an error and the search should be terminated. + The result is Py_None, suitably inc-ref'd, if no pretty-printer was found. + Otherwise the result is the pretty-printer function, suitably inc-ref'd. */ + +static PyObject * +find_pretty_printer_from_gdb (PyObject *value) +{ + PyObject *pp_list; + PyObject *function; + /* Fetch the global pretty printer dictionary. */ if (! PyObject_HasAttrString (gdb_module, "pretty_printers")) + Py_RETURN_NONE; + pp_list = PyObject_GetAttrString (gdb_module, "pretty_printers"); + if (pp_list == NULL || ! PyList_Check (pp_list)) { - function = Py_None; - Py_INCREF (function); - goto done; + Py_XDECREF (pp_list); + Py_RETURN_NONE; } - pp_list = PyObject_GetAttrString (gdb_module, "pretty_printers"); - if (! pp_list) - goto done; - if (! PyList_Check (pp_list)) - goto done; function = search_pp_list (pp_list, value); - - done: Py_XDECREF (pp_list); - return function; } +/* Find the pretty-printing constructor function for VALUE. If no + pretty-printer exists, return None. If one exists, return a new + reference. On error, set the Python error and return NULL. */ + +static PyObject * +find_pretty_printer (PyObject *value) +{ + PyObject *function; + + /* Look at the pretty-printer dictionary for each objfile + in the current program-space. */ + function = find_pretty_printer_from_objfiles (value); + if (function == NULL || function != Py_None) + return function; + Py_DECREF (function); + + /* Look at the pretty-printer dictionary for the current program-space. */ + function = find_pretty_printer_from_progspace (value); + if (function == NULL || function != Py_None) + return function; + Py_DECREF (function); + + /* Look at the pretty-printer dictionary in the gdb module. */ + function = find_pretty_printer_from_gdb (value); + return function; +} /* Pretty-print a single value, via the printer object PRINTER. If the function returns a string, a PyObject containing the string diff --git a/gdb/python/py-progspace.c b/gdb/python/py-progspace.c new file mode 100644 index 0000000..1460878 --- /dev/null +++ b/gdb/python/py-progspace.c @@ -0,0 +1,240 @@ +/* Python interface to program spaces. + + Copyright (C) 2010 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 "progspace.h" +#include "objfiles.h" +#include "language.h" + +typedef struct +{ + PyObject_HEAD + + /* The corresponding pspace. */ + struct program_space *pspace; + + /* The pretty-printer list of functions. */ + PyObject *printers; +} pspace_object; + +static PyTypeObject pspace_object_type; + +static const struct program_space_data *pspy_pspace_data_key; + + + +/* An Objfile method which returns the objfile's file name, or None. */ + +static PyObject * +pspy_get_filename (PyObject *self, void *closure) +{ + pspace_object *obj = (pspace_object *) self; + if (obj->pspace) + { + struct objfile *objfile = obj->pspace->symfile_object_file; + if (objfile && objfile->name) + return PyString_Decode (objfile->name, strlen (objfile->name), + host_charset (), NULL); + } + Py_RETURN_NONE; +} + +static void +pspy_dealloc (PyObject *self) +{ + pspace_object *ps_self = (pspace_object *) self; + Py_XDECREF (ps_self->printers); + self->ob_type->tp_free (self); +} + +static PyObject * +pspy_new (PyTypeObject *type, PyObject *args, PyObject *keywords) +{ + pspace_object *self = (pspace_object *) type->tp_alloc (type, 0); + if (self) + { + self->pspace = NULL; + + self->printers = PyList_New (0); + if (!self->printers) + { + Py_DECREF (self); + return NULL; + } + } + return (PyObject *) self; +} + +PyObject * +pspy_get_printers (PyObject *o, void *ignore) +{ + pspace_object *self = (pspace_object *) o; + Py_INCREF (self->printers); + return self->printers; +} + +static int +pspy_set_printers (PyObject *o, PyObject *value, void *ignore) +{ + PyObject *tmp; + pspace_object *self = (pspace_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 PSPACE pointer in a Pspace object and remove the reference. */ + +static void +py_free_pspace (struct program_space *pspace, void *datum) +{ + struct cleanup *cleanup; + pspace_object *object = datum; + /* FIXME: What's the right way to get a program space's arch? + There may be multiple. */ + struct gdbarch *arch = get_objfile_arch (pspace->symfile_object_file); + + cleanup = ensure_python_env (arch, current_language); + object->pspace = NULL; + Py_DECREF ((PyObject *) object); + do_cleanups (cleanup); +} + +/* Return a borrowed reference to the Python object of type Pspace + representing PSPACE. If the object has already been created, + return it. Otherwise, create it. Return NULL and set the Python + error on failure. */ + +PyObject * +pspace_to_pspace_object (struct program_space *pspace) +{ + pspace_object *object; + + object = program_space_data (pspace, pspy_pspace_data_key); + if (!object) + { + object = PyObject_New (pspace_object, &pspace_object_type); + if (object) + { + PyObject *dict; + + object->pspace = pspace; + + object->printers = PyList_New (0); + if (!object->printers) + { + Py_DECREF (object); + return NULL; + } + + set_program_space_data (pspace, pspy_pspace_data_key, object); + } + } + + return (PyObject *) object; +} + +void +gdbpy_initialize_pspace (void) +{ + pspy_pspace_data_key + = register_program_space_data_with_cleanup (py_free_pspace); + + if (PyType_Ready (&pspace_object_type) < 0) + return; + + Py_INCREF (&pspace_object_type); + PyModule_AddObject (gdb_module, "Progspace", (PyObject *) &pspace_object_type); +} + + + +static PyGetSetDef pspace_getset[] = +{ + { "filename", pspy_get_filename, NULL, + "The progspace's main filename, or None.", NULL }, + { "pretty_printers", pspy_get_printers, pspy_set_printers, + "Pretty printers.", NULL }, + { NULL } +}; + +static PyTypeObject pspace_object_type = +{ + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.Progspace", /*tp_name*/ + sizeof (pspace_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + pspy_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 progspace 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 */ + pspace_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 */ + pspy_new, /* tp_new */ +}; diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index 98d2b3f..e3368e3 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -68,6 +68,7 @@ typedef int Py_ssize_t; struct block; struct value; struct language_defn; +struct program_space; extern PyObject *gdb_module; extern PyTypeObject value_object_type; @@ -91,8 +92,11 @@ PyObject *symbol_to_symbol_object (struct symbol *sym); PyObject *block_to_block_object (struct block *block, struct objfile *objfile); PyObject *value_to_value_object (struct value *v); PyObject *type_to_type_object (struct type *); -PyObject *objfile_to_objfile_object (struct objfile *); +PyObject *pspace_to_pspace_object (struct program_space *); +PyObject *pspy_get_printers (PyObject *, void *); + +PyObject *objfile_to_objfile_object (struct objfile *); PyObject *objfpy_get_printers (PyObject *, void *); struct block *block_object_to_block (PyObject *obj); @@ -112,6 +116,7 @@ void gdbpy_initialize_symtabs (void); void gdbpy_initialize_blocks (void); void gdbpy_initialize_types (void); void gdbpy_initialize_functions (void); +void gdbpy_initialize_pspace (void); void gdbpy_initialize_objfile (void); void gdbpy_initialize_breakpoints (void); void gdbpy_initialize_lazy_string (void); diff --git a/gdb/python/python.c b/gdb/python/python.c index b21ea99..935715a 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -23,6 +23,7 @@ #include "ui-out.h" #include "cli/cli-script.h" #include "gdbcmd.h" +#include "progspace.h" #include "objfiles.h" #include "observer.h" #include "value.h" @@ -417,6 +418,47 @@ gdbpy_print_stack (void) +/* Return the current Progspace. + There always is one. */ + +static PyObject * +gdbpy_get_current_progspace (PyObject *unused1, PyObject *unused2) +{ + PyObject *result; + + result = pspace_to_pspace_object (current_program_space); + if (result) + Py_INCREF (result); + return result; +} + +/* Return a sequence holding all the Progspaces. */ + +static PyObject * +gdbpy_progspaces (PyObject *unused1, PyObject *unused2) +{ + struct program_space *ps; + PyObject *list; + + list = PyList_New (0); + if (!list) + return NULL; + + ALL_PSPACES (ps) + { + PyObject *item = pspace_to_pspace_object (ps); + if (!item || PyList_Append (list, item) == -1) + { + Py_DECREF (list); + return NULL; + } + } + + return list; +} + + + /* 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. */ @@ -512,6 +554,7 @@ gdbpy_get_current_objfile (PyObject *unused1, PyObject *unused2) } /* Return a sequence holding all the Objfiles. */ + static PyObject * gdbpy_objfiles (PyObject *unused1, PyObject *unused2) { @@ -668,6 +711,7 @@ Enables or disables auto-loading of Python code when an object is opened."), gdbpy_initialize_blocks (); gdbpy_initialize_functions (); gdbpy_initialize_types (); + gdbpy_initialize_pspace (); gdbpy_initialize_objfile (); gdbpy_initialize_breakpoints (); gdbpy_initialize_lazy_string (); @@ -734,6 +778,11 @@ static PyMethodDef GdbMethods[] = { "default_visualizer", gdbpy_default_visualizer, METH_VARARGS, "Find the default visualizer for a Value." }, + { "current_progspace", gdbpy_get_current_progspace, METH_NOARGS, + "Return the current Progspace." }, + { "progspaces", gdbpy_progspaces, METH_NOARGS, + "Return a sequence of all progspaces." }, + { "current_objfile", gdbpy_get_current_objfile, METH_NOARGS, "Return the current Objfile being loaded, or None." }, { "objfiles", gdbpy_objfiles, METH_NOARGS, |