import gdb-1999-12-21 snapshot
[deliverable/binutils-gdb.git] / gdb / procfs.c
index 4af048b3706eee1ae8eb79a63678ce7e31253e80..6abc092f12143b22223fa218abadc950a81ca262 100644 (file)
 /* Machine independent support for SVR4 /proc (process file system) for GDB.
-   Copyright (C) 1991 Free Software Foundation, Inc.
-   Written by Fred Fish at Cygnus Support.
+   Copyright 1991, 1992-98, 1999 Free Software Foundation, Inc.
+   Written by Fred Fish at Cygnus Support.  Changes for sysv4.2mp procfs
+   compatibility by Geoffrey Noer at Cygnus Solutions.
 
-This file is part of GDB.
+   This file is part of GDB.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
 
 
-/*                     N  O  T  E  S
+/*                      N  O  T  E  S
 
-For information on the details of using /proc consult section proc(4)
-in the UNIX System V Release 4 System Administrator's Reference Manual.
+   For information on the details of using /proc consult section proc(4)
+   in the UNIX System V Release 4 System Administrator's Reference Manual.
 
-The general register and floating point register sets are manipulated by
-separate ioctl's.  This file makes the assumption that if FP0_REGNUM is
-defined, then support for the floating point register set is desired,
-regardless of whether or not the actual target has floating point hardware.
+   The general register and floating point register sets are manipulated
+   separately.  This file makes the assumption that if FP0_REGNUM is
+   defined, then support for the floating point register set is desired,
+   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 <sys/types.h>
 #include <time.h>
+#include <sys/fault.h>
+#include <sys/syscall.h>
 #include <sys/procfs.h>
 #include <fcntl.h>
 #include <errno.h>
-#include <string.h>
+#include "gdb_string.h"
+#include <stropts.h>
+#include <poll.h>
+#include "gdb_stat.h"
 
 #include "inferior.h"
 #include "target.h"
 #include "command.h"
+#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 */
+/* Wrap Light Weight Process member in THE_PR_LWP macro for clearer code */
+#ifndef HAVE_PSTATUS_T
+typedef prstatus_t gdb_prstatus_t;
+#define THE_PR_LWP(a)  a
+#else /* HAVE_PSTATUS_T */
+typedef pstatus_t gdb_prstatus_t;
+#define THE_PR_LWP(a)  a.pr_lwp
+#if !defined(HAVE_PRRUN_T) && defined(HAVE_MULTIPLE_PROC_FDS)
+  /* Fallback definitions - for using configure information directly */
+#ifndef UNIXWARE
+#define UNIXWARE       1
+#endif
+#if !defined(PROCFS_USE_READ_WRITE) && !defined(HAVE_PROCFS_PIOCSET)
+#define PROCFS_USE_READ_WRITE  1
+#endif
+#endif /* !HAVE_PRRUN_T && HAVE_MULTIPLE_PROC_FDS */
+#endif /* HAVE_PSTATUS_T */
 
 #define MAX_SYSCALLS   256     /* Maximum number of syscalls for table */
 
-#ifndef PROC_NAME_FMT
-#define PROC_NAME_FMT "/proc/%05d"
+/* 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
+#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
+#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
 
-#if 1  /* FIXME: Gross and ugly hack to resolve coredep.c global */
+
+#define MAX_PROC_NAME_SIZE sizeof("/proc/1234567890/status")
+
+struct target_ops procfs_ops;
+
+int procfs_suppress_run = 0;   /* Non-zero if procfs should pretend not to
+                                  be a runnable target.  Used by targets
+                                  that can sit atop procfs, such as solaris
+                                  thread support.  */
+
+#if 1                          /* FIXME: Gross and ugly hack to resolve coredep.c global */
 CORE_ADDR kernel_u_addr;
 #endif
 
@@ -63,95 +167,176 @@ CORE_ADDR kernel_u_addr;
 #define si_uid _data._proc._pdata._kill.uid
 #endif /* BROKEN_SIGINFO_H */
 
-/*  All access to the inferior, either one started by gdb or one that has
-    been attached to, is controlled by an instance of a procinfo structure,
-    defined below.  Since gdb currently only handles one inferior at a time,
-    the procinfo structure for the inferior is statically allocated and
-    only one exists at any given time.  There is a separate procinfo
-    structure for use by the "info proc" command, so that we can print
-    useful information about any random process without interfering with
-    the inferior's procinfo information. */
-
-struct procinfo {
-  int valid;                   /* Nonzero if pid, fd, & pathname are valid */
-  int pid;                     /* Process ID of inferior */
-  int fd;                      /* File descriptor for /proc entry */
-  char *pathname;              /* Pathname to /proc entry */
-  int was_stopped;             /* Nonzero if was stopped prior to attach */
-  int nopass_next_sigstop;     /* Don't pass a sigstop on next resume */
-  prrun_t prrun;               /* Control state when it is run */
-  prstatus_t prstatus;         /* Current process status info */
-  gregset_t gregset;           /* General register set */
-  fpregset_t fpregset;         /* Floating point register set */
-  fltset_t fltset;             /* Current traced hardware fault set */
-  sigset_t trace;              /* Current traced signal set */
-  sysset_t exitset;            /* Current traced system call exit set */
-  sysset_t entryset;           /* Current traced system call entry set */
-  fltset_t saved_fltset;       /* Saved traced hardware fault set */
-  sigset_t saved_trace;                /* Saved traced signal set */
-  sigset_t saved_sighold;      /* Saved held signal set */
-  sysset_t saved_exitset;      /* Saved traced system call exit set */
-  sysset_t saved_entryset;     /* Saved traced system call entry set */
-};
+/* Define structures for passing commands to /proc/pid/ctl file.  Note that
+   while we create these for the PROCFS_USE_READ_WRITE world, we use them
+   and ignore the extra cmd int in other proc schemes.
+ */
+/* generic ctl msg */
+struct proc_ctl
+  {
+    int cmd;
+    long data;
+  };
+
+/* set general registers */
+struct greg_ctl
+  {
+    int cmd;
+    gdb_gregset_t gregset;
+  };
+
+/* set fp registers */
+struct fpreg_ctl
+  {
+    int cmd;
+    gdb_fpregset_t fpregset;
+  };
+
+/* set signals to be traced */
+struct sig_ctl
+  {
+    int cmd;
+    sigset_t sigset;
+  };
+
+/* set faults to be traced */
+struct flt_ctl
+  {
+    int cmd;
+    fltset_t fltset;
+  };
+
+/* set system calls to be traced */
+struct sys_ctl
+  {
+    int cmd;
+    sysset_t sysset;
+  };
+
+/* set current signal to be traced */
+struct sigi_ctl
+  {
+    int cmd;
+    siginfo_t siginfo;
+  };
 
