]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: initialize traceback variables earlier
authorKeith Randall <khr@golang.org>
Tue, 30 Sep 2014 04:21:36 +0000 (21:21 -0700)
committerKeith Randall <khr@golang.org>
Tue, 30 Sep 2014 04:21:36 +0000 (21:21 -0700)
Our traceback code needs to know the PC of several special
functions, including goexit, mcall, etc.  Make sure that
these PCs are initialized before any traceback occurs.

Fixes #8766

LGTM=rsc
R=golang-codereviews, rsc, khr, bradfitz
CC=golang-codereviews
https://golang.org/cl/145570043

src/runtime/proc.c
src/runtime/runtime.h
src/runtime/traceback.go

index 1f0a79098b2d4246d371bea3780a51d68c6e03f2..e84dc1d0487da1d4950c072fef191c806e717c01 100644 (file)
@@ -131,6 +131,7 @@ runtime·schedinit(void)
 
        runtime·sched.maxmcount = 10000;
 
+       runtime·tracebackinit();
        runtime·symtabinit();
        runtime·stackinit();
        runtime·mallocinit();
index 3a6d3e3262535e18118257f99d1e6452050a0157..aa300d7bb8eacef89dfca5ba61f4813d7ff1e2f5 100644 (file)
@@ -841,6 +841,7 @@ void        runtime·mpreinit(M*);
 void   runtime·minit(void);
 void   runtime·unminit(void);
 void   runtime·signalstack(byte*, int32);
+void   runtime·tracebackinit(void);
 void   runtime·symtabinit(void);
 Func*  runtime·findfunc(uintptr);
 int32  runtime·funcline(Func*, uintptr, String*);
index a93c42186bd8c48418aaccd46082d802ebfbeb79..24dc3eea951d6831e94425ef57d48a59c5ac12f1 100644 (file)
@@ -31,20 +31,36 @@ import "unsafe"
 const usesLR = GOARCH != "amd64" && GOARCH != "amd64p32" && GOARCH != "386"
 
 var (
-       deferprocPC = funcPC(deferproc)
-       goexitPC    = funcPC(goexit)
-       jmpdeferPC  = funcPC(jmpdefer)
-       mcallPC     = funcPC(mcall)
-       morestackPC = funcPC(morestack)
-       mstartPC    = funcPC(mstart)
-       newprocPC   = funcPC(newproc)
-       newstackPC  = funcPC(newstack)
-       rt0_goPC    = funcPC(rt0_go)
-       sigpanicPC  = funcPC(sigpanic)
+       // initialized in tracebackinit
+       deferprocPC uintptr
+       goexitPC    uintptr
+       jmpdeferPC  uintptr
+       mcallPC     uintptr
+       morestackPC uintptr
+       mstartPC    uintptr
+       newprocPC   uintptr
+       rt0_goPC    uintptr
+       sigpanicPC  uintptr
 
        externalthreadhandlerp uintptr // initialized elsewhere
 )
 
+func tracebackinit() {
+       // Go variable initialization happens late during runtime startup.
+       // Instead of initializing the variables above in the declarations,
+       // schedinit calls this function so that the variables are
+       // initialized and available earlier in the startup sequence.
+       deferprocPC = funcPC(deferproc)
+       goexitPC = funcPC(goexit)
+       jmpdeferPC = funcPC(jmpdefer)
+       mcallPC = funcPC(mcall)
+       morestackPC = funcPC(morestack)
+       mstartPC = funcPC(mstart)
+       newprocPC = funcPC(newproc)
+       rt0_goPC = funcPC(rt0_go)
+       sigpanicPC = funcPC(sigpanic)
+}
+
 // Traceback over the deferred function calls.
 // Report them like calls that have been invoked but not started executing yet.
 func tracebackdefers(gp *g, callback func(*stkframe, unsafe.Pointer) bool, v unsafe.Pointer) {
@@ -81,6 +97,9 @@ func tracebackdefers(gp *g, callback func(*stkframe, unsafe.Pointer) bool, v uns
 // collector (callback != nil).  A little clunky to merge these, but avoids
 // duplicating the code and all its subtlety.
 func gentraceback(pc0 uintptr, sp0 uintptr, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max int, callback func(*stkframe, unsafe.Pointer) bool, v unsafe.Pointer, printall bool) int {
+       if goexitPC == 0 {
+               gothrow("gentraceback before goexitPC initialization")
+       }
        g := getg()
        gotraceback := gotraceback(nil)
        if pc0 == ^uintptr(0) && sp0 == ^uintptr(0) { // Signal to fetch saved values from gp.