This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[csl-arm-branch] forced unwinding


I've installed this patch on the csl-arm-branch to implement arm forced unwinding. These are just arm specific bits to the unwinder.

Approved by Paul

built & tested with cross compiler & sim to arm-none-eabi

nathan
--
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
nathan@codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk

2005-10-11  Nathan Sidwell  <nathan@codesourcery.com>

	* gcc/unwind-arm.h: Reorder interface function declarations.
	(_URC_END_OF_STACK): New enumeration value.
	(_US_UNWIND_ACTION_MASK, _US_FORCE_UNWIND, _US_END_OF_STACK): Likewise.
	(struct _Unwind_Control_Block): Document reserved field use.
	(_Unwind_Stop_Fn): New typedef.
	(_Unwind_ForcedUnwind): Declare.
	(_Unwind_Resume_or_Rethrow): Declare.
	* gcc/config/arm/libunwind.S (UNWIND_WRAPER): Add nargs
	argument.  Adjust.
	(_Unwind_Resume_or_Rethrow, _Unwind_ForcedUnwind): New.
	* gcc/config/arm/unwind-arm.c (UCB_FORCED_STOP_FN,
	UCB_FORCED_STOP_ARG): New.
	(get_eit_entry): Return _URC_END_OF_STACK when cannot unwind.
	(unwind_phase2): Replace for with do..while.
	(unwind_phase2_forced): New.
	(__gnu_Unwind_RaiseException): Replace for with do..while.
	(__gnu_Unwind_ForcedUnwind): New.
	(__gnu_Unwind_Resume): Set FORCE_UNWIND flag, if forced unwinding.
	Use appropriate phase2 unwinder.
	(__gnu_Unwind_Resume_or_Rethrow): New.
	(__gnu_unwind_pr_common): Cope with forced unwinding.

	* gcc/testsuite/g++.dg/eh/forced1.C: Adjust to cope with ARM EABI
	structures.
	* gcc/testsuite/g++.dg/eh/forced2.C: Likewise.
	* gcc/testsuite/g++.dg/eh/forced3.C: Likewise.
	* gcc/testsuite/g++.dg/eh/forced4.C: Likewise.

	* libstdc++-v3/libsupc++/eh_arm.cc (__cxa_begin_cleanup): Remember a
	foreign exception too.
	(__gnu_end_cleanup): Recover a foreign exception too.
	* libstdc++-v3/libsupc++/eh_personality.cc (PERSONALITY_FUNCTION): Cope
	with forced unwinding.
	* libstdc++-v3/libsupc++/eh_throw.cc (__cxxabiv1::__cxa_rethrow): Use
	_Unwind_Resume_or_Rethrow for ARM EABI.

Index: gcc/unwind-arm.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/unwind-arm.h,v
retrieving revision 1.1.2.4
diff -c -3 -p -r1.1.2.4 unwind-arm.h
*** gcc/unwind-arm.h	16 Feb 2005 06:34:41 -0000	1.1.2.4
--- gcc/unwind-arm.h	11 Oct 2005 14:28:44 -0000
***************
*** 1,12 ****
  /* Header file for the ARM EABI unwinder
     Copyright (C) 2003, 2004  Free Software Foundation, Inc.
     Contributed by Paul Brook
! 
     This file is free software; you can redistribute it and/or modify it
     under the terms of the GNU General Public License as published by the
     Free Software Foundation; either version 2, or (at your option) any
     later version.
! 
     In addition to the permissions in the GNU General Public License, the
     Free Software Foundation gives you unlimited permission to link the
     compiled version of this file into combinations with other programs,
--- 1,12 ----
  /* Header file for the ARM EABI unwinder
     Copyright (C) 2003, 2004  Free Software Foundation, Inc.
     Contributed by Paul Brook
!    
     This file is free software; you can redistribute it and/or modify it
     under the terms of the GNU General Public License as published by the
     Free Software Foundation; either version 2, or (at your option) any
     later version.
!    
     In addition to the permissions in the GNU General Public License, the
     Free Software Foundation gives you unlimited permission to link the
     compiled version of this file into combinations with other programs,
***************
*** 15,26 ****
     do apply in other respects; for example, they cover modification of
     the file, and distribution when not linked into a combine
     executable.)
! 
     This file is distributed in the hope that it will be useful, but
     WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     General Public License for more details.
! 
     You should have received a copy of the GNU General Public License
     along with this program; see the file COPYING.  If not, write to
     the Free Software Foundation, 59 Temple Place - Suite 330,
--- 15,26 ----
     do apply in other respects; for example, they cover modification of
     the file, and distribution when not linked into a combine
     executable.)
!    
     This file is distributed in the hope that it will be useful, but
     WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     General Public License for more details.
!    
     You should have received a copy of the GNU General Public License
     along with this program; see the file COPYING.  If not, write to
     the Free Software Foundation, 59 Temple Place - Suite 330,
*************** extern "C" {
*** 53,58 ****
--- 53,59 ----
      {
        _URC_OK = 0,       /* operation completed successfully */
        _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
+       _URC_END_OF_STACK = 5,
        _URC_HANDLER_FOUND = 6,
        _URC_INSTALL_CONTEXT = 7,
        _URC_CONTINUE_UNWIND = 8,