-static struct procinfo pi;     /* Inferior's process information */
+/*  All access to the inferior, either one started by gdb or one that has
+   been attached to, is controlled by an instance of a procinfo structure,
+   defined below.  Since gdb currently only handles one inferior at a time,
+   the procinfo structure for the inferior is statically allocated and
+   only one exists at any given time.  There is a separate procinfo
+   structure for use by the "info proc" command, so that we can print
+   useful information about any random process without interfering with
+   the inferior's procinfo information. */
+
+struct procinfo
+  {
+    struct procinfo *next;
+    int pid;                   /* Process ID of inferior */
+    int ctl_fd;                        /* File descriptor for /proc ctl file */
+    int status_fd;             /* File descriptor for /proc status file */
+    int as_fd;                 /* File descriptor for /proc as file */
+    int map_fd;                        /* File descriptor for /proc map file */
+    char *pathname;            /* Pathname to /proc entry */
+    int had_event;             /* poll/select says something happened */
+    int was_stopped;           /* Nonzero if was stopped prior to attach */
+    int nopass_next_sigstop;   /* Don't pass a sigstop on next resume */
+#ifdef HAVE_PRRUN_T
+    prrun_t prrun;             /* Control state when it is run */
+#endif
+    gdb_prstatus_t prstatus;   /* Current process status info */
+    struct greg_ctl gregset;   /* General register set */
+    struct fpreg_ctl fpregset; /* Floating point register set */
+    struct flt_ctl fltset;     /* Current traced hardware fault set */
+    struct sig_ctl trace;      /* Current traced signal set */
+    struct sys_ctl exitset;    /* Current traced system call exit set */
+    struct sys_ctl entryset;   /* Current traced system call entry set */
+    struct sig_ctl saved_sighold;      /* Saved held signal set */
+    struct flt_ctl saved_fltset;       /* Saved traced hardware fault set */
+    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 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 */
 
 /*  Much of the information used in the /proc interface, particularly for
-    printing status information, is kept as tables of structures of the
-    following form.  These tables can be used to map numeric values to
-    their symbolic names and to a string that describes their specific use. */
-
-struct trans {
-  int value;                   /* The numeric value */
-  char *name;                  /* The equivalent symbolic value */
-  char *desc;                  /* Short description of value */
-};
+   printing status information, is kept as tables of structures of the
+   following form.  These tables can be used to map numeric values to
+   their symbolic names and to a string that describes their specific use. */
+
+struct trans
+  {
+    int value;                 /* The numeric value */
+    char *name;                        /* The equivalent symbolic value */
+    char *desc;                        /* Short description of value */
+  };
 
 /*  Translate bits in the pr_flags member of the prstatus structure, into the
-    names and desc information. */
+   names and desc information. */
 
 static struct trans pr_flag_table[] =
 {
 #if defined (PR_STOPPED)
-  PR_STOPPED, "PR_STOPPED", "Process is stopped",
+  {PR_STOPPED, "PR_STOPPED", "Process is stopped"},
 #endif
 #if defined (PR_ISTOP)
-  PR_ISTOP, "PR_ISTOP", "Stopped on an event of interest",
+  {PR_ISTOP, "PR_ISTOP", "Stopped on an event of interest"},
 #endif
 #if defined (PR_DSTOP)
-  PR_DSTOP, "PR_DSTOP", "A stop directive is in effect",
+  {PR_DSTOP, "PR_DSTOP", "A stop directive is in effect"},
 #endif
 #if defined (PR_ASLEEP)
-  PR_ASLEEP, "PR_ASLEEP", "Sleeping in an interruptible system call",
+  {PR_ASLEEP, "PR_ASLEEP", "Sleeping in an interruptible system call"},
 #endif
 #if defined (PR_FORK)
-  PR_FORK, "PR_FORK", "Inherit-on-fork is in effect",
+  {PR_FORK, "PR_FORK", "Inherit-on-fork is in effect"},
 #endif
 #if defined (PR_RLC)
-  PR_RLC, "PR_RLC", "Run-on-last-close is in effect",
+  {PR_RLC, "PR_RLC", "Run-on-last-close is in effect"},
 #endif
 #if defined (PR_PTRACE)
-  PR_PTRACE, "PR_PTRACE", "Process is being controlled by ptrace",
+  {PR_PTRACE, "PR_PTRACE", "Process is being controlled by ptrace"},
 #endif
 #if defined (PR_PCINVAL)
-  PR_PCINVAL, "PR_PCINVAL", "PC refers to an invalid virtual address",
+  {PR_PCINVAL, "PR_PCINVAL", "PC refers to an invalid virtual address"},
 #endif
 #if defined (PR_ISSYS)
-  PR_ISSYS, "PR_ISSYS", "Is a system process",
+  {PR_ISSYS, "PR_ISSYS", "Is a system process"},
 #endif
 #if defined (PR_STEP)
-  PR_STEP, "PR_STEP", "Process has single step pending",
+  {PR_STEP, "PR_STEP", "Process has single step pending"},
 #endif
 #if defined (PR_KLC)
-  PR_KLC, "PR_KLC", "Kill-on-last-close is in effect",
+  {PR_KLC, "PR_KLC", "Kill-on-last-close is in effect"},
 #endif
 #if defined (PR_ASYNC)
-  PR_ASYNC, "PR_ASYNC", "Asynchronous stop is in effect",
+  {PR_ASYNC, "PR_ASYNC", "Asynchronous stop is in effect"},
 #endif
 #if defined (PR_PCOMPAT)
-  PR_PCOMPAT, "PR_PCOMPAT", "Ptrace compatibility mode in effect",
+  {PR_PCOMPAT, "PR_PCOMPAT", "Ptrace compatibility mode in effect"},
 #endif
- 0, NULL, NULL
+#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}
 };
 
 /*  Translate values in the pr_why field of the prstatus struct. */
@@ -159,27 +344,30 @@ static struct trans pr_flag_table[] =
 static struct trans pr_why_table[] =
 {
 #if defined (PR_REQUESTED)
PR_REQUESTED, "PR_REQUESTED", "Directed to stop via PIOCSTOP/PIOCWSTOP",
 {PR_REQUESTED, "PR_REQUESTED", "Directed to stop via PIOCSTOP/PIOCWSTOP"},
 #endif
 #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",
+  {PR_SIGNALLED, "PR_SIGNALLED", "Receipt of a traced signal"},
 #endif
 #if defined (PR_SYSENTRY)
PR_SYSENTRY, "PR_SYSENTRY", "Entry to a traced system call",
 {PR_SYSENTRY, "PR_SYSENTRY", "Entry to a traced system call"},
 #endif
 #if defined (PR_SYSEXIT)
PR_SYSEXIT, "PR_SYSEXIT", "Exit from a traced system call",
 {PR_SYSEXIT, "PR_SYSEXIT", "Exit from a traced system call"},
 #endif
 #if defined (PR_JOBCONTROL)
- PR_JOBCONTROL, "PR_JOBCONTROL", "Default job control stop signal action",
+  {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",
+  {PR_SUSPENDED, "PR_SUSPENDED", "Process suspended"},
+#endif
+#if defined (PR_CHECKPOINT)
+  {PR_CHECKPOINT, "PR_CHECKPOINT", "(???)"},
 #endif
- 0, NULL, NULL
+  {0, NULL, NULL}
 };
 
 /*  Hardware fault translation table. */
@@ -187,442 +375,956 @@ static struct trans pr_why_table[] =
 static struct trans faults_table[] =
 {
 #if defined (FLTILL)
FLTILL, "FLTILL", "Illegal instruction",
 {FLTILL, "FLTILL", "Illegal instruction"},
 #endif
 #if defined (FLTPRIV)
FLTPRIV, "FLTPRIV", "Privileged instruction",
 {FLTPRIV, "FLTPRIV", "Privileged instruction"},
 #endif
 #if defined (FLTBPT)
FLTBPT, "FLTBPT", "Breakpoint trap",
 {FLTBPT, "FLTBPT", "Breakpoint trap"},
 #endif
 #if defined (FLTTRACE)
FLTTRACE, "FLTTRACE", "Trace trap",
 {FLTTRACE, "FLTTRACE", "Trace trap"},
 #endif
 #if defined (FLTACCESS)
FLTACCESS, "FLTACCESS", "Memory access fault",
 {FLTACCESS, "FLTACCESS", "Memory access fault"},
 #endif
 #if defined (FLTBOUNDS)
FLTBOUNDS, "FLTBOUNDS", "Memory bounds violation",
 {FLTBOUNDS, "FLTBOUNDS", "Memory bounds violation"},
 #endif
 #if defined (FLTIOVF)
FLTIOVF, "FLTIOVF", "Integer overflow",
 {FLTIOVF, "FLTIOVF", "Integer overflow"},
 #endif
 #if defined (FLTIZDIV)
FLTIZDIV, "FLTIZDIV", "Integer zero divide",
 {FLTIZDIV, "FLTIZDIV", "Integer zero divide"},
 #endif
 #if defined (FLTFPE)
FLTFPE, "FLTFPE", "Floating-point exception",
 {FLTFPE, "FLTFPE", "Floating-point exception"},
 #endif
 #if defined (FLTSTACK)
FLTSTACK, "FLTSTACK", "Unrecoverable stack fault",
 {FLTSTACK, "FLTSTACK", "Unrecoverable stack fault"},
 #endif
 #if defined (FLTPAGE)
FLTPAGE, "FLTPAGE", "Recoverable page fault",
 {FLTPAGE, "FLTPAGE", "Recoverable page fault"},
 #endif
- 0, NULL, NULL
+  {0, NULL, NULL}
 };
 
 /* Translation table for signal generation information.  See UNIX System
    V Release 4 Programmer's Reference Manual, siginfo(5).  */
 
-static struct sigcode {
-  int signo;
-  int code;
-  char *codename;
-  char *desc;
-} siginfo_table[] = {
+static struct sigcode
+  {
+    int signo;
+    int code;
+    char *codename;
+    char *desc;
+  }
+siginfo_table[] =
+{
 #if defined (SIGILL) && defined (ILL_ILLOPC)
-  SIGILL, ILL_ILLOPC, "ILL_ILLOPC", "Illegal opcode",
+  {
+    SIGILL, ILL_ILLOPC, "ILL_ILLOPC", "Illegal opcode"
+  }
+  ,
 #endif
 #if defined (SIGILL) && defined (ILL_ILLOPN)
-  SIGILL, ILL_ILLOPN, "ILL_ILLOPN", "Illegal operand",
+  {
+    SIGILL, ILL_ILLOPN, "ILL_ILLOPN", "Illegal operand",
+  }
+  ,
 #endif
 #if defined (SIGILL) && defined (ILL_ILLADR)
-  SIGILL, ILL_ILLADR, "ILL_ILLADR", "Illegal addressing mode",
+  {
+    SIGILL, ILL_ILLADR, "ILL_ILLADR", "Illegal addressing mode"
+  }
+  ,
 #endif
 #if defined (SIGILL) && defined (ILL_ILLTRP)
-  SIGILL, ILL_ILLTRP, "ILL_ILLTRP", "Illegal trap",
+  {
+    SIGILL, ILL_ILLTRP, "ILL_ILLTRP", "Illegal trap"
+  }
+  ,
 #endif
 #if defined (SIGILL) && defined (ILL_PRVOPC)
-  SIGILL, ILL_PRVOPC, "ILL_PRVOPC", "Privileged opcode",
+  {
+    SIGILL, ILL_PRVOPC, "ILL_PRVOPC", "Privileged opcode"
+  }
+  ,
 #endif
 #if defined (SIGILL) && defined (ILL_PRVREG)
-  SIGILL, ILL_PRVREG, "ILL_PRVREG", "Privileged register",
+  {
+    SIGILL, ILL_PRVREG, "ILL_PRVREG", "Privileged register"
+  }
+  ,
 #endif
 #if defined (SIGILL) && defined (ILL_COPROC)
-  SIGILL, ILL_COPROC, "ILL_COPROC", "Coprocessor error",
+  {
+    SIGILL, ILL_COPROC, "ILL_COPROC", "Coprocessor error"
+  }
+  ,
 #endif
 #if defined (SIGILL) && defined (ILL_BADSTK)
-  SIGILL, ILL_BADSTK, "ILL_BADSTK", "Internal stack error",
+  {
+    SIGILL, ILL_BADSTK, "ILL_BADSTK", "Internal stack error"
+  }
+  ,
 #endif
 #if defined (SIGFPE) && defined (FPE_INTDIV)
-  SIGFPE, FPE_INTDIV, "FPE_INTDIV", "Integer divide by zero",
+  {
+    SIGFPE, FPE_INTDIV, "FPE_INTDIV", "Integer divide by zero"
+  }
+  ,
 #endif
 #if defined (SIGFPE) && defined (FPE_INTOVF)
-  SIGFPE, FPE_INTOVF, "FPE_INTOVF", "Integer overflow",
+  {
+    SIGFPE, FPE_INTOVF, "FPE_INTOVF", "Integer overflow"
+  }
+  ,
 #endif
 #if defined (SIGFPE) && defined (FPE_FLTDIV)
-  SIGFPE, FPE_FLTDIV, "FPE_FLTDIV", "Floating point divide by zero",
+  {
+    SIGFPE, FPE_FLTDIV, "FPE_FLTDIV", "Floating point divide by zero"
+  }
+  ,
 #endif
 #if defined (SIGFPE) && defined (FPE_FLTOVF)
-  SIGFPE, FPE_FLTOVF, "FPE_FLTOVF", "Floating point overflow",
+  {
+    SIGFPE, FPE_FLTOVF, "FPE_FLTOVF", "Floating point overflow"
+  }
+  ,
 #endif
 #if defined (SIGFPE) && defined (FPE_FLTUND)
-  SIGFPE, FPE_FLTUND, "FPE_FLTUND", "Floating point underflow",
+  {
+    SIGFPE, FPE_FLTUND, "FPE_FLTUND", "Floating point underflow"
+  }
+  ,
 #endif
 #if defined (SIGFPE) && defined (FPE_FLTRES)
-  SIGFPE, FPE_FLTRES, "FPE_FLTRES", "Floating point inexact result",
+  {
+    SIGFPE, FPE_FLTRES, "FPE_FLTRES", "Floating point inexact result"
+  }
+  ,
 #endif
 #if defined (SIGFPE) && defined (FPE_FLTINV)
-  SIGFPE, FPE_FLTINV, "FPE_FLTINV", "Invalid floating point operation",
+  {
+    SIGFPE, FPE_FLTINV, "FPE_FLTINV", "Invalid floating point operation"
+  }
+  ,
 #endif
 #if defined (SIGFPE) && defined (FPE_FLTSUB)
-  SIGFPE, FPE_FLTSUB, "FPE_FLTSUB", "Subscript out of range",
+  {
+    SIGFPE, FPE_FLTSUB, "FPE_FLTSUB", "Subscript out of range"
+  }
+  ,
 #endif
 #if defined (SIGSEGV) && defined (SEGV_MAPERR)
-  SIGSEGV, SEGV_MAPERR, "SEGV_MAPERR", "Address not mapped to object",
+  {
+    SIGSEGV, SEGV_MAPERR, "SEGV_MAPERR", "Address not mapped to object"
+  }
+  ,
 #endif
 #if defined (SIGSEGV) && defined (SEGV_ACCERR)
-  SIGSEGV, SEGV_ACCERR, "SEGV_ACCERR", "Invalid permissions for object",
+  {
+    SIGSEGV, SEGV_ACCERR, "SEGV_ACCERR", "Invalid permissions for object"
+  }
+  ,
 #endif
 #if defined (SIGBUS) && defined (BUS_ADRALN)
-  SIGBUS, BUS_ADRALN, "BUS_ADRALN", "Invalid address alignment",
+  {
+    SIGBUS, BUS_ADRALN, "BUS_ADRALN", "Invalid address alignment"
+  }
+  ,
 #endif
 #if defined (SIGBUS) && defined (BUS_ADRERR)
-  SIGBUS, BUS_ADRERR, "BUS_ADRERR", "Non-existent physical address",
+  {
+    SIGBUS, BUS_ADRERR, "BUS_ADRERR", "Non-existent physical address"
+  }
+  ,
 #endif
 #if defined (SIGBUS) && defined (BUS_OBJERR)
-  SIGBUS, BUS_OBJERR, "BUS_OBJERR", "Object specific hardware error",
+  {
+    SIGBUS, BUS_OBJERR, "BUS_OBJERR", "Object specific hardware error"
+  }
+  ,
 #endif
 #if defined (SIGTRAP) && defined (TRAP_BRKPT)
-  SIGTRAP, TRAP_BRKPT, "TRAP_BRKPT", "Process breakpoint",
+  {
+    SIGTRAP, TRAP_BRKPT, "TRAP_BRKPT", "Process breakpoint"
+  }
+  ,
 #endif
 #if defined (SIGTRAP) && defined (TRAP_TRACE)
-  SIGTRAP, TRAP_TRACE, "TRAP_TRACE", "Process trace trap",
+  {
+    SIGTRAP, TRAP_TRACE, "TRAP_TRACE", "Process trace trap"
+  }
+  ,
 #endif
 #if defined (SIGCLD) && defined (CLD_EXITED)
-  SIGCLD, CLD_EXITED, "CLD_EXITED", "Child has exited",
+  {
+    SIGCLD, CLD_EXITED, "CLD_EXITED", "Child has exited"
+  }
+  ,
 #endif
 #if defined (SIGCLD) && defined (CLD_KILLED)
-  SIGCLD, CLD_KILLED, "CLD_KILLED", "Child was killed",
+  {
+    SIGCLD, CLD_KILLED, "CLD_KILLED", "Child was killed"
+  }
+  ,
 #endif
 #if defined (SIGCLD) && defined (CLD_DUMPED)
-  SIGCLD, CLD_DUMPED, "CLD_DUMPED", "Child has terminated abnormally",
+  {
+    SIGCLD, CLD_DUMPED, "CLD_DUMPED", "Child has terminated abnormally"
+  }
+  ,
 #endif
 #if defined (SIGCLD) && defined (CLD_TRAPPED)
-  SIGCLD, CLD_TRAPPED, "CLD_TRAPPED", "Traced child has trapped",
+  {
+    SIGCLD, CLD_TRAPPED, "CLD_TRAPPED", "Traced child has trapped"
+  }
+  ,
 #endif
 #if defined (SIGCLD) && defined (CLD_STOPPED)
-  SIGCLD, CLD_STOPPED, "CLD_STOPPED", "Child has stopped",
+  {
+    SIGCLD, CLD_STOPPED, "CLD_STOPPED", "Child has stopped"
+  }
+  ,
 #endif
 #if defined (SIGCLD) && defined (CLD_CONTINUED)
-  SIGCLD, CLD_CONTINUED, "CLD_CONTINUED", "Stopped child had continued",
+  {
+    SIGCLD, CLD_CONTINUED, "CLD_CONTINUED", "Stopped child had continued"
+  }
+  ,
 #endif
 #if defined (SIGPOLL) && defined (POLL_IN)
-  SIGPOLL, POLL_IN, "POLL_IN", "Input input available",
+  {
+    SIGPOLL, POLL_IN, "POLL_IN", "Input input available"
+  }
+  ,
 #endif
 #if defined (SIGPOLL) && defined (POLL_OUT)
-  SIGPOLL, POLL_OUT, "POLL_OUT", "Output buffers available",
+  {
+    SIGPOLL, POLL_OUT, "POLL_OUT", "Output buffers available"
+  }
+  ,
 #endif
 #if defined (SIGPOLL) && defined (POLL_MSG)
-  SIGPOLL, POLL_MSG, "POLL_MSG", "Input message available",
+  {
+    SIGPOLL, POLL_MSG, "POLL_MSG", "Input message available"
+  }
+  ,
 #endif
 #if defined (SIGPOLL) && defined (POLL_ERR)
-  SIGPOLL, POLL_ERR, "POLL_ERR", "I/O error",
+  {
+    SIGPOLL, POLL_ERR, "POLL_ERR", "I/O error"
+  }
+  ,
 #endif
 #if defined (SIGPOLL) && defined (POLL_PRI)
-  SIGPOLL, POLL_PRI, "POLL_PRI", "High priority input available",
+  {
+    SIGPOLL, POLL_PRI, "POLL_PRI", "High priority input available"
+  }
+  ,
 #endif
 #if defined (SIGPOLL) && defined (POLL_HUP)
-  SIGPOLL, POLL_HUP, "POLL_HUP", "Device disconnected",
+  {
+    SIGPOLL, POLL_HUP, "POLL_HUP", "Device disconnected"
+  }
+  ,
 #endif
-  0, 0, NULL, NULL
+  {
+    0, 0, NULL, NULL
+  }
 };
 
 static char *syscall_table[MAX_SYSCALLS];
 
 /* Prototypes for local functions */
 
-static void
-set_proc_siginfo PARAMS ((struct procinfo *, int));
+static void procfs_stop PARAMS ((void));
 
-static void
-init_syscall_table PARAMS ((void));
+static int procfs_thread_alive PARAMS ((int));
 
-static char *
-syscallname PARAMS ((int));
+static int procfs_can_run PARAMS ((void));
 
-static char *
-signalname PARAMS ((int));
+static void procfs_mourn_inferior PARAMS ((void));
 
-static char *
-errnoname PARAMS ((int));
+static void procfs_fetch_registers PARAMS ((int));
 
-static int
-proc_address_to_fd PARAMS ((CORE_ADDR, int));
+static int procfs_wait PARAMS ((int, struct target_waitstatus *));
 
-static int
-open_proc_file PARAMS ((int, struct procinfo *));
+static void procfs_open PARAMS ((char *, int));
 
-static void
-close_proc_file PARAMS ((struct procinfo *));
+static void procfs_files_info PARAMS ((struct target_ops *));
 
-static void
-unconditionally_kill_inferior PARAMS ((void));
+static void procfs_prepare_to_store PARAMS ((void));
 
-static void
-proc_init_failed PARAMS ((char *));
+static void procfs_detach PARAMS ((char *, int));
 
-static void
-info_proc PARAMS ((char *, int));
+static void procfs_attach PARAMS ((char *, int));
 
-static void
-info_proc_flags PARAMS ((struct procinfo *, int));
+static void proc_set_exec_trap PARAMS ((void));
 
-static void
-info_proc_stop PARAMS ((struct procinfo *, int));
+static void procfs_init_inferior PARAMS ((int));
 
-static void
-info_proc_siginfo PARAMS ((struct procinfo *, int));
+static struct procinfo *create_procinfo PARAMS ((int));
 
-static void
-info_proc_syscalls PARAMS ((struct procinfo *, int));
+static void procfs_store_registers PARAMS ((int));
 
-static void
-info_proc_mappings PARAMS ((struct procinfo *, int));
+static int procfs_xfer_memory PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *));
 
-static void
-info_proc_signals PARAMS ((struct procinfo *, int));
+static void procfs_kill_inferior PARAMS ((void));
 
-static void
-info_proc_faults PARAMS ((struct procinfo *, int));
+static char *sigcodedesc PARAMS ((siginfo_t *));
 
-static char *
-mappingflags PARAMS ((long));
+static char *sigcodename PARAMS ((siginfo_t *));
 
-static char *
-lookupname PARAMS ((struct trans *, unsigned int, char *));
+static struct procinfo *wait_fd PARAMS ((void));
 
-static char *
-lookupdesc PARAMS ((struct trans *, unsigned int));
+static void remove_fd PARAMS ((struct procinfo *));
 
-/* External function prototypes that can't be easily included in any
-   header file because the args are typedefs in system include files. */
+static void add_fd PARAMS ((struct procinfo *));
 
-extern void
-supply_gregset PARAMS ((gregset_t *));
+static void set_proc_siginfo PARAMS ((struct procinfo *, int));
 
-extern void
-fill_gregset PARAMS ((gregset_t *, int));
+static void init_syscall_table PARAMS ((void));
 
-extern void
-supply_fpregset PARAMS ((fpregset_t *));
+static char *syscallname PARAMS ((int));
 
-extern void
-fill_fpregset PARAMS ((fpregset_t *, int));
+static char *signalname PARAMS ((int));
 
-/*
+static char *errnoname PARAMS ((int));
 
-LOCAL FUNCTION
+static int proc_address_to_fd PARAMS ((struct procinfo *, CORE_ADDR, int));
 
-       lookupdesc -- translate a value to a summary desc string
+static int open_proc_file PARAMS ((int, struct procinfo *, int, int));
 
-SYNOPSIS
+static void close_proc_file PARAMS ((struct procinfo *));
 
-       static char *lookupdesc (struct trans *transp, unsigned int val);
+static void close_proc_file_cleanup PARAMS ((void *));
 
-DESCRIPTION
-       
-       Given a pointer to a translation table and a value to be translated,
-       lookup the desc string and return it.
- */
+static struct cleanup *make_cleanup_close_proc_file PARAMS ((struct procinfo *));
 
-static char *
-lookupdesc (transp, val)
-     struct trans *transp;
-     unsigned int val;
-{
-  char *desc;
-  
-  for (desc = NULL; transp -> name != NULL; transp++)
-    {
-      if (transp -> value == val)
-       {
-         desc = transp -> desc;
-         break;
-       }
-    }
+static void unconditionally_kill_inferior PARAMS ((struct procinfo *));
 
-  /* Didn't find a translation for the specified value, set a default one. */
+static NORETURN void proc_init_failed
+PARAMS ((struct procinfo *, char *, int)) ATTR_NORETURN;
 
-  if (desc == NULL)
-    {
-      desc = "Unknown";
-    }
-  return (desc);
-}
+     static void info_proc PARAMS ((char *, int));
 
-/*
+     static void info_proc_flags PARAMS ((struct procinfo *, int));
 
-LOCAL FUNCTION
+     static void info_proc_stop PARAMS ((struct procinfo *, int));
 
-       lookupname -- translate a value to symbolic name
+     static void info_proc_siginfo PARAMS ((struct procinfo *, int));
 
-SYNOPSIS
+     static void info_proc_syscalls PARAMS ((struct procinfo *, int));
 
-       static char *lookupname (struct trans *transp, unsigned int val,
-                                char *prefix);
+     static void info_proc_mappings PARAMS ((struct procinfo *, int));
 
-DESCRIPTION
-       
-       Given a pointer to a translation table, a value to be translated,
-       and a default prefix to return if the value can't be translated,
-       match the value with one of the translation table entries and
-       return a pointer to the symbolic name.
+     static void info_proc_signals PARAMS ((struct procinfo *, int));
 
-       If no match is found it just returns the value as a printable string,
-       with the given prefix.  The previous such value, if any, is freed
-       at this time.
- */
+     static void info_proc_faults PARAMS ((struct procinfo *, int));
 
-static char *
-lookupname (transp, val, prefix)
-     struct trans *transp;
-     unsigned int val;
-     char *prefix;
-{
-  static char *locbuf;
-  char *name;
-  
-  for (name = NULL; transp -> name != NULL; transp++)
-    {
-      if (transp -> value == val)
-       {
-         name = transp -> name;
-         break;
-       }
-    }
+     static char *mappingflags PARAMS ((long));
 
-  /* Didn't find a translation for the specified value, build a default
-     one using the specified prefix and return it.  The lifetime of
-     the value is only until the next one is needed. */
+     static char *lookupname PARAMS ((struct trans *, unsigned int, char *));
 
-  if (name == NULL)
-    {
-      if (locbuf != NULL)
-       {
-         free (locbuf);
-       }
-      locbuf = xmalloc (strlen (prefix) + 16);
-      (void) sprintf (locbuf, "%s %u", prefix, val);
-      name = locbuf;
-    }
-  return (name);
-}
+     static char *lookupdesc PARAMS ((struct trans *, unsigned int));
 
-static char *
-sigcodename (sip)
-     siginfo_t *sip;
-{
-  struct sigcode *scp;
-  char *name = NULL;
-  static char locbuf[32];
-  
-  for (scp = siginfo_table; scp -> codename != NULL; scp++)
-    {
-      if ((scp -> signo == sip -> si_signo) &&
-         (scp -> code == sip -> si_code))
-       {
-         name = scp -> codename;
-         break;
-       }
-    }
-  if (name == NULL)
-    {
-      (void) sprintf (locbuf, "sigcode %u", sip -> si_signo);
-      name = locbuf;
-    }
-  return (name);
-}
+     static int do_attach PARAMS ((int pid));
 
-static char *sigcodedesc (sip)
-     siginfo_t *sip;
-{
-  struct sigcode *scp;
-  char *desc = NULL;
-  
-  for (scp = siginfo_table; scp -> codename != NULL; scp++)
-    {
-      if ((scp -> signo == sip -> si_signo) &&
-         (scp -> code == sip -> si_code))
-       {
-         desc = scp -> desc;
-         break;
-       }
-    }
-  if (desc == NULL)
-    {
-      desc = "Unrecognized signal or trap use";
-    }
-  return (desc);
-}
+     static void do_detach PARAMS ((int siggnal));
 
-/*
+     static void procfs_create_inferior PARAMS ((char *, char *, char **));
 
-LOCAL FUNCTION
+     static void procfs_notice_signals PARAMS ((int pid));
 
-       syscallname - translate a system call number into a system call name
+     static void notice_signals PARAMS ((struct procinfo *, struct sig_ctl *));
 
-SYNOPSIS
+     static struct procinfo *find_procinfo PARAMS ((pid_t pid, int okfail));
 
-       char *syscallname (int syscallnum)
+     static int procfs_write_pcwstop PARAMS ((struct procinfo *));
+     static int procfs_read_status PARAMS ((struct procinfo *));
+     static void procfs_write_pckill PARAMS ((struct procinfo *));
 
-DESCRIPTION
+     typedef int syscall_func_t PARAMS ((struct procinfo * pi, int syscall_num,
+                                      int why, int *rtnval, int *statval));
 
-       Given a system call number, translate it into the printable name
-       of a system call, or into "syscall <num>" if it is an unknown
-       number.
- */
+     static void procfs_set_syscall_trap PARAMS ((struct procinfo * pi,
+                                                 int syscall_num, int flags,
+                                                 syscall_func_t * func));
 
-static char *
-syscallname (syscallnum)
-     int syscallnum;
-{
-  static char locbuf[32];
-  char *rtnval;
-  
-  if (syscallnum >= 0 && syscallnum < MAX_SYSCALLS)
-    {
-      rtnval = syscall_table[syscallnum];
-    }
-  else
+     static void procfs_clear_syscall_trap PARAMS ((struct procinfo * pi,
+                                              int syscall_num, int errok));
+
+#define PROCFS_SYSCALL_ENTRY 0x1       /* Trap on entry to sys call */
+#define PROCFS_SYSCALL_EXIT 0x2        /* Trap on exit from sys call */
+
+     static syscall_func_t procfs_exit_handler;
+
+     static syscall_func_t procfs_exec_handler;
+
+#ifdef SYS_sproc
+     static syscall_func_t procfs_sproc_handler;
+     static syscall_func_t procfs_fork_handler;
+#endif
+
+#ifdef SYS_lwp_create
+     static syscall_func_t procfs_lwp_creation_handler;
+#endif
+
+     static void modify_inherit_on_fork_flag PARAMS ((int fd, int flag));
+     static void modify_run_on_last_close_flag PARAMS ((int fd, int flag));
+
+/* */
+
+     struct procfs_syscall_handler
+       {
+        int syscall_num;       /* The number of the system call being handled */
+        /* The function to be called */
+        syscall_func_t *func;
+       };
+
+     static void procfs_resume PARAMS ((int pid, int step,
+                                       enum target_signal signo));
+
+     static void init_procfs_ops PARAMS ((void));
+
+/* 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 ((gdb_gregset_t *));
+
+     extern void fill_gregset PARAMS ((gdb_gregset_t *, int));
+
+#ifdef FP0_REGNUM
+     extern void supply_fpregset PARAMS ((gdb_fpregset_t *));
+
+     extern void fill_fpregset PARAMS ((gdb_fpregset_t *, int));
+#endif
+
+/*
+
+   LOCAL FUNCTION
+
+   find_procinfo -- convert a process id to a struct procinfo
+
+   SYNOPSIS
+
+   static struct procinfo * find_procinfo (pid_t pid, int okfail);
+
+   DESCRIPTION
+
+   Given a process id, look it up in the procinfo chain.  Returns
+   a struct procinfo *.  If can't find pid, then call error(),
+   unless okfail is set, in which case, return NULL;
+ */
+
+     static struct procinfo *
+       find_procinfo (pid, okfail)
+     pid_t pid;
+     int okfail;
+{
+  struct procinfo *procinfo;
+
+  for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)
+    if (procinfo->pid == pid)
+      return procinfo;
+
+  if (okfail)
+    return NULL;
+
+  error ("procfs (find_procinfo):  Couldn't locate pid %d", pid);
+}
+
+/*
+
+   LOCAL MACRO
+
+   current_procinfo -- convert inferior_pid to a struct procinfo
+
+   SYNOPSIS
+
+   static struct procinfo * current_procinfo;
+
+   DESCRIPTION
+
+   Looks up inferior_pid in the procinfo chain.  Always returns a
+   struct procinfo *.  If process can't be found, we error() out.
+ */
+
+#define current_procinfo find_procinfo (inferior_pid, 0)
+
+/*
+
+   LOCAL FUNCTION
+
+   add_fd -- Add the fd to the poll/select list
+
+   SYNOPSIS
+
+   static void add_fd (struct procinfo *);
+
+   DESCRIPTION
+
+   Add the fd of the supplied procinfo to the list of fds used for
+   poll/select operations.
+ */
+
+static void
+add_fd (pi)
+     struct procinfo *pi;
+{
+  if (num_poll_list <= 0)
+    poll_list = (struct pollfd *) xmalloc (sizeof (struct pollfd));
+  else
+    poll_list = (struct pollfd *) xrealloc (poll_list,
+                                           (num_poll_list + 1)
+                                           * sizeof (struct pollfd));
+  poll_list[num_poll_list].fd = pi->ctl_fd;
+#ifdef UNIXWARE
+  poll_list[num_poll_list].events = POLLWRNORM;
+#else
+  poll_list[num_poll_list].events = POLLPRI;
+#endif
+
+  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;
+{
+  int i;
+
+  for (i = 0; i < num_poll_list; i++)
     {
-      (void) sprintf (locbuf, "syscall %u", syscallnum);
-      rtnval = locbuf;
+      if (poll_list[i].fd == pi->ctl_fd)
+       {
+         if (i != num_poll_list - 1)
+           memcpy (poll_list + i, poll_list + i + 1,
+                   (num_poll_list - i - 1) * sizeof (struct pollfd));
+
+         num_poll_list--;
+
+         if (num_poll_list == 0)
+           free (poll_list);
+         else
+           poll_list = (struct pollfd *) xrealloc (poll_list,
+                                                   num_poll_list
+                                                 * sizeof (struct pollfd));
+         return;
+       }
+    }
+}
+
+/*
+
+   LOCAL FUNCTION
+
+   procfs_read_status - get procfs fd status
+
+   SYNOPSIS
+
+   static int procfs_read_status (pi) struct procinfo *pi;
+
+   DESCRIPTION
+
+   Given a pointer to a procinfo struct, get the status of
+   the status_fd in the appropriate way.  Returns 0 on failure,
+   1 on success.
+ */
+
+static int
+procfs_read_status (pi)
+     struct procinfo *pi;
+{
+#ifdef PROCFS_USE_READ_WRITE
+  if ((lseek (pi->status_fd, 0, SEEK_SET) < 0) ||
+      (read (pi->status_fd, (char *) &pi->prstatus,
+            sizeof (gdb_prstatus_t)) != sizeof (gdb_prstatus_t)))
+#else
+  if (ioctl (pi->status_fd, PIOCSTATUS, &pi->prstatus) < 0)
+#endif
+    return 0;
+  else
+    return 1;
+}
+
+/*
+
+   LOCAL FUNCTION
+
+   procfs_write_pcwstop - send a PCWSTOP to procfs fd
+
+   SYNOPSIS
+
+   static int procfs_write_pcwstop (pi) struct procinfo *pi;
+
+   DESCRIPTION
+
+   Given a pointer to a procinfo struct, send a PCWSTOP to
+   the ctl_fd in the appropriate way.  Returns 0 on failure,
+   1 on success.
+ */
+
+static int
+procfs_write_pcwstop (pi)
+     struct procinfo *pi;
+{
+#ifdef PROCFS_USE_READ_WRITE
+  long cmd = PCWSTOP;
+  if (write (pi->ctl_fd, (char *) &cmd, sizeof (long)) < 0)
+#else
+  if (ioctl (pi->ctl_fd, PIOCWSTOP, &pi->prstatus) < 0)
+#endif
+    return 0;
+  else
+    return 1;
+}
+
+/*
+
+   LOCAL FUNCTION
+
+   procfs_write_pckill - send a kill to procfs fd
+
+   SYNOPSIS
+
+   static void procfs_write_pckill (pi) struct procinfo *pi;
+
+   DESCRIPTION
+
+   Given a pointer to a procinfo struct, send a kill to
+   the ctl_fd in the appropriate way.  Returns 0 on failure,
+   1 on success.
+ */
+
+static void
+procfs_write_pckill (pi)
+     struct procinfo *pi;
+{
+#ifdef PROCFS_USE_READ_WRITE
+  struct proc_ctl pctl;
+  pctl.cmd = PCKILL;
+  pctl.data = SIGKILL;
+  write (pi->ctl_fd, &pctl, sizeof (struct proc_ctl));
+#else
+  int signo = SIGKILL;
+  ioctl (pi->ctl_fd, PIOCKILL, &signo);
+#endif
+}
+
+static struct procinfo *
+wait_fd ()
+{
+  struct procinfo *pi, *next_pi;
+#ifndef LOSING_POLL
+  int num_fds;
+  int i;
+#endif
+
+  set_sigint_trap ();          /* Causes SIGINT to be passed on to the
+                                  attached process. */
+  set_sigio_trap ();
+
+wait_again:
+#ifndef LOSING_POLL
+  while (1)
+    {
+      num_fds = poll (poll_list, num_poll_list, -1);
+      if (num_fds > 0)
+       break;
+      if (num_fds < 0 && errno == EINTR)
+       continue;
+      print_sys_errmsg ("poll failed", errno);
+      error ("Poll failed, returned %d", num_fds);
+    }
+#else /* LOSING_POLL */
+  pi = current_procinfo;
+
+  while (!procfs_write_pcwstop (pi))
+    {
+      if (errno == ENOENT)
+       {
+         /* Process exited.  */
+         pi->prstatus.pr_flags = 0;
+         break;
+       }
+      else if (errno != EINTR)
+       {
+         print_sys_errmsg (pi->pathname, errno);
+         error ("procfs_write_pcwstop failed");
+       }
+    }
+  pi->had_event = 1;
+#endif /* LOSING_POLL */
+
+  clear_sigint_trap ();
+  clear_sigio_trap ();
+
+#ifndef LOSING_POLL
+
+  for (i = 0; i < num_poll_list && num_fds > 0; i++)
+    {
+      if (0 == (poll_list[i].revents &
+               (POLLWRNORM | POLLPRI | POLLERR | POLLHUP | POLLNVAL)))
+       continue;
+      for (pi = procinfo_list; pi; pi = next_pi)
+       {
+         next_pi = pi->next;
+         if (poll_list[i].fd == pi->ctl_fd)
+           {
+             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);
+                 i--;          /* don't skip deleted entry */
+                 if (num_fds != 0)
+                   break;      /* already another event to process */
+                 else
+                   goto wait_again;    /* wait for another event */
+               }
+             pi->had_event = 1;
+             break;
+           }
+       }
+      if (!pi)
+       error ("wait_fd: Couldn't find procinfo for fd %d\n",
+              poll_list[i].fd);
+    }
+#endif /* LOSING_POLL */
+
+  return pi;
+}
+
+/*
+
+   LOCAL FUNCTION
+
+   lookupdesc -- translate a value to a summary desc string
+
+   SYNOPSIS
+
+   static char *lookupdesc (struct trans *transp, unsigned int val);
+
+   DESCRIPTION
+
+   Given a pointer to a translation table and a value to be translated,
+   lookup the desc string and return it.
+ */
+
+static char *
+lookupdesc (transp, val)
+     struct trans *transp;
+     unsigned int val;
+{
+  char *desc;
+
+  for (desc = NULL; transp->name != NULL; transp++)
+    {
+      if (transp->value == val)
+       {
+         desc = transp->desc;
+         break;
+       }
+    }
+
+  /* Didn't find a translation for the specified value, set a default one. */
+
+  if (desc == NULL)
+    {
+      desc = "Unknown";
+    }
+  return (desc);
+}
+
+/*
+
+   LOCAL FUNCTION
+
+   lookupname -- translate a value to symbolic name
+
+   SYNOPSIS
+
+   static char *lookupname (struct trans *transp, unsigned int val,
+   char *prefix);
+
+   DESCRIPTION
+
+   Given a pointer to a translation table, a value to be translated,
+   and a default prefix to return if the value can't be translated,
+   match the value with one of the translation table entries and
+   return a pointer to the symbolic name.
+
+   If no match is found it just returns the value as a printable string,
+   with the given prefix.  The previous such value, if any, is freed
+   at this time.
+ */
+
+static char *
+lookupname (transp, val, prefix)
+     struct trans *transp;
+     unsigned int val;
+     char *prefix;
+{
+  static char *locbuf;
+  char *name;
+
+  for (name = NULL; transp->name != NULL; transp++)
+    {
+      if (transp->value == val)
+       {
+         name = transp->name;
+         break;
+       }
+    }
+
+  /* Didn't find a translation for the specified value, build a default
+     one using the specified prefix and return it.  The lifetime of
+     the value is only until the next one is needed. */
+
+  if (name == NULL)
+    {
+      if (locbuf != NULL)
+       {
+         free (locbuf);
+       }
+      locbuf = xmalloc (strlen (prefix) + 16);
+      sprintf (locbuf, "%s %u", prefix, val);
+      name = locbuf;
+    }
+  return (name);
+}
+
+static char *
+sigcodename (sip)
+     siginfo_t *sip;
+{
+  struct sigcode *scp;
+  char *name = NULL;
+  static char locbuf[32];
+
+  for (scp = siginfo_table; scp->codename != NULL; scp++)
+    {
+      if ((scp->signo == sip->si_signo) &&
+         (scp->code == sip->si_code))
+       {
+         name = scp->codename;
+         break;
+       }
+    }
+  if (name == NULL)
+    {
+      sprintf (locbuf, "sigcode %u", sip->si_signo);
+      name = locbuf;
+    }
+  return (name);
+}
+
+static char *
+sigcodedesc (sip)
+     siginfo_t *sip;
+{
+  struct sigcode *scp;
+  char *desc = NULL;
+
+  for (scp = siginfo_table; scp->codename != NULL; scp++)
+    {
+      if ((scp->signo == sip->si_signo) &&
+         (scp->code == sip->si_code))
+       {
+         desc = scp->desc;
+         break;
+       }
+    }
+  if (desc == NULL)
+    {
+      desc = "Unrecognized signal or trap use";
+    }
+  return (desc);
+}
+
+/*
+
+   LOCAL FUNCTION
+
+   syscallname - translate a system call number into a system call name
+
+   SYNOPSIS
+
+   char *syscallname (int syscallnum)
+
+   DESCRIPTION
+
+   Given a system call number, translate it into the printable name
+   of a system call, or into "syscall <num>" if it is an unknown
+   number.
+ */
+
+static char *
+syscallname (syscallnum)
+     int syscallnum;
+{
+  static char locbuf[32];
+
+  if (syscallnum >= 0 && syscallnum < MAX_SYSCALLS
+      && syscall_table[syscallnum] != NULL)
+    return syscall_table[syscallnum];
+  else
+    {
+      sprintf (locbuf, "syscall %u", syscallnum);
+      return locbuf;
     }
-  return (rtnval);
 }
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       init_syscall_table - initialize syscall translation table
+   init_syscall_table - initialize syscall translation table
 
-SYNOPSIS
+   SYNOPSIS
 
-       void init_syscall_table (void)
+   void init_syscall_table (void)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Dynamically initialize the translation table to convert system
-       call numbers into printable system call names.  Done once per
-       gdb run, on initialization.
+   Dynamically initialize the translation table to convert system
+   call numbers into printable system call names.  Done once per
+   gdb run, on initialization.
 
-NOTES
+   NOTES
 
-       This is awfully ugly, but preprocessor tricks to make it prettier
-       tend to be nonportable.
+   This is awfully ugly, but preprocessor tricks to make it prettier
+   tend to be nonportable.
  */
 
 static void
@@ -784,6 +1486,9 @@ init_syscall_table ()
 #if defined (SYS_sys3b)
   syscall_table[SYS_sys3b] = "sys3b";
 #endif
+#if defined (SYS_sysi86)
+  syscall_table[SYS_sysi86] = "sysi86";
+#endif
 #if defined (SYS_acct)
   syscall_table[SYS_acct] = "acct";
 #endif
@@ -904,559 +1609,1395 @@ init_syscall_table ()
 #if defined (SYS_hrtsys)
   syscall_table[SYS_hrtsys] = "hrtsys";
 #endif
