1# Copyright 2014-2019 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 18standard_testfile 19 20if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } { 21 return -1 22} 23 24if ![runto main] { 25 return -1 26} 27 28# Delete all target-supplied memory regions. 29delete_memory_regions 30 31delete_breakpoints 32 33# Probe for hardware stepping. 34 35proc probe_target_hardware_step {} { 36 global gdb_prompt 37 38 set hw_step 0 39 40 gdb_test_no_output "set debug target 1" 41 set test "probe target hardware step" 42 gdb_test_multiple "si" $test { 43 -re "resume \\(\[^\r\n\]+, step, .*$gdb_prompt $" { 44 set hw_step 1 45 pass $test 46 } 47 -re "$gdb_prompt $" { 48 pass $test 49 } 50 } 51 gdb_test "set debug target 0" "->log_command.*\\).*" 52 return $hw_step 53} 54 55# Get the bounds of a function, and write them to FUNC_LO (inclusive), 56# FUNC_HI (exclusive). Return true on success and false on failure. 57proc get_function_bounds {function func_lo func_hi} { 58 global gdb_prompt 59 global hex decimal 60 61 upvar $func_lo lo 62 upvar $func_hi hi 63 64 set lo "" 65 set size "" 66 67 set test "get lo address of $function" 68 gdb_test_multiple "disassemble $function" $test { 69 -re "($hex) .*$hex <\\+($decimal)>:\[^\r\n\]+\r\nEnd of assembler dump\.\r\n$gdb_prompt $" { 70 set lo $expect_out(1,string) 71 set size $expect_out(2,string) 72 pass $test 73 } 74 } 75 76 if { $lo == "" || $size == "" } { 77 return false 78 } 79 80 # Account for the size of the last instruction. 81 set test "get hi address of $function" 82 gdb_test_multiple "x/2i $function+$size" $test { 83 -re ".*$hex <$function\\+$size>:\[^\r\n\]+\r\n\[ \]+($hex).*\.\r\n$gdb_prompt $" { 84 set hi $expect_out(1,string) 85 pass $test 86 } 87 } 88 89 if { $hi == "" } { 90 return false 91 } 92 93 # Remove unnecessary leading 0's (0x00000ADDR => 0xADDR) so we can 94 # easily do matches. Disassemble includes leading zeros, while 95 # x/i doesn't. 96 regsub -all "0x0\+" $lo "0x" lo 97 regsub -all "0x0\+" $hi "0x" hi 98 99 return true 100} 101 102# Get the address where the thread is currently stopped. 103proc get_curr_insn {} { 104 global gdb_prompt 105 global hex 106 107 set pc "" 108 set test "get current insn" 109 gdb_test_multiple "p /x \$pc" $test { 110 -re " = ($hex)\r\n$gdb_prompt $" { 111 set pc $expect_out(1,string) 112 pass $test 113 } 114 } 115 116 return $pc 117} 118 119# Get the address of where a single-step should land. 120proc get_next_insn {} { 121 global gdb_prompt 122 global hex 123 124 set next "" 125 set test "get next insn" 126 gdb_test_multiple "x/2i \$pc" $test { 127 -re "$hex .*:\[^\r\n\]+\r\n\[ \]+($hex).*\.\r\n$gdb_prompt $" { 128 set next $expect_out(1,string) 129 pass $test 130 } 131 } 132 133 return $next 134} 135 136set hw_step [probe_target_hardware_step] 137 138if ![get_function_bounds "main" main_lo main_hi] { 139 # Can't do the following tests if main's bounds are unknown. 140 return -1 141} 142 143# Manually create a read-only memory region that covers 'main'. 144gdb_test_no_output "mem $main_lo $main_hi ro" \ 145 "create read-only mem region covering main" 146 147# So that we don't fail inserting breakpoints on addresses outside 148# main, like the internal event breakpoints. 149gdb_test_no_output "set mem inaccessible-by-default off" 150 151# So we get an immediate warning/error without needing to resume the 152# target. 153gdb_test_no_output "set breakpoint always-inserted on" 154 155# Disable the automatic fallback to HW breakpoints. We want a 156# software breakpoint to be attempted, and to fail. 157gdb_test_no_output "set breakpoint auto-hw off" 158 159# Confirm manual writes to the read-only memory region fail. 160gdb_test "p /x *(char *) $main_lo = 1" \ 161 "Cannot access memory at address $main_lo" \ 162 "writing to read-only memory fails" 163 164# Ensure that inserting a software breakpoint in a known-read-only 165# region fails. 166gdb_test "break *$main_lo" \ 167 "Cannot insert breakpoint .*Cannot set software breakpoint at read-only address $main_lo.*" \ 168 "inserting software breakpoint in read-only memory fails" 169 170delete_breakpoints 171 172set supports_hbreak 0 173set test "probe hbreak support" 174gdb_test_multiple "hbreak *$main_lo" $test { 175 -re "You may have requested too many.*$gdb_prompt $" { 176 pass "$test (no support)" 177 } 178 -re "No hardware breakpoint support.*$gdb_prompt $" { 179 pass "$test (no support)" 180 } 181 -re "$gdb_prompt $" { 182 pass "$test (support)" 183 set supports_hbreak 1 184 } 185} 186 187delete_breakpoints 188 189# Check that the "auto-hw on/off" setting affects single-step 190# breakpoints as expected, by stepping through the read-only region. 191# If the target does hardware stepping, we won't exercise that aspect, 192# but we should be able to step through the region without seeing the 193# hardware breakpoint or read-only address errors. 194proc test_single_step { always_inserted auto_hw } { 195 global gdb_prompt 196 global decimal 197 global hex 198 global supports_hbreak 199 global hw_step 200 201 gdb_test_no_output "set breakpoint always-inserted $always_inserted" 202 gdb_test_no_output "set breakpoint auto-hw $auto_hw" 203 204 # Get the address of the current instruction so we know where SI is 205 # starting from. 206 set curr_insn [get_curr_insn] 207 208 # Get the address of the next instruction so we know where SI should 209 # land. 210 set next_insn [get_next_insn] 211 212 set test "step in ro region" 213 gdb_test_multiple "si" $test { 214 -re "Could not insert hardware breakpoints.*$gdb_prompt $" { 215 gdb_assert {!$hw_step && $auto_hw == "on" && !$supports_hbreak} \ 216 "$test (cannot insert hw break)" 217 } 218 -re "Cannot set software breakpoint at read-only address $next_insn.*$gdb_prompt $" { 219 gdb_assert {!$hw_step && $auto_hw == "off"} \ 220 "$test (cannot insert sw break)" 221 } 222 -re "^si\r\nNote: automatically using hardware breakpoints for read-only addresses\.\r\n\(\?\:${hex}\[ \t\]\)\?${decimal}\[ \t\]+i = 0;\r\n$gdb_prompt $" { 223 gdb_assert {!$hw_step && $auto_hw == "on" && $supports_hbreak} \ 224 "$test (auto-hw)" 225 } 226 -re "^si\r\n\(\?\:${hex}\[ \t\]\)\?${decimal}\[ \t\]+i = 0;\r\n$gdb_prompt $" { 227 gdb_assert {$hw_step || ($auto_hw == "on" && $supports_hbreak)} \ 228 "$test (no error)" 229 } 230 } 231 232 gdb_test "maint info breakpoints 0" \ 233 "No breakpoint or watchpoint matching '0'\." \ 234 "single-step breakpoint is not left behind" 235 236 # Confirm the thread really advanced. 237 if {$hw_step || ($auto_hw == "on" && $supports_hbreak)} { 238 gdb_test "p /x \$pc" " = $next_insn" "thread advanced" 239 } else { 240 gdb_test "p /x \$pc" " = $curr_insn" "thread did not advance" 241 } 242} 243 244foreach always_inserted {"off" "on"} { 245 foreach auto_hw {"off" "on"} { 246 with_test_prefix "always-inserted $always_inserted: auto-hw $auto_hw" { 247 test_single_step $always_inserted $auto_hw 248 } 249 } 250} 251