Source file src/runtime/os3_plan9.go

     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  	"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
    17  func 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  	}
   125  Throw:
   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  	}
   143  Exit:
   144  	goexitsall(note)
   145  	exits(note)
   146  	return _NDFLT // not reached
   147  }
   148  
   149  func sigenable(sig uint32) {
   150  }
   151  
   152  func sigdisable(sig uint32) {
   153  }
   154  
   155  func sigignore(sig uint32) {
   156  }
   157  
   158  func setProcessCPUProfiler(hz int32) {
   159  }
   160  
   161  func setThreadCPUProfiler(hz int32) {
   162  	// TODO: Enable profiling interrupts.
   163  	getg().m.profilehz = hz
   164  }
   165  
   166  // gsignalStack is unused on Plan 9.
   167  type gsignalStack struct{}
   168  

View as plain text