Home | History | Annotate | Line # | Download | only in libobjc
      1       1.1  mrg /* The implementation of exception handling primitives for Objective-C.
      2  1.1.1.12  mrg    Copyright (C) 2004-2024 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 the
      8       1.1  mrg Free Software Foundation; either version 3, or (at your option) any
      9       1.1  mrg 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 or
     13       1.1  mrg 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.1.2  mrg #include "objc-private/common.h"
     26       1.1  mrg #include <stdlib.h>
     27       1.1  mrg #include "config.h"
     28   1.1.1.2  mrg #include "objc/runtime.h"
     29   1.1.1.2  mrg #include "objc/objc-exception.h"
     30       1.1  mrg #include "unwind.h"
     31       1.1  mrg #include "unwind-pe.h"
     32   1.1.1.2  mrg #include <string.h> /* For memcpy */
     33   1.1.1.2  mrg 
     34   1.1.1.2  mrg /* 'is_kind_of_exception_matcher' is our default exception matcher -
     35   1.1.1.2  mrg    it determines if the object 'exception' is of class 'catch_class',
     36   1.1.1.2  mrg    or of a subclass.  */
     37   1.1.1.2  mrg static int
     38   1.1.1.2  mrg is_kind_of_exception_matcher (Class catch_class, id exception)
     39   1.1.1.2  mrg {
     40   1.1.1.2  mrg   /* NULL catch_class is catch-all (eg, @catch (id object)).  */
     41   1.1.1.2  mrg   if (catch_class == Nil)
     42   1.1.1.2  mrg     return 1;
     43   1.1.1.2  mrg 
     44   1.1.1.2  mrg   /* If exception is nil (eg, @throw nil;), then it can only be
     45   1.1.1.2  mrg      catched by a catch-all (eg, @catch (id object)).  */
     46   1.1.1.2  mrg   if (exception != nil)
     47   1.1.1.2  mrg     {
     48   1.1.1.2  mrg       Class c;
     49   1.1.1.2  mrg 
     50   1.1.1.2  mrg       for (c = exception->class_pointer; c != Nil;
     51   1.1.1.2  mrg 	   c = class_getSuperclass (c))
     52   1.1.1.2  mrg 	if (c == catch_class)
     53   1.1.1.2  mrg 	  return 1;
     54   1.1.1.2  mrg     }
     55   1.1.1.2  mrg   return 0;
     56   1.1.1.2  mrg }
     57   1.1.1.2  mrg 
     58   1.1.1.2  mrg /* The exception matcher currently in use.  */
     59   1.1.1.2  mrg static objc_exception_matcher
     60   1.1.1.2  mrg __objc_exception_matcher = is_kind_of_exception_matcher;
     61   1.1.1.2  mrg 
     62   1.1.1.2  mrg objc_exception_matcher
     63   1.1.1.2  mrg objc_setExceptionMatcher (objc_exception_matcher new_matcher)
     64   1.1.1.2  mrg {
     65   1.1.1.2  mrg   objc_exception_matcher old_matcher = __objc_exception_matcher;
     66   1.1.1.2  mrg   __objc_exception_matcher = new_matcher;
     67   1.1.1.2  mrg   return old_matcher;
     68   1.1.1.2  mrg }
     69   1.1.1.2  mrg 
     70   1.1.1.2  mrg /* The uncaught exception handler currently in use.  */
     71   1.1.1.2  mrg static objc_uncaught_exception_handler
     72   1.1.1.2  mrg __objc_uncaught_exception_handler = NULL;
     73   1.1.1.2  mrg 
     74   1.1.1.2  mrg objc_uncaught_exception_handler
     75   1.1.1.2  mrg objc_setUncaughtExceptionHandler (objc_uncaught_exception_handler
     76   1.1.1.2  mrg 				  new_handler)
     77   1.1.1.2  mrg {
     78   1.1.1.2  mrg   objc_uncaught_exception_handler old_handler
     79   1.1.1.2  mrg     = __objc_uncaught_exception_handler;
     80   1.1.1.2  mrg   __objc_uncaught_exception_handler = new_handler;
     81   1.1.1.2  mrg   return old_handler;
     82   1.1.1.2  mrg }
     83   1.1.1.2  mrg 
     84       1.1  mrg 
     85       1.1  mrg 
     86       1.1  mrg #ifdef __ARM_EABI_UNWINDER__
     88       1.1  mrg 
     89       1.1  mrg const _Unwind_Exception_Class __objc_exception_class
     90       1.1  mrg   = {'G', 'N', 'U', 'C', 'O', 'B', 'J', 'C'};
     91       1.1  mrg 
     92       1.1  mrg #else
     93       1.1  mrg 
     94       1.1  mrg /* This is the exception class we report -- "GNUCOBJC".  */
     95       1.1  mrg static const _Unwind_Exception_Class __objc_exception_class
     96       1.1  mrg   = ((((((((_Unwind_Exception_Class) 'G'
     97       1.1  mrg             << 8 | (_Unwind_Exception_Class) 'N')
     98       1.1  mrg            << 8 | (_Unwind_Exception_Class) 'U')
     99       1.1  mrg           << 8 | (_Unwind_Exception_Class) 'C')
    100       1.1  mrg          << 8 | (_Unwind_Exception_Class) 'O')
    101       1.1  mrg         << 8 | (_Unwind_Exception_Class) 'B')
    102       1.1  mrg        << 8 | (_Unwind_Exception_Class) 'J')
    103       1.1  mrg       << 8 | (_Unwind_Exception_Class) 'C');
    104       1.1  mrg 
    105       1.1  mrg #endif
    106       1.1  mrg 
    107       1.1  mrg /* This is the object that is passed around by the Objective C runtime
    108       1.1  mrg    to represent the exception in flight.  */
    109       1.1  mrg struct ObjcException
    110       1.1  mrg {
    111       1.1  mrg   /* This bit is needed in order to interact with the unwind runtime.  */
    112       1.1  mrg   struct _Unwind_Exception base;
    113   1.1.1.2  mrg 
    114   1.1.1.2  mrg   /* The actual object we want to throw. Note: must come immediately
    115       1.1  mrg      after unwind header.  */
    116       1.1  mrg   id value;
    117       1.1  mrg 
    118   1.1.1.2  mrg #ifdef __ARM_EABI_UNWINDER__
    119   1.1.1.2  mrg   /* Note: we use the barrier cache defined in the unwind control
    120       1.1  mrg      block for ARM EABI.  */
    121       1.1  mrg #else
    122       1.1  mrg   /* Cache some internal unwind data between phase 1 and phase 2.  */
    123       1.1  mrg   _Unwind_Ptr landingPad;
    124       1.1  mrg   int handlerSwitchValue;
    125       1.1  mrg #endif
    126       1.1  mrg };
    127       1.1  mrg 
    128       1.1  mrg 
    129       1.1  mrg 
    131       1.1  mrg struct lsda_header_info
    132       1.1  mrg {
    133       1.1  mrg   _Unwind_Ptr Start;
    134       1.1  mrg   _Unwind_Ptr LPStart;
    135       1.1  mrg   _Unwind_Ptr ttype_base;
    136       1.1  mrg   const unsigned char *TType;
    137       1.1  mrg   const unsigned char *action_table;
    138       1.1  mrg   unsigned char ttype_encoding;
    139       1.1  mrg   unsigned char call_site_encoding;
    140       1.1  mrg };
    141       1.1  mrg 
    142       1.1  mrg static const unsigned char *
    143       1.1  mrg parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p,
    144       1.1  mrg 		   struct lsda_header_info *info)
    145       1.1  mrg {
    146       1.1  mrg   _uleb128_t tmp;
    147       1.1  mrg   unsigned char lpstart_encoding;
    148       1.1  mrg 
    149   1.1.1.2  mrg   info->Start = (context ? _Unwind_GetRegionStart (context) : 0);
    150   1.1.1.2  mrg 
    151       1.1  mrg   /* Find @LPStart, the base to which landing pad offsets are
    152       1.1  mrg      relative.  */
    153       1.1  mrg   lpstart_encoding = *p++;
    154       1.1  mrg   if (lpstart_encoding != DW_EH_PE_omit)
    155       1.1  mrg     p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart);
    156       1.1  mrg   else
    157   1.1.1.2  mrg     info->LPStart = info->Start;
    158   1.1.1.2  mrg 
    159       1.1  mrg   /* Find @TType, the base of the handler and exception spec type
    160       1.1  mrg      data.  */
    161       1.1  mrg   info->ttype_encoding = *p++;
    162   1.1.1.2  mrg   if (info->ttype_encoding != DW_EH_PE_omit)
    163   1.1.1.2  mrg     {
    164   1.1.1.2  mrg #if _GLIBCXX_OVERRIDE_TTYPE_ENCODING
    165   1.1.1.2  mrg       /* Older ARM EABI toolchains set this value incorrectly, so use a
    166   1.1.1.2  mrg 	 hardcoded OS-specific format.  */
    167       1.1  mrg       info->ttype_encoding = _GLIBCXX_OVERRIDE_TTYPE_ENCODING;
    168       1.1  mrg #endif
    169       1.1  mrg       p = read_uleb128 (p, &tmp);
    170       1.1  mrg       info->TType = p + tmp;
    171       1.1  mrg     }
    172       1.1  mrg   else
    173       1.1  mrg     info->TType = 0;
    174       1.1  mrg 
    175       1.1  mrg   /* The encoding and length of the call-site table; the action table
    176       1.1  mrg      immediately follows.  */
    177       1.1  mrg   info->call_site_encoding = *p++;
    178       1.1  mrg   p = read_uleb128 (p, &tmp);
    179       1.1  mrg   info->action_table = p + tmp;
    180       1.1  mrg 
    181       1.1  mrg   return p;
    182       1.1  mrg }
    183       1.1  mrg 
    184       1.1  mrg static Class
    185       1.1  mrg get_ttype_entry (struct lsda_header_info *info, _Unwind_Word i)
    186       1.1  mrg {
    187       1.1  mrg   _Unwind_Ptr ptr;
    188       1.1  mrg 
    189       1.1  mrg   i *= size_of_encoded_value (info->ttype_encoding);
    190       1.1  mrg   read_encoded_value_with_base (info->ttype_encoding, info->ttype_base,
    191   1.1.1.2  mrg 				info->TType - i, &ptr);
    192   1.1.1.2  mrg 
    193       1.1  mrg   /* NULL ptr means catch-all.  Note that if the class is not found,
    194   1.1.1.2  mrg      this will abort the program.  */
    195       1.1  mrg   if (ptr)
    196       1.1  mrg     return objc_getRequiredClass ((const char *) ptr);
    197       1.1  mrg   else
    198       1.1  mrg     return 0;
    199       1.1  mrg }
    200   1.1.1.2  mrg 
    201   1.1.1.2  mrg /* Using a different personality function name causes link failures
    202   1.1.1.4  mrg    when trying to mix code using different exception handling
    203       1.1  mrg    models.  */
    204       1.1  mrg #ifdef __USING_SJLJ_EXCEPTIONS__
    205   1.1.1.4  mrg #define PERSONALITY_FUNCTION	__gnu_objc_personality_sj0
    206   1.1.1.2  mrg #define __builtin_eh_return_data_regno(x) x
    207       1.1  mrg #elif defined(__SEH__)
    208       1.1  mrg #define PERSONALITY_FUNCTION	__gnu_objc_personality_imp
    209       1.1  mrg #else
    210       1.1  mrg #define PERSONALITY_FUNCTION	__gnu_objc_personality_v0
    211       1.1  mrg #endif
    212       1.1  mrg 
    213       1.1  mrg #ifdef __ARM_EABI_UNWINDER__
    214       1.1  mrg 
    215       1.1  mrg #define CONTINUE_UNWINDING \
    216       1.1  mrg   do								\
    217       1.1  mrg     {								\
    218       1.1  mrg       if (__gnu_unwind_frame(ue_header, context) != _URC_OK)	\
    219       1.1  mrg 	return _URC_FAILURE;					\
    220       1.1  mrg       return _URC_CONTINUE_UNWIND;				\
    221       1.1  mrg     }								\
    222       1.1  mrg   while (0)
    223   1.1.1.9  mrg 
    224       1.1  mrg _Unwind_Reason_Code
    225       1.1  mrg __attribute__((target ("general-regs-only")))
    226       1.1  mrg PERSONALITY_FUNCTION (_Unwind_State state,
    227       1.1  mrg 		      struct _Unwind_Exception *ue_header,
    228       1.1  mrg 		      struct _Unwind_Context *context)
    229       1.1  mrg #else
    230       1.1  mrg 
    231   1.1.1.2  mrg #define CONTINUE_UNWINDING return _URC_CONTINUE_UNWIND
    232   1.1.1.2  mrg 
    233   1.1.1.2  mrg #if defined (__SEH__) && !defined (__USING_SJLJ_EXCEPTIONS__)
    234       1.1  mrg static
    235       1.1  mrg #endif
    236       1.1  mrg _Unwind_Reason_Code
    237       1.1  mrg PERSONALITY_FUNCTION (int version,
    238       1.1  mrg 		      _Unwind_Action actions,
    239       1.1  mrg 		      _Unwind_Exception_Class exception_class,
    240       1.1  mrg 		      struct _Unwind_Exception *ue_header,
    241       1.1  mrg 		      struct _Unwind_Context *context)
    242       1.1  mrg #endif
    243       1.1  mrg {
    244       1.1  mrg   struct ObjcException *xh = (struct ObjcException *) ue_header;
    245       1.1  mrg 
    246       1.1  mrg   struct lsda_header_info info;
    247       1.1  mrg   const unsigned char *language_specific_data;
    248       1.1  mrg   const unsigned char *action_record;
    249       1.1  mrg   const unsigned char *p;
    250       1.1  mrg   _Unwind_Ptr landing_pad, ip;
    251       1.1  mrg   int handler_switch_value;
    252       1.1  mrg   int saw_cleanup = 0, saw_handler, foreign_exception;
    253       1.1  mrg   void *return_object;
    254       1.1  mrg   int ip_before_insn = 0;
    255       1.1  mrg 
    256       1.1  mrg #ifdef __ARM_EABI_UNWINDER__
    257       1.1  mrg   _Unwind_Action actions;
    258       1.1  mrg 
    259       1.1  mrg   switch (state & _US_ACTION_MASK)
    260       1.1  mrg     {
    261       1.1  mrg     case _US_VIRTUAL_UNWIND_FRAME:
    262       1.1  mrg       actions = _UA_SEARCH_PHASE;
    263       1.1  mrg       break;
    264       1.1  mrg 
    265       1.1  mrg     case _US_UNWIND_FRAME_STARTING:
    266       1.1  mrg       actions = _UA_CLEANUP_PHASE;
    267       1.1  mrg       if (!(state & _US_FORCE_UNWIND)
    268       1.1  mrg 	  && ue_header->barrier_cache.sp == _Unwind_GetGR (context, 13))
    269       1.1  mrg 	actions |= _UA_HANDLER_FRAME;
    270       1.1  mrg       break;
    271       1.1  mrg 
    272       1.1  mrg     case _US_UNWIND_FRAME_RESUME:
    273       1.1  mrg       CONTINUE_UNWINDING;
    274       1.1  mrg       break;
    275       1.1  mrg 
    276       1.1  mrg     default:
    277       1.1  mrg       abort();
    278       1.1  mrg     }
    279   1.1.1.2  mrg   actions |= state & _US_FORCE_UNWIND;
    280   1.1.1.2  mrg 
    281       1.1  mrg   /* TODO: Foreign exceptions need some attention (e.g. rethrowing
    282       1.1  mrg      doesn't work).  */
    283   1.1.1.2  mrg   foreign_exception = 0;
    284   1.1.1.2  mrg 
    285   1.1.1.2  mrg   /* The dwarf unwinder assumes the context structure holds things
    286   1.1.1.2  mrg      like the function and LSDA pointers.  The ARM implementation
    287       1.1  mrg      caches these in the exception header (UCB).  To avoid rewriting
    288       1.1  mrg      everything we make the virtual IP register point at the UCB.  */
    289       1.1  mrg   ip = (_Unwind_Ptr) ue_header;
    290       1.1  mrg   _Unwind_SetGR (context, 12, ip);
    291       1.1  mrg 
    292       1.1  mrg #else  /* !__ARM_EABI_UNWINDER.  */
    293       1.1  mrg   /* Interface version check.  */
    294       1.1  mrg   if (version != 1)
    295       1.1  mrg     return _URC_FATAL_PHASE1_ERROR;
    296       1.1  mrg 
    297       1.1  mrg   foreign_exception = (exception_class != __objc_exception_class);
    298       1.1  mrg #endif
    299       1.1  mrg 
    300       1.1  mrg   /* Shortcut for phase 2 found handler for domestic exception.  */
    301       1.1  mrg   if (actions == (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME)
    302       1.1  mrg       && !foreign_exception)
    303       1.1  mrg     {
    304       1.1  mrg #ifdef __ARM_EABI_UNWINDER__
    305       1.1  mrg       handler_switch_value = (int) ue_header->barrier_cache.bitpattern[1];
    306       1.1  mrg       landing_pad = (_Unwind_Ptr) ue_header->barrier_cache.bitpattern[3];
    307       1.1  mrg #else
    308       1.1  mrg       handler_switch_value = xh->handlerSwitchValue;
    309       1.1  mrg       landing_pad = xh->landingPad;
    310       1.1  mrg #endif
    311       1.1  mrg       goto install_context;
    312       1.1  mrg     }
    313       1.1  mrg 
    314       1.1  mrg   language_specific_data = (const unsigned char *)
    315       1.1  mrg     _Unwind_GetLanguageSpecificData (context);
    316       1.1  mrg 
    317       1.1  mrg   /* If no LSDA, then there are no handlers or cleanups.  */
    318       1.1  mrg   if (! language_specific_data)
    319       1.1  mrg     CONTINUE_UNWINDING;
    320       1.1  mrg 
    321       1.1  mrg   /* Parse the LSDA header.  */
    322       1.1  mrg   p = parse_lsda_header (context, language_specific_data, &info);
    323       1.1  mrg   info.ttype_base = base_of_encoded_value (info.ttype_encoding, context);
    324       1.1  mrg #ifdef HAVE_GETIPINFO
    325       1.1  mrg   ip = _Unwind_GetIPInfo (context, &ip_before_insn);
    326       1.1  mrg #else
    327       1.1  mrg   ip = _Unwind_GetIP (context);
    328       1.1  mrg #endif
    329       1.1  mrg   if (!ip_before_insn)
    330       1.1  mrg     --ip;
    331       1.1  mrg   landing_pad = 0;
    332       1.1  mrg   action_record = 0;
    333   1.1.1.4  mrg   handler_switch_value = 0;
    334       1.1  mrg 
    335       1.1  mrg #ifdef __USING_SJLJ_EXCEPTIONS__
    336   1.1.1.2  mrg   /* The given "IP" is an index into the call-site table, with two
    337   1.1.1.2  mrg      exceptions -- -1 means no-action, and 0 means terminate.  But
    338       1.1  mrg      since we're using uleb128 values, we've not got random access to
    339       1.1  mrg      the array.  */
    340       1.1  mrg   if ((int) ip < 0)
    341       1.1  mrg     return _URC_CONTINUE_UNWIND;
    342       1.1  mrg   else
    343       1.1  mrg     {
    344       1.1  mrg       _uleb128_t cs_lp, cs_action;
    345       1.1  mrg       do
    346       1.1  mrg 	{
    347       1.1  mrg 	  p = read_uleb128 (p, &cs_lp);
    348       1.1  mrg 	  p = read_uleb128 (p, &cs_action);
    349       1.1  mrg 	}
    350       1.1  mrg       while (--ip);
    351       1.1  mrg 
    352       1.1  mrg       /* Can never have null landing pad for sjlj -- that would have
    353       1.1  mrg          been indicated by a -1 call site index.  */
    354       1.1  mrg       landing_pad = cs_lp + 1;
    355       1.1  mrg       if (cs_action)
    356       1.1  mrg 	action_record = info.action_table + cs_action - 1;
    357       1.1  mrg       goto found_something;
    358   1.1.1.2  mrg     }
    359   1.1.1.2  mrg #else
    360       1.1  mrg   /* Search the call-site table for the action associated with this
    361       1.1  mrg      IP.  */
    362       1.1  mrg   while (p < info.action_table)
    363       1.1  mrg     {
    364       1.1  mrg       _Unwind_Ptr cs_start, cs_len, cs_lp;
    365   1.1.1.2  mrg       _uleb128_t cs_action;
    366   1.1.1.2  mrg 
    367       1.1  mrg       /* Note that all call-site encodings are "absolute"
    368       1.1  mrg 	 displacements.  */
    369       1.1  mrg       p = read_encoded_value (0, info.call_site_encoding, p, &cs_start);
    370       1.1  mrg       p = read_encoded_value (0, info.call_site_encoding, p, &cs_len);
    371       1.1  mrg       p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp);
    372       1.1  mrg       p = read_uleb128 (p, &cs_action);
    373       1.1  mrg 
    374       1.1  mrg       /* The table is sorted, so if we've passed the ip, stop.  */
    375       1.1  mrg       if (ip < info.Start + cs_start)
    376       1.1  mrg 	p = info.action_table;
    377       1.1  mrg       else if (ip < info.Start + cs_start + cs_len)
    378       1.1  mrg 	{
    379       1.1  mrg 	  if (cs_lp)
    380       1.1  mrg 	    landing_pad = info.LPStart + cs_lp;
    381       1.1  mrg 	  if (cs_action)
    382       1.1  mrg 	    action_record = info.action_table + cs_action - 1;
    383       1.1  mrg 	  goto found_something;
    384   1.1.1.4  mrg 	}
    385       1.1  mrg     }
    386       1.1  mrg #endif /* __USING_SJLJ_EXCEPTIONS__  */
    387   1.1.1.2  mrg 
    388   1.1.1.2  mrg   /* If ip is not present in the table, C++ would call terminate.  */
    389       1.1  mrg   /* ??? As with Java, it's perhaps better to tweek the LSDA to that
    390       1.1  mrg      no-action is mapped to no-entry.  */
    391       1.1  mrg   CONTINUE_UNWINDING;
    392       1.1  mrg 
    393       1.1  mrg  found_something:
    394       1.1  mrg   saw_cleanup = 0;
    395       1.1  mrg   saw_handler = 0;
    396       1.1  mrg 
    397   1.1.1.2  mrg   if (landing_pad == 0)
    398   1.1.1.2  mrg     {
    399       1.1  mrg       /* If ip is present, and has a null landing pad, there are no
    400       1.1  mrg 	 cleanups or handlers to be run.  */
    401       1.1  mrg     }
    402       1.1  mrg   else if (action_record == 0)
    403       1.1  mrg     {
    404       1.1  mrg       /* If ip is present, has a non-null landing pad, and a null
    405       1.1  mrg          action table offset, then there are only cleanups present.
    406       1.1  mrg          Cleanups use a zero switch value, as set above.  */
    407       1.1  mrg       saw_cleanup = 1;
    408       1.1  mrg     }
    409       1.1  mrg   else
    410       1.1  mrg     {
    411       1.1  mrg       /* Otherwise we have a catch handler.  */
    412       1.1  mrg       _sleb128_t ar_filter, ar_disp;
    413       1.1  mrg 
    414       1.1  mrg       while (1)
    415       1.1  mrg 	{
    416       1.1  mrg 	  p = action_record;
    417       1.1  mrg 	  p = read_sleb128 (p, &ar_filter);
    418       1.1  mrg 	  read_sleb128 (p, &ar_disp);
    419       1.1  mrg 
    420       1.1  mrg 	  if (ar_filter == 0)
    421       1.1  mrg 	    {
    422       1.1  mrg 	      /* Zero filter values are cleanups.  */
    423       1.1  mrg 	      saw_cleanup = 1;
    424       1.1  mrg 	    }
    425   1.1.1.2  mrg 
    426   1.1.1.2  mrg 	  /* During forced unwinding, we only run cleanups.  With a
    427       1.1  mrg 	     foreign exception class, we have no class info to
    428       1.1  mrg 	     match.  */
    429       1.1  mrg 	  else if ((actions & _UA_FORCE_UNWIND) || foreign_exception)
    430       1.1  mrg 	    ;
    431       1.1  mrg 
    432       1.1  mrg 	  else if (ar_filter > 0)
    433       1.1  mrg 	    {
    434       1.1  mrg 	      /* Positive filter values are handlers.  */
    435   1.1.1.2  mrg 	      Class catch_type = get_ttype_entry (&info, ar_filter);
    436       1.1  mrg 
    437       1.1  mrg 	      if ((*__objc_exception_matcher) (catch_type, xh->value))
    438       1.1  mrg 		{
    439       1.1  mrg 		  handler_switch_value = ar_filter;
    440       1.1  mrg 		  saw_handler = 1;
    441       1.1  mrg 		  break;
    442       1.1  mrg 		}
    443       1.1  mrg 	    }
    444       1.1  mrg 	  else
    445       1.1  mrg 	    {
    446       1.1  mrg 	      /* Negative filter values are exception specifications,
    447       1.1  mrg 	         which Objective-C does not use.  */
    448       1.1  mrg 	      abort ();
    449       1.1  mrg 	    }
    450       1.1  mrg 
    451       1.1  mrg 	  if (ar_disp == 0)
    452       1.1  mrg 	    break;
    453       1.1  mrg 	  action_record = p + ar_disp;
    454       1.1  mrg 	}
    455       1.1  mrg     }
    456       1.1  mrg 
    457       1.1  mrg   if (! saw_handler && ! saw_cleanup)
    458       1.1  mrg     CONTINUE_UNWINDING;
    459       1.1  mrg 
    460       1.1  mrg   if (actions & _UA_SEARCH_PHASE)
    461       1.1  mrg     {
    462       1.1  mrg       if (!saw_handler)
    463   1.1.1.2  mrg 	CONTINUE_UNWINDING;
    464   1.1.1.2  mrg 
    465       1.1  mrg       /* For domestic exceptions, we cache data from phase 1 for phase
    466       1.1  mrg 	 2.  */
    467       1.1  mrg       if (!foreign_exception)
    468       1.1  mrg         {
    469       1.1  mrg #ifdef __ARM_EABI_UNWINDER__
    470       1.1  mrg 	  ue_header->barrier_cache.sp = _Unwind_GetGR (context, 13);
    471       1.1  mrg 	  ue_header->barrier_cache.bitpattern[1] = (_uw) handler_switch_value;
    472       1.1  mrg 	  ue_header->barrier_cache.bitpattern[3] = (_uw) landing_pad;
    473       1.1  mrg #else
    474       1.1  mrg           xh->handlerSwitchValue = handler_switch_value;
    475       1.1  mrg           xh->landingPad = landing_pad;
    476       1.1  mrg #endif
    477       1.1  mrg 	}
    478       1.1  mrg       return _URC_HANDLER_FOUND;
    479       1.1  mrg     }
    480       1.1  mrg 
    481       1.1  mrg  install_context:
    482       1.1  mrg   if (saw_cleanup == 0)
    483       1.1  mrg     {
    484       1.1  mrg       return_object = xh->value;
    485       1.1  mrg       if (!(actions & _UA_SEARCH_PHASE))
    486       1.1  mrg 	_Unwind_DeleteException(&xh->base);
    487       1.1  mrg     }
    488       1.1  mrg 
    489       1.1  mrg   _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
    490       1.1  mrg 		 __builtin_extend_pointer (saw_cleanup ? xh : return_object));
    491       1.1  mrg   _Unwind_SetGR (context, __builtin_eh_return_data_regno (1),
    492       1.1  mrg 		 handler_switch_value);
    493       1.1  mrg   _Unwind_SetIP (context, landing_pad);
    494       1.1  mrg   return _URC_INSTALL_CONTEXT;
    495       1.1  mrg }
    496       1.1  mrg 
    497       1.1  mrg static void
    498       1.1  mrg __objc_exception_cleanup (_Unwind_Reason_Code code __attribute__((unused)),
    499       1.1  mrg 			  struct _Unwind_Exception *exc)
    500       1.1  mrg {
    501       1.1  mrg   free (exc);
    502       1.1  mrg }
    503   1.1.1.2  mrg 
    504       1.1  mrg void
    505       1.1  mrg objc_exception_throw (id exception)
    506   1.1.1.2  mrg {
    507       1.1  mrg   struct ObjcException *header = calloc (1, sizeof (*header));
    508       1.1  mrg 
    509       1.1  mrg   memcpy (&header->base.exception_class, &__objc_exception_class,
    510   1.1.1.2  mrg 	  sizeof (__objc_exception_class));
    511       1.1  mrg   header->base.exception_cleanup = __objc_exception_cleanup;
    512   1.1.1.4  mrg   header->value = exception;
    513       1.1  mrg 
    514       1.1  mrg #ifdef __USING_SJLJ_EXCEPTIONS__
    515       1.1  mrg   _Unwind_SjLj_RaiseException (&header->base);
    516       1.1  mrg #else
    517       1.1  mrg   _Unwind_RaiseException (&header->base);
    518   1.1.1.2  mrg #endif
    519   1.1.1.2  mrg 
    520   1.1.1.2  mrg   /* No exception handler was installed.  Call the uncaught exception
    521       1.1  mrg      handler if any is defined.  */
    522   1.1.1.2  mrg   if (__objc_uncaught_exception_handler != 0)
    523       1.1  mrg     {
    524   1.1.1.2  mrg       (*__objc_uncaught_exception_handler) (exception);
    525       1.1  mrg     }
    526       1.1  mrg 
    527   1.1.1.2  mrg   abort ();
    528   1.1.1.2  mrg }
    529   1.1.1.2  mrg 
    530   1.1.1.2  mrg #if defined (__SEH__) && !defined (__USING_SJLJ_EXCEPTIONS__)
    531   1.1.1.2  mrg EXCEPTION_DISPOSITION
    532   1.1.1.2  mrg __gnu_objc_personality_seh0 (PEXCEPTION_RECORD ms_exc, void *this_frame,
    533   1.1.1.2  mrg 			     PCONTEXT ms_orig_context,
    534   1.1.1.2  mrg 			     PDISPATCHER_CONTEXT ms_disp)
    535   1.1.1.2  mrg {
    536   1.1.1.2  mrg   return _GCC_specific_handler (ms_exc, this_frame, ms_orig_context,
    537   1.1.1.2  mrg 				ms_disp, __gnu_objc_personality_imp);
    538                }
    539                #endif
    540