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