Add support for enabling/disabling individual pretty-printers.

* python/py-prettyprint.c (search_pp_list): Skip disabled printers.
	* python/python-internal.h (gdbpy_enabled_cst): Declare.
	* python/python.c (gdbpy_enabled_cst): Define.
	(_initialize_python): Initialize gdbpy_enabled_cst.
	* NEWS: Add entry.

	doc/
	* gdb.texinfo (Python API): New node `Disabling Pretty-Printers'.

	testsuite/
	* gdb.python/py-prettyprint.exp: Add new test for enabled and
	disabled printers.
	* gdb.python/py-prettyprint.py (disable_lookup_function): New function.
	(enable_lookup_function): New function.
This commit is contained in:
Doug Evans 2010-06-04 18:18:28 +00:00
parent 2dec564e91
commit 967cf47793
10 changed files with 102 additions and 5 deletions

View file

@ -1,3 +1,12 @@
2010-06-04 Doug Evans <dje@google.com>
Add support for enabling/disabling individual pretty-printers.
* python/py-prettyprint.c (search_pp_list): Skip disabled printers.
* python/python-internal.h (gdbpy_enabled_cst): Declare.
* python/python.c (gdbpy_enabled_cst): Define.
(_initialize_python): Initialize gdbpy_enabled_cst.
* NEWS: Add entry.
2010-06-04 Jan Kratochvil <jan.kratochvil@redhat.com> 2010-06-04 Jan Kratochvil <jan.kratochvil@redhat.com>
* breakpoint.c (update_global_location_list): Fix comment typo. * breakpoint.c (update_global_location_list): Fix comment typo.

View file

@ -104,6 +104,8 @@ is now deprecated.
** Pretty-printers are now also looked up in the current program space. ** Pretty-printers are now also looked up in the current program space.
** Pretty-printers can now be individually enabled and disabled.
** GDB now looks for names of Python scripts to auto-load in a ** GDB now looks for names of Python scripts to auto-load in a
special section named `.debug_gdb_scripts', in addition to looking special section named `.debug_gdb_scripts', in addition to looking
for a OBJFILE-gdb.py script when OBJFILE is read by the debugger. for a OBJFILE-gdb.py script when OBJFILE is read by the debugger.

View file

