| 12
 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
 
 | # This testcase is part of GDB, the GNU debugger.
# Copyright 2023-2024 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 test verifies that you can set a watchpoint that watches global
# memory, when the selected thread is running.
set allow_hw_watchpoint_tests_p [allow_hw_watchpoint_tests]
standard_testfile
if [build_executable "failed to prepare" $testfile $srcfile {debug}] {
    return -1
}
# STOP_MODE is either "all-stop" or "non-stop".  HW is true if we are
# testing hardware watchpoints, and false if we're testing software
# watchpoints.
proc test {stop_mode hw} {
    save_vars { ::GDBFLAGS } {
	if { $stop_mode == "non-stop" } {
	    append ::GDBFLAGS " -ex \"set non-stop on\""
	} elseif {[target_info gdb_protocol] == "remote"
		  || [target_info gdb_protocol]== "extended-remote"} {
	    # Communicating with the target while the inferior is
	    # running depends on target running in non-stop mode.
	    # Force it on for remote targets, until this is the
	    # default.
	    append ::GDBFLAGS " -ex \"maint set target-non-stop on\""
	}
	clean_restart $::binfile
    }
    gdb_test_no_output "set can-use-hw-watchpoints $hw"
    if {![runto_main]} {
	return
    }
    delete_breakpoints
    # Continue the program in the background.
    set test "continue&"
    gdb_test_multiple "continue&" $test {
	-re "Continuing\\.\r\n$::gdb_prompt " {
	    pass $test
	}
    }
    set val1 ""
    gdb_test_multiple "print global_var" "global_var once" {
	-re -wrap " = ($::decimal)" {
	    set val1 $expect_out(1,string)
	    pass "$gdb_test_name"
	}
    }
    # Sleep for a bit, so the variable is sure to be incremented, if
    # indeed we managed to get the target running.
    sleep 1
    set val2 ""
    gdb_test_multiple "print global_var" "global_var twice" {
	-re -wrap " = ($::decimal)" {
	    set val2 $expect_out(1,string)
	    pass "$gdb_test_name"
	}
    }
    # The variable should have incremented.  (Note we didn't give it
    # sufficient time to ever wrap around.)
    gdb_assert {$val1 != $val2} "values are different"
    set wp_str [expr ($hw)?"Hardware watchpoint":"Watchpoint"]
    # Now set a watchpoint, while the inferior is running.  Since
    # we're watching a global, and we can read global memory while the
    # target is running, this should be able to work.
    gdb_test_multiple "watch global_var" "" {
	-re "$wp_str $::decimal: global_var\r\n$::gdb_prompt " {
	    pass $gdb_test_name
	}
    }
    # Check that the watchpoint triggers.
    save_vars ::timeout {
	if {!$hw} {
	    # This doesn't currently work with software watchpoints.
	    # GDB should transparently temporarily pause the inferior,
	    # to force it to single step, but it doesn't, so the
	    # thread continues running free.
	    setup_kfail gdb/31833 *-*-*
	    # No point waiting too much for output we know isn't
	    # coming.
	    set ::timeout 1
	}
	set re [multi_line \
		    "$wp_str $::decimal: global_var" \
		    "" \
		    "Old value = $::decimal" \
		    "New value = $::decimal"]
	gdb_test_multiple "" "watchpoint hit" {
	    -re $re {
		pass $gdb_test_name
	    }
	}
    }
}
foreach hw {0 1} {
    if {$hw && !$allow_hw_watchpoint_tests_p} {
	continue
    }
    foreach stop_mode {all-stop non-stop} {
	set wp_type [expr ($hw)?"hardware":"software"]
	with_test_prefix "$stop_mode: $wp_type" {
	    test $stop_mode $hw
	}
    }
}
 |