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, pc, fn, 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 while stk do {
97 frame = head stk;
98 stk = tail stk;
99 fn = frame[0];
100 pc = frame[1];
101 callerpc = frame[2];
102 paramlist = frame[3];
103 locallist = frame[4];
105 print(stkprefix, fmt(fn, 'a'), "(");
106 params(paramlist);
107 print(")");
108 if pc != fn then
109 print("+", itoa(pc-fn, "%ux"));
110 print(" ");
111 pfl(pc);
112 if dolocals then
113 locals(locallist);
116 if callerpc then {
117 print(stkprefix, fmt(callerpc, 'a'), " ");
118 pfl(callerpc);
122 defn findsrc(file)
124 local lst, src;
126 if file[0] == '/' then {
127 src = file(file);
128 if src != {} then {
129 srcfiles = append srcfiles, file;
130 srctext = append srctext, src;
131 return src;
133 return {};
136 lst = srcpath;
137 while head lst do {
138 src = file(head lst+file);
139 if src != {} then {
140 srcfiles = append srcfiles, file;
141 srctext = append srctext, src;
142 return src;
144 lst = tail lst;
148 defn line(addr)
150 local src, file;
152 file = pcfile(addr);
153 src = match(file, srcfiles);
155 if src >= 0 then
156 src = srctext[src];
157 else
158 src = findsrc(file);
160 if src == {} then {
161 print("no source for ", file, "\n");
162 return {};
164 line = pcline(addr)-1;
165 print(file, ":", src[line], "\n");
168 defn addsrcdir(dir)
170 dir = dir+"/";
172 if match(dir, srcpath) >= 0 then {
173 print("already in srcpath\n");
174 return {};
177 srcpath = {dir}+srcpath;
180 defn source()
182 local l;
184 l = srcpath;
185 while l do {
186 print(head l, "\n");
187 l = tail l;
189 l = srcfiles;
191 while l do {
192 print("\t", head l, "\n");
193 l = tail l;
197 defn Bsrc(addr)
199 local lst;
201 lst = srcpath;
202 file = pcfile(addr);
203 if file[0] == '/' && access(file) then {
204 rc("B "+file+":"+itoa(pcline(addr)));
205 return {};
207 while head lst do {
208 name = head lst+file;
209 if access(name) then {
210 rc("B "+name+":"+itoa(pcline(addr)));
211 return {};
213 lst = tail lst;
215 print("no source for ", file, "\n");
218 defn srcline(addr)
220 local text, cline, line, file, src;
221 file = pcfile(addr);
222 src = match(file,srcfiles);
223 if (src>=0) then
224 src = srctext[src];
225 else
226 src = findsrc(file);
227 if (src=={}) then
229 return "(no source)";
231 return src[pcline(addr)-1];
234 defn src(addr)
236 local src, file, line, cline, text;
238 file = pcfile(addr);
239 src = match(file, srcfiles);
241 if src >= 0 then
242 src = srctext[src];
243 else
244 src = findsrc(file);
246 if src == {} then {
247 print("no source for ", file, "\n");
248 return {};
251 cline = pcline(addr)-1;
252 print(file, ":", cline+1, "\n");
253 line = cline-5;
254 loop 0,10 do {
255 if line >= 0 then {
256 if line == cline then
257 print(">");
258 else
259 print(" ");
260 text = src[line];
261 if text == {} then
262 return {};
263 print(line+1, "\t", text, "\n");
265 line = line+1;
269 defn step() // single step the process
271 local lst, lpl, addr, bput;
273 bput = 0;
274 if match(*PC, bplist) >= 0 then { // Sitting on a breakpoint
275 bput = fmt(*PC, bpfmt);
276 *bput = @bput;
279 lst = follow(*PC);
281 lpl = lst;
282 while lpl do { // place break points
283 *(head lpl) = bpinst;
284 lpl = tail lpl;
287 startstop(pid); // do the step
289 while lst do { // remove the breakpoints
290 addr = fmt(head lst, bpfmt);
291 *addr = @addr;
292 lst = tail lst;
294 if bput != 0 then
295 *bput = bpinst;
298 defn bpset(addr) // set a breakpoint
300 if status(pid) != "Stopped" then {
301 print("Waiting...\n");
302 stop(pid);
304 if match(addr, bplist) >= 0 then
305 print("breakpoint already set at ", fmt(addr, 'a'), "\n");
306 else {
307 *fmt(addr, bpfmt) = bpinst;
308 bplist = append bplist, addr;
312 defn bptab() // print a table of breakpoints
314 local lst, addr;
316 lst = bplist;
317 while lst do {
318 addr = head lst;
319 print("\t", fmt(addr, 'X'), " ", fmt(addr, 'a'), " ", fmt(addr, 'i'), "\n");
320 lst = tail lst;
324 defn bpdel(addr) // delete a breakpoint
326 local n, pc, nbplist;
328 n = match(addr, bplist);
329 if n < 0 then {
330 print("no breakpoint at ", fmt(addr, 'a'), "\n");
331 return {};
334 addr = fmt(addr, bpfmt);
335 *addr = @addr;
337 nbplist = {}; // delete from list
338 while bplist do {
339 pc = head bplist;
340 if pc != addr then
341 nbplist = append nbplist, pc;
342 bplist = tail bplist;
344 bplist = nbplist; // delete from memory
347 defn cont() // continue execution
349 local addr;
351 addr = fmt(*PC, bpfmt);
352 if match(addr, bplist) >= 0 then { // Sitting on a breakpoint
353 *addr = @addr;
354 step(); // Step over
355 *addr = bpinst;
357 startstop(pid); // Run
360 defn stopped(pid) // called from acid when a process changes state
362 pstop(pid); // stub so this is easy to replace
365 defn procs() // print status of processes
367 local c, lst, cpid;
369 cpid = pid;
370 lst = proclist;
371 while lst do {
372 np = head lst;
373 setproc(np);
374 if np == cpid then
375 c = '>';
376 else
377 c = ' ';
378 print(fmt(c, 'c'), np, ": ", status(np), " at ", fmt(*PC, 'a'), " setproc(", np, ")\n");
379 lst = tail lst;
381 pid = cpid;
382 if pid != 0 then
383 setproc(pid);
386 _asmlines = 30;
388 defn asm(addr)
390 local bound;
392 bound = fnbound(addr);
394 addr = fmt(addr, 'i');
395 loop 1,_asmlines do {
396 print(fmt(addr, 'a'), " ", fmt(addr, 'X'));
397 print("\t", @addr++, "\n");
398 if bound != {} && addr > bound[1] then {
399 lasmaddr = addr;
400 return {};
403 lasmaddr = addr;
406 defn casm()
408 asm(lasmaddr);
411 defn win()
413 local npid, estr;
415 bplist = {};
416 notes = {};
418 estr = "/sys/lib/acid/window '0 0 600 400' "+textfile;
419 if progargs != "" then
420 estr = estr+" "+progargs;
422 npid = rc(estr);
423 npid = atoi(npid);
424 if npid == 0 then
425 error("win failed to create process");
427 setproc(npid);
428 stopped(npid);
431 defn win2()
433 local npid, estr;
435 bplist = {};
436 notes = {};
438 estr = "/sys/lib/acid/transcript '0 0 600 400' '100 100 700 500' "+textfile;
439 if progargs != "" then
440 estr = estr+" "+progargs;
442 npid = rc(estr);
443 npid = atoi(npid);
444 if npid == 0 then
445 error("win failed to create process");
447 setproc(npid);
448 stopped(npid);
451 defn new()
453 bplist = {};
454 newproc(progargs);
455 // Dont miss the delay slot calls
456 bpset(follow(main)[0]);
457 cont();
458 bpdel(*PC);
461 defn stmnt() // step one statement
463 local line;
465 line = pcline(*PC);
466 while 1 do {
467 step();
468 if line != pcline(*PC) then {
469 src(*PC);
470 return {};
475 defn func() // step until we leave the current function
477 local bound, end, start, pc;
479 bound = fnbound(*PC);
480 if bound == {} then {
481 print("cannot locate text symbol\n");
482 return {};
485 pc = *PC;
486 start = bound[0];
487 end = bound[1];
488 while pc >= start && pc < end do {
489 step();
490 pc = *PC;
494 defn next()
496 local sp, bound;
498 sp = *SP;
499 bound = fnbound(*PC);
500 stmnt();
501 pc = *PC;
502 if pc >= bound[0] && pc < bound[1] then
503 return {};
505 while (pc < bound[0] || pc > bound[1]) && sp >= *SP do {
506 step();
507 pc = *PC;
509 src(*PC);
512 defn maps()
514 local m, mm;
516 m = map();
517 while m != {} do {
518 mm = head m;
519 m = tail m;
520 print(mm[2]\X, " ", mm[3]\X, " ", mm[4]\X, " ", mm[0], " ", mm[1], "\n");
524 defn dump(addr, n, fmt)
526 loop 0, n do {
527 print(fmt(addr, 'X'), ": ");
528 addr = mem(addr, fmt);
532 defn mem(addr, fmt)
535 local i, c, n;
537 i = 0;
538 while fmt[i] != 0 do {
539 c = fmt[i];
540 n = 0;
541 while '0' <= fmt[i] && fmt[i] <= '9' do {
542 n = 10*n + fmt[i]-'0';
543 i = i+1;
545 if n <= 0 then n = 1;
546 addr = fmt(addr, fmt[i]);
547 while n > 0 do {
548 print(*addr++, " ");
549 n = n-1;
551 i = i+1;
553 print("\n");
554 return addr;
557 defn symbols(pattern)
559 local l, s;
561 l = symbols;
562 while l do {
563 s = head l;
564 if regexp(pattern, s[0]) then
565 print(s[0], "\t", s[1], "\t", s[2], "\t", s[3], "\n");
566 l = tail l;
570 defn havesymbol(name)
572 local l, s;
574 l = symbols;
575 while l do {
576 s = head l;
577 l = tail l;
578 if s[0] == name then
579 return 1;
581 return 0;
584 defn spsrch(len)
586 local addr, a, s, e;
588 addr = *SP;
589 s = origin & 0x7fffffff;
590 e = etext & 0x7fffffff;
591 loop 1, len do {
592 a = *addr++;
593 c = a & 0x7fffffff;
594 if c > s && c < e then {
595 print("src(", a, ")\n");
596 pfl(a);
601 defn acidtypes()
603 local syms;
604 local l;
606 l = textfile();
607 if l != {} then {
608 syms = "acidtypes";
609 while l != {} do {
610 syms = syms + " " + ((head l)[0]);
611 l = tail l;
613 includepipe(syms);
617 progargs="";
618 print(acidfile);