github.com/letsencrypt/go@v0.0.0-20160714163537-4054769a31f6/src/runtime/signal_arm64.go (about)

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