From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 24835 invoked by alias); 6 Oct 2010 20:49:48 -0000 Received: (qmail 24819 invoked by uid 22791); 6 Oct 2010 20:49:45 -0000 X-SWARE-Spam-Status: No, hits=-1.9 required=5.0 tests=AWL,BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,SPF_HELO_PASS,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (216.239.44.51) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 06 Oct 2010 20:49:39 +0000 Received: from hpaq1.eem.corp.google.com (hpaq1.eem.corp.google.com [172.25.149.1]) by smtp-out.google.com with ESMTP id o96Knbor005688 for ; Wed, 6 Oct 2010 13:49:37 -0700 Received: from ruffy.mtv.corp.google.com (ruffy.mtv.corp.google.com [172.18.118.116]) by hpaq1.eem.corp.google.com with ESMTP id o96KiZmj023583 for ; Wed, 6 Oct 2010 13:44:35 -0700 Received: by ruffy.mtv.corp.google.com (Postfix, from userid 67641) id DCD842461B2; Wed, 6 Oct 2010 13:44:34 -0700 (PDT) To: gdb-patches@sourceware.org Subject: [RFA] New python module gdb.types Message-Id: <20101006204434.DCD842461B2@ruffy.mtv.corp.google.com> Date: Wed, 06 Oct 2010 20:49:00 -0000 From: dje@google.com (Doug Evans) X-System-Of-Record: true X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2010-10/txt/msg00084.txt.bz2 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 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 . + +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 . */ + +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 . + +# 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')" + } +}