Daily bump.
[official-gcc.git] / libobjc / exception.c
blob4883448afad89583b3b36015cb0690b1be7f1dd6
1 /* The implementation of exception handling primitives for Objective-C.
2 Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 3, or (at your option) any
9 later version.
11 GCC is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 <http://www.gnu.org/licenses/>. */
25 #include "objc-private/common.h"
26 #include <stdlib.h>
27 #include "config.h"
28 #include "objc/runtime.h"
29 #include "objc/objc-exception.h"
30 #include "unwind.h"
31 #include "unwind-pe.h"
32 #include <string.h> /* For memcpy */
34 /* This hook allows libraries to sepecify special actions when an
35 exception is thrown without a handler in place. This is deprecated
36 in favour of objc_set_uncaught_exception_handler ().
38 void (*_objc_unexpected_exception) (id exception); /* !T:SAFE */
41 /* 'is_kind_of_exception_matcher' is our default exception matcher -
42 it determines if the object 'exception' is of class 'catch_class',
43 or of a subclass.
45 static int
46 is_kind_of_exception_matcher (Class catch_class, id exception)
48 /* NULL catch_class is catch-all (eg, @catch (id object)). */
49 if (catch_class == Nil)
50 return 1;
52 /* If exception is nil (eg, @throw nil;), then it can only be catched
53 * by a catch-all (eg, @catch (id object)).
55 if (exception != nil)
57 Class c;
59 for (c = exception->class_pointer; c != Nil;
60 c = class_getSuperclass (c))
61 if (c == catch_class)
62 return 1;
64 return 0;
67 /* The exception matcher currently in use. */
68 static objc_exception_matcher
69 __objc_exception_matcher = is_kind_of_exception_matcher;
71 objc_exception_matcher
72 objc_setExceptionMatcher (objc_exception_matcher new_matcher)
74 objc_exception_matcher old_matcher = __objc_exception_matcher;
75 __objc_exception_matcher = new_matcher;
76 return old_matcher;
79 /* The uncaught exception handler currently in use. */
80 static objc_uncaught_exception_handler
81 __objc_uncaught_exception_handler = NULL;
83 objc_uncaught_exception_handler
84 objc_setUncaughtExceptionHandler (objc_uncaught_exception_handler
85 new_handler)
87 objc_uncaught_exception_handler old_handler
88 = __objc_uncaught_exception_handler;
89 __objc_uncaught_exception_handler = new_handler;
90 return old_handler;
95 #ifdef __ARM_EABI_UNWINDER__
97 const _Unwind_Exception_Class __objc_exception_class
98 = {'G', 'N', 'U', 'C', 'O', 'B', 'J', 'C'};
100 #else
102 /* This is the exception class we report -- "GNUCOBJC". */
103 static const _Unwind_Exception_Class __objc_exception_class
104 = ((((((((_Unwind_Exception_Class) 'G'
105 << 8 | (_Unwind_Exception_Class) 'N')
106 << 8 | (_Unwind_Exception_Class) 'U')
107 << 8 | (_Unwind_Exception_Class) 'C')
108 << 8 | (_Unwind_Exception_Class) 'O')
109 << 8 | (_Unwind_Exception_Class) 'B')
110 << 8 | (_Unwind_Exception_Class) 'J')
111 << 8 | (_Unwind_Exception_Class) 'C');
113 #endif
115 /* This is the object that is passed around by the Objective C runtime
116 to represent the exception in flight. */
118 struct ObjcException
120 /* This bit is needed in order to interact with the unwind runtime. */
121 struct _Unwind_Exception base;
123 /* The actual object we want to throw. Note: must come immediately after
124 unwind header. */
125 id value;
127 #ifdef __ARM_EABI_UNWINDER__
128 /* Note: we use the barrier cache defined in the unwind control block for
129 ARM EABI. */
130 #else
131 /* Cache some internal unwind data between phase 1 and phase 2. */
132 _Unwind_Ptr landingPad;
133 int handlerSwitchValue;
134 #endif
139 struct lsda_header_info
141 _Unwind_Ptr Start;
142 _Unwind_Ptr LPStart;
143 _Unwind_Ptr ttype_base;
144 const unsigned char *TType;
145 const unsigned char *action_table;
146 unsigned char ttype_encoding;
147 unsigned char call_site_encoding;
150 static const unsigned char *
151 parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p,
152 struct lsda_header_info *info)
154 _uleb128_t tmp;
155 unsigned char lpstart_encoding;
157 info->Start = (context ? _Unwind_GetRegionStart (context) : 0);
159 /* Find @LPStart, the base to which landing pad offsets are relative. */
160 lpstart_encoding = *p++;
161 if (lpstart_encoding != DW_EH_PE_omit)
162 p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart);
163 else
164 info->LPStart = info->Start;
166 /* Find @TType, the base of the handler and exception spec type data. */
167 info->ttype_encoding = *p++;
168 if (info->ttype_encoding != DW_EH_PE_omit)
170 p = read_uleb128 (p, &tmp);
171 info->TType = p + tmp;
173 else
174 info->TType = 0;
176 /* The encoding and length of the call-site table; the action table
177 immediately follows. */
178 info->call_site_encoding = *p++;
179 p = read_uleb128 (p, &tmp);
180 info->action_table = p + tmp;
182 return p;
185 #ifdef __ARM_EABI_UNWINDER__
187 static Class
188 get_ttype_entry (struct lsda_header_info *info, _uleb128_t i)
190 _Unwind_Ptr ptr;
192 ptr = (_Unwind_Ptr) (info->TType - (i * 4));
193 ptr = _Unwind_decode_target2 (ptr);
195 /* NULL ptr means catch-all. Note that if the class is not found,
196 this will abort the program. */
197 if (ptr)
198 return objc_getRequiredClass ((const char *) ptr);
199 else
200 return 0;
203 #else
205 static Class
206 get_ttype_entry (struct lsda_header_info *info, _Unwind_Word i)
208 _Unwind_Ptr ptr;
210 i *= size_of_encoded_value (info->ttype_encoding);
211 read_encoded_value_with_base (info->ttype_encoding, info->ttype_base,
212 info->TType - i, &ptr);
214 /* NULL ptr means catch-all. Note that if the class is not found,
215 this will abort the program. */
216 if (ptr)
217 return objc_getRequiredClass ((const char *) ptr);
218 else
219 return 0;
222 #endif
224 /* Using a different personality function name causes link failures
225 when trying to mix code using different exception handling models. */
226 #ifdef SJLJ_EXCEPTIONS
227 #define PERSONALITY_FUNCTION __gnu_objc_personality_sj0
228 #define __builtin_eh_return_data_regno(x) x
229 #else
230 #define PERSONALITY_FUNCTION __gnu_objc_personality_v0
231 #endif
233 #ifdef __ARM_EABI_UNWINDER__
235 #define CONTINUE_UNWINDING \
236 do \
238 if (__gnu_unwind_frame(ue_header, context) != _URC_OK) \
239 return _URC_FAILURE; \
240 return _URC_CONTINUE_UNWIND; \
242 while (0)
244 _Unwind_Reason_Code
245 PERSONALITY_FUNCTION (_Unwind_State state,
246 struct _Unwind_Exception *ue_header,
247 struct _Unwind_Context *context)
248 #else
250 #define CONTINUE_UNWINDING return _URC_CONTINUE_UNWIND
252 _Unwind_Reason_Code
253 PERSONALITY_FUNCTION (int version,
254 _Unwind_Action actions,
255 _Unwind_Exception_Class exception_class,
256 struct _Unwind_Exception *ue_header,
257 struct _Unwind_Context *context)
258 #endif
260 struct ObjcException *xh = (struct ObjcException *) ue_header;
262 struct lsda_header_info info;
263 const unsigned char *language_specific_data;
264 const unsigned char *action_record;
265 const unsigned char *p;
266 _Unwind_Ptr landing_pad, ip;
267 int handler_switch_value;
268 int saw_cleanup = 0, saw_handler, foreign_exception;
269 void *return_object;
270 int ip_before_insn = 0;
272 #ifdef __ARM_EABI_UNWINDER__
273 _Unwind_Action actions;
275 switch (state & _US_ACTION_MASK)
277 case _US_VIRTUAL_UNWIND_FRAME:
278 actions = _UA_SEARCH_PHASE;
279 break;
281 case _US_UNWIND_FRAME_STARTING:
282 actions = _UA_CLEANUP_PHASE;
283 if (!(state & _US_FORCE_UNWIND)
284 && ue_header->barrier_cache.sp == _Unwind_GetGR (context, 13))
285 actions |= _UA_HANDLER_FRAME;
286 break;
288 case _US_UNWIND_FRAME_RESUME:
289 CONTINUE_UNWINDING;
290 break;
292 default:
293 abort();
295 actions |= state & _US_FORCE_UNWIND;
297 /* TODO: Foreign exceptions need some attention (e.g. rethrowing doesn't
298 work). */
299 foreign_exception = 0;
301 /* The dwarf unwinder assumes the context structure holds things like the
302 function and LSDA pointers. The ARM implementation caches these in
303 the exception header (UCB). To avoid rewriting everything we make the
304 virtual IP register point at the UCB. */
305 ip = (_Unwind_Ptr) ue_header;
306 _Unwind_SetGR (context, 12, ip);
308 #else /* !__ARM_EABI_UNWINDER. */
309 /* Interface version check. */
310 if (version != 1)
311 return _URC_FATAL_PHASE1_ERROR;
313 foreign_exception = (exception_class != __objc_exception_class);
314 #endif
316 /* Shortcut for phase 2 found handler for domestic exception. */
317 if (actions == (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME)
318 && !foreign_exception)
320 #ifdef __ARM_EABI_UNWINDER__
321 handler_switch_value = (int) ue_header->barrier_cache.bitpattern[1];
322 landing_pad = (_Unwind_Ptr) ue_header->barrier_cache.bitpattern[3];
323 #else
324 handler_switch_value = xh->handlerSwitchValue;
325 landing_pad = xh->landingPad;
326 #endif
327 goto install_context;
330 language_specific_data = (const unsigned char *)
331 _Unwind_GetLanguageSpecificData (context);
333 /* If no LSDA, then there are no handlers or cleanups. */
334 if (! language_specific_data)
335 CONTINUE_UNWINDING;
337 /* Parse the LSDA header. */
338 p = parse_lsda_header (context, language_specific_data, &info);
339 info.ttype_base = base_of_encoded_value (info.ttype_encoding, context);
340 #ifdef HAVE_GETIPINFO
341 ip = _Unwind_GetIPInfo (context, &ip_before_insn);
342 #else
343 ip = _Unwind_GetIP (context);
344 #endif
345 if (!ip_before_insn)
346 --ip;
347 landing_pad = 0;
348 action_record = 0;
349 handler_switch_value = 0;
351 #ifdef SJLJ_EXCEPTIONS
352 /* The given "IP" is an index into the call-site table, with two
353 exceptions -- -1 means no-action, and 0 means terminate. But
354 since we're using uleb128 values, we've not got random access
355 to the array. */
356 if ((int) ip < 0)
357 return _URC_CONTINUE_UNWIND;
358 else
360 _uleb128_t cs_lp, cs_action;
363 p = read_uleb128 (p, &cs_lp);
364 p = read_uleb128 (p, &cs_action);
366 while (--ip);
368 /* Can never have null landing pad for sjlj -- that would have
369 been indicated by a -1 call site index. */
370 landing_pad = cs_lp + 1;
371 if (cs_action)
372 action_record = info.action_table + cs_action - 1;
373 goto found_something;
375 #else
376 /* Search the call-site table for the action associated with this IP. */
377 while (p < info.action_table)
379 _Unwind_Ptr cs_start, cs_len, cs_lp;
380 _uleb128_t cs_action;
382 /* Note that all call-site encodings are "absolute" displacements. */
383 p = read_encoded_value (0, info.call_site_encoding, p, &cs_start);
384 p = read_encoded_value (0, info.call_site_encoding, p, &cs_len);
385 p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp);
386 p = read_uleb128 (p, &cs_action);
388 /* The table is sorted, so if we've passed the ip, stop. */
389 if (ip < info.Start + cs_start)
390 p = info.action_table;
391 else if (ip < info.Start + cs_start + cs_len)
393 if (cs_lp)
394 landing_pad = info.LPStart + cs_lp;
395 if (cs_action)
396 action_record = info.action_table + cs_action - 1;
397 goto found_something;
400 #endif /* SJLJ_EXCEPTIONS */
402 /* If ip is not present in the table, C++ would call terminate. */
403 /* ??? As with Java, it's perhaps better to tweek the LSDA to
404 that no-action is mapped to no-entry. */
405 CONTINUE_UNWINDING;
407 found_something:
408 saw_cleanup = 0;
409 saw_handler = 0;
411 if (landing_pad == 0)
413 /* If ip is present, and has a null landing pad, there are
414 no cleanups or handlers to be run. */
416 else if (action_record == 0)
418 /* If ip is present, has a non-null landing pad, and a null
419 action table offset, then there are only cleanups present.
420 Cleanups use a zero switch value, as set above. */
421 saw_cleanup = 1;
423 else
425 /* Otherwise we have a catch handler. */
426 _sleb128_t ar_filter, ar_disp;
428 while (1)
430 p = action_record;
431 p = read_sleb128 (p, &ar_filter);
432 read_sleb128 (p, &ar_disp);
434 if (ar_filter == 0)
436 /* Zero filter values are cleanups. */
437 saw_cleanup = 1;
440 /* During forced unwinding, we only run cleanups. With a
441 foreign exception class, we have no class info to match. */
442 else if ((actions & _UA_FORCE_UNWIND) || foreign_exception)
445 else if (ar_filter > 0)
447 /* Positive filter values are handlers. */
449 Class catch_type = get_ttype_entry (&info, ar_filter);
451 if ((*__objc_exception_matcher) (catch_type, xh->value))
453 handler_switch_value = ar_filter;
454 saw_handler = 1;
455 break;
458 else
460 /* Negative filter values are exception specifications,
461 which Objective-C does not use. */
462 abort ();
465 if (ar_disp == 0)
466 break;
467 action_record = p + ar_disp;
471 if (! saw_handler && ! saw_cleanup)
472 CONTINUE_UNWINDING;
474 if (actions & _UA_SEARCH_PHASE)
476 if (!saw_handler)
477 CONTINUE_UNWINDING;
479 /* For domestic exceptions, we cache data from phase 1 for phase 2. */
480 if (!foreign_exception)
482 #ifdef __ARM_EABI_UNWINDER__
483 ue_header->barrier_cache.sp = _Unwind_GetGR (context, 13);
484 ue_header->barrier_cache.bitpattern[1] = (_uw) handler_switch_value;
485 ue_header->barrier_cache.bitpattern[3] = (_uw) landing_pad;
486 #else
487 xh->handlerSwitchValue = handler_switch_value;
488 xh->landingPad = landing_pad;
489 #endif
491 return _URC_HANDLER_FOUND;
494 install_context:
495 if (saw_cleanup == 0)
497 return_object = xh->value;
498 if (!(actions & _UA_SEARCH_PHASE))
499 _Unwind_DeleteException(&xh->base);
502 _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
503 __builtin_extend_pointer (saw_cleanup ? xh : return_object));
504 _Unwind_SetGR (context, __builtin_eh_return_data_regno (1),
505 handler_switch_value);
506 _Unwind_SetIP (context, landing_pad);
507 return _URC_INSTALL_CONTEXT;
510 static void
511 __objc_exception_cleanup (_Unwind_Reason_Code code __attribute__((unused)),
512 struct _Unwind_Exception *exc)
514 free (exc);
517 void
518 objc_exception_throw (id exception)
520 struct ObjcException *header = calloc (1, sizeof (*header));
522 memcpy (&header->base.exception_class, &__objc_exception_class,
523 sizeof (__objc_exception_class));
524 header->base.exception_cleanup = __objc_exception_cleanup;
525 header->value = exception;
527 #ifdef SJLJ_EXCEPTIONS
528 _Unwind_SjLj_RaiseException (&header->base);
529 #else
530 _Unwind_RaiseException (&header->base);
531 #endif
533 /* No exception handler was installed. Call the uncaught exception
534 handler if any is defined.
536 if (__objc_uncaught_exception_handler != 0)
538 (*__objc_uncaught_exception_handler) (exception);
541 /* As a last resort support the old, deprecated way of setting an
542 uncaught exception handler.
544 if (_objc_unexpected_exception != 0)
546 (*_objc_unexpected_exception) (exception);
549 abort ();