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 5 package runtime 6 7 import "unsafe" 8 9 // May run during STW, so write barriers are not allowed. 10 //go:nowritebarrier 11 func sighandler(_ureg *ureg, note *byte, gp *g) int { 12 _g_ := getg() 13 var t sigTabT 14 var docrash bool 15 var sig int 16 var flags int 17 18 c := &sigctxt{_ureg} 19 notestr := gostringnocopy(note) 20 21 // The kernel will never pass us a nil note or ureg so we probably 22 // made a mistake somewhere in sigtramp. 23 if _ureg == nil || note == nil { 24 print("sighandler: ureg ", _ureg, " note ", note, "\n") 25 goto Throw 26 } 27 // Check that the note is no more than ERRMAX bytes (including 28 // the trailing NUL). We should never receive a longer note. 29 if len(notestr) > _ERRMAX-1 { 30 print("sighandler: note is longer than ERRMAX\n") 31 goto Throw 32 } 33 // See if the note matches one of the patterns in sigtab. 34 // Notes that do not match any pattern can be handled at a higher 35 // level by the program but will otherwise be ignored. 36 flags = _SigNotify 37 for sig, t = range sigtable { 38 if hasprefix(notestr, t.name) { 39 flags = t.flags 40 break 41 } 42 } 43 if flags&_SigGoExit != 0 { 44 exits((*byte)(add(unsafe.Pointer(note), 9))) // Strip "go: exit " prefix. 45 } 46 if flags&_SigPanic != 0 { 47 // Copy the error string from sigtramp's stack into m->notesig so 48 // we can reliably access it from the panic routines. 49 memmove(unsafe.Pointer(_g_.m.notesig), unsafe.Pointer(note), uintptr(len(notestr)+1)) 50 gp.sig = uint32(sig) 51 gp.sigpc = c.pc() 52 53 pc := uintptr(c.pc()) 54 sp := uintptr(c.sp()) 55 56 // If we don't recognize the PC as code 57 // but we do recognize the top pointer on the stack as code, 58 // then assume this was a call to non-code and treat like 59 // pc == 0, to make unwinding show the context. 60 if pc != 0 && findfunc(pc) == nil && findfunc(*(*uintptr)(unsafe.Pointer(sp))) != nil { 61 pc = 0 62 } 63 64 // Only push sigpanic if PC != 0. 65 // 66 // If PC == 0, probably panicked because of a call to a nil func. 67 // Not pushing that onto SP will make the trace look like a call 68 // to sigpanic instead. (Otherwise the trace will end at 69 // sigpanic and we won't get to see who faulted). 70 if pc != 0 { 71 if regSize > ptrSize { 72 sp -= ptrSize 73 *(*uintptr)(unsafe.Pointer(sp)) = 0 74 } 75 sp -= ptrSize 76 *(*uintptr)(unsafe.Pointer(sp)) = pc 77 c.setsp(sp) 78 } 79 c.setpc(funcPC(sigpanic)) 80 return _NCONT 81 } 82 if flags&_SigNotify != 0 { 83 if sendNote(note) { 84 return _NCONT 85 } 86 } 87 if flags&_SigKill != 0 { 88 goto Exit 89 } 90 if flags&_SigThrow == 0 { 91 return _NCONT 92 } 93 Throw: 94 _g_.m.throwing = 1 95 _g_.m.caughtsig.set(gp) 96 startpanic() 97 print(notestr, "\n") 98 print("PC=", hex(c.pc()), "\n") 99 print("\n") 100 if gotraceback(&docrash) > 0 { 101 goroutineheader(gp) 102 tracebacktrap(c.pc(), c.sp(), 0, gp) 103 tracebackothers(gp) 104 print("\n") 105 dumpregs(_ureg) 106 } 107 if docrash { 108 crash() 109 } 110 Exit: 111 goexitsall(note) 112 exits(note) 113 return _NDFLT // not reached 114 } 115 116 func sigenable(sig uint32) { 117 } 118 119 func sigdisable(sig uint32) { 120 } 121 122 func sigignore(sig uint32) { 123 } 124 125 func resetcpuprofiler(hz int32) { 126 // TODO: Enable profiling interrupts. 127 getg().m.profilehz = hz 128 } 129