* gas/nios2/nios2.exp: Add copyright.
[deliverable/binutils-gdb.git] / gdb / linux-nat.c
index 33b13fad5bae8f6dc52a2d221f663257270f2a6b..57bca111119eeeee9763d39ecd78d320baec5945 100644 (file)
@@ -1,6 +1,6 @@
 /* GNU/Linux native-dependent code common to multiple platforms.
 
-   Copyright (C) 2001-2012 Free Software Foundation, Inc.
+   Copyright (C) 2001-2013 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -66,6 +66,7 @@
 #include "exceptions.h"
 #include "linux-ptrace.h"
 #include "buffer.h"
+#include "target-descriptions.h"
 
 #ifndef SPUFS_MAGIC
 #define SPUFS_MAGIC 0x23c9b64e
@@ -201,7 +202,7 @@ static LONGEST (*super_xfer_partial) (struct target_ops *,
                                      const gdb_byte *,
                                      ULONGEST, LONGEST);
 
-static int debug_linux_nat;
+static unsigned int debug_linux_nat;
 static void
 show_debug_linux_nat (struct ui_file *file, int from_tty,
                      struct cmd_list_element *c, const char *value)
@@ -583,6 +584,7 @@ linux_child_post_attach (int pid)
 {
   linux_enable_event_reporting (pid_to_ptid (pid));
   linux_enable_tracesysgood (pid_to_ptid (pid));
+  linux_ptrace_init_warnings ();
 }
 
 static void
@@ -590,6 +592,7 @@ linux_child_post_startup_inferior (ptid_t ptid)
 {
   linux_enable_event_reporting (ptid);
   linux_enable_tracesysgood (ptid);
+  linux_ptrace_init_warnings ();
 }
 
 /* Return the number of known LWPs in the tgid given by PID.  */
@@ -721,6 +724,8 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
          parent_inf = current_inferior ();
          child_inf->attach_flag = parent_inf->attach_flag;
          copy_terminal_info (child_inf, parent_inf);
+         child_inf->gdbarch = parent_inf->gdbarch;
+         copy_inferior_target_desc_info (child_inf, parent_inf);
 
          old_chain = save_inferior_ptid ();
          save_current_program_space ();
@@ -885,6 +890,8 @@ holding the child stopped.  Try \"set detach-on-fork\" or \
       parent_inf = current_inferior ();
       child_inf->attach_flag = parent_inf->attach_flag;
       copy_terminal_info (child_inf, parent_inf);
+      child_inf->gdbarch = parent_inf->gdbarch;
+      copy_inferior_target_desc_info (child_inf, parent_inf);
 
       parent_pspace = parent_inf->pspace;
 
@@ -1305,7 +1312,6 @@ linux_nat_iterate_watchpoint_lwps
       pid_t child_pid = GET_PID (inferior_ptid);
       ptid_t child_ptid = ptid_build (child_pid, child_pid, 0);
 
-      gdb_assert (!is_lwp (inferior_ptid));
       gdb_assert (find_lwp_pid (child_ptid) == NULL);
       child_lp = add_lwp (child_ptid);
       child_lp->stopped = 1;
@@ -1846,8 +1852,8 @@ linux_nat_detach (struct target_ops *ops, char *args, int from_tty)
 
   pid = GET_PID (inferior_ptid);
 
-  if (target_can_async_p ())
-    linux_nat_async (NULL, 0);
+  /* Don't unregister from the event loop, as there may be other
+     inferiors running. */
 
   /* Stop all threads before detaching.  ptrace requires that the
      thread is stopped to sucessfully detach.  */
@@ -1890,9 +1896,6 @@ linux_nat_detach (struct target_ops *ops, char *args, int from_tty)
         the current fork, and context-switch to the first
         available.  */
       linux_fork_detach (args, from_tty);
-
-      if (non_stop && target_can_async_p ())
-       target_async (inferior_event_handler, 0);
     }
   else
     linux_ops->to_detach (ops, args, from_tty);
@@ -1901,7 +1904,7 @@ linux_nat_detach (struct target_ops *ops, char *args, int from_tty)
 /* Resume LP.  */
 
 static void
