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 params(param)
37 {
38 while param do {
39 sym = head param;
40 print(sym[0], "=", itoa(sym[1], "%#ux"));
41 param = tail param;
42 if param then
43 print (",");
44 }
45 }
47 stkprefix = "";
48 stkignore = {};
49 stkend = 0;
51 defn locals(l)
52 {
53 local sym;
55 while l do {
56 sym = head l;
57 print(stkprefix, "\t", sym[0], "=", itoa(sym[1], "%#ux"), "\n");
58 l = tail l;
59 }
60 }
62 defn _stkign(frame)
63 {
64 local file;
66 file = pcfile(frame[0]);
67 s = stkignore;
68 while s do {
69 if regexp(head s, file) then
70 return 1;
71 s = tail s;
72 }
73 return 0;
74 }
76 // print a stack trace
77 //
78 // in a run of leading frames in files matched by regexps in stkignore,
79 // only print the last one.
80 defn _stk(regs, dolocals)
81 {
82 local stk, frame, pc, fn, done, callerpc, paramlist, locallist;
84 stk = strace(regs);
85 if stkignore then {
86 while stk && tail stk && _stkign(head tail stk) do
87 stk = tail stk;
88 }
90 callerpc = 0;
91 done = 0;
92 while stk && !done do {
93 frame = head stk;
94 stk = tail stk;
95 fn = frame[0];
96 pc = frame[1];
97 callerpc = frame[2];
98 paramlist = frame[3];
99 locallist = frame[4];
101 print(stkprefix, fmt(fn, 'a'), "(");
102 params(paramlist);
103 print(")");
104 if pc != fn then
105 print("+", itoa(pc-fn, "%#ux"));
106 print(" ");
107 pfl(pc);
108 if dolocals then
109 locals(locallist);
110 if fn == var("threadmain") || fn == var("p9main") then
111 done=1;
112 if fn == var("threadstart") || fn == var("scheduler") then
113 done=1;
114 if callerpc == 0 then
115 done=1;
117 if callerpc && !done then {
118 print(stkprefix, fmt(callerpc, 'a'), " ");
119 pfl(callerpc);
123 defn findsrc(file)
125 local lst, src;
127 if file[0] == '/' then {
128 src = file(file);
129 if src != {} then {
130 srcfiles = append srcfiles, file;
131 srctext = append srctext, src;
132 return src;
134 return {};
137 lst = srcpath;
138 while head lst do {
139 src = file(head lst+file);
140 if src != {} then {
141 srcfiles = append srcfiles, file;
142 srctext = append srctext, src;
143 return src;
145 lst = tail lst;
149 defn line(addr)
151 local src, file;
153 file = pcfile(addr);
154 src = match(file, srcfiles);
156 if src >= 0 then
157 src = srctext[src];
158 else
159 src = findsrc(file);
161 if src == {} then {
162 print("no source for ", file, "\n");
163 return {};
165 line = pcline(addr)-1;
166 print(file, ":", src[line], "\n");
169 defn addsrcdir(dir)
171 dir = dir+"/";
173 if match(dir, srcpath) >= 0 then {
174 print("already in srcpath\n");
175 return {};
178 srcpath = {dir}+srcpath;
181 defn source()
183 local l;
185 l = srcpath;
186 while l do {
187 print(head l, "\n");
188 l = tail l;
190 l = srcfiles;
192 while l do {
193 print("\t", head l, "\n");
194 l = tail l;
198 defn Bsrc(addr)
200 local lst;
202 lst = srcpath;
203 file = pcfile(addr);
204 if file[0] == '/' && access(file) then {
205 rc("B "+file+":"+itoa(pcline(addr)));
206 return {};
208 while head lst do {
209 name = head lst+file;
210 if access(name) then {
211 rc("B "+name+":"+itoa(pcline(addr)));
212 return {};
214 lst = tail lst;
216 print("no source for ", file, "\n");
219 defn srcline(addr)
221 local text, cline, line, file, src;
222 file = pcfile(addr);
223 src = match(file,srcfiles);
224 if (src>=0) then
225 src = srctext[src];
226 else
227 src = findsrc(file);
228 if (src=={}) then
230 return "(no source)";
232 return src[pcline(addr)-1];
235 defn src(addr)
237 local src, file, line, cline, text;
239 file = pcfile(addr);
240 src = match(file, srcfiles);
242 if src >= 0 then
243 src = srctext[src];
244 else
245 src = findsrc(file);
247 if src == {} then {
248 print("no source for ", file, "\n");
249 return {};
252 cline = pcline(addr)-1;
253 print(file, ":", cline+1, "\n");
254 line = cline-5;
255 loop 0,10 do {
256 if line >= 0 then {
257 if line == cline then
258 print(">");
259 else
260 print(" ");
261 text = src[line];
262 if text == {} then
263 return {};
264 print(line+1, "\t", text, "\n");
266 line = line+1;
270 defn step() // single step the process
272 local lst, lpl, addr, bput;
274 bput = 0;
275 if match(*PC, bplist) >= 0 then { // Sitting on a breakpoint
276 bput = fmt(*PC, bpfmt);
277 *bput = @bput;
280 lst = follow(*PC);
282 lpl = lst;
283 while lpl do { // place break points
284 *(head lpl) = bpinst;
285 lpl = tail lpl;
288 startstop(pid); // do the step
290 while lst do { // remove the breakpoints
291 addr = fmt(head lst, bpfmt);
292 *addr = @addr;
293 lst = tail lst;
295 if bput != 0 then
296 *bput = bpinst;
299 defn bpset(addr) // set a breakpoint
301 if status(pid) != "Stopped" then {
302 print("Waiting...\n");
303 stop(pid);
305 if match(addr, bplist) >= 0 then
306 print("breakpoint already set at ", fmt(addr, 'a'), "\n");
307 else {
308 *fmt(addr, bpfmt) = bpinst;
309 bplist = append bplist, addr;
313 defn bptab() // print a table of breakpoints
315 local lst, addr;
317 lst = bplist;
318 while lst do {
319 addr = head lst;
320 print("\t", fmt(addr, 'X'), " ", fmt(addr, 'a'), " ", fmt(addr, 'i'), "\n");
321 lst = tail lst;
325 defn bpdel(addr) // delete a breakpoint
327 local n, pc, nbplist;
329 n = match(addr, bplist);
330 if n < 0 then {
331 print("no breakpoint at ", fmt(addr, 'a'), "\n");
332 return {};
335 addr = fmt(addr, bpfmt);
336 *addr = @addr;
338 nbplist = {}; // delete from list
339 while bplist do {
340 pc = head bplist;
341 if pc != addr then
342 nbplist = append nbplist, pc;
343 bplist = tail bplist;
345 bplist = nbplist; // delete from memory
348 defn cont() // continue execution
350 local addr;
352 addr = fmt(*PC, bpfmt);
353 if match(addr, bplist) >= 0 then { // Sitting on a breakpoint
354 *addr = @addr;
355 step(); // Step over
356 *addr = bpinst;
358 startstop(pid); // Run
361 defn stopped(pid) // called from acid when a process changes state
363 pstop(pid); // stub so this is easy to replace
366 defn procs() // print status of processes
368 local c, lst, cpid;
370 cpid = pid;
371 lst = proclist;
372 while lst do {
373 np = head lst;
374 setproc(np);
375 if np == cpid then
376 c = '>';
377 else
378 c = ' ';
379 print(fmt(c, 'c'), np, ": ", status(np), " at ", fmt(*PC, 'a'), " setproc(", np, ")\n");
380 lst = tail lst;
382 pid = cpid;
383 if pid != 0 then
384 setproc(pid);
387 _asmlines = 30;
389 defn asm(addr)
391 local bound;
393 bound = fnbound(addr);
395 addr = fmt(addr, 'i');
396 loop 1,_asmlines do {
397 print(fmt(addr, 'a'), " ", fmt(addr, 'X'));
398 print("\t", @addr++, "\n");
399 if bound != {} && addr > bound[1] then {
400 lasmaddr = addr;
401 return {};
404 lasmaddr = addr;
407 defn casm()
409 asm(lasmaddr);
412 defn xasm(addr)
414 local bound;
416 bound = fnbound(addr);
418 addr = fmt(addr, 'i');
419 loop 1,_asmlines do {
420 print(fmt(addr, 'a'), " ", fmt(addr, 'X'));
421 print("\t", *addr++, "\n");
422 if bound != {} && addr > bound[1] then {
423 lasmaddr = addr;
424 return {};
427 lasmaddr = addr;
430 defn xcasm()
432 xasm(lasmaddr);
435 defn win()
437 local npid, estr;
439 bplist = {};
440 notes = {};
442 estr = "/sys/lib/acid/window '0 0 600 400' "+textfile;
443 if progargs != "" then
444 estr = estr+" "+progargs;
446 npid = rc(estr);
447 npid = atoi(npid);
448 if npid == 0 then
449 error("win failed to create process");
451 setproc(npid);
452 stopped(npid);
455 defn win2()
457 local npid, estr;
459 bplist = {};
460 notes = {};
462 estr = "/sys/lib/acid/transcript '0 0 600 400' '100 100 700 500' "+textfile;
463 if progargs != "" then
464 estr = estr+" "+progargs;
466 npid = rc(estr);
467 npid = atoi(npid);
468 if npid == 0 then
469 error("win failed to create process");
471 setproc(npid);
472 stopped(npid);
475 defn new()
477 bplist = {};
478 newproc(progargs);
479 // Dont miss the delay slot calls
480 bpset(follow(main)[0]);
481 cont();
482 bpdel(*PC);
485 defn stmnt() // step one statement
487 local line;
489 line = pcline(*PC);
490 while 1 do {
491 step();
492 if line != pcline(*PC) then {
493 src(*PC);
494 return {};
499 defn func() // step until we leave the current function
501 local bound, end, start, pc;
503 bound = fnbound(*PC);
504 if bound == {} then {
505 print("cannot locate text symbol\n");
506 return {};
509 pc = *PC;
510 start = bound[0];
511 end = bound[1];
512 while pc >= start && pc < end do {
513 step();
514 pc = *PC;
518 defn next()
520 local sp, bound;
522 sp = *SP;
523 bound = fnbound(*PC);
524 stmnt();
525 pc = *PC;
526 if pc >= bound[0] && pc < bound[1] then
527 return {};
529 while (pc < bound[0] || pc > bound[1]) && sp >= *SP do {
530 step();
531 pc = *PC;
533 src(*PC);
536 defn maps()
538 local m, mm;
540 m = map();
541 while m != {} do {
542 mm = head m;
543 m = tail m;
544 print(mm[2]\X, " ", mm[3]\X, " ", mm[4]\X, " ", mm[0], " ", mm[1], "\n");
548 defn dump(addr, n, fmt)
550 loop 0, n do {
551 print(fmt(addr, 'X'), ": ");
552 addr = mem(addr, fmt);
556 defn mem(addr, fmt)
559 local i, c, n;
561 i = 0;
562 while fmt[i] != 0 do {
563 c = fmt[i];
564 n = 0;
565 while '0' <= fmt[i] && fmt[i] <= '9' do {
566 n = 10*n + fmt[i]-'0';
567 i = i+1;
569 if n <= 0 then n = 1;
570 addr = fmt(addr, fmt[i]);
571 while n > 0 do {
572 print(*addr++, " ");
573 n = n-1;
575 i = i+1;
577 print("\n");
578 return addr;
581 defn symbols(pattern)
583 local l, s;
585 l = symbols;
586 while l do {
587 s = head l;
588 if regexp(pattern, s[0]) then
589 print(s[0], "\t", s[1], "\t", s[2], "\t", s[3], "\n");
590 l = tail l;
594 defn havesymbol(name)
596 local l, s;
598 l = symbols;
599 while l do {
600 s = head l;
601 l = tail l;
602 if s[0] == name then
603 return 1;
605 return 0;
608 defn spsrch(len)
610 local addr, a, s, e;
612 addr = *SP;
613 s = origin & 0x7fffffff;
614 e = etext & 0x7fffffff;
615 loop 1, len do {
616 a = *addr++;
617 c = a & 0x7fffffff;
618 if c > s && c < e then {
619 print("src(", a, ")\n");
620 pfl(a);
625 defn acidtypes()
627 local syms;
628 local l;
630 l = textfile();
631 if l != {} then {
632 syms = "acidtypes";
633 while l != {} do {
634 syms = syms + " " + ((head l)[0]);
635 l = tail l;
637 includepipe(syms);
641 defn getregs()
643 local regs, l;
645 regs = {};
646 l = registers;
647 while l != {} do {
648 regs = append regs, var(l[0]);
649 l = tail l;
651 return regs;
654 defn setregs(regs)
656 local l;
658 l = registers;
659 while l != {} do {
660 var(l[0]) = regs[0];
661 l = tail l;
662 regs = tail regs;
664 return regs;
667 defn resetregs()
669 local l;
671 l = registers;
672 while l != {} do {
673 var(l[0]) = register(l[0]);
674 l = tail l;
678 defn clearregs()
680 local l;
682 l = registers;
683 while l != {} do {
684 var(l[0]) = refconst(~0);
685 l = tail l;
689 progargs="";
690 print(acidfile);