Blame SOURCES/gcc32-pr26208.patch

6f1b0c
2006-02-27  Jakub Jelinek  <jakub@redhat.com>
6f1b0c
6f1b0c
	PR other/26208
6f1b0c
	* unwind-dw2.c (struct _Unwind_Context): Add signal_frame field.
6f1b0c
	(_Unwind_FrameState): Add signal_frame field.
6f1b0c
	(extract_cie_info): Handle S flag in augmentation string.
6f1b0c
	(execute_cfa_program): If context->signal_frame, execute also
6f1b0c
	fs->pc == context->ra instructions.
6f1b0c
	(uw_frame_state_for): If context->signal_frame, don't subtract one
6f1b0c
	from context->ra to find FDE.
6f1b0c
	(uw_update_context_1): Set context->signal_frame to
6f1b0c
	fs->signal_frame.
6f1b0c
	(_Unwind_GetIPInfo): New function.
6f1b0c
	* unwind-c.c (PERSONALITY_FUNCTION): Use _Unwind_GetIPInfo instead
6f1b0c
	of _Unwind_GetIP.
6f1b0c
	* unwind-sjlj.c (_Unwind_GetIPInfo): New function.
6f1b0c
	* unwind.h (_Unwind_GetIPInfo): New prototype.
6f1b0c
	* libgcc-std.ver (_Unwind_GetIPInfo): Export @@GCC_4.2.0.
6f1b0c
	* config/ia64/unwind-ia64.c (_Unwind_GetIPInfo): New function.
6f1b0c
	* config/i386/linux.h (MD_FALLBACK_FRAME_STATE_FOR): Set
6f1b0c
	(FS)->signal_frame.
6f1b0c
	* config/i386/linux64.h (MD_FALLBACK_FRAME_STATE_FOR): Likewise.
6f1b0c
	* config/rs6000/linux.h (MD_FALLBACK_FRAME_STATE_FOR): Likewise.
6f1b0c
	* config/rs6000/linux64.h (MD_FALLBACK_FRAME_STATE_FOR): Likewise.
6f1b0c
	* config/s390/linux.h (MD_FALLBACK_FRAME_STATE_FOR): Likewise.
6f1b0c
6f1b0c
	* libsupc++/eh_personality.cc (PERSONALITY_FUNCTION): Use
6f1b0c
	_Unwind_GetIPInfo instead of _Unwind_GetIP.
6f1b0c
6f1b0c
	* exception.cc (PERSONALITY_FUNCTION): Use _Unwind_GetIPInfo instead
6f1b0c
	of _Unwind_GetIP.
6f1b0c
	* include/i386-signal.h (MAKE_THROW_FRAME): Change into empty macro.
6f1b0c
	(HANDLE_DIVIDE_OVERFLOW): Don't adjust _res->eip if falling through
6f1b0c
	to throw.
6f1b0c
	* include/x86_64-signal.h (MAKE_THROW_FRAME): Change into empty
6f1b0c
	macro.
6f1b0c
	* include/powerpc-signal.h (MAKE_THROW_FRAME): Change into empty
6f1b0c
	macro.
