From 15c73eb7f6ae9d0be39182f797df10d573be4199 Mon Sep 17 00:00:00 2001
From: jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Mon, 27 Feb 2006 17:26:26 +0000
Subject: [PATCH] 	PR other/26208 	* unwind-dw2.c (struct
 _Unwind_Context): Add signal_frame field. 	(extract_cie_info): Handle S
 flag in augmentation string. 	(execute_cfa_program): If
 context->signal_frame, execute also 	fs->pc == context->ra instructions. 
 (uw_frame_state_for): If context->signal_frame, don't subtract one 	from
 context->ra to find FDE. 	(uw_update_context_1): Set
 context->signal_frame to 	fs->signal_frame. 	(_Unwind_GetIPInfo):
 New function. 	* unwind-dw2.h (_Unwind_FrameState): Add signal_frame field. 
 * unwind-c.c (PERSONALITY_FUNCTION): Use _Unwind_GetIPInfo instead 	of
 _Unwind_GetIP. 	* unwind-sjlj.c (_Unwind_GetIPInfo): New function. 
 * unwind-generic.h (_Unwind_GetIPInfo): New prototype. 	*
 unwind-compat.c (_Unwind_GetIPInfo): New function. 	* libgcc-std.ver
 (_Unwind_GetIPInfo): Export @@GCC_4.2.0. 	* config/ia64/unwind-ia64.c
 (_Unwind_GetIPInfo): New function. 	* config/arm/unwind-arm.h
 (_Unwind_GetIPInfo): Define. 	* config/i386/linux-unwind.h
 (x86_fallback_frame_state, 	x86_64_fallback_frame_state): Set
 fs->signal_frame. 	* config/rs6000/linux-unwind.h
 (ppc_fallback_frame_state): Likewise. 	(MD_FROB_UPDATE_CONTEXT): Define
 unconditionally. 	(frob_update_context): Likewise.  Workaround missing S
 flag in 	Linux 2.6.12 - 2.6.16 kernel vDSOs. 	*
 config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise. 	Remove
 the psw_addr + 1 hack. libjava/ 	* exception.cc (PERSONALITY_FUNCTION):
 Use _Unwind_GetIPInfo instead 	of _Unwind_GetIP. 	*
 include/i386-signal.h (MAKE_THROW_FRAME): Change into empty macro. 
 (HANDLE_DIVIDE_OVERFLOW): Don't adjust _res->eip if falling through 	to
 throw. 	* include/x86_64-signal.h (MAKE_THROW_FRAME): Change into
 empty 	macro. 	* include/powerpc-signal.h (MAKE_THROW_FRAME): Change into
 empty 	macro. libstdc++-v3/ 	* libsupc++/eh_personality.cc
 (PERSONALITY_FUNCTION): Use 	_Unwind_GetIPInfo instead of _Unwind_GetIP.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@111488 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/ChangeLog                            | 30 +++++++++++
 gcc/config/arm/unwind-arm.h              |  5 +-
 gcc/config/i386/linux-unwind.h           |  4 +-
 gcc/config/ia64/unwind-ia64.c            |  7 +++
 gcc/config/rs6000/linux-unwind.h         | 66 ++++++++++++++++--------
 gcc/config/s390/linux-unwind.h           | 28 +++-------
 gcc/libgcc-std.ver                       |  1 +
 gcc/unwind-c.c                           |  5 +-
 gcc/unwind-compat.c                      |  9 +++-
 gcc/unwind-dw2.c                         | 31 +++++++++--
 gcc/unwind-dw2.h                         |  1 +
 gcc/unwind-generic.h                     |  3 +-
 gcc/unwind-sjlj.c                        |  7 +++
 libjava/ChangeLog                        | 13 +++++
 libjava/exception.cc                     | 11 ++--
 libjava/include/i386-signal.h            | 24 +--------
 libjava/include/powerpc-signal.h         | 18 +++----
 libjava/include/x86_64-signal.h          | 13 +----
 libstdc++-v3/ChangeLog                   |  6 +++
 libstdc++-v3/libsupc++/eh_personality.cc |  5 +-
 20 files changed, 185 insertions(+), 102 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ca154bdd1fef..baabf6a5f1a6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,33 @@
