426 lines
8.9 KiB
C
426 lines
8.9 KiB
C
/*
|
|
* 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((uintptr)a, n, 0);
|
|
t = smalloc(n+1);
|
|
t[n] = 0;
|
|
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)
|
|
{
|
|
char *t, *e;
|
|
int n;
|
|
|
|
if(a == nil){
|
|
fmtprint(f, "0/\"\"%s", suffix);
|
|
return;
|
|
}
|
|
validaddr((uintptr)a, 1, 0);
|
|
n = 1<<16;
|
|
e = vmemchr(a, 0, n);
|
|
if(e != nil)
|
|
n = e - a;
|
|
t = smalloc(n+1);
|
|
memmove(t, a, n);
|
|
t[n] = 0;
|
|
fmtprint(f, "%#p/\"%s\"%s", a, t, suffix);
|
|
free(t);
|
|
}
|
|
|
|
void
|
|
syscallfmt(ulong syscallno, uintptr 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, " %uld ", syscallno);
|
|
else
|
|
fmtprint(&fmt, "%s ", sysctab[syscallno]?
|
|
sysctab[syscallno]: "huh?");
|
|
|
|
fmtprint(&fmt, "%p ", pc);
|
|
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((uintptr)argv);
|
|
for(;;){
|
|
validaddr((uintptr)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 TSEMACQUIRE:
|
|
v = va_arg(list, int*);
|
|
l = va_arg(list, ulong);
|
|
fmtprint(&fmt, "%#p %ld", v, l);
|
|
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;
|
|
case _NSEC:
|
|
if(sizeof(uintptr) == sizeof(vlong))
|
|
break;
|
|
v = va_arg(list, vlong*);
|
|
fmtprint(&fmt, "%#p", v);
|
|
break;
|
|
}
|
|
|
|
a = fmtstrflush(&fmt);
|
|
qlock(&up->debug);
|
|
free(up->syscalltrace);
|
|
up->syscalltrace = a;
|
|
qunlock(&up->debug);
|
|
}
|
|
|
|
void
|
|
sysretfmt(ulong syscallno, va_list list, uintptr ret, uvlong start, uvlong stop)
|
|
{
|
|
long l;
|
|
void* v;
|
|
Fmt fmt;
|
|
vlong vl;
|
|
int i, len;
|
|
char *a, *errstr;
|
|
|
|
fmtstrinit(&fmt);
|
|
|
|
errstr = "\"\"";
|
|
switch(syscallno){
|
|
case EXEC:
|
|
case SEGBRK:
|
|
case SEGATTACH:
|
|
case RENDEZVOUS:
|
|
if((void *)ret == (void*)-1)
|
|
errstr = up->syserrstr;
|
|
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, (long)ret);
|
|
}
|
|
else{
|
|
fmtprint(&fmt, "%#p/\"\" %lud = %ld", a, l, (long)ret);
|
|
errstr = up->syserrstr;
|
|
}
|
|
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, (long)ret);
|
|
}
|
|
else{
|
|
fmtprint(&fmt, "\"\" %lud = %ld", l, (long)ret);
|
|
errstr = up->syserrstr;
|
|
}
|
|
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, (long)ret);
|
|
}
|
|
else{
|
|
fmtprint(&fmt, "\"\" %lud = %ld", l, (long)ret);
|
|
errstr = up->syserrstr;
|
|
}
|
|
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->syserrstr;
|
|
}
|
|
fmtprint(&fmt, " %ld", l);
|
|
if(syscallno == PREAD){
|
|
vl = va_arg(list, vlong);
|
|
fmtprint(&fmt, " %lld", vl);
|
|
}
|
|
fmtprint(&fmt, " = %ld", (long)ret);
|
|
break;
|
|
case _NSEC:
|
|
if(sizeof(uintptr) == sizeof(vlong)){
|
|
fmtprint(&fmt, " = %lld", (vlong)ret);
|
|
break;
|
|
}
|
|
/* wet floor */
|
|
case ALARM:
|
|
case _WRITE:
|
|
case PWRITE:
|
|
default:
|
|
if((long)ret == -1)
|
|
errstr = up->syserrstr;
|
|
fmtprint(&fmt, " = %ld", (long)ret);
|
|
break;
|
|
}
|
|
fmtprint(&fmt, " %s %#llud %#llud\n", errstr, start, stop);
|
|
|
|
a = fmtstrflush(&fmt);
|
|
qlock(&up->debug);
|
|
free(up->syscalltrace);
|
|
up->syscalltrace = a;
|
|
qunlock(&up->debug);
|
|
}
|