6f1b0c
6f1b0c
--- libjava/exception.cc.jj	2002-04-09 16:20:32.000000000 +0200
6f1b0c
+++ libjava/exception.cc	2006-04-25 15:33:37.000000000 +0200
6f1b0c
@@ -196,6 +196,7 @@ PERSONALITY_FUNCTION (int version,
6f1b0c
   int handler_switch_value;
6f1b0c
   bool saw_cleanup;
6f1b0c
   bool saw_handler;
6f1b0c
+  int ip_before_insn = 0;
6f1b0c
 
6f1b0c
 
6f1b0c
   // Interface version check.
6f1b0c
@@ -211,10 +212,10 @@ PERSONALITY_FUNCTION (int version,
6f1b0c
       goto install_context;
6f1b0c
     }
6f1b0c
 
6f1b0c
-  // FIXME: In Phase 1, record _Unwind_GetIP in xh->obj as a part of
6f1b0c
+  // FIXME: In Phase 1, record _Unwind_GetIPInfo in xh->obj as a part of
6f1b0c
   // the stack trace for this exception.  This will only collect Java
6f1b0c
   // frames, but perhaps that is acceptable.
6f1b0c
-  // FIXME2: _Unwind_GetIP is nonsensical for SJLJ, being a call-site
6f1b0c
+  // FIXME2: _Unwind_GetIPInfo is nonsensical for SJLJ, being a call-site
6f1b0c
   // index instead of a PC value.  We could perhaps arrange for
6f1b0c
   // _Unwind_GetRegionStart to return context->fc->jbuf[1], which
6f1b0c
   // is the address of the handler label for __builtin_longjmp, but
6f1b0c
@@ -229,7 +230,9 @@ PERSONALITY_FUNCTION (int version,
6f1b0c
 
6f1b0c
   // Parse the LSDA header.
6f1b0c
   p = parse_lsda_header (context, language_specific_data, &info;;
6f1b0c
-  ip = _Unwind_GetIP (context) - 1;
6f1b0c
+  ip = _Unwind_GetIPInfo (context, &ip_before_insn);
6f1b0c
+  if (! ip_before_insn)
6f1b0c
+    --ip;
6f1b0c
   landing_pad = 0;
6f1b0c
   action_record = 0;
6f1b0c
   handler_switch_value = 0;
6f1b0c
--- libjava/include/i386-signal.h.jj	2002-03-18 23:27:01.000000000 +0100
6f1b0c
+++ libjava/include/i386-signal.h	2006-04-25 15:33:37.000000000 +0200
6f1b0c
@@ -22,19 +22,7 @@ details.  */
6f1b0c
 #define SIGNAL_HANDLER(_name)	\
6f1b0c
 static void _name (int _dummy)
6f1b0c
 
6f1b0c
-#define MAKE_THROW_FRAME(_exception)					\
6f1b0c
-do									\
6f1b0c
-{									\
6f1b0c
-  void **_p = (void **)&_dummy;						\
6f1b0c
-  struct sigcontext_struct *_regs = (struct sigcontext_struct *)++_p;	\
6f1b0c
-									\
6f1b0c
-  /* Advance the program counter so that it is after the start of the	\
6f1b0c
-     instruction:  the x86 exception handler expects			\
6f1b0c
-     the PC to point to the instruction after a call. */		\
6f1b0c
-  _regs->eip += 2;							\
6f1b0c
-									\
6f1b0c
-}									\
6f1b0c
-while (0)
6f1b0c
+#define MAKE_THROW_FRAME(_exception)
6f1b0c
 
6f1b0c
 #define HANDLE_DIVIDE_OVERFLOW						\
6f1b0c
 do									\
6f1b0c
@@ -84,14 +72,6 @@ do									\
6f1b0c
 	  _regs->eip = (unsigned long)_eip;				\
6f1b0c
 	  return;							\
6f1b0c
 	}								\
6f1b0c
-      else								\
6f1b0c
-	{								\
6f1b0c
-	  /* Advance the program counter so that it is after the start	\
6f1b0c
-	     of the instruction: this is because the x86 exception	\
6f1b0c
-	     handler expects the PC to point to the instruction after a	\
6f1b0c
-	     call. */							\
6f1b0c
-	  _regs->eip += 2;						\
6f1b0c
-	}								\
6f1b0c
     }									\
6f1b0c
 }									\
6f1b0c
 while (0)
6f1b0c
--- libjava/include/x86_64-signal.h.jj	2003-01-24 23:41:38.000000000 +0100
6f1b0c
+++ libjava/include/x86_64-signal.h	2006-04-25 15:34:23.000000000 +0200
6f1b0c
@@ -34,17 +34,7 @@ extern "C" 
6f1b0c
   };
6f1b0c
 }
6f1b0c
 
