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