-#if defined (SYS_acancel)
-  syscall_table[SYS_acancel] = "acancel";
+#if defined (SYS_acancel)
+  syscall_table[SYS_acancel] = "acancel";
+#endif
+#if defined (SYS_async)
+  syscall_table[SYS_async] = "async";
+#endif
+#if defined (SYS_priocntlsys)
+  syscall_table[SYS_priocntlsys] = "priocntlsys";
+#endif
+#if defined (SYS_pathconf)
+  syscall_table[SYS_pathconf] = "pathconf";
+#endif
+#if defined (SYS_mincore)
+  syscall_table[SYS_mincore] = "mincore";
+#endif
+#if defined (SYS_mmap)
+  syscall_table[SYS_mmap] = "mmap";
+#endif
+#if defined (SYS_mprotect)
+  syscall_table[SYS_mprotect] = "mprotect";
+#endif
+#if defined (SYS_munmap)
+  syscall_table[SYS_munmap] = "munmap";
+#endif
+#if defined (SYS_fpathconf)
+  syscall_table[SYS_fpathconf] = "fpathconf";
+#endif
+#if defined (SYS_vfork)
+  syscall_table[SYS_vfork] = "vfork";
+#endif
+#if defined (SYS_fchdir)
+  syscall_table[SYS_fchdir] = "fchdir";
+#endif
+#if defined (SYS_readv)
+  syscall_table[SYS_readv] = "readv";
+#endif
+#if defined (SYS_writev)
+  syscall_table[SYS_writev] = "writev";
+#endif
+#if defined (SYS_xstat)
+  syscall_table[SYS_xstat] = "xstat";
+#endif
+#if defined (SYS_lxstat)
+  syscall_table[SYS_lxstat] = "lxstat";
+#endif
+#if defined (SYS_fxstat)
+  syscall_table[SYS_fxstat] = "fxstat";
+#endif
+#if defined (SYS_xmknod)
+  syscall_table[SYS_xmknod] = "xmknod";
+#endif
+#if defined (SYS_clocal)
+  syscall_table[SYS_clocal] = "clocal";
+#endif
+#if defined (SYS_setrlimit)
+  syscall_table[SYS_setrlimit] = "setrlimit";
+#endif
+#if defined (SYS_getrlimit)
+  syscall_table[SYS_getrlimit] = "getrlimit";
+#endif
+#if defined (SYS_lchown)
+  syscall_table[SYS_lchown] = "lchown";
+#endif
+#if defined (SYS_memcntl)
+  syscall_table[SYS_memcntl] = "memcntl";
+#endif
+#if defined (SYS_getpmsg)
+  syscall_table[SYS_getpmsg] = "getpmsg";
+#endif
+#if defined (SYS_putpmsg)
+  syscall_table[SYS_putpmsg] = "putpmsg";
+#endif
+#if defined (SYS_rename)
+  syscall_table[SYS_rename] = "rename";
+#endif
+#if defined (SYS_uname)
+  syscall_table[SYS_uname] = "uname";
+#endif
+#if defined (SYS_setegid)
+  syscall_table[SYS_setegid] = "setegid";
+#endif
+#if defined (SYS_sysconfig)
+  syscall_table[SYS_sysconfig] = "sysconfig";
+#endif
+#if defined (SYS_adjtime)
+  syscall_table[SYS_adjtime] = "adjtime";
+#endif
+#if defined (SYS_systeminfo)
+  syscall_table[SYS_systeminfo] = "systeminfo";
+#endif
+#if defined (SYS_seteuid)
+  syscall_table[SYS_seteuid] = "seteuid";
+#endif
+#if defined (SYS_sproc)
+  syscall_table[SYS_sproc] = "sproc";
+#endif
+#if defined (SYS_keyctl)
+  syscall_table[SYS_keyctl] = "keyctl";
+#endif
+#if defined (SYS_secsys)
+  syscall_table[SYS_secsys] = "secsys";
+#endif
+#if defined (SYS_filepriv)
+  syscall_table[SYS_filepriv] = "filepriv";
+#endif
+#if defined (SYS_procpriv)
+  syscall_table[SYS_procpriv] = "procpriv";
+#endif
+#if defined (SYS_devstat)
+  syscall_table[SYS_devstat] = "devstat";
+#endif
+#if defined (SYS_aclipc)
+  syscall_table[SYS_aclipc] = "aclipc";
+#endif
+#if defined (SYS_fdevstat)
+  syscall_table[SYS_fdevstat] = "fdevstat";
+#endif
+#if defined (SYS_flvlfile)
+  syscall_table[SYS_flvlfile] = "flvlfile";
+#endif
+#if defined (SYS_lvlfile)
+  syscall_table[SYS_lvlfile] = "lvlfile";
+#endif
+#if defined (SYS_lvlequal)
+  syscall_table[SYS_lvlequal] = "lvlequal";
+#endif
+#if defined (SYS_lvlproc)
+  syscall_table[SYS_lvlproc] = "lvlproc";
+#endif
+#if defined (SYS_lvlipc)
+  syscall_table[SYS_lvlipc] = "lvlipc";
+#endif
+#if defined (SYS_acl)
+  syscall_table[SYS_acl] = "acl";
+#endif
+#if defined (SYS_auditevt)
+  syscall_table[SYS_auditevt] = "auditevt";
+#endif
+#if defined (SYS_auditctl)
+  syscall_table[SYS_auditctl] = "auditctl";
+#endif
+#if defined (SYS_auditdmp)
+  syscall_table[SYS_auditdmp] = "auditdmp";
+#endif
+#if defined (SYS_auditlog)
+  syscall_table[SYS_auditlog] = "auditlog";
+#endif
+#if defined (SYS_auditbuf)
+  syscall_table[SYS_auditbuf] = "auditbuf";
+#endif
+#if defined (SYS_lvldom)
+  syscall_table[SYS_lvldom] = "lvldom";
+#endif
+#if defined (SYS_lvlvfs)
+  syscall_table[SYS_lvlvfs] = "lvlvfs";
+#endif
+#if defined (SYS_mkmld)
+  syscall_table[SYS_mkmld] = "mkmld";
+#endif
+#if defined (SYS_mldmode)
+  syscall_table[SYS_mldmode] = "mldmode";
+#endif
+#if defined (SYS_secadvise)
+  syscall_table[SYS_secadvise] = "secadvise";
+#endif
+#if defined (SYS_online)
+  syscall_table[SYS_online] = "online";
+#endif
+#if defined (SYS_setitimer)
+  syscall_table[SYS_setitimer] = "setitimer";
+#endif
+#if defined (SYS_getitimer)
+  syscall_table[SYS_getitimer] = "getitimer";
+#endif
+#if defined (SYS_gettimeofday)
+  syscall_table[SYS_gettimeofday] = "gettimeofday";
+#endif
+#if defined (SYS_settimeofday)
+  syscall_table[SYS_settimeofday] = "settimeofday";
+#endif
+#if defined (SYS_lwp_create)
+  syscall_table[SYS_lwp_create] = "_lwp_create";
+#endif
+#if defined (SYS_lwp_exit)
+  syscall_table[SYS_lwp_exit] = "_lwp_exit";
+#endif
+#if defined (SYS_lwp_wait)
+  syscall_table[SYS_lwp_wait] = "_lwp_wait";
+#endif
+#if defined (SYS_lwp_self)
+  syscall_table[SYS_lwp_self] = "_lwp_self";
+#endif
+#if defined (SYS_lwp_info)
+  syscall_table[SYS_lwp_info] = "_lwp_info";
+#endif
+#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";
+#endif
+#if defined (SYS_processor_exbind)
+  syscall_table[SYS_processor_exbind] = "processor_exbind";
+#endif
+#if defined (SYS_prepblock)
+  syscall_table[SYS_prepblock] = "prepblock";
+#endif
+#if defined (SYS_block)
+  syscall_table[SYS_block] = "block";
+#endif
+#if defined (SYS_rdblock)
+  syscall_table[SYS_rdblock] = "rdblock";
+#endif
+#if defined (SYS_unblock)
+  syscall_table[SYS_unblock] = "unblock";
+#endif
+#if defined (SYS_cancelblock)
+  syscall_table[SYS_cancelblock] = "cancelblock";
+#endif
+#if defined (SYS_pread)
+  syscall_table[SYS_pread] = "pread";
+#endif
+#if defined (SYS_pwrite)
+  syscall_table[SYS_pwrite] = "pwrite";
+#endif
+#if defined (SYS_truncate)
+  syscall_table[SYS_truncate] = "truncate";
+#endif
+#if defined (SYS_ftruncate)
+  syscall_table[SYS_ftruncate] = "ftruncate";
+#endif
+#if defined (SYS_lwp_kill)
+  syscall_table[SYS_lwp_kill] = "_lwp_kill";
+#endif
+#if defined (SYS_sigwait)
+  syscall_table[SYS_sigwait] = "sigwait";
+#endif
+#if defined (SYS_fork1)
+  syscall_table[SYS_fork1] = "fork1";
+#endif
+#if defined (SYS_forkall)
+  syscall_table[SYS_forkall] = "forkall";
 #endif
-#if defined (SYS_async)
-  syscall_table[SYS_async] = "async";
+#if defined (SYS_modload)
+  syscall_table[SYS_modload] = "modload";
 #endif
-#if defined (SYS_priocntlsys)
-  syscall_table[SYS_priocntlsys] = "priocntlsys";
+#if defined (SYS_moduload)
+  syscall_table[SYS_moduload] = "moduload";
 #endif
-#if defined (SYS_pathconf)
-  syscall_table[SYS_pathconf] = "pathconf";
+#if defined (SYS_modpath)
+  syscall_table[SYS_modpath] = "modpath";
 #endif
-#if defined (SYS_mincore)
-  syscall_table[SYS_mincore] = "mincore";
+#if defined (SYS_modstat)
+  syscall_table[SYS_modstat] = "modstat";
 #endif
-#if defined (SYS_mmap)
-  syscall_table[SYS_mmap] = "mmap";
+#if defined (SYS_modadm)
+  syscall_table[SYS_modadm] = "modadm";
 #endif
-#if defined (SYS_mprotect)
-  syscall_table[SYS_mprotect] = "mprotect";
+#if defined (SYS_getksym)
+  syscall_table[SYS_getksym] = "getksym";
 #endif
-#if defined (SYS_munmap)
-  syscall_table[SYS_munmap] = "munmap";
+#if defined (SYS_lwp_suspend)
+  syscall_table[SYS_lwp_suspend] = "_lwp_suspend";
 #endif
-#if defined (SYS_fpathconf)
-  syscall_table[SYS_fpathconf] = "fpathconf";
+#if defined (SYS_lwp_continue)
+  syscall_table[SYS_lwp_continue] = "_lwp_continue";
 #endif
-#if defined (SYS_vfork)
-  syscall_table[SYS_vfork] = "vfork";
+#if defined (SYS_priocntllst)
+  syscall_table[SYS_priocntllst] = "priocntllst";
 #endif
-#if defined (SYS_fchdir)
-  syscall_table[SYS_fchdir] = "fchdir";
+#if defined (SYS_sleep)
+  syscall_table[SYS_sleep] = "sleep";
 #endif
-#if defined (SYS_readv)
-  syscall_table[SYS_readv] = "readv";
+#if defined (SYS_lwp_sema_wait)
+  syscall_table[SYS_lwp_sema_wait] = "_lwp_sema_wait";
 #endif
-#if defined (SYS_writev)
-  syscall_table[SYS_writev] = "writev";
+#if defined (SYS_lwp_sema_post)
+  syscall_table[SYS_lwp_sema_post] = "_lwp_sema_post";
 #endif
-#if defined (SYS_xstat)
-  syscall_table[SYS_xstat] = "xstat";
+#if defined (SYS_lwp_sema_trywait)
+  syscall_table[SYS_lwp_sema_trywait] = "lwp_sema_trywait";
 #endif
-#if defined (SYS_lxstat)
-  syscall_table[SYS_lxstat] = "lxstat";
+#if defined(SYS_fstatvfs64)
+  syscall_table[SYS_fstatvfs64] = "fstatvfs64";
 #endif
-#if defined (SYS_fxstat)
-  syscall_table[SYS_fxstat] = "fxstat";
+#if defined(SYS_statvfs64)
+  syscall_table[SYS_statvfs64] = "statvfs64";
 #endif
-#if defined (SYS_xmknod)
-  syscall_table[SYS_xmknod] = "xmknod";
+#if defined(SYS_ftruncate64)
+  syscall_table[SYS_ftruncate64] = "ftruncate64";
 #endif
-#if defined (SYS_clocal)
-  syscall_table[SYS_clocal] = "clocal";
+#if defined(SYS_truncate64)
+  syscall_table[SYS_truncate64] = "truncate64";
 #endif
-#if defined (SYS_setrlimit)
-  syscall_table[SYS_setrlimit] = "setrlimit";
+#if defined(SYS_getrlimit64)
+  syscall_table[SYS_getrlimit64] = "getrlimit64";
 #endif
-#if defined (SYS_getrlimit)
-  syscall_table[SYS_getrlimit] = "getrlimit";
+#if defined(SYS_setrlimit64)
+  syscall_table[SYS_setrlimit64] = "setrlimit64";
 #endif
-#if defined (SYS_lchown)
-  syscall_table[SYS_lchown] = "lchown";
+#if defined(SYS_lseek64)
+  syscall_table[SYS_lseek64] = "lseek64";
 #endif
-#if defined (SYS_memcntl)
-  syscall_table[SYS_memcntl] = "memcntl";
+#if defined(SYS_mmap64)
+  syscall_table[SYS_mmap64] = "mmap64";
 #endif
-#if defined (SYS_getpmsg)
-  syscall_table[SYS_getpmsg] = "getpmsg";
+#if defined(SYS_pread64)
+  syscall_table[SYS_pread64] = "pread64";
 #endif
-#if defined (SYS_putpmsg)
-  syscall_table[SYS_putpmsg] = "putpmsg";
+#if defined(SYS_creat64)
+  syscall_table[SYS_creat64] = "creat64";
 #endif
-#if defined (SYS_rename)
-  syscall_table[SYS_rename] = "rename";
+#if defined(SYS_dshmsys)
+  syscall_table[SYS_dshmsys] = "dshmsys";
 #endif
-#if defined (SYS_uname)
-  syscall_table[SYS_uname] = "uname";
+#if defined(SYS_invlpg)
+  syscall_table[SYS_invlpg] = "invlpg";
 #endif
-#if defined (SYS_setegid)
-  syscall_table[SYS_setegid] = "setegid";
+#if defined(SYS_cg_ids)
+  syscall_table[SYS_cg_ids] = "cg_ids";
 #endif
-#if defined (SYS_sysconfig)
-  syscall_table[SYS_sysconfig] = "sysconfig";
+#if defined(SYS_cg_processors)
+  syscall_table[SYS_cg_processors] = "cg_processors";
 #endif
-#if defined (SYS_adjtime)
-  syscall_table[SYS_adjtime] = "adjtime";
+#if defined(SYS_cg_info)
+  syscall_table[SYS_cg_info] = "cg_info";
 #endif
-#if defined (SYS_systeminfo)
-  syscall_table[SYS_systeminfo] = "systeminfo";
+#if defined(SYS_cg_bind)
+  syscall_table[SYS_cg_bind] = "cg_bind";
 #endif
-#if defined (SYS_seteuid)
-  syscall_table[SYS_seteuid] = "seteuid";
+#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
 }
 
 /*
 
-GLOBAL FUNCTION
+   LOCAL FUNCTION
 
-       ptrace -- override library version to force errors for /proc version
+   procfs_kill_inferior - kill any current inferior
 
-SYNOPSIS
+   SYNOPSIS
 
-       int ptrace (int request, int pid, PTRACE_ARG3_TYPE arg3, int arg4)
+   void procfs_kill_inferior (void)
 
-DESCRIPTION
+   DESCRIPTION
 
-       When gdb is configured to use /proc, it should not be calling
-       or otherwise attempting to use ptrace.  In order to catch errors
-       where use of /proc is configured, but some routine is still calling
-       ptrace, we provide a local version of a function with that name
-       that does nothing but issue an error message.
-*/
+   Kill any current inferior.
 
-int
-ptrace (request, pid, arg3, arg4)
-     int request;
-     int pid;
-     PTRACE_ARG3_TYPE arg3;
-     int arg4;
+   NOTES
+
+   Kills even attached inferiors.  Presumably the user has already
+   been prompted that the inferior is an attached one rather than
+   one started by gdb.  (FIXME?)
+
+ */
+
+static void
+procfs_kill_inferior ()
 {
-  error ("internal error - there is a call to ptrace() somewhere");
-  /*NOTREACHED*/
+  target_mourn_inferior ();
 }
 
 /*
 
-GLOBAL FUNCTION
+   LOCAL FUNCTION
 
-       kill_inferior_fast -- kill inferior while gdb is exiting
+   unconditionally_kill_inferior - terminate the inferior
 
-SYNOPSIS
+   SYNOPSIS
 
-       void kill_inferior_fast (void)
+   static void unconditionally_kill_inferior (struct procinfo *)
 
-DESCRIPTION
+   DESCRIPTION
 
-       This is used when GDB is exiting.  It gives less chance of error.
+   Kill the specified inferior.
 
-NOTES
+   NOTE
 
-       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.
+   A possibly useful enhancement would be to first try sending
+   the inferior a terminate signal, politely asking it to commit
+   suicide, before we murder it (we could call that
+   politely_kill_inferior()).
 
-*/
+ */
 
-void
-kill_inferior_fast ()
+static void
+unconditionally_kill_inferior (pi)
+     struct procinfo *pi;
+{
+  int ppid;
+
+  ppid = pi->prstatus.pr_ppid;
+
+#ifdef PROCFS_NEED_CLEAR_CURSIG_FOR_KILL
+  /* Alpha OSF/1-3.x procfs needs a clear of the current signal
+     before the PIOCKILL, otherwise it might generate a corrupted core
+     file for the inferior.  */
+  ioctl (pi->ctl_fd, PIOCSSIG, NULL);
+#endif
+#ifdef PROCFS_NEED_PIOCSSIG_FOR_KILL
+  /* Alpha OSF/1-2.x procfs needs a PIOCSSIG call with a SIGKILL signal
+     to kill the inferior, otherwise it might remain stopped with a
+     pending SIGKILL.
+     We do not check the result of the PIOCSSIG, the inferior might have
+     died already.  */
+  {
+    struct siginfo newsiginfo;
+
+    memset ((char *) &newsiginfo, 0, sizeof (newsiginfo));
+    newsiginfo.si_signo = SIGKILL;
+    newsiginfo.si_code = 0;
+    newsiginfo.si_errno = 0;
+    newsiginfo.si_pid = getpid ();
+    newsiginfo.si_uid = getuid ();
+    ioctl (pi->ctl_fd, PIOCSSIG, &newsiginfo);
+  }
+#else /* PROCFS_NEED_PIOCSSIG_FOR_KILL */
+  procfs_write_pckill (pi);
+#endif /* PROCFS_NEED_PIOCSSIG_FOR_KILL */
+
+  close_proc_file (pi);
+
+/* Only wait() for our direct children.  Our grandchildren zombies are killed
+   by the death of their parents.  */
+
+  if (ppid == getpid ())
+    wait ((int *) 0);
+}
+
+/*
+
+   LOCAL FUNCTION
+
+   procfs_xfer_memory -- copy data to or from inferior memory space
+
+   SYNOPSIS
+
+   int procfs_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
+   int dowrite, struct target_ops target)
+
+   DESCRIPTION
+
+   Copy LEN bytes to/from inferior's memory starting at MEMADDR
+   from/to debugger memory starting at MYADDR.  Copy from inferior
+   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 procfs_ops
+   doesn't allow memory operations to cross below us in the target stack
+   anyway.
+
+   NOTES
+
+   The /proc interface makes this an almost trivial task.
+ */
+
+static int
+procfs_xfer_memory (memaddr, myaddr, len, dowrite, target)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+     int dowrite;
+     struct target_ops *target;        /* ignored */
 {
-  if (inferior_pid != 0 && !attach_flag)
+  int nbytes = 0;
+  struct procinfo *pi;
+
+  pi = current_procinfo;
+
+  if (lseek (pi->as_fd, (off_t) memaddr, SEEK_SET) == (off_t) memaddr)
     {
-      unconditionally_kill_inferior ();
+      if (dowrite)
+       {
+         nbytes = write (pi->as_fd, myaddr, len);
+       }
+      else
+       {
+         nbytes = read (pi->as_fd, myaddr, len);
+       }
+      if (nbytes < 0)
+       {
+         nbytes = 0;
+       }
     }
+  return (nbytes);
 }
 
 /*
 
-GLOBAL FUNCTION
+   LOCAL FUNCTION
 
-       kill_inferior - kill any currently inferior
+   procfs_store_registers -- copy register values back to inferior
 
-SYNOPSIS
+   SYNOPSIS
 
-       void kill_inferior (void)
+   void procfs_store_registers (int regno)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Kill any current inferior.
+   Store our current register values back into the inferior.  If
+   REGNO is -1 then store all the register, otherwise store just
+   the value specified by REGNO.
 
-NOTES
+   NOTES
 
-       Kills even attached inferiors.  Presumably the user has already
-       been prompted that the inferior is an attached one rather than
-       one started by gdb.  (FIXME?)
+   If we are storing only a single register, we first have to get all
+   the current values from the process, overwrite the desired register
+   in the gregset with the one we want from gdb's registers, and then
+   send the whole set back to the process.  For writing all the
+   registers, all we have to do is generate the gregset and send it to
+   the process.
 
-*/
+   Also note that the process has to be stopped on an event of interest
+   for this to work, which basically means that it has to have been
+   run under the control of one of the other /proc ioctl calls and not
+   ptrace.  Since we don't use ptrace anyway, we don't worry about this
+   fine point, but it is worth noting for future reference.
 
