range stepping: tests

This adds tests to verify range stepping is used as expected, by
inspecting the RSP traffic, looking for vCont;s and vCont;r packets.

gdb/testsuite/
2013-05-23  Yao Qi  <yao@codesourcery.com>
	    Pedro Alves  <palves@redhat.com>

	* gdb.base/range-stepping.c: New file.
	* gdb.base/range-stepping.exp: New file.
	* gdb.trace/range-stepping.c: New file.
	* gdb.trace/range-stepping.exp: New file.
	* lib/range-stepping-support.exp: New file.
This commit is contained in:
Pedro Alves 2013-05-23 17:19:05 +00:00
parent c2d6af84da
commit bc5065a70f
6 changed files with 541 additions and 0 deletions

View File

@ -1,3 +1,12 @@
2013-05-23 Yao Qi <yao@codesourcery.com>
Pedro Alves <palves@redhat.com>
* gdb.base/range-stepping.c: New file.
* gdb.base/range-stepping.exp: New file.
* gdb.trace/range-stepping.c: New file.
* gdb.trace/range-stepping.exp: New file.
* lib/range-stepping-support.exp: New file.
2013-05-22 Tom Tromey <tromey@redhat.com>
* gdb.cp/class2.cc (main): New local 'aref'.

View File

@ -0,0 +1,104 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright 2013 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/>. */
/* Note: 'volatile' is used to make sure the compiler doesn't fold /
optimize out the arithmetic that uses the variables. */
static int
func1 (int a, int b)
{
volatile int r = a * b;
r += (a | b);
r += (a - b);
return r;
}
int
main(void)
{
volatile int a = 0;
volatile int b = 1;
volatile int c = 2;
volatile int d = 3;
volatile int e = 4;
volatile double d1 = 1.0;
volatile double d2 = 2.0;
/* A macro that expands to a single source line that compiles to a
number of instructions, with no branches. */
#define LINE_WITH_MULTIPLE_INSTRUCTIONS \
do \
{ \
a = b + c + d * e - a; \
} while (0)
LINE_WITH_MULTIPLE_INSTRUCTIONS; /* location 1 */
/* A line of source code that compiles to a function call (jump or
branch), surrounded by instructions before and after. IOW, this
will generate approximately the following pseudo-instructions:
addr1:
insn1;
insn2;
...
call func1;
...
insn3;
addr2:
insn4;
*/
e = 10 + func1 (a + b, c * d); /* location 2 */
e = 10 + func1 (a + b, c * d);
/* Generate a single source line that includes a short loop. */
#define LINE_WITH_LOOP \
do \
{ \
for (a = 0, e = 0; a < 15; a++) \
e += a; \
} while (0)
LINE_WITH_LOOP;
LINE_WITH_LOOP;
/* Generate a single source line that includes a time-consuming
loop. GDB breaks the loop early by clearing variable 'c'. */
#define LINE_WITH_TIME_CONSUMING_LOOP \
do \
{ \
for (c = 1, a = 0; a < 65535 && c; a++) \
for (b = 0; b < 65535 && c; b++) \
{ \
d1 = d2 * a / b; \
d2 = d1 * a; \
} \
} while (0)
LINE_WITH_TIME_CONSUMING_LOOP;
/* Some multi-instruction lines for software watchpoint tests. */
LINE_WITH_MULTIPLE_INSTRUCTIONS;
LINE_WITH_MULTIPLE_INSTRUCTIONS; /* soft-watch */
LINE_WITH_MULTIPLE_INSTRUCTIONS;
return 0;
}

View File

