This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[RFA] New python module gdb.types
- From: dje at google dot com (Doug Evans)
- To: gdb-patches at sourceware dot org
- Date: Wed, 6 Oct 2010 13:44:34 -0700 (PDT)
- Subject: [RFA] New python module gdb.types
Hi.
This patch adds a new python module to gdb, gdb.types.
It contains a small collection of utilities that I've been using.
Ok to check in?
2010-10-06 Doug Evans <dje@google.com>
New python module gdb.types.
* NEWS: Document it.
* data-directory/Makefile.in (PYTHON_FILES): Add gdb/types.py.
* python/lib/gdb/types.py: New file.
testsuite/
* lib/gdb-python.exp (gdb_check_python_config): New function.
* gdb.python/Makefile.in (EXECUTABLES): Add lib-types.
* gdb.python/lib-types.cc: New file.
* gdb.python/lib-types.exp: New file.
doc/
* gdb.texinfo (Python): Add "Python modules".
(Python modules): New node.
Index: NEWS
===================================================================
RCS file: /cvs/src/src/gdb/NEWS,v
retrieving revision 1.406
diff -u -p -r1.406 NEWS
--- NEWS 28 Sep 2010 21:40:23 -0000 1.406
+++ NEWS 6 Oct 2010 20:32:43 -0000
@@ -12,6 +12,10 @@
result = some_value (10,20)
+ ** Module gdb.types has been added.
+ It contains a collection of utilities for working with gdb.Types objects:
+ get_basic_type, has_field, make_enum_dict.
+
* C++ Improvements:
** GDB now puts template parameters in scope when debugging in an
Index: data-directory/Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/data-directory/Makefile.in,v
retrieving revision 1.1
diff -u -p -r1.1 Makefile.in
--- data-directory/Makefile.in 6 Oct 2010 16:02:44 -0000 1.1
+++ data-directory/Makefile.in 6 Oct 2010 20:32:43 -0000
@@ -51,7 +51,8 @@ SYSCALLS_FILES = \
PYTHON_DIR = python
PYTHON_INSTALL_DIR = $(DESTDIR)/$(GDB_DATADIR)/$(PYTHON_DIR)
PYTHON_FILES = \
- gdb/__init__.py
+ gdb/__init__.py \
+ gdb/types.py
# Host-dependent makefile fragment comes in here.
@host_makefile_frag@
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.767
diff -u -p -r1.767 gdb.texinfo
--- doc/gdb.texinfo 28 Sep 2010 21:40:23 -0000 1.767
+++ doc/gdb.texinfo 6 Oct 2010 20:32:43 -0000
@@ -20401,6 +20401,7 @@ the Python interpreter to locate all scr
* Python Commands:: Accessing Python from @value{GDBN}.
* Python API:: Accessing @value{GDBN} from Python.
* Auto-loading:: Automatically loading Python code.
+* Python modules:: Python modules provided by @value{GDBN}.
@end menu
@node Python Commands
@@ -22911,6 +22912,27 @@ cumbersome. It may be easier to specify
top of the source tree to the source search path.
@end itemize
+@node Python modules
+@subsection Python modules
+@cindex Python modules
+
+@value{GDBN} comes with module @code{gdb.types}.
+It provides a collection of utilities for working with @code{gdb.Types}
+objects.
+
+@table @code
+@item get_basic_type (@var{type})
+Return @var{type} with const and volatile qualifiers, typedefs,
+and references stripped away.
+
+@item has_field (@var{type}, @var{field})
+Return @code{True} if @var{type}, assumed to be a type with fields
+(e.g., a class, structure, or union), has field @var{field}.
+
+@item make_enum_dict (@var{enum_type})
+Return a dictionary made from @var{enum_type}.
+@end table
+
@node Interpreters
@chapter Command Interpreters
@cindex command interpreters
Index: python/lib/gdb/types.py
===================================================================
RCS file: python/lib/gdb/types.py
diff -N python/lib/gdb/types.py
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ python/lib/gdb/types.py 6 Oct 2010 20:32:43 -0000
@@ -0,0 +1,58 @@
+# Type utilities.
+# Copyright (C) 2010 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/>.
+
+import gdb
+
+# Given a type, return the same type with references, typedefs and qualifiers
+# (const, volatile) stripped away.
+
+def get_basic_type (typ):
+ """Return the 'basic' type of type TYP."""
+
+ if typ.code == gdb.TYPE_CODE_REF:
+ typ = typ.target ()
+ return typ.unqualified ().strip_typedefs ()
+
+# Return True if FIELD is in type TYP (spelled this way to avoid collision
+# with python's "type"), with extra handling so references, typedefs, and
+# subclasses "just work".
+
+def has_field (typ, field):
+ """Return True if type TYPE has the specified field."""
+
+ typ = get_basic_type (typ)
+ for f in typ.fields ():
+ if f.is_base_class:
+ if has_field (f.type, field):
+ return True
+ else:
+ # NOTE: f.name could be None
+ if f.name == field:
+ return True
+ return False
+
+# Create a dictionary out of an enum type.
+
+def make_enum_dict (enum_type):
+ """Build a dictionary from a program's enum type."""
+
+ if enum_type.code != gdb.TYPE_CODE_ENUM:
+ raise TypeError ("not an enum type")
+ enum_dict = {}
+ for field in enum_type.fields():
+ # The enum's value is stored in "bitpos".
+ enum_dict[field.name] = field.bitpos
+ return enum_dict
Index: testsuite/gdb.python/Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.python/Makefile.in,v
retrieving revision 1.8
diff -u -p -r1.8 Makefile.in
--- testsuite/gdb.python/Makefile.in 19 Aug 2010 17:00:57 -0000 1.8
+++ testsuite/gdb.python/Makefile.in 6 Oct 2010 20:32:43 -0000
@@ -3,7 +3,7 @@ srcdir = @srcdir@
EXECUTABLES = py-type py-value py-prettyprint py-template py-block \
py-symbol py-mi py-breakpoint py-inferior py-infthread \
- py-shared python
+ py-shared python lib-types
MISCELLANEOUS = py-shared-sl.sl
Index: testsuite/gdb.python/lib-types.cc
===================================================================
RCS file: testsuite/gdb.python/lib-types.cc
diff -N testsuite/gdb.python/lib-types.cc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/gdb.python/lib-types.cc 6 Oct 2010 20:32:43 -0000
@@ -0,0 +1,53 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2010 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/>. */
+
+class class1
+{
+ public:
+ class1 (int _x) : x (_x) {}
+ int x;
+};
+
+class1 simple_class1 (42);
+const class1 const_class1 (42);
+volatile class1 volatile_class1 (42);
+const volatile class1 const_volatile_class1 (42);
+
+typedef class1 class2;
+
+class2 typedef_class1 (42);
+
+class1& ref_class1 (simple_class1);
+
+class subclass1 : public class1
+{
+ public:
+ subclass1 (int _x, int _y) : class1 (_x), y (_y) {}
+ int y;
+};
+
+subclass1 simple_subclass1 (42, 43);
+
+enum enum1 { A, B, C };
+
+enum1 simple_enum1 (A);
+
+int
+main ()
+{
+ return 0;
+}
Index: testsuite/gdb.python/lib-types.exp
===================================================================
RCS file: testsuite/gdb.python/lib-types.exp
diff -N testsuite/gdb.python/lib-types.exp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/gdb.python/lib-types.exp 6 Oct 2010 20:32:43 -0000
@@ -0,0 +1,123 @@
+# Copyright (C) 2010 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 the types.py module.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+load_lib gdb-python.exp
+
+set testfile "lib-types"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ untested "Couldn't compile ${srcfile}"
+ return -1
+}
+
+# Start with a fresh gdb.
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# Skip all tests if Python scripting is not enabled.
+if { [skip_python_tests] } { continue }
+
+if ![runto_main] then {
+ fail "Can't run to main"
+ return 0
+}
+
+# Ensure sys.path, et.al. are initialized properly.
+gdb_check_python_config
+
+gdb_test_no_output "python import gdb.types"
+
+# test get_basic_type const stripping
+gdb_test_no_output "python const_class1 = gdb.parse_and_eval ('const_class1')"
+gdb_test_no_output "python basic_type_const_class1 = gdb.types.get_basic_type (const_class1.type)"
+gdb_test "python print str (const_class1.type)" "const class1"
+set test "const stripping"
+gdb_test_multiple "python print str (basic_type_const_class1)" $test {
+ -re "\[\r\n\]+class1\[\r\n\]+$gdb_prompt $" {
+ pass $test
+ }
+}
+
+gdb_test "python print str (basic_type_const_class1)" "class1"
+
+# test get_basic_type volatile stripping
+gdb_test_no_output "python volatile_class1 = gdb.parse_and_eval ('volatile_class1')"
+gdb_test_no_output "python basic_type_volatile_class1 = gdb.types.get_basic_type (volatile_class1.type)"
+gdb_test "python print str (volatile_class1.type)" "volatile class1"
+set test "volatile stripping"
+gdb_test_multiple "python print str (basic_type_volatile_class1)" $test {
+ -re "\[\r\n\]+class1\[\r\n\]+$gdb_prompt $" {
+ pass $test
+ }
+}
+
+# test get_basic_type volatile+const stripping
+gdb_test_no_output "python const_volatile_class1 = gdb.parse_and_eval ('const_volatile_class1')"
+gdb_test_no_output "python basic_type_const_volatile_class1 = gdb.types.get_basic_type (const_volatile_class1.type)"
+gdb_test "python print str (const_volatile_class1.type)" "const volatile class1"
+set test "volatile+const stripping"
+gdb_test_multiple "python print str (basic_type_const_volatile_class1)" $test {
+ -re "\[\r\n\]+class1\[\r\n\]+$gdb_prompt $" {
+ pass $test
+ }
+}
+
+# test get_basic_type typedef stripping
+gdb_test_no_output "python typedef_class1 = gdb.parse_and_eval ('typedef_class1')"
+gdb_test_no_output "python basic_type_typedef_class1 = gdb.types.get_basic_type (typedef_class1.type)"
+gdb_test "python print str (typedef_class1.type)" "class2"
+set test "typedef stripping"
+gdb_test_multiple "python print str (basic_type_typedef_class1)" $test {
+ -re "\[\r\n\]+class1\[\r\n\]+$gdb_prompt $" {
+ pass $test
+ }
+}
+
+# test get_basic_type reference stripping
+gdb_test_no_output "python ref_class1 = gdb.parse_and_eval ('ref_class1')"
+gdb_test_no_output "python basic_type_ref_class1 = gdb.types.get_basic_type (ref_class1.type)"
+gdb_test "python print str (ref_class1.type)" "class1 &"
+set test "reference stripping"
+gdb_test_multiple "python print str (basic_type_ref_class1)" $test {
+ -re "\[\r\n\]+class1\[\r\n\]+$gdb_prompt $" {
+ pass $test
+ }
+}
+
+# test has_field on simple class
+gdb_test_no_output "python simple_class1 = gdb.parse_and_eval ('simple_class1')"
+gdb_test "python print gdb.types.has_field (simple_class1.type, 'x')" "True"
+gdb_test "python print gdb.types.has_field (simple_class1.type, 'nope')" "False"
+
+# test has_field in base class
+gdb_test_no_output "python simple_subclass1 = gdb.parse_and_eval ('simple_subclass1')"
+gdb_test "python print gdb.types.has_field (simple_class1.type, 'x')" "True"
+
+# test make_enum_dict
+gdb_test_no_output "python simple_enum1 = gdb.parse_and_eval ('simple_enum1')"
+gdb_test_no_output "python enum1_dict = gdb.types.make_enum_dict (simple_enum1.type)"
+gdb_test_no_output "python enum1_list = enum1_dict.items ()"
+gdb_test_no_output "python enum1_list.sort ()"
+gdb_test "python print enum1_list" {\[\('A', 0L\), \('B', 1L\), \('C', 2L\)\]}
Index: testsuite/lib/gdb-python.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/lib/gdb-python.exp,v
retrieving revision 1.1
diff -u -p -r1.1 gdb-python.exp
--- testsuite/lib/gdb-python.exp 1 Oct 2010 17:03:50 -0000 1.1
+++ testsuite/lib/gdb-python.exp 6 Oct 2010 20:32:43 -0000
@@ -45,3 +45,21 @@ proc gdb_py_test_multiple { name args }
}
return 0
}
+
+# Establish various python configuration parameters if necessary.
+# E.g. sys.path.
+
+proc gdb_check_python_config { } {
+ global USE_INSTALLED_TREE
+ # If we're running an installed version of gdb, and we want to test the
+ # installed versions of the python support scripts, then we don't want
+ # to point data-directory at the build tree.
+ if { [info exists USE_INSTALLED_TREE] && "$USE_INSTALLED_TREE" == "yes" } {
+ verbose -log "Assuming system config already installed."
+ } else {
+ verbose -log "Installing system config from build tree."
+ set gdb_data_dir "[pwd]/../data-directory"
+ gdb_test_no_output "set data-directory $gdb_data_dir"
+ gdb_test_no_output "python GdbSetPythonDirectory ('$gdb_data_dir/python')"
+ }
+}