xref: /plan9/sys/src/9/port/syscallfmt.c (revision 86abb9fb23a9f11dbfd9e6dc2fe0c20d62417d94)
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
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
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
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 		evenaddr(PTR2UINT(argv));
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 	}
303 
304 	up->syscalltrace = fmtstrflush(&fmt);
305 }
306 
307 void
308 sysretfmt(int syscallno, va_list list, long ret, uvlong start, uvlong stop)
309 {
310 	long l;
311 	void* v;
312 	Fmt fmt;
313 	vlong vl;
314 	int i, len;
315 	char *a, *errstr;
316 
317 	fmtstrinit(&fmt);
318 
319 	if(up->syscalltrace)
320 		free(up->syscalltrace);
321 
322 	errstr = "\"\"";
323 	switch(syscallno){
324 	default:
325 	case ALARM:
326 	case _WRITE:
327 	case PWRITE:
328 		if(ret == -1)
329 			errstr = up->syserrstr;
330 		fmtprint(&fmt, " = %ld", ret);
331 		break;
332 	case EXEC:
333 	case SEGBRK:
334 	case SEGATTACH:
335 	case RENDEZVOUS:
336 		if((void *)ret == (void*)-1)
337 			errstr = up->syserrstr;
338 		fmtprint(&fmt, " = %#p", (void *)ret);
339 		break;
340 	case AWAIT:
341 		a = va_arg(list, char*);
342 		l = va_arg(list, unsigned long);
343 		if(ret > 0){
344 			fmtuserstring(&fmt, a, " ");
345 			fmtprint(&fmt, "%lud = %ld", l, ret);
346 		}
347 		else{
348 			fmtprint(&fmt, "%#p/\"\" %lud = %ld", a, l, ret);
349 			errstr = up->syserrstr;
350 		}
351 		break;
352 	case _ERRSTR:
353 	case ERRSTR:
354 		a = va_arg(list, char*);
355 		if(syscallno == _ERRSTR)
356 			l = 64;
357 		else
358 			l = va_arg(list, unsigned long);
359 		if(ret > 0){
360 			fmtuserstring(&fmt, a, " ");
361 			fmtprint(&fmt, "%lud = %ld", l, ret);
362 		}
363 		else{
364 			fmtprint(&fmt, "\"\" %lud = %ld", l, ret);
365 			errstr = up->syserrstr;
366 		}
367 		break;
368 	case FD2PATH:
369 		i = va_arg(list, int);
370 		USED(i);
371 		a = va_arg(list, char*);
372 		l = va_arg(list, unsigned long);
373 		if(ret > 0){
374 			fmtuserstring(&fmt, a, " ");
375 			fmtprint(&fmt, "%lud = %ld", l, ret);
376 		}
377 		else{
378 			fmtprint(&fmt, "\"\" %lud = %ld", l, ret);
379 			errstr = up->syserrstr;
380 		}
381 		break;
382 	case _READ:
383 	case PREAD:
384 		i = va_arg(list, int);
385 		USED(i);
386 		v = va_arg(list, void*);
387 		l = va_arg(list, long);
388 		if(ret > 0){
389 			len = MIN(ret, 64);
390 			fmtrwdata(&fmt, v, len, "");
391 		}
392 		else{
393 			fmtprint(&fmt, "/\"\"");
394 			errstr = up->syserrstr;
395 		}
396 		fmtprint(&fmt, " %ld", l);
397 		if(syscallno == PREAD){
398 			vl = va_arg(list, vlong);
399 			fmtprint(&fmt, " %lld", vl);
400 		}
401 		fmtprint(&fmt, " = %ld", ret);
402 		break;
403 	}
404 	fmtprint(&fmt, " %s %#llud %#llud\n", errstr, start, stop);
405 	up->syscalltrace = fmtstrflush(&fmt);
406 }
407