]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
* infrun.c (wait_for_inferior): When we hit a breakpoint for the
authorJeff Law <law@redhat.com>
Tue, 4 Jul 1995 17:40:41 +0000 (17:40 +0000)
committerJeff Law <law@redhat.com>
Tue, 4 Jul 1995 17:40:41 +0000 (17:40 +0000)
        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.

Some of the lynx-6100 single stepping fixes.

gdb/ChangeLog
gdb/infrun.c
gdb/lynx-nat.c

index 1e096fbb6e0081c424c3aa83b50c48c93b1a8980..2ff3c3f8aa51aa0e6d437c75263b3b40fb821b98 100644 (file)
@@ -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.
index cd6962984e09dd57f334f341a9f71ac6cc5da285..5ad2bfc45dbf47159f80bf40c3b61d25312ab2ba 100644 (file)
@@ -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
index f0e817e5653267b504134b6774e343bb44f7a693..1ab9cc7cc678934703198962e27f82df4c7af48c 100644 (file)
@@ -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