rsc.io/go@v0.0.0-20150416155037-e040fd465409/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  // May run during STW, so write barriers are not allowed.
    28  //go:nowritebarrier
    29  func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
    30  	_g_ := getg()
    31  	c := &sigctxt{info, ctxt}
    32  
    33  	if sig == _SIGPROF {
    34  		sigprof(uintptr(c.eip()), uintptr(c.esp()), 0, gp, _g_.m)
    35  		return
    36  	}
    37  
    38  	flags := int32(_SigThrow)
    39  	if sig < uint32(len(sigtable)) {
    40  		flags = sigtable[sig].flags
    41  	}
    42  	if c.sigcode() != _SI_USER && flags&_SigPanic != 0 {
    43  		// Make it look like a call to the signal func.
    44  		// Have to pass arguments out of band since
    45  		// augmenting the stack frame would break
    46  		// the unwinding code.
    47  		gp.sig = sig
    48  		gp.sigcode0 = uintptr(c.sigcode())
    49  		gp.sigcode1 = uintptr(c.sigaddr())
    50  		gp.sigpc = uintptr(c.eip())
    51  
    52  		if GOOS == "darwin" {
    53  			// Work around Leopard bug that doesn't set FPE_INTDIV.
    54  			// Look at instruction to see if it is a divide.
    55  			// Not necessary in Snow Leopard (si_code will be != 0).
    56  			if sig == _SIGFPE && gp.sigcode0 == 0 {
    57  				pc := (*[4]byte)(unsafe.Pointer(gp.sigpc))
    58  				i := 0
    59  				if pc[i] == 0x66 { // 16-bit instruction prefix
    60  					i++
    61  				}
    62  				if pc[i] == 0xF6 || pc[i] == 0xF7 {
    63  					gp.sigcode0 = _FPE_INTDIV
    64  				}
    65  			}
    66  		}
    67  
    68  		// Only push runtime.sigpanic if rip != 0.
    69  		// If 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 c.eip() != 0 {
    75  			sp := c.esp()
    76  			if regSize > ptrSize {
    77  				sp -= ptrSize
    78  				*(*uintptr)(unsafe.Pointer(uintptr(sp))) = 0
    79  			}
    80  			sp -= ptrSize
    81  			*(*uintptr)(unsafe.Pointer(uintptr(sp))) = uintptr(c.eip())
    82  			c.set_esp(sp)
    83  		}
    84  		c.set_eip(uint32(funcPC(sigpanic)))
    85  		return
    86  	}
    87  
    88  	if c.sigcode() == _SI_USER || flags&_SigNotify != 0 {
    89  		if sigsend(sig) {
    90  			return
    91  		}
    92  	}
    93  
    94  	if flags&_SigKill != 0 {
    95  		exit(2)
    96  	}
    97  
    98  	if flags&_SigThrow == 0 {
    99  		return
   100  	}
   101  
   102  	_g_.m.throwing = 1
   103  	setGNoWriteBarrier(&_g_.m.caughtsig, gp)
   104  	startpanic()
   105  
   106  	if sig < uint32(len(sigtable)) {
   107  		print(sigtable[sig].name, "\n")
   108  	} else {
   109  		print("Signal ", sig, "\n")
   110  	}
   111  
   112  	print("PC=", hex(c.eip()), "\n")
   113  	if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
   114  		print("signal arrived during cgo execution\n")
   115  		gp = _g_.m.lockedg
   116  	}
   117  	print("\n")
   118  
   119  	var docrash bool
   120  	if gotraceback(&docrash) > 0 {
   121  		goroutineheader(gp)
   122  		tracebacktrap(uintptr(c.eip()), uintptr(c.esp()), 0, gp)
   123  		tracebackothers(gp)
   124  		print("\n")
   125  		dumpregs(c)
   126  	}
   127  
   128  	if docrash {
   129  		crash()
   130  	}
   131  
   132  	exit(2)
   133  }