This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Fix libjava failure on powerpc64-linux
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Andrew Haley <aph at redhat dot com>,David Edelsohn <dje at watson dot ibm dot com>
- Date: Tue, 10 Feb 2004 22:02:26 +1030
- Subject: Fix libjava failure on powerpc64-linux
I finally found out why powerpc64 libjava tests were failing (See
http://gcc.gnu.org/ml/gcc-patches/2004-01/msg02462.html), and would have
a lot sooner if the sigaction syscall return value had been checked.
The powerpc64 linux kernel only provides a sigaction call for 32 bit
processes, something I wasn't aware of. 64 bit processes are supposed
to use rt_sigaction, so the syscall didn't manage to install a handler.
gcc/ChangeLog
* config/rs6000/linux64.h (MD_FALLBACK_FRAME_STATE_FOR): Don't
bump retaddr here.
libjava/ChangeLog
* include/powerpc-signal.h: Revert 2004-01-21 change.
(INIT_SEGV, INIT_FPE): Provide powerpc64 versions. Check return
from syscall for ppc32 versions.
I used an illegal instruction to bomb on syscall failure rather than
an abort, because abort in libjava doesn't do anything fancy, just
prints "Aborted" and exits. I like sigill because core dumps from a
sigill give you the reg set at the point of failure, instead of having
to look back up the call stack, which can be tedious when gdb doesn't
happen to work too well on your target. Maybe I should use _Jv_abort
here?
Regtested powerpc64-linux. OK mainline and 3.4?
Index: gcc/config/rs6000/linux64.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/linux64.h,v
retrieving revision 1.57
diff -u -p -r1.57 linux64.h
--- gcc/config/rs6000/linux64.h 3 Feb 2004 00:40:26 -0000 1.57
+++ gcc/config/rs6000/linux64.h 10 Feb 2004 10:22:36 -0000
@@ -643,15 +649,9 @@ enum { SIGNAL_FRAMESIZE = 64 };
(FS)->regs.reg[LINK_REGISTER_REGNUM].loc.offset \
= (long)&(sc_->regs->link) - new_cfa_; \
\
- /* The unwinder expects the IP to point to the following insn, \
- whereas the kernel returns the address of the actual \
- faulting insn. We store NIP+4 in an unused register slot to \
- get the same result for multiple evaluation of the same signal \
- frame. */ \
- sc_->regs->gpr[47] = sc_->regs->nip + 4; \
(FS)->regs.reg[ARG_POINTER_REGNUM].how = REG_SAVED_OFFSET; \
(FS)->regs.reg[ARG_POINTER_REGNUM].loc.offset \
- = (long)&(sc_->regs->gpr[47]) - new_cfa_; \
+ = (long)&(sc_->regs->nip) - new_cfa_; \
(FS)->retaddr_column = ARG_POINTER_REGNUM; \
goto SUCCESS; \
} while (0)
Index: libjava/include/powerpc-signal.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/include/powerpc-signal.h,v
retrieving revision 1.3
diff -u -p -w -r1.3 powerpc-signal.h
--- libjava/include/powerpc-signal.h 23 Jan 2004 17:32:16 -0000 1.3
+++ libjava/include/powerpc-signal.h 10 Feb 2004 10:41:45 -0000
@@ -13,8 +13,6 @@ details. */
#ifndef JAVA_SIGNAL_H
# define JAVA_SIGNAL_H 1
-# ifndef __powerpc64__
-
# include <signal.h>
# include <sys/syscall.h>
@@ -53,6 +51,7 @@ while (0)
compatibility hacks in MAKE_THROW_FRAME, as the ucontext layout
on PPC changed during the 2.5 kernel series. */
+#ifndef __powerpc64__
struct kernel_old_sigaction {
void (*k_sa_handler) (int, struct sigcontext *);
unsigned long k_sa_mask;
@@ -67,7 +66,8 @@ do \
kact.k_sa_handler = catch_segv; \
kact.k_sa_mask = 0; \
kact.k_sa_flags = 0; \
- syscall (SYS_sigaction, SIGSEGV, &kact, NULL); \
+ if (syscall (SYS_sigaction, SIGSEGV, &kact, NULL) != 0) \
+ __asm__ __volatile__ (".long 0"); \
} \
while (0)
@@ -78,17 +78,42 @@ do \
kact.k_sa_handler = catch_fpe; \
kact.k_sa_mask = 0; \
kact.k_sa_flags = 0; \
- syscall (SYS_sigaction, SIGFPE, &kact, NULL); \
+ if (syscall (SYS_sigaction, SIGFPE, &kact, NULL) != 0) \
+ __asm__ __volatile__ (".long 0"); \
} \
while (0)
-# else
+#else /* powerpc64 */
-# undef HANDLE_SEGV
-# undef HANDLE_FPE
+struct kernel_sigaction
+{
+ void (*k_sa_handler) (int, struct sigcontext *);
+ unsigned long k_sa_flags;
+ void (*k_sa_restorer)(void);
+ unsigned long k_sa_mask;
+};
+
+#define INIT_SEGV \
+do \
+ { \
+ struct kernel_sigaction kact; \
+ memset (&kact, 0, sizeof (kact)); \
+ kact.k_sa_handler = catch_segv; \
+ if (syscall (SYS_rt_sigaction, SIGSEGV, &kact, NULL, 8) != 0) \
+ __asm__ __volatile__ (".long 0"); \
+ } \
+while (0)
-# define INIT_SEGV do {} while (0)
-# define INIT_FPE do {} while (0)
+#define INIT_FPE \
+do \
+ { \
+ struct kernel_sigaction kact; \
+ memset (&kact, 0, sizeof (kact)); \
+ kact.k_sa_handler = catch_fpe; \
+ if (syscall (SYS_rt_sigaction, SIGFPE, &kact, NULL, 8) != 0) \
+ __asm__ __volatile__ (".long 0"); \
+ } \
+while (0)
# endif
#endif /* JAVA_SIGNAL_H */
--
Alan Modra
IBM OzLabs - Linux Technology Centre