From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 1057 invoked by alias); 10 Aug 2012 04:14:47 -0000 Received: (qmail 1037 invoked by uid 22791); 10 Aug 2012 04:14:42 -0000 X-SWARE-Spam-Status: No, hits=-4.8 required=5.0 tests=AWL,BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,KHOP_RCVD_TRUST,KHOP_THREADED,RCVD_IN_DNSWL_LOW,RCVD_IN_HOSTKARMA_YE,TW_BJ,TW_FN,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail-ob0-f201.google.com (HELO mail-ob0-f201.google.com) (209.85.214.201) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 10 Aug 2012 04:14:27 +0000 Received: by obbun3 with SMTP id un3so795193obb.0 for ; Thu, 09 Aug 2012 21:14:26 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=mime-version:content-type:content-transfer-encoding:message-id:date :to:cc:subject:in-reply-to:references:x-mailer:from :x-gm-message-state; bh=dvTqJajNVjEsvsvTuwj2B94URJxCo0gSuZTIL9eGyxE=; b=V3wURP0NLN8oc5tIaymJmXDo5t21ZFUaD1nPzKnR5Wydv9SobaDRCf1oBhB4IiuZ/h rD9onAqCoIW1701Wl9EEY/4fcZnkS3mzIYd1uwhNSrG3i0Vls5CJf5sHwW5Ya66HHCAk DPlotCENVOdH+cDQZL3JKR2DVmoMDRyg4lkhYblwHoZMLmCSk7bKl+5Eb8gRqKOip/xM R1LZ13jPdBeUKYjdtYJpRM7KG9q+P73LvJW1jPyMvyaZT0LgrPLl7sBzHjmk/5tht7aN TxTiSlBpmBrKg//TaKz+Jwlas2Lbms7bPxMB1Qi67frhxO/O7KhHmsoDsBxCHIW7Slbf xl0w== Received: by 10.42.167.72 with SMTP id r8mr832641icy.15.1344572066757; Thu, 09 Aug 2012 21:14:26 -0700 (PDT) Received: by 10.42.167.72 with SMTP id r8mr832631icy.15.1344572066700; Thu, 09 Aug 2012 21:14:26 -0700 (PDT) Received: from wpzn3.hot.corp.google.com (216-239-44-65.google.com [216.239.44.65]) by gmr-mx.google.com with ESMTPS id bg10si789913igc.3.2012.08.09.21.14.26 (version=TLSv1/SSLv3 cipher=AES128-SHA); Thu, 09 Aug 2012 21:14:26 -0700 (PDT) Received: from ruffy.mtv.corp.google.com (ruffy.mtv.corp.google.com [172.18.110.50]) by wpzn3.hot.corp.google.com (Postfix) with ESMTP id 81286100048; Thu, 9 Aug 2012 21:14:25 -0700 (PDT) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Message-ID: <20516.35488.801568.883424@ruffy.mtv.corp.google.com> Date: Fri, 10 Aug 2012 04:14:00 -0000 To: Tom Tromey , Eli Zaretskii , jan.kratochvil@redhat.com Cc: gdb-patches@sourceware.org Subject: Re: [RFA, doc RFA] Implement $_memeq, $_streq, $_strlen In-Reply-To: References: <834nodfi6f.fsf@gnu.org> <20514.39220.59446.622043@ruffy2.mtv.corp.google.com> <871ujhgt7h.fsf@fleche.redhat.com> From: dje@google.com X-Gm-Message-State: ALoCoQn+mUIirDdgrfGzYpl4aL6Ui+WmoYyQB7JZD6gigjJ+X9E4bsPBLIXDOzB2jXIe63N6nVTPMic4T1KNrLiVNyGsK5uIdlNEUtzzJLmLLF3b0qknqkuJhHFbMexehmI1F9qOLq3JdmNFG+WyzYROofv8zjQDtqPgCyQ3BDfOlyFD+dta++ZtUW2YpPeBih2NhX2SdmlmHGDSsyUG1XNpx/CgWaWfkQ== 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: 2012-08/txt/msg00302.txt.bz2 Here's, hopefully, my final revision. Ok to check in? 2012-08-09 Doug Evans Add $_memeq, $_regex, $_streq, $_strlen convenience functions. * NEWS: Document them. * data-directory/Makefile.in (PYTHON_FILES): Add function/__init__.py, function/strfns.py. * python/py-type.c (typy_array_1): New function. (typy_array): Call it. (typy_vector): New function. (type_object_methods): Add "vector". * python/lib/gdb/function/__init__.py: New file. * python/lib/gdb/function/strfns.py: New file. doc/ * gdb.texinfo (Convenience Funs): New node. (Types In Python): Document Type.vector. testsuite/ * gdb.python/py-strfns.c: New file. * gdb.python/py-strfns.exp: New file. * gdb.python/py-type.exp (test_fields): Add vector tests. Index: NEWS =================================================================== RCS file: /cvs/src/src/gdb/NEWS,v retrieving revision 1.539 diff -u -p -r1.539 NEWS --- NEWS 9 Aug 2012 12:53:43 -0000 1.539 +++ NEWS 10 Aug 2012 03:59:28 -0000 @@ -3,6 +3,17 @@ *** Changes since GDB 7.5 +* Python scripting + + ** Vectors can be created with gdb.Type.vector. + +* New Python-based convenience functions: + + ** $_memeq(buf1, buf2, length) + ** $_streq(str1, str2) + ** $_strlen(str) + ** $_regex(str, regex) + * The 'cd' command now defaults to using '~' (the home directory) if not given an argument. Index: data-directory/Makefile.in =================================================================== RCS file: /cvs/src/src/gdb/data-directory/Makefile.in,v retrieving revision 1.11 diff -u -p -r1.11 Makefile.in --- data-directory/Makefile.in 11 Apr 2012 05:50:44 -0000 1.11 +++ data-directory/Makefile.in 10 Aug 2012 03:59:28 -0000 @@ -59,7 +59,9 @@ PYTHON_FILES = \ gdb/command/__init__.py \ gdb/command/pretty_printers.py \ gdb/command/prompt.py \ - gdb/command/explore.py + gdb/command/explore.py \ + gdb/function/__init__.py \ + gdb/function/strfns.py FLAGS_TO_PASS = \ "prefix=$(prefix)" \ Index: doc/gdb.texinfo =================================================================== RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v retrieving revision 1.999 diff -u -p -r1.999 gdb.texinfo --- doc/gdb.texinfo 9 Aug 2012 12:53:44 -0000 1.999 +++ doc/gdb.texinfo 10 Aug 2012 03:59:30 -0000 @@ -7558,6 +7558,7 @@ being passed the type of @var{arg} as th * Pretty Printing:: Python pretty printing * Value History:: Value history * Convenience Vars:: Convenience variables +* Convenience Funs:: Convenience functions * Registers:: Registers * Floating Point Hardware:: Floating point hardware * Vector Unit:: Vector Unit @@ -9311,6 +9312,9 @@ On HP-UX systems, if you refer to a func begins with a dollar sign, @value{GDBN} searches for a user or system name first, before it searches for a convenience variable. +@node Convenience Funs +@section Convenience Functions + @cindex convenience functions @value{GDBN} also supplies some @dfn{convenience functions}. These have a syntax similar to convenience variables. A convenience @@ -9318,6 +9322,37 @@ function can be used in an expression ju however, a convenience function is implemented internally to @value{GDBN}. +These functions require GDB to be configured with @code{Python} support. + +@table @code + +@item $_memeq(@var{buf1}, @var{buf2}, @var{length}) +@findex $_memeq@r{, convenience function} +Returns one if the @var{length} bytes at the addresses given by +@var{buf1} and @var{buf2} are equal. +Otherwise it returns zero. + +@item $_regex(@var{str}, @var{regex}) +@findex $_regex@r{, convenience function} +Returns one if the string @var{str} matches the regular expression +@var{regex}. Otherwise it returns zero. +The syntax of the regular expression is that specified by @code{Python}'s +regular expression support. + +@item $_streq(@var{str1}, @var{str2}) +@findex $_streq@r{, convenience function} +Returns one if the strings @var{str1} and @var{str2} are equal. +Otherwise it returns zero. + +@item $_strlen(@var{str}) +@findex $_strlen@r{, convenience function} +Returns the length of string @var{str}. + +@end table + +@value{GDBN} provides the ability to list and get help on +convenience functions. + @table @code @item help function @kindex help function @@ -23361,6 +23396,19 @@ second argument is the upper bound of th must not be negative, but the bounds can be. @end defun +@defun Type.vector (@var{n1} @r{[}, @var{n2}@r{]}) +Return a new @code{gdb.Type} object which represents a vector of this +type. If one argument is given, it is the inclusive upper bound of +the vector; in this case the lower bound is zero. If two arguments are +given, the first argument is the lower bound of the vector, and the +second argument is the upper bound of the vector. A vector's length +must not be negative, but the bounds can be. + +The difference between an @code{array} and a @code{vector} is that +arrays behave like in C: when used in expressions they decay to a pointer +to the first element whereas vectors are treated as first class values. +@end defun + @defun Type.const () Return a new @code{gdb.Type} object which represents a @code{const}-qualified variant of this type. Index: python/py-type.c =================================================================== RCS file: /cvs/src/src/gdb/python/py-type.c,v retrieving revision 1.39 diff -u -p -r1.39 py-type.c --- python/py-type.c 18 May 2012 21:02:52 -0000 1.39 +++ python/py-type.c 10 Aug 2012 03:59:30 -0000 @@ -461,10 +461,10 @@ typy_get_composite (struct type *type) return type; } -/* Return an array type. */ +/* Helper for typy_array and typy_vector. */ static PyObject * -typy_array (PyObject *self, PyObject *args) +typy_array_1 (PyObject *self, PyObject *args, int is_vector) { long n1, n2; PyObject *n2_obj = NULL; @@ -503,12 +503,30 @@ typy_array (PyObject *self, PyObject *ar TRY_CATCH (except, RETURN_MASK_ALL) { array = lookup_array_range_type (type, n1, n2); + if (is_vector) + make_vector_type (array); } GDB_PY_HANDLE_EXCEPTION (except); return type_to_type_object (array); } +/* Return an array type. */ + +static PyObject * +typy_array (PyObject *self, PyObject *args) +{ + return typy_array_1 (self, args, 0); +} + +/* Return a vector type. */ + +static PyObject * +typy_vector (PyObject *self, PyObject *args) +{ + return typy_array_1 (self, args, 1); +} + /* Return a Type object which represents a pointer to SELF. */ static PyObject * typy_pointer (PyObject *self, PyObject *args) @@ -1559,6 +1577,14 @@ static PyMethodDef type_object_methods[] Return a type which represents an array of objects of this type.\n\ The bounds of the array are [LOW_BOUND, HIGH_BOUND] inclusive.\n\ If LOW_BOUND is omitted, a value of zero is used." }, + { "vector", typy_vector, METH_VARARGS, + "vector ([LOW_BOUND,] HIGH_BOUND) -> Type\n\ +Return a type which represents a vector of objects of this type.\n\ +The bounds of the array are [LOW_BOUND, HIGH_BOUND] inclusive.\n\ +If LOW_BOUND is omitted, a value of zero is used.\n\ +Vectors differ from arrays in that if the current language has C-style\n\ +arrays, vectors don't decay to a pointer to the first element.\n\ +They are first class values." }, { "__contains__", typy_has_key, METH_VARARGS, "T.__contains__(k) -> True if T has a field named k, else False" }, { "const", typy_const, METH_NOARGS, Index: python/lib/gdb/function/__init__.py =================================================================== RCS file: python/lib/gdb/function/__init__.py diff -N python/lib/gdb/function/__init__.py --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ python/lib/gdb/function/__init__.py 10 Aug 2012 03:59:30 -0000 @@ -0,0 +1,14 @@ +# Copyright (C) 2012 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 . Index: python/lib/gdb/function/strfns.py =================================================================== RCS file: python/lib/gdb/function/strfns.py diff -N python/lib/gdb/function/strfns.py --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ python/lib/gdb/function/strfns.py 10 Aug 2012 03:59:30 -0000 @@ -0,0 +1,108 @@ +# Useful gdb string convenience functions. +# Copyright (C) 2012 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 . + +"""$_memeq, $_strlen, $_streq, $_regex""" + +import gdb +import re + + +class _MemEq(gdb.Function): + """$_memeq - compare bytes of memory + +Usage: + $_memeq(a, b, len) + +Returns: + True if len bytes at a and b compare equally. +""" + def __init__(self): + super(_MemEq, self).__init__("_memeq") + + def invoke(self, a, b, length): + if length < 0: + raise ValueError("length must be non-negative") + if length == 0: + return True + # The argument(s) to vector are [low_bound,]high_bound. + byte_vector = gdb.lookup_type("char").vector(length - 1) + ptr_byte_vector = byte_vector.pointer() + a_ptr = a.reinterpret_cast(ptr_byte_vector) + b_ptr = b.reinterpret_cast(ptr_byte_vector) + return a_ptr.dereference() == b_ptr.dereference() + + +class _StrLen(gdb.Function): + """$_strlen - compute string length + +Usage: + $_strlen(a) + +Returns: + Length of string a, assumed to be a string in the current language. +""" + def __init__(self): + super(_StrLen, self).__init__("_strlen") + + def invoke(self, a): + s = a.string() + return len(s) + + +class _StrEq(gdb.Function): + """$_streq - check string equality + +Usage: + $_streq(a, b) + +Returns: + True if a and b are identical strings in the current language. + +Example (amd64-linux): + catch syscall open + cond $bpnum $_streq((char*) $rdi, "foo") +""" + def __init__(self): + super(_StrEq, self).__init__("_streq") + + def invoke(self, a, b): + return a.string() == b.string() + + +class _RegEx(gdb.Function): + """$_regex - check if a string matches a regular expression + +Usage: + $_regex(string, regex) + +Returns: + True if string str (in the current language) matches the + regular expression regex. +""" + def __init__(self): + super(_RegEx, self).__init__("_regex") + + def invoke(self, string, regex): + s = string.string() + r = re.compile(regex.string()) + return bool(r.match(s)) + + +# GDB will import us automagically via gdb/__init__.py. +_MemEq() +_StrLen() +_StrEq() +_RegEx() Index: testsuite/gdb.python/py-strfns.c =================================================================== RCS file: testsuite/gdb.python/py-strfns.c diff -N testsuite/gdb.python/py-strfns.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ testsuite/gdb.python/py-strfns.c 10 Aug 2012 03:59:30 -0000 @@ -0,0 +1,50 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2012 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 . */ + +const char str1[] = "Hello."; +const char str2[] = "Hello."; +const char str3[] = "Goodbye."; + +const char buf1[] = { 0, 1, 2, 3 }; +const char buf2[] = { 0, 1, 2, 3 }; +const char buf3[] = { 0, 1, 2, 4 }; + +static void +func (const char *arg) +{ + return; /* Break func here. */ +} + +static void +bfunc (const char *arg) +{ + return; /* Break bfunc here. */ +} + +int +main () +{ + func (str1); + func (str2); + func (str3); + + bfunc (buf1); + bfunc (buf2); + bfunc (buf3); + + return 0; +} Index: testsuite/gdb.python/py-strfns.exp =================================================================== RCS file: testsuite/gdb.python/py-strfns.exp diff -N testsuite/gdb.python/py-strfns.exp --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ testsuite/gdb.python/py-strfns.exp 10 Aug 2012 03:59:30 -0000 @@ -0,0 +1,103 @@ +# Copyright (C) 2012 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 convenience +# functions in strfns.py. + +load_lib gdb-python.exp + +standard_testfile + +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } { + return -1 +} + +if ![runto_main] { + return 0 +} + +# Skip all tests if Python scripting is not enabled. +if { [skip_python_tests] } { continue } + +proc test_all_strfns { } { + gdb_test "p \$_streq (str1, str2)" " = 1" + gdb_test "p \$_streq (str1, str3)" " = 0" + + gdb_test "p \$_strlen (str1)" " = 6" + gdb_test "p \$_strlen (buf1)" " = 0" + + gdb_test "p \$_memeq (buf1, buf2, 4)" " = 1" + gdb_test "p \$_memeq (buf1, buf3, 4)" " = 0" + + gdb_test {p $_regex (str1, "Hello")} " = 1" + gdb_test {p $_regex (str1, "Help")} " = 0" + gdb_test {p $_regex (str1, "^Hello")} " = 1" + gdb_test {p $_regex (str1, "^Hello.$")} " = 1" +} + +test_all_strfns + +# Verify use in a conditional breakpoint. + +gdb_breakpoint [gdb_get_line_number "Break func here."] +gdb_test_no_output "condition \$bpnum \$_streq (arg, \"Goodbye.\")" +gdb_continue_to_breakpoint "Break func here." +gdb_test "p arg" "= $hex \"Goodbye.\"" + +gdb_breakpoint [gdb_get_line_number "Break bfunc here."] +gdb_test_no_output "condition \$bpnum \$_memeq (arg, buf3, 4)" +gdb_continue_to_breakpoint "Break bfunc here." +gdb_test "p /d {char\[4\]} arg" "= \\{0, 1, 2, 4\\}" + +# Verify use on a core file. + +proc test_strfns_core_file { } { + global objdir subdir gdb_prompt testfile + + set filename "${objdir}/${subdir}/py-strfns.core" + set escapedfilename [string_to_regexp $filename] + + gdb_test_multiple "gcore $filename" \ + "save a corefile" \ + { + -re "Saved corefile ${escapedfilename}\[\r\n\]+$gdb_prompt $" { + pass "save a corefile" + } + -re "Can't create a corefile\[\r\n\]+$gdb_prompt $" { + unsupported "save a corefile" + # No use proceeding from here. + return + } + } + + clean_restart $testfile + + gdb_test_multiple "core $filename" \ + "re-load generated corefile" \ + { + -re "Core was generated by .*$gdb_prompt $" { + pass "re-load generated corefile" + } + -re ".*$gdb_prompt $" { + fail "re-load generated corefile" + # No use proceeding from here. + return + } + } + + test_all_strfns +} + +test_strfns_core_file Index: testsuite/gdb.python/py-type.exp =================================================================== RCS file: /cvs/src/src/gdb/testsuite/gdb.python/py-type.exp,v retrieving revision 1.24 diff -u -p -r1.24 py-type.exp --- testsuite/gdb.python/py-type.exp 22 Jun 2012 17:59:33 -0000 1.24 +++ testsuite/gdb.python/py-type.exp 10 Aug 2012 03:59:30 -0000 @@ -114,12 +114,27 @@ proc test_fields {lang} { gdb_test "python print len(fields)" "1" "Check the number of fields" gdb_test "python print fields\[0\].type" "" "Check array field type" + # Test gdb.Type.array. gdb_test "python print ar\[0\].cast(ar\[0\].type.array(1))" \ ".1, 2." "cast to array with one argument" gdb_test "python print ar\[0\].cast(ar\[0\].type.array(0, 1))" \ ".1, 2." "cast to array with two arguments" gdb_test "python print ar\[0\].type == ar\[0\].type" "True" + + # Test gdb.Type.vector. + # Note: vectors cast differently than arrays. Here ar[0] is replicated + # for the size of the vector. + gdb_py_test_silent_cmd \ + "python vec1 = ar\[0\].cast(ar\[0\].type.vector(1))" "set vec1" 1 + gdb_test "python print vec1" ".1, 1." "cast to vector with one argument" + gdb_py_test_silent_cmd \ + "python vec2 = ar\[0\].cast(ar\[0\].type.vector(0, 1))" "set vec2" 1 + gdb_test "python print vec2" ".1, 1." "cast to vector with two arguments" + gdb_test "python print vec1 == vec2" "True" + gdb_py_test_silent_cmd \ + "python vec3 = ar\[1\].cast(ar\[1\].type.vector(1))" "set vec3" 1 + gdb_test "python print vec1 == vec3" "False" } proc test_enums {} {