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(file)68 {69 s = stkignore;70 while s do {71 if regexp(head s, file) then72 return 1;73 s = tail s;74 }75 return 0;76 }78 // print a stack trace79 //80 // in a run of leading frames in files matched by regexps in stkignore,81 // only print the last one.82 defn _stk(regs, dolocals)83 {84 local stk, pc, fn, callerpc, paramlist, locallist;86 stk = strace(regs);87 if stkignore then {88 while stk && tail stk && _stkign((head tail stk)[1]) do89 stk = tail stk;90 }92 callerpc = 0;93 while stk do {94 frame = head stk;95 stk = tail stk;96 fn = frame[0];97 pc = frame[1];98 callerpc = frame[2];99 paramlist = frame[3];100 locallist = frame[4];102 print(stkprefix, fmt(fn, 'a'), "(");103 params(paramlist);104 print(")");105 if pc != fn then106 print("+", itoa(pc-fn, "%ux"));107 print(" ");108 pfl(pc);109 if dolocals then110 locals(locallist);111 }113 if callerpc then {114 print(stkprefix, fmt(callerpc, 'a'), " ");115 pfl(callerpc);116 }117 }119 defn findsrc(file)120 {121 local lst, src;123 if file[0] == '/' then {124 src = file(file);125 if src != {} then {126 srcfiles = append srcfiles, file;127 srctext = append srctext, src;128 return src;129 }130 return {};131 }133 lst = srcpath;134 while head lst do {135 src = file(head lst+file);136 if src != {} then {137 srcfiles = append srcfiles, file;138 srctext = append srctext, src;139 return src;140 }141 lst = tail lst;142 }143 }145 defn line(addr)146 {147 local src, file;149 file = pcfile(addr);150 src = match(file, srcfiles);152 if src >= 0 then153 src = srctext[src];154 else155 src = findsrc(file);157 if src == {} then {158 print("no source for ", file, "\n");159 return {};160 }161 line = pcline(addr)-1;162 print(file, ":", src[line], "\n");163 }165 defn addsrcdir(dir)166 {167 dir = dir+"/";169 if match(dir, srcpath) >= 0 then {170 print("already in srcpath\n");171 return {};172 }174 srcpath = {dir}+srcpath;175 }177 defn source()178 {179 local l;181 l = srcpath;182 while l do {183 print(head l, "\n");184 l = tail l;185 }186 l = srcfiles;188 while l do {189 print("\t", head l, "\n");190 l = tail l;191 }192 }194 defn Bsrc(addr)195 {196 local lst;198 lst = srcpath;199 file = pcfile(addr);200 if file[0] == '/' && access(file) then {201 rc("B "+file+":"+itoa(pcline(addr)));202 return {};203 }204 while head lst do {205 name = head lst+file;206 if access(name) then {207 rc("B "+name+":"+itoa(pcline(addr)));208 return {};209 }210 lst = tail lst;211 }212 print("no source for ", file, "\n");213 }215 defn srcline(addr)216 {217 local text, cline, line, file, src;218 file = pcfile(addr);219 src = match(file,srcfiles);220 if (src>=0) then221 src = srctext[src];222 else223 src = findsrc(file);224 if (src=={}) then225 {226 return "(no source)";227 }228 return src[pcline(addr)-1];229 }231 defn src(addr)232 {233 local src, file, line, cline, text;235 file = pcfile(addr);236 src = match(file, srcfiles);238 if src >= 0 then239 src = srctext[src];240 else241 src = findsrc(file);243 if src == {} then {244 print("no source for ", file, "\n");245 return {};246 }248 cline = pcline(addr)-1;249 print(file, ":", cline+1, "\n");250 line = cline-5;251 loop 0,10 do {252 if line >= 0 then {253 if line == cline then254 print(">");255 else256 print(" ");257 text = src[line];258 if text == {} then259 return {};260 print(line+1, "\t", text, "\n");261 }262 line = line+1;263 }264 }266 defn step() // single step the process267 {268 local lst, lpl, addr, bput;270 bput = 0;271 if match(*PC, bplist) >= 0 then { // Sitting on a breakpoint272 bput = fmt(*PC, bpfmt);273 *bput = @bput;274 }276 lst = follow(*PC);278 lpl = lst;279 while lpl do { // place break points280 *(head lpl) = bpinst;281 lpl = tail lpl;282 }284 startstop(pid); // do the step286 while lst do { // remove the breakpoints287 addr = fmt(head lst, bpfmt);288 *addr = @addr;289 lst = tail lst;290 }291 if bput != 0 then292 *bput = bpinst;293 }295 defn bpset(addr) // set a breakpoint296 {297 if status(pid) != "Stopped" then {298 print("Waiting...\n");299 stop(pid);300 }301 if match(addr, bplist) >= 0 then302 print("breakpoint already set at ", fmt(addr, 'a'), "\n");303 else {304 *fmt(addr, bpfmt) = bpinst;305 bplist = append bplist, addr;306 }307 }309 defn bptab() // print a table of breakpoints310 {311 local lst, addr;313 lst = bplist;314 while lst do {315 addr = head lst;316 print("\t", fmt(addr, 'X'), " ", fmt(addr, 'a'), " ", fmt(addr, 'i'), "\n");317 lst = tail lst;318 }319 }321 defn bpdel(addr) // delete a breakpoint322 {323 local n, pc, nbplist;325 n = match(addr, bplist);326 if n < 0 then {327 print("no breakpoint at ", fmt(addr, 'a'), "\n");328 return {};329 }331 addr = fmt(addr, bpfmt);332 *addr = @addr;334 nbplist = {}; // delete from list335 while bplist do {336 pc = head bplist;337 if pc != addr then338 nbplist = append nbplist, pc;339 bplist = tail bplist;340 }341 bplist = nbplist; // delete from memory342 }344 defn cont() // continue execution345 {346 local addr;348 addr = fmt(*PC, bpfmt);349 if match(addr, bplist) >= 0 then { // Sitting on a breakpoint350 *addr = @addr;351 step(); // Step over352 *addr = bpinst;353 }354 startstop(pid); // Run355 }357 defn stopped(pid) // called from acid when a process changes state358 {359 pstop(pid); // stub so this is easy to replace360 }362 defn procs() // print status of processes363 {364 local c, lst, cpid;366 cpid = pid;367 lst = proclist;368 while lst do {369 np = head lst;370 setproc(np);371 if np == cpid then372 c = '>';373 else374 c = ' ';375 print(fmt(c, 'c'), np, ": ", status(np), " at ", fmt(*PC, 'a'), " setproc(", np, ")\n");376 lst = tail lst;377 }378 pid = cpid;379 if pid != 0 then380 setproc(pid);381 }383 _asmlines = 30;385 defn asm(addr)386 {387 local bound;389 bound = fnbound(addr);391 addr = fmt(addr, 'i');392 loop 1,_asmlines do {393 print(fmt(addr, 'a'), " ", fmt(addr, 'X'));394 print("\t", @addr++, "\n");395 if bound != {} && addr > bound[1] then {396 lasmaddr = addr;397 return {};398 }399 }400 lasmaddr = addr;401 }403 defn casm()404 {405 asm(lasmaddr);406 }408 defn win()409 {410 local npid, estr;412 bplist = {};413 notes = {};415 estr = "/sys/lib/acid/window '0 0 600 400' "+textfile;416 if progargs != "" then417 estr = estr+" "+progargs;419 npid = rc(estr);420 npid = atoi(npid);421 if npid == 0 then422 error("win failed to create process");424 setproc(npid);425 stopped(npid);426 }428 defn win2()429 {430 local npid, estr;432 bplist = {};433 notes = {};435 estr = "/sys/lib/acid/transcript '0 0 600 400' '100 100 700 500' "+textfile;436 if progargs != "" then437 estr = estr+" "+progargs;439 npid = rc(estr);440 npid = atoi(npid);441 if npid == 0 then442 error("win failed to create process");444 setproc(npid);445 stopped(npid);446 }448 defn new()449 {450 bplist = {};451 newproc(progargs);452 // Dont miss the delay slot calls453 bpset(follow(main)[0]);454 cont();455 bpdel(*PC);456 }458 defn stmnt() // step one statement459 {460 local line;462 line = pcline(*PC);463 while 1 do {464 step();465 if line != pcline(*PC) then {466 src(*PC);467 return {};468 }469 }470 }472 defn func() // step until we leave the current function473 {474 local bound, end, start, pc;476 bound = fnbound(*PC);477 if bound == {} then {478 print("cannot locate text symbol\n");479 return {};480 }482 pc = *PC;483 start = bound[0];484 end = bound[1];485 while pc >= start && pc < end do {486 step();487 pc = *PC;488 }489 }491 defn next()492 {493 local sp, bound;495 sp = *SP;496 bound = fnbound(*PC);497 stmnt();498 pc = *PC;499 if pc >= bound[0] && pc < bound[1] then500 return {};502 while (pc < bound[0] || pc > bound[1]) && sp >= *SP do {503 step();504 pc = *PC;505 }506 src(*PC);507 }509 defn maps()510 {511 local m, mm;513 m = map();514 while m != {} do {515 mm = head m;516 m = tail m;517 print(mm[2]\X, " ", mm[3]\X, " ", mm[4]\X, " ", mm[0], " ", mm[1], "\n");518 }519 }521 defn dump(addr, n, fmt)522 {523 loop 0, n do {524 print(fmt(addr, 'X'), ": ");525 addr = mem(addr, fmt);526 }527 }529 defn mem(addr, fmt)530 {532 local i, c, n;534 i = 0;535 while fmt[i] != 0 do {536 c = fmt[i];537 n = 0;538 while '0' <= fmt[i] && fmt[i] <= '9' do {539 n = 10*n + fmt[i]-'0';540 i = i+1;541 }542 if n <= 0 then n = 1;543 addr = fmt(addr, fmt[i]);544 while n > 0 do {545 print(*addr++, " ");546 n = n-1;547 }548 i = i+1;549 }550 print("\n");551 return addr;552 }554 defn symbols(pattern)555 {556 local l, s;558 l = symbols;559 while l do {560 s = head l;561 if regexp(pattern, s[0]) then562 print(s[0], "\t", s[1], "\t", s[2], "\t", s[3], "\n");563 l = tail l;564 }565 }567 defn havesymbol(name)568 {569 local l, s;571 l = symbols;572 while l do {573 s = head l;574 l = tail l;575 if s[0] == name then576 return 1;577 }578 return 0;579 }581 defn spsrch(len)582 {583 local addr, a, s, e;585 addr = *SP;586 s = origin & 0x7fffffff;587 e = etext & 0x7fffffff;588 loop 1, len do {589 a = *addr++;590 c = a & 0x7fffffff;591 if c > s && c < e then {592 print("src(", a, ")\n");593 pfl(a);594 }595 }596 }598 progargs="";599 print(acidfile);