aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2009-01-09 15:52:43 -0800
committerRuss Cox <rsc@golang.org>2009-01-09 15:52:43 -0800
commita3ed4e716a61ffc8cbaba6094b82832a37d74222 (patch)
treeb19d3e5ce89087abec1452840fb7d1bff44b064d /src/runtime
parentcbd08ed2615e9393460760b8d3f2bd352b7e95f5 (diff)
downloadgo-a3ed4e716a61ffc8cbaba6094b82832a37d74222.tar.xz
add sys.caller
R=r DELTA=139 (101 added, 38 deleted, 0 changed) OCL=22462 CL=22466
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/rt2_amd64.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/src/runtime/rt2_amd64.c b/src/runtime/rt2_amd64.c
index 9c8436f177..62c74bf51b 100644
--- a/src/runtime/rt2_amd64.c
+++ b/src/runtime/rt2_amd64.c
@@ -69,3 +69,58 @@ traceback(byte *pc0, byte *sp, G *g)
}
prints("...\n");
}
+
+// func caller(n int) (pc uint64, file string, line int, ok bool)
+void
+sys·caller(int32 n, uint64 retpc, string retfile, int32 retline, bool retbool)
+{
+ uint64 pc;
+ byte *sp;
+ Stktop *stk;
+ Func *f;
+
+ // our caller's pc, sp.
+ sp = (byte*)&n;
+ pc = *(uint64*)(sp-8);
+ if((f = findfunc(pc)) == nil) {
+ error:
+ retpc = 0;
+ retline = 0;
+ retfile = nil;
+ retbool = false;
+ FLUSH(&retpc);
+ FLUSH(&retfile);
+ FLUSH(&retline);
+ FLUSH(&retbool);
+ return;
+ }
+
+ // now unwind n levels
+ stk = (Stktop*)g->stackbase;
+ while(n-- > 0) {
+ while(pc == (uint64)retfromnewstack) {
+ sp = stk->oldsp;
+ stk = (Stktop*)stk->oldbase;
+ pc = *(uint64*)(sp+8);
+ sp += 16;
+ }
+
+ if(f->frame < 8) // assembly functions lie
+ sp += 8;
+ else
+ sp += f->frame;
+
+ pc = *(uint64*)(sp-8);
+ if(pc <= 0x1000 || (f = findfunc(pc)) == nil)
+ goto error;
+ }
+
+ retpc = pc;
+ retfile = f->src;
+ retline = funcline(f, pc-1);
+ retbool = true;
+ FLUSH(&retpc);
+ FLUSH(&retfile);
+ FLUSH(&retline);
+ FLUSH(&retbool);
+}