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 is_virtual__base_class_type_info101 bool is_virtual() const { 102 return (__offset_flags & __virtual_mask) != 0; 103 } 104 is_public__base_class_type_info105 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) offset__base_class_type_info111 long offset() const { 112 return __offset_flags >> __offset_shift; 113 } 114 flags__base_class_type_info115 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 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 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 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