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
159 defn addressof(pattern) {
160 // translate to ape system calls if we have an ape binary
161 if _addressof("_EXITS") != 0 then
162 pattern = trussapecalls[match(pattern, trusscalls)];
163 if regexp("(seek|_SEEK)", pattern) && (objtype=="amd64" || objtype == "power64") then
164 pattern = "_" + pattern;
165 return _addressof(pattern);
169 local lst, offset, name, addr;
172 offset = trapoffset();
178 addr = addressof(name);
182 trussbpt = append trussbpt, (addr+offset);
183 // sometimes _exits is renamed $_exits
184 if(regexp("exits|exec", name)) then stopPC = append stopPC, (addr+offset);
185 if(regexp("read", name)) then readPC = append readPC, (addr+offset);
186 if(regexp("fd2path", name)) then fd2pathPC = append fd2pathPC, (addr+offset);
187 if(regexp("^\\$*await", name)) then awaitPC = append awaitPC, (addr+offset);
188 if(regexp("^\\$*errstr", name)) then errstrPC = append errstrPC, (addr+offset);
189 // compatibility hacks for old kernel
190 if(regexp("_wait", name)) then _waitPC = append _waitPC, (addr+offset);
191 if(regexp("_errstr", name)) then _errstrPC = append _errstrPC, (addr+offset);
197 stop(pid); // already stopped, but flushes output
203 bpset(follow(main)[0]);
206 // clear the hang bit, which is left set by newproc, so programs we fork/exec don't hang
207 printto("/proc/"+itoa(pid)+"/ctl", "nohang");
211 local pc, lst, offset, prevpc, pcspret, arg, ret;
213 offset = trapoffset();
218 pcspret = UPCSPRET();
220 while !_stoprunning do {
222 if notes[0]!="sys: breakpoint" then {
227 if match(*PC, stopPC)>=0 then {
228 print(pid,": ",trapreason(),"\t");
229 print(fmt(pc,'a'),"\t",fmt(pc,'i'),"\n");
233 if match(*PC, trussbpt)>=0 then {
238 arg = eval pcspret[1];
239 ret = eval pcspret[2];
240 print("\treturn value: ", ret\D, "\n");
241 if (ret>=0) && (match(prevpc, readPC)>=0) then {
243 printtextordata(arg[1], ret);
246 if (ret>=0) && (match(prevpc, fd2pathPC)>=0) then {
247 print("\tdata: \"", *(arg[1]\s), "\"\n");
249 if (ret>=0) && (match(prevpc, errstrPC)>=0) then {
250 print("\tdata: \"", *(arg[0]\s), "\"\n");
252 if (ret>=0) && (match(prevpc, awaitPC)>=0) then {
254 printtextordata(arg[0], ret);
257 // compatibility hacks for old kernel:
258 if (ret>=0) && (match(prevpc, _waitPC)>=0) then {
260 printtextordata(arg[0], 12+3*12+64);
263 if (ret>=0) && (match(prevpc, _errstrPC)>=0) then {
265 printtextordata(arg[0], 64);
274 local lst, offset, addr;
277 offset = trapoffset();
286 **PC = @*PC; // repair current instruction
294 print("/sys/lib/acid/truss");