Commit 54d73145 authored by Austin Clements's avatar Austin Clements

[dev.cc] runtime: convert power64 signal handlers from C to Go

The power64 equivalent of CL 168500044

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/175280043
parent cf06ea68
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#define SIG_REGS(ctxt) (*((Sigcontext*)&((Ucontext*)(ctxt))->uc_mcontext)->regs)
#define SIG_R0(info, ctxt) (SIG_REGS(ctxt).gpr[0])
#define SIG_R1(info, ctxt) (SIG_REGS(ctxt).gpr[1])
#define SIG_R2(info, ctxt) (SIG_REGS(ctxt).gpr[2])
#define SIG_R3(info, ctxt) (SIG_REGS(ctxt).gpr[3])
#define SIG_R4(info, ctxt) (SIG_REGS(ctxt).gpr[4])
#define SIG_R5(info, ctxt) (SIG_REGS(ctxt).gpr[5])
#define SIG_R6(info, ctxt) (SIG_REGS(ctxt).gpr[6])
#define SIG_R7(info, ctxt) (SIG_REGS(ctxt).gpr[7])
#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).gpr[8])
#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).gpr[9])
#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).gpr[10])
#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).gpr[11])
#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).gpr[12])
#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).gpr[13])
#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).gpr[14])
#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).gpr[15])
#define SIG_R16(info, ctxt) (SIG_REGS(ctxt).gpr[16])
#define SIG_R17(info, ctxt) (SIG_REGS(ctxt).gpr[17])
#define SIG_R18(info, ctxt) (SIG_REGS(ctxt).gpr[18])
#define SIG_R19(info, ctxt) (SIG_REGS(ctxt).gpr[19])
#define SIG_R20(info, ctxt) (SIG_REGS(ctxt).gpr[20])
#define SIG_R21(info, ctxt) (SIG_REGS(ctxt).gpr[21])
#define SIG_R22(info, ctxt) (SIG_REGS(ctxt).gpr[22])
#define SIG_R23(info, ctxt) (SIG_REGS(ctxt).gpr[23])
#define SIG_R24(info, ctxt) (SIG_REGS(ctxt).gpr[24])
#define SIG_R25(info, ctxt) (SIG_REGS(ctxt).gpr[25])
#define SIG_R26(info, ctxt) (SIG_REGS(ctxt).gpr[26])
#define SIG_R27(info, ctxt) (SIG_REGS(ctxt).gpr[27])
#define SIG_R28(info, ctxt) (SIG_REGS(ctxt).gpr[28])
#define SIG_R29(info, ctxt) (SIG_REGS(ctxt).gpr[29])
#define SIG_R30(info, ctxt) (SIG_REGS(ctxt).gpr[30])
#define SIG_R31(info, ctxt) (SIG_REGS(ctxt).gpr[31])
#define SIG_SP(info, ctxt) (SIG_REGS(ctxt).gpr[1])
#define SIG_PC(info, ctxt) (SIG_REGS(ctxt).nip)
#define SIG_TRAP(info, ctxt) (SIG_REGS(ctxt).trap)
#define SIG_CTR(info, ctxt) (SIG_REGS(ctxt).ctr)
#define SIG_LINK(info, ctxt) (SIG_REGS(ctxt).link)
#define SIG_XER(info, ctxt) (SIG_REGS(ctxt).xer)
#define SIG_CCR(info, ctxt) (SIG_REGS(ctxt).ccr)
#define SIG_CODE0(info, ctxt) ((uintptr)(info)->si_code)
#define SIG_FAULT(info, ctxt) (SIG_REGS(ctxt).dar)
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#define SIG_REGS(ctxt) (*((Sigcontext*)&((Ucontext*)(ctxt))->uc_mcontext)->regs)
#define SIG_R0(info, ctxt) (SIG_REGS(ctxt).gpr[0])
#define SIG_R1(info, ctxt) (SIG_REGS(ctxt).gpr[1])
#define SIG_R2(info, ctxt) (SIG_REGS(ctxt).gpr[2])
#define SIG_R3(info, ctxt) (SIG_REGS(ctxt).gpr[3])
#define SIG_R4(info, ctxt) (SIG_REGS(ctxt).gpr[4])
#define SIG_R5(info, ctxt) (SIG_REGS(ctxt).gpr[5])
#define SIG_R6(info, ctxt) (SIG_REGS(ctxt).gpr[6])
#define SIG_R7(info, ctxt) (SIG_REGS(ctxt).gpr[7])
#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).gpr[8])
#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).gpr[9])
#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).gpr[10])
#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).gpr[11])
#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).gpr[12])
#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).gpr[13])
#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).gpr[14])
#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).gpr[15])
#define SIG_R16(info, ctxt) (SIG_REGS(ctxt).gpr[16])
#define SIG_R17(info, ctxt) (SIG_REGS(ctxt).gpr[17])
#define SIG_R18(info, ctxt) (SIG_REGS(ctxt).gpr[18])
#define SIG_R19(info, ctxt) (SIG_REGS(ctxt).gpr[19])
#define SIG_R20(info, ctxt) (SIG_REGS(ctxt).gpr[20])
#define SIG_R21(info, ctxt) (SIG_REGS(ctxt).gpr[21])
#define SIG_R22(info, ctxt) (SIG_REGS(ctxt).gpr[22])
#define SIG_R23(info, ctxt) (SIG_REGS(ctxt).gpr[23])
#define SIG_R24(info, ctxt) (SIG_REGS(ctxt).gpr[24])
#define SIG_R25(info, ctxt) (SIG_REGS(ctxt).gpr[25])
#define SIG_R26(info, ctxt) (SIG_REGS(ctxt).gpr[26])
#define SIG_R27(info, ctxt) (SIG_REGS(ctxt).gpr[27])
#define SIG_R28(info, ctxt) (SIG_REGS(ctxt).gpr[28])
#define SIG_R29(info, ctxt) (SIG_REGS(ctxt).gpr[29])
#define SIG_R30(info, ctxt) (SIG_REGS(ctxt).gpr[30])
#define SIG_R31(info, ctxt) (SIG_REGS(ctxt).gpr[31])
#define SIG_SP(info, ctxt) (SIG_REGS(ctxt).gpr[1])
#define SIG_PC(info, ctxt) (SIG_REGS(ctxt).nip)
#define SIG_TRAP(info, ctxt) (SIG_REGS(ctxt).trap)
#define SIG_CTR(info, ctxt) (SIG_REGS(ctxt).ctr)
#define SIG_LINK(info, ctxt) (SIG_REGS(ctxt).link)
#define SIG_XER(info, ctxt) (SIG_REGS(ctxt).xer)
#define SIG_CCR(info, ctxt) (SIG_REGS(ctxt).ccr)
#define SIG_CODE0(info, ctxt) ((uintptr)(info)->si_code)
#define SIG_FAULT(info, ctxt) (SIG_REGS(ctxt).dar)
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build linux
// +build power64 power64le
package runtime
import "unsafe"
type sigctxt struct {
info *siginfo
ctxt unsafe.Pointer
}
func (c *sigctxt) regs() *ptregs { return (*ucontext)(c.ctxt).uc_mcontext.regs }
func (c *sigctxt) r0() uint64 { return c.regs().gpr[0] }
func (c *sigctxt) r1() uint64 { return c.regs().gpr[1] }
func (c *sigctxt) r2() uint64 { return c.regs().gpr[2] }
func (c *sigctxt) r3() uint64 { return c.regs().gpr[3] }
func (c *sigctxt) r4() uint64 { return c.regs().gpr[4] }
func (c *sigctxt) r5() uint64 { return c.regs().gpr[5] }
func (c *sigctxt) r6() uint64 { return c.regs().gpr[6] }
func (c *sigctxt) r7() uint64 { return c.regs().gpr[7] }
func (c *sigctxt) r8() uint64 { return c.regs().gpr[8] }
func (c *sigctxt) r9() uint64 { return c.regs().gpr[9] }
func (c *sigctxt) r10() uint64 { return c.regs().gpr[10] }
func (c *sigctxt) r11() uint64 { return c.regs().gpr[11] }
func (c *sigctxt) r12() uint64 { return c.regs().gpr[12] }
func (c *sigctxt) r13() uint64 { return c.regs().gpr[13] }
func (c *sigctxt) r14() uint64 { return c.regs().gpr[14] }
func (c *sigctxt) r15() uint64 { return c.regs().gpr[15] }
func (c *sigctxt) r16() uint64 { return c.regs().gpr[16] }
func (c *sigctxt) r17() uint64 { return c.regs().gpr[17] }
func (c *sigctxt) r18() uint64 { return c.regs().gpr[18] }
func (c *sigctxt) r19() uint64 { return c.regs().gpr[19] }
func (c *sigctxt) r20() uint64 { return c.regs().gpr[20] }
func (c *sigctxt) r21() uint64 { return c.regs().gpr[21] }
func (c *sigctxt) r22() uint64 { return c.regs().gpr[22] }
func (c *sigctxt) r23() uint64 { return c.regs().gpr[23] }
func (c *sigctxt) r24() uint64 { return c.regs().gpr[24] }
func (c *sigctxt) r25() uint64 { return c.regs().gpr[25] }
func (c *sigctxt) r26() uint64 { return c.regs().gpr[26] }
func (c *sigctxt) r27() uint64 { return c.regs().gpr[27] }
func (c *sigctxt) r28() uint64 { return c.regs().gpr[28] }
func (c *sigctxt) r29() uint64 { return c.regs().gpr[29] }
func (c *sigctxt) r30() uint64 { return c.regs().gpr[30] }
func (c *sigctxt) r31() uint64 { return c.regs().gpr[31] }
func (c *sigctxt) sp() uint64 { return c.regs().gpr[1] }
func (c *sigctxt) pc() uint64 { return c.regs().nip }
func (c *sigctxt) trap() uint64 { return c.regs().trap }
func (c *sigctxt) ctr() uint64 { return c.regs().ctr }
func (c *sigctxt) link() uint64 { return c.regs().link }
func (c *sigctxt) xer() uint64 { return c.regs().xer }
func (c *sigctxt) ccr() uint64 { return c.regs().ccr }
func (c *sigctxt) sigcode() uint32 { return uint32(c.info.si_code) }
func (c *sigctxt) sigaddr() uint64 { return uint64(*(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize))) }
func (c *sigctxt) fault() uint64 { return c.regs().dar }
func (c *sigctxt) set_r0(x uint64) { c.regs().gpr[0] = x }
func (c *sigctxt) set_r30(x uint64) { c.regs().gpr[30] = x }
func (c *sigctxt) set_pc(x uint64) { c.regs().nip = x }
func (c *sigctxt) set_sp(x uint64) { c.regs().gpr[1] = x }
func (c *sigctxt) set_link(x uint64) { c.regs().link = x }
func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) }
func (c *sigctxt) set_sigaddr(x uint64) {
*(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize)) = uintptr(x)
}
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build linux
// +build power64 power64le
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
#include "signal_GOOS_GOARCH.h"
#include "signals_GOOS.h"
void
runtime·dumpregs(Siginfo *info, void *ctxt)
{
USED(info); USED(ctxt);
runtime·printf("r0 %X\t", SIG_R0(info, ctxt));
runtime·printf("r1 %X\n", SIG_R1(info, ctxt));
runtime·printf("r2 %X\t", SIG_R2(info, ctxt));
runtime·printf("r3 %X\n", SIG_R3(info, ctxt));
runtime·printf("r4 %X\t", SIG_R4(info, ctxt));
runtime·printf("r5 %X\n", SIG_R5(info, ctxt));
runtime·printf("r6 %X\t", SIG_R6(info, ctxt));
runtime·printf("r7 %X\n", SIG_R7(info, ctxt));
runtime·printf("r8 %X\t", SIG_R8(info, ctxt));
runtime·printf("r9 %X\n", SIG_R9(info, ctxt));
runtime·printf("r10 %X\t", SIG_R10(info, ctxt));
runtime·printf("r11 %X\n", SIG_R11(info, ctxt));
runtime·printf("r12 %X\t", SIG_R12(info, ctxt));
runtime·printf("r13 %X\n", SIG_R13(info, ctxt));
runtime·printf("r14 %X\t", SIG_R14(info, ctxt));
runtime·printf("r15 %X\n", SIG_R15(info, ctxt));
runtime·printf("r16 %X\t", SIG_R16(info, ctxt));
runtime·printf("r17 %X\n", SIG_R17(info, ctxt));
runtime·printf("r18 %X\t", SIG_R18(info, ctxt));
runtime·printf("r19 %X\n", SIG_R19(info, ctxt));
runtime·printf("r20 %X\t", SIG_R20(info, ctxt));
runtime·printf("r21 %X\n", SIG_R21(info, ctxt));
runtime·printf("r22 %X\t", SIG_R22(info, ctxt));
runtime·printf("r23 %X\n", SIG_R23(info, ctxt));
runtime·printf("r24 %X\t", SIG_R24(info, ctxt));
runtime·printf("r25 %X\n", SIG_R25(info, ctxt));
runtime·printf("r26 %X\t", SIG_R26(info, ctxt));
runtime·printf("r27 %X\n", SIG_R27(info, ctxt));
runtime·printf("r28 %X\t", SIG_R28(info, ctxt));
runtime·printf("r29 %X\n", SIG_R29(info, ctxt));
runtime·printf("r30 %X\t", SIG_R30(info, ctxt));
runtime·printf("r31 %X\n", SIG_R31(info, ctxt));
runtime·printf("pc %X\t", SIG_PC(info, ctxt));
runtime·printf("ctr %X\n", SIG_CTR(info, ctxt));
runtime·printf("link %X\t", SIG_LINK(info, ctxt));
runtime·printf("xer %X\n", SIG_XER(info, ctxt));
runtime·printf("ccr %X\t", SIG_CCR(info, ctxt));
runtime·printf("trap %X\n", SIG_TRAP(info, ctxt));
}
void
runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
{
SigTab *t;
bool crash;
if(sig == SIGPROF) {
runtime·sigprof((uint8*)SIG_PC(info, ctxt), (uint8*)SIG_SP(info, ctxt), (uint8*)SIG_LINK(info, ctxt), gp, g->m);
return;
}
t = &runtime·sigtab[sig];
if(SIG_CODE0(info, ctxt) != SI_USER && (t->flags & SigPanic)) {
// Make it look like a call to the signal func.
// Have to pass arguments out of band since
// augmenting the stack frame would break
// the unwinding code.
gp->sig = sig;
gp->sigcode0 = SIG_CODE0(info, ctxt);
gp->sigcode1 = SIG_FAULT(info, ctxt);
gp->sigpc = SIG_PC(info, ctxt);
// We arrange link, and pc to pretend the panicking
// function calls sigpanic directly.
// Always save LINK to stack so that panics in leaf
// functions are correctly handled. This smashes
// the stack frame but we're not going back there
// anyway.
SIG_SP(info, ctxt) -= sizeof(uintptr);
*(uintptr*)SIG_SP(info, ctxt) = SIG_LINK(info, ctxt);
// Don't bother saving PC if it's zero, which is
// probably a call to a nil func: the old link register
// is more useful in the stack trace.
if(gp->sigpc != 0)
SIG_LINK(info, ctxt) = gp->sigpc;
// In case we are panicking from external C code
SIG_R0(info, ctxt) = 0;
SIG_R30(info, ctxt) = (uintptr)gp;
SIG_PC(info, ctxt) = (uintptr)runtime·sigpanic;
return;
}
if(SIG_CODE0(info, ctxt) == SI_USER || (t->flags & SigNotify))
if(runtime·sigsend(sig))
return;
if(t->flags & SigKill)
runtime·exit(2);
if(!(t->flags & SigThrow))
return;
g->m->throwing = 1;
g->m->caughtsig = gp;
if(runtime·panicking) // traceback already printed
runtime·exit(2);
runtime·panicking = 1;
if(sig < 0 || sig >= NSIG)
runtime·printf("Signal %d\n", sig);
else
runtime·printf("%s\n", runtime·sigtab[sig].name);
runtime·printf("PC=%x\n", SIG_PC(info, ctxt));
if(g->m->lockedg != nil && g->m->ncgo > 0 && gp == g->m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = g->m->lockedg;
}
runtime·printf("\n");
if(runtime·gotraceback(&crash)){
runtime·goroutineheader(gp);
runtime·tracebacktrap(SIG_PC(info, ctxt), SIG_SP(info, ctxt), SIG_LINK(info, ctxt), gp);
runtime·tracebackothers(gp);
runtime·printf("\n");
runtime·dumpregs(info, ctxt);
}
if(crash)
runtime·crash();
runtime·exit(2);
}
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build linux
// +build power64 power64le
package runtime
import "unsafe"
func dumpregs(c *sigctxt) {
print("r0 ", hex(c.r0()), "\t")
print("r1 ", hex(c.r1()), "\n")
print("r2 ", hex(c.r2()), "\t")
print("r3 ", hex(c.r3()), "\n")
print("r4 ", hex(c.r4()), "\t")
print("r5 ", hex(c.r5()), "\n")
print("r6 ", hex(c.r6()), "\t")
print("r7 ", hex(c.r7()), "\n")
print("r8 ", hex(c.r8()), "\t")
print("r9 ", hex(c.r9()), "\n")
print("r10 ", hex(c.r10()), "\t")
print("r11 ", hex(c.r11()), "\n")
print("r12 ", hex(c.r12()), "\t")
print("r13 ", hex(c.r13()), "\n")
print("r14 ", hex(c.r14()), "\t")
print("r15 ", hex(c.r15()), "\n")
print("r16 ", hex(c.r16()), "\t")
print("r17 ", hex(c.r17()), "\n")
print("r18 ", hex(c.r18()), "\t")
print("r19 ", hex(c.r19()), "\n")
print("r20 ", hex(c.r20()), "\t")
print("r21 ", hex(c.r21()), "\n")
print("r22 ", hex(c.r22()), "\t")
print("r23 ", hex(c.r23()), "\n")
print("r24 ", hex(c.r24()), "\t")
print("r25 ", hex(c.r25()), "\n")
print("r26 ", hex(c.r26()), "\t")
print("r27 ", hex(c.r27()), "\n")
print("r28 ", hex(c.r28()), "\t")
print("r29 ", hex(c.r29()), "\n")
print("r30 ", hex(c.r30()), "\t")
print("r31 ", hex(c.r31()), "\n")
print("pc ", hex(c.pc()), "\t")
print("ctr ", hex(c.ctr()), "\n")
print("link ", hex(c.link()), "\t")
print("xer ", hex(c.xer()), "\n")
print("ccr ", hex(c.ccr()), "\t")
print("trap ", hex(c.trap()), "\n")
}
func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
_g_ := getg()
c := &sigctxt{info, ctxt}
if sig == _SIGPROF {
sigprof((*byte)(unsafe.Pointer(uintptr(c.pc()))), (*byte)(unsafe.Pointer(uintptr(c.sp()))), (*byte)(unsafe.Pointer(uintptr(c.link()))), gp, _g_.m)
return
}
flags := int32(_SigThrow)
if sig < uint32(len(sigtable)) {
flags = sigtable[sig].flags
}
if c.sigcode() != _SI_USER && flags&_SigPanic != 0 {
// Make it look like a call to the signal func.
// Have to pass arguments out of band since
// augmenting the stack frame would break
// the unwinding code.
gp.sig = sig
gp.sigcode0 = uintptr(c.sigcode())
gp.sigcode1 = uintptr(c.fault())
gp.sigpc = uintptr(c.pc())
// We arrange link, and pc to pretend the panicking
// function calls sigpanic directly.
// Always save LINK to stack so that panics in leaf
// functions are correctly handled. This smashes
// the stack frame but we're not going back there
// anyway.
sp := c.sp() - ptrSize
c.set_sp(sp)
*(*uint64)(unsafe.Pointer(uintptr(sp))) = c.link()
// Don't bother saving PC if it's zero, which is
// probably a call to a nil func: the old link register
// is more useful in the stack trace.
if gp.sigpc != 0 {
c.set_link(uint64(gp.sigpc))
}
// In case we are panicking from external C code
c.set_r0(0)
c.set_r30(uint64(uintptr(unsafe.Pointer(gp))))
c.set_pc(uint64(funcPC(sigpanic)))
return
}
if c.sigcode() == _SI_USER || flags&_SigNotify != 0 {
if sigsend(sig) {
return
}
}
if flags&_SigKill != 0 {
exit(2)
}
if flags&_SigThrow == 0 {
return
}
_g_.m.throwing = 1
_g_.m.caughtsig = gp
startpanic()
if sig < uint32(len(sigtable)) {
print(sigtable[sig].name, "\n")
} else {
print("Signal ", sig, "\n")
}
print("PC=", hex(c.pc()), "\n")
if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
print("signal arrived during cgo execution\n")
gp = _g_.m.lockedg
}
print("\n")
var docrash bool
if gotraceback(&docrash) > 0 {
goroutineheader(gp)
tracebacktrap(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.link()), gp)
tracebackothers(gp)
print("\n")
dumpregs(c)
}
if docrash {
crash()
}
exit(2)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment