github.com/aloncn/graphics-go@v0.0.1/src/runtime/signal_arm64.go (about) 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 darwin 6 7 package runtime 8 9 import ( 10 "runtime/internal/sys" 11 "unsafe" 12 ) 13 14 func dumpregs(c *sigctxt) { 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("r11 ", hex(c.r11()), "\n") 27 print("r12 ", hex(c.r12()), "\n") 28 print("r13 ", hex(c.r13()), "\n") 29 print("r14 ", hex(c.r14()), "\n") 30 print("r15 ", hex(c.r15()), "\n") 31 print("r16 ", hex(c.r16()), "\n") 32 print("r17 ", hex(c.r17()), "\n") 33 print("r18 ", hex(c.r18()), "\n") 34 print("r19 ", hex(c.r19()), "\n") 35 print("r20 ", hex(c.r20()), "\n") 36 print("r21 ", hex(c.r21()), "\n") 37 print("r22 ", hex(c.r22()), "\n") 38 print("r23 ", hex(c.r23()), "\n") 39 print("r24 ", hex(c.r24()), "\n") 40 print("r25 ", hex(c.r25()), "\n") 41 print("r26 ", hex(c.r26()), "\n") 42 print("r27 ", hex(c.r27()), "\n") 43 print("r28 ", hex(c.r28()), "\n") 44 print("r29 ", hex(c.r29()), "\n") 45 print("lr ", hex(c.lr()), "\n") 46 print("sp ", hex(c.sp()), "\n") 47 print("pc ", hex(c.pc()), "\n") 48 print("fault ", hex(c.fault()), "\n") 49 } 50 51 var crashing int32 52 53 // May run during STW, so write barriers are not allowed. 54 // 55 //go:nowritebarrierrec 56 func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) { 57 _g_ := getg() 58 c := &sigctxt{info, ctxt} 59 60 if sig == _SIGPROF { 61 sigprof(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.lr()), gp, _g_.m) 62 return 63 } 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 lr, and pc to pretend the panicking 80 // function calls sigpanic directly. 81 // Always save LR 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() - sys.SpAlign // needs only sizeof uint64, but must align the stack 86 c.set_sp(sp) 87 *(*uint64)(unsafe.Pointer(uintptr(sp))) = c.lr() 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.lr())) != 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_lr(uint64(pc)) 104 } 105 106 // In case we are panicking from external C code 107 c.set_r28(uint64(uintptr(unsafe.Pointer(gp)))) 108 c.set_pc(uint64(funcPC(sigpanic))) 109 return 110 } 111 112 if c.sigcode() == _SI_USER || flags&_SigNotify != 0 { 113 if sigsend(sig) { 114 return 115 } 116 } 117 118 if c.sigcode() == _SI_USER && signal_ignored(sig) { 119 return 120 } 121 122 if flags&_SigKill != 0 { 123 dieFromSignal(int32(sig)) 124 } 125 126 if flags&_SigThrow == 0 { 127 return 128 } 129 130 _g_.m.throwing = 1 131 _g_.m.caughtsig.set(gp) 132 133 if crashing == 0 { 134 startpanic() 135 } 136 137 if sig < uint32(len(sigtable)) { 138 print(sigtable[sig].name, "\n") 139 } else { 140 print("Signal ", sig, "\n") 141 } 142 143 print("PC=", hex(c.pc()), " m=", _g_.m.id, "\n") 144 if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 { 145 print("signal arrived during cgo execution\n") 146 gp = _g_.m.lockedg 147 } 148 print("\n") 149 150 level, _, docrash := gotraceback() 151 if level > 0 { 152 goroutineheader(gp) 153 tracebacktrap(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.lr()), gp) 154 if crashing > 0 && gp != _g_.m.curg && _g_.m.curg != nil && readgstatus(_g_.m.curg)&^_Gscan == _Grunning { 155 // tracebackothers on original m skipped this one; trace it now. 156 goroutineheader(_g_.m.curg) 157 traceback(^uintptr(0), ^uintptr(0), 0, gp) 158 } else if crashing == 0 { 159 tracebackothers(gp) 160 print("\n") 161 } 162 dumpregs(c) 163 } 164 165 if docrash { 166 crashing++ 167 if crashing < sched.mcount { 168 // There are other m's that need to dump their stacks. 169 // Relay SIGQUIT to the next m by sending it to the current process. 170 // All m's that have already received SIGQUIT have signal masks blocking 171 // receipt of any signals, so the SIGQUIT will go to an m that hasn't seen it yet. 172 // When the last m receives the SIGQUIT, it will fall through to the call to 173 // crash below. Just in case the relaying gets botched, each m involved in 174 // the relay sleeps for 5 seconds and then does the crash/exit itself. 175 // In expected operation, the last m has received the SIGQUIT and run 176 // crash/exit and the process is gone, all long before any of the 177 // 5-second sleeps have finished. 178 print("\n-----\n\n") 179 raiseproc(_SIGQUIT) 180 usleep(5 * 1000 * 1000) 181 } 182 crash() 183 } 184 185 exit(2) 186 }