aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.python
diff options
context:
space:
mode:
authorAndrew Burgess <andrew.burgess@embecosm.com>2019-03-21 15:13:23 +0000
committerAndrew Burgess <andrew.burgess@embecosm.com>2019-04-29 22:01:09 +0100
commit2e62ab400ff96334c92e5acf0a462cb9dc0d19a7 (patch)
tree2904968bffb30b8fbac114461b987424210de56e /gdb/testsuite/gdb.python
parent4be290b2517839872ef7de47230be8dbd291a7e5 (diff)
downloadbinutils-2e62ab400ff96334c92e5acf0a462cb9dc0d19a7.zip
binutils-2e62ab400ff96334c92e5acf0a462cb9dc0d19a7.tar.gz
binutils-2e62ab400ff96334c92e5acf0a462cb9dc0d19a7.tar.bz2
gdb: Introduce 'print max-depth' feature
Introduce a new print setting max-depth which can be set with 'set print max-depth DEPTH'. The default value of DEPTH is 20, but this can also be set to unlimited. When GDB is printing a value containing nested structures GDB will stop descending at depth DEPTH. Here is a small example: typedef struct s1 { int a; } s1; typedef struct s2 { s1 b; } s2; typedef struct s3 { s2 c; } s3; typedef struct s4 { s3 d; } s4; s4 var = { { { { 3 } } } }; The following table shows how various depth settings affect printing of 'var': | Depth Setting | Result of 'p var' | |---------------+--------------------------------| | Unlimited | $1 = {d = {c = {b = {a = 3}}}} | | 4 | $1 = {d = {c = {b = {a = 3}}}} | | 3 | $1 = {d = {c = {b = {...}}}} | | 2 | $1 = {d = {c = {...}}} | | 1 | $1 = {d = {...}} | | 0 | $1 = {...} | Only structures, unions, and arrays are replaced in this way, scalars and strings are not replaced. The replacement is counted from the level at which you print, not from the top level of the structure. So, consider the above example and this GDB session: (gdb) set print max-depth 2 (gdb) p var $1 = {d = {c = {...}}} (gdb) p var.d $2 = {c = {b = {...}}} (gdb) p var.d.c $3 = {b = {a = 3}} Setting the max-depth to 2 doesn't prevent the user from exploring deeper into 'var' by asking for specific sub-fields to be printed. The motivation behind this feature is to try and give the user more control over how much is printed when examining large, complex data structures. The default max-depth of 20 means that there is a change in GDB's default behaviour. Someone printing a data structure with 20 levels of nesting will now see '{...}' instead of their data, they would need to adjust the max depth, or call print again naming a specific field in order to dig deeper into their data structure. If this is considered a problem then we could increase the default, or even make the default unlimited. This commit relies on the previous commit, which added a new field to the language structure, this new field was a string that contained the pattern that should be used when a structure/union/array is replaced in the output, this allows languages to use a syntax that is more appropriate, mostly this will be selecting the correct types of bracket '(...)' or '{...}', both of which are currently in use. This commit should have no impact on MI output, expressions are printed through the MI using -var-create and then -var-list-children. As each use of -var-list-children only ever displays a single level of an expression then the max-depth setting will have no impact. This commit also adds the max-depth mechanism to the scripting language pretty printers following basically the same rules as for the built in value printing. One quirk is that when printing a value using the display hint 'map', if the keys of the map are structs then GDB will hide the keys one depth level after it hides the values, this ensures that GDB produces output like this: $1 = map_object = {[{key1}] = {...}, [{key2}] = {...}} Instead of this less helpful output: $1 = map_object = {[{...}] = {...}, [{...}] = {...}} This is covered by the new tests in gdb.python/py-nested-maps.exp. gdb/ChangeLog: * cp-valprint.c (cp_print_value_fields): Allow an additional level of depth when printing anonymous structs or unions. * guile/scm-pretty-print.c (gdbscm_apply_val_pretty_printer): Don't print either the top-level value, or the children if the max-depth is exceeded. (ppscm_print_children): When printing the key of a map, allow one extra level of depth. * python/py-prettyprint.c (gdbpy_apply_val_pretty_printer): Don't print either the top-level value, or the children if the max-depth is exceeded. (print_children): When printing the key of a map, allow one extra level of depth. * python/py-value.c (valpy_format_string): Add max_depth keyword. * valprint.c: (PRINT_MAX_DEPTH_DEFAULT): Define. (user_print_options): Initialise max_depth field. (val_print_scalar_or_string_type_p): New function. (val_print): Check to see if the max depth has been reached. (val_print_check_max_depth): Define new function. (show_print_max_depth): New function. (_initialize_valprint): Add 'print max-depth' option. * valprint.h (struct value_print_options) <max_depth>: New field. (val_print_check_max_depth): Declare new function. * NEWS: Document new feature. gdb/doc/ChangeLog: * gdb.texinfo (Print Settings): Document 'print max-depth'. * guile.texi (Guile Pretty Printing API): Document that 'print max-depth' can effect the display of a values children. * python.texi (Pretty Printing API): Likewise. (Values From Inferior): Document max_depth keyword. gdb/testsuite/ChangeLog: * gdb.base/max-depth.c: New file. * gdb.base/max-depth.exp: New file. * gdb.python/py-nested-maps.c: New file. * gdb.python/py-nested-maps.exp: New file. * gdb.python/py-nested-maps.py: New file. * gdb.python/py-format-string.exp (test_max_depth): New proc. (test_all_common): Call test_max_depth. * gdb.fortran/max-depth.exp: New file. * gdb.fortran/max-depth.f90: New file. * gdb.go/max-depth.exp: New file. * gdb.go/max-depth.go: New file. * gdb.modula2/max-depth.exp: New file. * gdb.modula2/max-depth.c: New file. * lib/gdb.exp (get_print_expr_at_depths): New proc.
Diffstat (limited to 'gdb/testsuite/gdb.python')
-rw-r--r--gdb/testsuite/gdb.python/py-format-string.exp21
-rw-r--r--gdb/testsuite/gdb.python/py-nested-maps.c130
-rw-r--r--gdb/testsuite/gdb.python/py-nested-maps.exp238
-rw-r--r--gdb/testsuite/gdb.python/py-nested-maps.py135
4 files changed, 524 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.python/py-format-string.exp b/gdb/testsuite/gdb.python/py-format-string.exp
index 2f574fb..ebb2074 100644
--- a/gdb/testsuite/gdb.python/py-format-string.exp
+++ b/gdb/testsuite/gdb.python/py-format-string.exp
@@ -672,6 +672,26 @@ proc test_max_elements {} {
}
}
+# Test the max_depth option for gdb.Value.format_string.
+proc test_max_depth {} {
+ set opts "max_depth=-1"
+ with_test_prefix $opts {
+ check_format_string "a_struct_with_union" $opts
+ }
+ set opts "max_depth=0"
+ with_test_prefix $opts {
+ check_format_string "a_struct_with_union" $opts "\\{\.\.\.\\}"
+ }
+ set opts "max_depth=1"
+ with_test_prefix $opts {
+ check_format_string "a_struct_with_union" $opts "\\{the_union = \\{\.\.\.\\}\\}"
+ }
+ set opts "max_depth=2"
+ with_test_prefix $opts {
+ check_format_string "a_struct_with_union" $opts
+ }
+}
+
# Test the repeat_threshold option for gdb.Value.format_string.
proc test_repeat_threshold {} {
global current_lang
@@ -925,6 +945,7 @@ proc test_all_common {} {
test_actual_objects
test_static_members
test_max_elements
+ test_max_depth
test_repeat_threshold
test_format
# Multiple options mixed together.
diff --git a/gdb/testsuite/gdb.python/py-nested-maps.c b/gdb/testsuite/gdb.python/py-nested-maps.c
new file mode 100644
index 0000000..94107c0
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-nested-maps.c
@@ -0,0 +1,130 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2019 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/>. */
+
+#include <stdlib.h>
+#include <string.h>
+
+#define FIXED_MAP_SIZE 10
+
+struct key_t
+{
+ int a;
+ int b;
+};
+
+struct value_t
+{
+ int x;
+ int y;
+ int z;
+};
+
+struct map_t
+{
+ const char *name;
+ int length;
+ struct key_t *keys;
+ struct value_t *values;
+
+ /* This field is used only by the pretty printer. */
+ int show_header;
+};
+
+struct map_map_t
+{
+ int length;
+ struct map_t **values;
+
+ /* This field is used only by the pretty printer. */
+ int show_header;
+};
+
+struct map_t *
+create_map (const char *name)
+{
+ struct map_t *m = malloc (sizeof (struct map_t));
+ m->name = strdup (name);
+ m->length = 0;
+ m->keys = NULL;
+ m->values = NULL;
+ m->show_header = 0;
+}
+
+void
+add_map_element (struct map_t *m, struct key_t k, struct value_t v)
+{
+ if (m->length == 0)
+ {
+ m->keys = malloc (sizeof (struct key_t) * FIXED_MAP_SIZE);
+ m->values = malloc (sizeof (struct value_t) * FIXED_MAP_SIZE);
+ }
+
+ m->keys[m->length] = k;
+ m->values[m->length] = v;
+ m->length++;
+}
+
+struct map_map_t *
+create_map_map (void)
+{
+ struct map_map_t *mm = malloc (sizeof (struct map_map_t));
+ mm->length = 0;
+ mm->values = NULL;
+ mm->show_header = 0;
+}
+
+void
+add_map_map_element (struct map_map_t *mm, struct map_t *map)
+{
+ if (mm->length == 0)
+ mm->values = malloc (sizeof (struct map_t *) * FIXED_MAP_SIZE);
+
+ mm->values[mm->length] = map;
+ mm->length++;
+}
+
+int
+main (void)
+{
+ struct map_t *m1 = create_map ("m1");
+ struct key_t k1 = {3, 4};
+ struct key_t k2 = {4, 5};
+ struct key_t k3 = {5, 6};
+ struct key_t k4 = {6, 7};
+ struct key_t k5 = {7, 8};
+ struct key_t k6 = {8, 9};
+ struct value_t v1 = {0, 1, 2};
+ struct value_t v2 = {3, 4, 5};
+ struct value_t v3 = {6, 7, 8};
+ struct value_t v4 = {9, 0, 1};
+ struct value_t v5 = {2, 3, 4};
+ struct value_t v6 = {5, 6, 7};
+ add_map_element (m1, k1, v1);
+ add_map_element (m1, k2, v2);
+ add_map_element (m1, k3, v3);
+
+ struct map_t *m2 = create_map ("m2");
+ add_map_element (m2, k4, v4);
+ add_map_element (m2, k5, v5);
+ add_map_element (m2, k6, v6);
+
+ struct map_map_t *mm = create_map_map ();
+ add_map_map_element (mm, m1);
+ add_map_map_element (mm, m2);
+
+ return 0; /* Break here. */
+}
diff --git a/gdb/testsuite/gdb.python/py-nested-maps.exp b/gdb/testsuite/gdb.python/py-nested-maps.exp
new file mode 100644
index 0000000..81dd99c
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-nested-maps.exp
@@ -0,0 +1,238 @@
+# Copyright (C) 2019 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/>.
+
+# This tests GDB's python pretty printing of nested map like
+# structures using structures as keys and values, it then tests how
+# 'set print max-depth' affects this printing.
+
+load_lib gdb-python.exp
+
+standard_testfile
+
+# Start with a fresh gdb.
+gdb_exit
+gdb_start
+
+# Skip all tests if Python scripting is not enabled.
+if { [skip_python_tests] } { continue }
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile {debug}] } {
+ return -1
+}
+
+if ![runto_main ] then {
+ return -1
+}
+
+gdb_breakpoint [gdb_get_line_number "Break here"]
+gdb_continue_to_breakpoint "run to testing point" ".*Break here.*"
+
+set remote_python_file [gdb_remote_download host \
+ ${srcdir}/${subdir}/${testfile}.py]
+gdb_test_no_output "source ${remote_python_file}" "load python file"
+
+# Test printing with 'set print pretty off'.
+gdb_test_no_output "set print pretty off"
+with_test_prefix "pretty=off" {
+ gdb_print_expr_at_depths "*m1" \
+ [list \
+ "\{\\.\\.\\.\}" \
+ "\{\\\[\{a = 3, b = 4\}\\\] = \{\\.\\.\\.\}, \\\[\{a = 4, b = 5\}\\\] = \{\\.\\.\\.\}, \\\[\{a = 5, b = 6\}\\\] = \{\\.\\.\\.\}\}" \
+ "\{\\\[\{a = 3, b = 4\}\\\] = \{x = 0, y = 1, z = 2\}, \\\[\{a = 4, b = 5\}\\\] = \{x = 3, y = 4, z = 5\}, \\\[\{a = 5, b = 6\}\\\] = \{x = 6, y = 7, z = 8\}\}" \
+ ]
+
+ gdb_print_expr_at_depths "*mm" \
+ [list \
+ "\{\\.\\.\\.\}" \
+ "\{\\\[$hex \"m1\"\\\] = \{\\.\\.\\.\}, \\\[$hex \"m2\"\\\] = \{\\.\\.\\.\}\}" \
+ "\{\\\[$hex \"m1\"\\\] = \{\\\[\{a = 3, b = 4\}\\\] = \{\\.\\.\\.\}, \\\[\{a = 4, b = 5\}\\\] = \{\\.\\.\\.\}, \\\[\{a = 5, b = 6\}\\\] = \{\\.\\.\\.\}\}, \\\[$hex \"m2\"\\\] = \{\\\[\{a = 6, b = 7\}\\\] = \{\\.\\.\\.\}, \\\[\{a = 7, b = 8\}\\\] = \{\\.\\.\\.\}, \\\[\{a = 8, b = 9\}\\\] = \{\\.\\.\\.\}\}\}" \
+ "\{\\\[$hex \"m1\"\\\] = \{\\\[\{a = 3, b = 4\}\\\] = \{x = 0, y = 1, z = 2\}, \\\[\{a = 4, b = 5\}\\\] = \{x = 3, y = 4, z = 5\}, \\\[\{a = 5, b = 6\}\\\] = \{x = 6, y = 7, z = 8\}\}, \\\[$hex \"m2\"\\\] = \{\\\[\{a = 6, b = 7\}\\\] = \{x = 9, y = 0, z = 1\}, \\\[\{a = 7, b = 8\}\\\] = \{x = 2, y = 3, z = 4\}, \\\[\{a = 8, b = 9\}\\\] = \{x = 5, y = 6, z = 7\}\}\}" \
+ ]
+}
+
+# Now again, but with 'set print pretty on'.
+gdb_test_no_output "set print pretty on"
+with_test_prefix "pretty=on" {
+ gdb_print_expr_at_depths "*m1" \
+ [list \
+ "\{\\.\\.\\.\}" \
+ [multi_line \
+ " = \{" \
+ " \\\[\{" \
+ " a = 3," \
+ " b = 4" \
+ " \}\\\] = \{\\.\\.\\.\}," \
+ " \\\[\{" \
+ " a = 4," \
+ " b = 5" \
+ " \}\\\] = \{\\.\\.\\.\}," \
+ " \\\[\{" \
+ " a = 5," \
+ " b = 6" \
+ " \}\\\] = \{\\.\\.\\.\}" \
+ "\}" ] \
+ [multi_line \
+ " = \{" \
+ " \\\[\{" \
+ " a = 3," \
+ " b = 4" \
+ " \}\\\] = \{" \
+ " x = 0," \
+ " y = 1," \
+ " z = 2" \
+ " \}," \
+ " \\\[\{" \
+ " a = 4," \
+ " b = 5" \
+ " \}\\\] = \{" \
+ " x = 3," \
+ " y = 4," \
+ " z = 5" \
+ " \}," \
+ " \\\[\{" \
+ " a = 5," \
+ " b = 6" \
+ " \}\\\] = \{" \
+ " x = 6," \
+ " y = 7," \
+ " z = 8" \
+ " \}" \
+ "\}" ] \
+ ]
+
+ gdb_print_expr_at_depths "*mm" \
+ [list \
+ "\{\\.\\.\\.\}" \
+ [multi_line \
+ " = \{" \
+ " \\\[$hex \"m1\"\\\] = \{\\.\\.\\.\}," \
+ " \\\[$hex \"m2\"\\\] = \{\\.\\.\\.\}" \
+ "\}" ] \
+ [multi_line \
+ " = \{" \
+ " \\\[$hex \"m1\"\\\] = \{" \
+ " \\\[\{" \
+ " a = 3," \
+ " b = 4" \
+ " \}\\\] = \{\\.\\.\\.\}," \
+ " \\\[\{" \
+ " a = 4," \
+ " b = 5" \
+ " \}\\\] = \{\\.\\.\\.\}," \
+ " \\\[\{" \
+ " a = 5," \
+ " b = 6" \
+ " \}\\\] = \{\\.\\.\\.\}" \
+ " \}," \
+ " \\\[$hex \"m2\"\\\] = \{" \
+ " \\\[\{" \
+ " a = 6," \
+ " b = 7" \
+ " \}\\\] = \{\\.\\.\\.\}," \
+ " \\\[\{" \
+ " a = 7," \
+ " b = 8" \
+ " \}\\\] = \{\\.\\.\\.\}," \
+ " \\\[\{" \
+ " a = 8," \
+ " b = 9" \
+ " \}\\\] = \{\\.\\.\\.\}" \
+ " \}" \
+ "\}" ] \
+ [multi_line \
+ " = \{" \
+ " \\\[$hex \"m1\"\\\] = \{" \
+ " \\\[\{" \
+ " a = 3," \
+ " b = 4" \
+ " \}\\\] = \{" \
+ " x = 0," \
+ " y = 1," \
+ " z = 2" \
+ " \}," \
+ " \\\[\{" \
+ " a = 4," \
+ " b = 5" \
+ " \}\\\] = \{" \
+ " x = 3," \
+ " y = 4," \
+ " z = 5" \
+ " \}," \
+ " \\\[\{" \
+ " a = 5," \
+ " b = 6" \
+ " \}\\\] = \{" \
+ " x = 6," \
+ " y = 7," \
+ " z = 8" \
+ " \}" \
+ " \}," \
+ " \\\[$hex \"m2\"\\\] = \{" \
+ " \\\[\{" \
+ " a = 6," \
+ " b = 7" \
+ " \}\\\] = \{" \
+ " x = 9," \
+ " y = 0," \
+ " z = 1" \
+ " \}," \
+ " \\\[\{" \
+ " a = 7," \
+ " b = 8" \
+ " \}\\\] = \{" \
+ " x = 2," \
+ " y = 3," \
+ " z = 4" \
+ " \}," \
+ " \\\[\{" \
+ " a = 8," \
+ " b = 9" \
+ " \}\\\] = \{" \
+ " x = 5," \
+ " y = 6," \
+ " z = 7" \
+ " \}" \
+ " \}" \
+ "\}" ] \
+ ]
+}
+
+# Test printing with 'set print pretty off', but this time display a
+# top level string (returned from the to_string method) as part of the
+# printed value.
+gdb_test_no_output "set mm->show_header=1"
+gdb_test_no_output "set m1->show_header=1"
+gdb_test_no_output "set m2->show_header=1"
+with_test_prefix "headers=on" {
+ gdb_test_no_output "set print pretty off"
+ with_test_prefix "pretty=off" {
+ gdb_print_expr_at_depths "*m1" \
+ [list \
+ "\{\\.\\.\\.\}" \
+ "pp_map = \{\\\[\{a = 3, b = 4\}\\\] = \{\\.\\.\\.\}, \\\[\{a = 4, b = 5\}\\\] = \{\\.\\.\\.\}, \\\[\{a = 5, b = 6\}\\\] = \{\\.\\.\\.\}\}" \
+ "pp_map = \{\\\[\{a = 3, b = 4\}\\\] = \{x = 0, y = 1, z = 2\}, \\\[\{a = 4, b = 5\}\\\] = \{x = 3, y = 4, z = 5\}, \\\[\{a = 5, b = 6\}\\\] = \{x = 6, y = 7, z = 8\}\}" \
+ ]
+
+ gdb_print_expr_at_depths "*mm" \
+ [list \
+ "\{\\.\\.\\.\}" \
+ "pp_map_map = \{\\\[$hex \"m1\"\\\] = \{\\.\\.\\.\}, \\\[$hex \"m2\"\\\] = \{\\.\\.\\.\}\}" \
+ "pp_map_map = \{\\\[$hex \"m1\"\\\] = pp_map = \{\\\[\{a = 3, b = 4\}\\\] = \{\\.\\.\\.\}, \\\[\{a = 4, b = 5\}\\\] = \{\\.\\.\\.\}, \\\[\{a = 5, b = 6\}\\\] = \{\\.\\.\\.\}\}, \\\[$hex \"m2\"\\\] = pp_map = \{\\\[\{a = 6, b = 7\}\\\] = \{\\.\\.\\.\}, \\\[\{a = 7, b = 8\}\\\] = \{\\.\\.\\.\}, \\\[\{a = 8, b = 9\}\\\] = \{\\.\\.\\.\}\}\}" \
+ "pp_map_map = \{\\\[$hex \"m1\"\\\] = pp_map = \{\\\[\{a = 3, b = 4\}\\\] = \{x = 0, y = 1, z = 2\}, \\\[\{a = 4, b = 5\}\\\] = \{x = 3, y = 4, z = 5\}, \\\[\{a = 5, b = 6\}\\\] = \{x = 6, y = 7, z = 8\}\}, \\\[$hex \"m2\"\\\] = pp_map = \{\\\[\{a = 6, b = 7\}\\\] = \{x = 9, y = 0, z = 1\}, \\\[\{a = 7, b = 8\}\\\] = \{x = 2, y = 3, z = 4\}, \\\[\{a = 8, b = 9\}\\\] = \{x = 5, y = 6, z = 7\}\}\}" \
+ ]
+ }
+}
diff --git a/gdb/testsuite/gdb.python/py-nested-maps.py b/gdb/testsuite/gdb.python/py-nested-maps.py
new file mode 100644
index 0000000..d3fdf59
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-nested-maps.py
@@ -0,0 +1,135 @@
+# Copyright (C) 2019 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/>.
+
+# This file is part of the GDB testsuite. It tests GDB's printing of
+# nested map like structures.
+
+import re
+import gdb
+
+def _iterator1 (pointer, len):
+ while len > 0:
+ map = pointer.dereference()
+ yield ('', map['name'])
+ yield ('', map.dereference())
+ pointer += 1
+ len -= 1
+
+def _iterator2 (pointer1, pointer2, len):
+ while len > 0:
+ yield ("", pointer1.dereference())
+ yield ("", pointer2.dereference())
+ pointer1 += 1
+ pointer2 += 1
+ len -= 1
+
+class pp_map (object):
+ def __init__(self, val):
+ self.val = val
+
+ def to_string(self):
+ if (self.val['show_header'] == 0):
+ return None
+ else:
+ return "pp_map"
+
+ def children(self):
+ return _iterator2(self.val['keys'],
+ self.val['values'],
+ self.val['length'])
+
+ def display_hint (self):
+ return 'map'
+
+class pp_map_map (object):
+ def __init__(self, val):
+ self.val = val
+
+ def to_string(self):
+ if (self.val['show_header'] == 0):
+ return None
+ else:
+ return "pp_map_map"
+
+ def children(self):
+ return _iterator1(self.val['values'],
+ self.val['length'])
+
+ def display_hint (self):
+ return 'map'
+
+def lookup_function (val):
+ "Look-up and return a pretty-printer that can print val."
+
+ # Get the type.
+ type = val.type
+
+ # If it points to a reference, get the reference.
+ if type.code == gdb.TYPE_CODE_REF:
+ type = type.target ()
+
+ # Get the unqualified type, stripped of typedefs.
+ type = type.unqualified ().strip_typedefs ()
+
+ # Get the type name.
+ typename = type.tag
+
+ if typename == None:
+ return None
+
+ # Iterate over local dictionary of types to determine
+ # if a printer is registered for that type. Return an
+ # instantiation of the printer if found.
+ for function in pretty_printers_dict:
+ if function.match (typename):
+ return pretty_printers_dict[function] (val)
+
+ # Cannot find a pretty printer. Return None.
+ return None
+
+# Lookup a printer for VAL in the typedefs dict.
+def lookup_typedefs_function (val):
+ "Look-up and return a pretty-printer that can print val (typedefs)."
+
+ # Get the type.
+ type = val.type
+
+ if type == None or type.name == None or type.code != gdb.TYPE_CODE_TYPEDEF:
+ return None
+
+ # Iterate over local dictionary of typedef types to determine if a
+ # printer is registered for that type. Return an instantiation of
+ # the printer if found.
+ for function in typedefs_pretty_printers_dict:
+ if function.match (type.name):
+ return typedefs_pretty_printers_dict[function] (val)
+
+ # Cannot find a pretty printer.
+ return None
+
+def register_pretty_printers ():
+ pretty_printers_dict[re.compile ('^struct map_t$')] = pp_map
+ pretty_printers_dict[re.compile ('^map_t$')] = pp_map
+ pretty_printers_dict[re.compile ('^struct map_map_t$')] = pp_map_map
+ pretty_printers_dict[re.compile ('^map_map_t$')] = pp_map_map
+
+# Dict for struct types with typedefs fully stripped.
+pretty_printers_dict = {}
+# Dict for typedef types.
+typedefs_pretty_printers_dict = {}
+
+register_pretty_printers ()
+gdb.pretty_printers.append (lookup_function)
+gdb.pretty_printers.append (lookup_typedefs_function)