PR 15276: Add $_caller_is, $_caller_matches, $_any_caller_is, $_any_caller_matches
gdb/ChangeLog: PR 15276 * NEWS: Mention $_caller_is, $_caller_matches, $_any_caller_is, $_any_caller_matches. * data-directory/Makefile.in (PYTHON_FILE_LIST): Add caller_is.py. * python/lib/gdb/function/caller_is.py: New file. gdb/testsuite/ChangeLog: PR 15276 * gdb.python/py-caller-is.c: New file. * gdb.python/py-caller-is.exp: New file. gdb/doc/ChangeLog: PR 15276 * gdb.texinfo (Convenience Funs): Document $_caller_is, $_caller_matches, $_any_caller_is, $_any_caller_matches.
This commit is contained in:
parent
0d41ba00c6
commit
faa42425cb
@ -1,3 +1,11 @@
|
||||
2014-09-06 Doug Evans <xdje42@gmail.com>
|
||||
|
||||
PR 15276
|
||||
* NEWS: Mention $_caller_is, $_caller_matches, $_any_caller_is,
|
||||
$_any_caller_matches.
|
||||
* data-directory/Makefile.in (PYTHON_FILE_LIST): Add caller_is.py.
|
||||
* python/lib/gdb/function/caller_is.py: New file.
|
||||
|
||||
2014-09-06 Doug Evans <xdje42@gmail.com>
|
||||
|
||||
* infcmd.c (program_info): Fix typo.
|
||||
|
7
gdb/NEWS
7
gdb/NEWS
@ -6,6 +6,13 @@
|
||||
* Python Scripting
|
||||
You can now access frame registers from Python scripts.
|
||||
|
||||
* New Python-based convenience functions:
|
||||
|
||||
** $_caller_is(name [, number_of_frames])
|
||||
** $_caller_matches(regexp [, number_of_frames])
|
||||
** $_any_caller_is(name [, number_of_frames])
|
||||
** $_any_caller_matches(regexp [, number_of_frames])
|
||||
|
||||
* On resume, GDB now always passes the signal the program had stopped
|
||||
for to the thread the signal was sent to, even if the user changed
|
||||
threads before resuming. Previously GDB would often (but not
|
||||
|
@ -73,6 +73,7 @@ PYTHON_FILE_LIST = \
|
||||
gdb/command/prompt.py \
|
||||
gdb/command/explore.py \
|
||||
gdb/function/__init__.py \
|
||||
gdb/function/caller_is.py \
|
||||
gdb/function/strfns.py
|
||||
|
||||
@HAVE_PYTHON_TRUE@PYTHON_FILES = $(PYTHON_FILE_LIST)
|
||||
|
@ -1,3 +1,9 @@
|
||||
2014-09-06 Doug Evans <xdje42@gmail.com>
|
||||
|
||||
PR 15276
|
||||
* gdb.texinfo (Convenience Funs): Document $_caller_is,
|
||||
$_caller_matches, $_any_caller_is, $_any_caller_matches.
|
||||
|
||||
2014-09-03 Justin Lebar <jlebar@google.com>
|
||||
|
||||
* python.texi (Types In Python): Type.template_argument(n) returns a
|
||||
|
@ -10098,6 +10098,70 @@ Otherwise it returns zero.
|
||||
@findex $_strlen@r{, convenience function}
|
||||
Returns the length of string @var{str}.
|
||||
|
||||
@item $_caller_is(@var{name}@r{[}, @var{number_of_frames}@r{]})
|
||||
@findex $_caller_is@r{, convenience function}
|
||||
Returns one if the calling function's name is equal to @var{name}.
|
||||
Otherwise it returns zero.
|
||||
|
||||
If the optional argument @var{number_of_frames} is provided,
|
||||
it is the number of frames up in the stack to look.
|
||||
The default is 1.
|
||||
|
||||
Example:
|
||||
|
||||
@smallexample
|
||||
(gdb) backtrace
|
||||
#0 bottom_func ()
|
||||
at testsuite/gdb.python/py-caller-is.c:21
|
||||
#1 0x00000000004005a0 in middle_func ()
|
||||
at testsuite/gdb.python/py-caller-is.c:27
|
||||
#2 0x00000000004005ab in top_func ()
|
||||
at testsuite/gdb.python/py-caller-is.c:33
|
||||
#3 0x00000000004005b6 in main ()
|
||||
at testsuite/gdb.python/py-caller-is.c:39
|
||||
(gdb) print $_caller_is ("middle_func")
|
||||
$1 = 1
|
||||
(gdb) print $_caller_is ("top_func", 2)
|
||||
$1 = 1
|
||||
@end smallexample
|
||||
|
||||
@item $_caller_matches(@var{regexp}@r{[}, @var{number_of_frames}@r{]})
|
||||
@findex $_caller_matches@r{, convenience function}
|
||||
Returns one if the calling function's name matches the regular expression
|
||||
@var{regexp}. Otherwise it returns zero.
|
||||
|
||||
If the optional argument @var{number_of_frames} is provided,
|
||||
it is the number of frames up in the stack to look.
|
||||
The default is 1.
|
||||
|
||||
@item $_any_caller_is(@var{name}@r{[}, @var{number_of_frames}@r{]})
|
||||
@findex $_any_caller_is@r{, convenience function}
|
||||
Returns one if any calling function's name is equal to @var{name}.
|
||||
Otherwise it returns zero.
|
||||
|
||||
If the optional argument @var{number_of_frames} is provided,
|
||||
it is the number of frames up in the stack to look.
|
||||
The default is 1.
|
||||
|
||||
This function differs from @code{$_caller_is} in that this function
|
||||
checks all stack frames from the immediate caller to the frame specified
|
||||
by @var{number_of_frames}, whereas @code{$_caller_is} only checks the
|
||||
frame specified by @var{number_of_frames}.
|
||||
|
||||
@item $_any_caller_matches(@var{regexp}@r{[}, @var{number_of_frames}@r{]})
|
||||
@findex $_any_caller_matches@r{, convenience function}
|
||||
Returns one if any calling function's name matches the regular expression
|
||||
@var{regexp}. Otherwise it returns zero.
|
||||
|
||||
If the optional argument @var{number_of_frames} is provided,
|
||||
it is the number of frames up in the stack to look.
|
||||
The default is 1.
|
||||
|
||||
This function differs from @code{$_caller_matches} in that this function
|
||||
checks all stack frames from the immediate caller to the frame specified
|
||||
by @var{number_of_frames}, whereas @code{$_caller_matches} only checks the
|
||||
frame specified by @var{number_of_frames}.
|
||||
|
||||
@end table
|
||||
|
||||
@value{GDBN} provides the ability to list and get help on
|
||||
|
160
gdb/python/lib/gdb/function/caller_is.py
Normal file
160
gdb/python/lib/gdb/function/caller_is.py
Normal file
@ -0,0 +1,160 @@
|
||||
# Caller-is functions.
|
||||
# Copyright (C) 2008, 2014 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
|
||||
import re
|
||||
|
||||
class CallerIs(gdb.Function):
|
||||
"""Check the calling function's name.
|
||||
|
||||
Usage:
|
||||
$_caller_is(name [, number_of_frames])
|
||||
|
||||
Arguments:
|
||||
|
||||
name: The name of the function to search for.
|
||||
|
||||
number_of_frames: How many stack frames to traverse back from the currently
|
||||
selected frame to compare with. If the value is greater than the depth of
|
||||
the stack from that point then the result is False.
|
||||
The default is 1.
|
||||
|
||||
Returns:
|
||||
True if the function's name at the specified frame is equal to name.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super(CallerIs, self).__init__("_caller_is")
|
||||
|
||||
def invoke(self, name, nframes = 1):
|
||||
if nframes < 0:
|
||||
raise ValueError("nframes must be >= 0")
|
||||
frame = gdb.selected_frame()
|
||||
while nframes > 0:
|
||||
frame = frame.older()
|
||||
if frame is None:
|
||||
return False
|
||||
nframes = nframes - 1
|
||||
return frame.name() == name.string()
|
||||
|
||||
class CallerMatches(gdb.Function):
|
||||
"""Compare the calling function's name with a regexp.
|
||||
|
||||
Usage:
|
||||
$_caller_matches(regex [, number_of_frames])
|
||||
|
||||
Arguments:
|
||||
|
||||
regex: The regular expression to compare the function's name with.
|
||||
|
||||
number_of_frames: How many stack frames to traverse back from the currently
|
||||
selected frame to compare with. If the value is greater than the depth of
|
||||
the stack from that point then the result is False.
|
||||
The default is 1.
|
||||
|
||||
Returns:
|
||||
True if the function's name at the specified frame matches regex.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super(CallerMatches, self).__init__("_caller_matches")
|
||||
|
||||
def invoke(self, name, nframes = 1):
|
||||
if nframes < 0:
|
||||
raise ValueError("nframes must be >= 0")
|
||||
frame = gdb.selected_frame()
|
||||
while nframes > 0:
|
||||
frame = frame.older()
|
||||
if frame is None:
|
||||
return False
|
||||
nframes = nframes - 1
|
||||
return re.match(name.string(), frame.name()) is not None
|
||||
|
||||
class AnyCallerIs(gdb.Function):
|
||||
"""Check all calling function's names.
|
||||
|
||||
Usage:
|
||||
$_any_caller_is(name [, number_of_frames])
|
||||
|
||||
Arguments:
|
||||
|
||||
name: The name of the function to search for.
|
||||
|
||||
number_of_frames: How many stack frames to traverse back from the currently
|
||||
selected frame to compare with. If the value is greater than the depth of
|
||||
the stack from that point then the result is False.
|
||||
The default is 1.
|
||||
|
||||
Returns:
|
||||
True if any function's name is equal to name.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super(AnyCallerIs, self).__init__("_any_caller_is")
|
||||
|
||||
def invoke(self, name, nframes = 1):
|
||||
if nframes < 0:
|
||||
raise ValueError("nframes must be >= 0")
|
||||
frame = gdb.selected_frame()
|
||||
while nframes >= 0:
|
||||
if frame.name() == name.string():
|
||||
return True
|
||||
frame = frame.older()
|
||||
if frame is None:
|
||||
return False
|
||||
nframes = nframes - 1
|
||||
return False
|
||||
|
||||
class AnyCallerMatches(gdb.Function):
|
||||
"""Compare all calling function's names with a regexp.
|
||||
|
||||
Usage:
|
||||
$_any_caller_matches(regex [, number_of_frames])
|
||||
|
||||
Arguments:
|
||||
|
||||
regex: The regular expression to compare the function's name with.
|
||||
|
||||
number_of_frames: How many stack frames to traverse back from the currently
|
||||
selected frame to compare with. If the value is greater than the depth of
|
||||
the stack from that point then the result is False.
|
||||
The default is 1.
|
||||
|
||||
Returns:
|
||||
True if any function's name matches regex.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super(AnyCallerMatches, self).__init__("_any_caller_matches")
|
||||
|
||||
def invoke(self, name, nframes = 1):
|
||||
if nframes < 0:
|
||||
raise ValueError("nframes must be >= 0")
|
||||
frame = gdb.selected_frame()
|
||||
name_re = re.compile(name.string())
|
||||
while nframes >= 0:
|
||||
if name_re.match(frame.name()) is not None:
|
||||
return True
|
||||
frame = frame.older()
|
||||
if frame is None:
|
||||
return False
|
||||
nframes = nframes - 1
|
||||
return False
|
||||
|
||||
CallerIs()
|
||||
CallerMatches()
|
||||
AnyCallerIs()
|
||||
AnyCallerMatches()
|
@ -1,3 +1,9 @@
|
||||
2014-09-06 Doug Evans <xdje42@gmail.com>
|
||||
|
||||
PR 15276
|
||||
* gdb.python/py-caller-is.c: New file.
|
||||
* gdb.python/py-caller-is.exp: New file.
|
||||
|
||||
2014-09-05 Sergio Durigan Junior <sergiodj@redhat.com>
|
||||
|
||||
PR gdb/17235
|
||||
|
41
gdb/testsuite/gdb.python/py-caller-is.c
Normal file
41
gdb/testsuite/gdb.python/py-caller-is.c
Normal file
@ -0,0 +1,41 @@
|
||||
/* This testcase is part of GDB, the GNU debugger.
|
||||
|
||||
Copyright 2012-2014 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/>. */
|
||||
|
||||
static void
|
||||
bottom_func (void)
|
||||
{
|
||||
return; /* Break bottom_func here. */
|
||||
}
|
||||
|
||||
static void
|
||||
middle_func (void)
|
||||
{
|
||||
bottom_func ();
|
||||
}
|
||||
|
||||
static void
|
||||
top_func (void)
|
||||
{
|
||||
middle_func ();
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
top_func ();
|
||||
return 0;
|
||||
}
|
73
gdb/testsuite/gdb.python/py-caller-is.exp
Normal file
73
gdb/testsuite/gdb.python/py-caller-is.exp
Normal file
@ -0,0 +1,73 @@
|
||||
# Copyright (C) 2012-2014 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 caller_is.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 }
|
||||
|
||||
gdb_breakpoint "bottom_func"
|
||||
gdb_continue_to_breakpoint "bottom_func"
|
||||
|
||||
proc test_all_caller_is_fns { } {
|
||||
gdb_test "p \$_caller_is (\"bottom_func\", 0)" " = 1"
|
||||
gdb_test "p \$_caller_is (\"middle_func\")" " = 1"
|
||||
gdb_test "p \$_caller_is (\"top_func\")" " = 0"
|
||||
gdb_test "p \$_caller_is (\"middle_func\", 2)" " = 0"
|
||||
gdb_test "p \$_caller_is (\"top_func\", 2)" " = 1"
|
||||
gdb_test "p \$_caller_is (\"foo\", 100)" " = 0"
|
||||
gdb_test "p \$_caller_is (\"foo\", -1)" "nframes must be >= 0"
|
||||
|
||||
gdb_test "p \$_caller_matches (\"^bottom\", 0)" " = 1"
|
||||
gdb_test "p \$_caller_matches (\"^middle_\")" " = 1"
|
||||
gdb_test "p \$_caller_matches (\"^top_\")" " = 0"
|
||||
gdb_test "p \$_caller_matches (\"^middle_\", 2)" " = 0"
|
||||
gdb_test "p \$_caller_matches (\"^top_f\", 2)" " = 1"
|
||||
gdb_test "p \$_caller_matches (\"foo\", 100)" " = 0"
|
||||
gdb_test "p \$_caller_matches (\"foo\", -1)" "nframes must be >= 0"
|
||||
|
||||
gdb_test "p \$_any_caller_is (\"bottom_func\", 0)" " = 1"
|
||||
gdb_test "p \$_any_caller_is (\"middle_func\")" " = 1"
|
||||
gdb_test "p \$_any_caller_is (\"top_func\")" " = 0"
|
||||
gdb_test "p \$_any_caller_is (\"middle_func\", 2)" " = 1"
|
||||
gdb_test "p \$_any_caller_is (\"top_func\", 2)" " = 1"
|
||||
gdb_test "p \$_any_caller_is (\"main\", 100)" " = 1"
|
||||
gdb_test "p \$_any_caller_is (\"foo\", 100)" " = 0"
|
||||
gdb_test "p \$_any_caller_is (\"foo\", -1)" "nframes must be >= 0"
|
||||
|
||||
gdb_test "p \$_any_caller_matches (\"^bottom\", 0)" " = 1"
|
||||
gdb_test "p \$_any_caller_matches (\"^middle_\")" " = 1"
|
||||
gdb_test "p \$_any_caller_matches (\"^top_\")" " = 0"
|
||||
gdb_test "p \$_any_caller_matches (\"^middle_\", 2)" " = 1"
|
||||
gdb_test "p \$_any_caller_matches (\"^top_f\", 2)" " = 1"
|
||||
gdb_test "p \$_any_caller_matches (\"^main\", 100)" " = 1"
|
||||
gdb_test "p \$_any_caller_matches (\"foo\", 100)" " = 0"
|
||||
gdb_test "p \$_any_caller_matches (\"foo\", -1)" "nframes must be >= 0"
|
||||
}
|
||||
|
||||
test_all_caller_is_fns
|
Loading…
Reference in New Issue
Block a user