xref: /csrg-svn/sys/kern/sys_process.c (revision 41991)
123385Smckusick /*
237728Smckusick  * Copyright (c) 1982, 1986, 1989 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*41991Smckusick  *	@(#)sys_process.c	7.7 (Berkeley) 05/15/90
723385Smckusick  */
87426Sroot 
930376Skarels #define IPCREG
1017095Sbloom #include "param.h"
1117095Sbloom #include "user.h"
1217095Sbloom #include "proc.h"
1337728Smckusick #include "vnode.h"
1417095Sbloom #include "text.h"
1517095Sbloom #include "seg.h"
1617095Sbloom #include "buf.h"
1726278Skarels #include "ptrace.h"
187426Sroot 
1937520Smckusick #include "machine/reg.h"
2037520Smckusick #include "machine/psl.h"
2137520Smckusick #include "machine/pte.h"
2237520Smckusick 
237501Sroot /*
247501Sroot  * Priority for tracing
257501Sroot  */
267501Sroot #define	IPCPRI	PZERO
277501Sroot 
287501Sroot /*
297501Sroot  * Tracing variables.
307501Sroot  * Used to pass trace command from
317501Sroot  * parent to child being traced.
327501Sroot  * This data base cannot be
337501Sroot  * shared and is locked
347501Sroot  * per user.
357501Sroot  */
367501Sroot struct {
377501Sroot 	int	ip_lock;
387501Sroot 	int	ip_req;
397501Sroot 	int	*ip_addr;
407501Sroot 	int	ip_data;
417501Sroot } ipc;
427501Sroot 
437501Sroot /*
447501Sroot  * sys-trace system call.
457501Sroot  */
467501Sroot ptrace()
477501Sroot {
487501Sroot 	register struct proc *p;
497501Sroot 	register struct a {
507501Sroot 		int	req;
517501Sroot 		int	pid;
527501Sroot 		int	*addr;
537501Sroot 		int	data;
547501Sroot 	} *uap;
557501Sroot 
567501Sroot 	uap = (struct a *)u.u_ap;
577501Sroot 	if (uap->req <= 0) {
587501Sroot 		u.u_procp->p_flag |= STRC;
597501Sroot 		return;
607501Sroot 	}
617501Sroot 	p = pfind(uap->pid);
6212496Ssam 	if (p == 0 || p->p_stat != SSTOP || p->p_ppid != u.u_procp->p_pid ||
6312496Ssam 	    !(p->p_flag & STRC)) {
647501Sroot 		u.u_error = ESRCH;
657501Sroot 		return;
667501Sroot 	}
677501Sroot 	while (ipc.ip_lock)
687501Sroot 		sleep((caddr_t)&ipc, IPCPRI);
697501Sroot 	ipc.ip_lock = p->p_pid;
707501Sroot 	ipc.ip_data = uap->data;
717501Sroot 	ipc.ip_addr = uap->addr;
727501Sroot 	ipc.ip_req = uap->req;
737501Sroot 	p->p_flag &= ~SWTED;
747501Sroot 	while (ipc.ip_req > 0) {
757501Sroot 		if (p->p_stat==SSTOP)
767501Sroot 			setrun(p);
777501Sroot 		sleep((caddr_t)&ipc, IPCPRI);
787501Sroot 	}
797501Sroot 	u.u_r.r_val1 = ipc.ip_data;
807501Sroot 	if (ipc.ip_req < 0)
817501Sroot 		u.u_error = EIO;
827501Sroot 	ipc.ip_lock = 0;
837501Sroot 	wakeup((caddr_t)&ipc);
847501Sroot }
857501Sroot 
868953Sroot #define	PHYSOFF(p, o) \
878952Sroot 	((physadr)(p)+((o)/sizeof(((physadr)0)->r[0])))
888952Sroot 
897501Sroot /*
907501Sroot  * Code that the child process
917501Sroot  * executes to implement the command
927501Sroot  * of the parent process in tracing.
937501Sroot  */
947501Sroot procxmt()
957501Sroot {
967501Sroot 	register int i;
977501Sroot 	register *p;
987501Sroot 	register struct text *xp;
9937728Smckusick 	struct vattr vattr;
10037728Smckusick 	struct vnode *vp;
1017501Sroot 
1027501Sroot 	if (ipc.ip_lock != u.u_procp->p_pid)
1037501Sroot 		return (0);
1047501Sroot 	u.u_procp->p_slptime = 0;
1057501Sroot 	i = ipc.ip_req;
1067501Sroot 	ipc.ip_req = 0;
1077501Sroot 	switch (i) {
1087501Sroot 
10926278Skarels 	case PT_READ_I:			/* read the child's text space */
1107501Sroot 		if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
1117501Sroot 			goto error;
1127501Sroot 		ipc.ip_data = fuiword((caddr_t)ipc.ip_addr);
1137501Sroot 		break;
1147501Sroot 
11526278Skarels 	case PT_READ_D:			/* read the child's data space */
1167501Sroot 		if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
1177501Sroot 			goto error;
1187501Sroot 		ipc.ip_data = fuword((caddr_t)ipc.ip_addr);
1197501Sroot 		break;
1207501Sroot 
12126278Skarels 	case PT_READ_U:			/* read the child's u. */
122*41991Smckusick #ifdef HPUXCOMPAT
123*41991Smckusick 		if (u.u_pcb.pcb_flags & PCB_HPUXTRACE)
124*41991Smckusick 			i = hpuxtobsduoff(ipc.ip_addr);
125*41991Smckusick 		else
126*41991Smckusick #endif
1277501Sroot 		i = (int)ipc.ip_addr;
128*41991Smckusick 		if (i<0 || i > ctob(UPAGES)-sizeof(int))
1297501Sroot 			goto error;
1308952Sroot 		ipc.ip_data = *(int *)PHYSOFF(&u, i);
1317501Sroot 		break;
1327501Sroot 
13326278Skarels 	case PT_WRITE_I:		/* write the child's text space */
1347501Sroot 		/*
1357501Sroot 		 * If text, must assure exclusive use
1367501Sroot 		 */
1377501Sroot 		if (xp = u.u_procp->p_textp) {
13837728Smckusick 			vp = xp->x_vptr;
13937728Smckusick 			VOP_GETATTR(vp, &vattr, u.u_cred);
14037728Smckusick 			if (xp->x_count!=1 || (vattr.va_mode & VSVTX))
1417501Sroot 				goto error;
14225535Skarels 			xp->x_flag |= XTRC;
1437501Sroot 		}
1447501Sroot 		i = -1;
1458952Sroot 		if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) {
1468952Sroot 			if (chgprot((caddr_t)ipc.ip_addr, RW) &&
1478952Sroot 			    chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RW))
1488952Sroot 				i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data);
1498952Sroot 			(void) chgprot((caddr_t)ipc.ip_addr, RO);
1508952Sroot 			(void) chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RO);
1518952Sroot 		}
1527501Sroot 		if (i < 0)
1537501Sroot 			goto error;
15429946Skarels #if defined(tahoe)
15529946Skarels 		/* make sure the old value is not in cache */
15629946Skarels 		ckeyrelease(u.u_procp->p_ckey);
15729946Skarels 		u.u_procp->p_ckey = getcodekey();
15829946Skarels #endif
15929946Skarels 		if (xp) {
1607501Sroot 			xp->x_flag |= XWRIT;
16129946Skarels #if defined(tahoe)
16229946Skarels 			xp->x_ckey = u.u_procp->p_ckey;
16329946Skarels #endif
16429946Skarels 		}
1657501Sroot 		break;
1667501Sroot 
16726278Skarels 	case PT_WRITE_D:		/* write the child's data space */
1687501Sroot 		if (suword((caddr_t)ipc.ip_addr, 0) < 0)
1697501Sroot 			goto error;
1707501Sroot 		(void) suword((caddr_t)ipc.ip_addr, ipc.ip_data);
1717501Sroot 		break;
1727501Sroot 
17326278Skarels 	case PT_WRITE_U:		/* write the child's u. */
174*41991Smckusick #ifdef HPUXCOMPAT
175*41991Smckusick 		if (u.u_pcb.pcb_flags & PCB_HPUXTRACE)
176*41991Smckusick 			i = hpuxtobsduoff(ipc.ip_addr);
177*41991Smckusick 		else
178*41991Smckusick #endif
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;
186*41991Smckusick 			ipc.ip_data &= ~PSL_USERCLR;
18732863Skarels #ifdef PSL_CM_CLR
18832863Skarels 			if (ipc.ip_data & PSL_CM)
18932863Skarels 				ipc.ip_data &= ~PSL_CM_CLR;
19032863Skarels #endif
1917501Sroot 			goto ok;
1927501Sroot 		}
193*41991Smckusick #if defined(hp300)
194*41991Smckusick #ifdef FPCOPROC
195*41991Smckusick 		if (p >= (int *)u.u_pcb.pcb_fpregs.fpf_regs &&
196*41991Smckusick 		    p <= (int *)&u.u_pcb.pcb_fpregs.fpf_fpiar)
197*41991Smckusick 			goto ok;
198*41991Smckusick #endif
199*41991Smckusick #endif
2007501Sroot 		goto error;
2017501Sroot 
2027501Sroot 	ok:
2037501Sroot 		*p = ipc.ip_data;
2047501Sroot 		break;
2057501Sroot 
20626278Skarels 	case PT_STEP:			/* single step the child */
20726278Skarels 	case PT_CONTINUE:		/* continue the child */
2087501Sroot 		if ((int)ipc.ip_addr != 1)
2097501Sroot 			u.u_ar0[PC] = (int)ipc.ip_addr;
2107501Sroot 		if ((unsigned)ipc.ip_data > NSIG)
2117501Sroot 			goto error;
2127501Sroot 		u.u_procp->p_cursig = ipc.ip_data;	/* see issig */
21326278Skarels 		if (i == PT_STEP)
2147501Sroot 			u.u_ar0[PS] |= PSL_T;
2157501Sroot 		wakeup((caddr_t)&ipc);
2167501Sroot 		return (1);
2177501Sroot 
21826278Skarels 	case PT_KILL:			/* kill the child process */
2197501Sroot 		wakeup((caddr_t)&ipc);
2207501Sroot 		exit(u.u_procp->p_cursig);
2217501Sroot 
2227501Sroot 	default:
2237501Sroot 	error:
2247501Sroot 		ipc.ip_req = -1;
2257501Sroot 	}
2267501Sroot 	wakeup((caddr_t)&ipc);
2277501Sroot 	return (0);
2287501Sroot }
229