xref: /csrg-svn/sys/kern/sys_process.c (revision 49589)
1*49589Sbostic /*-
2*49589Sbostic  * Copyright (c) 1982, 1986, 1989 The Regents of the University of California.
3*49589Sbostic  * All rights reserved.
423385Smckusick  *
5*49589Sbostic  * %sccs.include.proprietary.c%
6*49589Sbostic  *
7*49589Sbostic  *	@(#)sys_process.c	7.21 (Berkeley) 05/09/91
823385Smckusick  */
97426Sroot 
1030376Skarels #define IPCREG
1117095Sbloom #include "param.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"
2048438Skarels #include "vm/vm.h"
2147543Skarels #include "vm/vm_page.h"
2237520Smckusick 
2348438Skarels #include "user.h"
2448438Skarels 
257501Sroot /*
267501Sroot  * Priority for tracing
277501Sroot  */
287501Sroot #define	IPCPRI	PZERO
297501Sroot 
307501Sroot /*
317501Sroot  * Tracing variables.
327501Sroot  * Used to pass trace command from
337501Sroot  * parent to child being traced.
347501Sroot  * This data base cannot be
357501Sroot  * shared and is locked
367501Sroot  * per user.
377501Sroot  */
387501Sroot struct {
397501Sroot 	int	ip_lock;
407501Sroot 	int	ip_req;
417501Sroot 	int	*ip_addr;
427501Sroot 	int	ip_data;
437501Sroot } ipc;
447501Sroot 
457501Sroot /*
467501Sroot  * sys-trace system call.
477501Sroot  */
4843378Smckusick ptrace(curp, uap, retval)
4943378Smckusick 	struct proc *curp;
5043378Smckusick 	register struct args {
517501Sroot 		int	req;
527501Sroot 		int	pid;
537501Sroot 		int	*addr;
547501Sroot 		int	data;
557501Sroot 	} *uap;
5643378Smckusick 	int *retval;
5743378Smckusick {
5843378Smckusick 	register struct proc *p;
597501Sroot 
607501Sroot 	if (uap->req <= 0) {
6143378Smckusick 		curp->p_flag |= STRC;
6244405Skarels 		return (0);
637501Sroot 	}
647501Sroot 	p = pfind(uap->pid);
6547543Skarels 	if (p == 0 || p->p_stat != SSTOP || p->p_pptr != curp ||
6643378Smckusick 	    !(p->p_flag & STRC))
6744405Skarels 		return (ESRCH);
687501Sroot 	while (ipc.ip_lock)
697501Sroot 		sleep((caddr_t)&ipc, IPCPRI);
707501Sroot 	ipc.ip_lock = p->p_pid;
717501Sroot 	ipc.ip_data = uap->data;
727501Sroot 	ipc.ip_addr = uap->addr;
737501Sroot 	ipc.ip_req = uap->req;
747501Sroot 	p->p_flag &= ~SWTED;
757501Sroot 	while (ipc.ip_req > 0) {
767501Sroot 		if (p->p_stat==SSTOP)
777501Sroot 			setrun(p);
787501Sroot 		sleep((caddr_t)&ipc, IPCPRI);
797501Sroot 	}
8043378Smckusick 	*retval = ipc.ip_data;
817501Sroot 	ipc.ip_lock = 0;
827501Sroot 	wakeup((caddr_t)&ipc);
8343378Smckusick 	if (ipc.ip_req < 0)
8444405Skarels 		return (EIO);
8544405Skarels 	return (0);
867501Sroot }
877501Sroot 
8849246Skarels #define	PHYSOFF(p, o) ((caddr_t)(p) + (o))
8949246Skarels 
9045882Swilliam #if defined(i386)
9145882Swilliam #undef        PC
9245882Swilliam #undef        SP
9345882Swilliam #undef        PS
9445882Swilliam #undef        R0
9545882Swilliam #undef        R1
968952Sroot 
9745882Swilliam #define       PC      tEIP
9845882Swilliam #define       SP      tESP
9945882Swilliam #define       PS      tEFLAGS
10045882Swilliam #define       R0      tEDX
10145882Swilliam #define       R1      tECX
10245882Swilliam #endif
10345882Swilliam 
1047501Sroot /*
1057501Sroot  * Code that the child process
1067501Sroot  * executes to implement the command
1077501Sroot  * of the parent process in tracing.
1087501Sroot  */
10942928Smckusick procxmt(p)
11042928Smckusick 	register struct proc *p;
1117501Sroot {
11242928Smckusick 	register int i, *poff;
11349246Skarels 	extern char kstack[];
1147501Sroot 
11542928Smckusick 	if (ipc.ip_lock != p->p_pid)
1167501Sroot 		return (0);
11742928Smckusick 	p->p_slptime = 0;
11849101Skarels 	p->p_addr->u_kproc.kp_proc.p_regs = p->p_regs;	/* u.u_ar0 */
1197501Sroot 	i = ipc.ip_req;
1207501Sroot 	ipc.ip_req = 0;
1217501Sroot 	switch (i) {
1227501Sroot 
12326278Skarels 	case PT_READ_I:			/* read the child's text space */
1247501Sroot 		if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
1257501Sroot 			goto error;
1267501Sroot 		ipc.ip_data = fuiword((caddr_t)ipc.ip_addr);
1277501Sroot 		break;
1287501Sroot 
12926278Skarels 	case PT_READ_D:			/* read the child's data space */
1307501Sroot 		if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
1317501Sroot 			goto error;
1327501Sroot 		ipc.ip_data = fuword((caddr_t)ipc.ip_addr);
1337501Sroot 		break;
1347501Sroot 
13526278Skarels 	case PT_READ_U:			/* read the child's u. */
13641991Smckusick #ifdef HPUXCOMPAT
13749101Skarels 		if (p->p_addr->u_pcb.pcb_flags & PCB_HPUXTRACE)
13841991Smckusick 			i = hpuxtobsduoff(ipc.ip_addr);
13941991Smckusick 		else
14041991Smckusick #endif
1417501Sroot 		i = (int)ipc.ip_addr;
14249246Skarels 		if ((u_int) i > ctob(UPAGES)-sizeof(int) || (i & 1) != 0)
1437501Sroot 			goto error;
14449101Skarels 		ipc.ip_data = *(int *)PHYSOFF(p->p_addr, i);
1457501Sroot 		break;
1467501Sroot 
14726278Skarels 	case PT_WRITE_I:		/* write the child's text space */
1488952Sroot 		if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) {
14945735Smckusick 			vm_offset_t sa, ea;
15045735Smckusick 			int rv;
15145735Smckusick 
15245735Smckusick 			sa = trunc_page((vm_offset_t)ipc.ip_addr);
15345735Smckusick 			ea = round_page((vm_offset_t)ipc.ip_addr+sizeof(int)-1);
15447543Skarels 			rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea,
15545735Smckusick 					VM_PROT_DEFAULT, FALSE);
15645735Smckusick 			if (rv == KERN_SUCCESS) {
1578952Sroot 				i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data);
15847543Skarels 				(void) vm_map_protect(&p->p_vmspace->vm_map,
15947543Skarels 					sa, ea, VM_PROT_READ|VM_PROT_EXECUTE,
16047543Skarels 					FALSE);
16145735Smckusick 			}
1628952Sroot 		}
1637501Sroot 		if (i < 0)
1647501Sroot 			goto error;
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. */
17441991Smckusick #ifdef HPUXCOMPAT
17549101Skarels 		if (p->p_addr->u_pcb.pcb_flags & PCB_HPUXTRACE)
17641991Smckusick 			i = hpuxtobsduoff(ipc.ip_addr);
17741991Smckusick 		else
17841991Smckusick #endif
1797501Sroot 		i = (int)ipc.ip_addr;
18049246Skarels 		poff = (int *)PHYSOFF(kstack, i);
1818952Sroot 		for (i=0; i<NIPCREG; i++)
18247543Skarels 			if (poff == &p->p_regs[ipcreg[i]])
1837501Sroot 				goto ok;
18447543Skarels 		if (poff == &p->p_regs[PS]) {
1858952Sroot 			ipc.ip_data |= PSL_USERSET;
18641991Smckusick 			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 		}
19341991Smckusick #if defined(hp300)
19441991Smckusick #ifdef FPCOPROC
19549246Skarels 		if (poff >= (int *)&((struct user *)kstack)->u_pcb.pcb_fpregs.fpf_regs &&
19649246Skarels 		    poff <= (int *)&((struct user *)kstack)->u_pcb.pcb_fpregs.fpf_fpiar)
19741991Smckusick 			goto ok;
19841991Smckusick #endif
19941991Smckusick #endif
2007501Sroot 		goto error;
2017501Sroot 
2027501Sroot 	ok:
20342928Smckusick 		*poff = 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)
20947543Skarels 			p->p_regs[PC] = (int)ipc.ip_addr;
2107501Sroot 		if ((unsigned)ipc.ip_data > NSIG)
2117501Sroot 			goto error;
21243895Skarels 		p->p_xstat = ipc.ip_data;	/* see issig */
21326278Skarels 		if (i == PT_STEP)
21447543Skarels 			p->p_regs[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);
22045111Smckusick 		exit(p, (int)p->p_xstat);
2217501Sroot 
2227501Sroot 	default:
2237501Sroot 	error:
2247501Sroot 		ipc.ip_req = -1;
2257501Sroot 	}
2267501Sroot 	wakeup((caddr_t)&ipc);
2277501Sroot 	return (0);
2287501Sroot }
22949534Smckusick 
23049534Smckusick /* ARGSUSED */
23149534Smckusick profil(p, uap, retval)
23249534Smckusick 	struct proc *p;
23349534Smckusick 	register struct args {
23449534Smckusick 		short	*bufbase;
23549534Smckusick 		unsigned bufsize;
23649534Smckusick 		unsigned pcoffset;
23749534Smckusick 		unsigned pcscale;
23849534Smckusick 	} *uap;
23949534Smckusick 	int *retval;
24049534Smckusick {
24149534Smckusick 	register struct uprof *upp = &p->p_stats->p_prof;
24249534Smckusick 
24349534Smckusick 	upp->pr_base = uap->bufbase;
24449534Smckusick 	upp->pr_size = uap->bufsize;
24549534Smckusick 	upp->pr_off = uap->pcoffset;
24649534Smckusick 	upp->pr_scale = uap->pcscale;
24749534Smckusick #ifdef PROFTIMER
24849534Smckusick 	initprofclock();
24949534Smckusick #endif
25049534Smckusick 	return (0);
25149534Smckusick }
252