master
  1//===----------------------------------------------------------------------===//
  2//
  3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4// See https://llvm.org/LICENSE.txt for license information.
  5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6//
  7//
  8//  This file implements the "Exception Handling APIs"
  9//  https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html
 10//
 11//===----------------------------------------------------------------------===//
 12
 13#ifndef _CXA_EXCEPTION_H
 14#define _CXA_EXCEPTION_H
 15
 16#include <exception> // for std::unexpected_handler and std::terminate_handler
 17#include "cxxabi.h"
 18#include "unwind.h"
 19
 20namespace __cxxabiv1 {
 21
 22static const uint64_t kOurExceptionClass          = 0x434C4E47432B2B00; // CLNGC++\0
 23static const uint64_t kOurDependentExceptionClass = 0x434C4E47432B2B01; // CLNGC++\1
 24static const uint64_t get_vendor_and_language     = 0xFFFFFFFFFFFFFF00; // mask for CLNGC++
 25
 26_LIBCXXABI_HIDDEN uint64_t __getExceptionClass  (const _Unwind_Exception*);
 27_LIBCXXABI_HIDDEN void     __setExceptionClass  (      _Unwind_Exception*, uint64_t);
 28_LIBCXXABI_HIDDEN bool     __isOurExceptionClass(const _Unwind_Exception*);
 29
 30struct _LIBCXXABI_HIDDEN __cxa_exception {
 31#if defined(__LP64__) || defined(_WIN64) || defined(_LIBCXXABI_ARM_EHABI)
 32    // Now _Unwind_Exception is marked with __attribute__((aligned)),
 33    // which implies __cxa_exception is also aligned. Insert padding
 34    // in the beginning of the struct, rather than before unwindHeader.
 35    void *reserve;
 36
 37    // This is a new field to support C++11 exception_ptr.
 38    // For binary compatibility it is at the start of this
 39    // struct which is prepended to the object thrown in
 40    // __cxa_allocate_exception.
 41    size_t referenceCount;
 42#endif
 43
 44    //  Manage the exception object itself.
 45    std::type_info *exceptionType;
 46#ifdef __wasm__
 47    // In Wasm, a destructor returns its argument
 48    void *(_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
 49#else
 50    void (_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
 51#endif
 52    std::unexpected_handler unexpectedHandler;
 53    std::terminate_handler  terminateHandler;
 54
 55    __cxa_exception *nextException;
 56
 57    int handlerCount;
 58
 59#if defined(_LIBCXXABI_ARM_EHABI)
 60    __cxa_exception* nextPropagatingException;
 61    int propagationCount;
 62#else
 63    int handlerSwitchValue;
 64    const unsigned char *actionRecord;
 65    const unsigned char *languageSpecificData;
 66    void *catchTemp;
 67    void *adjustedPtr;
 68#endif
 69
 70#if !defined(__LP64__) && !defined(_WIN64) && !defined(_LIBCXXABI_ARM_EHABI)
 71    // This is a new field to support C++11 exception_ptr.
 72    // For binary compatibility it is placed where the compiler
 73    // previously added padding to 64-bit align unwindHeader.
 74    size_t referenceCount;
 75#endif
 76    _Unwind_Exception unwindHeader;
 77};
 78
 79// http://sourcery.mentor.com/archives/cxx-abi-dev/msg01924.html
 80// The layout of this structure MUST match the layout of __cxa_exception, with
 81// primaryException instead of referenceCount.
 82struct _LIBCXXABI_HIDDEN __cxa_dependent_exception {
 83#if defined(__LP64__) || defined(_WIN64) || defined(_LIBCXXABI_ARM_EHABI)
 84    void* reserve; // padding.
 85    void* primaryException;
 86#endif
 87
 88    std::type_info *exceptionType;
 89    void (_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
 90    std::unexpected_handler unexpectedHandler;
 91    std::terminate_handler terminateHandler;
 92
 93    __cxa_exception *nextException;
 94
 95    int handlerCount;
 96
 97#if defined(_LIBCXXABI_ARM_EHABI)
 98    __cxa_exception* nextPropagatingException;
 99    int propagationCount;
100#else
101    int handlerSwitchValue;
102    const unsigned char *actionRecord;
103    const unsigned char *languageSpecificData;
104    void * catchTemp;
105    void *adjustedPtr;
106#endif
107
108#if !defined(__LP64__) && !defined(_WIN64) && !defined(_LIBCXXABI_ARM_EHABI)
109    void* primaryException;
110#endif
111    _Unwind_Exception unwindHeader;
112};
113
114// Verify the negative offsets of different fields.
115static_assert(sizeof(_Unwind_Exception) +
116                      offsetof(__cxa_exception, unwindHeader) ==
117                  sizeof(__cxa_exception),
118              "unwindHeader has wrong negative offsets");
119static_assert(sizeof(_Unwind_Exception) +
120                      offsetof(__cxa_dependent_exception, unwindHeader) ==
121                  sizeof(__cxa_dependent_exception),
122              "unwindHeader has wrong negative offsets");
123
124#if defined(_LIBCXXABI_ARM_EHABI)
125static_assert(offsetof(__cxa_exception, propagationCount) +
126                      sizeof(_Unwind_Exception) + sizeof(void*) ==
127                  sizeof(__cxa_exception),
128              "propagationCount has wrong negative offset");
129static_assert(offsetof(__cxa_dependent_exception, propagationCount) +
130                      sizeof(_Unwind_Exception) + sizeof(void*) ==
131                  sizeof(__cxa_dependent_exception),
132              "propagationCount has wrong negative offset");
133#elif defined(__LP64__) || defined(_WIN64)
134static_assert(offsetof(__cxa_exception, adjustedPtr) +
135                      sizeof(_Unwind_Exception) + sizeof(void*) ==
136                  sizeof(__cxa_exception),
137              "adjustedPtr has wrong negative offset");
138static_assert(offsetof(__cxa_dependent_exception, adjustedPtr) +
139                      sizeof(_Unwind_Exception) + sizeof(void*) ==
140                  sizeof(__cxa_dependent_exception),
141              "adjustedPtr has wrong negative offset");
142#else
143static_assert(offsetof(__cxa_exception, referenceCount) +
144                      sizeof(_Unwind_Exception) + sizeof(void*) ==
145                  sizeof(__cxa_exception),
146              "referenceCount has wrong negative offset");
147static_assert(offsetof(__cxa_dependent_exception, primaryException) +
148                      sizeof(_Unwind_Exception) + sizeof(void*) ==
149                  sizeof(__cxa_dependent_exception),
150              "primaryException has wrong negative offset");
151#endif
152
153struct _LIBCXXABI_HIDDEN __cxa_eh_globals {
154    __cxa_exception *   caughtExceptions;
155    unsigned int        uncaughtExceptions;
156#if defined(_LIBCXXABI_ARM_EHABI)
157    __cxa_exception* propagatingExceptions;
158#endif
159};
160
161extern "C" _LIBCXXABI_FUNC_VIS __cxa_eh_globals * __cxa_get_globals      ();
162extern "C" _LIBCXXABI_FUNC_VIS __cxa_eh_globals * __cxa_get_globals_fast ();
163
164extern "C" _LIBCXXABI_FUNC_VIS void * __cxa_allocate_dependent_exception ();
165extern "C" _LIBCXXABI_FUNC_VIS void __cxa_free_dependent_exception (void * dependent_exception);
166
167}  // namespace __cxxabiv1
168
169#endif // _CXA_EXCEPTION_H