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)
runtime·sched.maxmcount = 10000;
runtime·tracebackinit();
runtime·symtabinit();
runtime·stackinit();
runtime·mallocinit();
......
......@@ -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*);
......
......@@ -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.
......
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