1# Copyright (C) 2014-2020 Free Software Foundation, Inc. 2 3# This program is free software; you can redistribute it and/or modify 4# it under the terms of the GNU General Public License as published by 5# the Free Software Foundation; either version 3 of the License, or 6# (at your option) any later version. 7# 8# This program is distributed in the hope that it will be useful, 9# but WITHOUT ANY WARRANTY; without even the implied warranty of 10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11# GNU General Public License for more details. 12# 13# You should have received a copy of the GNU General Public License 14# along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16# This file is part of the gdb testsuite. 17 18# Test stepping over permanent breakpoints. 19 20standard_testfile 21 22set options { debug } 23if { ![target_info exists gdb,nosignals] } { 24 lappend options "additional_flags=-DSIGNALS" 25} 26 27if {[build_executable "failed to prepare" $testfile $srcfile $options]} { 28 return -1 29} 30 31set line_bp [gdb_get_line_number "write permanent bp"] 32 33# The test proper. ALWAYS_INSERTED indicates whether testing in 34# "breakpoint always-inserted" mode. If SW_WATCHPOINT is true, set a 35# software watchpoint, which forces constantly single-stepping, and 36# exercises stepping the permanent breakpoint while delivering a 37# signal at the same time. 38 39proc test {always_inserted sw_watchpoint} { 40 global line_bp 41 global hex decimal 42 global gdb_prompt 43 global srcfile binfile 44 45 clean_restart $binfile 46 47 if ![runto_main] then { 48 return -1 49 } 50 51 gdb_test "set breakpoint always-inserted $always_inserted" 52 53 if {$sw_watchpoint} { 54 # Watching a convenience variable forces a software 55 # watchpoint. 56 gdb_test "watch \$dummy_convenience" "Watchpoint .*" 57 } 58 59 set address_bp "" 60 set address_after_bp "" 61 62 with_test_prefix "setup" { 63 64 # Set a breakpoint where we'll manually plant a permanent 65 # breakpoint. 66 set test "set probe breakpoint" 67 gdb_test_multiple "break $line_bp" $test { 68 -re "Breakpoint .* at ($hex).*$gdb_prompt $" { 69 set address_bp $expect_out(1,string) 70 pass $test 71 } 72 } 73 if {$address_bp == ""} { 74 return 75 } 76 77 # Get the size of the instruction where the breakpoint will 78 # manually inserted. 79 set test "get size of instruction" 80 gdb_test_multiple "x/2i $address_bp" $test { 81 -re ".*$hex <test\\+$decimal>:\[^\r\n\]+\r\n\[ \]+($hex).*\.\r\n$gdb_prompt $" { 82 set address_after_bp $expect_out(1,string) 83 pass $test 84 } 85 } 86 if {$address_after_bp == ""} { 87 return 88 } 89 90 # Write address range where the breakpoint is inserted to the 91 # corresponding variables in the inferior. 92 gdb_test "p /x addr_bp = $address_bp" " = $address_bp" \ 93 "write addr_bp" 94 gdb_test "p /x addr_after_bp = $address_after_bp" " = $address_after_bp" \ 95 "write addr_after_bp" 96 97 # Run the "setup" function in the inferior. This memcpy's the 98 # breakpoint instruction to a buffer in the inferior. 99 gdb_test "next" "test_basics \\(\\).*" "next over setup" 100 101 delete_breakpoints 102 103 # We now have the breakpoint instruction stored in 'buffer'. Poke it 104 # to memory manually. 105 set count [expr $address_after_bp - $address_bp] 106 for {set i 0} {$i < $count} {incr i} { 107 set test "p /x addr_bp\[$i\] = buffer\[$i\]" 108 gdb_test_multiple $test $test { 109 -re "Cannot access memory at address $hex.*$gdb_prompt $" { 110 # Some targets (QEMU for one) will disallow writes to the 111 # .text section under certain circumstances. It is no use 112 # continuing with the test at this point. Just return. 113 unsupported "cannot modify memory" 114 return 115 } 116 -re " = .*$gdb_prompt $" { 117 pass $test 118 } 119 } 120 } 121 } 122 123 with_test_prefix "basics" { 124 # Run to the permanent breakpoint, just to make sure we've inserted it 125 # correctly. 126 # If the target fails to stop, the remainder of the test will not work 127 # so just return. This can happen on some simulator targets where 128 # the running program doesn't see breakpoints that are visible to 129 # the execution engine, or where writes to the .text section are 130 # quietly ignored. 131 set test "permanent breakpoint causes random signal" 132 gdb_test_multiple "continue" $test { 133 -re "exited normally.*$gdb_prompt $" { 134 unsupported "failed to stop at permanent breakpoint" 135 return 136 } 137 -re "Program received signal SIGTRAP.*$gdb_prompt $" { 138 pass $test 139 } 140 } 141 142 # Now set a breakpoint on top, thus creating a permanent breakpoint. 143 gdb_breakpoint "$line_bp" 144 145 # Depending on whether this is a decr_pc_after_break arch, the PC will 146 # be either pointing at the permanent breakpoint address, or just 147 # after. Set the GDB breakpoint on top, and continue, twice. At 148 # least once, GDB will need to step-over the permanent breakpoint. 149 150 gdb_test "continue" "Breakpoint .*" "stop at permanent breakpoint" 151 152 gdb_test "p \$prev_counter = counter" " = $decimal" 153 154 gdb_test "continue" "Breakpoint .*" "stop at permanent breakpoint twice" 155 156 # Check that indeed the continue made progress, instead of re-trapping 157 # without advancing. 158 gdb_test "p counter - \$prev_counter" " = 1" 159 160 gdb_test "info breakpoints" \ 161 "breakpoint.*keep.*y.*$hex.*in test at .*$srcfile:$line_bp.*already hit 2 times.*" \ 162 "info breakpoints show enabled breakpoint" 163 164 gdb_test "disable \$bpnum" 165 166 gdb_test "commands\nset \$commands_ran = 1\nend" "" \ 167 "set breakpoint commands" 168 169 gdb_test "info breakpoints" \ 170 "breakpoint.*keep.*n.*$hex.*in test at .*$srcfile:$line_bp.*already hit 2 times.*" \ 171 "info breakpoints shows disabled breakpoint" 172 173 # Run to the permanent breakpoint again. This time, since it's 174 # disabled, it should act as if we hadn't created it in the first 175 # place. IOW, we should get a random signal, and, the breakpoint's 176 # command should not run. 177 gdb_test "continue" "Program received signal SIGTRAP.*" \ 178 "disabled permanent breakpoint doesn't explain stop" 179 180 gdb_test "info breakpoints" \ 181 "breakpoint.*keep.*n.*$hex.*in test at .*$srcfile:$line_bp.*already hit 2 times.*" \ 182 "info breakpoints still shows same number of hits" 183 184 gdb_test "print \$commands_ran" " = void" \ 185 "breakpoint commands didn't run" 186 187 # Reenable the breakpoint, and check that it gets hit and accounted 188 # for this time. 189 gdb_test "enable \$bpnum" "" "reenable breakpoint" 190 191 gdb_test "continue" "Breakpoint .*" \ 192 "stop at permanent breakpoint thrice" 193 194 gdb_test "info breakpoints" \ 195 "breakpoint.*keep.*y.*$hex.*in test at .*$srcfile:$line_bp.*already hit 3 times.*" \ 196 "info breakpoints shows one more hit" 197 198 gdb_test "print \$commands_ran" " = 1" "breakpoint commands ran" 199 200 # Check that stepi advances only past the permanent breakpoint, and 201 # not a single instruction more. 202 gdb_test "stepi" "after permanent bp .*" \ 203 "single-step past permanent breakpoint" 204 } 205 206 with_test_prefix "next trips on permanent bp" { 207 delete_breakpoints 208 209 gdb_breakpoint "test_next" 210 gdb_continue_to_breakpoint "test_next" 211 212 gdb_breakpoint "$line_bp" 213 gdb_test "condition \$bpnum 0" 214 215 gdb_test "next" "after next .*" 216 } 217 218 if ![target_info exists gdb,nosignals] { 219 220 with_test_prefix "continue trips on nested permanent bp" { 221 delete_breakpoints 222 223 gdb_breakpoint "test_signal_nested" 224 gdb_continue_to_breakpoint "test_signal_nested" 225 226 gdb_breakpoint "$line_bp" 227 gdb_continue_to_breakpoint "permanent bp" 228 gdb_test "condition \$bpnum 0" 229 230 # Let SIGALRM trigger. 231 sleep 2 232 233 # We're now stopped at a permanent breakpoint, with a 234 # signal pending. 235 gdb_breakpoint "test_signal_nested_done" 236 gdb_continue_to_breakpoint "test_signal_nested_done" 237 238 # Ensure that the handler did run. There's one call to 239 # test in the mainline code, and another in the signal 240 # handler. 241 gdb_test "p counter" " = 2" 242 } 243 244 if [can_single_step_to_signal_handler] { 245 246 with_test_prefix "stepi signal with handler" { 247 delete_breakpoints 248 249 gdb_breakpoint "test_signal_with_handler" 250 gdb_continue_to_breakpoint "test_signal_with_handler" 251 252 gdb_breakpoint "$line_bp" 253 254 gdb_test "continue" "Breakpoint .*" "stop at permanent breakpoint" 255 256 gdb_test "queue-signal SIGUSR1" 257 258 set test "single-step to handler" 259 gdb_test_multiple "stepi" $test { 260 -re "Program received signal SIGTRAP.*$gdb_prompt $" { 261 fail $test 262 } 263 -re "handler .*$gdb_prompt $" { 264 pass $test 265 } 266 } 267 268 # Check that the mainline PC points at the permanent 269 # breakpoint. 270 gdb_test "up 2" "test .*" "up to mainline code" 271 272 gdb_test "p /x \$pc" " = $address_bp" \ 273 "mainline pc points at permanent breakpoint" 274 275 gdb_test "continue" "Breakpoint .*" \ 276 "stop at permanent breakpoint, out of handler" 277 } 278 279 with_test_prefix "stepi signal with no handler" { 280 gdb_breakpoint "test_signal_no_handler" 281 gdb_continue_to_breakpoint "test_signal_no_handler" 282 283 gdb_test "continue" "Breakpoint .*" "stop at permanent breakpoint" 284 285 gdb_test "queue-signal SIGUSR1" 286 287 gdb_test "stepi" "after permanent bp .*" \ 288 "single-step past permanent breakpoint" 289 } 290 } 291 } 292} 293 294foreach always_inserted {off on} { 295 foreach sw_watchpoint {0 1} { 296 with_test_prefix "always_inserted=$always_inserted, sw_watchpoint=$sw_watchpoint" { 297 test $always_inserted $sw_watchpoint 298 } 299 } 300} 301