github.com/4ad/go@v0.0.0-20161219182952-69a12818b605/src/runtime/signal_arm.go (about)

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