1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
|
# Copyright 2014-2015 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/>. */
# Test that the Zx breakpoint/watchpoint packets are idempotent.
# GDBserver used to not treat Zx breakpoints other than Z0 as
# idempotent, although it must, to avoid problems with
# retransmissions. Even without spurious transport problems, if the
# target supports target conditions or commands, GDB re-inserts Zx
# breakpoints even if they are already inserted, to update the
# target-side condition/commands. E.g., simply when a duplicate
# breakpoint is created, or when a shared library load causes a
# re-set, which creates duplicate locations while breakpoints are
# inserted, or when the condition is really changed while breakpoints
# are inserted. To make the test not depend on shared library support
# or on details of the breakpoint re-set implementation, or on GDB
# optimizing out re-sends if the condition hasn't actually changed, we
# force always-inserted on, and really change the breakpoint's
# condition. For good measure, test with both always-inserted "on"
# and "off" modes.
# The test is written in black-box style, and doesn't actually use
# anything target remote specific, so let it run on all targets.
standard_testfile
if {[prepare_for_testing "failed to prepare" $testfile $srcfile debug]} {
return -1
}
if ![runto_main] then {
fail "Can't run to main"
return 0
}
if [is_remote host] {
set arg [remote_download host $binfile]
if { $arg == "" } {
perror "download failed"
return -1
}
}
# Force a breakpoint re-set in GDB. Currently this is done by
# reloading symbols with the "file" command.
proc force_breakpoint_re_set {} {
global binfile gdb_prompt
set test "file \$binfile"
gdb_test_multiple "file $binfile" $test {
-re "Are you sure you want to change the file. .*y or n. $" {
send_gdb "y\n"
exp_continue
}
-re "Load new symbol table from \".*\".*y or n. $" {
send_gdb "y\n"
exp_continue
}
-re "Reading symbols from.*done.*$gdb_prompt $" {
pass $test
}
}
}
# Set a break/hbreak/watch/rwatch/awatch.
proc set_breakpoint { break_command } {
global gdb_prompt srcfile
if { $break_command == "break" } {
gdb_test "$break_command foo" "Breakpoint.*at.* file .*$srcfile, line.*"
} elseif { $break_command == "hbreak" } {
set test "$break_command foo"
gdb_test_multiple $test $test {
-re "No hardware breakpoint support in the target.*$gdb_prompt $" {
unsupported $test
}
-re "Hardware breakpoints used exceeds limit.*$gdb_prompt $" {
unsupported $test
}
-re "Cannot insert hardware breakpoint.*$gdb_prompt $" {
unsupported $test
}
-re "Hardware assisted breakpoint.*at.* file .*$srcfile, line.*$gdb_prompt $" {
pass $test
}
}
} elseif { [string first "watch" $break_command] != -1 } {
set test "$break_command global"
gdb_test_multiple $test $test {
-re "Target does not support this type of hardware watchpoint\\.\r\n$gdb_prompt $" {
unsupported $test
}
-re "Could not insert hardware watchpoint.*$gdb_prompt $" {
unsupported $test
}
-re "atchpoint \[0-9\]+: global\r\n$gdb_prompt $" {
pass $test
}
}
} else {
error "unhandled command: $break_command"
}
}
# Run the test proper. ALWAYS_INSERT determines whether
# always-inserted mode is on/off, and BREAK_COMMAND is the
# break/watch/etc. command being tested.
#
proc test_break { always_inserted break_command } {
set cmd [lindex [split "$break_command"] 0]
with_test_prefix "always-inserted $always_inserted: $cmd" {
delete_breakpoints
if ![runto_main] then {
fail "Can't run to main"
return
}
gdb_test_no_output "set breakpoint always-inserted $always_inserted"
# Set breakpoints/watchpoints twice. With always-inserted on,
# GDB reinserts the exact same Z breakpoint twice... Do this
# to make sure the stub pays attention to idempotency even
# when the condition doesn't change. If GDB end up optimizing
# out exact duplicate packets, we should come up with a way to
# keep testing this case.
foreach iter { "once" "twice" } {
with_test_prefix $iter {
set_breakpoint $break_command
}
}
# Force a breakpoint re-set. In always-inserted mode, this
# makes GDB re-send Z packets too...
force_breakpoint_re_set
# Now really change the condition, which forces a reinsert by
# design.
gdb_test "condition \$bpnum cond_global == 0" ".*"
# Now delete breakpoints, and let the program execute the
# address where the breakpoint used to be set. If the target
# doesn't treat insertions an idempotent way, we'll get a
# spurious SIGTRAP.
delete_breakpoints
gdb_test "b bar" "Breakpoint .* at .*"
gdb_test "continue" "Breakpoint .*, bar .*"
}
}
foreach always_inserted { "off" "on" } {
test_break $always_inserted "break"
if {![skip_hw_breakpoint_tests]} {
test_break $always_inserted "hbreak"
}
if {![skip_hw_watchpoint_tests]} {
test_break $always_inserted "watch"
}
if {![skip_hw_watchpoint_access_tests]
&& ![skip_hw_watchpoint_multi_tests]} {
test_break $always_inserted "rwatch"
test_break $always_inserted "awatch"
}
}
|