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.
This commit is contained in:
Doug Evans 2012-08-10 20:26:00 +00:00
parent 200bc880f4
commit a72c32530e
12 changed files with 405 additions and 3 deletions

View File

@ -1,3 +1,16 @@
2012-08-10 Doug Evans <dje@google.com>
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.
2012-08-10 Siddhesh Poyarekar <siddhesh@redhat.com>
* python/py-type.c (convert_field): Use gdb_py_long_from_longest

View File

@ -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.

View File

@ -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)" \

View File

@ -1,3 +1,8 @@
2012-08-10 Doug Evans <dje@google.com>
* gdb.texinfo (Convenience Funs): New node.
(Types In Python): Document Type.vector.
2012-08-09 Yao Qi <yao@codesourcery.com>
* observer.texi: New observer command_param_changed.

View File

@ -7558,6 +7558,7 @@ being passed the type of @var{arg} as the argument.
* 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 function or variable name that
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,38 @@ function can be used in an expression just like an ordinary function;
however, a convenience function is implemented internally to
@value{GDBN}.
These functions require @value{GDBN} 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 +23397,19 @@ second argument is the upper bound of the array. An array's length
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.

View File

@ -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 <http://www.gnu.org/licenses/>.

View File

@ -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 <http://www.gnu.org/licenses/>.
"""$_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()

View File

@ -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 *args)
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,

View File

@ -1,3 +1,9 @@
2012-08-10 Doug Evans <dje@google.com>
* gdb.python/py-strfns.c: New file.
* gdb.python/py-strfns.exp: New file.
* gdb.python/py-type.exp (test_fields): Add vector tests.
2012-08-10 Mike Frysinger <vapier@gentoo.org>
PR cli/10436:

View File

@ -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 <http://www.gnu.org/licenses/>. */
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;
}

View File

@ -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 <http://www.gnu.org/licenses/>.
# 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 <str3> \"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

View File

@ -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" "<range 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 {} {