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 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 then43 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) then70 return 1;71 s = tail s;72 }73 return 0;74 }76 // print a stack trace77 //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) do87 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 then105 print("+", itoa(pc-fn, "%ux"));106 print(" ");107 pfl(pc);108 if dolocals then109 locals(locallist);110 if fn == var("threadmain") || fn == var("p9main") then111 done=1;112 if fn == var("threadstart") || fn == var("scheduler") then113 done=1;114 if callerpc == 0 then115 done=1;116 }117 if callerpc && !done then {118 print(stkprefix, fmt(callerpc, 'a'), " ");119 pfl(callerpc);120 }121 }123 defn findsrc(file)124 {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;133 }134 return {};135 }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;144 }145 lst = tail lst;146 }147 }149 defn line(addr)150 {151 local src, file;153 file = pcfile(addr);154 src = match(file, srcfiles);156 if src >= 0 then157 src = srctext[src];158 else159 src = findsrc(file);161 if src == {} then {162 print("no source for ", file, "\n");163 return {};164 }165 line = pcline(addr)-1;166 print(file, ":", src[line], "\n");167 }169 defn addsrcdir(dir)170 {171 dir = dir+"/";173 if match(dir, srcpath) >= 0 then {174 print("already in srcpath\n");175 return {};176 }178 srcpath = {dir}+srcpath;179 }181 defn source()182 {183 local l;185 l = srcpath;186 while l do {187 print(head l, "\n");188 l = tail l;189 }190 l = srcfiles;192 while l do {193 print("\t", head l, "\n");194 l = tail l;195 }196 }198 defn Bsrc(addr)199 {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 {};207 }208 while head lst do {209 name = head lst+file;210 if access(name) then {211 rc("B "+name+":"+itoa(pcline(addr)));212 return {};213 }214 lst = tail lst;215 }216 print("no source for ", file, "\n");217 }219 defn srcline(addr)220 {221 local text, cline, line, file, src;222 file = pcfile(addr);223 src = match(file,srcfiles);224 if (src>=0) then225 src = srctext[src];226 else227 src = findsrc(file);228 if (src=={}) then229 {230 return "(no source)";231 }232 return src[pcline(addr)-1];233 }235 defn src(addr)236 {237 local src, file, line, cline, text;239 file = pcfile(addr);240 src = match(file, srcfiles);242 if src >= 0 then243 src = srctext[src];244 else245 src = findsrc(file);247 if src == {} then {248 print("no source for ", file, "\n");249 return {};250 }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 then258 print(">");259 else260 print(" ");261 text = src[line];262 if text == {} then263 return {};264 print(line+1, "\t", text, "\n");265 }266 line = line+1;267 }268 }270 defn step() // single step the process271 {272 local lst, lpl, addr, bput;274 bput = 0;275 if match(*PC, bplist) >= 0 then { // Sitting on a breakpoint276 bput = fmt(*PC, bpfmt);277 *bput = @bput;278 }280 lst = follow(*PC);282 lpl = lst;283 while lpl do { // place break points284 *(head lpl) = bpinst;285 lpl = tail lpl;286 }288 startstop(pid); // do the step290 while lst do { // remove the breakpoints291 addr = fmt(head lst, bpfmt);292 *addr = @addr;293 lst = tail lst;294 }295 if bput != 0 then296 *bput = bpinst;297 }299 defn bpset(addr) // set a breakpoint300 {301 if status(pid) != "Stopped" then {302 print("Waiting...\n");303 stop(pid);304 }305 if match(addr, bplist) >= 0 then306 print("breakpoint already set at ", fmt(addr, 'a'), "\n");307 else {308 *fmt(addr, bpfmt) = bpinst;309 bplist = append bplist, addr;310 }311 }313 defn bptab() // print a table of breakpoints314 {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;322 }323 }325 defn bpdel(addr) // delete a breakpoint326 {327 local n, pc, nbplist;329 n = match(addr, bplist);330 if n < 0 then {331 print("no breakpoint at ", fmt(addr, 'a'), "\n");332 return {};333 }335 addr = fmt(addr, bpfmt);336 *addr = @addr;338 nbplist = {}; // delete from list339 while bplist do {340 pc = head bplist;341 if pc != addr then342 nbplist = append nbplist, pc;343 bplist = tail bplist;344 }345 bplist = nbplist; // delete from memory346 }348 defn cont() // continue execution349 {350 local addr;352 addr = fmt(*PC, bpfmt);353 if match(addr, bplist) >= 0 then { // Sitting on a breakpoint354 *addr = @addr;355 step(); // Step over356 *addr = bpinst;357 }358 startstop(pid); // Run359 }361 defn stopped(pid) // called from acid when a process changes state362 {363 pstop(pid); // stub so this is easy to replace364 }366 defn procs() // print status of processes367 {368 local c, lst, cpid;370 cpid = pid;371 lst = proclist;372 while lst do {373 np = head lst;374 setproc(np);375 if np == cpid then376 c = '>';377 else378 c = ' ';379 print(fmt(c, 'c'), np, ": ", status(np), " at ", fmt(*PC, 'a'), " setproc(", np, ")\n");380 lst = tail lst;381 }382 pid = cpid;383 if pid != 0 then384 setproc(pid);385 }387 _asmlines = 30;389 defn asm(addr)390 {391 local bound;393 bound = fnbound(addr);395 addr = fmt(addr, 'i');396 loop 1,_asmlines do {397 print(fmt(addr, 'a'), " ", fmt(addr, 'X'));398 print("\t", @addr++, "\n");399 if bound != {} && addr > bound[1] then {400 lasmaddr = addr;401 return {};402 }403 }404 lasmaddr = addr;405 }407 defn casm()408 {409 asm(lasmaddr);410 }412 defn xasm(addr)413 {414 local bound;416 bound = fnbound(addr);418 addr = fmt(addr, 'i');419 loop 1,_asmlines do {420 print(fmt(addr, 'a'), " ", fmt(addr, 'X'));421 print("\t", *addr++, "\n");422 if bound != {} && addr > bound[1] then {423 lasmaddr = addr;424 return {};425 }426 }427 lasmaddr = addr;428 }430 defn xcasm()431 {432 xasm(lasmaddr);433 }435 defn win()436 {437 local npid, estr;439 bplist = {};440 notes = {};442 estr = "/sys/lib/acid/window '0 0 600 400' "+textfile;443 if progargs != "" then444 estr = estr+" "+progargs;446 npid = rc(estr);447 npid = atoi(npid);448 if npid == 0 then449 error("win failed to create process");451 setproc(npid);452 stopped(npid);453 }455 defn win2()456 {457 local npid, estr;459 bplist = {};460 notes = {};462 estr = "/sys/lib/acid/transcript '0 0 600 400' '100 100 700 500' "+textfile;463 if progargs != "" then464 estr = estr+" "+progargs;466 npid = rc(estr);467 npid = atoi(npid);468 if npid == 0 then469 error("win failed to create process");471 setproc(npid);472 stopped(npid);473 }475 defn new()476 {477 bplist = {};478 newproc(progargs);479 // Dont miss the delay slot calls480 bpset(follow(main)[0]);481 cont();482 bpdel(*PC);483 }485 defn stmnt() // step one statement486 {487 local line;489 line = pcline(*PC);490 while 1 do {491 step();492 if line != pcline(*PC) then {493 src(*PC);494 return {};495 }496 }497 }499 defn func() // step until we leave the current function500 {501 local bound, end, start, pc;503 bound = fnbound(*PC);504 if bound == {} then {505 print("cannot locate text symbol\n");506 return {};507 }509 pc = *PC;510 start = bound[0];511 end = bound[1];512 while pc >= start && pc < end do {513 step();514 pc = *PC;515 }516 }518 defn next()519 {520 local sp, bound;522 sp = *SP;523 bound = fnbound(*PC);524 stmnt();525 pc = *PC;526 if pc >= bound[0] && pc < bound[1] then527 return {};529 while (pc < bound[0] || pc > bound[1]) && sp >= *SP do {530 step();531 pc = *PC;532 }533 src(*PC);534 }536 defn maps()537 {538 local m, mm;540 m = map();541 while m != {} do {542 mm = head m;543 m = tail m;544 print(mm[2]\X, " ", mm[3]\X, " ", mm[4]\X, " ", mm[0], " ", mm[1], "\n");545 }546 }548 defn dump(addr, n, fmt)549 {550 loop 0, n do {551 print(fmt(addr, 'X'), ": ");552 addr = mem(addr, fmt);553 }554 }556 defn mem(addr, fmt)557 {559 local i, c, n;561 i = 0;562 while fmt[i] != 0 do {563 c = fmt[i];564 n = 0;565 while '0' <= fmt[i] && fmt[i] <= '9' do {566 n = 10*n + fmt[i]-'0';567 i = i+1;568 }569 if n <= 0 then n = 1;570 addr = fmt(addr, fmt[i]);571 while n > 0 do {572 print(*addr++, " ");573 n = n-1;574 }575 i = i+1;576 }577 print("\n");578 return addr;579 }581 defn symbols(pattern)582 {583 local l, s;585 l = symbols;586 while l do {587 s = head l;588 if regexp(pattern, s[0]) then589 print(s[0], "\t", s[1], "\t", s[2], "\t", s[3], "\n");590 l = tail l;591 }592 }594 defn havesymbol(name)595 {596 local l, s;598 l = symbols;599 while l do {600 s = head l;601 l = tail l;602 if s[0] == name then603 return 1;604 }605 return 0;606 }608 defn spsrch(len)609 {610 local addr, a, s, e;612 addr = *SP;613 s = origin & 0x7fffffff;614 e = etext & 0x7fffffff;615 loop 1, len do {616 a = *addr++;617 c = a & 0x7fffffff;618 if c > s && c < e then {619 print("src(", a, ")\n");620 pfl(a);621 }622 }623 }625 defn acidtypes()626 {627 local syms;628 local l;630 l = textfile();631 if l != {} then {632 syms = "acidtypes";633 while l != {} do {634 syms = syms + " " + ((head l)[0]);635 l = tail l;636 }637 includepipe(syms);638 }639 }641 defn getregs()642 {643 local regs, l;645 regs = {};646 l = registers;647 while l != {} do {648 regs = append regs, var(l[0]);649 l = tail l;650 }651 return regs;652 }654 defn setregs(regs)655 {656 local l;658 l = registers;659 while l != {} do {660 var(l[0]) = regs[0];661 l = tail l;662 regs = tail regs;663 }664 return regs;665 }667 defn resetregs()668 {669 local l;671 l = registers;672 while l != {} do {673 var(l[0]) = register(l[0]);674 l = tail l;675 }676 }678 defn clearregs()679 {680 local l;682 l = registers;683 while l != {} do {684 var(l[0]) = refconst(~0);685 l = tail l;686 }687 }689 progargs="";690 print(acidfile);