gdb/
[deliverable/binutils-gdb.git] / gdb / linux-nat.c
index eadbbc0f2e466fff856b1798a5b5bae1068fc789..ef0837bd3381a248bcae2c9d9afd5e6ba76dbc45 100644 (file)
@@ -200,35 +200,6 @@ show_debug_linux_nat (struct ui_file *file, int from_tty,
                    value);
 }
 
-static int disable_randomization = 1;
-
-static void
-show_disable_randomization (struct ui_file *file, int from_tty,
-                           struct cmd_list_element *c, const char *value)
-{
-#ifdef HAVE_PERSONALITY
-  fprintf_filtered (file,
-                   _("Disabling randomization of debuggee's "
-                     "virtual address space is %s.\n"),
-                   value);
-#else /* !HAVE_PERSONALITY */
-  fputs_filtered (_("Disabling randomization of debuggee's "
-                   "virtual address space is unsupported on\n"
-                   "this platform.\n"), file);
-#endif /* !HAVE_PERSONALITY */
-}
-
-static void
-set_disable_randomization (char *args, int from_tty,
-                          struct cmd_list_element *c)
-{
-#ifndef HAVE_PERSONALITY
-  error (_("Disabling randomization of debuggee's "
-          "virtual address space is unsupported on\n"
-          "this platform."));
-#endif /* !HAVE_PERSONALITY */
-}
-
 struct simple_pid_list
 {
   int pid;
@@ -701,6 +672,7 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
          add_thread (inferior_ptid);
          child_lp = add_lwp (inferior_ptid);
          child_lp->stopped = 1;
+         child_lp->last_resume_kind = resume_stop;
 
          /* If this is a vfork child, then the address-space is
             shared with the parent.  */
@@ -891,6 +863,7 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
       add_thread (inferior_ptid);
       child_lp = add_lwp (inferior_ptid);
       child_lp->stopped = 1;
+      child_lp->last_resume_kind = resume_stop;
 
       /* If this is a vfork child, then the address-space is shared
         with the parent.  If we detached from the parent, then we can
@@ -1158,6 +1131,7 @@ add_lwp (ptid_t ptid)
 
   memset (lp, 0, sizeof (struct lwp_info));
 
+  lp->last_resume_kind = resume_continue;
   lp->waitstatus.kind = TARGET_WAITKIND_IGNORE;
 
   lp->ptid = ptid;
@@ -1515,6 +1489,7 @@ lin_lwp_attach_lwp (ptid_t ptid)
       lp->stopped = 1;
     }
 
+  lp->last_resume_kind = resume_stop;
   restore_child_signals_mask (&prev_mask);
   return 0;
 }
@@ -1829,46 +1804,61 @@ linux_nat_detach (struct target_ops *ops, char *args, int from_tty)
 
 /* Resume LP.  */
 
-static int
-resume_callback (struct lwp_info *lp, void *data)
+static void
+resume_lwp (struct lwp_info *lp, int step)
 {
-  struct inferior *inf = find_inferior_pid (GET_PID (lp->ptid));
-
-  if (lp->stopped && inf->vfork_child != NULL)
+  if (lp->stopped)
     {
-      if (debug_linux_nat)
-       fprintf_unfiltered (gdb_stdlog,
-                           "RC: Not resuming %s (vfork parent)\n",
-                           target_pid_to_str (lp->ptid));
+      struct inferior *inf = find_inferior_pid (GET_PID (lp->ptid));
+
+      if (inf->vfork_child != NULL)
+       {
+         if (debug_linux_nat)
+           fprintf_unfiltered (gdb_stdlog,
+                               "RC: Not resuming %s (vfork parent)\n",
+                               target_pid_to_str (lp->ptid));
+       }
+      else if (lp->status == 0
+              && lp->waitstatus.kind == TARGET_WAITKIND_IGNORE)
+       {
+         if (debug_linux_nat)
+           fprintf_unfiltered (gdb_stdlog,
+                               "RC:  PTRACE_CONT %s, 0, 0 (resuming sibling)\n",
+                               target_pid_to_str (lp->ptid));
+
+         linux_ops->to_resume (linux_ops,
+                               pid_to_ptid (GET_LWP (lp->ptid)),
+                               step, TARGET_SIGNAL_0);
+         if (debug_linux_nat)
+           fprintf_unfiltered (gdb_stdlog,
+                               "RC:  PTRACE_CONT %s, 0, 0 (resume sibling)\n",
+                               target_pid_to_str (lp->ptid));
+         lp->stopped = 0;
+         lp->step = step;
+         memset (&lp->siginfo, 0, sizeof (lp->siginfo));
+         lp->stopped_by_watchpoint = 0;
+       }
+      else
+       {
+         if (debug_linux_nat)
+           fprintf_unfiltered (gdb_stdlog,
+                               "RC: Not resuming sibling %s (has pending)\n",
+                               target_pid_to_str (lp->ptid));
+       }
     }
-  else if (lp->stopped && lp->status == 0)
+  else
     {
       if (debug_linux_nat)
        fprintf_unfiltered (gdb_stdlog,
-                           "RC:  PTRACE_CONT %s, 0, 0 (resuming sibling)\n",
-                           target_pid_to_str (lp->ptid));
-
-      linux_ops->to_resume (linux_ops,
-                           pid_to_ptid (GET_LWP (lp->ptid)),
-                           0, TARGET_SIGNAL_0);
-      if (debug_linux_nat)
-       fprintf_unfiltered (gdb_stdlog,
-                           "RC:  PTRACE_CONT %s, 0, 0 (resume sibling)\n",
+                           "RC: Not resuming sibling %s (not stopped)\n",
                            target_pid_to_str (lp->ptid));
-      lp->stopped = 0;
-      lp->step = 0;
-      memset (&lp->siginfo, 0, sizeof (lp->siginfo));
-      lp->stopped_by_watchpoint = 0;
     }
-  else if (lp->stopped && debug_linux_nat)
-    fprintf_unfiltered (gdb_stdlog,
-                       "RC: Not resuming sibling %s (has pending)\n",
-                       target_pid_to_str (lp->ptid));
-  else if (debug_linux_nat)
-    fprintf_unfiltered (gdb_stdlog,
-                       "RC: Not resuming sibling %s (not stopped)\n",
-                       target_pid_to_str (lp->ptid));
+}
 
+static int
+resume_callback (struct lwp_info *lp, void *data)
+{
+  resume_lwp (lp, 0);
   return 0;
 }
 
@@ -1876,6 +1866,7 @@ static int
 resume_clear_callback (struct lwp_info *lp, void *data)
 {
   lp->resumed = 0;
+  lp->last_resume_kind = resume_stop;
   return 0;
 }
 
@@ -1883,6 +1874,7 @@ static int
 resume_set_callback (struct lwp_info *lp, void *data)
 {
   lp->resumed = 1;
+  lp->last_resume_kind = resume_continue;
   return 0;
 }
 
@@ -1922,6 +1914,7 @@ linux_nat_resume (struct target_ops *ops,
 
   /* Remember if we're stepping.  */
   lp->step = step;
+  lp->last_resume_kind = step ? resume_step : resume_continue;
 
   /* If we have a pending wait status for this thread, there is no
      point in resuming the process.  But first make sure that
@@ -2286,6 +2279,7 @@ linux_handle_extended_wait (struct lwp_info *lp, int status,
 
              new_lp->stopped = 0;
              new_lp->resumed = 1;
+             new_lp->last_resume_kind = resume_continue;
 
              signo = (status
                       ? target_signal_from_host (WSTOPSIG (status))
@@ -2918,7 +2912,10 @@ status_callback (struct lwp_info *lp, void *data)
 static int
 running_callback (struct lwp_info *lp, void *data)
 {
-  return (lp->stopped == 0 || (lp->status != 0 && lp->resumed));
+  return (!lp->stopped
+         || ((lp->status != 0
+              || lp->waitstatus.kind != TARGET_WAITKIND_IGNORE)
+             && lp->resumed));
 }
 
 /* Count the LWP's that have had events.  */
@@ -2942,7 +2939,8 @@ count_events_callback (struct lwp_info *lp, void *data)
 static int
 select_singlestep_lwp_callback (struct lwp_info *lp, void *data)
 {
-  if (lp->step && lp->status != 0)
+  if (lp->last_resume_kind == resume_step
+      && lp->status != 0)
     return 1;
   else
     return 0;
@@ -3094,19 +3092,22 @@ resumed_callback (struct lwp_info *lp, void *data)
 static int
 stop_and_resume_callback (struct lwp_info *lp, void *data)
 {
-  struct lwp_info *ptr;
-
-  if (!lp->stopped && !lp->signalled)
+  if (!lp->stopped)
     {
+      enum resume_kind last_resume_kind = lp->last_resume_kind;
+      ptid_t ptid = lp->ptid;
+
       stop_callback (lp, NULL);
       stop_wait_callback (lp, NULL);
-      /* Resume if the lwp still exists.  */
-      for (ptr = lwp_list; ptr; ptr = ptr->next)
-       if (lp == ptr)
-         {
-           resume_callback (lp, NULL);
-           resume_set_callback (lp, NULL);
-         }
+
+      /* Resume if the lwp still exists, and the core wanted it
+        running.  */
+      if (last_resume_kind != resume_stop)
+       {
+         lp = find_lwp_pid (ptid);
+         if (lp)
+           resume_lwp (lp, lp->step);
+       }
     }
   return 0;
 }
@@ -3267,25 +3268,29 @@ linux_nat_filter_event (int lwpid, int status, int options)
                            "LLW: Delayed SIGSTOP caught for %s.\n",
                            target_pid_to_str (lp->ptid));
 
-      /* This is a delayed SIGSTOP.  */
       lp->signalled = 0;
 
-      registers_changed ();
+      if (lp->last_resume_kind != resume_stop)
+       {
+         /* This is a delayed SIGSTOP.  */
 
-      linux_ops->to_resume (linux_ops, pid_to_ptid (GET_LWP (lp->ptid)),
+         registers_changed ();
+
+         linux_ops->to_resume (linux_ops, pid_to_ptid (GET_LWP (lp->ptid)),
                            lp->step, TARGET_SIGNAL_0);
-      if (debug_linux_nat)
-       fprintf_unfiltered (gdb_stdlog,
-                           "LLW: %s %s, 0, 0 (discard SIGSTOP)\n",
-                           lp->step ?
-                           "PTRACE_SINGLESTEP" : "PTRACE_CONT",
-                           target_pid_to_str (lp->ptid));
+         if (debug_linux_nat)
+           fprintf_unfiltered (gdb_stdlog,
+                               "LLW: %s %s, 0, 0 (discard SIGSTOP)\n",
+                               lp->step ?
+                               "PTRACE_SINGLESTEP" : "PTRACE_CONT",
+                               target_pid_to_str (lp->ptid));
 
-      lp->stopped = 0;
-      gdb_assert (lp->resumed);
+         lp->stopped = 0;
+         gdb_assert (lp->resumed);
 
-      /* Discard the event.  */
-      return NULL;
+         /* Discard the event.  */
+         return NULL;
+       }
     }
 
   /* Make sure we don't report a SIGINT that we have already displayed
@@ -3435,7 +3440,7 @@ retry:
        lp = NULL;
     }
 
-  if (lp && lp->signalled)
+  if (lp && lp->signalled && lp->last_resume_kind != resume_stop)
     {
       /* A pending SIGSTOP may interfere with the normal stream of
          events.  In a typical case where interference is a problem,
@@ -3747,7 +3752,10 @@ retry:
       iterate_over_lwps (minus_one_ptid, resume_clear_callback, NULL);
     }
   else
-    lp->resumed = 0;
+    {
+      lp->resumed = 0;
+      lp->last_resume_kind = resume_stop;
+    }
 
   if (linux_nat_status_is_event (status))
     {
@@ -3770,6 +3778,16 @@ retry:
 
   restore_child_signals_mask (&prev_mask);
 
+  if (lp->last_resume_kind == resume_stop
+      && ourstatus->kind == TARGET_WAITKIND_STOPPED
+      && WSTOPSIG (status) == SIGSTOP)
+    {
+      /* A thread that has been requested to stop by GDB with
+        target_stop, and it stopped cleanly, so report as SIG0.  The
+        use of SIGSTOP is an implementation detail.  */
+      ourstatus->value.sig = TARGET_SIGNAL_0;
+    }
+
   if (ourstatus->kind == TARGET_WAITKIND_EXITED
       || ourstatus->kind == TARGET_WAITKIND_SIGNALLED)
     lp->core = -1;
@@ -5261,6 +5279,16 @@ linux_nat_supports_multi_process (void)
   return linux_multi_process;
 }
 
