1// portable acid for all architectures 2 3defn pfl(addr) 4{ 5 print(pcfile(addr), ":", pcline(addr), "\n"); 6} 7 8defn 9notestk(addr) 10{ 11 local pc, sp; 12 complex Ureg addr; 13 14 pc = addr.pc\X; 15 sp = addr.sp\X; 16 17 print("Note pc:", pc, " sp:", sp, " ", fmt(pc, 'a'), " "); 18 pfl(pc); 19 _stk(pc, sp, linkreg(addr), 1); 20} 21 22defn 23notelstk(addr) 24{ 25 local pc, sp; 26 complex Ureg addr; 27 28 pc = addr.pc\X; 29 sp = addr.sp\X; 30 31 print("Note pc:", pc, " sp:", sp, " ", fmt(pc, 'a'), " "); 32 pfl(pc); 33 _stk(pc, sp, linkreg(addr), 1); 34} 35 36defn labstk(l) // trace from a label 37{ 38 _stk(*(l+4), *l, linkreg(0), 0); 39} 40 41defn 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 then 48 print (","); 49 } 50} 51 52stkprefix = ""; 53stkignore = {}; 54stkend = 0; 55 56defn locals(l) 57{ 58 local sym; 59 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} 66 67defn _stkign(file) 68{ 69 s = stkignore; 70 while s do { 71 if regexp(head s, file) then 72 return 1; 73 s = tail s; 74 } 75 return 0; 76} 77 78// print a stack trace 79// 80// in a run of leading frames in files matched by regexps in stkignore, 81// only print the last one. 82defn _stk(pc, sp, link, dolocals) 83{ 84 local stk, ign, last, lastpc; 85 86 stk = strace(pc, sp, link); 87 if stkignore then 88 ign = 1; 89 else 90 ign = 0; 91 last = stk; 92 lastpc = pc; 93 while stk do { 94 if ign then { 95 if !_stkign(pcfile(pc)) then { 96 ign = 0; 97 stk = last; 98 pc = lastpc; 99 } 100 } 101 frame = head stk; 102 if !ign then { 103 print(stkprefix, fmt(frame[0], 'a'), "("); 104 params(frame[2]); 105 print(")+", itoa(pc-frame[0], "%ux"), " "); 106 pfl(pc); 107 if dolocals then 108 locals(frame[3]); 109 } 110 last = stk; 111 lastpc = pc; 112 stk = tail stk; 113 pc = frame[1]; 114 } 115 print(stkprefix, fmt(pc, 'a'), " "); 116 pfl(pc); 117} 118 119defn findsrc(file) 120{ 121 local lst, src; 122 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 } 132 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} 144 145defn line(addr) 146{ 147 local src, file; 148 149 file = pcfile(addr); 150 src = match(file, srcfiles); 151 152 if src >= 0 then 153 src = srctext[src]; 154 else 155 src = findsrc(file); 156 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} 164 165defn addsrcdir(dir) 166{ 167 dir = dir+"/"; 168 169 if match(dir, srcpath) >= 0 then { 170 print("already in srcpath\n"); 171 return {}; 172 } 173 174 srcpath = {dir}+srcpath; 175} 176 177defn source() 178{ 179 local l; 180 181 l = srcpath; 182 while l do { 183 print(head l, "\n"); 184 l = tail l; 185 } 186 l = srcfiles; 187 188 while l do { 189 print("\t", head l, "\n"); 190 l = tail l; 191 } 192} 193 194defn Bsrc(addr) 195{ 196 local lst; 197 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} 214 215defn srcline(addr) 216{ 217 local text, cline, line, file, src; 218 file = pcfile(addr); 219 src = match(file,srcfiles); 220 if (src>=0) then 221 src = srctext[src]; 222 else 223 src = findsrc(file); 224 if (src=={}) then 225 { 226 return "(no source)"; 227 } 228 return src[pcline(addr)-1]; 229} 230 231defn src(addr) 232{ 233 local src, file, line, cline, text; 234 235 file = pcfile(addr); 236 src = match(file, srcfiles); 237 238 if src >= 0 then 239 src = srctext[src]; 240 else 241 src = findsrc(file); 242 243 if src == {} then { 244 print("no source for ", file, "\n"); 245 return {}; 246 } 247 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 text = src[line]; 254 if text == {} then 255 return {}; 256 if line == cline then 257 print(">"); 258 else 259 print(" "); 260 print(line+1, "\t", text, "\n"); 261 } 262 line = line+1; 263 } 264} 265 266defn step() // single step the process 267{ 268 local lst, lpl, addr, bput; 269 270 bput = 0; 271 if match(*PC, bplist) >= 0 then { // Sitting on a breakpoint 272 bput = fmt(*PC, bpfmt); 273 *bput = @bput; 274 } 275 276 lst = follow(*PC); 277 278 lpl = lst; 279 while lpl do { // place break points 280 *(head lpl) = bpinst; 281 lpl = tail lpl; 282 } 283 284 startstop(pid); // do the step 285 286 while lst do { // remove the breakpoints 287 addr = fmt(head lst, bpfmt); 288 *addr = @addr; 289 lst = tail lst; 290 } 291 if bput != 0 then 292 *bput = bpinst; 293} 294 295defn bpset(addr) // set a breakpoint 296{ 297 if status(pid) != "Stopped" then { 298 print("Waiting...\n"); 299 stop(pid); 300 } 301 if match(addr, bplist) >= 0 then 302 print("breakpoint already set at ", fmt(addr, 'a'), "\n"); 303 else { 304 *fmt(addr, bpfmt) = bpinst; 305 bplist = append bplist, addr; 306 } 307} 308 309defn bptab() // print a table of breakpoints 310{ 311 local lst, addr; 312 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} 320 321defn bpdel(addr) // delete a breakpoint 322{ 323 local n, pc, nbplist; 324 325 n = match(addr, bplist); 326 if n < 0 then { 327 print("no breakpoint at ", fmt(addr, 'a'), "\n"); 328 return {}; 329 } 330 331 addr = fmt(addr, bpfmt); 332 *addr = @addr; 333 334 nbplist = {}; // delete from list 335 while bplist do { 336 pc = head bplist; 337 if pc != addr then 338 nbplist = append nbplist, pc; 339 bplist = tail bplist; 340 } 341 bplist = nbplist; // delete from memory 342} 343 344defn cont() // continue execution 345{ 346 local addr; 347 348 addr = fmt(*PC, bpfmt); 349 if match(addr, bplist) >= 0 then { // Sitting on a breakpoint 350 *addr = @addr; 351 step(); // Step over 352 *addr = bpinst; 353 } 354 startstop(pid); // Run 355} 356 357defn stopped(pid) // called from acid when a process changes state 358{ 359 pstop(pid); // stub so this is easy to replace 360} 361 362defn procs() // print status of processes 363{ 364 local c, lst, cpid; 365 366 cpid = pid; 367 lst = proclist; 368 while lst do { 369 np = head lst; 370 setproc(np); 371 if np == cpid then 372 c = '>'; 373 else 374 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 then 380 setproc(pid); 381} 382 383_asmlines = 30; 384 385defn asm(addr) 386{ 387 local bound; 388 389 bound = fnbound(addr); 390 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} 402 403defn casm() 404{ 405 asm(lasmaddr); 406} 407 408defn win() 409{ 410 local npid, estr; 411 412 bplist = {}; 413 notes = {}; 414 415 estr = "/sys/lib/acid/window '0 0 600 400' "+textfile; 416 if progargs != "" then 417 estr = estr+" "+progargs; 418 419 npid = rc(estr); 420 npid = atoi(npid); 421 if npid == 0 then 422 error("win failed to create process"); 423 424 setproc(npid); 425 stopped(npid); 426} 427 428defn win2() 429{ 430 local npid, estr; 431 432 bplist = {}; 433 notes = {}; 434 435 estr = "/sys/lib/acid/transcript '0 0 600 400' '100 100 700 500' "+textfile; 436 if progargs != "" then 437 estr = estr+" "+progargs; 438 439 npid = rc(estr); 440 npid = atoi(npid); 441 if npid == 0 then 442 error("win failed to create process"); 443 444 setproc(npid); 445 stopped(npid); 446} 447 448defn new() 449{ 450 bplist = {}; 451 newproc(progargs); 452 // Dont miss the delay slot calls 453 bpset(follow(main)[0]); 454 cont(); 455 bpdel(*PC); 456} 457 458defn stmnt() // step one statement 459{ 460 local line; 461 462 line = pcline(*PC); 463 while 1 do { 464 step(); 465 if line != pcline(*PC) then { 466 src(*PC); 467 return {}; 468 } 469 } 470} 471 472defn func() // step until we leave the current function 473{ 474 local bound, end, start, pc; 475 476 bound = fnbound(*PC); 477 if bound == {} then { 478 print("cannot locate text symbol\n"); 479 return {}; 480 } 481 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} 490 491defn next() 492{ 493 local sp, bound; 494 495 sp = *SP; 496 bound = fnbound(*PC); 497 stmnt(); 498 pc = *PC; 499 if pc >= bound[0] && pc < bound[1] then 500 return {}; 501 502 while (pc < bound[0] || pc > bound[1]) && sp >= *SP do { 503 step(); 504 pc = *PC; 505 } 506 src(*PC); 507} 508 509defn dump(addr, n, fmt) 510{ 511 // see definition of dump in acid manual: it does n+1 iterations 512 loop 0, n do { 513 print(fmt(addr, 'X'), ": "); 514 addr = mem(addr, fmt); 515 } 516} 517 518defn mem(addr, fmt) 519{ 520 521 local i, c, n; 522 523 i = 0; 524 while fmt[i] != 0 do { 525 c = fmt[i]; 526 n = 0; 527 while '0' <= fmt[i] && fmt[i] <= '9' do { 528 n = 10*n + fmt[i]-'0'; 529 i = i+1; 530 } 531 if n <= 0 then n = 1; 532 addr = fmt(addr, fmt[i]); 533 while n > 0 do { 534 print(*addr++, " "); 535 n = n-1; 536 } 537 i = i+1; 538 } 539 print("\n"); 540 return addr; 541} 542 543defn symbols(pattern) 544{ 545 local l, s; 546 547 l = symbols; 548 while l do { 549 s = head l; 550 if regexp(pattern, s[0]) then 551 print(s[0], "\t", s[1], "\t", s[2], "\n"); 552 l = tail l; 553 } 554} 555 556defn spsrch(len) 557{ 558 local addr, a, s, e; 559 560 addr = *SP; 561 s = origin & 0x7fffffff; 562 e = etext & 0x7fffffff; 563 loop 1, len do { 564 a = *addr++; 565 c = a & 0x7fffffff; 566 if c > s && c < e then { 567 print("src(", a, ")\n"); 568 pfl(a); 569 } 570 } 571} 572 573progargs=""; 574print("/sys/lib/acid/port"); 575