This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH] remote: Fix hw watchpoint address matching
- From: "Maciej W. Rozycki" <macro at codesourcery dot com>
- To: <gdb-patches at sourceware dot org>
- Date: Wed, 30 Nov 2011 18:23:35 +0000
- Subject: [PATCH] remote: Fix hw watchpoint address matching
Hi,
There is a problem in the remote target where watchpoint addresses are
masked before they are passed on to the target, but later on if such a
watchpoint is hit the generic range-checker compares the masked address
reported by the remote side with the original unmasked address associated
with the watchpoint within GDB. The result for 32-bit MIPS processors and
KSEG addresses, which are sign-extended to 64 bits and thus non-zero in
the 32 high order bits, is the watchpoint hit is not recognised and a
SIGTRAP reported instead.
The fix below replaces the generic checker with a specific one that
applies the mask for the purpose of the range check. This is imperfect if
"set remoteaddresssize" was used to set the mask beyond the width of the
address used by the target, but I think it's about as reasonable as you
can get. And the setting looks like an awful hack to me, so my suggestion
is merely: "Don't do it."
Regression-tested with mips-sde-elf, fixing numerous failures like:
(gdb) PASS: gdb.base/display.exp: display/s &sum
cont
Continuing.
Program received signal SIGTRAP, Trace/breakpoint trap.
0x80001176 in do_loops () at .../gdb/testsuite/gdb.base/display.c:22
22 sum++; f++; force_mem (&k);
5: x/s &sum 0x80004cc0 <sum>: ""
4: /f f = 3.1415
3: x/i &k
0x80505b80: nop
2: /x j = 0x0
1: i = 0
(gdb) FAIL: gdb.base/display.exp: first disp
which is now:
(gdb) PASS: gdb.base/display.exp: display/s &sum
cont
Continuing.
Hardware watchpoint 3: sum
Old value = 0
New value = 1
0x80001176 in do_loops () at .../gdb/testsuite/gdb.base/display.c:22
22 sum++; f++; force_mem (&k);
5: x/s &sum 0x80004cc0 <sum>: ""
4: /f f = 3.1415
3: x/i &k
0x80505b80: nop
2: /x j = 0x0
1: i = 0
(gdb) PASS: gdb.base/display.exp: first disp
and introducing no new ones. Tested for mips-linux-gnu successfully too;
no improvement there as the issue with kernel-mode addresses does not
apply to Linux userland. OK to apply?
2011-11-30 Maciej W. Rozycki <macro@codesourcery.com>
gdb/
* remote.c (remote_watchpoint_addr_within_range): New function.
(init_remote_ops): Use it.
Maciej
gdb-remote-watch-range.diff
Index: gdb-fsf-trunk-quilt/gdb/remote.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/remote.c 2011-11-30 16:59:46.215590824 +0000
+++ gdb-fsf-trunk-quilt/gdb/remote.c 2011-11-30 17:01:56.045448615 +0000
@@ -7805,6 +7805,15 @@ remote_insert_watchpoint (CORE_ADDR addr
_("remote_insert_watchpoint: reached end of function"));
}
+static int
+remote_watchpoint_addr_within_range (struct target_ops *target, CORE_ADDR addr,
+ CORE_ADDR start, int length)
+{
+ CORE_ADDR diff = remote_address_masked (addr - start);
+
+ return diff >= 0 && diff < length;
+}
+
static int
remote_remove_watchpoint (CORE_ADDR addr, int len, int type,
@@ -10509,6 +10518,8 @@ Specify the serial device it is connecte
remote_ops.to_remove_breakpoint = remote_remove_breakpoint;
remote_ops.to_stopped_by_watchpoint = remote_stopped_by_watchpoint;
remote_ops.to_stopped_data_address = remote_stopped_data_address;
+ remote_ops.to_watchpoint_addr_within_range =
+ remote_watchpoint_addr_within_range;
remote_ops.to_can_use_hw_breakpoint = remote_check_watch_resources;
remote_ops.to_insert_hw_breakpoint = remote_insert_hw_breakpoint;
remote_ops.to_remove_hw_breakpoint = remote_remove_hw_breakpoint;