frame.c (2290B)
1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 #include <mach.h> 5 6 typedef struct LocRegs LocRegs; 7 struct LocRegs 8 { 9 Regs r; 10 Regs *oldregs; 11 Map *map; 12 u64int *val; 13 }; 14 15 static int 16 locregrw(Regs *regs, char *name, u64int *val, int isr) 17 { 18 int i; 19 LocRegs *lr; 20 21 lr = (LocRegs*)regs; 22 i = windindex(name); 23 if(i == -1) 24 return lr->oldregs->rw(lr->oldregs, name, val, isr); 25 if(isr){ 26 *val = lr->val[i]; 27 return 0; 28 }else{ 29 werrstr("saved registers are immutable"); 30 return -1; 31 } 32 } 33 34 int 35 stacktrace(Map *map, Regs *regs, Tracer trace) 36 { 37 char *rname; 38 int i, ipc, ret; 39 u64int nextpc, pc, v; 40 u64int *cur, *next; 41 LocRegs lr; 42 Symbol s, *sp; 43 44 /* 45 * Allocate location arrays. 46 */ 47 ret = -1; 48 cur = malloc(mach->nwindreg*sizeof(cur[0])); 49 next = malloc(mach->nwindreg*sizeof(cur[0])); 50 if(cur==nil || next==nil) 51 goto out; 52 53 /* 54 * Initialize current registers using regs. 55 */ 56 if(rget(regs, mach->pc, &pc) < 0){ 57 werrstr("cannot fetch initial pc: %r"); 58 goto out; 59 } 60 61 for(i=0; i<mach->nwindreg; i++){ 62 rname = mach->windreg[i]; 63 if(rget(regs, rname, &v) < 0) 64 v = ~(ulong)0; 65 cur[i] = v; 66 } 67 68 ipc = windindex(mach->pc); 69 ret = 0; 70 71 /* set up cur[i]==next[i] for unwindframe */ 72 memmove(next, cur, mach->nwindreg*sizeof(next[0])); 73 for(;;){ 74 sp = &s; 75 if(findsym(locaddr(pc), CTEXT, &s) < 0) 76 sp = nil; 77 78 lr.r.rw = locregrw; 79 lr.oldregs = regs; 80 lr.val = cur; 81 lr.map = map; 82 if((i = unwindframe(map, &lr.r, next, sp)) >= 0) 83 nextpc = next[ipc]; 84 else 85 nextpc = ~(ulong)0; 86 if((*trace)(map, &lr.r, pc, nextpc, sp, ++ret) <= 0) 87 break; 88 if(i < 0) 89 break; 90 if(sp){ 91 if(strcmp(sp->name, "main") == 0 92 || strcmp(sp->name, "procscheduler") == 0 93 || strcmp(sp->name, "threadstart") == 0) 94 break; 95 } 96 pc = nextpc; 97 memmove(cur, next, mach->nwindreg*sizeof(cur[0])); 98 } 99 100 out: 101 free(cur); 102 free(next); 103 return ret; 104 } 105 106 int 107 windindex(char *reg) 108 { 109 char **p; 110 int i; 111 112 p = mach->windreg; 113 for(i=0; i<mach->nwindreg; i++) 114 if(strcmp(p[i], reg) == 0) 115 return i; 116 werrstr("%s is not a winding register", reg); 117 return -1; 118 } 119 120 Loc* 121 windreglocs(void) 122 { 123 int i; 124 Loc *loc; 125 126 loc = malloc(mach->nwindreg*sizeof(loc[0])); 127 if(loc == nil) 128 return nil; 129 for(i=0; i<mach->nwindreg; i++){ 130 loc[i].type = LREG; 131 loc[i].reg = mach->windreg[i]; 132 } 133 return loc; 134 }