spelling fix.
[deliverable/binutils-gdb.git] / gdb / procfs.c
index 539835e815e3fe55f20dfa35d77f0f2848817f87..b5b331d01e63bb450b64dfbc74e81eac451846b4 100644 (file)
@@ -1,5 +1,5 @@
 /* Machine independent support for SVR4 /proc (process file system) for GDB.
-   Copyright 1991, 1992-96, 1997 Free Software Foundation, Inc.
+   Copyright 1991, 1992-97, 1998 Free Software Foundation, Inc.
    Written by Fred Fish at Cygnus Support.  Changes for sysv4.2mp procfs
    compatibility by Geoffrey Noer at Cygnus Solutions.
 
@@ -54,6 +54,42 @@ regardless of whether or not the actual target has floating point hardware.
 #include "gdbcore.h"
 #include "gdbthread.h"
 
+#if !defined(SYS_lwp_create) && defined(SYS_lwpcreate)
+# define SYS_lwp_create SYS_lwpcreate
+#endif
+
+#if !defined(SYS_lwp_exit) && defined(SYS_lwpexit)
+# define SYS_lwp_exit SYS_lwpexit
+#endif
+
+#if !defined(SYS_lwp_wait) && defined(SYS_lwpwait)
+# define SYS_lwp_wait SYS_lwpwait
+#endif
+
+#if !defined(SYS_lwp_self) && defined(SYS_lwpself)
+# define SYS_lwp_self SYS_lwpself
+#endif
+
+#if !defined(SYS_lwp_info) && defined(SYS_lwpinfo)
+# define SYS_lwp_info SYS_lwpinfo
+#endif
+
+#if !defined(SYS_lwp_private) && defined(SYS_lwpprivate)
+# define SYS_lwp_private SYS_lwpprivate
+#endif
+
+#if !defined(SYS_lwp_kill) && defined(SYS_lwpkill)
+# define SYS_lwp_kill SYS_lwpkill
+#endif
+
+#if !defined(SYS_lwp_suspend) && defined(SYS_lwpsuspend)
+# define SYS_lwp_suspend SYS_lwpsuspend
+#endif
+
+#if !defined(SYS_lwp_continue) && defined(SYS_lwpcontinue)
+# define SYS_lwp_continue SYS_lwpcontinue
+#endif
+
 /* the name of the proc status struct depends on the implementation */
 #ifdef HAVE_PSTATUS_T
   typedef pstatus_t gdb_prstatus_t;
@@ -65,21 +101,40 @@ regardless of whether or not the actual target has floating point hardware.
 
 /* proc name formats may vary depending on the proc implementation */
 #ifdef HAVE_MULTIPLE_PROC_FDS
-  #ifndef CTL_PROC_NAME_FMT
-  #define CTL_PROC_NAME_FMT "/proc/%d/ctl"
-  #define AS_PROC_NAME_FMT "/proc/%d/as"
-  #define MAP_PROC_NAME_FMT "/proc/%d/map"
-  #define STATUS_PROC_NAME_FMT "/proc/%d/status"
-  #endif
+#  ifndef CTL_PROC_NAME_FMT
+#  define CTL_PROC_NAME_FMT "/proc/%d/ctl"
+#  define AS_PROC_NAME_FMT "/proc/%d/as"
+#  define MAP_PROC_NAME_FMT "/proc/%d/map"
+#  define STATUS_PROC_NAME_FMT "/proc/%d/status"
+#  endif
 #else /* HAVE_MULTIPLE_PROC_FDS */
-  #ifndef CTL_PROC_NAME_FMT
-  #define CTL_PROC_NAME_FMT "/proc/%05d"
-  #define AS_PROC_NAME_FMT "/proc/%05d"
-  #define MAP_PROC_NAME_FMT "/proc/%05d"
-  #define STATUS_PROC_NAME_FMT "/proc/%05d"
-  #endif
+#  ifndef CTL_PROC_NAME_FMT
+#  define CTL_PROC_NAME_FMT "/proc/%05d"
+#  define AS_PROC_NAME_FMT "/proc/%05d"
+#  define MAP_PROC_NAME_FMT "/proc/%05d"
+#  define STATUS_PROC_NAME_FMT "/proc/%05d"
+#  endif
 #endif /* HAVE_MULTIPLE_PROC_FDS */
 
+
+/* These #ifdefs are for sol2.x in particular.  sol2.x has
+   both a "gregset_t" and a "prgregset_t", which have
+   similar uses but different layouts.  sol2.x gdb tries to
+   use prgregset_t (and prfpregset_t) everywhere. */
+
+#ifdef GDB_GREGSET_TYPE
+  typedef GDB_GREGSET_TYPE gdb_gregset_t;
+#else
+  typedef gregset_t gdb_gregset_t;
+#endif
+
+#ifdef GDB_FPREGSET_TYPE
+  typedef GDB_FPREGSET_TYPE gdb_fpregset_t;
+#else
+  typedef fpregset_t gdb_fpregset_t;
+#endif
+
+
 #define MAX_PROC_NAME_SIZE sizeof("/proc/1234567890/status")
 
 extern struct target_ops procfs_ops;           /* Forward declaration */
@@ -113,13 +168,13 @@ struct proc_ctl {
 /* set general registers */
 struct greg_ctl {
         int             cmd;
-        gregset_t       gregset;
+        gdb_gregset_t  gregset;
 };
 
 /* set fp registers */
 struct fpreg_ctl {
         int             cmd;
-        fpregset_t      fpregset;
+        gdb_fpregset_t fpregset;
 };
 
 /* set signals to be traced */
@@ -181,14 +236,17 @@ struct procinfo {
   struct sig_ctl saved_trace;   /* Saved traced signal set */
   struct sys_ctl saved_exitset; /* Saved traced system call exit set */
   struct sys_ctl saved_entryset;/* Saved traced system call entry set */
-  int num_syscall_handlers;    /* Number of syscall handlers currently installed */
-  struct procfs_syscall_handler *syscall_handlers; /* Pointer to list of syscall trap handlers */
+  int num_syscall_handlers;    /* Number of syscall trap handlers
+                                  currently installed */
+                               /* Pointer to list of syscall trap handlers */
+  struct procfs_syscall_handler *syscall_handlers; 
+  int saved_rtnval;            /* return value and status for wait(), */
+  int saved_statval;           /*  as supplied by a syscall handler. */
   int new_child;               /* Non-zero if it's a new thread */
 };
 
 /* List of inferior process information */
 static struct procinfo *procinfo_list = NULL;
-
 static struct pollfd *poll_list; /* pollfds used for waiting on /proc */
 
 static int num_poll_list = 0;  /* Number of entries in poll_list */
@@ -247,6 +305,15 @@ static struct trans pr_flag_table[] =
 #endif
 #if defined (PR_PCOMPAT)
   { PR_PCOMPAT, "PR_PCOMPAT", "Ptrace compatibility mode in effect" },
+#endif
+#if defined (PR_MSACCT)
+  { PR_MSACCT, "PR_MSACCT", "Microstate accounting enabled" },
+#endif
+#if defined (PR_BPTADJ)
+  { PR_BPTADJ, "PR_BPTADJ", "Breakpoint PC adjustment in effect" },
+#endif
+#if defined (PR_ASLWP)
+  { PR_ASLWP, "PR_ASLWP", "Asynchronus signal LWP" },
 #endif
   { 0, NULL, NULL }
 };
@@ -261,9 +328,6 @@ static struct trans pr_why_table[] =
 #if defined (PR_SIGNALLED)
   { PR_SIGNALLED, "PR_SIGNALLED", "Receipt of a traced signal" },
 #endif
-#if defined (PR_FAULTED)
-  { PR_FAULTED, "PR_FAULTED", "Incurred a traced hardware fault" },
-#endif
 #if defined (PR_SYSENTRY)
   { PR_SYSENTRY, "PR_SYSENTRY", "Entry to a traced system call" },
 #endif
@@ -273,8 +337,14 @@ static struct trans pr_why_table[] =
 #if defined (PR_JOBCONTROL)
   { PR_JOBCONTROL, "PR_JOBCONTROL", "Default job control stop signal action" },
 #endif
+#if defined (PR_FAULTED)
+  { PR_FAULTED, "PR_FAULTED", "Incurred a traced hardware fault" },
+#endif
 #if defined (PR_SUSPENDED)
   { PR_SUSPENDED, "PR_SUSPENDED", "Process suspended" },
+#endif
+#if defined (PR_CHECKPOINT)
+  { PR_CHECKPOINT, "PR_CHECKPOINT", "(???)" },
 #endif
   { 0, NULL, NULL }
 };
@@ -464,7 +534,7 @@ static void procfs_attach PARAMS ((char *, int));
 
 static void proc_set_exec_trap PARAMS ((void));
 
-static int procfs_init_inferior PARAMS ((int));
+static void  procfs_init_inferior PARAMS ((int));
 
 static struct procinfo *create_procinfo PARAMS ((int));
 
@@ -502,7 +572,7 @@ static void close_proc_file PARAMS ((struct procinfo *));
 
 static void unconditionally_kill_inferior PARAMS ((struct procinfo *));
 
-static NORETURN void proc_init_failed PARAMS ((struct procinfo *, char *)) ATTR_NORETURN;
+static NORETURN void proc_init_failed PARAMS ((struct procinfo *, char *, int)) ATTR_NORETURN;
 
 static void info_proc PARAMS ((char *, int));
 
@@ -538,8 +608,8 @@ static void notice_signals PARAMS ((struct procinfo *, struct sig_ctl *));
 
 static struct procinfo *find_procinfo PARAMS ((pid_t pid, int okfail));
 
-static int procfs_read_status PARAMS ((struct procinfo *));
 static int procfs_write_pcwstop PARAMS ((struct procinfo *));
