github.com/mdempsky/go@v0.0.0-20151201204031-5dd372bd1e70/src/runtime/signal_mips64x.go (about)

     1  // Copyright 2015 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
     6  // +build mips64 mips64le
     7  
     8  package runtime
     9  
    10  import (
    11  	"runtime/internal/sys"
    12  	"unsafe"
    13  )
    14  
    15  func dumpregs(c *sigctxt) {
    16  	print("r0   ", hex(c.r0()), "\t")
    17  	print("r1   ", hex(c.r1()), "\n")
    18  	print("r2   ", hex(c.r2()), "\t")
    19  	print("r3   ", hex(c.r3()), "\n")
    20  	print("r4   ", hex(c.r4()), "\t")
    21  	print("r5   ", hex(c.r5()), "\n")
    22  	print("r6   ", hex(c.r6()), "\t")
    23  	print("r7   ", hex(c.r7()), "\n")
    24  	print("r8   ", hex(c.r8()), "\t")
    25  	print("r9   ", hex(c.r9()), "\n")
    26  	print("r10  ", hex(c.r10()), "\t")
    27  	print("r11  ", hex(c.r11()), "\n")
    28  	print("r12  ", hex(c.r12()), "\t")
    29  	print("r13  ", hex(c.r13()), "\n")
    30  	print("r14  ", hex(c.r14()), "\t")
    31  	print("r15  ", hex(c.r15()), "\n")
    32  	print("r16  ", hex(c.r16()), "\t")
    33  	print("r17  ", hex(c.r17()), "\n")
    34  	print("r18  ", hex(c.r18()), "\t")
    35  	print("r19  ", hex(c.r19()), "\n")
    36  	print("r20  ", hex(c.r20()), "\t")
    37  	print("r21  ", hex(c.r21()), "\n")
    38  	print("r22  ", hex(c.r22()), "\t")
    39  	print("r23  ", hex(c.r23()), "\n")
    40  	print("r24  ", hex(c.r24()), "\t")
    41  	print("r25  ", hex(c.r25()), "\n")
    42  	print("r26  ", hex(c.r26()), "\t")
    43  	print("r27  ", hex(c.r27()), "\n")
    44  	print("r28  ", hex(c.r28()), "\t")
    45  	print("r29  ", hex(c.r29()), "\n")
    46  	print("r30  ", hex(c.r30()), "\t")
    47  	print("r31  ", hex(c.r31()), "\n")
    48  	print("pc   ", hex(c.pc()), "\t")
    49  	print("link ", hex(c.link()), "\n")
    50  	print("lo   ", hex(c.lo()), "\t")
    51  	print("hi   ", hex(c.hi()), "\n")
    52  }
    53  
    54  var crashing int32
    55  
    56  // May run during STW, so write barriers are not allowed.
    57  //
    58  //go:nowritebarrierrec
    59  func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
    60  	_g_ := getg()
    61  	c := &sigctxt{info, ctxt}
    62  
    63  	if sig == _SIGPROF {
    64  		sigprof(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.link()), gp, _g_.m)
    65  		return
    66  	}
    67  	flags := int32(_SigThrow)
    68  	if sig < uint32(len(sigtable)) {
    69  		flags = sigtable[sig].flags
    70  	}
    71  	if c.sigcode() != _SI_USER && flags&_SigPanic != 0 {
    72  		// Make it look like a call to the signal func.
    73  		// Have to pass arguments out of band since
    74  		// augmenting the stack frame would break
    75  		// the unwinding code.
    76  		gp.sig = sig
    77  		gp.sigcode0 = uintptr(c.sigcode())
    78  		gp.sigcode1 = uintptr(c.sigaddr())
    79  		gp.sigpc = uintptr(c.pc())
    80  
    81  		// We arrange link, and pc to pretend the panicking
    82  		// function calls sigpanic directly.
    83  		// Always save LINK to stack so that panics in leaf
    84  		// functions are correctly handled. This smashes
    85  		// the stack frame but we're not going back there
    86  		// anyway.
    87  		sp := c.sp() - sys.PtrSize
    88  		c.set_sp(sp)
    89  		*(*uint64)(unsafe.Pointer(uintptr(sp))) = c.link()
    90  
    91  		pc := uintptr(gp.sigpc)
    92  
    93  		// If we don't recognize the PC as code
    94  		// but we do recognize the link register as code,
    95  		// then assume this was a call to non-code and treat like
    96  		// pc == 0, to make unwinding show the context.
    97  		if pc != 0 && findfunc(pc) == nil && findfunc(uintptr(c.link())) != nil {
    98  			pc = 0
    99  		}
   100  
   101  		// Don't bother saving PC if it's zero, which is
   102  		// probably a call to a nil func: the old link register
   103  		// is more useful in the stack trace.
   104  		if pc != 0 {
   105  			c.set_link(uint64(pc))
   106  		}
   107  
   108  		// In case we are panicking from external C code
   109  		c.set_r30(uint64(uintptr(unsafe.Pointer(gp))))
   110  		c.set_pc(uint64(funcPC(sigpanic)))
   111  		return
   112  	}
   113  
   114  	if c.sigcode() == _SI_USER || flags&_SigNotify != 0 {
   115  		if sigsend(sig) {
   116  			return
   117  		}
   118  	}
   119  
   120  	if flags&_SigKill != 0 {
   121  		exit(2)
   122  	}
   123  
   124  	if flags&_SigThrow == 0 {
   125  		return
   126  	}
   127  
   128  	_g_.m.throwing = 1
   129  	_g_.m.caughtsig.set(gp)
   130  
   131  	if crashing == 0 {
   132  		startpanic()
   133  	}
   134  
   135  	if sig < uint32(len(sigtable)) {
   136  		print(sigtable[sig].name, "\n")
   137  	} else {
   138  		print("Signal ", sig, "\n")
   139  	}
   140  
   141  	print("PC=", hex(c.pc()), " m=", _g_.m.id, "\n")
   142  	if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
   143  		print("signal arrived during cgo execution\n")
   144  		gp = _g_.m.lockedg
   145  	}
   146  	print("\n")
   147  
   148  	level, _, docrash := gotraceback()
   149  	if level > 0 {
   150  		goroutineheader(gp)
   151  		tracebacktrap(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.link()), gp)
   152  		if crashing > 0 && gp != _g_.m.curg && _g_.m.curg != nil && readgstatus(_g_.m.curg)&^_Gscan == _Grunning {
   153  			// tracebackothers on original m skipped this one; trace it now.
   154  			goroutineheader(_g_.m.curg)
   155  			traceback(^uintptr(0), ^uintptr(0), 0, gp)
   156  		} else if crashing == 0 {
   157  			tracebackothers(gp)
   158  			print("\n")
   159  		}
   160  		dumpregs(c)
   161  	}
   162  
   163  	if docrash {
   164  		crashing++
   165  		if crashing < sched.mcount {
   166  			// There are other m's that need to dump their stacks.
   167  			// Relay SIGQUIT to the next m by sending it to the current process.
   168  			// All m's that have already received SIGQUIT have signal masks blocking
   169  			// receipt of any signals, so the SIGQUIT will go to an m that hasn't seen it yet.
   170  			// When the last m receives the SIGQUIT, it will fall through to the call to
   171  			// crash below. Just in case the relaying gets botched, each m involved in
   172  			// the relay sleeps for 5 seconds and then does the crash/exit itself.
   173  			// In expected operation, the last m has received the SIGQUIT and run
   174  			// crash/exit and the process is gone, all long before any of the
   175  			// 5-second sleeps have finished.
   176  			print("\n-----\n\n")
   177  			raiseproc(_SIGQUIT)
   178  			usleep(5 * 1000 * 1000)
   179  		}
   180  		crash()
   181  	}
   182  
   183  	exit(2)
   184  }