aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog12
-rw-r--r--gdb/infrun.c84
-rw-r--r--gdb/lynx-nat.c8
3 files changed, 81 insertions, 23 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 1e096fb..2ff3c3f 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,15 @@
+Tue Jul 4 10:30:22 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * infrun.c (wait_for_inferior): When we hit a breakpoint for the
+ wrong thread, make sure to write the fixed PC value into the thread
+ that stopped. Restart all threads after single stepping over a
+ breakpoint for a different thread.
+ * breakpoint.c (set_momentary_breakpoint): Make momentary
+ breakpoints thread specific in a multi-threaded program.
+ * lynx-nat.c (child_resume): Add some comments. Correctly
+ choose between the single and multi-threaded step and continue
+ ptrace calls.
+
Fri Jun 30 16:15:36 1995 Stan Shebs <shebs@andros.cygnus.com>
* config/h8300/h8300.mt: Renamed from h8300hms.mt.
diff --git a/gdb/infrun.c b/gdb/infrun.c
index cd69629..5ad2bfc 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -479,6 +479,8 @@ wait_for_inferior ()
else
pid = target_wait (-1, &w);
+ have_waited:
+
flush_cached_frames ();
/* If it's a new process, add it to the thread database */
@@ -501,24 +503,6 @@ wait_for_inferior ()
continue;
}
- stop_signal = w.value.sig;
-
- stop_pc = read_pc_pid (pid);
-
- if (STOPPED_BY_WATCHPOINT (w))
- {
- write_pc (stop_pc - DECR_PC_AFTER_BREAK);
-
- remove_breakpoints ();
- target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */
-
- if (target_wait_hook)
- target_wait_hook (pid, &w);
- else
- target_wait (pid, &w);
- insert_breakpoints ();
- }
-
switch (w.kind)
{
case TARGET_WAITKIND_LOADED:
@@ -587,6 +571,10 @@ wait_for_inferior ()
break;
}
+ stop_signal = w.value.sig;
+
+ stop_pc = read_pc_pid (pid);
+
/* See if a thread hit a thread-specific breakpoint that was meant for
another thread. If so, then step that thread past the breakpoint,
and continue it. */
@@ -599,7 +587,7 @@ wait_for_inferior ()
if (!breakpoint_thread_match (stop_pc - DECR_PC_AFTER_BREAK, pid))
{
/* Saw a breakpoint, but it was hit by the wrong thread. Just continue. */
- write_pc (stop_pc - DECR_PC_AFTER_BREAK);
+ write_pc_pid (stop_pc - DECR_PC_AFTER_BREAK, pid);
remove_breakpoints ();
target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */
@@ -611,7 +599,9 @@ wait_for_inferior ()
else
target_wait (pid, &w);
insert_breakpoints ();
- target_resume (pid, 0, TARGET_SIGNAL_0);
+
+ /* We need to restart all the threads now. */
+ target_resume (-1, 0, TARGET_SIGNAL_0);
continue;
}
}
@@ -703,6 +693,60 @@ wait_for_inferior ()
continue;
}
+#ifdef HAVE_STEPPABLE_WATCHPOINT
+ /* It may not be necessary to disable the watchpoint to stop over
+ it. For example, the PA can (with some kernel cooperation)
+ single step over a watchpoint without disabling the watchpoint. */
+ if (STOPPED_BY_WATCHPOINT (w))
+ {
+ resume (1, 0);
+ continue;
+ }
+#endif
+
+#ifdef HAVE_NONSTEPPABLE_WATCHPOINT
+ /* It is far more common to need to disable a watchpoint
+ to step the inferior over it. FIXME. What else might
+ a debug register or page protection watchpoint scheme need
+ here? */
+ if (STOPPED_BY_WATCHPOINT (w))
+ {
+/* At this point, we are stopped at an instruction which has attempted to write
+ to a piece of memory under control of a watchpoint. The instruction hasn't
+ actually executed yet. If we were to evaluate the watchpoint expression
+ now, we would get the old value, and therefore no change would seem to have
+ occurred.
+
+ In order to make watchpoints work `right', we really need to complete the
+ memory write, and then evaluate the watchpoint expression. The following
+ code does that by removing the watchpoint (actually, all watchpoints and
+ breakpoints), single-stepping the target, re-inserting watchpoints, and then
+ falling through to let normal single-step processing handle proceed. Since
+ this includes evaluating watchpoints, things will come to a stop in the
+ correct manner. */
+
+ write_pc (stop_pc - DECR_PC_AFTER_BREAK);
+
+ remove_breakpoints ();
+ target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */
+
+ if (target_wait_hook)
+ target_wait_hook (pid, &w);
+ else
+ target_wait (pid, &w);
+ insert_breakpoints ();
+ /* FIXME-maybe: is this cleaner than setting a flag? Does it
+ handle things like signals arriving and other things happening
+ in combination correctly? */
+ goto have_waited;
+ }
+#endif
+
+#ifdef HAVE_CONTINUABLE_WATCHPOINT
+ /* It may be possible to simply continue after a watchpoint. */
+ STOPPED_BY_WATCHPOINT (w);
+#endif
+
stop_func_start = 0;
stop_func_name = 0;
/* Don't care about return value; stop_func_start and stop_func_name
diff --git a/gdb/lynx-nat.c b/gdb/lynx-nat.c
index f0e817e..1ab9cc7 100644
--- a/gdb/lynx-nat.c
+++ b/gdb/lynx-nat.c
@@ -705,14 +705,16 @@ child_resume (pid, step, signal)
errno = 0;
+ /* If pid == -1, then we want to step/continue all threads, else
+ we only want to step/continue a single thread. */
if (pid == -1)
{
- /* Resume all threads. */
-
pid = inferior_pid;
+ func = step ? PTRACE_SINGLESTEP : PTRACE_CONT;
}
+ else
+ func = step ? PTRACE_SINGLESTEP_ONE : PTRACE_CONT_ONE;
- func = step ? PTRACE_SINGLESTEP_ONE : PTRACE_CONT;
/* An address of (PTRACE_ARG3_TYPE)1 tells ptrace to continue from where
it was. (If GDB wanted it to start some other way, we have already