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