xref: /csrg-svn/sys/kern/sys_process.c (revision 29946)
123385Smckusick /*
229105Smckusick  * Copyright (c) 1982, 1986 Regents of the University of California.
323385Smckusick  * All rights reserved.  The Berkeley software License Agreement
423385Smckusick  * specifies the terms and conditions for redistribution.
523385Smckusick  *
6*29946Skarels  *	@(#)sys_process.c	7.2 (Berkeley) 11/03/86
723385Smckusick  */
87426Sroot 
99759Ssam #include "../machine/reg.h"
109759Ssam #include "../machine/psl.h"
119759Ssam #include "../machine/pte.h"
129759Ssam 
1317095Sbloom #include "param.h"
1417095Sbloom #include "systm.h"
1517095Sbloom #include "dir.h"
1617095Sbloom #include "user.h"
1717095Sbloom #include "proc.h"
1817095Sbloom #include "inode.h"
1917095Sbloom #include "text.h"
2017095Sbloom #include "seg.h"
2117095Sbloom #include "vm.h"
2217095Sbloom #include "buf.h"
2317095Sbloom #include "acct.h"
2426278Skarels #include "ptrace.h"
257426Sroot 
267501Sroot /*
277501Sroot  * Priority for tracing
287501Sroot  */
297501Sroot #define	IPCPRI	PZERO
307501Sroot 
317501Sroot /*
327501Sroot  * Tracing variables.
337501Sroot  * Used to pass trace command from
347501Sroot  * parent to child being traced.
357501Sroot  * This data base cannot be
367501Sroot  * shared and is locked
377501Sroot  * per user.
387501Sroot  */
397501Sroot struct {
407501Sroot 	int	ip_lock;
417501Sroot 	int	ip_req;
427501Sroot 	int	*ip_addr;
437501Sroot 	int	ip_data;
447501Sroot } ipc;
457501Sroot 
467501Sroot /*
477501Sroot  * sys-trace system call.
487501Sroot  */
497501Sroot ptrace()
507501Sroot {
517501Sroot 	register struct proc *p;
527501Sroot 	register struct a {
537501Sroot 		int	req;
547501Sroot 		int	pid;
557501Sroot 		int	*addr;
567501Sroot 		int	data;
577501Sroot 	} *uap;
587501Sroot 
597501Sroot 	uap = (struct a *)u.u_ap;
607501Sroot 	if (uap->req <= 0) {
617501Sroot 		u.u_procp->p_flag |= STRC;
627501Sroot 		return;
637501Sroot 	}
647501Sroot 	p = pfind(uap->pid);
6512496Ssam 	if (p == 0 || p->p_stat != SSTOP || p->p_ppid != u.u_procp->p_pid ||
6612496Ssam 	    !(p->p_flag & STRC)) {
677501Sroot 		u.u_error = ESRCH;
687501Sroot 		return;
697501Sroot 	}
707501Sroot 	while (ipc.ip_lock)
717501Sroot 		sleep((caddr_t)&ipc, IPCPRI);
727501Sroot 	ipc.ip_lock = p->p_pid;
737501Sroot 	ipc.ip_data = uap->data;
747501Sroot 	ipc.ip_addr = uap->addr;
757501Sroot 	ipc.ip_req = uap->req;
767501Sroot 	p->p_flag &= ~SWTED;
777501Sroot 	while (ipc.ip_req > 0) {
787501Sroot 		if (p->p_stat==SSTOP)
797501Sroot 			setrun(p);
807501Sroot 		sleep((caddr_t)&ipc, IPCPRI);
817501Sroot 	}
827501Sroot 	u.u_r.r_val1 = ipc.ip_data;
837501Sroot 	if (ipc.ip_req < 0)
847501Sroot 		u.u_error = EIO;
857501Sroot 	ipc.ip_lock = 0;
867501Sroot 	wakeup((caddr_t)&ipc);
877501Sroot }
887501Sroot 
8926278Skarels #if defined(vax)
908952Sroot #define	NIPCREG 16
918952Sroot int ipcreg[NIPCREG] =
928952Sroot 	{R0,R1,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,AP,FP,SP,PC};
938952Sroot #endif
94*29946Skarels #if defined(tahoe)
95*29946Skarels #define	NIPCREG 18
96*29946Skarels int ipcreg[NIPCREG] =
97*29946Skarels 	{R0,R1,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,R12,FP,SP,PC,RACH,RACL};
98*29946Skarels #endif
998952Sroot 
1008953Sroot #define	PHYSOFF(p, o) \
1018952Sroot 	((physadr)(p)+((o)/sizeof(((physadr)0)->r[0])))
1028952Sroot 
1037501Sroot /*
1047501Sroot  * Code that the child process
1057501Sroot  * executes to implement the command
1067501Sroot  * of the parent process in tracing.
1077501Sroot  */
1087501Sroot procxmt()
1097501Sroot {
1107501Sroot 	register int i;
1117501Sroot 	register *p;
1127501Sroot 	register struct text *xp;
1137501Sroot 
1147501Sroot 	if (ipc.ip_lock != u.u_procp->p_pid)
1157501Sroot 		return (0);
1167501Sroot 	u.u_procp->p_slptime = 0;
1177501Sroot 	i = ipc.ip_req;
1187501Sroot 	ipc.ip_req = 0;
1197501Sroot 	switch (i) {
1207501Sroot 
12126278Skarels 	case PT_READ_I:			/* read the child's text space */
1227501Sroot 		if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
1237501Sroot 			goto error;
1247501Sroot 		ipc.ip_data = fuiword((caddr_t)ipc.ip_addr);
1257501Sroot 		break;
1267501Sroot 
12726278Skarels 	case PT_READ_D:			/* read the child's data space */
1287501Sroot 		if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
1297501Sroot 			goto error;
1307501Sroot 		ipc.ip_data = fuword((caddr_t)ipc.ip_addr);
1317501Sroot 		break;
1327501Sroot 
13326278Skarels 	case PT_READ_U:			/* read the child's u. */
1347501Sroot 		i = (int)ipc.ip_addr;
1357501Sroot 		if (i<0 || i >= ctob(UPAGES))
1367501Sroot 			goto error;
1378952Sroot 		ipc.ip_data = *(int *)PHYSOFF(&u, i);
1387501Sroot 		break;
1397501Sroot 
14026278Skarels 	case PT_WRITE_I:		/* write the child's text space */
1417501Sroot 		/*
1427501Sroot 		 * If text, must assure exclusive use
1437501Sroot 		 */
1447501Sroot 		if (xp = u.u_procp->p_textp) {
1457501Sroot 			if (xp->x_count!=1 || xp->x_iptr->i_mode&ISVTX)
1467501Sroot 				goto error;
14725535Skarels 			xp->x_flag |= XTRC;
1487501Sroot 		}
1497501Sroot 		i = -1;
1508952Sroot 		if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) {
1518952Sroot 			if (chgprot((caddr_t)ipc.ip_addr, RW) &&
1528952Sroot 			    chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RW))
1538952Sroot 				i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data);
1548952Sroot 			(void) chgprot((caddr_t)ipc.ip_addr, RO);
1558952Sroot 			(void) chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RO);
1568952Sroot 		}
1577501Sroot 		if (i < 0)
1587501Sroot 			goto error;
159*29946Skarels #if defined(tahoe)
160*29946Skarels 		/* make sure the old value is not in cache */
161*29946Skarels 		ckeyrelease(u.u_procp->p_ckey);
162*29946Skarels 		u.u_procp->p_ckey = getcodekey();
163*29946Skarels #endif
164*29946Skarels 		if (xp) {
1657501Sroot 			xp->x_flag |= XWRIT;
166*29946Skarels #if defined(tahoe)
167*29946Skarels 			xp->x_ckey = u.u_procp->p_ckey;
168*29946Skarels #endif
169*29946Skarels 		}
1707501Sroot 		break;
1717501Sroot 
17226278Skarels 	case PT_WRITE_D:		/* write the child's data space */
1737501Sroot 		if (suword((caddr_t)ipc.ip_addr, 0) < 0)
1747501Sroot 			goto error;
1757501Sroot 		(void) suword((caddr_t)ipc.ip_addr, ipc.ip_data);
1767501Sroot 		break;
1777501Sroot 
17826278Skarels 	case PT_WRITE_U:		/* write the child's u. */
1797501Sroot 		i = (int)ipc.ip_addr;
1808952Sroot 		p = (int *)PHYSOFF(&u, i);
1818952Sroot 		for (i=0; i<NIPCREG; i++)
1827501Sroot 			if (p == &u.u_ar0[ipcreg[i]])
1837501Sroot 				goto ok;
1847501Sroot 		if (p == &u.u_ar0[PS]) {
1858952Sroot 			ipc.ip_data |= PSL_USERSET;
1867501Sroot 			ipc.ip_data &=  ~PSL_USERCLR;
1877501Sroot 			goto ok;
1887501Sroot 		}
1897501Sroot 		goto error;
1907501Sroot 
1917501Sroot 	ok:
1927501Sroot 		*p = ipc.ip_data;
1937501Sroot 		break;
1947501Sroot 
19526278Skarels 	case PT_STEP:			/* single step the child */
19626278Skarels 	case PT_CONTINUE:		/* continue the child */
1977501Sroot 		if ((int)ipc.ip_addr != 1)
1987501Sroot 			u.u_ar0[PC] = (int)ipc.ip_addr;
1997501Sroot 		if ((unsigned)ipc.ip_data > NSIG)
2007501Sroot 			goto error;
2017501Sroot 		u.u_procp->p_cursig = ipc.ip_data;	/* see issig */
20226278Skarels 		if (i == PT_STEP)
2037501Sroot 			u.u_ar0[PS] |= PSL_T;
2047501Sroot 		wakeup((caddr_t)&ipc);
2057501Sroot 		return (1);
2067501Sroot 
20726278Skarels 	case PT_KILL:			/* kill the child process */
2087501Sroot 		wakeup((caddr_t)&ipc);
2097501Sroot 		exit(u.u_procp->p_cursig);
2107501Sroot 
2117501Sroot 	default:
2127501Sroot 	error:
2137501Sroot 		ipc.ip_req = -1;
2147501Sroot 	}
2157501Sroot 	wakeup((caddr_t)&ipc);
2167501Sroot 	return (0);
2177501Sroot }
218