6f1b0c
-#define MAKE_THROW_FRAME(_exception)					\
6f1b0c
-do									\
6f1b0c
-{									\
6f1b0c
-  /* Advance the program counter so that it is after the start of the	\
6f1b0c
-     instruction:  the x86_64 exception handler expects			\
6f1b0c
-     the PC to point to the instruction after a call. */		\
6f1b0c
-  struct ucontext *_uc = (struct ucontext *)_p;				\
6f1b0c
-  struct sigcontext *_sc = (struct sigcontext *) &_uc->uc_mcontext;	\
6f1b0c
-  _sc->rip += 2;							\
6f1b0c
-}									\
6f1b0c
-while (0)
6f1b0c
+#define MAKE_THROW_FRAME(_exception)
6f1b0c
 
6f1b0c
 #define RESTORE(name, syscall) RESTORE2 (name, syscall)
6f1b0c
 #define RESTORE2(name, syscall)			\
6f1b0c
--- libjava/include/powerpc-signal.h.jj	2004-02-28 12:27:44.000000000 +0100
6f1b0c
+++ libjava/include/powerpc-signal.h	2006-04-25 15:33:37.000000000 +0200
6f1b0c
@@ -22,18 +22,12 @@ details.  */
6f1b0c
 #define SIGNAL_HANDLER(_name)						\
6f1b0c
   static void _name (int /* _signal */, struct sigcontext *_sc)
6f1b0c
 
6f1b0c
-/* PPC either leaves PC pointing at a faulting instruction or the
6f1b0c
-   following instruction, depending on the signal.  SEGV always does
6f1b0c
-   the former, so we adjust the saved PC to point to the following
6f1b0c
-   instruction. This is what the handler in libgcc expects.  */
6f1b0c
+/* MD_FALBACK_FRAME_STATE_FOR takes care of special casing PC
6f1b0c
+   before the faulting instruction, so we don't need to do anything
6f1b0c
+   here.  */
6f1b0c
+
6f1b0c
+#define MAKE_THROW_FRAME(_exception)
6f1b0c
 
6f1b0c
-#define MAKE_THROW_FRAME(_exception)					\
6f1b0c
-do									\
6f1b0c
-  {									\
6f1b0c
-    _sc->regs->nip += 4;						\
6f1b0c
-  }									\
6f1b0c
-while (0)
6f1b0c
-  
6f1b0c
 /* For an explanation why we cannot simply use sigaction to
6f1b0c
    install the handlers, see i386-signal.h.  */
6f1b0c
 
