1
0
mirror of https://github.com/golang/go synced 2024-11-12 09:50:21 -07:00

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
This commit is contained in:
Keith Randall 2014-09-29 21:21:36 -07:00
parent f13cec9f57
commit 70b2da98ca
3 changed files with 31 additions and 10 deletions

View File

@ -131,6 +131,7 @@ runtime·schedinit(void)
runtime·sched.maxmcount = 10000;
runtime·tracebackinit();
runtime·symtabinit();
runtime·stackinit();
runtime·mallocinit();

View 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*);

View 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.