Blob
1 // portable acid for all architectures3 defn pfl(addr)4 {5 print(pcfile(addr), ":", pcline(addr), "\n");6 }8 defn9 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 defn23 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 label37 // {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 then48 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) then75 return 1;76 s = tail s;77 }78 return 0;79 }81 // print a stack trace82 //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) do92 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 then109 print("+", itoa(pc-fn, "%ux"));110 print(" ");111 pfl(pc);112 if dolocals then113 locals(locallist);114 }116 if callerpc then {117 print(stkprefix, fmt(callerpc, 'a'), " ");118 pfl(callerpc);119 }120 }122 defn findsrc(file)123 {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;132 }133 return {};134 }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;143 }144 lst = tail lst;145 }146 }148 defn line(addr)149 {150 local src, file;152 file = pcfile(addr);153 src = match(file, srcfiles);155 if src >= 0 then156 src = srctext[src];157 else158 src = findsrc(file);160 if src == {} then {161 print("no source for ", file, "\n");162 return {};163 }164 line = pcline(addr)-1;165 print(file, ":", src[line], "\n");166 }168 defn addsrcdir(dir)169 {170 dir = dir+"/";172 if match(dir, srcpath) >= 0 then {173 print("already in srcpath\n");174 return {};175 }177 srcpath = {dir}+srcpath;178 }180 defn source()181 {182 local l;184 l = srcpath;185 while l do {186 print(head l, "\n");187 l = tail l;188 }189 l = srcfiles;191 while l do {192 print("\t", head l, "\n");193 l = tail l;194 }195 }197 defn Bsrc(addr)198 {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 {};206 }207 while head lst do {208 name = head lst+file;209 if access(name) then {210 rc("B "+name+":"+itoa(pcline(addr)));211 return {};212 }213 lst = tail lst;214 }215 print("no source for ", file, "\n");216 }218 defn srcline(addr)219 {220 local text, cline, line, file, src;221 file = pcfile(addr);222 src = match(file,srcfiles);223 if (src>=0) then224 src = srctext[src];225 else226 src = findsrc(file);227 if (src=={}) then228 {229 return "(no source)";230 }231 return src[pcline(addr)-1];232 }234 defn src(addr)235 {236 local src, file, line, cline, text;238 file = pcfile(addr);239 src = match(file, srcfiles);241 if src >= 0 then242 src = srctext[src];243 else244 src = findsrc(file);246 if src == {} then {247 print("no source for ", file, "\n");248 return {};249 }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 then257 print(">");258 else259 print(" ");260 text = src[line];261 if text == {} then262 return {};263 print(line+1, "\t", text, "\n");264 }265 line = line+1;266 }267 }269 defn step() // single step the process270 {271 local lst, lpl, addr, bput;273 bput = 0;274 if match(*PC, bplist) >= 0 then { // Sitting on a breakpoint275 bput = fmt(*PC, bpfmt);276 *bput = @bput;277 }279 lst = follow(*PC);281 lpl = lst;282 while lpl do { // place break points283 *(head lpl) = bpinst;284 lpl = tail lpl;285 }287 startstop(pid); // do the step289 while lst do { // remove the breakpoints290 addr = fmt(head lst, bpfmt);291 *addr = @addr;292 lst = tail lst;293 }294 if bput != 0 then295 *bput = bpinst;296 }298 defn bpset(addr) // set a breakpoint299 {300 if status(pid) != "Stopped" then {301 print("Waiting...\n");302 stop(pid);303 }304 if match(addr, bplist) >= 0 then305 print("breakpoint already set at ", fmt(addr, 'a'), "\n");306 else {307 *fmt(addr, bpfmt) = bpinst;308 bplist = append bplist, addr;309 }310 }312 defn bptab() // print a table of breakpoints313 {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;321 }322 }324 defn bpdel(addr) // delete a breakpoint325 {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 {};332 }334 addr = fmt(addr, bpfmt);335 *addr = @addr;337 nbplist = {}; // delete from list338 while bplist do {339 pc = head bplist;340 if pc != addr then341 nbplist = append nbplist, pc;342 bplist = tail bplist;343 }344 bplist = nbplist; // delete from memory345 }347 defn cont() // continue execution348 {349 local addr;351 addr = fmt(*PC, bpfmt);352 if match(addr, bplist) >= 0 then { // Sitting on a breakpoint353 *addr = @addr;354 step(); // Step over355 *addr = bpinst;356 }357 startstop(pid); // Run358 }360 defn stopped(pid) // called from acid when a process changes state361 {362 pstop(pid); // stub so this is easy to replace363 }365 defn procs() // print status of processes366 {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 then375 c = '>';376 else377 c = ' ';378 print(fmt(c, 'c'), np, ": ", status(np), " at ", fmt(*PC, 'a'), " setproc(", np, ")\n");379 lst = tail lst;380 }381 pid = cpid;382 if pid != 0 then383 setproc(pid);384 }386 _asmlines = 30;388 defn asm(addr)389 {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 {};401 }402 }403 lasmaddr = addr;404 }406 defn casm()407 {408 asm(lasmaddr);409 }411 defn win()412 {413 local npid, estr;415 bplist = {};416 notes = {};418 estr = "/sys/lib/acid/window '0 0 600 400' "+textfile;419 if progargs != "" then420 estr = estr+" "+progargs;422 npid = rc(estr);423 npid = atoi(npid);424 if npid == 0 then425 error("win failed to create process");427 setproc(npid);428 stopped(npid);429 }431 defn win2()432 {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 != "" then440 estr = estr+" "+progargs;442 npid = rc(estr);443 npid = atoi(npid);444 if npid == 0 then445 error("win failed to create process");447 setproc(npid);448 stopped(npid);449 }451 defn new()452 {453 bplist = {};454 newproc(progargs);455 // Dont miss the delay slot calls456 bpset(follow(main)[0]);457 cont();458 bpdel(*PC);459 }461 defn stmnt() // step one statement462 {463 local line;465 line = pcline(*PC);466 while 1 do {467 step();468 if line != pcline(*PC) then {469 src(*PC);470 return {};471 }472 }473 }475 defn func() // step until we leave the current function476 {477 local bound, end, start, pc;479 bound = fnbound(*PC);480 if bound == {} then {481 print("cannot locate text symbol\n");482 return {};483 }485 pc = *PC;486 start = bound[0];487 end = bound[1];488 while pc >= start && pc < end do {489 step();490 pc = *PC;491 }492 }494 defn next()495 {496 local sp, bound;498 sp = *SP;499 bound = fnbound(*PC);500 stmnt();501 pc = *PC;502 if pc >= bound[0] && pc < bound[1] then503 return {};505 while (pc < bound[0] || pc > bound[1]) && sp >= *SP do {506 step();507 pc = *PC;508 }509 src(*PC);510 }512 defn maps()513 {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");521 }522 }524 defn dump(addr, n, fmt)525 {526 loop 0, n do {527 print(fmt(addr, 'X'), ": ");528 addr = mem(addr, fmt);529 }530 }532 defn mem(addr, fmt)533 {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;544 }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;550 }551 i = i+1;552 }553 print("\n");554 return addr;555 }557 defn symbols(pattern)558 {559 local l, s;561 l = symbols;562 while l do {563 s = head l;564 if regexp(pattern, s[0]) then565 print(s[0], "\t", s[1], "\t", s[2], "\t", s[3], "\n");566 l = tail l;567 }568 }570 defn havesymbol(name)571 {572 local l, s;574 l = symbols;575 while l do {576 s = head l;577 l = tail l;578 if s[0] == name then579 return 1;580 }581 return 0;582 }584 defn spsrch(len)585 {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);597 }598 }599 }601 defn acidtypes()602 {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;612 }613 includepipe(syms);614 }615 }617 progargs="";618 print(acidfile);