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 if addr == 0 then {
330 while bplist do {
331 pc = head bplist;
332 pc = fmt(pc, bpfmt);
333 *pc = @pc;
334 bplist = tail bplist;
336 return {};
339 n = match(addr, bplist);
340 if n < 0 then {
341 print("no breakpoint at ", fmt(addr, 'a'), "\n");
342 return {};
345 addr = fmt(addr, bpfmt);
346 *addr = @addr;
348 nbplist = {}; // delete from list
349 while bplist do {
350 pc = head bplist;
351 if pc != addr then
352 nbplist = append nbplist, pc;
353 bplist = tail bplist;
355 bplist = nbplist; // delete from memory
358 defn cont() // continue execution
360 local addr;
362 addr = fmt(*PC, bpfmt);
363 if match(addr, bplist) >= 0 then { // Sitting on a breakpoint
364 *addr = @addr;
365 step(); // Step over
366 *addr = bpinst;
368 startstop(pid); // Run
371 defn stopped(pid) // called from acid when a process changes state
373 pfixstop(pid);
374 pstop(pid); // stub so this is easy to replace
377 defn procs() // print status of processes
379 local c, lst, cpid;
381 cpid = pid;
382 lst = proclist;
383 while lst do {
384 np = head lst;
385 setproc(np);
386 if np == cpid then
387 c = '>';
388 else
389 c = ' ';
390 print(fmt(c, 'c'), np, ": ", status(np), " at ", fmt(*PC, 'a'), " setproc(", np, ")\n");
391 lst = tail lst;
393 pid = cpid;
394 if pid != 0 then
395 setproc(pid);
398 _asmlines = 30;
400 defn asm(addr)
402 local bound;
404 bound = fnbound(addr);
406 addr = fmt(addr, 'i');
407 loop 1,_asmlines do {
408 print(fmt(addr, 'a'), " ", fmt(addr, 'X'));
409 print("\t", @addr++, "\n");
410 if bound != {} && addr > bound[1] then {
411 lasmaddr = addr;
412 return {};
415 lasmaddr = addr;
418 defn casm()
420 asm(lasmaddr);
423 defn xasm(addr)
425 local bound;
427 bound = fnbound(addr);
429 addr = fmt(addr, 'i');
430 loop 1,_asmlines do {
431 print(fmt(addr, 'a'), " ", fmt(addr, 'X'));
432 print("\t", *addr++, "\n");
433 if bound != {} && addr > bound[1] then {
434 lasmaddr = addr;
435 return {};
438 lasmaddr = addr;
441 defn xcasm()
443 xasm(lasmaddr);
446 defn win()
448 local npid, estr;
450 bplist = {};
451 notes = {};
453 estr = "/sys/lib/acid/window '0 0 600 400' "+textfile;
454 if progargs != "" then
455 estr = estr+" "+progargs;
457 npid = rc(estr);
458 npid = atoi(npid);
459 if npid == 0 then
460 error("win failed to create process");
462 setproc(npid);
463 stopped(npid);
466 defn win2()
468 local npid, estr;
470 bplist = {};
471 notes = {};
473 estr = "/sys/lib/acid/transcript '0 0 600 400' '100 100 700 500' "+textfile;
474 if progargs != "" then
475 estr = estr+" "+progargs;
477 npid = rc(estr);
478 npid = atoi(npid);
479 if npid == 0 then
480 error("win failed to create process");
482 setproc(npid);
483 stopped(npid);
486 printstopped = 1;
487 defn new()
489 local a;
491 bplist = {};
492 newproc(progargs);
493 a = var("p9main");
494 if a == {} then
495 a = var("main");
496 if a == {} then
497 return {};
498 bpset(a);
499 while *PC != a do
500 cont();
501 bpdel(a);
504 defn stmnt() // step one statement
506 local line;
508 line = pcline(*PC);
509 while 1 do {
510 step();
511 if line != pcline(*PC) then {
512 src(*PC);
513 return {};
518 defn func() // step until we leave the current function
520 local bound, end, start, pc;
522 bound = fnbound(*PC);
523 if bound == {} then {
524 print("cannot locate text symbol\n");
525 return {};
528 pc = *PC;
529 start = bound[0];
530 end = bound[1];
531 while pc >= start && pc < end do {
532 step();
533 pc = *PC;
537 defn next()
539 local sp, bound, pc;
541 sp = *SP;
542 bound = fnbound(*PC);
543 if bound == {} then {
544 print("cannot locate text symbol\n");
545 return {};
547 stmnt();
548 pc = *PC;
549 if pc >= bound[0] && pc < bound[1] then
550 return {};
552 while (pc < bound[0] || pc > bound[1]) && sp >= *SP do {
553 step();
554 pc = *PC;
556 src(*PC);
559 defn maps()
561 local m, mm;
563 m = map();
564 while m != {} do {
565 mm = head m;
566 m = tail m;
567 print(mm[2]\X, " ", mm[3]\X, " ", mm[4]\X, " ", mm[0], " ", mm[1], "\n");
571 defn dump(addr, n, fmt)
573 loop 0, n do {
574 print(fmt(addr, 'X'), ": ");
575 addr = mem(addr, fmt);
579 defn mem(addr, fmt)
582 local i, c, n;
584 i = 0;
585 while fmt[i] != 0 do {
586 c = fmt[i];
587 n = 0;
588 while '0' <= fmt[i] && fmt[i] <= '9' do {
589 n = 10*n + fmt[i]-'0';
590 i = i+1;
592 if n <= 0 then n = 1;
593 addr = fmt(addr, fmt[i]);
594 while n > 0 do {
595 print(*addr++, " ");
596 n = n-1;
598 i = i+1;
600 print("\n");
601 return addr;
604 defn symbols(pattern)
606 local l, s, name;
608 l = symbols;
609 while l do {
610 s = head l;
611 if regexp(pattern, s[0]) then {
612 name = s[4];
613 if name == {} then
614 name = "";
615 print(s[0], "\t", s[1], "\t", s[2], "\t", s[3], "\t", name, "\n");
617 l = tail l;
621 defn havesymbol(name)
623 local l, s;
625 l = symbols;
626 while l do {
627 s = head l;
628 l = tail l;
629 if s[0] == name then
630 return 1;
632 return 0;
635 defn spsrch(len)
637 local addr, a, s, e;
639 addr = *SP;
640 s = origin & 0x7fffffff;
641 e = etext & 0x7fffffff;
642 loop 1, len do {
643 a = *addr++;
644 c = a & 0x7fffffff;
645 if c > s && c < e then {
646 print("src(", a, ")\n");
647 pfl(a);
652 defn acidtypes()
654 local syms;
655 local l;
657 l = textfile();
658 if l != {} then {
659 syms = "acidtypes";
660 while l != {} do {
661 syms = syms + " " + ((head l)[0]);
662 l = tail l;
664 includepipe(syms);
668 defn getregs()
670 local regs, l;
672 regs = {};
673 l = registers;
674 while l != {} do {
675 regs = append regs, var(l[0]);
676 l = tail l;
678 return regs;
681 defn setregs(regs)
683 local l;
685 l = registers;
686 while l != {} do {
687 var(l[0]) = regs[0];
688 l = tail l;
689 regs = tail regs;
691 return regs;
694 defn resetregs()
696 local l;
698 l = registers;
699 while l != {} do {
700 var(l[0]) = register(l[0]);
701 l = tail l;
705 defn clearregs()
707 local l;
709 l = registers;
710 while l != {} do {
711 var(l[0]) = refconst(~0);
712 l = tail l;
716 progargs="";
717 print(acidfile);