*** empty log message ***
[binutils-gdb.git] / gdb / linux-nat.c
index a659afa7b643061125ab854186480259ffb8cbf3..fc9dafec21d1c22ba4eb69843e1bd52e1f328a8b 100644 (file)
@@ -376,7 +376,7 @@ add_to_pid_list (struct simple_pid_list **listp, int pid, int status)
 }
 
 static int
-pull_pid_from_list (struct simple_pid_list **listp, int pid, int *status)
+pull_pid_from_list (struct simple_pid_list **listp, int pid, int *statusp)
 {
   struct simple_pid_list **p;
 
@@ -385,7 +385,7 @@ pull_pid_from_list (struct simple_pid_list **listp, int pid, int *status)
       {
        struct simple_pid_list *next = (*p)->next;
 
-       *status = (*p)->status;
+       *statusp = (*p)->status;
        xfree (*p);
        *p = next;
        return 1;
@@ -414,13 +414,13 @@ linux_tracefork_child (void)
 /* Wrapper function for waitpid which handles EINTR.  */
 
 static int
-my_waitpid (int pid, int *status, int flags)
+my_waitpid (int pid, int *statusp, int flags)
 {
   int ret;
 
   do
     {
-      ret = waitpid (pid, status, flags);
+      ret = waitpid (pid, statusp, flags);
     }
   while (ret == -1 && errno == EINTR);
 
@@ -1073,7 +1073,6 @@ restore_child_signals_mask (sigset_t *prev_mask)
 static int stop_wait_callback (struct lwp_info *lp, void *data);
 static int linux_thread_alive (ptid_t ptid);
 static char *linux_child_pid_to_exec_file (int pid);
-static int cancel_breakpoint (struct lwp_info *lp);
 
 \f
 /* Convert wait status STATUS to a string.  Used for printing debug
@@ -1095,7 +1094,7 @@ status_to_str (int status)
     }
   else if (WIFSIGNALED (status))
     snprintf (buf, sizeof (buf), "%s (terminated)",
-             strsignal (WSTOPSIG (status)));
+             strsignal (WTERMSIG (status)));
   else
     snprintf (buf, sizeof (buf), "%d (exited)", WEXITSTATUS (status));
 
@@ -2279,6 +2278,23 @@ linux_handle_extended_wait (struct lwp_info *lp, int status,
              linux_ops->to_resume (linux_ops, pid_to_ptid (new_pid),
                                    0, signo);
            }
+         else
+           {
+             if (status != 0)
+               {
+                 /* We created NEW_LP so it cannot yet contain STATUS.  */
+                 gdb_assert (new_lp->status == 0);
+
+                 /* Save the wait status to report later.  */
+                 if (debug_linux_nat)
+                   fprintf_unfiltered (gdb_stdlog,
+                                       "LHEW: waitpid of new LWP %ld, "
+                                       "saving status %s\n",
+                                       (long) GET_LWP (new_lp->ptid),
+                                       status_to_str (status));
+                 new_lp->status = status;
+               }
+           }
 
          if (debug_linux_nat)
            fprintf_unfiltered (gdb_stdlog,
@@ -2589,6 +2605,43 @@ linux_nat_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
   return lp->stopped_data_address_p;
 }
 
+/* Commonly any breakpoint / watchpoint generate only SIGTRAP.  */
+
+static int
+sigtrap_is_event (int status)
+{
+  return WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP;
+}
+
+/* SIGTRAP-like events recognizer.  */
+
+static int (*linux_nat_status_is_event) (int status) = sigtrap_is_event;
+
+/* Check for SIGTRAP-like events in LP.  */
+
+static int
+linux_nat_lp_status_is_event (struct lwp_info *lp)
+{
+  /* We check for lp->waitstatus in addition to lp->status, because we can
+     have pending process exits recorded in lp->status
+     and W_EXITCODE(0,0) == 0.  We should probably have an additional
+     lp->status_p flag.  */
+
+  return (lp->waitstatus.kind == TARGET_WAITKIND_IGNORE
+         && linux_nat_status_is_event (lp->status));
+}
+
+/* Set alternative SIGTRAP-like events recognizer.  If
+   breakpoint_inserted_here_p there then gdbarch_decr_pc_after_break will be
+   applied.  */
+
+void
+linux_nat_set_status_is_event (struct target_ops *t,
+                              int (*status_is_event) (int status))
+{
+  linux_nat_status_is_event = status_is_event;
+}
+
 /* Wait until LP is stopped.  */
 
 static int
@@ -2629,7 +2682,7 @@ stop_wait_callback (struct lwp_info *lp, void *data)
 
       if (WSTOPSIG (status) != SIGSTOP)
        {
-         if (WSTOPSIG (status) == SIGTRAP)
+         if (linux_nat_status_is_event (status))
            {
              /* If a LWP other than the LWP that we're reporting an
                 event for has hit a GDB breakpoint (as opposed to
@@ -2784,8 +2837,7 @@ count_events_callback (struct lwp_info *lp, void *data)
   gdb_assert (count != NULL);
 
   /* Count only resumed LWPs that have a SIGTRAP event pending.  */
-  if (lp->status != 0 && lp->resumed
-      && WIFSTOPPED (lp->status) && WSTOPSIG (lp->status) == SIGTRAP)
+  if (lp->resumed && linux_nat_lp_status_is_event (lp))
     (*count)++;
 
   return 0;
@@ -2812,8 +2864,7 @@ select_event_lwp_callback (struct lwp_info *lp, void *data)
   gdb_assert (selector != NULL);
 
   /* Select only resumed LWPs that have a SIGTRAP event pending. */
-  if (lp->status != 0 && lp->resumed
-      && WIFSTOPPED (lp->status) && WSTOPSIG (lp->status) == SIGTRAP)
+  if (lp->resumed && linux_nat_lp_status_is_event (lp))
     if ((*selector)-- == 0)
       return 1;
 
@@ -2873,9 +2924,7 @@ cancel_breakpoints_callback (struct lwp_info *lp, void *data)
      delete or disable the breakpoint, but the LWP will have already
      tripped on it.  */
 
-  if (lp->waitstatus.kind == TARGET_WAITKIND_IGNORE
-      && lp->status != 0
-      && WIFSTOPPED (lp->status) && WSTOPSIG (lp->status) == SIGTRAP
+  if (linux_nat_lp_status_is_event (lp)
       && cancel_breakpoint (lp))
     /* Throw away the SIGTRAP.  */
     lp->status = 0;
@@ -3048,7 +3097,7 @@ linux_nat_filter_event (int lwpid, int status, int options)
        return NULL;
     }
 
-  if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP)
+  if (linux_nat_status_is_event (status))
     {
       /* Save the trap's siginfo in case we need it later.  */
       save_siginfo (lp);
@@ -3367,6 +3416,9 @@ retry:
 
          lp = linux_nat_filter_event (lwpid, status, options);
 
+         /* STATUS is now no longer valid, use LP->STATUS instead.  */
+         status = 0;
+
          if (lp
              && ptid_is_pid (ptid)
              && ptid_get_pid (lp->ptid) != ptid_get_pid (ptid))
@@ -3375,7 +3427,7 @@ retry:
 
              if (debug_linux_nat)
                fprintf (stderr, "LWP %ld got an event %06x, leaving pending.\n",
-                        ptid_get_lwp (lp->ptid), status);
+                        ptid_get_lwp (lp->ptid), lp->status);
 
              if (WIFSTOPPED (lp->status))
                {
@@ -3391,8 +3443,7 @@ retry:
                         always cancels breakpoint hits in all
                         threads.  */
                      if (non_stop
-                         && lp->waitstatus.kind == TARGET_WAITKIND_IGNORE
-                         && WSTOPSIG (lp->status) == SIGTRAP
+                         && linux_nat_lp_status_is_event (lp)
                          && cancel_breakpoint (lp))
                        {
                          /* Throw away the SIGTRAP.  */
@@ -3412,7 +3463,7 @@ retry:
                      lp->signalled = 0;
                    }
                }
-             else if (WIFEXITED (status) || WIFSIGNALED (status))
+             else if (WIFEXITED (lp->status) || WIFSIGNALED (lp->status))
                {
                  if (debug_linux_nat)
                    fprintf (stderr, "Process %ld exited while stopping LWPs\n",
@@ -3608,7 +3659,7 @@ retry:
   else
     lp->resumed = 0;
 
-  if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP)
+  if (linux_nat_status_is_event (status))
     {
       if (debug_linux_nat)
        fprintf_unfiltered (gdb_stdlog,
@@ -4053,9 +4104,7 @@ read_mapping (FILE *mapfile,
    regions in the inferior for a corefile.  */
 
 static int
-linux_nat_find_memory_regions (int (*func) (CORE_ADDR,
-                                           unsigned long,
-                                           int, int, int, void *), void *obfd)
+linux_nat_find_memory_regions (find_memory_region_ftype func, void *obfd)
 {
   int pid = PIDGET (inferior_ptid);
   char mapsfilename[MAXPATHLEN];
@@ -4171,7 +4220,8 @@ linux_nat_do_thread_registers (bfd *obfd, ptid_t ptid,
        if (strcmp (sect_list->sect_name, ".reg") == 0)
          note_data = (char *) elfcore_write_prstatus
                                (obfd, note_data, note_size,
-                                lwp, stop_signal, gdb_regset);
+                                lwp, target_signal_to_host (stop_signal),
+                                gdb_regset);
        else
          note_data = (char *) elfcore_write_register_note
                                (obfd, note_data, note_size,
@@ -4198,11 +4248,9 @@ linux_nat_do_thread_registers (bfd *obfd, ptid_t ptid,
       else
        fill_gregset (regcache, &gregs, -1);
 
-      note_data = (char *) elfcore_write_prstatus (obfd,
-                                                  note_data,
-                                                  note_size,
-                                                  lwp,
-                                                  stop_signal, &gregs);
+      note_data = (char *) elfcore_write_prstatus
+       (obfd, note_data, note_size, lwp, target_signal_to_host (stop_signal),
+        &gregs);
 
       if (core_regset_p
           && (regset = gdbarch_regset_from_core_section (gdbarch, ".reg2",