Home | History | Annotate | Download | only in runtime
      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
      6 // +build ppc64 ppc64le
      7 
      8 package runtime
      9 
     10 import "unsafe"
     11 
     12 func dumpregs(c *sigctxt) {
     13 	print("r0   ", hex(c.r0()), "\t")
     14 	print("r1   ", hex(c.r1()), "\n")
     15 	print("r2   ", hex(c.r2()), "\t")
     16 	print("r3   ", hex(c.r3()), "\n")
     17 	print("r4   ", hex(c.r4()), "\t")
     18 	print("r5   ", hex(c.r5()), "\n")
     19 	print("r6   ", hex(c.r6()), "\t")
     20 	print("r7   ", hex(c.r7()), "\n")
     21 	print("r8   ", hex(c.r8()), "\t")
     22 	print("r9   ", hex(c.r9()), "\n")
     23 	print("r10  ", hex(c.r10()), "\t")
     24 	print("r11  ", hex(c.r11()), "\n")
     25 	print("r12  ", hex(c.r12()), "\t")
     26 	print("r13  ", hex(c.r13()), "\n")
     27 	print("r14  ", hex(c.r14()), "\t")
     28 	print("r15  ", hex(c.r15()), "\n")
     29 	print("r16  ", hex(c.r16()), "\t")
     30 	print("r17  ", hex(c.r17()), "\n")
     31 	print("r18  ", hex(c.r18()), "\t")
     32 	print("r19  ", hex(c.r19()), "\n")
     33 	print("r20  ", hex(c.r20()), "\t")
     34 	print("r21  ", hex(c.r21()), "\n")
     35 	print("r22  ", hex(c.r22()), "\t")
     36 	print("r23  ", hex(c.r23()), "\n")
     37 	print("r24  ", hex(c.r24()), "\t")
     38 	print("r25  ", hex(c.r25()), "\n")
     39 	print("r26  ", hex(c.r26()), "\t")
     40 	print("r27  ", hex(c.r27()), "\n")
     41 	print("r28  ", hex(c.r28()), "\t")
     42 	print("r29  ", hex(c.r29()), "\n")
     43 	print("r30  ", hex(c.r30()), "\t")
     44 	print("r31  ", hex(c.r31()), "\n")
     45 	print("pc   ", hex(c.pc()), "\t")
     46 	print("ctr  ", hex(c.ctr()), "\n")
     47 	print("link ", hex(c.link()), "\t")
     48 	print("xer  ", hex(c.xer()), "\n")
     49 	print("ccr  ", hex(c.ccr()), "\t")
     50 	print("trap ", hex(c.trap()), "\n")
     51 }
     52 
     53 var crashing int32
     54 
     55 // May run during STW, so write barriers are not allowed.
     56 //go:nowritebarrier
     57 func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
     58 	_g_ := getg()
     59 	c := &sigctxt{info, ctxt}
     60 
     61 	if sig == _SIGPROF {
     62 		sigprof(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.link()), gp, _g_.m)
     63 		return
     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 link, and pc to pretend the panicking
     80 		// function calls sigpanic directly.
     81 		// Always save LINK 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() - ptrSize
     86 		c.set_sp(sp)
     87 		*(*uint64)(unsafe.Pointer(uintptr(sp))) = c.link()
     88 
     89 		pc := uintptr(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.link())) != 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_link(uint64(pc))
    104 		}
    105 
    106 		// In case we are panicking from external C code
    107 		c.set_r0(0)
    108 		c.set_r30(uint64(uintptr(unsafe.Pointer(gp))))
    109 		c.set_pc(uint64(funcPC(sigpanic)))
    110 		return
    111 	}
    112 
    113 	if c.sigcode() == _SI_USER || flags&_SigNotify != 0 {
    114 		if sigsend(sig) {
    115 			return
    116 		}
    117 	}
    118 
    119 	if flags&_SigKill != 0 {
    120 		exit(2)
    121 	}
    122 
    123 	if flags&_SigThrow == 0 {
    124 		return
    125 	}
    126 
    127 	_g_.m.throwing = 1
    128 	_g_.m.caughtsig.set(gp)
    129 
    130 	if crashing == 0 {
    131 		startpanic()
    132 	}
    133 
    134 	if sig < uint32(len(sigtable)) {
    135 		print(sigtable[sig].name, "\n")
    136 	} else {
    137 		print("Signal ", sig, "\n")
    138 	}
    139 
    140 	print("PC=", hex(c.pc()), " m=", _g_.m.id, "\n")
    141 	if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
    142 		print("signal arrived during cgo execution\n")
    143 		gp = _g_.m.lockedg
    144 	}
    145 	print("\n")
    146 
    147 	var docrash bool
    148 	if gotraceback(&docrash) > 0 {
    149 		goroutineheader(gp)
    150 		tracebacktrap(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.link()), gp)
    151 		if crashing > 0 && gp != _g_.m.curg && _g_.m.curg != nil && readgstatus(_g_.m.curg)&^_Gscan == _Grunning {
    152 			// tracebackothers on original m skipped this one; trace it now.
    153 			goroutineheader(_g_.m.curg)
    154 			traceback(^uintptr(0), ^uintptr(0), 0, gp)
    155 		} else if crashing == 0 {
    156 			tracebackothers(gp)
    157 			print("\n")
    158 		}
    159 		dumpregs(c)
    160 	}
    161 
    162 	if docrash {
    163 		crashing++
    164 		if crashing < sched.mcount {
    165 			// There are other m's that need to dump their stacks.
    166 			// Relay SIGQUIT to the next m by sending it to the current process.
    167 			// All m's that have already received SIGQUIT have signal masks blocking
    168 			// receipt of any signals, so the SIGQUIT will go to an m that hasn't seen it yet.
    169 			// When the last m receives the SIGQUIT, it will fall through to the call to
    170 			// crash below. Just in case the relaying gets botched, each m involved in
    171 			// the relay sleeps for 5 seconds and then does the crash/exit itself.
    172 			// In expected operation, the last m has received the SIGQUIT and run
    173 			// crash/exit and the process is gone, all long before any of the
    174 			// 5-second sleeps have finished.
    175 			print("\n-----\n\n")
    176 			raiseproc(_SIGQUIT)
    177 			usleep(5 * 1000 * 1000)
    178 		}
    179 		crash()
    180 	}
    181 
    182 	exit(2)
    183 }
    184