1 // poor emulation of SVR5 truss command - traces system calls
3 include("/sys/lib/acid/syscall");
12 if (notes[0]!="sys: breakpoint") then
14 print(pid,": ",trapreason(),"\t");
15 print(fmt(pc,97),"\t",fmt(pc,105),"\n");
16 print("Notes pending:\n");
20 print("\t",head l,"\n");
28 defn _addressof(pattern) {
31 pattern = "^\\$*"+pattern+"$";
35 if regexp(pattern, s[0]) && ((s[1] == 'T') || (s[1] == 'L')) then
151 defn addressof(pattern) {
152 // translate to ape system calls if we have an ape binary
153 if _addressof("_EXITS") == 0 then
154 return _addressof(pattern);
155 return _addressof(trussapecalls[match(pattern, trusscalls)]);
159 local lst, offset, name, addr;
162 offset = trapoffset();
168 addr = addressof(name);
172 trussbpt = append trussbpt, (addr+offset);
173 // sometimes _exits is renamed $_exits
174 if(regexp("exits|exec", name)) then stopPC = append stopPC, (addr+offset);
175 if(regexp("read", name)) then readPC = append readPC, (addr+offset);
176 if(regexp("fd2path", name)) then fd2pathPC = append fd2pathPC, (addr+offset);
177 if(regexp("^\\$*await", name)) then awaitPC = append awaitPC, (addr+offset);
178 if(regexp("^\\$*errstr", name)) then errstrPC = append errstrPC, (addr+offset);
179 // compatibility hacks for old kernel
180 if(regexp("_wait", name)) then _waitPC = append _waitPC, (addr+offset);
181 if(regexp("_errstr", name)) then _errstrPC = append _errstrPC, (addr+offset);
187 stop(pid); // already stopped, but flushes output
193 bpset(follow(main)[0]);
196 // clear the hang bit, which is left set by newproc, so programs we fork/exec don't hang
197 printto("/proc/"+itoa(pid)+"/ctl", "nohang");
201 local pc, lst, offset, prevpc, pcspret, ret;
203 offset = trapoffset();
208 pcspret = UPCSPRET();
210 while !_stoprunning do {
212 if notes[0]!="sys: breakpoint" then {
217 if match(*PC, stopPC)>=0 then {
218 print(pid,": ",trapreason(),"\t");
219 print(fmt(pc,'a'),"\t",fmt(pc,'i'),"\n");
223 if match(*PC, trussbpt)>=0 then {
228 ret = eval pcspret[2];
229 print("\treturn value: ", ret\D, "\n");
230 if (ret>=0) && (match(prevpc, readPC)>=0) then {
232 printtextordata(*((eval pcspret[1])+4), ret);
235 if (ret>=0) && (match(prevpc, fd2pathPC)>=0) then {
236 print("\tdata: \"", *(*((eval pcspret[1])+4)\s), "\"\n");
238 if (ret>=0) && (match(prevpc, errstrPC)>=0) then {
239 print("\tdata: \"", *(*(eval pcspret[1])\s), "\"\n");
241 if (ret>=0) && (match(prevpc, awaitPC)>=0) then {
243 printtextordata(*(eval pcspret[1]), ret);
246 // compatibility hacks for old kernel:
247 if (ret>=0) && (match(prevpc, _waitPC)>=0) then {
249 printtextordata(*(eval pcspret[1]), 12+3*12+64);
252 if (ret>=0) && (match(prevpc, _errstrPC)>=0) then {
254 printtextordata(*(eval pcspret[1]), 64);
263 local lst, offset, addr;
266 offset = trapoffset();
275 **PC = @*PC; // repair current instruction
283 print("/sys/lib/acid/truss");