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, frame, pc, fn, done, 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 done = 0;97 while stk && !done do {98 frame = head stk;99 stk = tail stk;100 fn = frame[0];101 pc = frame[1];102 callerpc = frame[2];103 paramlist = frame[3];104 locallist = frame[4];106 print(stkprefix, fmt(fn, 'a'), "(");107 params(paramlist);108 print(")");109 if pc != fn then110 print("+", itoa(pc-fn, "%ux"));111 print(" ");112 pfl(pc);113 if dolocals then114 locals(locallist);115 if fn == var("threadmain") || fn == var("p9main") then116 done=1;117 if fn == var("threadstart") || fn == var("scheduler") then118 done=1;119 if callerpc == 0 then120 done=1;121 }123 if callerpc && !done then {124 print(stkprefix, fmt(callerpc, 'a'), " ");125 pfl(callerpc);126 }127 }129 defn findsrc(file)130 {131 local lst, src;133 if file[0] == '/' then {134 src = file(file);135 if src != {} then {136 srcfiles = append srcfiles, file;137 srctext = append srctext, src;138 return src;139 }140 return {};141 }143 lst = srcpath;144 while head lst do {145 src = file(head lst+file);146 if src != {} then {147 srcfiles = append srcfiles, file;148 srctext = append srctext, src;149 return src;150 }151 lst = tail lst;152 }153 }155 defn line(addr)156 {157 local src, file;159 file = pcfile(addr);160 src = match(file, srcfiles);162 if src >= 0 then163 src = srctext[src];164 else165 src = findsrc(file);167 if src == {} then {168 print("no source for ", file, "\n");169 return {};170 }171 line = pcline(addr)-1;172 print(file, ":", src[line], "\n");173 }175 defn addsrcdir(dir)176 {177 dir = dir+"/";179 if match(dir, srcpath) >= 0 then {180 print("already in srcpath\n");181 return {};182 }184 srcpath = {dir}+srcpath;185 }187 defn source()188 {189 local l;191 l = srcpath;192 while l do {193 print(head l, "\n");194 l = tail l;195 }196 l = srcfiles;198 while l do {199 print("\t", head l, "\n");200 l = tail l;201 }202 }204 defn Bsrc(addr)205 {206 local lst;208 lst = srcpath;209 file = pcfile(addr);210 if file[0] == '/' && access(file) then {211 rc("B "+file+":"+itoa(pcline(addr)));212 return {};213 }214 while head lst do {215 name = head lst+file;216 if access(name) then {217 rc("B "+name+":"+itoa(pcline(addr)));218 return {};219 }220 lst = tail lst;221 }222 print("no source for ", file, "\n");223 }225 defn srcline(addr)226 {227 local text, cline, line, file, src;228 file = pcfile(addr);229 src = match(file,srcfiles);230 if (src>=0) then231 src = srctext[src];232 else233 src = findsrc(file);234 if (src=={}) then235 {236 return "(no source)";237 }238 return src[pcline(addr)-1];239 }241 defn src(addr)242 {243 local src, file, line, cline, text;245 file = pcfile(addr);246 src = match(file, srcfiles);248 if src >= 0 then249 src = srctext[src];250 else251 src = findsrc(file);253 if src == {} then {254 print("no source for ", file, "\n");255 return {};256 }258 cline = pcline(addr)-1;259 print(file, ":", cline+1, "\n");260 line = cline-5;261 loop 0,10 do {262 if line >= 0 then {263 if line == cline then264 print(">");265 else266 print(" ");267 text = src[line];268 if text == {} then269 return {};270 print(line+1, "\t", text, "\n");271 }272 line = line+1;273 }274 }276 defn step() // single step the process277 {278 local lst, lpl, addr, bput;280 bput = 0;281 if match(*PC, bplist) >= 0 then { // Sitting on a breakpoint282 bput = fmt(*PC, bpfmt);283 *bput = @bput;284 }286 lst = follow(*PC);288 lpl = lst;289 while lpl do { // place break points290 *(head lpl) = bpinst;291 lpl = tail lpl;292 }294 startstop(pid); // do the step296 while lst do { // remove the breakpoints297 addr = fmt(head lst, bpfmt);298 *addr = @addr;299 lst = tail lst;300 }301 if bput != 0 then302 *bput = bpinst;303 }305 defn bpset(addr) // set a breakpoint306 {307 if status(pid) != "Stopped" then {308 print("Waiting...\n");309 stop(pid);310 }311 if match(addr, bplist) >= 0 then312 print("breakpoint already set at ", fmt(addr, 'a'), "\n");313 else {314 *fmt(addr, bpfmt) = bpinst;315 bplist = append bplist, addr;316 }317 }319 defn bptab() // print a table of breakpoints320 {321 local lst, addr;323 lst = bplist;324 while lst do {325 addr = head lst;326 print("\t", fmt(addr, 'X'), " ", fmt(addr, 'a'), " ", fmt(addr, 'i'), "\n");327 lst = tail lst;328 }329 }331 defn bpdel(addr) // delete a breakpoint332 {333 local n, pc, nbplist;335 n = match(addr, bplist);336 if n < 0 then {337 print("no breakpoint at ", fmt(addr, 'a'), "\n");338 return {};339 }341 addr = fmt(addr, bpfmt);342 *addr = @addr;344 nbplist = {}; // delete from list345 while bplist do {346 pc = head bplist;347 if pc != addr then348 nbplist = append nbplist, pc;349 bplist = tail bplist;350 }351 bplist = nbplist; // delete from memory352 }354 defn cont() // continue execution355 {356 local addr;358 addr = fmt(*PC, bpfmt);359 if match(addr, bplist) >= 0 then { // Sitting on a breakpoint360 *addr = @addr;361 step(); // Step over362 *addr = bpinst;363 }364 startstop(pid); // Run365 }367 defn stopped(pid) // called from acid when a process changes state368 {369 pstop(pid); // stub so this is easy to replace370 }372 defn procs() // print status of processes373 {374 local c, lst, cpid;376 cpid = pid;377 lst = proclist;378 while lst do {379 np = head lst;380 setproc(np);381 if np == cpid then382 c = '>';383 else384 c = ' ';385 print(fmt(c, 'c'), np, ": ", status(np), " at ", fmt(*PC, 'a'), " setproc(", np, ")\n");386 lst = tail lst;387 }388 pid = cpid;389 if pid != 0 then390 setproc(pid);391 }393 _asmlines = 30;395 defn asm(addr)396 {397 local bound;399 bound = fnbound(addr);401 addr = fmt(addr, 'i');402 loop 1,_asmlines do {403 print(fmt(addr, 'a'), " ", fmt(addr, 'X'));404 print("\t", @addr++, "\n");405 if bound != {} && addr > bound[1] then {406 lasmaddr = addr;407 return {};408 }409 }410 lasmaddr = addr;411 }413 defn casm()414 {415 asm(lasmaddr);416 }418 defn xasm(addr)419 {420 local bound;422 bound = fnbound(addr);424 addr = fmt(addr, 'i');425 loop 1,_asmlines do {426 print(fmt(addr, 'a'), " ", fmt(addr, 'X'));427 print("\t", *addr++, "\n");428 if bound != {} && addr > bound[1] then {429 lasmaddr = addr;430 return {};431 }432 }433 lasmaddr = addr;434 }436 defn xcasm()437 {438 xasm(lasmaddr);439 }441 defn win()442 {443 local npid, estr;445 bplist = {};446 notes = {};448 estr = "/sys/lib/acid/window '0 0 600 400' "+textfile;449 if progargs != "" then450 estr = estr+" "+progargs;452 npid = rc(estr);453 npid = atoi(npid);454 if npid == 0 then455 error("win failed to create process");457 setproc(npid);458 stopped(npid);459 }461 defn win2()462 {463 local npid, estr;465 bplist = {};466 notes = {};468 estr = "/sys/lib/acid/transcript '0 0 600 400' '100 100 700 500' "+textfile;469 if progargs != "" then470 estr = estr+" "+progargs;472 npid = rc(estr);473 npid = atoi(npid);474 if npid == 0 then475 error("win failed to create process");477 setproc(npid);478 stopped(npid);479 }481 defn new()482 {483 bplist = {};484 newproc(progargs);485 // Dont miss the delay slot calls486 bpset(follow(main)[0]);487 cont();488 bpdel(*PC);489 }491 defn stmnt() // step one statement492 {493 local line;495 line = pcline(*PC);496 while 1 do {497 step();498 if line != pcline(*PC) then {499 src(*PC);500 return {};501 }502 }503 }505 defn func() // step until we leave the current function506 {507 local bound, end, start, pc;509 bound = fnbound(*PC);510 if bound == {} then {511 print("cannot locate text symbol\n");512 return {};513 }515 pc = *PC;516 start = bound[0];517 end = bound[1];518 while pc >= start && pc < end do {519 step();520 pc = *PC;521 }522 }524 defn next()525 {526 local sp, bound;528 sp = *SP;529 bound = fnbound(*PC);530 stmnt();531 pc = *PC;532 if pc >= bound[0] && pc < bound[1] then533 return {};535 while (pc < bound[0] || pc > bound[1]) && sp >= *SP do {536 step();537 pc = *PC;538 }539 src(*PC);540 }542 defn maps()543 {544 local m, mm;546 m = map();547 while m != {} do {548 mm = head m;549 m = tail m;550 print(mm[2]\X, " ", mm[3]\X, " ", mm[4]\X, " ", mm[0], " ", mm[1], "\n");551 }552 }554 defn dump(addr, n, fmt)555 {556 loop 0, n do {557 print(fmt(addr, 'X'), ": ");558 addr = mem(addr, fmt);559 }560 }562 defn mem(addr, fmt)563 {565 local i, c, n;567 i = 0;568 while fmt[i] != 0 do {569 c = fmt[i];570 n = 0;571 while '0' <= fmt[i] && fmt[i] <= '9' do {572 n = 10*n + fmt[i]-'0';573 i = i+1;574 }575 if n <= 0 then n = 1;576 addr = fmt(addr, fmt[i]);577 while n > 0 do {578 print(*addr++, " ");579 n = n-1;580 }581 i = i+1;582 }583 print("\n");584 return addr;585 }587 defn symbols(pattern)588 {589 local l, s;591 l = symbols;592 while l do {593 s = head l;594 if regexp(pattern, s[0]) then595 print(s[0], "\t", s[1], "\t", s[2], "\t", s[3], "\n");596 l = tail l;597 }598 }600 defn havesymbol(name)601 {602 local l, s;604 l = symbols;605 while l do {606 s = head l;607 l = tail l;608 if s[0] == name then609 return 1;610 }611 return 0;612 }614 defn spsrch(len)615 {616 local addr, a, s, e;618 addr = *SP;619 s = origin & 0x7fffffff;620 e = etext & 0x7fffffff;621 loop 1, len do {622 a = *addr++;623 c = a & 0x7fffffff;624 if c > s && c < e then {625 print("src(", a, ")\n");626 pfl(a);627 }628 }629 }631 defn acidtypes()632 {633 local syms;634 local l;636 l = textfile();637 if l != {} then {638 syms = "acidtypes";639 while l != {} do {640 syms = syms + " " + ((head l)[0]);641 l = tail l;642 }643 includepipe(syms);644 }645 }647 defn getregs()648 {649 local regs, l;651 regs = {};652 l = registers;653 while l != {} do {654 regs = append regs, var(l[0]);655 l = tail l;656 }657 return regs;658 }660 defn setregs(regs)661 {662 local l;664 l = registers;665 while l != {} do {666 var(l[0]) = regs[0];667 l = tail l;668 regs = tail regs;669 }670 return regs;671 }673 defn resetregs()674 {675 local l;677 l = registers;678 while l != {} do {679 var(l[0]) = register(l[0]);680 l = tail l;681 }682 }684 defn clearregs()685 {686 local l;688 l = registers;689 while l != {} do {690 var(l[0]) = refconst(~0);691 l = tail l;692 }693 }695 progargs="";696 print(acidfile);