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