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