github.com/alash3al/go@v0.0.0-20150827002835-d497eeb00540/src/runtime/signal_amd64x.go (about)

     1  // Copyright 2013 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  // +build amd64 amd64p32
     6  // +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
     7  
     8  package runtime
     9  
    10  import (
    11  	"unsafe"
    12  )
    13  
    14  func dumpregs(c *sigctxt) {
    15  	print("rax    ", hex(c.rax()), "\n")
    16  	print("rbx    ", hex(c.rbx()), "\n")
    17  	print("rcx    ", hex(c.rcx()), "\n")
    18  	print("rdx    ", hex(c.rdx()), "\n")
    19  	print("rdi    ", hex(c.rdi()), "\n")
    20  	print("rsi    ", hex(c.rsi()), "\n")
    21  	print("rbp    ", hex(c.rbp()), "\n")
    22  	print("rsp    ", hex(c.rsp()), "\n")
    23  	print("r8     ", hex(c.r8()), "\n")
    24  	print("r9     ", hex(c.r9()), "\n")
    25  	print("r10    ", hex(c.r10()), "\n")
    26  	print("r11    ", hex(c.r11()), "\n")
    27  	print("r12    ", hex(c.r12()), "\n")
    28  	print("r13    ", hex(c.r13()), "\n")
    29  	print("r14    ", hex(c.r14()), "\n")
    30  	print("r15    ", hex(c.r15()), "\n")
    31  	print("rip    ", hex(c.rip()), "\n")
    32  	print("rflags ", hex(c.rflags()), "\n")
    33  	print("cs     ", hex(c.cs()), "\n")
    34  	print("fs     ", hex(c.fs()), "\n")
    35  	print("gs     ", hex(c.gs()), "\n")
    36  }
    37  
    38  var crashing int32
    39  
    40  // May run during STW, so write barriers are not allowed.
    41  //go:nowritebarrier
    42  func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
    43  	_g_ := getg()
    44  	c := &sigctxt{info, ctxt}
    45  
    46  	if sig == _SIGPROF {
    47  		sigprof(uintptr(c.rip()), uintptr(c.rsp()), 0, gp, _g_.m)
    48  		return
    49  	}
    50  
    51  	if GOOS == "darwin" {
    52  		// x86-64 has 48-bit virtual addresses. The top 16 bits must echo bit 47.
    53  		// The hardware delivers a different kind of fault for a malformed address
    54  		// than it does for an attempt to access a valid but unmapped address.
    55  		// OS X 10.9.2 mishandles the malformed address case, making it look like
    56  		// a user-generated signal (like someone ran kill -SEGV ourpid).
    57  		// We pass user-generated signals to os/signal, or else ignore them.
    58  		// Doing that here - and returning to the faulting code - results in an
    59  		// infinite loop. It appears the best we can do is rewrite what the kernel
    60  		// delivers into something more like the truth. The address used below
    61  		// has very little chance of being the one that caused the fault, but it is
    62  		// malformed, it is clearly not a real pointer, and if it does get printed
    63  		// in real life, people will probably search for it and find this code.
    64  		// There are no Google hits for b01dfacedebac1e or 0xb01dfacedebac1e
    65  		// as I type this comment.
    66  		if sig == _SIGSEGV && c.sigcode() == _SI_USER {
    67  			c.set_sigcode(_SI_USER + 1)
    68  			c.set_sigaddr(0xb01dfacedebac1e)
    69  		}
    70  	}
    71  
    72  	flags := int32(_SigThrow)
    73  	if sig < uint32(len(sigtable)) {
    74  		flags = sigtable[sig].flags
    75  	}
    76  	if c.sigcode() != _SI_USER && flags&_SigPanic != 0 {
    77  		// Make it look like a call to the signal func.
    78  		// Have to pass arguments out of band since
    79  		// augmenting the stack frame would break
    80  		// the unwinding code.
    81  		gp.sig = sig
    82  		gp.sigcode0 = uintptr(c.sigcode())
    83  		gp.sigcode1 = uintptr(c.sigaddr())
    84  		gp.sigpc = uintptr(c.rip())
    85  
    86  		if GOOS == "darwin" {
    87  			// Work around Leopard bug that doesn't set FPE_INTDIV.
    88  			// Look at instruction to see if it is a divide.
    89  			// Not necessary in Snow Leopard (si_code will be != 0).
    90  			if sig == _SIGFPE && gp.sigcode0 == 0 {
    91  				pc := (*[4]byte)(unsafe.Pointer(gp.sigpc))
    92  				i := 0
    93  				if pc[i]&0xF0 == 0x40 { // 64-bit REX prefix
    94  					i++
    95  				} else if pc[i] == 0x66 { // 16-bit instruction prefix
    96  					i++
    97  				}
    98  				if pc[i] == 0xF6 || pc[i] == 0xF7 {
    99  					gp.sigcode0 = _FPE_INTDIV
   100  				}
   101  			}
   102  		}
   103  
   104  		pc := uintptr(c.rip())
   105  		sp := uintptr(c.rsp())
   106  
   107  		// If we don't recognize the PC as code
   108  		// but we do recognize the top pointer on the stack as code,
   109  		// then assume this was a call to non-code and treat like
   110  		// pc == 0, to make unwinding show the context.
   111  		if pc != 0 && findfunc(pc) == nil && findfunc(*(*uintptr)(unsafe.Pointer(sp))) != nil {
   112  			pc = 0
   113  		}
   114  
   115  		// Only push runtime.sigpanic if pc != 0.
   116  		// If pc == 0, probably panicked because of a
   117  		// call to a nil func.  Not pushing that onto sp will
   118  		// make the trace look like a call to runtime.sigpanic instead.
   119  		// (Otherwise the trace will end at runtime.sigpanic and we
   120  		// won't get to see who faulted.)
   121  		if pc != 0 {
   122  			if regSize > ptrSize {
   123  				sp -= ptrSize
   124  				*(*uintptr)(unsafe.Pointer(sp)) = 0
   125  			}
   126  			sp -= ptrSize
   127  			*(*uintptr)(unsafe.Pointer(sp)) = pc
   128  			c.set_rsp(uint64(sp))
   129  		}
   130  		c.set_rip(uint64(funcPC(sigpanic)))
   131  		return
   132  	}
   133  
   134  	if c.sigcode() == _SI_USER || flags&_SigNotify != 0 {
   135  		if sigsend(sig) {
   136  			return
   137  		}
   138  	}
   139  
   140  	if flags&_SigKill != 0 {
   141  		exit(2)
   142  	}
   143  
   144  	if flags&_SigThrow == 0 {
   145  		return
   146  	}
   147  
   148  	_g_.m.throwing = 1
   149  	_g_.m.caughtsig.set(gp)
   150  
   151  	if crashing == 0 {
   152  		startpanic()
   153  	}
   154  
   155  	if sig < uint32(len(sigtable)) {
   156  		print(sigtable[sig].name, "\n")
   157  	} else {
   158  		print("Signal ", sig, "\n")
   159  	}
   160  
   161  	print("PC=", hex(c.rip()), " m=", _g_.m.id, "\n")
   162  	if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
   163  		print("signal arrived during cgo execution\n")
   164  		gp = _g_.m.lockedg
   165  	}
   166  	print("\n")
   167  
   168  	var docrash bool
   169  	if gotraceback(&docrash) > 0 {
   170  		goroutineheader(gp)
   171  		tracebacktrap(uintptr(c.rip()), uintptr(c.rsp()), 0, gp)
   172  		if crashing > 0 && gp != _g_.m.curg && _g_.m.curg != nil && readgstatus(_g_.m.curg)&^_Gscan == _Grunning {
   173  			// tracebackothers on original m skipped this one; trace it now.
   174  			goroutineheader(_g_.m.curg)
   175  			traceback(^uintptr(0), ^uintptr(0), 0, gp)
   176  		} else if crashing == 0 {
   177  			tracebackothers(gp)
   178  			print("\n")
   179  		}
   180  		dumpregs(c)
   181  	}
   182  
   183  	if docrash {
   184  		crashing++
   185  		if crashing < sched.mcount {
   186  			// There are other m's that need to dump their stacks.
   187  			// Relay SIGQUIT to the next m by sending it to the current process.
   188  			// All m's that have already received SIGQUIT have signal masks blocking
   189  			// receipt of any signals, so the SIGQUIT will go to an m that hasn't seen it yet.
   190  			// When the last m receives the SIGQUIT, it will fall through to the call to
   191  			// crash below. Just in case the relaying gets botched, each m involved in
   192  			// the relay sleeps for 5 seconds and then does the crash/exit itself.
   193  			// In expected operation, the last m has received the SIGQUIT and run
   194  			// crash/exit and the process is gone, all long before any of the
   195  			// 5-second sleeps have finished.
   196  			print("\n-----\n\n")
   197  			raiseproc(_SIGQUIT)
   198  			usleep(5 * 1000 * 1000)
   199  		}
   200  		crash()
   201  	}
   202  
   203  	exit(2)
   204  }