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