Home | History | Annotate | Download | only in include
      1 // Copyright (C) 2011 The Android Open Source Project
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions
      6 // are met:
      7 // 1. Redistributions of source code must retain the above copyright
      8 //    notice, this list of conditions and the following disclaimer.
      9 // 2. Redistributions in binary form must reproduce the above copyright
     10 //    notice, this list of conditions and the following disclaimer in the
     11 //    documentation and/or other materials provided with the distribution.
     12 // 3. Neither the name of the project nor the names of its contributors
     13 //    may be used to endorse or promote products derived from this software
     14 //    without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
     17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19 // ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
     20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26 // SUCH DAMAGE.
     27 //
     28 
     29 #ifndef __GABIXX_CXXABI_H__
     30 #define __GABIXX_CXXABI_H__
     31 
     32 #include <exception>
     33 #include <typeinfo>
     34 #include <unwind.h>
     35 
     36 namespace __cxxabiv1
     37 {
     38   // Derived types of type_info below are based on 2.9.5 of C++ ABI.
     39 
     40   class __shim_type_info : public std::type_info
     41   {
     42    public:
     43     virtual ~__shim_type_info();
     44     virtual bool can_catch(const __shim_type_info* thrown_type,
     45                            void*& adjustedPtr) const = 0;
     46   };
     47 
     48   // Typeinfo for fundamental types.
     49   class __fundamental_type_info : public __shim_type_info
     50   {
     51   public:
     52     virtual ~__fundamental_type_info();
     53     virtual bool can_catch(const __shim_type_info* thrown_type,
     54                            void*& adjustedPtr) const;
     55   };
     56 
     57   // Typeinfo for array types.
     58   class __array_type_info : public __shim_type_info
     59   {
     60   public:
     61     virtual ~__array_type_info();
     62     virtual bool can_catch(const __shim_type_info* thrown_type,
     63                            void*& adjustedPtr) const;
     64   };
     65 
     66   // Typeinfo for function types.
     67   class __function_type_info : public __shim_type_info
     68   {
     69   public:
     70     virtual ~__function_type_info();
     71     virtual bool can_catch(const __shim_type_info* thrown_type,
     72                            void*& adjustedPtr) const;
     73   };
     74 
     75   // Typeinfo for enum types.
     76   class __enum_type_info : public __shim_type_info
     77   {
     78   public:
     79     virtual ~__enum_type_info();
     80     virtual bool can_catch(const __shim_type_info* thrown_type,
     81                            void*& adjustedPtr) const;
     82   };
     83 
     84 
     85   class __class_type_info;
     86 
     87   // Used in __vmi_class_type_info
     88   struct __base_class_type_info
     89   {
     90   public:
     91     const __class_type_info *__base_type;
     92 
     93     long __offset_flags;
     94 
     95     enum __offset_flags_masks {
     96       __virtual_mask = 0x1,
     97       __public_mask = 0x2,
     98       __offset_shift = 8   // lower 8 bits are flags
     99     };
    100 
    101     bool is_virtual() const {
    102       return (__offset_flags & __virtual_mask) != 0;
    103     }
    104 
    105     bool is_public() const {
    106       return (__offset_flags & __public_mask) != 0;
    107     }
    108 
    109     // FIXME: Right-shift of signed integer is implementation dependent.
    110     // GCC Implement is as signed (as we expect)
    111     long offset() const {
    112       return __offset_flags >> __offset_shift;
    113     }
    114 
    115     long flags() const {
    116       return __offset_flags & ((1 << __offset_shift) - 1);
    117     }
    118   };
    119 
    120   // Helper struct to support catch-clause match
    121   struct __UpcastInfo {
    122     enum ContainedStatus {
    123       unknown = 0,
    124       has_public_contained,
    125       has_ambig_or_not_public
    126     };
    127 
    128     ContainedStatus status;
    129     const __class_type_info* base_type;
    130     void* adjustedPtr;
    131     unsigned int premier_flags;
    132     bool nullobj_may_conflict;
    133 
    134     __UpcastInfo(const __class_type_info* type);
    135   };
    136 
    137   // Typeinfo for classes with no bases.
    138   class __class_type_info : public __shim_type_info
    139   {
    140   public:
    141     virtual ~__class_type_info();
    142     virtual bool can_catch(const __shim_type_info* thrown_type,
    143                            void*& adjustedPtr) const;
    144 
    145     enum class_type_info_code {
    146       CLASS_TYPE_INFO_CODE,
    147       SI_CLASS_TYPE_INFO_CODE,
    148       VMI_CLASS_TYPE_INFO_CODE
    149     };
    150 
    151     virtual class_type_info_code
    152       code() const { return CLASS_TYPE_INFO_CODE; }
    153 
    154     virtual bool walk_to(const __class_type_info* base_type,
    155                          void*& adjustedPtr,
    156                          __UpcastInfo& info) const;
    157 
    158   protected:
    159     bool self_class_type_match(const __class_type_info* base_type,
    160                                void*& adjustedPtr,
    161                                __UpcastInfo& info) const;
    162   };
    163 
    164   // Typeinfo for classes containing only a single, public, non-virtual base at
    165   // offset zero.
    166   class __si_class_type_info : public __class_type_info
    167   {
    168   public:
    169     virtual ~__si_class_type_info();
    170     const __class_type_info *__base_type;
    171 
    172     virtual __class_type_info::class_type_info_code
    173       code() const { return SI_CLASS_TYPE_INFO_CODE; }
    174 
    175     virtual bool walk_to(const __class_type_info* base_type,
    176                          void*& adjustedPtr,
    177                          __UpcastInfo& info) const;
    178   };
    179 
    180 
    181   // Typeinfo for classes with bases that do not satisfy the
    182   // __si_class_type_info constraints.
    183   class __vmi_class_type_info : public __class_type_info
    184   {
    185   public:
    186     virtual ~__vmi_class_type_info();
    187     unsigned int __flags;
    188     unsigned int __base_count;
    189     __base_class_type_info __base_info[1];
    190 
    191     enum __flags_masks {
    192       __non_diamond_repeat_mask = 0x1,
    193       __diamond_shaped_mask = 0x2,
    194     };
    195 
    196     virtual __class_type_info::class_type_info_code
    197       code() const { return VMI_CLASS_TYPE_INFO_CODE; }
    198 
    199     virtual bool walk_to(const __class_type_info* base_type,
    200                          void*& adjustedPtr,
    201                          __UpcastInfo& info) const;
    202   };
    203 
    204   class __pbase_type_info : public __shim_type_info
    205   {
    206   public:
    207     virtual ~__pbase_type_info();
    208     virtual bool can_catch(const __shim_type_info* thrown_type,
    209                            void*& adjustedPtr) const;
    210     unsigned int __flags;
    211     const __shim_type_info* __pointee;
    212 
    213     enum __masks {
    214       __const_mask = 0x1,
    215       __volatile_mask = 0x2,
    216       __restrict_mask = 0x4,
    217       __incomplete_mask = 0x8,
    218       __incomplete_class_mask = 0x10
    219     };
    220 
    221 
    222     virtual bool can_catch_typeinfo_wrapper(const __shim_type_info* thrown_type,
    223                                             void*& adjustedPtr,
    224                                             unsigned tracker) const;
    225 
    226   protected:
    227     enum __constness_tracker_status {
    228       first_time_init = 0x1,
    229       keep_constness = 0x2,
    230       after_gap = 0x4         // after one non-const qualified,
    231                               // we cannot face const again in future
    232     };
    233 
    234   private:
    235     bool can_catch_ptr(const __pbase_type_info *thrown_type,
    236                        void *&adjustedPtr,
    237                        unsigned tracker) const;
    238 
    239     // Return true if making decision done.
    240     virtual bool do_can_catch_ptr(const __pbase_type_info* thrown_type,
    241                                   void*& adjustedPtr,
    242                                   unsigned tracker,
    243                                   bool& result) const = 0;
    244   };
    245 
    246   class __pointer_type_info : public __pbase_type_info
    247   {
    248   public:
    249     virtual ~__pointer_type_info();
    250 
    251   private:
    252     virtual bool do_can_catch_ptr(const __pbase_type_info* thrown_type,
    253                                   void*& adjustedPtr,
    254                                   unsigned tracker,
    255                                   bool& result) const;
    256   };
    257 
    258   class __pointer_to_member_type_info : public __pbase_type_info
    259   {
    260   public:
    261     __class_type_info* __context;
    262 
    263     virtual ~__pointer_to_member_type_info();
    264 
    265   private:
    266     virtual bool do_can_catch_ptr(const __pbase_type_info* thrown_type,
    267                                   void*& adjustedPtr,
    268                                   unsigned tracker,
    269                                   bool& result) const;
    270   };
    271 
    272 
    273   extern "C" {
    274 
    275     // Compatible with GNU C++
    276     const uint64_t __gxx_exception_class = 0x474E5543432B2B00LL; // GNUCC++\0
    277 
    278     // TODO: Support dependent exception
    279     // TODO: Support C++0x exception propagation
    280     // http://sourcery.mentor.com/archives/cxx-abi-dev/msg01924.html
    281     struct __cxa_exception {
    282       size_t referenceCount;
    283 
    284       std::type_info* exceptionType;
    285       void (*exceptionDestructor)(void*);
    286       std::unexpected_handler unexpectedHandler;
    287       std::terminate_handler terminateHandler;
    288       __cxa_exception* nextException;
    289 
    290       int handlerCount;
    291 #ifdef __arm__
    292       /**
    293        * ARM EHABI requires the unwind library to keep track of exceptions
    294        * during cleanups.  These support nesting, so we need to keep a list of
    295        * them.
    296        */
    297       __cxa_exception* nextCleanup;
    298       int cleanupCount;
    299 #endif
    300       int handlerSwitchValue;
    301       const uint8_t* actionRecord;
    302       const uint8_t* languageSpecificData;
    303       void* catchTemp;
    304       void* adjustedPtr;
    305 
    306       _Unwind_Exception unwindHeader; // must be last
    307     };
    308 
    309     struct __cxa_eh_globals {
    310       __cxa_exception* caughtExceptions;
    311       unsigned int uncaughtExceptions;
    312 #ifdef __arm__
    313       __cxa_exception* cleanupExceptions;
    314 #endif
    315     };
    316 
    317     struct __cxa_thread_info {
    318       std::unexpected_handler unexpectedHandler;
    319       std::terminate_handler terminateHandler;
    320       _Unwind_Exception* currentCleanup;
    321 
    322       __cxa_eh_globals globals;
    323     };
    324 
    325     __cxa_eh_globals* __cxa_get_globals();
    326     __cxa_eh_globals* __cxa_get_globals_fast();
    327 
    328     void* __cxa_allocate_exception(size_t thrown_size);
    329     void __cxa_free_exception(void* thrown_exception);
    330 
    331     void __cxa_throw(void* thrown_exception, std::type_info* tinfo, void (*dest)(void*));
    332     void __cxa_rethrow();
    333 
    334     void* __cxa_begin_catch(void* exceptionObject);
    335     void __cxa_end_catch();
    336 
    337     bool __cxa_begin_cleanup(_Unwind_Exception*);
    338     void __cxa_end_cleanup();
    339 
    340     void __cxa_bad_cast();
    341     void __cxa_bad_typeid();
    342 
    343     void* __cxa_get_exception_ptr(void* exceptionObject);
    344 
    345     void __cxa_pure_virtual();
    346 
    347     // Missing libcxxabi functions.
    348     bool __cxa_uncaught_exception() throw();
    349     void __cxa_decrement_exception_refcount(void* exceptionObject) throw();
    350     void __cxa_increment_exception_refcount(void* exceptionObject) throw();
    351     void __cxa_rethrow_primary_exception(void* exceptionObject);
    352     void* __cxa_current_primary_exception() throw();
    353 
    354   } // extern "C"
    355 
    356 } // namespace __cxxabiv1
    357 
    358 namespace abi = __cxxabiv1;
    359 
    360 #endif /* defined(__GABIXX_CXXABI_H__) */
    361 
    362