-resume_lwp (struct lwp_info *lp, int step)
+resume_lwp (struct lwp_info *lp, int step, enum gdb_signal signo)
 {
   if (lp->stopped)
     {
@@ -1919,17 +1922,20 @@ resume_lwp (struct lwp_info *lp, int step)
        {
          if (debug_linux_nat)
            fprintf_unfiltered (gdb_stdlog,
-                               "RC:  PTRACE_CONT %s, 0, 0 (resuming sibling)\n",
-                               target_pid_to_str (lp->ptid));
+                               "RC: Resuming sibling %s, %s, %s\n",
+                               target_pid_to_str (lp->ptid),
+                               (signo != GDB_SIGNAL_0
+                                ? strsignal (gdb_signal_to_host (signo))
+                                : "0"),
+                               step ? "step" : "resume");
 
          if (linux_nat_prepare_to_resume != NULL)
            linux_nat_prepare_to_resume (lp);
          linux_ops->to_resume (linux_ops,
                                pid_to_ptid (GET_LWP (lp->ptid)),
-                               step, GDB_SIGNAL_0);
+                               step, signo);
          lp->stopped = 0;
          lp->step = step;
-         memset (&lp->siginfo, 0, sizeof (lp->siginfo));
          lp->stopped_by_watchpoint = 0;
        }
       else
@@ -1949,10 +1955,27 @@ resume_lwp (struct lwp_info *lp, int step)
     }
 }
 
+/* Resume LWP, with the last stop signal, if it is in pass state.  */
+
 static int
-resume_callback (struct lwp_info *lp, void *data)
+linux_nat_resume_callback (struct lwp_info *lp, void *data)
 {
-  resume_lwp (lp, 0);
+  enum gdb_signal signo = GDB_SIGNAL_0;
+
+  if (lp->stopped)
+    {
+      struct thread_info *thread;
+
+      thread = find_thread_ptid (lp->ptid);
+      if (thread != NULL)
+       {
+         if (signal_pass_state (thread->suspend.stop_signal))
+           signo = thread->suspend.stop_signal;
+         thread->suspend.stop_signal = GDB_SIGNAL_0;
+       }
+    }
+
+  resume_lwp (lp, 0, signo);
   return 0;
 }
 
@@ -2059,11 +2082,11 @@ linux_nat_resume (struct target_ops *ops,
     }
 
   /* Mark LWP as not stopped to prevent it from being continued by
-     resume_callback.  */
+     linux_nat_resume_callback.  */
   lp->stopped = 0;
 
   if (resume_many)
-    iterate_over_lwps (ptid, resume_callback, NULL);
+    iterate_over_lwps (ptid, linux_nat_resume_callback, NULL);
 
   /* Convert to something the lower layer understands.  */
   ptid = pid_to_ptid (GET_LWP (lp->ptid));
