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 }