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