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 | * | |
c4ec2128 | 6 | * @(#)sys_process.c 7.6 (Berkeley) %G% |
da7c5cc6 | 7 | */ |
961945a8 | 8 | |
ff32eb64 | 9 | #define IPCREG |
94368568 | 10 | #include "param.h" |
94368568 JB |
11 | #include "user.h" |
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 | */ | |
46 | ptrace() | |
47 | { | |
48 | register struct proc *p; | |
49 | register struct a { | |
50 | int req; | |
51 | int pid; | |
52 | int *addr; | |
53 | int data; | |
54 | } *uap; | |
55 | ||
56 | uap = (struct a *)u.u_ap; | |
57 | if (uap->req <= 0) { | |
58 | u.u_procp->p_flag |= STRC; | |
59 | return; | |
60 | } | |
61 | p = pfind(uap->pid); | |
f05cf4fe SL |
62 | if (p == 0 || p->p_stat != SSTOP || p->p_ppid != u.u_procp->p_pid || |
63 | !(p->p_flag & STRC)) { | |
4147b3f6 BJ |
64 | u.u_error = ESRCH; |
65 | return; | |
66 | } | |
67 | while (ipc.ip_lock) | |
68 | sleep((caddr_t)&ipc, IPCPRI); | |
69 | ipc.ip_lock = p->p_pid; | |
70 | ipc.ip_data = uap->data; | |
71 | ipc.ip_addr = uap->addr; | |
72 | ipc.ip_req = uap->req; | |
73 | p->p_flag &= ~SWTED; | |
74 | while (ipc.ip_req > 0) { | |
75 | if (p->p_stat==SSTOP) | |
76 | setrun(p); | |
77 | sleep((caddr_t)&ipc, IPCPRI); | |
78 | } | |
79 | u.u_r.r_val1 = ipc.ip_data; | |
80 | if (ipc.ip_req < 0) | |
81 | u.u_error = EIO; | |
82 | ipc.ip_lock = 0; | |
83 | wakeup((caddr_t)&ipc); | |
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 | */ | |
94 | procxmt() | |
95 | { | |
96 | register int i; | |
97 | register *p; | |
98 | register struct text *xp; | |
c4ec2128 KM |
99 | struct vattr vattr; |
100 | struct vnode *vp; | |
4147b3f6 BJ |
101 | |
102 | if (ipc.ip_lock != u.u_procp->p_pid) | |
103 | return (0); | |
104 | u.u_procp->p_slptime = 0; | |
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. */ |
4147b3f6 BJ |
122 | i = (int)ipc.ip_addr; |
123 | if (i<0 || i >= ctob(UPAGES)) | |
124 | goto error; | |
883d0f83 | 125 | ipc.ip_data = *(int *)PHYSOFF(&u, i); |
4147b3f6 BJ |
126 | break; |
127 | ||
01b0e233 | 128 | case PT_WRITE_I: /* write the child's text space */ |
4147b3f6 BJ |
129 | /* |
130 | * If text, must assure exclusive use | |
131 | */ | |
132 | if (xp = u.u_procp->p_textp) { | |
c4ec2128 KM |
133 | vp = xp->x_vptr; |
134 | VOP_GETATTR(vp, &vattr, u.u_cred); | |
135 | if (xp->x_count!=1 || (vattr.va_mode & VSVTX)) | |
4147b3f6 | 136 | goto error; |
cdb14d96 | 137 | xp->x_flag |= XTRC; |
4147b3f6 BJ |
138 | } |
139 | i = -1; | |
883d0f83 BJ |
140 | if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) { |
141 | if (chgprot((caddr_t)ipc.ip_addr, RW) && | |
142 | chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RW)) | |
143 | i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data); | |
144 | (void) chgprot((caddr_t)ipc.ip_addr, RO); | |
145 | (void) chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RO); | |
146 | } | |
4147b3f6 BJ |
147 | if (i < 0) |
148 | goto error; | |
fb1db32c MK |
149 | #if defined(tahoe) |
150 | /* make sure the old value is not in cache */ | |
151 | ckeyrelease(u.u_procp->p_ckey); | |
152 | u.u_procp->p_ckey = getcodekey(); | |
153 | #endif | |
154 | if (xp) { | |
4147b3f6 | 155 | xp->x_flag |= XWRIT; |
fb1db32c MK |
156 | #if defined(tahoe) |
157 | xp->x_ckey = u.u_procp->p_ckey; | |
158 | #endif | |
159 | } | |
4147b3f6 BJ |
160 | break; |
161 | ||
01b0e233 | 162 | case PT_WRITE_D: /* write the child's data space */ |
4147b3f6 BJ |
163 | if (suword((caddr_t)ipc.ip_addr, 0) < 0) |
164 | goto error; | |
165 | (void) suword((caddr_t)ipc.ip_addr, ipc.ip_data); | |
166 | break; | |
167 | ||
01b0e233 | 168 | case PT_WRITE_U: /* write the child's u. */ |
4147b3f6 | 169 | i = (int)ipc.ip_addr; |
883d0f83 BJ |
170 | p = (int *)PHYSOFF(&u, i); |
171 | for (i=0; i<NIPCREG; i++) | |
4147b3f6 BJ |
172 | if (p == &u.u_ar0[ipcreg[i]]) |
173 | goto ok; | |
174 | if (p == &u.u_ar0[PS]) { | |
883d0f83 | 175 | ipc.ip_data |= PSL_USERSET; |
4147b3f6 | 176 | ipc.ip_data &= ~PSL_USERCLR; |
bf47fbca MK |
177 | #ifdef PSL_CM_CLR |
178 | if (ipc.ip_data & PSL_CM) | |
179 | ipc.ip_data &= ~PSL_CM_CLR; | |
180 | #endif | |
4147b3f6 BJ |
181 | goto ok; |
182 | } | |
183 | goto error; | |
184 | ||
185 | ok: | |
186 | *p = ipc.ip_data; | |
187 | break; | |
188 | ||
01b0e233 MK |
189 | case PT_STEP: /* single step the child */ |
190 | case PT_CONTINUE: /* continue the child */ | |
4147b3f6 BJ |
191 | if ((int)ipc.ip_addr != 1) |
192 | u.u_ar0[PC] = (int)ipc.ip_addr; | |
193 | if ((unsigned)ipc.ip_data > NSIG) | |
194 | goto error; | |
195 | u.u_procp->p_cursig = ipc.ip_data; /* see issig */ | |
01b0e233 | 196 | if (i == PT_STEP) |
4147b3f6 BJ |
197 | u.u_ar0[PS] |= PSL_T; |
198 | wakeup((caddr_t)&ipc); | |
199 | return (1); | |
200 | ||
01b0e233 | 201 | case PT_KILL: /* kill the child process */ |
4147b3f6 BJ |
202 | wakeup((caddr_t)&ipc); |
203 | exit(u.u_procp->p_cursig); | |
204 | ||
205 | default: | |
206 | error: | |
207 | ipc.ip_req = -1; | |
208 | } | |
209 | wakeup((caddr_t)&ipc); | |
210 | return (0); | |
211 | } |