+ 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)
+ {
+ wait_fd ();
+ goto scan_again;
+ }
+
+ if (!checkerr
+ && !(THE_PR_LWP(pi->prstatus).pr_flags & (PR_STOPPED | PR_ISTOP)))
+ {
+ 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) != (PIDGET (inferior_pid)))
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ error ("procfs_wait: wait failed, returned %d", rtnval);
+ /* NOTREACHED */
+ }
+ }
+ else
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ error ("PIOCSTATUS or PIOCWSTOP failed.");
+ /* NOTREACHED */
+ }
+ }
+ else if (THE_PR_LWP(pi->prstatus).pr_flags & (PR_STOPPED | PR_ISTOP))
+ {
+#ifdef UNIXWARE
+ rtnval = pi->prstatus.pr_pid;
+#else
+ rtnval = pi->pid;
+#endif
+ 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;
+ break;
+ case PR_JOBCONTROL:
+ statval = (what << 8) | 0177;
+ 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;
+ break;
+ case FLTBPT:
+ case FLTTRACE:
+ statval = (SIGTRAP << 8) | 0177;
+ break;
+ case FLTSTACK:
+ case FLTACCESS:
+ case FLTBOUNDS:
+ statval = (SIGSEGV << 8) | 0177;
+ break;
+ case FLTIOVF:
+ case FLTIZDIV:
+ case FLTFPE:
+ statval = (SIGFPE << 8) | 0177;
+ break;
+ case FLTPAGE: /* Recoverable page fault */
+#endif /* not FAULTED_USE_SIGINFO */
+ default:
+ /* 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;
+ }
+ break;
+ default:
+ error ("PIOCWSTOP, unknown why %d, what %d", why, what);
+ }
+ /* 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",
+ THE_PR_LWP(pi->prstatus).pr_flags);
+ }
+
+ store_waitstatus (ourstatus, statval);
+
+ if (rtnval == -1) /* No more children to wait for */
+ {
+ 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
+
+ set_proc_siginfo - set a process's current signal info
+
+SYNOPSIS
+
+ void set_proc_siginfo (struct procinfo *pip, int signo);
+
+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.
+
+ 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.
+
+ See siginfo(5) for more details.
+*/
+
+static void
+set_proc_siginfo (pip, signo)
+ struct procinfo *pip;
+ int signo;
+{
+ struct siginfo newsiginfo;
+ struct siginfo *sip;
+ struct sigi_ctl sictl;
+
+#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
+
+#ifdef UNIXWARE
+ if (signo == THE_PR_LWP(pip->prstatus).pr_info.si_signo)
+ {
+ 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;
+ struct proc_ctl pctl;
+
+ 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 *) ®isters[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
+ {
+ /* The LWP has apparently terminated. */
+ if (info_verbose)
+ printf_filtered ("LWP %d doesn't respond.\n",
+ (pi->pid >> 16) & 0xffff);
+ close_proc_file (pi);
+ }
+ }
+
+ /* 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)
+ {
+ 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);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ open_proc_file - open a /proc entry for a given process id
+
+SYNOPSIS
+
+ static int open_proc_file (int pid, struct procinfo *pip, int mode)
+
+DESCRIPTION
+
+ Given a process id and a mode, close the existing open /proc
+ entry (if any) and open one for the new process id, in the
+ specified mode. Once it is open, then mark the local process
+ information structure as valid, which guarantees that the pid,
+ fd, and pathname fields match an open /proc entry. Returns
+ zero if the open fails, nonzero otherwise.
+
+ Note that the pathname is left intact, even when the open fails,
+ so that callers can use it to construct meaningful error messages
+ rather than just "file open failed".
+
+ 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.
+ */
+
+static int
+open_proc_file (pid, pip, mode, control)
+ int pid;
+ struct procinfo *pip;
+ int mode;
+ int control;
+{
+ int tmp, tmpfd;
+
+ pip -> next = NULL;
+ pip -> had_event = 0;
+ pip -> pathname = xmalloc (MAX_PROC_NAME_SIZE);
+ pip -> pid = pid;
+
+#ifndef PIOCOPENLWP
+ tmp = pid;
+#else
+ tmp = pid & 0xffff;
+#endif
+
+#ifdef HAVE_MULTIPLE_PROC_FDS
+ sprintf (pip->pathname, STATUS_PROC_NAME_FMT, tmp);
+ if ((pip->status_fd = open (pip->pathname, O_RDONLY)) < 0)
+ {
+ return 0;
+ }
+
+ sprintf (pip->pathname, AS_PROC_NAME_FMT, tmp);
+ if ((pip->as_fd = open (pip->pathname, O_RDWR)) < 0)
+ {
+ close (pip->status_fd);
+ return 0;
+ }
+
+ sprintf (pip->pathname, MAP_PROC_NAME_FMT, tmp);
+ if ((pip->map_fd = open (pip->pathname, O_RDONLY)) < 0)
+ {
+ close (pip->status_fd);
+ close (pip->as_fd);
+ return 0;
+ }
+
+ if (control)
+ {
+ 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);
+
+ if ((tmpfd = open (pip -> pathname, mode)) < 0)
+ return 0;
+
+#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 */
+
+ 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");
+ }
+
+ tmp = pip -> prstatus.pr_who; /* Get thread id from prstatus_t */
+ pip -> pid = (tmp << 16) | pid; /* Update pip */
+ }
+
+ if ((pip -> ctl_fd = ioctl (tmpfd, PIOCOPENLWP, &tmp)) < 0)
+ {
+ close (tmpfd);
+ return 0;
+ }
+
+#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;
+
+ 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;
+{
+ 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)
+ {
+ printf_filtered ("\n\n");
+ }
+ for (transp = pr_flag_table; transp -> name != NULL; transp++)
+ {
+ if (flags & transp -> value)
+ {
+ if (summary)
+ {
+ printf_filtered ("%s ", transp -> name);
+ }
+ else
+ {
+ printf_filtered ("\t%-16s %s.\n", transp -> name, transp -> desc);
+ }
+ }
+ }
+ printf_filtered ("\n");
+}
+
+static void
+info_proc_stop (pip, summary)
+ struct procinfo *pip;
+ int summary;
+{
+ struct trans *transp;
+ int why;
+ int what;
+
+ why = THE_PR_LWP(pip->prstatus).pr_why;
+ what = THE_PR_LWP(pip->prstatus).pr_what;
+
+ 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;
+ }
+ }
+
+ /* 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");
+ }
+}
+
+static void
+info_proc_siginfo (pip, summary)
+ struct procinfo *pip;
+ int summary;
+{
+ struct siginfo *sip;
+
+ 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))
+ {
+ printf_filtered ("%-32s", "Additional signal/fault info:");
+ sip = &(THE_PR_LWP(pip->prstatus).pr_info);