-void
-kill_inferior ()
+   Gdb is confused about what this function is supposed to return.
+   Some versions return a value, others return nothing.  Some are
+   declared to return a value and actually return nothing.  Gdb ignores
+   anything returned.  (FIXME)
+
+ */
+
+static void
+procfs_store_registers (regno)
+     int regno;
+{
+  struct procinfo *pi;
+#ifdef PROCFS_USE_READ_WRITE
+  struct greg_ctl greg;
+  struct fpreg_ctl fpreg;
+#endif
+
+  pi = current_procinfo;
+
+#ifdef PROCFS_USE_READ_WRITE
+  if (regno != -1)
+    {
+      procfs_read_status (pi);
+      memcpy ((char *) &greg.gregset,
+             (char *) &pi->prstatus.pr_lwp.pr_context.uc_mcontext.gregs,
+             sizeof (gdb_gregset_t));
+    }
+  fill_gregset (&greg.gregset, regno);
+  greg.cmd = PCSREG;
+  write (pi->ctl_fd, &greg, sizeof (greg));
+#else /* PROCFS_USE_READ_WRITE */
+  if (regno != -1)
+    {
+      ioctl (pi->ctl_fd, PIOCGREG, &pi->gregset.gregset);
+    }
+  fill_gregset (&pi->gregset.gregset, regno);
+  ioctl (pi->ctl_fd, PIOCSREG, &pi->gregset.gregset);
+#endif /* PROCFS_USE_READ_WRITE */
+
+#if defined (FP0_REGNUM)
+
+  /* Now repeat everything using the floating point register set, if the
+     target has floating point hardware. Since we ignore the returned value,
+     we'll never know whether it worked or not anyway. */
+
+#ifdef PROCFS_USE_READ_WRITE
+  if (regno != -1)
+    {
+      procfs_read_status (pi);
+      memcpy ((char *) &fpreg.fpregset,
+             (char *) &pi->prstatus.pr_lwp.pr_context.uc_mcontext.fpregs,
+             sizeof (gdb_fpregset_t));
+    }
+  fill_fpregset (&fpreg.fpregset, regno);
+  fpreg.cmd = PCSFPREG;
+  write (pi->ctl_fd, &fpreg, sizeof (fpreg));
+#else /* PROCFS_USE_READ_WRITE */
+  if (regno != -1)
+    {
+      ioctl (pi->ctl_fd, PIOCGFPREG, &pi->fpregset.fpregset);
+    }
+  fill_fpregset (&pi->fpregset.fpregset, regno);
+  ioctl (pi->ctl_fd, PIOCSFPREG, &pi->fpregset.fpregset);
+#endif /* PROCFS_USE_READ_WRITE */
+
+#endif /* FP0_REGNUM */
+
+}
+
+/*
+
+   LOCAL FUNCTION
+
+   init_procinfo - setup a procinfo struct and connect it to a process
+
+   SYNOPSIS
+
+   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.  
+
+   NOTES
+
+   If proc_init_failed ever gets called, control returns to the command
+   processing loop via the standard error handling code.
+
+ */
+
+static struct procinfo *
+init_procinfo (pid, kill)
+     int pid;
+     int kill;
+{
+  struct procinfo *pi = (struct procinfo *)
+  xmalloc (sizeof (struct procinfo));
+#ifdef UNIXWARE
+  struct sig_ctl sctl;
+#endif /* UNIXWARE */
+
+  memset ((char *) pi, 0, sizeof (*pi));
+  if (!open_proc_file (pid, pi, O_RDWR, 1))
+    proc_init_failed (pi, "can't open process file", kill);
+
+  /* open_proc_file may modify pid.  */
+
+  pid = pi->pid;
+
+  /* Add new process to process info list */
+
+  pi->next = procinfo_list;
+  procinfo_list = pi;
+
+  add_fd (pi);                 /* Add to list for poll/select */
+
+  /*  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);
+#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);
+#endif /* UNIXWARE */
+
+  if (!procfs_read_status (pi))
+    proc_init_failed (pi, "procfs_read_status failed", kill);
+
+  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;
+#ifdef PROCFS_USE_READ_WRITE
+  struct flt_ctl fctl;
+#endif
+
+  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", 1);
+
+#ifdef PROCFS_USE_READ_WRITE
+  fctl.cmd = PCSFAULT;
+  prfillset (&fctl.fltset);
+  prdelset (&fctl.fltset, FLTPAGE);
+
+  if (write (pi->ctl_fd, (char *) &fctl, sizeof (struct flt_ctl)) < 0)
+      proc_init_failed (pi, "PCSFAULT failed", 1);
+#else
+  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) < 0)
+    proc_init_failed (pi, "PIOCSFAULT failed", 1);
+#endif
+
+  return pi;
+}
+
+/*
+
+   LOCAL FUNCTION
+
+   procfs_exit_handler - handle entry into the _exit syscall
+
+   SYNOPSIS
+
+   int procfs_exit_handler (pi, syscall_num, why, rtnvalp, statvalp)
+
+   DESCRIPTION
+
+   This routine is called when an inferior process enters the _exit()
+   system call.  It continues the process, and then collects the exit
+   status and pid which are returned in *statvalp and *rtnvalp.  After
+   that it returns non-zero to indicate that procfs_wait should wake up.
+
+   NOTES
+   There is probably a better way to do this.
+
+ */
+
+static int
+procfs_exit_handler (pi, syscall_num, why, rtnvalp, statvalp)
+     struct procinfo *pi;
+     int syscall_num;
+     int why;
+     int *rtnvalp;
+     int *statvalp;
 {
-  if (inferior_pid != 0)
+  struct procinfo *temp_pi, *next_pi;
+#if defined (UNIXWARE) || defined (PROCFS_USE_READ_WRITE)      
+  struct proc_ctl pctl;
+#endif
+
+#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);
+
+  if (attach_flag)
     {
-      unconditionally_kill_inferior ();
-      target_mourn_inferior ();
+      /* 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;
+}
+
+/*
+
+   LOCAL FUNCTION
+
+   procfs_exec_handler - handle exit from the exec family of syscalls
+
+   SYNOPSIS
+
+   int procfs_exec_handler (pi, syscall_num, why, rtnvalp, statvalp)
+
+   DESCRIPTION
+
+   This routine is called when an inferior process is about to finish any
+   of the exec() family of      system calls.  It pretends that we got a
+   SIGTRAP (for compatibility with ptrace behavior), and returns non-zero
+   to tell procfs_wait to wake up.
+
+   NOTES
+   This need for compatibility with ptrace is questionable.  In the
+   future, it shouldn't be necessary.
+
+ */
+
+static int
+procfs_exec_handler (pi, syscall_num, why, rtnvalp, statvalp)
+     struct procinfo *pi;
+     int syscall_num;
+     int why;
+     int *rtnvalp;
+     int *statvalp;
+{
+  *statvalp = (SIGTRAP << 8) | 0177;
+
+  return 1;
 }
 
+#if defined(SYS_sproc) && !defined(UNIXWARE)
+/* IRIX lwp creation system call */
+
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
+
+   procfs_sproc_handler - handle exit from the sproc syscall
 
-       unconditionally_kill_inferior - terminate the inferior
+   SYNOPSIS
+
+   int procfs_sproc_handler (pi, syscall_num, why, rtnvalp, statvalp)
+
+   DESCRIPTION
+
+   This routine is called when an inferior process is about to finish an
+   sproc() system call.  This is the system call that IRIX uses to create
+   a lightweight process.  When the target process gets this event, we can
+   look at rval1 to find the new child processes ID, and create a new
+   procinfo struct from that.
+
+   After that, it pretends that we got a SIGTRAP, and returns non-zero
+   to tell procfs_wait to wake up.  Subsequently, wait_for_inferior gets
+   woken up, sees the new process and continues it.
+
+   NOTES
+   We actually never see the child exiting from sproc because we will
+   shortly stop the child with PIOCSTOP, which is then registered as the
+   event of interest.
+ */
+
+static int
+procfs_sproc_handler (pi, syscall_num, why, rtnvalp, statvalp)
+     struct procinfo *pi;
+     int syscall_num;
+     int why;
+     int *rtnvalp;
+     int *statvalp;
+{
+/* We've just detected the completion of an sproc system call.  Now we need to
+   setup a procinfo struct for this thread, and notify the thread system of the
+   new arrival.  */
 
-SYNOPSIS
+/* If sproc failed, then nothing interesting happened.  Continue the process
+   and go back to sleep. */
 
-       static void unconditionally_kill_inferior (void)
+  if (pi->prstatus.pr_errno != 0)
+    {
+      pi->prrun.pr_flags &= PRSTEP;
+      pi->prrun.pr_flags |= PRCFAULT;
 
-DESCRIPTION
+      if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
+       perror_with_name (pi->pathname);
 
-       Kill the current inferior.  Should not be called until it
-       is at least tested that there is an inferior.
+      return 0;
+    }
 
-NOTE
+  /* At this point, the new thread is stopped at it's first instruction, and
+     the parent is stopped at the exit from sproc.  */
 
-       A possibly useful enhancement would be to first try sending
-       the inferior a terminate signal, politely asking it to commit
-       suicide, before we murder it.
+  /* Notify the caller of the arrival of a new thread. */
+  create_procinfo (pi->prstatus.pr_rval1);
 
-*/
+  *rtnvalp = pi->prstatus.pr_rval1;
+  *statvalp = (SIGTRAP << 8) | 0177;
 
-static void
-unconditionally_kill_inferior ()
-{
-  int signo;
-  
-  signo = SIGKILL;
-  (void) ioctl (pi.fd, PIOCKILL, &signo);
-  close_proc_file (&pi);
-  wait ((int *) 0);
+  return 1;
 }
 
 /*
 
-GLOBAL FUNCTION
+   LOCAL FUNCTION
 
-       child_xfer_memory -- copy data to or from inferior memory space
+   procfs_fork_handler - handle exit from the fork syscall
 
-SYNOPSIS
+   SYNOPSIS
 
-       int child_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
-               int dowrite, struct target_ops target)
+   int procfs_fork_handler (pi, syscall_num, why, rtnvalp, statvalp)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Copy LEN bytes to/from inferior's memory starting at MEMADDR
-       from/to debugger memory starting at MYADDR.  Copy from inferior
-       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
-       doesn't allow memory operations to cross below us in the target stack
-       anyway.
+   This routine is called when an inferior process is about to finish a
+   fork() system call.  We will open up the new process, and then close
+   it, which releases it from the clutches of the debugger.
 
-NOTES
+   After that, we continue the target process as though nothing had
+   happened.
 
-       The /proc interface makes this an almost trivial task.
+   NOTES
+   This is necessary for IRIX because we have to set PR_FORK in order
+   to catch the creation of lwps (via sproc()).  When an actual fork
+   occurs, it becomes necessary to reset the forks debugger flags and
+   continue it because we can't hack multiple processes yet.
  */
 
-
-int
-child_xfer_memory (memaddr, myaddr, len, dowrite, target)
-     CORE_ADDR memaddr;
-     char *myaddr;
-     int len;
-     int dowrite;
-     struct target_ops *target; /* ignored */
+static int
+procfs_fork_handler (pi, syscall_num, why, rtnvalp, statvalp)
+     struct procinfo *pi;
+     int syscall_num;
+     int why;
+     int *rtnvalp;
+     int *statvalp;
 {
-  int nbytes = 0;
+  struct procinfo *pitemp;
 
-  if (lseek (pi.fd, (off_t) memaddr, 0) == (off_t) memaddr)
-    {
-      if (dowrite)
-       {
-         nbytes = write (pi.fd, myaddr, len);
-       }
-      else
-       {
-         nbytes = read (pi.fd, myaddr, len);
-       }
-      if (nbytes < 0)
-       {
-         nbytes = 0;
-       }
-    }
-  return (nbytes);
-}
+/* At this point, we've detected the completion of a fork (or vfork) call in
+   our child.  The grandchild is also stopped because we set inherit-on-fork
+   earlier.  (Note that nobody has the grandchilds' /proc file open at this
+   point.)  We will release the grandchild from the debugger by opening it's
+   /proc file and then closing it.  Since run-on-last-close is set, the
+   grandchild continues on its' merry way.  */
 
-/*
 
-GLOBAL FUNCTION
+  pitemp = create_procinfo (pi->prstatus.pr_rval1);
+  if (pitemp)
+    close_proc_file (pitemp);
 
-       store_inferior_registers -- copy register values back to inferior
+  if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
+    perror_with_name (pi->pathname);
 
-SYNOPSIS
+  return 0;
+}
+#endif /* SYS_sproc && !UNIXWARE */
 
-       void store_inferior_registers (int regno)
+/*
 
-DESCRIPTION
+   LOCAL FUNCTION
 
-       Store our current register values back into the inferior.  If
-       REGNO is -1 then store all the register, otherwise store just
-       the value specified by REGNO.
+   procfs_set_inferior_syscall_traps - setup the syscall traps 
 
-NOTES
+   SYNOPSIS
 
-       If we are storing only a single register, we first have to get all
-       the current values from the process, overwrite the desired register
-       in the gregset with the one we want from gdb's registers, and then
-       send the whole set back to the process.  For writing all the
-       registers, all we have to do is generate the gregset and send it to
-       the process.
+   void procfs_set_inferior_syscall_traps (struct procinfo *pip)
 
-       Also note that the process has to be stopped on an event of interest
-       for this to work, which basically means that it has to have been
-       run under the control of one of the other /proc ioctl calls and not
-       ptrace.  Since we don't use ptrace anyway, we don't worry about this
-       fine point, but it is worth noting for future reference.
+   DESCRIPTION
 
-       Gdb is confused about what this function is supposed to return.
-       Some versions return a value, others return nothing.  Some are
-       declared to return a value and actually return nothing.  Gdb ignores
-       anything returned.  (FIXME)
+   Called for each "procinfo" (process, thread, or LWP) in the
+   inferior, to register for notification of and handlers for
+   syscall traps in the inferior.
 
  */
 
-void
-store_inferior_registers (regno)
-     int regno;
+static void
+procfs_set_inferior_syscall_traps (pip)
+     struct procinfo *pip;
 {
-  if (regno != -1)
-    {
-      (void) ioctl (pi.fd, PIOCGREG, &pi.gregset);
-    }
-  fill_gregset (&pi.gregset, regno);
-  (void) ioctl (pi.fd, PIOCSREG, &pi.gregset);
+  procfs_set_syscall_trap (pip, SYS_exit, PROCFS_SYSCALL_ENTRY,
+                          procfs_exit_handler);
 
-#if defined (FP0_REGNUM)
+#ifndef PRFS_STOPEXEC
+#ifdef SYS_exec
+  procfs_set_syscall_trap (pip, SYS_exec, PROCFS_SYSCALL_EXIT,
+                          procfs_exec_handler);
+#endif
+#ifdef SYS_execv
+  procfs_set_syscall_trap (pip, SYS_execv, PROCFS_SYSCALL_EXIT,
+                          procfs_exec_handler);
+#endif
+#ifdef SYS_execve
+  procfs_set_syscall_trap (pip, SYS_execve, PROCFS_SYSCALL_EXIT,
+                          procfs_exec_handler);
+#endif
+#endif /* PRFS_STOPEXEC */
 
-  /* Now repeat everything using the floating point register set, if the
-     target has floating point hardware. Since we ignore the returned value,
-     we'll never know whether it worked or not anyway. */
+  /* Setup traps on exit from sproc() */
 
-  if (regno != -1)
-    {
-      (void) ioctl (pi.fd, PIOCGFPREG, &pi.fpregset);
-    }
-  fill_fpregset (&pi.fpregset, regno);
-  (void) ioctl (pi.fd, PIOCSFPREG, &pi.fpregset);
+#ifdef SYS_sproc
+  procfs_set_syscall_trap (pip, SYS_sproc, PROCFS_SYSCALL_EXIT,
+                          procfs_sproc_handler);
+  procfs_set_syscall_trap (pip, SYS_fork, PROCFS_SYSCALL_EXIT,
+                          procfs_fork_handler);
+#ifdef SYS_vfork
+  procfs_set_syscall_trap (pip, SYS_vfork, PROCFS_SYSCALL_EXIT,
+                          procfs_fork_handler);
+#endif
+/* Turn on inherit-on-fork flag so that all children of the target process
+   start with tracing flags set.  This allows us to trap lwp creation.  Note
+   that we also have to trap on fork and vfork in order to disable all tracing
+   in the targets child processes.  */
 
-#endif /* FP0_REGNUM */
+  modify_inherit_on_fork_flag (pip->ctl_fd, 1);
+#endif
 
+#ifdef SYS_lwp_create
+  procfs_set_syscall_trap (pip, SYS_lwp_create, PROCFS_SYSCALL_EXIT,
+                          procfs_lwp_creation_handler);
+#endif
 }
 
 /*
 
-GLOBAL FUNCTION
+   LOCAL FUNCTION
 
-       inferior_proc_init - initialize access to a /proc entry
+   procfs_init_inferior - initialize target vector and access to a
+   /proc entry
 
-SYNOPSIS
+   SYNOPSIS
 
-       void inferior_proc_init (int pid)
+   void procfs_init_inferior (int pid)
 
-DESCRIPTION
+   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.
+   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
+   NOTES
 
-       If proc_init_failed ever gets called, control returns to the command
-       processing loop via the standard error handling code.
+   If proc_init_failed ever gets called, control returns to the command
+   processing loop via the standard error handling code.
 
  */
 
-void
-inferior_proc_init (pid)
+static void
+procfs_init_inferior (pid)
      int pid;
 {
-  if (!open_proc_file (pid, &pi))
-    {
-      proc_init_failed ("can't open process file");
-    }
-  else
-    {
-      (void) memset ((char *) &pi.prrun, 0, sizeof (pi.prrun));
-      prfillset (&pi.prrun.pr_trace);
-      proc_signal_handling_change ();
-      prfillset (&pi.prrun.pr_fault);
-      prdelset (&pi.prrun.pr_fault, FLTPAGE);
-      if (ioctl (pi.fd, PIOCWSTOP, &pi.prstatus) < 0)
-       {
-         proc_init_failed ("PIOCWSTOP failed");
-       }
-      else if (ioctl (pi.fd, PIOCSFAULT, &pi.prrun.pr_fault) < 0)
-       {
-         proc_init_failed ("PIOCSFAULT failed");
-       }
-    }
+  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.  */
+
+  pid = pip->pid;
+  inferior_pid = pid;
+
+  add_thread (pip->pid);       /* Setup initial thread */
+
+#ifdef START_INFERIOR_TRAPS_EXPECTED
+  startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
+#else
+  /* One trap to exec the shell, one to exec the program being debugged.  */
+  startup_inferior (2);
+#endif
 }
 
 /*
 
-GLOBAL FUNCTION
+   GLOBAL FUNCTION
 
-       proc_signal_handling_change
+   procfs_notice_signals
 
-SYNOPSIS
+   SYNOPSIS
 
-       void proc_signal_handling_change (void);
+   static void procfs_notice_signals (int pid);
 
-DESCRIPTION
+   DESCRIPTION
 
-       When the user changes the state of gdb's signal handling via the
-       "handle" command, this function gets called to see if any change
-       in the /proc interface is required.  It is also called internally
-       by other /proc interface functions to initialize the state of
-       the traced signal set.
+   When the user changes the state of gdb's signal handling via the
+   "handle" command, this function gets called to see if any change
+   in the /proc interface is required.  It is also called internally
+   by other /proc interface functions to initialize the state of
+   the traced signal set.
 
-       One thing it does is that signals for which the state is "nostop",
-       "noprint", and "pass", have their trace bits reset in the pr_trace
-       field, so that they are no longer traced.  This allows them to be
-       delivered directly to the inferior without the debugger ever being
-       involved.
+   One thing it does is that signals for which the state is "nostop",
+   "noprint", and "pass", have their trace bits reset in the pr_trace
+   field, so that they are no longer traced.  This allows them to be
+   delivered directly to the inferior without the debugger ever being
+   involved.
  */
 
-void
-proc_signal_handling_change ()
+static void
+procfs_notice_signals (pid)
+     int pid;
+{
+  struct procinfo *pi;
+  struct sig_ctl sctl;
+
+  pi = find_procinfo (pid, 0);
+
+#ifndef HAVE_PRRUN_T
+  premptyset (&sctl.sigset);
+#else
+  sctl.sigset = pi->prrun.pr_trace;
+#endif
+
+  notice_signals (pi, &sctl);
+
+#ifdef HAVE_PRRUN_T
+  pi->prrun.pr_trace = sctl.sigset;
+#endif
+}
+
+static void
+notice_signals (pi, sctl)
+     struct procinfo *pi;
+     struct sig_ctl *sctl;
 {
   int signo;
 
-  if (pi.valid)
+  for (signo = 0; signo < NSIG; signo++)
     {
-      for (signo = 0; signo < NSIG; signo++)
+      if (signal_stop_state (target_signal_from_host (signo)) == 0 &&
+         signal_print_state (target_signal_from_host (signo)) == 0 &&
+         signal_pass_state (target_signal_from_host (signo)) == 1)
        {
-         if (signal_stop_state (signo) == 0 &&
-             signal_print_state (signo) == 0 &&
-             signal_pass_state (signo) == 1)
-           {
-             prdelset (&pi.prrun.pr_trace, signo);
-           }
-         else
-           {
-             praddset (&pi.prrun.pr_trace, signo);
-           }
+         prdelset (&sctl->sigset, signo);
        }
-      if (ioctl (pi.fd, PIOCSTRACE, &pi.prrun.pr_trace))
+      else
        {
-         print_sys_errmsg ("PIOCSTRACE failed", errno);
+         praddset (&sctl->sigset, signo);
        }
     }
+#ifdef PROCFS_USE_READ_WRITE
+  sctl->cmd = PCSTRACE;
+  if (write (pi->ctl_fd, (char *) sctl, sizeof (struct sig_ctl)) < 0)
+#else
+  if (ioctl (pi->ctl_fd, PIOCSTRACE, &sctl->sigset))
+#endif
+    {
+      print_sys_errmsg ("PIOCSTRACE failed", errno);
+    }
 }
 
 /*
 
-GLOBAL FUNCTION
+   LOCAL FUNCTION
 
-       proc_set_exec_trap -- arrange for exec'd child to halt at startup
+   proc_set_exec_trap -- arrange for exec'd child to halt at startup
 
-SYNOPSIS
+   SYNOPSIS
 
-       void proc_set_exec_trap (void)
+   void proc_set_exec_trap (void)
 
-DESCRIPTION
+   DESCRIPTION
 
-       This function is called in the child process when starting up
-       an inferior, prior to doing the exec of the actual inferior.
-       It sets the child process's exitset to make exit from the exec
-       system call an event of interest to stop on, and then simply
-       returns.  The child does the exec, the system call returns, and
-       the child stops at the first instruction, ready for the gdb
-       parent process to take control of it.
+   This function is called in the child process when starting up
+   an inferior, prior to doing the exec of the actual inferior.
+   It sets the child process's exitset to make exit from the exec
+   system call an event of interest to stop on, and then simply
+   returns.  The child does the exec, the system call returns, and
+   the child stops at the first instruction, ready for the gdb
+   parent process to take control of it.
 
-NOTE
+   NOTE
 
-       We need to use all local variables since the child may be sharing
-       it's data space with the parent, if vfork was used rather than
-       fork.
+   We need to use all local variables since the child may be sharing
+   it's data space with the parent, if vfork was used rather than
+   fork.
 
-       Also note that we want to turn off the inherit-on-fork flag in
-       the child process so that any grand-children start with all
-       tracing flags cleared.
+   Also note that we want to turn off the inherit-on-fork flag in
+   the child process so that any grand-children start with all
+   tracing flags cleared.
  */
 
-void
+static void
 proc_set_exec_trap ()
 {
-  sysset_t exitset;
-  auto char procname[32];
+  struct sys_ctl exitset;
+  struct sys_ctl entryset;
+  char procname[MAX_PROC_NAME_SIZE];
   int fd;
-  
-  (void) sprintf (procname, PROC_NAME_FMT, getpid ());
+
+  sprintf (procname, CTL_PROC_NAME_FMT, getpid ());
+#ifdef UNIXWARE
+  if ((fd = open (procname, O_WRONLY)) < 0)
+#else
   if ((fd = open (procname, O_RDWR)) < 0)
+#endif
     {
       perror (procname);
-      fflush (stderr);
+      gdb_flush (gdb_stderr);
       _exit (127);
     }
-  premptyset (&exitset);
+  premptyset (&exitset.sysset);
+  premptyset (&entryset.sysset);
 
+#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.  */
+  {
+    int prfs_flags;
+
+    if (ioctl (fd, PIOCGSPCACT, &prfs_flags) < 0)
+      {
+       perror (procname);
+       gdb_flush (gdb_stderr);
+       _exit (127);
+      }
+    prfs_flags |= PRFS_STOPEXEC;
+    if (ioctl (fd, PIOCSSPCACT, &prfs_flags) < 0)
+      {
+       perror (procname);
+       gdb_flush (gdb_stderr);
+       _exit (127);
+      }
+  }
+#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
      *is* a SYS_execv.  So, we try to account for that. */
 
 #ifdef SYS_exec
-  praddset (&exitset, SYS_exec);
+  praddset (&exitset.sysset, SYS_exec);
 #endif
 #ifdef SYS_execve
-  praddset (&exitset, SYS_execve);
+  praddset (&exitset.sysset, SYS_execve);
 #endif
 #ifdef SYS_execv
-  praddset(&exitset, SYS_execv);
+  praddset (&exitset.sysset, SYS_execv);
 #endif
 
-  if (ioctl (fd, PIOCSEXIT, &exitset) < 0)
+#ifdef PROCFS_USE_READ_WRITE
+  exitset.cmd = PCSEXIT;
+  if (write (fd, (char *) &exitset, sizeof (struct sys_ctl)) < 0)
+#else
+  if (ioctl (fd, PIOCSEXIT, &exitset.sysset) < 0)
+#endif
     {
       perror (procname);
-      fflush (stderr);
+      gdb_flush (gdb_stderr);
       _exit (127);
     }
+#endif /* PRFS_STOPEXEC */
+
+  praddset (&entryset.sysset, SYS_exit);
+
+#ifdef PROCFS_USE_READ_WRITE
+  entryset.cmd = PCSENTRY;
+  if (write (fd, (char *) &entryset, sizeof (struct sys_ctl)) < 0)
+#else
+  if (ioctl (fd, PIOCSENTRY, &entryset.sysset) < 0)
+#endif
+    {
+      perror (procname);
+      gdb_flush (gdb_stderr);
+      _exit (126);
+    }
 
   /* Turn off inherit-on-fork flag so that all grand-children of gdb
      start with tracing flags cleared. */
 
-#if defined (PIOCRESET)        /* New method */
+  modify_inherit_on_fork_flag (fd, 0);
+
+  /* Turn on run-on-last-close flag so that this process will not hang
+     if GDB goes away for some reason.  */
+
+  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;
-      pr_flags = PR_FORK;
-      (void) ioctl (fd, PIOCRESET, &pr_flags);
-  }
-#else
-#if defined (PIOCRFORK)        /* Original method */
-  (void) ioctl (fd, PIOCRFORK, NULL);
+    long pr_flags;
+#ifdef PROCFS_USE_READ_WRITE
+    struct proc_ctl pctl;
 #endif
+
+/* Solaris needs this to make procfs treat all threads seperately.  Without
+   this, all threads halt whenever something happens to any thread.  Since
+   GDB wants to control all this itself, it needs to set PR_ASYNC.  */
+
+    pr_flags = PR_ASYNC;
+#ifdef PROCFS_USE_READ_WRITE
+    pctl.cmd = PCSET;
+    pctl.data = PR_FORK | PR_ASYNC;
+    write (fd, (char *) &pctl, sizeof (struct proc_ctl));
+#else
+    ioctl (fd, PIOCSET, &pr_flags);
 #endif
+  }
+#endif /* PR_ASYNC */
+#endif /* !UNIXWARE */
 }
 
 /*
 
-GLOBAL FUNCTION
+   GLOBAL FUNCTION
 
-       proc_iterate_over_mappings -- call function for every mapped space
+   proc_iterate_over_mappings -- call function for every mapped space
 
-SYNOPSIS
+   SYNOPSIS
 
-       int proc_iterate_over_mappings (int (*func)())
+   int proc_iterate_over_mappings (int (*func)())
 
-DESCRIPTION
+   DESCRIPTION
 
-       Given a pointer to a function, call that function for every
-       mapped address space, passing it an open file descriptor for
-       the file corresponding to that mapped address space (if any)
-       and the base address of the mapped space.  Quit when we hit
-       the end of the mappings or the function returns nonzero.
+   Given a pointer to a function, call that function for every
+   mapped address space, passing it an open file descriptor for
+   the file corresponding to that mapped address space (if any)
+   and the base address of the mapped space.  Quit when we hit
+   the end of the mappings or the function returns nonzero.
  */
 
+#ifdef UNIXWARE
+int
+proc_iterate_over_mappings (func)
+     int (*func) PARAMS ((int, CORE_ADDR));
+{
+  int nmap;
+  int fd;
+  int funcstat = 0;
+  prmap_t *prmaps;
+  prmap_t *prmap;
+  struct procinfo *pi;
+  struct stat sbuf;
+
+  pi = current_procinfo;
+
+  if (fstat (pi->map_fd, &sbuf) < 0)
+    return 0;
+
+  nmap = sbuf.st_size / sizeof (prmap_t);
+  prmaps = (prmap_t *) alloca (nmap * sizeof (prmap_t));
+  if ((lseek (pi->map_fd, 0, SEEK_SET) == 0) &&
+      (read (pi->map_fd, (char *) prmaps, nmap * sizeof (prmap_t)) ==
+       (nmap * sizeof (prmap_t))))
+    {
+      int i = 0;
+      for (prmap = prmaps; i < nmap && funcstat == 0; ++prmap, ++i)
+       {
+         char name[sizeof ("/proc/1234567890/object") +
+                   sizeof (prmap->pr_mapname)];
+         sprintf (name, "/proc/%d/object/%s", pi->pid, prmap->pr_mapname);
+         if ((fd = open (name, O_RDONLY)) == -1)
+           {
+             funcstat = 1;
+             break;
+           }
+         funcstat = (*func) (fd, (CORE_ADDR) prmap->pr_vaddr);
+         close (fd);
+       }
+    }
+  return (funcstat);
+}
+#else /* UNIXWARE */
 int
 proc_iterate_over_mappings (func)
      int (*func) PARAMS ((int, CORE_ADDR));
@@ -1466,46 +3007,48 @@ proc_iterate_over_mappings (func)
   int funcstat = 0;
   struct prmap *prmaps;
   struct prmap *prmap;
+  struct procinfo *pi;
 
-  if (pi.valid && (ioctl (pi.fd, PIOCNMAP, &nmap) == 0))
+  pi = current_procinfo;
+
+  if (ioctl (pi->map_fd, PIOCNMAP, &nmap) == 0)
     {
       prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
-      if (ioctl (pi.fd, PIOCMAP, prmaps) == 0)
+      if (ioctl (pi->map_fd, PIOCMAP, prmaps) == 0)
        {
-         for (prmap = prmaps; prmap -> pr_size && funcstat == 0; ++prmap)
+         for (prmap = prmaps; prmap->pr_size && funcstat == 0; ++prmap)
            {
-             fd = proc_address_to_fd ((CORE_ADDR) prmap -> pr_vaddr, 0);
-             funcstat = (*func) (fd, (CORE_ADDR) prmap -> pr_vaddr);
+             fd = proc_address_to_fd (pi, (CORE_ADDR) prmap->pr_vaddr, 0);
+             funcstat = (*func) (fd, (CORE_ADDR) prmap->pr_vaddr);
              close (fd);
            }
        }
     }
   return (funcstat);
 }
+#endif /* UNIXWARE */
 
+#if 0                          /* Currently unused */
 /*
 
-GLOBAL FUNCTION
-
-       proc_base_address -- find base address for segment containing address
+   GLOBAL FUNCTION
 
-SYNOPSIS
+   proc_base_address -- find base address for segment containing address
 
-       CORE_ADDR proc_base_address (CORE_ADDR addr)
+   SYNOPSIS
 
-DESCRIPTION
+   CORE_ADDR proc_base_address (CORE_ADDR addr)
 
-       Given an address of a location in the inferior, find and return
-       the base address of the mapped segment containing that address.
+   DESCRIPTION
 
-       This is used for example, by the shared library support code,
-       where we have the pc value for some location in the shared library
-       where we are stopped, and need to know the base address of the
-       segment containing that address.
-*/
+   Given an address of a location in the inferior, find and return
+   the base address of the mapped segment containing that address.
 
-
-#if 0  /* Currently unused */
+   This is used for example, by the shared library support code,
+   where we have the pc value for some location in the shared library
+   where we are stopped, and need to know the base address of the
+   segment containing that address.
+ */
 
 CORE_ADDR
 proc_base_address (addr)
@@ -1515,18 +3058,21 @@ proc_base_address (addr)
   struct prmap *prmaps;
   struct prmap *prmap;
   CORE_ADDR baseaddr = 0;
+  struct procinfo *pi;
 
