* config/m68k/monitor.mt (TDEPFILE): Add remote-es.o.
[deliverable/binutils-gdb.git] / gdb / procfs.c
index 844f8122361c52d4b7aeb07c5d88b0be2d42d7d8..0d7aee8775787c277ab58c70bba6bc0a11e145e2 100644 (file)
@@ -34,6 +34,7 @@ regardless of whether or not the actual target has floating point hardware.
 
 #include "defs.h"
 
+#include <sys/types.h>
 #include <time.h>
 #include <sys/procfs.h>
 #include <fcntl.h>
@@ -41,6 +42,8 @@ regardless of whether or not the actual target has floating point hardware.
 #include <string.h>
 #include <stropts.h>
 #include <poll.h>
+#include <unistd.h>
+#include <sys/stat.h>
 
 #include "inferior.h"
 #include "target.h"
@@ -1206,36 +1209,6 @@ init_syscall_table ()
 
 /*
 
-GLOBAL FUNCTION
-
-       ptrace -- override library version to force errors for /proc version
-
-SYNOPSIS
-
-       int ptrace (int request, int pid, PTRACE_ARG3_TYPE arg3, int arg4)
-
-DESCRIPTION
-
-       When gdb is configured to use /proc, it should not be calling
-       or otherwise attempting to use ptrace.  In order to catch errors
-       where use of /proc is configured, but some routine is still calling
-       ptrace, we provide a local version of a function with that name
-       that does nothing but issue an error message.
-*/
-
-int
-ptrace (request, pid, arg3, arg4)
-     int request;
-     int pid;
-     PTRACE_ARG3_TYPE arg3;
-     int arg4;
-{
-  error ("internal error - there is a call to ptrace() somewhere");
-  /*NOTREACHED*/
-}
-
-/*
-
 LOCAL FUNCTION
 
        procfs_kill_inferior - kill any currently inferior
@@ -1564,9 +1537,9 @@ procfs_notice_signals (pid)
 
   for (signo = 0; signo < NSIG; signo++)
     {
-      if (signal_stop_state (signo) == 0 &&
-         signal_print_state (signo) == 0 &&
-         signal_pass_state (signo) == 1)
+      if (signal_stop_state (target_signal_from_host (signo)) == 0 &&
+         signal_print_state (target_signal_from_host (signo)) == 0 &&
+         signal_pass_state (target_signal_from_host (signo)) == 1)
        {
          prdelset (&pi->prrun.pr_trace, signo);
        }
@@ -2174,50 +2147,35 @@ do_detach (signal)
   attach_flag = 0;
 }
 
-/*
-
-LOCAL FUNCTION
-
-       procfs_wait -- emulate wait() as much as possible
-       Wait for child to do something.  Return pid of child, or -1 in case
-       of error; store status through argument pointer STATUS.
-
-
-SYNOPSIS
-
-       int procfs_wait (int pid, int *statloc)
-
-DESCRIPTION
-
-       Try to emulate wait() as much as possible.  Not sure why we can't
-       just use wait(), but it seems to have problems when applied to a
-       process being controlled with the /proc interface.
-
-NOTES
-
-       We have a race problem here with no obvious solution.  We need to let
-       the inferior run until it stops on an event of interest, which means
-       that we need to use the PIOCWSTOP ioctl.  However, we cannot use this
-       ioctl if the process is already stopped on something that is not an
-       event of interest, or the call will hang indefinitely.  Thus we first
-       use PIOCSTATUS to see if the process is not stopped.  If not, then we
-       use PIOCWSTOP.  But during the window between the two, if the process
-       stops for any reason that is not an event of interest (such as a job
-       control signal) then gdb will hang.  One possible workaround is to set
-       an alarm to wake up every minute of so and check to see if the process
-       is still running, and if so, then reissue the PIOCWSTOP.  But this is
-       a real kludge, so has not been implemented.  FIXME: investigate
-       alternatives.
-
-       FIXME:  Investigate why wait() seems to have problems with programs
-       being control by /proc routines.
-
- */
+/*  emulate wait() as much as possible.
+    Wait for child to do something.  Return pid of child, or -1 in case
+    of error; store status in *OURSTATUS.
+
+    Not sure why we can't
+    just use wait(), but it seems to have problems when applied to a
+    process being controlled with the /proc interface.
+
+    We have a race problem here with no obvious solution.  We need to let
+    the inferior run until it stops on an event of interest, which means
+    that we need to use the PIOCWSTOP ioctl.  However, we cannot use this
+    ioctl if the process is already stopped on something that is not an
+    event of interest, or the call will hang indefinitely.  Thus we first
+    use PIOCSTATUS to see if the process is not stopped.  If not, then we
+    use PIOCWSTOP.  But during the window between the two, if the process
+    stops for any reason that is not an event of interest (such as a job
+    control signal) then gdb will hang.  One possible workaround is to set
+    an alarm to wake up every minute of so and check to see if the process
+    is still running, and if so, then reissue the PIOCWSTOP.  But this is
+    a real kludge, so has not been implemented.  FIXME: investigate
+    alternatives.
+
+    FIXME:  Investigate why wait() seems to have problems with programs
+    being control by /proc routines.  */
 
 static int
-procfs_wait (pid, statloc)
+procfs_wait (pid, ourstatus)
      int pid;
-     int *statloc;
+     struct target_waitstatus *ourstatus;
 {
   short what;
   short why;
@@ -2402,15 +2360,14 @@ wait_again:
             pi->prstatus.pr_flags);
     }
 
