plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }