github.com/mdempsky/go@v0.0.0-20151201204031-5dd372bd1e70/src/runtime/signal_mips64x.go (about) 1 // Copyright 2015 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 linux 6 // +build mips64 mips64le 7 8 package runtime 9 10 import ( 11 "runtime/internal/sys" 12 "unsafe" 13 ) 14 15 func dumpregs(c *sigctxt) { 16 print("r0 ", hex(c.r0()), "\t") 17 print("r1 ", hex(c.r1()), "\n") 18 print("r2 ", hex(c.r2()), "\t") 19 print("r3 ", hex(c.r3()), "\n") 20 print("r4 ", hex(c.r4()), "\t") 21 print("r5 ", hex(c.r5()), "\n") 22 print("r6 ", hex(c.r6()), "\t") 23 print("r7 ", hex(c.r7()), "\n") 24 print("r8 ", hex(c.r8()), "\t") 25 print("r9 ", hex(c.r9()), "\n") 26 print("r10 ", hex(c.r10()), "\t") 27 print("r11 ", hex(c.r11()), "\n") 28 print("r12 ", hex(c.r12()), "\t") 29 print("r13 ", hex(c.r13()), "\n") 30 print("r14 ", hex(c.r14()), "\t") 31 print("r15 ", hex(c.r15()), "\n") 32 print("r16 ", hex(c.r16()), "\t") 33 print("r17 ", hex(c.r17()), "\n") 34 print("r18 ", hex(c.r18()), "\t") 35 print("r19 ", hex(c.r19()), "\n") 36 print("r20 ", hex(c.r20()), "\t") 37 print("r21 ", hex(c.r21()), "\n") 38 print("r22 ", hex(c.r22()), "\t") 39 print("r23 ", hex(c.r23()), "\n") 40 print("r24 ", hex(c.r24()), "\t") 41 print("r25 ", hex(c.r25()), "\n") 42 print("r26 ", hex(c.r26()), "\t") 43 print("r27 ", hex(c.r27()), "\n") 44 print("r28 ", hex(c.r28()), "\t") 45 print("r29 ", hex(c.r29()), "\n") 46 print("r30 ", hex(c.r30()), "\t") 47 print("r31 ", hex(c.r31()), "\n") 48 print("pc ", hex(c.pc()), "\t") 49 print("link ", hex(c.link()), "\n") 50 print("lo ", hex(c.lo()), "\t") 51 print("hi ", hex(c.hi()), "\n") 52 } 53 54 var crashing int32 55 56 // May run during STW, so write barriers are not allowed. 57 // 58 //go:nowritebarrierrec 59 func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) { 60 _g_ := getg() 61 c := &sigctxt{info, ctxt} 62 63 if sig == _SIGPROF { 64 sigprof(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.link()), gp, _g_.m) 65 return 66 } 67 flags := int32(_SigThrow) 68 if sig < uint32(len(sigtable)) { 69 flags = sigtable[sig].flags 70 } 71 if c.sigcode() != _SI_USER && flags&_SigPanic != 0 { 72 // Make it look like a call to the signal func. 73 // Have to pass arguments out of band since 74 // augmenting the stack frame would break 75 // the unwinding code. 76 gp.sig = sig 77 gp.sigcode0 = uintptr(c.sigcode()) 78 gp.sigcode1 = uintptr(c.sigaddr()) 79 gp.sigpc = uintptr(c.pc()) 80 81 // We arrange link, and pc to pretend the panicking 82 // function calls sigpanic directly. 83 // Always save LINK to stack so that panics in leaf 84 // functions are correctly handled. This smashes 85 // the stack frame but we're not going back there 86 // anyway. 87 sp := c.sp() - sys.PtrSize 88 c.set_sp(sp) 89 *(*uint64)(unsafe.Pointer(uintptr(sp))) = c.link() 90 91 pc := uintptr(gp.sigpc) 92 93 // If we don't recognize the PC as code 94 // but we do recognize the link register as code, 95 // then assume this was a call to non-code and treat like 96 // pc == 0, to make unwinding show the context. 97 if pc != 0 && findfunc(pc) == nil && findfunc(uintptr(c.link())) != nil { 98 pc = 0 99 } 100 101 // Don't bother saving PC if it's zero, which is 102 // probably a call to a nil func: the old link register 103 // is more useful in the stack trace. 104 if pc != 0 { 105 c.set_link(uint64(pc)) 106 } 107 108 // In case we are panicking from external C code 109 c.set_r30(uint64(uintptr(unsafe.Pointer(gp)))) 110 c.set_pc(uint64(funcPC(sigpanic))) 111 return 112 } 113 114 if c.sigcode() == _SI_USER || flags&_SigNotify != 0 { 115 if sigsend(sig) { 116 return 117 } 118 } 119 120 if flags&_SigKill != 0 { 121 exit(2) 122 } 123 124 if flags&_SigThrow == 0 { 125 return 126 } 127 128 _g_.m.throwing = 1 129 _g_.m.caughtsig.set(gp) 130 131 if crashing == 0 { 132 startpanic() 133 } 134 135 if sig < uint32(len(sigtable)) { 136 print(sigtable[sig].name, "\n") 137 } else { 138 print("Signal ", sig, "\n") 139 } 140 141 print("PC=", hex(c.pc()), " m=", _g_.m.id, "\n") 142 if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 { 143 print("signal arrived during cgo execution\n") 144 gp = _g_.m.lockedg 145 } 146 print("\n") 147 148 level, _, docrash := gotraceback() 149 if level > 0 { 150 goroutineheader(gp) 151 tracebacktrap(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.link()), gp) 152 if crashing > 0 && gp != _g_.m.curg && _g_.m.curg != nil && readgstatus(_g_.m.curg)&^_Gscan == _Grunning { 153 // tracebackothers on original m skipped this one; trace it now. 154 goroutineheader(_g_.m.curg) 155 traceback(^uintptr(0), ^uintptr(0), 0, gp) 156 } else if crashing == 0 { 157 tracebackothers(gp) 158 print("\n") 159 } 160 dumpregs(c) 161 } 162 163 if docrash { 164 crashing++ 165 if crashing < sched.mcount { 166 // There are other m's that need to dump their stacks. 167 // Relay SIGQUIT to the next m by sending it to the current process. 168 // All m's that have already received SIGQUIT have signal masks blocking 169 // receipt of any signals, so the SIGQUIT will go to an m that hasn't seen it yet. 170 // When the last m receives the SIGQUIT, it will fall through to the call to 171 // crash below. Just in case the relaying gets botched, each m involved in 172 // the relay sleeps for 5 seconds and then does the crash/exit itself. 173 // In expected operation, the last m has received the SIGQUIT and run 174 // crash/exit and the process is gone, all long before any of the 175 // 5-second sleeps have finished. 176 print("\n-----\n\n") 177 raiseproc(_SIGQUIT) 178 usleep(5 * 1000 * 1000) 179 } 180 crash() 181 } 182 183 exit(2) 184 }