Blob


1 // portable acid for all architectures
3 defn pfl(addr)
4 {
5 print(pcfile(addr), ":", pcline(addr), "\n");
6 }
8 defn
9 notestk(addr)
10 {
11 local pc, sp;
12 complex Ureg addr;
14 pc = addr.pc\X;
15 sp = addr.sp\X;
17 print("Note pc:", pc, " sp:", sp, " ", fmt(pc, 'a'), " ");
18 pfl(pc);
19 _stk({"PC", pc, "SP", sp, linkreg(addr)}, 1);
20 }
22 defn
23 notelstk(addr)
24 {
25 local pc, sp;
26 complex Ureg addr;
28 pc = addr.pc\X;
29 sp = addr.sp\X;
31 print("Note pc:", pc, " sp:", sp, " ", fmt(pc, 'a'), " ");
32 pfl(pc);
33 _stk({"PC", pc, "SP", sp, linkreg(addr)}, 1);
34 }
36 // defn labstk(l) // trace from a label
37 // {
38 // _stk({"PC", *(l+4), "SP", *l, linkreg(0)}, 0);
39 // }
41 defn params(param)
42 {
43 while param do {
44 sym = head param;
45 print(sym[0], "=", itoa(sym[1], "%ux"));
46 param = tail param;
47 if param then
48 print (",");
49 }
50 }
52 stkprefix = "";
53 stkignore = {};
54 stkend = 0;
56 defn locals(l)
57 {
58 local sym;
60 while l do {
61 sym = head l;
62 print(stkprefix, "\t", sym[0], "=", itoa(sym[1], "%ux"), "\n");
63 l = tail l;
64 }
65 }
67 defn _stkign(frame)
68 {
69 local file;
71 file = pcfile(frame[0]);
72 s = stkignore;
73 while s do {
74 if regexp(head s, file) then
75 return 1;
76 s = tail s;
77 }
78 return 0;
79 }
81 // print a stack trace
82 //
83 // in a run of leading frames in files matched by regexps in stkignore,
84 // only print the last one.
85 defn _stk(regs, dolocals)
86 {
87 local stk, frame, pc, fn, done, callerpc, paramlist, locallist;
89 stk = strace(regs);
90 if stkignore then {
91 while stk && tail stk && _stkign(head tail stk) do
92 stk = tail stk;
93 }
95 callerpc = 0;
96 done = 0;
97 while stk && !done do {
98 frame = head stk;
99 stk = tail stk;
100 fn = frame[0];
101 pc = frame[1];
102 callerpc = frame[2];
103 paramlist = frame[3];
104 locallist = frame[4];
106 print(stkprefix, fmt(fn, 'a'), "(");
107 params(paramlist);
108 print(")");
109 if pc != fn then
110 print("+", itoa(pc-fn, "%ux"));
111 print(" ");
112 pfl(pc);
113 if dolocals then
114 locals(locallist);
115 if fn == var("threadmain") || fn == var("p9main") then
116 done=1;
117 if fn == var("threadstart") || fn == var("scheduler") then
118 done=1;
119 if callerpc == 0 then
120 done=1;
123 if callerpc && !done then {
124 print(stkprefix, fmt(callerpc, 'a'), " ");
125 pfl(callerpc);
129 defn findsrc(file)
131 local lst, src;
133 if file[0] == '/' then {
134 src = file(file);
135 if src != {} then {
136 srcfiles = append srcfiles, file;
137 srctext = append srctext, src;
138 return src;
140 return {};
143 lst = srcpath;
144 while head lst do {
145 src = file(head lst+file);
146 if src != {} then {
147 srcfiles = append srcfiles, file;
148 srctext = append srctext, src;
149 return src;
151 lst = tail lst;
155 defn line(addr)
157 local src, file;
159 file = pcfile(addr);
160 src = match(file, srcfiles);
162 if src >= 0 then
163 src = srctext[src];
164 else
165 src = findsrc(file);
167 if src == {} then {
168 print("no source for ", file, "\n");
169 return {};
171 line = pcline(addr)-1;
172 print(file, ":", src[line], "\n");
175 defn addsrcdir(dir)
177 dir = dir+"/";
179 if match(dir, srcpath) >= 0 then {
180 print("already in srcpath\n");
181 return {};
184 srcpath = {dir}+srcpath;
187 defn source()
189 local l;
191 l = srcpath;
192 while l do {
193 print(head l, "\n");
194 l = tail l;
196 l = srcfiles;
198 while l do {
199 print("\t", head l, "\n");
200 l = tail l;
204 defn Bsrc(addr)
206 local lst;
208 lst = srcpath;
209 file = pcfile(addr);
210 if file[0] == '/' && access(file) then {
211 rc("B "+file+":"+itoa(pcline(addr)));
212 return {};
214 while head lst do {
215 name = head lst+file;
216 if access(name) then {
217 rc("B "+name+":"+itoa(pcline(addr)));
218 return {};
220 lst = tail lst;
222 print("no source for ", file, "\n");
225 defn srcline(addr)
227 local text, cline, line, file, src;
228 file = pcfile(addr);
229 src = match(file,srcfiles);
230 if (src>=0) then
231 src = srctext[src];
232 else
233 src = findsrc(file);
234 if (src=={}) then
236 return "(no source)";
238 return src[pcline(addr)-1];
241 defn src(addr)
243 local src, file, line, cline, text;
245 file = pcfile(addr);
246 src = match(file, srcfiles);
248 if src >= 0 then
249 src = srctext[src];
250 else
251 src = findsrc(file);
253 if src == {} then {
254 print("no source for ", file, "\n");
255 return {};
258 cline = pcline(addr)-1;
259 print(file, ":", cline+1, "\n");
260 line = cline-5;
261 loop 0,10 do {
262 if line >= 0 then {
263 if line == cline then
264 print(">");
265 else
266 print(" ");
267 text = src[line];
268 if text == {} then
269 return {};
270 print(line+1, "\t", text, "\n");
272 line = line+1;
276 defn step() // single step the process
278 local lst, lpl, addr, bput;
280 bput = 0;
281 if match(*PC, bplist) >= 0 then { // Sitting on a breakpoint
282 bput = fmt(*PC, bpfmt);
283 *bput = @bput;
286 lst = follow(*PC);
288 lpl = lst;
289 while lpl do { // place break points
290 *(head lpl) = bpinst;
291 lpl = tail lpl;
294 startstop(pid); // do the step
296 while lst do { // remove the breakpoints
297 addr = fmt(head lst, bpfmt);
298 *addr = @addr;
299 lst = tail lst;
301 if bput != 0 then
302 *bput = bpinst;
305 defn bpset(addr) // set a breakpoint
307 if status(pid) != "Stopped" then {
308 print("Waiting...\n");
309 stop(pid);
311 if match(addr, bplist) >= 0 then
312 print("breakpoint already set at ", fmt(addr, 'a'), "\n");
313 else {
314 *fmt(addr, bpfmt) = bpinst;
315 bplist = append bplist, addr;
319 defn bptab() // print a table of breakpoints
321 local lst, addr;
323 lst = bplist;
324 while lst do {
325 addr = head lst;
326 print("\t", fmt(addr, 'X'), " ", fmt(addr, 'a'), " ", fmt(addr, 'i'), "\n");
327 lst = tail lst;
331 defn bpdel(addr) // delete a breakpoint
333 local n, pc, nbplist;
335 n = match(addr, bplist);
336 if n < 0 then {
337 print("no breakpoint at ", fmt(addr, 'a'), "\n");
338 return {};
341 addr = fmt(addr, bpfmt);
342 *addr = @addr;
344 nbplist = {}; // delete from list
345 while bplist do {
346 pc = head bplist;
347 if pc != addr then
348 nbplist = append nbplist, pc;
349 bplist = tail bplist;
351 bplist = nbplist; // delete from memory
354 defn cont() // continue execution
356 local addr;
358 addr = fmt(*PC, bpfmt);
359 if match(addr, bplist) >= 0 then { // Sitting on a breakpoint
360 *addr = @addr;
361 step(); // Step over
362 *addr = bpinst;
364 startstop(pid); // Run
367 defn stopped(pid) // called from acid when a process changes state
369 pstop(pid); // stub so this is easy to replace
372 defn procs() // print status of processes
374 local c, lst, cpid;
376 cpid = pid;
377 lst = proclist;
378 while lst do {
379 np = head lst;
380 setproc(np);
381 if np == cpid then
382 c = '>';
383 else
384 c = ' ';
385 print(fmt(c, 'c'), np, ": ", status(np), " at ", fmt(*PC, 'a'), " setproc(", np, ")\n");
386 lst = tail lst;
388 pid = cpid;
389 if pid != 0 then
390 setproc(pid);
393 _asmlines = 30;
395 defn asm(addr)
397 local bound;
399 bound = fnbound(addr);
401 addr = fmt(addr, 'i');
402 loop 1,_asmlines do {
403 print(fmt(addr, 'a'), " ", fmt(addr, 'X'));
404 print("\t", @addr++, "\n");
405 if bound != {} && addr > bound[1] then {
406 lasmaddr = addr;
407 return {};
410 lasmaddr = addr;
413 defn casm()
415 asm(lasmaddr);
418 defn xasm(addr)
420 local bound;
422 bound = fnbound(addr);
424 addr = fmt(addr, 'i');
425 loop 1,_asmlines do {
426 print(fmt(addr, 'a'), " ", fmt(addr, 'X'));
427 print("\t", *addr++, "\n");
428 if bound != {} && addr > bound[1] then {
429 lasmaddr = addr;
430 return {};
433 lasmaddr = addr;
436 defn xcasm()
438 xasm(lasmaddr);
441 defn win()
443 local npid, estr;
445 bplist = {};
446 notes = {};
448 estr = "/sys/lib/acid/window '0 0 600 400' "+textfile;
449 if progargs != "" then
450 estr = estr+" "+progargs;
452 npid = rc(estr);
453 npid = atoi(npid);
454 if npid == 0 then
455 error("win failed to create process");
457 setproc(npid);
458 stopped(npid);
461 defn win2()
463 local npid, estr;
465 bplist = {};
466 notes = {};
468 estr = "/sys/lib/acid/transcript '0 0 600 400' '100 100 700 500' "+textfile;
469 if progargs != "" then
470 estr = estr+" "+progargs;
472 npid = rc(estr);
473 npid = atoi(npid);
474 if npid == 0 then
475 error("win failed to create process");
477 setproc(npid);
478 stopped(npid);
481 defn new()
483 bplist = {};
484 newproc(progargs);
485 // Dont miss the delay slot calls
486 bpset(follow(main)[0]);
487 cont();
488 bpdel(*PC);
491 defn stmnt() // step one statement
493 local line;
495 line = pcline(*PC);
496 while 1 do {
497 step();
498 if line != pcline(*PC) then {
499 src(*PC);
500 return {};
505 defn func() // step until we leave the current function
507 local bound, end, start, pc;
509 bound = fnbound(*PC);
510 if bound == {} then {
511 print("cannot locate text symbol\n");
512 return {};
515 pc = *PC;
516 start = bound[0];
517 end = bound[1];
518 while pc >= start && pc < end do {
519 step();
520 pc = *PC;
524 defn next()
526 local sp, bound;
528 sp = *SP;
529 bound = fnbound(*PC);
530 stmnt();
531 pc = *PC;
532 if pc >= bound[0] && pc < bound[1] then
533 return {};
535 while (pc < bound[0] || pc > bound[1]) && sp >= *SP do {
536 step();
537 pc = *PC;
539 src(*PC);
542 defn maps()
544 local m, mm;
546 m = map();
547 while m != {} do {
548 mm = head m;
549 m = tail m;
550 print(mm[2]\X, " ", mm[3]\X, " ", mm[4]\X, " ", mm[0], " ", mm[1], "\n");
554 defn dump(addr, n, fmt)
556 loop 0, n do {
557 print(fmt(addr, 'X'), ": ");
558 addr = mem(addr, fmt);
562 defn mem(addr, fmt)
565 local i, c, n;
567 i = 0;
568 while fmt[i] != 0 do {
569 c = fmt[i];
570 n = 0;
571 while '0' <= fmt[i] && fmt[i] <= '9' do {
572 n = 10*n + fmt[i]-'0';
573 i = i+1;
575 if n <= 0 then n = 1;
576 addr = fmt(addr, fmt[i]);
577 while n > 0 do {
578 print(*addr++, " ");
579 n = n-1;
581 i = i+1;
583 print("\n");
584 return addr;
587 defn symbols(pattern)
589 local l, s;
591 l = symbols;
592 while l do {
593 s = head l;
594 if regexp(pattern, s[0]) then
595 print(s[0], "\t", s[1], "\t", s[2], "\t", s[3], "\n");
596 l = tail l;
600 defn havesymbol(name)
602 local l, s;
604 l = symbols;
605 while l do {
606 s = head l;
607 l = tail l;
608 if s[0] == name then
609 return 1;
611 return 0;
614 defn spsrch(len)
616 local addr, a, s, e;
618 addr = *SP;
619 s = origin & 0x7fffffff;
620 e = etext & 0x7fffffff;
621 loop 1, len do {
622 a = *addr++;
623 c = a & 0x7fffffff;
624 if c > s && c < e then {
625 print("src(", a, ")\n");
626 pfl(a);
631 defn acidtypes()
633 local syms;
634 local l;
636 l = textfile();
637 if l != {} then {
638 syms = "acidtypes";
639 while l != {} do {
640 syms = syms + " " + ((head l)[0]);
641 l = tail l;
643 includepipe(syms);
647 defn getregs()
649 local regs, l;
651 regs = {};
652 l = registers;
653 while l != {} do {
654 regs = append regs, var(l[0]);
655 l = tail l;
657 return regs;
660 defn setregs(regs)
662 local l;
664 l = registers;
665 while l != {} do {
666 var(l[0]) = regs[0];
667 l = tail l;
668 regs = tail regs;
670 return regs;
673 defn resetregs()
675 local l;
677 l = registers;
678 while l != {} do {
679 var(l[0]) = register(l[0]);
680 l = tail l;
684 defn clearregs()
686 local l;
688 l = registers;
689 while l != {} do {
690 var(l[0]) = refconst(~0);
691 l = tail l;
695 progargs="";
696 print(acidfile);