+static int procfs_read_status PARAMS ((struct procinfo *));
 static void procfs_write_pckill PARAMS ((struct procinfo *));
 
 typedef int syscall_func_t PARAMS ((struct procinfo *pi, int syscall_num,
@@ -586,14 +656,14 @@ static void procfs_resume PARAMS ((int pid, int step,
 /* External function prototypes that can't be easily included in any
    header file because the args are typedefs in system include files. */
 
-extern void supply_gregset PARAMS ((gregset_t *));
+extern void supply_gregset PARAMS ((gdb_gregset_t *));
 
-extern void fill_gregset PARAMS ((gregset_t *, int));
+extern void fill_gregset PARAMS ((gdb_gregset_t *, int));
 
 #ifdef FP0_REGNUM
-extern void supply_fpregset PARAMS ((fpregset_t *));
+extern void supply_fpregset PARAMS ((gdb_fpregset_t *));
 
-extern void fill_fpregset PARAMS ((fpregset_t *, int));
+extern void fill_fpregset PARAMS ((gdb_fpregset_t *, int));
 #endif
 
 /*
@@ -684,6 +754,22 @@ add_fd (pi)
   num_poll_list++;
 }
 
+/*
+
+LOCAL FUNCTION
+
+       remove_fd -- Remove the fd from the poll/select list
+
+SYNOPSIS
+
+       static void remove_fd (struct procinfo *);
+
+DESCRIPTION
+       
+       Remove the fd of the supplied procinfo from the list of fds used 
+       for poll/select operations.
+ */
+
 static void
 remove_fd (pi)
      struct procinfo *pi;
@@ -811,7 +897,7 @@ procfs_write_pckill (pi)
 static struct procinfo *
 wait_fd ()
 {
-  struct procinfo *pi;
+  struct procinfo *pi, *next_pi;
 #ifndef LOSING_POLL
   int num_fds;
   int i;
@@ -821,6 +907,7 @@ wait_fd ()
                           attached process. */
   set_sigio_trap ();
 
+ wait_again:
 #ifndef LOSING_POLL
   while (1)
     {
@@ -859,19 +946,33 @@ wait_fd ()
 
   for (i = 0; i < num_poll_list && num_fds > 0; i++)
     {
-      if ((poll_list[i].revents & (POLLWRNORM|POLLPRI|POLLERR|POLLHUP|POLLNVAL)) == 0)
+      if (0 == (poll_list[i].revents & 
+               (POLLWRNORM | POLLPRI | POLLERR | POLLHUP | POLLNVAL)))
        continue;
-      for (pi = procinfo_list; pi; pi = pi->next)
+      for (pi = procinfo_list; pi; pi = next_pi)
        {
+         next_pi = pi->next;
          if (poll_list[i].fd == pi->ctl_fd)
            {
-             if (!procfs_read_status(pi))
-               {
-                 print_sys_errmsg (pi->pathname, errno);
-                 error ("procfs_read_status failed");
-               }
-
              num_fds--;
+             if ((poll_list[i].revents & POLLHUP) != 0 ||
+                 !procfs_read_status(pi))
+               { /* The LWP has apparently terminated.  */
+                 if (num_poll_list <= 1)
+                   {
+                     pi->prstatus.pr_flags = 0;
+                     pi->had_event = 1;
+                     break;
+                   }
+                 if (info_verbose)
+                   printf_filtered ("LWP %d exited.\n", 
+                                    (pi->pid >> 16) & 0xffff);
+                 close_proc_file (pi);
+                 if (num_fds != 0)
+                   continue;           /* already another event to process */
+                 else
+                   goto wait_again;    /* wait for another event */
+               }
              pi->had_event = 1;
              break;
            }
@@ -1549,23 +1650,23 @@ init_syscall_table ()
 #if defined (SYS_settimeofday)
   syscall_table[SYS_settimeofday] = "settimeofday";
 #endif
-#if defined (SYS_lwpcreate)
-  syscall_table[SYS_lwpcreate] = "lwpcreate";
+#if defined (SYS_lwp_create)
+  syscall_table[SYS_lwp_create] = "_lwp_create";
 #endif
-#if defined (SYS_lwpexit)
-  syscall_table[SYS_lwpexit] = "lwpexit";
+#if defined (SYS_lwp_exit)
+  syscall_table[SYS_lwp_exit] = "_lwp_exit";
 #endif
-#if defined (SYS_lwpwait)
-  syscall_table[SYS_lwpwait] = "lwpwait";
+#if defined (SYS_lwp_wait)
+  syscall_table[SYS_lwp_wait] = "_lwp_wait";
 #endif
-#if defined (SYS_lwpself)
-  syscall_table[SYS_lwpself] = "lwpself";
+#if defined (SYS_lwp_self)
+  syscall_table[SYS_lwp_self] = "_lwp_self";
 #endif
-#if defined (SYS_lwpinfo)
-  syscall_table[SYS_lwpinfo] = "lwpinfo";
+#if defined (SYS_lwp_info)
+  syscall_table[SYS_lwp_info] = "_lwp_info";
 #endif
-#if defined (SYS_lwpprivate)
-  syscall_table[SYS_lwpprivate] = "lwpprivate";
+#if defined (SYS_lwp_private)
+  syscall_table[SYS_lwp_private] = "_lwp_private";
 #endif
 #if defined (SYS_processor_bind)
   syscall_table[SYS_processor_bind] = "processor_bind";
@@ -1600,8 +1701,8 @@ init_syscall_table ()
 #if defined (SYS_ftruncate)
   syscall_table[SYS_ftruncate] = "ftruncate";
 #endif
-#if defined (SYS_lwpkill)
-  syscall_table[SYS_lwpkill] = "lwpkill";
+#if defined (SYS_lwp_kill)
+  syscall_table[SYS_lwp_kill] = "_lwp_kill";
 #endif
 #if defined (SYS_sigwait)
   syscall_table[SYS_sigwait] = "sigwait";
@@ -1630,11 +1731,11 @@ init_syscall_table ()
 #if defined (SYS_getksym)
   syscall_table[SYS_getksym] = "getksym";
 #endif
-#if defined (SYS_lwpsuspend)
-  syscall_table[SYS_lwpsuspend] = "lwpsuspend";
+#if defined (SYS_lwp_suspend)
+  syscall_table[SYS_lwp_suspend] = "_lwp_suspend";
 #endif
-#if defined (SYS_lwpcontinue)
-  syscall_table[SYS_lwpcontinue] = "lwpcontinue";
+#if defined (SYS_lwp_continue)
+  syscall_table[SYS_lwp_continue] = "_lwp_continue";
 #endif
 #if defined (SYS_priocntllst)
   syscall_table[SYS_priocntllst] = "priocntllst";
@@ -1643,14 +1744,68 @@ init_syscall_table ()
   syscall_table[SYS_sleep] = "sleep";
 #endif
 #if defined (SYS_lwp_sema_wait)
-  syscall_table[SYS_lwp_sema_wait] = "lwp_sema_wait";
+  syscall_table[SYS_lwp_sema_wait] = "_lwp_sema_wait";
 #endif
 #if defined (SYS_lwp_sema_post)
-  syscall_table[SYS_lwp_sema_post] = "lwp_sema_post";
+  syscall_table[SYS_lwp_sema_post] = "_lwp_sema_post";
 #endif
 #if defined (SYS_lwp_sema_trywait)
   syscall_table[SYS_lwp_sema_trywait] = "lwp_sema_trywait";
 #endif
+#if defined(SYS_fstatvfs64)
+  syscall_table[SYS_fstatvfs64] = "fstatvfs64";
+#endif
+#if defined(SYS_statvfs64)
+  syscall_table[SYS_statvfs64] = "statvfs64";
+#endif
+#if defined(SYS_ftruncate64)
+  syscall_table[SYS_ftruncate64] = "ftruncate64";
+#endif
+#if defined(SYS_truncate64)
+  syscall_table[SYS_truncate64] = "truncate64";
+#endif
+#if defined(SYS_getrlimit64)
+  syscall_table[SYS_getrlimit64] = "getrlimit64";
+#endif
+#if defined(SYS_setrlimit64)
+  syscall_table[SYS_setrlimit64] = "setrlimit64";
+#endif
+#if defined(SYS_lseek64)
+  syscall_table[SYS_lseek64] = "lseek64";
+#endif
+#if defined(SYS_mmap64)
+  syscall_table[SYS_mmap64] = "mmap64";
+#endif
+#if defined(SYS_pread64)
+  syscall_table[SYS_pread64] = "pread64";
+#endif
+#if defined(SYS_creat64)
+  syscall_table[SYS_creat64] = "creat64";
+#endif
+#if defined(SYS_dshmsys)
+  syscall_table[SYS_dshmsys] = "dshmsys";
+#endif
+#if defined(SYS_invlpg)
+  syscall_table[SYS_invlpg] = "invlpg";
+#endif
+#if defined(SYS_cg_ids)
+  syscall_table[SYS_cg_ids] = "cg_ids";
+#endif
+#if defined(SYS_cg_processors)
+  syscall_table[SYS_cg_processors] = "cg_processors";
+#endif
+#if defined(SYS_cg_info)
+  syscall_table[SYS_cg_info] = "cg_info";
+#endif
+#if defined(SYS_cg_bind)
+  syscall_table[SYS_cg_bind] = "cg_bind";
+#endif
+#if defined(SYS_cg_current)
+  syscall_table[SYS_cg_current] = "cg_current";
+#endif
+#if defined(SYS_cg_memloc)
+  syscall_table[SYS_cg_memloc] = "cg_memloc";
+#endif
 }
 
 /*
@@ -1863,7 +2018,7 @@ procfs_store_registers (regno)
       procfs_read_status (pi);
       memcpy ((char *) &greg.gregset,
          (char *) &pi->prstatus.pr_lwp.pr_context.uc_mcontext.gregs,
-         sizeof (gregset_t));
+         sizeof (gdb_gregset_t));
     }
   fill_gregset (&greg.gregset, regno);
   greg.cmd = PCSREG;
@@ -1889,7 +2044,7 @@ procfs_store_registers (regno)
       procfs_read_status (pi);
       memcpy ((char *) &fpreg.fpregset,
           (char *) &pi->prstatus.pr_lwp.pr_context.uc_mcontext.fpregs,
-          sizeof (fpregset_t));
+          sizeof (gdb_fpregset_t));
     }
   fill_fpregset (&fpreg.fpregset, regno);
   fpreg.cmd = PCSFPREG;
@@ -1911,17 +2066,17 @@ procfs_store_registers (regno)
 
 LOCAL FUNCTION
 
-       create_procinfo - initialize access to a /proc entry
+       init_procinfo - setup a procinfo struct and connect it to a process
 
 SYNOPSIS
 
-       struct procinfo * create_procinfo (int pid)
+       struct procinfo * init_procinfo (int pid)
 
 DESCRIPTION
 
        Allocate a procinfo structure, open the /proc file and then set up the
        set of signals and faults that are to be traced.  Returns a pointer to
-       the new procinfo structure.
+       the new procinfo structure.  
 
 NOTES
 
@@ -1931,21 +2086,18 @@ NOTES
  */
 
 static struct procinfo *
-create_procinfo (pid)
+init_procinfo (pid, kill)
      int pid;
+     int kill;
 {
-  struct procinfo *pi;
+  struct procinfo *pi = (struct procinfo *) 
+    xmalloc (sizeof (struct procinfo));
   struct sig_ctl  sctl;
   struct flt_ctl  fctl;
 
-  pi = find_procinfo (pid, 1);
-  if (pi != NULL)
-    return pi;                 /* All done!  It already exists */
-
-  pi = (struct procinfo *) xmalloc (sizeof (struct procinfo));
-
+  memset ((char *) pi, 0, sizeof (*pi));
   if (!open_proc_file (pid, pi, O_RDWR, 1))
-    proc_init_failed (pi, "can't open process file");
+    proc_init_failed (pi, "can't open process file", kill);
 
   /* open_proc_file may modify pid.  */
 
@@ -1958,14 +2110,34 @@ create_procinfo (pid)
 
   add_fd (pi);                 /* Add to list for poll/select */
 
-  pi->num_syscall_handlers = 0;
-  pi->syscall_handlers = NULL;
+  /*  Remember some things about the inferior that we will, or might, change
+      so that we can restore them when we detach. */
 #ifdef UNIXWARE
+  memcpy ((char *) &pi->saved_trace.sigset,
+         (char *) &pi->prstatus.pr_sigtrace, sizeof (sigset_t));
+  memcpy ((char *) &pi->saved_fltset.fltset,
+         (char *) &pi->prstatus.pr_flttrace, sizeof (fltset_t));
+  memcpy ((char *) &pi->saved_entryset.sysset,
+         (char *) &pi->prstatus.pr_sysentry, sizeof (sysset_t));
+  memcpy ((char *) &pi->saved_exitset.sysset,
+         (char *) &pi->prstatus.pr_sysexit, sizeof (sysset_t));
+
+  /* Set up trace and fault sets, as gdb expects them. */
+
   prfillset (&sctl.sigset);
-  notice_signals (pi, &sctl); 
+  notice_signals (pi, &sctl);
   prfillset (&fctl.fltset);
   prdelset (&fctl.fltset, FLTPAGE);
-#else /* UNIXWARE */
+
+#else /* ! UNIXWARE */
+  ioctl (pi->ctl_fd, PIOCGTRACE, &pi->saved_trace.sigset);
+  ioctl (pi->ctl_fd, PIOCGHOLD, &pi->saved_sighold.sigset);
+  ioctl (pi->ctl_fd, PIOCGFAULT, &pi->saved_fltset.fltset);
+  ioctl (pi->ctl_fd, PIOCGENTRY, &pi->saved_entryset.sysset);
+  ioctl (pi->ctl_fd, PIOCGEXIT, &pi->saved_exitset.sysset);
+  
+  /* Set up trace and fault sets, as gdb expects them. */
+  
   memset ((char *) &pi->prrun, 0, sizeof (pi->prrun));
   prfillset (&pi->prrun.pr_trace);
   procfs_notice_signals (pid);
@@ -1977,24 +2149,63 @@ create_procinfo (pid)
 #endif /* UNIXWARE */
 
   if (!procfs_read_status (pi))
-    proc_init_failed (pi, "procfs_read_status failed");
+    proc_init_failed (pi, "procfs_read_status failed", kill);
 
-/* A bug in Solaris (2.5 at least) causes PIOCWSTOP to hang on LWPs that are
-   already stopped, even if they all have PR_ASYNC set.  */
+  return pi;
+}
+
+/*
+
+LOCAL FUNCTION
+
+       create_procinfo - initialize access to a /proc entry
+
+SYNOPSIS
+
+       struct procinfo * create_procinfo (int pid)
+
+DESCRIPTION
+
+       Allocate a procinfo structure, open the /proc file and then set up the
+       set of signals and faults that are to be traced.  Returns a pointer to
+       the new procinfo structure.
+
+NOTES
+
+       If proc_init_failed ever gets called, control returns to the command
+       processing loop via the standard error handling code.
+
+ */
+
+static struct procinfo *
+create_procinfo (pid)
+     int pid;
+{
+  struct procinfo *pi;
+  struct sig_ctl  sctl;
+  struct flt_ctl  fctl;
+
+  pi = find_procinfo (pid, 1);
+  if (pi != NULL)
+    return pi;                 /* All done!  It already exists */
+
+  pi = init_procinfo (pid, 1);
 
 #ifndef UNIXWARE
+/* A bug in Solaris (2.5 at least) causes PIOCWSTOP to hang on LWPs that are
+   already stopped, even if they all have PR_ASYNC set.  */
   if (!(pi->prstatus.pr_flags & PR_STOPPED))
 #endif
     if (!procfs_write_pcwstop (pi))
-      proc_init_failed (pi, "procfs_write_pcwstop failed");
+      proc_init_failed (pi, "procfs_write_pcwstop failed", 1);
 
 #ifdef PROCFS_USE_READ_WRITE
   fctl.cmd = PCSFAULT;
   if (write (pi->ctl_fd, (char *) &fctl, sizeof (struct flt_ctl)) < 0)
-    proc_init_failed (pi, "PCSFAULT failed");
+    proc_init_failed (pi, "PCSFAULT failed", 1);
 #else
   if (ioctl (pi->ctl_fd, PIOCSFAULT, &pi->prrun.pr_fault) < 0)
-    proc_init_failed (pi, "PIOCSFAULT failed");
+    proc_init_failed (pi, "PIOCSFAULT failed", 1);
 #endif
 
   return pi;
@@ -2030,15 +2241,47 @@ procfs_exit_handler (pi, syscall_num, why, rtnvalp, statvalp)
      int *rtnvalp;
      int *statvalp;
 {
+  struct procinfo *temp_pi, *next_pi;
+  struct proc_ctl pctl;
+
+#ifdef UNIXWARE
+  pctl.cmd = PCRUN;
+  pctl.data = PRCFAULT;
+#else
   pi->prrun.pr_flags = PRCFAULT;
+#endif
 
+#ifdef PROCFS_USE_READ_WRITE
+  if (write (pi->ctl_fd, (char *)&pctl, sizeof (struct proc_ctl)) < 0)
+#else
   if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
+#endif
     perror_with_name (pi->pathname);
 
-  *rtnvalp = wait (statvalp);
-  if (*rtnvalp >= 0)
-    *rtnvalp = pi->pid;
+  if (attach_flag)
+    {
+      /* Claim it exited (don't call wait). */
+      if (info_verbose)
+       printf_filtered ("(attached process has exited)\n");
+      *statvalp = 0;
+      *rtnvalp  = inferior_pid;
+    }
+  else
+    {
+      *rtnvalp = wait (statvalp);
+      if (*rtnvalp >= 0)
+       *rtnvalp = pi->pid;
+    }
 
+  /* Close ALL open proc file handles,
+     except the one that called SYS_exit. */
+  for (temp_pi = procinfo_list; temp_pi; temp_pi = next_pi)
+    {
+      next_pi = temp_pi->next;
+      if (temp_pi == pi)
+       continue;               /* Handled below */
+      close_proc_file (temp_pi);
+    }
   return 1;
 }
 
@@ -2206,43 +2449,28 @@ procfs_fork_handler (pi, syscall_num, why, rtnvalp, statvalp)
 
 LOCAL FUNCTION
 
-       procfs_init_inferior - initialize target vector and access to a
-       /proc entry
+       procfs_set_inferior_syscall_traps - setup the syscall traps 
 
 SYNOPSIS
 
-       int procfs_init_inferior (int pid)
+       void procfs_set_inferior_syscall_traps (struct procinfo *pip)
 
 DESCRIPTION
 
-       When gdb starts an inferior, this function is called in the parent
-       process immediately after the fork.  It waits for the child to stop
-       on the return from the exec system call (the child itself takes care
-       of ensuring that this is set up), then sets up the set of signals
-       and faults that are to be traced.  Returns the pid, which may have had
-       the thread-id added to it.
-
-NOTES
-
-       If proc_init_failed ever gets called, control returns to the command
-       processing loop via the standard error handling code.
+       Called for each "procinfo" (process, thread, or LWP) in the
+       inferior, to register for notification of and handlers for
+       syscall traps in the inferior.
 
  */
 
-static int
-procfs_init_inferior (pid)
-     int pid;
+static void
+procfs_set_inferior_syscall_traps (pip)
+     struct procinfo *pip;
 {
-  struct procinfo *pip;
-
-  push_target (&procfs_ops);
-
-  pip = create_procinfo (pid);
-
-#ifndef PIOCSSPCACT
   procfs_set_syscall_trap (pip, SYS_exit, PROCFS_SYSCALL_ENTRY,
                           procfs_exit_handler);
 
+#ifndef PRFS_STOPEXEC
 #ifdef SYS_exec
   procfs_set_syscall_trap (pip, SYS_exec, PROCFS_SYSCALL_EXIT,
                           procfs_exec_handler);
@@ -2255,7 +2483,7 @@ procfs_init_inferior (pid)
   procfs_set_syscall_trap (pip, SYS_execve, PROCFS_SYSCALL_EXIT,
                           procfs_exec_handler);
 #endif
-#endif  /* PIOCSSPCACT */
+#endif  /* PRFS_STOPEXEC */
 
   /* Setup traps on exit from sproc() */
 
@@ -2280,6 +2508,46 @@ procfs_init_inferior (pid)
   procfs_set_syscall_trap (pip, SYS_lwp_create, PROCFS_SYSCALL_EXIT,
                           procfs_lwp_creation_handler);
 #endif
+}
+
+/*
+
+LOCAL FUNCTION
+
+       procfs_init_inferior - initialize target vector and access to a
+       /proc entry
+
+SYNOPSIS
+
+       void procfs_init_inferior (int pid)
+
+DESCRIPTION
+
+       When gdb starts an inferior, this function is called in the parent
+       process immediately after the fork.  It waits for the child to stop
+       on the return from the exec system call (the child itself takes care
+       of ensuring that this is set up), then sets up the set of signals
+       and faults that are to be traced.  Returns the pid, which may have had
+       the thread-id added to it.
+
+NOTES
+
+       If proc_init_failed ever gets called, control returns to the command
+       processing loop via the standard error handling code.
+
+ */
+
+static void 
+procfs_init_inferior (pid)
+     int pid;
+{
+  struct procinfo *pip;
+
+  push_target (&procfs_ops);
+
+  pip = create_procinfo (pid);
+
+  procfs_set_inferior_syscall_traps (pip);
 
   /* create_procinfo may change the pid, so we have to update inferior_pid
      here before calling other gdb routines that need the right pid.  */
@@ -2295,8 +2563,6 @@ procfs_init_inferior (pid)
   /* One trap to exec the shell, one to exec the program being debugged.  */
   startup_inferior (2);
 #endif
-
-  return pid;
 }
 
 /*
@@ -2340,6 +2606,10 @@ procfs_notice_signals (pid)
 #endif
 
   notice_signals (pi, &sctl);
+
+#ifndef UNIXWARE
+  pi->prrun.pr_trace = sctl.sigset;
+#endif
 }
 
 static void
@@ -2426,12 +2696,9 @@ proc_set_exec_trap ()
   premptyset (&exitset.sysset);
   premptyset (&entryset.sysset);
 
-#ifdef PIOCSSPCACT
+#ifdef PRFS_STOPEXEC
   /* Under Alpha OSF/1 we have to use a PIOCSSPCACT ioctl to trace
-     exits from exec system calls because of the user level loader.
-     Starting with OSF/1-4.0, tracing the entry to the exit system
-     call no longer works. So we have to use PRFS_STOPTERM to trace
-     termination of the inferior.  */
+     exits from exec system calls because of the user level loader.  */
   {
     int prfs_flags;
 
@@ -2441,7 +2708,7 @@ proc_set_exec_trap ()
        gdb_flush (gdb_stderr);
        _exit (127);
       }
-    prfs_flags |= PRFS_STOPEXEC | PRFS_STOPTERM;
+    prfs_flags |= PRFS_STOPEXEC;
     if (ioctl (fd, PIOCSSPCACT, &prfs_flags) < 0)
       {
        perror (procname);
@@ -2449,7 +2716,7 @@ proc_set_exec_trap ()
        _exit (127);
       }
   }
-#else /* PIOCSSPCACT */
+#else /* PRFS_STOPEXEC */
   /* GW: Rationale...
      Not all systems with /proc have all the exec* syscalls with the same
      names.  On the SGI, for example, there is no SYS_exec, but there
@@ -2476,6 +2743,7 @@ proc_set_exec_trap ()
       gdb_flush (gdb_stderr);
       _exit (127);
     }
+#endif /* PRFS_STOPEXEC */
 
   praddset (&entryset.sysset, SYS_exit);
 
@@ -2490,7 +2758,6 @@ proc_set_exec_trap ()
       gdb_flush (gdb_stderr);
       _exit (126);
     }
-#endif /* PIOCSSPCACT */
 
   /* Turn off inherit-on-fork flag so that all grand-children of gdb
      start with tracing flags cleared. */
@@ -2502,6 +2769,8 @@ proc_set_exec_trap ()
 
   modify_run_on_last_close_flag (fd, 1);
 
+#ifndef UNIXWARE       /* since this is a solaris-ism, we don't want it */
+                       /* NOTE: revisit when doing thread support for UW */
 #ifdef PR_ASYNC
   {
     long pr_flags;
@@ -2521,6 +2790,7 @@ proc_set_exec_trap ()
 #endif
   }
 #endif /* PR_ASYNC */
+#endif /* !UNIXWARE */
 }
 
 /*
@@ -2669,6 +2939,7 @@ proc_base_address (addr)
 
 #endif /* 0 */
 
+#ifndef UNIXWARE
 /*
 
 LOCAL FUNCTION
@@ -2707,7 +2978,7 @@ proc_address_to_fd (pi, addr, complain)
     }
   return (fd);
 }
-
+#endif /* !UNIXWARE */
 
 /* Attach to process PID, then initialize for debugging it
    and wait for the trace-trap that results from attaching.  */
@@ -2842,131 +3113,93 @@ do_attach (pid)
   struct procinfo *pi;
   struct sig_ctl sctl;
   struct flt_ctl fctl;
+  int nlwp, *lwps;
 
-  pi = (struct procinfo *) xmalloc (sizeof (struct procinfo));
-
-  if (!open_proc_file (pid, pi, O_RDWR, 1))
-    {
-      free (pi);
-      perror_with_name (pi->pathname);
-      /* NOTREACHED */
-    }
-  
-  pid = pi -> pid;
-
-  /* Add new process to process info list */
-
-  pi->next = procinfo_list;
-  procinfo_list = pi;
+  pi  = init_procinfo (pid, 0);
 
-  add_fd (pi);                 /* Add to list for poll/select */
+#ifdef PIOCLWPIDS
+  nlwp = pi->prstatus.pr_nlwp;
+  lwps = alloca ((2 * nlwp + 2) * sizeof (id_t));
 
-  /*  Get current status of process and if it is not already stopped,
-      then stop it.  Remember whether or not it was stopped when we first
-      examined it. */
-  if (!procfs_read_status (pi))
+  if (ioctl (pi->ctl_fd, PIOCLWPIDS, lwps))
     {
-      print_sys_errmsg (pi->pathname, errno);
-      close_proc_file (pi);
-      error ("procfs_read_status failed");
+      print_sys_errmsg (pi -> pathname, errno);
+      error ("PIOCLWPIDS failed");
     }
-#ifdef UNIXWARE
-  if (pi->prstatus.pr_lwp.pr_flags & (PR_STOPPED | PR_ISTOP))
-#else
-  if (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
+#else /* PIOCLWPIDS */
+  nlwp = 1;
+  lwps = alloca ((2 * nlwp + 2) * sizeof *lwps);
+  lwps[0] = 0;
 #endif
+  for (; nlwp > 0; nlwp--, lwps++)
     {
-      pi->was_stopped = 1;
-    }
-  else
-    {
-      pi->was_stopped = 0;
-      if (1 || query ("Process is currently running, stop it? "))
-       {
-         long cmd;
-         /* Make it run again when we close it.  */
-
-         modify_run_on_last_close_flag (pi->ctl_fd, 1);
+      /* First one has already been created above.  */
+      if ((pi = find_procinfo ((*lwps << 16) | pid, 1)) == 0)
+       pi = init_procinfo ((*lwps << 16) | pid, 0);
 
-#ifdef PROCFS_USE_READ_WRITE
-          cmd = PCSTOP;
-          if (write (pi->ctl_fd, (char *) &cmd, sizeof (long)) < 0)
-#else
-         if (ioctl (pi->ctl_fd, PIOCSTOP, &pi->prstatus) < 0)
-#endif
-           {
-             print_sys_errmsg (pi->pathname, errno);
-             close_proc_file (pi);
-             error ("PIOCSTOP failed");
-           }
 #ifdef UNIXWARE
-          if (!procfs_read_status (pi))
-            {
-              print_sys_errmsg (pi->pathname, errno);
-              close_proc_file (pi);
-              error ("procfs_read_status failed");
-            } 
+      if (pi->prstatus.pr_lwp.pr_flags & (PR_STOPPED | PR_ISTOP))
+#else
+      if (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
 #endif
-         pi->nopass_next_sigstop = 1;
+       {
+         pi->was_stopped = 1;
        }
       else
        {
-         printf_unfiltered ("Ok, gdb will wait for %s to stop.\n", target_pid_to_str (pid));
+         pi->was_stopped = 0;
+         if (1 || query ("Process is currently running, stop it? "))
+           {
+             long cmd;
+             /* Make it run again when we close it.  */
+             modify_run_on_last_close_flag (pi->ctl_fd, 1);
+#ifdef PROCFS_USE_READ_WRITE
+             cmd = PCSTOP;
+             if (write (pi->ctl_fd, (char *) &cmd, sizeof (long)) < 0)
+#else
+             if (ioctl (pi->ctl_fd, PIOCSTOP, &pi->prstatus) < 0)
+#endif
+               {
+                 print_sys_errmsg (pi->pathname, errno);
+                 close_proc_file (pi);
+                 error ("PIOCSTOP failed");
+               }
+#ifdef UNIXWARE
+             if (!procfs_read_status (pi))
+               {
+                 print_sys_errmsg (pi->pathname, errno);
+                 close_proc_file (pi);
+                 error ("procfs_read_status failed");
+               } 
+#endif
+             pi->nopass_next_sigstop = 1;
+           }
+         else
+           {
+             printf_unfiltered ("Ok, gdb will wait for %s to stop.\n", 
+                                target_pid_to_str (pi->pid));
+           }
        }
-    }
 
-  /*  Remember some things about the inferior that we will, or might, change
-      so that we can restore them when we detach. */
 #ifdef PROCFS_USE_READ_WRITE
-  memcpy ((char *) &pi->saved_trace.sigset,
-               (char *) &pi->prstatus.pr_sigtrace, sizeof (sigset_t));
-  memcpy ((char *) &pi->saved_fltset.fltset,
-                (char *) &pi->prstatus.pr_flttrace, sizeof (fltset_t));
-  memcpy ((char *) &pi->saved_entryset.sysset,
-                (char *) &pi->prstatus.pr_sysentry, sizeof (sysset_t));
-  memcpy ((char *) &pi->saved_exitset.sysset,
-                (char *) &pi->prstatus.pr_sysexit, sizeof (sysset_t));
-
-  /* Set up trace and fault sets, as gdb expects them. */
-
-  prfillset (&sctl.sigset);
-  notice_signals (pi, &sctl);
-  prfillset (&fctl.fltset);
-  prdelset (&fctl.fltset, FLTPAGE);
-
-  fctl.cmd = PCSFAULT;
-  if (write (pi->ctl_fd, (char *) &fctl, sizeof (struct flt_ctl)) < 0)
-    print_sys_errmsg ("PCSFAULT failed", errno);
+      fctl.cmd = PCSFAULT;
+      if (write (pi->ctl_fd, (char *) &fctl, sizeof (struct flt_ctl)) < 0)
+       print_sys_errmsg ("PCSFAULT failed", errno);
 #else /* PROCFS_USE_READ_WRITE */
-  ioctl (pi->ctl_fd, PIOCGTRACE, &pi->saved_trace.sigset);
-  ioctl (pi->ctl_fd, PIOCGHOLD, &pi->saved_sighold.sigset);
-  ioctl (pi->ctl_fd, PIOCGFAULT, &pi->saved_fltset.fltset);
-  ioctl (pi->ctl_fd, PIOCGENTRY, &pi->saved_entryset.sysset);
-  ioctl (pi->ctl_fd, PIOCGEXIT, &pi->saved_exitset.sysset);
-  
-  /* Set up trace and fault sets, as gdb expects them. */
-  
-  memset (&pi->prrun, 0, sizeof (pi->prrun));
-  prfillset (&pi->prrun.pr_trace);
-  procfs_notice_signals (pid);
-  prfillset (&pi->prrun.pr_fault);
-  prdelset (&pi->prrun.pr_fault, FLTPAGE);
-
-#ifdef PROCFS_DONT_TRACE_FAULTS
-  premptyset (&pi->prrun.pr_fault);
-#endif
-
-  if (ioctl (pi->ctl_fd, PIOCSFAULT, &pi->prrun.pr_fault))
-    {
-      print_sys_errmsg ("PIOCSFAULT failed", errno);
-    }
-  if (ioctl (pi->ctl_fd, PIOCSTRACE, &pi->prrun.pr_trace))
-    {
-      print_sys_errmsg ("PIOCSTRACE failed", errno);
-    }
+      if (ioctl (pi->ctl_fd, PIOCSFAULT, &pi->prrun.pr_fault))
+       {
+         print_sys_errmsg ("PIOCSFAULT failed", errno);
+       }
+      if (ioctl (pi->ctl_fd, PIOCSTRACE, &pi->prrun.pr_trace))
+       {
+         print_sys_errmsg ("PIOCSTRACE failed", errno);
+       }
+      add_thread (pi->pid);
+      procfs_set_inferior_syscall_traps (pi);
 #endif /* PROCFS_USE_READ_WRITE */
+    }
   attach_flag = 1;
-  return (pid);
+  return (pi->pid);
 }
 
 /*
@@ -3004,106 +3237,107 @@ do_detach (signal)
 {
   struct procinfo *pi;
 
-  pi = current_procinfo;
-
-  if (signal)
+  for (pi = procinfo_list; pi; pi = pi->next)
     {
-      set_proc_siginfo (pi, signal);
-    }
+      if (signal)
+       {
+         set_proc_siginfo (pi, signal);
+       }
 #ifdef PROCFS_USE_READ_WRITE
-  pi->saved_exitset.cmd = PCSEXIT;
-  if (write (pi->ctl_fd, (char *) &pi->saved_exitset,
-       sizeof (struct sys_ctl)) < 0)
+      pi->saved_exitset.cmd = PCSEXIT;
+      if (write (pi->ctl_fd, (char *) &pi->saved_exitset,
+                sizeof (struct sys_ctl)) < 0)
 #else
-  if (ioctl (pi->ctl_fd, PIOCSEXIT, &pi->saved_exitset.sysset) < 0)
+       if (ioctl (pi->ctl_fd, PIOCSEXIT, &pi->saved_exitset.sysset) < 0)
 #endif
-    {
-      print_sys_errmsg (pi->pathname, errno);
-      printf_unfiltered ("PIOCSEXIT failed.\n");
-    }
+         {
+           print_sys_errmsg (pi->pathname, errno);
+           printf_unfiltered ("PIOCSEXIT failed.\n");
+         }
 #ifdef PROCFS_USE_READ_WRITE
-  pi->saved_entryset.cmd = PCSENTRY;
-  if (write (pi->ctl_fd, (char *) &pi->saved_entryset,
-        sizeof (struct sys_ctl)) < 0)
+      pi->saved_entryset.cmd = PCSENTRY;
+      if (write (pi->ctl_fd, (char *) &pi->saved_entryset,
+                sizeof (struct sys_ctl)) < 0)
 #else
-  if (ioctl (pi->ctl_fd, PIOCSENTRY, &pi->saved_entryset.sysset) < 0)
+       if (ioctl (pi->ctl_fd, PIOCSENTRY, &pi->saved_entryset.sysset) < 0)
 #endif
-    {
-      print_sys_errmsg (pi->pathname, errno);
-      printf_unfiltered ("PIOCSENTRY failed.\n");
-    }
+         {
+           print_sys_errmsg (pi->pathname, errno);
+           printf_unfiltered ("PIOCSENTRY failed.\n");
+         }
 #ifdef PROCFS_USE_READ_WRITE
-  pi->saved_trace.cmd = PCSTRACE;
-  if (write (pi->ctl_fd, (char *) &pi->saved_trace,
-        sizeof (struct sig_ctl)) < 0)
+      pi->saved_trace.cmd = PCSTRACE;
+      if (write (pi->ctl_fd, (char *) &pi->saved_trace,
+                sizeof (struct sig_ctl)) < 0)
 #else
-  if (ioctl (pi->ctl_fd, PIOCSTRACE, &pi->saved_trace.sigset) < 0)
+       if (ioctl (pi->ctl_fd, PIOCSTRACE, &pi->saved_trace.sigset) < 0)
 #endif
-    {
-      print_sys_errmsg (pi->pathname, errno);
-      printf_unfiltered ("PIOCSTRACE failed.\n");
-    }
+         {
+           print_sys_errmsg (pi->pathname, errno);
+           printf_unfiltered ("PIOCSTRACE failed.\n");
+         }
 #ifndef UNIXWARE
-  if (ioctl (pi->ctl_fd, PIOCSHOLD, &pi->saved_sighold.sigset) < 0)
-    {
-      print_sys_errmsg (pi->pathname, errno);
-      printf_unfiltered ("PIOSCHOLD failed.\n");
-    }
+      if (ioctl (pi->ctl_fd, PIOCSHOLD, &pi->saved_sighold.sigset) < 0)
+       {
+         print_sys_errmsg (pi->pathname, errno);
+         printf_unfiltered ("PIOSCHOLD failed.\n");
+       }
 #endif
 #ifdef PROCFS_USE_READ_WRITE
-    pi->saved_fltset.cmd = PCSFAULT;
-  if (write (pi->ctl_fd, (char *) &pi->saved_fltset,
-        sizeof (struct flt_ctl)) < 0)
+      pi->saved_fltset.cmd = PCSFAULT;
+      if (write (pi->ctl_fd, (char *) &pi->saved_fltset,
+                sizeof (struct flt_ctl)) < 0)
 #else
-  if (ioctl (pi->ctl_fd, PIOCSFAULT, &pi->saved_fltset.fltset) < 0)
+      if (ioctl (pi->ctl_fd, PIOCSFAULT, &pi->saved_fltset.fltset) < 0)
 #endif
-    {
-      print_sys_errmsg (pi->pathname, errno);
-      printf_unfiltered ("PIOCSFAULT failed.\n");
-    }
-  if (!procfs_read_status (pi))
-    {
-      print_sys_errmsg (pi->pathname, errno);
-      printf_unfiltered ("procfs_read_status failed.\n");
-    }
-  else
-    {
+       {
+         print_sys_errmsg (pi->pathname, errno);
+         printf_unfiltered ("PIOCSFAULT failed.\n");
+       }
+      if (!procfs_read_status (pi))
+       {
+         print_sys_errmsg (pi->pathname, errno);
+         printf_unfiltered ("procfs_read_status failed.\n");
+       }
+      else
+       {
 #ifdef UNIXWARE
-      if (signal || (pi->prstatus.pr_lwp.pr_flags & (PR_STOPPED | PR_ISTOP)))
+         if (signal || (pi->prstatus.pr_lwp.pr_flags & (PR_STOPPED | PR_ISTOP)))
 #else
-      if (signal || (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)))
+         if (signal || (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)))
 #endif
-       {
-          long cmd;
-          struct proc_ctl pctl;
-
-         if (signal || !pi->was_stopped ||
-             query ("Was stopped when attached, make it runnable again? "))
            {
-             /* Clear any pending signal if we want to detach without
-                a signal.  */
-             if (signal == 0)
-               set_proc_siginfo (pi, signal);
+             long cmd;
+             struct proc_ctl pctl;
+
+             if (signal || !pi->was_stopped ||
+                 query ("Was stopped when attached, make it runnable again? "))
+               {
+                 /* Clear any pending signal if we want to detach without
+                    a signal.  */
+                 if (signal == 0)
+                   set_proc_siginfo (pi, signal);
 
-             /* Clear any fault that might have stopped it.  */
+                 /* Clear any fault that might have stopped it.  */
 #ifdef PROCFS_USE_READ_WRITE
-              cmd = PCCFAULT;
-              if (write (pi->ctl_fd, (char *) &cmd, sizeof (long)) < 0)
+                 cmd = PCCFAULT;
+                 if (write (pi->ctl_fd, (char *) &cmd, sizeof (long)) < 0)
 #else
-             if (ioctl (pi->ctl_fd, PIOCCFAULT, 0))
+                 if (ioctl (pi->ctl_fd, PIOCCFAULT, 0))
 #endif
-               {
-                 print_sys_errmsg (pi->pathname, errno);
-                 printf_unfiltered ("PIOCCFAULT failed.\n");
-               }
+                   {
+                     print_sys_errmsg (pi->pathname, errno);
+                     printf_unfiltered ("PIOCCFAULT failed.\n");
+                   }
 
-             /* Make it run again when we close it.  */
+                 /* Make it run again when we close it.  */
 
-             modify_run_on_last_close_flag (pi->ctl_fd, 1);
+                 modify_run_on_last_close_flag (pi->ctl_fd, 1);
+               }
            }
        }
+      close_proc_file (pi);
     }
-  close_proc_file (pi);
   attach_flag = 0;
 }
 
@@ -3131,7 +3365,6 @@ do_detach (signal)
 
     FIXME:  Investigate why wait() seems to have problems with programs
     being control by /proc routines.  */
-
 static int
 procfs_wait (pid, ourstatus)
      int pid;
@@ -3145,32 +3378,67 @@ procfs_wait (pid, ourstatus)
   struct procinfo *pi;
   struct proc_ctl pctl;
 
-#ifndef UNIXWARE
-  if (pid != -1)               /* Non-specific process? */
-    pi = NULL;
-  else
-    for (pi = procinfo_list; pi; pi = pi->next)
-      if (pi->had_event)
-       break;
+scan_again:
 
-  if (!pi)
+  /* handle all syscall events first, otherwise we might not
+     notice a thread was created until too late. */
+
+  for (pi = procinfo_list; pi; pi = pi->next)
     {
-    wait_again:
+      if (!pi->had_event)
+       continue;
 
-      if (pi)
-       pi->had_event = 0;
+#ifdef UNIXWARE
+      if (! (pi->prstatus.pr_lwp.pr_flags & (PR_STOPPED | PR_ISTOP)) )
+       continue;
 
-      pi = wait_fd ();
-    }
+      why = pi->prstatus.pr_lwp.pr_why;
+      what = pi->prstatus.pr_lwp.pr_what;
+#else
+      if (! (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)) )
+       continue;
 
-  if (pid != -1)
-    for (pi = procinfo_list; pi; pi = pi->next)
-      if (pi->pid == pid && pi->had_event)
-       break;
+      why = pi->prstatus.pr_why;
+      what = pi->prstatus.pr_what;
 #endif
+      if (why == PR_SYSENTRY || why == PR_SYSEXIT)
+       {
+         int i;
+         int found_handler = 0;
+
+         for (i = 0; i < pi->num_syscall_handlers; i++)
+           if (pi->syscall_handlers[i].syscall_num == what)
+             {
+               found_handler = 1;
+               pi->saved_rtnval = pi->pid;
+               pi->saved_statval = 0;
+               if (!pi->syscall_handlers[i].func
+                   (pi, what, why, &pi->saved_rtnval, &pi->saved_statval))
+                 pi->had_event = 0;
+               break;
+             }
 
-  if (!pi && !checkerr)
-    goto wait_again;
+         if (!found_handler)
+           {
+             if (why == PR_SYSENTRY)
+               error ("PR_SYSENTRY, unhandled system call %d", what);
+             else
+               error ("PR_SYSEXIT, unhandled system call %d", what);
+           }
+       }
+    }
+
+  /* find a relevant process with an event */
+
+  for (pi = procinfo_list; pi; pi = pi->next)
+    if (pi->had_event && (pid == -1 || pi->pid == pid))
+      break;
+
+  if (!pi)
+    {
+      wait_fd ();
+      goto scan_again;
+    }
 
 #ifdef UNIXWARE
   if (!checkerr && !(pi->prstatus.pr_lwp.pr_flags & (PR_STOPPED | PR_ISTOP)))
