xref: /netbsd-src/external/gpl3/gcc/dist/libobjc/exception.c (revision b1e838363e3c6fc78a55519254d99869742dd33c)
14fee23f9Smrg /* The implementation of exception handling primitives for Objective-C.
2*b1e83836Smrg    Copyright (C) 2004-2022 Free Software Foundation, Inc.
34fee23f9Smrg 
44fee23f9Smrg This file is part of GCC.
54fee23f9Smrg 
64fee23f9Smrg GCC is free software; you can redistribute it and/or modify it
74fee23f9Smrg under the terms of the GNU General Public License as published by the
84fee23f9Smrg Free Software Foundation; either version 3, or (at your option) any
94fee23f9Smrg later version.
104fee23f9Smrg 
114fee23f9Smrg GCC is distributed in the hope that it will be useful, but WITHOUT
124fee23f9Smrg ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
134fee23f9Smrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
144fee23f9Smrg License for more details.
154fee23f9Smrg 
164fee23f9Smrg Under Section 7 of GPL version 3, you are granted additional
174fee23f9Smrg permissions described in the GCC Runtime Library Exception, version
184fee23f9Smrg 3.1, as published by the Free Software Foundation.
194fee23f9Smrg 
204fee23f9Smrg You should have received a copy of the GNU General Public License and
214fee23f9Smrg a copy of the GCC Runtime Library Exception along with this program;
224fee23f9Smrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
234fee23f9Smrg <http://www.gnu.org/licenses/>.  */
244fee23f9Smrg 
2548fb7bfaSmrg #include "objc-private/common.h"
264fee23f9Smrg #include <stdlib.h>
274fee23f9Smrg #include "config.h"
2848fb7bfaSmrg #include "objc/runtime.h"
2948fb7bfaSmrg #include "objc/objc-exception.h"
304fee23f9Smrg #include "unwind.h"
314fee23f9Smrg #include "unwind-pe.h"
3248fb7bfaSmrg #include <string.h> /* For memcpy */
3348fb7bfaSmrg 
3448fb7bfaSmrg /* 'is_kind_of_exception_matcher' is our default exception matcher -
3548fb7bfaSmrg    it determines if the object 'exception' is of class 'catch_class',
3648fb7bfaSmrg    or of a subclass.  */
3748fb7bfaSmrg static int
is_kind_of_exception_matcher(Class catch_class,id exception)3848fb7bfaSmrg is_kind_of_exception_matcher (Class catch_class, id exception)
3948fb7bfaSmrg {
4048fb7bfaSmrg   /* NULL catch_class is catch-all (eg, @catch (id object)).  */
4148fb7bfaSmrg   if (catch_class == Nil)
4248fb7bfaSmrg     return 1;
4348fb7bfaSmrg 
4448fb7bfaSmrg   /* If exception is nil (eg, @throw nil;), then it can only be
4548fb7bfaSmrg      catched by a catch-all (eg, @catch (id object)).  */
4648fb7bfaSmrg   if (exception != nil)
4748fb7bfaSmrg     {
4848fb7bfaSmrg       Class c;
4948fb7bfaSmrg 
5048fb7bfaSmrg       for (c = exception->class_pointer; c != Nil;
5148fb7bfaSmrg 	   c = class_getSuperclass (c))
5248fb7bfaSmrg 	if (c == catch_class)
5348fb7bfaSmrg 	  return 1;
5448fb7bfaSmrg     }
5548fb7bfaSmrg   return 0;
5648fb7bfaSmrg }
5748fb7bfaSmrg 
5848fb7bfaSmrg /* The exception matcher currently in use.  */
5948fb7bfaSmrg static objc_exception_matcher
6048fb7bfaSmrg __objc_exception_matcher = is_kind_of_exception_matcher;
6148fb7bfaSmrg 
6248fb7bfaSmrg objc_exception_matcher
objc_setExceptionMatcher(objc_exception_matcher new_matcher)6348fb7bfaSmrg objc_setExceptionMatcher (objc_exception_matcher new_matcher)
6448fb7bfaSmrg {
6548fb7bfaSmrg   objc_exception_matcher old_matcher = __objc_exception_matcher;
6648fb7bfaSmrg   __objc_exception_matcher = new_matcher;
6748fb7bfaSmrg   return old_matcher;
6848fb7bfaSmrg }
6948fb7bfaSmrg 
7048fb7bfaSmrg /* The uncaught exception handler currently in use.  */
7148fb7bfaSmrg static objc_uncaught_exception_handler
7248fb7bfaSmrg __objc_uncaught_exception_handler = NULL;
7348fb7bfaSmrg 
7448fb7bfaSmrg objc_uncaught_exception_handler
objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler new_handler)7548fb7bfaSmrg objc_setUncaughtExceptionHandler (objc_uncaught_exception_handler
7648fb7bfaSmrg 				  new_handler)
7748fb7bfaSmrg {
7848fb7bfaSmrg   objc_uncaught_exception_handler old_handler
7948fb7bfaSmrg     = __objc_uncaught_exception_handler;
8048fb7bfaSmrg   __objc_uncaught_exception_handler = new_handler;
8148fb7bfaSmrg   return old_handler;
8248fb7bfaSmrg }
8348fb7bfaSmrg 
844fee23f9Smrg 
854fee23f9Smrg 
864fee23f9Smrg #ifdef __ARM_EABI_UNWINDER__
874fee23f9Smrg 
884fee23f9Smrg const _Unwind_Exception_Class __objc_exception_class
894fee23f9Smrg   = {'G', 'N', 'U', 'C', 'O', 'B', 'J', 'C'};
904fee23f9Smrg 
914fee23f9Smrg #else
924fee23f9Smrg 
934fee23f9Smrg /* This is the exception class we report -- "GNUCOBJC".  */
944fee23f9Smrg static const _Unwind_Exception_Class __objc_exception_class
954fee23f9Smrg   = ((((((((_Unwind_Exception_Class) 'G'
964fee23f9Smrg             << 8 | (_Unwind_Exception_Class) 'N')
974fee23f9Smrg            << 8 | (_Unwind_Exception_Class) 'U')
984fee23f9Smrg           << 8 | (_Unwind_Exception_Class) 'C')
994fee23f9Smrg          << 8 | (_Unwind_Exception_Class) 'O')
1004fee23f9Smrg         << 8 | (_Unwind_Exception_Class) 'B')
1014fee23f9Smrg        << 8 | (_Unwind_Exception_Class) 'J')
1024fee23f9Smrg       << 8 | (_Unwind_Exception_Class) 'C');
1034fee23f9Smrg 
1044fee23f9Smrg #endif
1054fee23f9Smrg 
1064fee23f9Smrg /* This is the object that is passed around by the Objective C runtime
1074fee23f9Smrg    to represent the exception in flight.  */
1084fee23f9Smrg struct ObjcException
1094fee23f9Smrg {
1104fee23f9Smrg   /* This bit is needed in order to interact with the unwind runtime.  */
1114fee23f9Smrg   struct _Unwind_Exception base;
1124fee23f9Smrg 
11348fb7bfaSmrg   /* The actual object we want to throw. Note: must come immediately
11448fb7bfaSmrg      after unwind header.  */
1154fee23f9Smrg   id value;
1164fee23f9Smrg 
1174fee23f9Smrg #ifdef __ARM_EABI_UNWINDER__
11848fb7bfaSmrg   /* Note: we use the barrier cache defined in the unwind control
11948fb7bfaSmrg      block for ARM EABI.  */
1204fee23f9Smrg #else
1214fee23f9Smrg   /* Cache some internal unwind data between phase 1 and phase 2.  */
1224fee23f9Smrg   _Unwind_Ptr landingPad;
1234fee23f9Smrg   int handlerSwitchValue;
1244fee23f9Smrg #endif
1254fee23f9Smrg };
1264fee23f9Smrg 
1274fee23f9Smrg 
1284fee23f9Smrg 
1294fee23f9Smrg struct lsda_header_info
1304fee23f9Smrg {
1314fee23f9Smrg   _Unwind_Ptr Start;
1324fee23f9Smrg   _Unwind_Ptr LPStart;
1334fee23f9Smrg   _Unwind_Ptr ttype_base;
1344fee23f9Smrg   const unsigned char *TType;
1354fee23f9Smrg   const unsigned char *action_table;
1364fee23f9Smrg   unsigned char ttype_encoding;
1374fee23f9Smrg   unsigned char call_site_encoding;
1384fee23f9Smrg };
1394fee23f9Smrg 
1404fee23f9Smrg static const unsigned char *
parse_lsda_header(struct _Unwind_Context * context,const unsigned char * p,struct lsda_header_info * info)1414fee23f9Smrg parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p,
1424fee23f9Smrg 		   struct lsda_header_info *info)
1434fee23f9Smrg {
1444fee23f9Smrg   _uleb128_t tmp;
1454fee23f9Smrg   unsigned char lpstart_encoding;
1464fee23f9Smrg 
1474fee23f9Smrg   info->Start = (context ? _Unwind_GetRegionStart (context) : 0);
1484fee23f9Smrg 
14948fb7bfaSmrg   /* Find @LPStart, the base to which landing pad offsets are
15048fb7bfaSmrg      relative.  */
1514fee23f9Smrg   lpstart_encoding = *p++;
1524fee23f9Smrg   if (lpstart_encoding != DW_EH_PE_omit)
1534fee23f9Smrg     p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart);
1544fee23f9Smrg   else
1554fee23f9Smrg     info->LPStart = info->Start;
1564fee23f9Smrg 
15748fb7bfaSmrg   /* Find @TType, the base of the handler and exception spec type
15848fb7bfaSmrg      data.  */
1594fee23f9Smrg   info->ttype_encoding = *p++;
1604fee23f9Smrg   if (info->ttype_encoding != DW_EH_PE_omit)
1614fee23f9Smrg     {
16248fb7bfaSmrg #if _GLIBCXX_OVERRIDE_TTYPE_ENCODING
16348fb7bfaSmrg       /* Older ARM EABI toolchains set this value incorrectly, so use a
16448fb7bfaSmrg 	 hardcoded OS-specific format.  */
16548fb7bfaSmrg       info->ttype_encoding = _GLIBCXX_OVERRIDE_TTYPE_ENCODING;
16648fb7bfaSmrg #endif
1674fee23f9Smrg       p = read_uleb128 (p, &tmp);
1684fee23f9Smrg       info->TType = p + tmp;
1694fee23f9Smrg     }
1704fee23f9Smrg   else
1714fee23f9Smrg     info->TType = 0;
1724fee23f9Smrg 
1734fee23f9Smrg   /* The encoding and length of the call-site table; the action table
1744fee23f9Smrg      immediately follows.  */
1754fee23f9Smrg   info->call_site_encoding = *p++;
1764fee23f9Smrg   p = read_uleb128 (p, &tmp);
1774fee23f9Smrg   info->action_table = p + tmp;
1784fee23f9Smrg 
1794fee23f9Smrg   return p;
1804fee23f9Smrg }
1814fee23f9Smrg 
1824fee23f9Smrg static Class
get_ttype_entry(struct lsda_header_info * info,_Unwind_Word i)1834fee23f9Smrg get_ttype_entry (struct lsda_header_info *info, _Unwind_Word i)
1844fee23f9Smrg {
1854fee23f9Smrg   _Unwind_Ptr ptr;
1864fee23f9Smrg 
1874fee23f9Smrg   i *= size_of_encoded_value (info->ttype_encoding);
1884fee23f9Smrg   read_encoded_value_with_base (info->ttype_encoding, info->ttype_base,
1894fee23f9Smrg 				info->TType - i, &ptr);
1904fee23f9Smrg 
19148fb7bfaSmrg   /* NULL ptr means catch-all.  Note that if the class is not found,
19248fb7bfaSmrg      this will abort the program.  */
1934fee23f9Smrg   if (ptr)
19448fb7bfaSmrg     return objc_getRequiredClass ((const char *) ptr);
1954fee23f9Smrg   else
1964fee23f9Smrg     return 0;
1974fee23f9Smrg }
1984fee23f9Smrg 
1994fee23f9Smrg /* Using a different personality function name causes link failures
20048fb7bfaSmrg    when trying to mix code using different exception handling
20148fb7bfaSmrg    models.  */
202f9a78e0eSmrg #ifdef __USING_SJLJ_EXCEPTIONS__
2034fee23f9Smrg #define PERSONALITY_FUNCTION	__gnu_objc_personality_sj0
2044fee23f9Smrg #define __builtin_eh_return_data_regno(x) x
205f9a78e0eSmrg #elif defined(__SEH__)
20648fb7bfaSmrg #define PERSONALITY_FUNCTION	__gnu_objc_personality_imp
2074fee23f9Smrg #else
2084fee23f9Smrg #define PERSONALITY_FUNCTION	__gnu_objc_personality_v0
2094fee23f9Smrg #endif
2104fee23f9Smrg 
2114fee23f9Smrg #ifdef __ARM_EABI_UNWINDER__
2124fee23f9Smrg 
2134fee23f9Smrg #define CONTINUE_UNWINDING \
2144fee23f9Smrg   do								\
2154fee23f9Smrg     {								\
2164fee23f9Smrg       if (__gnu_unwind_frame(ue_header, context) != _URC_OK)	\
2174fee23f9Smrg 	return _URC_FAILURE;					\
2184fee23f9Smrg       return _URC_CONTINUE_UNWIND;				\
2194fee23f9Smrg     }								\
2204fee23f9Smrg   while (0)
2214fee23f9Smrg 
2224fee23f9Smrg _Unwind_Reason_Code
223181254a7Smrg __attribute__((target ("general-regs-only")))
PERSONALITY_FUNCTION(_Unwind_State state,struct _Unwind_Exception * ue_header,struct _Unwind_Context * context)2244fee23f9Smrg PERSONALITY_FUNCTION (_Unwind_State state,
2254fee23f9Smrg 		      struct _Unwind_Exception *ue_header,
2264fee23f9Smrg 		      struct _Unwind_Context *context)
2274fee23f9Smrg #else
2284fee23f9Smrg 
2294fee23f9Smrg #define CONTINUE_UNWINDING return _URC_CONTINUE_UNWIND
2304fee23f9Smrg 
23148fb7bfaSmrg #if defined (__SEH__) && !defined (__USING_SJLJ_EXCEPTIONS__)
23248fb7bfaSmrg static
23348fb7bfaSmrg #endif
2344fee23f9Smrg _Unwind_Reason_Code
2354fee23f9Smrg PERSONALITY_FUNCTION (int version,
2364fee23f9Smrg 		      _Unwind_Action actions,
2374fee23f9Smrg 		      _Unwind_Exception_Class exception_class,
2384fee23f9Smrg 		      struct _Unwind_Exception *ue_header,
2394fee23f9Smrg 		      struct _Unwind_Context *context)
2404fee23f9Smrg #endif
2414fee23f9Smrg {
2424fee23f9Smrg   struct ObjcException *xh = (struct ObjcException *) ue_header;
2434fee23f9Smrg 
2444fee23f9Smrg   struct lsda_header_info info;
2454fee23f9Smrg   const unsigned char *language_specific_data;
2464fee23f9Smrg   const unsigned char *action_record;
2474fee23f9Smrg   const unsigned char *p;
2484fee23f9Smrg   _Unwind_Ptr landing_pad, ip;
2494fee23f9Smrg   int handler_switch_value;
2504fee23f9Smrg   int saw_cleanup = 0, saw_handler, foreign_exception;
2514fee23f9Smrg   void *return_object;
2524fee23f9Smrg   int ip_before_insn = 0;
2534fee23f9Smrg 
2544fee23f9Smrg #ifdef __ARM_EABI_UNWINDER__
2554fee23f9Smrg   _Unwind_Action actions;
2564fee23f9Smrg 
2574fee23f9Smrg   switch (state & _US_ACTION_MASK)
2584fee23f9Smrg     {
2594fee23f9Smrg     case _US_VIRTUAL_UNWIND_FRAME:
2604fee23f9Smrg       actions = _UA_SEARCH_PHASE;
2614fee23f9Smrg       break;
2624fee23f9Smrg 
2634fee23f9Smrg     case _US_UNWIND_FRAME_STARTING:
2644fee23f9Smrg       actions = _UA_CLEANUP_PHASE;
2654fee23f9Smrg       if (!(state & _US_FORCE_UNWIND)
2664fee23f9Smrg 	  && ue_header->barrier_cache.sp == _Unwind_GetGR (context, 13))
2674fee23f9Smrg 	actions |= _UA_HANDLER_FRAME;
2684fee23f9Smrg       break;
2694fee23f9Smrg 
2704fee23f9Smrg     case _US_UNWIND_FRAME_RESUME:
2714fee23f9Smrg       CONTINUE_UNWINDING;
2724fee23f9Smrg       break;
2734fee23f9Smrg 
2744fee23f9Smrg     default:
2754fee23f9Smrg       abort();
2764fee23f9Smrg     }
2774fee23f9Smrg   actions |= state & _US_FORCE_UNWIND;
2784fee23f9Smrg 
27948fb7bfaSmrg   /* TODO: Foreign exceptions need some attention (e.g. rethrowing
28048fb7bfaSmrg      doesn't work).  */
2814fee23f9Smrg   foreign_exception = 0;
2824fee23f9Smrg 
28348fb7bfaSmrg   /* The dwarf unwinder assumes the context structure holds things
28448fb7bfaSmrg      like the function and LSDA pointers.  The ARM implementation
28548fb7bfaSmrg      caches these in the exception header (UCB).  To avoid rewriting
28648fb7bfaSmrg      everything we make the virtual IP register point at the UCB.  */
2874fee23f9Smrg   ip = (_Unwind_Ptr) ue_header;
2884fee23f9Smrg   _Unwind_SetGR (context, 12, ip);
2894fee23f9Smrg 
2904fee23f9Smrg #else  /* !__ARM_EABI_UNWINDER.  */
2914fee23f9Smrg   /* Interface version check.  */
2924fee23f9Smrg   if (version != 1)
2934fee23f9Smrg     return _URC_FATAL_PHASE1_ERROR;
2944fee23f9Smrg 
2954fee23f9Smrg   foreign_exception = (exception_class != __objc_exception_class);
2964fee23f9Smrg #endif
2974fee23f9Smrg 
2984fee23f9Smrg   /* Shortcut for phase 2 found handler for domestic exception.  */
2994fee23f9Smrg   if (actions == (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME)
3004fee23f9Smrg       && !foreign_exception)
3014fee23f9Smrg     {
3024fee23f9Smrg #ifdef __ARM_EABI_UNWINDER__
3034fee23f9Smrg       handler_switch_value = (int) ue_header->barrier_cache.bitpattern[1];
3044fee23f9Smrg       landing_pad = (_Unwind_Ptr) ue_header->barrier_cache.bitpattern[3];
3054fee23f9Smrg #else
3064fee23f9Smrg       handler_switch_value = xh->handlerSwitchValue;
3074fee23f9Smrg       landing_pad = xh->landingPad;
3084fee23f9Smrg #endif
3094fee23f9Smrg       goto install_context;
3104fee23f9Smrg     }
3114fee23f9Smrg 
3124fee23f9Smrg   language_specific_data = (const unsigned char *)
3134fee23f9Smrg     _Unwind_GetLanguageSpecificData (context);
3144fee23f9Smrg 
3154fee23f9Smrg   /* If no LSDA, then there are no handlers or cleanups.  */
3164fee23f9Smrg   if (! language_specific_data)
3174fee23f9Smrg     CONTINUE_UNWINDING;
3184fee23f9Smrg 
3194fee23f9Smrg   /* Parse the LSDA header.  */
3204fee23f9Smrg   p = parse_lsda_header (context, language_specific_data, &info);
3214fee23f9Smrg   info.ttype_base = base_of_encoded_value (info.ttype_encoding, context);
3224fee23f9Smrg #ifdef HAVE_GETIPINFO
3234fee23f9Smrg   ip = _Unwind_GetIPInfo (context, &ip_before_insn);
3244fee23f9Smrg #else
3254fee23f9Smrg   ip = _Unwind_GetIP (context);
3264fee23f9Smrg #endif
3274fee23f9Smrg   if (!ip_before_insn)
3284fee23f9Smrg     --ip;
3294fee23f9Smrg   landing_pad = 0;
3304fee23f9Smrg   action_record = 0;
3314fee23f9Smrg   handler_switch_value = 0;
3324fee23f9Smrg 
333f9a78e0eSmrg #ifdef __USING_SJLJ_EXCEPTIONS__
3344fee23f9Smrg   /* The given "IP" is an index into the call-site table, with two
3354fee23f9Smrg      exceptions -- -1 means no-action, and 0 means terminate.  But
33648fb7bfaSmrg      since we're using uleb128 values, we've not got random access to
33748fb7bfaSmrg      the array.  */
3384fee23f9Smrg   if ((int) ip < 0)
3394fee23f9Smrg     return _URC_CONTINUE_UNWIND;
3404fee23f9Smrg   else
3414fee23f9Smrg     {
3424fee23f9Smrg       _uleb128_t cs_lp, cs_action;
3434fee23f9Smrg       do
3444fee23f9Smrg 	{
3454fee23f9Smrg 	  p = read_uleb128 (p, &cs_lp);
3464fee23f9Smrg 	  p = read_uleb128 (p, &cs_action);
3474fee23f9Smrg 	}
3484fee23f9Smrg       while (--ip);
3494fee23f9Smrg 
3504fee23f9Smrg       /* Can never have null landing pad for sjlj -- that would have
3514fee23f9Smrg          been indicated by a -1 call site index.  */
3524fee23f9Smrg       landing_pad = cs_lp + 1;
3534fee23f9Smrg       if (cs_action)
3544fee23f9Smrg 	action_record = info.action_table + cs_action - 1;
3554fee23f9Smrg       goto found_something;
3564fee23f9Smrg     }
3574fee23f9Smrg #else
35848fb7bfaSmrg   /* Search the call-site table for the action associated with this
35948fb7bfaSmrg      IP.  */
3604fee23f9Smrg   while (p < info.action_table)
3614fee23f9Smrg     {
3624fee23f9Smrg       _Unwind_Ptr cs_start, cs_len, cs_lp;
3634fee23f9Smrg       _uleb128_t cs_action;
3644fee23f9Smrg 
36548fb7bfaSmrg       /* Note that all call-site encodings are "absolute"
36648fb7bfaSmrg 	 displacements.  */
3674fee23f9Smrg       p = read_encoded_value (0, info.call_site_encoding, p, &cs_start);
3684fee23f9Smrg       p = read_encoded_value (0, info.call_site_encoding, p, &cs_len);
3694fee23f9Smrg       p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp);
3704fee23f9Smrg       p = read_uleb128 (p, &cs_action);
3714fee23f9Smrg 
3724fee23f9Smrg       /* The table is sorted, so if we've passed the ip, stop.  */
3734fee23f9Smrg       if (ip < info.Start + cs_start)
3744fee23f9Smrg 	p = info.action_table;
3754fee23f9Smrg       else if (ip < info.Start + cs_start + cs_len)
3764fee23f9Smrg 	{
3774fee23f9Smrg 	  if (cs_lp)
3784fee23f9Smrg 	    landing_pad = info.LPStart + cs_lp;
3794fee23f9Smrg 	  if (cs_action)
3804fee23f9Smrg 	    action_record = info.action_table + cs_action - 1;
3814fee23f9Smrg 	  goto found_something;
3824fee23f9Smrg 	}
3834fee23f9Smrg     }
384f9a78e0eSmrg #endif /* __USING_SJLJ_EXCEPTIONS__  */
3854fee23f9Smrg 
3864fee23f9Smrg   /* If ip is not present in the table, C++ would call terminate.  */
38748fb7bfaSmrg   /* ??? As with Java, it's perhaps better to tweek the LSDA to that
38848fb7bfaSmrg      no-action is mapped to no-entry.  */
3894fee23f9Smrg   CONTINUE_UNWINDING;
3904fee23f9Smrg 
3914fee23f9Smrg  found_something:
3924fee23f9Smrg   saw_cleanup = 0;
3934fee23f9Smrg   saw_handler = 0;
3944fee23f9Smrg 
3954fee23f9Smrg   if (landing_pad == 0)
3964fee23f9Smrg     {
39748fb7bfaSmrg       /* If ip is present, and has a null landing pad, there are no
39848fb7bfaSmrg 	 cleanups or handlers to be run.  */
3994fee23f9Smrg     }
4004fee23f9Smrg   else if (action_record == 0)
4014fee23f9Smrg     {
4024fee23f9Smrg       /* If ip is present, has a non-null landing pad, and a null
4034fee23f9Smrg          action table offset, then there are only cleanups present.
4044fee23f9Smrg          Cleanups use a zero switch value, as set above.  */
4054fee23f9Smrg       saw_cleanup = 1;
4064fee23f9Smrg     }
4074fee23f9Smrg   else
4084fee23f9Smrg     {
4094fee23f9Smrg       /* Otherwise we have a catch handler.  */
4104fee23f9Smrg       _sleb128_t ar_filter, ar_disp;
4114fee23f9Smrg 
4124fee23f9Smrg       while (1)
4134fee23f9Smrg 	{
4144fee23f9Smrg 	  p = action_record;
4154fee23f9Smrg 	  p = read_sleb128 (p, &ar_filter);
4164fee23f9Smrg 	  read_sleb128 (p, &ar_disp);
4174fee23f9Smrg 
4184fee23f9Smrg 	  if (ar_filter == 0)
4194fee23f9Smrg 	    {
4204fee23f9Smrg 	      /* Zero filter values are cleanups.  */
4214fee23f9Smrg 	      saw_cleanup = 1;
4224fee23f9Smrg 	    }
4234fee23f9Smrg 
4244fee23f9Smrg 	  /* During forced unwinding, we only run cleanups.  With a
42548fb7bfaSmrg 	     foreign exception class, we have no class info to
42648fb7bfaSmrg 	     match.  */
4274fee23f9Smrg 	  else if ((actions & _UA_FORCE_UNWIND) || foreign_exception)
4284fee23f9Smrg 	    ;
4294fee23f9Smrg 
4304fee23f9Smrg 	  else if (ar_filter > 0)
4314fee23f9Smrg 	    {
4324fee23f9Smrg 	      /* Positive filter values are handlers.  */
4334fee23f9Smrg 	      Class catch_type = get_ttype_entry (&info, ar_filter);
4344fee23f9Smrg 
43548fb7bfaSmrg 	      if ((*__objc_exception_matcher) (catch_type, xh->value))
4364fee23f9Smrg 		{
4374fee23f9Smrg 		  handler_switch_value = ar_filter;
4384fee23f9Smrg 		  saw_handler = 1;
4394fee23f9Smrg 		  break;
4404fee23f9Smrg 		}
4414fee23f9Smrg 	    }
4424fee23f9Smrg 	  else
4434fee23f9Smrg 	    {
4444fee23f9Smrg 	      /* Negative filter values are exception specifications,
4454fee23f9Smrg 	         which Objective-C does not use.  */
4464fee23f9Smrg 	      abort ();
4474fee23f9Smrg 	    }
4484fee23f9Smrg 
4494fee23f9Smrg 	  if (ar_disp == 0)
4504fee23f9Smrg 	    break;
4514fee23f9Smrg 	  action_record = p + ar_disp;
4524fee23f9Smrg 	}
4534fee23f9Smrg     }
4544fee23f9Smrg 
4554fee23f9Smrg   if (! saw_handler && ! saw_cleanup)
4564fee23f9Smrg     CONTINUE_UNWINDING;
4574fee23f9Smrg 
4584fee23f9Smrg   if (actions & _UA_SEARCH_PHASE)
4594fee23f9Smrg     {
4604fee23f9Smrg       if (!saw_handler)
4614fee23f9Smrg 	CONTINUE_UNWINDING;
4624fee23f9Smrg 
46348fb7bfaSmrg       /* For domestic exceptions, we cache data from phase 1 for phase
46448fb7bfaSmrg 	 2.  */
4654fee23f9Smrg       if (!foreign_exception)
4664fee23f9Smrg         {
4674fee23f9Smrg #ifdef __ARM_EABI_UNWINDER__
4684fee23f9Smrg 	  ue_header->barrier_cache.sp = _Unwind_GetGR (context, 13);
4694fee23f9Smrg 	  ue_header->barrier_cache.bitpattern[1] = (_uw) handler_switch_value;
4704fee23f9Smrg 	  ue_header->barrier_cache.bitpattern[3] = (_uw) landing_pad;
4714fee23f9Smrg #else
4724fee23f9Smrg           xh->handlerSwitchValue = handler_switch_value;
4734fee23f9Smrg           xh->landingPad = landing_pad;
4744fee23f9Smrg #endif
4754fee23f9Smrg 	}
4764fee23f9Smrg       return _URC_HANDLER_FOUND;
4774fee23f9Smrg     }
4784fee23f9Smrg 
4794fee23f9Smrg  install_context:
4804fee23f9Smrg   if (saw_cleanup == 0)
4814fee23f9Smrg     {
4824fee23f9Smrg       return_object = xh->value;
4834fee23f9Smrg       if (!(actions & _UA_SEARCH_PHASE))
4844fee23f9Smrg 	_Unwind_DeleteException(&xh->base);
4854fee23f9Smrg     }
4864fee23f9Smrg 
4874fee23f9Smrg   _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
4884fee23f9Smrg 		 __builtin_extend_pointer (saw_cleanup ? xh : return_object));
4894fee23f9Smrg   _Unwind_SetGR (context, __builtin_eh_return_data_regno (1),
4904fee23f9Smrg 		 handler_switch_value);
4914fee23f9Smrg   _Unwind_SetIP (context, landing_pad);
4924fee23f9Smrg   return _URC_INSTALL_CONTEXT;
4934fee23f9Smrg }
4944fee23f9Smrg 
4954fee23f9Smrg static void
__objc_exception_cleanup(_Unwind_Reason_Code code,struct _Unwind_Exception * exc)4964fee23f9Smrg __objc_exception_cleanup (_Unwind_Reason_Code code __attribute__((unused)),
4974fee23f9Smrg 			  struct _Unwind_Exception *exc)
4984fee23f9Smrg {
4994fee23f9Smrg   free (exc);
5004fee23f9Smrg }
5014fee23f9Smrg 
5024fee23f9Smrg void
objc_exception_throw(id exception)50348fb7bfaSmrg objc_exception_throw (id exception)
5044fee23f9Smrg {
5054fee23f9Smrg   struct ObjcException *header = calloc (1, sizeof (*header));
5064fee23f9Smrg 
5074fee23f9Smrg   memcpy (&header->base.exception_class, &__objc_exception_class,
5084fee23f9Smrg 	  sizeof (__objc_exception_class));
5094fee23f9Smrg   header->base.exception_cleanup = __objc_exception_cleanup;
51048fb7bfaSmrg   header->value = exception;
5114fee23f9Smrg 
512f9a78e0eSmrg #ifdef __USING_SJLJ_EXCEPTIONS__
5134fee23f9Smrg   _Unwind_SjLj_RaiseException (&header->base);
5144fee23f9Smrg #else
5154fee23f9Smrg   _Unwind_RaiseException (&header->base);
5164fee23f9Smrg #endif
5174fee23f9Smrg 
51848fb7bfaSmrg   /* No exception handler was installed.  Call the uncaught exception
51948fb7bfaSmrg      handler if any is defined.  */
52048fb7bfaSmrg   if (__objc_uncaught_exception_handler != 0)
5214fee23f9Smrg     {
52248fb7bfaSmrg       (*__objc_uncaught_exception_handler) (exception);
5234fee23f9Smrg     }
52448fb7bfaSmrg 
5254fee23f9Smrg   abort ();
5264fee23f9Smrg }
52748fb7bfaSmrg 
52848fb7bfaSmrg #if defined (__SEH__) && !defined (__USING_SJLJ_EXCEPTIONS__)
52948fb7bfaSmrg EXCEPTION_DISPOSITION
__gnu_objc_personality_seh0(PEXCEPTION_RECORD ms_exc,void * this_frame,PCONTEXT ms_orig_context,PDISPATCHER_CONTEXT ms_disp)53048fb7bfaSmrg __gnu_objc_personality_seh0 (PEXCEPTION_RECORD ms_exc, void *this_frame,
53148fb7bfaSmrg 			     PCONTEXT ms_orig_context,
53248fb7bfaSmrg 			     PDISPATCHER_CONTEXT ms_disp)
53348fb7bfaSmrg {
53448fb7bfaSmrg   return _GCC_specific_handler (ms_exc, this_frame, ms_orig_context,
53548fb7bfaSmrg 				ms_disp, __gnu_objc_personality_imp);
53648fb7bfaSmrg }
53748fb7bfaSmrg #endif
538