xref: /plan9/sys/src/9/port/syscallfmt.c (revision fac6300f1f1b25611e114fc0bdda9cf428c13da4)
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