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