From 692590c19f459c379c6e13f83448ad5d11ebf1ed Mon Sep 17 00:00:00 2001 From: Michael Snyder Date: Tue, 28 Mar 2000 22:30:19 +0000 Subject: [PATCH] 2000-03-28 Peter Schauer breakpoint.c, breakpoint.h (remove_hw_watchpoints): New function. infrun.c (resume): Remove hardware watchpoints before stepping when CANNOT_STEP_HW_WATCHPOINTS is nonzero. --- gdb/ChangeLog | 6 ++++++ gdb/breakpoint.c | 21 +++++++++++++++++++++ gdb/infrun.c | 19 +++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 38256178df8..44d8c63a088 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,9 @@ +2000-03-28 Peter Schauer + + breakpoint.c, breakpoint.h (remove_hw_watchpoints): New function. + infrun.c (resume): Remove hardware watchpoints before stepping + when CANNOT_STEP_HW_WATCHPOINTS is nonzero. + 2000-03-28 Michael Snyder * Makefile.in: anchor tui-file.h dependency to $srcdir. diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index c5ebf6460a0..768a67f7534 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -1095,6 +1095,27 @@ remove_breakpoints () return 0; } +int +remove_hw_watchpoints () +{ + register struct breakpoint *b; + int val; + + ALL_BREAKPOINTS (b) + { + if (b->inserted + && (b->type == bp_hardware_watchpoint + || b->type == bp_read_watchpoint + || b->type == bp_access_watchpoint)) + { + val = remove_breakpoint (b, mark_uninserted); + if (val != 0) + return val; + } + } + return 0; +} + int reattach_breakpoints (pid) int pid; diff --git a/gdb/infrun.c b/gdb/infrun.c index 96a659ebf4a..6bc32d803be 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -296,6 +296,13 @@ a command like `return' or `jump' to continue execution.\n"); #define HAVE_CONTINUABLE_WATCHPOINT 1 #endif +#ifndef CANNOT_STEP_HW_WATCHPOINTS +#define CANNOT_STEP_HW_WATCHPOINTS 0 +#else +#undef CANNOT_STEP_HW_WATCHPOINTS +#define CANNOT_STEP_HW_WATCHPOINTS 1 +#endif + /* Tables of how to react to signals; the user sets them. */ static unsigned char *signal_stop; @@ -796,6 +803,18 @@ resume (int step, enum target_signal sig) step = 0; #endif + /* Some targets (e.g. Solaris x86) have a kernel bug when stepping + over an instruction that causes a page fault without triggering + a hardware watchpoint. The kernel properly notices that it shouldn't + stop, because the hardware watchpoint is not triggered, but it forgets + the step request and continues the program normally. + Work around the problem by removing hardware watchpoints if a step is + requested, GDB will check for a hardware watchpoint trigger after the + step anyway. */ + if (CANNOT_STEP_HW_WATCHPOINTS && step && breakpoints_inserted) + remove_hw_watchpoints (); + + /* Normally, by the time we reach `resume', the breakpoints are either removed or inserted, as appropriate. The exception is if we're sitting at a permanent breakpoint; we need to step over it, but permanent -- 2.30.2