github.com/shijuvar/go@v0.0.0-20141209052335-e8f13700b70c/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 "unsafe"
    11  
    12  func dumpregs(c *sigctxt) {
    13  	print("rax    ", hex(c.rax()), "\n")
    14  	print("rbx    ", hex(c.rbx()), "\n")
    15  	print("rcx    ", hex(c.rcx()), "\n")
    16  	print("rdx    ", hex(c.rdx()), "\n")
    17  	print("rdi    ", hex(c.rdi()), "\n")
    18  	print("rsi    ", hex(c.rsi()), "\n")
    19  	print("rbp    ", hex(c.rbp()), "\n")
    20  	print("rsp    ", hex(c.rsp()), "\n")
    21  	print("r8     ", hex(c.r8()), "\n")
    22  	print("r9     ", hex(c.r9()), "\n")
    23  	print("r10    ", hex(c.r10()), "\n")
    24  	print("r11    ", hex(c.r11()), "\n")
    25  	print("r12    ", hex(c.r12()), "\n")
    26  	print("r13    ", hex(c.r13()), "\n")
    27  	print("r14    ", hex(c.r14()), "\n")
    28  	print("r15    ", hex(c.r15()), "\n")
    29  	print("rip    ", hex(c.rip()), "\n")
    30  	print("rflags ", hex(c.rflags()), "\n")
    31  	print("cs     ", hex(c.cs()), "\n")
    32  	print("fs     ", hex(c.fs()), "\n")
    33  	print("gs     ", hex(c.gs()), "\n")
    34  }
    35  
    36  func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
    37  	_g_ := getg()
    38  	c := &sigctxt{info, ctxt}
    39  
    40  	if sig == _SIGPROF {
    41  		sigprof((*byte)(unsafe.Pointer(uintptr(c.rip()))), (*byte)(unsafe.Pointer(uintptr(c.rsp()))), nil, gp, _g_.m)
    42  		return
    43  	}
    44  
    45  	if GOOS == "darwin" {
    46  		// x86-64 has 48-bit virtual addresses. The top 16 bits must echo bit 47.
    47  		// The hardware delivers a different kind of fault for a malformed address
    48  		// than it does for an attempt to access a valid but unmapped address.
    49  		// OS X 10.9.2 mishandles the malformed address case, making it look like
    50  		// a user-generated signal (like someone ran kill -SEGV ourpid).
    51  		// We pass user-generated signals to os/signal, or else ignore them.
    52  		// Doing that here - and returning to the faulting code - results in an
    53  		// infinite loop. It appears the best we can do is rewrite what the kernel
    54  		// delivers into something more like the truth. The address used below
    55  		// has very little chance of being the one that caused the fault, but it is
    56  		// malformed, it is clearly not a real pointer, and if it does get printed
    57  		// in real life, people will probably search for it and find this code.
    58  		// There are no Google hits for b01dfacedebac1e or 0xb01dfacedebac1e
    59  		// as I type this comment.
    60  		if sig == _SIGSEGV && c.sigcode() == _SI_USER {
    61  			c.set_sigcode(_SI_USER + 1)
    62  			c.set_sigaddr(0xb01dfacedebac1e)
    63  		}
    64  	}
    65  
    66  	flags := int32(_SigThrow)
    67  	if sig < uint32(len(sigtable)) {
    68  		flags = sigtable[sig].flags
    69  	}
    70  	if c.sigcode() != _SI_USER && flags&_SigPanic != 0 {
    71  		// Make it look like a call to the signal func.
    72  		// Have to pass arguments out of band since
    73  		// augmenting the stack frame would break
    74  		// the unwinding code.
    75  		gp.sig = sig
    76  		gp.sigcode0 = uintptr(c.sigcode())
    77  		gp.sigcode1 = uintptr(c.sigaddr())
    78  		gp.sigpc = uintptr(c.rip())
    79  
    80  		if GOOS == "darwin" {
    81  			// Work around Leopard bug that doesn't set FPE_INTDIV.
    82  			// Look at instruction to see if it is a divide.
    83  			// Not necessary in Snow Leopard (si_code will be != 0).
    84  			if sig == _SIGFPE && gp.sigcode0 == 0 {
    85  				pc := (*[4]byte)(unsafe.Pointer(gp.sigpc))
    86  				i := 0
    87  				if pc[i]&0xF0 == 0x40 { // 64-bit REX prefix
    88  					i++
    89  				} else if pc[i] == 0x66 { // 16-bit instruction prefix
    90  					i++
    91  				}
    92  				if pc[i] == 0xF6 || pc[i] == 0xF7 {
    93  					gp.sigcode0 = _FPE_INTDIV
    94  				}
    95  			}
    96  		}
    97  
    98  		// Only push runtime.sigpanic if rip != 0.
    99  		// If rip == 0, probably panicked because of a
   100  		// call to a nil func.  Not pushing that onto sp will
   101  		// make the trace look like a call to runtime.sigpanic instead.
   102  		// (Otherwise the trace will end at runtime.sigpanic and we
   103  		// won't get to see who faulted.)
   104  		if c.rip() != 0 {
   105  			sp := c.rsp()
   106  			if regSize > ptrSize {
   107  				sp -= ptrSize
   108  				*(*uintptr)(unsafe.Pointer(uintptr(sp))) = 0
   109  			}
   110  			sp -= ptrSize
   111  			*(*uintptr)(unsafe.Pointer(uintptr(sp))) = uintptr(c.rip())
   112  			c.set_rsp(sp)
   113  		}
   114  		c.set_rip(uint64(funcPC(sigpanic)))
   115  		return
   116  	}
   117  
   118  	if c.sigcode() == _SI_USER || flags&_SigNotify != 0 {
   119  		if sigsend(sig) {
   120  			return
   121  		}
   122  	}
   123  
   124  	if flags&_SigKill != 0 {
   125  		exit(2)
   126  	}
   127  
   128  	if flags&_SigThrow == 0 {
   129  		return
   130  	}
   131  
   132  	_g_.m.throwing = 1
   133  	_g_.m.caughtsig = gp
   134  	startpanic()
   135  
   136  	if sig < uint32(len(sigtable)) {
   137  		print(sigtable[sig].name, "\n")
   138  	} else {
   139  		print("Signal ", sig, "\n")
   140  	}
   141  
   142  	print("PC=", hex(c.rip()), "\n")
   143  	if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
   144  		print("signal arrived during cgo execution\n")
   145  		gp = _g_.m.lockedg
   146  	}
   147  	print("\n")
   148  
   149  	var docrash bool
   150  	if gotraceback(&docrash) > 0 {
   151  		goroutineheader(gp)
   152  		tracebacktrap(uintptr(c.rip()), uintptr(c.rsp()), 0, gp)
   153  		tracebackothers(gp)
   154  		print("\n")
   155  		dumpregs(c)
   156  	}
   157  
   158  	if docrash {
   159  		crash()
   160  	}
   161  
   162  	exit(2)
   163  }