aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/proc.c1
-rw-r--r--src/runtime/runtime.h1
-rw-r--r--src/runtime/traceback.go39
3 files changed, 31 insertions, 10 deletions
diff --git a/src/runtime/proc.c b/src/runtime/proc.c
index 1f0a79098b..e84dc1d048 100644
--- a/src/runtime/proc.c
+++ b/src/runtime/proc.c
@@ -131,6 +131,7 @@ runtime·schedinit(void)
runtime·sched.maxmcount = 10000;
+ runtime·tracebackinit();
runtime·symtabinit();
runtime·stackinit();
runtime·mallocinit();
diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h
index 3a6d3e3262..aa300d7bb8 100644
--- a/src/runtime/runtime.h
+++ b/src/runtime/runtime.h
@@ -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*);
diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go
index a93c42186b..24dc3eea95 100644
--- a/src/runtime/traceback.go
+++ b/src/runtime/traceback.go
@@ -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.