diff options
author | Russ Cox <rsc@golang.org> | 2008-12-03 14:20:23 -0800 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2008-12-03 14:20:23 -0800 |
commit | ba6aabb92da924bfdcc9ae541c370bfee48185f8 (patch) | |
tree | 66e662352137d36fb3423aa77b5b48612729080d | |
parent | 1909fbebc26564e2dd317e93fe2d886d31068d6c (diff) | |
download | golang-ba6aabb92da924bfdcc9ae541c370bfee48185f8.tar.gz |
clean stack trace code.
format is unchanged but shows all frames
(old loop stopped one frame early).
wreck=; 6.out
cannot convert type *main.S·interface2 to interface main.I·interface2: missing method Foo
throw: interface conversion
SIGSEGV: segmentation violation
Faulting address: 0x0
pc: 0x256d
throw+0x46 /home/rsc/go/src/runtime/runtime.c:68
throw(0x863a, 0x0)
hashmap+0x188 /home/rsc/go/src/runtime/iface.c:167
hashmap(0x8760, 0x0, 0x85b0, 0x0, 0x0, ...)
sys·ifaceT2I+0xa8 /home/rsc/go/src/runtime/iface.c:201
sys·ifaceT2I(0x8760, 0x0, 0x85b0, 0x0, 0x0, ...)
main·main+0x4e /home/rsc/go/src/runtime/rt0_amd64_darwin.s:87
main·main()
mainstart+0xf /home/rsc/go/src/runtime/rt0_amd64.s:70
mainstart()
sys·goexit /home/rsc/go/src/runtime/proc.c:110
sys·goexit()
R=r
DELTA=44 (5 added, 15 deleted, 24 changed)
OCL=20358
CL=20368
-rw-r--r-- | src/runtime/rt2_amd64.c | 68 |
1 files changed, 29 insertions, 39 deletions
diff --git a/src/runtime/rt2_amd64.c b/src/runtime/rt2_amd64.c index fd40cefef..9c8436f17 100644 --- a/src/runtime/rt2_amd64.c +++ b/src/runtime/rt2_amd64.c @@ -9,64 +9,49 @@ extern int32 debug; extern uint8 end; void -traceback(uint8 *pc, uint8 *sp, void* r15) +traceback(byte *pc0, byte *sp, G *g) { - uint8* callpc; - int32 counter; - int32 i; - string name; + Stktop *stk; + uint64 pc; + int32 i, n; Func *f; - G g; - Stktop *stktop; - // store local copy of per-process data block that we can write as we unwind - mcpy((byte*)&g, (byte*)r15, sizeof(G)); + pc = (uint64)pc0; - // if the PC is zero, it's probably due to a nil function pointer. - // pop the failed frame. - if(pc == nil) { - pc = ((uint8**)sp)[0]; + // If the PC is zero, it's likely a nil function call. + // Start in the caller's frame. + if(pc == 0) { + pc = *(uint64*)sp; sp += 8; } - counter = 0; - for(;;){ - callpc = pc; - if((uint8*)retfromnewstack == pc) { - // call site is retfromnewstack(); pop to earlier stack block to get true caller - stktop = (Stktop*)g.stackbase; - g.stackbase = stktop->oldbase; - g.stackguard = stktop->oldguard; - sp = stktop->oldsp; - pc = ((uint8**)sp)[1]; - sp += 16; // two irrelevant calls on stack - morestack, plus the call morestack made - continue; + stk = (Stktop*)g->stackbase; + for(n=0; n<100; n++) { + while(pc == (uint64)retfromnewstack) { + // pop to earlier stack block + sp = stk->oldsp; + stk = (Stktop*)stk->oldbase; + pc = *(uint64*)(sp+8); + sp += 16; // two irrelevant calls on stack: morestack plus its call } - f = findfunc((uint64)callpc); + f = findfunc(pc); if(f == nil) { - printf("%p unknown pc\n", callpc); + printf("%p unknown pc\n", pc); return; } - name = f->name; if(f->frame < 8) // assembly funcs say 0 but lie sp += 8; else sp += f->frame; - if(counter++ > 100){ - prints("stack trace terminated\n"); - break; - } - if((pc = ((uint8**)sp)[-1]) <= (uint8*)0x1000) - break; // print this frame // main+0xf /home/rsc/go/src/runtime/x.go:23 // main(0x1, 0x2, 0x3) - printf("%S", name); - if((uint64)callpc > f->entry) - printf("+%X", (uint64)callpc - f->entry); - printf(" %S:%d\n", f->src, funcline(f, (uint64)callpc-1)); // -1 to get to CALL instr. - printf("\t%S(", name); + printf("%S", f->name); + if(pc > f->entry) + printf("+%X", pc - f->entry); + printf(" %S:%d\n", f->src, funcline(f, pc-1)); // -1 to get to CALL instr. + printf("\t%S(", f->name); for(i = 0; i < f->args; i++) { if(i != 0) prints(", "); @@ -77,5 +62,10 @@ traceback(uint8 *pc, uint8 *sp, void* r15) } } prints(")\n"); + + pc = *(uint64*)(sp-8); + if(pc <= 0x1000) + return; } + prints("...\n"); } |