1// Copyright 2010 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 5package runtime 6 7import ( 8 "internal/abi" 9 "internal/goarch" 10 "internal/stringslite" 11 "unsafe" 12) 13 14// May run during STW, so write barriers are not allowed. 15// 16//go:nowritebarrierrec 17func sighandler(_ureg *ureg, note *byte, gp *g) int { 18 gsignal := getg() 19 mp := gsignal.m 20 21 var t sigTabT 22 var docrash bool 23 var sig int 24 var flags int 25 var level int32 26 27 c := &sigctxt{_ureg} 28 notestr := gostringnocopy(note) 29 30 // The kernel will never pass us a nil note or ureg so we probably 31 // made a mistake somewhere in sigtramp. 32 if _ureg == nil || note == nil { 33 print("sighandler: ureg ", _ureg, " note ", note, "\n") 34 goto Throw 35 } 36 // Check that the note is no more than ERRMAX bytes (including 37 // the trailing NUL). We should never receive a longer note. 38 if len(notestr) > _ERRMAX-1 { 39 print("sighandler: note is longer than ERRMAX\n") 40 goto Throw 41 } 42 if isAbortPC(c.pc()) { 43 // Never turn abort into a panic. 44 goto Throw 45 } 46 // See if the note matches one of the patterns in sigtab. 47 // Notes that do not match any pattern can be handled at a higher 48 // level by the program but will otherwise be ignored. 49 flags = _SigNotify 50 for sig, t = range sigtable { 51 if stringslite.HasPrefix(notestr, t.name) { 52 flags = t.flags 53 break 54 } 55 } 56 if flags&_SigPanic != 0 && gp.throwsplit { 57 // We can't safely sigpanic because it may grow the 58 // stack. Abort in the signal handler instead. 59 flags = (flags &^ _SigPanic) | _SigThrow 60 } 61 if flags&_SigGoExit != 0 { 62 exits((*byte)(add(unsafe.Pointer(note), 9))) // Strip "go: exit " prefix. 63 } 64 if flags&_SigPanic != 0 { 65 // Copy the error string from sigtramp's stack into m->notesig so 66 // we can reliably access it from the panic routines. 67 memmove(unsafe.Pointer(mp.notesig), unsafe.Pointer(note), uintptr(len(notestr)+1)) 68 gp.sig = uint32(sig) 69 gp.sigpc = c.pc() 70 71 pc := c.pc() 72 sp := c.sp() 73 74 // If we don't recognize the PC as code 75 // but we do recognize the top pointer on the stack as code, 76 // then assume this was a call to non-code and treat like 77 // pc == 0, to make unwinding show the context. 78 if pc != 0 && !findfunc(pc).valid() && findfunc(*(*uintptr)(unsafe.Pointer(sp))).valid() { 79 pc = 0 80 } 81 82 // IF LR exists, sigpanictramp must save it to the stack 83 // before entry to sigpanic so that panics in leaf 84 // functions are correctly handled. This will smash 85 // the stack frame but we're not going back there 86 // anyway. 87 if usesLR { 88 c.savelr(c.lr()) 89 } 90 91 // If PC == 0, probably panicked because of a call to a nil func. 92 // Not faking that as the return address will make the trace look like a call 93 // to sigpanic instead. (Otherwise the trace will end at 94 // sigpanic and we won't get to see who faulted). 95 if pc != 0 { 96 if usesLR { 97 c.setlr(pc) 98 } else { 99 sp -= goarch.PtrSize 100 *(*uintptr)(unsafe.Pointer(sp)) = pc 101 c.setsp(sp) 102 } 103 } 104 if usesLR { 105 c.setpc(abi.FuncPCABI0(sigpanictramp)) 106 } else { 107 c.setpc(abi.FuncPCABI0(sigpanic0)) 108 } 109 return _NCONT 110 } 111 if flags&_SigNotify != 0 { 112 if ignoredNote(note) { 113 return _NCONT 114 } 115 if sendNote(note) { 116 return _NCONT 117 } 118 } 119 if flags&_SigKill != 0 { 120 goto Exit 121 } 122 if flags&_SigThrow == 0 { 123 return _NCONT 124 } 125Throw: 126 mp.throwing = throwTypeRuntime 127 mp.caughtsig.set(gp) 128 startpanic_m() 129 print(notestr, "\n") 130 print("PC=", hex(c.pc()), "\n") 131 print("\n") 132 level, _, docrash = gotraceback() 133 if level > 0 { 134 goroutineheader(gp) 135 tracebacktrap(c.pc(), c.sp(), c.lr(), gp) 136 tracebackothers(gp) 137 print("\n") 138 dumpregs(_ureg) 139 } 140 if docrash { 141 crash() 142 } 143Exit: 144 goexitsall(note) 145 exits(note) 146 return _NDFLT // not reached 147} 148 149func sigenable(sig uint32) { 150} 151 152func sigdisable(sig uint32) { 153} 154 155func sigignore(sig uint32) { 156} 157 158func setProcessCPUProfiler(hz int32) { 159} 160 161func setThreadCPUProfiler(hz int32) { 162 // TODO: Enable profiling interrupts. 163 getg().m.profilehz = hz 164} 165 166// gsignalStack is unused on Plan 9. 167type gsignalStack struct{} 168