xref: /csrg-svn/sys/kern/sys_process.c (revision 47543)
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*47543Skarels  *	@(#)sys_process.c	7.16 (Berkeley) 03/17/91
723385Smckusick  */
87426Sroot 
930376Skarels #define IPCREG
1017095Sbloom #include "param.h"
1144405Skarels #include "user.h"
1217095Sbloom #include "proc.h"
1337728Smckusick #include "vnode.h"
1417095Sbloom #include "seg.h"
1517095Sbloom #include "buf.h"
1626278Skarels #include "ptrace.h"
177426Sroot 
1837520Smckusick #include "machine/reg.h"
1937520Smckusick #include "machine/psl.h"
20*47543Skarels #include "vm/vm_page.h"
21*47543Skarels #include "vm/vm_prot.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  */
4643378Smckusick ptrace(curp, uap, retval)
4743378Smckusick 	struct proc *curp;
4843378Smckusick 	register struct args {
497501Sroot 		int	req;
507501Sroot 		int	pid;
517501Sroot 		int	*addr;
527501Sroot 		int	data;
537501Sroot 	} *uap;
5443378Smckusick 	int *retval;
5543378Smckusick {
5643378Smckusick 	register struct proc *p;
577501Sroot 
587501Sroot 	if (uap->req <= 0) {
5943378Smckusick 		curp->p_flag |= STRC;
6044405Skarels 		return (0);
617501Sroot 	}
627501Sroot 	p = pfind(uap->pid);
63*47543Skarels 	if (p == 0 || p->p_stat != SSTOP || p->p_pptr != curp ||
6443378Smckusick 	    !(p->p_flag & STRC))
6544405Skarels 		return (ESRCH);
667501Sroot 	while (ipc.ip_lock)
677501Sroot 		sleep((caddr_t)&ipc, IPCPRI);
687501Sroot 	ipc.ip_lock = p->p_pid;
697501Sroot 	ipc.ip_data = uap->data;
707501Sroot 	ipc.ip_addr = uap->addr;
717501Sroot 	ipc.ip_req = uap->req;
727501Sroot 	p->p_flag &= ~SWTED;
737501Sroot 	while (ipc.ip_req > 0) {
747501Sroot 		if (p->p_stat==SSTOP)
757501Sroot 			setrun(p);
767501Sroot 		sleep((caddr_t)&ipc, IPCPRI);
777501Sroot 	}
7843378Smckusick 	*retval = ipc.ip_data;
797501Sroot 	ipc.ip_lock = 0;
807501Sroot 	wakeup((caddr_t)&ipc);
8143378Smckusick 	if (ipc.ip_req < 0)
8244405Skarels 		return (EIO);
8344405Skarels 	return (0);
847501Sroot }
857501Sroot 
868953Sroot #define	PHYSOFF(p, o) \
878952Sroot 	((physadr)(p)+((o)/sizeof(((physadr)0)->r[0])))
8845882Swilliam #if defined(i386)
8945882Swilliam #undef        PC
9045882Swilliam #undef        SP
9145882Swilliam #undef        PS
9245882Swilliam #undef        R0
9345882Swilliam #undef        R1
948952Sroot 
9545882Swilliam #define       PC      tEIP
9645882Swilliam #define       SP      tESP
9745882Swilliam #define       PS      tEFLAGS
9845882Swilliam #define       R0      tEDX
9945882Swilliam #define       R1      tECX
10045882Swilliam #endif
10145882Swilliam 
1027501Sroot /*
1037501Sroot  * Code that the child process
1047501Sroot  * executes to implement the command
1057501Sroot  * of the parent process in tracing.
1067501Sroot  */
10742928Smckusick procxmt(p)
10842928Smckusick 	register struct proc *p;
1097501Sroot {
11042928Smckusick 	register int i, *poff;
1117501Sroot 
11242928Smckusick 	if (ipc.ip_lock != p->p_pid)
1137501Sroot 		return (0);
11442928Smckusick 	p->p_slptime = 0;
1157501Sroot 	i = ipc.ip_req;
1167501Sroot 	ipc.ip_req = 0;
1177501Sroot 	switch (i) {
1187501Sroot 
11926278Skarels 	case PT_READ_I:			/* read the child's text space */
1207501Sroot 		if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
1217501Sroot 			goto error;
1227501Sroot 		ipc.ip_data = fuiword((caddr_t)ipc.ip_addr);
1237501Sroot 		break;
1247501Sroot 
12526278Skarels 	case PT_READ_D:			/* read the child's data space */
1267501Sroot 		if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
1277501Sroot 			goto error;
1287501Sroot 		ipc.ip_data = fuword((caddr_t)ipc.ip_addr);
1297501Sroot 		break;
1307501Sroot 
13126278Skarels 	case PT_READ_U:			/* read the child's u. */
13241991Smckusick #ifdef HPUXCOMPAT
13341991Smckusick 		if (u.u_pcb.pcb_flags & PCB_HPUXTRACE)
13441991Smckusick 			i = hpuxtobsduoff(ipc.ip_addr);
13541991Smckusick 		else
13641991Smckusick #endif
1377501Sroot 		i = (int)ipc.ip_addr;
13841991Smckusick 		if (i<0 || i > ctob(UPAGES)-sizeof(int))
1397501Sroot 			goto error;
1408952Sroot 		ipc.ip_data = *(int *)PHYSOFF(&u, i);
1417501Sroot 		break;
1427501Sroot 
14326278Skarels 	case PT_WRITE_I:		/* write the child's text space */
1448952Sroot 		if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) {
14545735Smckusick 			vm_offset_t sa, ea;
14645735Smckusick 			int rv;
14745735Smckusick 
14845735Smckusick 			sa = trunc_page((vm_offset_t)ipc.ip_addr);
14945735Smckusick 			ea = round_page((vm_offset_t)ipc.ip_addr+sizeof(int)-1);
150*47543Skarels 			rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea,
15145735Smckusick 					VM_PROT_DEFAULT, FALSE);
15245735Smckusick 			if (rv == KERN_SUCCESS) {
1538952Sroot 				i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data);
154*47543Skarels 				(void) vm_map_protect(&p->p_vmspace->vm_map,
155*47543Skarels 					sa, ea, VM_PROT_READ|VM_PROT_EXECUTE,
156*47543Skarels 					FALSE);
15745735Smckusick 			}
1588952Sroot 		}
1597501Sroot 		if (i < 0)
1607501Sroot 			goto error;
1617501Sroot 		break;
1627501Sroot 
16326278Skarels 	case PT_WRITE_D:		/* write the child's data space */
1647501Sroot 		if (suword((caddr_t)ipc.ip_addr, 0) < 0)
1657501Sroot 			goto error;
1667501Sroot 		(void) suword((caddr_t)ipc.ip_addr, ipc.ip_data);
1677501Sroot 		break;
1687501Sroot 
16926278Skarels 	case PT_WRITE_U:		/* write the child's u. */
17041991Smckusick #ifdef HPUXCOMPAT
17141991Smckusick 		if (u.u_pcb.pcb_flags & PCB_HPUXTRACE)
17241991Smckusick 			i = hpuxtobsduoff(ipc.ip_addr);
17341991Smckusick 		else
17441991Smckusick #endif
1757501Sroot 		i = (int)ipc.ip_addr;
17642928Smckusick 		poff = (int *)PHYSOFF(&u, i);
1778952Sroot 		for (i=0; i<NIPCREG; i++)
178*47543Skarels 			if (poff == &p->p_regs[ipcreg[i]])
1797501Sroot 				goto ok;
180*47543Skarels 		if (poff == &p->p_regs[PS]) {
1818952Sroot 			ipc.ip_data |= PSL_USERSET;
18241991Smckusick 			ipc.ip_data &= ~PSL_USERCLR;
18332863Skarels #ifdef PSL_CM_CLR
18432863Skarels 			if (ipc.ip_data & PSL_CM)
18532863Skarels 				ipc.ip_data &= ~PSL_CM_CLR;
18632863Skarels #endif
1877501Sroot 			goto ok;
1887501Sroot 		}
18941991Smckusick #if defined(hp300)
19041991Smckusick #ifdef FPCOPROC
19142928Smckusick 		if (poff >= (int *)u.u_pcb.pcb_fpregs.fpf_regs &&
19242928Smckusick 		    poff <= (int *)&u.u_pcb.pcb_fpregs.fpf_fpiar)
19341991Smckusick 			goto ok;
19441991Smckusick #endif
19541991Smckusick #endif
1967501Sroot 		goto error;
1977501Sroot 
1987501Sroot 	ok:
19942928Smckusick 		*poff = ipc.ip_data;
2007501Sroot 		break;
2017501Sroot 
20226278Skarels 	case PT_STEP:			/* single step the child */
20326278Skarels 	case PT_CONTINUE:		/* continue the child */
2047501Sroot 		if ((int)ipc.ip_addr != 1)
205*47543Skarels 			p->p_regs[PC] = (int)ipc.ip_addr;
2067501Sroot 		if ((unsigned)ipc.ip_data > NSIG)
2077501Sroot 			goto error;
20843895Skarels 		p->p_xstat = ipc.ip_data;	/* see issig */
20926278Skarels 		if (i == PT_STEP)
210*47543Skarels 			p->p_regs[PS] |= PSL_T;
2117501Sroot 		wakeup((caddr_t)&ipc);
2127501Sroot 		return (1);
2137501Sroot 
21426278Skarels 	case PT_KILL:			/* kill the child process */
2157501Sroot 		wakeup((caddr_t)&ipc);
21645111Smckusick 		exit(p, (int)p->p_xstat);
2177501Sroot 
2187501Sroot 	default:
2197501Sroot 	error:
2207501Sroot 		ipc.ip_req = -1;
2217501Sroot 	}
2227501Sroot 	wakeup((caddr_t)&ipc);
2237501Sroot 	return (0);
2247501Sroot }
225