OSDN Git Service

PR libgcj/24170:
[pf3gnuchains/gcc-fork.git] / libjava / include / dwarf2-signal.h
index fa55d4d..43f0cbe 100644 (file)
@@ -67,11 +67,15 @@ while (0)
 do                                                                     \
 {                                                                      \
   /* Sparc-32 leaves PC pointing at a faulting instruction             \
-   always.  So we adjust the saved PC to point to the following                \
-   instruction; this is what the handler in libgcc expects.  */                \
-  /* Note that we are lying to the unwinder here, which expects the    \
-   faulting pc, not pc+1.  But we claim the unwind information can't   \
-   be changed by such a ld or st instruction, so it doesn't matter. */ \
+   always.                                                             \
+   We advance the PC one instruction past the exception causing PC.    \
+   This is done because FDEs are found with "context->ra - 1" in the   \
+   unwinder.                                                           \
+   Also, the dwarf2 unwind machinery is going to add 8 to the          \
+   PC it uses on Sparc.  So we adjust the PC here.  We do it here      \
+   because we run once for such an exception, however the Sparc specific\
+   unwind can run multiple times for the same exception and it would   \
+   adjust the PC more than once resulting in a bogus value.  */                \
   struct sig_regs {                                                    \
     unsigned int psr, pc, npc, y, u_regs[16];                          \
   } *regp;                                                             \
@@ -83,8 +87,7 @@ do                                                                    \
   else                                                                 \
     /* mov __NR_rt_sigaction, %g1; New signal stack layout */          \
     regp = (struct sig_regs *) (_sip + 1);                             \
-  regp->pc = regp->npc;                                                        \
-  regp->npc += 4;                                                      \
+  regp->pc = ((regp->pc + 4) - 8);                                     \
 }                                                                      \
 while (0)
 #else
@@ -92,18 +95,21 @@ while (0)
 do                                                                     \
 {                                                                      \
   /* Sparc-64 leaves PC pointing at a faulting instruction             \
-   always.  So we adjust the saved PC to point to the following                \
-   instruction; this is what the handler in libgcc expects.  */                \
-  /* Note that we are lying to the unwinder here, which expects the    \
-   faulting pc, not pc+1.  But we claim the unwind information can't   \
-   be changed by such a ld or st instruction, so it doesn't matter. */ \
+   always.                                                             \
+   We advance the PC one instruction past the exception causing PC.    \
+   This is done because FDEs are found with "context->ra - 1" in the   \
+   unwinder.                                                           \
+   Also, the dwarf2 unwind machinery is going to add 8 to the          \
+   PC it uses on Sparc.  So we adjust the PC here.  We do it here      \
+   because we run once for such an exception, however the Sparc specific\
+   unwind can run multiple times for the same exception and it would   \
+   adjust the PC more than once resulting in a bogus value.  */                \
   struct pt_regs {                                                     \
     unsigned long u_regs[16];                                          \
     unsigned long tstate, tpc, tnpc;                                   \
     unsigned int y, fprs;                                              \
   } *regp = (struct pt_regs *) (_sip + 1);                             \
-  regp->tpc = regp->tnpc;                                              \
-  regp->tnpc += 4;                                                     \
+  regp->tpc = ((regp->tpc + 4) - 8);                                   \
 }                                                                      \
 while (0)
 #endif
@@ -116,11 +122,90 @@ do                                                \
 while (0)
 #endif
 
