github.com/s1s1ty/go@v0.0.0-20180207192209-104445e3140f/src/runtime/signal_windows.go (about)

     1  // Copyright 2011 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package runtime
     6  
     7  import (
     8  	"unsafe"
     9  )
    10  
    11  func disableWER() {
    12  	// do not display Windows Error Reporting dialogue
    13  	const (
    14  		SEM_FAILCRITICALERRORS     = 0x0001
    15  		SEM_NOGPFAULTERRORBOX      = 0x0002
    16  		SEM_NOALIGNMENTFAULTEXCEPT = 0x0004
    17  		SEM_NOOPENFILEERRORBOX     = 0x8000
    18  	)
    19  	errormode := uint32(stdcall1(_SetErrorMode, SEM_NOGPFAULTERRORBOX))
    20  	stdcall1(_SetErrorMode, uintptr(errormode)|SEM_FAILCRITICALERRORS|SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX)
    21  }
    22  
    23  // in sys_windows_386.s and sys_windows_amd64.s
    24  func exceptiontramp()
    25  func firstcontinuetramp()
    26  func lastcontinuetramp()
    27  
    28  func initExceptionHandler() {
    29  	stdcall2(_AddVectoredExceptionHandler, 1, funcPC(exceptiontramp))
    30  	if _AddVectoredContinueHandler == nil || unsafe.Sizeof(&_AddVectoredContinueHandler) == 4 {
    31  		// use SetUnhandledExceptionFilter for windows-386 or
    32  		// if VectoredContinueHandler is unavailable.
    33  		// note: SetUnhandledExceptionFilter handler won't be called, if debugging.
    34  		stdcall1(_SetUnhandledExceptionFilter, funcPC(lastcontinuetramp))
    35  	} else {
    36  		stdcall2(_AddVectoredContinueHandler, 1, funcPC(firstcontinuetramp))
    37  		stdcall2(_AddVectoredContinueHandler, 0, funcPC(lastcontinuetramp))
    38  	}
    39  }
    40  
    41  func isgoexception(info *exceptionrecord, r *context) bool {
    42  	// Only handle exception if executing instructions in Go binary
    43  	// (not Windows library code).
    44  	// TODO(mwhudson): needs to loop to support shared libs
    45  	if r.ip() < firstmoduledata.text || firstmoduledata.etext < r.ip() {
    46  		return false
    47  	}
    48  
    49  	// Go will only handle some exceptions.
    50  	switch info.exceptioncode {
    51  	default:
    52  		return false
    53  	case _EXCEPTION_ACCESS_VIOLATION:
    54  	case _EXCEPTION_INT_DIVIDE_BY_ZERO:
    55  	case _EXCEPTION_INT_OVERFLOW:
    56  	case _EXCEPTION_FLT_DENORMAL_OPERAND:
    57  	case _EXCEPTION_FLT_DIVIDE_BY_ZERO:
    58  	case _EXCEPTION_FLT_INEXACT_RESULT:
    59  	case _EXCEPTION_FLT_OVERFLOW:
    60  	case _EXCEPTION_FLT_UNDERFLOW:
    61  	case _EXCEPTION_BREAKPOINT:
    62  	}
    63  	return true
    64  }
    65  
    66  // Called by sigtramp from Windows VEH handler.
    67  // Return value signals whether the exception has been handled (EXCEPTION_CONTINUE_EXECUTION)
    68  // or should be made available to other handlers in the chain (EXCEPTION_CONTINUE_SEARCH).
    69  func exceptionhandler(info *exceptionrecord, r *context, gp *g) int32 {
    70  	if !isgoexception(info, r) {
    71  		return _EXCEPTION_CONTINUE_SEARCH
    72  	}
    73  
    74  	if gp.throwsplit {
    75  		// We can't safely sigpanic because it may grow the
    76  		// stack. Let it fall through.
    77  		return _EXCEPTION_CONTINUE_SEARCH
    78  	}
    79  
    80  	// Make it look like a call to the signal func.
    81  	// Have to pass arguments out of band since
    82  	// augmenting the stack frame would break
    83  	// the unwinding code.
    84  	gp.sig = info.exceptioncode
    85  	gp.sigcode0 = uintptr(info.exceptioninformation[0])
    86  	gp.sigcode1 = uintptr(info.exceptioninformation[1])
    87  	gp.sigpc = r.ip()
    88  
    89  	// Only push runtime·sigpanic if r.ip() != 0.
    90  	// If r.ip() == 0, probably panicked because of a
    91  	// call to a nil func. Not pushing that onto sp will
    92  	// make the trace look like a call to runtime·sigpanic instead.
    93  	// (Otherwise the trace will end at runtime·sigpanic and we
    94  	// won't get to see who faulted.)
    95  	if r.ip() != 0 {
    96  		sp := unsafe.Pointer(r.sp())
    97  		sp = add(sp, ^(unsafe.Sizeof(uintptr(0)) - 1)) // sp--
    98  		*((*uintptr)(sp)) = r.ip()
    99  		r.setsp(uintptr(sp))
   100  	}
   101  	r.setip(funcPC(sigpanic))
   102  	return _EXCEPTION_CONTINUE_EXECUTION
   103  }
   104  
   105  // It seems Windows searches ContinueHandler's list even
   106  // if ExceptionHandler returns EXCEPTION_CONTINUE_EXECUTION.
   107  // firstcontinuehandler will stop that search,
   108  // if exceptionhandler did the same earlier.
   109  func firstcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 {
   110  	if !isgoexception(info, r) {
   111  		return _EXCEPTION_CONTINUE_SEARCH
   112  	}
   113  	return _EXCEPTION_CONTINUE_EXECUTION
   114  }
   115  
   116  var testingWER bool
   117  
   118  // lastcontinuehandler is reached, because runtime cannot handle
   119  // current exception. lastcontinuehandler will print crash info and exit.
   120  func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 {
   121  	if testingWER {
   122  		return _EXCEPTION_CONTINUE_SEARCH
   123  	}
   124  
   125  	_g_ := getg()
   126  
   127  	if panicking != 0 { // traceback already printed
   128  		exit(2)
   129  	}
   130  	panicking = 1
   131  
   132  	print("Exception ", hex(info.exceptioncode), " ", hex(info.exceptioninformation[0]), " ", hex(info.exceptioninformation[1]), " ", hex(r.ip()), "\n")
   133  
   134  	print("PC=", hex(r.ip()), "\n")
   135  	if _g_.m.lockedg != 0 && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
   136  		if iscgo {
   137  			print("signal arrived during external code execution\n")
   138  		}
   139  		gp = _g_.m.lockedg.ptr()
   140  	}
   141  	print("\n")
   142  
   143  	level, _, docrash := gotraceback()
   144  	if level > 0 {
   145  		tracebacktrap(r.ip(), r.sp(), 0, gp)
   146  		tracebackothers(gp)
   147  		dumpregs(r)
   148  	}
   149  
   150  	if docrash {
   151  		crash()
   152  	}
   153  
   154  	exit(2)
   155  	return 0 // not reached
   156  }
   157  
   158  func sigpanic() {
   159  	g := getg()
   160  	if !canpanic(g) {
   161  		throw("unexpected signal during runtime execution")
   162  	}
   163  
   164  	switch g.sig {
   165  	case _EXCEPTION_ACCESS_VIOLATION:
   166  		if g.sigcode1 < 0x1000 || g.paniconfault {
   167  			panicmem()
   168  		}
   169  		print("unexpected fault address ", hex(g.sigcode1), "\n")
   170  		throw("fault")
   171  	case _EXCEPTION_INT_DIVIDE_BY_ZERO:
   172  		panicdivide()
   173  	case _EXCEPTION_INT_OVERFLOW:
   174  		panicoverflow()
   175  	case _EXCEPTION_FLT_DENORMAL_OPERAND,
   176  		_EXCEPTION_FLT_DIVIDE_BY_ZERO,
   177  		_EXCEPTION_FLT_INEXACT_RESULT,
   178  		_EXCEPTION_FLT_OVERFLOW,
   179  		_EXCEPTION_FLT_UNDERFLOW:
   180  		panicfloat()
   181  	}
   182  	throw("fault")
   183  }
   184  
   185  var (
   186  	badsignalmsg [100]byte
   187  	badsignallen int32
   188  )
   189  
   190  func setBadSignalMsg() {
   191  	const msg = "runtime: signal received on thread not created by Go.\n"
   192  	for i, c := range msg {
   193  		badsignalmsg[i] = byte(c)
   194  		badsignallen++
   195  	}
   196  }
   197  
   198  // Following are not implemented.
   199  
   200  func initsig(preinit bool) {
   201  }
   202  
   203  func sigenable(sig uint32) {
   204  }
   205  
   206  func sigdisable(sig uint32) {
   207  }
   208  
   209  func sigignore(sig uint32) {
   210  }
   211  
   212  func badsignal2()
   213  
   214  func raisebadsignal(sig uint32) {
   215  	badsignal2()
   216  }
   217  
   218  func signame(sig uint32) string {
   219  	return ""
   220  }
   221  
   222  func crash() {
   223  	// TODO: This routine should do whatever is needed
   224  	// to make the Windows program abort/crash as it
   225  	// would if Go was not intercepting signals.
   226  	// On Unix the routine would remove the custom signal
   227  	// handler and then raise a signal (like SIGABRT).
   228  	// Something like that should happen here.
   229  	// It's okay to leave this empty for now: if crash returns
   230  	// the ordinary exit-after-panic happens.
   231  }
   232  
   233  // gsignalStack is unused on Windows.
   234  type gsignalStack struct{}