1 // -*- C++ -*- Exception handling routines for catching. 2 // Copyright (C) 2001, 2003, 2004 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 2, 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 // You should have received a copy of the GNU General Public License 17 // along with GCC; see the file COPYING. If not, write to 18 // the Free Software Foundation, 51 Franklin Street, Fifth Floor, 19 // Boston, MA 02110-1301, USA. 20 21 // As a special exception, you may use this file as part of a free software 22 // library without restriction. Specifically, if other files instantiate 23 // templates or use macros or inline functions from this file, or you compile 24 // this file and link it with other files to produce an executable, this 25 // file does not by itself cause the resulting executable to be covered by 26 // the GNU General Public License. This exception does not however 27 // invalidate any other reasons why the executable file might be covered by 28 // the GNU General Public License. 29 30 #include <cstdlib> 31 #include "unwind-cxx.h" 32 33 using namespace __cxxabiv1; 34 35 extern "C" void * 36 __cxxabiv1::__cxa_get_exception_ptr(void *exc_obj_in) throw() 37 { 38 _Unwind_Exception *exceptionObject 39 = reinterpret_cast <_Unwind_Exception *>(exc_obj_in); 40 41 return __gxx_caught_object(exceptionObject); 42 } 43 44 extern "C" void * 45 __cxxabiv1::__cxa_begin_catch (void *exc_obj_in) throw() 46 { 47 _Unwind_Exception *exceptionObject 48 = reinterpret_cast <_Unwind_Exception *>(exc_obj_in); 49 __cxa_eh_globals *globals = __cxa_get_globals (); 50 __cxa_exception *prev = globals->caughtExceptions; 51 __cxa_exception *header = __get_exception_header_from_ue (exceptionObject); 52 void* objectp; 53 54 // Foreign exceptions can't be stacked here. If the exception stack is 55 // empty, then fine. Otherwise we really have no choice but to terminate. 56 // Note that this use of "header" is a lie. It's fine so long as we only 57 // examine header->unwindHeader though. 58 if (!__is_gxx_exception_class(header->unwindHeader.exception_class)) 59 { 60 if (prev != 0) 61 std::terminate (); 62 63 // Remember for end_catch and rethrow. 64 globals->caughtExceptions = header; 65 66 // ??? No sensible value to return; we don't know what the 67 // object is, much less where it is in relation to the header. 68 return 0; 69 } 70 71 int count = header->handlerCount; 72 // Count is less than zero if this exception was rethrown from an 73 // immediately enclosing region. 74 if (count < 0) 75 count = -count + 1; 76 else 77 count += 1; 78 header->handlerCount = count; 79 globals->uncaughtExceptions -= 1; 80 81 if (header != prev) 82 { 83 header->nextException = prev; 84 globals->caughtExceptions = header; 85 } 86 87 objectp = __gxx_caught_object(exceptionObject); 88 #ifdef __ARM_EABI_UNWINDER__ 89 _Unwind_Complete(exceptionObject); 90 #endif 91 return objectp; 92 } 93 94 95 extern "C" void 96 __cxxabiv1::__cxa_end_catch () 97 { 98 __cxa_eh_globals *globals = __cxa_get_globals_fast (); 99 __cxa_exception *header = globals->caughtExceptions; 100 101 // A rethrow of a foreign exception will be removed from the 102 // the exception stack immediately by __cxa_rethrow. 103 if (!header) 104 return; 105 106 // A foreign exception couldn't have been stacked (see above), 107 // so by definition processing must be complete. 108 if (!__is_gxx_exception_class(header->unwindHeader.exception_class)) 109 { 110 globals->caughtExceptions = 0; 111 _Unwind_DeleteException (&header->unwindHeader); 112 return; 113 } 114 115 int count = header->handlerCount; 116 if (count < 0) 117 { 118 // This exception was rethrown. Decrement the (inverted) catch 119 // count and remove it from the chain when it reaches zero. 120 if (++count == 0) 121 globals->caughtExceptions = header->nextException; 122 } 123 else if (--count == 0) 124 { 125 // Handling for this exception is complete. Destroy the object. 126 globals->caughtExceptions = header->nextException; 127 _Unwind_DeleteException (&header->unwindHeader); 128 return; 129 } 130 else if (count < 0) 131 // A bug in the exception handling library or compiler. 132 std::terminate (); 133 134 header->handlerCount = count; 135 } 136 137 138 bool 139 std::uncaught_exception() throw() 140 { 141 __cxa_eh_globals *globals = __cxa_get_globals (); 142 return globals->uncaughtExceptions != 0; 143 } 144