xref: /netbsd-src/external/gpl3/gcc.old/dist/libobjc/exception.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
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