-  if (pi.valid && (ioctl (pi.fd, PIOCNMAP, &nmap) == 0))
+  pi = current_procinfo;
+
+  if (ioctl (pi->map_fd, PIOCNMAP, &nmap) == 0)
     {
       prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
-      if (ioctl (pi.fd, PIOCMAP, prmaps) == 0)
+      if (ioctl (pi->map_fd, PIOCMAP, prmaps) == 0)
        {
-         for (prmap = prmaps; prmap -> pr_size; ++prmap)
+         for (prmap = prmaps; prmap->pr_size; ++prmap)
            {
-             if ((prmap -> pr_vaddr <= (caddr_t) addr) &&
-                 (prmap -> pr_vaddr + prmap -> pr_size > (caddr_t) addr))
+             if ((prmap->pr_vaddr <= (caddr_t) addr) &&
+                 (prmap->pr_vaddr + prmap->pr_size > (caddr_t) addr))
                {
-                 baseaddr = (CORE_ADDR) prmap -> pr_vaddr;
+                 baseaddr = (CORE_ADDR) prmap->pr_vaddr;
                  break;
                }
            }
@@ -1535,352 +3081,575 @@ proc_base_address (addr)
   return (baseaddr);
 }
 
-#endif /* 0 */
+#endif /* 0 */
 
+#ifndef UNIXWARE
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       proc_address_to_fd -- return open fd for file mapped to address
+   proc_address_to_fd -- return open fd for file mapped to address
 
-SYNOPSIS
+   SYNOPSIS
 
-       int proc_address_to_fd (CORE_ADDR addr, complain)
+   int proc_address_to_fd (struct procinfo *pi, CORE_ADDR addr, complain)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Given an address in the current inferior's address space, use the
-       /proc interface to find an open file descriptor for the file that
-       this address was mapped in from.  Return -1 if there is no current
-       inferior.  Print a warning message if there is an inferior but
-       the address corresponds to no file (IE a bogus address).
+   Given an address in the current inferior's address space, use the
+   /proc interface to find an open file descriptor for the file that
+   this address was mapped in from.  Return -1 if there is no current
+   inferior.  Print a warning message if there is an inferior but
+   the address corresponds to no file (IE a bogus address).
 
-*/
+ */
 
 static int
-proc_address_to_fd (addr, complain)
+proc_address_to_fd (pi, addr, complain)
+     struct procinfo *pi;
      CORE_ADDR addr;
      int complain;
 {
   int fd = -1;
 
-  if (pi.valid)
+  if ((fd = ioctl (pi->ctl_fd, PIOCOPENM, (caddr_t *) & addr)) < 0)
     {
-      if ((fd = ioctl (pi.fd, PIOCOPENM, (caddr_t *) &addr)) < 0)
+      if (complain)
        {
-         if (complain)
-           {
-             print_sys_errmsg (pi.pathname, errno);
-             warning ("can't find mapped file for address 0x%x", addr);
-           }
+         print_sys_errmsg (pi->pathname, errno);
+         warning ("can't find mapped file for address 0x%x", addr);
        }
     }
   return (fd);
 }
+#endif /* !UNIXWARE */
 
+/* Attach to process PID, then initialize for debugging it
+   and wait for the trace-trap that results from attaching.  */
 
-#ifdef ATTACH_DETACH
-
-/*
+static void
+procfs_attach (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  char *exec_file;
+  int pid;
 
-GLOBAL FUNCTION
+  if (!args)
+    error_no_arg ("process-id to attach");
 
-       attach -- attach to an already existing process
+  pid = atoi (args);
 
-SYNOPSIS
+  if (pid == getpid ())                /* Trying to masturbate? */
+    error ("I refuse to debug myself!");
 
-       int attach (int pid)
+  if (from_tty)
+    {
+      exec_file = (char *) get_exec_file (0);
 
-DESCRIPTION
+      if (exec_file)
+       printf_unfiltered ("Attaching to program `%s', %s\n", exec_file, target_pid_to_str (pid));
+      else
+       printf_unfiltered ("Attaching to %s\n", target_pid_to_str (pid));
 
-       Attach to an already existing process with the specified process
-       id.  If the process is not already stopped, query whether to
-       stop it or not.
+      gdb_flush (gdb_stdout);
+    }
 
-NOTES
+  inferior_pid = pid = do_attach (pid);
+  push_target (&procfs_ops);
+}
 
-       The option of stopping at attach time is specific to the /proc
-       versions of gdb.  Versions using ptrace force the attachee
-       to stop.
 
-*/
+/* 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).  */
 
-int
-attach (pid)
-     int pid;
+static void
+procfs_detach (args, from_tty)
+     char *args;
+     int from_tty;
 {
-  if (!open_proc_file (pid, &pi))
-    {
-      perror_with_name (pi.pathname);
-      /* NOTREACHED */
-    }
-  
-  /*  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 (ioctl (pi.fd, PIOCSTATUS, &pi.prstatus) < 0)
-    {
-      print_sys_errmsg (pi.pathname, errno);
-      close_proc_file (&pi);
-      error ("PIOCSTATUS failed");
-    }
-  if (pi.prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
-    {
-      pi.was_stopped = 1;
-    }
-  else
-    {
-      pi.was_stopped = 0;
-      if (query ("Process is currently running, stop it? "))
-       {
-         if (ioctl (pi.fd, PIOCSTOP, &pi.prstatus) < 0)
-           {
-             print_sys_errmsg (pi.pathname, errno);
-             close_proc_file (&pi);
-             error ("PIOCSTOP failed");
-           }
-         pi.nopass_next_sigstop = 1;
-       }
-      else
-       {
-         printf ("Ok, gdb will wait for process %u to stop.\n", pid);
-       }
-    }
-  
-  /*  Remember some things about the inferior that we will, or might, change
-      so that we can restore them when we detach. */
-  
-  (void) ioctl (pi.fd, PIOCGTRACE, &pi.saved_trace);
-  (void) ioctl (pi.fd, PIOCGHOLD, &pi.saved_sighold);
-  (void) ioctl (pi.fd, PIOCGFAULT, &pi.saved_fltset);
-  (void) ioctl (pi.fd, PIOCGENTRY, &pi.saved_entryset);
-  (void) ioctl (pi.fd, PIOCGEXIT, &pi.saved_exitset);
-  
-  /* Set up trace and fault sets, as gdb expects them. */
-  
-  (void) memset (&pi.prrun, 0, sizeof (pi.prrun));
-  prfillset (&pi.prrun.pr_trace);
-  proc_signal_handling_change ();
-  prfillset (&pi.prrun.pr_fault);
-  prdelset (&pi.prrun.pr_fault, FLTPAGE);
-  if (ioctl (pi.fd, PIOCSFAULT, &pi.prrun.pr_fault))
-    {
-      print_sys_errmsg ("PIOCSFAULT failed", errno);
-    }
-  if (ioctl (pi.fd, PIOCSTRACE, &pi.prrun.pr_trace))
+  int siggnal = 0;
+
+  if (from_tty)
     {
-      print_sys_errmsg ("PIOCSTRACE failed", errno);
+      char *exec_file = get_exec_file (0);
+      if (exec_file == 0)
+       exec_file = "";
+      printf_unfiltered ("Detaching from program: %s %s\n",
+                        exec_file, target_pid_to_str (inferior_pid));
+      gdb_flush (gdb_stdout);
     }
-  attach_flag = 1;
-  return (pid);
+  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_unfiltered ("\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
+/*
 
-       detach -- detach from an attached-to process
+   LOCAL FUNCTION
 
-SYNOPSIS
+   do_attach -- attach to an already existing process
 
-       void detach (int signal)
+   SYNOPSIS
 
-DESCRIPTION
+   int do_attach (int pid)
 
-       Detach from the current attachee.
+   DESCRIPTION
 
-       If signal is non-zero, the attachee is started running again and sent
-       the specified signal.
+   Attach to an already existing process with the specified process
+   id.  If the process is not already stopped, query whether to
+   stop it or not.
 
-       If signal is zero and the attachee was not already stopped when we
-       attached to it, then we make it runnable again when we detach.
+   NOTES
 
-       Otherwise, we query whether or not to make the attachee runnable
-       again, since we may simply want to leave it in the state it was in
-       when we attached.
+   The option of stopping at attach time is specific to the /proc
+   versions of gdb.  Versions using ptrace force the attachee
+   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)
 
-       We report any problems, but do not consider them errors, since we
-       MUST detach even if some things don't seem to go right.  This may not
-       be the ideal situation.  (FIXME).
  */
 
-void
-detach (signal)
-     int signal;
+static int
+do_attach (pid)
+     int pid;
 {
-  if (signal)
-    {
-      set_proc_siginfo (&pi, signal);
-    }
-  if (ioctl (pi.fd, PIOCSEXIT, &pi.saved_exitset) < 0)
-    {
-      print_sys_errmsg (pi.pathname, errno);
-      printf ("PIOCSEXIT failed.\n");
-    }
-  if (ioctl (pi.fd, PIOCSENTRY, &pi.saved_entryset) < 0)
-    {
-      print_sys_errmsg (pi.pathname, errno);
-      printf ("PIOCSENTRY failed.\n");
-    }
-  if (ioctl (pi.fd, PIOCSTRACE, &pi.saved_trace) < 0)
-    {
-      print_sys_errmsg (pi.pathname, errno);
-      printf ("PIOCSTRACE failed.\n");
-    }
-  if (ioctl (pi.fd, PIOCSHOLD, &pi.saved_sighold) < 0)
-    {
-      print_sys_errmsg (pi.pathname, errno);
-      printf ("PIOSCHOLD failed.\n");
-    }
-  if (ioctl (pi.fd, PIOCSFAULT, &pi.saved_fltset) < 0)
-    {
-      print_sys_errmsg (pi.pathname, errno);
-      printf ("PIOCSFAULT failed.\n");
-    }
-  if (ioctl (pi.fd, PIOCSTATUS, &pi.prstatus) < 0)
+  struct procinfo *pi;
+#ifdef PROCFS_USE_READ_WRITE
+  struct flt_ctl fctl;
+#endif
+  int nlwp, *lwps;
+
+  pi = init_procinfo (pid, 0);
+
+#ifdef PIOCLWPIDS
+  nlwp = pi->prstatus.pr_nlwp;
+  lwps = alloca ((2 * nlwp + 2) * sizeof (id_t));
+
+  if (ioctl (pi->ctl_fd, PIOCLWPIDS, lwps))
     {
-      print_sys_errmsg (pi.pathname, errno);
-      printf ("PIOCSTATUS failed.\n");
+      print_sys_errmsg (pi->pathname, errno);
+      error ("PIOCLWPIDS failed");
     }
-  else
+#else /* PIOCLWPIDS */
+  nlwp = 1;
+  lwps = alloca ((2 * nlwp + 2) * sizeof *lwps);
+  lwps[0] = 0;
+#endif
+  for (; nlwp > 0; nlwp--, lwps++)
     {
-      if (signal || (pi.prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)))
+      /* First one has already been created above.  */
+      if ((pi = find_procinfo ((*lwps << 16) | pid, 1)) == 0)
+       pi = init_procinfo ((*lwps << 16) | pid, 0);
+
+      if (THE_PR_LWP (pi->prstatus).pr_flags & (PR_STOPPED | PR_ISTOP))
        {
-         if (signal || !pi.was_stopped ||
-             query ("Was stopped when attached, make it runnable again? "))
+         pi->was_stopped = 1;
+       }
+      else
+       {
+         pi->was_stopped = 0;
+         if (1 || query ("Process is currently running, stop it? "))
            {
-             (void) memset (&pi.prrun, 0, sizeof (pi.prrun));
-             pi.prrun.pr_flags = PRCFAULT;
-             if (ioctl (pi.fd, PIOCRUN, &pi.prrun))
+#ifdef PROCFS_USE_READ_WRITE
+             long cmd;
+#endif
+             /* 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);
-                 printf ("PIOCRUN failed.\n");
+                 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));
            }
        }
+
+#ifdef PROCFS_USE_READ_WRITE
+      fctl.cmd = PCSFAULT;
+      prfillset (&fctl.fltset);
+      prdelset (&fctl.fltset, FLTPAGE);
+
+      if (write (pi->ctl_fd, (char *) &fctl, sizeof (struct flt_ctl)) < 0)
+         print_sys_errmsg ("PCSFAULT failed", errno);
+#else /* PROCFS_USE_READ_WRITE */
+      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);
+       }
+      add_thread (pi->pid);
+      procfs_set_inferior_syscall_traps (pi);
+#endif /* PROCFS_USE_READ_WRITE */
     }
-  close_proc_file (&pi);
-  attach_flag = 0;
+  attach_flag = 1;
+  return (pi->pid);
 }
 
-#endif /* ATTACH_DETACH */
-
 /*
 
-GLOBAL FUNCTION
+   LOCAL FUNCTION
 
-       proc_wait -- emulate wait() as much as possible
+   do_detach -- detach from an attached-to process
 
-SYNOPSIS
+   SYNOPSIS
 
-       int proc_wait (int *statloc)
+   void do_detach (int signal)
 
-DESCRIPTION
+   DESCRIPTION
 
-       Try to emulate wait() as much as possible.  Not sure why we can't
-       just use wait(), but it seems to have problems when applied to a
-       process being controlled with the /proc interface.
+   Detach from the current attachee.
 
-NOTES
+   If signal is non-zero, the attachee is started running again and sent
+   the specified signal.
 
-       We have a race problem here with no obvious solution.  We need to let
-       the inferior run until it stops on an event of interest, which means
-       that we need to use the PIOCWSTOP ioctl.  However, we cannot use this
-       ioctl if the process is already stopped on something that is not an
-       event of interest, or the call will hang indefinitely.  Thus we first
-       use PIOCSTATUS to see if the process is not stopped.  If not, then we
-       use PIOCWSTOP.  But during the window between the two, if the process
-       stops for any reason that is not an event of interest (such as a job
-       control signal) then gdb will hang.  One possible workaround is to set
-       an alarm to wake up every minute of so and check to see if the process
-       is still running, and if so, then reissue the PIOCWSTOP.  But this is
-       a real kludge, so has not been implemented.  FIXME: investigate
-       alternatives.
+   If signal is zero and the attachee was not already stopped when we
+   attached to it, then we make it runnable again when we detach.
 
-       FIXME:  Investigate why wait() seems to have problems with programs
-       being control by /proc routines.
+   Otherwise, we query whether or not to make the attachee runnable
+   again, since we may simply want to leave it in the state it was in
+   when we attached.
 
+   We report any problems, but do not consider them errors, since we
+   MUST detach even if some things don't seem to go right.  This may not
+   be the ideal situation.  (FIXME).
  */
 
-int
-proc_wait (statloc)
-     int *statloc;
+static void
+do_detach (signal)
+     int signal;
+{
+  struct procinfo *pi;
+
+  for (pi = procinfo_list; pi; pi = pi->next)
+    {
+      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)
+#else
+      if (ioctl (pi->ctl_fd, PIOCSEXIT, &pi->saved_exitset.sysset) < 0)
+#endif
+       {
+         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)
+#else
+      if (ioctl (pi->ctl_fd, PIOCSENTRY, &pi->saved_entryset.sysset) < 0)
+#endif
+       {
+         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)
+#else
+      if (ioctl (pi->ctl_fd, PIOCSTRACE, &pi->saved_trace.sigset) < 0)
+#endif
+       {
+         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");
+       }
+#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)
+#else
+      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
+       {
+         if (signal
+         || (THE_PR_LWP (pi->prstatus).pr_flags & (PR_STOPPED | PR_ISTOP)))
+           {
+#ifdef PROCFS_USE_READ_WRITE
+             long cmd;
+#endif
+
+             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.  */
+#ifdef PROCFS_USE_READ_WRITE
+                 cmd = PCCFAULT;
+                 if (write (pi->ctl_fd, (char *) &cmd, sizeof (long)) < 0)
+#else
+                 if (ioctl (pi->ctl_fd, PIOCCFAULT, 0))
+#endif
+                   {
+                     print_sys_errmsg (pi->pathname, errno);
+                     printf_unfiltered ("PIOCCFAULT failed.\n");
+                   }
+
+                 /* Make it run again when we close it.  */
+
+                 modify_run_on_last_close_flag (pi->ctl_fd, 1);
+               }
+           }
+       }
+      close_proc_file (pi);
+    }
+  attach_flag = 0;
+}
+
+/*  emulate wait() as much as possible.
+   Wait for child to do something.  Return pid of child, or -1 in case
+   of error; store status in *OURSTATUS.
+
+   Not sure why we can't
+   just use wait(), but it seems to have problems when applied to a
+   process being controlled with the /proc interface.
+
+   We have a race problem here with no obvious solution.  We need to let
+   the inferior run until it stops on an event of interest, which means
+   that we need to use the PIOCWSTOP ioctl.  However, we cannot use this
+   ioctl if the process is already stopped on something that is not an
+   event of interest, or the call will hang indefinitely.  Thus we first
+   use PIOCSTATUS to see if the process is not stopped.  If not, then we
+   use PIOCWSTOP.  But during the window between the two, if the process
+   stops for any reason that is not an event of interest (such as a job
+   control signal) then gdb will hang.  One possible workaround is to set
+   an alarm to wake up every minute of so and check to see if the process
+   is still running, and if so, then reissue the PIOCWSTOP.  But this is
+   a real kludge, so has not been implemented.  FIXME: investigate
+   alternatives.
+
+   FIXME:  Investigate why wait() seems to have problems with programs
+   being control by /proc routines.  */
+static int
+procfs_wait (pid, ourstatus)
+     int pid;
+     struct target_waitstatus *ourstatus;
 {
   short what;
   short why;
   int statval = 0;
   int checkerr = 0;
   int rtnval = -1;
-  
-  if (ioctl (pi.fd, PIOCSTATUS, &pi.prstatus) < 0)
+  struct procinfo *pi;
+
+scan_again:
+
+  /* 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)
+    {
+      if (!pi->had_event)
+       continue;
+
+      if (!(THE_PR_LWP (pi->prstatus).pr_flags & (PR_STOPPED | PR_ISTOP)))
+       continue;
+
+      why = THE_PR_LWP (pi->prstatus).pr_why;
+      what = THE_PR_LWP (pi->prstatus).pr_what;
+      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 (!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)
     {
-      checkerr++;
+      wait_fd ();
+      goto scan_again;
     }
-  else if (!(pi.prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)))
+
+  if (!checkerr
+      && !(THE_PR_LWP (pi->prstatus).pr_flags & (PR_STOPPED | PR_ISTOP)))
     {
-      if (ioctl (pi.fd, PIOCWSTOP, &pi.prstatus) < 0)
+      if (!procfs_write_pcwstop (pi))
        {
          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)))
            {
-             error ("PIOCWSTOP, wait failed, returned %d", rtnval);
+             print_sys_errmsg (pi->pathname, errno);
+             error ("procfs_wait: wait failed, returned %d", rtnval);
              /* NOTREACHED */
            }
        }
       else
        {
-         print_sys_errmsg (pi.pathname, errno);
+         print_sys_errmsg (pi->pathname, errno);
          error ("PIOCSTATUS or PIOCWSTOP failed.");
          /* NOTREACHED */
        }
     }
-  else if (pi.prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
+  else if (THE_PR_LWP (pi->prstatus).pr_flags & (PR_STOPPED | PR_ISTOP))
     {
-      rtnval = pi.prstatus.pr_pid;
-      why = pi.prstatus.pr_why;
-      what = pi.prstatus.pr_what;
-      if (why == PR_SIGNALLED)
-       {
-         statval = (what << 8) | 0177;
-       }
-      else if ((why == PR_SYSEXIT)
-              &&
-              (
-#ifdef SYS_exec
-               what == SYS_exec
+#ifdef UNIXWARE
+      rtnval = pi->prstatus.pr_pid;
 #else
-               0 == 0
-#endif
-#ifdef SYS_execve
-               || what == SYS_execve
-#endif
-#ifdef SYS_execv
-               || what == SYS_execv
+      rtnval = pi->pid;
 #endif
-               ))
-       {
-         statval = (SIGTRAP << 8) | 0177;
-       }
-      else if (why == PR_REQUESTED)
+      why = THE_PR_LWP (pi->prstatus).pr_why;
+      what = THE_PR_LWP (pi->prstatus).pr_what;
+
+      switch (why)
        {
+       case PR_SIGNALLED:
+         statval = (what << 8) | 0177;
+         break;
+       case PR_SYSENTRY:
+       case PR_SYSEXIT:
+         rtnval = pi->saved_rtnval;
+         statval = pi->saved_statval;
+         break;
+       case PR_REQUESTED:
          statval = (SIGSTOP << 8) | 0177;
-       }
-      else if (why == PR_JOBCONTROL)
-       {
+         break;
+       case PR_JOBCONTROL:
          statval = (what << 8) | 0177;
-       }
-      else if (why == PR_FAULTED)
-       {
+         break;
+       case PR_FAULTED:
          switch (what)
            {
+#ifdef FLTWATCH
+           case FLTWATCH:
+             statval = (SIGTRAP << 8) | 0177;
+             break;
+#endif
+#ifdef FLTKWATCH
+           case FLTKWATCH:
+             statval = (SIGTRAP << 8) | 0177;
+             break;
+#endif
+#ifndef FAULTED_USE_SIGINFO
+             /* Irix, contrary to the documentation, fills in 0 for si_signo.
+                Solaris fills in si_signo.  I'm not sure about others.  */
            case FLTPRIV:
            case FLTILL:
              statval = (SIGILL << 8) | 0177;
@@ -1899,70 +3668,121 @@ proc_wait (statloc)
            case FLTFPE:
              statval = (SIGFPE << 8) | 0177;
              break;
-           case FLTPAGE:               /* Recoverable page fault */
+           case FLTPAGE:       /* Recoverable page fault */
+#endif /* not FAULTED_USE_SIGINFO */
            default:
-             rtnval = -1;
-             error ("PIOCWSTOP, unknown why %d, what %d", why, what);
-             /* NOTREACHED */
+             /* Use the signal which the kernel assigns.  This is better than
+                trying to second-guess it from the fault.  In fact, I suspect
+                that FLTACCESS can be either SIGSEGV or SIGBUS.  */
+             statval =
+               ((THE_PR_LWP (pi->prstatus).pr_info.si_signo) << 8) | 0177;
+             break;
            }
-       }
-      else
-       {
-         rtnval = -1;
+         break;
+       default:
          error ("PIOCWSTOP, unknown why %d, what %d", why, what);
-         /* NOTREACHED */
        }
+      /* Stop all the other threads when any of them stops.  */
+
+      {
+       struct procinfo *procinfo, *next_pi;
+
+       for (procinfo = procinfo_list; procinfo; procinfo = next_pi)
+         {
+           next_pi = procinfo->next;
+           if (!procinfo->had_event)
+             {
+#ifdef PROCFS_USE_READ_WRITE
+               long cmd = PCSTOP;
+               if (write (pi->ctl_fd, (char *) &cmd, sizeof (long)) < 0)
+                 {
+                   print_sys_errmsg (procinfo->pathname, errno);
+                   error ("PCSTOP failed");
+                 }
+#else
+               /* A bug in Solaris (2.5) causes us to hang when trying to
+                  stop a stopped process.  So, we have to check first in
+                  order to avoid the hang. */
+               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;
+                 }
+
+               if (!(procinfo->prstatus.pr_flags & PR_STOPPED))
+                 if (ioctl (procinfo->ctl_fd, PIOCSTOP, &procinfo->prstatus)
+                     < 0)
+                   {
+                     print_sys_errmsg (procinfo->pathname, errno);
+                     warning ("PIOCSTOP failed");
+                   }
+#endif
+             }
+         }
+      }
     }
   else
     {
-      error ("PIOCWSTOP, stopped for unknown/unhandled reason, flags %#x", 
-            pi.prstatus.pr_flags);
-         /* NOTREACHED */
+      error ("PIOCWSTOP, stopped for unknown/unhandled reason, flags %#x",
+            THE_PR_LWP (pi->prstatus).pr_flags);
     }
-  if (statloc)
+
+  store_waitstatus (ourstatus, statval);
+
+  if (rtnval == -1)            /* No more children to wait for */
     {
-      *statloc = statval;
+      warning ("Child process unexpectedly missing");
+      /* Claim it exited with unknown signal.  */
+      ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
+      ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
+      return rtnval;
     }
+
+  pi->had_event = 0;           /* Indicate that we've seen this one */
   return (rtnval);
 }
 
 /*
 
-LOCAL FUNCTION
+   LOCAL FUNCTION
 
-       set_proc_siginfo - set a process's current signal info
+   set_proc_siginfo - set a process's current signal info
 
-SYNOPSIS
+   SYNOPSIS
 
-       void set_proc_siginfo (struct procinfo *pip, int signo);
+   void set_proc_siginfo (struct procinfo *pip, int signo);
 
-DESCRIPTION
+   DESCRIPTION
 
-       Given a pointer to a process info struct in PIP and a signal number
-       in SIGNO, set the process's current signal and its associated signal
-       information.  The signal will be delivered to the process immediately
-       after execution is resumed, even if it is being held.  In addition,
-       this particular delivery will not cause another PR_SIGNALLED stop
-       even if the signal is being traced.
+   Given a pointer to a process info struct in PIP and a signal number
+   in SIGNO, set the process's current signal and its associated signal
+   information.  The signal will be delivered to the process immediately
+   after execution is resumed, even if it is being held.  In addition,
+   this particular delivery will not cause another PR_SIGNALLED stop
+   even if the signal is being traced.
 
-       If we are not delivering the same signal that the prstatus siginfo
-       struct contains information about, then synthesize a siginfo struct
-       to match the signal we are doing to deliver, make it of the type
-       "generated by a user process", and send this synthesized copy.  When
-       used to set the inferior's signal state, this will be required if we
-       are not currently stopped because of a traced signal, or if we decide
-       to continue with a different signal.
+   If we are not delivering the same signal that the prstatus siginfo
+   struct contains information about, then synthesize a siginfo struct
+   to match the signal we are going to deliver, make it of the type
+   "generated by a user process", and send this synthesized copy.  When
+   used to set the inferior's signal state, this will be required if we
+   are not currently stopped because of a traced signal, or if we decide
+   to continue with a different signal.
 
-       Note that when continuing the inferior from a stop due to receipt
-       of a traced signal, we either have set PRCSIG to clear the existing
-       signal, or we have to call this function to do a PIOCSSIG with either
-       the existing siginfo struct from pr_info, or one we have synthesized
-       appropriately for the signal we want to deliver.  Otherwise if the
-       signal is still being traced, the inferior will immediately stop
-       again.
+   Note that when continuing the inferior from a stop due to receipt
+   of a traced signal, we either have set PRCSIG to clear the existing
+   signal, or we have to call this function to do a PIOCSSIG with either
+   the existing siginfo struct from pr_info, or one we have synthesized
+   appropriately for the signal we want to deliver.  Otherwise if the
+   signal is still being traced, the inferior will immediately stop
+   again.
 
-       See siginfo(5) for more details.
-*/
+   See siginfo(5) for more details.
+ */
 
 static void
 set_proc_siginfo (pip, signo)
