gdb
[deliverable/binutils-gdb.git] / gdb / linux-nat.c
index a855219b53a6d78af72bc2a8a85996ad0918cc14..641a619727cce8ba78d616294c9367f38751685d 100644 (file)
@@ -30,6 +30,7 @@
 #endif
 #include <sys/ptrace.h>
 #include "linux-nat.h"
+#include "linux-ptrace.h"
 #include "linux-fork.h"
 #include "gdbthread.h"
 #include "gdbcmd.h"
@@ -160,49 +161,11 @@ blocked.  */
 #define O_LARGEFILE 0
 #endif
 
-/* If the system headers did not provide the constants, hard-code the normal
-   values.  */
-#ifndef PTRACE_EVENT_FORK
-
-#define PTRACE_SETOPTIONS      0x4200
-#define PTRACE_GETEVENTMSG     0x4201
-
-/* Options set using PTRACE_SETOPTIONS.  */
-#define PTRACE_O_TRACESYSGOOD  0x00000001
-#define PTRACE_O_TRACEFORK     0x00000002
-#define PTRACE_O_TRACEVFORK    0x00000004
-#define PTRACE_O_TRACECLONE    0x00000008
-#define PTRACE_O_TRACEEXEC     0x00000010
-#define PTRACE_O_TRACEVFORKDONE        0x00000020
-#define PTRACE_O_TRACEEXIT     0x00000040
-
-/* Wait extended result codes for the above trace options.  */
-#define PTRACE_EVENT_FORK      1
-#define PTRACE_EVENT_VFORK     2
-#define PTRACE_EVENT_CLONE     3
-#define PTRACE_EVENT_EXEC      4
-#define PTRACE_EVENT_VFORK_DONE        5
-#define PTRACE_EVENT_EXIT      6
-
-#endif /* PTRACE_EVENT_FORK */
-
 /* Unlike other extended result codes, WSTOPSIG (status) on
    PTRACE_O_TRACESYSGOOD syscall events doesn't return SIGTRAP, but
    instead SIGTRAP with bit 7 set.  */
 #define SYSCALL_SIGTRAP (SIGTRAP | 0x80)
 
-/* We can't always assume that this flag is available, but all systems
-   with the ptrace event handlers also have __WALL, so it's safe to use
-   here.  */
-#ifndef __WALL
-#define __WALL          0x40000000 /* Wait for any child.  */
-#endif
-
-#ifndef PTRACE_GETSIGINFO
-# define PTRACE_GETSIGINFO    0x4202
-# define PTRACE_SETSIGINFO    0x4203
-#endif
-
 /* The single-threaded native GNU/Linux target_ops.  We save a pointer for
    the use of the multi-threaded target.  */
 static struct target_ops *linux_ops;
@@ -980,18 +943,36 @@ linux_child_insert_fork_catchpoint (int pid)
   return !linux_supports_tracefork (pid);
 }
 
+static int
+linux_child_remove_fork_catchpoint (int pid)
+{
+  return 0;
+}
+
 static int
 linux_child_insert_vfork_catchpoint (int pid)
 {
   return !linux_supports_tracefork (pid);
 }
 
+static int
+linux_child_remove_vfork_catchpoint (int pid)
+{
+  return 0;
+}
+
 static int
 linux_child_insert_exec_catchpoint (int pid)
 {
   return !linux_supports_tracefork (pid);
 }
 
+static int
+linux_child_remove_exec_catchpoint (int pid)
+{
+  return 0;
+}
+
 static int
 linux_child_set_syscall_catchpoint (int pid, int needed, int any_count,
                                    int table_size, int *table)
@@ -1078,6 +1059,26 @@ restore_child_signals_mask (sigset_t *prev_mask)
 {
   sigprocmask (SIG_SETMASK, prev_mask, NULL);
 }
+
+/* Mask of signals to pass directly to the inferior.  */
+static sigset_t pass_mask;
+
+/* Update signals to pass to the inferior.  */
+static void
+linux_nat_pass_signals (int numsigs, unsigned char *pass_signals)
+{
+  int signo;
+
+  sigemptyset (&pass_mask);
+
+  for (signo = 1; signo < NSIG; signo++)
+    {
+      int target_signo = target_signal_from_host (signo);
+      if (target_signo < numsigs && pass_signals[target_signo])
+        sigaddset (&pass_mask, signo);
+    }
+}
+
 \f
 
 /* Prototypes for local functions.  */
@@ -1475,7 +1476,10 @@ lin_lwp_attach_lwp (ptid_t ptid)
 
       status = linux_nat_post_attach_wait (ptid, 0, &cloned, &signalled);
       if (!WIFSTOPPED (status))
