This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]