6f1b0c
--- libstdc++-v3/libsupc++/eh_personality.cc.jj	2003-06-11 15:08:13.000000000 +0200
6f1b0c
+++ libstdc++-v3/libsupc++/eh_personality.cc	2006-04-25 15:33:37.000000000 +0200
6f1b0c
@@ -201,6 +201,7 @@ PERSONALITY_FUNCTION (int version,
6f1b0c
   _Unwind_Ptr landing_pad, ip;
6f1b0c
   int handler_switch_value;
6f1b0c
   void *thrown_ptr = xh + 1;
6f1b0c
+  int ip_before_insn = 0;
6f1b0c
 
6f1b0c
   // Interface version check.
6f1b0c
   if (version != 1)
6f1b0c
@@ -227,7 +228,9 @@ PERSONALITY_FUNCTION (int version,
6f1b0c
   // Parse the LSDA header.
6f1b0c
   p = parse_lsda_header (context, language_specific_data, &info;;
6f1b0c
   info.ttype_base = base_of_encoded_value (info.ttype_encoding, context);
6f1b0c
-  ip = _Unwind_GetIP (context) - 1;
6f1b0c
+  ip = _Unwind_GetIPInfo (context, &ip_before_insn);
6f1b0c
+  if (! ip_before_insn)
6f1b0c
+    --ip;
6f1b0c
   landing_pad = 0;
6f1b0c
   action_record = 0;
6f1b0c
   handler_switch_value = 0;
6f1b0c
--- gcc/libgcc-std.ver.jj	2004-02-28 12:16:53.000000000 +0100
6f1b0c
+++ gcc/libgcc-std.ver	2006-04-25 15:33:37.000000000 +0200
6f1b0c
@@ -210,3 +210,8 @@ GCC_3.4 {
6f1b0c
   __paritydi2
6f1b0c
   __parityti2
6f1b0c
 }
6f1b0c
+
6f1b0c
+%inherit GCC_4.2.0 GCC_3.4
6f1b0c
+GCC_4.2.0 {
6f1b0c
+  _Unwind_GetIPInfo
6f1b0c
+}
6f1b0c
--- gcc/unwind-c.c.jj	2003-06-11 15:08:12.000000000 +0200
6f1b0c
+++ gcc/unwind-c.c	2006-04-25 15:33:37.000000000 +0200
6f1b0c
@@ -93,6 +93,7 @@ PERSONALITY_FUNCTION (int version,
6f1b0c
   lsda_header_info info;
6f1b0c
   const unsigned char *language_specific_data, *p, *action_record;
6f1b0c
   _Unwind_Ptr landing_pad, ip;
6f1b0c
+  int ip_before_insn = 0;
6f1b0c
 
6f1b0c
   if (version != 1)
6f1b0c
     return _URC_FATAL_PHASE1_ERROR;
6f1b0c
@@ -110,7 +111,9 @@ PERSONALITY_FUNCTION (int version,
6f1b0c
 
6f1b0c
   /* Parse the LSDA header.  */
6f1b0c
   p = parse_lsda_header (context, language_specific_data, &info;;
6f1b0c
-  ip = _Unwind_GetIP (context) - 1;
6f1b0c
+  ip = _Unwind_GetIPInfo (context, &ip_before_insn);
6f1b0c
+  if (! ip_before_insn)
6f1b0c
+    --ip;
6f1b0c
   landing_pad = 0;
6f1b0c
 
6f1b0c
 #ifdef __USING_SJLJ_EXCEPTIONS__
6f1b0c
--- gcc/config/rs6000/linux.h.jj	2004-02-28 12:27:45.000000000 +0100
6f1b0c
+++ gcc/config/rs6000/linux.h	2006-04-25 15:36:47.000000000 +0200
6f1b0c
@@ -171,6 +171,7 @@ enum { SIGNAL_FRAMESIZE = 64 };
6f1b0c
     (FS)->regs.reg[CR0_REGNO].loc.offset 				\
6f1b0c
       = (long)&(sc_->regs->nip) - new_cfa_;				\
6f1b0c
     (FS)->retaddr_column = CR0_REGNO;					\
6f1b0c
+    (FS)->signal_frame = 1;						\
6f1b0c
     goto SUCCESS;							\
6f1b0c
   } while (0)
6f1b0c
 
6f1b0c
--- gcc/config/rs6000/linux64.h.jj	2004-10-29 09:35:44.000000000 +0200
6f1b0c
+++ gcc/config/rs6000/linux64.h	2006-04-25 15:37:14.000000000 +0200
6f1b0c
@@ -656,6 +656,7 @@ enum { SIGNAL_FRAMESIZE = 64 };
6f1b0c
     (FS)->regs.reg[ARG_POINTER_REGNUM].loc.offset 			\
6f1b0c
       = (long)&(sc_->regs->nip) - new_cfa_;				\
6f1b0c
     (FS)->retaddr_column = ARG_POINTER_REGNUM;				\
6f1b0c
+    (FS)->signal_frame = 1;						\
6f1b0c
     goto SUCCESS;							\
6f1b0c
   } while (0)
6f1b0c
 
6f1b0c
@@ -720,6 +721,7 @@ enum { SIGNAL_FRAMESIZE = 64 };
6f1b0c
     (FS)->regs.reg[CR0_REGNO].loc.offset 				\
6f1b0c
       = (long)&(sc_->regs->nip) - new_cfa_;				\
6f1b0c
     (FS)->retaddr_column = CR0_REGNO;					\
6f1b0c
+    (FS)->signal_frame = 1;						\
6f1b0c
     goto SUCCESS;							\
6f1b0c
   } while (0)
6f1b0c
 
6f1b0c
--- gcc/config/s390/linux.h.jj	2003-10-31 11:36:50.000000000 +0100
6f1b0c
+++ gcc/config/s390/linux.h	2006-04-25 15:33:41.000000000 +0200
6f1b0c
@@ -339,6 +339,7 @@ do {                                    
6f1b0c
       } __attribute__ ((__aligned__ (8))) sigregs_;			\
6f1b0c
 									\
6f1b0c
     sigregs_ *regs_;							\
6f1b0c
+    int *signo_ = NULL;							\
6f1b0c
 									\
6f1b0c
     /* svc $__NR_sigreturn or svc $__NR_rt_sigreturn  */		\
6f1b0c
     if (pc_[0] != 0x0a || (pc_[1] != 119 && pc_[1] != 173))		\
6f1b0c
@@ -359,6 +360,7 @@ do {                                    
6f1b0c
 	  } *uc_ = (CONTEXT)->cfa + 8 + 128;				\
6f1b0c
 									\
6f1b0c
 	regs_ = &uc_->uc_mcontext;					\
6f1b0c
+	signo_ = (CONTEXT)->cfa + sizeof(long);				\
6f1b0c
       }									\
6f1b0c
 									\
6f1b0c
     /* Old-style RT frame and all non-RT frames:			\
6f1b0c
@@ -367,6 +369,11 @@ do {                                    
6f1b0c
     else								\
6f1b0c
       {									\
6f1b0c
 	regs_ = *(sigregs_ **)((CONTEXT)->cfa + 8);			\
6f1b0c
+	/* Recent kernels store the signal number immediately after	\
6f1b0c
+	   the sigregs; old kernels have the return trampoline at	\
6f1b0c
+	   this location.  */						\
6f1b0c
+	if ((void *)(regs_ + 1) != (CONTEXT)->ra)			\
6f1b0c
+	  signo_ = (int *)(regs_ + 1);					\
6f1b0c
       }									\
6f1b0c
       									\
6f1b0c
     new_cfa_ = regs_->gprs[15] + 16*sizeof(long) + 32;			\
6f1b0c
@@ -393,6 +400,12 @@ do {                                    
6f1b0c
     (FS)->regs.reg[32].loc.offset = (long)&regs_->psw_addr - new_cfa_;	\
6f1b0c
     (FS)->retaddr_column = 32;						\
6f1b0c
 									\
6f1b0c
+    /* SIGILL, SIGFPE and SIGTRAP are delivered with psw_addr		\
6f1b0c
+       after the faulting instruction rather than before it.		\
6f1b0c
+       Don't set FS->signal_frame in that case.  */			\
6f1b0c
+    if (!signo_ || (*signo_ != 4 && *signo_ != 5 && *signo_ != 8))	\
6f1b0c
+      (FS)->signal_frame = 1;						\
6f1b0c
+									\
6f1b0c
     goto SUCCESS;							\
6f1b0c
   } while (0)
6f1b0c
 
6f1b0c
--- gcc/config/i386/linux.h.jj	2003-06-11 14:56:49.000000000 +0200
6f1b0c
+++ gcc/config/i386/linux.h	2006-04-25 15:33:41.000000000 +0200
6f1b0c
@@ -280,6 +280,7 @@ Boston, MA 02111-1307, USA.  */
6f1b0c
     (FS)->regs.reg[8].how = REG_SAVED_OFFSET;				\
6f1b0c
     (FS)->regs.reg[8].loc.offset = (long)&sc_->eip - new_cfa_;		\
6f1b0c
     (FS)->retaddr_column = 8;						\
6f1b0c
+    (FS)->signal_frame = 1;						\
6f1b0c
     goto SUCCESS;							\
6f1b0c
   } while (0)