@@ -2071,7 +2094,6 @@ linux_nat_resume (struct target_ops *ops,
   if (linux_nat_prepare_to_resume != NULL)
     linux_nat_prepare_to_resume (lp);
   linux_ops->to_resume (linux_ops, ptid, step, signo);
-  memset (&lp->siginfo, 0, sizeof (lp->siginfo));
   lp->stopped_by_watchpoint = 0;
 
   if (debug_linux_nat)
@@ -2296,7 +2318,7 @@ linux_handle_extended_wait (struct lwp_info *lp, int status,
 
          /* This won't actually modify the breakpoint list, but will
             physically remove the breakpoints from the child.  */
-         detach_breakpoints (new_pid);
+         detach_breakpoints (ptid_build (new_pid, new_pid, 0));
 
          /* Retain child fork in ptrace (stopped) state.  */
          if (!find_fork_pid (new_pid))
@@ -2625,22 +2647,6 @@ wait_lwp (struct lwp_info *lp)
   return status;
 }
 
-/* Save the most recent siginfo for LP.  This is currently only called
-   for SIGTRAP; some ports use the si_addr field for
-   target_stopped_data_address.  In the future, it may also be used to
-   restore the siginfo of requeued signals.  */
-
-static void
-save_siginfo (struct lwp_info *lp)
-{
-  errno = 0;
-  ptrace (PTRACE_GETSIGINFO, GET_LWP (lp->ptid),
-         (PTRACE_TYPE_ARG3) 0, &lp->siginfo);
-
-  if (errno != 0)
-    memset (&lp->siginfo, 0, sizeof (lp->siginfo));
-}
-
 /* Send a SIGSTOP to LP.  */
 
 static int
@@ -2881,110 +2887,36 @@ stop_wait_callback (struct lwp_info *lp, void *data)
 
       if (WSTOPSIG (status) != SIGSTOP)
        {
-         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
-                some random trap signal), then just arrange for it to
-                hit it again later.  We don't keep the SIGTRAP status
-                and don't forward the SIGTRAP signal to the LWP.  We
-                will handle the current event, eventually we will
-                resume all LWPs, and this one will get its breakpoint
-                trap again.
-
-                If we do not do this, then we run the risk that the
-                user will delete or disable the breakpoint, but the
-                thread will have already tripped on it.  */
-
-             /* Save the trap's siginfo in case we need it later.  */
-             save_siginfo (lp);
-
-             save_sigtrap (lp);
-
-             /* Now resume this LWP and get the SIGSTOP event.  */
-             errno = 0;
-             ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
-             if (debug_linux_nat)
-               {
-                 fprintf_unfiltered (gdb_stdlog,
-                                     "PTRACE_CONT %s, 0, 0 (%s)\n",
-                                     target_pid_to_str (lp->ptid),
-                                     errno ? safe_strerror (errno) : "OK");
-
-                 fprintf_unfiltered (gdb_stdlog,
-                                     "SWC: Candidate SIGTRAP event in %s\n",
-                                     target_pid_to_str (lp->ptid));
-               }
-             /* Hold this event/waitstatus while we check to see if
-                there are any more (we still want to get that SIGSTOP).  */
-             stop_wait_callback (lp, NULL);
-
-             /* Hold the SIGTRAP for handling by linux_nat_wait.  If
-                there's another event, throw it back into the
-                queue.  */
-             if (lp->status)
-               {
-                 if (debug_linux_nat)
-                   fprintf_unfiltered (gdb_stdlog,
-                                       "SWC: kill %s, %s\n",
-                                       target_pid_to_str (lp->ptid),
-                                       status_to_str ((int) status));
-                 kill_lwp (GET_LWP (lp->ptid), WSTOPSIG (lp->status));
-               }
+         /* The thread was stopped with a signal other than SIGSTOP.  */
 
-             /* Save the sigtrap event.  */
-             lp->status = status;
-             return 0;
-           }
-         else
-           {
-             /* The thread was stopped with a signal other than
-                SIGSTOP, and didn't accidentally trip a breakpoint.  */
+         save_sigtrap (lp);
 
-             if (debug_linux_nat)
-               {
-                 fprintf_unfiltered (gdb_stdlog,
-                                     "SWC: Pending event %s in %s\n",
-                                     status_to_str ((int) status),
-                                     target_pid_to_str (lp->ptid));
-               }
-             /* Now resume this LWP and get the SIGSTOP event.  */
-             errno = 0;
-             ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
-             if (debug_linux_nat)
-               fprintf_unfiltered (gdb_stdlog,
-                                   "SWC: PTRACE_CONT %s, 0, 0 (%s)\n",
-                                   target_pid_to_str (lp->ptid),
-                                   errno ? safe_strerror (errno) : "OK");
-
-             /* Hold this event/waitstatus while we check to see if
-                there are any more (we still want to get that SIGSTOP).  */
-             stop_wait_callback (lp, NULL);
-
-             /* If the lp->status field is still empty, use it to
-                hold this event.  If not, then this event must be
-                returned to the event queue of the LWP.  */
-             if (lp->status)
-               {
-                 if (debug_linux_nat)
-                   {
-                     fprintf_unfiltered (gdb_stdlog,
-                                         "SWC: kill %s, %s\n",
-                                         target_pid_to_str (lp->ptid),
-                                         status_to_str ((int) status));
-                   }
-                 kill_lwp (GET_LWP (lp->ptid), WSTOPSIG (status));
-               }
-             else
-               lp->status = status;
-             return 0;
-           }
+         if (debug_linux_nat)
+           fprintf_unfiltered (gdb_stdlog,
+                               "SWC: Pending event %s in %s\n",
+                               status_to_str ((int) status),
+                               target_pid_to_str (lp->ptid));
+
+         /* Save the sigtrap event.  */
+         lp->status = status;
+         gdb_assert (!lp->stopped);
+         gdb_assert (lp->signalled);
+         lp->stopped = 1;
        }
       else
        {
          /* We caught the SIGSTOP that we intended to catch, so
             there's no SIGSTOP pending.  */
+
+         if (debug_linux_nat)
+           fprintf_unfiltered (gdb_stdlog,
+                               "SWC: Delayed SIGSTOP caught for %s.\n",
+                               target_pid_to_str (lp->ptid));
+
          lp->stopped = 1;
+
+         /* Reset SIGNALLED only after the stop_wait_callback call
+            above as it does gdb_assert on SIGNALLED.  */
          lp->signalled = 0;
        }
     }