@@ -1971,978 +3791,2153 @@ set_proc_siginfo (pip, signo)
 {
   struct siginfo newsiginfo;
   struct siginfo *sip;
+#if defined (UNIXWARE) || defined (PROCFS_USE_READ_WRITE)      
+  struct sigi_ctl sictl;
+#endif
+
+#ifdef PROCFS_DONT_PIOCSSIG_CURSIG
+  /* With Alpha OSF/1 procfs, the kernel gets really confused if it
+     receives a PIOCSSIG with a signal identical to the current signal,
+     it messes up the current signal. Work around the kernel bug.  */
+  if (signo == THE_PR_LWP (pip->prstatus).pr_cursig)
+    return;
+#endif
 
-  if (pip -> valid)
+#ifdef UNIXWARE
+  if (signo == THE_PR_LWP (pip->prstatus).pr_info.si_signo)
     {
-      if (signo == pip -> prstatus.pr_info.si_signo)
-       {
-         sip = &pip -> prstatus.pr_info;
-       }
-      else
+      memcpy ((char *) &sictl.siginfo, (char *) &pip->prstatus.pr_lwp.pr_info,
+             sizeof (siginfo_t));
+    }
+#else
+  if (signo == THE_PR_LWP (pip->prstatus).pr_info.si_signo)
+    {
+      sip = &pip->prstatus.pr_info;
+    }
+#endif
+  else
+    {
+#ifdef UNIXWARE
+      siginfo_t *sip = &sictl.siginfo;
+      memset ((char *) sip, 0, sizeof (siginfo_t));
+#else
+      memset ((char *) &newsiginfo, 0, sizeof (newsiginfo));
+      sip = &newsiginfo;
+#endif
+      sip->si_signo = signo;
+      sip->si_code = 0;
+      sip->si_errno = 0;
+      sip->si_pid = getpid ();
+      sip->si_uid = getuid ();
+    }
+#ifdef PROCFS_USE_READ_WRITE
+  sictl.cmd = PCSSIG;
+  if (write (pip->ctl_fd, (char *) &sictl, sizeof (struct sigi_ctl)) < 0)
+#else
+  if (ioctl (pip->ctl_fd, PIOCSSIG, sip) < 0)
+#endif
+    {
+      print_sys_errmsg (pip->pathname, errno);
+      warning ("PIOCSSIG failed");
+    }
+}
+
+/* Resume execution of process PID.  If STEP is nozero, then
+   just single step it.  If SIGNAL is nonzero, restart it with that
+   signal activated.  */
+
+static void
+procfs_resume (pid, step, signo)
+     int pid;
+     int step;
+     enum target_signal signo;
+{
+  int signal_to_pass;
+  struct procinfo *pi, *procinfo, *next_pi;
+#if defined (UNIXWARE) || defined (PROCFS_USE_READ_WRITE)      
+  struct proc_ctl pctl;
+#endif
+
+  pi = find_procinfo (pid == -1 ? inferior_pid : pid, 0);
+
+  errno = 0;
+#ifdef UNIXWARE
+  pctl.cmd = PCRUN;
+  pctl.data = PRCFAULT;
+#else
+  pi->prrun.pr_flags = PRSTRACE | PRSFAULT | PRCFAULT;
+#endif
+
+#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
+   random garbage.  We have to rely on the fact that PC and nPC have been
+   written previously via PIOCSREG during a register flush. */
+
+  pi->prrun.pr_vaddr = (caddr_t) * (int *) &registers[REGISTER_BYTE (PC_REGNUM)];
+  pi->prrun.pr_flags != PRSVADDR;
+#endif
+#endif
+
+  if (signo == TARGET_SIGNAL_STOP && pi->nopass_next_sigstop)
+    /* When attaching to a child process, if we forced it to stop with
+       a PIOCSTOP, then we will have set the nopass_next_sigstop flag.
+       Upon resuming the first time after such a stop, we explicitly
+       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 == TARGET_SIGNAL_TSTP
+          && THE_PR_LWP (pi->prstatus).pr_cursig == SIGTSTP
+          && THE_PR_LWP (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 = target_signal_to_host (signo);
+
+  if (signal_to_pass)
+    {
+      set_proc_siginfo (pi, signal_to_pass);
+    }
+  else
+    {
+#ifdef UNIXWARE
+      pctl.data |= PRCSIG;
+#else
+      pi->prrun.pr_flags |= PRCSIG;
+#endif
+    }
+  pi->nopass_next_sigstop = 0;
+  if (step)
+    {
+#ifdef UNIXWARE
+      pctl.data |= PRSTEP;
+#else
+      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)
+#else
+      if ((pi->prstatus.pr_flags & PR_ISTOP)
+         && ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
+#endif
        {
-         (void) memset ((char *) &newsiginfo, 0, sizeof (newsiginfo));
-         sip = &newsiginfo;
-         sip -> si_signo = signo;
-         sip -> si_code = 0;
-         sip -> si_errno = 0;
-         sip -> si_pid = getpid ();
-         sip -> si_uid = getuid ();
+         /* The LWP has apparently terminated.  */
+         if (info_verbose)
+           printf_filtered ("LWP %d doesn't respond.\n",
+                            (pi->pid >> 16) & 0xffff);
+         close_proc_file (pi);
        }
-      if (ioctl (pip -> fd, PIOCSSIG, sip) < 0)
+    }
+
+  /* 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 = next_pi)
+      {
+       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");
+               }
+#else
+             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.  */
+
+             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);
+      }
+}
+
+/*
+
+   LOCAL FUNCTION
+
+   procfs_fetch_registers -- fetch current registers from inferior
+
+   SYNOPSIS
+
+   void procfs_fetch_registers (int regno)
+
+   DESCRIPTION
+
+   Read the current values of the inferior's registers, both the
+   general register set and floating point registers (if supported)
+   and update gdb's idea of their current values.
+
+ */
+
+static void
+procfs_fetch_registers (regno)
+     int regno;
+{
+  struct procinfo *pi;
+
+  pi = current_procinfo;
+
+#ifdef UNIXWARE
+  if (procfs_read_status (pi))
+    {
+      supply_gregset (&pi->prstatus.pr_lwp.pr_context.uc_mcontext.gregs);
+#if defined (FP0_REGNUM)
+      supply_fpregset (&pi->prstatus.pr_lwp.pr_context.uc_mcontext.fpregs);
+#endif
+    }
+#else /* UNIXWARE */
+  if (ioctl (pi->ctl_fd, PIOCGREG, &pi->gregset.gregset) != -1)
+    {
+      supply_gregset (&pi->gregset.gregset);
+    }
+#if defined (FP0_REGNUM)
+  if (ioctl (pi->ctl_fd, PIOCGFPREG, &pi->fpregset.fpregset) != -1)
+    {
+      supply_fpregset (&pi->fpregset.fpregset);
+    }
+#endif
+#endif /* UNIXWARE */
+}
+
+/*
+
+   LOCAL FUNCTION
+
+   proc_init_failed - called when /proc access initialization fails
+   fails
+
+   SYNOPSIS
+
+   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.  If KILL_P is true, sends SIGKILL.
+ */
+
+static void
+proc_init_failed (pi, why, kill_p)
+     struct procinfo *pi;
+     char *why;
+     int kill_p;
+{
+  print_sys_errmsg (pi->pathname, errno);
+  if (kill_p)
+    kill (pi->pid, SIGKILL);
+  close_proc_file (pi);
+  error (why);
+  /* NOTREACHED */
+}
+
+/*
+
+   LOCAL FUNCTION
+
+   close_proc_file - close any currently open /proc entry
+
+   SYNOPSIS
+
+   static void close_proc_file (struct procinfo *pip)
+
+   DESCRIPTION
+
+   Close any currently open /proc entry and mark the process information
+   entry as invalid.  In order to ensure that we don't try to reuse any
+   stale information, the pid, fd, and pathnames are explicitly
+   invalidated, which may be overkill.
+
+ */
+
+static void
+close_proc_file (pip)
+     struct procinfo *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);
+#ifdef HAVE_MULTIPLE_PROC_FDS
+  close (pip->as_fd);
+  close (pip->status_fd);
+  close (pip->map_fd);
+#endif
+
+  free (pip->pathname);
+
+  /* Unlink pip from the procinfo chain.  Note pip might not be on the list. */
+
+  if (procinfo_list == pip)
+    procinfo_list = pip->next;
+  else
+    {
+      for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)
        {
-         print_sys_errmsg (pip -> pathname, errno);
-         warning ("PIOCSSIG failed");
+         if (procinfo->next == pip)
+           {
+             procinfo->next = pip->next;
+             break;
+           }
        }
+      free (pip);
     }
 }
 
-/*
+static void
+close_proc_file_cleanup (pip)
+     void *pip;
+{
+  close_proc_file ((struct procinfo *) pip);
+}
+
+static struct cleanup *
+make_cleanup_close_proc_file (pip)
+     struct procinfo *pip;
+{
+  return make_cleanup (close_proc_file_cleanup, pip);
+}
 
-GLOBAL FUNCTION
+/*
 
-       child_resume -- resume execution of the inferior process
+   LOCAL FUNCTION
 
-SYNOPSIS
+   open_proc_file - open a /proc entry for a given process id
 
-       void child_resume (int step, int signo)
+   SYNOPSIS
 
-DESCRIPTION
+   static int open_proc_file (int pid, struct procinfo *pip, int mode)
 
-       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.
+   DESCRIPTION
 
-NOTE
+   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.
 
-       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.
+   Note that the pathname is left intact, even when the open fails,
+   so that callers can use it to construct meaningful error messages
+   rather than just "file open failed".
 
-       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?)
+   Note that for Solaris, the process-id also includes an LWP-id, so we
+   actually attempt to open that.  If we are handed a pid with a 0 LWP-id,
+   then we will ask the kernel what it is and add it to the pid.  Hence,
+   the pid can be changed by us.
  */
 
-void
-child_resume (step, signo)
-     int step;
-     int signo;
+static int
+open_proc_file (pid, pip, mode, control)
+     int pid;
+     struct procinfo *pip;
+     int mode;
+     int control;
 {
-  errno = 0;
-  pi.prrun.pr_flags = PRSTRACE | PRSFAULT | PRCFAULT;
+  int tmp, tmpfd;
 
-#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
-   random garbage.  We have to rely on the fact that PC and nPC have been
-   written previously via PIOCSREG during a register flush. */
+  pip->next = NULL;
+  pip->had_event = 0;
+  pip->pathname = xmalloc (MAX_PROC_NAME_SIZE);
+  pip->pid = pid;
 
-  pi.prrun.pr_vaddr = (caddr_t) *(int *) &registers[REGISTER_BYTE (PC_REGNUM)];
-  pi.prrun.pr_flags != PRSVADDR;
+#ifndef PIOCOPENLWP
+  tmp = pid;
+#else
+  tmp = pid & 0xffff;
 #endif
 
-  if (signo && !(signo == SIGSTOP && pi.nopass_next_sigstop))
+#ifdef HAVE_MULTIPLE_PROC_FDS
+  sprintf (pip->pathname, STATUS_PROC_NAME_FMT, tmp);
+  if ((pip->status_fd = open (pip->pathname, O_RDONLY)) < 0)
     {
-      set_proc_siginfo (&pi, signo);
+      return 0;
     }
-  else
+
+  sprintf (pip->pathname, AS_PROC_NAME_FMT, tmp);
+  if ((pip->as_fd = open (pip->pathname, O_RDWR)) < 0)
     {
-      pi.prrun.pr_flags |= PRCSIG;
+      close (pip->status_fd);
+      return 0;
     }
-  pi.nopass_next_sigstop = 0;
-  if (step)
+
+  sprintf (pip->pathname, MAP_PROC_NAME_FMT, tmp);
+  if ((pip->map_fd = open (pip->pathname, O_RDONLY)) < 0)
     {
-      pi.prrun.pr_flags |= PRSTEP;
+      close (pip->status_fd);
+      close (pip->as_fd);
+      return 0;
     }
-  if (ioctl (pi.fd, PIOCRUN, &pi.prrun) != 0)
+
+  if (control)
     {
-      perror_with_name (pi.pathname);
-      /* NOTREACHED */
+      sprintf (pip->pathname, CTL_PROC_NAME_FMT, tmp);
+      if ((pip->ctl_fd = open (pip->pathname, O_WRONLY)) < 0)
+       {
+         close (pip->status_fd);
+         close (pip->as_fd);
+         close (pip->map_fd);
+         return 0;
+       }
     }
-}
 
-/*
+#else /* HAVE_MULTIPLE_PROC_FDS */
+  sprintf (pip->pathname, CTL_PROC_NAME_FMT, tmp);
 
-GLOBAL FUNCTION
+  if ((tmpfd = open (pip->pathname, mode)) < 0)
+    return 0;
 
-       fetch_inferior_registers -- fetch current registers from inferior
+#ifndef PIOCOPENLWP
+  pip->ctl_fd = tmpfd;
+  pip->as_fd = tmpfd;
+  pip->map_fd = tmpfd;
+  pip->status_fd = tmpfd;
+#else
+  tmp = (pid >> 16) & 0xffff;  /* Extract thread id */
 
-SYNOPSIS
+  if (tmp == 0)
+    {                          /* Don't know thread id yet */
+      if (ioctl (tmpfd, PIOCSTATUS, &pip->prstatus) < 0)
+       {
+         print_sys_errmsg (pip->pathname, errno);
+         close (tmpfd);
+         error ("open_proc_file: PIOCSTATUS failed");
+       }
 
-       void fetch_inferior_registers (int regno)
+      tmp = pip->prstatus.pr_who;      /* Get thread id from prstatus_t */
+      pip->pid = (tmp << 16) | pid;    /* Update pip */
+    }
 
-DESCRIPTION
+  if ((pip->ctl_fd = ioctl (tmpfd, PIOCOPENLWP, &tmp)) < 0)
+    {
+      close (tmpfd);
+      return 0;
+    }
 
-       Read the current values of the inferior's registers, both the
-       general register set and floating point registers (if supported)
-       and update gdb's idea of their current values.
+#ifdef PIOCSET                 /* New method */
+  {
+    long pr_flags;
+    pr_flags = PR_ASYNC;
+    ioctl (pip->ctl_fd, PIOCSET, &pr_flags);
+  }
+#endif
 
-*/
+  /* keep extra fds in sync */
+  pip->as_fd = pip->ctl_fd;
+  pip->map_fd = pip->ctl_fd;
+  pip->status_fd = pip->ctl_fd;
 
-void
-fetch_inferior_registers (regno)
-     int regno;
+  close (tmpfd);               /* All done with main pid */
+#endif /* PIOCOPENLWP */
+
+#endif /* HAVE_MULTIPLE_PROC_FDS */
+
+  return 1;
+}
+
+static char *
+mappingflags (flags)
+     long flags;
+{
+  static char asciiflags[8];
+
+  strcpy (asciiflags, "-------");
+#if defined (MA_PHYS)
+  if (flags & MA_PHYS)
+    asciiflags[0] = 'd';
+#endif
+  if (flags & MA_STACK)
+    asciiflags[1] = 's';
+  if (flags & MA_BREAK)
+    asciiflags[2] = 'b';
+  if (flags & MA_SHARED)
+    asciiflags[3] = 's';
+  if (flags & MA_READ)
+    asciiflags[4] = 'r';
+  if (flags & MA_WRITE)
+    asciiflags[5] = 'w';
+  if (flags & MA_EXEC)
+    asciiflags[6] = 'x';
+  return (asciiflags);
+}
+
+static void
+info_proc_flags (pip, summary)
+     struct procinfo *pip;
+     int summary;
 {
-  if (ioctl (pi.fd, PIOCGREG, &pi.gregset) != -1)
+  struct trans *transp;
+#ifdef UNIXWARE
+  long flags = pip->prstatus.pr_flags | pip->prstatus.pr_lwp.pr_flags;
+#else
+  long flags = pip->prstatus.pr_flags;
+#endif
+
+  printf_filtered ("%-32s", "Process status flags:");
+  if (!summary)
     {
-      supply_gregset (&pi.gregset);
+      printf_filtered ("\n\n");
     }
-#if defined (FP0_REGNUM)
-  if (ioctl (pi.fd, PIOCGFPREG, &pi.fpregset) != -1)
+  for (transp = pr_flag_table; transp->name != NULL; transp++)
     {
-      supply_fpregset (&pi.fpregset);
+      if (flags & transp->value)
+       {
+         if (summary)
+           {
+             printf_filtered ("%s ", transp->name);
+           }
+         else
+           {
+             printf_filtered ("\t%-16s %s.\n", transp->name, transp->desc);
+           }
+       }
     }
-#endif
+  printf_filtered ("\n");
 }
 
-/*
-
-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)
+static void
+info_proc_stop (pip, summary)
+     struct procinfo *pip;
+     int summary;
+{
+  struct trans *transp;
+  int why;
+  int what;
 
-DESCRIPTION
+  why = THE_PR_LWP (pip->prstatus).pr_why;
+  what = THE_PR_LWP (pip->prstatus).pr_what;
 
-       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.
+  if (THE_PR_LWP (pip->prstatus).pr_flags & PR_STOPPED)
+    {
+      printf_filtered ("%-32s", "Reason for stopping:");
+      if (!summary)
+       {
+         printf_filtered ("\n\n");
+       }
+      for (transp = pr_why_table; transp->name != NULL; transp++)
+       {
+         if (why == transp->value)
+           {
+             if (summary)
+               {
+                 printf_filtered ("%s ", transp->name);
+               }
+             else
+               {
+                 printf_filtered ("\t%-16s %s.\n",
+                                  transp->name, transp->desc);
+               }
+             break;
+           }
+       }
 
-NOTES
+      /* Use the pr_why field to determine what the pr_what field means, and
+         print more information. */
 
-       Use the indicated sizes to validate the gregset and fpregset
-       structures.
-*/
+      switch (why)
+       {
+       case PR_REQUESTED:
+         /* pr_what is unused for this case */
+         break;
+       case PR_JOBCONTROL:
+       case PR_SIGNALLED:
+         if (summary)
+           {
+             printf_filtered ("%s ", signalname (what));
+           }
+         else
+           {
+             printf_filtered ("\t%-16s %s.\n", signalname (what),
+                              safe_strsignal (what));
+           }
+         break;
+       case PR_SYSENTRY:
+         if (summary)
+           {
+             printf_filtered ("%s ", syscallname (what));
+           }
+         else
+           {
+             printf_filtered ("\t%-16s %s.\n", syscallname (what),
+                              "Entered this system call");
+           }
+         break;
+       case PR_SYSEXIT:
+         if (summary)
+           {
+             printf_filtered ("%s ", syscallname (what));
+           }
+         else
+           {
+             printf_filtered ("\t%-16s %s.\n", syscallname (what),
+                              "Returned from this system call");
+           }
+         break;
+       case PR_FAULTED:
+         if (summary)
+           {
+             printf_filtered ("%s ",
+                              lookupname (faults_table, what, "fault"));
+           }
+         else
+           {
+             printf_filtered ("\t%-16s %s.\n",
+                              lookupname (faults_table, what, "fault"),
+                              lookupdesc (faults_table, what));
+           }
+         break;
+       }
+      printf_filtered ("\n");
+    }
+}
 
-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 */
+static void
+info_proc_siginfo (pip, summary)
+     struct procinfo *pip;
+     int summary;
 {
+  struct siginfo *sip;
 
-  if (which == 0)
+  if ((THE_PR_LWP (pip->prstatus).pr_flags & PR_STOPPED) &&
+      (THE_PR_LWP (pip->prstatus).pr_why == PR_SIGNALLED ||
+       THE_PR_LWP (pip->prstatus).pr_why == PR_FAULTED))
     {
-      if (core_reg_size != sizeof (pi.gregset))
+      printf_filtered ("%-32s", "Additional signal/fault info:");
+      sip = &(THE_PR_LWP (pip->prstatus).pr_info);
+      if (summary)
        {
-         warning ("wrong size gregset struct in core file");
+         printf_filtered ("%s ", signalname (sip->si_signo));
+         if (sip->si_errno > 0)
+           {
+             printf_filtered ("%s ", errnoname (sip->si_errno));
+           }
+         if (sip->si_code <= 0)
+           {
+             printf_filtered ("sent by %s, uid %d ",
+                              target_pid_to_str (sip->si_pid),
+                              sip->si_uid);
+           }
+         else
+           {
+             printf_filtered ("%s ", sigcodename (sip));
+             if ((sip->si_signo == SIGILL) ||
+                 (sip->si_signo == SIGFPE) ||
+                 (sip->si_signo == SIGSEGV) ||
+                 (sip->si_signo == SIGBUS))
+               {
+                 printf_filtered ("addr=%#lx ",
+                                  (unsigned long) sip->si_addr);
+               }
+             else if ((sip->si_signo == SIGCHLD))
+               {
+                 printf_filtered ("child %s, status %u ",
+                                  target_pid_to_str (sip->si_pid),
+                                  sip->si_status);
+               }
+             else if ((sip->si_signo == SIGPOLL))
+               {
+                 printf_filtered ("band %u ", sip->si_band);
+               }
+           }
        }
       else
        {
-         (void) memcpy ((char *) &pi.gregset, core_reg_sect,
-                        sizeof (pi.gregset));
-         supply_gregset (&pi.gregset);
+         printf_filtered ("\n\n");
+         printf_filtered ("\t%-16s %s.\n", signalname (sip->si_signo),
+                          safe_strsignal (sip->si_signo));
+         if (sip->si_errno > 0)
+           {
+             printf_filtered ("\t%-16s %s.\n",
+                              errnoname (sip->si_errno),
+                              safe_strerror (sip->si_errno));
+           }
+         if (sip->si_code <= 0)
+           {
+             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");
+           }
+         else
+           {
+             printf_filtered ("\t%-16s %s.\n", sigcodename (sip),
+                              sigcodedesc (sip));
+             if ((sip->si_signo == SIGILL) ||
+                 (sip->si_signo == SIGFPE))
+               {
+                 printf_filtered ("\t%#-16lx %s.\n",
+                                  (unsigned long) sip->si_addr,
+                                  "Address of faulting instruction");
+               }
+             else if ((sip->si_signo == SIGSEGV) ||
+                      (sip->si_signo == SIGBUS))
+               {
+                 printf_filtered ("\t%#-16lx %s.\n",
+                                  (unsigned long) sip->si_addr,
+                                  "Address of faulting memory reference");
+               }
+             else if ((sip->si_signo == SIGCHLD))
+               {
+                 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");
+               }
+             else if ((sip->si_signo == SIGPOLL))
+               {
+                 printf_filtered ("\t%-16u %s.\n", sip->si_band,
+                                  "Band event for POLL_{IN,OUT,MSG}");
+               }
+           }
        }
+      printf_filtered ("\n");
     }
-  else if (which == 2)
+}
+
+static void
+info_proc_syscalls (pip, summary)
+     struct procinfo *pip;
+     int summary;
+{
+  int syscallnum;
+
+  if (!summary)
     {
-      if (core_reg_size != sizeof (pi.fpregset))
+
+#if 0                          /* FIXME:  Needs to use gdb-wide configured info about system calls. */
+      if (pip->prstatus.pr_flags & PR_ASLEEP)
        {
-         warning ("wrong size fpregset struct in core file");
+         int syscallnum = pip->prstatus.pr_reg[R_D0];
+         if (summary)
+           {
+             printf_filtered ("%-32s", "Sleeping in system call:");
+             printf_filtered ("%s", syscallname (syscallnum));
+           }
+         else
+           {
+             printf_filtered ("Sleeping in system call '%s'.\n",
+                              syscallname (syscallnum));
+           }
        }
-      else
+#endif
+
+#ifndef UNIXWARE
+      if (ioctl (pip->ctl_fd, PIOCGENTRY, &pip->entryset) < 0)
        {
-         (void) memcpy ((char *) &pi.fpregset, core_reg_sect,
-                        sizeof (pi.fpregset));
-#if defined (FP0_REGNUM)
-         supply_fpregset (&pi.fpregset);
+         print_sys_errmsg (pip->pathname, errno);
+         error ("PIOCGENTRY failed");
+       }
+
+      if (ioctl (pip->ctl_fd, PIOCGEXIT, &pip->exitset) < 0)
+       {
+         print_sys_errmsg (pip->pathname, errno);
+         error ("PIOCGEXIT failed");
+       }
+#endif
+
+      printf_filtered ("System call tracing information:\n\n");
+
+      printf_filtered ("\t%-12s %-8s %-8s\n",
+                      "System call",
+                      "Entry",
+                      "Exit");
+      for (syscallnum = 0; syscallnum < MAX_SYSCALLS; syscallnum++)
+       {
+         QUIT;
+         if (syscall_table[syscallnum] != NULL)
+           printf_filtered ("\t%-12s ", syscall_table[syscallnum]);
+         else
+           printf_filtered ("\t%-12d ", syscallnum);
+
+#ifdef UNIXWARE
+         printf_filtered ("%-8s ",
+                        prismember (&pip->prstatus.pr_sysentry, syscallnum)
+                          ? "on" : "off");
+         printf_filtered ("%-8s ",
+                          prismember (&pip->prstatus.pr_sysexit, syscallnum)
+                          ? "on" : "off");
+#else
+         printf_filtered ("%-8s ",
+                          prismember (&pip->entryset, syscallnum)
+                          ? "on" : "off");
+         printf_filtered ("%-8s ",
+                          prismember (&pip->exitset, syscallnum)
+                          ? "on" : "off");
 #endif
+         printf_filtered ("\n");
        }
+      printf_filtered ("\n");
     }
 }
 
-/*
-
-LOCAL FUNCTION
-
-       proc_init_failed - called whenever /proc access initialization fails
-
-SYNOPSIS
-
-       static void proc_init_failed (char *why)
-
-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.
- */
-
-static void
-proc_init_failed (why)
-     char *why;
+static char *
+signalname (signo)
+     int signo;
 {
-  print_sys_errmsg (pi.pathname, errno);
-  (void) kill (pi.pid, SIGKILL);
-  close_proc_file (&pi);
-  error (why);
-  /* NOTREACHED */
-}
-
-/*
-
-LOCAL FUNCTION
-
-       close_proc_file - close any currently open /proc entry
-
-SYNOPSIS
-
-       static void close_proc_file (struct procinfo *pip)
-
-DESCRIPTION
-
-       Close any currently open /proc entry and mark the process information
-       entry as invalid.  In order to ensure that we don't try to reuse any
-       stale information, the pid, fd, and pathnames are explicitly
-       invalidated, which may be overkill.
-
- */
+  const char *name;
+  static char locbuf[32];
 
-static void
-close_proc_file (pip)
-     struct procinfo *pip;
-{
-  pip -> pid = 0;
-  if (pip -> valid)
+  name = strsigno (signo);
+  if (name == NULL)
     {
-      (void) close (pip -> fd);
+      sprintf (locbuf, "Signal %d", signo);
     }
-  pip -> fd = -1;
-  if (pip -> pathname)
+  else
     {
-      free (pip -> pathname);
-      pip -> pathname = NULL;
+      sprintf (locbuf, "%s (%d)", name, signo);
     }
-  pip -> valid = 0;
+  return (locbuf);
 }
 
