xref: /csrg-svn/sys/kern/sys_process.c (revision 45735)
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*45735Smckusick  *	@(#)sys_process.c	7.14 (Berkeley) 12/05/90
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*45735Smckusick #include "../vm/vm_page.h"
21*45735Smckusick #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);
6343378Smckusick 	if (p == 0 || p->p_stat != SSTOP || p->p_ppid != curp->p_pid ||
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])))
888952Sroot 
897501Sroot /*
907501Sroot  * Code that the child process
917501Sroot  * executes to implement the command
927501Sroot  * of the parent process in tracing.
937501Sroot  */
9442928Smckusick procxmt(p)
9542928Smckusick 	register struct proc *p;
967501Sroot {
9742928Smckusick 	register int i, *poff;
987501Sroot 
9942928Smckusick 	if (ipc.ip_lock != p->p_pid)
1007501Sroot 		return (0);
10142928Smckusick 	p->p_slptime = 0;
1027501Sroot 	i = ipc.ip_req;
1037501Sroot 	ipc.ip_req = 0;
1047501Sroot 	switch (i) {
1057501Sroot 
10626278Skarels 	case PT_READ_I:			/* read the child's text space */
1077501Sroot 		if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
1087501Sroot 			goto error;
1097501Sroot 		ipc.ip_data = fuiword((caddr_t)ipc.ip_addr);
1107501Sroot 		break;
1117501Sroot 
11226278Skarels 	case PT_READ_D:			/* read the child's data space */
1137501Sroot 		if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
1147501Sroot 			goto error;
1157501Sroot 		ipc.ip_data = fuword((caddr_t)ipc.ip_addr);
1167501Sroot 		break;
1177501Sroot 
11826278Skarels 	case PT_READ_U:			/* read the child's u. */
11941991Smckusick #ifdef HPUXCOMPAT
12041991Smckusick 		if (u.u_pcb.pcb_flags & PCB_HPUXTRACE)
12141991Smckusick 			i = hpuxtobsduoff(ipc.ip_addr);
12241991Smckusick 		else
12341991Smckusick #endif
1247501Sroot 		i = (int)ipc.ip_addr;
12541991Smckusick 		if (i<0 || i > ctob(UPAGES)-sizeof(int))
1267501Sroot 			goto error;
1278952Sroot 		ipc.ip_data = *(int *)PHYSOFF(&u, i);
1287501Sroot 		break;
1297501Sroot 
13026278Skarels 	case PT_WRITE_I:		/* write the child's text space */
1318952Sroot 		if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) {
132*45735Smckusick 			vm_offset_t sa, ea;
133*45735Smckusick 			int rv;
134*45735Smckusick 
135*45735Smckusick 			sa = trunc_page((vm_offset_t)ipc.ip_addr);
136*45735Smckusick 			ea = round_page((vm_offset_t)ipc.ip_addr+sizeof(int)-1);
137*45735Smckusick 			rv = vm_map_protect(p->p_map, sa, ea,
138*45735Smckusick 					VM_PROT_DEFAULT, FALSE);
139*45735Smckusick 			if (rv == KERN_SUCCESS) {
1408952Sroot 				i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data);
141*45735Smckusick 				(void) vm_map_protect(p->p_map, sa, ea,
142*45735Smckusick 					VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
143*45735Smckusick 			}
1448952Sroot 		}
1457501Sroot 		if (i < 0)
1467501Sroot 			goto error;
1477501Sroot 		break;
1487501Sroot 
14926278Skarels 	case PT_WRITE_D:		/* write the child's data space */
1507501Sroot 		if (suword((caddr_t)ipc.ip_addr, 0) < 0)
1517501Sroot 			goto error;
1527501Sroot 		(void) suword((caddr_t)ipc.ip_addr, ipc.ip_data);
1537501Sroot 		break;
1547501Sroot 
15526278Skarels 	case PT_WRITE_U:		/* write the child's u. */
15641991Smckusick #ifdef HPUXCOMPAT
15741991Smckusick 		if (u.u_pcb.pcb_flags & PCB_HPUXTRACE)
15841991Smckusick 			i = hpuxtobsduoff(ipc.ip_addr);
15941991Smckusick 		else
16041991Smckusick #endif
1617501Sroot 		i = (int)ipc.ip_addr;
16242928Smckusick 		poff = (int *)PHYSOFF(&u, i);
1638952Sroot 		for (i=0; i<NIPCREG; i++)
16442928Smckusick 			if (poff == &u.u_ar0[ipcreg[i]])
1657501Sroot 				goto ok;
16642928Smckusick 		if (poff == &u.u_ar0[PS]) {
1678952Sroot 			ipc.ip_data |= PSL_USERSET;
16841991Smckusick 			ipc.ip_data &= ~PSL_USERCLR;
16932863Skarels #ifdef PSL_CM_CLR
17032863Skarels 			if (ipc.ip_data & PSL_CM)
17132863Skarels 				ipc.ip_data &= ~PSL_CM_CLR;
17232863Skarels #endif
1737501Sroot 			goto ok;
1747501Sroot 		}
17541991Smckusick #if defined(hp300)
17641991Smckusick #ifdef FPCOPROC
17742928Smckusick 		if (poff >= (int *)u.u_pcb.pcb_fpregs.fpf_regs &&
17842928Smckusick 		    poff <= (int *)&u.u_pcb.pcb_fpregs.fpf_fpiar)
17941991Smckusick 			goto ok;
18041991Smckusick #endif
18141991Smckusick #endif
1827501Sroot 		goto error;
1837501Sroot 
1847501Sroot 	ok:
18542928Smckusick 		*poff = ipc.ip_data;
1867501Sroot 		break;
1877501Sroot 
18826278Skarels 	case PT_STEP:			/* single step the child */
18926278Skarels 	case PT_CONTINUE:		/* continue the child */
1907501Sroot 		if ((int)ipc.ip_addr != 1)
1917501Sroot 			u.u_ar0[PC] = (int)ipc.ip_addr;
1927501Sroot 		if ((unsigned)ipc.ip_data > NSIG)
1937501Sroot 			goto error;
19443895Skarels 		p->p_xstat = ipc.ip_data;	/* see issig */
19526278Skarels 		if (i == PT_STEP)
1967501Sroot 			u.u_ar0[PS] |= PSL_T;
1977501Sroot 		wakeup((caddr_t)&ipc);
1987501Sroot 		return (1);
1997501Sroot 
20026278Skarels 	case PT_KILL:			/* kill the child process */
2017501Sroot 		wakeup((caddr_t)&ipc);
20245111Smckusick 		exit(p, (int)p->p_xstat);
2037501Sroot 
2047501Sroot 	default:
2057501Sroot 	error:
2067501Sroot 		ipc.ip_req = -1;
2077501Sroot 	}
2087501Sroot 	wakeup((caddr_t)&ipc);
2097501Sroot 	return (0);
2107501Sroot }
211