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 xasm(addr)412 {413 local bound;415 bound = fnbound(addr);417 addr = fmt(addr, 'i');418 loop 1,_asmlines do {419 print(fmt(addr, 'a'), " ", fmt(addr, 'X'));420 print("\t", *addr++, "\n");421 if bound != {} && addr > bound[1] then {422 lasmaddr = addr;423 return {};424 }425 }426 lasmaddr = addr;427 }429 defn xcasm()430 {431 xasm(lasmaddr);432 }434 defn win()435 {436 local npid, estr;438 bplist = {};439 notes = {};441 estr = "/sys/lib/acid/window '0 0 600 400' "+textfile;442 if progargs != "" then443 estr = estr+" "+progargs;445 npid = rc(estr);446 npid = atoi(npid);447 if npid == 0 then448 error("win failed to create process");450 setproc(npid);451 stopped(npid);452 }454 defn win2()455 {456 local npid, estr;458 bplist = {};459 notes = {};461 estr = "/sys/lib/acid/transcript '0 0 600 400' '100 100 700 500' "+textfile;462 if progargs != "" then463 estr = estr+" "+progargs;465 npid = rc(estr);466 npid = atoi(npid);467 if npid == 0 then468 error("win failed to create process");470 setproc(npid);471 stopped(npid);472 }474 defn new()475 {476 bplist = {};477 newproc(progargs);478 // Dont miss the delay slot calls479 bpset(follow(main)[0]);480 cont();481 bpdel(*PC);482 }484 defn stmnt() // step one statement485 {486 local line;488 line = pcline(*PC);489 while 1 do {490 step();491 if line != pcline(*PC) then {492 src(*PC);493 return {};494 }495 }496 }498 defn func() // step until we leave the current function499 {500 local bound, end, start, pc;502 bound = fnbound(*PC);503 if bound == {} then {504 print("cannot locate text symbol\n");505 return {};506 }508 pc = *PC;509 start = bound[0];510 end = bound[1];511 while pc >= start && pc < end do {512 step();513 pc = *PC;514 }515 }517 defn next()518 {519 local sp, bound;521 sp = *SP;522 bound = fnbound(*PC);523 stmnt();524 pc = *PC;525 if pc >= bound[0] && pc < bound[1] then526 return {};528 while (pc < bound[0] || pc > bound[1]) && sp >= *SP do {529 step();530 pc = *PC;531 }532 src(*PC);533 }535 defn maps()536 {537 local m, mm;539 m = map();540 while m != {} do {541 mm = head m;542 m = tail m;543 print(mm[2]\X, " ", mm[3]\X, " ", mm[4]\X, " ", mm[0], " ", mm[1], "\n");544 }545 }547 defn dump(addr, n, fmt)548 {549 loop 0, n do {550 print(fmt(addr, 'X'), ": ");551 addr = mem(addr, fmt);552 }553 }555 defn mem(addr, fmt)556 {558 local i, c, n;560 i = 0;561 while fmt[i] != 0 do {562 c = fmt[i];563 n = 0;564 while '0' <= fmt[i] && fmt[i] <= '9' do {565 n = 10*n + fmt[i]-'0';566 i = i+1;567 }568 if n <= 0 then n = 1;569 addr = fmt(addr, fmt[i]);570 while n > 0 do {571 print(*addr++, " ");572 n = n-1;573 }574 i = i+1;575 }576 print("\n");577 return addr;578 }580 defn symbols(pattern)581 {582 local l, s;584 l = symbols;585 while l do {586 s = head l;587 if regexp(pattern, s[0]) then588 print(s[0], "\t", s[1], "\t", s[2], "\t", s[3], "\n");589 l = tail l;590 }591 }593 defn havesymbol(name)594 {595 local l, s;597 l = symbols;598 while l do {599 s = head l;600 l = tail l;601 if s[0] == name then602 return 1;603 }604 return 0;605 }607 defn spsrch(len)608 {609 local addr, a, s, e;611 addr = *SP;612 s = origin & 0x7fffffff;613 e = etext & 0x7fffffff;614 loop 1, len do {615 a = *addr++;616 c = a & 0x7fffffff;617 if c > s && c < e then {618 print("src(", a, ")\n");619 pfl(a);620 }621 }622 }624 defn acidtypes()625 {626 local syms;627 local l;629 l = textfile();630 if l != {} then {631 syms = "acidtypes";632 while l != {} do {633 syms = syms + " " + ((head l)[0]);634 l = tail l;635 }636 includepipe(syms);637 }638 }640 defn getregs()641 {642 local regs, l;644 regs = {};645 l = registers;646 while l != {} do {647 regs = append regs, var(l[0]);648 l = tail l;649 }650 return regs;651 }653 defn setregs(regs)654 {655 local l;657 l = registers;658 while l != {} do {659 var(l[0]) = regs[0];660 l = tail l;661 regs = tail regs;662 }663 return regs;664 }666 defn resetregs()667 {668 local l;670 l = registers;671 while l != {} do {672 var(l[0]) = register(l[0]);673 l = tail l;674 }675 }677 defn clearregs()678 {679 local l;681 l = registers;682 while l != {} do {683 var(l[0]) = refconst(~0);684 l = tail l;685 }686 }688 progargs="";689 print(acidfile);