]> gcc.gnu.org Git - gcc.git/blobdiff - libgo/runtime/go-signal.c
runtime: portable access to sigev_notify_thread_id
[gcc.git] / libgo / runtime / go-signal.c
index 1e800578ffaf0c51a9581202d26fad5b8e2e9b20..aa1b6305ad09d90e6938330b5fda679d7b61becf 100644 (file)
@@ -8,11 +8,9 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/time.h>
+#include <ucontext.h>
 
 #include "runtime.h"
-#include "go-assert.h"
-#include "go-panic.h"
-#include "signal_unix.h"
 
 #ifndef SA_RESTART
   #define SA_RESTART 0
@@ -24,536 +22,406 @@ extern void __splitstack_getcontext(void *context[10]);
 
 extern void __splitstack_setcontext(void *context[10]);
 
+extern void *__splitstack_find_context(void *context[10], size_t *,
+                                      void **, void **, void **);
+
 #endif
 
-#define N SigNotify
-#define K SigKill
-#define T SigThrow
-#define P SigPanic
-#define D SigDefault
+// The rest of the signal handler, written in Go.
 
-/* Signal actions.  This collects the sigtab tables for several
-   different targets from the master library.  SIGKILL, SIGCONT, and
-   SIGSTOP are not listed, as we don't want to set signal handlers for
-   them.  */
-
-SigTab runtime_sigtab[] = {
-#ifdef SIGHUP
-  { SIGHUP,    N + K },
-#endif
-#ifdef SIGINT
-  { SIGINT,    N + K },
-#endif
-#ifdef SIGQUIT
-  { SIGQUIT,   N + T },
-#endif
-#ifdef SIGILL
-  { SIGILL,    T },
-#endif
-#ifdef SIGTRAP
-  { SIGTRAP,   T },
-#endif
-#ifdef SIGABRT
-  { SIGABRT,   N + T },
-#endif
-#ifdef SIGBUS
-  { SIGBUS,    P },
-#endif
-#ifdef SIGFPE
-  { SIGFPE,    P },
-#endif
-#ifdef SIGUSR1
-  { SIGUSR1,   N },
-#endif
-#ifdef SIGSEGV
-  { SIGSEGV,   P },
-#endif
-#ifdef SIGUSR2
-  { SIGUSR2,   N },
-#endif
-#ifdef SIGPIPE
-  { SIGPIPE,   N },
-#endif
-#ifdef SIGALRM
-  { SIGALRM,   N },
-#endif
-#ifdef SIGTERM
-  { SIGTERM,   N + K },
-#endif
-#ifdef SIGSTKFLT
-  { SIGSTKFLT,         T },
-#endif
-#ifdef SIGCHLD
-  { SIGCHLD,   N },
-#endif
-#ifdef SIGTSTP
-  { SIGTSTP,   N + D },
-#endif
-#ifdef SIGTTIN
-  { SIGTTIN,   N + D },
-#endif
-#ifdef SIGTTOU
-  { SIGTTOU,   N + D },
-#endif
-#ifdef SIGURG
-  { SIGURG,    N },
-#endif
-#ifdef SIGXCPU
-  { SIGXCPU,   N },
-#endif
-#ifdef SIGXFSZ
-  { SIGXFSZ,   N },
-#endif
-#ifdef SIGVTALRM
-  { SIGVTALRM,         N },
-#endif
-#ifdef SIGPROF
-  { SIGPROF,   N },
-#endif
-#ifdef SIGWINCH
-  { SIGWINCH,  N },
-#endif
-#ifdef SIGIO
-  { SIGIO,     N },
-#endif
-#ifdef SIGPWR
-  { SIGPWR,    N },
-#endif
-#ifdef SIGSYS
-  { SIGSYS,    N },
-#endif
-#ifdef SIGEMT
-  { SIGEMT,    T },
-#endif
-#ifdef SIGINFO
-  { SIGINFO,   N },
-#endif
-#ifdef SIGTHR
-  { SIGTHR,    N },
-#endif
-  { -1,                0 }
-};
-#undef N
-#undef K
-#undef T
-#undef P
-#undef D
+extern void sigtrampgo(uint32, siginfo_t *, void *)
+       __asm__(GOSYM_PREFIX "runtime.sigtrampgo");
 
