1 /*
2 * Print functions for system call tracing.
3 */
4 #include "u.h"
5 #include "../port/lib.h"
6 #include "mem.h"
7 #include "dat.h"
8 #include "fns.h"
9
10 #include "/sys/src/libc/9syscall/sys.h"
11
12 // WE ARE OVERRUNNING SOMEHOW
13 static void
fmtrwdata(Fmt * f,char * a,int n,char * suffix)14 fmtrwdata(Fmt* f, char* a, int n, char* suffix)
15 {
16 int i;
17 char *t;
18
19 if(a == nil){
20 fmtprint(f, "0x0%s", suffix);
21 return;
22 }
23 validaddr((ulong)a, n, 0);
24 t = smalloc(n+1);
25 for(i = 0; i < n; i++)
26 if(a[i] > 0x20 && a[i] < 0x7f) /* printable ascii? */
27 t[i] = a[i];
28 else
29 t[i] = '.';
30
31 fmtprint(f, " %#p/\"%s\"%s", a, t, suffix);
32 free(t);
33 }
34
35 static void
fmtuserstring(Fmt * f,char * a,char * suffix)36 fmtuserstring(Fmt* f, char* a, char* suffix)
37 {
38 int n;
39 char *t;
40
41 if(a == nil){
42 fmtprint(f, "0/\"\"%s", suffix);
43 return;
44 }
45 validaddr((ulong)a, 1, 0);
46 n = ((char*)vmemchr(a, 0, 0x7fffffff) - a) + 1;
47 t = smalloc(n+1);
48 memmove(t, a, n);
49 t[n] = 0;
50 fmtprint(f, "%#p/\"%s\"%s", a, t, suffix);
51 free(t);
52 }
53
54 void
syscallfmt(int syscallno,ulong pc,va_list list)55 syscallfmt(int syscallno, ulong pc, va_list list)
56 {
57 long l;
58 Fmt fmt;
59 void *v;
60 vlong vl;
61 uintptr p;
62 int i[2], len;
63 char *a, **argv;
64
65 fmtstrinit(&fmt);
66 fmtprint(&fmt, "%uld %s ", up->pid, up->text);
67
68 if(syscallno > nsyscall)
69 fmtprint(&fmt, " %d ", syscallno);
70 else
71 fmtprint(&fmt, "%s ", sysctab[syscallno]?
72 sysctab[syscallno]: "huh?");
73
74 fmtprint(&fmt, "%ulx ", pc);
75 if(up->syscalltrace != nil)
76 free(up->syscalltrace);
77
78 switch(syscallno){
79 case SYSR1:
80 p = va_arg(list, uintptr);
81 fmtprint(&fmt, "%#p", p);
82 break;
83 case _ERRSTR: /* deprecated */
84 case CHDIR:
85 case EXITS:
86 case REMOVE:
87 a = va_arg(list, char*);
88 fmtuserstring(&fmt, a, "");
89 break;
90 case BIND:
91 a = va_arg(list, char*);
92 fmtuserstring(&fmt, a, " ");
93 a = va_arg(list, char*);
94 fmtuserstring(&fmt, a, " ");
95 i[0] = va_arg(list, int);
96 fmtprint(&fmt, "%#ux", i[0]);
97 break;
98 case CLOSE:
99 case NOTED:
100 i[0] = va_arg(list, int);
101 fmtprint(&fmt, "%d", i[0]);
102 break;
103 case DUP:
104 i[0] = va_arg(list, int);
105 i[1] = va_arg(list, int);
106 fmtprint(&fmt, "%d %d", i[0], i[1]);
107 break;
108 case ALARM:
109 l = va_arg(list, unsigned long);
110 fmtprint(&fmt, "%#lud ", l);
111 break;
112 case EXEC:
113 a = va_arg(list, char*);
114 fmtuserstring(&fmt, a, "");
115 argv = va_arg(list, char**);
116 validalign(PTR2UINT(argv), sizeof(char*));
117 for(;;){
118 validaddr((ulong)argv, sizeof(char**), 0);
119 a = *(char **)argv;
120 if(a == nil)
121 break;
122 fmtprint(&fmt, " ");
123 fmtuserstring(&fmt, a, "");
124 argv++;
125 }
126 break;
127 case _FSESSION: /* deprecated */
128 case _FSTAT: /* deprecated */
129 case _FWSTAT: /* obsolete */
130 i[0] = va_arg(list, int);
131 a = va_arg(list, char*);
132 fmtprint(&fmt, "%d %#p", i[0], a);
133 break;
134 case FAUTH:
135 i[0] = va_arg(list, int);
136 a = va_arg(list, char*);
137 fmtprint(&fmt, "%d", i[0]);
138 fmtuserstring(&fmt, a, "");
139 break;
140 case SEGBRK:
141 case RENDEZVOUS:
142 v = va_arg(list, void*);
143 fmtprint(&fmt, "%#p ", v);
144 v = va_arg(list, void*);
145 fmtprint(&fmt, "%#p", v);
146 break;
147 case _MOUNT: /* deprecated */
148 i[0] = va_arg(list, int);
149 fmtprint(&fmt, "%d ", i[0]);
150 a = va_arg(list, char*);
151 fmtuserstring(&fmt, a, " ");
152 i[0] = va_arg(list, int);
153 fmtprint(&fmt, "%#ux ", i[0]);
154 a = va_arg(list, char*);
155 fmtuserstring(&fmt, a, "");
156 break;
157 case OPEN:
158 a = va_arg(list, char*);
159 fmtuserstring(&fmt, a, " ");
160 i[0] = va_arg(list, int);
161 fmtprint(&fmt, "%#ux", i[0]);
162 break;
163 case OSEEK: /* deprecated */
164 i[0] = va_arg(list, int);
165 l = va_arg(list, long);
166 i[1] = va_arg(list, int);
167 fmtprint(&fmt, "%d %ld %d", i[0], l, i[1]);
168 break;
169 case SLEEP:
170 l = va_arg(list, long);
171 fmtprint(&fmt, "%ld", l);
172 break;
173 case _STAT: /* obsolete */
174 case _WSTAT: /* obsolete */
175 a = va_arg(list, char*);
176 fmtuserstring(&fmt, a, " ");
177 a = va_arg(list, char*);
178 fmtprint(&fmt, "%#p", a);
179 break;
180 case RFORK:
181 i[0] = va_arg(list, int);
182 fmtprint(&fmt, "%#ux", i[0]);
183 break;
184 case PIPE:
185 case BRK_:
186 v = va_arg(list, int*);
187 fmtprint(&fmt, "%#p", v);
188 break;
189 case CREATE:
190 a = va_arg(list, char*);
191 fmtuserstring(&fmt, a, " ");
192 i[0] = va_arg(list, int);
193 i[1] = va_arg(list, int);
194 fmtprint(&fmt, "%#ux %#ux", i[0], i[1]);
195 break;
196 case FD2PATH:
197 case FSTAT:
198 case FWSTAT:
199 i[0] = va_arg(list, int);
200 a = va_arg(list, char*);
201 l = va_arg(list, unsigned long);
202 fmtprint(&fmt, "%d %#p %lud", i[0], a, l);
203 break;
204 case NOTIFY:
205 case SEGDETACH:
206 case _WAIT: /* deprecated */
207 v = va_arg(list, void*);
208 fmtprint(&fmt, "%#p", v);
209 break;
210 case SEGATTACH:
211 i[0] = va_arg(list, int);
212 fmtprint(&fmt, "%d ", i[0]);
213 a = va_arg(list, char*);
214 fmtuserstring(&fmt, a, " ");
215 /*FALLTHROUGH*/
216 case SEGFREE:
217 case SEGFLUSH:
218 v = va_arg(list, void*);
219 l = va_arg(list, unsigned long);
220 fmtprint(&fmt, "%#p %lud", v, l);
221 break;
222 case UNMOUNT:
223 a = va_arg(list, char*);
224 fmtuserstring(&fmt, a, " ");
225 a = va_arg(list, char*);
226 fmtuserstring(&fmt, a, "");
227 break;
228 case SEMACQUIRE:
229 case SEMRELEASE:
230 v = va_arg(list, int*);
231 i[0] = va_arg(list, int);
232 fmtprint(&fmt, "%#p %d", v, i[0]);
233 break;
234 case TSEMACQUIRE:
235 v = va_arg(list, long*);
236 l = va_arg(list, ulong);
237 fmtprint(&fmt, "%#p %ld", v, l);
238 break;
239 case SEEK:
240 v = va_arg(list, vlong*);
241 i[0] = va_arg(list, int);
242 vl = va_arg(list, vlong);
243 i[1] = va_arg(list, int);
244 fmtprint(&fmt, "%#p %d %#llux %d", v, i[0], vl, i[1]);
245 break;
246 case FVERSION:
247 i[0] = va_arg(list, int);
248 i[1] = va_arg(list, int);
249 fmtprint(&fmt, "%d %d ", i[0], i[1]);
250 a = va_arg(list, char*);
251 fmtuserstring(&fmt, a, " ");
252 l = va_arg(list, unsigned long);
253 fmtprint(&fmt, "%lud", l);
254 break;
255 case WSTAT:
256 case STAT:
257 a = va_arg(list, char*);
258 fmtuserstring(&fmt, a, " ");
259 /*FALLTHROUGH*/
260 case ERRSTR:
261 case AWAIT:
262 a = va_arg(list, char*);
263 l = va_arg(list, unsigned long);
264 fmtprint(&fmt, "%#p %lud", a, l);
265 break;
266 case MOUNT:
267 i[0] = va_arg(list, int);
268 i[1] = va_arg(list, int);
269 fmtprint(&fmt, "%d %d ", i[0], i[1]);
270 a = va_arg(list, char*);
271 fmtuserstring(&fmt, a, " ");
272 i[0] = va_arg(list, int);
273 fmtprint(&fmt, "%#ux ", i[0]);
274 a = va_arg(list, char*);
275 fmtuserstring(&fmt, a, "");
276 break;
277 case _READ: /* deprecated */
278 case PREAD:
279 i[0] = va_arg(list, int);
280 v = va_arg(list, void*);
281 l = va_arg(list, long);
282 fmtprint(&fmt, "%d %#p %ld", i[0], v, l);
283 if(syscallno == PREAD){
284 vl = va_arg(list, vlong);
285 fmtprint(&fmt, " %lld", vl);
286 }
287 break;
288 case _WRITE: /* deprecated */
289 case PWRITE:
290 i[0] = va_arg(list, int);
291 v = va_arg(list, void*);
292 l = va_arg(list, long);
293 fmtprint(&fmt, "%d ", i[0]);
294 len = MIN(l, 64);
295 fmtrwdata(&fmt, v, len, " ");
296 fmtprint(&fmt, "%ld", l);
297 if(syscallno == PWRITE){
298 vl = va_arg(list, vlong);
299 fmtprint(&fmt, " %lld", vl);
300 }
301 break;
302 case NSEC:
303 v = va_arg(list, vlong*);
304 fmtprint(&fmt, "%#p", v);
305 break;
306 }
307
308 up->syscalltrace = fmtstrflush(&fmt);
309 }
310
311 void
sysretfmt(int syscallno,va_list list,long ret,uvlong start,uvlong stop)312 sysretfmt(int syscallno, va_list list, long ret, uvlong start, uvlong stop)
313 {
314 long l;
315 void* v;
316 Fmt fmt;
317 vlong vl;
318 int i, len;
319 char *a, *errstr;
320
321 fmtstrinit(&fmt);
322
323 if(up->syscalltrace)
324 free(up->syscalltrace);
325
326 errstr = "\"\"";
327 switch(syscallno){
328 default:
329 case ALARM:
330 case _WRITE:
331 case PWRITE:
332 if(ret == -1)
333 errstr = up->syserrstr;
334 fmtprint(&fmt, " = %ld", ret);
335 break;
336 case EXEC:
337 case SEGBRK:
338 case SEGATTACH:
339 case RENDEZVOUS:
340 if((void *)ret == (void*)-1)
341 errstr = up->syserrstr;
342 fmtprint(&fmt, " = %#p", (void *)ret);
343 break;
344 case AWAIT:
345 a = va_arg(list, char*);
346 l = va_arg(list, unsigned long);
347 if(ret > 0){
348 fmtuserstring(&fmt, a, " ");
349 fmtprint(&fmt, "%lud = %ld", l, ret);
350 }
351 else{
352 fmtprint(&fmt, "%#p/\"\" %lud = %ld", a, l, ret);
353 errstr = up->syserrstr;
354 }
355 break;
356 case _ERRSTR:
357 case ERRSTR:
358 a = va_arg(list, char*);
359 if(syscallno == _ERRSTR)
360 l = 64;
361 else
362 l = va_arg(list, unsigned long);
363 if(ret > 0){
364 fmtuserstring(&fmt, a, " ");
365 fmtprint(&fmt, "%lud = %ld", l, ret);
366 }
367 else{
368 fmtprint(&fmt, "\"\" %lud = %ld", l, ret);
369 errstr = up->syserrstr;
370 }
371 break;
372 case FD2PATH:
373 i = va_arg(list, int);
374 USED(i);
375 a = va_arg(list, char*);
376 l = va_arg(list, unsigned long);
377 if(ret > 0){
378 fmtuserstring(&fmt, a, " ");
379 fmtprint(&fmt, "%lud = %ld", l, ret);
380 }
381 else{
382 fmtprint(&fmt, "\"\" %lud = %ld", l, ret);
383 errstr = up->syserrstr;
384 }
385 break;
386 case _READ:
387 case PREAD:
388 i = va_arg(list, int);
389 USED(i);
390 v = va_arg(list, void*);
391 l = va_arg(list, long);
392 if(ret > 0){
393 len = MIN(ret, 64);
394 fmtrwdata(&fmt, v, len, "");
395 }
396 else{
397 fmtprint(&fmt, "/\"\"");
398 errstr = up->syserrstr;
399 }
400 fmtprint(&fmt, " %ld", l);
401 if(syscallno == PREAD){
402 vl = va_arg(list, vlong);
403 fmtprint(&fmt, " %lld", vl);
404 }
405 fmtprint(&fmt, " = %ld", ret);
406 break;
407 case NSEC:
408 fmtprint(&fmt, " = %ld", ret); /* FoV */
409 break;
410 }
411 fmtprint(&fmt, " %s %#llud %#llud\n", errstr, start, stop);
412 up->syscalltrace = fmtstrflush(&fmt);
413 }
414