// print system calls defn printstring(s) { print("\"", s, "\""); } defn printtextordata(addr, n) { local a, i; a = addr\c; i = 0; loop 1, n do { if (a[i]>=127) then { print(fmt(addr, 'A'), ", ", n\D); return {}; } i = i+1; } print("\""); printstringn(addr, n); print("\""); } defn printstringn(s, n) { local m; m = n; if (m > 100) then m = 100; loop 1,m do { print(*(s\c)); s=s+1; } if(m != n) then print("..."); } defn printsyscall(name, fmt, arg) { local f, i, a, argp, sl; print(name, "("); i = 0; a = eval arg; while fmt[i] != 0 do { if fmt[i] == 's' then { if *a == 0 then print("nil"); else printstring(*(*a\s)); } else if fmt[i] == 'S' then { argp = *a; argl = {}; while *argp != 0 do { argl = append argl, *(*argp\s); argp++; } print(argl); } else if (fmt[i] == 'Z') && (~*a == 0) then { print("-1"); a++; // advance extra word for quadword } else if (fmt[i] == 'Y') || (fmt[i] == 'V') then { print(fmt(*a, fmt[i])); a++; // advance extra word for quadword } else if (fmt[i] == 'T') then { if *a == 0 then print("nil"); else printtextordata(*a, a[1]); } else print(fmt(*a, fmt[i])); if fmt[i+1] != 0 then print(", "); i = i+1; a++; } print(")\n"); } defn code(*e) { return e; } syscalls = { { 0, {"sysr1", "s", code(0)}}, { 1, {"_errstr", "s", code(*sys_errstr:list)}}, { 2, {"bind", "ssX", code(*sysbind:list)}}, { 3, {"chdir", "s", code(*sysbind:list)}}, { 4, {"close", "D", code(*sysclose:list)}}, { 5, {"dup", "DD", code(*sysdup:list)}}, { 6, {"alarm", "D", code(*sysalarm:list)}}, { 7, {"exec", "sS", code(*sysexec:list)}}, { 8, {"exits", "s", code(*sysexits:list)}}, { 9, {"_fsession", "DsD", code(*sys_fsession:list)}}, {10, {"fauth", "Ds", code(*sysfauth:list)}}, {11, {"_fstat", "DA", code(*sys_fstat:list)}}, {12, {"segbrk", "AA", code(*syssegbrk:list)}}, {13, {"_mount", "DsXs", code(*sys_mount:list)}}, {14, {"open", "sD", code(*sysopen:list)}}, {15, {"_read", "DAD", code(*sys_read:list)}}, {16, {"oseek", "DDD", code(*sysoseek:list)}}, {17, {"sleep", "D", code(*syssleep:list)}}, {18, {"_stat", "sA", code(*sys_stat:list)}}, {19, {"rfork", "X", code(*sysstat:list)}}, {20, {"_write", "DTD", code(*sys_write:list)}}, {21, {"pipe", "A", code(*syspipe:list)}}, {22, {"create", "sDO", code(*syscreate:list)}}, {23, {"fd2path", "DAD", code(*sysfd2path:list)}}, {24, {"brk_", "A", code(*sysbrk_:list)}}, {25, {"remove", "s", code(*sysremove:list)}}, {26, {"_wstat", "sA", code(*sys_wstat:list)}}, {27, {"_fwstat", "DA", code(*sys_fwstat:list)}}, {28, {"notify", "A", code(*sysnotify:list)}}, {29, {"noted", "D", code(*sysnoted:list)}}, {30, {"segattach", "DsAD", code(*syssegattach:list)}}, {31, {"segdetach", "A", code(*syssegdetach:list)}}, {32, {"segfree", "AD", code(*syssegfree:list)}}, {33, {"segflush", "AD", code(*syssegflush:list)}}, {34, {"rendezvous", "AA", code(*sysrendezvous:list)}}, {35, {"unmount", "ss", code(*sysunmount:list)}}, {36, {"_wait", "A", code(*sys_wait:list)}}, {37, {"semacquire", "AD", code(*syssemacquire:list)}}, {38, {"semrelease", "AD", code(*syssemrelease:list)}}, {39, {"seek", "ADVD", code(*sysseek:list)}}, {40, {"fversion", "DDsD", code(*sysfversion:list)}}, {41, {"errstr", "TD", code(*syserrstr:list)}}, {42, {"stat", "sAD", code(*sysstat:list)}}, {43, {"fstat", "DAD", code(*sysfstat:list)}}, {44, {"wstat", "sAD", code(*syswstat:list)}}, {45, {"fwstat", "DAD", code(*sysfwstat:list)}}, {46, {"mount", "DDsXs", code(*sysmount:list)}}, {47, {"await", "TD", code(*sysawait:list)}}, {50, {"pread", "DADZ", code(*syspread:list)}}, {51, {"pwrite", "DTDZ", code(*syspwrite:list)}}, {52, {"tsemacquire", "AD", code(*systsemacquire:list)}}, {53, {"_nsec", "A", code(*sys_nsec:list)}}, }; defn syscall() { local n, sl, h, p; map({"*data", 0, 0xffffffff, 0}); n = *syscall:scallnr; sl = syscalls; while sl != {} do { h = head sl; sl = tail sl; if n == h[0] then { p = h[1]; printsyscall(p[0], p[1], p[2]); } } } defn UPCSPRET() { // return sys call number, address of first argument, location of syscall return value if objtype == "386" then return { code(*(*PC-4)), code(*SP+4), code(*AX) }; if objtype == "amd64" then return { code(*BP), code(*SP+8), code(*AX) }; if (objtype == "mips") || (objtype == "mips2") then return { code(*(*PC-4) & 0xffff), code(*SP+4), code(*R1) }; if objtype == "arm" then return { code(*(*PC-4) & 0xffff), code(*SP+4), code(*R0) }; // untested if objtype == "alpha" then return { code(*(*PC-4) & 0xffff), code(*SP+4), code(*R0) }; // untested } defn trapoffset() { // return offset from entry point to trap instr if objtype == "386" then return 5; if objtype == "amd64" then return 12; if objtype == "mips" then return 8; if objtype == "mips2" then return 8; if objtype == "arm" then return 8; // untested if objtype == "alpha" then return 8; // untested } defn trapreason() { // return reason for trap if objtype == "386" then return reason(*TRAP); if objtype == "amd64" then return reason(*TYPE); if objtype == "mips" then return reason(*CAUSE); if objtype == "mips2" then return reason(*CAUSE); if objtype == "arm" then return "unknown trap"; // untested if objtype == "alpha" then return reason(cause); // untested } defn usyscall() { // gives args for system call in user level; not useful with -k local n, sl, h, p; // stopped at TRAP instruction in system call library pcsp = UPCSPRET(); n = eval pcsp[0]; sl = syscalls; while sl != {} do { h = head sl; sl = tail sl; if n == h[0] then { p = h[1]; printsyscall(p[0], p[1], pcsp[1]); } } }