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