Sun Aug 1 22:58:18 1993 Stu Grossman (grossman at cygnus.com)
[deliverable/binutils-gdb.git] / gdb / procfs.c
index 79f54aa658807bdb549a5adefab87d7eb3aee7e1..4c8ab5ccfe9d532b274b55f387fd30aeacd2dda3 100644 (file)
@@ -1,5 +1,5 @@
 /* Machine independent support for SVR4 /proc (process file system) for GDB.
-   Copyright (C) 1991 Free Software Foundation, Inc.
+   Copyright 1991, 1992 Free Software Foundation, Inc.
    Written by Fred Fish at Cygnus Support.
 
 This file is part of GDB.
@@ -34,8 +34,6 @@ regardless of whether or not the actual target has floating point hardware.
 
 #include "defs.h"
 
-#ifdef USE_PROC_FS     /* Entire file goes away if not using /proc */
-
 #include <time.h>
 #include <sys/procfs.h>
 #include <fcntl.h>
@@ -45,6 +43,7 @@ regardless of whether or not the actual target has floating point hardware.
 #include "inferior.h"
 #include "target.h"
 #include "command.h"
+#include "gdbcore.h"
 
 #define MAX_SYSCALLS   256     /* Maximum number of syscalls for table */
 
@@ -52,6 +51,8 @@ regardless of whether or not the actual target has floating point hardware.
 #define PROC_NAME_FMT "/proc/%05d"
 #endif
 
+extern struct target_ops procfs_ops;           /* Forward declaration */
+
 #if 1  /* FIXME: Gross and ugly hack to resolve coredep.c global */
 CORE_ADDR kernel_u_addr;
 #endif
@@ -362,7 +363,7 @@ static int
 proc_address_to_fd PARAMS ((CORE_ADDR, int));
 
 static int
-open_proc_file PARAMS ((int, struct procinfo *));
+open_proc_file PARAMS ((int, struct procinfo *, int));
 
 static void
 close_proc_file PARAMS ((struct procinfo *));
@@ -406,6 +407,18 @@ lookupname PARAMS ((struct trans *, unsigned int, char *));
 static char *
 lookupdesc PARAMS ((struct trans *, unsigned int));
 
+static int
+do_attach PARAMS ((int pid));
+
+static void
+do_detach PARAMS ((int siggnal));
+
+static void
+procfs_create_inferior PARAMS ((char *, char *, char **));
+
+static void
+procfs_notice_signals PARAMS ((void));
+
 /* External function prototypes that can't be easily included in any
    header file because the args are typedefs in system include files. */
 
@@ -545,7 +558,8 @@ sigcodename (sip)
   return (name);
 }
 
