summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/signal_freebsd_arm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime/signal_freebsd_arm.c')
-rw-r--r--src/pkg/runtime/signal_freebsd_arm.c193
1 files changed, 193 insertions, 0 deletions
diff --git a/src/pkg/runtime/signal_freebsd_arm.c b/src/pkg/runtime/signal_freebsd_arm.c
new file mode 100644
index 000000000..50c3221bb
--- /dev/null
+++ b/src/pkg/runtime/signal_freebsd_arm.c
@@ -0,0 +1,193 @@
+// Copyright 2012 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.
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "signals_GOOS.h"
+#include "os_GOOS.h"
+
+#define r0 __gregs[0]
+#define r1 __gregs[1]
+#define r2 __gregs[2]
+#define r3 __gregs[3]
+#define r4 __gregs[4]
+#define r5 __gregs[5]
+#define r6 __gregs[6]
+#define r7 __gregs[7]
+#define r8 __gregs[8]
+#define r9 __gregs[9]
+#define r10 __gregs[10]
+#define r11 __gregs[11]
+#define r12 __gregs[12]
+#define r13 __gregs[13]
+#define r14 __gregs[14]
+#define r15 __gregs[15]
+#define cpsr __gregs[16]
+
+void
+runtime·dumpregs(Mcontext *r)
+{
+ runtime·printf("r0 %x\n", r->r0);
+ runtime·printf("r1 %x\n", r->r1);
+ runtime·printf("r2 %x\n", r->r2);
+ runtime·printf("r3 %x\n", r->r3);
+ runtime·printf("r4 %x\n", r->r4);
+ runtime·printf("r5 %x\n", r->r5);
+ runtime·printf("r6 %x\n", r->r6);
+ runtime·printf("r7 %x\n", r->r7);
+ runtime·printf("r8 %x\n", r->r8);
+ runtime·printf("r9 %x\n", r->r9);
+ runtime·printf("r10 %x\n", r->r10);
+ runtime·printf("fp %x\n", r->r11);
+ runtime·printf("ip %x\n", r->r12);
+ runtime·printf("sp %x\n", r->r13);
+ runtime·printf("lr %x\n", r->r14);
+ runtime·printf("pc %x\n", r->r15);
+ runtime·printf("cpsr %x\n", r->cpsr);
+}
+
+extern void runtime·sigtramp(void);
+
+typedef struct sigaction {
+ union {
+ void (*__sa_handler)(int32);
+ void (*__sa_sigaction)(int32, Siginfo*, void *);
+ } __sigaction_u; /* signal handler */
+ int32 sa_flags; /* see signal options below */
+ Sigset sa_mask; /* signal mask to apply */
+} Sigaction;
+
+void
+runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
+{
+ Ucontext *uc;
+ Mcontext *r;
+ SigTab *t;
+
+ uc = context;
+ r = &uc->uc_mcontext;
+
+ if(sig == SIGPROF) {
+ runtime·sigprof((uint8*)r->r15, (uint8*)r->r13, (uint8*)r->r14, gp);
+ return;
+ }
+
+ t = &runtime·sigtab[sig];
+ if(info->si_code != 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 = info->si_code;
+ gp->sigcode1 = (uintptr)info->si_addr;
+ gp->sigpc = r->r15;
+
+ // Only push runtime·sigpanic if r->mc_rip != 0.
+ // If r->mc_rip == 0, probably panicked because of a
+ // call to a nil func. Not pushing that onto sp will
+ // make the trace look like a call to runtime·sigpanic instead.
+ // (Otherwise the trace will end at runtime·sigpanic and we
+ // won't get to see who faulted.)
+ if(r->r15 != 0)
+ r->r14 = r->r15;
+ // In case we are panicking from external C code
+ r->r10 = (uintptr)gp;
+ r->r9 = (uintptr)m;
+ r->r15 = (uintptr)runtime·sigpanic;
+ return;
+ }
+
+ if(info->si_code == SI_USER || (t->flags & SigNotify))
+ if(runtime·sigsend(sig))
+ return;
+ if(t->flags & SigKill)
+ runtime·exit(2);
+ if(!(t->flags & SigThrow))
+ return;
+
+Throw:
+ runtime·startpanic();
+
+ 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", r->r15);
+ 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()){
+ runtime·traceback((void*)r->r15, (void*)r->r13, (void*)r->r14, gp);
+ runtime·tracebackothers(gp);
+ runtime·printf("\n");
+ runtime·dumpregs(r);
+ }
+
+// breakpoint();
+ runtime·exit(2);
+}
+
+void
+runtime·signalstack(byte *p, int32 n)
+{
+ Sigaltstack st;
+
+ st.ss_sp = (uint8*)p;
+ st.ss_size = n;
+ st.ss_flags = 0;
+ if(p == nil)
+ st.ss_flags = SS_DISABLE;
+ runtime·sigaltstack(&st, nil);
+}
+
+void
+runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
+{
+ Sigaction sa;
+
+ // If SIGHUP handler is SIG_IGN, assume running
+ // under nohup and do not set explicit handler.
+ if(i == SIGHUP) {
+ runtime·memclr((byte*)&sa, sizeof sa);
+ runtime·sigaction(i, nil, &sa);
+ if(sa.__sigaction_u.__sa_sigaction == SIG_IGN)
+ return;
+ }
+
+ runtime·memclr((byte*)&sa, sizeof sa);
+ sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
+ if(restart)
+ sa.sa_flags |= SA_RESTART;
+ sa.sa_mask.__bits[0] = ~(uint32)0;
+ sa.sa_mask.__bits[1] = ~(uint32)0;
+ sa.sa_mask.__bits[2] = ~(uint32)0;
+ sa.sa_mask.__bits[3] = ~(uint32)0;
+ if (fn == runtime·sighandler)
+ fn = (void*)runtime·sigtramp;
+ sa.__sigaction_u.__sa_sigaction = (void*)fn;
+ runtime·sigaction(i, &sa, nil);
+}
+
+void
+runtime·checkgoarm(void)
+{
+ // TODO(minux)
+}
+
+#pragma textflag 7
+int64
+runtime·cputicks(void)
+{
+ // Currently cputicks() is used in blocking profiler and to seed runtime·fastrand1().
+ // runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
+ // TODO: need more entropy to better seed fastrand1.
+ return runtime·nanotime();
+}