diff options
author | Jan Kratochvil <jan.kratochvil@redhat.com> | 2009-11-20 19:57:29 +0000 |
---|---|---|
committer | Jan Kratochvil <jan.kratochvil@redhat.com> | 2009-11-20 19:57:29 +0000 |
commit | a79d3c27d1827de4f4b428644ae1447c93a13de5 (patch) | |
tree | 36a6ba5b863c026b202ce7eade50781a79e0aba6 /gdb/breakpoint.c | |
parent | ebec9a0f77584145a70e8f5627dd590bae43b580 (diff) | |
download | gdb-a79d3c27d1827de4f4b428644ae1447c93a13de5.zip gdb-a79d3c27d1827de4f4b428644ae1447c93a13de5.tar.gz gdb-a79d3c27d1827de4f4b428644ae1447c93a13de5.tar.bz2 |
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.
Diffstat (limited to 'gdb/breakpoint.c')
-rw-r--r-- | gdb/breakpoint.c | 41 |
1 files changed, 40 insertions, 1 deletions
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) { |