// 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" // TODO(rsc): Move this into portable code, with calls to a // machine-dependent isclosure() function. void traceback(byte *pc0, byte *sp, G *g) { // Stktop *stk; // uintptr pc; // int32 i, n; // Func *f; // byte *p; // pc = (uintptr)pc0; // // If the PC is zero, it's likely a nil function call. // // Start in the caller's frame. // if(pc == 0) { // pc = *(uintptr*)sp; // sp += sizeof(uintptr); // } // stk = (Stktop*)g->stackbase; // for(n=0; n<100; n++) { // while(pc == (uintptr)retfromnewstack) { // // pop to earlier stack block // sp = stk->oldsp; // stk = (Stktop*)stk->oldbase; // pc = *(uintptr*)(sp+sizeof(uintptr)); // sp += 2*sizeof(uintptr); // two irrelevant calls on stack: morestack plus its call // } // f = findfunc(pc); // if(f == nil) { // // dangerous, but poke around to see if it is a closure // p = (byte*)pc; // // ADDL $xxx, SP; RET // if(p[0] == 0x81 && p[1] == 0xc4 && p[6] == 0xc3) { // sp += *(uint32*)(p+2) + 8; // pc = *(uintptr*)(sp - 8); // if(pc <= 0x1000) // return; // continue; // } // printf("%p unknown pc\n", pc); // return; // } // if(f->frame < sizeof(uintptr)) // assembly funcs say 0 but lie // sp += sizeof(uintptr); // else // sp += f->frame; // // print this frame // // 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)); // 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(", "); // runtime·printhex(((uint32*)sp)[i]); // if(i >= 4) { // prints(", ..."); // break; // } // } // prints(")\n"); // pc = *(uintptr*)(sp-sizeof(uintptr)); // if(pc <= 0x1000) // return; // } // prints("...\n"); } // func caller(n int) (pc uintptr, file string, line int, ok bool) void runtime·Caller(int32 n, uintptr retpc, String retfile, int32 retline, bool retbool) { // uintptr pc; // byte *sp; // byte *p; // Stktop *stk; // Func *f; // // our caller's pc, sp. // sp = (byte*)&n; // pc = *((uintptr*)sp - 1); // if((f = findfunc(pc)) == nil) { // error: // retpc = 0; // retline = 0; // retfile = emptystring; // retbool = false; // FLUSH(&retpc); // FLUSH(&retfile); // FLUSH(&retline); // FLUSH(&retbool); // return; // } // // now unwind n levels // stk = (Stktop*)g->stackbase; // while(n-- > 0) { // while(pc == (uintptr)retfromnewstack) { // sp = stk->oldsp; // stk = (Stktop*)stk->oldbase; // pc = *((uintptr*)sp + 1); // sp += 2*sizeof(uintptr); // } // if(f->frame < sizeof(uintptr)) // assembly functions lie // sp += sizeof(uintptr); // else // sp += f->frame; // loop: // pc = *((uintptr*)sp - 1); // if(pc <= 0x1000 || (f = findfunc(pc)) == nil) { // // dangerous, but let's try this. // // see if it is a closure. // p = (byte*)pc; // // ADDL $xxx, SP; RET // if(p[0] == 0x81 && p[1] == 0xc4 && p[6] == 0xc3) { // sp += *(uint32*)(p+2) + sizeof(uintptr); // goto loop; // } // goto error; // } // } // retpc = pc; // retfile = f->src; // retline = funcline(f, pc-1); // retbool = true; // FLUSH(&retpc); // FLUSH(&retfile); // FLUSH(&retline); // FLUSH(&retbool); }