[PATCH v2][PR gdb/24052] Implement 'set print zero-values on|off'

Hannes Domani ssbssa@yahoo.de
Sat May 30 16:12:53 GMT 2020


With this option it's possible to suppress any zero value members when
printing a structure or array.

Consider this example:

(gdb) p t1
$1 = {
  i1 = 0,
  i2 = 0,
  i3 = 1,
  d1 = 0,
  d2 = 2.5,
  d3 = 0,
  p1 = 0x407980 <ix>,
  p2 = 0x0,
  p3 = 0x0,
  t1 = {
    v1 = 0,
    v2 = 0
  },
  t2 = {
    v1 = 3,
    v2 = 0
  },
  t3 = {
    v1 = 4,
    v2 = 5
  },
  ia = {0, 1, 2, 0, 0, 3, 4, 5, 0, 6},
  ea = {0, 0, 0},
  ipa = {0x0, 0x407980 <ix>, 0x0, 0x0, 0x403020 <t1>}
}

With suppressed zero value members, the ouput is concise:

(gdb) set print zero-values off
(gdb) p t1
$2 = {
  i3 = 1,
  d2 = 2.5,
  p1 = 0x407980 <ix>,
  t2 = {
    v1 = 3
  },
  t3 = {
    v1 = 4,
    v2 = 5
  },
  ia = {1, 2, 3, 4, 5, 6},
  ipa = {0x407980 <ix>, 0x403020 <t1>}
}

gdb/ChangeLog:

2020-05-30  Hannes Domani  <ssbssa@yahoo.de>

	PR gdb/24052
	* cp-valprint.c (cp_print_value_fields): Skip zero value members
	if requested.
	* python/py-value.c (valpy_format_string): Add zero_values keyword.
	* valprint.c (struct value_print_options): Add zero_value_print.
	(value_is_zero): New function.
	(value_print_array_elements): Skip zero value members if requested.
	(show_zero_value_print): New function.
	* valprint.h (struct value_print_options): Add zero_value_print.
	(value_is_zero): Declare.

gdb/doc/ChangeLog:

2020-05-30  Hannes Domani  <ssbssa@yahoo.de>

	PR gdb/24052
	* gdb.texinfo: Document 'print zero-values'.
	* python.texi: Document format_string keyword 'zero_values'.

gdb/testsuite/ChangeLog:

2020-05-30  Hannes Domani  <ssbssa@yahoo.de>

	PR gdb/24052
	* gdb.base/options.exp: Add -zero-values in the print completion
	list.
	* gdb.base/zero-values.c: New test.
	* gdb.base/zero-values.exp: New file.
	* gdb.python/py-format-string.c (main): Add variables with
	zero-value members.
	* gdb.python/py-format-string.exp (test_zero_values): New proc.
	(test_all_common): Call test_zero_values.
---
v2:
- Add python format_string keyword.
- Don't print zero value array elements.
---
 gdb/cp-valprint.c                             | 12 +++++
 gdb/doc/gdb.texinfo                           | 18 ++++++-
 gdb/doc/python.texi                           |  5 ++
 gdb/python/py-value.c                         |  7 ++-
 gdb/testsuite/gdb.base/options.exp            |  1 +
 gdb/testsuite/gdb.base/zero-values.c          | 40 ++++++++++++++
 gdb/testsuite/gdb.base/zero-values.exp        | 32 +++++++++++
 gdb/testsuite/gdb.python/py-format-string.c   |  3 ++
 gdb/testsuite/gdb.python/py-format-string.exp | 17 ++++++
 gdb/valprint.c                                | 54 ++++++++++++++++++-
 gdb/valprint.h                                |  7 +++
 11 files changed, 192 insertions(+), 4 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/zero-values.c
 create mode 100644 gdb/testsuite/gdb.base/zero-values.exp

diff --git a/gdb/cp-valprint.c b/gdb/cp-valprint.c
index 0c79b025bd..6be63eea10 100644
--- a/gdb/cp-valprint.c
+++ b/gdb/cp-valprint.c
@@ -194,6 +194,18 @@ cp_print_value_fields (struct value *val, struct ui_file *stream,
 	      && field_is_static (&type->field (i)))
 	    continue;
 
