|
@@ -0,0 +1,405 @@
|
|
|
+/*
|
|
|
+ * Print functions for system call tracing.
|
|
|
+ */
|
|
|
+#include "u.h"
|
|
|
+#include "../port/lib.h"
|
|
|
+#include "mem.h"
|
|
|
+#include "dat.h"
|
|
|
+#include "fns.h"
|
|
|
+
|
|
|
+#include "/sys/src/libc/9syscall/sys.h"
|
|
|
+
|
|
|
+// WE ARE OVERRUNNING SOMEHOW
|
|
|
+static void
|
|
|
+fmtrwdata(Fmt* f, char* a, int n, char* suffix)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ char *t;
|
|
|
+
|
|
|
+ if(a == nil){
|
|
|
+ fmtprint(f, "0x0%s", suffix);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ validaddr((ulong)a, n, 0);
|
|
|
+ t = smalloc(n+1);
|
|
|
+ for(i = 0; i < n; i++)
|
|
|
+ if(a[i] > 0x20 && a[i] < 0x7f) /* printable ascii? */
|
|
|
+ t[i] = a[i];
|
|
|
+ else
|
|
|
+ t[i] = '.';
|
|
|
+
|
|
|
+ fmtprint(f, " %#p/\"%s\"%s", a, t, suffix);
|
|
|
+ free(t);
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+fmtuserstring(Fmt* f, char* a, char* suffix)
|
|
|
+{
|
|
|
+ int n;
|
|
|
+ char *t;
|
|
|
+
|
|
|
+ if(a == nil){
|
|
|
+ fmtprint(f, "0/\"\"%s", suffix);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ validaddr((ulong)a, 1, 0);
|
|
|
+ n = ((char*)vmemchr(a, 0, 0x7fffffff) - a) + 1;
|
|
|
+ t = smalloc(n+1);
|
|
|
+ memmove(t, a, n);
|
|
|
+ t[n] = 0;
|
|
|
+ fmtprint(f, "%#p/\"%s\"%s", a, t, suffix);
|
|
|
+ free(t);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+syscallfmt(int syscallno, ulong pc, va_list list)
|
|
|
+{
|
|
|
+ long l;
|
|
|
+ Fmt fmt;
|
|
|
+ void *v;
|
|
|
+ vlong vl;
|
|
|
+ uintptr p;
|
|
|
+ int i[2], len;
|
|
|
+ char *a, **argv;
|
|
|
+
|
|
|
+ fmtstrinit(&fmt);
|
|
|
+ fmtprint(&fmt, "%uld %s ", up->pid, up->text);
|
|
|
+
|
|
|
+ if(syscallno > nsyscall)
|
|
|
+ fmtprint(&fmt, " %d ", syscallno);
|
|
|
+ else
|
|
|
+ fmtprint(&fmt, "%s ", sysctab[syscallno]?
|
|
|
+ sysctab[syscallno]: "huh?");
|
|
|
+
|
|
|
+ fmtprint(&fmt, "%ulx ", pc);
|
|
|
+ if(up->syscalltrace != nil)
|
|
|
+ free(up->syscalltrace);
|
|
|
+
|
|
|
+ switch(syscallno){
|
|
|
+ case SYSR1:
|
|
|
+ p = va_arg(list, uintptr);
|
|
|
+ fmtprint(&fmt, "%#p", p);
|
|
|
+ break;
|
|
|
+ case _ERRSTR: /* deprecated */
|
|
|
+ case CHDIR:
|
|
|
+ case EXITS:
|
|
|
+ case REMOVE:
|
|
|
+ a = va_arg(list, char*);
|
|
|
+ fmtuserstring(&fmt, a, "");
|
|
|
+ break;
|
|
|
+ case BIND:
|
|
|
+ a = va_arg(list, char*);
|
|
|
+ fmtuserstring(&fmt, a, " ");
|
|
|
+ a = va_arg(list, char*);
|
|
|
+ fmtuserstring(&fmt, a, " ");
|
|
|
+ i[0] = va_arg(list, int);
|
|
|
+ fmtprint(&fmt, "%#ux", i[0]);
|
|
|
+ break;
|
|
|
+ case CLOSE:
|
|
|
+ case NOTED:
|
|
|
+ i[0] = va_arg(list, int);
|
|
|
+ fmtprint(&fmt, "%d", i[0]);
|
|
|
+ break;
|
|
|
+ case DUP:
|
|
|
+ i[0] = va_arg(list, int);
|
|
|
+ i[1] = va_arg(list, int);
|
|
|
+ fmtprint(&fmt, "%d %d", i[0], i[1]);
|
|
|
+ break;
|
|
|
+ case ALARM:
|
|
|
+ l = va_arg(list, unsigned long);
|
|
|
+ fmtprint(&fmt, "%#lud ", l);
|
|
|
+ break;
|
|
|
+ case EXEC:
|
|
|
+ a = va_arg(list, char*);
|
|
|
+ fmtuserstring(&fmt, a, "");
|
|
|
+ argv = va_arg(list, char**);
|
|
|
+ evenaddr(PTR2UINT(argv));
|
|
|
+ for(;;){
|
|
|
+ validaddr((ulong)argv, sizeof(char**), 0);
|
|
|
+ a = *(char **)argv;
|
|
|
+ if(a == nil)
|
|
|
+ break;
|
|
|
+ fmtprint(&fmt, " ");
|
|
|
+ fmtuserstring(&fmt, a, "");
|
|
|
+ argv++;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case _FSESSION: /* deprecated */
|
|
|
+ case _FSTAT: /* deprecated */
|
|
|
+ case _FWSTAT: /* obsolete */
|
|
|
+ i[0] = va_arg(list, int);
|
|
|
+ a = va_arg(list, char*);
|
|
|
+ fmtprint(&fmt, "%d %#p", i[0], a);
|
|
|
+ break;
|
|
|
+ case FAUTH:
|
|
|
+ i[0] = va_arg(list, int);
|
|
|
+ a = va_arg(list, char*);
|
|
|
+ fmtprint(&fmt, "%d", i[0]);
|
|
|
+ fmtuserstring(&fmt, a, "");
|
|
|
+ break;
|
|
|
+ case SEGBRK:
|
|
|
+ case RENDEZVOUS:
|
|
|
+ v = va_arg(list, void*);
|
|
|
+ fmtprint(&fmt, "%#p ", v);
|
|
|
+ v = va_arg(list, void*);
|
|
|
+ fmtprint(&fmt, "%#p", v);
|
|
|
+ break;
|
|
|
+ case _MOUNT: /* deprecated */
|
|
|
+ i[0] = va_arg(list, int);
|
|
|
+ fmtprint(&fmt, "%d ", i[0]);
|
|
|
+ a = va_arg(list, char*);
|
|
|
+ fmtuserstring(&fmt, a, " ");
|
|
|
+ i[0] = va_arg(list, int);
|
|
|
+ fmtprint(&fmt, "%#ux ", i[0]);
|
|
|
+ a = va_arg(list, char*);
|
|
|
+ fmtuserstring(&fmt, a, "");
|
|
|
+ break;
|
|
|
+ case OPEN:
|
|
|
+ a = va_arg(list, char*);
|
|
|
+ fmtuserstring(&fmt, a, " ");
|
|
|
+ i[0] = va_arg(list, int);
|
|
|
+ fmtprint(&fmt, "%#ux", i[0]);
|
|
|
+ break;
|
|
|
+ case OSEEK: /* deprecated */
|
|
|
+ i[0] = va_arg(list, int);
|
|
|
+ l = va_arg(list, long);
|
|
|
+ i[1] = va_arg(list, int);
|
|
|
+ fmtprint(&fmt, "%d %ld %d", i[0], l, i[1]);
|
|
|
+ break;
|
|
|
+ case SLEEP:
|
|
|
+ l = va_arg(list, long);
|
|
|
+ fmtprint(&fmt, "%ld", l);
|
|
|
+ break;
|
|
|
+ case _STAT: /* obsolete */
|
|
|
+ case _WSTAT: /* obsolete */
|
|
|
+ a = va_arg(list, char*);
|
|
|
+ fmtuserstring(&fmt, a, " ");
|
|
|
+ a = va_arg(list, char*);
|
|
|
+ fmtprint(&fmt, "%#p", a);
|
|
|
+ break;
|
|
|
+ case RFORK:
|
|
|
+ i[0] = va_arg(list, int);
|
|
|
+ fmtprint(&fmt, "%#ux", i[0]);
|
|
|
+ break;
|
|
|
+ case PIPE:
|
|
|
+ case BRK_:
|
|
|
+ v = va_arg(list, int*);
|
|
|
+ fmtprint(&fmt, "%#p", v);
|
|
|
+ break;
|
|
|
+ case CREATE:
|
|
|
+ a = va_arg(list, char*);
|
|
|
+ fmtuserstring(&fmt, a, " ");
|
|
|
+ i[0] = va_arg(list, int);
|
|
|
+ i[1] = va_arg(list, int);
|
|
|
+ fmtprint(&fmt, "%#ux %#ux", i[0], i[1]);
|
|
|
+ break;
|
|
|
+ case FD2PATH:
|
|
|
+ case FSTAT:
|
|
|
+ case FWSTAT:
|
|
|
+ i[0] = va_arg(list, int);
|
|
|
+ a = va_arg(list, char*);
|
|
|
+ l = va_arg(list, unsigned long);
|
|
|
+ fmtprint(&fmt, "%d %#p %lud", i[0], a, l);
|
|
|
+ break;
|
|
|
+ case NOTIFY:
|
|
|
+ case SEGDETACH:
|
|
|
+ case _WAIT: /* deprecated */
|
|
|
+ v = va_arg(list, void*);
|
|
|
+ fmtprint(&fmt, "%#p", v);
|
|
|
+ break;
|
|
|
+ case SEGATTACH:
|
|
|
+ i[0] = va_arg(list, int);
|
|
|
+ fmtprint(&fmt, "%d ", i[0]);
|
|
|
+ a = va_arg(list, char*);
|
|
|
+ fmtuserstring(&fmt, a, " ");
|
|
|
+ /*FALLTHROUGH*/
|
|
|
+ case SEGFREE:
|
|
|
+ case SEGFLUSH:
|
|
|
+ v = va_arg(list, void*);
|
|
|
+ l = va_arg(list, unsigned long);
|
|
|
+ fmtprint(&fmt, "%#p %lud", v, l);
|
|
|
+ break;
|
|
|
+ case UNMOUNT:
|
|
|
+ a = va_arg(list, char*);
|
|
|
+ fmtuserstring(&fmt, a, " ");
|
|
|
+ a = va_arg(list, char*);
|
|
|
+ fmtuserstring(&fmt, a, "");
|
|
|
+ break;
|
|
|
+ case SEMACQUIRE:
|
|
|
+ case SEMRELEASE:
|
|
|
+ v = va_arg(list, int*);
|
|
|
+ i[0] = va_arg(list, int);
|
|
|
+ fmtprint(&fmt, "%#p %d", v, i[0]);
|
|
|
+ break;
|
|
|
+ case SEEK:
|
|
|
+ v = va_arg(list, vlong*);
|
|
|
+ i[0] = va_arg(list, int);
|
|
|
+ vl = va_arg(list, vlong);
|
|
|
+ i[1] = va_arg(list, int);
|
|
|
+ fmtprint(&fmt, "%#p %d %#llux %d", v, i[0], vl, i[1]);
|
|
|
+ break;
|
|
|
+ case FVERSION:
|
|
|
+ i[0] = va_arg(list, int);
|
|
|
+ i[1] = va_arg(list, int);
|
|
|
+ fmtprint(&fmt, "%d %d ", i[0], i[1]);
|
|
|
+ a = va_arg(list, char*);
|
|
|
+ fmtuserstring(&fmt, a, " ");
|
|
|
+ l = va_arg(list, unsigned long);
|
|
|
+ fmtprint(&fmt, "%lud", l);
|
|
|
+ break;
|
|
|
+ case WSTAT:
|
|
|
+ case STAT:
|
|
|
+ a = va_arg(list, char*);
|
|
|
+ fmtuserstring(&fmt, a, " ");
|
|
|
+ /*FALLTHROUGH*/
|
|
|
+ case ERRSTR:
|
|
|
+ case AWAIT:
|
|
|
+ a = va_arg(list, char*);
|
|
|
+ l = va_arg(list, unsigned long);
|
|
|
+ fmtprint(&fmt, "%#p %lud", a, l);
|
|
|
+ break;
|
|
|
+ case MOUNT:
|
|
|
+ i[0] = va_arg(list, int);
|
|
|
+ i[1] = va_arg(list, int);
|
|
|
+ fmtprint(&fmt, "%d %d ", i[0], i[1]);
|
|
|
+ a = va_arg(list, char*);
|
|
|
+ fmtuserstring(&fmt, a, " ");
|
|
|
+ i[0] = va_arg(list, int);
|
|
|
+ fmtprint(&fmt, "%#ux ", i[0]);
|
|
|
+ a = va_arg(list, char*);
|
|
|
+ fmtuserstring(&fmt, a, "");
|
|
|
+ break;
|
|
|
+ case _READ: /* deprecated */
|
|
|
+ case PREAD:
|
|
|
+ i[0] = va_arg(list, int);
|
|
|
+ v = va_arg(list, void*);
|
|
|
+ l = va_arg(list, long);
|
|
|
+ fmtprint(&fmt, "%d %#p %ld", i[0], v, l);
|
|
|
+ if(syscallno == PREAD){
|
|
|
+ vl = va_arg(list, vlong);
|
|
|
+ fmtprint(&fmt, " %lld", vl);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case _WRITE: /* deprecated */
|
|
|
+ case PWRITE:
|
|
|
+ i[0] = va_arg(list, int);
|
|
|
+ v = va_arg(list, void*);
|
|
|
+ l = va_arg(list, long);
|
|
|
+ fmtprint(&fmt, "%d ", i[0]);
|
|
|
+ len = MIN(l, 64);
|
|
|
+ fmtrwdata(&fmt, v, len, " ");
|
|
|
+ fmtprint(&fmt, "%ld", l);
|
|
|
+ if(syscallno == PWRITE){
|
|
|
+ vl = va_arg(list, vlong);
|
|
|
+ fmtprint(&fmt, " %lld", vl);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ up->syscalltrace = fmtstrflush(&fmt);
|
|
|
+}
|
|
|
+
|
|
|
+void
|
|
|
+sysretfmt(int syscallno, va_list list, long ret, uvlong start, uvlong stop)
|
|
|
+{
|
|
|
+ long l;
|
|
|
+ void* v;
|
|
|
+ Fmt fmt;
|
|
|
+ vlong vl;
|
|
|
+ int i, len;
|
|
|
+ char *a, *errstr;
|
|
|
+
|
|
|
+ fmtstrinit(&fmt);
|
|
|
+
|
|
|
+ if(up->syscalltrace)
|
|
|
+ free(up->syscalltrace);
|
|
|
+
|
|
|
+ errstr = "\"\"";
|
|
|
+ switch(syscallno){
|
|
|
+ default:
|
|
|
+ if(ret == -1)
|
|
|
+ errstr = up->errstr;
|
|
|
+ fmtprint(&fmt, " = %ld", ret);
|
|
|
+ break;
|
|
|
+ case ALARM:
|
|
|
+ case _WRITE:
|
|
|
+ case PWRITE:
|
|
|
+ if(ret == -1)
|
|
|
+ errstr = up->errstr;
|
|
|
+ fmtprint(&fmt, " = %ld", ret);
|
|
|
+ break;
|
|
|
+ case EXEC:
|
|
|
+ case SEGBRK:
|
|
|
+ case SEGATTACH:
|
|
|
+ case RENDEZVOUS:
|
|
|
+ if((void *)ret == (void*)-1)
|
|
|
+ errstr = up->errstr;
|
|
|
+ fmtprint(&fmt, " = %#p", (void *)ret);
|
|
|
+ break;
|
|
|
+ case AWAIT:
|
|
|
+ a = va_arg(list, char*);
|
|
|
+ l = va_arg(list, unsigned long);
|
|
|
+ if(ret > 0){
|
|
|
+ fmtuserstring(&fmt, a, " ");
|
|
|
+ fmtprint(&fmt, "%lud = %ld", l, ret);
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ fmtprint(&fmt, "%#p/\"\" %lud = %ld", a, l, ret);
|
|
|
+ errstr = up->errstr;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case _ERRSTR:
|
|
|
+ case ERRSTR:
|
|
|
+ a = va_arg(list, char*);
|
|
|
+ if(syscallno == _ERRSTR)
|
|
|
+ l = 64;
|
|
|
+ else
|
|
|
+ l = va_arg(list, unsigned long);
|
|
|
+ if(ret > 0){
|
|
|
+ fmtuserstring(&fmt, a, " ");
|
|
|
+ fmtprint(&fmt, "%lud = %ld", l, ret);
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ fmtprint(&fmt, "\"\" %lud = %ld", l, ret);
|
|
|
+ errstr = up->errstr;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case FD2PATH:
|
|
|
+ i = va_arg(list, int);
|
|
|
+ USED(i);
|
|
|
+ a = va_arg(list, char*);
|
|
|
+ l = va_arg(list, unsigned long);
|
|
|
+ if(ret > 0){
|
|
|
+ fmtuserstring(&fmt, a, " ");
|
|
|
+ fmtprint(&fmt, "%lud = %ld", l, ret);
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ fmtprint(&fmt, "\"\" %lud = %ld", l, ret);
|
|
|
+ errstr = up->errstr;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case _READ:
|
|
|
+ case PREAD:
|
|
|
+ i = va_arg(list, int);
|
|
|
+ USED(i);
|
|
|
+ v = va_arg(list, void*);
|
|
|
+ l = va_arg(list, long);
|
|
|
+ if(ret > 0){
|
|
|
+ len = MIN(ret, 64);
|
|
|
+ fmtrwdata(&fmt, v, len, "");
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ fmtprint(&fmt, "/\"\"");
|
|
|
+ errstr = up->errstr;
|
|
|
+ }
|
|
|
+ fmtprint(&fmt, " %ld", l);
|
|
|
+ if(syscallno == PREAD){
|
|
|
+ vl = va_arg(list, vlong);
|
|
|
+ fmtprint(&fmt, " %lld", vl);
|
|
|
+ }
|
|
|
+ fmtprint(&fmt, " = %ld", ret);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ fmtprint(&fmt, " %s %#llud %#llud\n", errstr, start, stop);
|
|
|
+ up->syscalltrace = fmtstrflush(&fmt);
|
|
|
+}
|