19a747e4fSDavid du Colombier// poor emulation of SVR5 truss command - traces system calls 29a747e4fSDavid du Colombier 39a747e4fSDavid du Colombierinclude("/sys/lib/acid/syscall"); 49a747e4fSDavid du Colombier 59a747e4fSDavid du Colombier_stoprunning = 0; 69a747e4fSDavid du Colombier 79a747e4fSDavid du Colombierdefn stopped(pid) { 89a747e4fSDavid du Colombier local l; 99a747e4fSDavid du Colombier local pc; 109a747e4fSDavid du Colombier pc = *PC; 119a747e4fSDavid du Colombier if notes then { 129a747e4fSDavid du Colombier if (notes[0]!="sys: breakpoint") then 139a747e4fSDavid du Colombier { 149a747e4fSDavid du Colombier print(pid,": ",trapreason(),"\t"); 159a747e4fSDavid du Colombier print(fmt(pc,97),"\t",fmt(pc,105),"\n"); 169a747e4fSDavid du Colombier print("Notes pending:\n"); 179a747e4fSDavid du Colombier l = notes; 189a747e4fSDavid du Colombier while l do 199a747e4fSDavid du Colombier { 209a747e4fSDavid du Colombier print("\t",head l,"\n"); 219a747e4fSDavid du Colombier l = tail l; 229a747e4fSDavid du Colombier } 239a747e4fSDavid du Colombier _stoprunning = 1; 249a747e4fSDavid du Colombier } 259a747e4fSDavid du Colombier } 269a747e4fSDavid du Colombier} 279a747e4fSDavid du Colombier 289a747e4fSDavid du Colombierdefn _addressof(pattern) { 299a747e4fSDavid du Colombier local s, l; 309a747e4fSDavid du Colombier l = symbols; 319a747e4fSDavid du Colombier pattern = "^\\$*"+pattern+"$"; 329a747e4fSDavid du Colombier while l do 339a747e4fSDavid du Colombier { 349a747e4fSDavid du Colombier s = head l; 359a747e4fSDavid du Colombier if regexp(pattern, s[0]) && ((s[1] == 'T') || (s[1] == 'L')) then 369a747e4fSDavid du Colombier return s[2]; 379a747e4fSDavid du Colombier l = tail l; 389a747e4fSDavid du Colombier } 399a747e4fSDavid du Colombier return 0; 409a747e4fSDavid du Colombier} 419a747e4fSDavid du Colombier 429a747e4fSDavid du ColombierstopPC = {}; 439a747e4fSDavid du ColombierreadPC = {}; 449a747e4fSDavid du Colombierfd2pathPC = {}; 459a747e4fSDavid du ColombiererrstrPC = {}; 469a747e4fSDavid du ColombierawaitPC = {}; 479a747e4fSDavid du Colombier_waitPC = {}; 489a747e4fSDavid du Colombier_errstrPC = {}; 499a747e4fSDavid du Colombiertrusscalls = { 509a747e4fSDavid du Colombier "sysr1", 519a747e4fSDavid du Colombier "_errstr", 529a747e4fSDavid du Colombier "bind", 539a747e4fSDavid du Colombier "chdir", 549a747e4fSDavid du Colombier "close", 559a747e4fSDavid du Colombier "dup", 569a747e4fSDavid du Colombier "alarm", 579a747e4fSDavid du Colombier "exec", 589a747e4fSDavid du Colombier "_exits", 599a747e4fSDavid du Colombier "_fsession", 609a747e4fSDavid du Colombier "fauth", 619a747e4fSDavid du Colombier "_fstat", 629a747e4fSDavid du Colombier "segbrk", 639a747e4fSDavid du Colombier "_mount", 649a747e4fSDavid du Colombier "open", 659a747e4fSDavid du Colombier "_read", 669a747e4fSDavid du Colombier "oseek", 679a747e4fSDavid du Colombier "sleep", 689a747e4fSDavid du Colombier "_stat", 699a747e4fSDavid du Colombier "rfork", 709a747e4fSDavid du Colombier "_write", 719a747e4fSDavid du Colombier "pipe", 729a747e4fSDavid du Colombier "create", 739a747e4fSDavid du Colombier "fd2path", 749a747e4fSDavid du Colombier "brk_", 759a747e4fSDavid du Colombier "remove", 769a747e4fSDavid du Colombier "_wstat", 779a747e4fSDavid du Colombier "_fwstat", 789a747e4fSDavid du Colombier "notify", 799a747e4fSDavid du Colombier "noted", 809a747e4fSDavid du Colombier "segattach", 819a747e4fSDavid du Colombier "segdetach", 829a747e4fSDavid du Colombier "segfree", 839a747e4fSDavid du Colombier "segflush", 849a747e4fSDavid du Colombier "rendezvous", 859a747e4fSDavid du Colombier "unmount", 869a747e4fSDavid du Colombier "_wait", 879a747e4fSDavid du Colombier "seek", 88d9306527SDavid du Colombier "fversion", 89d9306527SDavid du Colombier "errstr", 909a747e4fSDavid du Colombier "stat", 91d9306527SDavid du Colombier "fstat", 92d9306527SDavid du Colombier "wstat", 93d9306527SDavid du Colombier "fwstat", 94d9306527SDavid du Colombier "mount", 95d9306527SDavid du Colombier "await", 969a747e4fSDavid du Colombier "pread", 979a747e4fSDavid du Colombier "pwrite", 989a747e4fSDavid du Colombier }; 999a747e4fSDavid du Colombier 1009a747e4fSDavid du Colombiertrussapecalls = { 1019a747e4fSDavid du Colombier "_SYSR1", 1029a747e4fSDavid du Colombier "__ERRSTR", 1039a747e4fSDavid du Colombier "_BIND", 1049a747e4fSDavid du Colombier "_CHDIR", 1059a747e4fSDavid du Colombier "_CLOSE", 1069a747e4fSDavid du Colombier "_DUP", 1079a747e4fSDavid du Colombier "_ALARM", 1089a747e4fSDavid du Colombier "_EXEC", 1099a747e4fSDavid du Colombier "_EXITS", 1109a747e4fSDavid du Colombier "__FSESSION", 1119a747e4fSDavid du Colombier "_FAUTH", 1129a747e4fSDavid du Colombier "__FSTAT", 1139a747e4fSDavid du Colombier "_SEGBRK", 1149a747e4fSDavid du Colombier "__MOUNT", 1159a747e4fSDavid du Colombier "_OPEN", 1169a747e4fSDavid du Colombier "__READ", 1179a747e4fSDavid du Colombier "_OSEEK", 1189a747e4fSDavid du Colombier "_SLEEP", 1199a747e4fSDavid du Colombier "__STAT", 1209a747e4fSDavid du Colombier "_RFORK", 1219a747e4fSDavid du Colombier "__WRITE", 1229a747e4fSDavid du Colombier "_PIPE", 1239a747e4fSDavid du Colombier "_CREATE", 1249a747e4fSDavid du Colombier "_FD2PATH", 1259a747e4fSDavid du Colombier "_BRK_", 1269a747e4fSDavid du Colombier "_REMOVE", 1279a747e4fSDavid du Colombier "__WSTAT", 1289a747e4fSDavid du Colombier "__FWSTAT", 1299a747e4fSDavid du Colombier "_NOTIFY", 1309a747e4fSDavid du Colombier "_NOTED", 1319a747e4fSDavid du Colombier "_SEGATTACH", 1329a747e4fSDavid du Colombier "_SEGDETACH", 1339a747e4fSDavid du Colombier "_SEGFREE", 1349a747e4fSDavid du Colombier "_SEGFLUSH", 1359a747e4fSDavid du Colombier "_RENDEZVOUS", 1369a747e4fSDavid du Colombier "_UNMOUNT", 1379a747e4fSDavid du Colombier "__WAIT", 1389a747e4fSDavid du Colombier "_SEEK", 1399a747e4fSDavid du Colombier "__NFVERSION", 1409a747e4fSDavid du Colombier "__NERRSTR", 1419a747e4fSDavid du Colombier "_STAT", 1429a747e4fSDavid du Colombier "__NFSTAT", 1439a747e4fSDavid du Colombier "__NWSTAT", 1449a747e4fSDavid du Colombier "__NFWSTAT", 1459a747e4fSDavid du Colombier "__NMOUNT", 1469a747e4fSDavid du Colombier "__NAWAIT", 1479a747e4fSDavid du Colombier "_PREAD", 1489a747e4fSDavid du Colombier "_PWRITE", 1499a747e4fSDavid du Colombier }; 1509a747e4fSDavid du Colombier 1519a747e4fSDavid du Colombierdefn addressof(pattern) { 1529a747e4fSDavid du Colombier // translate to ape system calls if we have an ape binary 1539a747e4fSDavid du Colombier if _addressof("_EXITS") == 0 then 1549a747e4fSDavid du Colombier return _addressof(pattern); 1559a747e4fSDavid du Colombier return _addressof(trussapecalls[match(pattern, trusscalls)]); 1569a747e4fSDavid du Colombier} 1579a747e4fSDavid du Colombier 1589a747e4fSDavid du Colombierdefn setuptruss() { 1599a747e4fSDavid du Colombier local lst, offset, name, addr; 1609a747e4fSDavid du Colombier 1619a747e4fSDavid du Colombier trussbpt = {}; 1629a747e4fSDavid du Colombier offset = trapoffset(); 1639a747e4fSDavid du Colombier lst = trusscalls; 1649a747e4fSDavid du Colombier while lst do 1659a747e4fSDavid du Colombier { 1669a747e4fSDavid du Colombier name = head lst; 167*f8bc6aafSDavid du Colombier if objtype == "mips64" && name == "seek" then 168*f8bc6aafSDavid du Colombier name = "_seek"; 1699a747e4fSDavid du Colombier lst = tail lst; 1709a747e4fSDavid du Colombier addr = addressof(name); 1719a747e4fSDavid du Colombier if addr then 1729a747e4fSDavid du Colombier { 1739a747e4fSDavid du Colombier bpset(addr+offset); 1749a747e4fSDavid du Colombier trussbpt = append trussbpt, (addr+offset); 1759a747e4fSDavid du Colombier // sometimes _exits is renamed $_exits 1769a747e4fSDavid du Colombier if(regexp("exits|exec", name)) then stopPC = append stopPC, (addr+offset); 1779a747e4fSDavid du Colombier if(regexp("read", name)) then readPC = append readPC, (addr+offset); 1789a747e4fSDavid du Colombier if(regexp("fd2path", name)) then fd2pathPC = append fd2pathPC, (addr+offset); 1799a747e4fSDavid du Colombier if(regexp("^\\$*await", name)) then awaitPC = append awaitPC, (addr+offset); 1809a747e4fSDavid du Colombier if(regexp("^\\$*errstr", name)) then errstrPC = append errstrPC, (addr+offset); 1819a747e4fSDavid du Colombier // compatibility hacks for old kernel 1829a747e4fSDavid du Colombier if(regexp("_wait", name)) then _waitPC = append _waitPC, (addr+offset); 1839a747e4fSDavid du Colombier if(regexp("_errstr", name)) then _errstrPC = append _errstrPC, (addr+offset); 1849a747e4fSDavid du Colombier } 1859a747e4fSDavid du Colombier } 1869a747e4fSDavid du Colombier} 1879a747e4fSDavid du Colombier 1889a747e4fSDavid du Colombierdefn trussflush() { 1899a747e4fSDavid du Colombier stop(pid); // already stopped, but flushes output 1909a747e4fSDavid du Colombier} 1919a747e4fSDavid du Colombier 1929a747e4fSDavid du Colombierdefn new() { 1939a747e4fSDavid du Colombier bplist = {}; 1949a747e4fSDavid du Colombier newproc(progargs); 1959a747e4fSDavid du Colombier bpset(follow(main)[0]); 1969a747e4fSDavid du Colombier cont(); 1979a747e4fSDavid du Colombier bpdel(*PC); 1989a747e4fSDavid du Colombier // clear the hang bit, which is left set by newproc, so programs we fork/exec don't hang 1999a747e4fSDavid du Colombier printto("/proc/"+itoa(pid)+"/ctl", "nohang"); 2009a747e4fSDavid du Colombier} 2019a747e4fSDavid du Colombier 2029a747e4fSDavid du Colombierdefn truss() { 203*f8bc6aafSDavid du Colombier local pc, lst, offset, prevpc, pcspret, ret, dataoffset; 2049a747e4fSDavid du Colombier 2059a747e4fSDavid du Colombier offset = trapoffset(); 2069a747e4fSDavid du Colombier 2079a747e4fSDavid du Colombier stop(pid); 2089a747e4fSDavid du Colombier _stoprunning = 0; 2099a747e4fSDavid du Colombier setuptruss(); 2109a747e4fSDavid du Colombier pcspret = UPCSPRET(); 2119a747e4fSDavid du Colombier 212*f8bc6aafSDavid du Colombier if objtype == "mips64" then 213*f8bc6aafSDavid du Colombier dataoffset = 8; 214*f8bc6aafSDavid du Colombier else 215*f8bc6aafSDavid du Colombier dataoffset = 4; 216*f8bc6aafSDavid du Colombier 2179a747e4fSDavid du Colombier while !_stoprunning do { 2189a747e4fSDavid du Colombier cont(); 2199a747e4fSDavid du Colombier if notes[0]!="sys: breakpoint" then { 2209a747e4fSDavid du Colombier cleantruss(); 2219a747e4fSDavid du Colombier return {}; 2229a747e4fSDavid du Colombier } 2239a747e4fSDavid du Colombier pc = *PC; 2249a747e4fSDavid du Colombier if match(*PC, stopPC)>=0 then { 2259a747e4fSDavid du Colombier print(pid,": ",trapreason(),"\t"); 2269a747e4fSDavid du Colombier print(fmt(pc,'a'),"\t",fmt(pc,'i'),"\n"); 2279a747e4fSDavid du Colombier cleantruss(); 2289a747e4fSDavid du Colombier return {}; 2299a747e4fSDavid du Colombier } 2309a747e4fSDavid du Colombier if match(*PC, trussbpt)>=0 then { 2319a747e4fSDavid du Colombier usyscall(); 2329a747e4fSDavid du Colombier trussflush(); 2339a747e4fSDavid du Colombier prevpc = *PC; 2349a747e4fSDavid du Colombier step(); 2359a747e4fSDavid du Colombier ret = eval pcspret[2]; 2369a747e4fSDavid du Colombier print("\treturn value: ", ret\D, "\n"); 2379a747e4fSDavid du Colombier if (ret>=0) && (match(prevpc, readPC)>=0) then { 2389a747e4fSDavid du Colombier print("\tdata: "); 239*f8bc6aafSDavid du Colombier printtextordata(*((eval pcspret[1])+dataoffset), ret); 2409a747e4fSDavid du Colombier print("\n"); 2419a747e4fSDavid du Colombier } 2429a747e4fSDavid du Colombier if (ret>=0) && (match(prevpc, fd2pathPC)>=0) then { 243*f8bc6aafSDavid du Colombier print("\tdata: \"", *(*((eval pcspret[1])+dataoffset)\s), "\"\n"); 2449a747e4fSDavid du Colombier } 2459a747e4fSDavid du Colombier if (ret>=0) && (match(prevpc, errstrPC)>=0) then { 2469a747e4fSDavid du Colombier print("\tdata: \"", *(*(eval pcspret[1])\s), "\"\n"); 2479a747e4fSDavid du Colombier } 2489a747e4fSDavid du Colombier if (ret>=0) && (match(prevpc, awaitPC)>=0) then { 2499a747e4fSDavid du Colombier print("\tdata: "); 2509a747e4fSDavid du Colombier printtextordata(*(eval pcspret[1]), ret); 2519a747e4fSDavid du Colombier print("\n"); 2529a747e4fSDavid du Colombier } 2539a747e4fSDavid du Colombier // compatibility hacks for old kernel: 2549a747e4fSDavid du Colombier if (ret>=0) && (match(prevpc, _waitPC)>=0) then { 2559a747e4fSDavid du Colombier print("\tdata: "); 2569a747e4fSDavid du Colombier printtextordata(*(eval pcspret[1]), 12+3*12+64); 2579a747e4fSDavid du Colombier print("\n"); 2589a747e4fSDavid du Colombier } 2599a747e4fSDavid du Colombier if (ret>=0) && (match(prevpc, _errstrPC)>=0) then { 2609a747e4fSDavid du Colombier print("\tdata: "); 2619a747e4fSDavid du Colombier printtextordata(*(eval pcspret[1]), 64); 2629a747e4fSDavid du Colombier print("\n"); 2639a747e4fSDavid du Colombier } 2649a747e4fSDavid du Colombier } 2659a747e4fSDavid du Colombier trussflush(); 2669a747e4fSDavid du Colombier } 2679a747e4fSDavid du Colombier} 2689a747e4fSDavid du Colombier 2699a747e4fSDavid du Colombierdefn cleantruss() { 2709a747e4fSDavid du Colombier local lst, offset, addr; 2719a747e4fSDavid du Colombier 2729a747e4fSDavid du Colombier stop(pid); 2739a747e4fSDavid du Colombier offset = trapoffset(); 2749a747e4fSDavid du Colombier lst = trussbpt; 2759a747e4fSDavid du Colombier while lst do 2769a747e4fSDavid du Colombier { 2779a747e4fSDavid du Colombier addr = head lst; 2789a747e4fSDavid du Colombier lst = tail lst; 2799a747e4fSDavid du Colombier bpdel(addr); 2809a747e4fSDavid du Colombier } 2819a747e4fSDavid du Colombier trussbpt = {}; 2829a747e4fSDavid du Colombier **PC = @*PC; // repair current instruction 2839a747e4fSDavid du Colombier} 2849a747e4fSDavid du Colombier 2859a747e4fSDavid du Colombierdefn untruss() { 2869a747e4fSDavid du Colombier cleantruss(); 2879a747e4fSDavid du Colombier start(pid); 2889a747e4fSDavid du Colombier} 2899a747e4fSDavid du Colombier 2909a747e4fSDavid du Colombierprint("/sys/lib/acid/truss"); 291