111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Copyright (C) 2012 The Android Open Source Project
211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// All rights reserved.
311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//
411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Redistribution and use in source and binary forms, with or without
511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// modification, are permitted provided that the following conditions
611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// are met:
711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// 1. Redistributions of source code must retain the above copyright
811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//    notice, this list of conditions and the following disclaimer.
911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// 2. Redistributions in binary form must reproduce the above copyright
1011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//    notice, this list of conditions and the following disclaimer in the
1111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//    documentation and/or other materials provided with the distribution.
1211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// 3. Neither the name of the project nor the names of its contributors
1311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//    may be used to endorse or promote products derived from this software
1411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//    without specific prior written permission.
1511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//
1611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
1711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// SUCH DAMAGE.
2711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//===----------------------------------------------------------------------===//
2811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//                     The LLVM Compiler Infrastructure
2911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//
3011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// This file is dual licensed under the MIT and the University of Illinois Open
3111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Source Licenses. See LICENSE.TXT for details.
3211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//
3311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//
3411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//  This file implements the "Exception Handling APIs"
3511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//  http://www.codesourcery.com/public/cxx-abi/abi-eh.html
3611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//  http://www.intel.com/design/itanium/downloads/245358.htm
3711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//
3811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//===----------------------------------------------------------------------===//
3911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
4011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <exception>
4111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <unwind.h>
4211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "cxxabi_defines.h"
4311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "helper_func_internal.h"
4411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
4511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertnamespace __cxxabiv1 {
4611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
4711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  const __shim_type_info* getTypePtr(uint64_t ttypeIndex,
4811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                     const uint8_t* classInfo,
4911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                     uint8_t ttypeEncoding,
5011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                     _Unwind_Exception* unwind_exception);
5111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
5211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  _GABIXX_NORETURN void call_terminate(_Unwind_Exception* unwind_exception) {
5311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    __cxa_begin_catch(unwind_exception);  // terminate is also a handler
5411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::terminate();
5511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  }
5611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
5711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  // Boring stuff which has lots of encode/decode details
5811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  void scanEHTable(ScanResultInternal& results,
5911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                   _Unwind_Action actions,
6011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                   bool native_exception,
6111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                   _Unwind_Exception* unwind_exception,
6211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                   _Unwind_Context* context) {
6311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Initialize results to found nothing but an error
6411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    results.ttypeIndex = 0;
6511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    results.actionRecord = 0;
6611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    results.languageSpecificData = 0;
6711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    results.landingPad = 0;
6811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    results.adjustedPtr = 0;
6911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    results.reason = _URC_FATAL_PHASE1_ERROR;
7011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
7111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Check for consistent actions
7211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (actions & _UA_SEARCH_PHASE) {
7311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      if (actions & (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME | _UA_FORCE_UNWIND)) {
7411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        results.reason = _URC_FATAL_PHASE1_ERROR;
7511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return;
7611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      }
7711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else if (actions & _UA_CLEANUP_PHASE) {
7811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      if ((actions & _UA_HANDLER_FRAME) && (actions & _UA_FORCE_UNWIND)) {
7911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        results.reason = _URC_FATAL_PHASE2_ERROR;
8011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return;
8111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      }
8211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else {
8311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      results.reason = _URC_FATAL_PHASE1_ERROR;
8411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      return;
8511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
8611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
8711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
8811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Start scan by getting exception table address
8911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    const uint8_t* lsda = (const uint8_t*)_Unwind_GetLanguageSpecificData(context);
9011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (lsda == 0) {
9111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      // No exception table
9211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      results.reason = _URC_CONTINUE_UNWIND;
9311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      return;
9411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
9511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    results.languageSpecificData = lsda;
9611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    uintptr_t ip = _Unwind_GetIP(context) - 1;
9711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    uintptr_t funcStart = _Unwind_GetRegionStart(context);
9811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    uintptr_t ipOffset = ip - funcStart;
9911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    const uint8_t* classInfo = NULL;
10011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    uint8_t lpStartEncoding = *lsda++;
10111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding);
10211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (lpStart == 0) {
10311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      lpStart = (const uint8_t*)funcStart;
10411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
10511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    uint8_t ttypeEncoding = *lsda++;
10611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (ttypeEncoding != DW_EH_PE_omit) {
10711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      uintptr_t classInfoOffset = readULEB128(&lsda);
10811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      classInfo = lsda + classInfoOffset;
10911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
11011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    uint8_t callSiteEncoding = *lsda++;
11111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    uint32_t callSiteTableLength = static_cast<uint32_t>(readULEB128(&lsda));
11211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    const uint8_t* callSiteTableStart = lsda;
11311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    const uint8_t* callSiteTableEnd = callSiteTableStart + callSiteTableLength;
11411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    const uint8_t* actionTableStart = callSiteTableEnd;
11511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    const uint8_t* callSitePtr = callSiteTableStart;
11611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
11711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
11811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    while (callSitePtr < callSiteTableEnd) {
11911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding);
12011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      uintptr_t length = readEncodedPointer(&callSitePtr, callSiteEncoding);
12111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      uintptr_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding);
12211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      uintptr_t actionEntry = readULEB128(&callSitePtr);
12311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      if ((start <= ipOffset) && (ipOffset < (start + length))) {
12411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (landingPad == 0) {
12511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          // No handler here
12611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          results.reason = _URC_CONTINUE_UNWIND;
12711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          return;
12811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
12911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
13011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        landingPad = (uintptr_t)lpStart + landingPad;
13111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (actionEntry == 0) {
13211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME))
13311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          {
13411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            results.ttypeIndex = 0;
13511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            results.landingPad = landingPad;
13611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            results.reason = _URC_HANDLER_FOUND;
13711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return;
13811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          }
13911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          // No handler here
14011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          results.reason = _URC_CONTINUE_UNWIND;
14111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          return;
14211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
14311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
14411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        const uint8_t* action = actionTableStart + (actionEntry - 1);
14511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        while (true) {
14611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          const uint8_t* actionRecord = action;
14711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          int64_t ttypeIndex = readSLEB128(&action);
14811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          if (ttypeIndex > 0) {
14911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Found a catch, does it actually catch?
15011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // First check for catch (...)
15111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            const __shim_type_info* catchType =
15211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              getTypePtr(static_cast<uint64_t>(ttypeIndex),
15311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                         classInfo, ttypeEncoding, unwind_exception);
15411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (catchType == 0) {
15511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              // Found catch (...) catches everything, including foreign exceptions
15611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME))
15711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              {
15811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                // Save state and return _URC_HANDLER_FOUND
15911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                results.ttypeIndex = ttypeIndex;
16011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                results.actionRecord = actionRecord;
16111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                results.landingPad = landingPad;
16211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                results.adjustedPtr = unwind_exception+1;
16311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                results.reason = _URC_HANDLER_FOUND;
16411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                return;
16511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              }
16611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              else if (!(actions & _UA_FORCE_UNWIND))
16711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              {
16811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                // It looks like the exception table has changed
16911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                //    on us.  Likely stack corruption!
17011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                call_terminate(unwind_exception);
17111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              }
17211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            } else if (native_exception) {
17311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
17411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              void* adjustedPtr = unwind_exception+1;
17511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              const __shim_type_info* excpType =
17611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  static_cast<const __shim_type_info*>(exception_header->exceptionType);
17711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              if (adjustedPtr == 0 || excpType == 0) {
17811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                // Such a disaster! What's wrong?
17911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                call_terminate(unwind_exception);
18011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              }
18111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
18211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              // Only derefence once, so put ouside the recursive search below
18311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              if (dynamic_cast<const __pointer_type_info*>(excpType)) {
18411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                adjustedPtr = *static_cast<void**>(adjustedPtr);
18511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              }
18611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
18711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              // Let's play!
18811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              if (catchType->can_catch(excpType, adjustedPtr)) {
18911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if (actions & _UA_SEARCH_PHASE) {
19011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  // Cache it.
19111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  results.ttypeIndex = ttypeIndex;
19211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  results.actionRecord = actionRecord;
19311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  results.landingPad = landingPad;
19411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  results.adjustedPtr = adjustedPtr;
19511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  results.reason = _URC_HANDLER_FOUND;
19611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  return;
19711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                } else if (!(actions & _UA_FORCE_UNWIND)) {
19811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  // It looks like the exception table has changed
19911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  //    on us.  Likely stack corruption!
20011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  call_terminate(unwind_exception);
20111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                }
20211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              } // catchType->can_catch
20311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            } // if (catchType == 0)
20411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          } else if (ttypeIndex < 0) {
20511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Found an exception spec.
20611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (native_exception) {
20711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              __cxa_exception* header = reinterpret_cast<__cxa_exception*>(unwind_exception+1)-1;
20811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              void* adjustedPtr = unwind_exception+1;
20911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              const std::type_info* excpType = header->exceptionType;
21011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              if (adjustedPtr == 0 || excpType == 0) {
21111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                // Such a disaster! What's wrong?
21211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                call_terminate(unwind_exception);
21311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              }
21411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
21511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              // Let's play!
21611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              if (canExceptionSpecCatch(ttypeIndex, classInfo,
21711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                        ttypeEncoding, excpType,
21811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                        adjustedPtr, unwind_exception)) {
21911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if (actions & _UA_SEARCH_PHASE) {
22011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  // Cache it.
22111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  results.ttypeIndex = ttypeIndex;
22211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  results.actionRecord = actionRecord;
22311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  results.landingPad = landingPad;
22411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  results.adjustedPtr = adjustedPtr;
22511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  results.reason = _URC_HANDLER_FOUND;
22611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  return;
22711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                } else if (!(actions & _UA_FORCE_UNWIND)) {
22811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  // It looks like the exception table has changed
22911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  //    on us.  Likely stack corruption!
23011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  call_terminate(unwind_exception);
23111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                }
23211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              }
23311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            } else {  // ! native_exception
23411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              // foreign exception must be caught by exception spec
23511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME)) {
23611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                results.ttypeIndex = ttypeIndex;
23711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                results.actionRecord = actionRecord;
23811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                results.landingPad = landingPad;
23911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                results.adjustedPtr = unwind_exception+1;
24011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                results.reason = _URC_HANDLER_FOUND;
24111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                return;
24211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              }
24311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              else if (!(actions & _UA_FORCE_UNWIND)) {
24411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                // It looks like the exception table has changed
24511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                //    on us.  Likely stack corruption!
24611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                call_terminate(unwind_exception);
24711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              }
24811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
24911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          } else {  // ttypeIndex == 0
25011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Found a cleanup, or nothing
25111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME)) {
25211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              results.ttypeIndex = ttypeIndex;
25311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              results.actionRecord = actionRecord;
25411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              results.landingPad = landingPad;
25511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              results.adjustedPtr = unwind_exception+1;
25611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              results.reason = _URC_HANDLER_FOUND;
25711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              return;
25811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
25911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          }
26011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
26111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
26211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          const uint8_t* temp = action;
26311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          int64_t actionOffset = readSLEB128(&temp);
26411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          if (actionOffset == 0) {
26511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // End of action list, no matching handler or cleanup found
26611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            results.reason = _URC_CONTINUE_UNWIND;
26711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return;
26811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          }
26911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
27011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          // Go to next action
27111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          action += actionOffset;
27211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
27311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      } else if (ipOffset < start) {
27411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // There is no call site for this ip
27511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        call_terminate(unwind_exception);
27611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      }
27711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } // while (callSitePtr < callSiteTableEnd)
27811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
27911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    call_terminate(unwind_exception);
28011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  }
28111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
28211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  /*
28311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert   * Below is target-dependent part
28411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert   */
28511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
28611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef __arm__
28711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
28811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  /* Decode an R_ARM_TARGET2 relocation.  */
28911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  uint32_t decodeRelocTarget2 (uint32_t ptr) {
29011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    uint32_t tmp;
29111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
29211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    tmp = *reinterpret_cast<uint32_t*>(ptr);
29311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!tmp) {
29411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      return 0;
29511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
29611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
29711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    tmp += ptr;
29811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    tmp = *reinterpret_cast<uint32_t*>(tmp);
29911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return tmp;
30011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  }
30111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
30211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  const __shim_type_info* getTypePtr(uint64_t ttypeIndex,
30311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                     const uint8_t* classInfo,
30411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                     uint8_t ttypeEncoding,
30511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                     _Unwind_Exception* unwind_exception) {
30611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (classInfo == 0) { // eh table corrupted!
30711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      call_terminate(unwind_exception);
30811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
30911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    const uint8_t* ptr = classInfo - ttypeIndex * 4;
31011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return (const __shim_type_info*)decodeRelocTarget2((uint32_t)ptr);
31111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  }
31211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
31311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  bool canExceptionSpecCatch(int64_t specIndex,
31411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             const uint8_t* classInfo,
31511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             uint8_t ttypeEncoding,
31611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             const std::type_info* excpType,
31711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             void* adjustedPtr,
31811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             _Unwind_Exception* unwind_exception) {
31911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (classInfo == 0) { // eh table corrupted!
32011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      call_terminate(unwind_exception);
32111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
32211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
32311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    specIndex = -specIndex;
32411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    specIndex -= 1;
32511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    const uint32_t* temp = reinterpret_cast<const uint32_t*>(classInfo) + specIndex;
32611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
32711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    while (true) {
32811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      uint32_t ttypeIndex = *temp;
32911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      if (ttypeIndex == 0) {
33011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        break;
33111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      }
33211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      ttypeIndex = decodeRelocTarget2((uint32_t)temp);
33311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      temp += 1;
33411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      const __shim_type_info* catchType = (const __shim_type_info*) ttypeIndex;
33511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      void* tempPtr = adjustedPtr;
33611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      if (catchType->can_catch(
33711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              static_cast<const __shim_type_info*>(excpType), tempPtr)) {
33811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return false;
33911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      }
34011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } // while
34111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return true;
34211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  }
34311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
34411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  // lower-level runtime library API function that unwinds the frame
34511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  extern "C" _Unwind_Reason_Code __gnu_unwind_frame(_Unwind_Exception*,
34611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                    _Unwind_Context*);
34711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
34811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  void setRegisters(_Unwind_Exception* unwind_exception,
34911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    _Unwind_Context* context,
35011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    const ScanResultInternal& results) {
35111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    _Unwind_SetGR(context, 0, reinterpret_cast<uintptr_t>(unwind_exception));
35211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    _Unwind_SetGR(context, 1, static_cast<uintptr_t>(results.ttypeIndex));
35311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    _Unwind_SetIP(context, results.landingPad);
35411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  }
35511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
35611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  _Unwind_Reason_Code continueUnwinding(_Unwind_Exception *ex,
35711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                        _Unwind_Context *context) {
35811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (__gnu_unwind_frame(ex, context) != _URC_OK) {
35911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      return _URC_FAILURE;
36011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
36111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return _URC_CONTINUE_UNWIND;
36211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  }
36311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
36411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  void saveDataToBarrierCache(_Unwind_Exception* exc,
36511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              _Unwind_Context* ctx,
36611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              const ScanResultInternal& results) {
36711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    exc->barrier_cache.sp = _Unwind_GetGR(ctx, UNWIND_STACK_REG);
36811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    exc->barrier_cache.bitpattern[0] = (uint32_t)results.adjustedPtr;
36911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    exc->barrier_cache.bitpattern[1] = (uint32_t)results.ttypeIndex;
37011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    exc->barrier_cache.bitpattern[3] = (uint32_t)results.landingPad;
37111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  }
37211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
37311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  void loadDataFromBarrierCache(_Unwind_Exception* exc,
37411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                ScanResultInternal& results) {
37511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    results.adjustedPtr = (void*) exc->barrier_cache.bitpattern[0];
37611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    results.ttypeIndex = (int64_t) exc->barrier_cache.bitpattern[1];
37711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    results.landingPad = (uintptr_t) exc->barrier_cache.bitpattern[3];
37811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  }
37911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
38011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  void prepareBeginCleanup(_Unwind_Exception* exc) {
38111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    __cxa_begin_cleanup(exc);
38211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  }
38311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
38411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  void saveUnexpectedDataToBarrierCache(_Unwind_Exception* exc,
38511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                        _Unwind_Context* ctx,
38611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                        const ScanResultInternal& results) {
38711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    prepareBeginCleanup(exc);
38811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
38911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    const uint8_t* lsda = (const uint8_t*)_Unwind_GetLanguageSpecificData(ctx);
39011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    const uint8_t* classInfo = NULL;
39111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    uint8_t lpStartEncoding = *lsda++;
39211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    __attribute__((unused))
39311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding);
39411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    __attribute__((unused))
39511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    uintptr_t funcStart = _Unwind_GetRegionStart(ctx);
39611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    uint8_t ttypeEncoding = *lsda++;
39711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (ttypeEncoding != DW_EH_PE_omit) {
39811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      uintptr_t classInfoOffset = readULEB128(&lsda);
39911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      classInfo = lsda + classInfoOffset;
40011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
40111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
40211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    const uint32_t* e = (const uint32_t*) classInfo - results.ttypeIndex - 1;
40311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    uint32_t n = 0;
40411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    while (e[n] != 0) {
40511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      ++n;
40611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
40711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
40811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    exc->barrier_cache.bitpattern[1] = n;
40911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    exc->barrier_cache.bitpattern[3] = 4;
41011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    exc->barrier_cache.bitpattern[4] = (uint32_t)e;
41111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  }
41211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
41311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#else // ! __arm__
41411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
41511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  const __shim_type_info* getTypePtr(uint64_t ttypeIndex,
41611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                     const uint8_t* classInfo,
41711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                     uint8_t ttypeEncoding,
41811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                     _Unwind_Exception* unwind_exception) {
41911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (classInfo == 0) { // eh table corrupted!
42011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      call_terminate(unwind_exception);
42111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
42211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
42311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    switch (ttypeEncoding & 0x0F) {
42411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    case DW_EH_PE_absptr:
42511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      ttypeIndex *= sizeof(void*);
42611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      break;
42711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    case DW_EH_PE_udata2:
42811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    case DW_EH_PE_sdata2:
42911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      ttypeIndex *= 2;
43011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      break;
43111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    case DW_EH_PE_udata4:
43211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    case DW_EH_PE_sdata4:
43311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      ttypeIndex *= 4;
43411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      break;
43511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    case DW_EH_PE_udata8:
43611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    case DW_EH_PE_sdata8:
43711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      ttypeIndex *= 8;
43811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      break;
43911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    default:
44011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      // this should not happen.
44111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      call_terminate(unwind_exception);
44211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
44311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    classInfo -= ttypeIndex;
44411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return (const __shim_type_info*)readEncodedPointer(&classInfo, ttypeEncoding);
44511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  }
44611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
44711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  bool canExceptionSpecCatch(int64_t specIndex,
44811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             const uint8_t* classInfo,
44911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             uint8_t ttypeEncoding,
45011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             const std::type_info* excpType,
45111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             void* adjustedPtr,
45211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             _Unwind_Exception* unwind_exception) {
45311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (classInfo == 0) { // eh table corrupted!
45411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      call_terminate(unwind_exception);
45511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
45611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
45711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    specIndex = -specIndex;
45811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    specIndex -= 1;
45911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    const uint8_t* temp = classInfo + specIndex;
46011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
46111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    while (true) {
46211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      uint64_t ttypeIndex = readULEB128(&temp);
46311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      if (ttypeIndex == 0) {
46411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        break;
46511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      }
46611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      const __shim_type_info* catchType = getTypePtr(ttypeIndex,
46711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                     classInfo,
46811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                     ttypeEncoding,
46911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                     unwind_exception);
47011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      void* tempPtr = adjustedPtr;
47111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      if (catchType->can_catch(
47211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert              static_cast<const __shim_type_info*>(excpType), tempPtr)) {
47311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return false;
47411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert      }
47511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } // while
47611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return true;
47711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  }
47811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
47911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  void setRegisters(_Unwind_Exception* unwind_exception,
48011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    _Unwind_Context* context,
48111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    const ScanResultInternal& results) {
48211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    _Unwind_SetGR(context, __builtin_eh_return_data_regno(0),
48311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  reinterpret_cast<uintptr_t>(unwind_exception));
48411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    _Unwind_SetGR(context, __builtin_eh_return_data_regno(1),
48511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  static_cast<uintptr_t>(results.ttypeIndex));
48611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    _Unwind_SetIP(context, results.landingPad);
48711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  }
48811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
48911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  _Unwind_Reason_Code continueUnwinding(_Unwind_Exception *ex,
49011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                        _Unwind_Context *context) {
49111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return _URC_CONTINUE_UNWIND;
49211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  }
49311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
49411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  // Do nothing, only for API compatibility
49511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  // We don't use C++ polymorphism since we hope no virtual table cost.
49611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  void saveDataToBarrierCache(_Unwind_Exception* exc,
49711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              _Unwind_Context* ctx,
49811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              const ScanResultInternal& results) {}
49911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
50011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  void loadDataFromBarrierCache(_Unwind_Exception* exc,
50111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                ScanResultInternal& results) {}
50211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
50311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  void prepareBeginCleanup(_Unwind_Exception* exc) {}
50411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
50511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert  void saveUnexpectedDataToBarrierCache(_Unwind_Exception* exc,
50611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                        _Unwind_Context* ctx,
50711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                        const ScanResultInternal& results) {}
50811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
50911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // __arm__
51011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
51111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} // namespace __cxxabiv1
512