1// -*- C++ -*- Exception handling routines for catching. 2// Copyright (C) 2001-2022 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 <cstdlib> 26#include "unwind-cxx.h" 27 28using namespace __cxxabiv1; 29 30extern "C" void * 31__cxxabiv1::__cxa_get_exception_ptr(void *exc_obj_in) _GLIBCXX_NOTHROW 32{ 33 _Unwind_Exception *exceptionObject 34 = reinterpret_cast <_Unwind_Exception *>(exc_obj_in); 35 36 return __gxx_caught_object(exceptionObject); 37} 38 39extern "C" void * 40__cxxabiv1::__cxa_begin_catch (void *exc_obj_in) _GLIBCXX_NOTHROW 41{ 42 _Unwind_Exception *exceptionObject 43 = reinterpret_cast <_Unwind_Exception *>(exc_obj_in); 44 __cxa_eh_globals *globals = __cxa_get_globals (); 45 __cxa_exception *prev = globals->caughtExceptions; 46 __cxa_exception *header = __get_exception_header_from_ue (exceptionObject); 47 void* objectp; 48 49 // Foreign exceptions can't be stacked here. If the exception stack is 50 // empty, then fine. Otherwise we really have no choice but to terminate. 51 // Note that this use of "header" is a lie. It's fine so long as we only 52 // examine header->unwindHeader though. 53 if (!__is_gxx_exception_class(header->unwindHeader.exception_class)) 54 { 55 if (prev != 0) 56 std::terminate (); 57 58 // Remember for end_catch and rethrow. 59 globals->caughtExceptions = header; 60 61 // ??? No sensible value to return; we don't know what the 62 // object is, much less where it is in relation to the header. 63 return 0; 64 } 65 66 int count = header->handlerCount; 67 // Count is less than zero if this exception was rethrown from an 68 // immediately enclosing region. 69 if (count < 0) 70 count = -count + 1; 71 else 72 count += 1; 73 header->handlerCount = count; 74 globals->uncaughtExceptions -= 1; 75 76 if (header != prev) 77 { 78 header->nextException = prev; 79 globals->caughtExceptions = header; 80 } 81 82 objectp = __gxx_caught_object(exceptionObject); 83 84 PROBE2 (catch, objectp, header->exceptionType); 85 86#ifdef __ARM_EABI_UNWINDER__ 87 _Unwind_Complete(exceptionObject); 88#endif 89 return objectp; 90} 91 92 93extern "C" void 94__cxxabiv1::__cxa_end_catch () 95{ 96 __cxa_eh_globals *globals = __cxa_get_globals_fast (); 97 __cxa_exception *header = globals->caughtExceptions; 98 99 // A rethrow of a foreign exception will be removed from the 100 // the exception stack immediately by __cxa_rethrow. 101 if (!header) 102 return; 103 104 // A foreign exception couldn't have been stacked (see above), 105 // so by definition processing must be complete. 106 if (!__is_gxx_exception_class(header->unwindHeader.exception_class)) 107 { 108 globals->caughtExceptions = 0; 109 _Unwind_DeleteException (&header->unwindHeader); 110 return; 111 } 112 113 int count = header->handlerCount; 114 if (count < 0) 115 { 116 // This exception was rethrown. Decrement the (inverted) catch 117 // count and remove it from the chain when it reaches zero. 118 if (++count == 0) 119 globals->caughtExceptions = header->nextException; 120 } 121 else if (--count == 0) 122 { 123 // Handling for this exception is complete. Destroy the object. 124 globals->caughtExceptions = header->nextException; 125 _Unwind_DeleteException (&header->unwindHeader); 126 return; 127 } 128 else if (count < 0) 129 // A bug in the exception handling library or compiler. 130 std::terminate (); 131 132 header->handlerCount = count; 133} 134 135 136bool 137std::uncaught_exception() throw() 138{ 139#if __cpp_exceptions 140 __cxa_eh_globals *globals = __cxa_get_globals (); 141 return globals->uncaughtExceptions != 0; 142#else 143 return false; 144#endif 145} 146 147int 148std::uncaught_exceptions() throw() 149{ 150#if __cpp_exceptions 151 __cxa_eh_globals *globals = __cxa_get_globals (); 152 return globals->uncaughtExceptions; 153#else 154 return 0; 155#endif 156} 157