#include #include #include #include typedef struct LocRegs LocRegs; struct LocRegs { Regs r; Regs *oldregs; Map *map; u64int *val; }; static int locregrw(Regs *regs, char *name, u64int *val, int isr) { int i; LocRegs *lr; lr = (LocRegs*)regs; i = windindex(name); if(i == -1) return lr->oldregs->rw(lr->oldregs, name, val, isr); if(isr){ *val = lr->val[i]; return 0; }else{ werrstr("saved registers are immutable"); return -1; } } int stacktrace(Map *map, Regs *regs, Tracer trace) { char *rname; int i, ipc, ret; u64int nextpc, pc, v; u64int *cur, *next; LocRegs lr; Symbol s, *sp; /* * Allocate location arrays. */ ret = -1; cur = malloc(mach->nwindreg*sizeof(cur[0])); next = malloc(mach->nwindreg*sizeof(cur[0])); if(cur==nil || next==nil) goto out; /* * Initialize current registers using regs. */ if(rget(regs, mach->pc, &pc) < 0){ werrstr("cannot fetch initial pc: %r"); goto out; } for(i=0; inwindreg; i++){ rname = mach->windreg[i]; if(rget(regs, rname, &v) < 0) v = ~(ulong)0; cur[i] = v; } ipc = windindex(mach->pc); ret = 0; /* set up cur[i]==next[i] for unwindframe */ memmove(next, cur, mach->nwindreg*sizeof(next[0])); for(;;){ sp = &s; if(findsym(locaddr(pc), CTEXT, &s) < 0) sp = nil; lr.r.rw = locregrw; lr.oldregs = regs; lr.val = cur; lr.map = map; if((i = unwindframe(map, &lr.r, next, sp)) >= 0) nextpc = next[ipc]; else nextpc = ~(ulong)0; if((*trace)(map, &lr.r, pc, nextpc, sp, ++ret) <= 0) break; if(i < 0) break; if(sp){ if(strcmp(sp->name, "main") == 0 || strcmp(sp->name, "procscheduler") == 0 || strcmp(sp->name, "threadstart") == 0) break; } pc = nextpc; memmove(cur, next, mach->nwindreg*sizeof(cur[0])); } out: free(cur); free(next); return ret; } int windindex(char *reg) { char **p; int i; p = mach->windreg; for(i=0; inwindreg; i++) if(strcmp(p[i], reg) == 0) return i; werrstr("%s is not a winding register", reg); return -1; } Loc* windreglocs(void) { int i; Loc *loc; loc = malloc(mach->nwindreg*sizeof(loc[0])); if(loc == nil) return nil; for(i=0; inwindreg; i++){ loc[i].type = LREG; loc[i].reg = mach->windreg[i]; } return loc; }