Upstream version 8.36.169.0
[platform/framework/web/crosswalk.git] / src / third_party / libc++abi / trunk / src / cxa_personality.cpp
1 //===------------------------- cxa_exception.cpp --------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //  
9 //  This file implements the "Exception Handling APIs"
10 //  http://mentorembedded.github.io/cxx-abi/abi-eh.html
11 //  http://www.intel.com/design/itanium/downloads/245358.htm
12 //  
13 //===----------------------------------------------------------------------===//
14
15 #include "unwind.h"
16 #include "cxa_exception.hpp"
17 #include "cxa_handlers.hpp"
18 #include "private_typeinfo.h"
19 #include <typeinfo>
20 #include <stdlib.h>
21 #include <assert.h>
22
23 /*
24     Exception Header Layout:
25
26 +---------------------------+-----------------------------+---------------+
27 | __cxa_exception           | _Unwind_Exception CLNGC++\0 | thrown object |
28 +---------------------------+-----------------------------+---------------+
29                                                           ^
30                                                           |
31   +-------------------------------------------------------+
32   |
33 +---------------------------+-----------------------------+
34 | __cxa_dependent_exception | _Unwind_Exception CLNGC++\1 |
35 +---------------------------+-----------------------------+
36
37     Exception Handling Table Layout:
38
39 +-----------------+--------+
40 | lpStartEncoding | (char) |
41 +---------+-------+--------+---------------+-----------------------+
42 | lpStart | (encoded with lpStartEncoding) | defaults to funcStart |
43 +---------+-----+--------+-----------------+---------------+-------+
44 | ttypeEncoding | (char) | Encoding of the type_info table |
45 +---------------+-+------+----+----------------------------+----------------+
46 | classInfoOffset | (ULEB128) | Offset to type_info table, defaults to null |
47 +-----------------++--------+-+----------------------------+----------------+
48 | callSiteEncoding | (char) | Encoding for Call Site Table |
49 +------------------+--+-----+-----+------------------------+--------------------------+
50 | callSiteTableLength | (ULEB128) | Call Site Table length, used to find Action table |
51 +---------------------+-----------+---------------------------------------------------+
52 #if !__arm__
53 +---------------------+-----------+------------------------------------------------+
54 | Beginning of Call Site Table            The current ip lies within the           |
55 | ...                                     (start, length) range of one of these    |
56 |                                         call sites. There may be action needed.  |
57 | +-------------+---------------------------------+------------------------------+ |
58 | | start       | (encoded with callSiteEncoding) | offset relative to funcStart | |
59 | | length      | (encoded with callSiteEncoding) | length of code fragment      | |
60 | | landingPad  | (encoded with callSiteEncoding) | offset relative to lpStart   | |
61 | | actionEntry | (ULEB128)                       | Action Table Index 1-based   | |
62 | |             |                                 | actionEntry == 0 -> cleanup  | |
63 | +-------------+---------------------------------+------------------------------+ |
64 | ...                                                                              |
65 +----------------------------------------------------------------------------------+
66 #else  // __arm_
67 +---------------------+-----------+------------------------------------------------+
68 | Beginning of Call Site Table            The current ip is a 1-based index into   |
69 | ...                                     this table.  Or it is -1 meaning no      |
70 |                                         action is needed.  Or it is 0 meaning    |
71 |                                         terminate.                               |
72 | +-------------+---------------------------------+------------------------------+ |
73 | | landingPad  | (ULEB128)                       | offset relative to lpStart   | |
74 | | actionEntry | (ULEB128)                       | Action Table Index 1-based   | |
75 | |             |                                 | actionEntry == 0 -> cleanup  | |
76 | +-------------+---------------------------------+------------------------------+ |
77 | ...                                                                              |
78 +----------------------------------------------------------------------------------+
79 #endif  // __arm_
80 +---------------------------------------------------------------------+
81 | Beginning of Action Table       ttypeIndex == 0 : cleanup           |
82 | ...                             ttypeIndex  > 0 : catch             |
83 |                                 ttypeIndex  < 0 : exception spec    |
84 | +--------------+-----------+--------------------------------------+ |
85 | | ttypeIndex   | (SLEB128) | Index into type_info Table (1-based) | |
86 | | actionOffset | (SLEB128) | Offset into next Action Table entry  | |
87 | +--------------+-----------+--------------------------------------+ |
88 | ...                                                                 |
89 +---------------------------------------------------------------------+-----------------+
90 | type_info Table, but classInfoOffset does *not* point here!                           |
91 | +----------------+------------------------------------------------+-----------------+ |
92 | | Nth type_info* | Encoded with ttypeEncoding, 0 means catch(...) | ttypeIndex == N | |
93 | +----------------+------------------------------------------------+-----------------+ |
94 | ...                                                                                   |
95 | +----------------+------------------------------------------------+-----------------+ |
96 | | 1st type_info* | Encoded with ttypeEncoding, 0 means catch(...) | ttypeIndex == 1 | |
97 | +----------------+------------------------------------------------+-----------------+ |
98 | +---------------------------------------+-----------+------------------------------+  |
99 | | 1st ttypeIndex for 1st exception spec | (ULEB128) | classInfoOffset points here! |  |
100 | | ...                                   | (ULEB128) |                              |  |
101 | | Mth ttypeIndex for 1st exception spec | (ULEB128) |                              |  |
102 | | 0                                     | (ULEB128) |                              |  |
103 | +---------------------------------------+------------------------------------------+  |
104 | ...                                                                                   |
105 | +---------------------------------------+------------------------------------------+  |
106 | | 0                                     | (ULEB128) | throw()                      |  |
107 | +---------------------------------------+------------------------------------------+  |
108 | ...                                                                                   |
109 | +---------------------------------------+------------------------------------------+  |
110 | | 1st ttypeIndex for Nth exception spec | (ULEB128) |                              |  |
111 | | ...                                   | (ULEB128) |                              |  |
112 | | Mth ttypeIndex for Nth exception spec | (ULEB128) |                              |  |
113 | | 0                                     | (ULEB128) |                              |  |
114 | +---------------------------------------+------------------------------------------+  |
115 +---------------------------------------------------------------------------------------+
116
117 Notes:
118
119 *  ttypeIndex in the Action Table, and in the exception spec table, is an index,
120      not a byte count, if positive.  It is a negative index offset of
121      classInfoOffset and the sizeof entry depends on ttypeEncoding.
122    But if ttypeIndex is negative, it is a positive 1-based byte offset into the
123      type_info Table.
124    And if ttypeIndex is zero, it refers to a catch (...).
125
126 *  landingPad can be 0, this implies there is nothing to be done.
127
128 *  landingPad != 0 and actionEntry == 0 implies a cleanup needs to be done
129      @landingPad.
130
131 *  A cleanup can also be found under landingPad != 0 and actionEntry != 0 in
132      the Action Table with ttypeIndex == 0.
133 */
134
135 namespace __cxxabiv1
136 {
137
138 extern "C"
139 {
140
141 // private API
142
143 // Heavily borrowed from llvm/examples/ExceptionDemo/ExceptionDemo.cpp
144
145 // DWARF Constants
146 enum
147 {
148     DW_EH_PE_absptr   = 0x00,
149     DW_EH_PE_uleb128  = 0x01,
150     DW_EH_PE_udata2   = 0x02,
151     DW_EH_PE_udata4   = 0x03,
152     DW_EH_PE_udata8   = 0x04,
153     DW_EH_PE_sleb128  = 0x09,
154     DW_EH_PE_sdata2   = 0x0A,
155     DW_EH_PE_sdata4   = 0x0B,
156     DW_EH_PE_sdata8   = 0x0C,
157     DW_EH_PE_pcrel    = 0x10,
158     DW_EH_PE_textrel  = 0x20,
159     DW_EH_PE_datarel  = 0x30,
160     DW_EH_PE_funcrel  = 0x40,
161     DW_EH_PE_aligned  = 0x50,
162     DW_EH_PE_indirect = 0x80,
163     DW_EH_PE_omit     = 0xFF
164 };
165
166 /// Read a uleb128 encoded value and advance pointer 
167 /// See Variable Length Data Appendix C in: 
168 /// @link http://dwarfstd.org/Dwarf4.pdf @unlink
169 /// @param data reference variable holding memory pointer to decode from
170 /// @returns decoded value
171 static
172 uintptr_t
173 readULEB128(const uint8_t** data)
174 {
175     uintptr_t result = 0;
176     uintptr_t shift = 0;
177     unsigned char byte;
178     const uint8_t *p = *data;
179     do
180     {
181         byte = *p++;
182         result |= static_cast<uintptr_t>(byte & 0x7F) << shift;
183         shift += 7;
184     } while (byte & 0x80);
185     *data = p;
186     return result;
187 }
188
189 /// Read a sleb128 encoded value and advance pointer 
190 /// See Variable Length Data Appendix C in: 
191 /// @link http://dwarfstd.org/Dwarf4.pdf @unlink
192 /// @param data reference variable holding memory pointer to decode from
193 /// @returns decoded value
194 static
195 intptr_t
196 readSLEB128(const uint8_t** data)
197 {
198     uintptr_t result = 0;
199     uintptr_t shift = 0;
200     unsigned char byte;
201     const uint8_t *p = *data;
202     do
203     {
204         byte = *p++;
205         result |= static_cast<uintptr_t>(byte & 0x7F) << shift;
206         shift += 7;
207     } while (byte & 0x80);
208     *data = p;
209     if ((byte & 0x40) && (shift < (sizeof(result) << 3)))
210         result |= static_cast<uintptr_t>(~0) << shift;
211     return static_cast<intptr_t>(result);
212 }
213
214 /// Read a pointer encoded value and advance pointer 
215 /// See Variable Length Data in: 
216 /// @link http://dwarfstd.org/Dwarf3.pdf @unlink
217 /// @param data reference variable holding memory pointer to decode from
218 /// @param encoding dwarf encoding type
219 /// @returns decoded value
220 static
221 uintptr_t
222 readEncodedPointer(const uint8_t** data, uint8_t encoding)
223 {
224     uintptr_t result = 0;
225     if (encoding == DW_EH_PE_omit) 
226         return result;
227     const uint8_t* p = *data;
228     // first get value 
229     switch (encoding & 0x0F)
230     {
231     case DW_EH_PE_absptr:
232         result = *((uintptr_t*)p);
233         p += sizeof(uintptr_t);
234         break;
235     case DW_EH_PE_uleb128:
236         result = readULEB128(&p);
237         break;
238     case DW_EH_PE_sleb128:
239         result = static_cast<uintptr_t>(readSLEB128(&p));
240         break;
241     case DW_EH_PE_udata2:
242         result = *((uint16_t*)p);
243         p += sizeof(uint16_t);
244         break;
245     case DW_EH_PE_udata4:
246         result = *((uint32_t*)p);
247         p += sizeof(uint32_t);
248         break;
249     case DW_EH_PE_udata8:
250         result = static_cast<uintptr_t>(*((uint64_t*)p));
251         p += sizeof(uint64_t);
252         break;
253     case DW_EH_PE_sdata2:
254         result = static_cast<uintptr_t>(*((int16_t*)p));
255         p += sizeof(int16_t);
256         break;
257     case DW_EH_PE_sdata4:
258         result = static_cast<uintptr_t>(*((int32_t*)p));
259         p += sizeof(int32_t);
260         break;
261     case DW_EH_PE_sdata8:
262         result = static_cast<uintptr_t>(*((int64_t*)p));
263         p += sizeof(int64_t);
264         break;
265     default:
266         // not supported 
267         abort();
268         break;
269     }
270     // then add relative offset 
271     switch (encoding & 0x70)
272     {
273     case DW_EH_PE_absptr:
274         // do nothing 
275         break;
276     case DW_EH_PE_pcrel:
277         if (result)
278             result += (uintptr_t)(*data);
279         break;
280     case DW_EH_PE_textrel:
281     case DW_EH_PE_datarel:
282     case DW_EH_PE_funcrel:
283     case DW_EH_PE_aligned:
284     default:
285         // not supported 
286         abort();
287         break;
288     }
289     // then apply indirection 
290     if (result && (encoding & DW_EH_PE_indirect))
291         result = *((uintptr_t*)result);
292     *data = p;
293     return result;
294 }
295
296 static
297 void
298 call_terminate(bool native_exception, _Unwind_Exception* unwind_exception)
299 {
300     __cxa_begin_catch(unwind_exception);
301     if (native_exception)
302     {
303         // Use the stored terminate_handler if possible
304         __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
305         std::__terminate(exception_header->terminateHandler);
306     }
307     std::terminate();
308 }
309
310 static
311 const __shim_type_info*
312 get_shim_type_info(uint64_t ttypeIndex, const uint8_t* classInfo,
313                    uint8_t ttypeEncoding, bool native_exception,
314                    _Unwind_Exception* unwind_exception)
315 {
316     if (classInfo == 0)
317     {
318         // this should not happen.  Indicates corrupted eh_table.
319         call_terminate(native_exception, unwind_exception);
320     }
321     switch (ttypeEncoding & 0x0F)
322     {
323     case DW_EH_PE_absptr:
324         ttypeIndex *= sizeof(void*);
325         break;
326     case DW_EH_PE_udata2:
327     case DW_EH_PE_sdata2:
328         ttypeIndex *= 2;
329         break;
330     case DW_EH_PE_udata4:
331     case DW_EH_PE_sdata4:
332         ttypeIndex *= 4;
333         break;
334     case DW_EH_PE_udata8:
335     case DW_EH_PE_sdata8:
336         ttypeIndex *= 8;
337         break;
338     default:
339         // this should not happen.   Indicates corrupted eh_table.
340         call_terminate(native_exception, unwind_exception);
341     }
342     classInfo -= ttypeIndex;
343     return (const __shim_type_info*)readEncodedPointer(&classInfo, ttypeEncoding);
344 }
345
346 /*
347     This is checking a thrown exception type, excpType, against a possibly empty
348     list of catchType's which make up an exception spec.
349
350     An exception spec acts like a catch handler, but in reverse.  This "catch
351     handler" will catch an excpType if and only if none of the catchType's in
352     the list will catch a excpType.  If any catchType in the list can catch an
353     excpType, then this exception spec does not catch the excpType.
354 */
355 static
356 bool
357 exception_spec_can_catch(int64_t specIndex, const uint8_t* classInfo,
358                          uint8_t ttypeEncoding, const __shim_type_info* excpType,
359                          void* adjustedPtr, _Unwind_Exception* unwind_exception)
360 {
361     if (classInfo == 0)
362     {
363         // this should not happen.   Indicates corrupted eh_table.
364         call_terminate(false, unwind_exception);
365     }
366     // specIndex is negative of 1-based byte offset into classInfo;
367     specIndex = -specIndex;
368     --specIndex;
369     const uint8_t* temp = classInfo + specIndex;
370     // If any type in the spec list can catch excpType, return false, else return true
371     //    adjustments to adjustedPtr are ignored.
372     while (true)
373     {
374         uint64_t ttypeIndex = readULEB128(&temp);
375         if (ttypeIndex == 0)
376             break;
377         const __shim_type_info* catchType = get_shim_type_info(ttypeIndex,
378                                                                classInfo,
379                                                                ttypeEncoding,
380                                                                true,
381                                                                unwind_exception);
382         void* tempPtr = adjustedPtr;
383         if (catchType->can_catch(excpType, tempPtr))
384             return false;
385     }
386     return true;
387 }
388
389 static
390 void*
391 get_thrown_object_ptr(_Unwind_Exception* unwind_exception)
392 {
393     // Even for foreign exceptions, the exception object is *probably* at unwind_exception + 1
394     //    Regardless, this library is prohibited from touching a foreign exception
395     void* adjustedPtr = unwind_exception + 1;
396     if (unwind_exception->exception_class == kOurDependentExceptionClass)
397         adjustedPtr = ((__cxa_dependent_exception*)adjustedPtr - 1)->primaryException;
398     return adjustedPtr;
399 }
400
401 namespace
402 {
403
404 struct scan_results
405 {
406     int64_t        ttypeIndex;   // > 0 catch handler, < 0 exception spec handler, == 0 a cleanup
407     const uint8_t* actionRecord;         // Currently unused.  Retained to ease future maintenance.
408     const uint8_t* languageSpecificData;  // Needed only for __cxa_call_unexpected
409     uintptr_t      landingPad;   // null -> nothing found, else something found
410     void*          adjustedPtr;  // Used in cxa_exception.cpp
411     _Unwind_Reason_Code reason;  // One of _URC_FATAL_PHASE1_ERROR,
412                                  //        _URC_FATAL_PHASE2_ERROR,
413                                  //        _URC_CONTINUE_UNWIND,
414                                  //        _URC_HANDLER_FOUND
415 };
416
417 }  // unnamed namespace
418
419 static
420 void
421 set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context,
422               const scan_results& results)
423 {
424 #if __arm__
425     _Unwind_SetGR(context, 0, reinterpret_cast<uintptr_t>(unwind_exception));
426     _Unwind_SetGR(context, 1, static_cast<uintptr_t>(results.ttypeIndex));
427 #else
428     _Unwind_SetGR(context, __builtin_eh_return_data_regno(0),
429                                  reinterpret_cast<uintptr_t>(unwind_exception));
430     _Unwind_SetGR(context, __builtin_eh_return_data_regno(1),
431                                     static_cast<uintptr_t>(results.ttypeIndex));
432 #endif
433     _Unwind_SetIP(context, results.landingPad);
434 }
435
436 /*
437     There are 3 types of scans needed:
438
439     1.  Scan for handler with native or foreign exception.  If handler found,
440         save state and return _URC_HANDLER_FOUND, else return _URC_CONTINUE_UNWIND.
441         May also report an error on invalid input.
442         May terminate for invalid exception table.
443         _UA_SEARCH_PHASE
444
445     2.  Scan for handler with foreign exception.  Must return _URC_HANDLER_FOUND,
446         or call terminate.
447         _UA_CLEANUP_PHASE && _UA_HANDLER_FRAME && !native_exception
448
449     3.  Scan for cleanups.  If a handler is found and this isn't forced unwind,
450         then terminate, otherwise ignore the handler and keep looking for cleanup.
451         If a cleanup is found, return _URC_HANDLER_FOUND, else return _URC_CONTINUE_UNWIND.
452         May also report an error on invalid input.
453         May terminate for invalid exception table.
454         _UA_CLEANUP_PHASE && !_UA_HANDLER_FRAME
455 */
456
457 static
458 void
459 scan_eh_tab(scan_results& results, _Unwind_Action actions, bool native_exception,
460             _Unwind_Exception* unwind_exception, _Unwind_Context* context)
461 {
462     // Initialize results to found nothing but an error
463     results.ttypeIndex = 0;
464     results.actionRecord = 0;
465     results.languageSpecificData = 0;
466     results.landingPad = 0;
467     results.adjustedPtr = 0;
468     results.reason = _URC_FATAL_PHASE1_ERROR;
469     // Check for consistent actions
470     if (actions & _UA_SEARCH_PHASE)
471     {
472         // Do Phase 1
473         if (actions & (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME | _UA_FORCE_UNWIND))
474         {
475             // None of these flags should be set during Phase 1
476             //   Client error
477             results.reason = _URC_FATAL_PHASE1_ERROR;
478             return;
479         }
480     }
481     else if (actions & _UA_CLEANUP_PHASE)
482     {
483         if ((actions & _UA_HANDLER_FRAME) && (actions & _UA_FORCE_UNWIND))
484         {
485             // _UA_HANDLER_FRAME should only be set if phase 1 found a handler.
486             // If _UA_FORCE_UNWIND is set, phase 1 shouldn't have happened.
487             //    Client error
488             results.reason = _URC_FATAL_PHASE2_ERROR;
489             return;
490         }
491     }
492     else // Neither _UA_SEARCH_PHASE nor _UA_CLEANUP_PHASE is set
493     {
494         // One of these should be set.
495         //   Client error
496         results.reason = _URC_FATAL_PHASE1_ERROR;
497         return;
498     }
499     // Start scan by getting exception table address
500     const uint8_t* lsda = (const uint8_t*)_Unwind_GetLanguageSpecificData(context);
501     if (lsda == 0)
502     {
503         // There is no exception table
504         results.reason = _URC_CONTINUE_UNWIND;
505         return;
506     }
507     results.languageSpecificData = lsda;
508     // Get the current instruction pointer and offset it before next
509     // instruction in the current frame which threw the exception.
510     uintptr_t ip = _Unwind_GetIP(context) - 1;
511     // Get beginning current frame's code (as defined by the 
512     // emitted dwarf code)
513     uintptr_t funcStart = _Unwind_GetRegionStart(context);
514 #if __arm__
515     if (ip == uintptr_t(-1))
516     {
517         // no action
518         results.reason = _URC_CONTINUE_UNWIND;
519         return;
520     }
521     else if (ip == 0)
522         call_terminate(native_exception, unwind_exception);
523     // ip is 1-based index into call site table
524 #else  // __arm__
525     uintptr_t ipOffset = ip - funcStart;
526 #endif  // __arm__
527     const uint8_t* classInfo = NULL;
528     // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding
529     //       dwarf emission
530     // Parse LSDA header.
531     uint8_t lpStartEncoding = *lsda++;
532     const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding);
533     if (lpStart == 0)
534         lpStart = (const uint8_t*)funcStart;
535     uint8_t ttypeEncoding = *lsda++;
536     if (ttypeEncoding != DW_EH_PE_omit)
537     {
538         // Calculate type info locations in emitted dwarf code which
539         // were flagged by type info arguments to llvm.eh.selector
540         // intrinsic
541         uintptr_t classInfoOffset = readULEB128(&lsda);
542         classInfo = lsda + classInfoOffset;
543     }
544     // Walk call-site table looking for range that 
545     // includes current PC. 
546     uint8_t callSiteEncoding = *lsda++;
547 #if __arm__
548     (void)callSiteEncoding;  // On arm callSiteEncoding is never used
549 #endif
550     uint32_t callSiteTableLength = static_cast<uint32_t>(readULEB128(&lsda));
551     const uint8_t* callSiteTableStart = lsda;
552     const uint8_t* callSiteTableEnd = callSiteTableStart + callSiteTableLength;
553     const uint8_t* actionTableStart = callSiteTableEnd;
554     const uint8_t* callSitePtr = callSiteTableStart;
555     while (callSitePtr < callSiteTableEnd)
556     {
557         // There is one entry per call site.
558 #if !__arm__
559         // The call sites are non-overlapping in [start, start+length)
560         // The call sites are ordered in increasing value of start
561         uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding);
562         uintptr_t length = readEncodedPointer(&callSitePtr, callSiteEncoding);
563         uintptr_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding);
564         uintptr_t actionEntry = readULEB128(&callSitePtr);
565         if ((start <= ipOffset) && (ipOffset < (start + length)))
566 #else  // __arm__
567         // ip is 1-based index into this table
568         uintptr_t landingPad = readULEB128(&callSitePtr);
569         uintptr_t actionEntry = readULEB128(&callSitePtr);
570         if (--ip == 0)
571 #endif  // __arm__
572         {
573             // Found the call site containing ip.
574 #if !__arm__
575             if (landingPad == 0)
576             {
577                 // No handler here
578                 results.reason = _URC_CONTINUE_UNWIND;
579                 return;
580             }
581             landingPad = (uintptr_t)lpStart + landingPad;
582 #else  // __arm__
583             ++landingPad;
584 #endif  // __arm__
585             if (actionEntry == 0)
586             {
587                 // Found a cleanup
588                 // If this is a type 1 or type 2 search, there are no handlers
589                 // If this is a type 3 search, you want to install the cleanup.
590                 if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME))
591                 {
592                     results.ttypeIndex = 0;  // Redundant but clarifying
593                     results.landingPad = landingPad;
594                     results.reason = _URC_HANDLER_FOUND;
595                     return;
596                 }
597                 // No handler here
598                 results.reason = _URC_CONTINUE_UNWIND;
599                 return;
600             }
601             // Convert 1-based byte offset into
602             const uint8_t* action = actionTableStart + (actionEntry - 1);
603             // Scan action entries until you find a matching handler, cleanup, or the end of action list
604             while (true)
605             {
606                 const uint8_t* actionRecord = action;
607                 int64_t ttypeIndex = readSLEB128(&action);
608                 if (ttypeIndex > 0)
609                 {
610                     // Found a catch, does it actually catch?
611                     // First check for catch (...)
612                     const __shim_type_info* catchType =
613                         get_shim_type_info(static_cast<uint64_t>(ttypeIndex),
614                                            classInfo, ttypeEncoding,
615                                            native_exception, unwind_exception);
616                     if (catchType == 0)
617                     {
618                         // Found catch (...) catches everything, including foreign exceptions
619                         // If this is a type 1 search save state and return _URC_HANDLER_FOUND
620                         // If this is a type 2 search save state and return _URC_HANDLER_FOUND
621                         // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1!
622                         // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan
623                         if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME))
624                         {
625                             // Save state and return _URC_HANDLER_FOUND
626                             results.ttypeIndex = ttypeIndex;
627                             results.actionRecord = actionRecord;
628                             results.landingPad = landingPad;
629                             results.adjustedPtr = get_thrown_object_ptr(unwind_exception);
630                             results.reason = _URC_HANDLER_FOUND;
631                             return;
632                         }
633                         else if (!(actions & _UA_FORCE_UNWIND))
634                         {
635                             // It looks like the exception table has changed
636                             //    on us.  Likely stack corruption!
637                             call_terminate(native_exception, unwind_exception);
638                         }
639                     }
640                     // Else this is a catch (T) clause and will never
641                     //    catch a foreign exception
642                     else if (native_exception)
643                     {
644                         __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
645                         void* adjustedPtr = get_thrown_object_ptr(unwind_exception);
646                         const __shim_type_info* excpType =
647                             static_cast<const __shim_type_info*>(exception_header->exceptionType);
648                         if (adjustedPtr == 0 || excpType == 0)
649                         {
650                             // Something very bad happened
651                             call_terminate(native_exception, unwind_exception);
652                         }
653                         if (catchType->can_catch(excpType, adjustedPtr))
654                         {
655                             // Found a matching handler
656                             // If this is a type 1 search save state and return _URC_HANDLER_FOUND
657                             // If this is a type 3 search and !_UA_FORCE_UNWIND, we should have found this in phase 1!
658                             // If this is a type 3 search and _UA_FORCE_UNWIND, ignore handler and continue scan
659                             if (actions & _UA_SEARCH_PHASE)
660                             {
661                                 // Save state and return _URC_HANDLER_FOUND
662                                 results.ttypeIndex = ttypeIndex;
663                                 results.actionRecord = actionRecord;
664                                 results.landingPad = landingPad;
665                                 results.adjustedPtr = adjustedPtr;
666                                 results.reason = _URC_HANDLER_FOUND;
667                                 return;
668                             }
669                             else if (!(actions & _UA_FORCE_UNWIND))
670                             {
671                                 // It looks like the exception table has changed
672                                 //    on us.  Likely stack corruption!
673                                 call_terminate(native_exception, unwind_exception);
674                             }
675                         }
676                     }
677                     // Scan next action ...
678                 }
679                 else if (ttypeIndex < 0)
680                 {
681                     // Found an exception spec.  If this is a foreign exception,
682                     //   it is always caught.
683                     if (native_exception)
684                     {
685                         // Does the exception spec catch this native exception?
686                         __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
687                         void* adjustedPtr = get_thrown_object_ptr(unwind_exception);
688                         const __shim_type_info* excpType =
689                             static_cast<const __shim_type_info*>(exception_header->exceptionType);
690                         if (adjustedPtr == 0 || excpType == 0)
691                         {
692                             // Something very bad happened
693                             call_terminate(native_exception, unwind_exception);
694                         }
695                         if (exception_spec_can_catch(ttypeIndex, classInfo,
696                                                      ttypeEncoding, excpType,
697                                                      adjustedPtr, unwind_exception))
698                         {
699                             // native exception caught by exception spec
700                             // If this is a type 1 search, save state and return _URC_HANDLER_FOUND
701                             // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1!
702                             // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan
703                             if (actions & _UA_SEARCH_PHASE)
704                             {
705                                 // Save state and return _URC_HANDLER_FOUND
706                                 results.ttypeIndex = ttypeIndex;
707                                 results.actionRecord = actionRecord;
708                                 results.landingPad = landingPad;
709                                 results.adjustedPtr = adjustedPtr;
710                                 results.reason = _URC_HANDLER_FOUND;
711                                 return;
712                             }
713                             else if (!(actions & _UA_FORCE_UNWIND))
714                             {
715                                 // It looks like the exception table has changed
716                                 //    on us.  Likely stack corruption!
717                                 call_terminate(native_exception, unwind_exception);
718                             }
719                         }
720                     }
721                     else
722                     {
723                         // foreign exception caught by exception spec
724                         // If this is a type 1 search, save state and return _URC_HANDLER_FOUND
725                         // If this is a type 2 search, save state and return _URC_HANDLER_FOUND
726                         // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1!
727                         // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan
728                         if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME))
729                         {
730                             // Save state and return _URC_HANDLER_FOUND
731                             results.ttypeIndex = ttypeIndex;
732                             results.actionRecord = actionRecord;
733                             results.landingPad = landingPad;
734                             results.adjustedPtr = get_thrown_object_ptr(unwind_exception);
735                             results.reason = _URC_HANDLER_FOUND;
736                             return;
737                         }
738                         else if (!(actions & _UA_FORCE_UNWIND))
739                         {
740                             // It looks like the exception table has changed
741                             //    on us.  Likely stack corruption!
742                             call_terminate(native_exception, unwind_exception);
743                         }
744                     }
745                     // Scan next action ...
746                 }
747                 else  // ttypeIndex == 0
748                 {
749                     // Found a cleanup
750                     // If this is a type 1 search, ignore it and continue scan
751                     // If this is a type 2 search, ignore it and continue scan
752                     // If this is a type 3 search, save state and return _URC_HANDLER_FOUND
753                     if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME))
754                     {
755                         // Save state and return _URC_HANDLER_FOUND
756                         results.ttypeIndex = ttypeIndex;
757                         results.actionRecord = actionRecord;
758                         results.landingPad = landingPad;
759                         results.adjustedPtr = get_thrown_object_ptr(unwind_exception);
760                         results.reason = _URC_HANDLER_FOUND;
761                         return;
762                     }
763                 }
764                 const uint8_t* temp = action;
765                 int64_t actionOffset = readSLEB128(&temp);
766                 if (actionOffset == 0)
767                 {
768                     // End of action list, no matching handler or cleanup found
769                     results.reason = _URC_CONTINUE_UNWIND;
770                     return;
771                 }
772                 // Go to next action
773                 action += actionOffset;
774             }  // there is no break out of this loop, only return
775         }
776 #if !__arm__
777         else if (ipOffset < start)
778         {
779             // There is no call site for this ip
780             // Something bad has happened.  We should never get here.
781             // Possible stack corruption.
782             call_terminate(native_exception, unwind_exception);
783         }
784 #endif  // !__arm__
785     }  // there might be some tricky cases which break out of this loop
786
787     // It is possible that no eh table entry specify how to handle
788     // this exception. By spec, terminate it immediately.
789     call_terminate(native_exception, unwind_exception);
790 }
791
792 // public API
793
794 /*
795 The personality function branches on actions like so:
796
797 _UA_SEARCH_PHASE
798
799     If _UA_CLEANUP_PHASE or _UA_HANDLER_FRAME or _UA_FORCE_UNWIND there's
800       an error from above, return _URC_FATAL_PHASE1_ERROR.
801
802     Scan for anything that could stop unwinding:
803
804        1.  A catch clause that will catch this exception
805            (will never catch foreign).
806        2.  A catch (...) (will always catch foreign).
807        3.  An exception spec that will catch this exception
808            (will always catch foreign).
809     If a handler is found
810         If not foreign
811             Save state in header
812         return _URC_HANDLER_FOUND
813     Else a handler not found
814         return _URC_CONTINUE_UNWIND
815
816 _UA_CLEANUP_PHASE
817
818     If _UA_HANDLER_FRAME
819         If _UA_FORCE_UNWIND
820             How did this happen?  return _URC_FATAL_PHASE2_ERROR
821         If foreign
822             Do _UA_SEARCH_PHASE to recover state
823         else
824             Recover state from header
825         Transfer control to landing pad.  return _URC_INSTALL_CONTEXT
826     
827     Else
828
829         This branch handles both normal C++ non-catching handlers (cleanups)
830           and forced unwinding.    
831         Scan for anything that can not stop unwinding:
832     
833             1.  A cleanup.
834
835         If a cleanup is found
836             transfer control to it. return _URC_INSTALL_CONTEXT
837         Else a cleanup is not found: return _URC_CONTINUE_UNWIND
838 */
839
840 _Unwind_Reason_Code
841 #if __arm__
842 __gxx_personality_sj0
843 #else
844 __gxx_personality_v0
845 #endif
846                     (int version, _Unwind_Action actions, uint64_t exceptionClass,
847                      _Unwind_Exception* unwind_exception, _Unwind_Context* context)
848 {
849     if (version != 1 || unwind_exception == 0 || context == 0)
850         return _URC_FATAL_PHASE1_ERROR;
851     bool native_exception = (exceptionClass     & get_vendor_and_language) ==
852                             (kOurExceptionClass & get_vendor_and_language);
853     scan_results results;
854     if (actions & _UA_SEARCH_PHASE)
855     {
856         // Phase 1 search:  All we're looking for in phase 1 is a handler that
857         //   halts unwinding
858         scan_eh_tab(results, actions, native_exception, unwind_exception, context);
859         if (results.reason == _URC_HANDLER_FOUND)
860         {
861             // Found one.  Can we cache the results somewhere to optimize phase 2?
862             if (native_exception)
863             {
864                 __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
865                 exception_header->handlerSwitchValue = static_cast<int>(results.ttypeIndex);
866                 exception_header->actionRecord = results.actionRecord;
867                 exception_header->languageSpecificData = results.languageSpecificData;
868                 exception_header->catchTemp = reinterpret_cast<void*>(results.landingPad);
869                 exception_header->adjustedPtr = results.adjustedPtr;
870             }
871             return _URC_HANDLER_FOUND;
872         }
873         // Did not find a catching-handler.  Return the results of the scan
874         //    (normally _URC_CONTINUE_UNWIND, but could have been _URC_FATAL_PHASE1_ERROR
875         //     if we were called improperly).
876         return results.reason;
877     }
878     if (actions & _UA_CLEANUP_PHASE)
879     {
880         // Phase 2 search:
881         //  Did we find a catching handler in phase 1?
882         if (actions & _UA_HANDLER_FRAME)
883         {
884             // Yes, phase 1 said we have a catching handler here.
885             // Did we cache the results of the scan?
886             if (native_exception)
887             {
888                 // Yes, reload the results from the cache.
889                 __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
890                 results.ttypeIndex = exception_header->handlerSwitchValue;
891                 results.actionRecord = exception_header->actionRecord;
892                 results.languageSpecificData = exception_header->languageSpecificData;
893                 results.landingPad = reinterpret_cast<uintptr_t>(exception_header->catchTemp);
894                 results.adjustedPtr = exception_header->adjustedPtr;
895             }
896             else
897             {
898                 // No, do the scan again to reload the results.
899                 scan_eh_tab(results, actions, native_exception, unwind_exception, context);
900                 // Phase 1 told us we would find a handler.  Now in Phase 2 we
901                 //   didn't find a handler.  The eh table should not be changing!
902                 if (results.reason != _URC_HANDLER_FOUND)
903                     call_terminate(native_exception, unwind_exception);
904             }
905             // Jump to the handler
906             set_registers(unwind_exception, context, results);
907             return _URC_INSTALL_CONTEXT;
908         }
909         // Either we didn't do a phase 1 search (due to forced unwinding), or
910         //   phase 1 reported no catching-handlers.
911         // Search for a (non-catching) cleanup
912         scan_eh_tab(results, actions, native_exception, unwind_exception, context);
913         if (results.reason == _URC_HANDLER_FOUND)
914         {
915             // Found a non-catching handler.  Jump to it:
916             set_registers(unwind_exception, context, results);
917             return _URC_INSTALL_CONTEXT;
918         }
919         // Did not find a cleanup.  Return the results of the scan
920         //    (normally _URC_CONTINUE_UNWIND, but could have been _URC_FATAL_PHASE2_ERROR
921         //     if we were called improperly).
922         return results.reason;
923     }
924     // We were called improperly: neither a phase 1 or phase 2 search
925     return _URC_FATAL_PHASE1_ERROR;
926 }
927
928 __attribute__((noreturn))
929 void
930 __cxa_call_unexpected(void* arg)
931 {
932     _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(arg);
933     if (unwind_exception == 0)
934         call_terminate(false, unwind_exception);
935     __cxa_begin_catch(unwind_exception);
936     bool native_old_exception =
937         (unwind_exception->exception_class & get_vendor_and_language) ==
938         (kOurExceptionClass                & get_vendor_and_language);
939     std::unexpected_handler u_handler;
940     std::terminate_handler t_handler;
941     __cxa_exception* old_exception_header = 0;
942     int64_t ttypeIndex;
943     const uint8_t* lsda;
944     if (native_old_exception)
945     {
946         old_exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
947         t_handler = old_exception_header->terminateHandler;
948         u_handler = old_exception_header->unexpectedHandler;
949         // If std::__unexpected(u_handler) rethrows the same exception,
950         //   these values get overwritten by the rethrow.  So save them now:
951         ttypeIndex = old_exception_header->handlerSwitchValue;
952         lsda = old_exception_header->languageSpecificData;
953     }
954     else
955     {
956         t_handler = std::get_terminate();
957         u_handler = std::get_unexpected();
958     }
959     try
960     {
961         std::__unexpected(u_handler);
962     }
963     catch (...)
964     {
965         // If the old exception is foreign, then all we can do is terminate.
966         //   We have no way to recover the needed old exception spec.  There's
967         //   no way to pass that information here.  And the personality routine
968         //   can't call us directly and do anything but terminate() if we throw
969         //   from here.
970         if (native_old_exception)
971         {
972             // Have:
973             //   old_exception_header->languageSpecificData
974             //   old_exception_header->actionRecord
975             // Need
976             //   const uint8_t* classInfo
977             //   uint8_t ttypeEncoding
978             uint8_t lpStartEncoding = *lsda++;
979             const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding);
980             (void)lpStart;  // purposefully unused.  Just needed to increment lsda.
981             uint8_t ttypeEncoding = *lsda++;
982             if (ttypeEncoding == DW_EH_PE_omit)
983                 std::__terminate(t_handler);
984             uintptr_t classInfoOffset = readULEB128(&lsda);
985             const uint8_t* classInfo = lsda + classInfoOffset;
986             // Is this new exception catchable by the exception spec at ttypeIndex?
987             // The answer is obviously yes if the new and old exceptions are the same exception
988             // If no
989             //    throw;
990             __cxa_eh_globals* globals = __cxa_get_globals_fast();
991             __cxa_exception* new_exception_header = globals->caughtExceptions;
992             if (new_exception_header == 0)
993                 // This shouldn't be able to happen!
994                 std::__terminate(t_handler);
995             bool native_new_exception =
996                 (new_exception_header->unwindHeader.exception_class & get_vendor_and_language) ==
997                                                 (kOurExceptionClass & get_vendor_and_language);
998             void* adjustedPtr;
999             if (native_new_exception && (new_exception_header != old_exception_header))
1000             {
1001                 const __shim_type_info* excpType =
1002                     static_cast<const __shim_type_info*>(new_exception_header->exceptionType);
1003                 adjustedPtr =
1004                     new_exception_header->unwindHeader.exception_class == kOurDependentExceptionClass ?
1005                         ((__cxa_dependent_exception*)new_exception_header)->primaryException :
1006                         new_exception_header + 1;
1007                 if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding,
1008                                               excpType, adjustedPtr, unwind_exception))
1009                 {
1010                     // We need to __cxa_end_catch, but for the old exception,
1011                     //   not the new one.  This is a little tricky ...
1012                     // Disguise new_exception_header as a rethrown exception, but
1013                     //   don't actually rethrow it.  This means you can temporarily
1014                     //   end the catch clause enclosing new_exception_header without
1015                     //   __cxa_end_catch destroying new_exception_header.
1016                     new_exception_header->handlerCount = -new_exception_header->handlerCount;
1017                     globals->uncaughtExceptions += 1;
1018                     // Call __cxa_end_catch for new_exception_header
1019                     __cxa_end_catch();
1020                     // Call __cxa_end_catch for old_exception_header
1021                     __cxa_end_catch();
1022                     // Renter this catch clause with new_exception_header
1023                     __cxa_begin_catch(&new_exception_header->unwindHeader);
1024                     // Rethrow new_exception_header
1025                     throw;
1026                 }
1027             }
1028             // Will a std::bad_exception be catchable by the exception spec at
1029             //   ttypeIndex?
1030             // If no
1031             //    throw std::bad_exception();
1032             const __shim_type_info* excpType =
1033                 static_cast<const __shim_type_info*>(&typeid(std::bad_exception));
1034             std::bad_exception be;
1035             adjustedPtr = &be;
1036             if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding,
1037                                           excpType, adjustedPtr, unwind_exception))
1038             {
1039                 // We need to __cxa_end_catch for both the old exception and the
1040                 //   new exception.  Technically we should do it in that order.
1041                 //   But it is expedient to do it in the opposite order:
1042                 // Call __cxa_end_catch for new_exception_header
1043                 __cxa_end_catch();
1044                 // Throw std::bad_exception will __cxa_end_catch for
1045                 //   old_exception_header
1046                 throw be;
1047             }
1048         }
1049     }
1050     std::__terminate(t_handler);
1051 }
1052
1053 }  // extern "C"
1054
1055 }  // __cxxabiv1