-#if !(defined(__ia64__) || defined(__sparc__))
+#if defined(__sparc__)
+#if defined(__arch64__)
+extern "C" {
+    static void __rt_sigreturn_stub(void)
+    {
+      __asm__("mov %0, %%g1\n\t"
+             "ta  0x6d\n\t"
+             : /* no outputs */
+             : "i" (__NR_rt_sigreturn));
+    }
+    struct kernel_sigaction
+    {
+      void (*k_sa_sigaction)(int,siginfo_t *,void *);
+      unsigned long k_sa_flags;
+      void (*k_sa_restorer)(void);
+      sigset_t k_sa_mask;
+    };
+}
+#define INIT_SEGV                                              \
+do                                                             \
+  {                                                            \
+    struct kernel_sigaction act;                               \
+    unsigned long stub = ((unsigned long)&__rt_sigreturn_stub); \
+    act.k_sa_sigaction = _Jv_catch_segv;                       \
+    sigemptyset (&act.k_sa_mask);                              \
+    act.k_sa_flags = SA_SIGINFO;                               \
+    act.k_sa_restorer = NULL;                                  \
+    syscall (SYS_rt_sigaction, SIGSEGV, &act, NULL,            \
+             stub - 8, _NSIG / 8);                             \
+  }                                                            \
+while (0)  
+
+#define INIT_FPE                                               \
+do                                                             \
+  {                                                            \
+    struct kernel_sigaction act;                               \
+    unsigned long stub = ((unsigned long)&__rt_sigreturn_stub); \
+    act.k_sa_sigaction = _Jv_catch_fpe;                                \
+    sigemptyset (&act.k_sa_mask);                              \
+    act.k_sa_flags = SA_SIGINFO;                               \
+    act.k_sa_restorer = NULL;                                  \
+    syscall (SYS_rt_sigaction, SIGFPE, &act, NULL,             \
+             stub - 8, _NSIG / 8);                             \
+  }                                                            \
+while (0)  
+#else /* __arch64__ */
+
+extern "C" {
+    struct kernel_sigaction
+    {
+      void (*k_sa_sigaction)(int,siginfo_t *,void *);
+      unsigned long k_sa_mask, k_sa_flags;
+      void (*k_sa_restorer)(void);
+    };
+}
+
+#define INIT_SEGV                                              \
+do                                                             \
+  {                                                            \
+    struct kernel_sigaction act;                               \
+    act.k_sa_sigaction = _Jv_catch_segv;                       \
+    act.k_sa_mask = 0;                                         \
+    act.k_sa_flags = SA_SIGINFO;                               \
+    act.k_sa_restorer = NULL;                                  \
+    syscall (SYS_sigaction, -SIGSEGV, &act, NULL);             \
+  }                                                            \
+while (0)  
+
+#define INIT_FPE                                               \
+do                                                             \
+  {                                                            \
+    struct kernel_sigaction act;                               \
+    act.k_sa_sigaction = _Jv_catch_fpe;                                \
+    act.k_sa_mask = 0;                                         \
+    act.k_sa_flags = SA_SIGINFO;                               \
+    act.k_sa_restorer = NULL;                                  \
+    syscall (SYS_sigaction, -SIGFPE, &act, NULL);              \
+  }                                                            \
+while (0)  
+#endif
+#elif !defined(__ia64__)
 #define INIT_SEGV                                              \
 do                                                             \
   {                                                            \
-    nullp = new java::lang::NullPointerException ();           \
     struct sigaction act;                                      \
     act.sa_sigaction = _Jv_catch_segv;                         \
     sigemptyset (&act.sa_mask);                                        \
@@ -132,8 +217,6 @@ while (0)
 #define INIT_FPE                                               \
 do                                                             \
   {                                                            \
-    arithexception = new java::lang::ArithmeticException       \
-      (JvNewStringLatin1 ("/ by zero"));                       \
     struct sigaction act;                                      \
     act.sa_sigaction = _Jv_catch_fpe;                          \
     sigemptyset (&act.sa_mask);                                        \
@@ -149,40 +232,31 @@ while (0)
  * go away once all systems have pthreads libraries that are
  * compiled with full unwind info.  */
 
-#else  /* __ia64__ || __sparc__ */
+#else  /* __ia64__ */
 
-// FIXME: We shouldn't be using libc_sigaction here, since it should
-// be glibc private.  But using syscall here would mean translating to
-// the kernel's struct sigaction and argument sequence, which we
-// shouldn't either.  The right solution is to call sigaction and to
-// make sure that we can unwind correctly through the pthread signal
-// wrapper.
-extern "C" int __libc_sigaction (int __sig, 
-                     __const struct sigaction *__restrict __act,
-                      struct sigaction *__restrict __oact) throw ();
+// On IA64, unwind information is mandatory, so we can unwind
+// correctly through glibc frames.  Thus we call the ordinary
+// sigaction.
 
 #define INIT_SEGV                                              \
 do                                                             \
   {                                                            \
-    nullp = new java::lang::NullPointerException ();           \
     struct sigaction act;                                      \
     act.sa_sigaction = _Jv_catch_segv;                         \
     sigemptyset (&act.sa_mask);                                        \
     act.sa_flags = SA_SIGINFO;                                 \
-    __libc_sigaction (SIGSEGV, &act, NULL);                    \
+    sigaction (SIGSEGV, &act, NULL);                           \
   }                                                            \
 while (0)  
 
 #define INIT_FPE                                               \
 do                                                             \
   {                                                            \
-    arithexception = new java::lang::ArithmeticException       \
-      (JvNewStringLatin1 ("/ by zero"));                       \
     struct sigaction act;                                      \
     act.sa_sigaction = _Jv_catch_fpe;                          \
     sigemptyset (&act.sa_mask);                                        \
     act.sa_flags = SA_SIGINFO;                                 \
-    __libc_sigaction (SIGFPE, &act, NULL);                     \
+    sigaction (SIGFPE, &act, NULL);                            \
   }                                                            \
 while (0)  
 #endif /* __ia64__ || __sparc__ */