*************** extern "C" {
*** 64,73 ****
      {
        _US_VIRTUAL_UNWIND_FRAME = 0,
        _US_UNWIND_FRAME_STARTING = 1,
!       _US_UNWIND_FRAME_RESUME = 2
      }
    _Unwind_State;
    
    typedef struct _Unwind_Control_Block _Unwind_Control_Block;
    typedef struct _Unwind_Context _Unwind_Context;
    typedef _uw _Unwind_EHT_Header;
--- 65,86 ----
      {
        _US_VIRTUAL_UNWIND_FRAME = 0,
        _US_UNWIND_FRAME_STARTING = 1,
!       _US_UNWIND_FRAME_RESUME = 2,
!       _US_ACTION_MASK = 3,
!       _US_FORCE_UNWIND = 8,
!       _US_END_OF_STACK = 16
      }
    _Unwind_State;
    
+   /* Provided only for for compatibility with existing code.  */
+   typedef int _Unwind_Action;
+ #define _UA_SEARCH_PHASE	1
+ #define _UA_CLEANUP_PHASE	2
+ #define _UA_HANDLER_FRAME	4
+ #define _UA_FORCE_UNWIND	8
+ #define _UA_END_OF_STACK	16
+ #define _URC_NO_REASON 	_URC_OK
+ 
    typedef struct _Unwind_Control_Block _Unwind_Control_Block;
    typedef struct _Unwind_Context _Unwind_Context;
    typedef _uw _Unwind_EHT_Header;
*************** extern "C" {
*** 82,91 ****
        /* Unwinder cache, private fields for the unwinder's use */
        struct
  	{
! 	  _uw reserved1;	/* init reserved1 to 0, then don't touch */
! 	  _uw reserved2;
! 	  _uw reserved3;
! 	  _uw reserved4;
  	  _uw reserved5;
  	}
        unwinder_cache;
--- 95,104 ----
        /* Unwinder cache, private fields for the unwinder's use */
        struct
  	{
! 	  _uw reserved1;  /* Forced unwind stop fn, 0 if not forced */
! 	  _uw reserved2;  /* Personality routine address */
! 	  _uw reserved3;  /* Saved callsite address */
! 	  _uw reserved4;  /* Forced unwind stop arg */
  	  _uw reserved5;
  	}
        unwinder_cache;
*************** extern "C" {
*** 114,124 ****
        long long int :0;	/* Force alignment to 8-byte boundary */
      };
    
-   /* Interface functions: */
-   _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Control_Block *ucbp);
-   void __attribute__((noreturn)) _Unwind_Resume(_Unwind_Control_Block *ucbp);
-   void _Unwind_Complete(_Unwind_Control_Block *ucbp);
- 
    /* Virtual Register Set*/
          
    typedef enum
--- 127,132 ----
*************** extern "C" {
*** 199,204 ****
--- 207,223 ----
        abort ();
      }
  
+   /* Interface functions: */
+   _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Control_Block *ucbp);
+   void __attribute__((noreturn)) _Unwind_Resume(_Unwind_Control_Block *ucbp);
+   _Unwind_Reason_Code _Unwind_Resume_or_Rethrow (_Unwind_Control_Block *ucbp);
+   
+   typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)
+        (int, _Unwind_Action, _Unwind_Exception_Class,
+ 	_Unwind_Control_Block *, struct _Unwind_Context *, void *);
+   _Unwind_Reason_Code _Unwind_ForcedUnwind (_Unwind_Control_Block *,
+ 					    _Unwind_Stop_Fn, void *);
+   void _Unwind_Complete(_Unwind_Control_Block *ucbp);
    void _Unwind_DeleteException (_Unwind_Exception *);
  
    _Unwind_Reason_Code __gnu_unwind_frame (_Unwind_Control_Block *,
*************** extern "C" {
*** 220,226 ****
        tmp += ptr;
        tmp = *(_Unwind_Word *) tmp;
  #elif defined(__symbian__)
!       /* Absoute pointer.  Nothing more to do.  */
  #else
        /* Pc-relative pointer.  */
        tmp += ptr;
--- 239,245 ----
        tmp += ptr;
        tmp = *(_Unwind_Word *) tmp;
  #elif defined(__symbian__)
!       /* Absolute pointer.  Nothing more to do.  */
  #else
        /* Pc-relative pointer.  */
        tmp += ptr;
*************** extern "C" {
*** 254,269 ****
  #define _Unwind_SetIP(context, val) \
    _Unwind_SetGR (context, 15, val | (_Unwind_GetGR (context, 15) & 1))
  
-   /* Provided only for for compatibility with existing code.  */
-   typedef int _Unwind_Action;
- #define _UA_SEARCH_PHASE	1
- #define _UA_CLEANUP_PHASE	2
- #define _UA_HANDLER_FRAME	4
- #define _UA_FORCE_UNWIND	8
- #define _UA_END_OF_STACK	16
- 
- #define _URC_NO_REASON _URC_OK
- 
  #ifdef __cplusplus
  }   /* extern "C" */
  #endif
--- 273,278 ----
Index: gcc/config/arm/libunwind.S
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/libunwind.S,v
retrieving revision 1.1.2.3
diff -c -3 -p -r1.1.2.3 libunwind.S
*** gcc/config/arm/libunwind.S	16 Feb 2005 06:34:41 -0000	1.1.2.3
--- gcc/config/arm/libunwind.S	11 Oct 2005 14:28:46 -0000
*************** ARM_FUNC_START gnu_Unwind_Save_VFP
*** 71,77 ****
  
  /* Wrappers to save core registers, then call the real routine.   */
  
! .macro  UNWIND_WRAPPER name
  	ARM_FUNC_START \name
  	/* Create a phase2_vrs structure.  */
  	/* Split reg push in two to ensure the correct value for sp.  */
--- 71,77 ----
  
  /* Wrappers to save core registers, then call the real routine.   */
  
! .macro  UNWIND_WRAPPER name nargs
  	ARM_FUNC_START \name
  	/* Create a phase2_vrs structure.  */
  	/* Split reg push in two to ensure the correct value for sp.  */
*************** ARM_FUNC_START gnu_Unwind_Save_VFP
*** 82,89 ****
  	mov r3, #0
  	stmfd sp!, {r2, r3}
  
! 	/* Point r1 at the block.  Pass r0 unchanged.  */
! 	add r1, sp, #4
  #if defined(__thumb__)
  	/* Switch back to thumb mode to avoid interworking hassle.  */
  	adr ip, .L1_\name
--- 82,89 ----
  	mov r3, #0
  	stmfd sp!, {r2, r3}
  
! 	/* Point r1 at the block.  Pass r[0..nargs) unchanged.  */
! 	add r\nargs, sp, #4
  #if defined(__thumb__)
  	/* Switch back to thumb mode to avoid interworking hassle.  */
  	adr ip, .L1_\name
*************** ARM_FUNC_START gnu_Unwind_Save_VFP
*** 105,110 ****
  	UNPREFIX \name
  .endm
  
! UNWIND_WRAPPER _Unwind_RaiseException
! UNWIND_WRAPPER _Unwind_Resume
  
--- 105,112 ----
  	UNPREFIX \name
  .endm
  
! UNWIND_WRAPPER _Unwind_RaiseException 1
! UNWIND_WRAPPER _Unwind_Resume 1
! UNWIND_WRAPPER _Unwind_Resume_or_Rethrow 1
! UNWIND_WRAPPER _Unwind_ForcedUnwind 3
  
Index: gcc/config/arm/unwind-arm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/unwind-arm.c,v
retrieving revision 1.1.2.9
diff -c -3 -p -r1.1.2.9 unwind-arm.c
*** gcc/config/arm/unwind-arm.c	7 May 2005 00:01:46 -0000	1.1.2.9
--- gcc/config/arm/unwind-arm.c	11 Oct 2005 14:28:46 -0000
*************** __gnu_Unwind_Find_exidx (_Unwind_Ptr, in
*** 51,58 ****
--- 51,60 ----
  #define EXIDX_CANTUNWIND 1
  #define uint32_highbit (((_uw) 1) << 31)
  
+ #define UCB_FORCED_STOP_FN(ucbp) ((ucbp)->unwinder_cache.reserved1)
  #define UCB_PR_ADDR(ucbp) ((ucbp)->unwinder_cache.reserved2)
  #define UCB_SAVED_CALLSITE_ADDR(ucbp) ((ucbp)->unwinder_cache.reserved3)
+ #define UCB_FORCED_STOP_ARG(ucb) ((ucbp)->unwinder_cache.reserved4)
  
  struct core_regs
  {
*************** search_EIT_table (const __EIT_entry * ta
*** 354,362 ****
        n = (left + right) / 2;
        this_fn = selfrel_offset31 (&table[n].fnoffset);
        if (n != nrec - 1)
! 	next_fn = selfrel_offset31 (&table[n + 1].fnoffset);
        else
! 	next_fn = ~(_uw) 0;
  
        if (return_address < this_fn)
  	{
--- 356,364 ----
        n = (left + right) / 2;
        this_fn = selfrel_offset31 (&table[n].fnoffset);
        if (n != nrec - 1)
! 	next_fn = selfrel_offset31 (&table[n + 1].fnoffset) - 1;
        else
! 	next_fn = (_uw)0 - 1;
  
        if (return_address < this_fn)
  	{
*************** search_EIT_table (const __EIT_entry * ta
*** 364,370 ****
  	    return (__EIT_entry *) 0;
  	  right = n - 1;
  	}
!       else if (return_address < next_fn)
  	return &table[n];
        else
  	left = n + 1;
--- 366,372 ----
  	    return (__EIT_entry *) 0;
  	  right = n - 1;
  	}
!       else if (return_address <= next_fn)
  	return &table[n];
        else
  	left = n + 1;
*************** get_eit_entry (_Unwind_Control_Block *uc
*** 412,422 ****
      }
    ucbp->pr_cache.fnstart = selfrel_offset31 (&eitp->fnoffset);
  
    /* Can this frame be unwound at all?  */
    if (eitp->content == EXIDX_CANTUNWIND)
      {
        UCB_PR_ADDR (ucbp) = 0;
!       return _URC_FAILURE;
      }
  
    /* Obtain the address of the "real" __EHT_Header word.  */
--- 414,426 ----
      }
    ucbp->pr_cache.fnstart = selfrel_offset31 (&eitp->fnoffset);
  
+   /*  printf ("unwound %x\n", return_address + 2);*/
+   
    /* Can this frame be unwound at all?  */
    if (eitp->content == EXIDX_CANTUNWIND)
      {
        UCB_PR_ADDR (ucbp) = 0;
!       return _URC_END_OF_STACK;
      }
  
    /* Obtain the address of the "real" __EHT_Header word.  */
*************** unwind_phase2 (_Unwind_Control_Block * u
*** 469,489 ****
  {
    _Unwind_Reason_Code pr_result;
  
!   for(;;)
      {
        /* Find the entry for this routine.  */
        if (get_eit_entry (ucbp, vrs->core.r[R_PC]) != _URC_OK)
  	abort ();
  
        UCB_SAVED_CALLSITE_ADDR (ucbp) = vrs->core.r[R_PC];
!       
        /* Call the pr to decide what to do.  */
        pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
  	(_US_UNWIND_FRAME_STARTING, ucbp, (_Unwind_Context *) vrs);
- 
-       if (pr_result != _URC_CONTINUE_UNWIND)
- 	break;
      }
    
    if (pr_result != _URC_INSTALL_CONTEXT)
      abort();
--- 473,491 ----
  {
    _Unwind_Reason_Code pr_result;
  
!   do
      {
        /* Find the entry for this routine.  */
        if (get_eit_entry (ucbp, vrs->core.r[R_PC]) != _URC_OK)
  	abort ();
  
        UCB_SAVED_CALLSITE_ADDR (ucbp) = vrs->core.r[R_PC];
! 
        /* Call the pr to decide what to do.  */
        pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
  	(_US_UNWIND_FRAME_STARTING, ucbp, (_Unwind_Context *) vrs);
      }
+   while (pr_result == _URC_CONTINUE_UNWIND);
    
    if (pr_result != _URC_INSTALL_CONTEXT)
      abort();
*************** unwind_phase2 (_Unwind_Control_Block * u
*** 491,496 ****
--- 493,549 ----
    restore_core_regs (&vrs->core);
  }
  
+ /* Perform phase2 forced unwinding.  */
+ 
+ static _Unwind_Reason_Code
+ unwind_phase2_forced (_Unwind_Control_Block *ucbp, phase2_vrs *entry_vrs)
+ {
+   _Unwind_Stop_Fn stop_fn = (_Unwind_Stop_Fn) UCB_FORCED_STOP_FN (ucbp);
+   void *stop_arg = (void *)UCB_FORCED_STOP_ARG (ucbp);
+   _Unwind_Reason_Code pr_result;
+ 
+   /* Unwind until we reach a propagation barrier.  */
+   do
+     {
+       _Unwind_State action;
+       _Unwind_Reason_Code entry_code;
+       _Unwind_Reason_Code stop_code;
+       
+       /* Find the entry for this routine.  */
+       entry_code = get_eit_entry (ucbp, entry_vrs->core.r[R_PC]);
+       
+       action = _US_UNWIND_FRAME_STARTING | _US_FORCE_UNWIND;
+       if (entry_code == _URC_END_OF_STACK)
+ 	action |= _US_END_OF_STACK;
+       else if (entry_code != _URC_OK)
+ 	return _URC_FAILURE;
+ 
+       stop_code = stop_fn (1, action, ucbp->exception_class, ucbp,
+ 			   (void *)entry_vrs, stop_arg);
+       if (stop_code != _URC_NO_REASON)
+ 	return _URC_FAILURE;
+ 
+       if (entry_code == _URC_END_OF_STACK)
+ 	return entry_code;
+ 
+       UCB_SAVED_CALLSITE_ADDR (ucbp) = entry_vrs->core.r[R_PC];
+       
+       /* Call the pr to decide what to do.  */
+       pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
+ 	(action, ucbp, (void *) entry_vrs);
+     }
+   while (pr_result == _URC_CONTINUE_UNWIND);
+ 
+   if (pr_result != _URC_INSTALL_CONTEXT)
+     {
+       /* Some sort of failure has occurred in the pr and probably the
+ 	 pr returned _URC_FAILURE.  */
+       return _URC_FAILURE;
+     }
+ 
+   restore_core_regs (&entry_vrs->core);
+ }
+ 
  /* Perform phase1 unwinding.  */
  
  _Unwind_Reason_Code
*************** __gnu_Unwind_RaiseException (_Unwind_Con
*** 512,518 ****
    saved_vrs.demand_save_flags = ~(_uw) 0;
    
    /* Unwind until we reach a propagation barrier.  */
!   for (;;)
      {
        /* Find the entry for this routine.  */
        if (get_eit_entry (ucbp, saved_vrs.core.r[R_PC]) != _URC_OK)
--- 565,571 ----
    saved_vrs.demand_save_flags = ~(_uw) 0;
    
    /* Unwind until we reach a propagation barrier.  */
!   do
      {
        /* Find the entry for this routine.  */
        if (get_eit_entry (ucbp, saved_vrs.core.r[R_PC]) != _URC_OK)
*************** __gnu_Unwind_RaiseException (_Unwind_Con
*** 521,530 ****
        /* Call the pr to decide what to do.  */
        pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
  	(_US_VIRTUAL_UNWIND_FRAME, ucbp, (void *) &saved_vrs);
- 
-       if (pr_result != _URC_CONTINUE_UNWIND)
- 	break;
      }
  
    /* We've unwound as far as we want to go, so restore the original
       register state.  */
--- 574,581 ----
        /* Call the pr to decide what to do.  */
        pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
  	(_US_VIRTUAL_UNWIND_FRAME, ucbp, (void *) &saved_vrs);
      }
+   while (pr_result == _URC_CONTINUE_UNWIND);
  
    /* We've unwound as far as we want to go, so restore the original
       register state.  */
*************** __gnu_Unwind_RaiseException (_Unwind_Con
*** 540,558 ****
  }
  
  _Unwind_Reason_Code
  __gnu_Unwind_Resume (_Unwind_Control_Block *, phase2_vrs *);
  
  _Unwind_Reason_Code
  __gnu_Unwind_Resume (_Unwind_Control_Block * ucbp, phase2_vrs * entry_vrs)
  {
    _Unwind_Reason_Code pr_result;
  
    /* Recover the saved address.  */
    entry_vrs->core.r[R_PC] = UCB_SAVED_CALLSITE_ADDR (ucbp);
!   
    /* Call the cached PR.  */
    pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
! 	(_US_UNWIND_FRAME_RESUME, ucbp, (_Unwind_Context *) entry_vrs);
  
    switch (pr_result)
      {
--- 591,632 ----
  }
  
  _Unwind_Reason_Code
+ __gnu_Unwind_ForcedUnwind (_Unwind_Control_Block *,
+ 			   _Unwind_Stop_Fn, void *, phase2_vrs *);
+ 
+ _Unwind_Reason_Code
+ __gnu_Unwind_ForcedUnwind (_Unwind_Control_Block *ucbp,
+ 			   _Unwind_Stop_Fn stop_fn, void *stop_arg,
+ 			   phase2_vrs *entry_vrs)
+ {
+   UCB_FORCED_STOP_FN (ucbp) = (_uw) stop_fn;
+   UCB_FORCED_STOP_ARG (ucbp) = (_uw) stop_arg;
+   
+   /* Set the pc to the call site.  */
+   entry_vrs->core.r[R_PC] = entry_vrs->core.r[R_LR];
+ 
+   return unwind_phase2_forced (ucbp, entry_vrs);
+ }
+ 
+ _Unwind_Reason_Code
  __gnu_Unwind_Resume (_Unwind_Control_Block *, phase2_vrs *);
  
  _Unwind_Reason_Code
  __gnu_Unwind_Resume (_Unwind_Control_Block * ucbp, phase2_vrs * entry_vrs)
  {
    _Unwind_Reason_Code pr_result;
+   _Unwind_State action;
  
    /* Recover the saved address.  */
    entry_vrs->core.r[R_PC] = UCB_SAVED_CALLSITE_ADDR (ucbp);
! 
    /* Call the cached PR.  */
+   action = _US_UNWIND_FRAME_RESUME;
+   if (UCB_FORCED_STOP_FN (ucbp))
+     action |= _US_FORCE_UNWIND;
+   
    pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
! 	(action, ucbp, (_Unwind_Context *) entry_vrs);
  
    switch (pr_result)
      {
*************** __gnu_Unwind_Resume (_Unwind_Control_Blo
*** 562,574 ****
  
      case _URC_CONTINUE_UNWIND:
        /* Continue unwinding the next frame.  */
!       unwind_phase2 (ucbp, entry_vrs);
  
      default:
        abort ();
      }
  }
  
  void
  _Unwind_Complete (_Unwind_Control_Block * ucbp __attribute__((unused)))
  {
--- 636,667 ----
  
      case _URC_CONTINUE_UNWIND:
        /* Continue unwinding the next frame.  */
!       if (UCB_FORCED_STOP_FN (ucbp))
! 	return unwind_phase2_forced (ucbp, entry_vrs);
!       else
! 	unwind_phase2 (ucbp, entry_vrs);
  
      default:
        abort ();
      }
  }
  
+ _Unwind_Reason_Code
+ __gnu_Unwind_Resume_or_Rethrow (_Unwind_Control_Block *, phase2_vrs *);
+ 
+ _Unwind_Reason_Code
+ __gnu_Unwind_Resume_or_Rethrow (_Unwind_Control_Block * ucbp,
+ 				phase2_vrs * entry_vrs)
+ {
+   if (!UCB_FORCED_STOP_FN (ucbp))
+     return __gnu_Unwind_RaiseException (ucbp, entry_vrs);
+ 
+   /* Set the pc to the call site.  */
+   entry_vrs->core.r[R_PC] = entry_vrs->core.r[R_LR];
+   /* Continue unwinding the next frame.  */
+   return unwind_phase2_forced (ucbp, entry_vrs);
+ }
+ 
  void
  _Unwind_Complete (_Unwind_Control_Block * ucbp __attribute__((unused)))
  {
*************** __gnu_unwind_pr_common (_Unwind_State st
*** 608,613 ****
--- 701,709 ----
    _uw rtti_count;
    int phase2_call_unexpected_after_unwind = 0;
    int in_range = 0;
+   int forced_unwind = state & _US_FORCE_UNWIND;
+   
+   state &= _US_ACTION_MASK;
  
    data = (_uw *) ucbp->pr_cache.ehtp;
    uws.data = *(data++);
*************** __gnu_unwind_pr_common (_Unwind_State st
*** 665,671 ****
  		  /* Cleanup in range, and we are running cleanups.  */
  		  _uw lp;
  
! 		  /* Landing pad address is 31-bit pc-relatvie offset.  */
  		  lp = selfrel_offset31 (data);
  		  data++;
  		  /* Save the exception data pointer.  */
--- 761,767 ----
  		  /* Cleanup in range, and we are running cleanups.  */
  		  _uw lp;
  
! 		  /* Landing pad address is 31-bit pc-relative offset.  */
  		  lp = selfrel_offset31 (data);
  		  data++;
  		  /* Save the exception data pointer.  */
*************** __gnu_unwind_pr_common (_Unwind_State st
*** 694,700 ****
  		      if (data[1] == (_uw) -2)
  			return _URC_FAILURE;
  
! 		      /* The thrown object immediately folows the ECB.  */
  		      matched = (void *)(ucbp + 1);
  		      if (data[1] != (_uw) -1)
  			{
--- 790,796 ----
  		      if (data[1] == (_uw) -2)
  			return _URC_FAILURE;
  
! 		      /* The thrown object immediately follows the ECB.  */
  		      matched = (void *)(ucbp + 1);
  		      if (data[1] != (_uw) -1)
  			{
*************** __gnu_unwind_pr_common (_Unwind_State st
*** 737,745 ****
  	      /* Exception specification.  */
  	      if (state == _US_VIRTUAL_UNWIND_FRAME)
  		{
! 		  if (in_range)
  		    {
! 		      /* Match against teh exception specification.  */
  		      _uw i;
  		      _uw rtti;
  		      void *matched;
--- 833,841 ----
  	      /* Exception specification.  */
  	      if (state == _US_VIRTUAL_UNWIND_FRAME)
  		{
! 		  if (in_range && (!forced_unwind || !rtti_count))
  		    {
! 		      /* Match against the exception specification.  */
  		      _uw i;
  		      _uw rtti;
  		      void *matched;
Index: gcc/testsuite/g++.dg/eh/forced1.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/eh/forced1.C,v
retrieving revision 1.3.16.1
diff -c -3 -p -r1.3.16.1 forced1.C
*** gcc/testsuite/g++.dg/eh/forced1.C	3 Mar 2004 16:05:07 -0000	1.3.16.1
--- gcc/testsuite/g++.dg/eh/forced1.C	11 Oct 2005 14:28:50 -0000
***************
*** 6,11 ****
--- 6,12 ----
  
  #include <unwind.h>
  #include <stdlib.h>
+ #include <string.h>
  
  static int test = 0;
  
*************** force_unwind_cleanup (_Unwind_Reason_Cod
*** 35,41 ****
  static void force_unwind ()
  {
    _Unwind_Exception *exc = new _Unwind_Exception;
!   exc->exception_class = 0;
    exc->exception_cleanup = force_unwind_cleanup;
  
  #ifndef __USING_SJLJ_EXCEPTIONS__
--- 36,43 ----
  static void force_unwind ()
  {
    _Unwind_Exception *exc = new _Unwind_Exception;
!   // exception_class might not be a scalar.
!   memset (&exc->exception_class, 0, sizeof (exc->exception_class));
    exc->exception_cleanup = force_unwind_cleanup;
  
  #ifndef __USING_SJLJ_EXCEPTIONS__
*************** struct S
*** 54,60 ****
    ~S() { test |= bit; }
  };
    
! static void doit ()
  {
    try {
      S four(4);
--- 56,62 ----
    ~S() { test |= bit; }
  };
    
! static __attribute__ ((noinline)) void doit ()
  {
    try {
      S four(4);
*************** static void doit ()
*** 62,68 ****
      try {
        S one(1);
        force_unwind ();
-   
      } catch(...) { 
        test |= 2;
        throw;
--- 64,69 ----
Index: gcc/testsuite/g++.dg/eh/forced2.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/eh/forced2.C,v
retrieving revision 1.3.16.1
diff -c -3 -p -r1.3.16.1 forced2.C
*** gcc/testsuite/g++.dg/eh/forced2.C	3 Mar 2004 16:05:07 -0000	1.3.16.1
--- gcc/testsuite/g++.dg/eh/forced2.C	11 Oct 2005 14:28:50 -0000
***************
*** 6,11 ****
--- 6,12 ----
  
  #include <unwind.h>
  #include <stdlib.h>
+ #include <string.h>
  
  static _Unwind_Reason_Code
  force_unwind_stop (int version, _Unwind_Action actions,
*************** static void
*** 29,35 ****
  force_unwind ()
  {
    _Unwind_Exception *exc = new _Unwind_Exception;
!   exc->exception_class = 0;
    exc->exception_cleanup = force_unwind_cleanup;
  
  #ifndef __USING_SJLJ_EXCEPTIONS__
--- 30,37 ----
  force_unwind ()
  {
    _Unwind_Exception *exc = new _Unwind_Exception;
!   // exception_class might not be a scalar.
!   memset (&exc->exception_class, 0, sizeof (exc->exception_class));
    exc->exception_cleanup = force_unwind_cleanup;
  
  #ifndef __USING_SJLJ_EXCEPTIONS__
Index: gcc/testsuite/g++.dg/eh/forced3.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/eh/forced3.C,v
retrieving revision 1.2.22.1
diff -c -3 -p -r1.2.22.1 forced3.C
*** gcc/testsuite/g++.dg/eh/forced3.C	3 Mar 2004 16:05:07 -0000	1.2.22.1
--- gcc/testsuite/g++.dg/eh/forced3.C	11 Oct 2005 14:28:50 -0000
***************
*** 7,12 ****
--- 7,13 ----
  #include <unwind.h>
  #include <stdlib.h>
  #include <exception>
+ #include <string.h>
  
  static _Unwind_Reason_Code
  force_unwind_stop (int version, _Unwind_Action actions,
*************** static void __attribute__((noreturn))
*** 24,30 ****
  force_unwind ()
  {
    _Unwind_Exception *exc = new _Unwind_Exception;
!   exc->exception_class = 0;
    exc->exception_cleanup = 0;
  
  #ifndef __USING_SJLJ_EXCEPTIONS__
--- 25,32 ----
  force_unwind ()
  {
    _Unwind_Exception *exc = new _Unwind_Exception;
!   // exception_class might not be a scalar.
!   memset (&exc->exception_class, 0, sizeof (exc->exception_class));
    exc->exception_cleanup = 0;
  
  #ifndef __USING_SJLJ_EXCEPTIONS__
Index: gcc/testsuite/g++.dg/eh/forced4.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/eh/forced4.C,v
retrieving revision 1.2.22.1
diff -c -3 -p -r1.2.22.1 forced4.C
*** gcc/testsuite/g++.dg/eh/forced4.C	3 Mar 2004 16:05:07 -0000	1.2.22.1
--- gcc/testsuite/g++.dg/eh/forced4.C	11 Oct 2005 14:28:50 -0000
***************
*** 6,11 ****
--- 6,12 ----
  
  #include <unwind.h>
  #include <stdlib.h>
+ #include <string.h>
  
  static _Unwind_Reason_Code
  force_unwind_stop (int version, _Unwind_Action actions,
*************** static void __attribute__((noreturn))
*** 23,29 ****
  force_unwind ()
  {
    _Unwind_Exception *exc = new _Unwind_Exception;
!   exc->exception_class = 0;
    exc->exception_cleanup = 0;
  
  #ifndef __USING_SJLJ_EXCEPTIONS__
--- 24,31 ----
  force_unwind ()
  {
    _Unwind_Exception *exc = new _Unwind_Exception;
!   // exception_class might not be a scalar.
!   memset (&exc->exception_class, 0, sizeof (exc->exception_class));
    exc->exception_cleanup = 0;
  
  #ifndef __USING_SJLJ_EXCEPTIONS__
Index: libstdc++-v3/libsupc++/eh_arm.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/libsupc++/eh_arm.cc,v
retrieving revision 1.1.2.4
diff -c -3 -p -r1.1.2.4 eh_arm.cc
*** libstdc++-v3/libsupc++/eh_arm.cc	17 Dec 2004 17:56:51 -0000	1.1.2.4
--- libstdc++-v3/libsupc++/eh_arm.cc	11 Oct 2005 14:29:01 -0000
*************** __cxa_begin_cleanup(_Unwind_Exception* u
*** 88,107 ****
  {
    __cxa_eh_globals *globals = __cxa_get_globals();
    __cxa_exception *header = __get_exception_header_from_ue(ue_header);
  
!   if (!__is_gxx_exception_class(header->unwindHeader.exception_class))
      {
!       // TODO: cleanups with foreign exceptions.
!       return false;
      }
!   header->propagationCount++;
!   // Add it to the chain if this is the first time we've seen this exception.
!   if (header->propagationCount == 1)
      {
!       header->nextPropagatingException = globals->propagatingExceptions;
        globals->propagatingExceptions = header;
      }
!   return true;
  }
  
  /* Do the work for __cxa_end_cleanup.  Returns the currently propagating
--- 88,118 ----
  {
    __cxa_eh_globals *globals = __cxa_get_globals();
    __cxa_exception *header = __get_exception_header_from_ue(ue_header);
+   bool native = __is_gxx_exception_class(header->unwindHeader.exception_class);
+   
  
!   if (native)
      {
!       header->propagationCount++;
!       // Add it to the chain if this is the first time we've seen this
!       // exception.
!       if (header->propagationCount == 1)
! 	{
! 	  header->nextPropagatingException = globals->propagatingExceptions;
! 	  globals->propagatingExceptions = header;
! 	}
      }
!   else
      {
!       // Remember the exception object, so end_cleanup can return it.
!       // These cannot be stacked, so we must abort if we already have
!       // a propagating exception.
!       if (globals->propagatingExceptions)
! 	std::terminate ();
        globals->propagatingExceptions = header;
      }
!   
!   return !native;
  }
  
  /* Do the work for __cxa_end_cleanup.  Returns the currently propagating
*************** __gnu_end_cleanup(void)
*** 118,130 ****
    if (!header)
      std::terminate();
  
!   header->propagationCount--;
!   if (header->propagationCount == 0)
      {
!       // Remove exception from chain.
!       globals->propagatingExceptions = header->nextPropagatingException;
!       header->nextPropagatingException = NULL;
      }
    return &header->unwindHeader;
  }
  
--- 129,147 ----
    if (!header)
      std::terminate();
  
!   if (__is_gxx_exception_class(header->unwindHeader.exception_class))
      {
!       header->propagationCount--;
!       if (header->propagationCount == 0)
! 	{
! 	  // Remove exception from chain.
! 	  globals->propagatingExceptions = header->nextPropagatingException;
! 	  header->nextPropagatingException = NULL;
! 	}
      }
+   else
+     globals->propagatingExceptions = NULL;
+   
    return &header->unwindHeader;
  }
  
Index: libstdc++-v3/libsupc++/eh_personality.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/libsupc++/eh_personality.cc,v
retrieving revision 1.13.8.3
diff -c -3 -p -r1.13.8.3 eh_personality.cc
*** libstdc++-v3/libsupc++/eh_personality.cc	17 Nov 2004 00:10:57 -0000	1.13.8.3
--- libstdc++-v3/libsupc++/eh_personality.cc	11 Oct 2005 14:29:02 -0000
*************** PERSONALITY_FUNCTION (int version,
*** 290,296 ****
  #ifdef __ARM_EABI_UNWINDER__
    _Unwind_Action actions;
  
!   switch (state)
      {
      case _US_VIRTUAL_UNWIND_FRAME:
        actions = _UA_SEARCH_PHASE;
--- 290,296 ----
  #ifdef __ARM_EABI_UNWINDER__
    _Unwind_Action actions;
  
!   switch (state & _US_ACTION_MASK)
      {
      case _US_VIRTUAL_UNWIND_FRAME:
        actions = _UA_SEARCH_PHASE;
*************** PERSONALITY_FUNCTION (int version,
*** 298,304 ****
  
      case _US_UNWIND_FRAME_STARTING:
        actions = _UA_CLEANUP_PHASE;
!       if (ue_header->barrier_cache.sp == _Unwind_GetGR(context, 13))
  	actions |= _UA_HANDLER_FRAME;
        break;
  
--- 298,305 ----
  
      case _US_UNWIND_FRAME_STARTING:
        actions = _UA_CLEANUP_PHASE;
!       if (!(state & _US_FORCE_UNWIND)
! 	  && ue_header->barrier_cache.sp == _Unwind_GetGR(context, 13))
  	actions |= _UA_HANDLER_FRAME;
        break;
  
*************** PERSONALITY_FUNCTION (int version,
*** 309,314 ****
--- 310,316 ----
      default:
        abort();
      }
+   actions |= state & _US_FORCE_UNWIND;
  
    /* We don't know which runtime we're working with, so can't check this.
       However the ABI routines hide this from us, and we don't actually need
*************** PERSONALITY_FUNCTION (int version,
*** 452,464 ****
        // exception class, there's no exception type.
        // ??? What to do about GNU Java and GNU Ada exceptions.
  
- #ifdef __ARM_EABI_UNWINDER__
-       throw_type = ue_header;
- #else
        if ((actions & _UA_FORCE_UNWIND)
  	  || foreign_exception)
  	throw_type = 0;
        else
  	throw_type = xh->exceptionType;
  #endif
  
--- 454,466 ----
        // exception class, there's no exception type.
        // ??? What to do about GNU Java and GNU Ada exceptions.
  
        if ((actions & _UA_FORCE_UNWIND)
  	  || foreign_exception)
  	throw_type = 0;
        else
+ #ifdef __ARM_EABI_UNWINDER__
+ 	throw_type = ue_header;
+ #else
  	throw_type = xh->exceptionType;
  #endif
  
*************** PERSONALITY_FUNCTION (int version,
*** 557,563 ****
  
   install_context:
    
- #ifndef __ARM_EABI_UNWINDER__
    // We can't use any of the cxa routines with foreign exceptions,
    // because they all expect ue_header to be a struct __cxa_exception.
    // So in that case, call terminate or unexpected directly.
--- 559,564 ----
*************** PERSONALITY_FUNCTION (int version,
*** 575,581 ****
  	}
      }
    else
- #endif
      {
        if (found_type == found_terminate)
  	__cxa_call_terminate(ue_header);
--- 576,581 ----
Index: libstdc++-v3/libsupc++/eh_throw.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/libsupc++/eh_throw.cc,v
retrieving revision 1.7.8.2
diff -c -3 -p -r1.7.8.2 eh_throw.cc
*** libstdc++-v3/libsupc++/eh_throw.cc	22 Sep 2004 15:40:33 -0000	1.7.8.2
--- libstdc++-v3/libsupc++/eh_throw.cc	11 Oct 2005 14:29:02 -0000
*************** __cxxabiv1::__cxa_rethrow ()
*** 98,104 ****
  #ifdef _GLIBCXX_SJLJ_EXCEPTIONS
        _Unwind_SjLj_Resume_or_Rethrow (&header->unwindHeader);
  #else
! #if defined(_LIBUNWIND_STD_ABI) || defined (__ARM_EABI_UNWINDER__)
        _Unwind_RaiseException (&header->unwindHeader);
  #else
        _Unwind_Resume_or_Rethrow (&header->unwindHeader);
--- 98,104 ----
  #ifdef _GLIBCXX_SJLJ_EXCEPTIONS
        _Unwind_SjLj_Resume_or_Rethrow (&header->unwindHeader);
  #else
! #if defined(_LIBUNWIND_STD_ABI)
        _Unwind_RaiseException (&header->unwindHeader);
  #else
        _Unwind_Resume_or_Rethrow (&header->unwindHeader);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]