| // Copyright 2009 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| #include "runtime.h" | |
| extern int32 debug; | |
| static int8 spmark[] = "\xa7\xf1\xd9\x2a\x82\xc8\xd8\xfe"; | |
| extern uint8 end; | |
| void | |
| traceback(uint8 *pc, uint8 *sp, void* r15) | |
| { | |
| int32 spoff; | |
| int8* spp; | |
| uint8* callpc; | |
| int32 counter; | |
| int32 i; | |
| int8* name; | |
| 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)); | |
| counter = 0; | |
| name = "panic"; | |
| 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; | |
| } | |
| /* find SP offset by stepping back through instructions to SP offset marker */ | |
| while(pc > (uint8*)0x1000+sizeof spmark-1) { | |
| if(pc >= &end) | |
| return; | |
| for(spp = spmark; *spp != '\0' && *pc++ == (uint8)*spp++; ) | |
| ; | |
| if(*spp == '\0'){ | |
| spoff = *pc++; | |
| spoff += *pc++ << 8; | |
| spoff += *pc++ << 16; | |
| name = (int8*)pc; | |
| sp += spoff + 8; | |
| break; | |
| } | |
| } | |
| if(counter++ > 100){ | |
| prints("stack trace terminated\n"); | |
| break; | |
| } | |
| if((pc = ((uint8**)sp)[-1]) <= (uint8*)0x1000) | |
| break; | |
| /* print this frame */ | |
| prints("0x"); | |
| sys·printpointer(callpc); | |
| prints("?zi\n"); | |
| prints("\t"); | |
| prints(name); | |
| prints("("); | |
| for(i = 0; i < 3; i++){ | |
| if(i != 0) | |
| prints(", "); | |
| sys·printint(((uint32*)sp)[i]); | |
| } | |
| prints(", ...)\n"); | |
| prints("\t"); | |
| prints(name); | |
| prints("("); | |
| for(i = 0; i < 3; i++){ | |
| if(i != 0) | |
| prints(", "); | |
| prints("0x"); | |
| sys·printpointer(((void**)sp)[i]); | |
| } | |
| prints(", ...)\n"); | |
| } | |
| } |