1*8f1d5724Srobert //===----------------------------------------------------------------------===// 279c2e3e6Spatrick // 379c2e3e6Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 479c2e3e6Spatrick // See https://llvm.org/LICENSE.txt for license information. 579c2e3e6Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 679c2e3e6Spatrick // 779c2e3e6Spatrick // 879c2e3e6Spatrick // This file implements the "Exception Handling APIs" 979c2e3e6Spatrick // https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html 1079c2e3e6Spatrick // 1179c2e3e6Spatrick //===----------------------------------------------------------------------===// 1279c2e3e6Spatrick 1379c2e3e6Spatrick #ifndef _CXA_EXCEPTION_H 1479c2e3e6Spatrick #define _CXA_EXCEPTION_H 1579c2e3e6Spatrick 1679c2e3e6Spatrick #include <exception> // for std::unexpected_handler and std::terminate_handler 1779c2e3e6Spatrick #include "cxxabi.h" 1879c2e3e6Spatrick #include "unwind.h" 1979c2e3e6Spatrick 2079c2e3e6Spatrick namespace __cxxabiv1 { 2179c2e3e6Spatrick 2279c2e3e6Spatrick static const uint64_t kOurExceptionClass = 0x434C4E47432B2B00; // CLNGC++\0 2379c2e3e6Spatrick static const uint64_t kOurDependentExceptionClass = 0x434C4E47432B2B01; // CLNGC++\1 2479c2e3e6Spatrick static const uint64_t get_vendor_and_language = 0xFFFFFFFFFFFFFF00; // mask for CLNGC++ 2579c2e3e6Spatrick 2679c2e3e6Spatrick _LIBCXXABI_HIDDEN uint64_t __getExceptionClass (const _Unwind_Exception*); 2779c2e3e6Spatrick _LIBCXXABI_HIDDEN void __setExceptionClass ( _Unwind_Exception*, uint64_t); 2879c2e3e6Spatrick _LIBCXXABI_HIDDEN bool __isOurExceptionClass(const _Unwind_Exception*); 2979c2e3e6Spatrick 3079c2e3e6Spatrick struct _LIBCXXABI_HIDDEN __cxa_exception { 3179c2e3e6Spatrick #if defined(__LP64__) || defined(_WIN64) || defined(_LIBCXXABI_ARM_EHABI) 3279c2e3e6Spatrick // Now _Unwind_Exception is marked with __attribute__((aligned)), 3379c2e3e6Spatrick // which implies __cxa_exception is also aligned. Insert padding 3479c2e3e6Spatrick // in the beginning of the struct, rather than before unwindHeader. 3579c2e3e6Spatrick void *reserve; 3679c2e3e6Spatrick 37*8f1d5724Srobert // This is a new field to support C++11 exception_ptr. 3879c2e3e6Spatrick // For binary compatibility it is at the start of this 3979c2e3e6Spatrick // struct which is prepended to the object thrown in 4079c2e3e6Spatrick // __cxa_allocate_exception. 4179c2e3e6Spatrick size_t referenceCount; 4279c2e3e6Spatrick #endif 4379c2e3e6Spatrick 4479c2e3e6Spatrick // Manage the exception object itself. 4579c2e3e6Spatrick std::type_info *exceptionType; 46*8f1d5724Srobert void (_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *); 4779c2e3e6Spatrick std::unexpected_handler unexpectedHandler; 4879c2e3e6Spatrick std::terminate_handler terminateHandler; 4979c2e3e6Spatrick 5079c2e3e6Spatrick __cxa_exception *nextException; 5179c2e3e6Spatrick 5279c2e3e6Spatrick int handlerCount; 5379c2e3e6Spatrick 5479c2e3e6Spatrick #if defined(_LIBCXXABI_ARM_EHABI) 5579c2e3e6Spatrick __cxa_exception* nextPropagatingException; 5679c2e3e6Spatrick int propagationCount; 5779c2e3e6Spatrick #else 5879c2e3e6Spatrick int handlerSwitchValue; 5979c2e3e6Spatrick const unsigned char *actionRecord; 6079c2e3e6Spatrick const unsigned char *languageSpecificData; 6179c2e3e6Spatrick void *catchTemp; 6279c2e3e6Spatrick void *adjustedPtr; 6379c2e3e6Spatrick #endif 6479c2e3e6Spatrick 6579c2e3e6Spatrick #if !defined(__LP64__) && !defined(_WIN64) && !defined(_LIBCXXABI_ARM_EHABI) 66*8f1d5724Srobert // This is a new field to support C++11 exception_ptr. 6779c2e3e6Spatrick // For binary compatibility it is placed where the compiler 68*8f1d5724Srobert // previously added padding to 64-bit align unwindHeader. 6979c2e3e6Spatrick size_t referenceCount; 7079c2e3e6Spatrick #endif 7179c2e3e6Spatrick _Unwind_Exception unwindHeader; 7279c2e3e6Spatrick }; 7379c2e3e6Spatrick 7479c2e3e6Spatrick // http://sourcery.mentor.com/archives/cxx-abi-dev/msg01924.html 7579c2e3e6Spatrick // The layout of this structure MUST match the layout of __cxa_exception, with 7679c2e3e6Spatrick // primaryException instead of referenceCount. 7779c2e3e6Spatrick struct _LIBCXXABI_HIDDEN __cxa_dependent_exception { 7879c2e3e6Spatrick #if defined(__LP64__) || defined(_WIN64) || defined(_LIBCXXABI_ARM_EHABI) 7979c2e3e6Spatrick void* reserve; // padding. 8079c2e3e6Spatrick void* primaryException; 8179c2e3e6Spatrick #endif 8279c2e3e6Spatrick 8379c2e3e6Spatrick std::type_info *exceptionType; 84*8f1d5724Srobert void (_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *); 8579c2e3e6Spatrick std::unexpected_handler unexpectedHandler; 8679c2e3e6Spatrick std::terminate_handler terminateHandler; 8779c2e3e6Spatrick 8879c2e3e6Spatrick __cxa_exception *nextException; 8979c2e3e6Spatrick 9079c2e3e6Spatrick int handlerCount; 9179c2e3e6Spatrick 9279c2e3e6Spatrick #if defined(_LIBCXXABI_ARM_EHABI) 9379c2e3e6Spatrick __cxa_exception* nextPropagatingException; 9479c2e3e6Spatrick int propagationCount; 9579c2e3e6Spatrick #else 9679c2e3e6Spatrick int handlerSwitchValue; 9779c2e3e6Spatrick const unsigned char *actionRecord; 9879c2e3e6Spatrick const unsigned char *languageSpecificData; 9979c2e3e6Spatrick void * catchTemp; 10079c2e3e6Spatrick void *adjustedPtr; 10179c2e3e6Spatrick #endif 10279c2e3e6Spatrick 10379c2e3e6Spatrick #if !defined(__LP64__) && !defined(_WIN64) && !defined(_LIBCXXABI_ARM_EHABI) 10479c2e3e6Spatrick void* primaryException; 10579c2e3e6Spatrick #endif 10679c2e3e6Spatrick _Unwind_Exception unwindHeader; 10779c2e3e6Spatrick }; 10879c2e3e6Spatrick 10979c2e3e6Spatrick // Verify the negative offsets of different fields. 11079c2e3e6Spatrick static_assert(sizeof(_Unwind_Exception) + 11179c2e3e6Spatrick offsetof(__cxa_exception, unwindHeader) == 11279c2e3e6Spatrick sizeof(__cxa_exception), 11379c2e3e6Spatrick "unwindHeader has wrong negative offsets"); 11479c2e3e6Spatrick static_assert(sizeof(_Unwind_Exception) + 11579c2e3e6Spatrick offsetof(__cxa_dependent_exception, unwindHeader) == 11679c2e3e6Spatrick sizeof(__cxa_dependent_exception), 11779c2e3e6Spatrick "unwindHeader has wrong negative offsets"); 11879c2e3e6Spatrick 11979c2e3e6Spatrick #if defined(_LIBCXXABI_ARM_EHABI) 12079c2e3e6Spatrick static_assert(offsetof(__cxa_exception, propagationCount) + 12179c2e3e6Spatrick sizeof(_Unwind_Exception) + sizeof(void*) == 12279c2e3e6Spatrick sizeof(__cxa_exception), 12379c2e3e6Spatrick "propagationCount has wrong negative offset"); 12479c2e3e6Spatrick static_assert(offsetof(__cxa_dependent_exception, propagationCount) + 12579c2e3e6Spatrick sizeof(_Unwind_Exception) + sizeof(void*) == 12679c2e3e6Spatrick sizeof(__cxa_dependent_exception), 12779c2e3e6Spatrick "propagationCount has wrong negative offset"); 12879c2e3e6Spatrick #elif defined(__LP64__) || defined(_WIN64) 12979c2e3e6Spatrick static_assert(offsetof(__cxa_exception, adjustedPtr) + 13079c2e3e6Spatrick sizeof(_Unwind_Exception) + sizeof(void*) == 13179c2e3e6Spatrick sizeof(__cxa_exception), 13279c2e3e6Spatrick "adjustedPtr has wrong negative offset"); 13379c2e3e6Spatrick static_assert(offsetof(__cxa_dependent_exception, adjustedPtr) + 13479c2e3e6Spatrick sizeof(_Unwind_Exception) + sizeof(void*) == 13579c2e3e6Spatrick sizeof(__cxa_dependent_exception), 13679c2e3e6Spatrick "adjustedPtr has wrong negative offset"); 13779c2e3e6Spatrick #else 13879c2e3e6Spatrick static_assert(offsetof(__cxa_exception, referenceCount) + 13979c2e3e6Spatrick sizeof(_Unwind_Exception) + sizeof(void*) == 14079c2e3e6Spatrick sizeof(__cxa_exception), 14179c2e3e6Spatrick "referenceCount has wrong negative offset"); 14279c2e3e6Spatrick static_assert(offsetof(__cxa_dependent_exception, primaryException) + 14379c2e3e6Spatrick sizeof(_Unwind_Exception) + sizeof(void*) == 14479c2e3e6Spatrick sizeof(__cxa_dependent_exception), 14579c2e3e6Spatrick "primaryException has wrong negative offset"); 14679c2e3e6Spatrick #endif 14779c2e3e6Spatrick 14879c2e3e6Spatrick struct _LIBCXXABI_HIDDEN __cxa_eh_globals { 14979c2e3e6Spatrick __cxa_exception * caughtExceptions; 15079c2e3e6Spatrick unsigned int uncaughtExceptions; 15179c2e3e6Spatrick #if defined(_LIBCXXABI_ARM_EHABI) 15279c2e3e6Spatrick __cxa_exception* propagatingExceptions; 15379c2e3e6Spatrick #endif 15479c2e3e6Spatrick }; 15579c2e3e6Spatrick 15679c2e3e6Spatrick extern "C" _LIBCXXABI_FUNC_VIS __cxa_eh_globals * __cxa_get_globals (); 15779c2e3e6Spatrick extern "C" _LIBCXXABI_FUNC_VIS __cxa_eh_globals * __cxa_get_globals_fast (); 15879c2e3e6Spatrick 15979c2e3e6Spatrick extern "C" _LIBCXXABI_FUNC_VIS void * __cxa_allocate_dependent_exception (); 16079c2e3e6Spatrick extern "C" _LIBCXXABI_FUNC_VIS void __cxa_free_dependent_exception (void * dependent_exception); 16179c2e3e6Spatrick 16279c2e3e6Spatrick } // namespace __cxxabiv1 16379c2e3e6Spatrick 16479c2e3e6Spatrick #endif // _CXA_EXCEPTION_H 165