@@ -3182,16 +3450,17 @@ procfs_wait (pid, ourstatus)
        {
          checkerr++;
        }
-    }    
+    }
   if (checkerr)
     {
       if (errno == ENOENT)
        {
+         /* XXX Fixme -- what to do if attached?  Can't call wait... */
          rtnval = wait (&statval);
-         if (rtnval != inferior_pid)
+         if ((rtnval) != (PIDGET (inferior_pid)))
            {
              print_sys_errmsg (pi->pathname, errno);
-             error ("procfs_write_pcwstop, wait failed, returned %d", rtnval);
+             error ("procfs_wait: wait failed, returned %d", rtnval);
              /* NOTREACHED */
            }
        }
@@ -3202,7 +3471,11 @@ procfs_wait (pid, ourstatus)
          /* NOTREACHED */
        }
     }
+#ifdef UNIXWARE
+  else if (pi->prstatus.pr_lwp.pr_flags & (PR_STOPPED | PR_ISTOP))
+#else
   else if (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
+#endif
     {
 #ifdef UNIXWARE
       rtnval = pi->prstatus.pr_pid;
@@ -3221,54 +3494,9 @@ procfs_wait (pid, ourstatus)
          break;
        case PR_SYSENTRY:
        case PR_SYSEXIT:
-         {
-           int i;
-           int found_handler = 0;
-
-           for (i = 0; i < pi->num_syscall_handlers; i++)
-             if (pi->syscall_handlers[i].syscall_num == what)
-               {
-                 found_handler = 1;
-                 if (!pi->syscall_handlers[i].func (pi, what, why,
-                                                    &rtnval, &statval))
-                   goto wait_again;
-
-                 break;
-               }
-
-           if (!found_handler)
-             if (why == PR_SYSENTRY)
-               error ("PR_SYSENTRY, unhandled system call %d", what);
-             else
-               error ("PR_SYSEXIT, unhandled system call %d", what);
-         }
+         rtnval = pi->saved_rtnval;
+         statval = pi->saved_statval;
          break;
-#ifdef PR_DEAD
-       case (short)PR_DEAD:
-         {
-           int dummy;
-
-           /* The inferior process is about to terminate.
-              pr_what has the process's exit or return value.
-              A PIOCRUN ioctl must be used to restart the process so it
-              can finish exiting.  */
-
-#ifdef PROCFS_USE_READ_WRITE
-            pctl.cmd = PCRUN;
-            pctl.data = PRCFAULT;
-            if (write (pi->ctl_fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
-#else
-           pi->prrun.pr_flags = PRCFAULT;
-           if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
-#endif
-             perror_with_name (pi->pathname);
-
-           if (wait (&dummy) < 0)
-             rtnval = -1;
-           statval = pi->prstatus.pr_what;
-         }
-         break;
-#endif
        case PR_REQUESTED:
          statval = (SIGSTOP << 8) | 0177;
          break;
@@ -3298,7 +3526,7 @@ procfs_wait (pid, ourstatus)
            case FLTBPT:
            case FLTTRACE:
              statval = (SIGTRAP << 8) | 0177;
-             break;          
+             break;
            case FLTSTACK:
            case FLTACCESS:
            case FLTBOUNDS:
@@ -3326,17 +3554,18 @@ procfs_wait (pid, ourstatus)
        default:
          error ("PIOCWSTOP, unknown why %d, what %d", why, what);
        }
-/* Stop all the other threads when any of them stops.  */
+      /* Stop all the other threads when any of them stops.  */
 
       {
-       struct procinfo *procinfo;
+       struct procinfo *procinfo, *next_pi;
 
-       for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)
+       for (procinfo = procinfo_list; procinfo; procinfo = next_pi)
          {
+           next_pi = procinfo->next;
            if (!procinfo->had_event)
              {
 #ifdef PROCFS_USE_READ_WRITE
-               cmd = PCSTOP;
+               long cmd = PCSTOP;
                if (write (pi->ctl_fd, (char *) &cmd, sizeof (long)) < 0)
                  {
                    print_sys_errmsg (procinfo->pathname, errno);
@@ -3348,15 +3577,20 @@ procfs_wait (pid, ourstatus)
                   order to avoid the hang. */
                if (!procfs_read_status (procinfo))
                  {
-                   print_sys_errmsg (procinfo->pathname, errno);
-                   error ("procfs_read_status failed");
+                   /* The LWP has apparently terminated.  */
+                   if (info_verbose)
+                     printf_filtered ("LWP %d doesn't respond.\n", 
+                                      (procinfo->pid >> 16) & 0xffff);
+                   close_proc_file (procinfo);
+                   continue;
                  }
 
                if (!(procinfo->prstatus.pr_flags & PR_STOPPED))
-                 if (ioctl (procinfo->ctl_fd, PIOCSTOP, &procinfo->prstatus) < 0)
+                 if (ioctl (procinfo->ctl_fd, PIOCSTOP, &procinfo->prstatus)
+                     < 0)
                    {
                      print_sys_errmsg (procinfo->pathname, errno);
-                     error ("PIOCSTOP failed");
+                     warning ("PIOCSTOP failed");
                    }
 #endif
              }
@@ -3365,15 +3599,19 @@ procfs_wait (pid, ourstatus)
     }
   else
     {
-      error ("PIOCWSTOP, stopped for unknown/unhandled reason, flags %#x", 
+      error ("PIOCWSTOP, stopped for unknown/unhandled reason, flags %#x",
+#ifdef UNIXWARE
+            pi->prstatus.pr_lwp.pr_flags);
+#else
             pi->prstatus.pr_flags);
+#endif
     }
 
   store_waitstatus (ourstatus, statval);
 
   if (rtnval == -1)            /* No more children to wait for */
     {
-      fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing.\n");
+      warning ("Child process unexpectedly missing");
       /* Claim it exited with unknown signal.  */
       ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
       ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
@@ -3493,7 +3731,7 @@ procfs_resume (pid, step, signo)
      enum target_signal signo;
 {
   int signal_to_pass;
-  struct procinfo *pi, *procinfo;
+  struct procinfo *pi, *procinfo, *next_pi;
   struct proc_ctl pctl;
 
   pi = find_procinfo (pid == -1 ? inferior_pid : pid, 0);
@@ -3541,11 +3779,12 @@ procfs_resume (pid, step, signo)
   else if (signo == TARGET_SIGNAL_TSTP
 #ifdef UNIXWARE
           && pi->prstatus.pr_lwp.pr_cursig == SIGTSTP
-          && pi->prstatus.pr_lwp.pr_action.sa_handler == SIG_DFL)
+          && pi->prstatus.pr_lwp.pr_action.sa_handler == SIG_DFL
 #else
           && pi->prstatus.pr_cursig == SIGTSTP
-          && pi->prstatus.pr_action.sa_handler == SIG_DFL)
+          && pi->prstatus.pr_action.sa_handler == SIG_DFL
 #endif
+          )
 
     /* We are about to pass the inferior a SIGTSTP whose action is
        SIG_DFL.  The SIG_DFL action for a SIGTSTP is to stop
@@ -3586,65 +3825,90 @@ procfs_resume (pid, step, signo)
       pi->prrun.pr_flags |= PRSTEP;
 #endif
     }
-
+  pi->had_event = 0;
   /* Don't try to start a process unless it's stopped on an
      `event of interest'.  Doing so will cause errors.  */
 
+  if (!procfs_read_status (pi))
+    {
+      /* The LWP has apparently terminated.  */
+      if (info_verbose)
+       printf_filtered ("LWP %d doesn't respond.\n", 
+                        (pi->pid >> 16) & 0xffff);
+      close_proc_file (pi);
+    }
+  else
+    {
 #ifdef PROCFS_USE_READ_WRITE
-  if (write (pi->ctl_fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
+      if (write (pi->ctl_fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
 #else
-  if ((pi->prstatus.pr_flags & PR_ISTOP)
-       && ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
+      if ((pi->prstatus.pr_flags & PR_ISTOP)
+         && ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
 #endif
-    {
-      perror_with_name (pi->pathname);
-      /* NOTREACHED */
+       {
+         /* The LWP has apparently terminated.  */
+         if (info_verbose)
+           printf_filtered ("LWP %d doesn't respond.\n", 
+                            (pi->pid >> 16) & 0xffff);
+         close_proc_file (pi);
+       }
     }
 
-  pi->had_event = 0;
-
-  /* Continue all the other threads that haven't had an event of
-     interest.  */
+  /* Continue all the other threads that haven't had an event of interest.
+     Also continue them if they have NOPASS_NEXT_SIGSTOP set; this is only
+     set by do_attach, and means this is the first resume after an attach.  
+     All threads were CSTOP'd by do_attach, and should be resumed now.  */
 
   if (pid == -1)
-    for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)
+    for (procinfo = procinfo_list; procinfo; procinfo = next_pi)
       {
-       if (pi != procinfo && !procinfo->had_event)
-         {
+       next_pi = procinfo->next;
+       if (pi != procinfo)
+         if (!procinfo->had_event || 
+             (procinfo->nopass_next_sigstop && signo == TARGET_SIGNAL_STOP))
+           {
+             procinfo->had_event = procinfo->nopass_next_sigstop = 0;
 #ifdef PROCFS_USE_READ_WRITE
-           pctl.data = PRCFAULT | PRCSIG;
-           if (write (procinfo->ctl_fd, (char *) &pctl,
-               sizeof (struct proc_ctl)) < 0)
-             {
-               if (!procfs_read_status (procinfo))
-                 {
-                   fprintf_unfiltered(gdb_stderr, "procfs_read_status failed, errno=%d\n", errno);
-                 }
-               print_sys_errmsg (procinfo->pathname, errno);
-               error ("PCRUN failed");
-             }
-           procfs_read_status (procinfo);
+             pctl.data = PRCFAULT | PRCSIG;
+             if (write (procinfo->ctl_fd, (char *) &pctl,
+                        sizeof (struct proc_ctl)) < 0)
+               {
+                 if (!procfs_read_status (procinfo))
+                   fprintf_unfiltered(gdb_stderr, 
+                                      "procfs_read_status failed, errno=%d\n",
+                                      errno);
+                 print_sys_errmsg (procinfo->pathname, errno);
+                 error ("PCRUN failed");
+               }
 #else
-           procinfo->prrun.pr_flags &= PRSTEP;
-           procinfo->prrun.pr_flags |= PRCFAULT | PRCSIG;
-           procfs_read_status (procinfo);
+             procinfo->prrun.pr_flags &= PRSTEP;
+             procinfo->prrun.pr_flags |= PRCFAULT | PRCSIG;
+             if (!procfs_read_status (procinfo))
+               {
+                 /* The LWP has apparently terminated.  */
+                 if (info_verbose)
+                   printf_filtered ("LWP %d doesn't respond.\n", 
+                                    (procinfo->pid >> 16) & 0xffff);
+                 close_proc_file (procinfo);
+                 continue;
+               }
 
-           /* Don't try to start a process unless it's stopped on an
-              `event of interest'.  Doing so will cause errors.  */
+             /* Don't try to start a process unless it's stopped on an
+                `event of interest'.  Doing so will cause errors.  */
 
-           if ((procinfo->prstatus.pr_flags & PR_ISTOP)
-               && ioctl (procinfo->ctl_fd, PIOCRUN, &procinfo->prrun) < 0)
-             {
-               if (!procfs_read_status (procinfo))
-                 {
-                   fprintf_unfiltered(gdb_stderr, "procfs_read_status failed, errno=%d\n", errno);
-                 }
-               print_sys_errmsg (procinfo->pathname, errno);
-               error ("PIOCRUN failed");
-             }
-           procfs_read_status (procinfo);
+             if ((procinfo->prstatus.pr_flags & PR_ISTOP)
+                 && ioctl (procinfo->ctl_fd, PIOCRUN, &procinfo->prrun) < 0)
+               {
+                 if (!procfs_read_status (procinfo))
+                   fprintf_unfiltered(gdb_stderr, 
+                                      "procfs_read_status failed, errno=%d\n",
+                                      errno);
+                 print_sys_errmsg (procinfo->pathname, errno);
+                 warning ("PIOCRUN failed");
+               }
 #endif
-         }
+           }
+       procfs_read_status (procinfo);
       }
 }
 
@@ -3700,28 +3964,31 @@ procfs_fetch_registers (regno)
 
 LOCAL FUNCTION
 
-       proc_init_failed - called whenever /proc access initialization
+       proc_init_failed - called when /proc access initialization fails
 fails
 
 SYNOPSIS
 
-       static void proc_init_failed (struct procinfo *pi, char *why)
+       static void proc_init_failed (struct procinfo *pi, 
+                                     char *why, int kill_p)
 
 DESCRIPTION
 
        This function is called whenever initialization of access to a /proc
        entry fails.  It prints a suitable error message, does some cleanup,
        and then invokes the standard error processing routine which dumps
-       us back into the command loop.
+       us back into the command loop.  If KILL_P is true, sends SIGKILL.
  */
 
 static void
-proc_init_failed (pi, why)
+proc_init_failed (pi, why, kill_p)
      struct procinfo *pi;
      char *why;
+     int  kill_p;
 {
   print_sys_errmsg (pi->pathname, errno);
-  kill (pi->pid, SIGKILL);
+  if (kill_p)
+    kill (pi->pid, SIGKILL);
   close_proc_file (pi);
   error (why);
   /* NOTREACHED */
@@ -3752,6 +4019,7 @@ close_proc_file (pip)
 {
   struct procinfo *procinfo;
 
+  delete_thread (pip->pid);    /* remove thread from GDB's thread list */
   remove_fd (pip);             /* Remove fd from poll/select list */
 
   close (pip->ctl_fd);
@@ -3869,7 +4137,7 @@ open_proc_file (pid, pip, mode, control)
           close (pip->as_fd);
           close (pip->map_fd);
           return 0;
-        }      
+        }
     }
 
 #else /* HAVE_MULTIPLE_PROC_FDS */
@@ -4510,7 +4778,7 @@ info_proc (args, from_tty)
      char *args;
      int from_tty;
 {
-  int pid = inferior_pid;
+  int pid;
   struct procinfo *pip;
   struct cleanup *old_chain;
   char **argv;
@@ -4533,7 +4801,10 @@ info_proc (args, from_tty)
   /* Default to using the current inferior if no pid specified.  Note
      that inferior_pid may be 0, hence we set okerr.  */
 
-  pip = find_procinfo (inferior_pid, 1);
+  pid = inferior_pid & 0x7fffffff;             /* strip off sol-thread bit */
+  if (!(pip = find_procinfo (pid, 1)))         /* inferior_pid no good?  */
+    pip = procinfo_list;                       /* take first available */
+  pid = pid & 0xffff;                          /* extract "real" pid */
 
   if (args != NULL)
     {
@@ -4631,12 +4902,12 @@ No process.  Start debugging a program or specify an explicit process ID.");
 #ifndef PROCFS_USE_READ_WRITE
 #ifdef PIOCLWPIDS
   nlwp = pip->prstatus.pr_nlwp;
-  lwps = alloca ((2 * nlwp + 2) * sizeof (id_t));
+  lwps = alloca ((2 * nlwp + 2) * sizeof (*lwps));
 
   if (ioctl (pip->ctl_fd, PIOCLWPIDS, lwps))
     {
       print_sys_errmsg (pip -> pathname, errno);
-      error ("PIOCLWPIDS failed");      
+      error ("PIOCLWPIDS failed");
     }
 #else /* PIOCLWPIDS */
   nlwp = 1;
@@ -4677,6 +4948,14 @@ No process.  Start debugging a program or specify an explicit process ID.");
       if (summary || all)
        {
          info_proc_stop (pip, summary);
+#ifdef UNIXWARE
+         supply_gregset (&pip->prstatus.pr_lwp.pr_context.uc_mcontext.gregs);
+#else
+         supply_gregset (&pip->prstatus.pr_reg);
+#endif
+         printf_filtered ("PC: ");
+         print_address (read_pc (), gdb_stdout);
+         printf_filtered ("\n");
        }
       if (summary || all || signals || faults)
        {
@@ -4881,7 +5160,8 @@ procfs_clear_syscall_trap (pi, syscall_num, errok)
 {
   sysset_t sysset;
   int goterr, i;
-  
+
+#ifndef UNIXWARE
   goterr = ioctl (pi->ctl_fd, PIOCGENTRY, &sysset) < 0;
 
   if (goterr && !errok)
@@ -4921,6 +5201,7 @@ procfs_clear_syscall_trap (pi, syscall_num, errok)
          error ("PIOCSEXIT failed");
        }
     }
+#endif
 
   if (!pi->syscall_handlers)
     {
@@ -4984,7 +5265,8 @@ procfs_set_syscall_trap (pi, syscall_num, flags, func)
      syscall_func_t *func;
 {
   sysset_t sysset;
-  
+
+#ifndef UNIXWARE
   if (flags & PROCFS_SYSCALL_ENTRY)
     {
       if (ioctl (pi->ctl_fd, PIOCGENTRY, &sysset) < 0)
@@ -5020,6 +5302,7 @@ procfs_set_syscall_trap (pi, syscall_num, flags, func)
          error ("PIOCSEXIT failed");
        }
     }
+#endif
 
   if (!pi->syscall_handlers)
     {
@@ -5089,6 +5372,7 @@ procfs_lwp_creation_handler (pi, syscall_num, why, rtnvalp, statvalp)
 {
   int lwp_id;
   struct procinfo *childpi;
+  struct proc_ctl pctl;
 
   /* We've just detected the completion of an lwp_create system call.  Now we
      need to setup a procinfo struct for this thread, and notify the thread
@@ -5097,7 +5381,20 @@ procfs_lwp_creation_handler (pi, syscall_num, why, rtnvalp, statvalp)
   /* If lwp_create failed, then nothing interesting happened.  Continue the
      process and go back to sleep. */
 
-  if (pi->prstatus.pr_reg[R_PSR] & PS_FLAG_CARRY)
+#ifdef UNIXWARE
+  /* Joel ... can you check this logic out please? JKJ */
+  if (pi->prstatus.pr_lwp.pr_context.uc_mcontext.gregs[R_EFL] & 1)
+    { /* _lwp_create failed */
+      pctl.cmd = PCRUN;
+      pctl.data = PRCFAULT;
+
+      if (write (pi->ctl_fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
+       perror_with_name (pi->pathname);
+
+      return 0;
+    }
+#else /* UNIXWARE */
+  if (PROCFS_GET_CARRY (pi->prstatus.pr_reg))
     {                          /* _lwp_create failed */
       pi->prrun.pr_flags &= PRSTEP;
       pi->prrun.pr_flags |= PRCFAULT;
@@ -5107,17 +5404,25 @@ procfs_lwp_creation_handler (pi, syscall_num, why, rtnvalp, statvalp)
 
       return 0;
     }
+#endif
 
   /* At this point, the new thread is stopped at it's first instruction, and
      the parent is stopped at the exit from lwp_create.  */
 
   if (pi->new_child)           /* Child? */
     {                          /* Yes, just continue it */
+#ifdef UNIXWARE
+      pctl.cmd = PCRUN;
+      pctl.data = PRCFAULT;
+
+      if (write(pi->ctl_fd, (char *)&pctl, sizeof (struct proc_ctl)) < 0)
+#else /* !UNIXWARE */
       pi->prrun.pr_flags &= PRSTEP;
       pi->prrun.pr_flags |= PRCFAULT;
 
       if ((pi->prstatus.pr_flags & PR_ISTOP)
          && ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
+#endif /* !UNIXWARE */
        perror_with_name (pi->pathname);
 
       pi->new_child = 0;       /* No longer new */
@@ -5127,27 +5432,66 @@ procfs_lwp_creation_handler (pi, syscall_num, why, rtnvalp, statvalp)
 
   /* We're the proud parent of a new thread.  Setup an exit trap for lwp_create
      in the child and continue the parent.  */
-  
+
   /* Third arg is pointer to new thread id. */
+#ifdef UNIXWARE
+  lwp_id = read_memory_integer (pi->prstatus.pr_lwp.pr_sysarg[2], sizeof (int));
+#else
   lwp_id = read_memory_integer (pi->prstatus.pr_sysarg[2], sizeof (int));
+#endif
 
   lwp_id = (lwp_id << 16) | PIDGET (pi->pid);
 
   childpi = create_procinfo (lwp_id);
 
   /* The new process has actually inherited the lwp_create syscall trap from
-     it's parent, but we still have to call this to register a handler for
+     it's parent, but we still have to call this to register handlers for
      that child.  */
 
-  procfs_set_syscall_trap (childpi, SYS_lwp_create, PROCFS_SYSCALL_EXIT,
-                          procfs_lwp_creation_handler);
+  procfs_set_inferior_syscall_traps (childpi);
+  add_thread (lwp_id);
+  printf_filtered ("[New %s]\n", target_pid_to_str (lwp_id));
 
-  childpi->new_child = 1;      /* Flag this as an unseen child process */
+  /* Continue the parent */
+#ifdef UNIXWARE
+  pctl.cmd = PCRUN;
+  pctl.data = PRCFAULT;
 
-  *rtnvalp = lwp_id;   /* the new arrival. */
-  *statvalp = (SIGTRAP << 8) | 0177;
+  if (write(pi->ctl_fd, (char *)&pctl, sizeof (struct proc_ctl)) < 0)
+#else
+  pi->prrun.pr_flags &= PRSTEP;
+  pi->prrun.pr_flags |= PRCFAULT;
+  if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
+#endif
+    perror_with_name (pi->pathname);
 
-  return 1;
+  /* The new child may have been created in one of two states: 
+     SUSPENDED or RUNNABLE.  If runnable, we will simply signal it to run.
+     If suspended, we flag it to be continued later, when it has an event.  */
+
+#ifdef UNIXWARE
+  if (childpi->prstatus.pr_lwp.pr_why == PR_SUSPENDED)
+#else
+  if (childpi->prstatus.pr_why == PR_SUSPENDED)
+#endif
+    childpi->new_child = 1;    /* Flag this as an unseen child process */
+  else
+    {
+      /* Continue the child */
+#ifdef UNIXWARE
+      pctl.cmd = PCRUN;
+      pctl.data = PRCFAULT;
+
+      if (write(pi->ctl_fd, (char *)&pctl, sizeof (struct proc_ctl)) < 0)
+#else
+      childpi->prrun.pr_flags &= PRSTEP;
+      childpi->prrun.pr_flags |= PRCFAULT;
+
+      if (ioctl (childpi->ctl_fd, PIOCRUN, &childpi->prrun) != 0)
+#endif
+       perror_with_name (childpi->pathname);
+    }
+  return 0;
 }
 #endif /* SYS_lwp_create */
 
@@ -5229,7 +5573,7 @@ procfs_create_inferior (exec_file, allargs, env)
     }
 
   fork_inferior (exec_file, allargs, env,
-                proc_set_exec_trap, procfs_init_inferior, shell_file);
+                proc_set_exec_trap, procfs_init_inferior, NULL, shell_file);
 
   /* We are at the first instruction we care about.  */
   /* Pedal to the metal... */
@@ -5267,6 +5611,7 @@ procfs_can_run ()
   return !procfs_suppress_run;
 }
 #ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
+#ifndef UNIXWARE
 \f
 /* Insert a watchpoint */
 int
@@ -5326,6 +5671,7 @@ procfs_stopped_by_watchpoint(pid)
     }
   return 0;
 }
+#endif /* !UNIXWARE */
 #endif /* TARGET_HAS_HARDWARE_WATCHPOINTS */
 
 /* Why is this necessary?  Shouldn't dead threads just be removed from the
@@ -5335,7 +5681,46 @@ static int
 procfs_thread_alive (pid)
      int pid;
 {
-  return 1;
+  struct procinfo *pi, *next_pi;
+
+  for (pi = procinfo_list; pi; pi = next_pi)
+    {
+      next_pi = pi->next;
+      if (pi -> pid == pid)
+       if (procfs_read_status (pi))    /* alive */
+         return 1;
+       else                            /* defunct (exited) */
+         {
+           close_proc_file (pi);
+           return 0;
+         }
+    }
+  return 0;
+}
+
+int
+procfs_first_available ()
+{
+  struct procinfo *pi;
+
+  for (pi = procinfo_list; pi; pi = pi->next)
+    {
+      if (procfs_read_status (pi))
+       return pi->pid;
+    }
+  return -1;
+}
+
+int
+procfs_get_pid_fd (pid)
+     int pid;
+{
+  struct procinfo *pi = find_procinfo (pid, 1);
+
+  if (pi == NULL)
+    return -1;
+
+  return pi->ctl_fd;
 }
 
 /* Send a SIGINT to the process group.  This acts just like the user typed a
@@ -5373,10 +5758,14 @@ struct target_ops procfs_ops = {
   "Unix /proc child process (started by the \"run\" command).",        /* to_doc */
   procfs_open,                 /* to_open */
   0,                           /* to_close */
-  procfs_attach,                       /* to_attach */
+  procfs_attach,               /* to_attach */
+  NULL,                         /* to_post_attach */
+  procfs_attach,                       /* to_require_attach */
   procfs_detach,               /* to_detach */
-  procfs_resume,                       /* to_resume */
+  procfs_detach,                       /* to_require_detach */
+  procfs_resume,               /* to_resume */
   procfs_wait,                 /* to_wait */
+  NULL,                         /* to_post_wait */
   procfs_fetch_registers,      /* to_fetch_registers */
   procfs_store_registers,      /* to_store_registers */
   procfs_prepare_to_store,     /* to_prepare_to_store */
@@ -5393,11 +5782,33 @@ struct target_ops procfs_ops = {
   0,                           /* to_load */
   0,                           /* to_lookup_symbol */
   procfs_create_inferior,      /* to_create_inferior */
+  NULL,                         /* to_post_startup_inferior */
+  NULL,                         /* to_acknowledge_created_inferior */
+  NULL,                         /* to_clone_and_follow_inferior */
+  NULL,                         /* to_post_follow_inferior_by_clone */
+  NULL,                         /* to_insert_fork_catchpoint */
+  NULL,                         /* to_remove_fork_catchpoint */
+  NULL,                         /* to_insert_vfork_catchpoint */
+  NULL,                         /* to_remove_vfork_catchpoint */
+  NULL,                         /* to_has_forked */
+  NULL,                         /* to_has_vforked */
+  NULL,                         /* to_can_follow_vfork_prior_to_exec */
+  NULL,                         /* to_post_follow_vfork */
+  NULL,                         /* to_insert_exec_catchpoint */
+  NULL,                         /* to_remove_exec_catchpoint */
+  NULL,                         /* to_has_execd */
+  NULL,                         /* to_reported_exec_events_per_exec_call */
+  NULL,                         /* to_has_syscall_event */
+  NULL,                         /* to_has_exited */
   procfs_mourn_inferior,       /* to_mourn_inferior */
   procfs_can_run,              /* to_can_run */
   procfs_notice_signals,       /* to_notice_signals */
   procfs_thread_alive,         /* to_thread_alive */
   procfs_stop,                 /* to_stop */
+  NULL,                         /* to_enable_exception_callback */
+  NULL,                         /* to_get_current_exception_event */
+  NULL,                         /* to_pid_to_exec_file */
+  NULL,                         /* to_core_file_to_sym_file */
   process_stratum,             /* to_stratum */
   0,                           /* to_next */
   1,                           /* to_has_all_memory */
@@ -5428,7 +5839,7 @@ _initialize_procfs ()
 
   add_target (&procfs_ops);
 
-  add_info ("proc", info_proc, 
+  add_info ("processes", 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\
This page took 0.052912 seconds and 4 git commands to generate.