/* * * debugger * */ #include "defs.h" #include "fns.h" #define ptrace dbptrace extern int infile; extern int outfile; extern int maxpos; /* general printing routines ($) */ char *Ipath = INCDIR; static int tracetype; static void printfp(Map*, int); /* * callback on stack trace */ static int ptrace(Map *map, Regs *regs, u64int pc, u64int nextpc, Symbol *sym, int depth) { char buf[512]; USED(map); if(sym){ dprint("%s(", sym->name); printparams(sym, regs); dprint(") "); }else dprint("%#lux ", pc); printsource(pc); dprint(" called from "); symoff(buf, 512, nextpc, CTEXT); dprint("%s ", buf); /* printsource(nextpc); */ dprint("\n"); if(tracetype == 'C' && sym) printlocals(sym, regs); return depth<40; } static ulong *adrregvals; static int adrrw(Regs *regs, char *name, u64int *val, int isr) { int i; if((i = windindex(name)) == -1) return correg->rw(correg, name, val, isr); if(isr){ *val = adrregvals[i]; return 0; } werrstr("saved registers are immutable"); return -1; } Regs* adrregs(void) { int i; static Regs r; static u32int x; if(adrregvals== nil){ adrregvals = malloc(mach->nwindreg*sizeof(adrregvals[0])); if(adrregvals == nil) error("%r"); } for(i=0; inwindreg; i++){ if(get4(cormap, adrval+4*i, &x) < 0) error("%r"); adrregvals[i] = x; } r.rw = adrrw; return &r; } void printdollar(int modif) { int i; u32int u4; BKPT *bk; Symbol s; int stack; char *fname; char buf[512]; Regs *r; if (cntflg==0) cntval = -1; switch (modif) { case '<': if (cntval == 0) { while (readchar() != EOR) ; reread(); break; } if (rdc() == '<') stack = 1; else { stack = 0; reread(); } fname = getfname(); redirin(stack, fname); break; case '>': fname = getfname(); redirout(fname); break; case 'a': attachprocess(); break; /* maybe use this for lwpids? case 'A': attachpthread(); break; */ case 'k': kmsys(); break; case 'q': case 'Q': done(); case 'w': maxpos=(adrflg?adrval:MAXPOS); break; case 'S': printsym(); break; case 's': maxoff=(adrflg?adrval:MAXOFF); break; case 'm': printmap("? map", symmap); printmap("/ map", cormap); break; case 0: case '?': if (pid) dprint("pid = %d\n",pid); else prints("no process\n"); flushbuf(); case 'r': case 'R': printregs(modif); return; case 'f': case 'F': printfp(cormap, modif); return; case 'c': case 'C': tracetype = modif; if (adrflg) r = adrregs(); else r = correg; if(stacktrace(cormap, correg, ptrace) <= 0) error("no stack frame"); break; /*print externals*/ case 'e': for (i = 0; indexsym(i, &s)>=0; i++) { if (s.class==CDATA) if (s.loc.type==LADDR) if (get4(cormap, s.loc.addr, &u4) > 0) dprint("%s/%12t%#lux\n", s.name, (ulong)u4); } break; /*print breakpoints*/ case 'b': case 'B': for (bk=bkpthead; bk; bk=bk->nxtbkpt) if (bk->flag) { symoff(buf, 512, (WORD)bk->loc, CTEXT); dprint(buf); if (bk->count != 1) dprint(",%d", bk->count); dprint(":%c %s", bk->flag == BKPTTMP ? 'B' : 'b', bk->comm); } break; case 'M': fname = getfname(); if (machbyname(fname) == 0) dprint("unknown name\n");; break; default: error("bad `$' command"); } USED(r); } char * getfname(void) { static char fname[ARB]; char *p; if (rdc() == EOR) { reread(); return (0); } p = fname; do { *p++ = lastc; if (p >= &fname[ARB-1]) error("filename too long"); } while (rdc() != EOR); *p = 0; reread(); return (fname); } static void printfp(Map *map, int modif) { Regdesc *rp; int i; int ret; char buf[512]; for (i = 0, rp = mach->reglist; rp->name; rp += ret) { ret = 1; if (!(rp->flags&RFLT)) continue; ret = fpformat(map, rp, buf, sizeof(buf), modif); if (ret < 0) { werrstr("Register %s: %r", rp->name); error("%r"); } /* double column print */ if (i&0x01) dprint("%40t%-8s%-12s\n", rp->name, buf); else dprint("\t%-8s%-12s", rp->name, buf); i++; } } void redirin(int stack, char *file) { char pfile[ARB]; if (file == 0) { iclose(-1, 0); return; } iclose(stack, 0); if ((infile = open(file, 0)) < 0) { strcpy(pfile, Ipath); strcat(pfile, "/"); strcat(pfile, file); if ((infile = open(pfile, 0)) < 0) { infile = STDIN; error("cannot open"); } } } void printmap(char *s, Map *map) { int i; if (!map) return; if (map == symmap) dprint("%s%12t`%s'\n", s, symfil==nil ? "-" : symfil); else if (map == cormap) dprint("%s%12t`%s'\n", s, corfil==nil ? "-" : corfil); else dprint("%s\n", s); for (i = 0; i < map->nseg; i++) { dprint("%s%8t%-16#lux %-16#lux %-16#lux %s\n", map->seg[i].name, map->seg[i].base, map->seg[i].base+map->seg[i].size, map->seg[i].offset, map->seg[i].file ? map->seg[i].file : ""); } } /* * dump the raw symbol table */ void printsym(void) { int i; Symbol *sp, s; for (i=0; indexsym(i, &s)>=0; i++){ sp = &s; switch(sp->type) { case 't': case 'l': dprint("%8#lux t %s\n", sp->loc.addr, sp->name); break; case 'T': case 'L': dprint("%8#lux T %s\n", sp->loc.addr, sp->name); break; case 'D': case 'd': case 'B': case 'b': case 'a': case 'p': case 'm': dprint("%8#lux %c %s\n", sp->loc.addr, sp->type, sp->name); break; default: break; } } } #define STRINGSZ 128 /* * print the value of dot as file:line */ void printsource(long dot) { char str[STRINGSZ]; if (fileline(dot, str, STRINGSZ) >= 0) dprint("%s", str); } void printpc(void) { char buf[512]; u64int u; if(rget(correg, mach->pc, &u) < 0) error("%r"); dot = u; if(dot){ printsource((long)dot); printc(' '); symoff(buf, sizeof(buf), (long)dot, CTEXT); dprint("%s/", buf); if (mach->das(cormap, dot, 'i', buf, sizeof(buf)) < 0) error("%r"); dprint("%16t%s\n", buf); } } void printlocals(Symbol *fn, Regs *regs) { int i; u32int v; Symbol s; for (i = 0; indexlsym(fn, i, &s)>=0; i++) { if (s.class != CAUTO) continue; if(lget4(cormap, regs, s.loc, &v) >= 0) dprint("%8t%s.%s/%10t%#lux\n", fn->name, s.name, v); else dprint("%8t%s.%s/%10t?\n", fn->name, s.name); } } void printparams(Symbol *fn, Regs *regs) { int i; Symbol s; u32int v; int first = 0; for (i = 0; indexlsym(fn, i, &s)>=0; i++) { if (s.class != CPARAM) continue; if (first++) dprint(", "); if(lget4(cormap, regs, s.loc, &v) >= 0) dprint("%s=%#lux", s.name, v); else dprint("%s=?", s.name); } }