+	  /* If requested, skip printing of zero value fields.  */
+	  if (!options->zero_value_print
+	      && !field_is_static (&type->field (i)))
+	    {
+	      if (TYPE_FIELD_IGNORE (type, i))
+		continue;
+
+	      struct value *v = value_primitive_field (val, 0, i, type);
+	      if (value_is_zero (v))
+		continue;
+	    }
+
 	  if (fields_seen)
 	    {
 	      fputs_filtered (",", stream);
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 84755d374e..810fe52858 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -1978,7 +1978,7 @@ on @code{-} after the command name.  For example:
 (@value{GDBP}) print -@key{TAB}@key{TAB}
 -address         -max-depth       -raw-values      -union
 -array           -null-stop       -repeats         -vtbl
--array-indexes   -object          -static-members
+-array-indexes   -object          -static-members  -zero-values
 -elements        -pretty          -symbol
 @end smallexample
 
@@ -9757,6 +9757,10 @@ Set printing of unions interior to structures.  Related setting:
 @item -vtbl [@code{on}|@code{off}]
 Set printing of C++ virtual function tables.  Related setting:
 @ref{set print vtbl}.
+
+@item -zero-values [@code{on}|@code{off}]
+Set printing of zero value members. Related setting: @ref{set print
+zero-values}.
 @end table
 
 Because the @code{print} command accepts arbitrary expressions which
@@ -11546,6 +11550,18 @@ Do not pretty print C@t{++} virtual function tables.
 
 @item show print vtbl
 Show whether C@t{++} virtual function tables are pretty printed, or not.
+
+@anchor{set print zero-values}
+@item set print zero-values
+@itemx set print zero-values on
+@cindex zero value members
+Print zero value members of structures and arrays.  The default is on.
+
+@item set print zero-values off
+Do not print zero value members of structures and arrays.
+
+@item show print zero-values
+Show whether zero value members are printed or not.
 @end table
 
 @node Pretty Printing
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index a38f1dab42..e86fb7eab9 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -905,6 +905,11 @@ corresponding symbol name (if one exists), @code{False} if it shouldn't
 should be expanded, @code{False} if they shouldn't (see @code{set print
 union} in @ref{Print Settings}).
 
+@item zero_values
+@code{True} if zero value members should be included in the string
+representation of structures and arrays, @code{False} if they shouldn't
+(see @code{set print zero-values} in @ref{Print Settings}).
+
 @item deref_refs
 @code{True} if C@t{++} references should be resolved to the value they
 refer to, @code{False} (the default) if they shouldn't.  Note that, unlike
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index 2ebbe0a356..c45705c377 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -617,6 +617,7 @@ valpy_format_string (PyObject *self, PyObject *args, PyObject *kw)
       "array_indexes",		/* See set print array-indexes on|off.  */
       "symbols",		/* See set print symbol on|off.  */
       "unions",			/* See set print union on|off.  */
+      "zero_values",		/* See set print zero-values on|off.  */
       /* C++ options.  */
       "deref_refs",		/* No corresponding setting.  */
       "actual_objects",		/* See set print object on|off.  */
@@ -660,13 +661,14 @@ valpy_format_string (PyObject *self, PyObject *args, PyObject *kw)
   PyObject *array_indexes_obj = NULL;
   PyObject *symbols_obj = NULL;
   PyObject *unions_obj = NULL;
