Blame


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