tframe.c - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       tframe.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 }