{
std::vector<value_ref_ptr> val_chain;
struct value *v, *result;
- struct program_space *frame_pspace;
+ struct program_space *wp_pspace;
fetch_subexp_value (b->exp.get (), b->exp->op.get (), &v, &result,
&val_chain, false);
b->val_valid = true;
}
- frame_pspace = get_frame_program_space (get_selected_frame (NULL));
+ if (b->exp_valid_block == nullptr)
+ wp_pspace = current_program_space;
+ else
+ wp_pspace = get_frame_program_space (get_selected_frame (NULL));
/* Look at each value on the value chain. */
gdb_assert (!val_chain.empty ());
bp_location *loc = b->allocate_location ();
loc->gdbarch = v->type ()->arch ();
- loc->pspace = frame_pspace;
+ loc->pspace = wp_pspace;
loc->address
= gdbarch_remove_non_address_bits (loc->gdbarch, addr);
b->add_location (*loc);
bpstat_stop_status requires a location to be able to report
stops, so make sure there's at least a dummy one. */
if (b->type == bp_watchpoint && !b->has_locations ())
- add_dummy_location (b, frame_pspace);
+ add_dummy_location (b, wp_pspace);
}
else if (!within_current_scope)
{
--- /dev/null
+/* 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/>.
+
+*/
+
+#include <unistd.h>
+#include <stdint.h>
+
+uint64_t global_var;
+
+/* How long to usleep, in us. The exp file assumes this is lower than
+ 1s. */
+#define MS_USLEEP 100000
+
+/* How many increments per second MS_USLEEP corresponds to. */
+#define INCREMENTS_PER_SEC (1000000 / MS_USLEEP)
+
+int
+main ()
+{
+ while (1)
+ {
+ usleep (MS_USLEEP);
+ global_var++;
+
+ /* Time out after 30s. */
+ if (global_var >= (30 * INCREMENTS_PER_SEC))
+ return 1;
+ }
+
+ return 0;
+}
--- /dev/null
+# 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.
+
+#require allow_hw_watchpoint_multi_tests
+
+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/111111 *-*-*
+
+ # 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 {!$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
+ }
+ }
+}