xref: /csrg-svn/sys/kern/sys_process.c (revision 48438)
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*48438Skarels  *	@(#)sys_process.c	7.17 (Berkeley) 04/20/91
723385Smckusick  */
87426Sroot 
930376Skarels #define IPCREG
1017095Sbloom #include "param.h"
1117095Sbloom #include "proc.h"
1237728Smckusick #include "vnode.h"
1317095Sbloom #include "seg.h"
1417095Sbloom #include "buf.h"
1526278Skarels #include "ptrace.h"
167426Sroot 
1737520Smckusick #include "machine/reg.h"
1837520Smckusick #include "machine/psl.h"
19*48438Skarels #include "vm/vm.h"
2047543Skarels #include "vm/vm_page.h"
2137520Smckusick 
22*48438Skarels #include "user.h"
23*48438Skarels 
247501Sroot /*
257501Sroot  * Priority for tracing
267501Sroot  */
277501Sroot #define	IPCPRI	PZERO
287501Sroot 
297501Sroot /*
307501Sroot  * Tracing variables.
317501Sroot  * Used to pass trace command from
327501Sroot  * parent to child being traced.
337501Sroot  * This data base cannot be
347501Sroot  * shared and is locked
357501Sroot  * per user.
367501Sroot  */
377501Sroot struct {
387501Sroot 	int	ip_lock;
397501Sroot 	int	ip_req;
407501Sroot 	int	*ip_addr;
417501Sroot 	int	ip_data;
427501Sroot } ipc;
437501Sroot 
447501Sroot /*
457501Sroot  * sys-trace system call.
467501Sroot  */
4743378Smckusick ptrace(curp, uap, retval)
4843378Smckusick 	struct proc *curp;
4943378Smckusick 	register struct args {
507501Sroot 		int	req;
517501Sroot 		int	pid;
527501Sroot 		int	*addr;
537501Sroot 		int	data;
547501Sroot 	} *uap;
5543378Smckusick 	int *retval;
5643378Smckusick {
5743378Smckusick 	register struct proc *p;
587501Sroot 
597501Sroot 	if (uap->req <= 0) {
6043378Smckusick 		curp->p_flag |= STRC;
6144405Skarels 		return (0);
627501Sroot 	}
637501Sroot 	p = pfind(uap->pid);
6447543Skarels 	if (p == 0 || p->p_stat != SSTOP || p->p_pptr != curp ||
6543378Smckusick 	    !(p->p_flag & STRC))
6644405Skarels 		return (ESRCH);
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 	}
7943378Smckusick 	*retval = ipc.ip_data;
807501Sroot 	ipc.ip_lock = 0;
817501Sroot 	wakeup((caddr_t)&ipc);
8243378Smckusick 	if (ipc.ip_req < 0)
8344405Skarels 		return (EIO);
8444405Skarels 	return (0);
857501Sroot }
867501Sroot 
878953Sroot #define	PHYSOFF(p, o) \
888952Sroot 	((physadr)(p)+((o)/sizeof(((physadr)0)->r[0])))
8945882Swilliam #if defined(i386)
9045882Swilliam #undef        PC
9145882Swilliam #undef        SP
9245882Swilliam #undef        PS
9345882Swilliam #undef        R0
9445882Swilliam #undef        R1
958952Sroot 
9645882Swilliam #define       PC      tEIP
9745882Swilliam #define       SP      tESP
9845882Swilliam #define       PS      tEFLAGS
9945882Swilliam #define       R0      tEDX
10045882Swilliam #define       R1      tECX
10145882Swilliam #endif
10245882Swilliam 
1037501Sroot /*
1047501Sroot  * Code that the child process
1057501Sroot  * executes to implement the command
1067501Sroot  * of the parent process in tracing.
1077501Sroot  */
10842928Smckusick procxmt(p)
10942928Smckusick 	register struct proc *p;
1107501Sroot {
11142928Smckusick 	register int i, *poff;
1127501Sroot 
11342928Smckusick 	if (ipc.ip_lock != p->p_pid)
1147501Sroot 		return (0);
11542928Smckusick 	p->p_slptime = 0;
116*48438Skarels 	u.u_kproc.kp_proc.p_regs = p->p_regs;	/* u.u_ar0 */
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. */
13441991Smckusick #ifdef HPUXCOMPAT
13541991Smckusick 		if (u.u_pcb.pcb_flags & PCB_HPUXTRACE)
13641991Smckusick 			i = hpuxtobsduoff(ipc.ip_addr);
13741991Smckusick 		else
13841991Smckusick #endif
1397501Sroot 		i = (int)ipc.ip_addr;
14041991Smckusick 		if (i<0 || i > ctob(UPAGES)-sizeof(int))
1417501Sroot 			goto error;
1428952Sroot 		ipc.ip_data = *(int *)PHYSOFF(&u, i);
1437501Sroot 		break;
1447501Sroot 
14526278Skarels 	case PT_WRITE_I:		/* write the child's text space */
1468952Sroot 		if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) {
14745735Smckusick 			vm_offset_t sa, ea;
14845735Smckusick 			int rv;
14945735Smckusick 
15045735Smckusick 			sa = trunc_page((vm_offset_t)ipc.ip_addr);
15145735Smckusick 			ea = round_page((vm_offset_t)ipc.ip_addr+sizeof(int)-1);
15247543Skarels 			rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea,
15345735Smckusick 					VM_PROT_DEFAULT, FALSE);
15445735Smckusick 			if (rv == KERN_SUCCESS) {
1558952Sroot 				i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data);
15647543Skarels 				(void) vm_map_protect(&p->p_vmspace->vm_map,
15747543Skarels 					sa, ea, VM_PROT_READ|VM_PROT_EXECUTE,
15847543Skarels 					FALSE);
15945735Smckusick 			}
1608952Sroot 		}
1617501Sroot 		if (i < 0)
1627501Sroot 			goto error;
1637501Sroot 		break;
1647501Sroot 
16526278Skarels 	case PT_WRITE_D:		/* write the child's data space */
1667501Sroot 		if (suword((caddr_t)ipc.ip_addr, 0) < 0)
1677501Sroot 			goto error;
1687501Sroot 		(void) suword((caddr_t)ipc.ip_addr, ipc.ip_data);
1697501Sroot 		break;
1707501Sroot 
17126278Skarels 	case PT_WRITE_U:		/* write the child's u. */
17241991Smckusick #ifdef HPUXCOMPAT
17341991Smckusick 		if (u.u_pcb.pcb_flags & PCB_HPUXTRACE)
17441991Smckusick 			i = hpuxtobsduoff(ipc.ip_addr);
17541991Smckusick 		else
17641991Smckusick #endif
1777501Sroot 		i = (int)ipc.ip_addr;
17842928Smckusick 		poff = (int *)PHYSOFF(&u, i);
1798952Sroot 		for (i=0; i<NIPCREG; i++)
18047543Skarels 			if (poff == &p->p_regs[ipcreg[i]])
1817501Sroot 				goto ok;
18247543Skarels 		if (poff == &p->p_regs[PS]) {
1838952Sroot 			ipc.ip_data |= PSL_USERSET;
18441991Smckusick 			ipc.ip_data &= ~PSL_USERCLR;
18532863Skarels #ifdef PSL_CM_CLR
18632863Skarels 			if (ipc.ip_data & PSL_CM)
18732863Skarels 				ipc.ip_data &= ~PSL_CM_CLR;
18832863Skarels #endif
1897501Sroot 			goto ok;
1907501Sroot 		}
19141991Smckusick #if defined(hp300)
19241991Smckusick #ifdef FPCOPROC
19342928Smckusick 		if (poff >= (int *)u.u_pcb.pcb_fpregs.fpf_regs &&
19442928Smckusick 		    poff <= (int *)&u.u_pcb.pcb_fpregs.fpf_fpiar)
19541991Smckusick 			goto ok;
19641991Smckusick #endif
19741991Smckusick #endif
1987501Sroot 		goto error;
1997501Sroot 
2007501Sroot 	ok:
20142928Smckusick 		*poff = ipc.ip_data;
2027501Sroot 		break;
2037501Sroot 
20426278Skarels 	case PT_STEP:			/* single step the child */
20526278Skarels 	case PT_CONTINUE:		/* continue the child */
2067501Sroot 		if ((int)ipc.ip_addr != 1)
20747543Skarels 			p->p_regs[PC] = (int)ipc.ip_addr;
2087501Sroot 		if ((unsigned)ipc.ip_data > NSIG)
2097501Sroot 			goto error;
21043895Skarels 		p->p_xstat = ipc.ip_data;	/* see issig */
21126278Skarels 		if (i == PT_STEP)
21247543Skarels 			p->p_regs[PS] |= PSL_T;
2137501Sroot 		wakeup((caddr_t)&ipc);
2147501Sroot 		return (1);
2157501Sroot 
21626278Skarels 	case PT_KILL:			/* kill the child process */
2177501Sroot 		wakeup((caddr_t)&ipc);
21845111Smckusick 		exit(p, (int)p->p_xstat);
2197501Sroot 
2207501Sroot 	default:
2217501Sroot 	error:
2227501Sroot 		ipc.ip_req = -1;
2237501Sroot 	}
2247501Sroot 	wakeup((caddr_t)&ipc);
2257501Sroot 	return (0);
2267501Sroot }
227