diff options
author | Alex Brainman <alex.brainman@gmail.com> | 2015-04-09 15:13:48 +1000 |
---|---|---|
committer | Alex Brainman <alex.brainman@gmail.com> | 2015-04-09 09:55:38 +0000 |
commit | 6e774faed773afa1ff7345e2c2d4367e9510388d (patch) | |
tree | 6a533770d97b32a5acbb642aeb77b3889d4926b5 /src/runtime/signal_windows.go | |
parent | a513088396d28794c2b2e1bb5e5f2a827e922b4a (diff) | |
download | go-6e774faed773afa1ff7345e2c2d4367e9510388d.tar.gz go-6e774faed773afa1ff7345e2c2d4367e9510388d.zip |
runtime: make windows exception handler code arch independent
Mainly it is simple copy. But I had to change amd64
lastcontinuehandler return value from uint32 to int32.
I don't remember how it happened to be uint32, but new
int32 is matching better with Windows documentation (LONG).
I don't think it matters one way or the others.
Change-Id: I6935224a2470ad6301e27590f2baa86c13bbe8d5
Reviewed-on: https://go-review.googlesource.com/8686
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src/runtime/signal_windows.go')
-rw-r--r-- | src/runtime/signal_windows.go | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/src/runtime/signal_windows.go b/src/runtime/signal_windows.go new file mode 100644 index 0000000000..ab8fe206c7 --- /dev/null +++ b/src/runtime/signal_windows.go @@ -0,0 +1,117 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime + +import ( + "unsafe" +) + +func isgoexception(info *exceptionrecord, r *context) bool { + // Only handle exception if executing instructions in Go binary + // (not Windows library code). + if r.ip() < themoduledata.text || themoduledata.etext < r.ip() { + return false + } + + if issigpanic(info.exceptioncode) == 0 { + return false + } + + return true +} + +// Called by sigtramp from Windows VEH handler. +// Return value signals whether the exception has been handled (EXCEPTION_CONTINUE_EXECUTION) +// or should be made available to other handlers in the chain (EXCEPTION_CONTINUE_SEARCH). + +func exceptionhandler(info *exceptionrecord, r *context, gp *g) int32 { + if !isgoexception(info, r) { + return _EXCEPTION_CONTINUE_SEARCH + } + + // Make it look like a call to the signal func. + // Have to pass arguments out of band since + // augmenting the stack frame would break + // the unwinding code. + gp.sig = info.exceptioncode + gp.sigcode0 = uintptr(info.exceptioninformation[0]) + gp.sigcode1 = uintptr(info.exceptioninformation[1]) + gp.sigpc = r.ip() + + // Only push runtime·sigpanic if r.ip() != 0. + // If r.ip() == 0, probably panicked because of a + // call to a nil func. Not pushing that onto sp will + // make the trace look like a call to runtime·sigpanic instead. + // (Otherwise the trace will end at runtime·sigpanic and we + // won't get to see who faulted.) + if r.ip() != 0 { + sp := unsafe.Pointer(r.sp()) + sp = add(sp, ^uintptr(unsafe.Sizeof(uintptr(0))-1)) // sp-- + *((*uintptr)(sp)) = r.ip() + r.setsp(uintptr(sp)) + } + r.setip(funcPC(sigpanic)) + return _EXCEPTION_CONTINUE_EXECUTION +} + +// It seems Windows searches ContinueHandler's list even +// if ExceptionHandler returns EXCEPTION_CONTINUE_EXECUTION. +// firstcontinuehandler will stop that search, +// if exceptionhandler did the same earlier. +func firstcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 { + if !isgoexception(info, r) { + return _EXCEPTION_CONTINUE_SEARCH + } + return _EXCEPTION_CONTINUE_EXECUTION +} + +var testingWER bool + +// lastcontinuehandler is reached, because runtime cannot handle +// current exception. lastcontinuehandler will print crash info and exit. +func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 { + if testingWER { + return _EXCEPTION_CONTINUE_SEARCH + } + + _g_ := getg() + + if panicking != 0 { // traceback already printed + exit(2) + } + panicking = 1 + + print("Exception ", hex(info.exceptioncode), " ", hex(info.exceptioninformation[0]), " ", hex(info.exceptioninformation[1]), " ", hex(r.ip()), "\n") + + print("PC=", hex(r.ip()), "\n") + if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 { + print("signal arrived during cgo execution\n") + gp = _g_.m.lockedg + } + print("\n") + + var docrash bool + if gotraceback(&docrash) > 0 { + tracebacktrap(r.ip(), r.sp(), 0, gp) + tracebackothers(gp) + dumpregs(r) + } + + if docrash { + crash() + } + + exit(2) + return 0 // not reached +} + +func sigenable(sig uint32) { +} + +func sigdisable(sig uint32) { +} + +func sigignore(sig uint32) { +} |