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