github.com/reiver/go@v0.0.0-20150109200633-1d0c7792f172/src/runtime/os1_windows_amd64.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  var text struct{}
    12  
    13  func dumpregs(r *context) {
    14  	print("rax     ", hex(r.rax), "\n")
    15  	print("rbx     ", hex(r.rbx), "\n")
    16  	print("rcx     ", hex(r.rcx), "\n")
    17  	print("rdi     ", hex(r.rdi), "\n")
    18  	print("rsi     ", hex(r.rsi), "\n")
    19  	print("rbp     ", hex(r.rbp), "\n")
    20  	print("rsp     ", hex(r.rsp), "\n")
    21  	print("r8      ", hex(r.r8), "\n")
    22  	print("r9      ", hex(r.r9), "\n")
    23  	print("r10     ", hex(r.r10), "\n")
    24  	print("r11     ", hex(r.r11), "\n")
    25  	print("r12     ", hex(r.r12), "\n")
    26  	print("r13     ", hex(r.r13), "\n")
    27  	print("r14     ", hex(r.r14), "\n")
    28  	print("r15     ", hex(r.r15), "\n")
    29  	print("rip     ", hex(r.rip), "\n")
    30  	print("rflags  ", hex(r.eflags), "\n")
    31  	print("cs      ", hex(r.segcs), "\n")
    32  	print("fs      ", hex(r.segfs), "\n")
    33  	print("gs      ", hex(r.seggs), "\n")
    34  }
    35  
    36  func isgoexception(info *exceptionrecord, r *context) bool {
    37  	// Only handle exception if executing instructions in Go binary
    38  	// (not Windows library code).
    39  	if r.rip < uint64(uintptr(unsafe.Pointer(&text))) || uint64(uintptr(unsafe.Pointer(&etext))) < r.rip {
    40  		return false
    41  	}
    42  
    43  	if issigpanic(info.exceptioncode) == 0 {
    44  		return false
    45  	}
    46  
    47  	return true
    48  }
    49  
    50  // Called by sigtramp from Windows VEH handler.
    51  // Return value signals whether the exception has been handled (EXCEPTION_CONTINUE_EXECUTION)
    52  // or should be made available to other handlers in the chain (EXCEPTION_CONTINUE_SEARCH).
    53  
    54  func exceptionhandler(info *exceptionrecord, r *context, gp *g) int32 {
    55  	if !isgoexception(info, r) {
    56  		return _EXCEPTION_CONTINUE_SEARCH
    57  	}
    58  
    59  	// Make it look like a call to the signal func.
    60  	// Have to pass arguments out of band since
    61  	// augmenting the stack frame would break
    62  	// the unwinding code.
    63  	gp.sig = info.exceptioncode
    64  	gp.sigcode0 = uintptr(info.exceptioninformation[0])
    65  	gp.sigcode1 = uintptr(info.exceptioninformation[1])
    66  	gp.sigpc = uintptr(r.rip)
    67  
    68  	// Only push runtime·sigpanic if r->rip != 0.
    69  	// If r->rip == 0, probably panicked because of a
    70  	// call to a nil func.  Not pushing that onto sp will
    71  	// make the trace look like a call to runtime·sigpanic instead.
    72  	// (Otherwise the trace will end at runtime·sigpanic and we
    73  	// won't get to see who faulted.)
    74  	if r.rip != 0 {
    75  		sp := unsafe.Pointer(uintptr(r.rsp))
    76  		sp = add(sp, ^uintptr(unsafe.Sizeof(uintptr(0))-1)) // sp--
    77  		*((*uintptr)(sp)) = uintptr(r.rip)
    78  		r.rsp = uint64(uintptr(sp))
    79  	}
    80  	r.rip = uint64(funcPC(sigpanic))
    81  	return _EXCEPTION_CONTINUE_EXECUTION
    82  }
    83  
    84  // It seems Windows searches ContinueHandler's list even
    85  // if ExceptionHandler returns EXCEPTION_CONTINUE_EXECUTION.
    86  // firstcontinuehandler will stop that search,
    87  // if exceptionhandler did the same earlier.
    88  func firstcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 {
    89  	if !isgoexception(info, r) {
    90  		return _EXCEPTION_CONTINUE_SEARCH
    91  	}
    92  	return _EXCEPTION_CONTINUE_EXECUTION
    93  }
    94  
    95  var testingWER bool
    96  
    97  // lastcontinuehandler is reached, because runtime cannot handle
    98  // current exception. lastcontinuehandler will print crash info and exit.
    99  func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) uint32 {
   100  	if testingWER {
   101  		return _EXCEPTION_CONTINUE_SEARCH
   102  	}
   103  
   104  	_g_ := getg()
   105  
   106  	if panicking != 0 { // traceback already printed
   107  		exit(2)
   108  	}
   109  	panicking = 1
   110  
   111  	print("Exception ", hex(info.exceptioncode), " ", hex(info.exceptioninformation[0]), " ", hex(info.exceptioninformation[1]), " ", hex(r.rip), "\n")
   112  
   113  	print("PC=", hex(r.rip), "\n")
   114  	if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
   115  		print("signal arrived during cgo execution\n")
   116  		gp = _g_.m.lockedg
   117  	}
   118  	print("\n")
   119  
   120  	var docrash bool
   121  	if gotraceback(&docrash) > 0 {
   122  		tracebacktrap(uintptr(r.rip), uintptr(r.rsp), 0, gp)
   123  		tracebackothers(gp)
   124  		dumpregs(r)
   125  	}
   126  
   127  	if docrash {
   128  		crash()
   129  	}
   130  
   131  	exit(2)
   132  	return 0 // not reached
   133  }
   134  
   135  func sigenable(sig uint32) {
   136  }
   137  
   138  func sigdisable(sig uint32) {
   139  }
   140  
   141  func dosigprof(r *context, gp *g, mp *m) {
   142  	sigprof((*byte)(unsafe.Pointer(uintptr(r.rip))), (*byte)(unsafe.Pointer(uintptr(r.rsp))), nil, gp, mp)
   143  }