+2006-02-27  Jakub Jelinek  <jakub@redhat.com>
+
+	PR other/26208
+	* unwind-dw2.c (struct _Unwind_Context): Add signal_frame field.
+	(extract_cie_info): Handle S flag in augmentation string.
+	(execute_cfa_program): If context->signal_frame, execute also
+	fs->pc == context->ra instructions.
+	(uw_frame_state_for): If context->signal_frame, don't subtract one
+	from context->ra to find FDE.
+	(uw_update_context_1): Set context->signal_frame to
+	fs->signal_frame.
+	(_Unwind_GetIPInfo): New function.
+	* unwind-dw2.h (_Unwind_FrameState): Add signal_frame field.
+	* unwind-c.c (PERSONALITY_FUNCTION): Use _Unwind_GetIPInfo instead
+	of _Unwind_GetIP.
+	* unwind-sjlj.c (_Unwind_GetIPInfo): New function.
+	* unwind-generic.h (_Unwind_GetIPInfo): New prototype.
+	* unwind-compat.c (_Unwind_GetIPInfo): New function.
+	* libgcc-std.ver (_Unwind_GetIPInfo): Export @@GCC_4.2.0.
+	* config/ia64/unwind-ia64.c (_Unwind_GetIPInfo): New function.
+	* config/arm/unwind-arm.h (_Unwind_GetIPInfo): Define.
+	* config/i386/linux-unwind.h (x86_fallback_frame_state,
+	x86_64_fallback_frame_state): Set fs->signal_frame.
+	* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise.
+	(MD_FROB_UPDATE_CONTEXT): Define unconditionally.
+	(frob_update_context): Likewise.  Workaround missing S flag in
+	Linux 2.6.12 - 2.6.16 kernel vDSOs.
+	* config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise.
+	Remove the psw_addr + 1 hack.
+
 2006-02-27  Daniel Berlin  <dberlin@dberlin.org>
 
 	* tree-ssa-structalias.c (get_constraint_for): Move code to deal
diff --git a/gcc/config/arm/unwind-arm.h b/gcc/config/arm/unwind-arm.h
index dd8d2affe39c..f7cfcab88903 100644
--- a/gcc/config/arm/unwind-arm.h
+++ b/gcc/config/arm/unwind-arm.h
@@ -1,5 +1,5 @@
 /* Header file for the ARM EABI unwinder
-   Copyright (C) 2003, 2004, 2005  Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
    Contributed by Paul Brook
 
    This file is free software; you can redistribute it and/or modify it
@@ -250,6 +250,9 @@ extern "C" {
 #define _Unwind_GetIP(context) \
   (_Unwind_GetGR (context, 15) & ~(_Unwind_Word)1)
 
+#define _Unwind_GetIP(context, ip_before_insn) \
+  (*ip_before_insn = 0, _Unwind_GetGR (context, 15) & ~(_Unwind_Word)1)
+
   static inline void
   _Unwind_SetGR (_Unwind_Context *context, int regno, _Unwind_Word val)
     {
diff --git a/gcc/config/i386/linux-unwind.h b/gcc/config/i386/linux-unwind.h
index 6ca1309c73cc..07979d319b65 100644
--- a/gcc/config/i386/linux-unwind.h
+++ b/gcc/config/i386/linux-unwind.h
@@ -1,5 +1,5 @@
 /* DWARF2 EH unwinding support for AMD x86-64 and x86.
-   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -100,6 +100,7 @@ x86_64_fallback_frame_state (struct _Unwind_Context *context,
   fs->regs.reg[16].how = REG_SAVED_OFFSET;
   fs->regs.reg[16].loc.offset = (long)&sc->rip - new_cfa;
   fs->retaddr_column = 16;
+  fs->signal_frame = 1;
   return _URC_NO_REASON;
 }
 
@@ -172,6 +173,7 @@ x86_fallback_frame_state (struct _Unwind_Context *context,
   fs->regs.reg[8].how = REG_SAVED_OFFSET;
   fs->regs.reg[8].loc.offset = (long)&sc->REG_NAME(eip) - new_cfa;
   fs->retaddr_column = 8;
+  fs->signal_frame = 1;
   return _URC_NO_REASON;
 }
 #endif /* not glibc 2.0 */
diff --git a/gcc/config/ia64/unwind-ia64.c b/gcc/config/ia64/unwind-ia64.c
index 302f0d149278..fc7b20701cd6 100644
--- a/gcc/config/ia64/unwind-ia64.c
+++ b/gcc/config/ia64/unwind-ia64.c
@@ -1704,6 +1704,13 @@ _Unwind_GetIP (struct _Unwind_Context *context)
   return context->rp;
 }
 
