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