Commit | Line | Data |
---|---|---|
da7c5cc6 | 1 | /* |
c4ec2128 | 2 | * Copyright (c) 1982, 1986, 1989 Regents of the University of California. |
da7c5cc6 KM |
3 | * All rights reserved. The Berkeley software License Agreement |
4 | * specifies the terms and conditions for redistribution. | |
5 | * | |
19dec745 | 6 | * @(#)sys_process.c 7.11 (Berkeley) %G% |
da7c5cc6 | 7 | */ |
961945a8 | 8 | |
ff32eb64 | 9 | #define IPCREG |
94368568 | 10 | #include "param.h" |
8c7d0e2a | 11 | #include "syscontext.h" |
94368568 | 12 | #include "proc.h" |
c4ec2128 | 13 | #include "vnode.h" |
94368568 JB |
14 | #include "text.h" |
15 | #include "seg.h" | |
94368568 | 16 | #include "buf.h" |
01b0e233 | 17 | #include "ptrace.h" |
9ce4de2d | 18 | |
d301d150 KM |
19 | #include "machine/reg.h" |
20 | #include "machine/psl.h" | |
21 | #include "machine/pte.h" | |
22 | ||
4147b3f6 BJ |
23 | /* |
24 | * Priority for tracing | |
25 | */ | |
26 | #define IPCPRI PZERO | |
27 | ||
28 | /* | |
29 | * Tracing variables. | |
30 | * Used to pass trace command from | |
31 | * parent to child being traced. | |
32 | * This data base cannot be | |
33 | * shared and is locked | |
34 | * per user. | |
35 | */ | |
36 | struct { | |
37 | int ip_lock; | |
38 | int ip_req; | |
39 | int *ip_addr; | |
40 | int ip_data; | |
41 | } ipc; | |
42 | ||
43 | /* | |
44 | * sys-trace system call. | |
45 | */ | |
8c7d0e2a KM |
46 | ptrace(curp, uap, retval) |
47 | struct proc *curp; | |
48 | register struct args { | |
4147b3f6 BJ |
49 | int req; |
50 | int pid; | |
51 | int *addr; | |
52 | int data; | |
53 | } *uap; | |
8c7d0e2a KM |
54 | int *retval; |
55 | { | |
56 | register struct proc *p; | |
4147b3f6 | 57 | |
4147b3f6 | 58 | if (uap->req <= 0) { |
8c7d0e2a KM |
59 | curp->p_flag |= STRC; |
60 | RETURN (0); | |
4147b3f6 BJ |
61 | } |
62 | p = pfind(uap->pid); | |
8c7d0e2a KM |
63 | if (p == 0 || p->p_stat != SSTOP || p->p_ppid != curp->p_pid || |
64 | !(p->p_flag & STRC)) | |
65 | RETURN (ESRCH); | |
4147b3f6 BJ |
66 | while (ipc.ip_lock) |
67 | sleep((caddr_t)&ipc, IPCPRI); | |
68 | ipc.ip_lock = p->p_pid; | |
69 | ipc.ip_data = uap->data; | |
70 | ipc.ip_addr = uap->addr; | |
71 | ipc.ip_req = uap->req; | |
72 | p->p_flag &= ~SWTED; | |
73 | while (ipc.ip_req > 0) { | |
74 | if (p->p_stat==SSTOP) | |
75 | setrun(p); | |
76 | sleep((caddr_t)&ipc, IPCPRI); | |
77 | } | |
8c7d0e2a | 78 | *retval = ipc.ip_data; |
4147b3f6 BJ |
79 | ipc.ip_lock = 0; |
80 | wakeup((caddr_t)&ipc); | |
8c7d0e2a KM |
81 | if (ipc.ip_req < 0) |
82 | RETURN (EIO); | |
83 | RETURN (0); | |
4147b3f6 BJ |
84 | } |
85 | ||
fc0890b1 | 86 | #define PHYSOFF(p, o) \ |
883d0f83 BJ |
87 | ((physadr)(p)+((o)/sizeof(((physadr)0)->r[0]))) |
88 | ||
4147b3f6 BJ |
89 | /* |
90 | * Code that the child process | |
91 | * executes to implement the command | |
92 | * of the parent process in tracing. | |
93 | */ | |
82655668 KM |
94 | procxmt(p) |
95 | register struct proc *p; | |
4147b3f6 | 96 | { |
82655668 | 97 | register int i, *poff; |
4147b3f6 | 98 | register struct text *xp; |
c4ec2128 KM |
99 | struct vattr vattr; |
100 | struct vnode *vp; | |
4147b3f6 | 101 | |
82655668 | 102 | if (ipc.ip_lock != p->p_pid) |
4147b3f6 | 103 | return (0); |
82655668 | 104 | p->p_slptime = 0; |
4147b3f6 BJ |
105 | i = ipc.ip_req; |
106 | ipc.ip_req = 0; | |
107 | switch (i) { | |
108 | ||
01b0e233 | 109 | case PT_READ_I: /* read the child's text space */ |
4147b3f6 BJ |
110 | if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) |
111 | goto error; | |
112 | ipc.ip_data = fuiword((caddr_t)ipc.ip_addr); | |
113 | break; | |
114 | ||
01b0e233 | 115 | case PT_READ_D: /* read the child's data space */ |
4147b3f6 BJ |
116 | if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) |
117 | goto error; | |
118 | ipc.ip_data = fuword((caddr_t)ipc.ip_addr); | |
119 | break; | |
120 | ||
01b0e233 | 121 | case PT_READ_U: /* read the child's u. */ |
dc57440c KM |
122 | #ifdef HPUXCOMPAT |
123 | if (u.u_pcb.pcb_flags & PCB_HPUXTRACE) | |
124 | i = hpuxtobsduoff(ipc.ip_addr); | |
125 | else | |
126 | #endif | |
4147b3f6 | 127 | i = (int)ipc.ip_addr; |
dc57440c | 128 | if (i<0 || i > ctob(UPAGES)-sizeof(int)) |
4147b3f6 | 129 | goto error; |
883d0f83 | 130 | ipc.ip_data = *(int *)PHYSOFF(&u, i); |
4147b3f6 BJ |
131 | break; |
132 | ||
01b0e233 | 133 | case PT_WRITE_I: /* write the child's text space */ |
4147b3f6 BJ |
134 | /* |
135 | * If text, must assure exclusive use | |
136 | */ | |
82655668 | 137 | if (xp = p->p_textp) { |
c4ec2128 KM |
138 | vp = xp->x_vptr; |
139 | VOP_GETATTR(vp, &vattr, u.u_cred); | |
140 | if (xp->x_count!=1 || (vattr.va_mode & VSVTX)) | |
4147b3f6 | 141 | goto error; |
cdb14d96 | 142 | xp->x_flag |= XTRC; |
4147b3f6 BJ |
143 | } |
144 | i = -1; | |
883d0f83 | 145 | if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) { |
eeec7d1d KM |
146 | if (!chgprot((caddr_t)ipc.ip_addr, RW) && |
147 | !chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RW)) | |
883d0f83 BJ |
148 | i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data); |
149 | (void) chgprot((caddr_t)ipc.ip_addr, RO); | |
150 | (void) chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RO); | |
151 | } | |
4147b3f6 BJ |
152 | if (i < 0) |
153 | goto error; | |
fb1db32c MK |
154 | #if defined(tahoe) |
155 | /* make sure the old value is not in cache */ | |
82655668 KM |
156 | ckeyrelease(p->p_ckey); |
157 | p->p_ckey = getcodekey(); | |
fb1db32c MK |
158 | #endif |
159 | if (xp) { | |
4147b3f6 | 160 | xp->x_flag |= XWRIT; |
fb1db32c | 161 | #if defined(tahoe) |
82655668 | 162 | xp->x_ckey = p->p_ckey; |
fb1db32c MK |
163 | #endif |
164 | } | |
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 KM |
174 | #ifdef HPUXCOMPAT |
175 | if (u.u_pcb.pcb_flags & PCB_HPUXTRACE) | |
176 | i = hpuxtobsduoff(ipc.ip_addr); | |
177 | else | |
178 | #endif | |
4147b3f6 | 179 | i = (int)ipc.ip_addr; |
82655668 | 180 | poff = (int *)PHYSOFF(&u, i); |
883d0f83 | 181 | for (i=0; i<NIPCREG; i++) |
82655668 | 182 | if (poff == &u.u_ar0[ipcreg[i]]) |
4147b3f6 | 183 | goto ok; |
82655668 | 184 | if (poff == &u.u_ar0[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 | |
82655668 KM |
195 | if (poff >= (int *)u.u_pcb.pcb_fpregs.fpf_regs && |
196 | poff <= (int *)&u.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 BJ |
208 | if ((int)ipc.ip_addr != 1) |
209 | u.u_ar0[PC] = (int)ipc.ip_addr; | |
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) |
4147b3f6 BJ |
214 | u.u_ar0[PS] |= PSL_T; |
215 | wakeup((caddr_t)&ipc); | |
216 | return (1); | |
217 | ||
01b0e233 | 218 | case PT_KILL: /* kill the child process */ |
4147b3f6 | 219 | wakeup((caddr_t)&ipc); |
19dec745 | 220 | exit(p, 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 | } |