+inline _Unwind_Ptr
+_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
+{
+  *ip_before_insn = 0;
+  return context->rp;
+}
+
 /* Overwrite the return address for CONTEXT with VAL.  */
 
 inline void
diff --git a/gcc/config/rs6000/linux-unwind.h b/gcc/config/rs6000/linux-unwind.h
index 6e822bde0e2a..d01e6b1fb329 100644
--- a/gcc/config/rs6000/linux-unwind.h
+++ b/gcc/config/rs6000/linux-unwind.h
@@ -1,5 +1,5 @@
 /* DWARF2 EH unwinding support for PowerPC and PowerPC64 Linux.
-   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
 
    This file is part of GCC.
 
@@ -89,26 +89,6 @@ struct gcc_ucontext
 
 enum { SIGNAL_FRAMESIZE = 128 };
 
-/* If the current unwind info (FS) does not contain explicit info
-   saving R2, then we have to do a minor amount of code reading to
-   figure out if it was saved.  The big problem here is that the
-   code that does the save/restore is generated by the linker, so
-   we have no good way to determine at compile time what to do.  */
-
-#define MD_FROB_UPDATE_CONTEXT frob_update_context
-
-static void
-frob_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
-{
-  if (fs->regs.reg[2].how == REG_UNSAVED)
-    {
-      unsigned int *insn
-	= (unsigned int *) _Unwind_GetGR (context, LINK_REGISTER_REGNUM);
-      if (*insn == 0xE8410028)
-	_Unwind_SetGRPtr (context, 2, context->cfa + 40);
-    }
-}
-
 /* If PC is at a sigreturn trampoline, return a pointer to the
    regs.  Otherwise return NULL.  */
 
@@ -272,6 +252,7 @@ ppc_fallback_frame_state (struct _Unwind_Context *context,
   fs->regs.reg[ARG_POINTER_REGNUM].how = REG_SAVED_OFFSET;
   fs->regs.reg[ARG_POINTER_REGNUM].loc.offset = (long) &regs->nip - new_cfa;
   fs->retaddr_column = ARG_POINTER_REGNUM;
+  fs->signal_frame = 1;
 
   if (hwcap == 0)
     {
@@ -322,3 +303,46 @@ ppc_fallback_frame_state (struct _Unwind_Context *context,
 
   return _URC_NO_REASON;
 }
+
+#define MD_FROB_UPDATE_CONTEXT frob_update_context
+
+static void
+frob_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  const unsigned int *pc = (const unsigned int *) context->ra;
+
+  /* Fix up for 2.6.12 - 2.6.16 Linux kernels that have vDSO, but don't
+     have S flag in it.  */
+#ifdef __powerpc64__
+  /* addi r1, r1, 128; li r0, 0x0077; sc  (sigreturn) */
+  /* addi r1, r1, 128; li r0, 0x00AC; sc  (rt_sigreturn) */
+  if (pc[0] == 0x38210000 + SIGNAL_FRAMESIZE
+      && (pc[1] == 0x38000077 || pc[1] == 0x380000AC)
+      && pc[2] == 0x44000002)
+    context->signal_frame = 1;
+#else
+  /* li r0, 0x7777; sc  (sigreturn old)  */
+  /* li r0, 0x0077; sc  (sigreturn new)  */
+  /* li r0, 0x6666; sc  (rt_sigreturn old)  */
+  /* li r0, 0x00AC; sc  (rt_sigreturn new)  */
+  if ((pc[0] == 0x38007777 || pc[0] == 0x38000077
+       || pc[0] == 0x38006666 || pc[0] == 0x380000AC)
+      && pc[1] == 0x44000002)
+    context->signal_frame = 1;
+#endif
+
+#ifdef __powerpc64__
+  if (fs->regs.reg[2].how == REG_UNSAVED)
+    {
+      /* If the current unwind info (FS) does not contain explicit info
+	 saving R2, then we have to do a minor amount of code reading to
+	 figure out if it was saved.  The big problem here is that the
+	 code that does the save/restore is generated by the linker, so
+	 we have no good way to determine at compile time what to do.  */
+      unsigned int *insn
+	= (unsigned int *) _Unwind_GetGR (context, LINK_REGISTER_REGNUM);
+      if (*insn == 0xE8410028)
+	_Unwind_SetGRPtr (context, 2, context->cfa + 40);
+    }
+#endif
+}
diff --git a/gcc/config/s390/linux-unwind.h b/gcc/config/s390/linux-unwind.h
index 5f22dfc1bffe..d1e9b735edbc 100644
--- a/gcc/config/s390/linux-unwind.h
+++ b/gcc/config/s390/linux-unwind.h
@@ -1,5 +1,5 @@
 /* DWARF2 EH unwinding support for S/390 Linux.
-   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -113,27 +113,11 @@ s390_fallback_frame_state (struct _Unwind_Context *context,
   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 =
-	(unsigned char *)regs->psw_addr + 1;
-      fs->regs.reg[32].loc.offset =
-	(long)&fs->regs.reg[33].loc.exp - new_cfa;
-    }
+  /* SIGILL, SIGFPE and SIGTRAP are delivered with psw_addr
+     after the faulting instruction rather than before it.
+     Don't set FS->signal_frame in that case.  */
+  if (!signo || (*signo != 4 && *signo != 5 && *signo != 8))
+    fs->signal_frame = 1;
 
   return _URC_NO_REASON;
 }
