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