@ -1,3 +1,7 @@
2010-06-04 Doug Evans <dje@google.com>
* gdb.texinfo (Python API): New node `Disabling Pretty-Printers'.
2010-06-03 Doug Evans <dje@google.com> 2010-06-03 Doug Evans <dje@google.com>
* gdbint.texinfo (Coding): Add subsection on command names. * gdbint.texinfo (Coding): Add subsection on command names.

View file

@ -20019,6 +20019,7 @@ situation, a Python @code{KeyboardInterrupt} exception is thrown.
* Types In Python:: Python representation of types. * Types In Python:: Python representation of types.
* Pretty Printing API:: Pretty-printing values. * Pretty Printing API:: Pretty-printing values.
* Selecting Pretty-Printers:: How GDB chooses a pretty-printer. * Selecting Pretty-Printers:: How GDB chooses a pretty-printer.
* Disabling Pretty-Printers:: Disabling broken printers.
* Commands In Python:: Implementing new commands in Python. * Commands In Python:: Implementing new commands in Python.
* Parameters In Python:: Adding new @value{GDBN} parameters. * Parameters In Python:: Adding new @value{GDBN} parameters.
* Functions In Python:: Writing new convenience functions. * Functions In Python:: Writing new convenience functions.
@ -20710,7 +20711,8 @@ If the result is not one of these types, an exception is raised.
@subsubsection Selecting Pretty-Printers @subsubsection Selecting Pretty-Printers
The Python list @code{gdb.pretty_printers} contains an array of The Python list @code{gdb.pretty_printers} contains an array of
functions that have been registered via addition as a pretty-printer. functions or callable objects that have been registered via addition
as a pretty-printer.
Each @code{gdb.Progspace} contains a @code{pretty_printers} attribute. Each @code{gdb.Progspace} contains a @code{pretty_printers} attribute.
Each @code{gdb.Objfile} also contains a @code{pretty_printers} Each @code{gdb.Objfile} also contains a @code{pretty_printers}
attribute. attribute.
@ -20723,13 +20725,14 @@ cannot create a pretty-printer for the value, it should return
@value{GDBN} first checks the @code{pretty_printers} attribute of each @value{GDBN} first checks the @code{pretty_printers} attribute of each
@code{gdb.Objfile} in the current program space and iteratively calls @code{gdb.Objfile} in the current program space and iteratively calls
each function in the list for that @code{gdb.Objfile} until it receives each enabled function (@pxref{Disabling Pretty-Printers})
in the list for that @code{gdb.Objfile} until it receives
a pretty-printer object. a pretty-printer object.
If no pretty-printer is found in the objfile lists, @value{GDBN} then If no pretty-printer is found in the objfile lists, @value{GDBN} then
searches the pretty-printer list of the current program space, searches the pretty-printer list of the current program space,
calling each function until an object is returned. calling each enabled function until an object is returned.
After these lists have been exhausted, it tries the global After these lists have been exhausted, it tries the global
@code{gdb.pretty-printers} list, again calling each function until an @code{gdb.pretty_printers} list, again calling each enabled function until an
object is returned. object is returned.
The order in which the objfiles are searched is not specified. For a The order in which the objfiles are searched is not specified. For a
@ -20814,6 +20817,25 @@ import gdb.libstdcxx.v6
gdb.libstdcxx.v6.register_printers (gdb.current_objfile ()) gdb.libstdcxx.v6.register_printers (gdb.current_objfile ())
@end smallexample @end smallexample
@node Disabling Pretty-Printers
@subsubsection Disabling Pretty-Printers
@cindex disabling pretty-printers
For various reasons a pretty-printer may not work.
For example, the underlying data structure may have changed and
the pretty-printer is out of date.
The consequences of a broken pretty-printer are severe enough that
@value{GDBN} provides support for enabling and disabling individual
printers. For example, if @code{print frame-arguments} is on,
a backtrace can become highly illegible if any argument is printed
with a broken printer.
Pretty-printers are enabled and disabled by attaching an @code{enabled}
attribute to the registered function or callable object. If this attribute
is present and its value is @code{False}, the printer is disabled, otherwise
the printer is enabled.
@node Commands In Python @node Commands In Python
@subsubsection Commands In Python @subsubsection Commands In Python

View file

@ -48,6 +48,11 @@ search_pp_list (PyObject *list, PyObject *value)
if (! function) if (! function)
return NULL; return NULL;
/* Skip if disabled. */
if (PyObject_HasAttr (function, gdbpy_enabled_cst)
&& ! PyObject_IsTrue (PyObject_GetAttr (function, gdbpy_enabled_cst)))
continue;
printer = PyObject_CallFunctionObjArgs (function, value, NULL); printer = PyObject_CallFunctionObjArgs (function, value, NULL);
if (! printer) if (! printer)
return NULL; return NULL;

View file

@ -200,6 +200,7 @@ extern PyObject *gdbpy_doc_cst;
extern PyObject *gdbpy_children_cst; extern PyObject *gdbpy_children_cst;
extern PyObject *gdbpy_to_string_cst; extern PyObject *gdbpy_to_string_cst;
extern PyObject *gdbpy_display_hint_cst; extern PyObject *gdbpy_display_hint_cst;
extern PyObject *gdbpy_enabled_cst;
extern PyObject *gdbpy_gdberror_exc; extern PyObject *gdbpy_gdberror_exc;

View file

@ -56,6 +56,7 @@ PyObject *gdbpy_to_string_cst;
PyObject *gdbpy_children_cst; PyObject *gdbpy_children_cst;
PyObject *gdbpy_display_hint_cst; PyObject *gdbpy_display_hint_cst;
PyObject *gdbpy_doc_cst; PyObject *gdbpy_doc_cst;
PyObject *gdbpy_enabled_cst;
/* The GdbError exception. */ /* The GdbError exception. */
PyObject *gdbpy_gdberror_exc; PyObject *gdbpy_gdberror_exc;
@ -693,6 +694,7 @@ Enables or disables printing of Python stack traces."),
gdbpy_children_cst = PyString_FromString ("children"); gdbpy_children_cst = PyString_FromString ("children");
gdbpy_display_hint_cst = PyString_FromString ("display_hint"); gdbpy_display_hint_cst = PyString_FromString ("display_hint");
gdbpy_doc_cst = PyString_FromString ("__doc__"); gdbpy_doc_cst = PyString_FromString ("__doc__");
gdbpy_enabled_cst = PyString_FromString ("enabled");
/* Create a couple objects which are used for Python's stdout and /* Create a couple objects which are used for Python's stdout and
stderr. */ stderr. */

View file

@ -1,3 +1,10 @@
2010-06-04 Doug Evans <dje@google.com>
* gdb.python/py-prettyprint.exp: Add new test for enabled and
disabled printers.
* gdb.python/py-prettyprint.py (disable_lookup_function): New function.
(enable_lookup_function): New function.
2010-06-04 Tom Tromey <tromey@redhat.com> 2010-06-04 Tom Tromey <tromey@redhat.com>
* gdb.python/py-value.exp (test_value_hash): Don't test equality * gdb.python/py-value.exp (test_value_hash): Don't test equality

View file

@ -57,7 +57,6 @@ proc run_lang_tests {lang} {
gdb_reinitialize_dir $srcdir/$subdir gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${binfile} gdb_load ${binfile}
if ![runto_main ] then { if ![runto_main ] then {
perror "couldn't run to breakpoint" perror "couldn't run to breakpoint"
return return
@ -109,3 +108,44 @@ proc run_lang_tests {lang} {
run_lang_tests "c" run_lang_tests "c"
run_lang_tests "c++" run_lang_tests "c++"
# Run various other tests.
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "debug"] != "" } {
untested "Couldn't compile ${srcfile}"
return -1
}
# Start with a fresh gdb.
gdb_exit
gdb_start
gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${binfile}
if ![runto_main ] then {
perror "couldn't run to breakpoint"
return
}
gdb_test "b [gdb_get_line_number {break to inspect} ${testfile}.c ]" \
".*Breakpoint.*"
gdb_test "continue" ".*Breakpoint.*"
set remote_python_file [remote_download host ${srcdir}/${subdir}/${testfile}.py]
gdb_test "python execfile ('${remote_python_file}')" ""
gdb_test "print ss" " = a=< a=<1> b=<$hex>> b=< a=<2> b=<$hex>>" \
"print ss enabled #1"
gdb_test "python disable_lookup_function ()" ""
gdb_test "print ss" " = {a = {a = 1, b = $hex}, b = {a = 2, b = $hex}}" \
"print ss disabled"
gdb_test "python enable_lookup_function ()" ""
gdb_test "print ss" " = a=< a=<1> b=<$hex>> b=< a=<2> b=<$hex>>" \
"print ss enabled #2"
remote_file host delete ${remote_python_file}

View file

@ -194,6 +194,11 @@ def lookup_function (val):
return None return None
def disable_lookup_function ():
lookup_function.enabled = False
def enable_lookup_function ():
lookup_function.enabled = True
def register_pretty_printers (): def register_pretty_printers ():
pretty_printers_dict[re.compile ('^struct s$')] = pp_s pretty_printers_dict[re.compile ('^struct s$')] = pp_s