diff --git a/gcc/libgcc-std.ver b/gcc/libgcc-std.ver
index cb2e7fe40d81..f8e9e52d0820 100644
--- a/gcc/libgcc-std.ver
+++ b/gcc/libgcc-std.ver
@@ -272,4 +272,5 @@ GCC_4.2.0 {
   __floatuntisf
   __floatuntixf
   __floatuntitf
+  _Unwind_GetIPInfo
 }
diff --git a/gcc/unwind-c.c b/gcc/unwind-c.c
index e3e2eca1804b..cf17b6174d2c 100644
--- a/gcc/unwind-c.c
+++ b/gcc/unwind-c.c
@@ -127,6 +127,7 @@ PERSONALITY_FUNCTION (int version,
   lsda_header_info info;
   const unsigned char *language_specific_data, *p, *action_record;
   _Unwind_Ptr landing_pad, ip;
+  int ip_before_insn = 0;
 
 #ifdef __ARM_EABI_UNWINDER__
   if ((state & _US_ACTION_MASK) != _US_UNWIND_FRAME_STARTING)
@@ -156,7 +157,9 @@ PERSONALITY_FUNCTION (int version,
 
   /* Parse the LSDA header.  */
   p = parse_lsda_header (context, language_specific_data, &info);
-  ip = _Unwind_GetIP (context) - 1;
+  ip = _Unwind_GetIPInfo (context, &ip_before_insn);
+  if (! ip_before_insn)
+    --ip;
   landing_pad = 0;
 
 #ifdef __USING_SJLJ_EXCEPTIONS__
diff --git a/gcc/unwind-compat.c b/gcc/unwind-compat.c
index f5316f0b6cb2..fa40ab27cba7 100644
--- a/gcc/unwind-compat.c
+++ b/gcc/unwind-compat.c
@@ -1,5 +1,5 @@
 /* Backward compatibility unwind routines.
-   Copyright (C) 2004, 2005
+   Copyright (C) 2004, 2005, 2006
    Free Software Foundation, Inc.
 
    This file is part of GCC.
@@ -136,6 +136,13 @@ _Unwind_GetIP (struct _Unwind_Context *context)
 }
 symver (_Unwind_GetIP, GCC_3.0);
 
+_Unwind_Ptr
+_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
+{
+  *ip_before_insn = 0;
+  return __libunwind_Unwind_GetIP (context);
+}
+
 extern void *__libunwind_Unwind_GetLanguageSpecificData
   (struct _Unwind_Context *);
 
diff --git a/gcc/unwind-dw2.c b/gcc/unwind-dw2.c
index 930f02f37992..8707391a86b1 100644
--- a/gcc/unwind-dw2.c
+++ b/gcc/unwind-dw2.c
@@ -1,5 +1,5 @@
 /* DWARF2 exception handling and frame unwind runtime interface routines.
-   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
 
    This file is part of GCC.
@@ -71,6 +71,7 @@ struct _Unwind_Context
   void *lsda;
   struct dwarf_eh_bases bases;
   _Unwind_Word args_size;
+  char signal_frame;
 };
 
 /* Byte size of every register managed by these routines.  */
@@ -207,6 +208,16 @@ _Unwind_GetIP (struct _Unwind_Context *context)
   return (_Unwind_Ptr) context->ra;
 }
 
+/* Retrieve the return address and flag whether that IP is before
+   or after first not yet fully executed instruction.  */
+
+inline _Unwind_Ptr
+_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
+{
+  *ip_before_insn = context->signal_frame != 0;
+  return (_Unwind_Ptr) context->ra;
+}
+
 /* Overwrite the return address for CONTEXT with VAL.  */
 
 inline void
@@ -327,6 +338,13 @@ extract_cie_info (const struct dwarf_cie *cie, struct _Unwind_Context *context,
 	  aug += 1;
 	}
 
+      /* "S" indicates a signal frame.  */
+      else if (aug[0] == 'S')
+	{
+	  fs->signal_frame = 1;
+	  aug += 1;
+	}
+
       /* Otherwise we have an unknown augmentation string.
 	 Bail unless we saw a 'z' prefix.  */
       else
@@ -761,8 +779,10 @@ execute_cfa_program (const unsigned char *insn_ptr,
      a different stack configuration that we are not interested in.  We
      assume that the call itself is unwind info-neutral; if not, or if
      there are delay instructions that adjust the stack, these must be
-     reflected at the point immediately before the call insn.  */
-  while (insn_ptr < insn_end && fs->pc < context->ra)
+     reflected at the point immediately before the call insn.
+     In signal frames, return address is after last completed instruction,
+     so we add 1 to return address to make the comparison <=.  */
+  while (insn_ptr < insn_end && fs->pc < context->ra + context->signal_frame)
     {
       unsigned char insn = *insn_ptr++;
       _Unwind_Word reg, utmp;
@@ -974,7 +994,8 @@ uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
   if (context->ra == 0)
     return _URC_END_OF_STACK;
 
-  fde = _Unwind_Find_FDE (context->ra - 1, &context->bases);
+  fde = _Unwind_Find_FDE (context->ra + context->signal_frame - 1,
+			  &context->bases);
   if (fde == NULL)
     {
 #ifdef MD_FALLBACK_FRAME_STATE_FOR
@@ -1192,6 +1213,8 @@ uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
 	break;
       }
 
+  context->signal_frame = fs->signal_frame;
+
 #ifdef MD_FROB_UPDATE_CONTEXT
   MD_FROB_UPDATE_CONTEXT (context, fs);
 #endif
diff --git a/gcc/unwind-dw2.h b/gcc/unwind-dw2.h
index e894dd913dce..4851067fdfbc 100644
--- a/gcc/unwind-dw2.h
+++ b/gcc/unwind-dw2.h
@@ -83,6 +83,7 @@ typedef struct
   unsigned char fde_encoding;
   unsigned char lsda_encoding;
   unsigned char saw_z;
+  unsigned char signal_frame;
   void *eh_ptr;
 } _Unwind_FrameState;
 
diff --git a/gcc/unwind-generic.h b/gcc/unwind-generic.h
index 9c0c7da07adf..3f4c06530ce1 100644
--- a/gcc/unwind-generic.h
+++ b/gcc/unwind-generic.h
@@ -1,5 +1,5 @@
 /* Exception handling and frame unwind runtime interface routines.
-   Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2003, 2004, 2006 Free Software Foundation, Inc.
 
    This file is part of GCC.
 
@@ -155,6 +155,7 @@ extern _Unwind_Word _Unwind_GetGR (struct _Unwind_Context *, int);
 extern void _Unwind_SetGR (struct _Unwind_Context *, int, _Unwind_Word);
 
 extern _Unwind_Ptr _Unwind_GetIP (struct _Unwind_Context *);
+extern _Unwind_Ptr _Unwind_GetIPInfo (struct _Unwind_Context *, int *);
 extern void _Unwind_SetIP (struct _Unwind_Context *, _Unwind_Ptr);
 
 /* @@@ Retrieve the CFA of the given context.  */
diff --git a/gcc/unwind-sjlj.c b/gcc/unwind-sjlj.c
index 4c06aa1f894a..72c363c7af12 100644
--- a/gcc/unwind-sjlj.c
+++ b/gcc/unwind-sjlj.c
@@ -214,6 +214,13 @@ _Unwind_GetIP (struct _Unwind_Context *context)
   return context->fc->call_site + 1;
 }
 
+_Unwind_Ptr
+_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
+{
+  *ip_before_insn = 0;
+  return context->fc->call_site + 1;
+}
+
 /* Set the return landing pad index in CONTEXT.  */
 
 void
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 6804217ce4fc..ba8b42b50c74 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,16 @@
+2006-02-27  Jakub Jelinek  <jakub@redhat.com>
+
+	PR other/26208
+	* exception.cc (PERSONALITY_FUNCTION): Use _Unwind_GetIPInfo instead
+	of _Unwind_GetIP.
+	* include/i386-signal.h (MAKE_THROW_FRAME): Change into empty macro.
+	(HANDLE_DIVIDE_OVERFLOW): Don't adjust _res->eip if falling through
+	to throw.
+	* include/x86_64-signal.h (MAKE_THROW_FRAME): Change into empty
+	macro.
+	* include/powerpc-signal.h (MAKE_THROW_FRAME): Change into empty
+	macro.
+
 2006-02-23  Scott Gilbertson  <scottg@mantatest.com>
 
 	* gnu/awt/j2d/IntegerGraphicsState.java (getClip): Clone clip
diff --git a/libjava/exception.cc b/libjava/exception.cc
index 367df3618b90..65bc4ed196bd 100644
--- a/libjava/exception.cc
+++ b/libjava/exception.cc
@@ -1,6 +1,6 @@
 // Functions for Exception Support for Java.
 
-/* Copyright (C) 1998, 1999, 2001, 2002  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2001, 2002, 2006  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -197,6 +197,7 @@ PERSONALITY_FUNCTION (int version,
   int handler_switch_value;
   bool saw_cleanup;
   bool saw_handler;
+  int ip_before_insn = 0;
 
 
   // Interface version check.
@@ -212,10 +213,10 @@ PERSONALITY_FUNCTION (int version,
       goto install_context;
     }
 
-  // FIXME: In Phase 1, record _Unwind_GetIP in xh->obj as a part of
+  // FIXME: In Phase 1, record _Unwind_GetIPInfo in xh->obj as a part of
   // the stack trace for this exception.  This will only collect Java
   // frames, but perhaps that is acceptable.
-  // FIXME2: _Unwind_GetIP is nonsensical for SJLJ, being a call-site
+  // FIXME2: _Unwind_GetIPInfo is nonsensical for SJLJ, being a call-site
   // index instead of a PC value.  We could perhaps arrange for
   // _Unwind_GetRegionStart to return context->fc->jbuf[1], which
   // is the address of the handler label for __builtin_longjmp, but
@@ -230,7 +231,9 @@ PERSONALITY_FUNCTION (int version,
 
   // Parse the LSDA header.
   p = parse_lsda_header (context, language_specific_data, &info);
-  ip = _Unwind_GetIP (context) - 1;
+  ip = _Unwind_GetIPInfo (context, &ip_before_insn);
+  if (! ip_before_insn)
+    --ip;
   landing_pad = 0;
   action_record = 0;
   handler_switch_value = 0;
diff --git a/libjava/include/i386-signal.h b/libjava/include/i386-signal.h
index a5c8ae4bf54a..a30ceeb257f8 100644
--- a/libjava/include/i386-signal.h
+++ b/libjava/include/i386-signal.h
@@ -1,7 +1,7 @@
 // i386-signal.h - Catch runtime signals and turn them into exceptions
 // on an i386 based Linux system.
 
-/* Copyright (C) 1998, 1999, 2001, 2002  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2001, 2002, 2006  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -22,19 +22,7 @@ details.  */
 #define SIGNAL_HANDLER(_name)	\
 static void _name (int _dummy __attribute__ ((__unused__)))
 
-#define MAKE_THROW_FRAME(_exception)					\
-do									\
-{									\
-  void **_p = (void **)&_dummy;						\
-  volatile struct sigcontext_struct *_regs = (struct sigcontext_struct *)++_p;	\
-									\
-  /* Advance the program counter so that it is after the start of the	\
-     instruction:  the x86 exception handler expects			\
-     the PC to point to the instruction after a call. */		\
-  _regs->eip += 2;							\
-									\
-}									\
-while (0)
+#define MAKE_THROW_FRAME(_exception)
 
 #define HANDLE_DIVIDE_OVERFLOW						\
 do									\
@@ -91,14 +79,6 @@ do									\
 	  _regs->eip = (unsigned long)_eip;				\
 	  return;							\
 	}								\
