• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <assert.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <typeinfo>
19 
20 #include "__cxxabi_config.h"
21 #include "cxa_exception.hpp"
22 #include "cxa_handlers.hpp"
23 #include "private_typeinfo.h"
24 #include "unwind.h"
25 
26 #if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
27 #include <windows.h>
28 #include <winnt.h>
29 
30 extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD,
31                                                        void *, PCONTEXT,
32                                                        PDISPATCHER_CONTEXT,
33                                                        _Unwind_Personality_Fn);
34 #endif
35 
36 /*
37     Exception Header Layout:
38 
39 +---------------------------+-----------------------------+---------------+
40 | __cxa_exception           | _Unwind_Exception CLNGC++\0 | thrown object |
41 +---------------------------+-----------------------------+---------------+
42                                                           ^
43                                                           |
44   +-------------------------------------------------------+
45   |
46 +---------------------------+-----------------------------+
47 | __cxa_dependent_exception | _Unwind_Exception CLNGC++\1 |
48 +---------------------------+-----------------------------+
49 
50     Exception Handling Table Layout:
51 
52 +-----------------+--------+
53 | lpStartEncoding | (char) |
54 +---------+-------+--------+---------------+-----------------------+
55 | lpStart | (encoded with lpStartEncoding) | defaults to funcStart |
56 +---------+-----+--------+-----------------+---------------+-------+
57 | ttypeEncoding | (char) | Encoding of the type_info table |
58 +---------------+-+------+----+----------------------------+----------------+
59 | classInfoOffset | (ULEB128) | Offset to type_info table, defaults to null |
60 +-----------------++--------+-+----------------------------+----------------+
61 | callSiteEncoding | (char) | Encoding for Call Site Table |
62 +------------------+--+-----+-----+------------------------+--------------------------+
63 | callSiteTableLength | (ULEB128) | Call Site Table length, used to find Action table |
64 +---------------------+-----------+---------------------------------------------------+
65 #ifndef __USING_SJLJ_EXCEPTIONS__
66 +---------------------+-----------+------------------------------------------------+
67 | Beginning of Call Site Table            The current ip lies within the           |
68 | ...                                     (start, length) range of one of these    |
69 |                                         call sites. There may be action needed.  |
70 | +-------------+---------------------------------+------------------------------+ |
71 | | start       | (encoded with callSiteEncoding) | offset relative to funcStart | |
72 | | length      | (encoded with callSiteEncoding) | length of code fragment      | |
73 | | landingPad  | (encoded with callSiteEncoding) | offset relative to lpStart   | |
74 | | actionEntry | (ULEB128)                       | Action Table Index 1-based   | |
75 | |             |                                 | actionEntry == 0 -> cleanup  | |
76 | +-------------+---------------------------------+------------------------------+ |
77 | ...                                                                              |
78 +----------------------------------------------------------------------------------+
79 #else  // __USING_SJLJ_EXCEPTIONS__
80 +---------------------+-----------+------------------------------------------------+
81 | Beginning of Call Site Table            The current ip is a 1-based index into   |
82 | ...                                     this table.  Or it is -1 meaning no      |
83 |                                         action is needed.  Or it is 0 meaning    |
84 |                                         terminate.                               |
85 | +-------------+---------------------------------+------------------------------+ |
86 | | landingPad  | (ULEB128)                       | offset relative to lpStart   | |
87 | | actionEntry | (ULEB128)                       | Action Table Index 1-based   | |
88 | |             |                                 | actionEntry == 0 -> cleanup  | |
89 | +-------------+---------------------------------+------------------------------+ |
90 | ...                                                                              |
91 +----------------------------------------------------------------------------------+
92 #endif  // __USING_SJLJ_EXCEPTIONS__
93 +---------------------------------------------------------------------+
94 | Beginning of Action Table       ttypeIndex == 0 : cleanup           |
95 | ...                             ttypeIndex  > 0 : catch             |
96 |                                 ttypeIndex  < 0 : exception spec    |
97 | +--------------+-----------+--------------------------------------+ |
98 | | ttypeIndex   | (SLEB128) | Index into type_info Table (1-based) | |
99 | | actionOffset | (SLEB128) | Offset into next Action Table entry  | |
100 | +--------------+-----------+--------------------------------------+ |
101 | ...                                                                 |
102 +---------------------------------------------------------------------+-----------------+
103 | type_info Table, but classInfoOffset does *not* point here!                           |
104 | +----------------+------------------------------------------------+-----------------+ |
105 | | Nth type_info* | Encoded with ttypeEncoding, 0 means catch(...) | ttypeIndex == N | |
106 | +----------------+------------------------------------------------+-----------------+ |
107 | ...                                                                                   |
108 | +----------------+------------------------------------------------+-----------------+ |
109 | | 1st type_info* | Encoded with ttypeEncoding, 0 means catch(...) | ttypeIndex == 1 | |
110 | +----------------+------------------------------------------------+-----------------+ |
111 | +---------------------------------------+-----------+------------------------------+  |
112 | | 1st ttypeIndex for 1st exception spec | (ULEB128) | classInfoOffset points here! |  |
113 | | ...                                   | (ULEB128) |                              |  |
114 | | Mth ttypeIndex for 1st exception spec | (ULEB128) |                              |  |
115 | | 0                                     | (ULEB128) |                              |  |
116 | +---------------------------------------+------------------------------------------+  |
117 | ...                                                                                   |
118 | +---------------------------------------+------------------------------------------+  |
119 | | 0                                     | (ULEB128) | throw()                      |  |
120 | +---------------------------------------+------------------------------------------+  |
121 | ...                                                                                   |
122 | +---------------------------------------+------------------------------------------+  |
123 | | 1st ttypeIndex for Nth exception spec | (ULEB128) |                              |  |
124 | | ...                                   | (ULEB128) |                              |  |
125 | | Mth ttypeIndex for Nth exception spec | (ULEB128) |                              |  |
126 | | 0                                     | (ULEB128) |                              |  |
127 | +---------------------------------------+------------------------------------------+  |
128 +---------------------------------------------------------------------------------------+
129 
130 Notes:
131 
132 *  ttypeIndex in the Action Table, and in the exception spec table, is an index,
133      not a byte count, if positive.  It is a negative index offset of
134      classInfoOffset and the sizeof entry depends on ttypeEncoding.
135    But if ttypeIndex is negative, it is a positive 1-based byte offset into the
136      type_info Table.
137    And if ttypeIndex is zero, it refers to a catch (...).
138 
139 *  landingPad can be 0, this implies there is nothing to be done.
140 
141 *  landingPad != 0 and actionEntry == 0 implies a cleanup needs to be done
142      @landingPad.
143 
144 *  A cleanup can also be found under landingPad != 0 and actionEntry != 0 in
145      the Action Table with ttypeIndex == 0.
146 */
147 
148 namespace __cxxabiv1
149 {
150 
151 namespace
152 {
153 
154 template <class AsType>
readPointerHelper(const uint8_t * & p)155 uintptr_t readPointerHelper(const uint8_t*& p) {
156     AsType value;
157     memcpy(&value, p, sizeof(AsType));
158     p += sizeof(AsType);
159     return static_cast<uintptr_t>(value);
160 }
161 
162 } // end namespace
163 
164 extern "C"
165 {
166 
167 // private API
168 
169 // Heavily borrowed from llvm/examples/ExceptionDemo/ExceptionDemo.cpp
170 
171 // DWARF Constants
172 enum
173 {
174     DW_EH_PE_absptr   = 0x00,
175     DW_EH_PE_uleb128  = 0x01,
176     DW_EH_PE_udata2   = 0x02,
177     DW_EH_PE_udata4   = 0x03,
178     DW_EH_PE_udata8   = 0x04,
179     DW_EH_PE_sleb128  = 0x09,
180     DW_EH_PE_sdata2   = 0x0A,
181     DW_EH_PE_sdata4   = 0x0B,
182     DW_EH_PE_sdata8   = 0x0C,
183     DW_EH_PE_pcrel    = 0x10,
184     DW_EH_PE_textrel  = 0x20,
185     DW_EH_PE_datarel  = 0x30,
186     DW_EH_PE_funcrel  = 0x40,
187     DW_EH_PE_aligned  = 0x50,
188     DW_EH_PE_indirect = 0x80,
189     DW_EH_PE_omit     = 0xFF
190 };
191 
192 /// Read a uleb128 encoded value and advance pointer
193 /// See Variable Length Data Appendix C in:
194 /// @link http://dwarfstd.org/Dwarf4.pdf @unlink
195 /// @param data reference variable holding memory pointer to decode from
196 /// @returns decoded value
197 static
198 uintptr_t
readULEB128(const uint8_t ** data)199 readULEB128(const uint8_t** data)
200 {
201     uintptr_t result = 0;
202     uintptr_t shift = 0;
203     unsigned char byte;
204     const uint8_t *p = *data;
205     do
206     {
207         byte = *p++;
208         result |= static_cast<uintptr_t>(byte & 0x7F) << shift;
209         shift += 7;
210     } while (byte & 0x80);
211     *data = p;
212     return result;
213 }
214 
215 /// Read a sleb128 encoded value and advance pointer
216 /// See Variable Length Data Appendix C in:
217 /// @link http://dwarfstd.org/Dwarf4.pdf @unlink
218 /// @param data reference variable holding memory pointer to decode from
219 /// @returns decoded value
220 static
221 intptr_t
readSLEB128(const uint8_t ** data)222 readSLEB128(const uint8_t** data)
223 {
224     uintptr_t result = 0;
225     uintptr_t shift = 0;
226     unsigned char byte;
227     const uint8_t *p = *data;
228     do
229     {
230         byte = *p++;
231         result |= static_cast<uintptr_t>(byte & 0x7F) << shift;
232         shift += 7;
233     } while (byte & 0x80);
234     *data = p;
235     if ((byte & 0x40) && (shift < (sizeof(result) << 3)))
236         result |= static_cast<uintptr_t>(~0) << shift;
237     return static_cast<intptr_t>(result);
238 }
239 
240 /// Read a pointer encoded value and advance pointer
241 /// See Variable Length Data in:
242 /// @link http://dwarfstd.org/Dwarf3.pdf @unlink
243 /// @param data reference variable holding memory pointer to decode from
244 /// @param encoding dwarf encoding type
245 /// @returns decoded value
246 static
247 uintptr_t
readEncodedPointer(const uint8_t ** data,uint8_t encoding)248 readEncodedPointer(const uint8_t** data, uint8_t encoding)
249 {
250     uintptr_t result = 0;
251     if (encoding == DW_EH_PE_omit)
252         return result;
253     const uint8_t* p = *data;
254     // first get value
255     switch (encoding & 0x0F)
256     {
257     case DW_EH_PE_absptr:
258         result = readPointerHelper<uintptr_t>(p);
259         break;
260     case DW_EH_PE_uleb128:
261         result = readULEB128(&p);
262         break;
263     case DW_EH_PE_sleb128:
264         result = static_cast<uintptr_t>(readSLEB128(&p));
265         break;
266     case DW_EH_PE_udata2:
267         result = readPointerHelper<uint16_t>(p);
268         break;
269     case DW_EH_PE_udata4:
270         result = readPointerHelper<uint32_t>(p);
271         break;
272     case DW_EH_PE_udata8:
273         result = readPointerHelper<uint64_t>(p);
274         break;
275     case DW_EH_PE_sdata2:
276         result = readPointerHelper<int16_t>(p);
277         break;
278     case DW_EH_PE_sdata4:
279         result = readPointerHelper<int32_t>(p);
280         break;
281     case DW_EH_PE_sdata8:
282         result = readPointerHelper<int64_t>(p);
283         break;
284     default:
285         // not supported
286         abort();
287         break;
288     }
289     // then add relative offset
290     switch (encoding & 0x70)
291     {
292     case DW_EH_PE_absptr:
293         // do nothing
294         break;
295     case DW_EH_PE_pcrel:
296         if (result)
297             result += (uintptr_t)(*data);
298         break;
299     case DW_EH_PE_textrel:
300     case DW_EH_PE_datarel:
301     case DW_EH_PE_funcrel:
302     case DW_EH_PE_aligned:
303     default:
304         // not supported
305         abort();
306         break;
307     }
308     // then apply indirection
309     if (result && (encoding & DW_EH_PE_indirect))
310         result = *((uintptr_t*)result);
311     *data = p;
312     return result;
313 }
314 
315 static
316 void
call_terminate(bool native_exception,_Unwind_Exception * unwind_exception)317 call_terminate(bool native_exception, _Unwind_Exception* unwind_exception)
318 {
319     __cxa_begin_catch(unwind_exception);
320     if (native_exception)
321     {
322         // Use the stored terminate_handler if possible
323         __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
324         std::__terminate(exception_header->terminateHandler);
325     }
326     std::terminate();
327 }
328 
329 #if defined(_LIBCXXABI_ARM_EHABI)
read_target2_value(const void * ptr)330 static const void* read_target2_value(const void* ptr)
331 {
332     uintptr_t offset = *reinterpret_cast<const uintptr_t*>(ptr);
333     if (!offset)
334         return 0;
335     // "ARM EABI provides a TARGET2 relocation to describe these typeinfo
336     // pointers. The reason being it allows their precise semantics to be
337     // deferred to the linker. For bare-metal they turn into absolute
338     // relocations. For linux they turn into GOT-REL relocations."
339     // https://gcc.gnu.org/ml/gcc-patches/2009-08/msg00264.html
340 #if defined(LIBCXXABI_BAREMETAL)
341     return reinterpret_cast<const void*>(reinterpret_cast<uintptr_t>(ptr) +
342                                          offset);
343 #else
344     return *reinterpret_cast<const void **>(reinterpret_cast<uintptr_t>(ptr) +
345                                             offset);
346 #endif
347 }
348 
349 static const __shim_type_info*
get_shim_type_info(uint64_t ttypeIndex,const uint8_t * classInfo,uint8_t ttypeEncoding,bool native_exception,_Unwind_Exception * unwind_exception)350 get_shim_type_info(uint64_t ttypeIndex, const uint8_t* classInfo,
351                    uint8_t ttypeEncoding, bool native_exception,
352                    _Unwind_Exception* unwind_exception)
353 {
354     if (classInfo == 0)
355     {
356         // this should not happen.  Indicates corrupted eh_table.
357         call_terminate(native_exception, unwind_exception);
358     }
359 
360     assert(((ttypeEncoding == DW_EH_PE_absptr) ||  // LLVM or GCC 4.6
361             (ttypeEncoding == DW_EH_PE_pcrel) ||  // GCC 4.7 baremetal
362             (ttypeEncoding == (DW_EH_PE_pcrel | DW_EH_PE_indirect))) &&  // GCC 4.7 linux
363            "Unexpected TTypeEncoding");
364     (void)ttypeEncoding;
365 
366     const uint8_t* ttypePtr = classInfo - ttypeIndex * sizeof(uintptr_t);
367     return reinterpret_cast<const __shim_type_info *>(
368         read_target2_value(ttypePtr));
369 }
370 #else // !defined(_LIBCXXABI_ARM_EHABI)
371 static
372 const __shim_type_info*
get_shim_type_info(uint64_t ttypeIndex,const uint8_t * classInfo,uint8_t ttypeEncoding,bool native_exception,_Unwind_Exception * unwind_exception)373 get_shim_type_info(uint64_t ttypeIndex, const uint8_t* classInfo,
374                    uint8_t ttypeEncoding, bool native_exception,
375                    _Unwind_Exception* unwind_exception)
376 {
377     if (classInfo == 0)
378     {
379         // this should not happen.  Indicates corrupted eh_table.
380         call_terminate(native_exception, unwind_exception);
381     }
382     switch (ttypeEncoding & 0x0F)
383     {
384     case DW_EH_PE_absptr:
385         ttypeIndex *= sizeof(void*);
386         break;
387     case DW_EH_PE_udata2:
388     case DW_EH_PE_sdata2:
389         ttypeIndex *= 2;
390         break;
391     case DW_EH_PE_udata4:
392     case DW_EH_PE_sdata4:
393         ttypeIndex *= 4;
394         break;
395     case DW_EH_PE_udata8:
396     case DW_EH_PE_sdata8:
397         ttypeIndex *= 8;
398         break;
399     default:
400         // this should not happen.   Indicates corrupted eh_table.
401         call_terminate(native_exception, unwind_exception);
402     }
403     classInfo -= ttypeIndex;
404     return (const __shim_type_info*)readEncodedPointer(&classInfo, ttypeEncoding);
405 }
406 #endif // !defined(_LIBCXXABI_ARM_EHABI)
407 
408 /*
409     This is checking a thrown exception type, excpType, against a possibly empty
410     list of catchType's which make up an exception spec.
411 
412     An exception spec acts like a catch handler, but in reverse.  This "catch
413     handler" will catch an excpType if and only if none of the catchType's in
414     the list will catch a excpType.  If any catchType in the list can catch an
415     excpType, then this exception spec does not catch the excpType.
416 */
417 #if defined(_LIBCXXABI_ARM_EHABI)
418 static
419 bool
exception_spec_can_catch(int64_t specIndex,const uint8_t * classInfo,uint8_t ttypeEncoding,const __shim_type_info * excpType,void * adjustedPtr,_Unwind_Exception * unwind_exception)420 exception_spec_can_catch(int64_t specIndex, const uint8_t* classInfo,
421                          uint8_t ttypeEncoding, const __shim_type_info* excpType,
422                          void* adjustedPtr, _Unwind_Exception* unwind_exception)
423 {
424     if (classInfo == 0)
425     {
426         // this should not happen.   Indicates corrupted eh_table.
427         call_terminate(false, unwind_exception);
428     }
429 
430     assert(((ttypeEncoding == DW_EH_PE_absptr) ||  // LLVM or GCC 4.6
431             (ttypeEncoding == DW_EH_PE_pcrel) ||  // GCC 4.7 baremetal
432             (ttypeEncoding == (DW_EH_PE_pcrel | DW_EH_PE_indirect))) &&  // GCC 4.7 linux
433            "Unexpected TTypeEncoding");
434     (void)ttypeEncoding;
435 
436     // specIndex is negative of 1-based byte offset into classInfo;
437     specIndex = -specIndex;
438     --specIndex;
439     const void** temp = reinterpret_cast<const void**>(
440         reinterpret_cast<uintptr_t>(classInfo) +
441         static_cast<uintptr_t>(specIndex) * sizeof(uintptr_t));
442     // If any type in the spec list can catch excpType, return false, else return true
443     //    adjustments to adjustedPtr are ignored.
444     while (true)
445     {
446         // ARM EHABI exception specification table (filter table) consists of
447         // several pointers which will directly point to the type info object
448         // (instead of ttypeIndex).  The table will be terminated with 0.
449         const void** ttypePtr = temp++;
450         if (*ttypePtr == 0)
451             break;
452         // We can get the __shim_type_info simply by performing a
453         // R_ARM_TARGET2 relocation, and cast the result to __shim_type_info.
454         const __shim_type_info* catchType =
455             static_cast<const __shim_type_info*>(read_target2_value(ttypePtr));
456         void* tempPtr = adjustedPtr;
457         if (catchType->can_catch(excpType, tempPtr))
458             return false;
459     }
460     return true;
461 }
462 #else
463 static
464 bool
exception_spec_can_catch(int64_t specIndex,const uint8_t * classInfo,uint8_t ttypeEncoding,const __shim_type_info * excpType,void * adjustedPtr,_Unwind_Exception * unwind_exception)465 exception_spec_can_catch(int64_t specIndex, const uint8_t* classInfo,
466                          uint8_t ttypeEncoding, const __shim_type_info* excpType,
467                          void* adjustedPtr, _Unwind_Exception* unwind_exception)
468 {
469     if (classInfo == 0)
470     {
471         // this should not happen.   Indicates corrupted eh_table.
472         call_terminate(false, unwind_exception);
473     }
474     // specIndex is negative of 1-based byte offset into classInfo;
475     specIndex = -specIndex;
476     --specIndex;
477     const uint8_t* temp = classInfo + specIndex;
478     // If any type in the spec list can catch excpType, return false, else return true
479     //    adjustments to adjustedPtr are ignored.
480     while (true)
481     {
482         uint64_t ttypeIndex = readULEB128(&temp);
483         if (ttypeIndex == 0)
484             break;
485         const __shim_type_info* catchType = get_shim_type_info(ttypeIndex,
486                                                                classInfo,
487                                                                ttypeEncoding,
488                                                                true,
489                                                                unwind_exception);
490         void* tempPtr = adjustedPtr;
491         if (catchType->can_catch(excpType, tempPtr))
492             return false;
493     }
494     return true;
495 }
496 #endif
497 
498 static
499 void*
get_thrown_object_ptr(_Unwind_Exception * unwind_exception)500 get_thrown_object_ptr(_Unwind_Exception* unwind_exception)
501 {
502     // Even for foreign exceptions, the exception object is *probably* at unwind_exception + 1
503     //    Regardless, this library is prohibited from touching a foreign exception
504     void* adjustedPtr = unwind_exception + 1;
505     if (__getExceptionClass(unwind_exception) == kOurDependentExceptionClass)
506         adjustedPtr = ((__cxa_dependent_exception*)adjustedPtr - 1)->primaryException;
507     return adjustedPtr;
508 }
509 
510 namespace
511 {
512 
513 struct scan_results
514 {
515     int64_t        ttypeIndex;   // > 0 catch handler, < 0 exception spec handler, == 0 a cleanup
516     const uint8_t* actionRecord;         // Currently unused.  Retained to ease future maintenance.
517     const uint8_t* languageSpecificData;  // Needed only for __cxa_call_unexpected
518     uintptr_t      landingPad;   // null -> nothing found, else something found
519     void*          adjustedPtr;  // Used in cxa_exception.cpp
520     _Unwind_Reason_Code reason;  // One of _URC_FATAL_PHASE1_ERROR,
521                                  //        _URC_FATAL_PHASE2_ERROR,
522                                  //        _URC_CONTINUE_UNWIND,
523                                  //        _URC_HANDLER_FOUND
524 };
525 
526 }  // unnamed namespace
527 
528 static
529 void
set_registers(_Unwind_Exception * unwind_exception,_Unwind_Context * context,const scan_results & results)530 set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context,
531               const scan_results& results)
532 {
533 #if defined(__USING_SJLJ_EXCEPTIONS__)
534 #define __builtin_eh_return_data_regno(regno) regno
535 #endif
536   _Unwind_SetGR(context, __builtin_eh_return_data_regno(0),
537                 reinterpret_cast<uintptr_t>(unwind_exception));
538   _Unwind_SetGR(context, __builtin_eh_return_data_regno(1),
539                 static_cast<uintptr_t>(results.ttypeIndex));
540   _Unwind_SetIP(context, results.landingPad);
541 }
542 
543 /*
544     There are 3 types of scans needed:
545 
546     1.  Scan for handler with native or foreign exception.  If handler found,
547         save state and return _URC_HANDLER_FOUND, else return _URC_CONTINUE_UNWIND.
548         May also report an error on invalid input.
549         May terminate for invalid exception table.
550         _UA_SEARCH_PHASE
551 
552     2.  Scan for handler with foreign exception.  Must return _URC_HANDLER_FOUND,
553         or call terminate.
554         _UA_CLEANUP_PHASE && _UA_HANDLER_FRAME && !native_exception
555 
556     3.  Scan for cleanups.  If a handler is found and this isn't forced unwind,
557         then terminate, otherwise ignore the handler and keep looking for cleanup.
558         If a cleanup is found, return _URC_HANDLER_FOUND, else return _URC_CONTINUE_UNWIND.
559         May also report an error on invalid input.
560         May terminate for invalid exception table.
561         _UA_CLEANUP_PHASE && !_UA_HANDLER_FRAME
562 */
563 
scan_eh_tab(scan_results & results,_Unwind_Action actions,bool native_exception,_Unwind_Exception * unwind_exception,_Unwind_Context * context)564 static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
565                         bool native_exception,
566                         _Unwind_Exception *unwind_exception,
567                         _Unwind_Context *context) {
568     // Initialize results to found nothing but an error
569     results.ttypeIndex = 0;
570     results.actionRecord = 0;
571     results.languageSpecificData = 0;
572     results.landingPad = 0;
573     results.adjustedPtr = 0;
574     results.reason = _URC_FATAL_PHASE1_ERROR;
575     // Check for consistent actions
576     if (actions & _UA_SEARCH_PHASE)
577     {
578         // Do Phase 1
579         if (actions & (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME | _UA_FORCE_UNWIND))
580         {
581             // None of these flags should be set during Phase 1
582             //   Client error
583             results.reason = _URC_FATAL_PHASE1_ERROR;
584             return;
585         }
586     }
587     else if (actions & _UA_CLEANUP_PHASE)
588     {
589         if ((actions & _UA_HANDLER_FRAME) && (actions & _UA_FORCE_UNWIND))
590         {
591             // _UA_HANDLER_FRAME should only be set if phase 1 found a handler.
592             // If _UA_FORCE_UNWIND is set, phase 1 shouldn't have happened.
593             //    Client error
594             results.reason = _URC_FATAL_PHASE2_ERROR;
595             return;
596         }
597     }
598     else // Neither _UA_SEARCH_PHASE nor _UA_CLEANUP_PHASE is set
599     {
600         // One of these should be set.
601         //   Client error
602         results.reason = _URC_FATAL_PHASE1_ERROR;
603         return;
604     }
605     // Start scan by getting exception table address
606     const uint8_t *lsda = (const uint8_t *)_Unwind_GetLanguageSpecificData(context);
607     if (lsda == 0)
608     {
609         // There is no exception table
610         results.reason = _URC_CONTINUE_UNWIND;
611         return;
612     }
613     results.languageSpecificData = lsda;
614     // Get the current instruction pointer and offset it before next
615     // instruction in the current frame which threw the exception.
616     uintptr_t ip = _Unwind_GetIP(context) - 1;
617     // Get beginning current frame's code (as defined by the
618     // emitted dwarf code)
619     uintptr_t funcStart = _Unwind_GetRegionStart(context);
620 #ifdef __USING_SJLJ_EXCEPTIONS__
621     if (ip == uintptr_t(-1))
622     {
623         // no action
624         results.reason = _URC_CONTINUE_UNWIND;
625         return;
626     }
627     else if (ip == 0)
628         call_terminate(native_exception, unwind_exception);
629     // ip is 1-based index into call site table
630 #else  // !__USING_SJLJ_EXCEPTIONS__
631     uintptr_t ipOffset = ip - funcStart;
632 #endif  // !defined(_USING_SLJL_EXCEPTIONS__)
633     const uint8_t* classInfo = NULL;
634     // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding
635     //       dwarf emission
636     // Parse LSDA header.
637     uint8_t lpStartEncoding = *lsda++;
638     const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding);
639     if (lpStart == 0)
640         lpStart = (const uint8_t*)funcStart;
641     uint8_t ttypeEncoding = *lsda++;
642     if (ttypeEncoding != DW_EH_PE_omit)
643     {
644         // Calculate type info locations in emitted dwarf code which
645         // were flagged by type info arguments to llvm.eh.selector
646         // intrinsic
647         uintptr_t classInfoOffset = readULEB128(&lsda);
648         classInfo = lsda + classInfoOffset;
649     }
650     // Walk call-site table looking for range that
651     // includes current PC.
652     uint8_t callSiteEncoding = *lsda++;
653 #ifdef __USING_SJLJ_EXCEPTIONS__
654     (void)callSiteEncoding;  // When using SjLj exceptions, callSiteEncoding is never used
655 #endif
656     uint32_t callSiteTableLength = static_cast<uint32_t>(readULEB128(&lsda));
657     const uint8_t* callSiteTableStart = lsda;
658     const uint8_t* callSiteTableEnd = callSiteTableStart + callSiteTableLength;
659     const uint8_t* actionTableStart = callSiteTableEnd;
660     const uint8_t* callSitePtr = callSiteTableStart;
661     while (callSitePtr < callSiteTableEnd)
662     {
663         // There is one entry per call site.
664 #ifndef __USING_SJLJ_EXCEPTIONS__
665         // The call sites are non-overlapping in [start, start+length)
666         // The call sites are ordered in increasing value of start
667         uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding);
668         uintptr_t length = readEncodedPointer(&callSitePtr, callSiteEncoding);
669         uintptr_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding);
670         uintptr_t actionEntry = readULEB128(&callSitePtr);
671         if ((start <= ipOffset) && (ipOffset < (start + length)))
672 #else  // __USING_SJLJ_EXCEPTIONS__
673         // ip is 1-based index into this table
674         uintptr_t landingPad = readULEB128(&callSitePtr);
675         uintptr_t actionEntry = readULEB128(&callSitePtr);
676         if (--ip == 0)
677 #endif  // __USING_SJLJ_EXCEPTIONS__
678         {
679             // Found the call site containing ip.
680 #ifndef __USING_SJLJ_EXCEPTIONS__
681             if (landingPad == 0)
682             {
683                 // No handler here
684                 results.reason = _URC_CONTINUE_UNWIND;
685                 return;
686             }
687             landingPad = (uintptr_t)lpStart + landingPad;
688 #else  // __USING_SJLJ_EXCEPTIONS__
689             ++landingPad;
690 #endif  // __USING_SJLJ_EXCEPTIONS__
691             if (actionEntry == 0)
692             {
693                 // Found a cleanup
694                 // If this is a type 1 or type 2 search, there are no handlers
695                 // If this is a type 3 search, you want to install the cleanup.
696                 if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME))
697                 {
698                     results.ttypeIndex = 0;  // Redundant but clarifying
699                     results.landingPad = landingPad;
700                     results.reason = _URC_HANDLER_FOUND;
701                     return;
702                 }
703                 // No handler here
704                 results.reason = _URC_CONTINUE_UNWIND;
705                 return;
706             }
707             // Convert 1-based byte offset into
708             const uint8_t* action = actionTableStart + (actionEntry - 1);
709             // Scan action entries until you find a matching handler, cleanup, or the end of action list
710             while (true)
711             {
712                 const uint8_t* actionRecord = action;
713                 int64_t ttypeIndex = readSLEB128(&action);
714                 if (ttypeIndex > 0)
715                 {
716                     // Found a catch, does it actually catch?
717                     // First check for catch (...)
718                     const __shim_type_info* catchType =
719                         get_shim_type_info(static_cast<uint64_t>(ttypeIndex),
720                                            classInfo, ttypeEncoding,
721                                            native_exception, unwind_exception);
722                     if (catchType == 0)
723                     {
724                         // Found catch (...) catches everything, including foreign exceptions
725                         // If this is a type 1 search save state and return _URC_HANDLER_FOUND
726                         // If this is a type 2 search save state and return _URC_HANDLER_FOUND
727                         // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1!
728                         // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan
729                         if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME))
730                         {
731                             // Save state and return _URC_HANDLER_FOUND
732                             results.ttypeIndex = ttypeIndex;
733                             results.actionRecord = actionRecord;
734                             results.landingPad = landingPad;
735                             results.adjustedPtr = get_thrown_object_ptr(unwind_exception);
736                             results.reason = _URC_HANDLER_FOUND;
737                             return;
738                         }
739                         else if (!(actions & _UA_FORCE_UNWIND))
740                         {
741                             // It looks like the exception table has changed
742                             //    on us.  Likely stack corruption!
743                             call_terminate(native_exception, unwind_exception);
744                         }
745                     }
746                     // Else this is a catch (T) clause and will never
747                     //    catch a foreign exception
748                     else if (native_exception)
749                     {
750                         __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
751                         void* adjustedPtr = get_thrown_object_ptr(unwind_exception);
752                         const __shim_type_info* excpType =
753                             static_cast<const __shim_type_info*>(exception_header->exceptionType);
754                         if (adjustedPtr == 0 || excpType == 0)
755                         {
756                             // Something very bad happened
757                             call_terminate(native_exception, unwind_exception);
758                         }
759                         if (catchType->can_catch(excpType, adjustedPtr))
760                         {
761                             // Found a matching handler
762                             // If this is a type 1 search save state and return _URC_HANDLER_FOUND
763                             // If this is a type 3 search and !_UA_FORCE_UNWIND, we should have found this in phase 1!
764                             // If this is a type 3 search and _UA_FORCE_UNWIND, ignore handler and continue scan
765                             if (actions & _UA_SEARCH_PHASE)
766                             {
767                                 // Save state and return _URC_HANDLER_FOUND
768                                 results.ttypeIndex = ttypeIndex;
769                                 results.actionRecord = actionRecord;
770                                 results.landingPad = landingPad;
771                                 results.adjustedPtr = adjustedPtr;
772                                 results.reason = _URC_HANDLER_FOUND;
773                                 return;
774                             }
775                             else if (!(actions & _UA_FORCE_UNWIND))
776                             {
777                                 // It looks like the exception table has changed
778                                 //    on us.  Likely stack corruption!
779                                 call_terminate(native_exception, unwind_exception);
780                             }
781                         }
782                     }
783                     // Scan next action ...
784                 }
785                 else if (ttypeIndex < 0)
786                 {
787                     // Found an exception spec.  If this is a foreign exception,
788                     //   it is always caught.
789                     if (native_exception)
790                     {
791                         // Does the exception spec catch this native exception?
792                         __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
793                         void* adjustedPtr = get_thrown_object_ptr(unwind_exception);
794                         const __shim_type_info* excpType =
795                             static_cast<const __shim_type_info*>(exception_header->exceptionType);
796                         if (adjustedPtr == 0 || excpType == 0)
797                         {
798                             // Something very bad happened
799                             call_terminate(native_exception, unwind_exception);
800                         }
801                         if (exception_spec_can_catch(ttypeIndex, classInfo,
802                                                      ttypeEncoding, excpType,
803                                                      adjustedPtr, unwind_exception))
804                         {
805                             // native exception caught by exception spec
806                             // If this is a type 1 search, save state and return _URC_HANDLER_FOUND
807                             // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1!
808                             // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan
809                             if (actions & _UA_SEARCH_PHASE)
810                             {
811                                 // Save state and return _URC_HANDLER_FOUND
812                                 results.ttypeIndex = ttypeIndex;
813                                 results.actionRecord = actionRecord;
814                                 results.landingPad = landingPad;
815                                 results.adjustedPtr = adjustedPtr;
816                                 results.reason = _URC_HANDLER_FOUND;
817                                 return;
818                             }
819                             else if (!(actions & _UA_FORCE_UNWIND))
820                             {
821                                 // It looks like the exception table has changed
822                                 //    on us.  Likely stack corruption!
823                                 call_terminate(native_exception, unwind_exception);
824                             }
825                         }
826                     }
827                     else
828                     {
829                         // foreign exception caught by exception spec
830                         // If this is a type 1 search, save state and return _URC_HANDLER_FOUND
831                         // If this is a type 2 search, save state and return _URC_HANDLER_FOUND
832                         // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1!
833                         // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan
834                         if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME))
835                         {
836                             // Save state and return _URC_HANDLER_FOUND
837                             results.ttypeIndex = ttypeIndex;
838                             results.actionRecord = actionRecord;
839                             results.landingPad = landingPad;
840                             results.adjustedPtr = get_thrown_object_ptr(unwind_exception);
841                             results.reason = _URC_HANDLER_FOUND;
842                             return;
843                         }
844                         else if (!(actions & _UA_FORCE_UNWIND))
845                         {
846                             // It looks like the exception table has changed
847                             //    on us.  Likely stack corruption!
848                             call_terminate(native_exception, unwind_exception);
849                         }
850                     }
851                     // Scan next action ...
852                 }
853                 else  // ttypeIndex == 0
854                 {
855                     // Found a cleanup
856                     // If this is a type 1 search, ignore it and continue scan
857                     // If this is a type 2 search, ignore it and continue scan
858                     // If this is a type 3 search, save state and return _URC_HANDLER_FOUND
859                     if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME))
860                     {
861                         // Save state and return _URC_HANDLER_FOUND
862                         results.ttypeIndex = ttypeIndex;
863                         results.actionRecord = actionRecord;
864                         results.landingPad = landingPad;
865                         results.adjustedPtr = get_thrown_object_ptr(unwind_exception);
866                         results.reason = _URC_HANDLER_FOUND;
867                         return;
868                     }
869                 }
870                 const uint8_t* temp = action;
871                 int64_t actionOffset = readSLEB128(&temp);
872                 if (actionOffset == 0)
873                 {
874                     // End of action list, no matching handler or cleanup found
875                     results.reason = _URC_CONTINUE_UNWIND;
876                     return;
877                 }
878                 // Go to next action
879                 action += actionOffset;
880             }  // there is no break out of this loop, only return
881         }
882 #ifndef __USING_SJLJ_EXCEPTIONS__
883         else if (ipOffset < start)
884         {
885             // There is no call site for this ip
886             // Something bad has happened.  We should never get here.
887             // Possible stack corruption.
888             call_terminate(native_exception, unwind_exception);
889         }
890 #endif  // !__USING_SJLJ_EXCEPTIONS__
891     }  // there might be some tricky cases which break out of this loop
892 
893     // It is possible that no eh table entry specify how to handle
894     // this exception. By spec, terminate it immediately.
895     call_terminate(native_exception, unwind_exception);
896 }
897 
898 // public API
899 
900 /*
901 The personality function branches on actions like so:
902 
903 _UA_SEARCH_PHASE
904 
905     If _UA_CLEANUP_PHASE or _UA_HANDLER_FRAME or _UA_FORCE_UNWIND there's
906       an error from above, return _URC_FATAL_PHASE1_ERROR.
907 
908     Scan for anything that could stop unwinding:
909 
910        1.  A catch clause that will catch this exception
911            (will never catch foreign).
912        2.  A catch (...) (will always catch foreign).
913        3.  An exception spec that will catch this exception
914            (will always catch foreign).
915     If a handler is found
916         If not foreign
917             Save state in header
918         return _URC_HANDLER_FOUND
919     Else a handler not found
920         return _URC_CONTINUE_UNWIND
921 
922 _UA_CLEANUP_PHASE
923 
924     If _UA_HANDLER_FRAME
925         If _UA_FORCE_UNWIND
926             How did this happen?  return _URC_FATAL_PHASE2_ERROR
927         If foreign
928             Do _UA_SEARCH_PHASE to recover state
929         else
930             Recover state from header
931         Transfer control to landing pad.  return _URC_INSTALL_CONTEXT
932 
933     Else
934 
935         This branch handles both normal C++ non-catching handlers (cleanups)
936           and forced unwinding.
937         Scan for anything that can not stop unwinding:
938 
939             1.  A cleanup.
940 
941         If a cleanup is found
942             transfer control to it. return _URC_INSTALL_CONTEXT
943         Else a cleanup is not found: return _URC_CONTINUE_UNWIND
944 */
945 
946 #if !defined(_LIBCXXABI_ARM_EHABI)
947 #if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
__gxx_personality_imp(int version,_Unwind_Action actions,uint64_t exceptionClass,_Unwind_Exception * unwind_exception,_Unwind_Context * context)948 static _Unwind_Reason_Code __gxx_personality_imp
949 #else
950 _LIBCXXABI_FUNC_VIS _Unwind_Reason_Code
951 #ifdef __USING_SJLJ_EXCEPTIONS__
952 __gxx_personality_sj0
953 #else
954 __gxx_personality_v0
955 #endif
956 #endif
957                     (int version, _Unwind_Action actions, uint64_t exceptionClass,
958                      _Unwind_Exception* unwind_exception, _Unwind_Context* context)
959 {
960     if (version != 1 || unwind_exception == 0 || context == 0)
961         return _URC_FATAL_PHASE1_ERROR;
962 
963     bool native_exception = (exceptionClass     & get_vendor_and_language) ==
964                             (kOurExceptionClass & get_vendor_and_language);
965     scan_results results;
966     if (actions & _UA_SEARCH_PHASE)
967     {
968         // Phase 1 search:  All we're looking for in phase 1 is a handler that
969         //   halts unwinding
970         scan_eh_tab(results, actions, native_exception, unwind_exception, context);
971         if (results.reason == _URC_HANDLER_FOUND)
972         {
973             // Found one.  Can we cache the results somewhere to optimize phase 2?
974             if (native_exception)
975             {
976                 __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
977                 exception_header->handlerSwitchValue = static_cast<int>(results.ttypeIndex);
978                 exception_header->actionRecord = results.actionRecord;
979                 exception_header->languageSpecificData = results.languageSpecificData;
980                 exception_header->catchTemp = reinterpret_cast<void*>(results.landingPad);
981                 exception_header->adjustedPtr = results.adjustedPtr;
982             }
983             return _URC_HANDLER_FOUND;
984         }
985         // Did not find a catching-handler.  Return the results of the scan
986         //    (normally _URC_CONTINUE_UNWIND, but could have been _URC_FATAL_PHASE1_ERROR
987         //     if we were called improperly).
988         return results.reason;
989     }
990     if (actions & _UA_CLEANUP_PHASE)
991     {
992         // Phase 2 search:
993         //  Did we find a catching handler in phase 1?
994         if (actions & _UA_HANDLER_FRAME)
995         {
996             // Yes, phase 1 said we have a catching handler here.
997             // Did we cache the results of the scan?
998             if (native_exception)
999             {
1000                 // Yes, reload the results from the cache.
1001                 __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
1002                 results.ttypeIndex = exception_header->handlerSwitchValue;
1003                 results.actionRecord = exception_header->actionRecord;
1004                 results.languageSpecificData = exception_header->languageSpecificData;
1005                 results.landingPad = reinterpret_cast<uintptr_t>(exception_header->catchTemp);
1006                 results.adjustedPtr = exception_header->adjustedPtr;
1007             }
1008             else
1009             {
1010                 // No, do the scan again to reload the results.
1011                 scan_eh_tab(results, actions, native_exception, unwind_exception, context);
1012                 // Phase 1 told us we would find a handler.  Now in Phase 2 we
1013                 //   didn't find a handler.  The eh table should not be changing!
1014                 if (results.reason != _URC_HANDLER_FOUND)
1015                     call_terminate(native_exception, unwind_exception);
1016             }
1017             // Jump to the handler
1018             set_registers(unwind_exception, context, results);
1019             return _URC_INSTALL_CONTEXT;
1020         }
1021         // Either we didn't do a phase 1 search (due to forced unwinding), or
1022         //   phase 1 reported no catching-handlers.
1023         // Search for a (non-catching) cleanup
1024         scan_eh_tab(results, actions, native_exception, unwind_exception, context);
1025         if (results.reason == _URC_HANDLER_FOUND)
1026         {
1027             // Found a non-catching handler.  Jump to it:
1028             set_registers(unwind_exception, context, results);
1029             return _URC_INSTALL_CONTEXT;
1030         }
1031         // Did not find a cleanup.  Return the results of the scan
1032         //    (normally _URC_CONTINUE_UNWIND, but could have been _URC_FATAL_PHASE2_ERROR
1033         //     if we were called improperly).
1034         return results.reason;
1035     }
1036     // We were called improperly: neither a phase 1 or phase 2 search
1037     return _URC_FATAL_PHASE1_ERROR;
1038 }
1039 
1040 #if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
1041 extern "C" _LIBCXXABI_FUNC_VIS EXCEPTION_DISPOSITION
__gxx_personality_seh0(PEXCEPTION_RECORD ms_exc,void * this_frame,PCONTEXT ms_orig_context,PDISPATCHER_CONTEXT ms_disp)1042 __gxx_personality_seh0(PEXCEPTION_RECORD ms_exc, void *this_frame,
1043                        PCONTEXT ms_orig_context, PDISPATCHER_CONTEXT ms_disp)
1044 {
1045   return _GCC_specific_handler(ms_exc, this_frame, ms_orig_context, ms_disp,
1046                                __gxx_personality_imp);
1047 }
1048 #endif
1049 
1050 #else
1051 
1052 extern "C" _Unwind_Reason_Code __gnu_unwind_frame(_Unwind_Exception*,
1053                                                   _Unwind_Context*);
1054 
1055 // Helper function to unwind one frame.
1056 // ARM EHABI 7.3 and 7.4: If the personality function returns _URC_CONTINUE_UNWIND, the
1057 // personality routine should update the virtual register set (VRS) according to the
1058 // corresponding frame unwinding instructions (ARM EHABI 9.3.)
continue_unwind(_Unwind_Exception * unwind_exception,_Unwind_Context * context)1059 static _Unwind_Reason_Code continue_unwind(_Unwind_Exception* unwind_exception,
1060                                            _Unwind_Context* context)
1061 {
1062     if (__gnu_unwind_frame(unwind_exception, context) != _URC_OK)
1063         return _URC_FAILURE;
1064     return _URC_CONTINUE_UNWIND;
1065 }
1066 
1067 // ARM register names
1068 #if !defined(LIBCXXABI_USE_LLVM_UNWINDER)
1069 static const uint32_t REG_UCB = 12;  // Register to save _Unwind_Control_Block
1070 #endif
1071 static const uint32_t REG_SP = 13;
1072 
save_results_to_barrier_cache(_Unwind_Exception * unwind_exception,const scan_results & results)1073 static void save_results_to_barrier_cache(_Unwind_Exception* unwind_exception,
1074                                           const scan_results& results)
1075 {
1076     unwind_exception->barrier_cache.bitpattern[0] = (uint32_t)results.adjustedPtr;
1077     unwind_exception->barrier_cache.bitpattern[1] = (uint32_t)results.actionRecord;
1078     unwind_exception->barrier_cache.bitpattern[2] = (uint32_t)results.languageSpecificData;
1079     unwind_exception->barrier_cache.bitpattern[3] = (uint32_t)results.landingPad;
1080     unwind_exception->barrier_cache.bitpattern[4] = (uint32_t)results.ttypeIndex;
1081 }
1082 
load_results_from_barrier_cache(scan_results & results,const _Unwind_Exception * unwind_exception)1083 static void load_results_from_barrier_cache(scan_results& results,
1084                                             const _Unwind_Exception* unwind_exception)
1085 {
1086     results.adjustedPtr = (void*)unwind_exception->barrier_cache.bitpattern[0];
1087     results.actionRecord = (const uint8_t*)unwind_exception->barrier_cache.bitpattern[1];
1088     results.languageSpecificData = (const uint8_t*)unwind_exception->barrier_cache.bitpattern[2];
1089     results.landingPad = (uintptr_t)unwind_exception->barrier_cache.bitpattern[3];
1090     results.ttypeIndex = (int64_t)(int32_t)unwind_exception->barrier_cache.bitpattern[4];
1091 }
1092 
1093 extern "C" _LIBCXXABI_FUNC_VIS _Unwind_Reason_Code
__gxx_personality_v0(_Unwind_State state,_Unwind_Exception * unwind_exception,_Unwind_Context * context)1094 __gxx_personality_v0(_Unwind_State state,
1095                      _Unwind_Exception* unwind_exception,
1096                      _Unwind_Context* context)
1097 {
1098     if (unwind_exception == 0 || context == 0)
1099         return _URC_FATAL_PHASE1_ERROR;
1100 
1101     bool native_exception = __isOurExceptionClass(unwind_exception);
1102 
1103 #if !defined(LIBCXXABI_USE_LLVM_UNWINDER)
1104     // Copy the address of _Unwind_Control_Block to r12 so that
1105     // _Unwind_GetLanguageSpecificData() and _Unwind_GetRegionStart() can
1106     // return correct address.
1107     _Unwind_SetGR(context, REG_UCB, reinterpret_cast<uint32_t>(unwind_exception));
1108 #endif
1109 
1110     // Check the undocumented force unwinding behavior
1111     bool is_force_unwinding = state & _US_FORCE_UNWIND;
1112     state &= ~_US_FORCE_UNWIND;
1113 
1114     scan_results results;
1115     switch (state) {
1116     case _US_VIRTUAL_UNWIND_FRAME:
1117         if (is_force_unwinding)
1118             return continue_unwind(unwind_exception, context);
1119 
1120         // Phase 1 search:  All we're looking for in phase 1 is a handler that halts unwinding
1121         scan_eh_tab(results, _UA_SEARCH_PHASE, native_exception, unwind_exception, context);
1122         if (results.reason == _URC_HANDLER_FOUND)
1123         {
1124             unwind_exception->barrier_cache.sp = _Unwind_GetGR(context, REG_SP);
1125             if (native_exception)
1126                 save_results_to_barrier_cache(unwind_exception, results);
1127             return _URC_HANDLER_FOUND;
1128         }
1129         // Did not find the catch handler
1130         if (results.reason == _URC_CONTINUE_UNWIND)
1131             return continue_unwind(unwind_exception, context);
1132         return results.reason;
1133 
1134     case _US_UNWIND_FRAME_STARTING:
1135         // TODO: Support force unwinding in the phase 2 search.
1136         // NOTE: In order to call the cleanup functions, _Unwind_ForcedUnwind()
1137         // will call this personality function with (_US_FORCE_UNWIND |
1138         // _US_UNWIND_FRAME_STARTING).
1139 
1140         // Phase 2 search
1141         if (unwind_exception->barrier_cache.sp == _Unwind_GetGR(context, REG_SP))
1142         {
1143             // Found a catching handler in phase 1
1144             if (native_exception)
1145             {
1146                 // Load the result from the native exception barrier cache.
1147                 load_results_from_barrier_cache(results, unwind_exception);
1148                 results.reason = _URC_HANDLER_FOUND;
1149             }
1150             else
1151             {
1152                 // Search for the catching handler again for the foreign exception.
1153                 scan_eh_tab(results, static_cast<_Unwind_Action>(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME),
1154                             native_exception, unwind_exception, context);
1155                 if (results.reason != _URC_HANDLER_FOUND)  // phase1 search should guarantee to find one
1156                     call_terminate(native_exception, unwind_exception);
1157             }
1158 
1159             // Install the context for the catching handler
1160             set_registers(unwind_exception, context, results);
1161             return _URC_INSTALL_CONTEXT;
1162         }
1163 
1164         // Either we didn't do a phase 1 search (due to forced unwinding), or
1165         //  phase 1 reported no catching-handlers.
1166         // Search for a (non-catching) cleanup
1167         scan_eh_tab(results, _UA_CLEANUP_PHASE, native_exception, unwind_exception, context);
1168         if (results.reason == _URC_HANDLER_FOUND)
1169         {
1170             // Found a non-catching handler
1171 
1172             // ARM EHABI 8.4.2: Before we can jump to the cleanup handler, we have to setup some
1173             // internal data structures, so that __cxa_end_cleanup() can get unwind_exception from
1174             // __cxa_get_globals().
1175             __cxa_begin_cleanup(unwind_exception);
1176 
1177             // Install the context for the cleanup handler
1178             set_registers(unwind_exception, context, results);
1179             return _URC_INSTALL_CONTEXT;
1180         }
1181 
1182         // Did not find any handler
1183         if (results.reason == _URC_CONTINUE_UNWIND)
1184             return continue_unwind(unwind_exception, context);
1185         return results.reason;
1186 
1187     case _US_UNWIND_FRAME_RESUME:
1188         return continue_unwind(unwind_exception, context);
1189     }
1190 
1191     // We were called improperly: neither a phase 1 or phase 2 search
1192     return _URC_FATAL_PHASE1_ERROR;
1193 }
1194 #endif
1195 
1196 
1197 __attribute__((noreturn))
1198 _LIBCXXABI_FUNC_VIS void
__cxa_call_unexpected(void * arg)1199 __cxa_call_unexpected(void* arg)
1200 {
1201     _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(arg);
1202     if (unwind_exception == 0)
1203         call_terminate(false, unwind_exception);
1204     __cxa_begin_catch(unwind_exception);
1205     bool native_old_exception = __isOurExceptionClass(unwind_exception);
1206     std::unexpected_handler u_handler;
1207     std::terminate_handler t_handler;
1208     __cxa_exception* old_exception_header = 0;
1209     int64_t ttypeIndex;
1210     const uint8_t* lsda;
1211     if (native_old_exception)
1212     {
1213         old_exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
1214         t_handler = old_exception_header->terminateHandler;
1215         u_handler = old_exception_header->unexpectedHandler;
1216         // If std::__unexpected(u_handler) rethrows the same exception,
1217         //   these values get overwritten by the rethrow.  So save them now:
1218 #if defined(_LIBCXXABI_ARM_EHABI)
1219         ttypeIndex = (int64_t)(int32_t)unwind_exception->barrier_cache.bitpattern[4];
1220         lsda = (const uint8_t*)unwind_exception->barrier_cache.bitpattern[2];
1221 #else
1222         ttypeIndex = old_exception_header->handlerSwitchValue;
1223         lsda = old_exception_header->languageSpecificData;
1224 #endif
1225     }
1226     else
1227     {
1228         t_handler = std::get_terminate();
1229         u_handler = std::get_unexpected();
1230     }
1231     try
1232     {
1233         std::__unexpected(u_handler);
1234     }
1235     catch (...)
1236     {
1237         // If the old exception is foreign, then all we can do is terminate.
1238         //   We have no way to recover the needed old exception spec.  There's
1239         //   no way to pass that information here.  And the personality routine
1240         //   can't call us directly and do anything but terminate() if we throw
1241         //   from here.
1242         if (native_old_exception)
1243         {
1244             // Have:
1245             //   old_exception_header->languageSpecificData
1246             //   old_exception_header->actionRecord
1247             // Need
1248             //   const uint8_t* classInfo
1249             //   uint8_t ttypeEncoding
1250             uint8_t lpStartEncoding = *lsda++;
1251             const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding);
1252             (void)lpStart;  // purposefully unused.  Just needed to increment lsda.
1253             uint8_t ttypeEncoding = *lsda++;
1254             if (ttypeEncoding == DW_EH_PE_omit)
1255                 std::__terminate(t_handler);
1256             uintptr_t classInfoOffset = readULEB128(&lsda);
1257             const uint8_t* classInfo = lsda + classInfoOffset;
1258             // Is this new exception catchable by the exception spec at ttypeIndex?
1259             // The answer is obviously yes if the new and old exceptions are the same exception
1260             // If no
1261             //    throw;
1262             __cxa_eh_globals* globals = __cxa_get_globals_fast();
1263             __cxa_exception* new_exception_header = globals->caughtExceptions;
1264             if (new_exception_header == 0)
1265                 // This shouldn't be able to happen!
1266                 std::__terminate(t_handler);
1267             bool native_new_exception = __isOurExceptionClass(&new_exception_header->unwindHeader);
1268             void* adjustedPtr;
1269             if (native_new_exception && (new_exception_header != old_exception_header))
1270             {
1271                 const __shim_type_info* excpType =
1272                     static_cast<const __shim_type_info*>(new_exception_header->exceptionType);
1273                 adjustedPtr =
1274                     __getExceptionClass(&new_exception_header->unwindHeader) == kOurDependentExceptionClass ?
1275                         ((__cxa_dependent_exception*)new_exception_header)->primaryException :
1276                         new_exception_header + 1;
1277                 if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding,
1278                                               excpType, adjustedPtr, unwind_exception))
1279                 {
1280                     // We need to __cxa_end_catch, but for the old exception,
1281                     //   not the new one.  This is a little tricky ...
1282                     // Disguise new_exception_header as a rethrown exception, but
1283                     //   don't actually rethrow it.  This means you can temporarily
1284                     //   end the catch clause enclosing new_exception_header without
1285                     //   __cxa_end_catch destroying new_exception_header.
1286                     new_exception_header->handlerCount = -new_exception_header->handlerCount;
1287                     globals->uncaughtExceptions += 1;
1288                     // Call __cxa_end_catch for new_exception_header
1289                     __cxa_end_catch();
1290                     // Call __cxa_end_catch for old_exception_header
1291                     __cxa_end_catch();
1292                     // Renter this catch clause with new_exception_header
1293                     __cxa_begin_catch(&new_exception_header->unwindHeader);
1294                     // Rethrow new_exception_header
1295                     throw;
1296                 }
1297             }
1298             // Will a std::bad_exception be catchable by the exception spec at
1299             //   ttypeIndex?
1300             // If no
1301             //    throw std::bad_exception();
1302             const __shim_type_info* excpType =
1303                 static_cast<const __shim_type_info*>(&typeid(std::bad_exception));
1304             std::bad_exception be;
1305             adjustedPtr = &be;
1306             if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding,
1307                                           excpType, adjustedPtr, unwind_exception))
1308             {
1309                 // We need to __cxa_end_catch for both the old exception and the
1310                 //   new exception.  Technically we should do it in that order.
1311                 //   But it is expedient to do it in the opposite order:
1312                 // Call __cxa_end_catch for new_exception_header
1313                 __cxa_end_catch();
1314                 // Throw std::bad_exception will __cxa_end_catch for
1315                 //   old_exception_header
1316                 throw be;
1317             }
1318         }
1319     }
1320     std::__terminate(t_handler);
1321 }
1322 
1323 }  // extern "C"
1324 
1325 }  // __cxxabiv1
1326