Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mach.h>
6 typedef struct LocRegs LocRegs;
7 struct LocRegs
8 {
9 Regs r;
10 Regs *oldregs;
11 Map *map;
12 u64int *val;
13 };
15 static int
16 locregrw(Regs *regs, char *name, u64int *val, int isr)
17 {
18 int i;
19 LocRegs *lr;
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 }
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;
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;
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 }
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 }
68 ipc = windindex(mach->pc);
69 ret = 0;
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;
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 }
100 out:
101 free(cur);
102 free(next);
103 return ret;
106 int
107 windindex(char *reg)
109 char **p;
110 int i;
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;
120 Loc*
121 windreglocs(void)
123 int i;
124 Loc *loc;
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];
133 return loc;