@@ -3238,7 +3170,7 @@ stop_and_resume_callback (struct lwp_info *lp, void *data)
                fprintf_unfiltered (gdb_stdlog,
                                    "SARC: re-resuming LWP %ld\n",
                                    GET_LWP (lp->ptid));
-             resume_lwp (lp, lp->step);
+             resume_lwp (lp, lp->step, GDB_SIGNAL_0);
            }
          else
            {
@@ -3334,12 +3266,7 @@ linux_nat_filter_event (int lwpid, int status, int *new_pending_p)
     }
 
   if (linux_nat_status_is_event (status))
-    {
-      /* Save the trap's siginfo in case we need it later.  */
-      save_siginfo (lp);
-
-      save_sigtrap (lp);
-    }
+    save_sigtrap (lp);
 
   /* Check if the thread has exited.  */
   if ((WIFEXITED (status) || WIFSIGNALED (status))
@@ -3612,54 +3539,6 @@ retry:
        lp = NULL;
     }
 
-  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,
-         we have a SIGSTOP signal pending for LWP A while
-         single-stepping it, encounter an event in LWP B, and take the
-         pending SIGSTOP while trying to stop LWP A.  After processing
-         the event in LWP B, LWP A is continued, and we'll never see
-         the SIGTRAP associated with the last time we were
-         single-stepping LWP A.  */
-
-      /* Resume the thread.  It should halt immediately returning the
-         pending SIGSTOP.  */
-      registers_changed ();
-      if (linux_nat_prepare_to_resume != NULL)
-       linux_nat_prepare_to_resume (lp);
-      linux_ops->to_resume (linux_ops, pid_to_ptid (GET_LWP (lp->ptid)),
-                           lp->step, GDB_SIGNAL_0);
-      if (debug_linux_nat)
-       fprintf_unfiltered (gdb_stdlog,
-                           "LLW: %s %s, 0, 0 (expect SIGSTOP)\n",
-                           lp->step ? "PTRACE_SINGLESTEP" : "PTRACE_CONT",
-                           target_pid_to_str (lp->ptid));
-      lp->stopped = 0;
-      gdb_assert (lp->resumed);
-
-      /* Catch the pending SIGSTOP.  */
-      status = lp->status;
-      lp->status = 0;
-
-      stop_wait_callback (lp, NULL);
-
-      /* If the lp->status field isn't empty, we caught another signal
-        while flushing the SIGSTOP.  Return it back to the event
-        queue of the LWP, as we already have an event to handle.  */
-      if (lp->status)
-       {
-         if (debug_linux_nat)
-           fprintf_unfiltered (gdb_stdlog,
-                               "LLW: kill %s, %s\n",
-                               target_pid_to_str (lp->ptid),
-                               status_to_str (lp->status));
-         kill_lwp (GET_LWP (lp->ptid), WSTOPSIG (lp->status));
-       }
-
-      lp->status = status;
-    }
-
   if (!target_can_async_p ())
     {
       /* Causes SIGINT to be passed on to the attached process.  */
@@ -4040,7 +3919,6 @@ resume_stopped_resumed_lwps (struct lwp_info *lp, void *data)
       linux_ops->to_resume (linux_ops, pid_to_ptid (GET_LWP (lp->ptid)),
                            lp->step, GDB_SIGNAL_0);
       lp->stopped = 0;
-      memset (&lp->siginfo, 0, sizeof (lp->siginfo));
       lp->stopped_by_watchpoint = 0;
     }
 
