Commit 70b2da98 authored by Keith Randall's avatar Keith Randall

runtime: initialize traceback variables earlier

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
parent f13cec9f
...@@ -131,6 +131,7 @@ runtime·schedinit(void) ...@@ -131,6 +131,7 @@ runtime·schedinit(void)
runtime·sched.maxmcount = 10000; runtime·sched.maxmcount = 10000;
runtime·tracebackinit();
runtime·symtabinit(); runtime·symtabinit();
runtime·stackinit(); runtime·stackinit();
runtime·mallocinit(); runtime·mallocinit();
......
...@@ -841,6 +841,7 @@ void runtime·mpreinit(M*); ...@@ -841,6 +841,7 @@ void runtime·mpreinit(M*);
void runtime·minit(void); void runtime·minit(void);
void runtime·unminit(void); void runtime·unminit(void);
void runtime·signalstack(byte*, int32); void runtime·signalstack(byte*, int32);
void runtime·tracebackinit(void);
void runtime·symtabinit(void); void runtime·symtabinit(void);
Func* runtime·findfunc(uintptr); Func* runtime·findfunc(uintptr);
int32 runtime·funcline(Func*, uintptr, String*); int32 runtime·funcline(Func*, uintptr, String*);
......
...@@ -31,20 +31,36 @@ import "unsafe" ...@@ -31,20 +31,36 @@ import "unsafe"
const usesLR = GOARCH != "amd64" && GOARCH != "amd64p32" && GOARCH != "386" const usesLR = GOARCH != "amd64" && GOARCH != "amd64p32" && GOARCH != "386"
var ( var (
deferprocPC = funcPC(deferproc) // initialized in tracebackinit
goexitPC = funcPC(goexit) deferprocPC uintptr
jmpdeferPC = funcPC(jmpdefer) goexitPC uintptr
mcallPC = funcPC(mcall) jmpdeferPC uintptr
morestackPC = funcPC(morestack) mcallPC uintptr
mstartPC = funcPC(mstart) morestackPC uintptr
newprocPC = funcPC(newproc) mstartPC uintptr
newstackPC = funcPC(newstack) newprocPC uintptr
rt0_goPC = funcPC(rt0_go) rt0_goPC uintptr
sigpanicPC = funcPC(sigpanic) sigpanicPC uintptr
externalthreadhandlerp uintptr // initialized elsewhere 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. // Traceback over the deferred function calls.
// Report them like calls that have been invoked but not started executing yet. // 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) { 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 ...@@ -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 // collector (callback != nil). A little clunky to merge these, but avoids
// duplicating the code and all its subtlety. // 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 { 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() g := getg()
gotraceback := gotraceback(nil) gotraceback := gotraceback(nil)
if pc0 == ^uintptr(0) && sp0 == ^uintptr(0) { // Signal to fetch saved values from gp. if pc0 == ^uintptr(0) && sp0 == ^uintptr(0) { // Signal to fetch saved values from gp.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment