diff options
Diffstat (limited to 'src/pkg/runtime/arm/traceback.c')
-rw-r--r-- | src/pkg/runtime/arm/traceback.c | 86 |
1 files changed, 82 insertions, 4 deletions
diff --git a/src/pkg/runtime/arm/traceback.c b/src/pkg/runtime/arm/traceback.c index edddafe86..5d32980f6 100644 --- a/src/pkg/runtime/arm/traceback.c +++ b/src/pkg/runtime/arm/traceback.c @@ -4,17 +4,95 @@ #include "runtime.h" -// TODO(rsc): Move this into portable code, with calls to a -// machine-dependent isclosure() function. +static int32 +gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr *pcbuf, int32 m) +{ + byte *p; + int32 i, n, iter; + uintptr pc, lr, tracepc; + Stktop *stk; + Func *f; + + pc = (uintptr)pc0; + lr = (uintptr)lr0; + + // If the PC is zero, it's likely a nil function call. + // Start in the caller's frame. + if(pc == 0) { + pc = lr; + lr = 0; + } + + n = 0; + stk = (Stktop*)g->stackbase; + for(iter = 0; iter < 100 && n < m; iter++) { // iter avoids looping forever + if(pc == (uintptr)·lessstack) { + // Hit top of stack segment. Unwind to next segment. + pc = (uintptr)stk->gobuf.pc; + sp = stk->gobuf.sp; + lr = *(uintptr*)sp; + stk = (Stktop*)stk->stackbase; + continue; + } + if(pc <= 0x1000 || (f = findfunc(pc-4)) == nil) { + // TODO: Check for closure. + break; + } + + // Found an actual function worth reporting. + if(skip > 0) + skip--; + else if(pcbuf != nil) + pcbuf[n++] = pc; + else { + // Print during crash. + // main+0xf /home/rsc/go/src/runtime/x.go:23 + // main(0x1, 0x2, 0x3) + printf("%S", f->name); + if(pc > f->entry) + printf("+%p", (uintptr)(pc - f->entry)); + tracepc = pc; // back up to CALL instruction for funcline. + if(n > 0 && pc > f->entry) + tracepc -= sizeof(uintptr); + printf(" %S:%d\n", f->src, funcline(f, tracepc)); + printf("\t%S(", f->name); + for(i = 0; i < f->args; i++) { + if(i != 0) + prints(", "); + ·printhex(((uintptr*)sp)[1+i]); + if(i >= 4) { + prints(", ..."); + break; + } + } + prints(")\n"); + n++; + } + + if(lr == 0) + lr = *(uintptr*)sp; + pc = lr; + lr = 0; + if(f->frame >= 0) + sp += f->frame; + } + return n; +} void -traceback(byte *pc0, byte *sp, G *g) +traceback(byte *pc0, byte *sp, byte *lr, G *g) { + gentraceback(pc0, sp, lr, g, 0, nil, 100); } // func caller(n int) (pc uintptr, file string, line int, ok bool) int32 callers(int32 skip, uintptr *pcbuf, int32 m) { - return 0; + byte *pc, *sp; + + sp = getcallersp(&skip); + pc = ·getcallerpc(&skip); + + return gentraceback(pc, sp, 0, g, skip, pcbuf, m); } |