}
}
+ /* Helper function to bundle possibly emitting a warning along with
+ changing the type of B to bp_watchpoint. */
+ auto change_type_to_bp_watchpoint = [] (breakpoint *bp)
+ {
+ /* Only warn for breakpoints that have been assigned a +ve number,
+ anything else is either an internal watchpoint (which we don't
+ currently create) or has not yet been finalized, in which case
+ this change of type will be occurring before the user is told
+ the type of this watchpoint. */
+ if (bp->type == bp_hardware_watchpoint && bp->number > 0)
+ warning (_("watchpoint %d downgraded to software watchpoint"),
+ bp->number);
+ bp->type = bp_watchpoint;
+ };
+
/* Change the type of breakpoint between hardware assisted or
an ordinary watchpoint depending on the hardware support and
free hardware slots. Recheck the number of free hardware slots
"resources for this watchpoint."));
/* Downgrade to software watchpoint. */
- b->type = bp_watchpoint;
+ change_type_to_bp_watchpoint (b);
}
else
{
"read/access watchpoint."));
}
else
- b->type = bp_watchpoint;
+ change_type_to_bp_watchpoint (b);
loc_type = (b->type == bp_watchpoint? bp_loc_software_watchpoint
: bp_loc_hardware_watchpoint);
--- /dev/null
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2023 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/>. */
+
+struct struct_type
+{
+ unsigned long long array[100];
+};
+
+struct struct_type global_var;
+
+int
+main ()
+{
+ return 0;
+}
--- /dev/null
+# Copyright 2023 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/>.
+
+# Ask GDB to watch a large structure before the inferior has started,
+# GDB will assume it can place a hardware watchpoint.
+#
+# Once the inferior starts GDB realises that it is not able to watch
+# such a large structure and downgrades to a software watchpoint.
+#
+# This test checks that GDB emits a warnings about this downgrade, as
+# a software watchpoint will be significantly slower than a hardware
+# watchpoint, and the user probably wants to know about this.
+
+require target_can_use_run_cmd is_x86_64_m64_target
+
+# The remote/extended-remote target has its own set of flags to
+# control the use of s/w vs h/w watchpoints, this test isn't about
+# those, so skip the test in these cases.
+if {[target_info gdb_protocol] == "remote"
+ || [target_info gdb_protocol] == "extended-remote"} {
+ unsupported "using [target_info gdb_protocol] protocol"
+ return -1
+}
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
+ { debug }] } {
+ return -1
+}
+
+# Insert the watchpoint, it should default to a h/w watchpoint.
+gdb_test "watch global_var" \
+ "Hardware watchpoint $decimal: global_var"
+set num [get_integer_valueof "\$bpnum" "*UNKNOWN*" \
+ "get watchpoint number"]
+
+# Watchpoint should initially show as a h/w watchpoint.
+gdb_test "info watchpoints" \
+ "\r\n$num\\s+hw watchpoint\\s+keep\\s+y\\s+global_var" \
+ "check info watchpoints before starting"
+
+# Start the inferior, GDB should emit a warning that the watchpoint
+# type has changed.
+gdb_test "starti" \
+ [multi_line \
+ "warning: watchpoint $num downgraded to software watchpoint" \
+ "" \
+ "Program stopped\\." \
+ ".*"]
+
+# Watchpoint should now have downgraded to a s/w watchpoint.
+gdb_test "info watchpoints" \
+ "\r\n$num\\s+watchpoint\\s+keep\\s+y\\s+global_var" \
+ "check info watchpoints after starting"
global gdb_prompt
if {[runto marker1]} {
- gdb_test "watch ival2" ".*\[Ww\]atchpoint \[0-9\]*: ival2"
+ gdb_test "watch ival2" \
+ "^watch ival2\r\n\[^\r\n\]*\[Ww\]atchpoint \[0-9\]*: ival2"
# Well, let's not be too mundane. It should be a *bit* of a challenge
gdb_test "break func2 if 0" "Breakpoint.*at.*"
global gdb_prompt
if {[runto marker4]} {
- gdb_test "watch ptr1->val" ".*\[Ww\]atchpoint \[0-9\]*: ptr1->val"
+ gdb_test "watch ptr1->val" \
+ "^watch ptr1->val\r\n\[^\r\n\]*\[Ww\]atchpoint \[0-9\]*: ptr1->val"
gdb_test "break marker5" ".*Breakpoint.*"
gdb_test "cont" "Continuing.*\[Ww\]atchpoint.*ptr1->val.*Old value = 1.*New value = 2.*" "test complex watchpoint"
# is the function we're now in. This should auto-delete when
# execution exits the scope of the watchpoint.
#
- gdb_test "watch local_a" ".*\[Ww\]atchpoint \[0-9\]*: local_a" "set local watch"
+ gdb_test "watch local_a" \
+ "^watch local_a\r\n\[^\r\n\]*\[Ww\]atchpoint \[0-9\]*: local_a" \
+ "set local watch"
gdb_test "cont" "\[Ww\]atchpoint.*local_a.*" "trigger local watch"
set test "self-delete local watch"
# something whose scope is larger than this invocation
# of "func2". This should also auto-delete.
#
- gdb_test "watch local_a + ival5" ".*\[Ww\]atchpoint \[0-9\]*: local_a . ival5" \
+ gdb_test "watch local_a + ival5" \
+ "^watch local_a \\+ ival5\r\n\[^\r\n\]*\[Ww\]atchpoint \[0-9\]*: local_a . ival5" \
"set partially local watch"
gdb_test "cont" "Continuing.*\[Ww\]atchpoint .*: local_a . ival5.*" \
"trigger1 partially local watch"
# delete.
#
gdb_continue_to_breakpoint "func2 breakpoint here, third time"
- gdb_test "watch static_b" ".*\[Ww\]atchpoint \[0-9\]*: static_b" \
+ gdb_test "watch static_b" \
+ "^watch static_b\r\n\[^\r\n\]*\[Ww\]atchpoint \[0-9\]*: static_b" \
"set static local watch"
gdb_test "cont" "Continuing.*\[Ww\]atchpoint .*: static_b.*" \
"trigger static local watch"
gdb_test "tbreak recurser" ".*breakpoint.*"
gdb_test "cont" "Continuing.*recurser.*"
gdb_test "next" "if \\(x > 0.*" "next past local_x initialization"
- gdb_test "watch local_x" ".*\[Ww\]atchpoint \[0-9\]*: local_x" \
+ gdb_test "watch local_x" \
+ "^watch local_x\r\n\[^\r\n\]*\[Ww\]atchpoint \[0-9\]*: local_x" \
"set local watch in recursive call"
gdb_test "cont" "Continuing.*\[Ww\]atchpoint .*: local_x.*New value = 2.*" \
"trigger local watch in recursive call"
gdb_test "tbreak recurser" ".*breakpoint.*"
gdb_test "cont" "Continuing.*recurser.*" "continue to recurser"
gdb_test "next" "if \\(x > 0.*" "next past local_x initialization"
- gdb_test "watch recurser::local_x" ".*\[Ww\]atchpoint \[0-9\]*: recurser::local_x" \
+ gdb_test "watch recurser::local_x" \
+ "^watch recurser::local_x\r\n\[^\r\n\]*\[Ww\]atchpoint \[0-9\]*: recurser::local_x" \
"set local watch in recursive call with explicit scope"
gdb_test "cont" "Continuing.*\[Ww\]atchpoint .*: recurser::local_x.*New value = 2.*" \
"trigger local watch with explicit scope in recursive call"
if {[runto func3]} {
gdb_breakpoint [gdb_get_line_number "second x assignment"]
gdb_continue_to_breakpoint "second x assignment"
- gdb_test "watch x" ".*atchpoint \[0-9\]+: x"
+ gdb_test "watch x" \
+ "^watch x\r\n\[^\r\n\]*\[Ww\]atchpoint \[0-9\]+: x"
gdb_test "next" \
".*atchpoint \[0-9\]+: x\r\n\r\nOld value = 0\r\nNew value = 1\r\n.*" \
"next after watch x"
"marker1 is constant"
gdb_test "watch count + 6" ".*atchpoint \[0-9\]+: count \\+ 6"
gdb_test_no_output "delete \$bpnum" "delete watchpoint `count + 6'"
- gdb_test "watch 7 + count" ".*atchpoint \[0-9\]+: 7 \\+ count"
+ gdb_test "watch 7 + count" \
+ "^watch 7 \\+ count\r\n\[^\r\n\]*atchpoint \[0-9\]+: 7 \\+ count"
gdb_test_no_output "delete \$bpnum" "delete watchpoint `7 + count'"
}
# for software watchpoints.
# Watch something not memory to force a software watchpoint.
- gdb_test {watch $pc} ".*atchpoint \[0-9\]+: .pc"
+ gdb_test {watch $pc} "^watch \\\$pc\r\n\[^\r\n\]*\[Ww\]atchpoint \[0-9\]+: .pc"
gdb_test_no_output "disable \$bpnum" "disable watchpoint `\$pc'"
gdb_test_no_output "enable \$bpnum" "reenable watchpoint `\$pc'"
"show disable fast watches"
gdb_test "watch ival3 if count > 1" \
- "Watchpoint \[0-9\]*: ival3.*" \
+ "^watch ival3 if count > 1\r\nWatchpoint \[0-9\]*: ival3.*" \
"set slow conditional watch"
gdb_test "continue" \
gdb_test_no_output "delete \$bpnum" "delete watch ival3"
gdb_test "watch ival3 if count > 1 thread 1 " \
- "Watchpoint \[0-9\]*: ival3.*" \
+ "watch ival3 if count > 1 thread 1 \r\nWatchpoint \[0-9\]*: ival3.*" \
"set slow condition watch w/thread"
gdb_test_no_output "delete \$bpnum" "delete watch w/condition and thread"