197403Sobrien// -*- C++ -*- Exception handling routines for catching. 2132720Skan// Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc. 397403Sobrien// 4132720Skan// This file is part of GCC. 597403Sobrien// 6132720Skan// GCC is free software; you can redistribute it and/or modify 797403Sobrien// it under the terms of the GNU General Public License as published by 897403Sobrien// the Free Software Foundation; either version 2, or (at your option) 997403Sobrien// any later version. 1097403Sobrien// 11132720Skan// GCC is distributed in the hope that it will be useful, 1297403Sobrien// but WITHOUT ANY WARRANTY; without even the implied warranty of 1397403Sobrien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1497403Sobrien// GNU General Public License for more details. 1597403Sobrien// 1697403Sobrien// You should have received a copy of the GNU General Public License 17132720Skan// along with GCC; see the file COPYING. If not, write to 18169691Skan// the Free Software Foundation, 51 Franklin Street, Fifth Floor, 19169691Skan// Boston, MA 02110-1301, USA. 2097403Sobrien 2197403Sobrien// As a special exception, you may use this file as part of a free software 2297403Sobrien// library without restriction. Specifically, if other files instantiate 2397403Sobrien// templates or use macros or inline functions from this file, or you compile 2497403Sobrien// this file and link it with other files to produce an executable, this 2597403Sobrien// file does not by itself cause the resulting executable to be covered by 2697403Sobrien// the GNU General Public License. This exception does not however 2797403Sobrien// invalidate any other reasons why the executable file might be covered by 2897403Sobrien// the GNU General Public License. 2997403Sobrien 3097403Sobrien#include <cstdlib> 3197403Sobrien#include "unwind-cxx.h" 3297403Sobrien 3397403Sobrienusing namespace __cxxabiv1; 3497403Sobrien 35169691Skanextern "C" void * 36169691Skan__cxxabiv1::__cxa_get_exception_ptr(void *exc_obj_in) throw() 37169691Skan{ 38169691Skan _Unwind_Exception *exceptionObject 39169691Skan = reinterpret_cast <_Unwind_Exception *>(exc_obj_in); 4097403Sobrien 41169691Skan return __gxx_caught_object(exceptionObject); 42169691Skan} 43169691Skan 4497403Sobrienextern "C" void * 45169691Skan__cxxabiv1::__cxa_begin_catch (void *exc_obj_in) throw() 4697403Sobrien{ 4797403Sobrien _Unwind_Exception *exceptionObject 4897403Sobrien = reinterpret_cast <_Unwind_Exception *>(exc_obj_in); 49117397Skan __cxa_eh_globals *globals = __cxa_get_globals (); 50117397Skan __cxa_exception *prev = globals->caughtExceptions; 51117397Skan __cxa_exception *header = __get_exception_header_from_ue (exceptionObject); 52169691Skan void* objectp; 5397403Sobrien 54117397Skan // Foreign exceptions can't be stacked here. If the exception stack is 55117397Skan // empty, then fine. Otherwise we really have no choice but to terminate. 56117397Skan // Note that this use of "header" is a lie. It's fine so long as we only 57117397Skan // examine header->unwindHeader though. 58169691Skan if (!__is_gxx_exception_class(header->unwindHeader.exception_class)) 59117397Skan { 60117397Skan if (prev != 0) 61117397Skan std::terminate (); 6297403Sobrien 63117397Skan // Remember for end_catch and rethrow. 64117397Skan globals->caughtExceptions = header; 65117397Skan 66117397Skan // ??? No sensible value to return; we don't know what the 67117397Skan // object is, much less where it is in relation to the header. 68117397Skan return 0; 69117397Skan } 70117397Skan 7197403Sobrien int count = header->handlerCount; 72169691Skan // Count is less than zero if this exception was rethrown from an 73169691Skan // immediately enclosing region. 7497403Sobrien if (count < 0) 7597403Sobrien count = -count + 1; 7697403Sobrien else 77169691Skan count += 1; 7897403Sobrien header->handlerCount = count; 79169691Skan globals->uncaughtExceptions -= 1; 8097403Sobrien 8197403Sobrien if (header != prev) 8297403Sobrien { 8397403Sobrien header->nextException = prev; 8497403Sobrien globals->caughtExceptions = header; 8597403Sobrien } 8697403Sobrien 87169691Skan objectp = __gxx_caught_object(exceptionObject); 88169691Skan#ifdef __ARM_EABI_UNWINDER__ 89169691Skan _Unwind_Complete(exceptionObject); 90169691Skan#endif 91169691Skan return objectp; 9297403Sobrien} 9397403Sobrien 9497403Sobrien 9597403Sobrienextern "C" void 96169691Skan__cxxabiv1::__cxa_end_catch () 9797403Sobrien{ 9897403Sobrien __cxa_eh_globals *globals = __cxa_get_globals_fast (); 9997403Sobrien __cxa_exception *header = globals->caughtExceptions; 100117397Skan 101117397Skan // A rethrow of a foreign exception will be removed from the 102117397Skan // the exception stack immediately by __cxa_rethrow. 103117397Skan if (!header) 104117397Skan return; 105117397Skan 106117397Skan // A foreign exception couldn't have been stacked (see above), 107117397Skan // so by definition processing must be complete. 108169691Skan if (!__is_gxx_exception_class(header->unwindHeader.exception_class)) 109117397Skan { 110117397Skan globals->caughtExceptions = 0; 111117397Skan _Unwind_DeleteException (&header->unwindHeader); 112117397Skan return; 113117397Skan } 114117397Skan 11597403Sobrien int count = header->handlerCount; 11697403Sobrien if (count < 0) 11797403Sobrien { 11897403Sobrien // This exception was rethrown. Decrement the (inverted) catch 11997403Sobrien // count and remove it from the chain when it reaches zero. 12097403Sobrien if (++count == 0) 121169691Skan globals->caughtExceptions = header->nextException; 12297403Sobrien } 12397403Sobrien else if (--count == 0) 12497403Sobrien { 12597403Sobrien // Handling for this exception is complete. Destroy the object. 12697403Sobrien globals->caughtExceptions = header->nextException; 12797403Sobrien _Unwind_DeleteException (&header->unwindHeader); 12897403Sobrien return; 12997403Sobrien } 13097403Sobrien else if (count < 0) 13197403Sobrien // A bug in the exception handling library or compiler. 132117397Skan std::terminate (); 13397403Sobrien 13497403Sobrien header->handlerCount = count; 13597403Sobrien} 13697403Sobrien 13797403Sobrien 13897403Sobrienbool 13997403Sobrienstd::uncaught_exception() throw() 14097403Sobrien{ 14197403Sobrien __cxa_eh_globals *globals = __cxa_get_globals (); 14297403Sobrien return globals->uncaughtExceptions != 0; 14397403Sobrien} 144