forked from Imagelibrary/binutils-gdb
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
This commit is contained in:
24
gdb/infrun.c
24
gdb/infrun.c
@@ -4491,9 +4491,9 @@ handle_syscall_event (struct execution_control_state *ecs)
|
||||
infrun_debug_printf ("syscall number=%d", syscall_number);
|
||||
|
||||
ecs->event_thread->control.stop_bpstat
|
||||
= bpstat_stop_status (regcache->aspace (),
|
||||
ecs->event_thread->stop_pc (),
|
||||
ecs->event_thread, ecs->ws);
|
||||
= bpstat_stop_status_nowatch (regcache->aspace (),
|
||||
ecs->event_thread->stop_pc (),
|
||||
ecs->event_thread, ecs->ws);
|
||||
|
||||
if (handle_stop_requested (ecs))
|
||||
return false;
|
||||
@@ -5288,9 +5288,9 @@ handle_inferior_event (struct execution_control_state *ecs)
|
||||
|
||||
ecs->event_thread->set_stop_pc (regcache_read_pc (regcache));
|
||||
ecs->event_thread->control.stop_bpstat
|
||||
= bpstat_stop_status (regcache->aspace (),
|
||||
ecs->event_thread->stop_pc (),
|
||||
ecs->event_thread, ecs->ws);
|
||||
= bpstat_stop_status_nowatch (regcache->aspace (),
|
||||
ecs->event_thread->stop_pc (),
|
||||
ecs->event_thread, ecs->ws);
|
||||
|
||||
if (handle_stop_requested (ecs))
|
||||
return;
|
||||
@@ -5531,9 +5531,9 @@ handle_inferior_event (struct execution_control_state *ecs)
|
||||
(regcache_read_pc (get_thread_regcache (ecs->event_thread)));
|
||||
|
||||
ecs->event_thread->control.stop_bpstat
|
||||
= bpstat_stop_status (get_current_regcache ()->aspace (),
|
||||
ecs->event_thread->stop_pc (),
|
||||
ecs->event_thread, ecs->ws);
|
||||
= bpstat_stop_status_nowatch (get_current_regcache ()->aspace (),
|
||||
ecs->event_thread->stop_pc (),
|
||||
ecs->event_thread, ecs->ws);
|
||||
|
||||
if (handle_stop_requested (ecs))
|
||||
return;
|
||||
@@ -5642,9 +5642,9 @@ handle_inferior_event (struct execution_control_state *ecs)
|
||||
(regcache_read_pc (get_thread_regcache (ecs->event_thread)));
|
||||
|
||||
ecs->event_thread->control.stop_bpstat
|
||||
= bpstat_stop_status (get_current_regcache ()->aspace (),
|
||||
ecs->event_thread->stop_pc (),
|
||||
ecs->event_thread, ecs->ws);
|
||||
= bpstat_stop_status_nowatch (get_current_regcache ()->aspace (),
|
||||
ecs->event_thread->stop_pc (),
|
||||
ecs->event_thread, ecs->ws);
|
||||
|
||||
if (handle_stop_requested (ecs))
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user