-/*
-
-LOCAL FUNCTION
-
-       open_proc_file - open a /proc entry for a given process id
-
-SYNOPSIS
-
-       static int open_proc_file (pid, struct procinfo *pip)
-
-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.
-
-       Note that the pathname is left intact, even when the open fails,
-       so that callers can use it to construct meaningful error messages
-       rather than just "file open failed".
- */
-
-static int
-open_proc_file (pid, pip)
-     int pid;
-     struct procinfo *pip;
+static char *
+errnoname (errnum)
+     int errnum;
 {
-  pip -> valid = 0;
-  if (pip -> valid)
-    {
-      (void) close (pip -> fd);
-    }
-  if (pip -> pathname == NULL)
+  const char *name;
+  static char locbuf[32];
+
+  name = strerrno (errnum);
+  if (name == NULL)
     {
-      pip -> pathname = xmalloc (32);
+      sprintf (locbuf, "Errno %d", errnum);
     }
-  sprintf (pip -> pathname, PROC_NAME_FMT, pid);
-  if ((pip -> fd = open (pip -> pathname, O_RDWR)) >= 0)
+  else
     {
-      pip -> valid = 1;
-      pip -> pid = pid;
+      sprintf (locbuf, "%s (%d)", name, errnum);
     }
-  return (pip -> valid);
+  return (locbuf);
 }
 
-static char *
-mappingflags (flags)
-     long flags;
+static void
+info_proc_signals (pip, summary)
+     struct procinfo *pip;
+     int summary;
 {
-  static char asciiflags[8];
-  
-  strcpy (asciiflags, "-------");
-#if defined (MA_PHYS)
-  if (flags & MA_PHYS)   asciiflags[0] = 'd';
-#endif
-  if (flags & MA_STACK)  asciiflags[1] = 's';
-  if (flags & MA_BREAK)  asciiflags[2] = 'b';
-  if (flags & MA_SHARED) asciiflags[3] = 's';
-  if (flags & MA_READ)   asciiflags[4] = 'r';
-  if (flags & MA_WRITE)  asciiflags[5] = 'w';
-  if (flags & MA_EXEC)   asciiflags[6] = 'x';
-  return (asciiflags);
+  int signo;
+
+  if (!summary)
+    {
+#ifndef PROCFS_USE_READ_WRITE
+      if (ioctl (pip->ctl_fd, PIOCGTRACE, &pip->trace) < 0)
+       {
+         print_sys_errmsg (pip->pathname, errno);
+         error ("PIOCGTRACE failed");
+       }
+#endif
+
+      printf_filtered ("Disposition of signals:\n\n");
+      printf_filtered ("\t%-15s %-8s %-8s %-8s  %s\n\n",
+                      "Signal", "Trace", "Hold", "Pending", "Description");
+      for (signo = 0; signo < NSIG; signo++)
+       {
+         QUIT;
+         printf_filtered ("\t%-15s ", signalname (signo));
+#ifdef UNIXWARE
+         printf_filtered ("%-8s ",
+                          prismember (&pip->prstatus.pr_sigtrace, signo)
+                          ? "on" : "off");
+         printf_filtered ("%-8s ",
+            prismember (&pip->prstatus.pr_lwp.pr_context.uc_sigmask, signo)
+                          ? "on" : "off");
+#else
+         printf_filtered ("%-8s ",
+                          prismember (&pip->trace, signo)
+                          ? "on" : "off");
+         printf_filtered ("%-8s ",
+                          prismember (&pip->prstatus.pr_sighold, signo)
+                          ? "on" : "off");
+#endif
+
+#ifdef UNIXWARE
+         if (prismember (&pip->prstatus.pr_sigpend, signo) ||
+             prismember (&pip->prstatus.pr_lwp.pr_lwppend, signo))
+           printf_filtered ("%-8s ", "yes");
+         else
+           printf_filtered ("%-8s ", "no");
+#else /* UNIXWARE */
+#ifdef PROCFS_SIGPEND_OFFSET
+         /* Alpha OSF/1 numbers the pending signals from 1.  */
+         printf_filtered ("%-8s ",
+                          (signo ? prismember (&pip->prstatus.pr_sigpend,
+                                               signo - 1)
+                           : 0)
+                          ? "yes" : "no");
+#else
+         printf_filtered ("%-8s ",
+                          prismember (&pip->prstatus.pr_sigpend, signo)
+                          ? "yes" : "no");
+#endif
+#endif /* UNIXWARE */
+         printf_filtered (" %s\n", safe_strsignal (signo));
+       }
+      printf_filtered ("\n");
+    }
 }
 
 static void
-info_proc_flags (pip, summary)
+info_proc_faults (pip, summary)
      struct procinfo *pip;
      int summary;
 {
   struct trans *transp;
 
-  printf_filtered ("%-32s", "Process status flags:");
   if (!summary)
     {
-      printf_filtered ("\n\n");
-    }
-  for (transp = pr_flag_table; transp -> name != NULL; transp++)
-    {
-      if (pip -> prstatus.pr_flags & transp -> value)
+#ifndef UNIXWARE
+      if (ioctl (pip->ctl_fd, PIOCGFAULT, &pip->fltset.fltset) < 0)
        {
-         if (summary)
-           {
-             printf_filtered ("%s ", transp -> name);
-           }
-         else
-           {
-             printf_filtered ("\t%-16s %s.\n", transp -> name, transp -> desc);
-           }
+         print_sys_errmsg (pip->pathname, errno);
+         error ("PIOCGFAULT failed");
        }
+#endif
+
+      printf_filtered ("Current traced hardware fault set:\n\n");
+      printf_filtered ("\t%-12s %-8s\n", "Fault", "Trace");
+
+      for (transp = faults_table; transp->name != NULL; transp++)
+       {
+         QUIT;
+         printf_filtered ("\t%-12s ", transp->name);
+#ifdef UNIXWARE
+         printf_filtered ("%-8s", prismember (&pip->prstatus.pr_flttrace, transp->value)
+                          ? "on" : "off");
+#else
+         printf_filtered ("%-8s", prismember (&pip->fltset.fltset, transp->value)
+                          ? "on" : "off");
+#endif
+         printf_filtered ("\n");
+       }
+      printf_filtered ("\n");
     }
-  printf_filtered ("\n");
 }
 
 static void