-      else								\
-	{								\
-	  /* Advance the program counter so that it is after the start	\
-	     of the instruction: this is because the x86 exception	\
-	     handler expects the PC to point to the instruction after a	\
-	     call. */							\
-	  _regs->eip += 2;						\
-	}								\
     }									\
 }									\
 while (0)
diff --git a/libjava/include/powerpc-signal.h b/libjava/include/powerpc-signal.h
index 0d5a6627fe76..66133e96d0e9 100644
--- a/libjava/include/powerpc-signal.h
+++ b/libjava/include/powerpc-signal.h
@@ -1,7 +1,7 @@
 // powerpc-signal.h - Catch runtime signals and turn them into exceptions
 // on a powerpc based Linux system.
 
-/* Copyright (C) 2003  Free Software Foundation
+/* Copyright (C) 2003, 2006  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -22,18 +22,12 @@ details.  */
 #define SIGNAL_HANDLER(_name)						\
   static void _name (int /* _signal */, struct sigcontext *_sc)
 
-/* PPC either leaves PC pointing at a faulting instruction or the
-   following instruction, depending on the signal.  SEGV always does
-   the former, so we adjust the saved PC to point to the following
-   instruction. This is what the handler in libgcc expects.  */
+/* MD_FALBACK_FRAME_STATE_FOR takes care of special casing PC
+   before the faulting instruction, so we don't need to do anything
+   here.  */
+
+#define MAKE_THROW_FRAME(_exception)
 
