new include syntax
[unix-history] / usr / src / sys / kern / sys_process.c
CommitLineData
5dc2581e
KB
1/*-
2 * Copyright (c) 1982, 1986, 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.proprietary.c%
da7c5cc6 6 *
afc12c69 7 * @(#)sys_process.c 7.30 (Berkeley) %G%
da7c5cc6 8 */
961945a8 9
ff32eb64 10#define IPCREG
94368568 11#include "param.h"
94368568 12#include "proc.h"
c4ec2128 13#include "vnode.h"
94368568 14#include "buf.h"
01b0e233 15#include "ptrace.h"
9ce4de2d 16
d301d150
KM
17#include "machine/reg.h"
18#include "machine/psl.h"
de5931fb 19#include "vm/vm.h"
d7db4999 20#include "vm/vm_page.h"
de5931fb
MK
21
22#include "user.h"
d301d150 23
4147b3f6
BJ
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 */
37struct {
38 int ip_lock;
39 int ip_req;
40 int *ip_addr;
41 int ip_data;
42} ipc;
43
44/*
3f75397a 45 * Process debugging system call.
4147b3f6 46 */
afc12c69
CT
47struct ptrace_args {
48 int req;
49 int pid;
50 int *addr;
51 int data;
52};
8c7d0e2a
KM
53ptrace(curp, uap, retval)
54 struct proc *curp;
afc12c69 55 register struct ptrace_args *uap;
8c7d0e2a
KM
56 int *retval;
57{
58 register struct proc *p;
ee8c7b71 59 int error;
4147b3f6 60
ee8c7b71
KM
61 p = pfind(uap->pid);
62 if (uap->req == PT_ATTACH) {
63 /*
64 * Must be root if the process has used set user or
65 * group privileges or does not belong to the real
66 * user. Must not be already traced.
67 */
68 if ((p->p_flag & SUGID ||
69 p->p_cred->p_ruid != curp->p_cred->p_ruid) &&
70 (error = suser(p->p_ucred, &p->p_acflag)) != 0)
71 return (error);
72 if (p->p_flag & STRC)
73 return (EALREADY); /* ??? */
74 /*
75 * It would be nice if the tracing relationship was separate
76 * from the parent relationship but that would require
77 * another set of links in the proc struct or for "wait"
78 * to scan the entire proc table. To make life easier,
79 * we just re-parent the process we're trying to trace.
80 * The old parent is remembered so we can put things back
81 * on a "detach".
82 */
83 p->p_flag |= STRC;
84 p->p_oppid = p->p_pptr->p_pid;
85 proc_reparent(p, curp);
86 psignal(p, SIGSTOP);
87 return (0);
88 }
4147b3f6 89 if (uap->req <= 0) {
8c7d0e2a 90 curp->p_flag |= STRC;
d9c2f47f 91 return (0);
4147b3f6 92 }
d7db4999 93 if (p == 0 || p->p_stat != SSTOP || p->p_pptr != curp ||
8c7d0e2a 94 !(p->p_flag & STRC))
d9c2f47f 95 return (ESRCH);
4147b3f6
BJ
96 while (ipc.ip_lock)
97 sleep((caddr_t)&ipc, IPCPRI);
98 ipc.ip_lock = p->p_pid;
99 ipc.ip_data = uap->data;
100 ipc.ip_addr = uap->addr;
101 ipc.ip_req = uap->req;
102 p->p_flag &= ~SWTED;
103 while (ipc.ip_req > 0) {
104 if (p->p_stat==SSTOP)
105 setrun(p);
106 sleep((caddr_t)&ipc, IPCPRI);
107 }
8c7d0e2a 108 *retval = ipc.ip_data;
4147b3f6
BJ
109 ipc.ip_lock = 0;
110 wakeup((caddr_t)&ipc);
8c7d0e2a 111 if (ipc.ip_req < 0)
d9c2f47f
MK
112 return (EIO);
113 return (0);
4147b3f6
BJ
114}
115
e128a701
MK
116#define PHYSOFF(p, o) ((caddr_t)(p) + (o))
117
6ce8aff2
WN
118#if defined(i386)
119#undef PC
120#undef SP
121#undef PS
122#undef R0
123#undef R1
124
125#define PC tEIP
126#define SP tESP
127#define PS tEFLAGS
128#define R0 tEDX
129#define R1 tECX
130#endif
883d0f83 131
4147b3f6 132/*
3f75397a
KM
133 * Transmit a tracing request from the parent to the child process
134 * being debugged. This code runs in the context of the child process
135 * to fulfill the command requested by the parent.
4147b3f6 136 */
82655668
KM
137procxmt(p)
138 register struct proc *p;
4147b3f6 139{
82655668 140 register int i, *poff;
e128a701 141 extern char kstack[];
4147b3f6 142
82655668 143 if (ipc.ip_lock != p->p_pid)
4147b3f6 144 return (0);
82655668 145 p->p_slptime = 0;
974b11f9 146 p->p_addr->u_kproc.kp_proc.p_md.md_regs = p->p_md.md_regs; /* u.u_ar0 */
4147b3f6
BJ
147 i = ipc.ip_req;
148 ipc.ip_req = 0;
149 switch (i) {
150
01b0e233 151 case PT_READ_I: /* read the child's text space */
4147b3f6
BJ
152 if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
153 goto error;
154 ipc.ip_data = fuiword((caddr_t)ipc.ip_addr);
155 break;
156
01b0e233 157 case PT_READ_D: /* read the child's data space */
4147b3f6
BJ
158 if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
159 goto error;
160 ipc.ip_data = fuword((caddr_t)ipc.ip_addr);
161 break;
162
01b0e233 163 case PT_READ_U: /* read the child's u. */
dc57440c 164#ifdef HPUXCOMPAT
eadb8ef2 165 if (p->p_addr->u_pcb.pcb_flags & PCB_HPUXTRACE)
dc57440c
KM
166 i = hpuxtobsduoff(ipc.ip_addr);
167 else
168#endif
4147b3f6 169 i = (int)ipc.ip_addr;
e128a701 170 if ((u_int) i > ctob(UPAGES)-sizeof(int) || (i & 1) != 0)
4147b3f6 171 goto error;
eadb8ef2 172 ipc.ip_data = *(int *)PHYSOFF(p->p_addr, i);
4147b3f6
BJ
173 break;
174
01b0e233 175 case PT_WRITE_I: /* write the child's text space */
883d0f83 176 if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) {
9db58063
KM
177 vm_offset_t sa, ea;
178 int rv;
179
180 sa = trunc_page((vm_offset_t)ipc.ip_addr);
181 ea = round_page((vm_offset_t)ipc.ip_addr+sizeof(int)-1);
d7db4999 182 rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea,
9db58063
KM
183 VM_PROT_DEFAULT, FALSE);
184 if (rv == KERN_SUCCESS) {
883d0f83 185 i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data);
d7db4999
MK
186 (void) vm_map_protect(&p->p_vmspace->vm_map,
187 sa, ea, VM_PROT_READ|VM_PROT_EXECUTE,
188 FALSE);
9db58063 189 }
883d0f83 190 }
4147b3f6
BJ
191 if (i < 0)
192 goto error;
4147b3f6
BJ
193 break;
194
01b0e233 195 case PT_WRITE_D: /* write the child's data space */
4147b3f6
BJ
196 if (suword((caddr_t)ipc.ip_addr, 0) < 0)
197 goto error;
198 (void) suword((caddr_t)ipc.ip_addr, ipc.ip_data);
199 break;
200
01b0e233 201 case PT_WRITE_U: /* write the child's u. */
dc57440c 202#ifdef HPUXCOMPAT
eadb8ef2 203 if (p->p_addr->u_pcb.pcb_flags & PCB_HPUXTRACE)
dc57440c
KM
204 i = hpuxtobsduoff(ipc.ip_addr);
205 else
206#endif
4147b3f6 207 i = (int)ipc.ip_addr;
d89b7f8b
MT
208#ifdef mips
209 poff = (int *)PHYSOFF(curproc->p_addr, i);
210#else
e128a701 211 poff = (int *)PHYSOFF(kstack, i);
d89b7f8b 212#endif
883d0f83 213 for (i=0; i<NIPCREG; i++)
974b11f9 214 if (poff == &p->p_md.md_regs[ipcreg[i]])
4147b3f6 215 goto ok;
974b11f9 216 if (poff == &p->p_md.md_regs[PS]) {
883d0f83 217 ipc.ip_data |= PSL_USERSET;
dc57440c 218 ipc.ip_data &= ~PSL_USERCLR;
bf47fbca
MK
219#ifdef PSL_CM_CLR
220 if (ipc.ip_data & PSL_CM)
221 ipc.ip_data &= ~PSL_CM_CLR;
222#endif
4147b3f6
BJ
223 goto ok;
224 }
7c02c1d3 225#if defined(hp300) || defined(luna68k)
dc57440c 226#ifdef FPCOPROC
e128a701
MK
227 if (poff >= (int *)&((struct user *)kstack)->u_pcb.pcb_fpregs.fpf_regs &&
228 poff <= (int *)&((struct user *)kstack)->u_pcb.pcb_fpregs.fpf_fpiar)
dc57440c
KM
229 goto ok;
230#endif
231#endif
4147b3f6
BJ
232 goto error;
233
234 ok:
82655668 235 *poff = ipc.ip_data;
4147b3f6
BJ
236 break;
237
01b0e233
MK
238 case PT_STEP: /* single step the child */
239 case PT_CONTINUE: /* continue the child */
ee8c7b71
KM
240 if ((unsigned)ipc.ip_data >= NSIG)
241 goto error;
4147b3f6 242 if ((int)ipc.ip_addr != 1)
974b11f9 243 p->p_md.md_regs[PC] = (int)ipc.ip_addr;
19dec745 244 p->p_xstat = ipc.ip_data; /* see issig */
d89b7f8b
MT
245#ifdef PSL_T
246 /* need something more machine independent here... */
01b0e233 247 if (i == PT_STEP)
974b11f9 248 p->p_md.md_regs[PS] |= PSL_T;
d89b7f8b 249#endif
4147b3f6
BJ
250 wakeup((caddr_t)&ipc);
251 return (1);
252
01b0e233 253 case PT_KILL: /* kill the child process */
4147b3f6 254 wakeup((caddr_t)&ipc);
21d115dd 255 exit(p, (int)p->p_xstat);
4147b3f6 256
ee8c7b71
KM
257 case PT_DETACH: /* stop tracing the child */
258 if ((unsigned)ipc.ip_data >= NSIG)
259 goto error;
260 if ((int)ipc.ip_addr != 1)
261 p->p_md.md_regs[PC] = (int)ipc.ip_addr;
262 p->p_xstat = ipc.ip_data; /* see issig */
263 p->p_flag &= ~STRC;
264 if (p->p_oppid != p->p_pptr->p_pid) {
265 register struct proc *pp = pfind(p->p_oppid);
266
267 if (pp)
268 proc_reparent(p, pp);
269 }
270 p->p_oppid = 0;
271 wakeup((caddr_t)&ipc);
272 return (1);
273
4147b3f6
BJ
274 default:
275 error:
276 ipc.ip_req = -1;
277 }
278 wakeup((caddr_t)&ipc);
279 return (0);
280}