Blame


1 a84cbb2a 2004-04-19 devnull /*
2 1b135a78 2004-04-19 devnull * process interface for FreeBSD
3 1b135a78 2004-04-19 devnull *
4 1b135a78 2004-04-19 devnull * we could be a little more careful about not using
5 1b135a78 2004-04-19 devnull * ptrace unless absolutely necessary. this would let us
6 1b135a78 2004-04-19 devnull * look at processes without stopping them.
7 1b135a78 2004-04-19 devnull *
8 1b135a78 2004-04-19 devnull * I'd like to make this a bit more generic (there's too much
9 1b135a78 2004-04-19 devnull * duplication with Linux and presumably other systems),
10 1b135a78 2004-04-19 devnull * but ptrace is too damn system-specific.
11 a84cbb2a 2004-04-19 devnull */
12 a84cbb2a 2004-04-19 devnull
13 a84cbb2a 2004-04-19 devnull #include <u.h>
14 a84cbb2a 2004-04-19 devnull #include <sys/ptrace.h>
15 a84cbb2a 2004-04-19 devnull #include <sys/types.h>
16 a84cbb2a 2004-04-19 devnull #include <sys/wait.h>
17 1b135a78 2004-04-19 devnull #include <machine/reg.h>
18 a84cbb2a 2004-04-19 devnull #include <signal.h>
19 a84cbb2a 2004-04-19 devnull #include <errno.h>
20 a84cbb2a 2004-04-19 devnull #include <libc.h>
21 a84cbb2a 2004-04-19 devnull #include <mach.h>
22 a84cbb2a 2004-04-19 devnull #include "ureg386.h"
23 a84cbb2a 2004-04-19 devnull
24 1b135a78 2004-04-19 devnull Mach *machcpu = &mach386;
25 1b135a78 2004-04-19 devnull
26 1b135a78 2004-04-19 devnull typedef struct PtraceRegs PtraceRegs;
27 1b135a78 2004-04-19 devnull struct PtraceRegs
28 1b135a78 2004-04-19 devnull {
29 1b135a78 2004-04-19 devnull Regs r;
30 1b135a78 2004-04-19 devnull int pid;
31 1b135a78 2004-04-19 devnull };
32 1b135a78 2004-04-19 devnull
33 d4605310 2020-01-15 cross static int ptracerw(Map*, Seg*, u64int, void*, uint, int);
34 d4605310 2020-01-15 cross static int ptraceregrw(Regs*, char*, u64int*, int);
35 1b135a78 2004-04-19 devnull
36 a84cbb2a 2004-04-19 devnull void
37 1b135a78 2004-04-19 devnull unmapproc(Map *map)
38 a84cbb2a 2004-04-19 devnull {
39 1b135a78 2004-04-19 devnull int i;
40 1b135a78 2004-04-19 devnull
41 1b135a78 2004-04-19 devnull if(map == nil)
42 1b135a78 2004-04-19 devnull return;
43 1b135a78 2004-04-19 devnull for(i=0; i<map->nseg; i++)
44 1b135a78 2004-04-19 devnull while(i<map->nseg && map->seg[i].pid){
45 1b135a78 2004-04-19 devnull map->nseg--;
46 fa325e9b 2020-01-10 cross memmove(&map->seg[i], &map->seg[i+1],
47 1b135a78 2004-04-19 devnull (map->nseg-i)*sizeof(map->seg[0]));
48 1b135a78 2004-04-19 devnull }
49 a84cbb2a 2004-04-19 devnull }
50 a84cbb2a 2004-04-19 devnull
51 a84cbb2a 2004-04-19 devnull int
52 1b135a78 2004-04-19 devnull mapproc(int pid, Map *map, Regs **rp)
53 a84cbb2a 2004-04-19 devnull {
54 1b135a78 2004-04-19 devnull Seg s;
55 1b135a78 2004-04-19 devnull PtraceRegs *r;
56 1b135a78 2004-04-19 devnull
57 1b135a78 2004-04-19 devnull if(ptrace(PT_ATTACH, pid, 0, 0) < 0)
58 1b135a78 2004-04-19 devnull if(ptrace(PT_READ_I, pid, 0, 0)<0 && errno!=EINVAL)
59 1b135a78 2004-04-19 devnull if(ptrace(PT_ATTACH, pid, 0, 0) < 0){
60 1b135a78 2004-04-19 devnull werrstr("ptrace attach %d: %r", pid);
61 1b135a78 2004-04-19 devnull return -1;
62 1b135a78 2004-04-19 devnull }
63 1b135a78 2004-04-19 devnull
64 1b135a78 2004-04-19 devnull if(ctlproc(pid, "waitanyway") < 0){
65 1b135a78 2004-04-19 devnull ptrace(PT_DETACH, pid, 0, 0);
66 1b135a78 2004-04-19 devnull return -1;
67 1b135a78 2004-04-19 devnull }
68 1b135a78 2004-04-19 devnull
69 1b135a78 2004-04-19 devnull memset(&s, 0, sizeof s);
70 1b135a78 2004-04-19 devnull s.base = 0;
71 1b135a78 2004-04-19 devnull s.size = 0xFFFFFFFF;
72 1b135a78 2004-04-19 devnull s.offset = 0;
73 1b135a78 2004-04-19 devnull s.name = "data";
74 1b135a78 2004-04-19 devnull s.file = nil;
75 1b135a78 2004-04-19 devnull s.rw = ptracerw;
76 1b135a78 2004-04-19 devnull s.pid = pid;
77 1b135a78 2004-04-19 devnull if(addseg(map, s) < 0)
78 1b135a78 2004-04-19 devnull return -1;
79 1b135a78 2004-04-19 devnull
80 1b135a78 2004-04-19 devnull if((r = mallocz(sizeof(PtraceRegs), 1)) == nil)
81 1b135a78 2004-04-19 devnull return -1;
82 1b135a78 2004-04-19 devnull r->r.rw = ptraceregrw;
83 1b135a78 2004-04-19 devnull r->pid = pid;
84 1b135a78 2004-04-19 devnull *rp = (Regs*)r;
85 1b135a78 2004-04-19 devnull return 0;
86 a84cbb2a 2004-04-19 devnull }
87 a84cbb2a 2004-04-19 devnull
88 a84cbb2a 2004-04-19 devnull int
89 1b135a78 2004-04-19 devnull detachproc(int pid)
90 a84cbb2a 2004-04-19 devnull {
91 1b135a78 2004-04-19 devnull return ptrace(PT_DETACH, pid, 0, 0);
92 a84cbb2a 2004-04-19 devnull }
93 a84cbb2a 2004-04-19 devnull
94 1b135a78 2004-04-19 devnull static int
95 d4605310 2020-01-15 cross ptracerw(Map *map, Seg *seg, u64int addr, void *v, uint n, int isr)
96 a84cbb2a 2004-04-19 devnull {
97 1b135a78 2004-04-19 devnull int i;
98 1b135a78 2004-04-19 devnull u32int u;
99 1b135a78 2004-04-19 devnull uchar buf[4];
100 1b135a78 2004-04-19 devnull
101 1b135a78 2004-04-19 devnull addr += seg->base;
102 1b135a78 2004-04-19 devnull for(i=0; i<n; i+=4){
103 1b135a78 2004-04-19 devnull if(isr){
104 1b135a78 2004-04-19 devnull errno = 0;
105 1b135a78 2004-04-19 devnull u = ptrace(PT_READ_D, seg->pid, (char*)addr+i, 0);
106 1b135a78 2004-04-19 devnull if(errno)
107 1b135a78 2004-04-19 devnull goto ptraceerr;
108 1b135a78 2004-04-19 devnull if(n-i >= 4)
109 1b135a78 2004-04-19 devnull *(u32int*)((char*)v+i) = u;
110 1b135a78 2004-04-19 devnull else{
111 1b135a78 2004-04-19 devnull *(u32int*)buf = u;
112 1b135a78 2004-04-19 devnull memmove((char*)v+i, buf, n-i);
113 1b135a78 2004-04-19 devnull }
114 1b135a78 2004-04-19 devnull }else{
115 1b135a78 2004-04-19 devnull if(n-i >= 4)
116 1b135a78 2004-04-19 devnull u = *(u32int*)((char*)v+i);
117 1b135a78 2004-04-19 devnull else{
118 1b135a78 2004-04-19 devnull errno = 0;
119 1b135a78 2004-04-19 devnull u = ptrace(PT_READ_D, seg->pid, (char*)addr+i, 0);
120 1b135a78 2004-04-19 devnull if(errno)
121 1b135a78 2004-04-19 devnull return -1;
122 1b135a78 2004-04-19 devnull *(u32int*)buf = u;
123 1b135a78 2004-04-19 devnull memmove(buf, (char*)v+i, n-i);
124 1b135a78 2004-04-19 devnull u = *(u32int*)buf;
125 1b135a78 2004-04-19 devnull }
126 1b135a78 2004-04-19 devnull if(ptrace(PT_WRITE_D, seg->pid, (char*)addr+i, u) < 0)
127 1b135a78 2004-04-19 devnull goto ptraceerr;
128 1b135a78 2004-04-19 devnull }
129 1b135a78 2004-04-19 devnull }
130 1b135a78 2004-04-19 devnull return 0;
131 1b135a78 2004-04-19 devnull
132 1b135a78 2004-04-19 devnull ptraceerr:
133 1b135a78 2004-04-19 devnull werrstr("ptrace: %r");
134 1b135a78 2004-04-19 devnull return -1;
135 a84cbb2a 2004-04-19 devnull }
136 a84cbb2a 2004-04-19 devnull
137 1b135a78 2004-04-19 devnull static char *freebsdregs[] = {
138 1b135a78 2004-04-19 devnull "FS",
139 1b135a78 2004-04-19 devnull "ES",
140 1b135a78 2004-04-19 devnull "DS",
141 1b135a78 2004-04-19 devnull "DI",
142 1b135a78 2004-04-19 devnull "SI",
143 1b135a78 2004-04-19 devnull "BP",
144 1b135a78 2004-04-19 devnull "SP",
145 1b135a78 2004-04-19 devnull "BX",
146 1b135a78 2004-04-19 devnull "DX",
147 1b135a78 2004-04-19 devnull "CX",
148 1b135a78 2004-04-19 devnull "AX",
149 1b135a78 2004-04-19 devnull "TRAP",
150 1b135a78 2004-04-19 devnull "PC",
151 1b135a78 2004-04-19 devnull "CS",
152 1b135a78 2004-04-19 devnull "EFLAGS",
153 1b135a78 2004-04-19 devnull "SP",
154 1b135a78 2004-04-19 devnull "SS",
155 1b135a78 2004-04-19 devnull "GS",
156 1b135a78 2004-04-19 devnull };
157 1b135a78 2004-04-19 devnull
158 1b135a78 2004-04-19 devnull static ulong
159 1b135a78 2004-04-19 devnull reg2freebsd(char *reg)
160 a84cbb2a 2004-04-19 devnull {
161 1b135a78 2004-04-19 devnull int i;
162 1b135a78 2004-04-19 devnull
163 1b135a78 2004-04-19 devnull for(i=0; i<nelem(freebsdregs); i++)
164 1b135a78 2004-04-19 devnull if(strcmp(freebsdregs[i], reg) == 0)
165 1b135a78 2004-04-19 devnull return 4*i;
166 1b135a78 2004-04-19 devnull return ~(ulong)0;
167 a84cbb2a 2004-04-19 devnull }
168 a84cbb2a 2004-04-19 devnull
169 1b135a78 2004-04-19 devnull static int
170 d4605310 2020-01-15 cross ptraceregrw(Regs *regs, char *name, u64int *val, int isr)
171 1b135a78 2004-04-19 devnull {
172 1b135a78 2004-04-19 devnull int pid;
173 1b135a78 2004-04-19 devnull ulong addr;
174 1b135a78 2004-04-19 devnull struct reg mregs;
175 1b135a78 2004-04-19 devnull
176 1b135a78 2004-04-19 devnull addr = reg2freebsd(name);
177 1b135a78 2004-04-19 devnull if(~addr == 0){
178 1b135a78 2004-04-19 devnull if(isr){
179 1b135a78 2004-04-19 devnull *val = ~(ulong)0;
180 1b135a78 2004-04-19 devnull return 0;
181 1b135a78 2004-04-19 devnull }
182 1b135a78 2004-04-19 devnull werrstr("register not available");
183 1b135a78 2004-04-19 devnull return -1;
184 1b135a78 2004-04-19 devnull }
185 1b135a78 2004-04-19 devnull
186 1b135a78 2004-04-19 devnull pid = ((PtraceRegs*)regs)->pid;
187 1b135a78 2004-04-19 devnull if(ptrace(PT_GETREGS, pid, (char*)&mregs, 0) < 0)
188 1b135a78 2004-04-19 devnull return -1;
189 1b135a78 2004-04-19 devnull if(isr)
190 1b135a78 2004-04-19 devnull *val = *(u32int*)((char*)&mregs+addr);
191 1b135a78 2004-04-19 devnull else{
192 1b135a78 2004-04-19 devnull *(u32int*)((char*)&mregs+addr) = *val;
193 1b135a78 2004-04-19 devnull if(ptrace(PT_SETREGS, pid, (char*)&mregs, 0) < 0)
194 1b135a78 2004-04-19 devnull return -1;
195 1b135a78 2004-04-19 devnull }
196 1b135a78 2004-04-19 devnull return 0;
197 1b135a78 2004-04-19 devnull }
198 1b135a78 2004-04-19 devnull
199 a84cbb2a 2004-04-19 devnull char*
200 1b135a78 2004-04-19 devnull proctextfile(int pid)
201 a84cbb2a 2004-04-19 devnull {
202 1b135a78 2004-04-19 devnull static char buf[1024], pbuf[128];
203 1b135a78 2004-04-19 devnull
204 1b135a78 2004-04-19 devnull snprint(pbuf, sizeof pbuf, "/proc/%d/file", pid);
205 1b135a78 2004-04-19 devnull if(readlink(pbuf, buf, sizeof buf) >= 0)
206 1b135a78 2004-04-19 devnull return buf;
207 1b135a78 2004-04-19 devnull if(access(pbuf, AEXIST) >= 0)
208 1b135a78 2004-04-19 devnull return pbuf;
209 1b135a78 2004-04-19 devnull return nil;
210 a84cbb2a 2004-04-19 devnull }
211 1b135a78 2004-04-19 devnull
212 1b135a78 2004-04-19 devnull /*
213 1b135a78 2004-04-19 devnull
214 1b135a78 2004-04-19 devnull status The process status. This file is read-only and returns a single
215 1b135a78 2004-04-19 devnull line containing multiple space-separated fields as follows:
216 1b135a78 2004-04-19 devnull
217 1b135a78 2004-04-19 devnull o command name
218 1b135a78 2004-04-19 devnull o process id
219 1b135a78 2004-04-19 devnull o parent process id
220 1b135a78 2004-04-19 devnull o process group id
221 1b135a78 2004-04-19 devnull o session id
222 1b135a78 2004-04-19 devnull o major,minor of the controlling terminal, or -1,-1 if there is
223 1b135a78 2004-04-19 devnull no controlling terminal.
224 1b135a78 2004-04-19 devnull o a list of process flags: ctty if there is a controlling ter-
225 1b135a78 2004-04-19 devnull minal, sldr if the process is a session leader, noflags if
226 1b135a78 2004-04-19 devnull neither of the other two flags are set.
227 1b135a78 2004-04-19 devnull o the process start time in seconds and microseconds, comma
228 1b135a78 2004-04-19 devnull separated.
229 1b135a78 2004-04-19 devnull o the user time in seconds and microseconds, comma separated.
230 1b135a78 2004-04-19 devnull o the system time in seconds and microseconds, comma separated.
231 1b135a78 2004-04-19 devnull o the wait channel message
232 1b135a78 2004-04-19 devnull o the process credentials consisting of the effective user id
233 1b135a78 2004-04-19 devnull and the list of groups (whose first member is the effective
234 1b135a78 2004-04-19 devnull group id) all comma separated.
235 1b135a78 2004-04-19 devnull */
236 1b135a78 2004-04-19 devnull
237 1b135a78 2004-04-19 devnull int
238 1b135a78 2004-04-19 devnull procnotes(int pid, char ***pnotes)
239 1b135a78 2004-04-19 devnull {
240 1b135a78 2004-04-19 devnull /* figure out the set of pending notes - how? */
241 1b135a78 2004-04-19 devnull *pnotes = nil;
242 1b135a78 2004-04-19 devnull return 0;
243 1b135a78 2004-04-19 devnull }
244 1b135a78 2004-04-19 devnull
245 1b135a78 2004-04-19 devnull static int
246 1b135a78 2004-04-19 devnull isstopped(int pid)
247 1b135a78 2004-04-19 devnull {
248 1b135a78 2004-04-19 devnull char buf[1024], *f[12];
249 1b135a78 2004-04-19 devnull int fd, n, nf;
250 1b135a78 2004-04-19 devnull
251 1b135a78 2004-04-19 devnull snprint(buf, sizeof buf, "/proc/%d/status", pid);
252 1b135a78 2004-04-19 devnull if((fd = open(buf, OREAD)) < 0)
253 1b135a78 2004-04-19 devnull return 0;
254 1b135a78 2004-04-19 devnull n = read(fd, buf, sizeof buf-1);
255 1b135a78 2004-04-19 devnull close(fd);
256 1b135a78 2004-04-19 devnull if(n <= 0)
257 1b135a78 2004-04-19 devnull return 0;
258 1b135a78 2004-04-19 devnull buf[n] = 0;
259 1b135a78 2004-04-19 devnull
260 1b135a78 2004-04-19 devnull if((nf = tokenize(buf, f, nelem(f))) < 11)
261 1b135a78 2004-04-19 devnull return 0;
262 1b135a78 2004-04-19 devnull if(strcmp(f[10], "nochan") == 0)
263 1b135a78 2004-04-19 devnull return 1;
264 1b135a78 2004-04-19 devnull return 0;
265 1b135a78 2004-04-19 devnull }
266 1b135a78 2004-04-19 devnull
267 1b135a78 2004-04-19 devnull #undef waitpid
268 1b135a78 2004-04-19 devnull
269 1b135a78 2004-04-19 devnull int
270 1b135a78 2004-04-19 devnull ctlproc(int pid, char *msg)
271 1b135a78 2004-04-19 devnull {
272 1b135a78 2004-04-19 devnull int p, status;
273 1b135a78 2004-04-19 devnull
274 1b135a78 2004-04-19 devnull if(strcmp(msg, "hang") == 0){
275 1b135a78 2004-04-19 devnull if(pid == getpid())
276 1b135a78 2004-04-19 devnull return ptrace(PT_TRACE_ME, 0, 0, 0);
277 1b135a78 2004-04-19 devnull werrstr("can only hang self");
278 1b135a78 2004-04-19 devnull return -1;
279 1b135a78 2004-04-19 devnull }
280 1b135a78 2004-04-19 devnull if(strcmp(msg, "kill") == 0)
281 1b135a78 2004-04-19 devnull return ptrace(PT_KILL, pid, 0, 0);
282 1b135a78 2004-04-19 devnull if(strcmp(msg, "startstop") == 0){
283 1b135a78 2004-04-19 devnull if(ptrace(PT_CONTINUE, pid, 0, 0) < 0)
284 1b135a78 2004-04-19 devnull return -1;
285 1b135a78 2004-04-19 devnull goto waitstop;
286 1b135a78 2004-04-19 devnull }
287 1b135a78 2004-04-19 devnull /*
288 1b135a78 2004-04-19 devnull if(strcmp(msg, "sysstop") == 0){
289 1b135a78 2004-04-19 devnull if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
290 1b135a78 2004-04-19 devnull return -1;
291 1b135a78 2004-04-19 devnull goto waitstop;
292 1b135a78 2004-04-19 devnull }
293 1b135a78 2004-04-19 devnull */
294 1b135a78 2004-04-19 devnull if(strcmp(msg, "stop") == 0){
295 1b135a78 2004-04-19 devnull if(kill(pid, SIGSTOP) < 0)
296 1b135a78 2004-04-19 devnull return -1;
297 1b135a78 2004-04-19 devnull goto waitstop;
298 1b135a78 2004-04-19 devnull }
299 1b135a78 2004-04-19 devnull if(strcmp(msg, "waitanyway") == 0)
300 1b135a78 2004-04-19 devnull goto waitanyway;
301 1b135a78 2004-04-19 devnull if(strcmp(msg, "waitstop") == 0){
302 1b135a78 2004-04-19 devnull waitstop:
303 1b135a78 2004-04-19 devnull if(isstopped(pid))
304 1b135a78 2004-04-19 devnull return 0;
305 1b135a78 2004-04-19 devnull waitanyway:
306 1b135a78 2004-04-19 devnull for(;;){
307 1b135a78 2004-04-19 devnull p = waitpid(pid, &status, WUNTRACED);
308 1b135a78 2004-04-19 devnull if(p <= 0)
309 1b135a78 2004-04-19 devnull return -1;
310 1b135a78 2004-04-19 devnull if(WIFEXITED(status) || WIFSTOPPED(status))
311 1b135a78 2004-04-19 devnull return 0;
312 1b135a78 2004-04-19 devnull }
313 1b135a78 2004-04-19 devnull }
314 1b135a78 2004-04-19 devnull if(strcmp(msg, "start") == 0)
315 1b135a78 2004-04-19 devnull return ptrace(PT_CONTINUE, pid, 0, 0);
316 1b135a78 2004-04-19 devnull werrstr("unknown control message '%s'", msg);
317 1b135a78 2004-04-19 devnull return -1;
318 1b135a78 2004-04-19 devnull }