Home | History | Annotate | Download | only in sys
      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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     32 
     33 #pragma weak _ptrace = ptrace
     34 
     35 #include "lint.h"
     36 #include <stdio.h>
     37 #include <stdlib.h>
     38 #include <unistd.h>
     39 #include <memory.h>
     40 #include <string.h>
     41 #include <fcntl.h>
     42 #include <errno.h>
     43 #include <sys/types.h>
     44 #include <sys/uio.h>
     45 #include <signal.h>
     46 #include <sys/siginfo.h>
     47 #include <sys/fault.h>
     48 #include <sys/syscall.h>
     49 #include <procfs.h>
     50 #include <sys/psw.h>
     51 #include <sys/user.h>
     52 /*
     53  * mtlib.h must precede thread.h
     54  */
     55 #include <mtlib.h>
     56 #include <thread.h>
     57 #include <synch.h>
     58 
     59 static mutex_t pt_lock = DEFAULTMUTEX;
     60 
     61 #define	TRUE	1
     62 #define	FALSE	0
     63 
     64 /*
     65  * All my children...
     66  */
     67 typedef 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 
     85 static 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 */
     99 extern	int	ptrace(int, pid_t, int, int);
    100 /* static routines defined in this module */
    101 static	cstatus_t *FindProc(pid_t);
    102 static	void	CheckAllProcs(void);
    103 static	int	Dupfd(int, int);
    104 static	void	MakeProcName(char *, pid_t);
    105 static	int	OpenProc(cstatus_t *);
    106 static	void	CloseProc(cstatus_t *);
    107 static	cstatus_t *GrabProc(pid_t);
    108 static	void	ReleaseProc(cstatus_t *);
    109 static	int	ProcUpdate(cstatus_t *);
    110 static	void	MakeUser(cstatus_t *);
    111 static	void	GetPsargs(cstatus_t *);
    112 static	void	GetSignal(cstatus_t *);
    113 
    114 #if PTRACE_DEBUG
    115 /* for debugging */
    116 static char *
    117 map(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 
    138 int
    139 ptrace(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 
    212 again:
    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 		if (pwrite(cp->asfd, (char *)&data, sizeof (data), (off_t)addr)
    268 		    == sizeof (data)) {
    269 			(void) mutex_unlock(&pt_lock);
    270 			return (data);
    271 		}
    272 		goto eio;
    273 
    274 	case 6:		/* PTRACE_POKEUSER */
    275 		if (addr & 03)
    276 			goto eio;
    277 		xaddr = addr;
    278 		if (xaddr >= REGADDR && xaddr < REGADDR+sizeof (gregset_t))
    279 			xaddr -= REGADDR-U_REG;
    280 		if ((int)xaddr >= U_REG && xaddr < U_REG+sizeof (gregset_t)) {
    281 			int rx = (xaddr-U_REG)/sizeof (greg_t);
    282 			if (rx == EFL)
    283 				data = (cp->user.u_reg[EFL] & ~PSL_USERMASK) |
    284 				    (data & PSL_USERMASK);
    285 			cp->user.u_reg[rx] = data;
    286 			cp->flags |= CS_SETREGS;
    287 			(void) mutex_unlock(&pt_lock);
    288 			return (data);
    289 		}
    290 		goto eio;
    291 
    292 	case 7:		/* PTRACE_CONT */
    293 	case 9:		/* PTRACE_SINGLESTEP */
    294 	{
    295 		long runctl[3];
    296 
    297 		if (cp->flags & CS_SETREGS) {
    298 			long cmd;
    299 			iovec_t iov[2];
    300 
    301 			ps->pr_lwp.pr_reg[GS] = cp->user.u_reg[GS];
    302 			ps->pr_lwp.pr_reg[FS] = cp->user.u_reg[FS];
    303 			ps->pr_lwp.pr_reg[ES] = cp->user.u_reg[ES];
    304 			ps->pr_lwp.pr_reg[DS] = cp->user.u_reg[DS];
    305 			ps->pr_lwp.pr_reg[EDI] = cp->user.u_reg[EDI];
    306 			ps->pr_lwp.pr_reg[ESI] = cp->user.u_reg[ESI];
    307 			ps->pr_lwp.pr_reg[EBP] = cp->user.u_reg[EBP];
    308 			ps->pr_lwp.pr_reg[ESP] = cp->user.u_reg[ESP];
    309 			ps->pr_lwp.pr_reg[EBX] = cp->user.u_reg[EBX];
    310 			ps->pr_lwp.pr_reg[EDX] = cp->user.u_reg[EDX];
    311 			ps->pr_lwp.pr_reg[ECX] = cp->user.u_reg[ECX];
    312 			ps->pr_lwp.pr_reg[EAX] = cp->user.u_reg[EAX];
    313 			ps->pr_lwp.pr_reg[TRAPNO] = cp->user.u_reg[TRAPNO];
    314 			ps->pr_lwp.pr_reg[ERR] = cp->user.u_reg[ERR];
    315 			ps->pr_lwp.pr_reg[EIP] = cp->user.u_reg[EIP];
    316 			ps->pr_lwp.pr_reg[CS] = cp->user.u_reg[CS];
    317 			ps->pr_lwp.pr_reg[EFL] = cp->user.u_reg[EFL];
    318 			ps->pr_lwp.pr_reg[UESP] = cp->user.u_reg[UESP];
    319 			ps->pr_lwp.pr_reg[SS] = cp->user.u_reg[SS];
    320 			cmd = PCSREG;
    321 			iov[0].iov_base = (caddr_t)&cmd;
    322 			iov[0].iov_len = sizeof (long);
    323 			iov[1].iov_base = (caddr_t)&ps->pr_lwp.pr_reg[0];
    324 			iov[1].iov_len = sizeof (ps->pr_lwp.pr_reg);
    325 			if (writev(cp->ctlfd, iov, 2) < 0)
    326 				goto tryagain;
    327 		}
    328 		if (addr != 1 &&	/* new virtual address */
    329 		    addr != cp->user.u_reg[EIP]) {
    330 			runctl[0] = PCSVADDR;
    331 			runctl[1] = addr;
    332 			if (write(cp->ctlfd, (char *)runctl, 2*sizeof (long))
    333 			    != 2*sizeof (long))
    334 				goto tryagain;
    335 		}
    336 		/* make data the current signal */
    337 		if (data != 0 && data != ps->pr_lwp.pr_cursig) {
    338 			(void) memset((char *)&ctl.arg.siginfo, 0,
    339 			    sizeof (siginfo_t));
    340 			ctl.arg.siginfo.si_signo = data;
    341 			ctl.cmd = PCSSIG;
    342 			if (write(cp->ctlfd, (char *)&ctl,
    343 			    sizeof (long)+sizeof (siginfo_t))
    344 			    != sizeof (long)+sizeof (siginfo_t))
    345 				goto tryagain;
    346 		}
    347 		if (data == 0)
    348 			runctl[0] = PCCSIG;
    349 		else
    350 			runctl[0] = PCNULL;
    351 		runctl[1] = PCRUN;
    352 		runctl[2] = (request == 9)? PRSTEP : 0;
    353 		if (write(cp->ctlfd, (char *)runctl, 3*sizeof (long))
    354 		    != 3*sizeof (long)) {
    355 			if (errno == ENOENT) {
    356 				/* current signal must have killed it */
    357 				ReleaseProc(cp);
    358 				(void) mutex_unlock(&pt_lock);
    359 				return (data);
    360 			}
    361 			goto tryagain;
    362 		}
    363 		(void) memset((char *)ps, 0, sizeof (pstatus_t));
    364 		cp->flags = 0;
    365 		(void) mutex_unlock(&pt_lock);
    366 		return (data);
    367 	}
    368 
    369 	case 8:		/* PTRACE_KILL */
    370 		/* overkill? */
    371 		(void) memset((char *)&ctl.arg.siginfo, 0, sizeof (siginfo_t));
    372 		ctl.arg.siginfo.si_signo = SIGKILL;
    373 		ctl.cmd = PCSSIG;
    374 		(void) write(cp->ctlfd, (char *)&ctl,
    375 		    sizeof (long)+sizeof (siginfo_t));
    376 		(void) kill(pid, SIGKILL);
    377 		ReleaseProc(cp);
    378 		(void) mutex_unlock(&pt_lock);
    379 		return (0);
    380 
    381 	default:
    382 		goto eio;
    383 	}
    384 
    385 tryagain:
    386 	if (errno == EAGAIN) {
    387 		if (OpenProc(cp) == 0)
    388 			goto again;
    389 		ReleaseProc(cp);
    390 	}
    391 eio:
    392 	errno = EIO;
    393 	(void) mutex_unlock(&pt_lock);
    394 	return (-1);
    395 esrch:
    396 	errno = ESRCH;
    397 	(void) mutex_unlock(&pt_lock);
    398 	return (-1);
    399 }
    400 
    401 /*
    402  * Find the cstatus structure corresponding to pid.
    403  */
    404 static cstatus_t *
    405 FindProc(pid_t pid)
    406 {
    407 	cstatus_t *cp;
    408 
    409 	for (cp = childp; cp != NULLCP; cp = cp->next)
    410 		if (cp->pid == pid)
    411 			break;
    412 
    413 	return (cp);
    414 }
    415 
    416 /*
    417  * Check every proc for existence, release those that are gone.
    418  * Be careful about the linked list; ReleaseProc() changes it.
    419  */
    420 static void
    421 CheckAllProcs()
    422 {
    423 	cstatus_t *cp = childp;
    424 
    425 	while (cp != NULLCP) {
    426 		cstatus_t *next = cp->next;
    427 
    428 		if (ProcUpdate(cp) != 0)
    429 			ReleaseProc(cp);
    430 		cp = next;
    431 	}
    432 }
    433 
    434 /*
    435  * Utility for OpenProc().
    436  */
    437 static int
    438 Dupfd(int fd, int dfd)
    439 {
    440 	/*
    441 	 * Make sure fd not one of 0, 1, or 2 to avoid stdio interference.
    442 	 * Also, if dfd is greater than 2, dup fd to be exactly dfd.
    443 	 */
    444 	if (dfd > 2 || (0 <= fd && fd <= 2)) {
    445 		if (dfd > 2 && fd != dfd)
    446 			(void) close(dfd);
    447 		else
    448 			dfd = 3;
    449 		if (fd != dfd) {
    450 			dfd = fcntl(fd, F_DUPFD, (intptr_t)dfd);
    451 			(void) close(fd);
    452 			fd = dfd;
    453 		}
    454 	}
    455 	/*
    456 	 * Mark filedescriptor close-on-exec.
    457 	 * Should also be close-on-return-from-fork-in-child.
    458 	 */
    459 	(void) fcntl(fd, F_SETFD, (intptr_t)1);
    460 	return (fd);
    461 }
    462 
    463 /*
    464  * Construct the /proc directory name:  "/proc/<pid>"
    465  * The name buffer passed by the caller must be large enough.
    466  */
    467 static void
    468 MakeProcName(char *procname, pid_t pid)
    469 {
    470 	(void) sprintf(procname, "/proc/%ld", pid);
    471 }
    472 
    473 /*
    474  * Open/reopen the /proc/<pid> files.
    475  */
    476 static int
    477 OpenProc(cstatus_t *cp)
    478 {
    479 	char procname[64];		/* /proc/nnnnn/fname */
    480 	char *fname;
    481 	int fd;
    482 	int omode;
    483 
    484 	MakeProcName(procname, cp->pid);
    485 	fname = procname + strlen(procname);
    486 
    487 	/*
    488 	 * Use exclusive-open only if this is the first open.
    489 	 */
    490 	omode = (cp->asfd > 0)? O_RDWR : (O_RDWR|O_EXCL);
    491 	(void) strcpy(fname, "/as");
    492 	if ((fd = open(procname, omode, 0)) < 0 ||
    493 	    (cp->asfd = Dupfd(fd, cp->asfd)) < 0)
    494 		goto err;
    495 
    496 	(void) strcpy(fname, "/ctl");
    497 	if ((fd = open(procname, O_WRONLY, 0)) < 0 ||
    498 	    (cp->ctlfd = Dupfd(fd, cp->ctlfd)) < 0)
    499 		goto err;
    500 
    501 	(void) strcpy(fname, "/status");
    502 	if ((fd = open(procname, O_RDONLY, 0)) < 0 ||
    503 	    (cp->statusfd = Dupfd(fd, cp->statusfd)) < 0)
    504 		goto err;
    505 
    506 	return (0);
    507 
    508 err:
    509 	CloseProc(cp);
    510 	return (-1);
    511 }
    512 
    513 /*
    514  * Close the /proc/<pid> files.
    515  */
    516 static void
    517 CloseProc(cstatus_t *cp)
    518 {
    519 	if (cp->asfd > 0)
    520 		(void) close(cp->asfd);
    521 	if (cp->ctlfd > 0)
    522 		(void) close(cp->ctlfd);
    523 	if (cp->statusfd > 0)
    524 		(void) close(cp->statusfd);
    525 	cp->asfd = 0;
    526 	cp->ctlfd = 0;
    527 	cp->statusfd = 0;
    528 }
    529 
    530 /*
    531  * Take control of a child process.
    532  */
    533 static cstatus_t *
    534 GrabProc(pid_t pid)
    535 {
    536 	cstatus_t *cp;
    537 	long ctl[2];
    538 	pid_t ppid;
    539 
    540 	if (pid <= 0)
    541 		return (NULLCP);
    542 
    543 	if ((cp = FindProc(pid)) != NULLCP)	/* already grabbed */
    544 		return (cp);
    545 
    546 	CheckAllProcs();	/* clean up before grabbing new process */
    547 
    548 	cp = (cstatus_t *)malloc(sizeof (cstatus_t));
    549 	if (cp == NULLCP)
    550 		return (NULLCP);
    551 	(void) memset((char *)cp, 0, sizeof (cstatus_t));
    552 	cp->pid = pid;
    553 
    554 	ppid = getpid();
    555 	while (OpenProc(cp) == 0) {
    556 		ctl[0] = PCSET;
    557 		ctl[1] = PR_RLC;
    558 		errno = 0;
    559 
    560 		if (pread(cp->statusfd, (char *)&cp->pstatus,
    561 		    sizeof (cp->pstatus), (off_t)0) == sizeof (cp->pstatus) &&
    562 		    cp->pstatus.pr_ppid == ppid &&
    563 		    (cp->pstatus.pr_flags & PR_PTRACE) &&
    564 		    write(cp->ctlfd, (char *)ctl, 2*sizeof (long))
    565 		    == 2*sizeof (long)) {
    566 			cp->next = childp;
    567 			childp = cp;
    568 			MakeUser(cp);
    569 			return (cp);
    570 		}
    571 
    572 		if (errno != EAGAIN)
    573 			break;
    574 	}
    575 
    576 	free((char *)cp);
    577 	return (NULLCP);
    578 }
    579 
    580 /*
    581  * Close the /proc/<pid> file, if open.
    582  * Deallocate the memory used by the cstatus_t structure.
    583  */
    584 static void
    585 ReleaseProc(cstatus_t *cp)
    586 {
    587 	CloseProc(cp);
    588 
    589 	if (childp == cp)
    590 		childp = cp->next;
    591 	else {
    592 		cstatus_t *pcp;
    593 
    594 		for (pcp = childp; pcp != NULLCP; pcp = pcp->next) {
    595 			if (pcp->next == cp) {
    596 				pcp->next = cp->next;
    597 				break;
    598 			}
    599 		}
    600 	}
    601 
    602 	free((char *)cp);
    603 }
    604 
    605 /*
    606  * Update process information from /proc.
    607  * Return 0 on success, -1 on failure.
    608  */
    609 static int
    610 ProcUpdate(cstatus_t *cp)
    611 {
    612 	pstatus_t *ps = &cp->pstatus;
    613 
    614 	if (cp->flags & CS_SETREGS) {
    615 		long cmd;
    616 		iovec_t iov[2];
    617 
    618 		ps->pr_lwp.pr_reg[GS]   = cp->user.u_reg[GS];
    619 		ps->pr_lwp.pr_reg[FS]   = cp->user.u_reg[FS];
    620 		ps->pr_lwp.pr_reg[ES]   = cp->user.u_reg[ES];
    621 		ps->pr_lwp.pr_reg[DS]   = cp->user.u_reg[DS];
    622 		ps->pr_lwp.pr_reg[EDI]  = cp->user.u_reg[EDI];
    623 		ps->pr_lwp.pr_reg[ESI]  = cp->user.u_reg[ESI];
    624 		ps->pr_lwp.pr_reg[EBP]  = cp->user.u_reg[EBP];
    625 		ps->pr_lwp.pr_reg[ESP]  = cp->user.u_reg[ESP];
    626 		ps->pr_lwp.pr_reg[EBX]  = cp->user.u_reg[EBX];
    627 		ps->pr_lwp.pr_reg[EDX]  = cp->user.u_reg[EDX];
    628 		ps->pr_lwp.pr_reg[ECX]  = cp->user.u_reg[ECX];
    629 		ps->pr_lwp.pr_reg[EAX]  = cp->user.u_reg[EAX];
    630 		ps->pr_lwp.pr_reg[TRAPNO] = cp->user.u_reg[TRAPNO];
    631 		ps->pr_lwp.pr_reg[ERR]  = cp->user.u_reg[ERR];
    632 		ps->pr_lwp.pr_reg[EIP]  = cp->user.u_reg[EIP];
    633 		ps->pr_lwp.pr_reg[CS]   = cp->user.u_reg[CS];
    634 		ps->pr_lwp.pr_reg[EFL]  = cp->user.u_reg[EFL];
    635 		ps->pr_lwp.pr_reg[UESP] = cp->user.u_reg[UESP];
    636 		ps->pr_lwp.pr_reg[SS]   = cp->user.u_reg[SS];
    637 		cmd = PCSREG;
    638 		iov[0].iov_base = (caddr_t)&cmd;
    639 		iov[0].iov_len = sizeof (long);
    640 		iov[1].iov_base = (caddr_t)&ps->pr_lwp.pr_reg[0];
    641 		iov[1].iov_len = sizeof (ps->pr_lwp.pr_reg);
    642 		(void) writev(cp->ctlfd, iov, 2);
    643 		cp->flags &= ~CS_SETREGS;
    644 	}
    645 
    646 	while (pread(cp->statusfd, (char *)ps, sizeof (*ps), (off_t)0) < 0) {
    647 		/* attempt to regain control */
    648 		if (errno != EINTR &&
    649 		    !(errno == EAGAIN && OpenProc(cp) == 0))
    650 			return (-1);
    651 	}
    652 
    653 	if (ps->pr_flags & PR_ISTOP)
    654 		MakeUser(cp);
    655 	else
    656 		(void) memset((char *)ps, 0, sizeof (pstatus_t));
    657 
    658 	return (0);
    659 }
    660 
    661 /*
    662  * Manufacture the contents of the fake u-block.
    663  */
    664 static void
    665 MakeUser(cstatus_t *cp)
    666 {
    667 	pstatus_t *ps = &cp->pstatus;
    668 
    669 	cp->user.u_reg[GS]   = ps->pr_lwp.pr_reg[GS];
    670 	cp->user.u_reg[FS]   = ps->pr_lwp.pr_reg[FS];
    671 	cp->user.u_reg[ES]   = ps->pr_lwp.pr_reg[ES];
    672 	cp->user.u_reg[DS]   = ps->pr_lwp.pr_reg[DS];
    673 	cp->user.u_reg[EDI]  = ps->pr_lwp.pr_reg[EDI];
    674 	cp->user.u_reg[ESI]  = ps->pr_lwp.pr_reg[ESI];
    675 	cp->user.u_reg[EBP]  = ps->pr_lwp.pr_reg[EBP];
    676 	cp->user.u_reg[ESP]  = ps->pr_lwp.pr_reg[ESP];
    677 	cp->user.u_reg[EBX]  = ps->pr_lwp.pr_reg[EBX];
    678 	cp->user.u_reg[EDX]  = ps->pr_lwp.pr_reg[EDX];
    679 	cp->user.u_reg[ECX]  = ps->pr_lwp.pr_reg[ECX];
    680 	cp->user.u_reg[EAX]  = ps->pr_lwp.pr_reg[EAX];
    681 	cp->user.u_reg[TRAPNO] = ps->pr_lwp.pr_reg[TRAPNO];
    682 	cp->user.u_reg[ERR]  = ps->pr_lwp.pr_reg[ERR];
    683 	cp->user.u_reg[EIP]  = ps->pr_lwp.pr_reg[EIP];
    684 	cp->user.u_reg[CS]   = ps->pr_lwp.pr_reg[CS];
    685 	cp->user.u_reg[EFL]  = ps->pr_lwp.pr_reg[EFL];
    686 	cp->user.u_reg[UESP] = ps->pr_lwp.pr_reg[UESP];
    687 	cp->user.u_reg[SS]   = ps->pr_lwp.pr_reg[SS];
    688 	cp->user.u_ar0 = (greg_t *)REGADDR;
    689 	cp->user.u_code = ps->pr_lwp.pr_info.si_code;
    690 	cp->user.u_addr = ps->pr_lwp.pr_info.si_addr;
    691 	cp->flags &= ~(CS_PSARGS|CS_SIGNAL);
    692 }
    693 
    694 /*
    695  * Fetch the contents of u_psargs[].
    696  */
    697 static void
    698 GetPsargs(cstatus_t *cp)
    699 {
    700 	char procname[64];	/* /proc/<pid>/psinfo */
    701 	int fd;
    702 
    703 	MakeProcName(procname, cp->pid);
    704 	(void) strcat(procname, "/psinfo");
    705 	if ((fd = open(procname, O_RDONLY, 0)) < 0) {
    706 		(void) memset(cp->user.u_psargs, 0, PSARGSZ);
    707 		return;
    708 	}
    709 	(void) pread(fd, cp->user.u_psargs, PSARGSZ,
    710 	    (off_t)((psinfo_t *)0)->pr_psargs);
    711 	(void) close(fd);
    712 
    713 	cp->flags |= CS_PSARGS;
    714 }
    715 
    716 /*
    717  * Fetch the contents of u_signal[].
    718  */
    719 static void
    720 GetSignal(cstatus_t *cp)
    721 {
    722 	char procname[64];	/* /proc/<pid>/sigact */
    723 	int fd;
    724 	struct sigaction action[MAXSIG];
    725 	int i;
    726 
    727 	MakeProcName(procname, cp->pid);
    728 	(void) strcat(procname, "/sigact");
    729 	(void) memset((char *)action, 0, sizeof (action));
    730 	if ((fd = open(procname, O_RDONLY, 0)) >= 0) {
    731 		(void) read(fd, (char *)action, sizeof (action));
    732 		(void) close(fd);
    733 	}
    734 	for (i = 0; i < MAXSIG; i++)
    735 		cp->user.u_signal[i] = action[i].sa_handler;
    736 	cp->flags |= CS_SIGNAL;
    737 }
    738