/* * Heavily modified copy of /sys/src/9/pc/trap.c * A shell of its former self. */#define WANT_M #include "u.h"#include "libvx32/vx32.h"#include "tos.h"#include "lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h"#include "ureg.h"#include "error.h"#include "trace.h"#include "systab.h" int tracesyscalls;static void noted(Ureg*, ulong);static void mathemu(Ureg*, void*);static void syscall(Ureg*); /* going to user space */voidkexit(Ureg *ureg){ uvlong t; Tos *tos; /* precise time accounting, kernel exit */ tos = (Tos*)(up->pmmu.uzero+USTKTOP-sizeof(Tos)); cycles(&t); tos->kcycles += t - up->kentry; tos->pcycles = up->pcycles; tos->pid = up->pid;} static char* excname[32] = { "divide error", "debug exception", "nonmaskable interrupt", "breakpoint", "overflow", "bounds check", "invalid opcode", "coprocessor not available", "double fault", "coprocessor segment overrun", "invalid TSS", "segment not present", "stack exception", "general protection violation", "page fault", "15 (reserved)", "coprocessor error", "alignment check", "machine check", "19 (reserved)", "20 (reserved)", "21 (reserved)", "22 (reserved)", "23 (reserved)", "24 (reserved)", "25 (reserved)", "26 (reserved)", "27 (reserved)", "28 (reserved)", "29 (reserved)", "30 (reserved)", "31 (reserved)",}; /* * Handle a trap. */voidtrap(Ureg *ureg){ char buf[ERRMAX]; int vno; vno = ureg->trap; switch(vno){ case VXTRAP_FPOFF: mathemu(ureg, nil); return; case VXTRAP_SOFT+0x40: /* int $0x40 - system call */ if(tracesyscalls){ uint32 *sp = (uint32*)(up->pmmu.uzero + ureg->usp); iprint("%d [%s] %s %#ux %08ux %08ux %08ux %08ux\n", up->pid, up->text, sysctab[ureg->ax], sp[0], sp[1], sp[2], sp[3]); } syscall(ureg); if(tracesyscalls){ if(ureg->ax == -1) iprint("%d [%s] -> %s\n", up->pid, up->text, up->syserrstr); else iprint("%d [%s] -> %#ux\n", up->pid, up->text, ureg->ax); } return; case VXTRAP_IRQ+VXIRQ_TIMER: sched(); break; case 3: // breakpoint /* restore pc to instruction that caused the trap */ ureg->pc--; sprint(buf, "sys: breakpoint"); postnote(up, 1, buf, NDebug); break; default: if(vno < nelem(excname)){ spllo(); sprint(buf, "sys: trap: %s", excname[vno]); postnote(up, 1, buf, NDebug); }else{ dumpregs(ureg); if(vno < nelem(excname)) panic("%s", excname[vno]); panic("unknown trap/intr: %#x", vno); } break; } if(up->procctl || up->nnote) notify(ureg); spllo(); /* no actual effect, just silences prints */ kexit(ureg);} voiddumpregs2(Ureg* ureg){ if(up) print("cpu%d: registers for %s %lud\n", m->machno, up->text, up->pid); else print("cpu%d: registers for kernel\n", m->machno); print("FLAGS=%luX TRAP=%luX ECODE=%luX PC=%luX", ureg->flags, ureg->trap, ureg->ecode, ureg->pc); print(" USP=%luX\n", ureg->usp); print(" AX %8.8luX BX %8.8luX CX %8.8luX DX %8.8luX\n", ureg->ax, ureg->bx, ureg->cx, ureg->dx); print(" SI %8.8luX DI %8.8luX BP %8.8luX\n", ureg->si, ureg->di, ureg->bp);} voiddumpregs(Ureg* ureg){ dumpregs2(ureg); /* * Processor control registers. * If machine check exception, time stamp counter, page size extensions * or enhanced virtual 8086 mode extensions are supported, there is a * CR4. If there is a CR4 and machine check extensions, read the machine * check address and machine check type registers if RDMSR supported. print(" CR0 %8.8lux CR2 %8.8lux CR3 %8.8lux", getcr0(), getcr2(), getcr3()); if(m->cpuiddx & 0x9A){ vlong mca, mct; iprint(" CR4 %8.8lux", getcr4()); if((m->cpuiddx & 0xA0) == 0xA0){ rdmsr(0x00, &mca); rdmsr(0x01, &mct); iprint("\n MCA %8.8llux MCT %8.8llux", mca, mct); } } print("\n ur %lux up %lux\n", ureg, up); */} static voidfmtrwdata(Fmt *f, ulong s, int n, char *suffix){ char *t, *src; int i; if (! s) { fmtprint(f, "0x0", suffix); return; } src = uvalidaddr(s, 1, 0); t = smalloc(n+1); for(i = 0; i < n; i++) if (isgraph(src[i])) t[i] = src[i]; else t[i] = '.'; fmtprint(f, "%08ux/\"%s\"%s", s, t, suffix); free(t);} static voidfmtuserstring(Fmt *f, ulong s, char *suffix){ char *es, *t, *src; int n; if (! s){ fmtprint(f, "0/\"\"%s", suffix); return; } src = uvalidaddr(s, 1, 0); es = vmemchr(src, 0, 1<<16); n = es - src; t = smalloc(n+1); memmove(t, src, n); t[n] = 0; fmtprint(f, "%08ux/\"%s\"%s", s, t, suffix); free(t);} static voidsyscallprint(Ureg *ureg){ uint32 *sp; int syscallno; vlong offset; Fmt fmt; int len; uint32 argp, a; sp = (uint32*)(up->pmmu.uzero + ureg->usp); syscallno = ureg->ax; offset = 0; fmtstrinit(&fmt); fmtprint(&fmt, "%d %s ", up->pid, up->text); /* accomodate process-private system calls */ if(syscallno > nelem(sysctab)) fmtprint(&fmt, " %d %#x ", syscallno, sp[0]); else fmtprint(&fmt, "%s %#ux ", sysctab[syscallno], sp[0]); if(up->syscalltrace) free(up->syscalltrace); switch(syscallno) { case SYSR1: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case _ERRSTR: fmtuserstring(&fmt, sp[1], ""); break; case BIND: fmtuserstring(&fmt, sp[1], " "); fmtuserstring(&fmt, sp[2], " "); fmtprint(&fmt, "%#ux", sp[3]); break; case CHDIR: fmtuserstring(&fmt, sp[1], ""); break; case CLOSE: fmtprint(&fmt, "%d", sp[1]); break; case DUP: fmtprint(&fmt, "%08ux %08ux", sp[1], sp[2]); break; case ALARM: fmtprint(&fmt, "%08ux ", sp[1]); break; case EXEC: fmtuserstring(&fmt, sp[1], ""); argp = sp[2]; for(;;argp += BY2WD) { a = *(uint32*)uvalidaddr(argp, BY2WD, 0); if(a == 0) break; fmtprint(&fmt, " "); fmtuserstring(&fmt, a, ""); } break; case EXITS: fmtuserstring(&fmt, sp[1], ""); break; case _FSESSION: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case FAUTH: fmtprint(&fmt, "%08ux", sp[1]); fmtuserstring(&fmt, sp[2], ""); break; case _FSTAT: fmtprint(&fmt, "%08ux %#ux %08ux", sp[1], sp[2], sp[3]); break; case SEGBRK: fmtprint(&fmt, "%#ux %#ux", sp[1], sp[2]); break; case _MOUNT: fmtprint(&fmt, "%d %d ", sp[1], sp[2]); fmtuserstring(&fmt, sp[3], " "); fmtprint(&fmt, "%08ux ", sp[4]); fmtuserstring(&fmt, sp[5], ""); break; case OPEN: fmtuserstring(&fmt, sp[1], " "); fmtprint(&fmt, "%08ux", sp[2]); break; case OSEEK: fmtprint(&fmt, "%08ux %08ux", sp[1], sp[2]); break; case SLEEP: fmtprint(&fmt, "%d", sp[1]); break; case _STAT: fmtuserstring(&fmt, sp[1], " "); fmtprint(&fmt, "%#ux %d", sp[2], sp[3]); break; case RFORK: fmtprint(&fmt, "%08ux", sp[1] ); break; case PIPE: break; case CREATE: fmtuserstring(&fmt, sp[1], " "); fmtprint(&fmt, "%08ux %08ux", sp[2], sp[3]); break; case FD2PATH: fmtprint(&fmt, "%d ", sp[1]); break; case BRK_: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case REMOVE: fmtuserstring(&fmt, sp[1], " "); break; /* deprecated */ case _WSTAT: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case _FWSTAT: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case NOTIFY: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case NOTED: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case SEGATTACH: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case SEGDETACH: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case SEGFREE: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case SEGFLUSH: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case RENDEZVOUS: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case UNMOUNT: fmtuserstring(&fmt, sp[1], " "); break; case _WAIT: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case SEMACQUIRE: fmtprint(&fmt, "%08ux %#ux %d", sp[1], sp[2], sp[3]); break; case SEMRELEASE: fmtprint(&fmt, "%08ux %#ux %d", sp[1], sp[2], sp[3]); break; case SEEK: fmtprint(&fmt, "%08ux %016ux %08ux", sp[1], *(vlong *)&sp[2], sp[4]); break; case FVERSION: fmtprint(&fmt, "%08ux %08ux ", sp[1], sp[2]); fmtuserstring(&fmt, sp[5], ""); break; case ERRSTR: fmtprint(&fmt, "%#ux/", sp[1]); break; case WSTAT: case STAT: fmtprint(&fmt, "%08ux ", sp[1]); fmtuserstring(&fmt, sp[2], " "); fmtprint(&fmt, "%08ux", sp[3]); break; case FSTAT: case FWSTAT: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case MOUNT: fmtprint(&fmt, "%d %d ", sp[1], sp[3]); fmtuserstring(&fmt, sp[3], " "); fmtprint(&fmt, "%08ux", sp[4]); fmtuserstring(&fmt, sp[5], ""); break; case AWAIT: break; case _READ: case PREAD: fmtprint(&fmt, "%d ", sp[1]); break; case _WRITE: offset = -1; case PWRITE: fmtprint(&fmt, "%d ", sp[1]); if (sp[3] < 64) len = sp[3]; else len = 64; fmtrwdata(&fmt, sp[2], len, " "); if(! offset) offset = *(vlong *)&sp[4]; fmtprint(&fmt, "%d %#llx", sp[3], offset); break; } up->syscalltrace = fmtstrflush(&fmt);} static voidretprint(Ureg *ureg, int syscallno, uvlong start, uvlong stop){ int errstrlen, len; vlong offset; char *errstr; Fmt fmt; fmtstrinit(&fmt); len = 0; errstrlen = 0; offset = 0; if (ureg->ax != -1) errstr = ""; else errstr = up->syserrstr; if(up->syscalltrace) free(up->syscalltrace); switch(syscallno) { case SYSR1: case BIND: case CHDIR: case CLOSE: case DUP: case ALARM: case EXEC: case EXITS: case _FSESSION: case FAUTH: case _FSTAT: case SEGBRK: case _MOUNT: case OPEN: case OSEEK: case SLEEP: case _STAT: case _WRITE: case PIPE: case CREATE: case BRK_: case REMOVE: case _WSTAT: case _FWSTAT: case NOTIFY: case NOTED: case SEGATTACH: case SEGDETACH: case SEGFREE: case SEGFLUSH: case RENDEZVOUS: case UNMOUNT: case _WAIT: case SEMACQUIRE: case SEMRELEASE: case SEEK: case FVERSION: case STAT: case FSTAT: case WSTAT: case FWSTAT: case MOUNT: case PWRITE: case RFORK: default: break; case AWAIT: if(ureg->ax > 0){ fmtuserstring(&fmt, up->s.args[0], " "); fmtprint(&fmt, "%d", up->s.args[1]); } else { fmtprint(&fmt, "%#ux/\"\" %d", up->s.args[0], up->s.args[1]); } break;Lines 1–500 of 1107. Load more
/* * Heavily modified copy of /sys/src/9/pc/trap.c * A shell of its former self. */ #define WANT_M #include "u.h" #include "libvx32/vx32.h" #include "tos.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "ureg.h" #include "error.h" #include "trace.h" #include "systab.h" int tracesyscalls; static void noted(Ureg*, ulong); static void mathemu(Ureg*, void*); static void syscall(Ureg*); /* going to user space */ void kexit(Ureg *ureg) { uvlong t; Tos *tos; /* precise time accounting, kernel exit */ tos = (Tos*)(up->pmmu.uzero+USTKTOP-sizeof(Tos)); cycles(&t); tos->kcycles += t - up->kentry; tos->pcycles = up->pcycles; tos->pid = up->pid; } static char* excname[32] = { "divide error", "debug exception", "nonmaskable interrupt", "breakpoint", "overflow", "bounds check", "invalid opcode", "coprocessor not available", "double fault", "coprocessor segment overrun", "invalid TSS", "segment not present", "stack exception", "general protection violation", "page fault", "15 (reserved)", "coprocessor error", "alignment check", "machine check", "19 (reserved)", "20 (reserved)", "21 (reserved)", "22 (reserved)", "23 (reserved)", "24 (reserved)", "25 (reserved)", "26 (reserved)", "27 (reserved)", "28 (reserved)", "29 (reserved)", "30 (reserved)", "31 (reserved)", }; /* * Handle a trap. */ void trap(Ureg *ureg) { char buf[ERRMAX]; int vno; vno = ureg->trap; switch(vno){ case VXTRAP_FPOFF: mathemu(ureg, nil); return; case VXTRAP_SOFT+0x40: /* int $0x40 - system call */ if(tracesyscalls){ uint32 *sp = (uint32*)(up->pmmu.uzero + ureg->usp); iprint("%d [%s] %s %#ux %08ux %08ux %08ux %08ux\n", up->pid, up->text, sysctab[ureg->ax], sp[0], sp[1], sp[2], sp[3]); } syscall(ureg); if(tracesyscalls){ if(ureg->ax == -1) iprint("%d [%s] -> %s\n", up->pid, up->text, up->syserrstr); else iprint("%d [%s] -> %#ux\n", up->pid, up->text, ureg->ax); } return; case VXTRAP_IRQ+VXIRQ_TIMER: sched(); break; case 3: // breakpoint /* restore pc to instruction that caused the trap */ ureg->pc--; sprint(buf, "sys: breakpoint"); postnote(up, 1, buf, NDebug); break; default: if(vno < nelem(excname)){ spllo(); sprint(buf, "sys: trap: %s", excname[vno]); postnote(up, 1, buf, NDebug); }else{ dumpregs(ureg); if(vno < nelem(excname)) panic("%s", excname[vno]); panic("unknown trap/intr: %#x", vno); } break; } if(up->procctl || up->nnote) notify(ureg); spllo(); /* no actual effect, just silences prints */ kexit(ureg); } void dumpregs2(Ureg* ureg) { if(up) print("cpu%d: registers for %s %lud\n", m->machno, up->text, up->pid); else print("cpu%d: registers for kernel\n", m->machno); print("FLAGS=%luX TRAP=%luX ECODE=%luX PC=%luX", ureg->flags, ureg->trap, ureg->ecode, ureg->pc); print(" USP=%luX\n", ureg->usp); print(" AX %8.8luX BX %8.8luX CX %8.8luX DX %8.8luX\n", ureg->ax, ureg->bx, ureg->cx, ureg->dx); print(" SI %8.8luX DI %8.8luX BP %8.8luX\n", ureg->si, ureg->di, ureg->bp); } void dumpregs(Ureg* ureg) { dumpregs2(ureg); /* * Processor control registers. * If machine check exception, time stamp counter, page size extensions * or enhanced virtual 8086 mode extensions are supported, there is a * CR4. If there is a CR4 and machine check extensions, read the machine * check address and machine check type registers if RDMSR supported. print(" CR0 %8.8lux CR2 %8.8lux CR3 %8.8lux", getcr0(), getcr2(), getcr3()); if(m->cpuiddx & 0x9A){ vlong mca, mct; iprint(" CR4 %8.8lux", getcr4()); if((m->cpuiddx & 0xA0) == 0xA0){ rdmsr(0x00, &mca); rdmsr(0x01, &mct); iprint("\n MCA %8.8llux MCT %8.8llux", mca, mct); } } print("\n ur %lux up %lux\n", ureg, up); */ } static void fmtrwdata(Fmt *f, ulong s, int n, char *suffix) { char *t, *src; int i; if (! s) { fmtprint(f, "0x0", suffix); return; } src = uvalidaddr(s, 1, 0); t = smalloc(n+1); for(i = 0; i < n; i++) if (isgraph(src[i])) t[i] = src[i]; else t[i] = '.'; fmtprint(f, "%08ux/\"%s\"%s", s, t, suffix); free(t); } static void fmtuserstring(Fmt *f, ulong s, char *suffix) { char *es, *t, *src; int n; if (! s){ fmtprint(f, "0/\"\"%s", suffix); return; } src = uvalidaddr(s, 1, 0); es = vmemchr(src, 0, 1<<16); n = es - src; t = smalloc(n+1); memmove(t, src, n); t[n] = 0; fmtprint(f, "%08ux/\"%s\"%s", s, t, suffix); free(t); } static void syscallprint(Ureg *ureg) { uint32 *sp; int syscallno; vlong offset; Fmt fmt; int len; uint32 argp, a; sp = (uint32*)(up->pmmu.uzero + ureg->usp); syscallno = ureg->ax; offset = 0; fmtstrinit(&fmt); fmtprint(&fmt, "%d %s ", up->pid, up->text); /* accomodate process-private system calls */ if(syscallno > nelem(sysctab)) fmtprint(&fmt, " %d %#x ", syscallno, sp[0]); else fmtprint(&fmt, "%s %#ux ", sysctab[syscallno], sp[0]); if(up->syscalltrace) free(up->syscalltrace); switch(syscallno) { case SYSR1: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case _ERRSTR: fmtuserstring(&fmt, sp[1], ""); break; case BIND: fmtuserstring(&fmt, sp[1], " "); fmtuserstring(&fmt, sp[2], " "); fmtprint(&fmt, "%#ux", sp[3]); break; case CHDIR: fmtuserstring(&fmt, sp[1], ""); break; case CLOSE: fmtprint(&fmt, "%d", sp[1]); break; case DUP: fmtprint(&fmt, "%08ux %08ux", sp[1], sp[2]); break; case ALARM: fmtprint(&fmt, "%08ux ", sp[1]); break; case EXEC: fmtuserstring(&fmt, sp[1], ""); argp = sp[2]; for(;;argp += BY2WD) { a = *(uint32*)uvalidaddr(argp, BY2WD, 0); if(a == 0) break; fmtprint(&fmt, " "); fmtuserstring(&fmt, a, ""); } break; case EXITS: fmtuserstring(&fmt, sp[1], ""); break; case _FSESSION: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case FAUTH: fmtprint(&fmt, "%08ux", sp[1]); fmtuserstring(&fmt, sp[2], ""); break; case _FSTAT: fmtprint(&fmt, "%08ux %#ux %08ux", sp[1], sp[2], sp[3]); break; case SEGBRK: fmtprint(&fmt, "%#ux %#ux", sp[1], sp[2]); break; case _MOUNT: fmtprint(&fmt, "%d %d ", sp[1], sp[2]); fmtuserstring(&fmt, sp[3], " "); fmtprint(&fmt, "%08ux ", sp[4]); fmtuserstring(&fmt, sp[5], ""); break; case OPEN: fmtuserstring(&fmt, sp[1], " "); fmtprint(&fmt, "%08ux", sp[2]); break; case OSEEK: fmtprint(&fmt, "%08ux %08ux", sp[1], sp[2]); break; case SLEEP: fmtprint(&fmt, "%d", sp[1]); break; case _STAT: fmtuserstring(&fmt, sp[1], " "); fmtprint(&fmt, "%#ux %d", sp[2], sp[3]); break; case RFORK: fmtprint(&fmt, "%08ux", sp[1] ); break; case PIPE: break; case CREATE: fmtuserstring(&fmt, sp[1], " "); fmtprint(&fmt, "%08ux %08ux", sp[2], sp[3]); break; case FD2PATH: fmtprint(&fmt, "%d ", sp[1]); break; case BRK_: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case REMOVE: fmtuserstring(&fmt, sp[1], " "); break; /* deprecated */ case _WSTAT: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case _FWSTAT: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case NOTIFY: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case NOTED: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case SEGATTACH: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case SEGDETACH: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case SEGFREE: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case SEGFLUSH: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case RENDEZVOUS: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case UNMOUNT: fmtuserstring(&fmt, sp[1], " "); break; case _WAIT: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case SEMACQUIRE: fmtprint(&fmt, "%08ux %#ux %d", sp[1], sp[2], sp[3]); break; case SEMRELEASE: fmtprint(&fmt, "%08ux %#ux %d", sp[1], sp[2], sp[3]); break; case SEEK: fmtprint(&fmt, "%08ux %016ux %08ux", sp[1], *(vlong *)&sp[2], sp[4]); break; case FVERSION: fmtprint(&fmt, "%08ux %08ux ", sp[1], sp[2]); fmtuserstring(&fmt, sp[5], ""); break; case ERRSTR: fmtprint(&fmt, "%#ux/", sp[1]); break; case WSTAT: case STAT: fmtprint(&fmt, "%08ux ", sp[1]); fmtuserstring(&fmt, sp[2], " "); fmtprint(&fmt, "%08ux", sp[3]); break; case FSTAT: case FWSTAT: fmtprint(&fmt, "%08ux %08ux %08ux", sp[1], sp[2], sp[3]); break; case MOUNT: fmtprint(&fmt, "%d %d ", sp[1], sp[3]); fmtuserstring(&fmt, sp[3], " "); fmtprint(&fmt, "%08ux", sp[4]); fmtuserstring(&fmt, sp[5], ""); break; case AWAIT: break; case _READ: case PREAD: fmtprint(&fmt, "%d ", sp[1]); break; case _WRITE: offset = -1; case PWRITE: fmtprint(&fmt, "%d ", sp[1]); if (sp[3] < 64) len = sp[3]; else len = 64; fmtrwdata(&fmt, sp[2], len, " "); if(! offset) offset = *(vlong *)&sp[4]; fmtprint(&fmt, "%d %#llx", sp[3], offset); break; } up->syscalltrace = fmtstrflush(&fmt); } static void retprint(Ureg *ureg, int syscallno, uvlong start, uvlong stop) { int errstrlen, len; vlong offset; char *errstr; Fmt fmt; fmtstrinit(&fmt); len = 0; errstrlen = 0; offset = 0; if (ureg->ax != -1) errstr = ""; else errstr = up->syserrstr; if(up->syscalltrace) free(up->syscalltrace); switch(syscallno) { case SYSR1: case BIND: case CHDIR: case CLOSE: case DUP: case ALARM: case EXEC: case EXITS: case _FSESSION: case FAUTH: case _FSTAT: case SEGBRK: case _MOUNT: case OPEN: case OSEEK: case SLEEP: case _STAT: case _WRITE: case PIPE: case CREATE: case BRK_: case REMOVE: case _WSTAT: case _FWSTAT: case NOTIFY: case NOTED: case SEGATTACH: case SEGDETACH: case SEGFREE: case SEGFLUSH: case RENDEZVOUS: case UNMOUNT: case _WAIT: case SEMACQUIRE: case SEMRELEASE: case SEEK: case FVERSION: case STAT: case FSTAT: case WSTAT: case FWSTAT: case MOUNT: case PWRITE: case RFORK: default: break; case AWAIT: if(ureg->ax > 0){ fmtuserstring(&fmt, up->s.args[0], " "); fmtprint(&fmt, "%d", up->s.args[1]); } else { fmtprint(&fmt, "%#ux/\"\" %d", up->s.args[0], up->s.args[1]); } break;