1 // -*- C++ -*- Helpers for calling unextected and terminate 2 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 3 // 2011 4 // Free Software Foundation, Inc. 5 // 6 // This file is part of GCC. 7 // 8 // GCC is free software; you can redistribute it and/or modify 9 // it under the terms of the GNU General Public License as published by 10 // the Free Software Foundation; either version 3, or (at your option) 11 // any later version. 12 // 13 // GCC is distributed in the hope that it will be useful, 14 // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 // GNU General Public License for more details. 17 // 18 // Under Section 7 of GPL version 3, you are granted additional 19 // permissions described in the GCC Runtime Library Exception, version 20 // 3.1, as published by the Free Software Foundation. 21 22 // You should have received a copy of the GNU General Public License and 23 // a copy of the GCC Runtime Library Exception along with this program; 24 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 25 // <http://www.gnu.org/licenses/>. 26 27 #include <bits/c++config.h> 28 #include <cstdlib> 29 #include <bits/exception_defines.h> 30 #include "unwind-cxx.h" 31 32 using namespace __cxxabiv1; 33 34 #include "unwind-pe.h" 35 36 37 // Helper routine for when the exception handling code needs to call 38 // terminate. 39 40 extern "C" void 41 __cxa_call_terminate(_Unwind_Exception* ue_header) throw () 42 { 43 44 if (ue_header) 45 { 46 // terminate is classed as a catch handler. 47 __cxa_begin_catch(ue_header); 48 49 // Call the terminate handler that was in effect when we threw this 50 // exception. */ 51 if (__is_gxx_exception_class(ue_header->exception_class)) 52 { 53 __cxa_exception* xh; 54 55 xh = __get_exception_header_from_ue(ue_header); 56 __terminate(xh->terminateHandler); 57 } 58 } 59 /* Call the global routine if we don't have anything better. */ 60 std::terminate(); 61 } 62 63 64 #ifdef __ARM_EABI_UNWINDER__ 65 // The ARM EABI __cxa_call_unexpected has the same semantics as the generic 66 // routine, but the exception specification has a different format. 67 extern "C" void 68 __cxa_call_unexpected(void* exc_obj_in) 69 { 70 _Unwind_Exception* exc_obj 71 = reinterpret_cast<_Unwind_Exception*>(exc_obj_in); 72 73 int rtti_count = 0; 74 _Unwind_Word rtti_stride = 0; 75 _Unwind_Word* rtti_list = NULL; 76 _Unwind_Ptr rtti_base = 0; 77 bool foreign_exception; 78 std::unexpected_handler unexpectedHandler = NULL; 79 std::terminate_handler terminateHandler = NULL; 80 __cxa_exception* xh; 81 if (__is_gxx_exception_class(exc_obj->exception_class)) 82 { 83 // Save data from the EO, which may be clobbered by _cxa_begin_catch. 84 xh = __get_exception_header_from_ue(exc_obj); 85 unexpectedHandler = xh->unexpectedHandler; 86 terminateHandler = xh->terminateHandler; 87 rtti_count = exc_obj->barrier_cache.bitpattern[1]; 88 rtti_base = (_Unwind_Ptr) exc_obj->barrier_cache.bitpattern[2]; 89 rtti_stride = exc_obj->barrier_cache.bitpattern[3]; 90 rtti_list = (_Unwind_Word*) exc_obj->barrier_cache.bitpattern[4]; 91 foreign_exception = false; 92 } 93 else 94 foreign_exception = true; 95 96 /* This must be called after extracting data from the EO, but before 97 calling unexpected(). */ 98 __cxa_begin_catch(exc_obj); 99 100 // This function is a handler for our exception argument. If we exit 101 // by throwing a different exception, we'll need the original cleaned up. 102 struct end_catch_protect 103 { 104 end_catch_protect() { } 105 ~end_catch_protect() { __cxa_end_catch(); } 106 } end_catch_protect_obj; 107 108 109 __try 110 { 111 if (foreign_exception) 112 std::unexpected(); 113 else 114 __unexpected(unexpectedHandler); 115 } 116 __catch(...) 117 { 118 /* See if the new exception matches the rtti list. */ 119 if (foreign_exception) 120 std::terminate(); 121 122 // Get the exception thrown from unexpected. 123 124 __cxa_eh_globals* globals = __cxa_get_globals_fast(); 125 __cxa_exception* new_xh = globals->caughtExceptions; 126 void* new_ptr = __get_object_from_ambiguous_exception (new_xh); 127 const std::type_info* catch_type; 128 int n; 129 bool bad_exception_allowed = false; 130 const std::type_info& bad_exc = typeid(std::bad_exception); 131 132 // Check the new exception against the rtti list 133 for (n = 0; n < rtti_count; n++) 134 { 135 _Unwind_Word offset; 136 137 offset = (_Unwind_Word) &rtti_list[n * (rtti_stride >> 2)]; 138 offset = _Unwind_decode_typeinfo_ptr(rtti_base, offset); 139 catch_type = (const std::type_info*) (offset); 140 141 if (__cxa_type_match(&new_xh->unwindHeader, catch_type, false, 142 &new_ptr) != ctm_failed) 143 __throw_exception_again; 144 145 if (catch_type->__do_catch(&bad_exc, 0, 1)) 146 bad_exception_allowed = true; 147 } 148 149 // If the exception spec allows std::bad_exception, throw that. 150 #ifdef __EXCEPTIONS 151 if (bad_exception_allowed) 152 throw std::bad_exception(); 153 #endif 154 155 // Otherwise, die. 156 __terminate(terminateHandler); 157 } 158 } 159 #endif // __ARM_EABI_UNWINDER__ 160