xref: /openbsd-src/gnu/llvm/libcxxabi/src/cxa_exception.h (revision 8f1d572453a8bab44a2fe956e25efc4124e87e82)
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