This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[RFA] add support for disabling individual pretty-printers
- From: dje at google dot com (Doug Evans)
- To: gdb-patches at sourceware dot org
- Date: Thu, 20 May 2010 00:12:12 -0700 (PDT)
- Subject: [RFA] add support for disabling individual pretty-printers
Hi.
As discussed in irc, I'd like to add support for disabling
individual pretty-printers. Broken printers do get installed
and/or the underlying data structures do change with developers
not always updating the pretty-printer. When this happens
the consequences to a user's debugging session can be severe enough
that IMO we need to do *something*.
The user may be in a completely different group and/or not have
any knowledge of pretty-printer details. Asking him/her to put up
with the breakage until the printer is fixed is unreasonable (IMO).
The approach below uses the presence of an "enabled" attribute
on the lookup function (or callable object!) to control the
enabling/disabling.
Ok to check in?
For reference sake, I'd also like to establish some conventions
when writing pretty printers but that's for another patch.
E.g., some pretty printers handle *lots* of types (e.g. libstdc++'s
pretty printer).
It'd be unfortunate to have to disable pretty-printing of all
of the handled types just because one of them is broken.
2010-05-19 Doug Evans <dje@google.com>
Add support for enabling/disabling individual pretty-printers.
* py-prettyprint.c (search_pp_list): Skip disabled printers.
* python-internal.h (gdbpy_enabled_cst): Declare.
* 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.
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.716
diff -u -p -r1.716 gdb.texinfo
--- doc/gdb.texinfo 29 Apr 2010 15:45:56 -0000 1.716
+++ doc/gdb.texinfo 20 May 2010 06:50:57 -0000
@@ -19940,6 +19940,7 @@ situation, a Python @code{KeyboardInterr
* Types In Python:: Python representation of types.
* Pretty Printing API:: Pretty-printing values.
* Selecting Pretty-Printers:: How GDB chooses a pretty-printer.
+* Disabling Pretty-Printers:: Disabling broken printers.
* Commands In Python:: Implementing new commands in Python.
* Parameters In Python:: Adding new @value{GDBN} parameters.
* Functions In Python:: Writing new convenience functions.
@@ -20607,7 +20608,8 @@ If the result is not one of these types,
@subsubsection Selecting Pretty-Printers
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.Objfile} also contains a @code{pretty_printers}
attribute.
@@ -20620,13 +20622,14 @@ cannot create a pretty-printer for the v
@value{GDBN} first checks the @code{pretty_printers} attribute of each
@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.
If no pretty-printer is found in the objfile lists, @value{GDBN} then
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
-@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.
The order in which the objfiles are searched is not specified. For a
@@ -20711,6 +20714,24 @@ import gdb.libstdcxx.v6
gdb.libstdcxx.v6.register_printers (gdb.current_objfile ())
@end smallexample
+@node Disabling Pretty-Printers
+@subsubsection 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
@subsubsection Commands In Python
Index: python/py-prettyprint.c
===================================================================
RCS file: /cvs/src/src/gdb/python/py-prettyprint.c,v
retrieving revision 1.10
diff -u -p -r1.10 py-prettyprint.c
--- python/py-prettyprint.c 17 May 2010 21:23:25 -0000 1.10
+++ python/py-prettyprint.c 20 May 2010 06:50:57 -0000
@@ -48,6 +48,11 @@ search_pp_list (PyObject *list, PyObject
if (! function)
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);
if (! printer)
return NULL;
Index: python/python-internal.h
===================================================================
RCS file: /cvs/src/src/gdb/python/python-internal.h,v
retrieving revision 1.26
diff -u -p -r1.26 python-internal.h
--- python/python-internal.h 29 Apr 2010 15:45:56 -0000 1.26
+++ python/python-internal.h 20 May 2010 06:50:57 -0000
@@ -196,5 +196,6 @@ extern PyObject *gdbpy_doc_cst;
extern PyObject *gdbpy_children_cst;
extern PyObject *gdbpy_to_string_cst;
extern PyObject *gdbpy_display_hint_cst;
+extern PyObject *gdbpy_enabled_cst;
#endif /* GDB_PYTHON_INTERNAL_H */
Index: python/python.c
===================================================================
RCS file: /cvs/src/src/gdb/python/python.c,v
retrieving revision 1.38
diff -u -p -r1.38 python.c
--- python/python.c 19 May 2010 23:32:24 -0000 1.38
+++ python/python.c 20 May 2010 06:50:57 -0000
@@ -56,7 +56,7 @@ PyObject *gdbpy_to_string_cst;
PyObject *gdbpy_children_cst;
PyObject *gdbpy_display_hint_cst;
PyObject *gdbpy_doc_cst;
-
+PyObject *gdbpy_enabled_cst;
/* Architecture and language to be used in callbacks from
the Python interpreter. */
@@ -677,6 +683,7 @@ Enables or disables printing of Python s
gdbpy_children_cst = PyString_FromString ("children");
gdbpy_display_hint_cst = PyString_FromString ("display_hint");
gdbpy_doc_cst = PyString_FromString ("__doc__");
+ gdbpy_enabled_cst = PyString_FromString ("enabled");
/* Create a couple objects which are used for Python's stdout and
stderr. */
Index: testsuite/gdb.python/py-prettyprint.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.python/py-prettyprint.exp,v
retrieving revision 1.8
diff -u -p -r1.8 py-prettyprint.exp
--- testsuite/gdb.python/py-prettyprint.exp 14 Apr 2010 12:02:46 -0000 1.8
+++ testsuite/gdb.python/py-prettyprint.exp 20 May 2010 06:50:57 -0000
@@ -57,7 +57,6 @@ proc run_lang_tests {lang} {
gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${binfile}
-
if ![runto_main ] then {
perror "couldn't run to breakpoint"
return
@@ -109,3 +108,44 @@ proc run_lang_tests {lang} {
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}
Index: testsuite/gdb.python/py-prettyprint.py
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.python/py-prettyprint.py,v
retrieving revision 1.6
diff -u -p -r1.6 py-prettyprint.py
--- testsuite/gdb.python/py-prettyprint.py 14 Apr 2010 12:02:46 -0000 1.6
+++ testsuite/gdb.python/py-prettyprint.py 20 May 2010 06:50:57 -0000
@@ -194,6 +194,11 @@ def lookup_function (val):
return None
+def disable_lookup_function ():
+ lookup_function.enabled = False
+
+def enable_lookup_function ():
+ lookup_function.enabled = True
def register_pretty_printers ():
pretty_printers_dict[re.compile ('^struct s$')] = pp_s
Index: NEWS
===================================================================
RCS file: /cvs/src/src/gdb/NEWS,v
retrieving revision 1.379
diff -u -p -r1.379 NEWS
--- NEWS 30 Apr 2010 07:04:52 -0000 1.379
+++ NEWS 20 May 2010 06:52:44 -0000
@@ -91,6 +91,8 @@ is now deprecated.
** 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
special section named `.debug_gdb_scripts', in addition to looking
for a OBJFILE-gdb.py script when OBJFILE is read by the debugger.