Re: question about ARM watchpoints

Pedro Alves <[email protected]>
Newsgroups gmane.comp.gdb.devel
Message-ID <[email protected]>
On 09/05/2014 10:46 AM, Pedro Alves wrote:

> Like this?  This "hopefully" is failing on ARMv7-M currently.
> 
> Passes on x86-64 native and gdbserver.
> 
> Also uploaded to:
> 
>   [email protected]:palves/gdb.git palves/hw_watch_test

Hey guys, I guess I should just push it in (and post it to gdb-patches) ?

> 
> ----------->8-----------
> From e4035b618fdca66038bae8fd51b14cc2913f6298 Mon Sep 17 00:00:00 2001
> From: Pedro Alves <[email protected]>
> Date: Fri, 5 Sep 2014 10:29:08 +0100
> Subject: [PATCH] Add test to make sure GDB knows which "kind" of watchpoint
>  the target has
> 
> This adds a test that makes sure GDB knows whether the target has
> continuable, or non-continuable watchpoints.
> 
> That is, the test confirms that GDB presents a watchpoint value change
> at the first instruction right after the instruction that changes
> memory.
> 
> gdb/testsuite/ChangeLog:
> 
> 2014-09-05  Pedro Alves  <[email protected]>
> 
> 	* gdb.base/watchpoint-stops-at-right-insn.c: New file.
> 	* gdb.base/watchpoint-stops-at-right-insn.exp: New file.
> ---
>  .../gdb.base/watchpoint-stops-at-right-insn.c      |  33 ++++
>  .../gdb.base/watchpoint-stops-at-right-insn.exp    | 177 +++++++++++++++++++++
>  2 files changed, 210 insertions(+)
>  create mode 100644 gdb/testsuite/gdb.base/watchpoint-stops-at-right-insn.c
>  create mode 100644 gdb/testsuite/gdb.base/watchpoint-stops-at-right-insn.exp
> 
> diff --git a/gdb/testsuite/gdb.base/watchpoint-stops-at-right-insn.c b/gdb/testsuite/gdb.base/watchpoint-stops-at-right-insn.c
> new file mode 100644
> index 0000000..005d63f
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/watchpoint-stops-at-right-insn.c
> @@ -0,0 +1,33 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2014 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/>.  */
> +
> +volatile int global;
> +
> +void
> +set_global (int val)
> +{
> +  global = val;
> +}
> +
> +int
> +main (void)
> +{
> +  set_global (1);
> +  set_global (2);
> +
> +  return 0;
> +}
> diff --git a/gdb/testsuite/gdb.base/watchpoint-stops-at-right-insn.exp b/gdb/testsuite/gdb.base/watchpoint-stops-at-right-insn.exp
> new file mode 100644
> index 0000000..9ad6080
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/watchpoint-stops-at-right-insn.exp
> @@ -0,0 +1,177 @@
> +# This testcase is part of GDB, the GNU debugger.
> +
> +# Copyright 2014 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 file is part of the gdb testsuite.
> +
> +# Test that GDB presents a hardware watchpoint stop at the first
> +# instruction right after the instruction that changes memory.
> +#
> +# Some targets trigger a hardware watchpoint after the instruction
> +# that wrote memory executes, thus with the memory already changed and
> +# the PC pointing to the instruction after the instruction that wrote
> +# to memory.  These targets are said to have "continuable"
> +# watchpoints, referring to the fact that to make progress after the
> +# watchpoint triggers, GDB just needs to continue the target.
> +#
> +# Other targets trigger a hardware watchpoint at the instruction which
> +# has attempted to write to the piece of memory under control of the
> +# watchpoint, with the instruction actually not executed yet.  To be
> +# able to check whether the watched value changed, GDB needs to
> +# complete the memory write, single-stepping the target once.  These
> +# targets are said to have "non-continuable" watchpoints.
> +#
> +# This test makes sure that GDB knows which kind of watchpoint the
> +# target has, using this sequence of steps:
> +#
> +# 1 - run to main
> +#
> +# 2 - set a software watchpoint
> +#
> +# 3 - continue until watchpoint triggers
> +#
> +# 4 - the PC now points to the instruction right after the instruction
> +#     that actually caused the memory write.  So this is the address a
> +#     hardware watchpoint should present the stop to the user too.
> +#     Store the PC address.
> +#
> +# 5 - replace the software watchpoint by a hardware watchpoint
> +#
> +# 6 - continue until hardware watchpoint triggers
> +#
> +# 7 - the PC must point to the same address the software watchpoint
> +#     triggered at.
> +#
> +# If the target has continuable watchpoints, but GDB thinks it has
> +# non-continuable watchpoints, GDB will stop the inferior two
> +# instructions after the watched value change, rather than at the next
> +# instruction.
> +#
> +# If the target has non-continuable watchpoints, while GDB thinks it
> +# has continuable watchpoints, GDB will see a watchpoint trigger,
> +# notice no value changed, and immediatly continue the target.  Now,
> +# either the target manages to step-over the watchpoint transparently,
> +# and GDB thus fails to present to value change to the user, or, the
> +# watchpoint will keep re-triggering, with the program never making
> +# any progress.
> +
> +standard_testfile
> +
> +# No use testing this if we can't use hardware watchpoints.
> +if {[target_info exists gdb,no_hardware_watchpoints]} {
> +    return -1
> +}
> +
> +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
> +    untested ${testfile}.exp
> +    return -1
> +}
> +
> +if { ![runto main] } then {
> +    fail "run to main"
> +    return
> +}
> +
> +# Get the current PC.  TEST is used as test prefix.
> +
> +proc get_pc {test} {
> +    global hex gdb_prompt
> +
> +    set addr ""
> +    gdb_test_multiple "p /x \$pc" "$test" {
> +	-re " = ($hex).*$gdb_prompt $" {
> +	    set addr $expect_out(1,string)
> +	    pass "$test"
> +	}
> +    }
> +
> +    return $addr
> +}
> +
> +# So we get an immediate warning/error if the target doesn't support a
> +# given watchpoint type.
> +gdb_test_no_output "set breakpoint always-inserted on"
> +
> +set hw_watchpoints_supported 0
> +
> +set test "set probe hw watchpoint"
> +gdb_test_multiple "watch global" $test {
> +    -re "You may have requested too many.*$gdb_prompt $" {
> +	pass $test
> +    }
> +    -re "Target does not support.*$gdb_prompt $" {
> +	pass $test
> +    }
> +    -re "$gdb_prompt $" {
> +	pass $test
> +	set hw_watchpoints_supported 1
> +    }
> +}
> +
> +if {!$hw_watchpoints_supported} {
> +    unsupported "no hw watchpoints support"
> +    return
> +}
> +
> +delete_breakpoints
> +
> +proc test {always_inserted} {
> +    global srcfile binfile
> +
> +    with_test_prefix "always-inserted $always_inserted" {
> +
> +	clean_restart $binfile
> +
> +	if { ![runto main] } then {
> +	    fail "run to main"
> +	    return
> +	}
> +
> +	# Force use of software watchpoints.
> +	gdb_test_no_output "set can-use-hw-watchpoints 0"
> +
> +	gdb_test "watch global" \
> +	    "Watchpoint .*: global" \
> +	    "set software watchpoint on global variable"
> +
> +	gdb_test "continue" \
> +	    "Watchpoint .*: global.*Old value = 0.*New value = 1.*set_global \\(val=1\\).*$srcfile.*" \
> +	    "software watchpoint triggers"
> +
> +	set sw_watch_pc [get_pc "get sw watchpoint PC"]
> +
> +	delete_breakpoints
> +
> +	# Allow hardware watchpoints again.
> +	gdb_test_no_output "set can-use-hw-watchpoints 1"
> +
> +	gdb_test "watch global" \
> +	    "Hardware watchpoint .*: global" \
> +	    "set hardware watchpoint on global variable"
> +
> +	gdb_test "continue" \
> +	    "Hardware watchpoint .*: global.*Old value = 1.*New value = 2.*set_global \\(val=2\\).*$srcfile.*" \
> +	    "hardware watchpoint triggers"
> +
> +	set hw_watch_pc [get_pc "get hw watchpoint PC"]
> +
> +	gdb_assert {$sw_watch_pc == $sw_watch_pc} "hw watchpoint stops at right instruction"
> +    }
> +}
> +
> +foreach always_inserted {"off" "on" } {
> +    test $always_inserted
> +}
> 


Thanks,
Pedro Alves
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.