+  PyObject *zero_values_obj = NULL;
   PyObject *deref_refs_obj = NULL;
   PyObject *actual_objects_obj = NULL;
   PyObject *static_members_obj = NULL;
   char *format = NULL;
   if (!gdb_PyArg_ParseTupleAndKeywords (args,
 					kw,
-					"|O!O!O!O!O!O!O!O!O!IIIs",
+					"|O!O!O!O!O!O!O!O!O!O!IIIs",
 					keywords,
 					&PyBool_Type, &raw_obj,
 					&PyBool_Type, &pretty_arrays_obj,
@@ -674,6 +676,7 @@ valpy_format_string (PyObject *self, PyObject *args, PyObject *kw)
 					&PyBool_Type, &array_indexes_obj,
 					&PyBool_Type, &symbols_obj,
 					&PyBool_Type, &unions_obj,
+					&PyBool_Type, &zero_values_obj,
 					&PyBool_Type, &deref_refs_obj,
 					&PyBool_Type, &actual_objects_obj,
 					&PyBool_Type, &static_members_obj,
@@ -696,6 +699,8 @@ valpy_format_string (PyObject *self, PyObject *args, PyObject *kw)
     return NULL;
   if (!copy_py_bool_obj (&opts.unionprint, unions_obj))
     return NULL;
+  if (!copy_py_bool_obj (&opts.zero_value_print, zero_values_obj))
+    return NULL;
   if (!copy_py_bool_obj (&opts.deref_ref, deref_refs_obj))
     return NULL;
   if (!copy_py_bool_obj (&opts.objectprint, actual_objects_obj))
diff --git a/gdb/testsuite/gdb.base/options.exp b/gdb/testsuite/gdb.base/options.exp
index 37a7e1ec8a..1c8bb923e6 100644
--- a/gdb/testsuite/gdb.base/options.exp
+++ b/gdb/testsuite/gdb.base/options.exp
@@ -174,6 +174,7 @@ proc_with_prefix test-print {{prefix ""}} {
 	"-symbol"
 	"-union"
 	"-vtbl"
+	"-zero-values"
     }
 
     global binfile
diff --git a/gdb/testsuite/gdb.base/zero-values.c b/gdb/testsuite/gdb.base/zero-values.c
new file mode 100644
index 0000000000..0a281d9671
--- /dev/null
+++ b/gdb/testsuite/gdb.base/zero-values.c
@@ -0,0 +1,40 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2020 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/>.  */
+
+int ix;
+struct two
+{
+  int v1, v2;
+};
+struct t
+{
+  int i1, i2, i3;
+  double d1, d2, d3;
+  int *p1, *p2, *p3;
+  struct two t1, t2, t3;
+  int ia[10];
+  int ea[3];
+  int *ipa[5];
+} t1 = {0, 0, 1, 0, 2.5, 0, &ix, 0, 0, {0, 0}, {3, 0}, {4, 5},
+	{0, 1, 2, 0, 0, 3, 4, 5, 0, 6}, {0, 0, 0},
+	{0, &ix, 0, 0, &t1.i1}};
+
+int
+main ()
+{
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/zero-values.exp b/gdb/testsuite/gdb.base/zero-values.exp
new file mode 100644
index 0000000000..a8f377b8f7
--- /dev/null
+++ b/gdb/testsuite/gdb.base/zero-values.exp
@@ -0,0 +1,32 @@
+# Copyright 2020 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/>.
+
+# Test disabled printing of zero-values in structures and arrays.
+
+standard_testfile
+
+if {[prepare_for_testing $testfile.exp $testfile $srcfile debug]} {
+    untested $testfile.exp
+    return -1
+}
+
+if ![runto_main] {
+    untested $testfile.exp
+    return -1
+}
+
+gdb_test "print t1" " = \\{i1 = 0, i2 = 0, i3 = 1, d1 = 0, d2 = 2\\.5, d3 = 0, p1 = $hex <ix>, p2 = 0x0, p3 = 0x0, t1 = \\{v1 = 0, v2 = 0\\}, t2 = \\{v1 = 3, v2 = 0\\}, t3 = \\{v1 = 4, v2 = 5\\}, ia = \\{0, 1, 2, 0, 0, 3, 4, 5, 0, 6\\}, ea = \\{0, 0, 0\\}, ipa = \\{0x0, $hex <ix>, 0x0, 0x0, $hex <t1>\\}\\}"
+
+gdb_test "print -zero-values off -- t1" " = \\{i3 = 1, d2 = 2\\.5, p1 = $hex <ix>, t2 = \\{v1 = 3\\}, t3 = \\{v1 = 4, v2 = 5\\}, ia = \\{1, 2, 3, 4, 5, 6\\}, ipa = \\{$hex <ix>, $hex <t1>\\}\\}"
diff --git a/gdb/testsuite/gdb.python/py-format-string.c b/gdb/testsuite/gdb.python/py-format-string.c
index a771370fde..ee1c4ae684 100644
--- a/gdb/testsuite/gdb.python/py-format-string.c
+++ b/gdb/testsuite/gdb.python/py-format-string.c
@@ -113,6 +113,9 @@ main ()
 
   int *a_symbol_pointer = &global_symbol;
 
+  point_t zero_one_point = { 0, 1 };
+  int an_array_with_zeroes[] = { 1, 2, 0, 3, 4, 0, 5, 0 };
+
 #ifdef __cplusplus
   Deriv a_deriv (123);
   Base &a_base_ref = a_deriv;
diff --git a/gdb/testsuite/gdb.python/py-format-string.exp b/gdb/testsuite/gdb.python/py-format-string.exp
index f809ef30cb..5b78799062 100644
--- a/gdb/testsuite/gdb.python/py-format-string.exp
+++ b/gdb/testsuite/gdb.python/py-format-string.exp
@@ -874,6 +874,22 @@ proc test_format {} {
   }
 }
 
+proc test_zero_values {} {
+  check_format_string "zero_one_point" \
+    "raw=True" \
+    "\\{x = 0, y = 1\\}"
+  check_format_string "zero_one_point" \
+    "raw=True, zero_values=False" \
+    "\\{y = 1\\}"
+
+  check_format_string "an_array_with_zeroes" \
+    "raw=True" \
+    "\\{1, 2, 0, 3, 4, 0, 5, 0\\}"
+  check_format_string "an_array_with_zeroes" \
+    "raw=True, zero_values=False" \
+    "\\{1, 2, 3, 4, 5\\}"
+}
+
 # Test mixing options.
 proc test_mixed {} {
   global current_lang
@@ -948,6 +964,7 @@ proc test_all_common {} {
   test_max_depth
   test_repeat_threshold
   test_format
+  test_zero_values
   # Multiple options mixed together.
   test_mixed
   # Various error conditions.
diff --git a/gdb/valprint.c b/gdb/valprint.c
index 2cb7779161..fccdaccb4a 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -117,7 +117,8 @@ struct value_print_options user_print_options =
   0,				/* summary */
   1,				/* symbol_print */
   PRINT_MAX_DEPTH_DEFAULT,	/* max_depth */
-  1				/* finish_print */
+  1,				/* finish_print */
+  1,				/* zero_value_print */
 };
 
 /* Initialize *OPTS to be a copy of the user print options.  */
@@ -1859,6 +1860,23 @@ maybe_print_array_index (struct type *index_type, LONGEST index,
 
 /* See valprint.h.  */
 
+bool
+value_is_zero (struct value *v)
+{
+  struct type *type = check_typedef (value_type (v));
+  const gdb_byte *addr = value_contents_for_printing (v);
+  unsigned int len = TYPE_LENGTH (type);
+  unsigned int zeros;
+  for (zeros = 0; zeros < len; zeros++)
+    {
+      if (addr[zeros] != 0)
+	return false;
+    }
+  return true;
+}
+
+/* See valprint.h.  */
+
 void
 value_print_array_elements (struct value *val, struct ui_file *stream,
 			    int recurse,
@@ -1905,11 +1923,21 @@ value_print_array_elements (struct value *val, struct ui_file *stream,
 
   annotate_array_section_begin (i, elttype);
 
+  bool need_comma = i != 0;
   for (; i < len && things_printed < options->print_max; i++)
     {
       scoped_value_mark free_values;
 
-      if (i != 0)
+      /* If requested, skip printing of zero value fields.  */
+      if (!options->zero_value_print)
+	{
+	  struct value *v = value_from_component (val, elttype,
+						  eltlen * i);
+	  if (value_is_zero (v))
+	    continue;
+	}
+
+      if (need_comma)
 	{
 	  if (options->prettyformat_arrays)
 	    {
@@ -1963,6 +1991,8 @@ value_print_array_elements (struct value *val, struct ui_file *stream,
 	  annotate_elt ();
 	  things_printed++;
 	}
+
+      need_comma = true;
     }
   annotate_array_section_end ();
   if (i < len)
@@ -2967,6 +2997,17 @@ show_static_field_print (struct ui_file *file, int from_tty,
 		    value);
 }
 
+/* Controls printing of zero value members.  */
+static void
+show_zero_value_print (struct ui_file *file, int from_tty,
+		       struct cmd_list_element *c,
+		       const char *value)
+{
+  fprintf_filtered (file,
+		    _("Printing of zero value members is %s.\n"),
+		    value);
+}
+
 
 
 /* A couple typedefs to make writing the options a bit more
@@ -3110,6 +3151,15 @@ pretty-printers for that value.")
     N_("Show printing of C++ virtual function tables."),
     NULL, /* help_doc */
   },
+
+  boolean_option_def {
+    "zero-values",
+    [] (value_print_options *opt) { return &opt->zero_value_print; },
+    show_zero_value_print, /* show_cmd_cb */
+    N_("Set printing of zero value members."),
+    N_("Show printing of zero value members."),
+    NULL, /* help_doc */
+  },
 };
 
 /* See valprint.h.  */
diff --git a/gdb/valprint.h b/gdb/valprint.h
index 57bc0339fc..81b11452a4 100644
--- a/gdb/valprint.h
+++ b/gdb/valprint.h
@@ -100,6 +100,9 @@ struct value_print_options
 
   /* Whether "finish" should print the value.  */
   bool finish_print;
+
+  /* If true, print fields with a zero value.  */
+  bool zero_value_print;
 };
 
 /* Create an option_def_group for the value_print options, with OPTS
@@ -129,6 +132,10 @@ extern void maybe_print_array_index (struct type *index_type, LONGEST index,
 				     const struct value_print_options *);
 
 
+/* Check if V only contains zero bytes.  */
+
+extern bool value_is_zero (struct value *v);
+
 /* Print elements of an array.  */
 
 extern void value_print_array_elements (struct value *, struct ui_file *, int,
-- 
2.26.2



More information about the Gdb-patches mailing list