// 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"; //typedef struct U U; //struct U { // uint8* stackguard; // uint8* stackbase; // uint8* istackguard; // uint8* istackbase; //}; typedef struct Stktop Stktop; struct Stktop { uint8* oldbase; uint8* oldsp; uint8* magic; uint8* oldguard; }; extern void _morestack(); extern void _endmorestack(); void traceback(uint8 *pc, uint8 *sp, void* r15) { int32 spoff; int8* spp; uint8* callpc; int32 counter; int32 i; int8* name; U u; Stktop *stktop; // store local copy of per-process data block that we can write as we unwind mcpy((byte*)&u, (byte*)r15, sizeof(U)); counter = 0; name = "panic"; for(;;){ callpc = pc; if((uint8*)_morestack < pc && pc < (uint8*)_endmorestack) { // call site in _morestack(); pop to earlier stack block to get true caller stktop = (Stktop*)u.stackbase; u.stackbase = stktop->oldbase; u.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) { 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"); /* print pc for next frame */ } }