summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2008-12-03 14:20:23 -0800
committerRuss Cox <rsc@golang.org>2008-12-03 14:20:23 -0800
commitba6aabb92da924bfdcc9ae541c370bfee48185f8 (patch)
tree66e662352137d36fb3423aa77b5b48612729080d
parent1909fbebc26564e2dd317e93fe2d886d31068d6c (diff)
downloadgolang-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.c68
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");
}