-info_proc_stop (pip, summary)
+info_proc_mappings (pip, summary)
      struct procinfo *pip;
      int summary;
 {
-  struct trans *transp;
-  int why;
-  int what;
-
-  why = pip -> prstatus.pr_why;
-  what = pip -> prstatus.pr_what;
+  int nmap;
+  struct prmap *prmaps;
+  struct prmap *prmap;
+#ifdef PROCFS_USE_READ_WRITE
+  struct stat sbuf;
+#endif
 
-  if (pip -> prstatus.pr_flags & PR_STOPPED)
+  if (!summary)
     {
-      printf_filtered ("%-32s", "Reason for stopping:");
-      if (!summary)
+      printf_filtered ("Mapped address spaces:\n\n");
+#ifdef BFD_HOST_64_BIT
+      printf_filtered ("  %18s %18s %10s %10s %7s\n",
+#else
+      printf_filtered ("\t%10s %10s %10s %10s %7s\n",
+#endif
+                      "Start Addr",
+                      "  End Addr",
+                      "      Size",
+                      "    Offset",
+                      "Flags");
+#ifdef PROCFS_USE_READ_WRITE
+      if (fstat (pip->map_fd, &sbuf) == 0)
        {
-         printf_filtered ("\n\n");
-       }
-      for (transp = pr_why_table; transp -> name != NULL; transp++)
+         nmap = sbuf.st_size / sizeof (prmap_t);
+         prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
+         if ((lseek (pip->map_fd, 0, SEEK_SET) == 0) &&
+             (read (pip->map_fd, (char *) prmaps,
+                    nmap * sizeof (*prmaps)) == (nmap * sizeof (*prmaps))))
+           {
+             int i = 0;
+             for (prmap = prmaps; i < nmap; ++prmap, ++i)
+#else
+      if (ioctl (pip->ctl_fd, PIOCNMAP, &nmap) == 0)
        {
-         if (why == transp -> value)
+         prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
+         if (ioctl (pip->ctl_fd, PIOCMAP, prmaps) == 0)
            {
-             if (summary)
+             for (prmap = prmaps; prmap->pr_size; ++prmap)
+#endif /* PROCFS_USE_READ_WRITE */
                {
-                 printf_filtered ("%s ", transp -> name);
-               }
-             else
-               {
-                 printf_filtered ("\t%-16s %s.\n",
-                                  transp -> name, transp -> desc);
+#ifdef BFD_HOST_64_BIT
+                 printf_filtered ("  %#18lx %#18lx %#10x %#10x %7s\n",
+#else
+                 printf_filtered ("\t%#10lx %#10lx %#10x %#10x %7s\n",
+#endif
+                                  (unsigned long) prmap->pr_vaddr,
+                                  (unsigned long) prmap->pr_vaddr
+                                  + prmap->pr_size - 1,
+                                  prmap->pr_size,
+                                  prmap->pr_off,
+                                  mappingflags (prmap->pr_mflags));
                }
-             break;
            }
        }
-      
-      /* Use the pr_why field to determine what the pr_what field means, and
-        print more information. */
-      
-      switch (why)
-       {
-         case PR_REQUESTED:
-           /* pr_what is unused for this case */
-           break;
-         case PR_JOBCONTROL:
-         case PR_SIGNALLED:
-           if (summary)
-             {
-               printf_filtered ("%s ", signalname (what));
-             }
-           else
-             {
-               printf_filtered ("\t%-16s %s.\n", signalname (what),
-                                safe_strsignal (what));
-             }
-           break;
-         case PR_SYSENTRY:
-           if (summary)
-             {
-               printf_filtered ("%s ", syscallname (what));
-             }
-           else
-             {
-               printf_filtered ("\t%-16s %s.\n", syscallname (what),
-                                "Entered this system call");
-             }
-           break;
-         case PR_SYSEXIT:
-           if (summary)
-             {
-               printf_filtered ("%s ", syscallname (what));
-             }
-           else
-             {
-               printf_filtered ("\t%-16s %s.\n", syscallname (what),
-                                "Returned from this system call");
-             }
-           break;
-         case PR_FAULTED:
-           if (summary)
-             {
-               printf_filtered ("%s ",
-                                lookupname (faults_table, what, "fault"));
-             }
-           else
-             {
-               printf_filtered ("\t%-16s %s.\n",
-                                lookupname (faults_table, what, "fault"),
-                                lookupdesc (faults_table, what));
-             }
-           break;
-         }
       printf_filtered ("\n");
     }
 }
 
+/*
+
+   LOCAL FUNCTION
+
+   info_proc -- implement the "info proc" command
+
+   SYNOPSIS
+
+   void info_proc (char *args, int from_tty)
+
+   DESCRIPTION
+
+   Implement gdb's "info proc" command by using the /proc interface
+   to print status information about any currently running process.
+
+   Examples of the use of "info proc" are:
+
+   info proc            (prints summary info for current inferior)
+   info proc 123                (prints summary info for process with pid 123)
+   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)
+
+ */
+
 static void
-info_proc_siginfo (pip, summary)
-     struct procinfo *pip;
-     int summary;
+info_proc (args, from_tty)
+     char *args;
+     int from_tty;
 {
-  struct siginfo *sip;
+  int pid;
+  struct procinfo *pip;
+  struct cleanup *old_chain;
+  char **argv;
+  int argsize;
+  int summary = 1;
+  int flags = 0;
+  int syscalls = 0;
+  int signals = 0;
+  int faults = 0;
+  int mappings = 0;
+  int times = 0;
+  int id = 0;
+  int status = 0;
+  int all = 0;
+  int nlwp;
+  int *lwps;
 
-  if ((pip -> prstatus.pr_flags & PR_STOPPED) &&
-      (pip -> prstatus.pr_why == PR_SIGNALLED ||
-       pip -> prstatus.pr_why == PR_FAULTED))
+  old_chain = make_cleanup (null_cleanup, 0);
+
+  /* Default to using the current inferior if no pid specified.  Note
+     that inferior_pid may be 0, hence we set okerr.  */
+
+  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)
     {
-      printf_filtered ("%-32s", "Additional signal/fault info:");
-      sip = &pip -> prstatus.pr_info;
-      if (summary)
+      if ((argv = buildargv (args)) == NULL)
        {
-         printf_filtered ("%s ", signalname (sip -> si_signo));
-         if (sip -> si_errno > 0)
+         nomem (0);
+       }
+      make_cleanup_freeargv (argv);
+
+      while (*argv != NULL)
+       {
+         argsize = strlen (*argv);
+         if (argsize >= 1 && strncmp (*argv, "all", argsize) == 0)
+           {
+             summary = 0;
+             all = 1;
+           }
+         else if (argsize >= 2 && strncmp (*argv, "faults", argsize) == 0)
+           {
+             summary = 0;
+             faults = 1;
+           }
+         else if (argsize >= 2 && strncmp (*argv, "flags", argsize) == 0)
            {
-             printf_filtered ("%s ", errnoname (sip -> si_errno));
+             summary = 0;
+             flags = 1;
            }
-         if (sip -> si_code <= 0)
+         else if (argsize >= 1 && strncmp (*argv, "id", argsize) == 0)
            {
-             printf_filtered ("sent by pid %d, uid %d ", sip -> si_pid,
-                              sip -> si_uid);
+             summary = 0;
+             id = 1;
            }
-         else
+         else if (argsize >= 1 && strncmp (*argv, "mappings", argsize) == 0)
            {
-             printf_filtered ("%s ", sigcodename (sip));
-             if ((sip -> si_signo == SIGILL) ||
-                 (sip -> si_signo == SIGFPE) ||
-                 (sip -> si_signo == SIGSEGV) ||
-                 (sip -> si_signo == SIGBUS))
-               {
-                 printf_filtered ("addr=%#x ", sip -> si_addr);
-               }
-             else if ((sip -> si_signo == SIGCHLD))
-               {
-                 printf_filtered ("child pid %u, status %u ",
-                                  sip -> si_pid,
-                                  sip -> si_status);
-               }
-             else if ((sip -> si_signo == SIGPOLL))
-               {
-                 printf_filtered ("band %u ", sip -> si_band);
-               }
+             summary = 0;
+             mappings = 1;
            }
-       }
-      else
-       {
-         printf_filtered ("\n\n");
-         printf_filtered ("\t%-16s %s.\n", signalname (sip -> si_signo),
-                          safe_strsignal (sip -> si_signo));
-         if (sip -> si_errno > 0)
+         else if (argsize >= 2 && strncmp (*argv, "signals", argsize) == 0)
            {
-             printf_filtered ("\t%-16s %s.\n",
-                              errnoname (sip -> si_errno),
-                              safe_strerror (sip -> si_errno));
+             summary = 0;
+             signals = 1;
            }
-         if (sip -> si_code <= 0)
+         else if (argsize >= 2 && strncmp (*argv, "status", argsize) == 0)
            {
-             printf_filtered ("\t%-16u %s\n", sip -> si_pid,
-                              "PID of process sending signal");
-             printf_filtered ("\t%-16u %s\n", sip -> si_uid,
-                              "UID of process sending signal");
+             summary = 0;
+             status = 1;
            }
-         else
+         else if (argsize >= 2 && strncmp (*argv, "syscalls", argsize) == 0)
            {
-             printf_filtered ("\t%-16s %s.\n", sigcodename (sip),
-                              sigcodedesc (sip));
-             if ((sip -> si_signo == SIGILL) ||
-                 (sip -> si_signo == SIGFPE))
-               {
-                 printf_filtered ("\t%-16#x %s.\n", sip -> si_addr,
-                                  "Address of faulting instruction");
-               }
-             else if ((sip -> si_signo == SIGSEGV) ||
-                      (sip -> si_signo == SIGBUS))
-               {
-                 printf_filtered ("\t%-16#x %s.\n", sip -> si_addr,
-                                  "Address of faulting memory reference");
-               }
-             else if ((sip -> si_signo == SIGCHLD))
-               {
-                 printf_filtered ("\t%-16u %s.\n", sip -> si_pid,
-                                  "Child process ID");
-                 printf_filtered ("\t%-16u %s.\n", sip -> si_status,
-                                  "Child process exit value or signal");
-               }
-             else if ((sip -> si_signo == SIGPOLL))
+             summary = 0;
+             syscalls = 1;
+           }
+         else if (argsize >= 1 && strncmp (*argv, "times", argsize) == 0)
+           {
+             summary = 0;
+             times = 1;
+           }
+         else if ((pid = atoi (*argv)) > 0)
+           {
+             pip = (struct procinfo *) xmalloc (sizeof (struct procinfo));
+             memset (pip, 0, sizeof (*pip));
+
+             pip->pid = pid;
+             if (!open_proc_file (pid, pip, O_RDONLY, 0))
                {
-                 printf_filtered ("\t%-16u %s.\n", sip -> si_band,
-                                  "Band event for POLL_{IN,OUT,MSG}");
+                 perror_with_name (pip->pathname);
+                 /* NOTREACHED */
                }
+             pid = pip->pid;
+             make_cleanup_close_proc_file (pip);
            }
+         else if (**argv != '\000')
+           {
+             error ("Unrecognized or ambiguous keyword `%s'.", *argv);
+           }
+         argv++;
        }
-      printf_filtered ("\n");
     }
-}
 
-static void
-info_proc_syscalls (pip, summary)
-     struct procinfo *pip;
-     int summary;
-{
-  int syscallnum;
+  /* If we don't have a valid open process at this point, then we have no
+     inferior or didn't specify a specific pid. */
 
-  if (!summary)
+  if (!pip)
+    {
+      error ("\
+No process.  Start debugging a program or specify an explicit process ID.");
+    }
+
+  if (!procfs_read_status (pip))
+    {
+      print_sys_errmsg (pip->pathname, errno);
+      error ("procfs_read_status failed");
+    }
+
+#ifndef PROCFS_USE_READ_WRITE
+#ifdef PIOCLWPIDS
+  nlwp = pip->prstatus.pr_nlwp;
+  lwps = alloca ((2 * nlwp + 2) * sizeof (*lwps));
+
+  if (ioctl (pip->ctl_fd, PIOCLWPIDS, lwps))
+    {
+      print_sys_errmsg (pip->pathname, errno);
+      error ("PIOCLWPIDS failed");
+    }
+#else /* PIOCLWPIDS */
+  nlwp = 1;
+  lwps = alloca ((2 * nlwp + 2) * sizeof *lwps);
+  lwps[0] = 0;
+#endif /* PIOCLWPIDS */
+
+  for (; nlwp > 0; nlwp--, lwps++)
     {
+      pip = find_procinfo ((*lwps << 16) | pid, 1);
 
-#if 0  /* FIXME:  Needs to use gdb-wide configured info about system calls. */
-      if (pip -> prstatus.pr_flags & PR_ASLEEP)
+      if (!pip)
        {
-         int syscallnum = pip -> prstatus.pr_reg[R_D0];
-         if (summary)
-           {
-             printf_filtered ("%-32s", "Sleeping in system call:");
-             printf_filtered ("%s", syscallname (syscallnum));
-           }
-         else
+         pip = (struct procinfo *) xmalloc (sizeof (struct procinfo));
+         memset (pip, 0, sizeof (*pip));
+         if (!open_proc_file ((*lwps << 16) | pid, pip, O_RDONLY, 0))
+           continue;
+
+         make_cleanup_close_proc_file (pip);
+
+         if (!procfs_read_status (pip))
            {
-             printf_filtered ("Sleeping in system call '%s'.\n",
-                              syscallname (syscallnum));
+             print_sys_errmsg (pip->pathname, errno);
+             error ("procfs_read_status failed");
            }
        }
-#endif
 
-      if (ioctl (pip -> fd, PIOCGENTRY, &pip -> entryset) < 0)
+#endif /* PROCFS_USE_READ_WRITE */
+
+      /* Print verbose information of the requested type(s), or just a summary
+         of the information for all types. */
+
+      printf_filtered ("\nInformation for %s.%d:\n\n", pip->pathname, *lwps);
+      if (summary || all || flags)
        {
-         print_sys_errmsg (pip -> pathname, errno);
-         error ("PIOCGENTRY failed");
+         info_proc_flags (pip, summary);
        }
-      
-      if (ioctl (pip -> fd, PIOCGEXIT, &pip -> exitset) < 0)
+      if (summary || all)
        {
-         print_sys_errmsg (pip -> pathname, errno);
-         error ("PIOCGEXIT failed");
+         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");
        }
-      
-      printf_filtered ("System call tracing information:\n\n");
-      
-      printf_filtered ("\t%-12s %-8s %-8s\n",
-                      "System call",
-                      "Entry",
-                      "Exit");
-      for (syscallnum = 0; syscallnum < MAX_SYSCALLS; syscallnum++)
+      if (summary || all || signals || faults)
        {
-         QUIT;
-         if (syscall_table[syscallnum] != NULL)
-           {
-             printf_filtered ("\t%-12s ", syscall_table[syscallnum]);
-             printf_filtered ("%-8s ",
-                              prismember (&pip -> entryset, syscallnum)
-                              ? "on" : "off");
-             printf_filtered ("%-8s ",
-                              prismember (&pip -> exitset, syscallnum)
-                              ? "on" : "off");
-             printf_filtered ("\n");
-           }
-         }
+         info_proc_siginfo (pip, summary);
+       }
+      if (summary || all || syscalls)
+       {
+         info_proc_syscalls (pip, summary);
+       }
+      if (summary || all || mappings)
+       {
+         info_proc_mappings (pip, summary);
+       }
+      if (summary || all || signals)
+       {
+         info_proc_signals (pip, summary);
+       }
+      if (summary || all || faults)
+       {
+         info_proc_faults (pip, summary);
+       }
       printf_filtered ("\n");
+
+      /* All done, deal with closing any temporary process info structure,
+         freeing temporary memory , etc. */
+
+      do_cleanups (old_chain);
+#ifndef PROCFS_USE_READ_WRITE
     }
+#endif
 }
 
-static char *
-signalname (signo)
-     int signo;
+/*
+
+   LOCAL FUNCTION
+
+   modify_inherit_on_fork_flag - Change the inherit-on-fork flag
+
+   SYNOPSIS
+
+   void modify_inherit_on_fork_flag (fd, flag)
+
+   DESCRIPTION
+
+   Call this routine to modify the inherit-on-fork flag.  This routine is
+   just a nice wrapper to hide the #ifdefs needed by various systems to
+   control this flag.
+
+ */
+
+static void
+modify_inherit_on_fork_flag (fd, flag)
+     int fd;
+     int flag;
 {
-  char *name;
-  static char locbuf[32];
+#if defined (PIOCSET) || defined (PCSET)
+  long pr_flags;
+#endif
+  int retval = 0;
+#ifdef PROCFS_USE_READ_WRITE
+  struct proc_ctl pctl;
+#endif
 
-  name = strsigno (signo);
-  if (name == NULL)
+#if defined (PIOCSET) || defined (PCSET)       /* New method */
+  pr_flags = PR_FORK;
+  if (flag)
     {
-      sprintf (locbuf, "Signal %d", signo);
+#ifdef PROCFS_USE_READ_WRITE
+      pctl.cmd = PCSET;
+      pctl.data = PR_FORK;
+      if (write (fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
+         retval = -1;
+#else
+      retval = ioctl (fd, PIOCSET, &pr_flags);
+#endif
     }
   else
     {
-      sprintf (locbuf, "%s (%d)", name, signo);
+#ifdef PROCFS_USE_READ_WRITE
+      pctl.cmd = PCRESET;
+      pctl.data = PR_FORK;
+      if (write (fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
+         retval = -1;
+#else
+      retval = ioctl (fd, PIOCRESET, &pr_flags);
+#endif
     }
-  return (locbuf);
+
+#else
+#ifdef PIOCSFORK               /* Original method */
+  if (flag)
+    {
+      retval = ioctl (fd, PIOCSFORK, NULL);
+    }
+  else
+    {
+      retval = ioctl (fd, PIOCRFORK, NULL);
+    }
+#else
+  Neither PR_FORK nor PIOCSFORK exist ! !!
+#endif
+#endif
+
+  if (!retval)
+      return;
+
+  print_sys_errmsg ("modify_inherit_on_fork_flag", errno);
+  error ("PIOCSFORK or PR_FORK modification failed");
 }
 
-static char *
-errnoname (errnum)
-     int errnum;
+/*
+
+   LOCAL FUNCTION
+
+   modify_run_on_last_close_flag - Change the run-on-last-close flag
+
+   SYNOPSIS
+
+   void modify_run_on_last_close_flag (fd, flag)
+
+   DESCRIPTION
+
+   Call this routine to modify the run-on-last-close flag.  This routine
+   is just a nice wrapper to hide the #ifdefs needed by various systems to
+   control this flag.
+
+ */
+
+static void
+modify_run_on_last_close_flag (fd, flag)
+     int fd;
+     int flag;
 {
-  char *name;
-  static char locbuf[32];
+#if defined (PIOCSET) || defined (PCSET)
+  long pr_flags;
+#endif
+  int retval = 0;
+#ifdef PROCFS_USE_READ_WRITE
+  struct proc_ctl pctl;
+#endif
 
-  name = strerrno (errnum);
-  if (name == NULL)
+#if defined (PIOCSET) || defined (PCSET)       /* New method */
+  pr_flags = PR_RLC;
+  if (flag)
     {
-      sprintf (locbuf, "Errno %d", errnum);
+#ifdef PROCFS_USE_READ_WRITE
+      pctl.cmd = PCSET;
+      pctl.data = PR_RLC;
+      if (write (fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
+         retval = -1;
+#else
+      retval = ioctl (fd, PIOCSET, &pr_flags);
+#endif
     }
   else
     {
-      sprintf (locbuf, "%s (%d)", name, errnum);
+#ifdef PROCFS_USE_READ_WRITE
+      pctl.cmd = PCRESET;
+      pctl.data = PR_RLC;
+      if (write (fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
+         retval = -1;
+#else
+      retval = ioctl (fd, PIOCRESET, &pr_flags);
+#endif
     }
-  return (locbuf);
+
+#else
+#ifdef PIOCSRLC                        /* Original method */
+  if (flag)
+    retval = ioctl (fd, PIOCSRLC, NULL);
+  else
+    retval = ioctl (fd, PIOCRRLC, NULL);
+#else
+  Neither PR_RLC nor PIOCSRLC exist ! !!
+#endif
+#endif
+
+  if (!retval)
+      return;
+
+  print_sys_errmsg ("modify_run_on_last_close_flag", errno);
+  error ("PIOCSRLC or PR_RLC modification failed");
 }
 
+/*
+
+   LOCAL FUNCTION
+
+   procfs_clear_syscall_trap -- Deletes the trap for the specified system call.
+
+   SYNOPSIS
+
+   void procfs_clear_syscall_trap (struct procinfo *, int syscall_num, int errok)
+
+   DESCRIPTION
+
+   This function function disables traps for the specified system call.
+   errok is non-zero if errors should be ignored.
+ */
+
 static void
-info_proc_signals (pip, summary)
-     struct procinfo *pip;
-     int summary;
+procfs_clear_syscall_trap (pi, syscall_num, errok)
+     struct procinfo *pi;
+     int syscall_num;
+     int errok;
 {
-  int signo;
+  sysset_t sysset;
+  int goterr, i;
 
-  if (!summary)
+#ifndef UNIXWARE
+  goterr = ioctl (pi->ctl_fd, PIOCGENTRY, &sysset) < 0;
+
+  if (goterr && !errok)
     {
-      if (ioctl (pip -> fd, PIOCGTRACE, &pip -> trace) < 0)
+      print_sys_errmsg (pi->pathname, errno);
+      error ("PIOCGENTRY failed");
+    }
+
+  if (!goterr)
+    {
+      prdelset (&sysset, syscall_num);
+
+      if ((ioctl (pi->ctl_fd, PIOCSENTRY, &sysset) < 0) && !errok)
        {
-         print_sys_errmsg (pip -> pathname, errno);
-         error ("PIOCGTRACE failed");
+         print_sys_errmsg (pi->pathname, errno);
+         error ("PIOCSENTRY failed");
        }
-      
-      printf_filtered ("Disposition of signals:\n\n");
-      printf_filtered ("\t%-15s %-8s %-8s %-8s  %s\n\n",
-                      "Signal", "Trace", "Hold", "Pending", "Description");
-      for (signo = 0; signo < NSIG; signo++)
+    }
+
+  goterr = ioctl (pi->ctl_fd, PIOCGEXIT, &sysset) < 0;
+
+  if (goterr && !errok)
+    {
+      procfs_clear_syscall_trap (pi, syscall_num, 1);
+      print_sys_errmsg (pi->pathname, errno);
+      error ("PIOCGEXIT failed");
+    }
+
+  if (!goterr)
+    {
+      praddset (&sysset, syscall_num);
+
+      if ((ioctl (pi->ctl_fd, PIOCSEXIT, &sysset) < 0) && !errok)
        {
-         QUIT;
-         printf_filtered ("\t%-15s ", signalname (signo));
-         printf_filtered ("%-8s ",
-                          prismember (&pip -> trace, signo)
-                          ? "on" : "off");
-         printf_filtered ("%-8s ",
-                          prismember (&pip -> prstatus.pr_sighold, signo)
-                          ? "on" : "off");
-         printf_filtered ("%-8s ",
-                          prismember (&pip -> prstatus.pr_sigpend, signo)
-                          ? "yes" : "no");
-         printf_filtered (" %s\n", safe_strsignal (signo));
+         procfs_clear_syscall_trap (pi, syscall_num, 1);
+         print_sys_errmsg (pi->pathname, errno);
+         error ("PIOCSEXIT failed");
        }
-      printf_filtered ("\n");
     }
+#endif
+
+  if (!pi->syscall_handlers)
+    {
+      if (!errok)
+       error ("procfs_clear_syscall_trap:  syscall_handlers is empty");
+      return;
+    }
+
+  /* Remove handler func from the handler list */
+
+  for (i = 0; i < pi->num_syscall_handlers; i++)
+    if (pi->syscall_handlers[i].syscall_num == syscall_num)
+      {
+       if (i + 1 != pi->num_syscall_handlers)
+         {                     /* Not the last entry.
+                                  Move subsequent entries fwd. */
+           memcpy (&pi->syscall_handlers[i], &pi->syscall_handlers[i + 1],
+                   (pi->num_syscall_handlers - i - 1)
+                   * sizeof (struct procfs_syscall_handler));
+         }
+
+       pi->syscall_handlers = xrealloc (pi->syscall_handlers,
+                                        (pi->num_syscall_handlers - 1)
+                                 * sizeof (struct procfs_syscall_handler));
+       pi->num_syscall_handlers--;
+       return;
+      }
+
+  if (!errok)
+    error ("procfs_clear_syscall_trap:  Couldn't find handler for sys call %d",
+          syscall_num);
 }
 
+/*
+
+   LOCAL FUNCTION
+
+   procfs_set_syscall_trap -- arrange for a function to be called when the
+   child executes the specified system call.
+
+   SYNOPSIS
+
+   void procfs_set_syscall_trap (struct procinfo *, int syscall_num, int flags,
+   syscall_func_t *function)
+
+   DESCRIPTION
+
+   This function sets up an entry and/or exit trap for the specified system
+   call.  When the child executes the specified system call, your function
+   will be      called with the call #, a flag that indicates entry or exit, and
+   pointers to rtnval and statval (which are used by procfs_wait).  The
+   function should return non-zero if something interesting happened, zero
+   otherwise.
+ */
+
 static void
-info_proc_faults (pip, summary)
-     struct procinfo *pip;
-     int summary;
+procfs_set_syscall_trap (pi, syscall_num, flags, func)
+     struct procinfo *pi;
+     int syscall_num;
+     int flags;
+     syscall_func_t *func;
 {
-  struct trans *transp;
+  sysset_t sysset;
 
-  if (!summary)
+#ifndef UNIXWARE
+  if (flags & PROCFS_SYSCALL_ENTRY)
     {
-      if (ioctl (pip -> fd, PIOCGFAULT, &pip -> fltset) < 0)
+      if (ioctl (pi->ctl_fd, PIOCGENTRY, &sysset) < 0)
        {
-         print_sys_errmsg (pip -> pathname, errno);
-         error ("PIOCGFAULT failed");
+         print_sys_errmsg (pi->pathname, errno);
+         error ("PIOCGENTRY failed");
        }
-      
-      printf_filtered ("Current traced hardware fault set:\n\n");
-      printf_filtered ("\t%-12s %-8s\n", "Fault", "Trace");
 
-      for (transp = faults_table; transp -> name != NULL; transp++)
+      praddset (&sysset, syscall_num);
+
+      if (ioctl (pi->ctl_fd, PIOCSENTRY, &sysset) < 0)
        {
-         QUIT;
-         printf_filtered ("\t%-12s ", transp -> name);
-         printf_filtered ("%-8s", prismember (&pip -> fltset, transp -> value)
-                          ? "on" : "off");
-         printf_filtered ("\n");
+         print_sys_errmsg (pi->pathname, errno);
+         error ("PIOCSENTRY failed");
        }
-      printf_filtered ("\n");
     }
-}
-
-static void
-info_proc_mappings (pip, summary)
-     struct procinfo *pip;
-     int summary;
-{
-  int nmap;
-  struct prmap *prmaps;
-  struct prmap *prmap;
 
-  if (!summary)
+  if (flags & PROCFS_SYSCALL_EXIT)
     {
-      printf_filtered ("Mapped address spaces:\n\n");
-      printf_filtered ("\t%10s %10s %10s %10s %7s\n",
-                      "Start Addr",
-                      "  End Addr",
-                      "      Size",
-                      "    Offset",
-                      "Flags");
-      if (ioctl (pip -> fd, PIOCNMAP, &nmap) == 0)
+      if (ioctl (pi->ctl_fd, PIOCGEXIT, &sysset) < 0)
        {
-         prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
-         if (ioctl (pip -> fd, PIOCMAP, prmaps) == 0)
-           {
-             for (prmap = prmaps; prmap -> pr_size; ++prmap)
-               {
-                 printf_filtered ("\t%#10x %#10x %#10x %#10x %7s\n",
-                                  prmap -> pr_vaddr,
-                                  prmap -> pr_vaddr + prmap -> pr_size - 1,
-                                  prmap -> pr_size,
-                                  prmap -> pr_off,
-                                  mappingflags (prmap -> pr_mflags));
-               }
-           }
+         procfs_clear_syscall_trap (pi, syscall_num, 1);
+         print_sys_errmsg (pi->pathname, errno);
+         error ("PIOCGEXIT failed");
        }
-      printf_filtered ("\n");
+
+      praddset (&sysset, syscall_num);
+
+      if (ioctl (pi->ctl_fd, PIOCSEXIT, &sysset) < 0)
+       {
+         procfs_clear_syscall_trap (pi, syscall_num, 1);
+         print_sys_errmsg (pi->pathname, errno);
+         error ("PIOCSEXIT failed");
+       }
+    }
+#endif
+
+  if (!pi->syscall_handlers)
+    {
+      pi->syscall_handlers = xmalloc (sizeof (struct procfs_syscall_handler));
+      pi->syscall_handlers[0].syscall_num = syscall_num;
+      pi->syscall_handlers[0].func = func;
+      pi->num_syscall_handlers = 1;
+    }
+  else
+    {
+      int i;
+
+      for (i = 0; i < pi->num_syscall_handlers; i++)
+       if (pi->syscall_handlers[i].syscall_num == syscall_num)
+         {
+           pi->syscall_handlers[i].func = func;
+           return;
+         }
+
+      pi->syscall_handlers = xrealloc (pi->syscall_handlers, (i + 1)
+                                 * sizeof (struct procfs_syscall_handler));
+      pi->syscall_handlers[i].syscall_num = syscall_num;
+      pi->syscall_handlers[i].func = func;
+      pi->num_syscall_handlers++;
     }
 }
 
-/*
+#ifdef SYS_lwp_create
 
-LOCAL FUNCTION
+/*
 
-       info_proc -- implement the "info proc" command
+   LOCAL FUNCTION
 
-SYNOPSIS
+   procfs_lwp_creation_handler - handle exit from the _lwp_create syscall
 
-       void info_proc (char *args, int from_tty)
+   SYNOPSIS
 
-DESCRIPTION
+   int procfs_lwp_creation_handler (pi, syscall_num, why, rtnvalp, statvalp)
 
-       Implement gdb's "info proc" command by using the /proc interface
-       to print status information about any currently running process.
+   DESCRIPTION
 
-       Examples of the use of "info proc" are:
+   This routine is called both when an inferior process and it's new lwp
+   are about to finish a _lwp_create() system call.  This is the system
+   call that Solaris uses to create a lightweight process.  When the
+   target process gets this event, we can look at sysarg[2] to find the
+   new childs lwp ID, and create a procinfo struct from that.  After that,
+   we pretend that we got a SIGTRAP, and return non-zero to tell
+   procfs_wait to wake up.  Subsequently, wait_for_inferior gets woken up,
+   sees the new process and continues it.
 
-       info proc               (prints summary info for current inferior)
-       info proc 123           (prints summary info for process with pid 123)
-       info proc mappings      (prints address mappings)
-       info proc times         (prints process/children times)
-       info proc id            (prints pid, ppid, gid, sid, etc)
-       info proc status        (prints general process state info)
-       info proc signals       (prints info about signal handling)
-       info proc all           (prints all info)
+   When we see the child exiting from lwp_create, we just contine it,
+   since everything was handled when the parent trapped.
 
+   NOTES
+   In effect, we are only paying attention to the parent's completion of
+   the lwp_create syscall.  If we only paid attention to the child
+   instead, then we wouldn't detect the creation of a suspended thread.
  */
 
-static void
-info_proc (args, from_tty)
-     char *args;
-     int from_tty;
+static int
+procfs_lwp_creation_handler (pi, syscall_num, why, rtnvalp, statvalp)
+     struct procinfo *pi;
+     int syscall_num;
+     int why;
+     int *rtnvalp;
+     int *statvalp;
 {
-  int pid;
-  struct procinfo pii;
-  struct procinfo *pip;
-  struct cleanup *old_chain;
-  char **argv;
-  int argsize;
-  int summary = 1;
-  int flags = 0;
-  int syscalls = 0;
-  int signals = 0;
-  int faults = 0;
-  int mappings = 0;
-  int times = 0;
-  int id = 0;
-  int status = 0;
-  int all = 0;
+  int lwp_id;
+  struct procinfo *childpi;
+#ifdef UNIXWARE
+  struct proc_ctl pctl;
+#endif
 
-  old_chain = make_cleanup (null_cleanup, 0);
+  /* 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
+     system of the new arrival.  */
 
-  /* Default to using the current inferior if no pid specified */
+  /* If lwp_create failed, then nothing interesting happened.  Continue the
+     process and go back to sleep. */
 
-  pip = &pi;
+#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 (args != NULL)
-    {
-      if ((argv = buildargv (args)) == NULL)
-       {
-         nomem (0);
-       }
-      make_cleanup (freeargv, (char *) argv);
+      if (write (pi->ctl_fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
+         perror_with_name (pi->pathname);
 
-      while (*argv != NULL)
-       {
-         argsize = strlen (*argv);
-         if (argsize >= 1 && strncmp (*argv, "all", argsize) == 0)
-           {
-             summary = 0;
-             all = 1;
-           }
-         else if (argsize >= 2 && strncmp (*argv, "faults", argsize) == 0)
-           {
-             summary = 0;
-             faults = 1;
-           }
-         else if (argsize >= 2 && strncmp (*argv, "flags", argsize) == 0)
-           {
-             summary = 0;
-             flags = 1;
-           }
-         else if (argsize >= 1 && strncmp (*argv, "id", argsize) == 0)
-           {
-             summary = 0;
-             id = 1;
-           }
-         else if (argsize >= 1 && strncmp (*argv, "mappings", argsize) == 0)
-           {
-             summary = 0;
-             mappings = 1;
-           }
-         else if (argsize >= 2 && strncmp (*argv, "signals", argsize) == 0)
-           {
-             summary = 0;
-             signals = 1;
-           }
-         else if (argsize >= 2 && strncmp (*argv, "status", argsize) == 0)
-           {
-             summary = 0;
-             status = 1;
-           }
-         else if (argsize >= 2 && strncmp (*argv, "syscalls", argsize) == 0)
-           {
-             summary = 0;
-             syscalls = 1;
-           }
-         else if (argsize >= 1 && strncmp (*argv, "times", argsize) == 0)
-           {
-             summary = 0;
-             times = 1;
-           }
-         else if ((pii.pid = atoi (*argv)) > 0)
-           {
-             pid = pii.pid;
-             pip = &pii;
-             (void) memset (&pii, 0, sizeof (pii));
-             if (!open_proc_file (pid, pip))
-               {
-                 perror_with_name (pip -> pathname);
-                 /* NOTREACHED */
-               }
-             make_cleanup (close_proc_file, pip);
-           }
-         else if (**argv != '\000')
-           {
-             error ("Unrecognized or ambiguous keyword `%s'.", *argv);
-           }
-         argv++;
-       }
+      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;
 
-  /* If we don't have a valid open process at this point, then we have no
-     inferior or didn't specify a specific pid. */
+      if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
+       perror_with_name (pi->pathname);
 
-  if (!pip -> valid)
-    {
-      error ("No process.  Run an inferior or specify an explicit pid.");
+      return 0;
     }
-  if (ioctl (pip -> fd, PIOCSTATUS, &(pip -> prstatus)) < 0)
-    {
-      print_sys_errmsg (pip -> pathname, errno);
-      error ("PIOCSTATUS failed");
+#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 */
+
+      return 0;
     }
 
-  /* Print verbose information of the requested type(s), or just a summary
-     of the information for all types. */
+  /* 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. */
+  lwp_id = read_memory_integer (
+                     THE_PR_LWP (pi->prstatus).pr_sysarg[2], sizeof (int));
+
+  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 handlers for
+     that child.  */
+
+  procfs_set_inferior_syscall_traps (childpi);
+  add_thread (lwp_id);
+  printf_filtered ("[New %s]\n", target_pid_to_str (lwp_id));
+
+  /* Continue the parent */
+#ifdef UNIXWARE
+  pctl.cmd = PCRUN;
+  pctl.data = PRCFAULT;
+
+  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);
 
-  printf_filtered ("\nInformation for %s:\n\n", pip -> pathname);
-  if (summary || all || flags)
+  /* 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.  */
+
+  if (THE_PR_LWP (childpi->prstatus).pr_why == PR_SUSPENDED)
+    childpi->new_child = 1;    /* Flag this as an unseen child process */
+  else
     {
-      info_proc_flags (pip, summary);
+      /* 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);
     }
-  if (summary || all)
+  return 0;
+}
+#endif /* SYS_lwp_create */
+
+/* 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;
+{
+  char *shell_file = getenv ("SHELL");
+  char *tryname;
+  if (shell_file != NULL && strchr (shell_file, '/') == NULL)
     {
-      info_proc_stop (pip, summary);
+
+      /* We will be looking down the PATH to find shell_file.  If we
+         just do this the normal way (via execlp, which operates by
+         attempting an exec for each element of the PATH until it
+         finds one which succeeds), then there will be an exec for
+         each failed attempt, each of which will cause a PR_SYSEXIT
+         stop, and we won't know how to distinguish the PR_SYSEXIT's
+         for these failed execs with the ones for successful execs
+         (whether the exec has succeeded is stored at that time in the
+         carry bit or some such architecture-specific and
+         non-ABI-specified place).
+
+         So I can't think of anything better than to search the PATH
+         now.  This has several disadvantages: (1) There is a race
+         condition; if we find a file now and it is deleted before we
+         exec it, we lose, even if the deletion leaves a valid file
+         further down in the PATH, (2) there is no way to know exactly
+         what an executable (in the sense of "capable of being
+         exec'd") file is.  Using access() loses because it may lose
+         if the caller is the superuser; failing to use it loses if
+         there are ACLs or some such.  */
+
+      char *p;
+      char *p1;
+      /* FIXME-maybe: might want "set path" command so user can change what
+         path is used from within GDB.  */
+      char *path = getenv ("PATH");
+      int len;
+      struct stat statbuf;
+
+      if (path == NULL)
+       path = "/bin:/usr/bin";
+
+      tryname = alloca (strlen (path) + strlen (shell_file) + 2);
+      for (p = path; p != NULL; p = p1 ? p1 + 1 : NULL)
+       {
+         p1 = strchr (p, ':');
+         if (p1 != NULL)
+           len = p1 - p;
+         else
+           len = strlen (p);
+         strncpy (tryname, p, len);
+         tryname[len] = '\0';
+         strcat (tryname, "/");
+         strcat (tryname, shell_file);
+         if (access (tryname, X_OK) < 0)
+           continue;
+         if (stat (tryname, &statbuf) < 0)
+           continue;
+         if (!S_ISREG (statbuf.st_mode))
+           /* We certainly need to reject directories.  I'm not quite
+              as sure about FIFOs, sockets, etc., but I kind of doubt
+              that people want to exec() these things.  */
+           continue;
+         break;
+       }
+      if (p == NULL)
+       /* Not found.  This must be an error rather than merely passing
+          the file to execlp(), because execlp() would try all the
+          exec()s, causing GDB to get confused.  */
+       error ("Can't find shell %s in PATH", shell_file);
+
+      shell_file = tryname;
     }
-  if (summary || all || signals || faults)
+
+  fork_inferior (exec_file, allargs, env,
+                proc_set_exec_trap, procfs_init_inferior, NULL, shell_file);
+
+  /* We are at the first instruction we care about.  */
+  /* Pedal to the metal... */
+
+  proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
+}
+
+/* Clean up after the inferior dies.  */
+
+static void
+procfs_mourn_inferior ()
+{
+  struct procinfo *pi;
+  struct procinfo *next_pi;
+
+  for (pi = procinfo_list; pi; pi = next_pi)
     {
-      info_proc_siginfo (pip, summary);
+      next_pi = pi->next;
+      unconditionally_kill_inferior (pi);
     }
-  if (summary || all || syscalls)
+
+  unpush_target (&procfs_ops);
+  generic_mourn_inferior ();
+}
+
+
+/* Mark our target-struct as eligible for stray "run" and "attach" commands.  */
+static int
+procfs_can_run ()
+{
+  /* This variable is controlled by modules that sit atop procfs that may layer
+     their own process structure atop that provided here.  sol-thread.c does
+     this because of the Solaris two-level thread model.  */
+
+  return !procfs_suppress_run;
+}
+#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
+#ifndef UNIXWARE
+\f
+/* Insert a watchpoint */
+int
+procfs_set_watchpoint (pid, addr, len, rw)
+     int pid;
+     CORE_ADDR addr;
+     int len;
+     int rw;
+{
+  struct procinfo *pi;
+  prwatch_t wpt;
+
+  pi = find_procinfo (pid == -1 ? inferior_pid : pid, 0);
+  wpt.pr_vaddr = (caddr_t) addr;
+  wpt.pr_size = len;
+  wpt.pr_wflags = ((rw & 1) ? MA_READ : 0) | ((rw & 2) ? MA_WRITE : 0);
+  if (ioctl (pi->ctl_fd, PIOCSWATCH, &wpt) < 0)
     {
-      info_proc_syscalls (pip, summary);
+      if (errno == E2BIG)
+       return -1;
+      /* Currently it sometimes happens that the same watchpoint gets
+         deleted twice - don't die in this case (FIXME please) */
+      if (errno == ESRCH && len == 0)
+       return 0;
+      print_sys_errmsg (pi->pathname, errno);
+      error ("PIOCSWATCH failed");
     }
-  if (summary || all || mappings)
+  return 0;
+}
+
+int
+procfs_stopped_by_watchpoint (pid)
+     int pid;
+{
+  struct procinfo *pi;
+  short what;
+  short why;
+
+  pi = find_procinfo (pid == -1 ? inferior_pid : pid, 0);
+  if (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
     {
-      info_proc_mappings (pip, summary);
+      why = pi->prstatus.pr_why;
+      what = pi->prstatus.pr_what;
+      if (why == PR_FAULTED
+#if defined (FLTWATCH) && defined (FLTKWATCH)
+         && (what == FLTWATCH || what == FLTKWATCH)
+#else
+#ifdef FLTWATCH
+         && (what == FLTWATCH)
+#endif
+#ifdef FLTKWATCH
+         && (what == FLTKWATCH)
+#endif
+#endif
+       )
+       return what;
     }
-  if (summary || all || signals)
+  return 0;
+}
+#endif /* !UNIXWARE */
+#endif /* TARGET_HAS_HARDWARE_WATCHPOINTS */
+
+/* Why is this necessary?  Shouldn't dead threads just be removed from the
+   thread database?  */
+
+static int
+procfs_thread_alive (pid)
+     int pid;
+{
+  struct procinfo *pi, *next_pi;
+
+  for (pi = procinfo_list; pi; pi = next_pi)
     {
-      info_proc_signals (pip, summary);
+      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;
+           }
+       }
     }
-  if (summary || all || faults)
+  return 0;
+}
+
+int
+procfs_first_available ()
+{
+  struct procinfo *pi;
+
+  for (pi = procinfo_list; pi; pi = pi->next)
     {
-      info_proc_faults (pip, summary);
+      if (procfs_read_status (pi))
+       return pi->pid;
     }
-  printf_filtered ("\n");
+  return -1;
+}
 
-  /* All done, deal with closing any temporary process info structure,
-     freeing temporary memory , etc. */
+int
+procfs_get_pid_fd (pid)
+     int pid;
+{
+  struct procinfo *pi = find_procinfo (pid, 1);
+
+  if (pi == NULL)
+    return -1;
 
-  do_cleanups (old_chain);
+  return pi->ctl_fd;
 }
 
-/*
+/* Send a SIGINT to the process group.  This acts just like the user typed a
+   ^C on the controlling terminal.
+
+   XXX - This may not be correct for all systems.  Some may want to use
+   killpg() instead of kill (-pgrp). */
+
+static void
+procfs_stop ()
+{
+  extern pid_t inferior_process_group;
+
+  kill (-inferior_process_group, SIGINT);
+}
+\f
+/* Convert a pid to printable form. */
 
-GLOBAL FUNCTION
+#ifdef TIDGET
+char *
+procfs_pid_to_str (pid)
+     int pid;
+{
+  static char buf[100];
 
-       _initialize_proc_fs -- initialize the process file system stuff
+  sprintf (buf, "Kernel thread %d", TIDGET (pid));
 
-SYNOPSIS
+  return buf;
+}
+#endif /* TIDGET */
+\f
 
-       void _initialize_proc_fs (void)
+static void
+init_procfs_ops ()
+{
+  procfs_ops.to_shortname = "procfs";
+  procfs_ops.to_longname = "Unix /proc child process";
+  procfs_ops.to_doc = "Unix /proc child process (started by the \"run\" command).";
+  procfs_ops.to_open = procfs_open;
+  procfs_ops.to_attach = procfs_attach;
+  procfs_ops.to_detach = procfs_detach;
+  procfs_ops.to_resume = procfs_resume;
+  procfs_ops.to_wait = procfs_wait;
+  procfs_ops.to_fetch_registers = procfs_fetch_registers;
+  procfs_ops.to_store_registers = procfs_store_registers;
+  procfs_ops.to_prepare_to_store = procfs_prepare_to_store;
+  procfs_ops.to_xfer_memory = procfs_xfer_memory;
+  procfs_ops.to_files_info = procfs_files_info;
+  procfs_ops.to_insert_breakpoint = memory_insert_breakpoint;
+  procfs_ops.to_remove_breakpoint = memory_remove_breakpoint;
+  procfs_ops.to_terminal_init = terminal_init_inferior;
+  procfs_ops.to_terminal_inferior = terminal_inferior;
+  procfs_ops.to_terminal_ours_for_output = terminal_ours_for_output;
+  procfs_ops.to_terminal_ours = terminal_ours;
+  procfs_ops.to_terminal_info = child_terminal_info;
+  procfs_ops.to_kill = procfs_kill_inferior;
+  procfs_ops.to_create_inferior = procfs_create_inferior;
+  procfs_ops.to_mourn_inferior = procfs_mourn_inferior;
+  procfs_ops.to_can_run = procfs_can_run;
+  procfs_ops.to_notice_signals = procfs_notice_signals;
+  procfs_ops.to_thread_alive = procfs_thread_alive;
+#ifdef TIDGET
+  procfs_ops.to_pid_to_str = procfs_pid_to_str;
+#endif
+  procfs_ops.to_stop = procfs_stop;
+  procfs_ops.to_stratum = process_stratum;
+  procfs_ops.to_has_all_memory = 1;
+  procfs_ops.to_has_memory = 1;
+  procfs_ops.to_has_stack = 1;
+  procfs_ops.to_has_registers = 1;
+  procfs_ops.to_has_execution = 1;
+  procfs_ops.to_magic = OPS_MAGIC;
+}
 
-DESCRIPTION
+void
+_initialize_procfs ()
+{
+#ifdef HAVE_OPTIONAL_PROC_FS
+  char procname[MAX_PROC_NAME_SIZE];
+  int fd;
 
-       Do required initializations during gdb startup for using the
-       /proc file system interface.
+  /* If we have an optional /proc filesystem (e.g. under OSF/1),
+     don't add procfs support if we cannot access the running
+     GDB via /proc.  */
+  sprintf (procname, STATUS_PROC_NAME_FMT, getpid ());
+  if ((fd = open (procname, O_RDONLY)) < 0)
+    return;
+  close (fd);
+#endif
 
-*/
+  init_procfs_ops ();
+  add_target (&procfs_ops);
 
-static char *proc_desc =
-"Show process status information using /proc entry.\n\
+  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\
 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.100825 seconds and 4 git commands to generate.