-       return -1;
+       {
+         restore_child_signals_mask (&prev_mask);
+         return -1;
+       }
 
       lp = add_lwp (ptid);
       lp->stopped = 1;
@@ -1543,6 +1547,9 @@ linux_nat_create_inferior (struct target_ops *ops,
     }
 #endif /* HAVE_PERSONALITY */
 
+  /* Make sure we report all signals during startup.  */
+  linux_nat_pass_signals (0, NULL);
+
   linux_ops->to_create_inferior (ops, exec_file, allargs, env, from_tty);
 
 #ifdef HAVE_PERSONALITY
@@ -1564,6 +1571,9 @@ linux_nat_attach (struct target_ops *ops, char *args, int from_tty)
   int status;
   ptid_t ptid;
 
+  /* Make sure we report all signals during attach.  */
+  linux_nat_pass_signals (0, NULL);
+
   linux_ops->to_attach (ops, args, from_tty);
 
   /* The ptrace base target adds the main thread with (pid,0,0)
@@ -1922,19 +1932,9 @@ linux_nat_resume (struct target_ops *ops,
 
   if (lp->status && WIFSTOPPED (lp->status))
     {
-      enum target_signal saved_signo;
-      struct inferior *inf;
-
-      inf = find_inferior_pid (ptid_get_pid (lp->ptid));
-      gdb_assert (inf);
-      saved_signo = target_signal_from_host (WSTOPSIG (lp->status));
-
-      /* Defer to common code if we're gaining control of the
-        inferior.  */
-      if (inf->control.stop_soon == NO_STOP_QUIETLY
-         && signal_stop_state (saved_signo) == 0
-         && signal_print_state (saved_signo) == 0
-         && signal_pass_state (saved_signo) == 1)
+      if (!lp->step
+         && WSTOPSIG (lp->status)
+         && sigismember (&pass_mask, WSTOPSIG (lp->status)))
        {
          if (debug_linux_nat)
            fprintf_unfiltered (gdb_stdlog,
@@ -1944,7 +1944,7 @@ linux_nat_resume (struct target_ops *ops,
          /* FIXME: What should we do if we are supposed to continue
             this thread with a signal?  */
          gdb_assert (signo == TARGET_SIGNAL_0);
-         signo = saved_signo;
+         signo = target_signal_from_host (WSTOPSIG (lp->status));
          lp->status = 0;
        }
     }
@@ -2198,8 +2198,6 @@ linux_handle_extended_wait (struct lwp_info *lp, int status,
       if (event == PTRACE_EVENT_FORK
          && linux_fork_checkpointing_p (GET_PID (lp->ptid)))
        {
-         struct fork_info *fp;
-
          /* Handle checkpointing by linux-fork.c here as a special
             case.  We don't want the follow-fork-mode or 'catch fork'
             to interfere with this.  */
@@ -2209,9 +2207,8 @@ linux_handle_extended_wait (struct lwp_info *lp, int status,
          detach_breakpoints (new_pid);
 
          /* Retain child fork in ptrace (stopped) state.  */
-         fp = find_fork_pid (new_pid);
-         if (!fp)
-           fp = add_fork (new_pid);
+         if (!find_fork_pid (new_pid))
+           add_fork (new_pid);
 
          /* Report as spurious, so that infrun doesn't want to follow
             this fork.  We're actually doing an infcall in
@@ -2828,7 +2825,7 @@ status_callback (struct lwp_info *lp, void *data)
   if (lp->waitstatus.kind != TARGET_WAITKIND_IGNORE)
     {
       /* A ptrace event, like PTRACE_FORK|VFORK|EXEC, syscall event,
-        or a pending process exit.  Note that `W_EXITCODE(0,0) ==
+        or a pending process exit.  Note that `W_EXITCODE(0,0) ==
         0', so a clean process exit can not be stored pending in
         lp->status, it is indistinguishable from
         no-pending-status.  */
@@ -3064,7 +3061,7 @@ linux_nat_filter_event (int lwpid, int status, int options)
 
   /* Make sure we don't report an event for the exit of an LWP not in
      our list, i.e. not part of the current process.  This can happen
-     if we detach from a program we original forked and then it
+     if we detach from a program we originally forked and then it
      exits.  */
   if (!WIFSTOPPED (status) && !lp)
     return NULL;
@@ -3593,20 +3590,11 @@ retry:
   if (WIFSTOPPED (status))
     {
       enum target_signal signo = target_signal_from_host (WSTOPSIG (status));
-      struct inferior *inf;
 
-      inf = find_inferior_pid (ptid_get_pid (lp->ptid));
-      gdb_assert (inf);
-
-      /* Defer to common code if we get a signal while
-        single-stepping, since that may need special care, e.g. to
-        skip the signal handler, or, if we're gaining control of the
-        inferior.  */
+      /* When using hardware single-step, we need to report every signal.
+        Otherwise, signals in pass_mask may be short-circuited.  */
       if (!lp->step
-         && inf->control.stop_soon == NO_STOP_QUIETLY
-         && signal_stop_state (signo) == 0
-         && signal_print_state (signo) == 0
-         && signal_pass_state (signo) == 1)
+         && WSTOPSIG (status) && sigismember (&pass_mask, WSTOPSIG (status)))
        {
          /* FIMXE: kettenis/2001-06-06: Should we resume all threads
             here?  It is not clear we should.  GDB may not expect
@@ -4035,7 +4023,7 @@ linux_nat_xfer_partial (struct target_ops *ops, enum target_object object,
 static int
 linux_thread_alive (ptid_t ptid)
 {
-  int err;
+  int err, tmp_errno;
 
   gdb_assert (is_lwp (ptid));
 
@@ -4043,12 +4031,12 @@ linux_thread_alive (ptid_t ptid)
      running thread errors out claiming that the thread doesn't
      exist.  */
   err = kill_lwp (GET_LWP (ptid), 0);
-
+  tmp_errno = errno;
   if (debug_linux_nat)
     fprintf_unfiltered (gdb_stdlog,
                        "LLTA: KILL(SIG0) %s (%s)\n",
                        target_pid_to_str (ptid),
-                       err ? safe_strerror (err) : "OK");
+                       err ? safe_strerror (tmp_errno) : "OK");
 
   if (err != 0)
     return 0;
@@ -4494,7 +4482,7 @@ linux_nat_make_corefile_notes (bfd *obfd, int *note_size)
 
   if (get_exec_file (0))
     {
-      strncpy (fname, strrchr (get_exec_file (0), '/') + 1, sizeof (fname));
+      strncpy (fname, lbasename (get_exec_file (0)), sizeof (fname));
       strncpy (psargs, get_exec_file (0), sizeof (psargs));
       if (get_inferior_args ())
        {
@@ -5145,16 +5133,16 @@ linux_nat_xfer_osdata (struct target_ops *ops, enum target_object object,
 
                  if ((f = fopen (pathname, "r")) != NULL)
                    {
-                     size_t len = fread (cmd, 1, sizeof (cmd) - 1, f);
+                     size_t length = fread (cmd, 1, sizeof (cmd) - 1, f);
 
-                     if (len > 0)
+                     if (length > 0)
                        {
                          int i;
 
-                         for (i = 0; i < len; i++)
+                         for (i = 0; i < length; i++)
                            if (cmd[i] == '\0')
                              cmd[i] = ' ';
-                         cmd[len] = '\0';
+                         cmd[length] = '\0';
 
                          obstack_xml_printf (
                            &obstack,
@@ -5247,8 +5235,11 @@ static void
 linux_target_install_ops (struct target_ops *t)
 {
   t->to_insert_fork_catchpoint = linux_child_insert_fork_catchpoint;
+  t->to_remove_fork_catchpoint = linux_child_remove_fork_catchpoint;
   t->to_insert_vfork_catchpoint = linux_child_insert_vfork_catchpoint;
+  t->to_remove_vfork_catchpoint = linux_child_remove_vfork_catchpoint;
   t->to_insert_exec_catchpoint = linux_child_insert_exec_catchpoint;
+  t->to_remove_exec_catchpoint = linux_child_remove_exec_catchpoint;
   t->to_set_syscall_catchpoint = linux_child_set_syscall_catchpoint;
   t->to_pid_to_exec_file = linux_child_pid_to_exec_file;
   t->to_post_startup_inferior = linux_child_post_startup_inferior;
@@ -5715,6 +5706,7 @@ linux_nat_add_target (struct target_ops *t)
   t->to_detach = linux_nat_detach;
   t->to_resume = linux_nat_resume;
   t->to_wait = linux_nat_wait;
+  t->to_pass_signals = linux_nat_pass_signals;
   t->to_xfer_partial = linux_nat_xfer_partial;
   t->to_kill = linux_nat_kill;
   t->to_mourn_inferior = linux_nat_mourn_inferior;
This page took 0.027341 seconds and 4 git commands to generate.