@ -0,0 +1,237 @@
# Copyright 2013 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/>.
load_lib "range-stepping-support.exp"
standard_testfile
set executable $testfile
if { [prepare_for_testing $testfile.exp $testfile $srcfile {debug}] } {
return -1
}
if ![runto_main] {
fail "Can't run to main"
return -1
}
# Check whether range stepping is supported by the target.
proc gdb_range_stepping_enabled { } {
global gdb_prompt
set command "set range-stepping on"
set message "probe range-stepping support"
gdb_test_multiple $command $message {
-re "Range stepping is not supported.*\r\n$gdb_prompt $" {
pass $message
return 0
}
-re "^$command\r\n$gdb_prompt $" {
pass $message
return 1
}
}
return 0
}
if ![gdb_range_stepping_enabled] {
unsupported "range stepping not supported by the target"
return -1
}
# Check that range stepping can step a range of multiple instructions.
with_test_prefix "multi insns" {
gdb_breakpoint [gdb_get_line_number "location 1"]
gdb_continue_to_breakpoint "location 1"
set pc_before_stepping ""
set test "pc before stepping"
gdb_test_multiple "print/x \$pc" $test {
-re "\\\$$decimal = (\[^\r\n\]*)\r\n$gdb_prompt $" {
set pc_before_stepping $expect_out(1,string)
pass $test
}
}
# When "next" is executed, GDB should send one vCont;s and vCont;r
# and receive two stop replies:
#
# --> vCont;s (step over breakpoint)
# <-- T05
# --> vCont;rSTART,END (range step)
# <-- T05
exec_cmd_expect_vCont_count "next" 1 1
set pc_after_stepping ""
set msg "pc after stepping"
gdb_test_multiple "print/x \$pc" $msg {
-re "\\\$$decimal = (\[^\r\n\]*)\r\n$gdb_prompt $" {
set pc_after_stepping $expect_out(1,string)
pass $msg
}
}
# There should be at least two instructions between
# PC_BEFORE_STEPPING and PC_AFTER_STEPPING.
gdb_test "disassemble ${pc_before_stepping},${pc_after_stepping}" \
"${hex} <main\\+${decimal}>:.*${hex} <main\\+${decimal}>:.*" \
"stepped multiple insns"
}
# Check that range stepping can step over a function.
with_test_prefix "step over func" {
set line_num [gdb_get_line_number "location 2"]
gdb_test "where" "main \\(\\) at .*${srcfile}:${line_num}.*"
# It's expected to get three stops and two 'vCont;r's. In the C
# code, the line of C source produces roughly the following
# instructions:
#
# addr1:
# insn1
# insn2
# ...
# call func1
# addr2:
# ...
# insn3
# addr3:
# insn4
#
# Something like this will happen:
# --> vCont;rADDR1,ADDR3 (range step from ADDR1 to ADDR3)
# <-- T05 (target single-stepped to func, which is out of the step range)
# --> $Z0,ADDR2 (place step-resume breakpoint at ADDR2)
# --> vCont;c (resume)
# <-- T05 (target stops at ADDR2)
# --> vCont;rADDR1,ADDR3 (continues range stepping)
# <-- T05
exec_cmd_expect_vCont_count "next" 0 2
}
# Check that breakpoints interrupt range stepping correctly.
with_test_prefix "breakpoint" {
gdb_breakpoint "func1"
# Something like this will happen:
# --> vCont;rADDR1,ADDR3
# <-- T05 (target single-steps to func1, which is out of the step range)
# --> $Z0,ADDR2 (step-resume breakpoint at ADDR2)
# --> vCont;c (resume)
# <-- T05 (target hits the breakpoint at func1)
exec_cmd_expect_vCont_count "next" 0 1
gdb_test "backtrace" "#0 .* func1 .*#1 .* main .*" \
"backtrace from func1"
# A cancelled range step should not confuse the following
# execution commands.
exec_cmd_expect_vCont_count "stepi" 1 0
gdb_test "finish" ".*"
gdb_test "next" ".*"
delete_breakpoints
}
# Check that range stepping works well even when there's a loop in the
# step range.
with_test_prefix "loop" {
# GDB should send one vCont;r and receive one stop reply:
# --> vCont;rSTART,END (range step)
# <-- T05
exec_cmd_expect_vCont_count "next" 0 1
# Confirm the loop completed.
gdb_test "print a" " = 15"
gdb_test "print e" " = 105"
}
# Check that range stepping works well even when the target's PC was
# already within the loop's body.
with_test_prefix "loop 2" {
# Stepi into the loop body. 15 should be large enough to make
# sure the program stops within the loop's body.
gdb_test "stepi 15" ".*"
# GDB should send one vCont;r and receive one stop reply:
# --> vCont;rSTART,END (range step)
# <-- T05
exec_cmd_expect_vCont_count "next" 0 1
# Confirm the loop completed.
gdb_test "print a" " = 15"
gdb_test "print e" " = 105"
}
# Check that range stepping works well even when it is interrupted by
# ctrl-c.
with_test_prefix "interrupt" {
gdb_test_no_output "set debug remote 1"
send_gdb "next\n"
sleep 1
send_gdb "\003"
# GDB should send one vCont;r and receive one stop reply for
# SIGINT:
# --> vCont;rSTART,END (range step)
# <-- T02 (SIGINT)
set vcont_r_counter 0
set test "send ctrl-c to GDB"
gdb_test_multiple "" $test {
-re "vCont;r\[^\r\n\]*\.\.\." {
incr vcont_r_counter
exp_continue
}
-re "Program received signal SIGINT.*$gdb_prompt $" {
pass $test
}
}
gdb_test_no_output "set debug remote 0"
# Check the number of 'vCont;r' packets.
if { $vcont_r_counter == 1 } {
pass "${test}: 1 vCont;r"
} else {
fail "${test}: 1 vCont;r"
}
# Break the loop earlier and continue range stepping.
gdb_test "set variable c = 0"
exec_cmd_expect_vCont_count "next" 0 1
}
# Check that range stepping doesn't break software watchpoints. With
# those, GDB needs to be notified of all single-steps, to evaluate
# whether the watched value changes at each step.
with_test_prefix "software watchpoint" {
gdb_test "step" "soft-watch.*" "step into multiple instruction line"
# A software watchpoint at PC makes the thread stop before the
# whole line range is over (after one single-step, actually).
gdb_test "watch \$pc" ".*" "set watchpoint"
gdb_test "step" "soft-watch.*" "step still in same line"
}
return 0