-#define MAKE_THROW_FRAME(_exception)					\
-do									\
-  {									\
-    _sc->regs->nip += 4;						\
-  }									\
-while (0)
-  
 /* For an explanation why we cannot simply use sigaction to
    install the handlers, see i386-signal.h.  */
 
diff --git a/libjava/include/x86_64-signal.h b/libjava/include/x86_64-signal.h
index f6df7d71732e..b4b4c2b988cd 100644
--- a/libjava/include/x86_64-signal.h
+++ b/libjava/include/x86_64-signal.h
@@ -1,7 +1,7 @@
 // x86_64-signal.h - Catch runtime signals and turn them into exceptions
 // on an x86_64 based GNU/Linux system.
 
-/* Copyright (C) 2003  Free Software Foundation
+/* Copyright (C) 2003, 2006  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -34,16 +34,7 @@ extern "C"
   };
 }
 
-#define MAKE_THROW_FRAME(_exception)					     \
-do									     \
-{									     \
-  /* Advance the program counter so that it is after the start of the	     \
-     instruction:  the x86_64 exception handler expects			     \
-     the PC to point to the instruction after a call. */		     \
-  struct ucontext *_uc = (struct ucontext *)_p;				     \
-  _uc->uc_mcontext.gregs[REG_RIP] += 2;				     	     \
-}									     \
-while (0)
+#define MAKE_THROW_FRAME(_exception)
 
 #define RESTORE(name, syscall) RESTORE2 (name, syscall)
 #define RESTORE2(name, syscall)			\
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 6774b4cf7ddc..1745127b84c2 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,9 @@
+2006-02-27  Jakub Jelinek  <jakub@redhat.com>
+
+	PR other/26208
+	* libsupc++/eh_personality.cc (PERSONALITY_FUNCTION): Use
+	_Unwind_GetIPInfo instead of _Unwind_GetIP.
+
 2006-02-27  Paolo Carlini  <pcarlini@suse.de>
 
 	PR libstdc++/14866
diff --git a/libstdc++-v3/libsupc++/eh_personality.cc b/libstdc++-v3/libsupc++/eh_personality.cc
index 5a03495cc896..6832f7ceff14 100644
--- a/libstdc++-v3/libsupc++/eh_personality.cc
+++ b/libstdc++-v3/libsupc++/eh_personality.cc
@@ -364,6 +364,7 @@ PERSONALITY_FUNCTION (int version,
   int handler_switch_value;
   void* thrown_ptr = ue_header + 1;
   bool foreign_exception;
+  int ip_before_insn = 0;
 
 #ifdef __ARM_EABI_UNWINDER__
   _Unwind_Action actions;
@@ -430,7 +431,9 @@ PERSONALITY_FUNCTION (int version,
   // Parse the LSDA header.
   p = parse_lsda_header (context, language_specific_data, &info);
   info.ttype_base = base_of_encoded_value (info.ttype_encoding, context);
-  ip = _Unwind_GetIP (context) - 1;
+  ip = _Unwind_GetIPInfo (context, &ip_before_insn);
+  if (! ip_before_insn)
+    --ip;
   landing_pad = 0;
   action_record = 0;
   handler_switch_value = 0;
-- 
GitLab