summaryrefslogtreecommitdiff
path: root/src/runtime/os_windows.go
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2014-09-08 14:05:23 -0400
committerRuss Cox <rsc@golang.org>2014-09-08 14:05:23 -0400
commit9ad3fba8367769ee742f07e83aa714c9ae6b8d8a (patch)
tree927a0d6982e643c90edd5ddefaf706b4d20bd984 /src/runtime/os_windows.go
parent87cb94fa270003e8d950d001e1c85e34a5457a8a (diff)
downloadgo-9ad3fba8367769ee742f07e83aa714c9ae6b8d8a.tar.gz
liblink, runtime: diagnose and fix C code running on Go stack
This CL contains compiler+runtime changes that detect C code running on Go (not g0, not gsignal) stacks, and it contains corrections for what it detected. The detection works by changing the C prologue to use a different stack guard word in the G than Go prologue does. On the g0 and gsignal stacks, that stack guard word is set to the usual stack guard value. But on ordinary Go stacks, that stack guard word is set to ^0, which will make any stack split check fail. The C prologue then calls morestackc instead of morestack, and morestackc aborts the program with a message about running C code on a Go stack. This check catches all C code running on the Go stack except NOSPLIT code. The NOSPLIT code is allowed, so the check is complete. Since it is a dynamic check, the code must execute to be caught. But unlike the static checks we've been using in cmd/ld, the dynamic check works with function pointers and other indirect calls. For example it caught sigpanic being pushed onto Go stacks in the signal handlers. Fixes issue 8667. LGTM=khr, iant R=golang-codereviews, khr, iant CC=golang-codereviews, r https://codereview.appspot.com/133700043
Diffstat (limited to 'src/runtime/os_windows.go')
-rw-r--r--src/runtime/os_windows.go27
1 files changed, 27 insertions, 0 deletions
diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go
index 6a3bfca41..da4c736ad 100644
--- a/src/runtime/os_windows.go
+++ b/src/runtime/os_windows.go
@@ -31,3 +31,30 @@ const stackSystem = 512 * ptrSize
func os_sigpipe() {
gothrow("too many writes on closed pipe")
}
+
+func sigpanic() {
+ g := getg()
+ if !canpanic(g) {
+ gothrow("unexpected signal during runtime execution")
+ }
+
+ switch uint32(g.sig) {
+ case _EXCEPTION_ACCESS_VIOLATION:
+ if g.sigcode1 < 0x1000 || g.paniconfault {
+ panicmem()
+ }
+ print("unexpected fault address ", hex(g.sigcode1), "\n")
+ gothrow("fault")
+ case _EXCEPTION_INT_DIVIDE_BY_ZERO:
+ panicdivide()
+ case _EXCEPTION_INT_OVERFLOW:
+ panicoverflow()
+ case _EXCEPTION_FLT_DENORMAL_OPERAND,
+ _EXCEPTION_FLT_DIVIDE_BY_ZERO,
+ _EXCEPTION_FLT_INEXACT_RESULT,
+ _EXCEPTION_FLT_OVERFLOW,
+ _EXCEPTION_FLT_UNDERFLOW:
+ panicfloat()
+ }
+ gothrow("fault")
+}