aboutsummaryrefslogtreecommitdiff
path: root/gdb/breakpoint.h
diff options
context:
space:
mode:
authorPedro Alves <pedro@palves.net>2021-11-23 14:19:07 +0000
committerPedro Alves <pedro@palves.net>2022-03-21 17:27:17 +0000
commitd37e084783a04c63ae137f953ebdb58bb6f7f704 (patch)
tree90e82c9060245f0cec3f94d3cb6a2a73bc8df4c0 /gdb/breakpoint.h
parent4414150d33212f5f395c3bf8a940bccf80ffc508 (diff)
downloadbinutils-d37e084783a04c63ae137f953ebdb58bb6f7f704.zip
binutils-d37e084783a04c63ae137f953ebdb58bb6f7f704.tar.gz
binutils-d37e084783a04c63ae137f953ebdb58bb6f7f704.tar.bz2
Watchpoint followed by catchpoint misreports watchpoint (PR gdb/28621)
If GDB reports a watchpoint hit, and then the next event is not TARGET_WAITKIND_STOPPED, but instead some event for which there's a catchpoint, such that GDB calls bpstat_stop_status, GDB mistakenly thinks the watchpoint triggered. Vis, using foll-fork.c: (gdb) awatch v Hardware access (read/write) watchpoint 2: v (gdb) catch fork Catchpoint 3 (fork) (gdb) c Continuing. Hardware access (read/write) watchpoint 2: v Old value = 0 New value = 5 main () at gdb.base/foll-fork.c:16 16 pid = fork (); (gdb) Continuing. Hardware access (read/write) watchpoint 2: v <<<< <<<< these lines are spurious Value = 5 <<<< Catchpoint 3 (forked process 1712369), arch_fork (ctid=0x7ffff7fa4810) at arch-fork.h:49 49 arch-fork.h: No such file or directory. (gdb) The problem is that when we handle the fork event, nothing called watchpoints_triggered before calling bpstat_stop_status. Thus, each watchpoint's watchpoint_triggered field was still set to watch_triggered_yes from the previous (real) watchpoint stop. watchpoint_triggered is only current called in the handle_signal_stop path, when handling TARGET_WAITKIND_STOPPED. This fixes it by adding watchpoint_triggered calls in the other events paths that call bpstat_stop_status. But instead of adding them explicitly, it adds a new function bpstat_stop_status_nowatch that wraps bpstat_stop_status and calls watchpoint_triggered, and then replaces most calls to bpstat_stop_status with calls to bpstat_stop_status_nowatch. This required constifying watchpoints_triggered. New test included, which fails without the fix. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28621 Change-Id: I282b38c2eee428d25319af3bc842f9feafed461c
Diffstat (limited to 'gdb/breakpoint.h')
-rw-r--r--gdb/breakpoint.h25
1 files changed, 22 insertions, 3 deletions
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index ba28219..e412c4d 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -968,13 +968,31 @@ extern bpstat *build_bpstat_chain (const address_space *aspace,
several reasons concurrently.)
Each element of the chain has valid next, breakpoint_at,
- commands, FIXME??? fields. */
+ commands, FIXME??? fields.
+
+ watchpoints_triggered must be called beforehand to set up each
+ watchpoint's watchpoint_triggered value.
+
+*/
extern bpstat *bpstat_stop_status (const address_space *aspace,
CORE_ADDR pc, thread_info *thread,
const target_waitstatus &ws,
bpstat *stop_chain = nullptr);
+
+/* Like bpstat_stop_status, but clears all watchpoints'
+ watchpoint_triggered flag. Unlike with bpstat_stop_status, there's
+ no need to call watchpoint_triggered beforehand. You'll typically
+ use this variant when handling a known-non-watchpoint event, like a
+ fork or exec event. */
+
+extern bpstat *bpstat_stop_status_nowatch (const address_space *aspace,
+ CORE_ADDR bp_addr,
+ thread_info *thread,
+ const target_waitstatus &ws);
+
+
/* This bpstat_what stuff tells wait_for_inferior what to do with a
breakpoint (a challenging task).
@@ -1607,8 +1625,9 @@ extern void insert_single_step_breakpoint (struct gdbarch *,
otherwise, return false. */
extern int insert_single_step_breakpoints (struct gdbarch *);
-/* Check if any hardware watchpoints have triggered, according to the
- target. */
+/* Check whether any hardware watchpoints have triggered or not,
+ according to the target, and record it in each watchpoint's
+ 'watchpoint_triggered' field. */
int watchpoints_triggered (const target_waitstatus &);
/* Helper for transparent breakpoint hiding for memory read and write