+// The Go signal handler, written in C.  This should be running on the
+// alternate signal stack.  This is responsible for setting up the
+// split stack context so that stack guard checks will work as
+// expected.
 
-static int8 badsignal[] = "runtime: signal received on thread not created by Go.\n";
+void sigtramp(int, siginfo_t *, void *)
+       __attribute__ ((no_split_stack));
 
-static void
-runtime_badsignal(int32 sig)
-{
-       // Avoid -D_FORTIFY_SOURCE problems.
-       int rv __attribute__((unused));
+void sigtramp(int, siginfo_t *, void *)
+       __asm__ (GOSYM_PREFIX "runtime.sigtramp");
 
-       if (sig == SIGPROF) {
-               return;  // Ignore SIGPROFs intended for a non-Go thread.
-       }
-       rv = runtime_write(2, badsignal, sizeof badsignal - 1);
-       runtime_exit(1);
-}
+#ifndef USING_SPLIT_STACK
 
-/* Handle a signal, for cases where we don't panic.  We can split the
-   stack here.  */
+// When not using split stacks, there are no stack checks, and there
+// is nothing special for this function to do.
 
 void
-runtime_sighandler (int sig, Siginfo *info,
-                   void *context __attribute__ ((unused)), G *gp)
+sigtramp(int sig, siginfo_t *info, void *context)
 {
-  M *m;
-  int i;
-
-  m = runtime_m ();
-  if (m == NULL)
-    {
-      runtime_badsignal (sig);
-      return;
-    }
-
-#ifdef SIGPROF
-  if (sig == SIGPROF)
-    {
-      if (gp != runtime_m ()->g0 && gp != runtime_m ()->gsignal)
-       runtime_sigprof ();
-      return;
-    }
-#endif
-
-  for (i = 0; runtime_sigtab[i].sig != -1; ++i)
-    {
-      SigTab *t;
-      bool notify, crash;
-
-      t = &runtime_sigtab[i];
+       sigtrampgo(sig, info, context);
+}
 
-      if (t->sig != sig)
-       continue;
+#else // USING_SPLIT_STACK
 
-      notify = false;
-#ifdef SA_SIGINFO
-      notify = info != NULL && info->si_code == SI_USER;
-#endif
-      if (notify || (t->flags & SigNotify) != 0)
-       {
-         if (__go_sigsend (sig))
-           return;
+void
+sigtramp(int sig, siginfo_t *info, void *context)
+{
+       G *gp;
+       void *stack_context[10];
+       void *stack;
+       void *find_stack;
+       size_t stack_size;
+       void *next_segment;
+       void *next_sp;
+       void *initial_sp;
+       uintptr sp;
+       stack_t st;
+       uintptr stsp;
+
+       gp = runtime_g();
+
+       if (gp == nil) {
+               // Let the Go code handle this case.
+               // It should only call nosplit functions in this case.
+               sigtrampgo(sig, info, context);
+               return;
        }
-      if ((t->flags & SigKill) != 0)
-       runtime_exit (2);
-      if ((t->flags & SigThrow) == 0)
-       return;
-
-      runtime_startpanic ();
-
-      {
-       const char *name = NULL;
-
-#ifdef HAVE_STRSIGNAL
-       name = strsignal (sig);
-#endif
 
-       if (name == NULL)
-         runtime_printf ("Signal %d\n", sig);
-       else
-         runtime_printf ("%s\n", name);
-      }
-
-      if (m->lockedg != NULL && m->ncgo > 0 && gp == m->g0)
-       {
-         runtime_printf("signal arrived during cgo execution\n");
-         gp = m->lockedg;
+       // If this signal is one for which we will panic, we are not
+       // on the alternate signal stack.  It's OK to call split-stack
+       // functions here.
+       if (sig == SIGBUS || sig == SIGFPE || sig == SIGSEGV) {
+               sigtrampgo(sig, info, context);
+               return;
        }
 
-      runtime_printf ("\n");
+       // We are running on the alternate signal stack.
 
-      if (runtime_gotraceback (&crash))
-       {
-         G *g;
+       __splitstack_getcontext(&stack_context[0]);
 
-         g = runtime_g ();
-         runtime_traceback (g);
-         runtime_tracebackothers (g);
+       find_stack = 
+         __splitstack_find_context((void*)(&gp->m->gsignal->stackcontext[0]),
+                                   &stack_size, &next_segment,
+                                   &next_sp, &initial_sp);
+       stack = find_stack;
+       if (stack == NULL) {
+               stack = gp->m->gsignalstack;
+               stack_size = gp->m->gsignalstacksize;
+       }
 
-         /* The gc library calls runtime_dumpregs here, and provides
-            a function that prints the registers saved in context in
-            a readable form.  */
+       // If some non-Go code called sigaltstack, adjust.
+       sp = (uintptr)(&stack_size);
+       if (sp < (uintptr)(stack) || sp >= (uintptr)(stack) + stack_size) {
+               sigaltstack(nil, &st);
+               if ((st.ss_flags & SS_DISABLE) != 0) {
+                       runtime_printf("signal %d received on thread with no signal stack\n", (int32)(sig));
+                       runtime_throw("non-Go code disabled sigaltstack");
+               }
+
+               stsp = (uintptr)(st.ss_sp);
+               if (sp < stsp || sp >= stsp + st.ss_size) {
+                       runtime_printf("signal %d received but handler not on signal stack\n", (int32)(sig));
+                       runtime_throw("non-Go code set up signal handler without SA_ONSTACK flag");
+               }
+
+               // Unfortunately __splitstack_find_context will return NULL
+               // when it is called on a context that has never been used.
+               // There isn't much we can do but assume all is well.
+               if (find_stack != NULL) {
+                       // Here the gc runtime adjusts the gsignal
+                       // stack guard to match the values returned by
+                       // sigaltstack.  Unfortunately we have no way
+                       // to do that.
+                       runtime_printf("signal %d received on unknown signal stack\n", (int32)(sig));
+                       runtime_throw("non-Go code changed signal stack");
+               }
        }
 
-      if (crash)
-       runtime_crash ();
+       // Set the split stack context so that the stack guards are
+       // checked correctly.
 
-      runtime_exit (2);
-    }
+       __splitstack_setcontext((void*)(&gp->m->gsignal->stackcontext[0]));
 
-  __builtin_unreachable ();
-}
+       sigtrampgo(sig, info, context);
 
-/* The start of handling a signal which panics.  */
+       // We are going to return back to the signal trampoline and
+       // then to whatever we were doing before we got the signal.
+       // Restore the split stack context so that stack guards are
+       // checked correctly.
 
-static void
-sig_panic_leadin (int sig)
-{
-  int i;
-  sigset_t clear;
-
-  if (runtime_m ()->mallocing)
-    {
-      runtime_printf ("caught signal while mallocing: %d\n", sig);
-      runtime_throw ("caught signal while mallocing");
-    }
-
-  /* The signal handler blocked signals; unblock them.  */
-  i = sigfillset (&clear);
-  __go_assert (i == 0);
-  i = sigprocmask (SIG_UNBLOCK, &clear, NULL);
-  __go_assert (i == 0);
+       __splitstack_setcontext(&stack_context[0]);
 }
 
-#ifdef SA_SIGINFO
+#endif // USING_SPLIT_STACK
 
-/* Signal dispatch for signals which panic, on systems which support
-   SA_SIGINFO.  This is called on the thread stack, and as such it is
-   permitted to split the stack.  */
+// C function to return the address of the sigtramp function.
+uintptr getSigtramp(void) __asm__ (GOSYM_PREFIX "runtime.getSigtramp");
 
-static void
-sig_panic_info_handler (int sig, Siginfo *info, void *context)
+uintptr
+getSigtramp()
 {
-  G *g;
-
-  g = runtime_g ();
-  if (g == NULL || info->si_code == SI_USER)
-    {
-      runtime_sighandler (sig, info, context, g);
-      return;
-    }
-
-  g->sig = sig;
-  g->sigcode0 = info->si_code;
-  g->sigcode1 = (uintptr_t) info->si_addr;
-
-  /* It would be nice to set g->sigpc here as the gc library does, but
-     I don't know how to get it portably.  */
-
-  sig_panic_leadin (sig);
-
-  switch (sig)
-    {
-#ifdef SIGBUS
-    case SIGBUS:
-      if (info->si_code == BUS_ADRERR && (uintptr_t) info->si_addr < 0x1000)
-       runtime_panicstring ("invalid memory address or "
-                            "nil pointer dereference");
-      runtime_printf ("unexpected fault address %p\n", info->si_addr);
-      runtime_throw ("fault");
-#endif
-
-#ifdef SIGSEGV
-    case SIGSEGV:
-      if ((info->si_code == 0
-          || info->si_code == SEGV_MAPERR
-          || info->si_code == SEGV_ACCERR)
-         && (uintptr_t) info->si_addr < 0x1000)
-       runtime_panicstring ("invalid memory address or "
-                            "nil pointer dereference");
-      runtime_printf ("unexpected fault address %p\n", info->si_addr);
-      runtime_throw ("fault");
-#endif
-
-#ifdef SIGFPE
-    case SIGFPE:
-      switch (info->si_code)
-       {
-       case FPE_INTDIV:
-         runtime_panicstring ("integer divide by zero");
-       case FPE_INTOVF:
-         runtime_panicstring ("integer overflow");
-       }
-      runtime_panicstring ("floating point error");
-#endif
-    }
-
-  /* All signals with SigPanic should be in cases above, and this
-     handler should only be invoked for those signals.  */
-  __builtin_unreachable ();
+  return (uintptr)(void*)sigtramp;
 }
 
-#else /* !defined (SA_SIGINFO) */
+// C code to manage the sigaction sa_sigaction field, which is
+// typically a union and so hard for mksysinfo.sh to handle.
 
-static void
-sig_panic_handler (int sig)
-{
-  G *g;
-
-  g = runtime_g ();
-  if (g == NULL)
-    {
-      runtime_sighandler (sig, NULL, NULL, g);
-      return;
-    }
-
-  g->sig = sig;
-  g->sigcode0 = 0;
-  g->sigcode1 = 0;
-
-  sig_panic_leadin (sig);
-
-  switch (sig)
-    {
-#ifdef SIGBUS
-    case SIGBUS:
-      runtime_panicstring ("invalid memory address or "
-                          "nil pointer dereference");
-#endif
+uintptr getSigactionHandler(struct sigaction*)
+       __attribute__ ((no_split_stack));
 
-#ifdef SIGSEGV
-    case SIGSEGV:
-      runtime_panicstring ("invalid memory address or "
-                          "nil pointer dereference");
-#endif
+uintptr getSigactionHandler(struct sigaction*)
+       __asm__ (GOSYM_PREFIX "runtime.getSigactionHandler");
 
-#ifdef SIGFPE
-    case SIGFPE:
-      runtime_panicstring ("integer divide by zero or floating point error");
-#endif
-    }
-
-  /* All signals with SigPanic should be in cases above, and this
-     handler should only be invoked for those signals.  */
-  __builtin_unreachable ();
-}
-
-#endif /* !defined (SA_SIGINFO) */
-
-/* A signal handler used for signals which are not going to panic.
-   This is called on the alternate signal stack so it may not split
-   the stack.  */
-
-static void
-sig_tramp_info (int, Siginfo *, void *) __attribute__ ((no_split_stack));
-
-static void
-sig_tramp_info (int sig, Siginfo *info, void *context)
+uintptr
+getSigactionHandler(struct sigaction* sa)
 {
-  G *gp;
-  M *mp;
-
-  /* We are now running on the stack registered via sigaltstack.
-     (Actually there is a small span of time between runtime_siginit
-     and sigaltstack when the program starts.)  */
-  gp = runtime_g ();
-  mp = runtime_m ();
-
-  if (gp != NULL)
-    {
-#ifdef USING_SPLIT_STACK
-      __splitstack_getcontext (&gp->stack_context[0]);
-#endif
-    }
-
-  if (gp != NULL && mp->gsignal != NULL)
-    {
-      /* We are running on the signal stack.  Set the split stack
-        context so that the stack guards are checked correctly.  */
-#ifdef USING_SPLIT_STACK
-      __splitstack_setcontext (&mp->gsignal->stack_context[0]);
-#endif
-    }
-
-  runtime_sighandler (sig, info, context, gp);
-
-  /* We are going to return back to the signal trampoline and then to
-     whatever we were doing before we got the signal.  Restore the
-     split stack context so that stack guards are checked
-     correctly.  */
-
-  if (gp != NULL)
-    {
-#ifdef USING_SPLIT_STACK
-      __splitstack_setcontext (&gp->stack_context[0]);
-#endif
-    }
+       return (uintptr)(sa->sa_sigaction);
 }
 
-#ifndef SA_SIGINFO
+void setSigactionHandler(struct sigaction*, uintptr)
+       __attribute__ ((no_split_stack));
 
-static void sig_tramp (int sig) __attribute__ ((no_split_stack));
+void setSigactionHandler(struct sigaction*, uintptr)
+       __asm__ (GOSYM_PREFIX "runtime.setSigactionHandler");
 
-static void
-sig_tramp (int sig)
+void
+setSigactionHandler(struct sigaction* sa, uintptr handler)
 {
-  sig_tramp_info (sig, NULL, NULL);
+       sa->sa_sigaction = (void*)(handler);
 }
 
-#endif
+#ifdef __linux__
 
-void
-runtime_setsig (int32 i, GoSighandler *fn, bool restart)
-{
-  struct sigaction sa;
-  int r;
-  SigTab *t;
-
-  memset (&sa, 0, sizeof sa);
-
-  r = sigfillset (&sa.sa_mask);
-  __go_assert (r == 0);
-
-  t = &runtime_sigtab[i];
-
-  if ((t->flags & SigPanic) == 0)
-    {
-#ifdef SA_SIGINFO
-      sa.sa_flags = SA_ONSTACK | SA_SIGINFO;
-      if (fn == runtime_sighandler)
-       fn = (void *) sig_tramp_info;
-      sa.sa_sigaction = (void *) fn;
-#else
-      sa.sa_flags = SA_ONSTACK;
-      if (fn == runtime_sighandler)
-       fn = (void *) sig_tramp;
-      sa.sa_handler = (void *) fn;
+// Workaround for https://sourceware.org/bugzilla/show_bug.cgi?id=27417
+#ifndef sigev_notify_thread_id
+  #define sigev_notify_thread_id _sigev_un._tid
 #endif
-    }
-  else
-    {
-#ifdef SA_SIGINFO
-      sa.sa_flags = SA_SIGINFO;
-      if (fn == runtime_sighandler)
-       fn = (void *) sig_panic_info_handler;
-      sa.sa_sigaction = (void *) fn;
-#else
-      sa.sa_flags = 0;
-      if (fn == runtime_sighandler)
-       fn = (void *) sig_panic_handler;
-      sa.sa_handler = (void *) fn;
-#endif
-    }
-
-  if (restart)
-    sa.sa_flags |= SA_RESTART;
 
-  if (sigaction (t->sig, &sa, NULL) != 0)
-    __go_assert (0);
-}
+void setSigeventTID(struct sigevent*, int32_t)
+       __asm__ (GOSYM_PREFIX "runtime.setSigeventTID");
 
-GoSighandler*
-runtime_getsig (int32 i)
+void
+setSigeventTID(struct sigevent *sev, int32_t v)
 {
-  struct sigaction sa;
-  int r;
-  SigTab *t;
-
-  memset (&sa, 0, sizeof sa);
+       sev->sigev_notify_thread_id = v;
+}
 
-  r = sigemptyset (&sa.sa_mask);
-  __go_assert (r == 0);
+#endif // defined(__linux__)
 
-  t = &runtime_sigtab[i];
+// C code to fetch values from the siginfo_t and ucontext_t pointers
+// passed to a signal handler.
 
-  if (sigaction (t->sig, NULL, &sa) != 0)
-    runtime_throw ("sigaction read failure");
+uintptr getSiginfoCode(siginfo_t *)
+       __attribute__ ((no_split_stack));
 
-  if ((void *) sa.sa_handler == sig_tramp_info)
-    return runtime_sighandler;
-#ifdef SA_SIGINFO
-  if ((void *) sa.sa_handler == sig_panic_info_handler)
-    return runtime_sighandler;
-#else
-  if ((void *) sa.sa_handler == sig_tramp
-      || (void *) sa.sa_handler == sig_panic_handler)
-    return runtime_sighandler;
-#endif
+uintptr getSiginfoCode(siginfo_t *)
+       __asm__ (GOSYM_PREFIX "runtime.getSiginfoCode");
 
-  return (void *) sa.sa_handler;
+uintptr
+getSiginfoCode(siginfo_t *info)
+{
+       return (uintptr)(info->si_code);
 }
 
-/* Used by the os package to raise SIGPIPE.  */
+struct getSiginfoRet {
+       uintptr sigaddr;
+       uintptr sigpc;
+};
 
-void os_sigpipe (void) __asm__ (GOSYM_PREFIX "os.sigpipe");
+struct getSiginfoRet getSiginfo(siginfo_t *, void *)
+       __asm__(GOSYM_PREFIX "runtime.getSiginfo");
 
-void
-os_sigpipe (void)
+struct getSiginfoRet
+getSiginfo(siginfo_t *info, void *context __attribute__((unused)))
 {
-  struct sigaction sa;
-  int i;
-
-  memset (&sa, 0, sizeof sa);
-
-  sa.sa_handler = SIG_DFL;
+       struct getSiginfoRet ret;
+       Location loc[1];
+       int32 n;
+
+       if (info == nil) {
+               ret.sigaddr = 0;
+       } else {
+               ret.sigaddr = (uintptr)(info->si_addr);
+       }
+       ret.sigpc = 0;
+
+       // There doesn't seem to be a portable way to get the PC.
+       // Use unportable code to pull it from context, and if that fails
+       // try a stack backtrace across the signal handler.
+
+#if defined(__x86_64__) && defined(__linux__)
+       ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.gregs[REG_RIP];
+#elif defined(__i386__) && defined(__linux__)
+       ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.gregs[REG_EIP];
+#elif defined(__alpha__) && defined(__linux__)
+       ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.sc_pc;
+#elif defined(__PPC64__) && defined(__linux__)
+       ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.gp_regs[32];
+#elif defined(__PPC__) && defined(__linux__)
+# if defined(__GLIBC__)
+       ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.uc_regs->gregs[32];
+# else
+       ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.gregs[32];
+# endif
+#elif defined(__PPC__) && defined(_AIX)
+       ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.jmp_context.iar;
+#elif defined(__aarch64__) && defined(__linux__)
+       ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.pc;
+#elif defined(__NetBSD__)
+       ret.sigpc = _UC_MACHINE_PC(((ucontext_t*)(context)));
+#endif
+
+       if (ret.sigpc == 0) {
+               // Skip getSiginfo/sighandler/sigtrampgo/sigtramp/handler.
+               n = runtime_callers(5, &loc[0], 1, false);
+               if (n > 0) {
+                       ret.sigpc = loc[0].pc;
+               }
+       }
 
-  i = sigemptyset (&sa.sa_mask);
-  __go_assert (i == 0);
+       return ret;
+}
 
-  if (sigaction (SIGPIPE, &sa, NULL) != 0)
-    abort ();
+// Dump registers when crashing in a signal.
+// There is no portable way to write this,
+// so we just have some CPU/OS specific implementations.
 
-  raise (SIGPIPE);
-}
+void dumpregs(siginfo_t *, void *)
+       __asm__(GOSYM_PREFIX "runtime.dumpregs");
 
 void
-runtime_setprof(bool on)
+dumpregs(siginfo_t *info __attribute__((unused)), void *context __attribute__((unused)))
 {
-       USED(on);
+#if defined(__x86_64__) && defined(__linux__)
+       {
+               mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext;
+
+               runtime_printf("rax    %X\n", m->gregs[REG_RAX]);
+               runtime_printf("rbx    %X\n", m->gregs[REG_RBX]);
+               runtime_printf("rcx    %X\n", m->gregs[REG_RCX]);
+               runtime_printf("rdx    %X\n", m->gregs[REG_RDX]);
+               runtime_printf("rdi    %X\n", m->gregs[REG_RDI]);
+               runtime_printf("rsi    %X\n", m->gregs[REG_RSI]);
+               runtime_printf("rbp    %X\n", m->gregs[REG_RBP]);
+               runtime_printf("rsp    %X\n", m->gregs[REG_RSP]);
+               runtime_printf("r8     %X\n", m->gregs[REG_R8]);
+               runtime_printf("r9     %X\n", m->gregs[REG_R9]);
+               runtime_printf("r10    %X\n", m->gregs[REG_R10]);
+               runtime_printf("r11    %X\n", m->gregs[REG_R11]);
+               runtime_printf("r12    %X\n", m->gregs[REG_R12]);
+               runtime_printf("r13    %X\n", m->gregs[REG_R13]);
+               runtime_printf("r14    %X\n", m->gregs[REG_R14]);
+               runtime_printf("r15    %X\n", m->gregs[REG_R15]);
+               runtime_printf("rip    %X\n", m->gregs[REG_RIP]);
+               runtime_printf("rflags %X\n", m->gregs[REG_EFL]);
+               runtime_printf("cs     %X\n", m->gregs[REG_CSGSFS] & 0xffff);
+               runtime_printf("fs     %X\n", (m->gregs[REG_CSGSFS] >> 16) & 0xffff);
+               runtime_printf("gs     %X\n", (m->gregs[REG_CSGSFS] >> 32) & 0xffff);
+         }
+#elif defined(__i386__) && defined(__linux__)
+       {
+               mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext;
+
+               runtime_printf("eax    %x\n", m->gregs[REG_EAX]);
+               runtime_printf("ebx    %x\n", m->gregs[REG_EBX]);
+               runtime_printf("ecx    %x\n", m->gregs[REG_ECX]);
+               runtime_printf("edx    %x\n", m->gregs[REG_EDX]);
+               runtime_printf("edi    %x\n", m->gregs[REG_EDI]);
+               runtime_printf("esi    %x\n", m->gregs[REG_ESI]);
+               runtime_printf("ebp    %x\n", m->gregs[REG_EBP]);
+               runtime_printf("esp    %x\n", m->gregs[REG_ESP]);
+               runtime_printf("eip    %x\n", m->gregs[REG_EIP]);
+               runtime_printf("eflags %x\n", m->gregs[REG_EFL]);
+               runtime_printf("cs     %x\n", m->gregs[REG_CS]);
+               runtime_printf("fs     %x\n", m->gregs[REG_FS]);
+               runtime_printf("gs     %x\n", m->gregs[REG_GS]);
+         }
+#elif defined(__alpha__) && defined(__linux__)
+       {
+               mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext;
+
+               runtime_printf("v0  %X\n", m->sc_regs[0]);
+               runtime_printf("t0  %X\n", m->sc_regs[1]);
+               runtime_printf("t1  %X\n", m->sc_regs[2]);
+               runtime_printf("t2  %X\n", m->sc_regs[3]);
+               runtime_printf("t3  %X\n", m->sc_regs[4]);
+               runtime_printf("t4  %X\n", m->sc_regs[5]);
+               runtime_printf("t5  %X\n", m->sc_regs[6]);
+               runtime_printf("t6  %X\n", m->sc_regs[7]);
+               runtime_printf("t7  %X\n", m->sc_regs[8]);
+               runtime_printf("s0  %X\n", m->sc_regs[9]);
+               runtime_printf("s1  %X\n", m->sc_regs[10]);
+               runtime_printf("s2  %X\n", m->sc_regs[11]);
+               runtime_printf("s3  %X\n", m->sc_regs[12]);
+               runtime_printf("s4  %X\n", m->sc_regs[13]);
+               runtime_printf("s5  %X\n", m->sc_regs[14]);
+               runtime_printf("fp  %X\n", m->sc_regs[15]);
+               runtime_printf("a0  %X\n", m->sc_regs[16]);
+               runtime_printf("a1  %X\n", m->sc_regs[17]);
+               runtime_printf("a2  %X\n", m->sc_regs[18]);
+               runtime_printf("a3  %X\n", m->sc_regs[19]);
+               runtime_printf("a4  %X\n", m->sc_regs[20]);
+               runtime_printf("a5  %X\n", m->sc_regs[21]);
+               runtime_printf("t8  %X\n", m->sc_regs[22]);
+               runtime_printf("t9  %X\n", m->sc_regs[23]);
+               runtime_printf("t10 %X\n", m->sc_regs[24]);
+               runtime_printf("t11 %X\n", m->sc_regs[25]);
+               runtime_printf("ra  %X\n", m->sc_regs[26]);
+               runtime_printf("t12 %X\n", m->sc_regs[27]);
+               runtime_printf("at  %X\n", m->sc_regs[28]);
+               runtime_printf("gp  %X\n", m->sc_regs[29]);
+               runtime_printf("sp  %X\n", m->sc_regs[30]);
+               runtime_printf("pc  %X\n", m->sc_pc);
+         }
+#elif defined(__PPC__) && defined(__linux__)
+         {
+               int i;
+
+# if defined(__PPC64__)
+               mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext;
+
+               for (i = 0; i < 32; i++)
+                       runtime_printf("r%d %X\n", i, m->gp_regs[i]);
+               runtime_printf("pc  %X\n", m->gp_regs[32]);
+               runtime_printf("msr %X\n", m->gp_regs[33]);
+               runtime_printf("cr  %X\n", m->gp_regs[38]);
+               runtime_printf("lr  %X\n", m->gp_regs[36]);
+               runtime_printf("ctr %X\n", m->gp_regs[35]);
+               runtime_printf("xer %X\n", m->gp_regs[37]);
+# else
+#  if defined(__GLIBC__)
+               mcontext_t *m = ((ucontext_t*)(context))->uc_mcontext.uc_regs;
+#  else
+               mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext;
+#  endif
+
+               for (i = 0; i < 32; i++)
+                       runtime_printf("r%d %x\n", i, m->gregs[i]);
+               runtime_printf("pc  %x\n", m->gregs[32]);
+               runtime_printf("msr %x\n", m->gregs[33]);
+               runtime_printf("cr  %x\n", m->gregs[38]);
+               runtime_printf("lr  %x\n", m->gregs[36]);
+               runtime_printf("ctr %x\n", m->gregs[35]);
+               runtime_printf("xer %x\n", m->gregs[37]);
+# endif
+         }
+#elif defined(__PPC__) && defined(_AIX)
+         {
+               mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext;
+               int i;
+
+               for (i = 0; i < 32; i++)
+                       runtime_printf("r%d %p\n", i, m->jmp_context.gpr[i]);
+               runtime_printf("pc  %p\n", m->jmp_context.iar);
+               runtime_printf("msr %p\n", m->jmp_context.msr);
+               runtime_printf("cr  %x\n", m->jmp_context.cr);
+               runtime_printf("lr  %p\n", m->jmp_context.lr);
+               runtime_printf("ctr %p\n", m->jmp_context.ctr);
+               runtime_printf("xer %x\n", m->jmp_context.xer);
+         }
+#elif defined(__aarch64__) && defined(__linux__)
+         {
+               mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext;
+               int i;
+
+               for (i = 0; i < 31; i++)
+                       runtime_printf("x%d    %X\n", i, m->regs[i]);
+               runtime_printf("sp     %X\n", m->sp);
+               runtime_printf("pc     %X\n", m->pc);
+               runtime_printf("pstate %X\n", m->pstate);
+         }
+#endif
 }
This page took 0.042642 seconds and 5 git commands to generate.