linux.h (MD_FALLBACK_FRAME_STATE_FOR): For SIGSEGV and SIGBUS signal frames...
authorUlrich Weigand <uweigand@de.ibm.com>
Sun, 11 Jul 2004 11:49:25 +0000 (11:49 +0000)
committerUlrich Weigand <uweigand@gcc.gnu.org>
Sun, 11 Jul 2004 11:49:25 +0000 (11:49 +0000)
ChangeLog:

* config/s390/linux.h (MD_FALLBACK_FRAME_STATE_FOR): For SIGSEGV and
SIGBUS signal frames, the PSW address points *to* the faulting
instruction, not after it.

libjava/ChangeLog:

* include/s390-signal.c (SIGNAL_HANDLER): Use SIGINFO-style prototype.
(struct old_s390_kernel_sigaction): Likewise for k_sa_handler.
(MAKE_THROW_FRAME): Do not modify PSW address.
(INIT_SEGV): Install SIGINFO-style signal handler.
(INIT_FPE): Likewise.

From-SVN: r84506

gcc/ChangeLog
gcc/config/s390/linux.h
libjava/ChangeLog
libjava/include/s390-signal.h

index 147f9ec..414b18b 100644 (file)
@@ -1,5 +1,11 @@
 2004-07-11  Ulrich Weigand  <uweigand@de.ibm.com>
 
+       * config/s390/linux.h (MD_FALLBACK_FRAME_STATE_FOR): For SIGSEGV and 
+       SIGBUS signal frames, the PSW address points *to* the faulting
+       instruction, not after it.
+
+2004-07-11  Ulrich Weigand  <uweigand@de.ibm.com>
+
        * config/s390/s390.c (legitimize_tls_address): Handle constant offsets
        added to TLS symbol addresses.
 
index 9a6db9d..0f51ef7 100644 (file)
@@ -113,6 +113,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
       } __attribute__ ((__aligned__ (8))) sigregs_;                    \
                                                                        \
     sigregs_ *regs_;                                                   \
+    int *signo_ = NULL;                                                        \
                                                                        \
     /* svc $__NR_sigreturn or svc $__NR_rt_sigreturn  */               \
     if (pc_[0] != 0x0a || (pc_[1] != 119 && pc_[1] != 173))            \
@@ -133,6 +134,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
          } *uc_ = (CONTEXT)->cfa + 8 + 128;                            \
                                                                        \
        regs_ = &uc_->uc_mcontext;                                      \
+       signo_ = (CONTEXT)->cfa + sizeof(long);                         \
       }                                                                        \
                                                                        \
     /* Old-style RT frame and all non-RT frames:                       \
@@ -141,6 +143,12 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
     else                                                               \
       {                                                                        \
        regs_ = *(sigregs_ **)((CONTEXT)->cfa + 8);                     \
+                                                                       \
+       /* Recent kernels store the signal number immediately after     \
+          the sigregs; old kernels have the return trampoline at       \
+          this location.  */                                           \
+       if ((void *)(regs_ + 1) != (CONTEXT)->ra)                       \
+         signo_ = (int *)(regs_ + 1);                                  \
       }                                                                        \
                                                                        \
     new_cfa_ = regs_->gprs[15] + 16*sizeof(long) + 32;                 \
@@ -163,10 +171,31 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
       }                                                                        \
                                                                        \
     /* Load return addr from PSW into dummy register 32.  */           \
+                                                                       \
     (FS)->regs.reg[32].how = REG_SAVED_OFFSET;                         \
     (FS)->regs.reg[32].loc.offset = (long)&regs_->psw_addr - new_cfa_; \
     (FS)->retaddr_column = 32;                                         \
                                                                        \
