1: # 2: /* 3: 4: C debugger 5: 6: */ 7: 8: #include "/usr/sys/param.h" 9: #include "/usr/sys/user.h" 10: 11: #define DSP 0 12: #define ISP 1 13: #define NBKP 10 14: #define SYMSIZ 12*400 15: #define BADJST 01 16: 17: int fcore; 18: int errno; 19: int fsym; 20: int symoff; 21: char *lp; 22: int errflg; 23: int symlen; 24: int symct; 25: int symcor; 26: int symbuf[SYMSIZ]; 27: int *symptr; 28: struct { 29: int loc; 30: int ins; 31: int count; 32: int flag; 33: } bkptl[NBKP]; 34: int lastbp; 35: char symbol[8]; 36: int symflg; 37: int symval; 38: char tsym[8]; 39: char fsymbol[10]; 40: char ssymbol[8]; 41: int ssymflg; 42: int ssymval; 43: int signo; 44: char line[128]; 45: int regbuf[512]; 46: char **uregs ®buf[512]; 47: char *rtsize; 48: int loccsv; 49: int locsr5; 50: #define RUSER 1 51: #define RIUSER 2 52: #define WUSER 4 53: #define RUREGS 3 54: #define WUREGS 6 55: #define SETTRC 0 56: #define CONTIN 7 57: #define EXIT 8 58: 59: #define ps -1 60: #define pc -2 61: #define sp -6 62: #define r5 -9 63: #define r4 -10 64: #define r3 -11 65: #define r2 -12 66: #define r1 -5 67: #define r0 -3 68: struct reglist { 69: char *rname; 70: int roffs; 71: } reglist[] { 72: "ps", ps, 73: "pc", pc, 74: "sp", sp, 75: "r5", r5, 76: "r4", r4, 77: "r3", r3, 78: "r2", r2, 79: "r1", r1, 80: "r0", r0, 81: }; 82: 83: struct sfregs { 84: int junk[2]; 85: int fpsr; 86: float sfr[6]; 87: }; 88: 89: struct lfregs { 90: int junk[2]; 91: int fpsr; 92: double lfr[6]; 93: }; 94: 95: int frnames[] { 0, 3, 4, 5, 1, 2 }; 96: int dot; 97: int tdot; 98: int dotinc 2; 99: int lastcom '/'; 100: int lastype 'o'; 101: int modifier; 102: char *symfil "a.out"; 103: char *corfil "core"; 104: int callist[50]; 105: int entpt[50]; 106: int callev; 107: int pid; 108: int adrflg; 109: int idsep; 110: char *signals[] { 111: "", 112: "Hangup", 113: "Interrupt", 114: "Quit", 115: "Illegal instruction", 116: "Trace/BTP", 117: "IOT", 118: "EMT", 119: "Floating exception", 120: "Killed", 121: "Bus error", 122: "Memory fault", 123: "Bad system call", 124: "", 125: "", 126: "", 127: }; 128: 129: main(argc, argv) 130: char **argv; 131: { 132: int onintr(); 133: 134: if (argc>1) 135: symfil = argv[1]; 136: if (argc>2) 137: corfil = argv[2]; 138: fcore = open(corfil, 0); 139: if ((fsym = open(symfil, 0)) < 0) { 140: printf("%s not found\n", symfil); 141: return; 142: } 143: read(fsym, regbuf, 020); 144: if (regbuf[0]==0411) /* I/D separated */ 145: idsep++; 146: else if (regbuf[0]!=0410 && regbuf[0]!=0407) { /* magic */ 147: printf("Bad format: %s\n", symfil); 148: return; 149: } 150: symoff = regbuf[1] + regbuf[2]; 151: symlen = regbuf[4]; 152: if (regbuf[7] != 1) 153: symoff =<< 1; 154: symoff =+ 020; 155: seek(fsym, symoff, 0); 156: symcor = read(fsym, symbuf, sizeof symbuf); 157: if (symcor>0) 158: symoff =+ symcor; 159: symcor =>> 1; 160: read(fcore, regbuf, 1024); 161: signo = regbuf[0].u_arg[0]&017; 162: regbuf->u_tsize =<< 6; 163: regbuf->u_dsize =<< 6; 164: regbuf->u_ssize =<< 6; 165: rtsize = (regbuf->u_tsize+017777) & ~017777; 166: if (symlook("csv\0\0\0\0")) 167: loccsv = ssymval; 168: if (symlook("savr5\0\0\0")) 169: locsr5 = ssymval; 170: setstack(); 171: signal(SIGINS, onintr); 172: setexit(); 173: signal(SIGINT, onintr); 174: loop: 175: if (errflg) { 176: printf("?\n"); 177: errflg = 0; 178: } 179: lp = line; 180: while ((*lp = getchar()) != '\n') 181: if (*lp++ == '\0') { 182: if (pid) 183: ptrace(EXIT, pid, 0, 0); 184: return; 185: } 186: lp = line; 187: command(); 188: goto loop; 189: } 190: 191: command() 192: { 193: register n; 194: 195: adrflg = expr(); 196: if (errflg) 197: return; 198: n = getcnt(); 199: if (lastcom=='$') 200: lastcom = '/'; 201: if (*lp == '\n') { 202: if (!adrflg) 203: dot =+ dotinc; 204: } else 205: lastcom = *lp++; 206: modifier = 0; 207: if (*lp != '\n') 208: modifier = *lp++; 209: if (lastcom=='%' && modifier=='r') { 210: runcom(); 211: return; 212: } 213: if (*lp != '\n') { 214: errflg++; 215: return; 216: } 217: if (adrflg) 218: dot = tdot; 219: while(n) { 220: scommand(n); 221: if (errflg) 222: return; 223: if (--n) 224: dot =+ dotinc; 225: } 226: } 227: 228: scommand(n) 229: { 230: register w, c; 231: double fw; 232: struct { int i[4]; }; 233: int onintr(); 234: 235: switch(lastcom) { 236: 237: case '/': 238: w = cget(dot, DSP); 239: if (modifier) 240: lastype = modifier; 241: switch(lastype) { 242: 243: case 'o': 244: printf("%.1o\n", w); 245: dotinc = 2; 246: return; 247: 248: case 'i': 249: printf("%d\n", w); 250: dotinc = 2; 251: return; 252: 253: case 'f': 254: fw = 0; 255: fw.i[0] = w; 256: fw.i[1] = cget(dot+2, DSP); 257: printf("%e\n", fw); 258: dotinc = 4; 259: return; 260: 261: case 'd': 262: fw.i[0] = w; 263: fw.i[1] = cget(dot+2, DSP); 264: fw.i[2] = cget(dot+4, DSP); 265: fw.i[3] = cget(dot+6, DSP); 266: printf("%e\n", fw); 267: dotinc = 8; 268: return; 269: } 270: errflg++; 271: return; 272: 273: case '\\': 274: printf("%.1o\n", cget(dot, DSP)&0377); 275: dotinc = 1; 276: return; 277: 278: case '=': 279: printf("%.1o\n", dot); 280: return; 281: 282: case '\'': 283: printc(cget(dot, DSP) & 0377); 284: if (n<=1) 285: putchar('\n'); 286: dotinc = 1; 287: return; 288: 289: case '"': 290: w = cget(dot, DSP); 291: while(c = cget(w++, DSP)&0377) 292: printc(c); 293: putchar('\n'); 294: return; 295: 296: case '&': 297: psymoff(cget(dot, DSP), 0100000); 298: printf("\n"); 299: return; 300: 301: case '$': 302: printf("%s\n", signals[signo]); 303: printtrace(); 304: return; 305: 306: case '?': 307: printins(0); 308: printf("\n"); 309: return; 310: 311: case '%': 312: runcom(); 313: signal(SIGINT, onintr); 314: return; 315: 316: } 317: errflg++; 318: } 319: 320: getcnt() 321: { 322: register t1, t2; 323: 324: if (*lp != ',') 325: return(1); 326: lp++; 327: t1 = tdot; 328: if (expr() == 0) { 329: tdot = t1; 330: return(1); 331: } 332: t2 = tdot; 333: tdot = t1; 334: return(t2); 335: } 336: 337: cget(n, space) 338: { 339: register w; 340: 341: w = get(n, space); 342: if (errflg) 343: reset(); 344: return(w); 345: } 346: 347: printc(c) 348: { 349: if (c<' ' || c>'~') 350: printf("\\%o", c); 351: else 352: printf("%c", c); 353: } 354: 355: expr() 356: { 357: int i, t1, t2, donef, lastop, b; 358: 359: tdot = 0; 360: adrflg = 0; 361: lastop = '+'; 362: ssymval = 0; 363: donef = 0; 364: loop: 365: fsymbol[0] = 0; 366: if (symchar(0)) { 367: adrflg++; 368: symcollect('_'); 369: if (*lp++==':' && symchar(0)) { 370: for (i=0; i<8; i++) 371: fsymbol[i] = tsym[i]; 372: fsymbol[0] = '~'; 373: symcollect(0); 374: } else 375: lp--; 376: if (symlook(tsym) == 0) { 377: errflg++; 378: reset(); 379: } 380: goto loop; 381: } 382: if (*lp>='0' && *lp<='9') { 383: adrflg++; 384: ssymval = 0; 385: if (*lp == '0') 386: b = 8; 387: else 388: b = 10; 389: while (*lp>='0' && *lp<='9') { 390: ssymval =* b; 391: ssymval =+ *lp++ -'0'; 392: } 393: goto loop; 394: } 395: switch (*lp) { 396: 397: default: 398: donef++; 399: 400: case '+': 401: case '-': 402: switch(lastop) { 403: 404: case '+': 405: tdot =+ ssymval; 406: goto op; 407: 408: case '-': 409: tdot =- ssymval; 410: 411: op: 412: if (donef) 413: return(adrflg); 414: else 415: lastop = *lp++; 416: } 417: goto loop; 418: 419: case ' ': 420: case '\t': 421: lp++; 422: goto loop; 423: 424: case '[': 425: lp++; 426: t1 = ssymval; 427: t2 = tdot; 428: if (expr() == 0) 429: tdot = 0; 430: ssymval = cget(t1 + (tdot<<1), DSP); 431: tdot = t2; 432: if (*lp == ']') 433: lp++; 434: goto loop; 435: } 436: } 437: 438: symcollect(c) 439: { 440: register char *p; 441: 442: p = tsym; 443: if (c) 444: *p++ = c; 445: while (symchar(1)) { 446: if (p < &tsym[8]) 447: *p++ = *lp; 448: lp++; 449: } 450: while (p < &tsym[8]) 451: *p++ = 0; 452: } 453: 454: symchar(dig) 455: { 456: if (*lp>='a'&&*lp<='z' || *lp=='_') 457: return(1); 458: if (dig && *lp>='0' && *lp<='9') 459: return(1); 460: return(0); 461: } 462: 463: error() 464: { 465: errflg++; 466: reset(); 467: } 468: 469: printtrace() 470: { 471: int tpc, tr5, narg, argp, i; 472: 473: if (modifier=='r') { 474: printregs(); 475: return; 476: } 477: if (modifier=='f' || modifier=='d') { 478: printfregs(); 479: return; 480: } 481: tpc = uregs[pc]; 482: tr5 = uregs[r5]; 483: if (locsr5) 484: if (narg = get(locsr5, DSP)) { 485: tr5 = narg; 486: } 487: callev = 0; 488: while (errflg == 0) { 489: narg = findroutine(tpc, tr5); 490: printf("%2d: %.8s(", callev, ssymbol); 491: if (--narg >= 0) 492: printf("%.1o", get(tr5+4, DSP)); 493: argp = tr5+4; 494: while(--narg >= 0) 495: printf(",%.1o", get(argp =+ 2, DSP)); 496: printf(")\n"); 497: tpc = get(tr5+2, DSP); 498: if (callev < 50) { 499: entpt[callev] = ssymval; 500: callist[callev++] = tr5; 501: } 502: if ((tr5 = get(tr5, DSP)) == 0) 503: break; 504: } 505: } 506: 507: setstack() 508: { 509: register int tpc, tr5, i; 510: 511: tpc = uregs[pc]; 512: tr5 = uregs[r5]; 513: if (locsr5) 514: if (i = get(locsr5, DSP)) { 515: tr5 = i; 516: } 517: callev = 0; 518: while (errflg == 0) { 519: findroutine(tpc, tr5); 520: tpc = get(tr5+2, DSP); 521: if (callev >= 50) 522: break; 523: entpt[callev] = ssymval; 524: callist[callev++] = tr5; 525: if ((tr5 = get(tr5, DSP)) == 0) 526: break; 527: } 528: errflg = 0; 529: } 530: 531: printfregs() 532: { 533: register i; 534: double f; 535: 536: printf("fpsr %.1o\n", regbuf[0].fpsr); 537: for (i=0; i<6; i++) { 538: if (regbuf[0].fpsr&0200) /* long mode */ 539: f = regbuf[0].lfr[frnames[i]]; 540: else 541: f = regbuf[0].sfr[frnames[i]]; 542: printf("fr%d %e\n", i, f); 543: } 544: } 545: 546: printregs() 547: { 548: register struct reglist *p; 549: register char *v, *d; 550: 551: for (p=reglist; p < ®list[9]; p++) { 552: printf("%s %.1o", p->rname, v=uregs[p->roffs]); 553: d = vallook(v); 554: if (d < 010000) { 555: printf(" %.8s", ssymbol); 556: if (d) 557: printf("+%.1o", d); 558: } 559: printf("\n"); 560: } 561: } 562: 563: findroutine(rpc, rr5) 564: { 565: register callpt, inst, narg; 566: 567: callpt = get(rr5+2, DSP); 568: if ((inst=get(callpt-4, ISP)) == 04737) /* jsr pc,*$... */ 569: narg = 1; 570: else if ((inst&~077)==04700) /* jsr pc,... */ 571: narg = 0; 572: else { 573: errflg++; 574: return(0); 575: } 576: inst = vallook((inst==04767?callpt:0) + get(callpt-2, ISP)); 577: if (inst) { 578: ssymbol[0] = '?'; 579: ssymbol[1] = 0; 580: ssymval = 0; 581: } 582: inst = get(callpt, ISP); 583: if (inst == 05726) /* tst (sp)+ */ 584: return(narg+1); 585: if (inst == 022626) /* cmp (sp)+,(sp)+ */ 586: return(narg+2); 587: if (inst == 062706) /* add $n,sp */ 588: return(narg+get(callpt+2, ISP)/2); 589: return(narg); 590: } 591: 592: runcom() 593: { 594: int stat; 595: register w, i; 596: 597: switch(modifier) { 598: 599: 600: /* delete breakpoint */ 601: case 'd': 602: if (adrflg==0) 603: error(); 604: for (w=0; w<NBKP; w++) { 605: i = bkptl[w].loc; 606: if (bkptl[w].flag & BADJST) 607: i =- 4; 608: if (dot==i) { 609: if (lastbp==bkptl[w].loc) { 610: ptrace(WUREGS,pid,2*(512+ps),uregs[ps]&~020); 611: lastbp = 0; 612: } else { 613: ptrace(WUSER,pid,bkptl[w].loc,bkptl[w].ins); 614: } 615: bkptl[w].loc = 0; 616: bkptl[w].flag = 0; 617: return; 618: } 619: } 620: error(); 621: 622: /* set breakpoint */ 623: case 'b': 624: if (adrflg==0) 625: error(); 626: for (w=0; w<NBKP; w++) { 627: i = bkptl[w].loc; 628: if (bkptl[w].flag&BADJST) 629: i =- 4; 630: if (i==dot) 631: return; 632: } 633: for (w=0; w<NBKP; w++) 634: if (bkptl[w].loc==0) { 635: bkptl[w].loc = dot; 636: return; 637: } 638: error(); 639: 640: /* run program */ 641: case 'r': 642: lastbp = 0; 643: if (pid) { 644: ptrace(EXIT, pid, 0, 0); 645: pid = 0; 646: } 647: if ((pid = fork())==0) { 648: ptrace(SETTRC, 0, 0, 0); 649: signal(SIGINT, 0); 650: signal(SIGINS, 0); 651: doexec(); 652: printf("Can't execute %s\n", symfil); 653: exit(0); 654: } 655: bpwait(0); 656: setbp(1); 657: ptrace(WUREGS, pid, 2*(512+ps), 0170000); 658: 659: case 'c': 660: if (pid==0) 661: error(); 662: setbp(0); 663: if (lastbp) { 664: w = lastbp; 665: ptrace(CONTIN, pid, 0, 0); 666: bpwait(1); 667: ptrace(WUSER, pid, w, 03); 668: ptrace(WUREGS, pid, 2*(512+ps), uregs[ps]&~020); 669: lastbp = 0; 670: } 671: ptrace(CONTIN, pid, 0, 0); 672: bpwait(1); 673: w = uregs[pc]-2; 674: for (i=0; i<NBKP; i++) 675: if (bkptl[i].loc == w) 676: break; 677: if (i >= NBKP) { 678: printf("%s\n", signals[signo]); 679: return; 680: } 681: lastbp = w; 682: ptrace(WUSER, pid, w, bkptl[i].ins); 683: ptrace(WUREGS, pid, 2*(512+pc), w); 684: ptrace(WUREGS, pid, 2*(512+ps), uregs[ps]|020); 685: printf("Breakpoint: "); 686: psymoff(w, 0777); 687: printf("\n"); 688: return; 689: } 690: error(); 691: } 692: 693: doexec() 694: { 695: extern _exectrap; 696: char *argl[32]; 697: register char *p, **ap; 698: register c; 699: 700: _exectrap++; 701: ap = argl; 702: *ap++ = symfil; 703: p = lp; 704: do { 705: while (*p==' ') 706: p++; 707: if (*p=='\n' || *p=='\0') 708: break; 709: *ap++ = p; 710: while (*p!=' ' && *p!='\n') 711: p++; 712: c = *p; 713: *p++ = '\0'; 714: } while (c != '\n'); 715: *ap++ = 0; 716: execv(symfil, argl); 717: } 718: 719: setbp(runflag) 720: { 721: register w, i1, l; 722: int i2; 723: 724: for (w=0; w<NBKP; w++) { 725: l = bkptl[w].loc; 726: if (l && (runflag||bkptl[w].ins==0)) { 727: i1 = ptrace(RUSER, pid, l, 0); 728: if (i1==04567) { /* jsr r5,... */ 729: i2 = ptrace(RUSER, pid, l+2, 0); 730: if (loccsv == i2+l+4) { /* jsr r5,csv */ 731: l =+ 4; 732: bkptl[w].loc = l; 733: bkptl[w].flag =| BADJST; 734: i1 = ptrace(RUSER, pid, l, 0); 735: } 736: } 737: bkptl[w].ins = i1; 738: ptrace(WUSER, pid, l, 03); 739: if (errno) { 740: printf("Can't set breakpoint "); 741: psymoff(bkptl[w].loc); 742: printf("\n"); 743: } 744: } 745: } 746: } 747: 748: bpwait(f) 749: { 750: extern int onintr(); 751: register w; 752: int stat; 753: 754: loop: 755: signal(SIGINT, 1); 756: while ((w = wait(&stat))!=pid && w != -1); 757: signal(SIGINT, onintr); 758: if (w == -1) { 759: ptrace(EXIT, pid, 0, 0); 760: pid = 0; 761: printf("Wait error\n"); 762: reset(); 763: } 764: if ((stat & 0377) != 0177) { 765: if (signo = stat&0177) 766: printf("%s\n", signals[signo]); 767: printf("Process terminated.\n"); 768: if (pid == w) { 769: pid = 0; 770: reset(); 771: } 772: goto loop; 773: } 774: signo = stat>>8; 775: collinfo(); 776: if (signo!=SIGTRC) { 777: printf("%s\n", signals[signo]); 778: reset(); 779: } 780: } 781: 782: collinfo() 783: { 784: register i; 785: 786: for (i=0; i<9; i++) 787: uregs[reglist[i].roffs] = 788: ptrace(RUREGS, pid, 2*(512+reglist[i].roffs), 0); 789: setstack(); 790: } 791: 792: symlook(symstr) 793: char *symstr; 794: { 795: register i; 796: register symv; 797: 798: symset(); 799: if (fsymbol[0]==0) { 800: while(symget()) { 801: if (eqstr(symbol, symstr)) { 802: savsym(); 803: return(1); 804: } 805: } 806: return(0); 807: } 808: while (symget()) { 809: /* wait for function symbol */ 810: if (symbol[0]!='~' || !eqstr(symbol, fsymbol)) 811: continue; 812: symv = symval; 813: while (symget()&& symbol[0]!='~' &&symflg!=037) 814: if (eqstr(symbol, symstr)) 815: return(localsym(symv)); 816: return(0); 817: } 818: } 819: 820: localsym(s) 821: { 822: register i, xr5; 823: 824: /* label, static */ 825: if (symflg>=2 && symflg<=4) { 826: ssymval = symval; 827: return(1); 828: } 829: /* auto, arg */ 830: if (symflg==1) { 831: for (i=0; i<callev; i++) 832: if (entpt[i]==s) { 833: ssymval = symval+callist[i]; 834: return(1); 835: } 836: return(0); 837: } 838: /* register */ 839: if (symflg==20) { 840: for (i=0; i<callev; i++) 841: if (entpt[i]==s) { 842: if (i==0) { 843: return(0); /* temp, no reg lvalue */ 844: } 845: ssymval = callist[i-1] - 10 + 2*symval; 846: return(1); 847: } 848: return(0); 849: } 850: return(0); 851: } 852: 853: eqstr(as1, as2) 854: int *as1, *as2; 855: { 856: register char *s1, *s2, *es1; 857: 858: s1 = as1; 859: s2 = as2; 860: for (es1 = s1+8; s1 < es1; ) 861: if (*s1++ != *s2++) 862: return(0); 863: return(1); 864: } 865: 866: vallook(value) 867: char *value; 868: { 869: register char *diff; 870: 871: diff = 0177777; 872: symset(); 873: while (symget()) 874: if (symflg&040 && value-symval<=diff) { 875: if (symflg==1 && value!=symval) 876: continue; 877: savsym('_'); 878: diff = value-symval; 879: } 880: return(diff); 881: } 882: 883: get(aaddr, space) 884: char *aaddr; 885: { 886: int w; 887: register int w1; 888: register char *addr; 889: 890: addr = aaddr; 891: if (pid) { /* tracing on? */ 892: w = ptrace(space==DSP?RUSER:RIUSER, pid, addr, 0); 893: if (addr&01) { 894: w1 = ptrace(space==DSP?RUSER:RIUSER, pid, addr+1, 0); 895: w = (w>>8)&0377 | (w1<<8); 896: } 897: errflg = errno; 898: return(w); 899: } 900: w = 0; 901: if (idsep==0&&addr<regbuf->u_tsize || idsep&&space==ISP) { 902: seek(fsym, addr+020, 0); 903: if (read(fsym, &w, 2) != 2) 904: errflg++; 905: return(w); 906: } 907: if (addr < rtsize+regbuf->u_dsize) { 908: if (idsep==0) 909: addr =- rtsize; 910: } else if (-addr < regbuf->u_ssize) 911: addr =+ regbuf->u_dsize + regbuf->u_ssize; 912: else 913: errflg++; 914: seek(fcore, addr+1024, 0); 915: if (read(fcore, &w, 2) < 2) 916: errflg++; 917: return(w); 918: } 919: 920: symset() 921: { 922: symct = symlen; 923: symptr = symbuf; 924: seek(fsym, symoff, 0); 925: } 926: 927: symget() 928: { 929: register int *p, *q; 930: if ((symct =- 12) < 0) 931: return(0); 932: if (symptr < &symbuf[symcor]) { 933: p = symptr; 934: for (q=symbol; q <= &symval;) 935: *q++ = *p++; 936: symptr = p; 937: return(1); 938: } 939: return(read(fsym, symbol, 12) == 12); 940: } 941: 942: savsym(skip) 943: { 944: register int ch; 945: register char *p, *q; 946: 947: p = symbol; 948: q = ssymbol; 949: while (p<symbol+8 && (ch = *p++)) { 950: if (ch == skip) 951: continue; 952: *q++ = ch; 953: } 954: while (q < ssymbol+8) 955: *q++ = '\0'; 956: ssymflg = symflg; 957: ssymval = symval; 958: } 959: 960: onintr() 961: { 962: putchar('\n'); 963: errflg++; 964: reset(); 965: }