6f1b0c
 #endif /* ifndef inhibit_libc  */
6f1b0c
--- gcc/config/i386/linux64.h.jj	2003-06-11 14:56:49.000000000 +0200
6f1b0c
+++ gcc/config/i386/linux64.h	2006-04-25 15:33:41.000000000 +0200
6f1b0c
@@ -135,6 +135,7 @@ Boston, MA 02111-1307, USA.  */
6f1b0c
     (FS)->regs.reg[16].how = REG_SAVED_OFFSET;				\
6f1b0c
     (FS)->regs.reg[16].loc.offset = (long)&sc_->rip - new_cfa_;		\
6f1b0c
     (FS)->retaddr_column = 16;						\
6f1b0c
+    (FS)->signal_frame = 1;						\
6f1b0c
     goto SUCCESS;							\
6f1b0c
   } while (0)
6f1b0c
 #else /* ifdef __x86_64__  */
6f1b0c
@@ -189,6 +190,7 @@ Boston, MA 02111-1307, USA.  */
6f1b0c
     (FS)->regs.reg[8].how = REG_SAVED_OFFSET;				\
6f1b0c
     (FS)->regs.reg[8].loc.offset = (long)&sc_->eip - new_cfa_;		\
6f1b0c
     (FS)->retaddr_column = 8;						\