+    /* If we got a SIGSEGV or a SIGBUS, the PSW address points *to*    \
+       the faulting instruction, not after it.  This causes the logic  \
+       in unwind-dw2.c that decrements the RA to determine the correct \
+       CFI region to get confused.  To fix that, we *increment* the RA \
+       here in that case.  Note that we cannot modify the RA in place, \
+       and the frame state wants a *pointer*, not a value; thus we put \
+       the modified RA value into the unused register 33 slot of FS and        \
+       have the register 32 save address point to that slot.           \
+                                                                       \
+       Unfortunately, for regular signals on old kernels, we don't know        \
+       the signal number.  We default to not fiddling with the RA;     \
+       that can fail in rare cases.  Upgrade your kernel.  */          \
+                                                                       \
+    if (signo_ && (*signo_ == 11 || *signo_ == 7))                     \
+      {                                                                        \
+       (FS)->regs.reg[33].loc.exp = regs_->psw_addr + 1;               \
+       (FS)->regs.reg[32].loc.offset =                                 \
+               (long)&(FS)->regs.reg[33].loc.exp - new_cfa_;           \
+      }                                                                        \
+                                                                       \
     goto SUCCESS;                                                      \
   } while (0)
 
index 15cdf79..01952d6 100644 (file)
@@ -1,3 +1,11 @@
+2004-07-11  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * include/s390-signal.c (SIGNAL_HANDLER): Use SIGINFO-style prototype.
+       (struct old_s390_kernel_sigaction): Likewise for k_sa_handler.
+       (MAKE_THROW_FRAME): Do not modify PSW address.
+       (INIT_SEGV): Install SIGINFO-style signal handler.
+       (INIT_FPE): Likewise.
+
 2004-07-10  Bryce McKinlay  <mckinlay@redhat.com>
 
        * testsuite/libjava.jacks/jacks.xfail: Updates to reflect current
index 8b9adae..743c398 100644 (file)
@@ -20,18 +20,11 @@ details.  */
 #undef HANDLE_FPE
 
 #define SIGNAL_HANDLER(_name)  \
-static void _name (int /* _signal */, struct sigcontext _sc)
+static void _name (int, siginfo_t *, void *)
 
-#define MAKE_THROW_FRAME(_exception)                                   \
-do                                                                     \
-{                                                                      \
-  /* Advance the program counter so that it is after the start of the  \
-     instruction:  the s390 exception handler expects the PSW to point         \
-     to the instruction after a call. */                               \
-  _sc.sregs->regs.psw.addr += 2;                                       \
-                                                                       \
-}                                                                      \
-while (0)
+/* We no longer need to fiddle with the PSW address in the signal handler;
+   this is now all handled correctly in MD_FALLBACK_FRAME_STATE_FOR.  */
+#define MAKE_THROW_FRAME(_exception)
 
 
 /* For an explanation why we cannot simply use sigaction to
@@ -43,7 +36,7 @@ while (0)
    visible to us in a header file so we define it here.  */
 
 struct old_s390_kernel_sigaction {
-       void (*k_sa_handler) (int, struct sigcontext);
+       void (*k_sa_handler) (int, siginfo_t *, void *);
        unsigned long k_sa_mask;
        unsigned long k_sa_flags;
        void (*sa_restorer) (void);
@@ -55,7 +48,7 @@ do                                                    \
     struct old_s390_kernel_sigaction kact;             \
     kact.k_sa_handler = catch_segv;                    \
     kact.k_sa_mask = 0;                                        \
-    kact.k_sa_flags = 0;                               \
+    kact.k_sa_flags = SA_SIGINFO;                      \
     syscall (SYS_sigaction, SIGSEGV, &kact, NULL);     \
   }                                                    \
 while (0)  
@@ -66,7 +59,7 @@ do                                                            \
     struct old_s390_kernel_sigaction kact;                     \
     kact.k_sa_handler = catch_fpe;                             \
     kact.k_sa_mask = 0;                                                \
-    kact.k_sa_flags = 0;                                       \
+    kact.k_sa_flags = SA_SIGINFO;                              \
     syscall (SYS_sigaction, SIGFPE, &kact, NULL);              \
   }                                                            \
 while (0)