github.com/mdempsky/go@v0.0.0-20151201204031-5dd372bd1e70/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 := uintptr(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 flags&_SigKill != 0 {
   103  		exit(2)
   104  	}
   105  
   106  	if flags&_SigThrow == 0 {
   107  		return
   108  	}
   109  
   110  	_g_.m.throwing = 1
   111  	_g_.m.caughtsig.set(gp)
   112  
   113  	if crashing == 0 {
   114  		startpanic()
   115  	}
   116  
   117  	if sig < uint32(len(sigtable)) {
   118  		print(sigtable[sig].name, "\n")
   119  	} else {
   120  		print("Signal ", sig, "\n")
   121  	}
   122  
   123  	print("PC=", hex(c.pc()), " m=", _g_.m.id, "\n")
   124  	if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
   125  		print("signal arrived during cgo execution\n")
   126  		gp = _g_.m.lockedg
   127  	}
   128  	print("\n")
   129  
   130  	level, _, docrash := gotraceback()
   131  	if level > 0 {
   132  		goroutineheader(gp)
   133  		tracebacktrap(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.lr()), gp)
   134  		if crashing > 0 && gp != _g_.m.curg && _g_.m.curg != nil && readgstatus(_g_.m.curg)&^_Gscan == _Grunning {
   135  			// tracebackothers on original m skipped this one; trace it now.
   136  			goroutineheader(_g_.m.curg)
   137  			traceback(^uintptr(0), ^uintptr(0), 0, gp)
   138  		} else if crashing == 0 {
   139  			tracebackothers(gp)
   140  			print("\n")
   141  		}
   142  		dumpregs(c)
   143  	}
   144  
   145  	if docrash {
   146  		crashing++
   147  		if crashing < sched.mcount {
   148  			// There are other m's that need to dump their stacks.
   149  			// Relay SIGQUIT to the next m by sending it to the current process.
   150  			// All m's that have already received SIGQUIT have signal masks blocking
   151  			// receipt of any signals, so the SIGQUIT will go to an m that hasn't seen it yet.
   152  			// When the last m receives the SIGQUIT, it will fall through to the call to
   153  			// crash below. Just in case the relaying gets botched, each m involved in
   154  			// the relay sleeps for 5 seconds and then does the crash/exit itself.
   155  			// In expected operation, the last m has received the SIGQUIT and run
   156  			// crash/exit and the process is gone, all long before any of the
   157  			// 5-second sleeps have finished.
   158  			print("\n-----\n\n")
   159  			raiseproc(_SIGQUIT)
   160  			usleep(5 * 1000 * 1000)
   161  		}
   162  		crash()
   163  	}
   164  
   165  	exit(2)
   166  }