# /* C debugger */ #include "/usr/sys/param.h" #include "/usr/sys/user.h" #define DSP 0 #define ISP 1 #define NBKP 10 #define SYMSIZ 12*400 #define BADJST 01 int fcore; int errno; int fsym; int symoff; char *lp; int errflg; int symlen; int symct; int symcor; int symbuf[SYMSIZ]; int *symptr; struct { int loc; int ins; int count; int flag; } bkptl[NBKP]; int lastbp; char symbol[8]; int symflg; int symval; char tsym[8]; char fsymbol[10]; char ssymbol[8]; int ssymflg; int ssymval; int signo; char line[128]; int regbuf[512]; char **uregs ®buf[512]; char *rtsize; int loccsv; int locsr5; #define RUSER 1 #define RIUSER 2 #define WUSER 4 #define RUREGS 3 #define WUREGS 6 #define SETTRC 0 #define CONTIN 7 #define EXIT 8 #define ps -1 #define pc -2 #define sp -6 #define r5 -9 #define r4 -10 #define r3 -11 #define r2 -12 #define r1 -5 #define r0 -3 struct reglist { char *rname; int roffs; } reglist[] { "ps", ps, "pc", pc, "sp", sp, "r5", r5, "r4", r4, "r3", r3, "r2", r2, "r1", r1, "r0", r0, }; struct sfregs { int junk[2]; int fpsr; float sfr[6]; }; struct lfregs { int junk[2]; int fpsr; double lfr[6]; }; int frnames[] { 0, 3, 4, 5, 1, 2 }; int dot; int tdot; int dotinc 2; int lastcom '/'; int lastype 'o'; int modifier; char *symfil "a.out"; char *corfil "core"; int callist[50]; int entpt[50]; int callev; int pid; int adrflg; int idsep; char *signals[] { "", "Hangup", "Interrupt", "Quit", "Illegal instruction", "Trace/BTP", "IOT", "EMT", "Floating exception", "Killed", "Bus error", "Memory fault", "Bad system call", "", "", "", }; main(argc, argv) char **argv; { int onintr(); if (argc>1) symfil = argv[1]; if (argc>2) corfil = argv[2]; fcore = open(corfil, 0); if ((fsym = open(symfil, 0)) < 0) { printf("%s not found\n", symfil); return; } read(fsym, regbuf, 020); if (regbuf[0]==0411) /* I/D separated */ idsep++; else if (regbuf[0]!=0410 && regbuf[0]!=0407) { /* magic */ printf("Bad format: %s\n", symfil); return; } symoff = regbuf[1] + regbuf[2]; symlen = regbuf[4]; if (regbuf[7] != 1) symoff =<< 1; symoff =+ 020; seek(fsym, symoff, 0); symcor = read(fsym, symbuf, sizeof symbuf); if (symcor>0) symoff =+ symcor; symcor =>> 1; read(fcore, regbuf, 1024); signo = regbuf[0].u_arg[0]&017; regbuf->u_tsize =<< 6; regbuf->u_dsize =<< 6; regbuf->u_ssize =<< 6; rtsize = (regbuf->u_tsize+017777) & ~017777; if (symlook("csv\0\0\0\0")) loccsv = ssymval; if (symlook("savr5\0\0\0")) locsr5 = ssymval; setstack(); signal(SIGINS, onintr); setexit(); signal(SIGINT, onintr); loop: if (errflg) { printf("?\n"); errflg = 0; } lp = line; while ((*lp = getchar()) != '\n') if (*lp++ == '\0') { if (pid) ptrace(EXIT, pid, 0, 0); return; } lp = line; command(); goto loop; } command() { register n; adrflg = expr(); if (errflg) return; n = getcnt(); if (lastcom=='$') lastcom = '/'; if (*lp == '\n') { if (!adrflg) dot =+ dotinc; } else lastcom = *lp++; modifier = 0; if (*lp != '\n') modifier = *lp++; if (lastcom=='%' && modifier=='r') { runcom(); return; } if (*lp != '\n') { errflg++; return; } if (adrflg) dot = tdot; while(n) { scommand(n); if (errflg) return; if (--n) dot =+ dotinc; } } scommand(n) { register w, c; double fw; struct { int i[4]; }; int onintr(); switch(lastcom) { case '/': w = cget(dot, DSP); if (modifier) lastype = modifier; switch(lastype) { case 'o': printf("%.1o\n", w); dotinc = 2; return; case 'i': printf("%d\n", w); dotinc = 2; return; case 'f': fw = 0; fw.i[0] = w; fw.i[1] = cget(dot+2, DSP); printf("%e\n", fw); dotinc = 4; return; case 'd': fw.i[0] = w; fw.i[1] = cget(dot+2, DSP); fw.i[2] = cget(dot+4, DSP); fw.i[3] = cget(dot+6, DSP); printf("%e\n", fw); dotinc = 8; return; } errflg++; return; case '\\': printf("%.1o\n", cget(dot, DSP)&0377); dotinc = 1; return; case '=': printf("%.1o\n", dot); return; case '\'': printc(cget(dot, DSP) & 0377); if (n<=1) putchar('\n'); dotinc = 1; return; case '"': w = cget(dot, DSP); while(c = cget(w++, DSP)&0377) printc(c); putchar('\n'); return; case '&': psymoff(cget(dot, DSP), 0100000); printf("\n"); return; case '$': printf("%s\n", signals[signo]); printtrace(); return; case '?': printins(0); printf("\n"); return; case '%': runcom(); signal(SIGINT, onintr); return; } errflg++; } getcnt() { register t1, t2; if (*lp != ',') return(1); lp++; t1 = tdot; if (expr() == 0) { tdot = t1; return(1); } t2 = tdot; tdot = t1; return(t2); } cget(n, space) { register w; w = get(n, space); if (errflg) reset(); return(w); } printc(c) { if (c<' ' || c>'~') printf("\\%o", c); else printf("%c", c); } expr() { int i, t1, t2, donef, lastop, b; tdot = 0; adrflg = 0; lastop = '+'; ssymval = 0; donef = 0; loop: fsymbol[0] = 0; if (symchar(0)) { adrflg++; symcollect('_'); if (*lp++==':' && symchar(0)) { for (i=0; i<8; i++) fsymbol[i] = tsym[i]; fsymbol[0] = '~'; symcollect(0); } else lp--; if (symlook(tsym) == 0) { errflg++; reset(); } goto loop; } if (*lp>='0' && *lp<='9') { adrflg++; ssymval = 0; if (*lp == '0') b = 8; else b = 10; while (*lp>='0' && *lp<='9') { ssymval =* b; ssymval =+ *lp++ -'0'; } goto loop; } switch (*lp) { default: donef++; case '+': case '-': switch(lastop) { case '+': tdot =+ ssymval; goto op; case '-': tdot =- ssymval; op: if (donef) return(adrflg); else lastop = *lp++; } goto loop; case ' ': case '\t': lp++; goto loop; case '[': lp++; t1 = ssymval; t2 = tdot; if (expr() == 0) tdot = 0; ssymval = cget(t1 + (tdot<<1), DSP); tdot = t2; if (*lp == ']') lp++; goto loop; } } symcollect(c) { register char *p; p = tsym; if (c) *p++ = c; while (symchar(1)) { if (p < &tsym[8]) *p++ = *lp; lp++; } while (p < &tsym[8]) *p++ = 0; } symchar(dig) { if (*lp>='a'&&*lp<='z' || *lp=='_') return(1); if (dig && *lp>='0' && *lp<='9') return(1); return(0); } error() { errflg++; reset(); } printtrace() { int tpc, tr5, narg, argp, i; if (modifier=='r') { printregs(); return; } if (modifier=='f' || modifier=='d') { printfregs(); return; } tpc = uregs[pc]; tr5 = uregs[r5]; if (locsr5) if (narg = get(locsr5, DSP)) { tr5 = narg; } callev = 0; while (errflg == 0) { narg = findroutine(tpc, tr5); printf("%2d: %.8s(", callev, ssymbol); if (--narg >= 0) printf("%.1o", get(tr5+4, DSP)); argp = tr5+4; while(--narg >= 0) printf(",%.1o", get(argp =+ 2, DSP)); printf(")\n"); tpc = get(tr5+2, DSP); if (callev < 50) { entpt[callev] = ssymval; callist[callev++] = tr5; } if ((tr5 = get(tr5, DSP)) == 0) break; } } setstack() { register int tpc, tr5, i; tpc = uregs[pc]; tr5 = uregs[r5]; if (locsr5) if (i = get(locsr5, DSP)) { tr5 = i; } callev = 0; while (errflg == 0) { findroutine(tpc, tr5); tpc = get(tr5+2, DSP); if (callev >= 50) break; entpt[callev] = ssymval; callist[callev++] = tr5; if ((tr5 = get(tr5, DSP)) == 0) break; } errflg = 0; } printfregs() { register i; double f; printf("fpsr %.1o\n", regbuf[0].fpsr); for (i=0; i<6; i++) { if (regbuf[0].fpsr&0200) /* long mode */ f = regbuf[0].lfr[frnames[i]]; else f = regbuf[0].sfr[frnames[i]]; printf("fr%d %e\n", i, f); } } printregs() { register struct reglist *p; register char *v, *d; for (p=reglist; p < ®list[9]; p++) { printf("%s %.1o", p->rname, v=uregs[p->roffs]); d = vallook(v); if (d < 010000) { printf(" %.8s", ssymbol); if (d) printf("+%.1o", d); } printf("\n"); } } findroutine(rpc, rr5) { register callpt, inst, narg; callpt = get(rr5+2, DSP); if ((inst=get(callpt-4, ISP)) == 04737) /* jsr pc,*$... */ narg = 1; else if ((inst&~077)==04700) /* jsr pc,... */ narg = 0; else { errflg++; return(0); } inst = vallook((inst==04767?callpt:0) + get(callpt-2, ISP)); if (inst) { ssymbol[0] = '?'; ssymbol[1] = 0; ssymval = 0; } inst = get(callpt, ISP); if (inst == 05726) /* tst (sp)+ */ return(narg+1); if (inst == 022626) /* cmp (sp)+,(sp)+ */ return(narg+2); if (inst == 062706) /* add $n,sp */ return(narg+get(callpt+2, ISP)/2); return(narg); } runcom() { int stat; register w, i; switch(modifier) { /* delete breakpoint */ case 'd': if (adrflg==0) error(); for (w=0; w= NBKP) { printf("%s\n", signals[signo]); return; } lastbp = w; ptrace(WUSER, pid, w, bkptl[i].ins); ptrace(WUREGS, pid, 2*(512+pc), w); ptrace(WUREGS, pid, 2*(512+ps), uregs[ps]|020); printf("Breakpoint: "); psymoff(w, 0777); printf("\n"); return; } error(); } doexec() { extern _exectrap; char *argl[32]; register char *p, **ap; register c; _exectrap++; ap = argl; *ap++ = symfil; p = lp; do { while (*p==' ') p++; if (*p=='\n' || *p=='\0') break; *ap++ = p; while (*p!=' ' && *p!='\n') p++; c = *p; *p++ = '\0'; } while (c != '\n'); *ap++ = 0; execv(symfil, argl); } setbp(runflag) { register w, i1, l; int i2; for (w=0; w>8; collinfo(); if (signo!=SIGTRC) { printf("%s\n", signals[signo]); reset(); } } collinfo() { register i; for (i=0; i<9; i++) uregs[reglist[i].roffs] = ptrace(RUREGS, pid, 2*(512+reglist[i].roffs), 0); setstack(); } symlook(symstr) char *symstr; { register i; register symv; symset(); if (fsymbol[0]==0) { while(symget()) { if (eqstr(symbol, symstr)) { savsym(); return(1); } } return(0); } while (symget()) { /* wait for function symbol */ if (symbol[0]!='~' || !eqstr(symbol, fsymbol)) continue; symv = symval; while (symget()&& symbol[0]!='~' &&symflg!=037) if (eqstr(symbol, symstr)) return(localsym(symv)); return(0); } } localsym(s) { register i, xr5; /* label, static */ if (symflg>=2 && symflg<=4) { ssymval = symval; return(1); } /* auto, arg */ if (symflg==1) { for (i=0; i>8)&0377 | (w1<<8); } errflg = errno; return(w); } w = 0; if (idsep==0&&addru_tsize || idsep&&space==ISP) { seek(fsym, addr+020, 0); if (read(fsym, &w, 2) != 2) errflg++; return(w); } if (addr < rtsize+regbuf->u_dsize) { if (idsep==0) addr =- rtsize; } else if (-addr < regbuf->u_ssize) addr =+ regbuf->u_dsize + regbuf->u_ssize; else errflg++; seek(fcore, addr+1024, 0); if (read(fcore, &w, 2) < 2) errflg++; return(w); } symset() { symct = symlen; symptr = symbuf; seek(fsym, symoff, 0); } symget() { register int *p, *q; if ((symct =- 12) < 0) return(0); if (symptr < &symbuf[symcor]) { p = symptr; for (q=symbol; q <= &symval;) *q++ = *p++; symptr = p; return(1); } return(read(fsym, symbol, 12) == 12); } savsym(skip) { register int ch; register char *p, *q; p = symbol; q = ssymbol; while (p