| // Copyright (C) 2011 The Android Open Source Project |
| // All rights reserved. |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions |
| // are met: |
| // 1. Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // 2. Redistributions in binary form must reproduce the above copyright |
| // notice, this list of conditions and the following disclaimer in the |
| // documentation and/or other materials provided with the distribution. |
| // 3. Neither the name of the project nor the names of its contributors |
| // may be used to endorse or promote products derived from this software |
| // without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND |
| // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| // ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE |
| // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| // SUCH DAMAGE. |
| // |
| |
| #ifndef __GABIXX_CXXABI_H__ |
| #define __GABIXX_CXXABI_H__ |
| |
| #include <exception> |
| #include <stdint.h> |
| #include <typeinfo> |
| #include <unwind.h> |
| |
| namespace __cxxabiv1 |
| { |
| // Derived types of type_info below are based on 2.9.5 of C++ ABI. |
| |
| class __shim_type_info : public std::type_info |
| { |
| public: |
| virtual ~__shim_type_info(); |
| virtual bool can_catch(const __shim_type_info* thrown_type, |
| void*& adjustedPtr) const = 0; |
| }; |
| |
| // Typeinfo for fundamental types. |
| class __fundamental_type_info : public __shim_type_info |
| { |
| public: |
| virtual ~__fundamental_type_info(); |
| virtual bool can_catch(const __shim_type_info* thrown_type, |
| void*& adjustedPtr) const; |
| }; |
| |
| // Typeinfo for array types. |
| class __array_type_info : public __shim_type_info |
| { |
| public: |
| virtual ~__array_type_info(); |
| virtual bool can_catch(const __shim_type_info* thrown_type, |
| void*& adjustedPtr) const; |
| }; |
| |
| // Typeinfo for function types. |
| class __function_type_info : public __shim_type_info |
| { |
| public: |
| virtual ~__function_type_info(); |
| virtual bool can_catch(const __shim_type_info* thrown_type, |
| void*& adjustedPtr) const; |
| }; |
| |
| // Typeinfo for enum types. |
| class __enum_type_info : public __shim_type_info |
| { |
| public: |
| virtual ~__enum_type_info(); |
| virtual bool can_catch(const __shim_type_info* thrown_type, |
| void*& adjustedPtr) const; |
| }; |
| |
| |
| class __class_type_info; |
| |
| // Used in __vmi_class_type_info |
| struct __base_class_type_info |
| { |
| public: |
| const __class_type_info *__base_type; |
| |
| long __offset_flags; |
| |
| enum __offset_flags_masks { |
| __virtual_mask = 0x1, |
| __public_mask = 0x2, |
| __offset_shift = 8 // lower 8 bits are flags |
| }; |
| |
| bool is_virtual() const { |
| return (__offset_flags & __virtual_mask) != 0; |
| } |
| |
| bool is_public() const { |
| return (__offset_flags & __public_mask) != 0; |
| } |
| |
| // FIXME: Right-shift of signed integer is implementation dependent. |
| // GCC Implement is as signed (as we expect) |
| long offset() const { |
| return __offset_flags >> __offset_shift; |
| } |
| |
| long flags() const { |
| return __offset_flags & ((1 << __offset_shift) - 1); |
| } |
| }; |
| |
| // Helper struct to support catch-clause match |
| struct __UpcastInfo { |
| enum ContainedStatus { |
| unknown = 0, |
| has_public_contained, |
| has_ambig_or_not_public |
| }; |
| |
| ContainedStatus status; |
| const __class_type_info* base_type; |
| void* adjustedPtr; |
| unsigned int premier_flags; |
| bool nullobj_may_conflict; |
| |
| __UpcastInfo(const __class_type_info* type); |
| }; |
| |
| // Typeinfo for classes with no bases. |
| class __class_type_info : public __shim_type_info |
| { |
| public: |
| virtual ~__class_type_info(); |
| virtual bool can_catch(const __shim_type_info* thrown_type, |
| void*& adjustedPtr) const; |
| |
| enum class_type_info_code { |
| CLASS_TYPE_INFO_CODE, |
| SI_CLASS_TYPE_INFO_CODE, |
| VMI_CLASS_TYPE_INFO_CODE |
| }; |
| |
| virtual class_type_info_code |
| code() const { return CLASS_TYPE_INFO_CODE; } |
| |
| virtual bool walk_to(const __class_type_info* base_type, |
| void*& adjustedPtr, |
| __UpcastInfo& info) const; |
| |
| protected: |
| bool self_class_type_match(const __class_type_info* base_type, |
| void*& adjustedPtr, |
| __UpcastInfo& info) const; |
| }; |
| |
| // Typeinfo for classes containing only a single, public, non-virtual base at |
| // offset zero. |
| class __si_class_type_info : public __class_type_info |
| { |
| public: |
| virtual ~__si_class_type_info(); |
| const __class_type_info *__base_type; |
| |
| virtual __class_type_info::class_type_info_code |
| code() const { return SI_CLASS_TYPE_INFO_CODE; } |
| |
| virtual bool walk_to(const __class_type_info* base_type, |
| void*& adjustedPtr, |
| __UpcastInfo& info) const; |
| }; |
| |
| |
| // Typeinfo for classes with bases that do not satisfy the |
| // __si_class_type_info constraints. |
| class __vmi_class_type_info : public __class_type_info |
| { |
| public: |
| virtual ~__vmi_class_type_info(); |
| unsigned int __flags; |
| unsigned int __base_count; |
| __base_class_type_info __base_info[1]; |
| |
| enum __flags_masks { |
| __non_diamond_repeat_mask = 0x1, |
| __diamond_shaped_mask = 0x2, |
| }; |
| |
| virtual __class_type_info::class_type_info_code |
| code() const { return VMI_CLASS_TYPE_INFO_CODE; } |
| |
| virtual bool walk_to(const __class_type_info* base_type, |
| void*& adjustedPtr, |
| __UpcastInfo& info) const; |
| }; |
| |
| class __pbase_type_info : public __shim_type_info |
| { |
| public: |
| virtual ~__pbase_type_info(); |
| virtual bool can_catch(const __shim_type_info* thrown_type, |
| void*& adjustedPtr) const; |
| unsigned int __flags; |
| const __shim_type_info* __pointee; |
| |
| enum __masks { |
| __const_mask = 0x1, |
| __volatile_mask = 0x2, |
| __restrict_mask = 0x4, |
| __incomplete_mask = 0x8, |
| __incomplete_class_mask = 0x10 |
| }; |
| |
| |
| virtual bool can_catch_typeinfo_wrapper(const __shim_type_info* thrown_type, |
| void*& adjustedPtr, |
| unsigned tracker) const; |
| |
| protected: |
| enum __constness_tracker_status { |
| first_time_init = 0x1, |
| keep_constness = 0x2, |
| after_gap = 0x4 // after one non-const qualified, |
| // we cannot face const again in future |
| }; |
| |
| private: |
| bool can_catch_ptr(const __pbase_type_info *thrown_type, |
| void *&adjustedPtr, |
| unsigned tracker) const; |
| |
| // Return true if making decision done. |
| virtual bool do_can_catch_ptr(const __pbase_type_info* thrown_type, |
| void*& adjustedPtr, |
| unsigned tracker, |
| bool& result) const = 0; |
| }; |
| |
| class __pointer_type_info : public __pbase_type_info |
| { |
| public: |
| virtual ~__pointer_type_info(); |
| |
| private: |
| virtual bool do_can_catch_ptr(const __pbase_type_info* thrown_type, |
| void*& adjustedPtr, |
| unsigned tracker, |
| bool& result) const; |
| }; |
| |
| class __pointer_to_member_type_info : public __pbase_type_info |
| { |
| public: |
| __class_type_info* __context; |
| |
| virtual ~__pointer_to_member_type_info(); |
| |
| private: |
| virtual bool do_can_catch_ptr(const __pbase_type_info* thrown_type, |
| void*& adjustedPtr, |
| unsigned tracker, |
| bool& result) const; |
| }; |
| |
| |
| extern "C" { |
| |
| // Compatible with GNU C++ |
| const uint64_t __gxx_exception_class = 0x474E5543432B2B00LL; // GNUCC++\0 |
| |
| // TODO: Support dependent exception |
| // TODO: Support C++0x exception propagation |
| // http://sourcery.mentor.com/archives/cxx-abi-dev/msg01924.html |
| struct __cxa_exception { |
| size_t referenceCount; |
| |
| std::type_info* exceptionType; |
| void (*exceptionDestructor)(void*); |
| std::unexpected_handler unexpectedHandler; |
| std::terminate_handler terminateHandler; |
| __cxa_exception* nextException; |
| |
| int handlerCount; |
| #ifdef __arm__ |
| /** |
| * ARM EHABI requires the unwind library to keep track of exceptions |
| * during cleanups. These support nesting, so we need to keep a list of |
| * them. |
| */ |
| __cxa_exception* nextCleanup; |
| int cleanupCount; |
| #endif |
| int handlerSwitchValue; |
| const uint8_t* actionRecord; |
| const uint8_t* languageSpecificData; |
| void* catchTemp; |
| void* adjustedPtr; |
| |
| _Unwind_Exception unwindHeader; // must be last |
| }; |
| |
| struct __cxa_eh_globals { |
| __cxa_exception* caughtExceptions; |
| unsigned int uncaughtExceptions; |
| #ifdef __arm__ |
| __cxa_exception* cleanupExceptions; |
| #endif |
| }; |
| |
| struct __cxa_thread_info { |
| std::unexpected_handler unexpectedHandler; |
| std::terminate_handler terminateHandler; |
| _Unwind_Exception* currentCleanup; |
| |
| __cxa_eh_globals globals; |
| }; |
| |
| __cxa_eh_globals* __cxa_get_globals(); |
| __cxa_eh_globals* __cxa_get_globals_fast(); |
| |
| void* __cxa_allocate_exception(size_t thrown_size); |
| void __cxa_free_exception(void* thrown_exception); |
| |
| void __cxa_throw(void* thrown_exception, std::type_info* tinfo, void (*dest)(void*)); |
| void __cxa_rethrow(); |
| |
| void* __cxa_begin_catch(void* exceptionObject); |
| void __cxa_end_catch(); |
| |
| bool __cxa_begin_cleanup(_Unwind_Exception*); |
| void __cxa_end_cleanup(); |
| |
| void __cxa_bad_cast(); |
| void __cxa_bad_typeid(); |
| |
| void* __cxa_get_exception_ptr(void* exceptionObject); |
| |
| void __cxa_pure_virtual(); |
| |
| // Missing libcxxabi functions. |
| bool __cxa_uncaught_exception() throw(); |
| void __cxa_decrement_exception_refcount(void* exceptionObject) throw(); |
| void __cxa_increment_exception_refcount(void* exceptionObject) throw(); |
| void __cxa_rethrow_primary_exception(void* exceptionObject); |
| void* __cxa_current_primary_exception() throw(); |
| |
| } // extern "C" |
| |
| } // namespace __cxxabiv1 |
| |
| namespace abi = __cxxabiv1; |
| |
| #endif /* defined(__GABIXX_CXXABI_H__) */ |
| |