View File

@ -0,0 +1,56 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright 2013 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/>. */
#ifdef SYMBOL_PREFIX
#define SYMBOL(str) SYMBOL_PREFIX #str
#else
#define SYMBOL(str) #str
#endif
/* `set_point' further below is the label where we'll set tracepoints
at. The insn at the label must the large enough to fit a fast
tracepoint jump. */
#if (defined __x86_64__ || defined __i386__)
# define NOP " .byte 0xe9,0x00,0x00,0x00,0x00\n" /* jmp $+5 (5-byte nop) */
#else
# define NOP "" /* port me */
#endif
int
main(void)
{
/* Note: 'volatile' is used to make sure the compiler doesn't
optimize out these variables. We want to be sure instructions
are generated for accesses. */
volatile int i = 0;
/* Generate a single line with a label in the middle where we can
place either a trap tracepoint or a fast tracepoint. */
#define LINE_WITH_FAST_TRACEPOINT \
do { \
i = 1; \
asm (" .global " SYMBOL (set_point) "\n" \
SYMBOL (set_point) ":\n" \
NOP \
); \
i = 2; \
} while (0)
LINE_WITH_FAST_TRACEPOINT; /* location 1 */
return 0;
}

View File

@ -0,0 +1,85 @@
# Copyright 2013 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/>.
load_lib "trace-support.exp"
load_lib "range-stepping-support.exp"
standard_testfile
set executable $testfile
if [prepare_for_testing $testfile.exp $executable $srcfile \
{debug nowarnings}] {
return -1
}
if ![runto_main] {
fail "Can't run to main to check for trace support"
return -1
}
if ![gdb_target_supports_trace] {
unsupported "target does not support trace"
return -1;
}
# Check that range stepping works well with tracepoints.
proc range_stepping_with_tracepoint { type } {
with_test_prefix "${type}" {
gdb_breakpoint [gdb_get_line_number "location 1"]
gdb_continue_to_breakpoint "location 1"
delete_breakpoints
gdb_test "${type} *set_point" ".*"
gdb_test_no_output "tstart"
# Step a line with a tracepoint in the middle. The tracepoint
# itself shouldn't have any effect on range stepping. We
# should see one vCont;r and no vCont;s's.
exec_cmd_expect_vCont_count "step" 0 1
gdb_test_no_output "tstop"
gdb_test "tfind" "Found trace frame .*" "first tfind"
gdb_test "tfind" \
"Target failed to find requested trace frame.*" \
"second tfind"
delete_breakpoints
}
}
range_stepping_with_tracepoint "trace"
set libipa [get_in_proc_agent]
gdb_load_shlibs $libipa
if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
executable [list debug nowarnings shlib=$libipa] ] != "" } {
untested "failed to compile ftrace tests"
return -1
}
clean_restart ${executable}
if ![runto_main] {
fail "Can't run to main for ftrace tests"
return 0
}
gdb_reinitialize_dir $srcdir/$subdir
if { [gdb_test "info sharedlibrary" ".*${libipa}.*" "IPA loaded"] != 0 } {
untested "Could not find IPA lib loaded"
} else {
range_stepping_with_tracepoint "ftrace"
}

View File

@ -0,0 +1,50 @@
# Copyright 2013 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/>.
# Execute command CMD and check that GDB sends the expected number of
# vCont;s and vCont;r packets.
proc exec_cmd_expect_vCont_count { cmd exp_vCont_s exp_vCont_r } {
global gdb_prompt
gdb_test_no_output "set debug remote 1" ""
set test "${cmd}: vCont;s=${exp_vCont_s} vCont;r=${exp_vCont_r}"
set r_counter 0
set s_counter 0
gdb_test_multiple $cmd $test {
-re "vCont;s\[^\r\n\]*Packet received: T\[\[:xdigit:\]\]\[\[:xdigit:\]\]" {
incr s_counter
exp_continue
}
-re "vCont;r\[^\r\n\]*Packet received: T\[\[:xdigit:\]\]\[\[:xdigit:\]\]" {
incr r_counter
exp_continue
}
-re "\r\n" {
# Prevent overflowing the expect buffer.
exp_continue
}
-re "$gdb_prompt $" {
if { $r_counter == ${exp_vCont_r} && $s_counter == ${exp_vCont_s} } {
pass $test
} else {
fail $test
}
}
}
gdb_test_no_output "set debug remote 0" ""
}