From a79d3c27d1827de4f4b428644ae1447c93a13de5 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Fri, 20 Nov 2009 19:57:29 +0000 Subject: gdb/ Fix repeated rwatch output. * amd64-linux-nat.c (amd64_linux_dr_set, amd64_linux_dr_set_control) (amd64_linux_dr_set_addr, amd64_linux_dr_reset_addr) (amd64_linux_dr_get_status): New comments. (amd64_linux_dr_unset_status): New function. (_initialize_amd64_linux_nat): Install it. * i386-linux-nat.c (i386_linux_dr_get, i386_linux_dr_set) (i386_linux_dr_set_control, i386_linux_dr_set_addr) (i386_linux_dr_reset_addr, i386_linux_dr_get_status): New comments. (i386_linux_dr_unset_status): New function. (_initialize_i386_linux_nat): Install it. * i386-nat.c (I386_DR_WATCH_MASK): New macro. (I386_DR_WATCH_HIT): Use I386_DR_WATCH_MASK. (i386_insert_aligned_watchpoint): Call i386_dr_low.unset_status. * i386-nat.h (struct i386_dr_low_type): Extend comments for set_control, set_addr, reset_addr and get_status. New unset_status. * breakpoint.c (update_watchpoint): Extend the comment. gdb/testsuite/ * gdb.base/watchpoint-hw-hit-once.exp, gdb.base/watchpoint-hw-hit-once.c: New. --- gdb/breakpoint.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) (limited to 'gdb/breakpoint.c') diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 1c30f6d..d879b57 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -993,7 +993,46 @@ fetch_watchpoint_value (struct expression *exp, struct value **valp, - Update the list of values that must be watched in B->loc. If the watchpoint disposition is disp_del_at_next_stop, then do nothing. - If this is local watchpoint that is out of scope, delete it. */ + If this is local watchpoint that is out of scope, delete it. + + Even with `set breakpoint always-inserted on' the watchpoints are removed + + inserted on each stop here. Normal breakpoints must never be removed + because they might be missed by a running thread when debugging in non-stop + mode. On the other hand, hardware watchpoints (is_hardware_watchpoint; + processed here) are specific to each LWP since they are stored in each LWP's + hardware debug registers. Therefore, such LWP must be stopped first in + order to be able to modify its hardware watchpoints. + + Hardware watchpoints must be reset exactly once after being presented to the + user. It cannot be done sooner, because it would reset the data used to + present the watchpoint hit to the user. And it must not be done later + because it could display the same single watchpoint hit during multiple GDB + stops. Note that the latter is relevant only to the hardware watchpoint + types bp_read_watchpoint and bp_access_watchpoint. False hit by + bp_hardware_watchpoint is not user-visible - its hit is suppressed if the + memory content has not changed. + + The following constraints influence the location where we can reset hardware + watchpoints: + + * target_stopped_by_watchpoint and target_stopped_data_address are called + several times when GDB stops. + + [linux] + * Multiple hardware watchpoints can be hit at the same time, causing GDB to + stop. GDB only presents one hardware watchpoint hit at a time as the + reason for stopping, and all the other hits are presented later, one after + the other, each time the user requests the execution to be resumed. + Execution is not resumed for the threads still having pending hit event + stored in LWP_INFO->STATUS. While the watchpoint is already removed from + the inferior on the first stop the thread hit event is kept being reported + from its cached value by linux_nat_stopped_data_address until the real + thread resume happens after the watchpoint gets presented and thus its + LWP_INFO->STATUS gets reset. + + Therefore the hardware watchpoint hit can get safely reset on the watchpoint + removal from inferior. */ + static void update_watchpoint (struct breakpoint *b, int reparse) { -- cgit v1.1