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