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 
     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 
     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 		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 
    393 tryagain:
    394 	if (errno == EAGAIN) {
    395 		if (OpenProc(cp) == 0)
    396 			goto again;
    397 		ReleaseProc(cp);
    398 	}
    399 eio:
    400 	errno = EIO;
    401 	(void) mutex_unlock(&pt_lock);
    402 	return (-1);
    403 esrch:
    404 	errno = ESRCH;
    405 	(void) mutex_unlock(&pt_lock);
    406 	return (-1);
    407 }
    408 
    409 /*
    410  * Find the cstatus structure corresponding to pid.
    411  */
    412 static cstatus_t *
    413 FindProc(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  */
    428 static void
    429 CheckAllProcs()
    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  */
    445 static int
    446 Dupfd(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  */
    475 static void
    476 MakeProcName(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  */
    484 static int
    485 OpenProc(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 
    516 err:
    517 	CloseProc(cp);
    518 	return (-1);
    519 }
    520 
    521 /*
    522  * Close the /proc/<pid> files.
    523  */
    524 static void
    525 CloseProc(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  */
    541 static cstatus_t *
    542 GrabProc(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  */
    592 static void
    593 ReleaseProc(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  */
    617 static int
    618 ProcUpdate(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  */
    674 static void
    675 MakeUser(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  */
    707 static void
    708 GetPsargs(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  */
    729 static void
    730 GetSignal(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