1 // portable acid for all architectures
5 print(pcfile(addr), ":", pcline(addr), "\n");
17 print("Note pc:", pc, " sp:", sp, " ", fmt(pc, 'a'), " ");
19 _stk(pc, sp, linkreg(addr), 1);
31 print("Note pc:", pc, " sp:", sp, " ", fmt(pc, 'a'), " ");
33 _stk(pc, sp, linkreg(addr), 1);
40 print(sym[0], "=", itoa(sym[1], "%ux"));
57 print(stkprefix, "\t", sym[0], "=", itoa(sym[1], "%ux"), "\n");
66 if regexp(head s, file) then
73 // print a stack trace
75 // in a run of leading frames in files matched by regexps in stkignore,
76 // only print the last one.
77 defn _stk(pc, sp, link, dolocals)
79 local stk, ign, last, lastpc;
81 stk = strace(pc, sp, link);
90 if !_stkign(pcfile(pc)) then {
98 print(stkprefix, fmt(frame[0], 'a'), "(");
100 print(")+", itoa(pc-frame[0], "%ux"), " ");
110 print(stkprefix, fmt(pc, 'a'), " ");
118 if file[0] == '/' then {
121 srcfiles = append srcfiles, file;
122 srctext = append srctext, src;
130 src = file(head lst+file);
132 srcfiles = append srcfiles, file;
133 srctext = append srctext, src;
145 src = match(file, srcfiles);
153 print("no source for ", file, "\n");
156 line = pcline(addr)-1;
157 print(file, ":", line+1, ":", src[line], "\n");
164 if match(dir, srcpath) >= 0 then {
165 print("already in srcpath\n");
169 srcpath = {dir}+srcpath;
184 print("\t", head l, "\n");
195 if file[0] == '/' && access(file) then {
196 rc("B "+file+":"+itoa(pcline(addr)));
200 name = head lst+file;
201 if access(name) then {
202 rc("B "+name+":"+itoa(pcline(addr)));
207 print("no source for ", file, "\n");
212 local text, cline, line, file, src;
214 src = match(file,srcfiles);
221 return "(no source)";
223 return src[pcline(addr)-1];
228 local src, file, line, cline, text;
231 src = match(file, srcfiles);
239 print("no source for ", file, "\n");
243 cline = pcline(addr)-1;
244 print(file, ":", cline+1, "\n");
251 if line == cline then
255 print(line+1, "\t", text, "\n");
261 defn step() // single step the process
263 local lst, lpl, addr, bput;
266 if match(*PC, bplist) >= 0 then { // Sitting on a breakpoint
267 bput = fmt(*PC, bpfmt);
275 while lpl do { // place break points
276 *(head lpl) = bpinst;
280 startstop(pid); // do the step
282 while lst do { // remove the breakpoints
283 addr = fmt(head lst, bpfmt);
291 defn bpset(addr) // set a breakpoint
293 if status(pid) != "Stopped" then {
294 print("Waiting...\n");
297 if match(addr, bplist) >= 0 then
298 print("breakpoint already set at ", fmt(addr, 'a'), "\n");
300 *fmt(addr, bpfmt) = bpinst;
301 bplist = append bplist, addr;
305 defn bptab() // print a table of breakpoints
312 print("\t", fmt(addr, 'A'), " ", fmt(addr, 'a'), " ", fmt(addr, 'i'), "\n");
317 defn bpdel(addr) // delete a breakpoint
319 local n, pc, nbplist;
321 n = match(addr, bplist);
323 print("no breakpoint at ", fmt(addr, 'a'), "\n");
327 addr = fmt(addr, bpfmt);
330 nbplist = {}; // delete from list
334 nbplist = append nbplist, pc;
335 bplist = tail bplist;
337 bplist = nbplist; // delete from memory
340 defn wpflush() // copy wplist to /proc/$pid/watchpt
348 s = s + (el[0] + " " + itoa(el[1]) + " " + itoa(el[2]) + "\n");
353 if access("/proc/"+itoa(head lst)+"/watchpt") then
354 printto("/proc/"+itoa(head lst)+"/watchpt", s);
359 defn wpset(type, addr, len) // set a watchpoint
363 if status(pid) != "Stopped" then {
364 print("Waiting...\n");
367 if !regexp("^[rwx\\-]+$", type) then {
368 print("invalid type\n");
373 if rc("echo '"+type+" "+itoa(addr)+" "+itoa(len)+"' >> /proc/"+itoa(head lst)+"/watchpt") != "" then
377 wplist = append wplist, {type, addr, len, {}};
380 defn wptab() // print a table of watchpoints
387 print("\t", el[0], " ", fmt(el[1], 'A'), " ", fmt(el[1], 'a'), " ", fmt(el[2], 'd'), "\n");
394 local lst, el, found, nwplist;
401 if el[1] == addr then
404 nwplist = append nwplist, el;
408 print("no watchpoint at ", fmt(addr, 'a'), "\n");
421 s = s + itoa(head b, "%#.2x ");
427 defn wpupdate(ch) // update remembered values
429 local el, nwplist, mem, lst, i;
438 mem = append mem, *((el[1] + i)\b);
441 if ch && el[3] != {} && el[3] != mem then {
442 print("\t", fmt(el[1], 'a'), "\twas ", bytes(el[3]), "\n");
443 print("\t", fmt(el[1], 'a'), "\tis ", bytes(mem), "\n");
445 nwplist = append nwplist, {el[0], el[1], el[2], mem};
451 defn wpprocess() // trapped at watchpoint
456 pts = getfields(getfields(notes[0], " ", 1)[2], ",", 1);
459 el = wplist[atoi(el)];
461 print("\ttriggered ", el[0], " watchpoint at ", fmt(el[1], 'a'), " (", fmt(el[1], 'A'), ")\n");
468 defn cont() // continue execution
472 addr = fmt(*PC, bpfmt);
473 if match(addr, bplist) >= 0 then { // Sitting on a breakpoint
479 startstop(pid); // Run
482 defn stopped(pid) // called from acid when a process changes state
484 pstop(pid); // stub so this is easy to replace
487 defn procs() // print status of processes
500 print(fmt(c, 'c'), np, ": ", status(np), " at ", fmt(*PC, 'a'), " setproc(", np, ")\n");
514 bound = fnbound(addr);
516 addr = fmt(addr, 'i');
517 loop 1,_asmlines do {
518 print(fmt(addr, 'a'), " ", fmt(addr, 'A'));
519 print("\t", @addr++, "\n");
520 if bound != {} && addr > bound[1] then {
541 estr = "/sys/lib/acid/window '0 0 600 400' "+textfile;
542 if progargs != "" then
543 estr = estr+" "+progargs;
548 error("win failed to create process");
562 estr = "/sys/lib/acid/transcript '0 0 600 400' '100 100 700 500' "+textfile;
563 if progargs != "" then
564 estr = estr+" "+progargs;
569 error("win failed to create process");
580 // Dont miss the delay slot calls
581 bpset(follow(main)[0]);
586 defn stmnt() // step one statement
593 if line != pcline(*PC) then {
600 defn func() // step until we leave the current function
602 local bound, end, start, pc;
604 bound = fnbound(*PC);
605 if bound == {} then {
606 print("cannot locate text symbol\n");
613 while pc >= start && pc < end do {
624 bound = fnbound(*PC);
627 if pc >= bound[0] && pc < bound[1] then
630 while (pc < bound[0] || pc > bound[1]) && sp >= *SP do {
637 defn dump(addr, n, fmt)
639 // see definition of dump in acid manual: it does n+1 iterations
641 print(fmt(addr, 'A'), ": ");
642 addr = mem(addr, fmt);
652 while fmt[i] != 0 do {
655 while '0' <= fmt[i] && fmt[i] <= '9' do {
656 n = 10*n + fmt[i]-'0';
659 if n <= 0 then n = 1;
660 addr = fmt(addr, fmt[i]);
671 defn symbols(pattern)
678 if regexp(pattern, s[0]) then
679 print(s[0], "\t", s[1], "\t", s[2], "\n");
689 s = origin & 0x7fffffff;
690 e = etext & 0x7fffffff;
694 if c > s && c < e then {
695 print("src(", a, ")\n");
714 print("/sys/lib/acid/port");