Commit | Line | Data |
---|---|---|
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 | * |
3f75397a | 7 | * @(#)sys_process.c 7.22 (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 "seg.h" |
94368568 | 15 | #include "buf.h" |
01b0e233 | 16 | #include "ptrace.h" |
9ce4de2d | 17 | |
d301d150 KM |
18 | #include "machine/reg.h" |
19 | #include "machine/psl.h" | |
de5931fb | 20 | #include "vm/vm.h" |
d7db4999 | 21 | #include "vm/vm_page.h" |
de5931fb MK |
22 | |
23 | #include "user.h" | |
d301d150 | 24 | |
4147b3f6 BJ |
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 | /* | |
3f75397a | 46 | * Process debugging system call. |
4147b3f6 | 47 | */ |
8c7d0e2a KM |
48 | ptrace(curp, uap, retval) |
49 | struct proc *curp; | |
50 | register struct args { | |
4147b3f6 BJ |
51 | int req; |
52 | int pid; | |
53 | int *addr; | |
54 | int data; | |
55 | } *uap; | |
8c7d0e2a KM |
56 | int *retval; |
57 | { | |
58 | register struct proc *p; | |
4147b3f6 | 59 | |
4147b3f6 | 60 | if (uap->req <= 0) { |
8c7d0e2a | 61 | curp->p_flag |= STRC; |
d9c2f47f | 62 | return (0); |
4147b3f6 BJ |
63 | } |
64 | p = pfind(uap->pid); | |
d7db4999 | 65 | if (p == 0 || p->p_stat != SSTOP || p->p_pptr != curp || |
8c7d0e2a | 66 | !(p->p_flag & STRC)) |
d9c2f47f | 67 | return (ESRCH); |
4147b3f6 BJ |
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 | } | |
8c7d0e2a | 80 | *retval = ipc.ip_data; |
4147b3f6 BJ |
81 | ipc.ip_lock = 0; |
82 | wakeup((caddr_t)&ipc); | |
8c7d0e2a | 83 | if (ipc.ip_req < 0) |
d9c2f47f MK |
84 | return (EIO); |
85 | return (0); | |
4147b3f6 BJ |
86 | } |
87 | ||
e128a701 MK |
88 | #define PHYSOFF(p, o) ((caddr_t)(p) + (o)) |
89 | ||
6ce8aff2 WN |
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 | |
883d0f83 | 103 | |
4147b3f6 | 104 | /* |
3f75397a KM |
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. | |
4147b3f6 | 108 | */ |
82655668 KM |
109 | procxmt(p) |
110 | register struct proc *p; | |
4147b3f6 | 111 | { |
82655668 | 112 | register int i, *poff; |
e128a701 | 113 | extern char kstack[]; |
4147b3f6 | 114 | |
82655668 | 115 | if (ipc.ip_lock != p->p_pid) |
4147b3f6 | 116 | return (0); |
82655668 | 117 | p->p_slptime = 0; |
eadb8ef2 | 118 | p->p_addr->u_kproc.kp_proc.p_regs = p->p_regs; /* u.u_ar0 */ |
4147b3f6 BJ |
119 | i = ipc.ip_req; |
120 | ipc.ip_req = 0; | |
121 | switch (i) { | |
122 | ||
01b0e233 | 123 | case PT_READ_I: /* read the child's text space */ |
4147b3f6 BJ |
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 | ||
01b0e233 | 129 | case PT_READ_D: /* read the child's data space */ |
4147b3f6 BJ |
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 | ||
01b0e233 | 135 | case PT_READ_U: /* read the child's u. */ |
dc57440c | 136 | #ifdef HPUXCOMPAT |
eadb8ef2 | 137 | if (p->p_addr->u_pcb.pcb_flags & PCB_HPUXTRACE) |
dc57440c KM |
138 | i = hpuxtobsduoff(ipc.ip_addr); |
139 | else | |
140 | #endif | |
4147b3f6 | 141 | i = (int)ipc.ip_addr; |
e128a701 | 142 | if ((u_int) i > ctob(UPAGES)-sizeof(int) || (i & 1) != 0) |
4147b3f6 | 143 | goto error; |
eadb8ef2 | 144 | ipc.ip_data = *(int *)PHYSOFF(p->p_addr, i); |
4147b3f6 BJ |
145 | break; |
146 | ||
01b0e233 | 147 | case PT_WRITE_I: /* write the child's text space */ |
883d0f83 | 148 | if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) { |
9db58063 KM |
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); | |
d7db4999 | 154 | rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea, |
9db58063 KM |
155 | VM_PROT_DEFAULT, FALSE); |
156 | if (rv == KERN_SUCCESS) { | |
883d0f83 | 157 | i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data); |
d7db4999 MK |
158 | (void) vm_map_protect(&p->p_vmspace->vm_map, |
159 | sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, | |
160 | FALSE); | |
9db58063 | 161 | } |
883d0f83 | 162 | } |
4147b3f6 BJ |
163 | if (i < 0) |
164 | goto error; | |
4147b3f6 BJ |
165 | break; |
166 | ||
01b0e233 | 167 | case PT_WRITE_D: /* write the child's data space */ |
4147b3f6 BJ |
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 | ||
01b0e233 | 173 | case PT_WRITE_U: /* write the child's u. */ |
dc57440c | 174 | #ifdef HPUXCOMPAT |
eadb8ef2 | 175 | if (p->p_addr->u_pcb.pcb_flags & PCB_HPUXTRACE) |
dc57440c KM |
176 | i = hpuxtobsduoff(ipc.ip_addr); |
177 | else | |
178 | #endif | |
4147b3f6 | 179 | i = (int)ipc.ip_addr; |
e128a701 | 180 | poff = (int *)PHYSOFF(kstack, i); |
883d0f83 | 181 | for (i=0; i<NIPCREG; i++) |
d7db4999 | 182 | if (poff == &p->p_regs[ipcreg[i]]) |
4147b3f6 | 183 | goto ok; |
d7db4999 | 184 | if (poff == &p->p_regs[PS]) { |
883d0f83 | 185 | ipc.ip_data |= PSL_USERSET; |
dc57440c | 186 | ipc.ip_data &= ~PSL_USERCLR; |
bf47fbca MK |
187 | #ifdef PSL_CM_CLR |
188 | if (ipc.ip_data & PSL_CM) | |
189 | ipc.ip_data &= ~PSL_CM_CLR; | |
190 | #endif | |
4147b3f6 BJ |
191 | goto ok; |
192 | } | |
dc57440c KM |
193 | #if defined(hp300) |
194 | #ifdef FPCOPROC | |
e128a701 MK |
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) | |
dc57440c KM |
197 | goto ok; |
198 | #endif | |
199 | #endif | |
4147b3f6 BJ |
200 | goto error; |
201 | ||
202 | ok: | |
82655668 | 203 | *poff = ipc.ip_data; |
4147b3f6 BJ |
204 | break; |
205 | ||
01b0e233 MK |
206 | case PT_STEP: /* single step the child */ |
207 | case PT_CONTINUE: /* continue the child */ | |
4147b3f6 | 208 | if ((int)ipc.ip_addr != 1) |
d7db4999 | 209 | p->p_regs[PC] = (int)ipc.ip_addr; |
4147b3f6 BJ |
210 | if ((unsigned)ipc.ip_data > NSIG) |
211 | goto error; | |
19dec745 | 212 | p->p_xstat = ipc.ip_data; /* see issig */ |
01b0e233 | 213 | if (i == PT_STEP) |
d7db4999 | 214 | p->p_regs[PS] |= PSL_T; |
4147b3f6 BJ |
215 | wakeup((caddr_t)&ipc); |
216 | return (1); | |
217 | ||
01b0e233 | 218 | case PT_KILL: /* kill the child process */ |
4147b3f6 | 219 | wakeup((caddr_t)&ipc); |
21d115dd | 220 | exit(p, (int)p->p_xstat); |
4147b3f6 BJ |
221 | |
222 | default: | |
223 | error: | |
224 | ipc.ip_req = -1; | |
225 | } | |
226 | wakeup((caddr_t)&ipc); | |
227 | return (0); | |
228 | } | |
f7fd221a | 229 | |
3f75397a KM |
230 | /* |
231 | * Process debugging system call. | |
232 | */ | |
f7fd221a KM |
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 | } |