master
   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
  38extern "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
 138Notes:
 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
 156namespace __cxxabiv1
 157{
 158
 159namespace
 160{
 161
 162template <class AsType>
 163uintptr_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
 172extern "C"
 173{
 174
 175// private API
 176
 177// Heavily borrowed from llvm/examples/ExceptionDemo/ExceptionDemo.cpp
 178
 179// DWARF Constants
 180enum
 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
 205static
 206uintptr_t
 207readULEB128(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
 228static
 229intptr_t
 230readSLEB128(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
 255static
 256uintptr_t
 257readEncodedPointer(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
 328static
 329void
 330call_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)
 343static 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
 362static const __shim_type_info*
 363get_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)
 384static
 385const __shim_type_info*
 386get_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)
 432static
 433bool
 434exception_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
 478static
 479bool
 480exception_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
 515static
 516void*
 517get_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
 527namespace
 528{
 529
 530struct 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
 545static
 546void
 547set_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
 584static 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/*
 860The 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__)
 909static _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__)
1001extern "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
1012extern "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.)
1019static _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)
1034static const uint32_t REG_UCB = 12;  // Register to save _Unwind_Control_Block
1035#endif
1036static const uint32_t REG_SP = 13;
1037
1038static 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
1048static 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
1058extern "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