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