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

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