| /* |
| * |
| * 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; i<mach->nwindreg; 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); |
| } |
| } |