197403Sobrien// -*- C++ -*- Exception handling and frame unwind runtime interface routines. 297403Sobrien// Copyright (C) 2001 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// This is derived from the C++ ABI for IA-64. Where we diverge 3197403Sobrien// for cross-architecture compatibility are noted with "@@@". 3297403Sobrien 33132720Skan#ifndef _UNWIND_CXX_H 34132720Skan#define _UNWIND_CXX_H 1 3597403Sobrien 3697403Sobrien// Level 2: C++ ABI 3797403Sobrien 3897403Sobrien#include <typeinfo> 3997403Sobrien#include <exception> 4097403Sobrien#include <cstddef> 4197403Sobrien#include "unwind.h" 4297403Sobrien 43169691Skan#pragma GCC visibility push(default) 44169691Skan 4597403Sobriennamespace __cxxabiv1 4697403Sobrien{ 4797403Sobrien 4897403Sobrien// A C++ exception object consists of a header, which is a wrapper around 4997403Sobrien// an unwind object header with additional C++ specific information, 5097403Sobrien// followed by the exception object itself. 5197403Sobrien 5297403Sobrienstruct __cxa_exception 5397403Sobrien{ 5497403Sobrien // Manage the exception object itself. 5597403Sobrien std::type_info *exceptionType; 5697403Sobrien void (*exceptionDestructor)(void *); 5797403Sobrien 5897403Sobrien // The C++ standard has entertaining rules wrt calling set_terminate 5997403Sobrien // and set_unexpected in the middle of the exception cleanup process. 6097403Sobrien std::unexpected_handler unexpectedHandler; 6197403Sobrien std::terminate_handler terminateHandler; 6297403Sobrien 6397403Sobrien // The caught exception stack threads through here. 6497403Sobrien __cxa_exception *nextException; 6597403Sobrien 6697403Sobrien // How many nested handlers have caught this exception. A negated 6797403Sobrien // value is a signal that this object has been rethrown. 6897403Sobrien int handlerCount; 6997403Sobrien 70169691Skan#ifdef __ARM_EABI_UNWINDER__ 71169691Skan // Stack of exceptions in cleanups. 72169691Skan __cxa_exception* nextPropagatingException; 73169691Skan 74169691Skan // The nuber of active cleanup handlers for this exception. 75169691Skan int propagationCount; 76169691Skan#else 7797403Sobrien // Cache parsed handler data from the personality routine Phase 1 7897403Sobrien // for Phase 2 and __cxa_call_unexpected. 7997403Sobrien int handlerSwitchValue; 8097403Sobrien const unsigned char *actionRecord; 8197403Sobrien const unsigned char *languageSpecificData; 82117397Skan _Unwind_Ptr catchTemp; 8397403Sobrien void *adjustedPtr; 84169691Skan#endif 8597403Sobrien 8697403Sobrien // The generic exception header. Must be last. 8797403Sobrien _Unwind_Exception unwindHeader; 8897403Sobrien}; 8997403Sobrien 9097403Sobrien// Each thread in a C++ program has access to a __cxa_eh_globals object. 9197403Sobrienstruct __cxa_eh_globals 9297403Sobrien{ 9397403Sobrien __cxa_exception *caughtExceptions; 9497403Sobrien unsigned int uncaughtExceptions; 95169691Skan#ifdef __ARM_EABI_UNWINDER__ 96169691Skan __cxa_exception* propagatingExceptions; 97169691Skan#endif 9897403Sobrien}; 9997403Sobrien 10097403Sobrien 10197403Sobrien// The __cxa_eh_globals for the current thread can be obtained by using 10297403Sobrien// either of the following functions. The "fast" version assumes at least 10397403Sobrien// one prior call of __cxa_get_globals has been made from the current 10497403Sobrien// thread, so no initialization is necessary. 10597403Sobrienextern "C" __cxa_eh_globals *__cxa_get_globals () throw(); 10697403Sobrienextern "C" __cxa_eh_globals *__cxa_get_globals_fast () throw(); 10797403Sobrien 10897403Sobrien// Allocate memory for the exception plus the thown object. 10997403Sobrienextern "C" void *__cxa_allocate_exception(std::size_t thrown_size) throw(); 11097403Sobrien 11197403Sobrien// Free the space allocated for the exception. 11297403Sobrienextern "C" void __cxa_free_exception(void *thrown_exception) throw(); 11397403Sobrien 11497403Sobrien// Throw the exception. 11597403Sobrienextern "C" void __cxa_throw (void *thrown_exception, 11697403Sobrien std::type_info *tinfo, 11797403Sobrien void (*dest) (void *)) 11897403Sobrien __attribute__((noreturn)); 11997403Sobrien 12097403Sobrien// Used to implement exception handlers. 121169691Skanextern "C" void *__cxa_get_exception_ptr (void *) throw(); 12297403Sobrienextern "C" void *__cxa_begin_catch (void *) throw(); 12397403Sobrienextern "C" void __cxa_end_catch (); 12497403Sobrienextern "C" void __cxa_rethrow () __attribute__((noreturn)); 12597403Sobrien 12697403Sobrien// These facilitate code generation for recurring situations. 12797403Sobrienextern "C" void __cxa_bad_cast (); 12897403Sobrienextern "C" void __cxa_bad_typeid (); 12997403Sobrien 13097403Sobrien// @@@ These are not directly specified by the IA-64 C++ ABI. 13197403Sobrien 13297403Sobrien// Handles re-checking the exception specification if unexpectedHandler 13397403Sobrien// throws, and if bad_exception needs to be thrown. Called from the 13497403Sobrien// compiler. 13597403Sobrienextern "C" void __cxa_call_unexpected (void *) __attribute__((noreturn)); 136252387Sdimextern "C" void __cxa_call_terminate (_Unwind_Exception*) __attribute__((noreturn)); 13797403Sobrien 138169691Skan#ifdef __ARM_EABI_UNWINDER__ 139169691Skan// Arm EABI specified routines. 140169691Skantypedef enum { 141169691Skan ctm_failed = 0, 142169691Skan ctm_succeeded = 1, 143169691Skan ctm_succeeded_with_ptr_to_base = 2 144169691Skan} __cxa_type_match_result; 145269792Sianextern "C" __cxa_type_match_result __cxa_type_match(_Unwind_Exception*, const std::type_info*, 146169691Skan bool, void**); 147269792Sianextern "C" bool __cxa_begin_cleanup (_Unwind_Exception*); 148169691Skanextern "C" void __cxa_end_cleanup (void); 149169691Skan#endif 150169691Skan 15197403Sobrien// Invokes given handler, dying appropriately if the user handler was 15297403Sobrien// so inconsiderate as to return. 15397403Sobrienextern void __terminate(std::terminate_handler) __attribute__((noreturn)); 15497403Sobrienextern void __unexpected(std::unexpected_handler) __attribute__((noreturn)); 15597403Sobrien 15697403Sobrien// The current installed user handlers. 15797403Sobrienextern std::terminate_handler __terminate_handler; 15897403Sobrienextern std::unexpected_handler __unexpected_handler; 15997403Sobrien 16097403Sobrien// These are explicitly GNU C++ specific. 16197403Sobrien 162169691Skan// Acquire the C++ exception header from the C++ object. 163169691Skanstatic inline __cxa_exception * 164169691Skan__get_exception_header_from_obj (void *ptr) 165169691Skan{ 166169691Skan return reinterpret_cast<__cxa_exception *>(ptr) - 1; 167169691Skan} 168169691Skan 169169691Skan// Acquire the C++ exception header from the generic exception header. 170169691Skanstatic inline __cxa_exception * 171169691Skan__get_exception_header_from_ue (_Unwind_Exception *exc) 172169691Skan{ 173169691Skan return reinterpret_cast<__cxa_exception *>(exc + 1) - 1; 174169691Skan} 175169691Skan 176246314Sandrew#if defined(__ARM_EABI_UNWINDER__) && !defined(__FreeBSD__) 177169691Skanstatic inline bool 178169691Skan__is_gxx_exception_class(_Unwind_Exception_Class c) 179169691Skan{ 180169691Skan // TODO: Take advantage of the fact that c will always be word aligned. 181169691Skan return c[0] == 'G' 182169691Skan && c[1] == 'N' 183169691Skan && c[2] == 'U' 184169691Skan && c[3] == 'C' 185169691Skan && c[4] == 'C' 186169691Skan && c[5] == '+' 187169691Skan && c[6] == '+' 188169691Skan && c[7] == '\0'; 189169691Skan} 190169691Skan 191169691Skanstatic inline void 192169691Skan__GXX_INIT_EXCEPTION_CLASS(_Unwind_Exception_Class c) 193169691Skan{ 194169691Skan c[0] = 'G'; 195169691Skan c[1] = 'N'; 196169691Skan c[2] = 'U'; 197169691Skan c[3] = 'C'; 198169691Skan c[4] = 'C'; 199169691Skan c[5] = '+'; 200169691Skan c[6] = '+'; 201169691Skan c[7] = '\0'; 202169691Skan} 203246314Sandrew#else // !__ARM_EABI_UNWINDER__ || __FreeBSD__ 20497403Sobrien// This is the exception class we report -- "GNUCC++\0". 20597403Sobrienconst _Unwind_Exception_Class __gxx_exception_class 20697403Sobrien= ((((((((_Unwind_Exception_Class) 'G' 20797403Sobrien << 8 | (_Unwind_Exception_Class) 'N') 20897403Sobrien << 8 | (_Unwind_Exception_Class) 'U') 20997403Sobrien << 8 | (_Unwind_Exception_Class) 'C') 21097403Sobrien << 8 | (_Unwind_Exception_Class) 'C') 21197403Sobrien << 8 | (_Unwind_Exception_Class) '+') 21297403Sobrien << 8 | (_Unwind_Exception_Class) '+') 21397403Sobrien << 8 | (_Unwind_Exception_Class) '\0'); 21497403Sobrien 215169691Skanstatic inline bool 216169691Skan__is_gxx_exception_class(_Unwind_Exception_Class c) 217169691Skan{ 218169691Skan return c == __gxx_exception_class; 219169691Skan} 220169691Skan#define __GXX_INIT_EXCEPTION_CLASS(c) c = __gxx_exception_class 221246314Sandrew#endif 222169691Skan 223246314Sandrew#ifdef __ARM_EABI_UNWINDER__ 224246314Sandrewstatic inline void* 225246314Sandrew__gxx_caught_object(_Unwind_Exception* eo) 226246314Sandrew{ 227246314Sandrew return (void*)eo->barrier_cache.bitpattern[0]; 228246314Sandrew} 229246314Sandrew#else // !__ARM_EABI_UNWINDER__ 230246314Sandrew 23197403Sobrien// GNU C++ personality routine, Version 0. 23297403Sobrienextern "C" _Unwind_Reason_Code __gxx_personality_v0 23397403Sobrien (int, _Unwind_Action, _Unwind_Exception_Class, 23497403Sobrien struct _Unwind_Exception *, struct _Unwind_Context *); 23597403Sobrien 23697403Sobrien// GNU C++ sjlj personality routine, Version 0. 23797403Sobrienextern "C" _Unwind_Reason_Code __gxx_personality_sj0 23897403Sobrien (int, _Unwind_Action, _Unwind_Exception_Class, 23997403Sobrien struct _Unwind_Exception *, struct _Unwind_Context *); 24097403Sobrien 241169691Skanstatic inline void* 242169691Skan__gxx_caught_object(_Unwind_Exception* eo) 24397403Sobrien{ 244169691Skan __cxa_exception* header = __get_exception_header_from_ue (eo); 245169691Skan return header->adjustedPtr; 24697403Sobrien} 247169691Skan#endif // !__ARM_EABI_UNWINDER__ 24897403Sobrien 24997403Sobrien} /* namespace __cxxabiv1 */ 25097403Sobrien 251169691Skan#pragma GCC visibility pop 252169691Skan 253132720Skan#endif // _UNWIND_CXX_H 254