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