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(file)
68 {
69 s = stkignore;
70 while s do {
71 if regexp(head s, file) then
72 return 1;
73 s = tail s;
74 }
75 return 0;
76 }
78 // print a stack trace
79 //
80 // in a run of leading frames in files matched by regexps in stkignore,
81 // only print the last one.
82 defn _stk(regs, dolocals)
83 {
84 local stk, pc, fn, callerpc, paramlist, locallist;
86 stk = strace(regs);
87 if stkignore then {
88 while stk && tail stk && _stkign((head tail stk)[1]) do
89 stk = tail stk;
90 }
92 callerpc = 0;
93 while stk do {
94 frame = head stk;
95 stk = tail stk;
96 fn = frame[0];
97 pc = frame[1];
98 callerpc = frame[2];
99 paramlist = frame[3];
100 locallist = frame[4];
102 print(stkprefix, fmt(fn, 'a'), "(");
103 params(paramlist);
104 print(")");
105 if pc != fn then
106 print("+", itoa(pc-fn, "%ux"));
107 print(" ");
108 pfl(pc);
109 if dolocals then
110 locals(locallist);
113 if callerpc then {
114 print(stkprefix, fmt(callerpc, 'a'), " ");
115 pfl(callerpc);
119 defn findsrc(file)
121 local lst, src;
123 if file[0] == '/' then {
124 src = file(file);
125 if src != {} then {
126 srcfiles = append srcfiles, file;
127 srctext = append srctext, src;
128 return src;
130 return {};
133 lst = srcpath;
134 while head lst do {
135 src = file(head lst+file);
136 if src != {} then {
137 srcfiles = append srcfiles, file;
138 srctext = append srctext, src;
139 return src;
141 lst = tail lst;
145 defn line(addr)
147 local src, file;
149 file = pcfile(addr);
150 src = match(file, srcfiles);
152 if src >= 0 then
153 src = srctext[src];
154 else
155 src = findsrc(file);
157 if src == {} then {
158 print("no source for ", file, "\n");
159 return {};
161 line = pcline(addr)-1;
162 print(file, ":", src[line], "\n");
165 defn addsrcdir(dir)
167 dir = dir+"/";
169 if match(dir, srcpath) >= 0 then {
170 print("already in srcpath\n");
171 return {};
174 srcpath = {dir}+srcpath;
177 defn source()
179 local l;
181 l = srcpath;
182 while l do {
183 print(head l, "\n");
184 l = tail l;
186 l = srcfiles;
188 while l do {
189 print("\t", head l, "\n");
190 l = tail l;
194 defn Bsrc(addr)
196 local lst;
198 lst = srcpath;
199 file = pcfile(addr);
200 if file[0] == '/' && access(file) then {
201 rc("B "+file+":"+itoa(pcline(addr)));
202 return {};
204 while head lst do {
205 name = head lst+file;
206 if access(name) then {
207 rc("B "+name+":"+itoa(pcline(addr)));
208 return {};
210 lst = tail lst;
212 print("no source for ", file, "\n");
215 defn srcline(addr)
217 local text, cline, line, file, src;
218 file = pcfile(addr);
219 src = match(file,srcfiles);
220 if (src>=0) then
221 src = srctext[src];
222 else
223 src = findsrc(file);
224 if (src=={}) then
226 return "(no source)";
228 return src[pcline(addr)-1];
231 defn src(addr)
233 local src, file, line, cline, text;
235 file = pcfile(addr);
236 src = match(file, srcfiles);
238 if src >= 0 then
239 src = srctext[src];
240 else
241 src = findsrc(file);
243 if src == {} then {
244 print("no source for ", file, "\n");
245 return {};
248 cline = pcline(addr)-1;
249 print(file, ":", cline+1, "\n");
250 line = cline-5;
251 loop 0,10 do {
252 if line >= 0 then {
253 if line == cline then
254 print(">");
255 else
256 print(" ");
257 text = src[line];
258 if text == {} then
259 return {};
260 print(line+1, "\t", text, "\n");
262 line = line+1;
266 defn step() // single step the process
268 local lst, lpl, addr, bput;
270 bput = 0;
271 if match(*PC, bplist) >= 0 then { // Sitting on a breakpoint
272 bput = fmt(*PC, bpfmt);
273 *bput = @bput;
276 lst = follow(*PC);
278 lpl = lst;
279 while lpl do { // place break points
280 *(head lpl) = bpinst;
281 lpl = tail lpl;
284 startstop(pid); // do the step
286 while lst do { // remove the breakpoints
287 addr = fmt(head lst, bpfmt);
288 *addr = @addr;
289 lst = tail lst;
291 if bput != 0 then
292 *bput = bpinst;
295 defn bpset(addr) // set a breakpoint
297 if status(pid) != "Stopped" then {
298 print("Waiting...\n");
299 stop(pid);
301 if match(addr, bplist) >= 0 then
302 print("breakpoint already set at ", fmt(addr, 'a'), "\n");
303 else {
304 *fmt(addr, bpfmt) = bpinst;
305 bplist = append bplist, addr;
309 defn bptab() // print a table of breakpoints
311 local lst, addr;
313 lst = bplist;
314 while lst do {
315 addr = head lst;
316 print("\t", fmt(addr, 'X'), " ", fmt(addr, 'a'), " ", fmt(addr, 'i'), "\n");
317 lst = tail lst;
321 defn bpdel(addr) // delete a breakpoint
323 local n, pc, nbplist;
325 n = match(addr, bplist);
326 if n < 0 then {
327 print("no breakpoint at ", fmt(addr, 'a'), "\n");
328 return {};
331 addr = fmt(addr, bpfmt);
332 *addr = @addr;
334 nbplist = {}; // delete from list
335 while bplist do {
336 pc = head bplist;
337 if pc != addr then
338 nbplist = append nbplist, pc;
339 bplist = tail bplist;
341 bplist = nbplist; // delete from memory
344 defn cont() // continue execution
346 local addr;
348 addr = fmt(*PC, bpfmt);
349 if match(addr, bplist) >= 0 then { // Sitting on a breakpoint
350 *addr = @addr;
351 step(); // Step over
352 *addr = bpinst;
354 startstop(pid); // Run
357 defn stopped(pid) // called from acid when a process changes state
359 pstop(pid); // stub so this is easy to replace
362 defn procs() // print status of processes
364 local c, lst, cpid;
366 cpid = pid;
367 lst = proclist;
368 while lst do {
369 np = head lst;
370 setproc(np);
371 if np == cpid then
372 c = '>';
373 else
374 c = ' ';
375 print(fmt(c, 'c'), np, ": ", status(np), " at ", fmt(*PC, 'a'), " setproc(", np, ")\n");
376 lst = tail lst;
378 pid = cpid;
379 if pid != 0 then
380 setproc(pid);
383 _asmlines = 30;
385 defn asm(addr)
387 local bound;
389 bound = fnbound(addr);
391 addr = fmt(addr, 'i');
392 loop 1,_asmlines do {
393 print(fmt(addr, 'a'), " ", fmt(addr, 'X'));
394 print("\t", @addr++, "\n");
395 if bound != {} && addr > bound[1] then {
396 lasmaddr = addr;
397 return {};
400 lasmaddr = addr;
403 defn casm()
405 asm(lasmaddr);
408 defn win()
410 local npid, estr;
412 bplist = {};
413 notes = {};
415 estr = "/sys/lib/acid/window '0 0 600 400' "+textfile;
416 if progargs != "" then
417 estr = estr+" "+progargs;
419 npid = rc(estr);
420 npid = atoi(npid);
421 if npid == 0 then
422 error("win failed to create process");
424 setproc(npid);
425 stopped(npid);
428 defn win2()
430 local npid, estr;
432 bplist = {};
433 notes = {};
435 estr = "/sys/lib/acid/transcript '0 0 600 400' '100 100 700 500' "+textfile;
436 if progargs != "" then
437 estr = estr+" "+progargs;
439 npid = rc(estr);
440 npid = atoi(npid);
441 if npid == 0 then
442 error("win failed to create process");
444 setproc(npid);
445 stopped(npid);
448 defn new()
450 bplist = {};
451 newproc(progargs);
452 // Dont miss the delay slot calls
453 bpset(follow(main)[0]);
454 cont();
455 bpdel(*PC);
458 defn stmnt() // step one statement
460 local line;
462 line = pcline(*PC);
463 while 1 do {
464 step();
465 if line != pcline(*PC) then {
466 src(*PC);
467 return {};
472 defn func() // step until we leave the current function
474 local bound, end, start, pc;
476 bound = fnbound(*PC);
477 if bound == {} then {
478 print("cannot locate text symbol\n");
479 return {};
482 pc = *PC;
483 start = bound[0];
484 end = bound[1];
485 while pc >= start && pc < end do {
486 step();
487 pc = *PC;
491 defn next()
493 local sp, bound;
495 sp = *SP;
496 bound = fnbound(*PC);
497 stmnt();
498 pc = *PC;
499 if pc >= bound[0] && pc < bound[1] then
500 return {};
502 while (pc < bound[0] || pc > bound[1]) && sp >= *SP do {
503 step();
504 pc = *PC;
506 src(*PC);
509 defn maps()
511 local m, mm;
513 m = map();
514 while m != {} do {
515 mm = head m;
516 m = tail m;
517 print(mm[2]\X, " ", mm[3]\X, " ", mm[4]\X, " ", mm[0], " ", mm[1], "\n");
521 defn dump(addr, n, fmt)
523 loop 0, n do {
524 print(fmt(addr, 'X'), ": ");
525 addr = mem(addr, fmt);
529 defn mem(addr, fmt)
532 local i, c, n;
534 i = 0;
535 while fmt[i] != 0 do {
536 c = fmt[i];
537 n = 0;
538 while '0' <= fmt[i] && fmt[i] <= '9' do {
539 n = 10*n + fmt[i]-'0';
540 i = i+1;
542 if n <= 0 then n = 1;
543 addr = fmt(addr, fmt[i]);
544 while n > 0 do {
545 print(*addr++, " ");
546 n = n-1;
548 i = i+1;
550 print("\n");
551 return addr;
554 defn symbols(pattern)
556 local l, s;
558 l = symbols;
559 while l do {
560 s = head l;
561 if regexp(pattern, s[0]) then
562 print(s[0], "\t", s[1], "\t", s[2], "\t", s[3], "\n");
563 l = tail l;
567 defn havesymbol(name)
569 local l, s;
571 l = symbols;
572 while l do {
573 s = head l;
574 l = tail l;
575 if s[0] == name then
576 return 1;
578 return 0;
581 defn spsrch(len)
583 local addr, a, s, e;
585 addr = *SP;
586 s = origin & 0x7fffffff;
587 e = etext & 0x7fffffff;
588 loop 1, len do {
589 a = *addr++;
590 c = a & 0x7fffffff;
591 if c > s && c < e then {
592 print("src(", a, ")\n");
593 pfl(a);
598 progargs="";
599 print(acidfile);