6f1b0c
+    (FS)->signal_frame = 1;						\
6f1b0c
     goto SUCCESS;							\
6f1b0c
   } while (0)
6f1b0c
 #endif /* ifdef __x86_64__  */
6f1b0c
--- gcc/config/ia64/unwind-ia64.c.jj	2004-07-01 12:49:33.000000000 +0200
6f1b0c
+++ gcc/config/ia64/unwind-ia64.c	2006-04-25 15:33:41.000000000 +0200
6f1b0c
@@ -1700,6 +1700,13 @@ _Unwind_GetIP (struct _Unwind_Context *c
6f1b0c
   return context->rp;
6f1b0c
 }
6f1b0c
 
6f1b0c
+inline _Unwind_Ptr
6f1b0c
+_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
6f1b0c
+{
6f1b0c
+  *ip_before_insn = 0;
6f1b0c
+  return context->rp;
6f1b0c
+}
6f1b0c
+
6f1b0c
 /* Overwrite the return address for CONTEXT with VAL.  */
6f1b0c
 
6f1b0c
 inline void
6f1b0c
--- gcc/unwind-sjlj.c.jj	2003-06-11 15:12:42.000000000 +0200
6f1b0c
+++ gcc/unwind-sjlj.c	2006-04-25 15:33:44.000000000 +0200
6f1b0c
@@ -197,6 +197,13 @@ _Unwind_GetIP (struct _Unwind_Context *c
6f1b0c
   return context->fc->call_site + 1;
6f1b0c
 }
6f1b0c
 
6f1b0c
+_Unwind_Ptr
6f1b0c
+_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
6f1b0c
+{
6f1b0c
+  *ip_before_insn = 0;
6f1b0c
+  return context->fc->call_site + 1;
6f1b0c
+}
6f1b0c
+
6f1b0c
 /* Set the return landing pad index in CONTEXT.  */
6f1b0c
 
6f1b0c
 void
6f1b0c
--- gcc/unwind.h.jj	2003-09-04 11:16:10.000000000 +0200
6f1b0c
+++ gcc/unwind.h	2006-04-25 15:33:44.000000000 +0200
6f1b0c
@@ -136,6 +136,7 @@ extern _Unwind_Word _Unwind_GetGR (struc
6f1b0c
 extern void _Unwind_SetGR (struct _Unwind_Context *, int, _Unwind_Word);
6f1b0c
 
6f1b0c
 extern _Unwind_Ptr _Unwind_GetIP (struct _Unwind_Context *);
6f1b0c
+extern _Unwind_Ptr _Unwind_GetIPInfo (struct _Unwind_Context *, int *);
6f1b0c
 extern void _Unwind_SetIP (struct _Unwind_Context *, _Unwind_Ptr);
6f1b0c
 
6f1b0c
 /* @@@ Retrieve the CFA of the given context.  */
6f1b0c
--- gcc/unwind-dw2.c.jj	2003-07-16 13:38:32.000000000 +0200
6f1b0c
+++ gcc/unwind-dw2.c	2006-04-25 15:33:44.000000000 +0200
6f1b0c
@@ -62,6 +62,7 @@ struct _Unwind_Context
6f1b0c
   void *lsda;
6f1b0c
   struct dwarf_eh_bases bases;
6f1b0c
   _Unwind_Word args_size;
6f1b0c
+  char signal_frame;
6f1b0c
 };