@@ -4055,8 +3933,16 @@ linux_nat_wait (struct target_ops *ops,
   ptid_t event_ptid;
 
   if (debug_linux_nat)
-    fprintf_unfiltered (gdb_stdlog,
-                       "linux_nat_wait: [%s]\n", target_pid_to_str (ptid));
+    {
+      char *options_string;
+
+      options_string = target_options_to_string (target_options);
+      fprintf_unfiltered (gdb_stdlog,
+                         "linux_nat_wait: [%s], [%s]\n",
+                         target_pid_to_str (ptid),
+                         options_string);
+      xfree (options_string);
+    }
 
   /* Flush the async file first.  */
   if (target_can_async_p ())
@@ -4433,7 +4319,7 @@ linux_child_pid_to_exec_file (int pid)
   memset (name2, 0, MAXPATHLEN);
 
   sprintf (name1, "/proc/%d/exe", pid);
-  if (readlink (name1, name2, MAXPATHLEN) > 0)
+  if (readlink (name1, name2, MAXPATHLEN - 1) > 0)
     return name2;
   else
     return name1;
@@ -4490,7 +4376,7 @@ linux_nat_make_corefile_notes (bfd *obfd, int *note_size)
 {
   /* FIXME: uweigand/2011-10-06: Once all GNU/Linux architectures have been
      converted to gdbarch_core_regset_sections, this function can go away.  */
-  return linux_make_corefile_notes (target_gdbarch, obfd, note_size,
+  return linux_make_corefile_notes (target_gdbarch (), obfd, note_size,
                                    linux_nat_collect_thread_registers);
 }
 
@@ -4545,7 +4431,7 @@ linux_proc_xfer_partial (struct target_ops *ops, enum target_object object,
 static LONGEST
 spu_enumerate_spu_ids (int pid, gdb_byte *buf, ULONGEST offset, LONGEST len)
 {
-  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
   LONGEST pos = 0;
   LONGEST written = 0;
   char path[128];
@@ -4754,7 +4640,7 @@ linux_xfer_partial (struct target_ops *ops, enum target_object object,
 
   if (object == TARGET_OBJECT_MEMORY)
     {
-      int addr_bit = gdbarch_addr_bit (target_gdbarch);
+      int addr_bit = gdbarch_addr_bit (target_gdbarch ());
 
       if (addr_bit < (sizeof (ULONGEST) * HOST_CHAR_BIT))
        offset &= ((ULONGEST) 1 << addr_bit) - 1;
@@ -5090,8 +4976,6 @@ linux_nat_stop_lwp (struct lwp_info *lwp, void *data)
 {
   if (!lwp->stopped)
     {
-      ptid_t ptid = lwp->ptid;
-
       if (debug_linux_nat)
        fprintf_unfiltered (gdb_stdlog,
                            "LNSL: running -> suspending %s\n",
@@ -5285,15 +5169,25 @@ linux_nat_set_prepare_to_resume (struct target_ops *t,
   linux_nat_prepare_to_resume = prepare_to_resume;
 }
 
-/* Return the saved siginfo associated with PTID.  */
-siginfo_t *
-linux_nat_get_siginfo (ptid_t ptid)
+/* See linux-nat.h.  */
+
+int
+linux_nat_get_siginfo (ptid_t ptid, siginfo_t *siginfo)
 {
-  struct lwp_info *lp = find_lwp_pid (ptid);
+  int pid;
 
-  gdb_assert (lp != NULL);
+  pid = GET_LWP (ptid);
+  if (pid == 0)
+    pid = GET_PID (ptid);
 
-  return &lp->siginfo;
+  errno = 0;
+  ptrace (PTRACE_GETSIGINFO, pid, (PTRACE_TYPE_ARG3) 0, siginfo);
+  if (errno != 0)
+    {
+      memset (siginfo, 0, sizeof (*siginfo));
+      return 0;
+    }
+  return 1;
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
@@ -5302,14 +5196,14 @@ extern initialize_file_ftype _initialize_linux_nat;
 void
 _initialize_linux_nat (void)
 {
-  add_setshow_zinteger_cmd ("lin-lwp", class_maintenance,
-                           &debug_linux_nat, _("\
+  add_setshow_zuinteger_cmd ("lin-lwp", class_maintenance,
+                            &debug_linux_nat, _("\
 Set debugging of GNU/Linux lwp module."), _("\
 Show debugging of GNU/Linux lwp module."), _("\
 Enables printf debugging output."),
-                           NULL,
-                           show_debug_linux_nat,
-                           &setdebuglist, &showdebuglist);
+                            NULL,
+                            show_debug_linux_nat,
+                            &setdebuglist, &showdebuglist);
 
   /* Save this mask as the default.  */
   sigprocmask (SIG_SETMASK, NULL, &normal_mask);
This page took 0.031129 seconds and 4 git commands to generate.