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 <stdint.h>
     34 #include <typeinfo>
     35 #include <unwind.h>
     36 
     37 namespace __cxxabiv1
     38 {
     39   // Derived types of type_info below are based on 2.9.5 of C++ ABI.
     40 
     41   class __shim_type_info : public std::type_info
     42   {
     43    public:
     44     virtual ~__shim_type_info();
     45     virtual bool can_catch(const __shim_type_info* thrown_type,
     46                            void*& adjustedPtr) const = 0;
     47   };
     48 
     49   // Typeinfo for fundamental types.
     50   class __fundamental_type_info : public __shim_type_info
     51   {
     52   public:
     53     virtual ~__fundamental_type_info();
     54     virtual bool can_catch(const __shim_type_info* thrown_type,
     55                            void*& adjustedPtr) const;
     56   };
     57 
     58   // Typeinfo for array types.
     59   class __array_type_info : public __shim_type_info
     60   {
     61   public:
     62     virtual ~__array_type_info();
     63     virtual bool can_catch(const __shim_type_info* thrown_type,
     64                            void*& adjustedPtr) const;
     65   };
     66 
     67   // Typeinfo for function types.
     68   class __function_type_info : public __shim_type_info
     69   {
     70   public:
     71     virtual ~__function_type_info();
     72     virtual bool can_catch(const __shim_type_info* thrown_type,
     73                            void*& adjustedPtr) const;
     74   };
     75 
     76   // Typeinfo for enum types.
     77   class __enum_type_info : public __shim_type_info
     78   {
     79   public:
     80     virtual ~__enum_type_info();
     81     virtual bool can_catch(const __shim_type_info* thrown_type,
     82                            void*& adjustedPtr) const;
     83   };
     84 
     85 
     86   class __class_type_info;
     87 
     88   // Used in __vmi_class_type_info
     89   struct __base_class_type_info
     90   {
     91   public:
     92     const __class_type_info *__base_type;
     93 
     94     long __offset_flags;
     95 
     96     enum __offset_flags_masks {
     97       __virtual_mask = 0x1,
     98       __public_mask = 0x2,
     99       __offset_shift = 8   // lower 8 bits are flags
    100     };
    101 
    102     bool is_virtual() const {
    103       return (__offset_flags & __virtual_mask) != 0;
    104     }
    105 
    106     bool is_public() const {
    107       return (__offset_flags & __public_mask) != 0;
    108     }
    109 
    110     // FIXME: Right-shift of signed integer is implementation dependent.
    111     // GCC Implement is as signed (as we expect)
    112     long offset() const {
    113       return __offset_flags >> __offset_shift;
    114     }
    115 
    116     long flags() const {
    117       return __offset_flags & ((1 << __offset_shift) - 1);
    118     }
    119   };
    120 
    121   // Helper struct to support catch-clause match
    122   struct __UpcastInfo {
    123     enum ContainedStatus {
    124       unknown = 0,
    125       has_public_contained,
    126       has_ambig_or_not_public
    127     };
    128 
    129     ContainedStatus status;
    130     const __class_type_info* base_type;
    131     void* adjustedPtr;
    132     unsigned int premier_flags;
    133     bool nullobj_may_conflict;
    134 
    135     __UpcastInfo(const __class_type_info* type);
    136   };
    137 
    138   // Typeinfo for classes with no bases.
    139   class __class_type_info : public __shim_type_info
    140   {
    141   public:
    142     virtual ~__class_type_info();
    143     virtual bool can_catch(const __shim_type_info* thrown_type,
    144                            void*& adjustedPtr) const;
    145 
    146     enum class_type_info_code {
    147       CLASS_TYPE_INFO_CODE,
    148       SI_CLASS_TYPE_INFO_CODE,
    149       VMI_CLASS_TYPE_INFO_CODE
    150     };
    151 
    152     virtual class_type_info_code
    153       code() const { return CLASS_TYPE_INFO_CODE; }
    154 
    155     virtual bool walk_to(const __class_type_info* base_type,
    156                          void*& adjustedPtr,
    157                          __UpcastInfo& info) const;
    158 
    159   protected:
    160     bool self_class_type_match(const __class_type_info* base_type,
    161                                void*& adjustedPtr,
    162                                __UpcastInfo& info) const;
    163   };
    164 
    165   // Typeinfo for classes containing only a single, public, non-virtual base at
    166   // offset zero.
    167   class __si_class_type_info : public __class_type_info
    168   {
    169   public:
    170     virtual ~__si_class_type_info();
    171     const __class_type_info *__base_type;
    172 
    173     virtual __class_type_info::class_type_info_code
    174       code() const { return SI_CLASS_TYPE_INFO_CODE; }
    175 
    176     virtual bool walk_to(const __class_type_info* base_type,
    177                          void*& adjustedPtr,
    178                          __UpcastInfo& info) const;
    179   };
    180 
    181 
    182   // Typeinfo for classes with bases that do not satisfy the
    183   // __si_class_type_info constraints.
    184   class __vmi_class_type_info : public __class_type_info
    185   {
    186   public:
    187     virtual ~__vmi_class_type_info();
    188     unsigned int __flags;
    189     unsigned int __base_count;
    190     __base_class_type_info __base_info[1];
    191 
    192     enum __flags_masks {
    193       __non_diamond_repeat_mask = 0x1,
    194       __diamond_shaped_mask = 0x2,
    195     };
    196 
    197     virtual __class_type_info::class_type_info_code
    198       code() const { return VMI_CLASS_TYPE_INFO_CODE; }
    199 
    200     virtual bool walk_to(const __class_type_info* base_type,
    201                          void*& adjustedPtr,
    202                          __UpcastInfo& info) const;
    203   };
    204 
    205   class __pbase_type_info : public __shim_type_info
    206   {
    207   public:
    208     virtual ~__pbase_type_info();
    209     virtual bool can_catch(const __shim_type_info* thrown_type,
    210                            void*& adjustedPtr) const;
    211     unsigned int __flags;
    212     const __shim_type_info* __pointee;
    213 
    214     enum __masks {
    215       __const_mask = 0x1,
    216       __volatile_mask = 0x2,
    217       __restrict_mask = 0x4,
    218       __incomplete_mask = 0x8,
    219       __incomplete_class_mask = 0x10
    220     };
    221 
    222 
    223     virtual bool can_catch_typeinfo_wrapper(const __shim_type_info* thrown_type,
    224                                             void*& adjustedPtr,
    225                                             unsigned tracker) const;
    226 
    227   protected:
    228     enum __constness_tracker_status {
    229       first_time_init = 0x1,
    230       keep_constness = 0x2,
    231       after_gap = 0x4         // after one non-const qualified,
    232                               // we cannot face const again in future
    233     };
    234 
    235   private:
    236     bool can_catch_ptr(const __pbase_type_info *thrown_type,
    237                        void *&adjustedPtr,
    238                        unsigned tracker) const;
    239 
    240     // Return true if making decision done.
    241     virtual bool do_can_catch_ptr(const __pbase_type_info* thrown_type,
    242                                   void*& adjustedPtr,
    243                                   unsigned tracker,
    244                                   bool& result) const = 0;
    245   };
    246 
    247   class __pointer_type_info : public __pbase_type_info
    248   {
    249   public:
    250     virtual ~__pointer_type_info();
    251 
    252   private:
    253     virtual bool do_can_catch_ptr(const __pbase_type_info* thrown_type,
    254                                   void*& adjustedPtr,
    255                                   unsigned tracker,
    256                                   bool& result) const;
    257   };
    258 
    259   class __pointer_to_member_type_info : public __pbase_type_info
    260   {
    261   public:
    262     __class_type_info* __context;
    263 
    264     virtual ~__pointer_to_member_type_info();
    265 
    266   private:
    267     virtual bool do_can_catch_ptr(const __pbase_type_info* thrown_type,
    268                                   void*& adjustedPtr,
    269                                   unsigned tracker,
    270                                   bool& result) const;
    271   };
    272 
    273 
    274   extern "C" {
    275 
    276     // Compatible with GNU C++
    277     const uint64_t __gxx_exception_class = 0x474E5543432B2B00LL; // GNUCC++\0
    278 
    279     // TODO: Support dependent exception
    280     // TODO: Support C++0x exception propagation
    281     // http://sourcery.mentor.com/archives/cxx-abi-dev/msg01924.html
    282     struct __cxa_exception {
    283       size_t referenceCount;
    284 
    285       std::type_info* exceptionType;
    286       void (*exceptionDestructor)(void*);
    287       std::unexpected_handler unexpectedHandler;
    288       std::terminate_handler terminateHandler;
    289       __cxa_exception* nextException;
    290 
    291       int handlerCount;
    292 #ifdef __arm__
    293       /**
    294        * ARM EHABI requires the unwind library to keep track of exceptions
    295        * during cleanups.  These support nesting, so we need to keep a list of
    296        * them.
    297        */
    298       __cxa_exception* nextCleanup;
    299       int cleanupCount;
    300 #endif
    301       int handlerSwitchValue;
    302       const uint8_t* actionRecord;
    303       const uint8_t* languageSpecificData;
    304       void* catchTemp;
    305       void* adjustedPtr;
    306 
    307       _Unwind_Exception unwindHeader; // must be last
    308     };
    309 
    310     struct __cxa_eh_globals {
    311       __cxa_exception* caughtExceptions;
    312       unsigned int uncaughtExceptions;
    313 #ifdef __arm__
    314       __cxa_exception* cleanupExceptions;
    315 #endif
    316     };
    317 
    318     struct __cxa_thread_info {
    319       std::unexpected_handler unexpectedHandler;
    320       std::terminate_handler terminateHandler;
    321       _Unwind_Exception* currentCleanup;
    322 
    323       __cxa_eh_globals globals;
    324     };
    325 
    326     __cxa_eh_globals* __cxa_get_globals();
    327     __cxa_eh_globals* __cxa_get_globals_fast();
    328 
    329     void* __cxa_allocate_exception(size_t thrown_size);
    330     void __cxa_free_exception(void* thrown_exception);
    331 
    332     void __cxa_throw(void* thrown_exception, std::type_info* tinfo, void (*dest)(void*));
    333     void __cxa_rethrow();
    334 
    335     void* __cxa_begin_catch(void* exceptionObject);
    336     void __cxa_end_catch();
    337 
    338     bool __cxa_begin_cleanup(_Unwind_Exception*);
    339     void __cxa_end_cleanup();
    340 
    341     void __cxa_bad_cast();
    342     void __cxa_bad_typeid();
    343 
    344     void* __cxa_get_exception_ptr(void* exceptionObject);
    345 
    346     void __cxa_pure_virtual();
    347 
    348     // Missing libcxxabi functions.
    349     bool __cxa_uncaught_exception() throw();
    350     void __cxa_decrement_exception_refcount(void* exceptionObject) throw();
    351     void __cxa_increment_exception_refcount(void* exceptionObject) throw();
    352     void __cxa_rethrow_primary_exception(void* exceptionObject);
    353     void* __cxa_current_primary_exception() throw();
    354 
    355   } // extern "C"
    356 
    357 } // namespace __cxxabiv1
    358 
    359 namespace abi = __cxxabiv1;
    360 
    361 #endif /* defined(__GABIXX_CXXABI_H__) */
    362 
    363