-  if (statloc)
-    {
-      *statloc = statval;
-    }
+  store_waitstatus (ourstatus, statval);
 
   if (rtnval == -1)            /* No more children to wait for */
     {
       fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing.\n");
-      *statloc = 42;   /* Claim it exited with signal 42 */
+      /* Claim it exited with unknown signal.  */
+      ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
+      ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
       return rtnval;
     }
 
@@ -2493,7 +2450,7 @@ static void
 procfs_resume (pid, step, signo)
      int pid;
      int step;
-     int signo;
+     enum target_signal signo;
 {
   int signal_to_pass;
   struct procinfo *pi, *procinfo;
@@ -2523,7 +2480,7 @@ procfs_resume (pid, step, signo)
 #endif
 #endif
 
-  if (signo == SIGSTOP && pi->nopass_next_sigstop)
+  if (signo == TARGET_SIGNAL_STOP && pi->nopass_next_sigstop)
     /* When attaching to a child process, if we forced it to stop with
        a PIOCSTOP, then we will have set the nopass_next_sigstop flag.
        Upon resuming the first time after such a stop, we explicitly
@@ -2535,7 +2492,7 @@ procfs_resume (pid, step, signo)
        deal with the inferior a little smarter, and possibly even allow
        an inferior to continue running at the same time as gdb.  (FIXME?)  */
     signal_to_pass = 0;
-  else if (signo == SIGTSTP
+  else if (signo == TARGET_SIGNAL_TSTP
           && pi->prstatus.pr_cursig == SIGTSTP
           && pi->prstatus.pr_action.sa_handler == SIG_DFL)
 
@@ -2555,7 +2512,7 @@ procfs_resume (pid, step, signo)
        because the handler needs to get executed.  */
     signal_to_pass = 0;
   else
-    signal_to_pass = signo;
+    signal_to_pass = target_signal_to_host (signo);
 
   if (signal_to_pass)
     {
@@ -3464,8 +3421,78 @@ procfs_create_inferior (exec_file, allargs, env)
      char *allargs;
      char **env;
 {
+  char *shell_file = getenv ("SHELL");
+  char *tryname;
+  if (shell_file != NULL && strchr (shell_file, '/') == NULL)
+    {
+
+      /* We will be looking down the PATH to find shell_file.  If we
+        just do this the normal way (via execlp, which operates by
+        attempting an exec for each element of the PATH until it
+        finds one which succeeds), then there will be an exec for
+        each failed attempt, each of which will cause a PR_SYSEXIT
+        stop, and we won't know how to distinguish the PR_SYSEXIT's
+        for these failed execs with the ones for successful execs
+        (whether the exec has succeeded is stored at that time in the
+        carry bit or some such architecture-specific and
+        non-ABI-specified place).
+
+        So I can't think of anything better than to search the PATH
+        now.  This has several disadvantages: (1) There is a race
+        condition; if we find a file now and it is deleted before we
+        exec it, we lose, even if the deletion leaves a valid file
+        further down in the PATH, (2) there is no way to know exactly
+        what an executable (in the sense of "capable of being
+        exec'd") file is.  Using access() loses because it may lose
+        if the caller is the superuser; failing to use it loses if
+        there are ACLs or some such.  */
+
+      char *p;
+      char *p1;
+      /* FIXME-maybe: might want "set path" command to replace putenv hack
+        in set_in_environ.  */
+      char *path = getenv ("PATH");
+      int len;
+      struct stat statbuf;
+
+      if (path == NULL)
+       path = "/bin:/usr/bin";
+
+      tryname = alloca (strlen (path) + strlen (shell_file) + 2);
+      for (p = path; p != NULL; p = p1 ? p1 + 1: NULL)
+       {
+         p1 = strchr (p, ':');
+         if (p1 != NULL)
+           len = p1 - p;
+         else
+           len = strlen (p);
+         strncpy (tryname, p, len);
+         tryname[len] = '\0';
+         strcat (tryname, "/");
+         strcat (tryname, shell_file);
+         if (access (tryname, X_OK) < 0)
+           continue;
+         if (stat (tryname, &statbuf) < 0)
+           continue;
+         if (!S_ISREG (statbuf.st_mode))
+           /* We certainly need to reject directories.  I'm not quite
+              as sure about FIFOs, sockets, etc., but I kind of doubt
+              that people want to exec() these things.  */
+           continue;
+         break;
+       }
+      if (p == NULL)
+       /* Not found.  This must be an error rather than merely passing
+          the file to execlp(), because execlp() would try all the
+          exec()s, causing GDB to get confused.  */
+       error ("Can't find shell %s in PATH", shell_file);
+
+      shell_file = tryname;
+    }
+
   fork_inferior (exec_file, allargs, env,
-                proc_set_exec_trap, procfs_init_inferior);
+                proc_set_exec_trap, procfs_init_inferior, shell_file);
+
   /* We are at the first instruction we care about.  */
   /* Pedal to the metal... */
 
@@ -3475,7 +3502,7 @@ procfs_create_inferior (exec_file, allargs, env)
   procfs_set_sproc_trap (current_procinfo);
 #endif
 
-  proceed ((CORE_ADDR) -1, 0, 0);
+  proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
 }
 
 /* Clean up after the inferior dies.  */
This page took 0.026448 seconds and 4 git commands to generate.