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 }