port (10931B)
1 // portable acid for all architectures 2 3 defn pfl(addr) 4 { 5 print(pcfile(addr), ":", pcline(addr), "\n"); 6 } 7 8 defn 9 notestk(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", pc, "SP", sp, linkreg(addr)}, 1); 20 } 21 22 defn 23 notelstk(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", pc, "SP", sp, linkreg(addr)}, 1); 34 } 35 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 then 43 print (","); 44 } 45 } 46 47 stkprefix = ""; 48 stkignore = {}; 49 stkend = 0; 50 51 defn locals(l) 52 { 53 local sym; 54 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 } 61 62 defn _stkign(frame) 63 { 64 local file; 65 66 file = pcfile(frame[0]); 67 s = stkignore; 68 while s do { 69 if regexp(head s, file) then 70 return 1; 71 s = tail s; 72 } 73 return 0; 74 } 75 76 // print a stack trace 77 // 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; 83 84 stk = strace(regs); 85 if stkignore then { 86 while stk && tail stk && _stkign(head tail stk) do 87 stk = tail stk; 88 } 89 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]; 100 101 print(stkprefix, fmt(fn, 'a'), "("); 102 params(paramlist); 103 print(")"); 104 if pc != fn then 105 print("+", itoa(pc-fn, "%#ux")); 106 print(" "); 107 pfl(pc); 108 if dolocals then 109 locals(locallist); 110 if fn == var("threadmain") || fn == var("p9main") then 111 done=1; 112 if fn == var("threadstart") || fn == var("scheduler") then 113 done=1; 114 if callerpc == 0 then 115 done=1; 116 } 117 if callerpc && !done then { 118 print(stkprefix, fmt(callerpc, 'a'), " "); 119 pfl(callerpc); 120 } 121 } 122 123 defn findsrc(file) 124 { 125 local lst, src; 126 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 } 136 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 } 148 149 defn line(addr) 150 { 151 local src, file; 152 153 file = pcfile(addr); 154 src = match(file, srcfiles); 155 156 if src >= 0 then 157 src = srctext[src]; 158 else 159 src = findsrc(file); 160 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 } 168 169 defn addsrcdir(dir) 170 { 171 dir = dir+"/"; 172 173 if match(dir, srcpath) >= 0 then { 174 print("already in srcpath\n"); 175 return {}; 176 } 177 178 srcpath = {dir}+srcpath; 179 } 180 181 defn source() 182 { 183 local l; 184 185 l = srcpath; 186 while l do { 187 print(head l, "\n"); 188 l = tail l; 189 } 190 l = srcfiles; 191 192 while l do { 193 print("\t", head l, "\n"); 194 l = tail l; 195 } 196 } 197 198 defn Bsrc(addr) 199 { 200 local lst; 201 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 } 218 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) then 225 src = srctext[src]; 226 else 227 src = findsrc(file); 228 if (src=={}) then 229 { 230 return "(no source)"; 231 } 232 return src[pcline(addr)-1]; 233 } 234 235 defn src(addr) 236 { 237 local src, file, line, cline, text; 238 239 file = pcfile(addr); 240 src = match(file, srcfiles); 241 242 if src >= 0 then 243 src = srctext[src]; 244 else 245 src = findsrc(file); 246 247 if src == {} then { 248 print("no source for ", file, "\n"); 249 return {}; 250 } 251 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 then 258 print(">"); 259 else 260 print(" "); 261 text = src[line]; 262 if text == {} then 263 return {}; 264 print(line+1, "\t", text, "\n"); 265 } 266 line = line+1; 267 } 268 } 269 270 defn step() // single step the process 271 { 272 local lst, lpl, addr, bput; 273 274 bput = 0; 275 if match(*PC, bplist) >= 0 then { // Sitting on a breakpoint 276 bput = fmt(*PC, bpfmt); 277 *bput = @bput; 278 } 279 280 lst = follow(*PC); 281 282 lpl = lst; 283 while lpl do { // place break points 284 *(head lpl) = bpinst; 285 lpl = tail lpl; 286 } 287 288 startstop(pid); // do the step 289 290 while lst do { // remove the breakpoints 291 addr = fmt(head lst, bpfmt); 292 *addr = @addr; 293 lst = tail lst; 294 } 295 if bput != 0 then 296 *bput = bpinst; 297 } 298 299 defn bpset(addr) // set a breakpoint 300 { 301 if status(pid) != "Stopped" then { 302 print("Waiting...\n"); 303 stop(pid); 304 } 305 if match(addr, bplist) >= 0 then 306 print("breakpoint already set at ", fmt(addr, 'a'), "\n"); 307 else { 308 *fmt(addr, bpfmt) = bpinst; 309 bplist = append bplist, addr; 310 } 311 } 312 313 defn bptab() // print a table of breakpoints 314 { 315 local lst, addr; 316 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 } 324 325 defn bpdel(addr) // delete a breakpoint 326 { 327 local n, pc, nbplist; 328 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 } 338 339 n = match(addr, bplist); 340 if n < 0 then { 341 print("no breakpoint at ", fmt(addr, 'a'), "\n"); 342 return {}; 343 } 344 345 addr = fmt(addr, bpfmt); 346 *addr = @addr; 347 348 nbplist = {}; // delete from list 349 while bplist do { 350 pc = head bplist; 351 if pc != addr then 352 nbplist = append nbplist, pc; 353 bplist = tail bplist; 354 } 355 bplist = nbplist; // delete from memory 356 } 357 358 defn cont() // continue execution 359 { 360 local addr; 361 362 addr = fmt(*PC, bpfmt); 363 if match(addr, bplist) >= 0 then { // Sitting on a breakpoint 364 *addr = @addr; 365 step(); // Step over 366 *addr = bpinst; 367 } 368 startstop(pid); // Run 369 } 370 371 defn stopped(pid) // called from acid when a process changes state 372 { 373 pfixstop(pid); 374 pstop(pid); // stub so this is easy to replace 375 } 376 377 defn procs() // print status of processes 378 { 379 local c, lst, cpid; 380 381 cpid = pid; 382 lst = proclist; 383 while lst do { 384 np = head lst; 385 setproc(np); 386 if np == cpid then 387 c = '>'; 388 else 389 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 then 395 setproc(pid); 396 } 397 398 _asmlines = 30; 399 400 defn asm(addr) 401 { 402 local bound; 403 404 bound = fnbound(addr); 405 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 } 417 418 defn casm() 419 { 420 asm(lasmaddr); 421 } 422 423 defn xasm(addr) 424 { 425 local bound; 426 427 bound = fnbound(addr); 428 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 } 440 441 defn xcasm() 442 { 443 xasm(lasmaddr); 444 } 445 446 defn win() 447 { 448 local npid, estr; 449 450 bplist = {}; 451 notes = {}; 452 453 estr = "/sys/lib/acid/window '0 0 600 400' "+textfile; 454 if progargs != "" then 455 estr = estr+" "+progargs; 456 457 npid = rc(estr); 458 npid = atoi(npid); 459 if npid == 0 then 460 error("win failed to create process"); 461 462 setproc(npid); 463 stopped(npid); 464 } 465 466 defn win2() 467 { 468 local npid, estr; 469 470 bplist = {}; 471 notes = {}; 472 473 estr = "/sys/lib/acid/transcript '0 0 600 400' '100 100 700 500' "+textfile; 474 if progargs != "" then 475 estr = estr+" "+progargs; 476 477 npid = rc(estr); 478 npid = atoi(npid); 479 if npid == 0 then 480 error("win failed to create process"); 481 482 setproc(npid); 483 stopped(npid); 484 } 485 486 printstopped = 1; 487 defn new() 488 { 489 local a; 490 491 bplist = {}; 492 newproc(progargs); 493 a = var("p9main"); 494 if a == {} then 495 a = var("main"); 496 if a == {} then 497 return {}; 498 bpset(a); 499 while *PC != a do 500 cont(); 501 bpdel(a); 502 } 503 504 defn stmnt() // step one statement 505 { 506 local line; 507 508 line = pcline(*PC); 509 while 1 do { 510 step(); 511 if line != pcline(*PC) then { 512 src(*PC); 513 return {}; 514 } 515 } 516 } 517 518 defn func() // step until we leave the current function 519 { 520 local bound, end, start, pc; 521 522 bound = fnbound(*PC); 523 if bound == {} then { 524 print("cannot locate text symbol\n"); 525 return {}; 526 } 527 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 } 536 537 defn next() 538 { 539 local sp, bound, pc; 540 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] then 550 return {}; 551 552 while (pc < bound[0] || pc > bound[1]) && sp >= *SP do { 553 step(); 554 pc = *PC; 555 } 556 src(*PC); 557 } 558 559 defn maps() 560 { 561 local m, mm; 562 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 } 570 571 defn dump(addr, n, fmt) 572 { 573 loop 0, n do { 574 print(fmt(addr, 'X'), ": "); 575 addr = mem(addr, fmt); 576 } 577 } 578 579 defn mem(addr, fmt) 580 { 581 582 local i, c, n; 583 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 } 603 604 defn symbols(pattern) 605 { 606 local l, s, name; 607 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 == {} then 614 name = ""; 615 print(s[0], "\t", s[1], "\t", s[2], "\t", s[3], "\t", name, "\n"); 616 } 617 l = tail l; 618 } 619 } 620 621 defn havesymbol(name) 622 { 623 local l, s; 624 625 l = symbols; 626 while l do { 627 s = head l; 628 l = tail l; 629 if s[0] == name then 630 return 1; 631 } 632 return 0; 633 } 634 635 defn spsrch(len) 636 { 637 local addr, a, s, e; 638 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 } 651 652 defn acidtypes() 653 { 654 local syms; 655 local l; 656 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 } 667 668 defn getregs() 669 { 670 local regs, l; 671 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 } 680 681 defn setregs(regs) 682 { 683 local l; 684 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 } 693 694 defn resetregs() 695 { 696 local l; 697 698 l = registers; 699 while l != {} do { 700 var(l[0]) = register(l[0]); 701 l = tail l; 702 } 703 } 704 705 defn clearregs() 706 { 707 local l; 708 709 l = registers; 710 while l != {} do { 711 var(l[0]) = refconst(~0); 712 l = tail l; 713 } 714 } 715 716 progargs=""; 717 print(acidfile); 718