github.com/hbdrawn/golang@v0.0.0-20141214014649-6b835209aba2/src/runtime/signal_386.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 darwin dragonfly freebsd linux nacl netbsd openbsd
     6  
     7  package runtime
     8  
     9  import "unsafe"
    10  
    11  func dumpregs(c *sigctxt) {
    12  	print("eax    ", hex(c.eax()), "\n")
    13  	print("ebx    ", hex(c.ebx()), "\n")
    14  	print("ecx    ", hex(c.ecx()), "\n")
    15  	print("edx    ", hex(c.edx()), "\n")
    16  	print("edi    ", hex(c.edi()), "\n")
    17  	print("esi    ", hex(c.esi()), "\n")
    18  	print("ebp    ", hex(c.ebp()), "\n")
    19  	print("esp    ", hex(c.esp()), "\n")
    20  	print("eip    ", hex(c.eip()), "\n")
    21  	print("eflags ", hex(c.eflags()), "\n")
    22  	print("cs     ", hex(c.cs()), "\n")
    23  	print("fs     ", hex(c.fs()), "\n")
    24  	print("gs     ", hex(c.gs()), "\n")
    25  }
    26  
    27  func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
    28  	_g_ := getg()
    29  	c := &sigctxt{info, ctxt}
    30  
    31  	if sig == _SIGPROF {
    32  		sigprof((*byte)(unsafe.Pointer(uintptr(c.eip()))), (*byte)(unsafe.Pointer(uintptr(c.esp()))), nil, gp, _g_.m)
    33  		return
    34  	}
    35  
    36  	flags := int32(_SigThrow)
    37  	if sig < uint32(len(sigtable)) {
    38  		flags = sigtable[sig].flags
    39  	}
    40  	if c.sigcode() != _SI_USER && flags&_SigPanic != 0 {
    41  		// Make it look like a call to the signal func.
    42  		// Have to pass arguments out of band since
    43  		// augmenting the stack frame would break
    44  		// the unwinding code.
    45  		gp.sig = sig
    46  		gp.sigcode0 = uintptr(c.sigcode())
    47  		gp.sigcode1 = uintptr(c.sigaddr())
    48  		gp.sigpc = uintptr(c.eip())
    49  
    50  		if GOOS == "darwin" {
    51  			// Work around Leopard bug that doesn't set FPE_INTDIV.
    52  			// Look at instruction to see if it is a divide.
    53  			// Not necessary in Snow Leopard (si_code will be != 0).
    54  			if sig == _SIGFPE && gp.sigcode0 == 0 {
    55  				pc := (*[4]byte)(unsafe.Pointer(gp.sigpc))
    56  				i := 0
    57  				if pc[i] == 0x66 { // 16-bit instruction prefix
    58  					i++
    59  				}
    60  				if pc[i] == 0xF6 || pc[i] == 0xF7 {
    61  					gp.sigcode0 = _FPE_INTDIV
    62  				}
    63  			}
    64  		}
    65  
    66  		// Only push runtime.sigpanic if rip != 0.
    67  		// If rip == 0, probably panicked because of a
    68  		// call to a nil func.  Not pushing that onto sp will
    69  		// make the trace look like a call to runtime.sigpanic instead.
    70  		// (Otherwise the trace will end at runtime.sigpanic and we
    71  		// won't get to see who faulted.)
    72  		if c.eip() != 0 {
    73  			sp := c.esp()
    74  			if regSize > ptrSize {
    75  				sp -= ptrSize
    76  				*(*uintptr)(unsafe.Pointer(uintptr(sp))) = 0
    77  			}
    78  			sp -= ptrSize
    79  			*(*uintptr)(unsafe.Pointer(uintptr(sp))) = uintptr(c.eip())
    80  			c.set_esp(sp)
    81  		}
    82  		c.set_eip(uint32(funcPC(sigpanic)))
    83  		return
    84  	}
    85  
    86  	if c.sigcode() == _SI_USER || flags&_SigNotify != 0 {
    87  		if sigsend(sig) {
    88  			return
    89  		}
    90  	}
    91  
    92  	if flags&_SigKill != 0 {
    93  		exit(2)
    94  	}
    95  
    96  	if flags&_SigThrow == 0 {
    97  		return
    98  	}
    99  
   100  	_g_.m.throwing = 1
   101  	_g_.m.caughtsig = gp
   102  	startpanic()
   103  
   104  	if sig < uint32(len(sigtable)) {
   105  		print(sigtable[sig].name, "\n")
   106  	} else {
   107  		print("Signal ", sig, "\n")
   108  	}
   109  
   110  	print("PC=", hex(c.eip()), "\n")
   111  	if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
   112  		print("signal arrived during cgo execution\n")
   113  		gp = _g_.m.lockedg
   114  	}
   115  	print("\n")
   116  
   117  	var docrash bool
   118  	if gotraceback(&docrash) > 0 {
   119  		goroutineheader(gp)
   120  		tracebacktrap(uintptr(c.eip()), uintptr(c.esp()), 0, gp)
   121  		tracebackothers(gp)
   122  		print("\n")
   123  		dumpregs(c)
   124  	}
   125  
   126  	if docrash {
   127  		crash()
   128  	}
   129  
   130  	exit(2)
   131  }