xref: /original-bsd/sys/kern/sys_process.c (revision 68549010)
1 /*-
2  * Copyright (c) 1982, 1986, 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.proprietary.c%
6  *
7  *	@(#)sys_process.c	7.24 (Berkeley) 02/05/92
8  */
9 
10 #define IPCREG
11 #include "param.h"
12 #include "proc.h"
13 #include "vnode.h"
14 #include "buf.h"
15 #include "ptrace.h"
16 
17 #include "machine/reg.h"
18 #include "machine/psl.h"
19 #include "vm/vm.h"
20 #include "vm/vm_page.h"
21 
22 #include "user.h"
23 
24 /*
25  * Priority for tracing
26  */
27 #define	IPCPRI	PZERO
28 
29 /*
30  * Tracing variables.
31  * Used to pass trace command from
32  * parent to child being traced.
33  * This data base cannot be
34  * shared and is locked
35  * per user.
36  */
37 struct {
38 	int	ip_lock;
39 	int	ip_req;
40 	int	*ip_addr;
41 	int	ip_data;
42 } ipc;
43 
44 /*
45  * Process debugging system call.
46  */
47 ptrace(curp, uap, retval)
48 	struct proc *curp;
49 	register struct args {
50 		int	req;
51 		int	pid;
52 		int	*addr;
53 		int	data;
54 	} *uap;
55 	int *retval;
56 {
57 	register struct proc *p;
58 
59 	if (uap->req <= 0) {
60 		curp->p_flag |= STRC;
61 		return (0);
62 	}
63 	p = pfind(uap->pid);
64 	if (p == 0 || p->p_stat != SSTOP || p->p_pptr != curp ||
65 	    !(p->p_flag & STRC))
66 		return (ESRCH);
67 	while (ipc.ip_lock)
68 		sleep((caddr_t)&ipc, IPCPRI);
69 	ipc.ip_lock = p->p_pid;
70 	ipc.ip_data = uap->data;
71 	ipc.ip_addr = uap->addr;
72 	ipc.ip_req = uap->req;
73 	p->p_flag &= ~SWTED;
74 	while (ipc.ip_req > 0) {
75 		if (p->p_stat==SSTOP)
76 			setrun(p);
77 		sleep((caddr_t)&ipc, IPCPRI);
78 	}
79 	*retval = ipc.ip_data;
80 	ipc.ip_lock = 0;
81 	wakeup((caddr_t)&ipc);
82 	if (ipc.ip_req < 0)
83 		return (EIO);
84 	return (0);
85 }
86 
87 #define	PHYSOFF(p, o) ((caddr_t)(p) + (o))
88 
89 #if defined(i386)
90 #undef        PC
91 #undef        SP
92 #undef        PS
93 #undef        R0
94 #undef        R1
95 
96 #define       PC      tEIP
97 #define       SP      tESP
98 #define       PS      tEFLAGS
99 #define       R0      tEDX
100 #define       R1      tECX
101 #endif
102 
103 /*
104  * Transmit a tracing request from the parent to the child process
105  * being debugged. This code runs in the context of the child process
106  * to fulfill the command requested by the parent.
107  */
108 procxmt(p)
109 	register struct proc *p;
110 {
111 	register int i, *poff;
112 	extern char kstack[];
113 
114 	if (ipc.ip_lock != p->p_pid)
115 		return (0);
116 	p->p_slptime = 0;
117 	p->p_addr->u_kproc.kp_proc.p_md.md_regs = p->p_md.md_regs; /* u.u_ar0 */
118 	i = ipc.ip_req;
119 	ipc.ip_req = 0;
120 	switch (i) {
121 
122 	case PT_READ_I:			/* read the child's text space */
123 		if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
124 			goto error;
125 		ipc.ip_data = fuiword((caddr_t)ipc.ip_addr);
126 		break;
127 
128 	case PT_READ_D:			/* read the child's data space */
129 		if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
130 			goto error;
131 		ipc.ip_data = fuword((caddr_t)ipc.ip_addr);
132 		break;
133 
134 	case PT_READ_U:			/* read the child's u. */
135 #ifdef HPUXCOMPAT
136 		if (p->p_addr->u_pcb.pcb_flags & PCB_HPUXTRACE)
137 			i = hpuxtobsduoff(ipc.ip_addr);
138 		else
139 #endif
140 		i = (int)ipc.ip_addr;
141 		if ((u_int) i > ctob(UPAGES)-sizeof(int) || (i & 1) != 0)
142 			goto error;
143 		ipc.ip_data = *(int *)PHYSOFF(p->p_addr, i);
144 		break;
145 
146 	case PT_WRITE_I:		/* write the child's text space */
147 		if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) {
148 			vm_offset_t sa, ea;
149 			int rv;
150 
151 			sa = trunc_page((vm_offset_t)ipc.ip_addr);
152 			ea = round_page((vm_offset_t)ipc.ip_addr+sizeof(int)-1);
153 			rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea,
154 					VM_PROT_DEFAULT, FALSE);
155 			if (rv == KERN_SUCCESS) {
156 				i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data);
157 				(void) vm_map_protect(&p->p_vmspace->vm_map,
158 					sa, ea, VM_PROT_READ|VM_PROT_EXECUTE,
159 					FALSE);
160 			}
161 		}
162 		if (i < 0)
163 			goto error;
164 		break;
165 
166 	case PT_WRITE_D:		/* write the child's data space */
167 		if (suword((caddr_t)ipc.ip_addr, 0) < 0)
168 			goto error;
169 		(void) suword((caddr_t)ipc.ip_addr, ipc.ip_data);
170 		break;
171 
172 	case PT_WRITE_U:		/* write the child's u. */
173 #ifdef HPUXCOMPAT
174 		if (p->p_addr->u_pcb.pcb_flags & PCB_HPUXTRACE)
175 			i = hpuxtobsduoff(ipc.ip_addr);
176 		else
177 #endif
178 		i = (int)ipc.ip_addr;
179 #ifdef mips
180 		poff = (int *)PHYSOFF(curproc->p_addr, i);
181 #else
182 		poff = (int *)PHYSOFF(kstack, i);
183 #endif
184 		for (i=0; i<NIPCREG; i++)
185 			if (poff == &p->p_md.md_regs[ipcreg[i]])
186 				goto ok;
187 		if (poff == &p->p_md.md_regs[PS]) {
188 			ipc.ip_data |= PSL_USERSET;
189 			ipc.ip_data &= ~PSL_USERCLR;
190 #ifdef PSL_CM_CLR
191 			if (ipc.ip_data & PSL_CM)
192 				ipc.ip_data &= ~PSL_CM_CLR;
193 #endif
194 			goto ok;
195 		}
196 #if defined(hp300)
197 #ifdef FPCOPROC
198 		if (poff >= (int *)&((struct user *)kstack)->u_pcb.pcb_fpregs.fpf_regs &&
199 		    poff <= (int *)&((struct user *)kstack)->u_pcb.pcb_fpregs.fpf_fpiar)
200 			goto ok;
201 #endif
202 #endif
203 		goto error;
204 
205 	ok:
206 		*poff = ipc.ip_data;
207 		break;
208 
209 	case PT_STEP:			/* single step the child */
210 	case PT_CONTINUE:		/* continue the child */
211 		if ((int)ipc.ip_addr != 1)
212 			p->p_md.md_regs[PC] = (int)ipc.ip_addr;
213 		if ((unsigned)ipc.ip_data > NSIG)
214 			goto error;
215 		p->p_xstat = ipc.ip_data;	/* see issig */
216 #ifdef PSL_T
217 		/* need something more machine independent here... */
218 		if (i == PT_STEP)
219 			p->p_md.md_regs[PS] |= PSL_T;
220 #endif
221 		wakeup((caddr_t)&ipc);
222 		return (1);
223 
224 	case PT_KILL:			/* kill the child process */
225 		wakeup((caddr_t)&ipc);
226 		exit(p, (int)p->p_xstat);
227 
228 	default:
229 	error:
230 		ipc.ip_req = -1;
231 	}
232 	wakeup((caddr_t)&ipc);
233 	return (0);
234 }
235 
236 /*
237  * Process debugging system call.
238  */
239 /* ARGSUSED */
240 profil(p, uap, retval)
241 	struct proc *p;
242 	register struct args {
243 		short	*bufbase;
244 		unsigned bufsize;
245 		unsigned pcoffset;
246 		unsigned pcscale;
247 	} *uap;
248 	int *retval;
249 {
250 	register struct uprof *upp = &p->p_stats->p_prof;
251 
252 	upp->pr_base = uap->bufbase;
253 	upp->pr_size = uap->bufsize;
254 	upp->pr_off = uap->pcoffset;
255 	upp->pr_scale = uap->pcscale;
256 #ifdef PROFTIMER
257 	initprofclock();
258 #endif
259 	return (0);
260 }
261