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 if addr == 0 then {330 while bplist do {331 pc = head bplist;332 pc = fmt(pc, bpfmt);333 *pc = @pc;334 bplist = tail bplist;335 }336 return {};337 }339 n = match(addr, bplist);340 if n < 0 then {341 print("no breakpoint at ", fmt(addr, 'a'), "\n");342 return {};343 }345 addr = fmt(addr, bpfmt);346 *addr = @addr;348 nbplist = {}; // delete from list349 while bplist do {350 pc = head bplist;351 if pc != addr then352 nbplist = append nbplist, pc;353 bplist = tail bplist;354 }355 bplist = nbplist; // delete from memory356 }358 defn cont() // continue execution359 {360 local addr;362 addr = fmt(*PC, bpfmt);363 if match(addr, bplist) >= 0 then { // Sitting on a breakpoint364 *addr = @addr;365 step(); // Step over366 *addr = bpinst;367 }368 startstop(pid); // Run369 }371 defn stopped(pid) // called from acid when a process changes state372 {373 pfixstop(pid);374 pstop(pid); // stub so this is easy to replace375 }377 defn procs() // print status of processes378 {379 local c, lst, cpid;381 cpid = pid;382 lst = proclist;383 while lst do {384 np = head lst;385 setproc(np);386 if np == cpid then387 c = '>';388 else389 c = ' ';390 print(fmt(c, 'c'), np, ": ", status(np), " at ", fmt(*PC, 'a'), " setproc(", np, ")\n");391 lst = tail lst;392 }393 pid = cpid;394 if pid != 0 then395 setproc(pid);396 }398 _asmlines = 30;400 defn asm(addr)401 {402 local bound;404 bound = fnbound(addr);406 addr = fmt(addr, 'i');407 loop 1,_asmlines do {408 print(fmt(addr, 'a'), " ", fmt(addr, 'X'));409 print("\t", @addr++, "\n");410 if bound != {} && addr > bound[1] then {411 lasmaddr = addr;412 return {};413 }414 }415 lasmaddr = addr;416 }418 defn casm()419 {420 asm(lasmaddr);421 }423 defn xasm(addr)424 {425 local bound;427 bound = fnbound(addr);429 addr = fmt(addr, 'i');430 loop 1,_asmlines do {431 print(fmt(addr, 'a'), " ", fmt(addr, 'X'));432 print("\t", *addr++, "\n");433 if bound != {} && addr > bound[1] then {434 lasmaddr = addr;435 return {};436 }437 }438 lasmaddr = addr;439 }441 defn xcasm()442 {443 xasm(lasmaddr);444 }446 defn win()447 {448 local npid, estr;450 bplist = {};451 notes = {};453 estr = "/sys/lib/acid/window '0 0 600 400' "+textfile;454 if progargs != "" then455 estr = estr+" "+progargs;457 npid = rc(estr);458 npid = atoi(npid);459 if npid == 0 then460 error("win failed to create process");462 setproc(npid);463 stopped(npid);464 }466 defn win2()467 {468 local npid, estr;470 bplist = {};471 notes = {};473 estr = "/sys/lib/acid/transcript '0 0 600 400' '100 100 700 500' "+textfile;474 if progargs != "" then475 estr = estr+" "+progargs;477 npid = rc(estr);478 npid = atoi(npid);479 if npid == 0 then480 error("win failed to create process");482 setproc(npid);483 stopped(npid);484 }486 printstopped = 1;487 defn new()488 {489 local a;491 bplist = {};492 newproc(progargs);493 a = var("p9main");494 if a == {} then495 a = var("main");496 if a == {} then497 return {};498 bpset(a);499 while *PC != a do500 cont();501 bpdel(a);502 }504 defn stmnt() // step one statement505 {506 local line;508 line = pcline(*PC);509 while 1 do {510 step();511 if line != pcline(*PC) then {512 src(*PC);513 return {};514 }515 }516 }518 defn func() // step until we leave the current function519 {520 local bound, end, start, pc;522 bound = fnbound(*PC);523 if bound == {} then {524 print("cannot locate text symbol\n");525 return {};526 }528 pc = *PC;529 start = bound[0];530 end = bound[1];531 while pc >= start && pc < end do {532 step();533 pc = *PC;534 }535 }537 defn next()538 {539 local sp, bound, pc;541 sp = *SP;542 bound = fnbound(*PC);543 if bound == {} then {544 print("cannot locate text symbol\n");545 return {};546 }547 stmnt();548 pc = *PC;549 if pc >= bound[0] && pc < bound[1] then550 return {};552 while (pc < bound[0] || pc > bound[1]) && sp >= *SP do {553 step();554 pc = *PC;555 }556 src(*PC);557 }559 defn maps()560 {561 local m, mm;563 m = map();564 while m != {} do {565 mm = head m;566 m = tail m;567 print(mm[2]\X, " ", mm[3]\X, " ", mm[4]\X, " ", mm[0], " ", mm[1], "\n");568 }569 }571 defn dump(addr, n, fmt)572 {573 loop 0, n do {574 print(fmt(addr, 'X'), ": ");575 addr = mem(addr, fmt);576 }577 }579 defn mem(addr, fmt)580 {582 local i, c, n;584 i = 0;585 while fmt[i] != 0 do {586 c = fmt[i];587 n = 0;588 while '0' <= fmt[i] && fmt[i] <= '9' do {589 n = 10*n + fmt[i]-'0';590 i = i+1;591 }592 if n <= 0 then n = 1;593 addr = fmt(addr, fmt[i]);594 while n > 0 do {595 print(*addr++, " ");596 n = n-1;597 }598 i = i+1;599 }600 print("\n");601 return addr;602 }604 defn symbols(pattern)605 {606 local l, s, name;608 l = symbols;609 while l do {610 s = head l;611 if regexp(pattern, s[0]) then {612 name = s[4];613 if name == {} then614 name = "";615 print(s[0], "\t", s[1], "\t", s[2], "\t", s[3], "\t", name, "\n");616 }617 l = tail l;618 }619 }621 defn havesymbol(name)622 {623 local l, s;625 l = symbols;626 while l do {627 s = head l;628 l = tail l;629 if s[0] == name then630 return 1;631 }632 return 0;633 }635 defn spsrch(len)636 {637 local addr, a, s, e;639 addr = *SP;640 s = origin & 0x7fffffff;641 e = etext & 0x7fffffff;642 loop 1, len do {643 a = *addr++;644 c = a & 0x7fffffff;645 if c > s && c < e then {646 print("src(", a, ")\n");647 pfl(a);648 }649 }650 }652 defn acidtypes()653 {654 local syms;655 local l;657 l = textfile();658 if l != {} then {659 syms = "acidtypes";660 while l != {} do {661 syms = syms + " " + ((head l)[0]);662 l = tail l;663 }664 includepipe(syms);665 }666 }668 defn getregs()669 {670 local regs, l;672 regs = {};673 l = registers;674 while l != {} do {675 regs = append regs, var(l[0]);676 l = tail l;677 }678 return regs;679 }681 defn setregs(regs)682 {683 local l;685 l = registers;686 while l != {} do {687 var(l[0]) = regs[0];688 l = tail l;689 regs = tail regs;690 }691 return regs;692 }694 defn resetregs()695 {696 local l;698 l = registers;699 while l != {} do {700 var(l[0]) = register(l[0]);701 l = tail l;702 }703 }705 defn clearregs()706 {707 local l;709 l = registers;710 while l != {} do {711 var(l[0]) = refconst(~0);712 l = tail l;713 }714 }716 progargs="";717 print(acidfile);