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; \
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
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
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); \
#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); \
* 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__ */