136ac495dSmrg /* The implementation of exception handling primitives for Objective-C.
2*8feb0f0bSmrg Copyright (C) 2004-2020 Free Software Foundation, Inc.
336ac495dSmrg
436ac495dSmrg This file is part of GCC.
536ac495dSmrg
636ac495dSmrg GCC is free software; you can redistribute it and/or modify it
736ac495dSmrg under the terms of the GNU General Public License as published by the
836ac495dSmrg Free Software Foundation; either version 3, or (at your option) any
936ac495dSmrg later version.
1036ac495dSmrg
1136ac495dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT
1236ac495dSmrg ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1336ac495dSmrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
1436ac495dSmrg License for more details.
1536ac495dSmrg
1636ac495dSmrg Under Section 7 of GPL version 3, you are granted additional
1736ac495dSmrg permissions described in the GCC Runtime Library Exception, version
1836ac495dSmrg 3.1, as published by the Free Software Foundation.
1936ac495dSmrg
2036ac495dSmrg You should have received a copy of the GNU General Public License and
2136ac495dSmrg a copy of the GCC Runtime Library Exception along with this program;
2236ac495dSmrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
2336ac495dSmrg <http://www.gnu.org/licenses/>. */
2436ac495dSmrg
2536ac495dSmrg #include "objc-private/common.h"
2636ac495dSmrg #include <stdlib.h>
2736ac495dSmrg #include "config.h"
2836ac495dSmrg #include "objc/runtime.h"
2936ac495dSmrg #include "objc/objc-exception.h"
3036ac495dSmrg #include "unwind.h"
3136ac495dSmrg #include "unwind-pe.h"
3236ac495dSmrg #include <string.h> /* For memcpy */
3336ac495dSmrg
3436ac495dSmrg /* 'is_kind_of_exception_matcher' is our default exception matcher -
3536ac495dSmrg it determines if the object 'exception' is of class 'catch_class',
3636ac495dSmrg or of a subclass. */
3736ac495dSmrg static int
is_kind_of_exception_matcher(Class catch_class,id exception)3836ac495dSmrg is_kind_of_exception_matcher (Class catch_class, id exception)
3936ac495dSmrg {
4036ac495dSmrg /* NULL catch_class is catch-all (eg, @catch (id object)). */
4136ac495dSmrg if (catch_class == Nil)
4236ac495dSmrg return 1;
4336ac495dSmrg
4436ac495dSmrg /* If exception is nil (eg, @throw nil;), then it can only be
4536ac495dSmrg catched by a catch-all (eg, @catch (id object)). */
4636ac495dSmrg if (exception != nil)
4736ac495dSmrg {
4836ac495dSmrg Class c;
4936ac495dSmrg
5036ac495dSmrg for (c = exception->class_pointer; c != Nil;
5136ac495dSmrg c = class_getSuperclass (c))
5236ac495dSmrg if (c == catch_class)
5336ac495dSmrg return 1;
5436ac495dSmrg }
5536ac495dSmrg return 0;
5636ac495dSmrg }
5736ac495dSmrg
5836ac495dSmrg /* The exception matcher currently in use. */
5936ac495dSmrg static objc_exception_matcher
6036ac495dSmrg __objc_exception_matcher = is_kind_of_exception_matcher;
6136ac495dSmrg
6236ac495dSmrg objc_exception_matcher
objc_setExceptionMatcher(objc_exception_matcher new_matcher)6336ac495dSmrg objc_setExceptionMatcher (objc_exception_matcher new_matcher)
6436ac495dSmrg {
6536ac495dSmrg objc_exception_matcher old_matcher = __objc_exception_matcher;
6636ac495dSmrg __objc_exception_matcher = new_matcher;
6736ac495dSmrg return old_matcher;
6836ac495dSmrg }
6936ac495dSmrg
7036ac495dSmrg /* The uncaught exception handler currently in use. */
7136ac495dSmrg static objc_uncaught_exception_handler
7236ac495dSmrg __objc_uncaught_exception_handler = NULL;
7336ac495dSmrg
7436ac495dSmrg objc_uncaught_exception_handler
objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler new_handler)7536ac495dSmrg objc_setUncaughtExceptionHandler (objc_uncaught_exception_handler
7636ac495dSmrg new_handler)
7736ac495dSmrg {
7836ac495dSmrg objc_uncaught_exception_handler old_handler
7936ac495dSmrg = __objc_uncaught_exception_handler;
8036ac495dSmrg __objc_uncaught_exception_handler = new_handler;
8136ac495dSmrg return old_handler;
8236ac495dSmrg }
8336ac495dSmrg
8436ac495dSmrg
8536ac495dSmrg
8636ac495dSmrg #ifdef __ARM_EABI_UNWINDER__
8736ac495dSmrg
8836ac495dSmrg const _Unwind_Exception_Class __objc_exception_class
8936ac495dSmrg = {'G', 'N', 'U', 'C', 'O', 'B', 'J', 'C'};
9036ac495dSmrg
9136ac495dSmrg #else
9236ac495dSmrg
9336ac495dSmrg /* This is the exception class we report -- "GNUCOBJC". */
9436ac495dSmrg static const _Unwind_Exception_Class __objc_exception_class
9536ac495dSmrg = ((((((((_Unwind_Exception_Class) 'G'
9636ac495dSmrg << 8 | (_Unwind_Exception_Class) 'N')
9736ac495dSmrg << 8 | (_Unwind_Exception_Class) 'U')
9836ac495dSmrg << 8 | (_Unwind_Exception_Class) 'C')
9936ac495dSmrg << 8 | (_Unwind_Exception_Class) 'O')
10036ac495dSmrg << 8 | (_Unwind_Exception_Class) 'B')
10136ac495dSmrg << 8 | (_Unwind_Exception_Class) 'J')
10236ac495dSmrg << 8 | (_Unwind_Exception_Class) 'C');
10336ac495dSmrg
10436ac495dSmrg #endif
10536ac495dSmrg
10636ac495dSmrg /* This is the object that is passed around by the Objective C runtime
10736ac495dSmrg to represent the exception in flight. */
10836ac495dSmrg struct ObjcException
10936ac495dSmrg {
11036ac495dSmrg /* This bit is needed in order to interact with the unwind runtime. */
11136ac495dSmrg struct _Unwind_Exception base;
11236ac495dSmrg
11336ac495dSmrg /* The actual object we want to throw. Note: must come immediately
11436ac495dSmrg after unwind header. */
11536ac495dSmrg id value;
11636ac495dSmrg
11736ac495dSmrg #ifdef __ARM_EABI_UNWINDER__
11836ac495dSmrg /* Note: we use the barrier cache defined in the unwind control
11936ac495dSmrg block for ARM EABI. */
12036ac495dSmrg #else
12136ac495dSmrg /* Cache some internal unwind data between phase 1 and phase 2. */
12236ac495dSmrg _Unwind_Ptr landingPad;
12336ac495dSmrg int handlerSwitchValue;
12436ac495dSmrg #endif
12536ac495dSmrg };
12636ac495dSmrg
12736ac495dSmrg
12836ac495dSmrg
12936ac495dSmrg struct lsda_header_info
13036ac495dSmrg {
13136ac495dSmrg _Unwind_Ptr Start;
13236ac495dSmrg _Unwind_Ptr LPStart;
13336ac495dSmrg _Unwind_Ptr ttype_base;
13436ac495dSmrg const unsigned char *TType;
13536ac495dSmrg const unsigned char *action_table;
13636ac495dSmrg unsigned char ttype_encoding;
13736ac495dSmrg unsigned char call_site_encoding;
13836ac495dSmrg };
13936ac495dSmrg
14036ac495dSmrg static const unsigned char *
parse_lsda_header(struct _Unwind_Context * context,const unsigned char * p,struct lsda_header_info * info)14136ac495dSmrg parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p,
14236ac495dSmrg struct lsda_header_info *info)
14336ac495dSmrg {
14436ac495dSmrg _uleb128_t tmp;
14536ac495dSmrg unsigned char lpstart_encoding;
14636ac495dSmrg
14736ac495dSmrg info->Start = (context ? _Unwind_GetRegionStart (context) : 0);
14836ac495dSmrg
14936ac495dSmrg /* Find @LPStart, the base to which landing pad offsets are
15036ac495dSmrg relative. */
15136ac495dSmrg lpstart_encoding = *p++;
15236ac495dSmrg if (lpstart_encoding != DW_EH_PE_omit)
15336ac495dSmrg p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart);
15436ac495dSmrg else
15536ac495dSmrg info->LPStart = info->Start;
15636ac495dSmrg
15736ac495dSmrg /* Find @TType, the base of the handler and exception spec type
15836ac495dSmrg data. */
15936ac495dSmrg info->ttype_encoding = *p++;
16036ac495dSmrg if (info->ttype_encoding != DW_EH_PE_omit)
16136ac495dSmrg {
16236ac495dSmrg #if _GLIBCXX_OVERRIDE_TTYPE_ENCODING
16336ac495dSmrg /* Older ARM EABI toolchains set this value incorrectly, so use a
16436ac495dSmrg hardcoded OS-specific format. */
16536ac495dSmrg info->ttype_encoding = _GLIBCXX_OVERRIDE_TTYPE_ENCODING;
16636ac495dSmrg #endif
16736ac495dSmrg p = read_uleb128 (p, &tmp);
16836ac495dSmrg info->TType = p + tmp;
16936ac495dSmrg }
17036ac495dSmrg else
17136ac495dSmrg info->TType = 0;
17236ac495dSmrg
17336ac495dSmrg /* The encoding and length of the call-site table; the action table
17436ac495dSmrg immediately follows. */
17536ac495dSmrg info->call_site_encoding = *p++;
17636ac495dSmrg p = read_uleb128 (p, &tmp);
17736ac495dSmrg info->action_table = p + tmp;
17836ac495dSmrg
17936ac495dSmrg return p;
18036ac495dSmrg }
18136ac495dSmrg
18236ac495dSmrg static Class
get_ttype_entry(struct lsda_header_info * info,_Unwind_Word i)18336ac495dSmrg get_ttype_entry (struct lsda_header_info *info, _Unwind_Word i)
18436ac495dSmrg {
18536ac495dSmrg _Unwind_Ptr ptr;
18636ac495dSmrg
18736ac495dSmrg i *= size_of_encoded_value (info->ttype_encoding);
18836ac495dSmrg read_encoded_value_with_base (info->ttype_encoding, info->ttype_base,
18936ac495dSmrg info->TType - i, &ptr);
19036ac495dSmrg
19136ac495dSmrg /* NULL ptr means catch-all. Note that if the class is not found,
19236ac495dSmrg this will abort the program. */
19336ac495dSmrg if (ptr)
19436ac495dSmrg return objc_getRequiredClass ((const char *) ptr);
19536ac495dSmrg else
19636ac495dSmrg return 0;
19736ac495dSmrg }
19836ac495dSmrg
19936ac495dSmrg /* Using a different personality function name causes link failures
20036ac495dSmrg when trying to mix code using different exception handling
20136ac495dSmrg models. */
20236ac495dSmrg #ifdef __USING_SJLJ_EXCEPTIONS__
20336ac495dSmrg #define PERSONALITY_FUNCTION __gnu_objc_personality_sj0
20436ac495dSmrg #define __builtin_eh_return_data_regno(x) x
20536ac495dSmrg #elif defined(__SEH__)
20636ac495dSmrg #define PERSONALITY_FUNCTION __gnu_objc_personality_imp
20736ac495dSmrg #else
20836ac495dSmrg #define PERSONALITY_FUNCTION __gnu_objc_personality_v0
20936ac495dSmrg #endif
21036ac495dSmrg
21136ac495dSmrg #ifdef __ARM_EABI_UNWINDER__
21236ac495dSmrg
21336ac495dSmrg #define CONTINUE_UNWINDING \
21436ac495dSmrg do \
21536ac495dSmrg { \
21636ac495dSmrg if (__gnu_unwind_frame(ue_header, context) != _URC_OK) \
21736ac495dSmrg return _URC_FAILURE; \
21836ac495dSmrg return _URC_CONTINUE_UNWIND; \
21936ac495dSmrg } \
22036ac495dSmrg while (0)
22136ac495dSmrg
22236ac495dSmrg _Unwind_Reason_Code
223c0a68be4Smrg __attribute__((target ("general-regs-only")))
PERSONALITY_FUNCTION(_Unwind_State state,struct _Unwind_Exception * ue_header,struct _Unwind_Context * context)22436ac495dSmrg PERSONALITY_FUNCTION (_Unwind_State state,
22536ac495dSmrg struct _Unwind_Exception *ue_header,
22636ac495dSmrg struct _Unwind_Context *context)
22736ac495dSmrg #else
22836ac495dSmrg
22936ac495dSmrg #define CONTINUE_UNWINDING return _URC_CONTINUE_UNWIND
23036ac495dSmrg
23136ac495dSmrg #if defined (__SEH__) && !defined (__USING_SJLJ_EXCEPTIONS__)
23236ac495dSmrg static
23336ac495dSmrg #endif
23436ac495dSmrg _Unwind_Reason_Code
23536ac495dSmrg PERSONALITY_FUNCTION (int version,
23636ac495dSmrg _Unwind_Action actions,
23736ac495dSmrg _Unwind_Exception_Class exception_class,
23836ac495dSmrg struct _Unwind_Exception *ue_header,
23936ac495dSmrg struct _Unwind_Context *context)
24036ac495dSmrg #endif
24136ac495dSmrg {
24236ac495dSmrg struct ObjcException *xh = (struct ObjcException *) ue_header;
24336ac495dSmrg
24436ac495dSmrg struct lsda_header_info info;
24536ac495dSmrg const unsigned char *language_specific_data;
24636ac495dSmrg const unsigned char *action_record;
24736ac495dSmrg const unsigned char *p;
24836ac495dSmrg _Unwind_Ptr landing_pad, ip;
24936ac495dSmrg int handler_switch_value;
25036ac495dSmrg int saw_cleanup = 0, saw_handler, foreign_exception;
25136ac495dSmrg void *return_object;
25236ac495dSmrg int ip_before_insn = 0;
25336ac495dSmrg
25436ac495dSmrg #ifdef __ARM_EABI_UNWINDER__
25536ac495dSmrg _Unwind_Action actions;
25636ac495dSmrg
25736ac495dSmrg switch (state & _US_ACTION_MASK)
25836ac495dSmrg {
25936ac495dSmrg case _US_VIRTUAL_UNWIND_FRAME:
26036ac495dSmrg actions = _UA_SEARCH_PHASE;
26136ac495dSmrg break;
26236ac495dSmrg
26336ac495dSmrg case _US_UNWIND_FRAME_STARTING:
26436ac495dSmrg actions = _UA_CLEANUP_PHASE;
26536ac495dSmrg if (!(state & _US_FORCE_UNWIND)
26636ac495dSmrg && ue_header->barrier_cache.sp == _Unwind_GetGR (context, 13))
26736ac495dSmrg actions |= _UA_HANDLER_FRAME;
26836ac495dSmrg break;
26936ac495dSmrg
27036ac495dSmrg case _US_UNWIND_FRAME_RESUME:
27136ac495dSmrg CONTINUE_UNWINDING;
27236ac495dSmrg break;
27336ac495dSmrg
27436ac495dSmrg default:
27536ac495dSmrg abort();
27636ac495dSmrg }
27736ac495dSmrg actions |= state & _US_FORCE_UNWIND;
27836ac495dSmrg
27936ac495dSmrg /* TODO: Foreign exceptions need some attention (e.g. rethrowing
28036ac495dSmrg doesn't work). */
28136ac495dSmrg foreign_exception = 0;
28236ac495dSmrg
28336ac495dSmrg /* The dwarf unwinder assumes the context structure holds things
28436ac495dSmrg like the function and LSDA pointers. The ARM implementation
28536ac495dSmrg caches these in the exception header (UCB). To avoid rewriting
28636ac495dSmrg everything we make the virtual IP register point at the UCB. */
28736ac495dSmrg ip = (_Unwind_Ptr) ue_header;
28836ac495dSmrg _Unwind_SetGR (context, 12, ip);
28936ac495dSmrg
29036ac495dSmrg #else /* !__ARM_EABI_UNWINDER. */
29136ac495dSmrg /* Interface version check. */
29236ac495dSmrg if (version != 1)
29336ac495dSmrg return _URC_FATAL_PHASE1_ERROR;
29436ac495dSmrg
29536ac495dSmrg foreign_exception = (exception_class != __objc_exception_class);
29636ac495dSmrg #endif
29736ac495dSmrg
29836ac495dSmrg /* Shortcut for phase 2 found handler for domestic exception. */
29936ac495dSmrg if (actions == (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME)
30036ac495dSmrg && !foreign_exception)
30136ac495dSmrg {
30236ac495dSmrg #ifdef __ARM_EABI_UNWINDER__
30336ac495dSmrg handler_switch_value = (int) ue_header->barrier_cache.bitpattern[1];
30436ac495dSmrg landing_pad = (_Unwind_Ptr) ue_header->barrier_cache.bitpattern[3];
30536ac495dSmrg #else
30636ac495dSmrg handler_switch_value = xh->handlerSwitchValue;
30736ac495dSmrg landing_pad = xh->landingPad;
30836ac495dSmrg #endif
30936ac495dSmrg goto install_context;
31036ac495dSmrg }
31136ac495dSmrg
31236ac495dSmrg language_specific_data = (const unsigned char *)
31336ac495dSmrg _Unwind_GetLanguageSpecificData (context);
31436ac495dSmrg
31536ac495dSmrg /* If no LSDA, then there are no handlers or cleanups. */
31636ac495dSmrg if (! language_specific_data)
31736ac495dSmrg CONTINUE_UNWINDING;
31836ac495dSmrg
31936ac495dSmrg /* Parse the LSDA header. */
32036ac495dSmrg p = parse_lsda_header (context, language_specific_data, &info);
32136ac495dSmrg info.ttype_base = base_of_encoded_value (info.ttype_encoding, context);
32236ac495dSmrg #ifdef HAVE_GETIPINFO
32336ac495dSmrg ip = _Unwind_GetIPInfo (context, &ip_before_insn);
32436ac495dSmrg #else
32536ac495dSmrg ip = _Unwind_GetIP (context);
32636ac495dSmrg #endif
32736ac495dSmrg if (!ip_before_insn)
32836ac495dSmrg --ip;
32936ac495dSmrg landing_pad = 0;
33036ac495dSmrg action_record = 0;
33136ac495dSmrg handler_switch_value = 0;
33236ac495dSmrg
33336ac495dSmrg #ifdef __USING_SJLJ_EXCEPTIONS__
33436ac495dSmrg /* The given "IP" is an index into the call-site table, with two
33536ac495dSmrg exceptions -- -1 means no-action, and 0 means terminate. But
33636ac495dSmrg since we're using uleb128 values, we've not got random access to
33736ac495dSmrg the array. */
33836ac495dSmrg if ((int) ip < 0)
33936ac495dSmrg return _URC_CONTINUE_UNWIND;
34036ac495dSmrg else
34136ac495dSmrg {
34236ac495dSmrg _uleb128_t cs_lp, cs_action;
34336ac495dSmrg do
34436ac495dSmrg {
34536ac495dSmrg p = read_uleb128 (p, &cs_lp);
34636ac495dSmrg p = read_uleb128 (p, &cs_action);
34736ac495dSmrg }
34836ac495dSmrg while (--ip);
34936ac495dSmrg
35036ac495dSmrg /* Can never have null landing pad for sjlj -- that would have
35136ac495dSmrg been indicated by a -1 call site index. */
35236ac495dSmrg landing_pad = cs_lp + 1;
35336ac495dSmrg if (cs_action)
35436ac495dSmrg action_record = info.action_table + cs_action - 1;
35536ac495dSmrg goto found_something;
35636ac495dSmrg }
35736ac495dSmrg #else
35836ac495dSmrg /* Search the call-site table for the action associated with this
35936ac495dSmrg IP. */
36036ac495dSmrg while (p < info.action_table)
36136ac495dSmrg {
36236ac495dSmrg _Unwind_Ptr cs_start, cs_len, cs_lp;
36336ac495dSmrg _uleb128_t cs_action;
36436ac495dSmrg
36536ac495dSmrg /* Note that all call-site encodings are "absolute"
36636ac495dSmrg displacements. */
36736ac495dSmrg p = read_encoded_value (0, info.call_site_encoding, p, &cs_start);
36836ac495dSmrg p = read_encoded_value (0, info.call_site_encoding, p, &cs_len);
36936ac495dSmrg p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp);
37036ac495dSmrg p = read_uleb128 (p, &cs_action);
37136ac495dSmrg
37236ac495dSmrg /* The table is sorted, so if we've passed the ip, stop. */
37336ac495dSmrg if (ip < info.Start + cs_start)
37436ac495dSmrg p = info.action_table;
37536ac495dSmrg else if (ip < info.Start + cs_start + cs_len)
37636ac495dSmrg {
37736ac495dSmrg if (cs_lp)
37836ac495dSmrg landing_pad = info.LPStart + cs_lp;
37936ac495dSmrg if (cs_action)
38036ac495dSmrg action_record = info.action_table + cs_action - 1;
38136ac495dSmrg goto found_something;
38236ac495dSmrg }
38336ac495dSmrg }
38436ac495dSmrg #endif /* __USING_SJLJ_EXCEPTIONS__ */
38536ac495dSmrg
38636ac495dSmrg /* If ip is not present in the table, C++ would call terminate. */
38736ac495dSmrg /* ??? As with Java, it's perhaps better to tweek the LSDA to that
38836ac495dSmrg no-action is mapped to no-entry. */
38936ac495dSmrg CONTINUE_UNWINDING;
39036ac495dSmrg
39136ac495dSmrg found_something:
39236ac495dSmrg saw_cleanup = 0;
39336ac495dSmrg saw_handler = 0;
39436ac495dSmrg
39536ac495dSmrg if (landing_pad == 0)
39636ac495dSmrg {
39736ac495dSmrg /* If ip is present, and has a null landing pad, there are no
39836ac495dSmrg cleanups or handlers to be run. */
39936ac495dSmrg }
40036ac495dSmrg else if (action_record == 0)
40136ac495dSmrg {
40236ac495dSmrg /* If ip is present, has a non-null landing pad, and a null
40336ac495dSmrg action table offset, then there are only cleanups present.
40436ac495dSmrg Cleanups use a zero switch value, as set above. */
40536ac495dSmrg saw_cleanup = 1;
40636ac495dSmrg }
40736ac495dSmrg else
40836ac495dSmrg {
40936ac495dSmrg /* Otherwise we have a catch handler. */
41036ac495dSmrg _sleb128_t ar_filter, ar_disp;
41136ac495dSmrg
41236ac495dSmrg while (1)
41336ac495dSmrg {
41436ac495dSmrg p = action_record;
41536ac495dSmrg p = read_sleb128 (p, &ar_filter);
41636ac495dSmrg read_sleb128 (p, &ar_disp);
41736ac495dSmrg
41836ac495dSmrg if (ar_filter == 0)
41936ac495dSmrg {
42036ac495dSmrg /* Zero filter values are cleanups. */
42136ac495dSmrg saw_cleanup = 1;
42236ac495dSmrg }
42336ac495dSmrg
42436ac495dSmrg /* During forced unwinding, we only run cleanups. With a
42536ac495dSmrg foreign exception class, we have no class info to
42636ac495dSmrg match. */
42736ac495dSmrg else if ((actions & _UA_FORCE_UNWIND) || foreign_exception)
42836ac495dSmrg ;
42936ac495dSmrg
43036ac495dSmrg else if (ar_filter > 0)
43136ac495dSmrg {
43236ac495dSmrg /* Positive filter values are handlers. */
43336ac495dSmrg Class catch_type = get_ttype_entry (&info, ar_filter);
43436ac495dSmrg
43536ac495dSmrg if ((*__objc_exception_matcher) (catch_type, xh->value))
43636ac495dSmrg {
43736ac495dSmrg handler_switch_value = ar_filter;
43836ac495dSmrg saw_handler = 1;
43936ac495dSmrg break;
44036ac495dSmrg }
44136ac495dSmrg }
44236ac495dSmrg else
44336ac495dSmrg {
44436ac495dSmrg /* Negative filter values are exception specifications,
44536ac495dSmrg which Objective-C does not use. */
44636ac495dSmrg abort ();
44736ac495dSmrg }
44836ac495dSmrg
44936ac495dSmrg if (ar_disp == 0)
45036ac495dSmrg break;
45136ac495dSmrg action_record = p + ar_disp;
45236ac495dSmrg }
45336ac495dSmrg }
45436ac495dSmrg
45536ac495dSmrg if (! saw_handler && ! saw_cleanup)
45636ac495dSmrg CONTINUE_UNWINDING;
45736ac495dSmrg
45836ac495dSmrg if (actions & _UA_SEARCH_PHASE)
45936ac495dSmrg {
46036ac495dSmrg if (!saw_handler)
46136ac495dSmrg CONTINUE_UNWINDING;
46236ac495dSmrg
46336ac495dSmrg /* For domestic exceptions, we cache data from phase 1 for phase
46436ac495dSmrg 2. */
46536ac495dSmrg if (!foreign_exception)
46636ac495dSmrg {
46736ac495dSmrg #ifdef __ARM_EABI_UNWINDER__
46836ac495dSmrg ue_header->barrier_cache.sp = _Unwind_GetGR (context, 13);
46936ac495dSmrg ue_header->barrier_cache.bitpattern[1] = (_uw) handler_switch_value;
47036ac495dSmrg ue_header->barrier_cache.bitpattern[3] = (_uw) landing_pad;
47136ac495dSmrg #else
47236ac495dSmrg xh->handlerSwitchValue = handler_switch_value;
47336ac495dSmrg xh->landingPad = landing_pad;
47436ac495dSmrg #endif
47536ac495dSmrg }
47636ac495dSmrg return _URC_HANDLER_FOUND;
47736ac495dSmrg }
47836ac495dSmrg
47936ac495dSmrg install_context:
48036ac495dSmrg if (saw_cleanup == 0)
48136ac495dSmrg {
48236ac495dSmrg return_object = xh->value;
48336ac495dSmrg if (!(actions & _UA_SEARCH_PHASE))
48436ac495dSmrg _Unwind_DeleteException(&xh->base);
48536ac495dSmrg }
48636ac495dSmrg
48736ac495dSmrg _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
48836ac495dSmrg __builtin_extend_pointer (saw_cleanup ? xh : return_object));
48936ac495dSmrg _Unwind_SetGR (context, __builtin_eh_return_data_regno (1),
49036ac495dSmrg handler_switch_value);
49136ac495dSmrg _Unwind_SetIP (context, landing_pad);
49236ac495dSmrg return _URC_INSTALL_CONTEXT;
49336ac495dSmrg }
49436ac495dSmrg
49536ac495dSmrg static void
__objc_exception_cleanup(_Unwind_Reason_Code code,struct _Unwind_Exception * exc)49636ac495dSmrg __objc_exception_cleanup (_Unwind_Reason_Code code __attribute__((unused)),
49736ac495dSmrg struct _Unwind_Exception *exc)
49836ac495dSmrg {
49936ac495dSmrg free (exc);
50036ac495dSmrg }
50136ac495dSmrg
50236ac495dSmrg void
objc_exception_throw(id exception)50336ac495dSmrg objc_exception_throw (id exception)
50436ac495dSmrg {
50536ac495dSmrg struct ObjcException *header = calloc (1, sizeof (*header));
50636ac495dSmrg
50736ac495dSmrg memcpy (&header->base.exception_class, &__objc_exception_class,
50836ac495dSmrg sizeof (__objc_exception_class));
50936ac495dSmrg header->base.exception_cleanup = __objc_exception_cleanup;
51036ac495dSmrg header->value = exception;
51136ac495dSmrg
51236ac495dSmrg #ifdef __USING_SJLJ_EXCEPTIONS__
51336ac495dSmrg _Unwind_SjLj_RaiseException (&header->base);
51436ac495dSmrg #else
51536ac495dSmrg _Unwind_RaiseException (&header->base);
51636ac495dSmrg #endif
51736ac495dSmrg
51836ac495dSmrg /* No exception handler was installed. Call the uncaught exception
51936ac495dSmrg handler if any is defined. */
52036ac495dSmrg if (__objc_uncaught_exception_handler != 0)
52136ac495dSmrg {
52236ac495dSmrg (*__objc_uncaught_exception_handler) (exception);
52336ac495dSmrg }
52436ac495dSmrg
52536ac495dSmrg abort ();
52636ac495dSmrg }
52736ac495dSmrg
52836ac495dSmrg #if defined (__SEH__) && !defined (__USING_SJLJ_EXCEPTIONS__)
52936ac495dSmrg EXCEPTION_DISPOSITION
__gnu_objc_personality_seh0(PEXCEPTION_RECORD ms_exc,void * this_frame,PCONTEXT ms_orig_context,PDISPATCHER_CONTEXT ms_disp)53036ac495dSmrg __gnu_objc_personality_seh0 (PEXCEPTION_RECORD ms_exc, void *this_frame,
53136ac495dSmrg PCONTEXT ms_orig_context,
53236ac495dSmrg PDISPATCHER_CONTEXT ms_disp)
53336ac495dSmrg {
53436ac495dSmrg return _GCC_specific_handler (ms_exc, this_frame, ms_orig_context,
53536ac495dSmrg ms_disp, __gnu_objc_personality_imp);
53636ac495dSmrg }
53736ac495dSmrg #endif
538