1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/*
28 * ptrace(2) interface built on top of proc(4).
29 */
30
31
32#pragma weak _ptrace = ptrace
33
34#include "lint.h"
35#include <stdio.h>
36#include <stdlib.h>
37#include <unistd.h>
38#include <memory.h>
39#include <string.h>
40#include <fcntl.h>
41#include <errno.h>
42#include <sys/types.h>
43#include <sys/uio.h>
44#include <signal.h>
45#include <sys/siginfo.h>
46#include <sys/fault.h>
47#include <sys/syscall.h>
48#include <procfs.h>
49#include <sys/psw.h>
50#include <sys/user.h>
51/*
52 * mtlib.h must precede thread.h
53 */
54#include <mtlib.h>
55#include <thread.h>
56#include <synch.h>
57#include <unistd.h>
58
59static mutex_t pt_lock = DEFAULTMUTEX;
60
61#define	TRUE	1
62#define	FALSE	0
63
64/*
65 * All my children...
66 */
67typedef struct cstatus {
68	struct cstatus	*next;		/* linked list			*/
69	pid_t		pid;		/* process-id			*/
70	int		asfd;		/* /proc/<pid>/as		*/
71	int		ctlfd;		/* /proc/<pid>/ctl		*/
72	int		statusfd;	/* /proc/<pid>/status		*/
73	int		flags;		/* see below			*/
74	pstatus_t	pstatus;	/* from /proc/<pid>/status	*/
75	user_t		user;		/* manufactured u-block		*/
76} cstatus_t;
77
78/* flags */
79#define	CS_SETREGS	0x01		/* set registers on run		*/
80#define	CS_PSARGS	0x02		/* u_psargs[] has been fetched	*/
81#define	CS_SIGNAL	0x04		/* u_signal[] has been fetched	*/
82
83#define	NULLCP	((cstatus_t *)0)
84
85static cstatus_t *childp = NULLCP;
86
87/* fake u-block offsets */
88#define	UP		((user_t *)NULL)
89#define	U_REG		((int)(&UP->u_reg[0]))
90#define	U_AR0		((int)(&UP->u_ar0))
91#define	U_PSARGS	((int)(&UP->u_psargs[0]))
92#define	U_SIGNAL	((int)(&UP->u_signal[0]))
93#define	U_CODE		((int)(&UP->u_code))
94#define	U_ADDR		((int)(&UP->u_addr))
95#define	U_END		((int)sizeof (user_t))
96#define	REGADDR		0xffff0000	/* arbitrary kernel address for u_ar0 */
97
98/* external routines defined in this module */
99extern	int	ptrace(int, pid_t, int, int);
100/* static routines defined in this module */
101static	cstatus_t *FindProc(pid_t);
102static	void	CheckAllProcs(void);
103static	int	Dupfd(int, int);
104static	void	MakeProcName(char *, pid_t);
105static	int	OpenProc(cstatus_t *);
106static	void	CloseProc(cstatus_t *);
107static	cstatus_t *GrabProc(pid_t);
108static	void	ReleaseProc(cstatus_t *);
109static	int	ProcUpdate(cstatus_t *);
110static	void	MakeUser(cstatus_t *);
111static	void	GetPsargs(cstatus_t *);
112static	void	GetSignal(cstatus_t *);
113
114#if PTRACE_DEBUG
115/* for debugging */
116static char *
117map(int request)
118{
119	static char name[20];
120
121	switch (request) {
122	case 0:	return ("PTRACE_TRACEME");
123	case 1:	return ("PTRACE_PEEKTEXT");
124	case 2:	return ("PTRACE_PEEKDATA");
125	case 3:	return ("PTRACE_PEEKUSER");
126	case 4:	return ("PTRACE_POKETEXT");
127	case 5:	return ("PTRACE_POKEDATA");
128	case 6:	return ("PTRACE_POKEUSER");
129	case 7:	return ("PTRACE_CONT");
130	case 8:	return ("PTRACE_KILL");
131	case 9:	return ("PTRACE_SINGLESTEP");
132	}
133	(void) sprintf(name, "%d", request);
134	return (name);
135}
136#endif
137
138int
139ptrace(int request, pid_t pid, int addr, int data)
140{
141	pstatus_t *ps;
142	cstatus_t *cp;
143	unsigned xaddr;
144	struct {
145		long cmd;
146		union {
147			long flags;
148			sigset_t signals;
149			fltset_t faults;
150			sysset_t syscalls;
151			siginfo_t siginfo;
152		} arg;
153	} ctl;
154
155#if PTRACE_DEBUG
156	fprintf(stderr, " ptrace(%s, 0x%X, 0x%X, 0x%X)\n",
157	    map(request), pid, addr, data);
158#endif
159
160	(void) mutex_lock(&pt_lock);
161
162	if (request == 0) {	/* PTRACE_TRACEME, executed by traced process */
163		/*
164		 * Set stop-on-all-signals and nothing else.
165		 * Turn off inherit-on-fork flag (grandchildren run away).
166		 * Set ptrace-compatible flag.
167		 */
168		char procname[64];	/* /proc/<pid>/ctl */
169		int fd;
170
171		MakeProcName(procname, getpid());
172		(void) strcat(procname, "/ctl");
173		if ((fd = open(procname, O_WRONLY, 0)) < 0)
174			exit(255);
175		ctl.cmd = PCSTRACE;
176		prfillset(&ctl.arg.signals);
177		if (write(fd, (char *)&ctl, sizeof (long)+sizeof (sigset_t))
178		    != sizeof (long)+sizeof (sigset_t))
179			exit(255);
180		ctl.cmd = PCSFAULT;
181		premptyset(&ctl.arg.faults);
182		if (write(fd, (char *)&ctl, sizeof (long)+sizeof (fltset_t))
183		    != sizeof (long)+sizeof (fltset_t))
184			exit(255);
185		ctl.cmd = PCSENTRY;
186		premptyset(&ctl.arg.syscalls);
187		if (write(fd, (char *)&ctl, sizeof (long)+sizeof (sysset_t))
188		    != sizeof (long)+sizeof (sysset_t))
189			exit(255);
190		ctl.cmd = PCSEXIT;
191		premptyset(&ctl.arg.syscalls);
192		if (write(fd, (char *)&ctl, sizeof (long)+sizeof (sysset_t))
193		    != sizeof (long)+sizeof (sysset_t))
194			exit(255);
195		ctl.cmd = PCUNSET;
196		ctl.arg.flags = PR_FORK;
197		if (write(fd, (char *)&ctl, sizeof (long)+sizeof (long))
198		    != sizeof (long)+sizeof (long))
199			exit(255);
200		ctl.cmd = PCSET;
201		ctl.arg.flags = PR_PTRACE;
202		if (write(fd, (char *)&ctl, sizeof (long)+sizeof (long))
203		    != sizeof (long)+sizeof (long))
204			exit(255);
205		if (close(fd) != 0)
206			exit(255);
207
208		(void) mutex_unlock(&pt_lock);
209		return (0);
210	}
211
212again:
213	errno = 0;
214
215	/* find the cstatus structure corresponding to pid */
216	if ((cp = GrabProc(pid)) == NULLCP)
217		goto esrch;
218
219	ps = &cp->pstatus;
220	if (!(ps->pr_flags & PR_ISTOP)) {
221		if (ProcUpdate(cp) != 0) {
222			ReleaseProc(cp);
223			goto esrch;
224		}
225		if (!(ps->pr_flags & PR_ISTOP))
226			goto esrch;
227	}
228
229	/*
230	 * Process the request.
231	 */
232	errno = 0;
233	switch (request) {
234	case 1:		/* PTRACE_PEEKTEXT */
235	case 2:		/* PTRACE_PEEKDATA */
236		if (addr & 03)
237			goto eio;
238		if (pread(cp->asfd, (char *)&data, sizeof (data), (off_t)addr)
239		    == sizeof (data)) {
240			(void) mutex_unlock(&pt_lock);
241			return (data);
242		}
243		goto eio;
244
245	case 3:		/* PTRACE_PEEKUSER */
246		if (addr & 03)
247			goto eio;
248		xaddr = addr;
249		if (xaddr >= REGADDR && xaddr < REGADDR+sizeof (gregset_t))
250			xaddr -= REGADDR-U_REG;
251		if (xaddr >= U_PSARGS && xaddr < U_PSARGS+sizeof (UP->u_psargs))
252			GetPsargs(cp);
253		if (xaddr >= U_SIGNAL && xaddr < U_SIGNAL+sizeof (UP->u_signal))
254			GetSignal(cp);
255		if ((int)xaddr >= 0 && xaddr < U_END) {
256			/* LINTED pointer alignment */
257			data = *((int *)((caddr_t)(&cp->user) + xaddr));
258			(void) mutex_unlock(&pt_lock);
259			return (data);
260		}
261		goto eio;
262
263	case 4:		/* PTRACE_POKETEXT */
264	case 5:		/* PTRACE_POKEDATA */
265		if (addr & 03)
266			goto eio;
267		xaddr = addr;
268		if (xaddr >= (unsigned)cp->user.u_reg[REG_SP] &&
269		    xaddr < (unsigned)cp->user.u_reg[REG_SP]+16*sizeof (int))
270			cp->flags |= CS_SETREGS;
271		if (pwrite(cp->asfd, (char *)&data, sizeof (data), (off_t)addr)
272		    == sizeof (data)) {
273			(void) mutex_unlock(&pt_lock);
274			return (data);
275		}
276		goto eio;
277
278	case 6:		/* PTRACE_POKEUSER */
279		if (addr & 03)
280			goto eio;
281		xaddr = addr;
282		if (xaddr >= REGADDR && xaddr < REGADDR+sizeof (gregset_t))
283			xaddr -= REGADDR-U_REG;
284		if ((int)xaddr >= U_REG && xaddr < U_REG+sizeof (gregset_t)) {
285			int rx = (xaddr-U_REG)/sizeof (greg_t);
286			if (rx == REG_PS)
287				data = (cp->user.u_reg[REG_PS] &
288				    ~PSL_USERMASK) | (data & PSL_USERMASK);
289			else if (rx == REG_SP || rx == REG_PC || rx == REG_nPC)
290				data &= ~03;
291			cp->user.u_reg[rx] = data;
292			cp->flags |= CS_SETREGS;
293			(void) mutex_unlock(&pt_lock);
294			return (data);
295		}
296		goto eio;
297
298	case 7:		/* PTRACE_CONT */
299	case 9:		/* PTRACE_SINGLESTEP */
300	{
301		long runctl[3];
302
303		if (cp->flags & CS_SETREGS) {
304			long cmd;
305			iovec_t iov[2];
306
307			ps->pr_lwp.pr_reg[R_PSR] = cp->user.u_reg[REG_PSR];
308			ps->pr_lwp.pr_reg[R_PC]  = cp->user.u_reg[REG_PC];
309			ps->pr_lwp.pr_reg[R_nPC] = cp->user.u_reg[REG_nPC];
310			ps->pr_lwp.pr_reg[R_Y]   = cp->user.u_reg[REG_Y];
311			ps->pr_lwp.pr_reg[R_G1]  = cp->user.u_reg[REG_G1];
312			ps->pr_lwp.pr_reg[R_G2]  = cp->user.u_reg[REG_G2];
313			ps->pr_lwp.pr_reg[R_G3]  = cp->user.u_reg[REG_G3];
314			ps->pr_lwp.pr_reg[R_G4]  = cp->user.u_reg[REG_G4];
315			ps->pr_lwp.pr_reg[R_G5]  = cp->user.u_reg[REG_G5];
316			ps->pr_lwp.pr_reg[R_G6]  = cp->user.u_reg[REG_G6];
317			ps->pr_lwp.pr_reg[R_G7]  = cp->user.u_reg[REG_G7];
318			ps->pr_lwp.pr_reg[R_O0]  = cp->user.u_reg[REG_O0];
319			ps->pr_lwp.pr_reg[R_O1]  = cp->user.u_reg[REG_O1];
320			ps->pr_lwp.pr_reg[R_O2]  = cp->user.u_reg[REG_O2];
321			ps->pr_lwp.pr_reg[R_O3]  = cp->user.u_reg[REG_O3];
322			ps->pr_lwp.pr_reg[R_O4]  = cp->user.u_reg[REG_O4];
323			ps->pr_lwp.pr_reg[R_O5]  = cp->user.u_reg[REG_O5];
324			ps->pr_lwp.pr_reg[R_O6]  = cp->user.u_reg[REG_O6];
325			ps->pr_lwp.pr_reg[R_O7]  = cp->user.u_reg[REG_O7];
326			(void) pread(cp->asfd, (char *)&ps->pr_lwp.pr_reg[R_L0],
327			    16*sizeof (int), (off_t)cp->user.u_reg[REG_SP]);
328			cmd = PCSREG;
329			iov[0].iov_base = (caddr_t)&cmd;
330			iov[0].iov_len = sizeof (long);
331			iov[1].iov_base = (caddr_t)&ps->pr_lwp.pr_reg[0];
332			iov[1].iov_len = sizeof (ps->pr_lwp.pr_reg);
333			if (writev(cp->ctlfd, iov, 2) < 0)
334				goto tryagain;
335		}
336		if (addr != 1 &&	/* new virtual address */
337		    (addr & ~03) != cp->user.u_reg[REG_PC]) {
338			runctl[0] = PCSVADDR;
339			runctl[1] = (addr & ~03);
340			if (write(cp->ctlfd, (char *)runctl, 2*sizeof (long))
341			    != 2*sizeof (long))
342				goto tryagain;
343		}
344		/* make data the current signal */
345		if (data != 0 && data != ps->pr_lwp.pr_cursig) {
346			(void) memset((char *)&ctl.arg.siginfo, 0,
347			    sizeof (siginfo_t));
348			ctl.arg.siginfo.si_signo = data;
349			ctl.cmd = PCSSIG;
350			if (write(cp->ctlfd, (char *)&ctl,
351			    sizeof (long)+sizeof (siginfo_t))
352			    != sizeof (long)+sizeof (siginfo_t))
353				goto tryagain;
354		}
355		if (data == 0)
356			runctl[0] = PCCSIG;
357		else
358			runctl[0] = PCNULL;
359		runctl[1] = PCRUN;
360		runctl[2] = (request == 9)? PRSTEP : 0;
361		if (write(cp->ctlfd, (char *)runctl, 3*sizeof (long))
362		    != 3*sizeof (long)) {
363			if (errno == ENOENT) {
364				/* current signal must have killed it */
365				ReleaseProc(cp);
366				(void) mutex_unlock(&pt_lock);
367				return (data);
368			}
369			goto tryagain;
370		}
371		(void) memset((char *)ps, 0, sizeof (pstatus_t));
372		cp->flags = 0;
373		(void) mutex_unlock(&pt_lock);
374		return (data);
375	}
376
377	case 8:		/* PTRACE_KILL */
378		/* overkill? */
379		(void) memset((char *)&ctl.arg.siginfo, 0, sizeof (siginfo_t));
380		ctl.arg.siginfo.si_signo = SIGKILL;
381		ctl.cmd = PCSSIG;
382		(void) write(cp->ctlfd, (char *)&ctl,
383		    sizeof (long)+sizeof (siginfo_t));
384		(void) kill(pid, SIGKILL);
385		ReleaseProc(cp);
386		(void) mutex_unlock(&pt_lock);
387		return (0);
388
389	default:
390		goto eio;
391	}
392
393tryagain:
394	if (errno == EAGAIN) {
395		if (OpenProc(cp) == 0)
396			goto again;
397		ReleaseProc(cp);
398	}
399eio:
400	errno = EIO;
401	(void) mutex_unlock(&pt_lock);
402	return (-1);
403esrch:
404	errno = ESRCH;
405	(void) mutex_unlock(&pt_lock);
406	return (-1);
407}
408
409/*
410 * Find the cstatus structure corresponding to pid.
411 */
412static cstatus_t *
413FindProc(pid_t pid)
414{
415	cstatus_t *cp;
416
417	for (cp = childp; cp != NULLCP; cp = cp->next)
418		if (cp->pid == pid)
419			break;
420
421	return (cp);
422}
423
424/*
425 * Check every proc for existence, release those that are gone.
426 * Be careful about the linked list; ReleaseProc() changes it.
427 */
428static void
429CheckAllProcs()
430{
431	cstatus_t *cp = childp;
432
433	while (cp != NULLCP) {
434		cstatus_t *next = cp->next;
435
436		if (ProcUpdate(cp) != 0)
437			ReleaseProc(cp);
438		cp = next;
439	}
440}
441
442/*
443 * Utility for OpenProc().
444 */
445static int
446Dupfd(int fd, int dfd)
447{
448	/*
449	 * Make sure fd not one of 0, 1, or 2 to avoid stdio interference.
450	 * Also, if dfd is greater than 2, dup fd to be exactly dfd.
451	 */
452	if (dfd > 2 || (0 <= fd && fd <= 2)) {
453		if (dfd > 2 && fd != dfd)
454			(void) close(dfd);
455		else
456			dfd = 3;
457		if (fd != dfd) {
458			dfd = fcntl(fd, F_DUPFD, (intptr_t)dfd);
459			(void) close(fd);
460			fd = dfd;
461		}
462	}
463	/*
464	 * Mark filedescriptor close-on-exec.
465	 * Should also be close-on-return-from-fork-in-child.
466	 */
467	(void) fcntl(fd, F_SETFD, (intptr_t)1);
468	return (fd);
469}
470
471/*
472 * Construct the /proc directory name:  "/proc/<pid>"
473 * The name buffer passed by the caller must be large enough.
474 */
475static void
476MakeProcName(char *procname, pid_t pid)
477{
478	(void) sprintf(procname, "/proc/%d", (int)pid);
479}
480
481/*
482 * Open/reopen the /proc/<pid> files.
483 */
484static int
485OpenProc(cstatus_t *cp)
486{
487	char procname[64];		/* /proc/nnnnn/fname */
488	char *fname;
489	int fd;
490	int omode;
491
492	MakeProcName(procname, cp->pid);
493	fname = procname + strlen(procname);
494
495	/*
496	 * Use exclusive-open only if this is the first open.
497	 */
498	omode = (cp->asfd > 0)? O_RDWR : (O_RDWR|O_EXCL);
499	(void) strcpy(fname, "/as");
500	if ((fd = open(procname, omode, 0)) < 0 ||
501	    (cp->asfd = Dupfd(fd, cp->asfd)) < 0)
502		goto err;
503
504	(void) strcpy(fname, "/ctl");
505	if ((fd = open(procname, O_WRONLY, 0)) < 0 ||
506	    (cp->ctlfd = Dupfd(fd, cp->ctlfd)) < 0)
507		goto err;
508
509	(void) strcpy(fname, "/status");
510	if ((fd = open(procname, O_RDONLY, 0)) < 0 ||
511	    (cp->statusfd = Dupfd(fd, cp->statusfd)) < 0)
512		goto err;
513
514	return (0);
515
516err:
517	CloseProc(cp);
518	return (-1);
519}
520
521/*
522 * Close the /proc/<pid> files.
523 */
524static void
525CloseProc(cstatus_t *cp)
526{
527	if (cp->asfd > 0)
528		(void) close(cp->asfd);
529	if (cp->ctlfd > 0)
530		(void) close(cp->ctlfd);
531	if (cp->statusfd > 0)
532		(void) close(cp->statusfd);
533	cp->asfd = 0;
534	cp->ctlfd = 0;
535	cp->statusfd = 0;
536}
537
538/*
539 * Take control of a child process.
540 */
541static cstatus_t *
542GrabProc(pid_t pid)
543{
544	cstatus_t *cp;
545	long ctl[2];
546	pid_t ppid;
547
548	if (pid <= 0)
549		return (NULLCP);
550
551	if ((cp = FindProc(pid)) != NULLCP)	/* already grabbed */
552		return (cp);
553
554	CheckAllProcs();	/* clean up before grabbing new process */
555
556	cp = (cstatus_t *)malloc(sizeof (cstatus_t));
557	if (cp == NULLCP)
558		return (NULLCP);
559	(void) memset((char *)cp, 0, sizeof (cstatus_t));
560	cp->pid = pid;
561
562	ppid = getpid();
563	while (OpenProc(cp) == 0) {
564		ctl[0] = PCSET;
565		ctl[1] = PR_RLC;
566		errno = 0;
567
568		if (pread(cp->statusfd, (char *)&cp->pstatus,
569		    sizeof (cp->pstatus), (off_t)0) == sizeof (cp->pstatus) &&
570		    cp->pstatus.pr_ppid == ppid &&
571		    (cp->pstatus.pr_flags & PR_PTRACE) &&
572		    write(cp->ctlfd, (char *)ctl, 2*sizeof (long))
573		    == 2*sizeof (long)) {
574			cp->next = childp;
575			childp = cp;
576			MakeUser(cp);
577			return (cp);
578		}
579
580		if (errno != EAGAIN)
581			break;
582	}
583
584	free((char *)cp);
585	return (NULLCP);
586}
587
588/*
589 * Close the /proc/<pid> file, if open.
590 * Deallocate the memory used by the cstatus_t structure.
591 */
592static void
593ReleaseProc(cstatus_t *cp)
594{
595	CloseProc(cp);
596
597	if (childp == cp)
598		childp = cp->next;
599	else {
600		cstatus_t *pcp;
601
602		for (pcp = childp; pcp != NULLCP; pcp = pcp->next) {
603			if (pcp->next == cp) {
604				pcp->next = cp->next;
605				break;
606			}
607		}
608	}
609
610	free((char *)cp);
611}
612
613/*
614 * Update process information from /proc.
615 * Return 0 on success, -1 on failure.
616 */
617static int
618ProcUpdate(cstatus_t *cp)
619{
620	pstatus_t *ps = &cp->pstatus;
621
622	if (cp->flags & CS_SETREGS) {
623		long cmd;
624		iovec_t iov[2];
625
626		ps->pr_lwp.pr_reg[R_PSR] = cp->user.u_reg[REG_PSR];
627		ps->pr_lwp.pr_reg[R_PC]  = cp->user.u_reg[REG_PC];
628		ps->pr_lwp.pr_reg[R_nPC] = cp->user.u_reg[REG_nPC];
629		ps->pr_lwp.pr_reg[R_Y]   = cp->user.u_reg[REG_Y];
630		ps->pr_lwp.pr_reg[R_G1]  = cp->user.u_reg[REG_G1];
631		ps->pr_lwp.pr_reg[R_G2]  = cp->user.u_reg[REG_G2];
632		ps->pr_lwp.pr_reg[R_G3]  = cp->user.u_reg[REG_G3];
633		ps->pr_lwp.pr_reg[R_G4]  = cp->user.u_reg[REG_G4];
634		ps->pr_lwp.pr_reg[R_G5]  = cp->user.u_reg[REG_G5];
635		ps->pr_lwp.pr_reg[R_G6]  = cp->user.u_reg[REG_G6];
636		ps->pr_lwp.pr_reg[R_G7]  = cp->user.u_reg[REG_G7];
637		ps->pr_lwp.pr_reg[R_O0]  = cp->user.u_reg[REG_O0];
638		ps->pr_lwp.pr_reg[R_O1]  = cp->user.u_reg[REG_O1];
639		ps->pr_lwp.pr_reg[R_O2]  = cp->user.u_reg[REG_O2];
640		ps->pr_lwp.pr_reg[R_O3]  = cp->user.u_reg[REG_O3];
641		ps->pr_lwp.pr_reg[R_O4]  = cp->user.u_reg[REG_O4];
642		ps->pr_lwp.pr_reg[R_O5]  = cp->user.u_reg[REG_O5];
643		ps->pr_lwp.pr_reg[R_O6]  = cp->user.u_reg[REG_O6];
644		ps->pr_lwp.pr_reg[R_O7]  = cp->user.u_reg[REG_O7];
645		(void) pread(cp->asfd, (char *)&ps->pr_lwp.pr_reg[R_L0],
646		    16*sizeof (int), (off_t)cp->user.u_reg[REG_SP]);
647		cmd = PCSREG;
648		iov[0].iov_base = (caddr_t)&cmd;
649		iov[0].iov_len = sizeof (long);
650		iov[1].iov_base = (caddr_t)&ps->pr_lwp.pr_reg[0];
651		iov[1].iov_len = sizeof (ps->pr_lwp.pr_reg);
652		(void) writev(cp->ctlfd, iov, 2);
653		cp->flags &= ~CS_SETREGS;
654	}
655
656	while (pread(cp->statusfd, (char *)ps, sizeof (*ps), (off_t)0) < 0) {
657		/* attempt to regain control */
658		if (errno != EINTR &&
659		    !(errno == EAGAIN && OpenProc(cp) == 0))
660			return (-1);
661	}
662
663	if (ps->pr_flags & PR_ISTOP)
664		MakeUser(cp);
665	else
666		(void) memset((char *)ps, 0, sizeof (pstatus_t));
667
668	return (0);
669}
670
671/*
672 * Manufacture the contents of the fake u-block.
673 */
674static void
675MakeUser(cstatus_t *cp)
676{
677	pstatus_t *ps = &cp->pstatus;
678
679	cp->user.u_reg[REG_PSR] = ps->pr_lwp.pr_reg[R_PSR];
680	cp->user.u_reg[REG_PC]  = ps->pr_lwp.pr_reg[R_PC];
681	cp->user.u_reg[REG_nPC] = ps->pr_lwp.pr_reg[R_nPC];
682	cp->user.u_reg[REG_Y]   = ps->pr_lwp.pr_reg[R_Y];
683	cp->user.u_reg[REG_G1]  = ps->pr_lwp.pr_reg[R_G1];
684	cp->user.u_reg[REG_G2]  = ps->pr_lwp.pr_reg[R_G2];
685	cp->user.u_reg[REG_G3]  = ps->pr_lwp.pr_reg[R_G3];
686	cp->user.u_reg[REG_G4]  = ps->pr_lwp.pr_reg[R_G4];
687	cp->user.u_reg[REG_G5]  = ps->pr_lwp.pr_reg[R_G5];
688	cp->user.u_reg[REG_G6]  = ps->pr_lwp.pr_reg[R_G6];
689	cp->user.u_reg[REG_G7]  = ps->pr_lwp.pr_reg[R_G7];
690	cp->user.u_reg[REG_O0]  = ps->pr_lwp.pr_reg[R_O0];
691	cp->user.u_reg[REG_O1]  = ps->pr_lwp.pr_reg[R_O1];
692	cp->user.u_reg[REG_O2]  = ps->pr_lwp.pr_reg[R_O2];
693	cp->user.u_reg[REG_O3]  = ps->pr_lwp.pr_reg[R_O3];
694	cp->user.u_reg[REG_O4]  = ps->pr_lwp.pr_reg[R_O4];
695	cp->user.u_reg[REG_O5]  = ps->pr_lwp.pr_reg[R_O5];
696	cp->user.u_reg[REG_O6]  = ps->pr_lwp.pr_reg[R_O6];
697	cp->user.u_reg[REG_O7]  = ps->pr_lwp.pr_reg[R_O7];
698	cp->user.u_ar0 = (greg_t *)REGADDR;
699	cp->user.u_code = ps->pr_lwp.pr_info.si_code;
700	cp->user.u_addr = ps->pr_lwp.pr_info.si_addr;
701	cp->flags &= ~(CS_PSARGS|CS_SIGNAL);
702}
703
704/*
705 * Fetch the contents of u_psargs[].
706 */
707static void
708GetPsargs(cstatus_t *cp)
709{
710	char procname[64];	/* /proc/<pid>/psinfo */
711	int fd;
712
713	MakeProcName(procname, cp->pid);
714	(void) strcat(procname, "/psinfo");
715	if ((fd = open(procname, O_RDONLY, 0)) < 0) {
716		(void) memset(cp->user.u_psargs, 0, PSARGSZ);
717		return;
718	}
719	(void) pread(fd, cp->user.u_psargs, PSARGSZ,
720	    (off_t)((psinfo_t *)0)->pr_psargs);
721	(void) close(fd);
722
723	cp->flags |= CS_PSARGS;
724}
725
726/*
727 * Fetch the contents of u_signal[].
728 */
729static void
730GetSignal(cstatus_t *cp)
731{
732	char procname[64];	/* /proc/<pid>/sigact */
733	int fd;
734	struct sigaction action[MAXSIG];
735	int i;
736
737	MakeProcName(procname, cp->pid);
738	(void) strcat(procname, "/sigact");
739	(void) memset((char *)action, 0, sizeof (action));
740	if ((fd = open(procname, O_RDONLY, 0)) >= 0) {
741		(void) read(fd, (char *)action, sizeof (action));
742		(void) close(fd);
743	}
744	for (i = 0; i < MAXSIG; i++)
745		cp->user.u_signal[i] = action[i].sa_handler;
746	cp->flags |= CS_SIGNAL;
747}
748