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 }