summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/signal_arm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime/signal_arm.c')
-rw-r--r--src/pkg/runtime/signal_arm.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/src/pkg/runtime/signal_arm.c b/src/pkg/runtime/signal_arm.c
new file mode 100644
index 000000000..adf61de6b
--- /dev/null
+++ b/src/pkg/runtime/signal_arm.c
@@ -0,0 +1,124 @@
+// Copyright 2009 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 darwin freebsd linux netbsd openbsd
+
+#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("trap %x\n", SIG_TRAP(info, ctxt));
+ runtime·printf("error %x\n", SIG_ERROR(info, ctxt));
+ runtime·printf("oldmask %x\n", SIG_OLDMASK(info, ctxt));
+ runtime·printf("r0 %x\n", SIG_R0(info, ctxt));
+ runtime·printf("r1 %x\n", SIG_R1(info, ctxt));
+ runtime·printf("r2 %x\n", SIG_R2(info, ctxt));
+ runtime·printf("r3 %x\n", SIG_R3(info, ctxt));
+ runtime·printf("r4 %x\n", SIG_R4(info, ctxt));
+ runtime·printf("r5 %x\n", SIG_R5(info, ctxt));
+ runtime·printf("r6 %x\n", SIG_R6(info, ctxt));
+ runtime·printf("r7 %x\n", SIG_R7(info, ctxt));
+ runtime·printf("r8 %x\n", SIG_R8(info, ctxt));
+ runtime·printf("r9 %x\n", SIG_R9(info, ctxt));
+ runtime·printf("r10 %x\n", SIG_R10(info, ctxt));
+ runtime·printf("fp %x\n", SIG_FP(info, ctxt));
+ runtime·printf("ip %x\n", SIG_IP(info, ctxt));
+ runtime·printf("sp %x\n", SIG_SP(info, ctxt));
+ runtime·printf("lr %x\n", SIG_LR(info, ctxt));
+ runtime·printf("pc %x\n", SIG_PC(info, ctxt));
+ runtime·printf("cpsr %x\n", SIG_CPSR(info, ctxt));
+ runtime·printf("fault %x\n", SIG_FAULT(info, ctxt));
+}
+
+void
+runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
+{
+ SigTab *t;
+ bool crash;
+
+ if(sig == SIGPROF) {
+ if(gp != m->g0 && gp != m->gsignal)
+ runtime·sigprof((uint8*)SIG_PC(info, ctxt), (uint8*)SIG_SP(info, ctxt), (uint8*)SIG_LR(info, ctxt), gp);
+ return;
+ }
+
+ t = &runtime·sigtab[sig];
+ if(SIG_CODE0(info, ctxt) != SI_USER && (t->flags & SigPanic)) {
+ if(gp == nil || gp == m->g0)
+ goto Throw;
+
+ // 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 lr, and pc to pretend the panicking
+ // function calls sigpanic directly.
+ // Always save LR 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) -= 4;
+ *(uint32*)SIG_SP(info, ctxt) = SIG_LR(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_LR(info, ctxt) = gp->sigpc;
+ // In case we are panicking from external C code
+ SIG_R10(info, ctxt) = (uintptr)gp;
+ SIG_R9(info, ctxt) = (uintptr)m;
+ 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;
+
+Throw:
+ 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(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
+ runtime·printf("signal arrived during cgo execution\n");
+ gp = m->lockedg;
+ }
+ runtime·printf("\n");
+
+ if(runtime·gotraceback(&crash)){
+ runtime·traceback((void*)SIG_PC(info, ctxt), (void*)SIG_SP(info, ctxt), (void*)SIG_LR(info, ctxt), gp);
+ runtime·tracebackothers(gp);
+ runtime·printf("\n");
+ runtime·dumpregs(info, ctxt);
+ }
+
+ if(crash)
+ runtime·crash();
+
+ runtime·exit(2);
+}