|  | // 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, 'X'), ", ", 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:arg)}}, | 
|  | { 2, {"bind",		"ssX",		code(*sysbind:arg)}}, | 
|  | { 3, {"chdir",		"s",		code(*sysbind:arg)}}, | 
|  | { 4, {"close",		"D",		code(*sysclose:arg)}}, | 
|  | { 5, {"dup",		"DD",		code(*sysdup:arg)}}, | 
|  | { 6, {"alarm",		"D",		code(*sysalarm:arg)}}, | 
|  | { 7, {"exec",		"sS",		code(*sysexec:arg)}}, | 
|  | { 8, {"exits",		"s",		code(*sysexits:arg)}}, | 
|  | { 9, {"_fsession",	"DX",		code(*sys_fsession:arg)}}, | 
|  | {10, {"fauth",		"DX",		code(*sysfauth:arg)}}, | 
|  | {11, {"_fstat",		"DX",		code(*sys_fstat:arg)}}, | 
|  | {12, {"segbrk",		"XX",		code(*syssegbrk:arg)}}, | 
|  | {13, {"_mount",		"DsXs",		code(*sys_mount:arg)}}, | 
|  | {14, {"open",		"sD",		code(*sysopen:arg)}}, | 
|  | {15, {"_read",		"DXD",		code(*sys_read:arg)}}, | 
|  | {16, {"oseek",		"DDD",		code(*sysoseek:arg)}}, | 
|  | {17, {"sleep",		"D",		code(*syssleep:arg)}}, | 
|  | {18, {"_stat",		"sX",		code(*sys_stat:arg)}}, | 
|  | {19, {"rfork",		"X",		code(*sysstat:arg)}}, | 
|  | {20, {"_write",		"DXD",		code(*sys_write:arg)}}, | 
|  | {21, {"pipe",		"X",		code(*syspipe:arg)}}, | 
|  | {22, {"create",		"sDO",		code(*syscreate:arg)}}, | 
|  | {23, {"fd2path",	"DXD",		code(*sysfd2path:arg)}}, | 
|  | {24, {"brk_",		"X",		code(*sysbrk_:arg)}}, | 
|  | {25, {"remove",		"s",		code(*sysremove:arg)}}, | 
|  | {26, {"_wstat",		"sX",		code(*sys_wstat:arg)}}, | 
|  | {27, {"_fwstat",		"DX",		code(*sys_fwstat:arg)}}, | 
|  | {28, {"notify",		"X",		code(*sysnotify:arg)}}, | 
|  | {29, {"noted",		"D",		code(*sysnoted:arg)}}, | 
|  | {30, {"segattach",	"DsXD",		code(*syssegattach:arg)}}, | 
|  | {31, {"segdetach",	"X",		code(*syssegdetach:arg)}}, | 
|  | {32, {"segfree",	"XD",		code(*syssegfree:arg)}}, | 
|  | {33, {"segflush",	"XD",		code(*syssegflush:arg)}}, | 
|  | {34, {"rendezvous",	"XX",		code(*sysrendezvous:arg)}}, | 
|  | {35, {"unmount",	"ss",		code(*sysunmount:arg)}}, | 
|  | {36, {"_wait",		"X",		code(*sys_wait:arg)}}, | 
|  | {39, {"seek",		"XDVD",		code(*sysseek:arg)}}, | 
|  | {40, {"fversion",	"DDsD",		code(*sysfversion:arg)}}, | 
|  | {41, {"errstr",		"TD",		code(*syserrstr:arg)}}, | 
|  | {42, {"stat",		"sXD",		code(*sysstat:arg)}}, | 
|  | {43, {"fstat",		"DXD",		code(*sysfstat:arg)}}, | 
|  | {44, {"wstat",		"sXD",		code(*syswstat:arg)}}, | 
|  | {45, {"fwstat",		"DXD",		code(*sysfwstat:arg)}}, | 
|  | {46, {"mount",		"DDsXs",		code(*sysmount:arg)}}, | 
|  | {47, {"await",		"TD",		code(*sysawait:arg)}}, | 
|  | {50, {"pread",		"DXDZ",		code(*syspread:arg)}}, | 
|  | {51, {"pwrite",		"DTDZ",		code(*syspwrite:arg)}}, | 
|  | }; | 
|  |  | 
|  | 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 == "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 == "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 == "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]); | 
|  | } | 
|  | } | 
|  | } |