6f1b0c
 
6f1b0c
 /* Byte size of every register managed by these routines.  */
6f1b0c
@@ -117,6 +118,7 @@ typedef struct
6f1b0c
   unsigned char fde_encoding;
6f1b0c
   unsigned char lsda_encoding;
6f1b0c
   unsigned char saw_z;
6f1b0c
+  unsigned char signal_frame;
6f1b0c
   void *eh_ptr;
6f1b0c
 } _Unwind_FrameState;
6f1b0c
 
6f1b0c
@@ -193,6 +195,16 @@ _Unwind_GetIP (struct _Unwind_Context *c
6f1b0c
   return (_Unwind_Ptr) context->ra;
6f1b0c
 }
6f1b0c
 
6f1b0c
+/* Retrieve the return address and flag whether that IP is before
6f1b0c
+   or after first not yet fully executed instruction.  */
6f1b0c
+
6f1b0c
+inline _Unwind_Ptr
6f1b0c
+_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
6f1b0c
+{
6f1b0c
+  *ip_before_insn = context->signal_frame != 0;
6f1b0c
+  return (_Unwind_Ptr) context->ra;
6f1b0c
+}
6f1b0c
+
6f1b0c
 /* Overwrite the return address for CONTEXT with VAL.  */
6f1b0c
 
6f1b0c
 inline void
6f1b0c
@@ -304,6 +316,13 @@ extract_cie_info (struct dwarf_cie *cie,
6f1b0c
 	  aug += 1;
6f1b0c
 	}
6f1b0c
 
6f1b0c
+      /* "S" indicates a signal frame.  */
6f1b0c
+      else if (aug[0] == 'S')
6f1b0c
+	{
6f1b0c
+	  fs->signal_frame = 1;
6f1b0c
+	  aug += 1;
6f1b0c
+	}
6f1b0c
+
6f1b0c
       /* Otherwise we have an unknown augmentation string.
6f1b0c
 	 Bail unless we saw a 'z' prefix.  */
6f1b0c
       else
6f1b0c
@@ -736,8 +755,10 @@ execute_cfa_program (const unsigned char
6f1b0c
      a different stack configuration that we are not interested in.  We
6f1b0c
      assume that the call itself is unwind info-neutral; if not, or if
6f1b0c
      there are delay instructions that adjust the stack, these must be
6f1b0c
-     reflected at the point immediately before the call insn.  */
6f1b0c
-  while (insn_ptr < insn_end && fs->pc < context->ra)
6f1b0c
+     reflected at the point immediately before the call insn.
6f1b0c
+     In signal frames, return address is after last completed instruction,
6f1b0c
+     so we add 1 to return address to make the comparison <=.  */
6f1b0c
+  while (insn_ptr < insn_end && fs->pc < context->ra + context->signal_frame)
6f1b0c
     {
6f1b0c
       unsigned char insn = *insn_ptr++;
6f1b0c
       _Unwind_Word reg, utmp;
6f1b0c
@@ -927,7 +948,8 @@ uw_frame_state_for (struct _Unwind_Conte
6f1b0c
   context->args_size = 0;
6f1b0c
   context->lsda = 0;
6f1b0c
 
6f1b0c
-  fde = _Unwind_Find_FDE (context->ra - 1, &context->bases);
6f1b0c
+  fde = _Unwind_Find_FDE (context->ra + context->signal_frame - 1,
6f1b0c
+			  &context->bases);
6f1b0c
   if (fde == NULL)
6f1b0c
     {
6f1b0c
       /* Couldn't find frame unwind info for this function.  Try a
6f1b0c
@@ -1265,6 +1287,8 @@ uw_update_context_1 (struct _Unwind_Cont
6f1b0c
 	break;
6f1b0c
       }
6f1b0c
 
6f1b0c
+  context->signal_frame = fs->signal_frame;
6f1b0c
+
6f1b0c
   MD_FROB_UPDATE_CONTEXT (context, fs);
6f1b0c
 }
6f1b0c