-static char *sigcodedesc (sip)
+static char *
+sigcodedesc (sip)
      siginfo_t *sip;
 {
   struct sigcode *scp;
@@ -1031,46 +1045,13 @@ ptrace (request, pid, arg3, arg4)
 
 /*
 
-GLOBAL FUNCTION
-
-       kill_inferior_fast -- kill inferior while gdb is exiting
-
-SYNOPSIS
-
-       void kill_inferior_fast (void)
-
-DESCRIPTION
-
-       This is used when GDB is exiting.  It gives less chance of error.
-
-NOTES
-
-       Don't attempt to kill attached inferiors since we may be called
-       when gdb is in the process of aborting, and killing the attached
-       inferior may be very anti-social.  This is particularly true if we
-       were attached just so we could use the /proc facilities to get
-       detailed information about it's status.
-
-*/
-
-void
-kill_inferior_fast ()
-{
-  if (inferior_pid != 0 && !attach_flag)
-    {
-      unconditionally_kill_inferior ();
-    }
-}
-
-/*
-
-GLOBAL FUNCTION
+LOCAL FUNCTION
 
-       kill_inferior - kill any currently inferior
+       procfs_kill_inferior - kill any currently inferior
 
 SYNOPSIS
 
-       void kill_inferior (void)
+       void procfs_kill_inferior (void)
 
 DESCRIPTION
 
@@ -1084,8 +1065,8 @@ NOTES
 
 */
 
-void
-kill_inferior ()
+static void
+procfs_kill_inferior ()
 {
   if (inferior_pid != 0)
     {
@@ -1130,13 +1111,13 @@ unconditionally_kill_inferior ()
 
 /*
 
-GLOBAL FUNCTION
+LOCAL FUNCTION
 
-       child_xfer_memory -- copy data to or from inferior memory space
+       procfs_xfer_memory -- copy data to or from inferior memory space
 
 SYNOPSIS
 
-       int child_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
+       int procfs_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
                int dowrite, struct target_ops target)
 
 DESCRIPTION
@@ -1146,7 +1127,7 @@ DESCRIPTION
        if DOWRITE is zero or to inferior if DOWRITE is nonzero.
   
        Returns the length copied, which is either the LEN argument or
-       zero.  This xfer function does not do partial moves, since child_ops
+       zero.  This xfer function does not do partial moves, since procfs_ops
        doesn't allow memory operations to cross below us in the target stack
        anyway.
 
@@ -1155,9 +1136,8 @@ NOTES
        The /proc interface makes this an almost trivial task.
  */
 
-
-int
-child_xfer_memory (memaddr, myaddr, len, dowrite, target)
+static int
+procfs_xfer_memory (memaddr, myaddr, len, dowrite, target)
      CORE_ADDR memaddr;
      char *myaddr;
      int len;
@@ -1186,13 +1166,13 @@ child_xfer_memory (memaddr, myaddr, len, dowrite, target)
 
 /*
 
-GLOBAL FUNCTION
+LOCAL FUNCTION
 
-       store_inferior_registers -- copy register values back to inferior
+       procfs_store_registers -- copy register values back to inferior
 
 SYNOPSIS
 
-       void store_inferior_registers (int regno)
+       void procfs_store_registers (int regno)
 
 DESCRIPTION
 
@@ -1222,8 +1202,8 @@ NOTES
 
  */
 
-void
-store_inferior_registers (regno)
+static void
+procfs_store_registers (regno)
      int regno;
 {
   if (regno != -1)
@@ -1252,13 +1232,13 @@ store_inferior_registers (regno)
 
 /*
 
-GLOBAL FUNCTION
+LOCAL FUNCTION
 
-       inferior_proc_init - initialize access to a /proc entry
+       procfs_init_inferior - initialize access to a /proc entry
 
 SYNOPSIS
 
-       void inferior_proc_init (int pid)
+       void procfs_init_inferior (int pid)
 
 DESCRIPTION
 
@@ -1275,11 +1255,14 @@ NOTES
 
  */
 
-void
-inferior_proc_init (pid)
+static void
+procfs_init_inferior (pid)
      int pid;
 {
-  if (!open_proc_file (pid, &pi))
+
+  push_target (&procfs_ops);
+
+  if (!open_proc_file (pid, &pi, O_RDWR))
     {
       proc_init_failed ("can't open process file");
     }
@@ -1287,7 +1270,7 @@ inferior_proc_init (pid)
     {
       memset ((char *) &pi.prrun, 0, sizeof (pi.prrun));
       prfillset (&pi.prrun.pr_trace);
-      proc_signal_handling_change ();
+      procfs_notice_signals ();
       prfillset (&pi.prrun.pr_fault);
       prdelset (&pi.prrun.pr_fault, FLTPAGE);
       if (ioctl (pi.fd, PIOCWSTOP, &pi.prstatus) < 0)
@@ -1305,11 +1288,11 @@ inferior_proc_init (pid)
 
 GLOBAL FUNCTION
 
-       proc_signal_handling_change
+       procfs_notice_signals
 
 SYNOPSIS
 
-       void proc_signal_handling_change (void);
+       static void procfs_notice_signals (void);
 
 DESCRIPTION
 
@@ -1326,8 +1309,8 @@ DESCRIPTION
        involved.
  */
 
-void
-proc_signal_handling_change ()
+static void
+procfs_notice_signals ()
 {
   int signo;
 
@@ -1355,7 +1338,7 @@ proc_signal_handling_change ()
 
 /*
 
-GLOBAL FUNCTION
+LOCAL FUNCTION
 
        proc_set_exec_trap -- arrange for exec'd child to halt at startup
 
@@ -1384,7 +1367,7 @@ NOTE
        tracing flags cleared.
  */
 
-void
+static void
 proc_set_exec_trap ()
 {
   sysset_t exitset;
@@ -1435,6 +1418,21 @@ proc_set_exec_trap ()
 #if defined (PIOCRFORK)        /* Original method */
   ioctl (fd, PIOCRFORK, NULL);
 #endif
+#endif
+
+  /* Turn on run-on-last-close flag so that this process will not hang
+     if GDB goes away for some reason.  */
+
+#if defined (PIOCSET)  /* New method */
+  {
+      long pr_flags;
+      pr_flags = PR_RLC;
+      (void) ioctl (fd, PIOCSET, &pr_flags);
+  }
+#else
+#if defined (PIOCSRLC) /* Original method */
+  (void) ioctl (fd, PIOCSRLC, 0);
+#endif
 #endif
 }
 
@@ -1483,6 +1481,7 @@ proc_iterate_over_mappings (func)
   return (funcstat);
 }
 
+#if 0  /* Currently unused */
 /*
 
 GLOBAL FUNCTION
@@ -1504,9 +1503,6 @@ DESCRIPTION
        segment containing that address.
 */
 
-
-#if 0  /* Currently unused */
-
 CORE_ADDR
 proc_base_address (addr)
      CORE_ADDR addr;
@@ -1579,17 +1575,117 @@ proc_address_to_fd (addr, complain)
 }
 
 
-#ifdef ATTACH_DETACH
+/* Attach to process PID, then initialize for debugging it
+   and wait for the trace-trap that results from attaching.  */
+
+static void
+procfs_attach (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  char *exec_file;
+  int pid;
+
+  if (!args)
+    error_no_arg ("process-id to attach");
+
+  pid = atoi (args);
+
+  if (pid == getpid())         /* Trying to masturbate? */
+    error ("I refuse to debug myself!");
+
+  if (from_tty)
+    {
+      exec_file = (char *) get_exec_file (0);
+
+      if (exec_file)
+       printf ("Attaching to program `%s', %s\n", exec_file, target_pid_to_str (pid));
+      else
+       printf ("Attaching to %s\n", target_pid_to_str (pid));
+
+      fflush (stdout);
+    }
+
+  do_attach (pid);
+  inferior_pid = pid;
+  push_target (&procfs_ops);
+}
+
+
+/* Take a program previously attached to and detaches it.
+   The program resumes execution and will no longer stop
+   on signals, etc.  We'd better not have left any breakpoints
+   in the program or it'll die when it hits one.  For this
+   to work, it may be necessary for the process to have been
+   previously attached.  It *might* work if the program was
+   started via the normal ptrace (PTRACE_TRACEME).  */
+
+static void
+procfs_detach (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  int siggnal = 0;
+
+  if (from_tty)
+    {
+      char *exec_file = get_exec_file (0);
+      if (exec_file == 0)
+       exec_file = "";
+      printf ("Detaching from program: %s %s\n",
+             exec_file, target_pid_to_str (inferior_pid));
+      fflush (stdout);
+    }
+  if (args)
+    siggnal = atoi (args);
+  
+  do_detach (siggnal);
+  inferior_pid = 0;
+  unpush_target (&procfs_ops);         /* Pop out of handling an inferior */
+}
+
+/* Get ready to modify the registers array.  On machines which store
+   individual registers, this doesn't need to do anything.  On machines
+   which store all the registers in one fell swoop, this makes sure
+   that registers contains all the registers from the program being
+   debugged.  */
+
+static void
+procfs_prepare_to_store ()
+{
+#ifdef CHILD_PREPARE_TO_STORE
+  CHILD_PREPARE_TO_STORE ();
+#endif
+}
+
+/* Print status information about what we're accessing.  */
+
+static void
+procfs_files_info (ignore)
+     struct target_ops *ignore;
+{
+  printf ("\tUsing the running image of %s %s via /proc.\n",
+         attach_flag? "attached": "child", target_pid_to_str (inferior_pid));
+}
+
+/* ARGSUSED */
+static void
+procfs_open (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  error ("Use the \"run\" command to start a Unix child process.");
+}
 
 /*
 
-GLOBAL FUNCTION
+LOCAL FUNCTION
 
-       attach -- attach to an already existing process
+       do_attach -- attach to an already existing process
 
 SYNOPSIS
 
-       int attach (int pid)
+       int do_attach (int pid)
 
 DESCRIPTION
 
@@ -1601,15 +1697,18 @@ NOTES
 
        The option of stopping at attach time is specific to the /proc
        versions of gdb.  Versions using ptrace force the attachee
-       to stop.
+       to stop.  (I have changed this version to do so, too.  All you
+       have to do is "continue" to make it go on. -- gnu@cygnus.com)
 
 */
 
-int
-attach (pid)
+static int
+do_attach (pid)
      int pid;
 {
-  if (!open_proc_file (pid, &pi))
+  int result;
+
+  if (!open_proc_file (pid, &pi, O_RDWR))
     {
       perror_with_name (pi.pathname);
       /* NOTREACHED */
@@ -1632,8 +1731,26 @@ attach (pid)
   else
     {
       pi.was_stopped = 0;
-      if (query ("Process is currently running, stop it? "))
+      if (1 || query ("Process is currently running, stop it? "))
        {
+         /* Make it run again when we close it.  */
+#if defined (PIOCSET)  /* New method */
+         {
+             long pr_flags;
+             pr_flags = PR_RLC;
+             result = ioctl (pi.fd, PIOCSET, &pr_flags);
+         }
+#else
+#if defined (PIOCSRLC) /* Original method */
+         result = ioctl (pi.fd, PIOCSRLC, 0);
+#endif
+#endif
+         if (result < 0)
+           {
+             print_sys_errmsg (pi.pathname, errno);
+             close_proc_file (&pi);
+             error ("PIOCSRLC or PIOCSET failed");
+           }
          if (ioctl (pi.fd, PIOCSTOP, &pi.prstatus) < 0)
            {
              print_sys_errmsg (pi.pathname, errno);
@@ -1644,10 +1761,10 @@ attach (pid)
        }
       else
        {
-         printf ("Ok, gdb will wait for process %u to stop.\n", pid);
+         printf ("Ok, gdb will wait for %s to stop.\n", target_pid_to_str (pid));
        }
     }
-  
+
   /*  Remember some things about the inferior that we will, or might, change
       so that we can restore them when we detach. */
   
@@ -1661,7 +1778,7 @@ attach (pid)
   
   memset (&pi.prrun, 0, sizeof (pi.prrun));
   prfillset (&pi.prrun.pr_trace);
-  proc_signal_handling_change ();
+  procfs_notice_signals ();
   prfillset (&pi.prrun.pr_fault);
   prdelset (&pi.prrun.pr_fault, FLTPAGE);
   if (ioctl (pi.fd, PIOCSFAULT, &pi.prrun.pr_fault))
@@ -1678,13 +1795,13 @@ attach (pid)
 
 /*
 
-GLOBAL FUNCTION
+LOCAL FUNCTION
 
-       detach -- detach from an attached-to process
+       do_detach -- detach from an attached-to process
 
 SYNOPSIS
 
-       void detach (int signal)
+       void do_detach (int signal)
 
 DESCRIPTION
 
@@ -1705,10 +1822,12 @@ DESCRIPTION
        be the ideal situation.  (FIXME).
  */
 
-void
-detach (signal)
+static void
+do_detach (signal)
      int signal;
 {
+  int result;
+
   if (signal)
     {
       set_proc_siginfo (&pi, signal);
@@ -1750,12 +1869,29 @@ detach (signal)
          if (signal || !pi.was_stopped ||
              query ("Was stopped when attached, make it runnable again? "))
            {
-             memset (&pi.prrun, 0, sizeof (pi.prrun));
-             pi.prrun.pr_flags = PRCFAULT;
-             if (ioctl (pi.fd, PIOCRUN, &pi.prrun))
+             /* Clear any fault that might have stopped it.  */
+             if (ioctl (pi.fd, PIOCCFAULT, 0))
+               {
+                 print_sys_errmsg (pi.pathname, errno);
+                 printf ("PIOCCFAULT failed.\n");
+               }
+
+             /* Make it run again when we close it.  */
+#if defined (PIOCSET)  /* New method */
+             {
+                 long pr_flags;
+                 pr_flags = PR_RLC;
+                 result = ioctl (pi.fd, PIOCSET, &pr_flags);
+             }
+#else
+#if defined (PIOCSRLC) /* Original method */
+             result = ioctl (pi.fd, PIOCSRLC, 0);
+#endif
+#endif
+             if (result)
                {
                  print_sys_errmsg (pi.pathname, errno);
-                 printf ("PIOCRUN failed.\n");
+                 printf ("PIOCSRLC or PIOCSET failed.\n");
                }
            }
        }
@@ -1764,17 +1900,18 @@ detach (signal)
   attach_flag = 0;
 }
 
-#endif /* ATTACH_DETACH */
-
 /*
 
-GLOBAL FUNCTION
+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.
 
-       proc_wait -- emulate wait() as much as possible
 
 SYNOPSIS
 
-       int proc_wait (int *statloc)
+       int procfs_wait (int *statloc)
 
 DESCRIPTION
 
@@ -1803,8 +1940,8 @@ NOTES
 
  */
 
-int
-proc_wait (statloc)
+static int
+procfs_wait (statloc)
      int *statloc;
 {
   short what;
@@ -1819,10 +1956,17 @@ proc_wait (statloc)
     }
   else if (!(pi.prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)))
     {
+      if (attach_flag)
+       set_sigint_trap();      /* Causes SIGINT to be passed on to the
+                                  attached process. */
+
       if (ioctl (pi.fd, PIOCWSTOP, &pi.prstatus) < 0)
        {
          checkerr++;
        }
+
+      if (attach_flag)
+       clear_sigint_trap();
     }    
   if (checkerr)
     {
@@ -1831,6 +1975,7 @@ proc_wait (statloc)
          rtnval = wait (&statval);
          if (rtnval != inferior_pid)
            {
+             print_sys_errmsg (pi.pathname, errno);
              error ("PIOCWSTOP, wait failed, returned %d", rtnval);
              /* NOTREACHED */
            }
@@ -1919,10 +2064,19 @@ proc_wait (statloc)
             pi.prstatus.pr_flags);
          /* NOTREACHED */
     }
+
   if (statloc)
     {
       *statloc = statval;
     }
+
+  if (rtnval == -1)            /* No more children to wait for */
+    {
+      fprintf (stderr, "Child process unexpectedly missing.\n");
+      *statloc = 42;   /* Claim it exited with signal 42 */
+      return rtnval;
+    }
+
   return (rtnval);
 }
 
@@ -1996,50 +2150,30 @@ set_proc_siginfo (pip, signo)
     }
 }
 
-/*
-
-GLOBAL FUNCTION
-
-       child_resume -- resume execution of the inferior process
-
-SYNOPSIS
-
-       void child_resume (int step, int signo)
-
-DESCRIPTION
-
-       Resume execution of the inferior process.  If STEP is nozero, then
-       just single step it.  If SIGNAL is nonzero, restart it with that
-       signal activated.
-
-NOTE
-
-       It may not be absolutely necessary to specify the PC value for
-       restarting, but to be safe we use the value that gdb considers
-       to be current.  One case where this might be necessary is if the
-       user explicitly changes the PC value that gdb considers to be
-       current.  FIXME:  Investigate if this is necessary or not.
-
-       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
-       inhibit sending it another SIGSTOP, which would be the normal
-       result of default signal handling.  One potential drawback to
-       this is that we will also ignore any attempt to by the user
-       to explicitly continue after the attach with a SIGSTOP.  Ultimately
-       this problem should be dealt with by making the routines that
-       deal with the inferior a little smarter, and possibly even allow
-       an inferior to continue running at the same time as gdb.  (FIXME?)
- */
+/* Resume execution of process PID.  If STEP is nozero, then
+   just single step it.  If SIGNAL is nonzero, restart it with that
+   signal activated.  */
 
-void
-child_resume (step, signo)
+static void
+procfs_resume (pid, step, signo)
+     int pid;
      int step;
      int signo;
 {
+  int signal_to_pass;
+
   errno = 0;
   pi.prrun.pr_flags = PRSTRACE | PRSFAULT | PRCFAULT;
 
+#if 0
+  /* It should not be necessary.  If the user explicitly changes the value,
+     value_assign calls write_register_bytes, which writes it.  */
+/*     It may not be absolutely necessary to specify the PC value for
+       restarting, but to be safe we use the value that gdb considers
+       to be current.  One case where this might be necessary is if the
+       user explicitly changes the PC value that gdb considers to be
+       current.  FIXME:  Investigate if this is necessary or not.  */
+
 #ifdef PRSVADDR_BROKEN
 /* Can't do this under Solaris running on a Sparc, as there seems to be no
    place to put nPC.  In fact, if you use this, nPC seems to be set to some
@@ -2048,11 +2182,46 @@ child_resume (step, signo)
 
   pi.prrun.pr_vaddr = (caddr_t) *(int *) &registers[REGISTER_BYTE (PC_REGNUM)];
   pi.prrun.pr_flags != PRSVADDR;
+#endif
 #endif
 
-  if (signo && !(signo == SIGSTOP && pi.nopass_next_sigstop))
+  if (signo == SIGSTOP && 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
+       inhibit sending it another SIGSTOP, which would be the normal
+       result of default signal handling.  One potential drawback to
+       this is that we will also ignore any attempt to by the user
+       to explicitly continue after the attach with a SIGSTOP.  Ultimately
+       this problem should be dealt with by making the routines that
+       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
+          && pi.prstatus.pr_cursig == SIGTSTP
+          && pi.prstatus.pr_action.sa_handler == SIG_DFL)
+
+    /* We are about to pass the inferior a SIGTSTP whose action is
+       SIG_DFL.  The SIG_DFL action for a SIGTSTP is to stop
+       (notifying the parent via wait()), and then keep going from the
+       same place when the parent is ready for you to keep going.  So
+       under the debugger, it should do nothing (as if the program had
+       been stopped and then later resumed.  Under ptrace, this
+       happens for us, but under /proc, the system obligingly stops
+       the process, and wait_for_inferior would have no way of
+       distinguishing that type of stop (which indicates that we
+       should just start it again), with a stop due to the pr_trace
+       field of the prrun_t struct.
+
+       Note that if the SIGTSTP is being caught, we *do* need to pass it,
+       because the handler needs to get executed.  */
+    signal_to_pass = 0;
+  else
+    signal_to_pass = signo;
+
+  if (signal_to_pass)
     {
-      set_proc_siginfo (&pi, signo);
+      set_proc_siginfo (&pi, signal_to_pass);
     }
   else
     {
@@ -2072,13 +2241,13 @@ child_resume (step, signo)
 
 /*
 
-GLOBAL FUNCTION
+LOCAL FUNCTION
 
-       fetch_inferior_registers -- fetch current registers from inferior
+       procfs_fetch_registers -- fetch current registers from inferior
 
 SYNOPSIS
 
-       void fetch_inferior_registers (int regno)
+       void procfs_fetch_registers (int regno)
 
 DESCRIPTION
 
@@ -2088,8 +2257,8 @@ DESCRIPTION
 
 */
 
-void
-fetch_inferior_registers (regno)
+static void
+procfs_fetch_registers (regno)
      int regno;
 {
   if (ioctl (pi.fd, PIOCGREG, &pi.gregset) != -1)
@@ -2106,66 +2275,6 @@ fetch_inferior_registers (regno)
 
 /*
 
-GLOBAL FUNCTION
-
-       fetch_core_registers -- fetch current registers from core file data
-
-SYNOPSIS
-
-       void fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
-                                  int which, unsigned in reg_addr)
-
-DESCRIPTION
-
-       Read the values of either the general register set (WHICH equals 0)
-       or the floating point register set (WHICH equals 2) from the core
-       file data (pointed to by CORE_REG_SECT), and update gdb's idea of
-       their current values.  The CORE_REG_SIZE parameter is ignored.
-
-NOTES
-
-       Use the indicated sizes to validate the gregset and fpregset
-       structures.
-*/
-
-void
-fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
-     char *core_reg_sect;
-     unsigned core_reg_size;
-     int which;
-     unsigned int reg_addr;    /* Unused in this version */
-{
-
-  if (which == 0)
-    {
-      if (core_reg_size != sizeof (pi.gregset))
-       {
-         warning ("wrong size gregset struct in core file");
-       }
-      else
-       {
-         memcpy ((char *) &pi.gregset, core_reg_sect, sizeof (pi.gregset));
-         supply_gregset (&pi.gregset);
-       }
-    }
-  else if (which == 2)
-    {
-      if (core_reg_size != sizeof (pi.fpregset))
-       {
-         warning ("wrong size fpregset struct in core file");
-       }
-      else
-       {
-         memcpy ((char *) &pi.fpregset, core_reg_sect, sizeof (pi.fpregset));
-#if defined (FP0_REGNUM)
-         supply_fpregset (&pi.fpregset);
-#endif
-       }
-    }
-}
-
-/*
-
 LOCAL FUNCTION
 
        proc_init_failed - called whenever /proc access initialization fails
@@ -2238,15 +2347,16 @@ LOCAL FUNCTION
 
 SYNOPSIS
 
-       static int open_proc_file (pid, struct procinfo *pip)
+       static int open_proc_file (int pid, struct procinfo *pip, int mode)
 
 DESCRIPTION
 
-       Given a process id, close the existing open /proc entry (if any)
-       and open one for the new process id.  Once it is open, then
-       mark the local process information structure as valid, which
-       guarantees that the pid, fd, and pathname fields match an open
-       /proc entry.  Returns zero if the open fails, nonzero otherwise.
+       Given a process id and a mode, close the existing open /proc
+       entry (if any) and open one for the new process id, in the
+       specified mode.  Once it is open, then mark the local process
+       information structure as valid, which guarantees that the pid,
+       fd, and pathname fields match an open /proc entry.  Returns
+       zero if the open fails, nonzero otherwise.
 
        Note that the pathname is left intact, even when the open fails,
        so that callers can use it to construct meaningful error messages
@@ -2254,11 +2364,12 @@ DESCRIPTION
  */
 
 static int
-open_proc_file (pid, pip)
+open_proc_file (pid, pip, mode)
      int pid;
      struct procinfo *pip;
+     int mode;
 {
-  pip -> valid = 0;
+  pip -> valid = 0;            /* FIXME, what is this? ?!  */
   if (pip -> valid)
     {
       close (pip -> fd);
@@ -2268,7 +2379,7 @@ open_proc_file (pid, pip)
       pip -> pathname = xmalloc (32);
     }
   sprintf (pip -> pathname, PROC_NAME_FMT, pid);
-  if ((pip -> fd = open (pip -> pathname, O_RDWR)) >= 0)
+  if ((pip -> fd = open (pip -> pathname, mode)) >= 0)
     {
       pip -> valid = 1;
       pip -> pid = pid;
@@ -2442,7 +2553,8 @@ info_proc_siginfo (pip, summary)
            }
          if (sip -> si_code <= 0)
            {
-             printf_filtered ("sent by pid %d, uid %d ", sip -> si_pid,
+             printf_filtered ("sent by %s, uid %d ",
+                              target_pid_to_str (sip -> si_pid),
                               sip -> si_uid);
            }
          else
@@ -2457,8 +2569,8 @@ info_proc_siginfo (pip, summary)
                }
              else if ((sip -> si_signo == SIGCHLD))
                {
-                 printf_filtered ("child pid %u, status %u ",
-                                  sip -> si_pid,
+                 printf_filtered ("child %s, status %u ",
+                                  target_pid_to_str (sip -> si_pid),
                                   sip -> si_status);
                }
              else if ((sip -> si_signo == SIGPOLL))
@@ -2480,7 +2592,7 @@ info_proc_siginfo (pip, summary)
            }
          if (sip -> si_code <= 0)
            {
-             printf_filtered ("\t%-16u %s\n", sip -> si_pid,
+             printf_filtered ("\t%-16u %s\n", sip -> si_pid, /* XXX need target_pid_to_str() */
                               "PID of process sending signal");
              printf_filtered ("\t%-16u %s\n", sip -> si_uid,
                               "UID of process sending signal");
@@ -2503,7 +2615,7 @@ info_proc_siginfo (pip, summary)
                }
              else if ((sip -> si_signo == SIGCHLD))
                {
-                 printf_filtered ("\t%-16u %s.\n", sip -> si_pid,
+                 printf_filtered ("\t%-16u %s.\n", sip -> si_pid, /* XXX need target_pid_to_str() */
                                   "Child process ID");
                  printf_filtered ("\t%-16u %s.\n", sip -> si_status,
                                   "Child process exit value or signal");
@@ -2748,7 +2860,9 @@ DESCRIPTION
        info proc mappings      (prints address mappings)
        info proc times         (prints process/children times)
        info proc id            (prints pid, ppid, gid, sid, etc)
+               FIXME:  i proc id not implemented.
        info proc status        (prints general process state info)
+               FIXME:  i proc status not implemented.
        info proc signals       (prints info about signal handling)
        info proc all           (prints all info)
 
@@ -2843,7 +2957,7 @@ info_proc (args, from_tty)
              pid = pii.pid;
              pip = &pii;
              memset (&pii, 0, sizeof (pii));
-             if (!open_proc_file (pid, pip))
+             if (!open_proc_file (pid, pip, O_RDONLY))
                {
                  perror_with_name (pip -> pathname);
                  /* NOTREACHED */
@@ -2863,7 +2977,8 @@ info_proc (args, from_tty)
 
   if (!pip -> valid)
     {
-      error ("No process.  Run an inferior or specify an explicit pid.");
+      error ("\
+No process.  Start debugging a program or specify an explicit process ID.");
     }
   if (ioctl (pip -> fd, PIOCSTATUS, &(pip -> prstatus)) < 0)
     {
@@ -2911,15 +3026,87 @@ info_proc (args, from_tty)
   do_cleanups (old_chain);
 }
 
+/* Fork an inferior process, and start debugging it with /proc.  */
+
+static void
+procfs_create_inferior (exec_file, allargs, env)
+     char *exec_file;
+     char *allargs;
+     char **env;
+{
+  fork_inferior (exec_file, allargs, env,
+                proc_set_exec_trap, procfs_init_inferior);
+  /* We are at the first instruction we care about.  */
+  /* Pedal to the metal... */
+  proceed ((CORE_ADDR) -1, 0, 0);
+}
+
+/* Clean up after the inferior dies.  */
+
+static void
+procfs_mourn_inferior ()
+{
+  unpush_target (&procfs_ops);
+  generic_mourn_inferior ();
+}
+
+/* Mark our target-struct as eligible for stray "run" and "attach" commands.  */
+static int
+procfs_can_run ()
+{
+  return(1);
+}
+\f
+struct target_ops procfs_ops = {
+  "procfs",                    /* to_shortname */
+  "Unix /proc child process",  /* to_longname */
+  "Unix /proc child process (started by the \"run\" command).",        /* to_doc */
+  procfs_open,                 /* to_open */
+  0,                           /* to_close */
+  procfs_attach,                       /* to_attach */
+  procfs_detach,               /* to_detach */
+  procfs_resume,                       /* to_resume */
+  procfs_wait,                 /* to_wait */
+  procfs_fetch_registers,      /* to_fetch_registers */
+  procfs_store_registers,      /* to_store_registers */
+  procfs_prepare_to_store,     /* to_prepare_to_store */
+  procfs_xfer_memory,          /* to_xfer_memory */
+  procfs_files_info,           /* to_files_info */
+  memory_insert_breakpoint,    /* to_insert_breakpoint */
+  memory_remove_breakpoint,    /* to_remove_breakpoint */
+  terminal_init_inferior,      /* to_terminal_init */
+  terminal_inferior,           /* to_terminal_inferior */
+  terminal_ours_for_output,    /* to_terminal_ours_for_output */
+  terminal_ours,               /* to_terminal_ours */
+  child_terminal_info,         /* to_terminal_info */
+  procfs_kill_inferior,                /* to_kill */
+  0,                           /* to_load */
+  0,                           /* to_lookup_symbol */
+  procfs_create_inferior,      /* to_create_inferior */
+  procfs_mourn_inferior,       /* to_mourn_inferior */
+  procfs_can_run,              /* to_can_run */
+  procfs_notice_signals,       /* to_notice_signals */
+  process_stratum,             /* to_stratum */
+  0,                           /* to_next */
+  1,                           /* to_has_all_memory */
+  1,                           /* to_has_memory */
+  1,                           /* to_has_stack */
+  1,                           /* to_has_registers */
+  1,                           /* to_has_execution */
+  0,                           /* sections */
+  0,                           /* sections_end */
+  OPS_MAGIC                    /* to_magic */
+};
+
 /*
 
 GLOBAL FUNCTION
 
-       _initialize_proc_fs -- initialize the process file system stuff
+       _initialize_procfs -- initialize the process file system stuff
 
 SYNOPSIS
 
-       void _initialize_proc_fs (void)
+       void _initialize_procfs (void)
 
 DESCRIPTION
 
@@ -2928,19 +3115,18 @@ DESCRIPTION
 
 */
 
-static char *proc_desc =
+void
+_initialize_procfs ()
+{
+  add_target (&procfs_ops);
+
+  add_info ("proc", info_proc, 
 "Show process status information using /proc entry.\n\
 Specify process id or use current inferior by default.\n\
 Specify keywords for detailed information; default is summary.\n\
 Keywords are: `all', `faults', `flags', `id', `mappings', `signals',\n\
 `status', `syscalls', and `times'.\n\
-Unambiguous abbreviations may be used.";
+Unambiguous abbreviations may be used.");
 
-void
-_initialize_proc_fs ()
-{
-  add_info ("proc", info_proc, proc_desc);
   init_syscall_table ();
 }
-
-#endif /* USE_PROC_FS */
This page took 0.037872 seconds and 4 git commands to generate.