SOURCES (GCC_4_1): gcc-unwind-through-signal-frames.patch (NEW) - ...

pluto pluto at pld-linux.org
Wed Aug 30 01:25:36 CEST 2006


Author: pluto                        Date: Tue Aug 29 23:25:36 2006 GMT
Module: SOURCES                       Tag: GCC_4_1
---- Log message:
- backport from 4.2.

---- Files affected:
SOURCES:
   gcc-unwind-through-signal-frames.patch (NONE -> 1.1.2.1)  (NEW)

---- Diffs:

================================================================
Index: SOURCES/gcc-unwind-through-signal-frames.patch
diff -u /dev/null SOURCES/gcc-unwind-through-signal-frames.patch:1.1.2.1
--- /dev/null	Wed Aug 30 01:25:36 2006
+++ SOURCES/gcc-unwind-through-signal-frames.patch	Wed Aug 30 01:25:31 2006
@@ -0,0 +1,461 @@
+--- gcc/unwind-compat.c	(revision 111580)
++++ gcc/unwind-compat.c	(revision 111581)
+@@ -136,6 +136,13 @@
+ }
+ 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 *);
+ 
+--- gcc/unwind-dw2.c	(revision 111580)
++++ gcc/unwind-dw2.c	(revision 111581)
+@@ -71,6 +71,7 @@
+   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 @@
+   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 @@
+ 	  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 @@
+      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 @@
+   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 @@
+ 	break;
+       }
+ 
++  context->signal_frame = fs->signal_frame;
++
+ #ifdef MD_FROB_UPDATE_CONTEXT
+   MD_FROB_UPDATE_CONTEXT (context, fs);
+ #endif
+--- gcc/unwind-dw2.h	(revision 111580)
++++ gcc/unwind-dw2.h	(revision 111581)
+@@ -83,6 +83,7 @@
+   unsigned char fde_encoding;
+   unsigned char lsda_encoding;
+   unsigned char saw_z;
++  unsigned char signal_frame;
+   void *eh_ptr;
+ } _Unwind_FrameState;
+ 
+--- gcc/unwind-c.c	(revision 111580)
++++ gcc/unwind-c.c	(revision 111581)
+@@ -127,6 +127,7 @@
+   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 @@
+ 
+   /* 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__
+--- gcc/unwind-sjlj.c	(revision 111580)
++++ gcc/unwind-sjlj.c	(revision 111581)
+@@ -214,6 +214,13 @@
+   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
+--- gcc/unwind-generic.h	(revision 111580)
++++ gcc/unwind-generic.h	(revision 111581)
+@@ -155,6 +155,7 @@
+ 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.  */
+--- gcc/config/s390/linux-unwind.h	(revision 111580)
++++ gcc/config/s390/linux-unwind.h	(revision 111581)
+@@ -113,27 +113,11 @@
+   fs->regs.reg[32].how = REG_SAVED_OFFSET;
+   fs->regs.reg[32].loc.offset = (long)&regs->psw_addr - new_cfa;
+   fs->retaddr_column = 32;
++  /* 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;
+ 
+-  /* 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;
+-    }
+-
+   return _URC_NO_REASON;
+ }
+--- gcc/config/ia64/unwind-ia64.c	(revision 111580)
++++ gcc/config/ia64/unwind-ia64.c	(revision 111581)
+@@ -1704,6 +1704,13 @@
+   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
+--- gcc/config/i386/linux-unwind.h	(revision 111580)
++++ gcc/config/i386/linux-unwind.h	(revision 111581)
+@@ -100,6 +100,7 @@
+   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 @@
+   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 */
+--- gcc/config/rs6000/linux-unwind.h	(revision 111580)
++++ gcc/config/rs6000/linux-unwind.h	(revision 111581)
+@@ -89,26 +89,6 @@
+ 
+ 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 @@
+   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 @@
+ 
+   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
++}
+--- gcc/config/arm/unwind-arm.h	(revision 111580)
++++ gcc/config/arm/unwind-arm.h	(revision 111581)
+@@ -250,6 +250,9 @@
+ #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)
+     {
+--- gcc/libgcc-std.ver	(revision 111580)
++++ gcc/libgcc-std.ver	(revision 111581)
+@@ -256,3 +256,7 @@
+ %inherit GCC_4.1.0 GCC_4.0.0
+ GCC_4.1.0 {
+ }
++
++GCC_4.2.0 {
++  _Unwind_GetIPInfo
++}
+--- libstdc++-v3/libsupc++/eh_personality.cc	(revision 111580)
++++ libstdc++-v3/libsupc++/eh_personality.cc	(revision 111581)
+@@ -365,6 +365,7 @@
+   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;
+@@ -431,7 +432,9 @@
+   // 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;
+--- libjava/exception.cc	(revision 111580)
++++ libjava/exception.cc	(revision 111581)
+@@ -197,6 +197,7 @@
+   int handler_switch_value;
+   bool saw_cleanup;
+   bool saw_handler;
++  int ip_before_insn = 0;
+ 
+ 
+   // Interface version check.
+@@ -212,10 +213,10 @@
+       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 @@
+ 
+   // 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;
+--- libjava/include/i386-signal.h	(revision 111580)
++++ libjava/include/i386-signal.h	(revision 111581)
+@@ -22,19 +22,7 @@
+ #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 @@
+ 	  _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)
+--- libjava/include/powerpc-signal.h	(revision 111580)
++++ libjava/include/powerpc-signal.h	(revision 111581)
+@@ -22,18 +22,12 @@
+ #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)					\
+-do									\
+-  {									\
+-    _sc->regs->nip += 4;						\
+-  }									\
+-while (0)
+-  
++#define MAKE_THROW_FRAME(_exception)
++
+ /* For an explanation why we cannot simply use sigaction to
+    install the handlers, see i386-signal.h.  */
+ 
+--- libjava/include/x86_64-signal.h	(revision 111580)
++++ libjava/include/x86_64-signal.h	(revision 111581)
+@@ -34,17 +34,7 @@
+   };
+ }
+ 
+-#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;				     \
+-  volatile struct sigcontext *_sc = (struct sigcontext *) &_uc->uc_mcontext; \
+-  _sc->rip += 2;							     \
+-}									     \
+-while (0)
++#define MAKE_THROW_FRAME(_exception)
+ 
+ #define RESTORE(name, syscall) RESTORE2 (name, syscall)
+ #define RESTORE2(name, syscall)			\
================================================================


More information about the pld-cvs-commit mailing list