Fix dwarf2 signal unwind regressions

David S. Miller davem@redhat.com
Wed May 1 23:25:00 GMT 2002


When I added dwarf2 signal unwind support for Linux/SPARC I created a
build regression for pre-glibc-2.2.x Linux systems.  This in and of
itself would not warrant a fix, but the fact that the scheme that
ia64 and sparc uses to call sigaction() to install the handlers is
guarenteed to break with glibc-2.3.x IS a valid reason to fix this.

The problem is that on ia64 and sparc we use __libc_sigaction to
install the signal handler.  These are internal glibc symbols and
they are not supposed to be referenced by applications.  In
glibc-2.3.x they will be inaccessible and thus the current situation
will result in java apps not linking anymore.

The fix requires calling the signal installation system call directly.
Doing that on ia64 turned out to be REALLY easy, since the kernel data
structures match the userlevel ones.  On Sparc it was a bit more
difficult since the structures are a little bit different, however I
was able to implement this part and fully regression test it on a
glibc-2.2.x syste.

Alexander Oliva is currently making sure this also makes the
RedHat-6.2 Sparc bootstrap regression go away (this is
PR bootstrap/6525).

I feel this is a pretty critical issue to close before we
release 3.1

Could someone regression test the ia64-linux bits for me?  Those were
the easy side of these changes, but it's possible I made a typo
somewhere.

2002-05-01  David S. Miller  <davem@redhat.com>

	PR bootstrap/6525
	* include/dwarf2-signal.h (INIT_SEGV, INIT_FPE): Don't use
	__libc_sigaction on Sparc and IA-64.

--- include/dwarf2-signal.h.~1~	Wed May  1 22:55:59 2002
+++ include/dwarf2-signal.h	Wed May  1 22:57:44 2002
@@ -122,7 +122,91 @@
 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								\
+  {								\
+    nullp = new java::lang::NullPointerException ();    	\
+    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								\
+  { 								\
+    arithexception = new java::lang::ArithmeticException 	\
+      (JvNewStringLatin1 ("/ by zero"));			\
+    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;				\
+    nullp = new java::lang::NullPointerException ();    	\
+    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								\
+  { 								\
+    arithexception = new java::lang::ArithmeticException 	\
+      (JvNewStringLatin1 ("/ by zero"));			\
+    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								\
   {								\
@@ -155,17 +239,7 @@
  * go away once all systems have pthreads libraries that are
  * compiled with full unwind info.  */
 
-#else  /* __ia64__ || __sparc__ */
-
-// 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 ();
+#else  /* __ia64__ */
 
 #define INIT_SEGV						\
 do								\
@@ -175,7 +249,7 @@
     act.sa_sigaction = _Jv_catch_segv;      			\
     sigemptyset (&act.sa_mask);					\
     act.sa_flags = SA_SIGINFO;	       				\
-    __libc_sigaction (SIGSEGV, &act, NULL);			\
+    syscall (SYS_rt_sigaction, SIGSEGV, &act, NULL, _NSIG / 8);	\
   }								\
 while (0)  
 
@@ -188,7 +262,7 @@
     act.sa_sigaction = _Jv_catch_fpe;				\
     sigemptyset (&act.sa_mask);					\
     act.sa_flags = SA_SIGINFO;		       			\
-    __libc_sigaction (SIGFPE, &act, NULL);			\
+    syscall (SYS_rt_sigaction, SIGFPE, &act, NULL, _NSIG / 8);	\
   }								\
 while (0)  
 #endif /* __ia64__ || __sparc__ */



More information about the Java-patches mailing list