+static int
+linux_nat_supports_disable_randomization (void)
+{
+#ifdef HAVE_PERSONALITY
+  return 1;
+#else
+  return 0;
+#endif
+}
+
 static int async_terminal_is_ours = 1;
 
 /* target_terminal_inferior implementation.  */
@@ -5426,22 +5454,18 @@ linux_nat_stop_lwp (struct lwp_info *lwp, void *data)
                            target_pid_to_str (lwp->ptid));
 
 
-      stop_callback (lwp, NULL);
-      stop_wait_callback (lwp, NULL);
-
-      /* If the lwp exits while we try to stop it, there's nothing
-        else to do.  */
-      lwp = find_lwp_pid (ptid);
-      if (lwp == NULL)
-       return 0;
+      if (lwp->last_resume_kind == resume_stop)
+       {
+         if (debug_linux_nat)
+           fprintf_unfiltered (gdb_stdlog,
+                               "linux-nat: already stopping LWP %ld at "
+                               "GDB's request\n",
+                               ptid_get_lwp (lwp->ptid));
+         return 0;
+       }
 
-      /* If we didn't collect any signal other than SIGSTOP while
-        stopping the LWP, push a SIGNAL_0 event.  In either case, the
-        event-loop will end up calling target_wait which will collect
-        these.  */
-      if (lwp->status == 0)
-       lwp->status = W_STOPCODE (0);
-      async_file_mark ();
+      stop_callback (lwp, NULL);
+      lwp->last_resume_kind = resume_stop;
     }
   else
     {
@@ -5634,6 +5658,9 @@ linux_nat_add_target (struct target_ops *t)
 
   t->to_supports_multi_process = linux_nat_supports_multi_process;
 
+  t->to_supports_disable_randomization
+    = linux_nat_supports_disable_randomization;
+
   t->to_core_of_thread = linux_nat_core_of_thread;
 
   /* We don't change the stratum; this target will sit at
@@ -5719,17 +5746,6 @@ Enables printf debugging output."),
   sigdelset (&suspend_mask, SIGCHLD);
 
   sigemptyset (&blocked_mask);
-
-  add_setshow_boolean_cmd ("disable-randomization", class_support,
-                          &disable_randomization, _("\
-Set disabling of debuggee's virtual address space randomization."), _("\
-Show disabling of debuggee's virtual address space randomization."), _("\
-When this mode is on (which is the default), randomization of the virtual\n\
-address space is disabled.  Standalone programs run with the randomization\n\
-enabled by default on some platforms."),
-                          &set_disable_randomization,
-                          &show_disable_randomization,
-                          &setlist, &showlist);
 }
 \f
 
This page took 0.030686 seconds and 4 git commands to generate.