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