Home | History | Annotate | Line # | Download | only in libgcc
      1   1.1  mrg /* Exception handling and frame unwind runtime interface routines. -*- C -*-
      2  1.10  mrg    Copyright (C) 2001-2022 Free Software Foundation, Inc.
      3   1.1  mrg 
      4   1.1  mrg    This file is part of GCC.
      5   1.1  mrg 
      6   1.1  mrg    GCC is free software; you can redistribute it and/or modify it
      7   1.1  mrg    under the terms of the GNU General Public License as published by
      8   1.1  mrg    the Free Software Foundation; either version 3, or (at your option)
      9   1.1  mrg    any later version.
     10   1.1  mrg 
     11   1.1  mrg    GCC is distributed in the hope that it will be useful, but WITHOUT
     12   1.1  mrg    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     13   1.1  mrg    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     14   1.1  mrg    License for more details.
     15   1.1  mrg 
     16   1.1  mrg    Under Section 7 of GPL version 3, you are granted additional
     17   1.1  mrg    permissions described in the GCC Runtime Library Exception, version
     18   1.1  mrg    3.1, as published by the Free Software Foundation.
     19   1.1  mrg 
     20   1.1  mrg    You should have received a copy of the GNU General Public License and
     21   1.1  mrg    a copy of the GCC Runtime Library Exception along with this program;
     22   1.1  mrg    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23   1.1  mrg    <http://www.gnu.org/licenses/>.  */
     24   1.1  mrg 
     25   1.1  mrg /* This is derived from the C++ ABI for IA-64.  Where we diverge
     26   1.1  mrg    for cross-architecture compatibility are noted with "@@@".
     27   1.1  mrg    This file is included from unwind-dw2.c, unwind-sjlj.c or
     28   1.1  mrg    unwind-ia64.c.  */
     29   1.1  mrg 
     30   1.1  mrg /* Subroutine of _Unwind_RaiseException also invoked from _Unwind_Resume.
     31   1.1  mrg 
     32   1.1  mrg    Unwind the stack calling the personality routine to find both the
     33   1.1  mrg    exception handler and intermediary cleanup code.  We'll only locate
     34   1.1  mrg    the first such frame here.  Cleanup code will call back into
     35   1.1  mrg    _Unwind_Resume and we'll continue Phase 2 there.  */
     36   1.1  mrg 
     37   1.1  mrg static _Unwind_Reason_Code
     38   1.1  mrg _Unwind_RaiseException_Phase2(struct _Unwind_Exception *exc,
     39   1.7  mrg 			      struct _Unwind_Context *context,
     40   1.7  mrg 			      unsigned long *frames_p)
     41   1.1  mrg {
     42   1.1  mrg   _Unwind_Reason_Code code;
     43   1.7  mrg   unsigned long frames = 1;
     44   1.1  mrg 
     45   1.1  mrg   while (1)
     46   1.1  mrg     {
     47   1.1  mrg       _Unwind_FrameState fs;
     48   1.1  mrg       int match_handler;
     49   1.1  mrg 
     50   1.1  mrg       code = uw_frame_state_for (context, &fs);
     51   1.1  mrg 
     52   1.1  mrg       /* Identify when we've reached the designated handler context.  */
     53   1.1  mrg       match_handler = (uw_identify_context (context) == exc->private_2
     54   1.1  mrg 		       ? _UA_HANDLER_FRAME : 0);
     55   1.1  mrg 
     56   1.1  mrg       if (code != _URC_NO_REASON)
     57   1.1  mrg 	/* Some error encountered.  Usually the unwinder doesn't
     58   1.1  mrg 	   diagnose these and merely crashes.  */
     59   1.1  mrg 	return _URC_FATAL_PHASE2_ERROR;
     60   1.1  mrg 
     61   1.1  mrg       /* Unwind successful.  Run the personality routine, if any.  */
     62   1.1  mrg       if (fs.personality)
     63   1.1  mrg 	{
     64   1.1  mrg 	  code = (*fs.personality) (1, _UA_CLEANUP_PHASE | match_handler,
     65   1.1  mrg 				    exc->exception_class, exc, context);
     66   1.1  mrg 	  if (code == _URC_INSTALL_CONTEXT)
     67   1.1  mrg 	    break;
     68   1.1  mrg 	  if (code != _URC_CONTINUE_UNWIND)
     69   1.1  mrg 	    return _URC_FATAL_PHASE2_ERROR;
     70   1.1  mrg 	}
     71   1.1  mrg 
     72   1.1  mrg       /* Don't let us unwind past the handler context.  */
     73   1.1  mrg       gcc_assert (!match_handler);
     74   1.1  mrg 
     75   1.1  mrg       uw_update_context (context, &fs);
     76   1.7  mrg       _Unwind_Frames_Increment (context, frames);
     77   1.1  mrg     }
     78   1.1  mrg 
     79   1.7  mrg   *frames_p = frames;
     80   1.1  mrg   return code;
     81   1.1  mrg }
     82   1.1  mrg 
     83   1.1  mrg /* Raise an exception, passing along the given exception object.  */
     84   1.1  mrg 
     85   1.1  mrg _Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
     86   1.1  mrg _Unwind_RaiseException(struct _Unwind_Exception *exc)
     87   1.1  mrg {
     88   1.1  mrg   struct _Unwind_Context this_context, cur_context;
     89   1.1  mrg   _Unwind_Reason_Code code;
     90   1.7  mrg   unsigned long frames;
     91   1.1  mrg 
     92   1.1  mrg   /* Set up this_context to describe the current stack frame.  */
     93   1.1  mrg   uw_init_context (&this_context);
     94   1.1  mrg   cur_context = this_context;
     95   1.1  mrg 
     96   1.1  mrg   /* Phase 1: Search.  Unwind the stack, calling the personality routine
     97   1.1  mrg      with the _UA_SEARCH_PHASE flag set.  Do not modify the stack yet.  */
     98   1.1  mrg   while (1)
     99   1.1  mrg     {
    100   1.1  mrg       _Unwind_FrameState fs;
    101   1.1  mrg 
    102   1.1  mrg       /* Set up fs to describe the FDE for the caller of cur_context.  The
    103   1.1  mrg 	 first time through the loop, that means __cxa_throw.  */
    104   1.1  mrg       code = uw_frame_state_for (&cur_context, &fs);
    105   1.1  mrg 
    106   1.1  mrg       if (code == _URC_END_OF_STACK)
    107   1.1  mrg 	/* Hit end of stack with no handler found.  */
    108   1.1  mrg 	return _URC_END_OF_STACK;
    109   1.1  mrg 
    110   1.1  mrg       if (code != _URC_NO_REASON)
    111   1.1  mrg 	/* Some error encountered.  Usually the unwinder doesn't
    112   1.1  mrg 	   diagnose these and merely crashes.  */
    113   1.1  mrg 	return _URC_FATAL_PHASE1_ERROR;
    114   1.1  mrg 
    115   1.1  mrg       /* Unwind successful.  Run the personality routine, if any.  */
    116   1.1  mrg       if (fs.personality)
    117   1.1  mrg 	{
    118   1.1  mrg 	  code = (*fs.personality) (1, _UA_SEARCH_PHASE, exc->exception_class,
    119   1.1  mrg 				    exc, &cur_context);
    120   1.1  mrg 	  if (code == _URC_HANDLER_FOUND)
    121   1.1  mrg 	    break;
    122   1.1  mrg 	  else if (code != _URC_CONTINUE_UNWIND)
    123   1.1  mrg 	    return _URC_FATAL_PHASE1_ERROR;
    124   1.1  mrg 	}
    125   1.1  mrg 
    126   1.1  mrg       /* Update cur_context to describe the same frame as fs.  */
    127   1.1  mrg       uw_update_context (&cur_context, &fs);
    128   1.1  mrg     }
    129   1.1  mrg 
    130   1.1  mrg   /* Indicate to _Unwind_Resume and associated subroutines that this
    131   1.1  mrg      is not a forced unwind.  Further, note where we found a handler.  */
    132   1.1  mrg   exc->private_1 = 0;
    133   1.1  mrg   exc->private_2 = uw_identify_context (&cur_context);
    134   1.1  mrg 
    135   1.1  mrg   cur_context = this_context;
    136   1.7  mrg   code = _Unwind_RaiseException_Phase2 (exc, &cur_context, &frames);
    137   1.1  mrg   if (code != _URC_INSTALL_CONTEXT)
    138   1.1  mrg     return code;
    139   1.1  mrg 
    140   1.7  mrg   uw_install_context (&this_context, &cur_context, frames);
    141   1.1  mrg }
    142   1.1  mrg 
    143   1.1  mrg 
    144   1.1  mrg /* Subroutine of _Unwind_ForcedUnwind also invoked from _Unwind_Resume.  */
    145   1.1  mrg 
    146   1.1  mrg static _Unwind_Reason_Code
    147   1.1  mrg _Unwind_ForcedUnwind_Phase2 (struct _Unwind_Exception *exc,
    148   1.7  mrg 			     struct _Unwind_Context *context,
    149   1.7  mrg 			     unsigned long *frames_p)
    150   1.1  mrg {
    151   1.1  mrg   _Unwind_Stop_Fn stop = (_Unwind_Stop_Fn) (_Unwind_Ptr) exc->private_1;
    152   1.1  mrg   void *stop_argument = (void *) (_Unwind_Ptr) exc->private_2;
    153   1.1  mrg   _Unwind_Reason_Code code, stop_code;
    154   1.7  mrg   unsigned long frames = 1;
    155   1.1  mrg 
    156   1.1  mrg   while (1)
    157   1.1  mrg     {
    158   1.1  mrg       _Unwind_FrameState fs;
    159   1.1  mrg       int action;
    160   1.1  mrg 
    161   1.1  mrg       /* Set up fs to describe the FDE for the caller of cur_context.  */
    162   1.1  mrg       code = uw_frame_state_for (context, &fs);
    163  1.10  mrg       if (code != _URC_NO_REASON && code != _URC_END_OF_STACK
    164  1.10  mrg 	  && code != _URC_NORMAL_STOP)
    165   1.1  mrg 	return _URC_FATAL_PHASE2_ERROR;
    166   1.1  mrg 
    167   1.1  mrg       /* Unwind successful.  */
    168   1.1  mrg       action = _UA_FORCE_UNWIND | _UA_CLEANUP_PHASE;
    169  1.10  mrg       if (code == _URC_END_OF_STACK || code == _URC_NORMAL_STOP)
    170   1.1  mrg 	action |= _UA_END_OF_STACK;
    171   1.1  mrg       stop_code = (*stop) (1, action, exc->exception_class, exc,
    172   1.1  mrg 			   context, stop_argument);
    173   1.1  mrg       if (stop_code != _URC_NO_REASON)
    174   1.1  mrg 	return _URC_FATAL_PHASE2_ERROR;
    175   1.1  mrg 
    176   1.1  mrg       /* Stop didn't want to do anything.  Invoke the personality
    177   1.1  mrg 	 handler, if applicable, to run cleanups.  */
    178   1.1  mrg       if (code == _URC_END_OF_STACK)
    179   1.1  mrg 	break;
    180   1.1  mrg 
    181   1.1  mrg       if (fs.personality)
    182   1.1  mrg 	{
    183   1.1  mrg 	  code = (*fs.personality) (1, _UA_FORCE_UNWIND | _UA_CLEANUP_PHASE,
    184   1.1  mrg 				    exc->exception_class, exc, context);
    185   1.1  mrg 	  if (code == _URC_INSTALL_CONTEXT)
    186   1.1  mrg 	    break;
    187   1.1  mrg 	  if (code != _URC_CONTINUE_UNWIND)
    188   1.1  mrg 	    return _URC_FATAL_PHASE2_ERROR;
    189   1.1  mrg 	}
    190   1.1  mrg 
    191   1.1  mrg       /* Update cur_context to describe the same frame as fs, and discard
    192   1.1  mrg 	 the previous context if necessary.  */
    193   1.1  mrg       uw_advance_context (context, &fs);
    194   1.7  mrg       _Unwind_Frames_Increment (context, frames);
    195   1.1  mrg     }
    196   1.1  mrg 
    197   1.7  mrg   *frames_p = frames;
    198   1.1  mrg   return code;
    199   1.1  mrg }
    200   1.1  mrg 
    201   1.1  mrg 
    202   1.1  mrg /* Raise an exception for forced unwinding.  */
    203   1.1  mrg 
    204   1.1  mrg _Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
    205   1.1  mrg _Unwind_ForcedUnwind (struct _Unwind_Exception *exc,
    206   1.1  mrg 		      _Unwind_Stop_Fn stop, void * stop_argument)
    207   1.1  mrg {
    208   1.1  mrg   struct _Unwind_Context this_context, cur_context;
    209   1.1  mrg   _Unwind_Reason_Code code;
    210   1.7  mrg   unsigned long frames;
    211   1.1  mrg 
    212   1.1  mrg   uw_init_context (&this_context);
    213   1.1  mrg   cur_context = this_context;
    214   1.1  mrg 
    215   1.1  mrg   exc->private_1 = (_Unwind_Ptr) stop;
    216   1.1  mrg   exc->private_2 = (_Unwind_Ptr) stop_argument;
    217   1.1  mrg 
    218   1.7  mrg   code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context, &frames);
    219   1.1  mrg   if (code != _URC_INSTALL_CONTEXT)
    220   1.1  mrg     return code;
    221   1.1  mrg 
    222   1.7  mrg   uw_install_context (&this_context, &cur_context, frames);
    223   1.1  mrg }
    224   1.1  mrg 
    225   1.1  mrg 
    226   1.1  mrg /* Resume propagation of an existing exception.  This is used after
    227   1.1  mrg    e.g. executing cleanup code, and not to implement rethrowing.  */
    228   1.1  mrg 
    229   1.1  mrg void LIBGCC2_UNWIND_ATTRIBUTE
    230   1.1  mrg _Unwind_Resume (struct _Unwind_Exception *exc)
    231   1.1  mrg {
    232   1.1  mrg   struct _Unwind_Context this_context, cur_context;
    233   1.1  mrg   _Unwind_Reason_Code code;
    234   1.7  mrg   unsigned long frames;
    235   1.1  mrg 
    236   1.1  mrg   uw_init_context (&this_context);
    237   1.1  mrg   cur_context = this_context;
    238   1.1  mrg 
    239   1.1  mrg   /* Choose between continuing to process _Unwind_RaiseException
    240   1.1  mrg      or _Unwind_ForcedUnwind.  */
    241   1.1  mrg   if (exc->private_1 == 0)
    242   1.7  mrg     code = _Unwind_RaiseException_Phase2 (exc, &cur_context, &frames);
    243   1.1  mrg   else
    244   1.7  mrg     code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context, &frames);
    245   1.1  mrg 
    246   1.1  mrg   gcc_assert (code == _URC_INSTALL_CONTEXT);
    247   1.1  mrg 
    248   1.7  mrg   uw_install_context (&this_context, &cur_context, frames);
    249   1.1  mrg }
    250   1.1  mrg 
    251   1.1  mrg 
    252   1.1  mrg /* Resume propagation of an FORCE_UNWIND exception, or to rethrow
    253   1.1  mrg    a normal exception that was handled.  */
    254   1.1  mrg 
    255   1.1  mrg _Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
    256   1.1  mrg _Unwind_Resume_or_Rethrow (struct _Unwind_Exception *exc)
    257   1.1  mrg {
    258   1.1  mrg   struct _Unwind_Context this_context, cur_context;
    259   1.1  mrg   _Unwind_Reason_Code code;
    260   1.7  mrg   unsigned long frames;
    261   1.1  mrg 
    262   1.1  mrg   /* Choose between continuing to process _Unwind_RaiseException
    263   1.1  mrg      or _Unwind_ForcedUnwind.  */
    264   1.1  mrg   if (exc->private_1 == 0)
    265   1.1  mrg     return _Unwind_RaiseException (exc);
    266   1.1  mrg 
    267   1.1  mrg   uw_init_context (&this_context);
    268   1.1  mrg   cur_context = this_context;
    269   1.1  mrg 
    270   1.7  mrg   code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context, &frames);
    271   1.1  mrg 
    272   1.1  mrg   gcc_assert (code == _URC_INSTALL_CONTEXT);
    273   1.1  mrg 
    274   1.7  mrg   uw_install_context (&this_context, &cur_context, frames);
    275   1.1  mrg }
    276   1.1  mrg 
    277   1.1  mrg 
    278   1.1  mrg /* A convenience function that calls the exception_cleanup field.  */
    279   1.1  mrg 
    280   1.1  mrg void
    281   1.1  mrg _Unwind_DeleteException (struct _Unwind_Exception *exc)
    282   1.1  mrg {
    283   1.1  mrg   if (exc->exception_cleanup)
    284   1.1  mrg     (*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc);
    285   1.1  mrg }
    286   1.1  mrg 
    287   1.1  mrg 
    288   1.1  mrg /* Perform stack backtrace through unwind data.  */
    289   1.1  mrg 
    290   1.1  mrg _Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
    291   1.1  mrg _Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument)
    292   1.1  mrg {
    293   1.1  mrg   struct _Unwind_Context context;
    294   1.1  mrg   _Unwind_Reason_Code code;
    295   1.1  mrg 
    296   1.1  mrg   uw_init_context (&context);
    297   1.1  mrg 
    298   1.1  mrg   while (1)
    299   1.1  mrg     {
    300   1.1  mrg       _Unwind_FrameState fs;
    301   1.1  mrg 
    302   1.1  mrg       /* Set up fs to describe the FDE for the caller of context.  */
    303   1.1  mrg       code = uw_frame_state_for (&context, &fs);
    304  1.10  mrg       if (code != _URC_NO_REASON && code != _URC_END_OF_STACK
    305  1.10  mrg           && code != _URC_NORMAL_STOP)
    306   1.1  mrg 	return _URC_FATAL_PHASE1_ERROR;
    307   1.1  mrg 
    308   1.1  mrg       /* Call trace function.  */
    309   1.1  mrg       if ((*trace) (&context, trace_argument) != _URC_NO_REASON)
    310   1.1  mrg 	return _URC_FATAL_PHASE1_ERROR;
    311   1.1  mrg 
    312  1.10  mrg #ifdef MD_BACKCHAIN_FALLBACK
    313  1.10  mrg       /* Do a backchain if there is no DWARF data.  */
    314  1.10  mrg       if (code == _URC_NORMAL_STOP)
    315  1.10  mrg 	{
    316  1.10  mrg 	  MD_BACKCHAIN_FALLBACK(&context, trace_argument);
    317  1.10  mrg 	  break;
    318  1.10  mrg 	}
    319  1.10  mrg #endif
    320  1.10  mrg 
    321  1.10  mrg       /* We're done at end of stack.  */
    322   1.1  mrg       if (code == _URC_END_OF_STACK)
    323   1.1  mrg 	break;
    324   1.1  mrg 
    325   1.1  mrg       /* Update context to describe the same frame as fs.  */
    326   1.1  mrg       uw_update_context (&context, &fs);
    327   1.1  mrg     }
    328   1.1  mrg 
    329   1.1  mrg   return code;
    330   1.1  mrg }
    331