This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
ia64 eh, part 20c [libstdc++]
- To: gcc-patches at gcc dot gnu dot org, libstdc++ at gcc dot gnu dot org
- Subject: ia64 eh, part 20c [libstdc++]
- From: Richard Henderson <rth at redhat dot com>
- Date: Wed, 28 Mar 2001 02:06:39 -0800
This is the libstdc++ change. Differences since the last time
that Ben saw this are bug fixes to the personality routine and
the --enable-sjlj-exceptions configury (based on a change he
suggested).
r~
IA-64 ABI Exception Handling:
* acinclude.m4 (GLIBCPP_ENABLE_SJLJ_EXCEPTIONS): New.
* configure.in: Use it.
* Makefile.in, aclocal.m4, config.h.in, configure: Regenerate.
* libsupc++/Makefile.am (sources): Update files list.
* libsupc++/Makefile.in: Regenerate.
* libsupc++/eh_alloc.cc, libsupc++/eh_aux_runtime.cc: New files.
* libsupc++/eh_catch.cc, libsupc++/eh_exception.cc: New files.
* libsupc++/eh_globals.cc, libsupc++/eh_personality.cc: New files.
* libsupc++/eh_terminate.cc, libsupc++/eh_throw.cc: New files.
* libsupc++/exception_support.cc: Remove.
* libsupc++/exception_support.h: Remove.
* libsupc++/pure.cc: Use std::terminate.
* libsupc++/tinfo2.cc (__throw_type_match_rtti_2): Remove.
(__is_pointer): Remove.
* libsupc++/unwind-cxx.h: New file.
* libsupc++/vec.cc (uncatch_exception): Update for new abi.
Index: acinclude.m4
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/acinclude.m4,v
retrieving revision 1.138
diff -c -p -d -r1.138 acinclude.m4
*** acinclude.m4 2001/03/25 00:16:54 1.138
--- acinclude.m4 2001/03/28 09:55:14
*************** AC_DEFUN(GLIBCPP_ENABLE_THREADS, [
*** 1258,1263 ****
--- 1258,1323 ----
dnl
+ dnl Check for exception handling support. If an explicit enable/disable
+ dnl sjlj exceptions is given, we don't have to detect. Otherwise the
+ dnl target may or may not support call frame exceptions.
+ dnl
+ dnl GLIBCPP_ENABLE_SJLJ_EXCEPTIONS
+ dnl --enable-sjlj-exceptions forces the use of builtin setjmp.
+ dnl --disable-sjlj-exceptions forces the use of call frame unwinding.
+ dnl
+ dnl Define _GLIBCPP_SJLJ_EXCEPTIONS if the compiler is configured for it.
+ dnl
+ AC_DEFUN(GLIBCPP_ENABLE_SJLJ_EXCEPTIONS, [
+ AC_MSG_CHECKING([for exception model to use])
+ AC_LANG_SAVE
+ AC_LANG_CPLUSPLUS
+ AC_ARG_ENABLE(sjlj-exceptions,
+ [ --enable-sjlj-exceptions force use of builtin_setjmp for exceptions],
+ [:],
+ [dnl Botheration. Now we've got to detect the exception model.
+ dnl Link tests against libgcc.a are problematic since -- at least
+ dnl as of this writing -- we've not been given proper -L bits for
+ dnl single-tree newlib and libgloss.
+ dnl
+ dnl This is what AC_TRY_COMPILE would do if it didn't delete the
+ dnl conftest files before we got a change to grep them first.
+ cat > conftest.$ac_ext << EOF
+ [#]line __oline__ "configure"
+ struct S { ~S(); };
+ void bar();
+ void foo()
+ {
+ S s;
+ bar();
+ }
+ EOF
+ old_CXXFLAGS="$CXXFLAGS"
+ CXXFLAGS=-S
+ if AC_TRY_EVAL(ac_compile); then
+ if grep _Unwind_Sjlj_Resume conftest.s >/dev/null 2>&1 ; then
+ enable_sjlj_exceptions=yes
+ elif grep _Unwind_Resume conftest.s >/dev/null 2>&1 ; then
+ enable_sjlj_exceptions=no
+ fi
+ fi
+ CXXFLAGS="$old_CXXFLAGS"
+ rm -f conftest*])
+ if test x$enable_sjlj_exceptions = xyes; then
+ AC_DEFINE(_GLIBCPP_SJLJ_EXCEPTIONS, 1,
+ [Define if the compiler is configured for setjmp/longjmp exceptions.])
+ ac_exception_model_name=sjlj
+ elif test x$enable_sjlj_exceptions = xno; then
+ ac_exception_model_name="call frame"
+ else
+ AC_MSG_ERROR([unable to detect exception model])
+ fi
+ AC_LANG_RESTORE
+ AC_MSG_RESULT($ac_exception_model_name)
+ ])
+
+
+ dnl
dnl Check for template specializations for the 'long long' type extension.
dnl
dnl GLIBCPP_ENABLE_LONG_LONG
Index: configure.in
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/configure.in,v
retrieving revision 1.55
diff -c -p -d -r1.55 configure.in
*** configure.in 2001/02/26 21:47:59 1.55
--- configure.in 2001/03/28 09:55:15
*************** GLIBCPP_ENABLE_LONG_LONG([no])
*** 68,73 ****
--- 68,74 ----
GLIBCPP_ENABLE_CHEADERS([c_std])
GLIBCPP_ENABLE_THREADS
GLIBCPP_ENABLE_CXX_FLAGS([none])
+ GLIBCPP_ENABLE_SJLJ_EXCEPTIONS
if test -n "$with_cross_host"; then
Index: libsupc++/Makefile.am
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/libsupc++/Makefile.am,v
retrieving revision 1.22
diff -c -p -d -r1.22 Makefile.am
*** Makefile.am 2001/03/28 01:19:41 1.22
--- Makefile.am 2001/03/28 09:55:15
*************** sources = \
*** 75,81 ****
del_opnt.cc \
del_opv.cc \
del_opvnt.cc \
! exception_support.cc \
new_handler.cc \
new_op.cc \
new_opnt.cc \
--- 75,88 ----
del_opnt.cc \
del_opv.cc \
del_opvnt.cc \
! eh_alloc.cc \
! eh_aux_runtime.cc \
! eh_catch.cc \
! eh_exception.cc \
! eh_globals.cc \
! eh_personality.cc \
! eh_terminate.cc \
! eh_throw.cc \
new_handler.cc \
new_op.cc \
new_opnt.cc \
Index: libsupc++/eh_alloc.cc
===================================================================
RCS file: eh_alloc.cc
diff -N eh_alloc.cc
*** /dev/null Tue May 5 13:32:27 1998
--- eh_alloc.cc Wed Mar 28 01:55:15 2001
***************
*** 0 ****
--- 1,157 ----
+ // -*- C++ -*- Allocate exception objects.
+ // Copyright (C) 2001 Free Software Foundation, Inc.
+ //
+ // This file is part of GNU CC.
+ //
+ // GNU CC is free software; you can redistribute it and/or modify
+ // it under the terms of the GNU General Public License as published by
+ // the Free Software Foundation; either version 2, or (at your option)
+ // any later version.
+ //
+ // GNU CC is distributed in the hope that it will be useful,
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ // GNU General Public License for more details.
+ //
+ // You should have received a copy of the GNU General Public License
+ // along with GNU CC; see the file COPYING. If not, write to
+ // the Free Software Foundation, 59 Temple Place - Suite 330,
+ // Boston, MA 02111-1307, USA.
+
+ // As a special exception, you may use this file as part of a free software
+ // library without restriction. Specifically, if other files instantiate
+ // templates or use macros or inline functions from this file, or you compile
+ // this file and link it with other files to produce an executable, this
+ // file does not by itself cause the resulting executable to be covered by
+ // the GNU General Public License. This exception does not however
+ // invalidate any other reasons why the executable file might be covered by
+ // the GNU General Public License.
+
+ // This is derived from the C++ ABI for IA-64. Where we diverge
+ // for cross-architecture compatibility are noted with "@@@".
+
+ #include <exception>
+ #include <cstdlib>
+ #include <cstring>
+ #include <limits.h>
+ #include "unwind-cxx.h"
+ #include "gthr.h"
+
+ using namespace __cxxabiv1;
+
+
+ // ??? How to control these parameters.
+
+ // Guess from the size of basic types how large a buffer is reasonable.
+ // Note that the basic c++ exception header has 13 pointers and 2 ints,
+ // so on a system with PSImode pointers we're talking about 56 bytes
+ // just for overhead.
+
+ #if INT_MAX == 32767
+ # define EMERGENCY_OBJ_SIZE 128
+ # define EMERGENCY_OBJ_COUNT 16
+ #elif LONG_MAX == 2147483647
+ # define EMERGENCY_OBJ_SIZE 512
+ # define EMERGENCY_OBJ_COUNT 32
+ #else
+ # define EMERGENCY_OBJ_SIZE 1024
+ # define EMERGENCY_OBJ_COUNT 64
+ #endif
+
+ #ifndef __GTHREADS
+ # undef EMERGENCY_OBJ_COUNT
+ # define EMERGENCY_OBJ_COUNT 4
+ #endif
+
+ #if INT_MAX == 32767 || EMERGENCY_OBJ_COUNT <= 32
+ typedef unsigned int bitmask_type;
+ #else
+ typedef unsigned long bitmask_type;
+ #endif
+
+
+ typedef char one_buffer[EMERGENCY_OBJ_SIZE] __attribute__((aligned));
+ static one_buffer emergency_buffer[EMERGENCY_OBJ_COUNT];
+ static bitmask_type emergency_used;
+
+
+ #ifdef __GTHREADS
+ #ifdef __GTHREAD_MUTEX_INIT
+ static __gthread_mutex_t emergency_mutex =__GTHREAD_MUTEX_INIT;
+ #else
+ static __gthread_mutex_t emergency_mutex;
+ #endif
+
+ #ifdef __GTHREAD_MUTEX_INIT_FUNCTION
+ static void
+ emergency_mutex_init ()
+ {
+ __GTHREAD_MUTEX_INIT_FUNCTION (&emergency_mutex);
+ }
+ #endif
+ #endif
+
+
+ extern "C" void *
+ __cxa_allocate_exception(std::size_t thrown_size)
+ {
+ void *ret;
+
+ thrown_size += sizeof (__cxa_exception);
+ ret = malloc (thrown_size);
+
+ if (! ret)
+ {
+ #ifdef __GTHREADS
+ #ifdef __GTHREAD_MUTEX_INIT_FUNCTION
+ static __gthread_once_t once = __GTHREAD_ONCE_INIT;
+ __gthread_once (&once, emergency_mutex_init);
+ #endif
+ __gthread_mutex_lock (&emergency_mutex);
+ #endif
+
+ bitmask_type used = emergency_used;
+ unsigned int which = 0;
+
+ while (used & 1)
+ {
+ used >>= 1;
+ if (++which >= EMERGENCY_OBJ_COUNT)
+ std::terminate ();
+ }
+
+ emergency_used |= (bitmask_type)1 << which;
+ ret = &emergency_buffer[which][0];
+
+ #ifdef __GTHREADS
+ __gthread_mutex_unlock (&emergency_mutex);
+ #endif
+ }
+
+ memset (ret, 0, sizeof (__cxa_exception));
+
+ return (void *)((char *)ret + sizeof (__cxa_exception));
+ }
+
+
+ extern "C" void
+ __cxa_free_exception(void *vptr)
+ {
+ char *ptr = (char *) vptr;
+ if (ptr >= &emergency_buffer[0][0]
+ && ptr < &emergency_buffer[0][0] + sizeof (emergency_buffer))
+ {
+ unsigned int which
+ = (unsigned)(ptr - &emergency_buffer[0][0]) / EMERGENCY_OBJ_SIZE;
+
+ #ifdef __GTHREADS
+ __gthread_mutex_lock (&emergency_mutex);
+ emergency_used &= ~((bitmask_type)1 << which);
+ __gthread_mutex_unlock (&emergency_mutex);
+ #else
+ emergency_used &= ~((bitmask_type)1 << which);
+ #endif
+ }
+ else
+ free (ptr - sizeof (__cxa_exception));
+ }
Index: libsupc++/eh_aux_runtime.cc
===================================================================
RCS file: eh_aux_runtime.cc
diff -N eh_aux_runtime.cc
*** /dev/null Tue May 5 13:32:27 1998
--- eh_aux_runtime.cc Wed Mar 28 01:55:15 2001
***************
*** 0 ****
--- 1,56 ----
+ // -*- C++ -*- Common throw conditions.
+ // Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+ // Free Software Foundation
+ //
+ // This file is part of GNU CC.
+ //
+ // GNU CC is free software; you can redistribute it and/or modify
+ // it under the terms of the GNU General Public License as published by
+ // the Free Software Foundation; either version 2, or (at your option)
+ // any later version.
+ //
+ // GNU CC is distributed in the hope that it will be useful,
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ // GNU General Public License for more details.
+ //
+ // You should have received a copy of the GNU General Public License
+ // along with GNU CC; see the file COPYING. If not, write to
+ // the Free Software Foundation, 59 Temple Place - Suite 330,
+ // Boston, MA 02111-1307, USA.
+
+ // As a special exception, you may use this file as part of a free software
+ // library without restriction. Specifically, if other files instantiate
+ // templates or use macros or inline functions from this file, or you compile
+ // this file and link it with other files to produce an executable, this
+ // file does not by itself cause the resulting executable to be covered by
+ // the GNU General Public License. This exception does not however
+ // invalidate any other reasons why the executable file might be covered by
+ // the GNU General Public License.
+
+ #include "typeinfo"
+ #include "exception"
+ #include <cstddef>
+ #include "unwind-cxx.h"
+ #include "exception_defines.h"
+
+
+ extern "C" void
+ __cxa_bad_cast ()
+ {
+ #ifdef __EXCEPTIONS
+ throw std::bad_cast();
+ #else
+ std::abort();
+ #endif
+ }
+
+ extern "C" void
+ __cxa_bad_typeid ()
+ {
+ #ifdef __EXCEPTIONS
+ throw std::bad_typeid();
+ #else
+ std::abort();
+ #endif
+ }
Index: libsupc++/eh_catch.cc
===================================================================
RCS file: eh_catch.cc
diff -N eh_catch.cc
*** /dev/null Tue May 5 13:32:27 1998
--- eh_catch.cc Wed Mar 28 01:55:15 2001
***************
*** 0 ****
--- 1,103 ----
+ // -*- C++ -*- Exception handling routines for catching.
+ // Copyright (C) 2001 Free Software Foundation, Inc.
+ //
+ // This file is part of GNU CC.
+ //
+ // GNU CC is free software; you can redistribute it and/or modify
+ // it under the terms of the GNU General Public License as published by
+ // the Free Software Foundation; either version 2, or (at your option)
+ // any later version.
+ //
+ // GNU CC is distributed in the hope that it will be useful,
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ // GNU General Public License for more details.
+ //
+ // You should have received a copy of the GNU General Public License
+ // along with GNU CC; see the file COPYING. If not, write to
+ // the Free Software Foundation, 59 Temple Place - Suite 330,
+ // Boston, MA 02111-1307, USA.
+
+ // As a special exception, you may use this file as part of a free software
+ // library without restriction. Specifically, if other files instantiate
+ // templates or use macros or inline functions from this file, or you compile
+ // this file and link it with other files to produce an executable, this
+ // file does not by itself cause the resulting executable to be covered by
+ // the GNU General Public License. This exception does not however
+ // invalidate any other reasons why the executable file might be covered by
+ // the GNU General Public License.
+
+
+ #include <cstdlib>
+ #include "unwind-cxx.h"
+
+ using namespace __cxxabiv1;
+
+
+ extern "C" void *
+ __cxa_begin_catch (_Unwind_Exception *exceptionObject)
+ {
+ // ??? Foreign exceptions can't be stacked here, and there doesn't
+ // appear to be any place to store for __cxa_end_catch to destroy.
+
+ __cxa_exception *header = __get_exception_header_from_ue (exceptionObject);
+ __cxa_eh_globals *globals = __cxa_get_globals ();
+ __cxa_exception *prev = globals->caughtExceptions;
+ int count = header->handlerCount;
+
+ if (count < 0)
+ // This exception was rethrown from an immediately enclosing region.
+ count = -count + 1;
+ else
+ count += 1;
+ header->handlerCount = count;
+
+ globals->uncaughtExceptions -= 1;
+ if (header != prev)
+ {
+ header->nextException = prev;
+ globals->caughtExceptions = header;
+ }
+
+ return header->adjustedPtr;
+ }
+
+
+ extern "C" void
+ __cxa_end_catch ()
+ {
+ __cxa_eh_globals *globals = __cxa_get_globals_fast ();
+ __cxa_exception *header = globals->caughtExceptions;
+ int count = header->handlerCount;
+
+ if (count < 0)
+ {
+ // This exception was rethrown. Decrement the (inverted) catch
+ // count and remove it from the chain when it reaches zero.
+ if (++count == 0)
+ {
+ globals->uncaughtExceptions += 1;
+ globals->caughtExceptions = header->nextException;
+ }
+ }
+ else if (--count == 0)
+ {
+ // Handling for this exception is complete. Destroy the object.
+ globals->caughtExceptions = header->nextException;
+ _Unwind_DeleteException (&header->unwindHeader);
+ return;
+ }
+ else if (count < 0)
+ // A bug in the exception handling library or compiler.
+ abort ();
+
+ header->handlerCount = count;
+ }
+
+
+ bool
+ std::uncaught_exception() throw()
+ {
+ __cxa_eh_globals *globals = __cxa_get_globals ();
+ return globals->uncaughtExceptions != 0;
+ }
Index: libsupc++/eh_exception.cc
===================================================================
RCS file: eh_exception.cc
diff -N eh_exception.cc
*** /dev/null Tue May 5 13:32:27 1998
--- eh_exception.cc Wed Mar 28 01:55:15 2001
***************
*** 0 ****
--- 1,44 ----
+ // -*- C++ -*- std::exception implementation.
+ // Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+ // Free Software Foundation
+ //
+ // This file is part of GNU CC.
+ //
+ // GNU CC is free software; you can redistribute it and/or modify
+ // it under the terms of the GNU General Public License as published by
+ // the Free Software Foundation; either version 2, or (at your option)
+ // any later version.
+ //
+ // GNU CC is distributed in the hope that it will be useful,
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ // GNU General Public License for more details.
+ //
+ // You should have received a copy of the GNU General Public License
+ // along with GNU CC; see the file COPYING. If not, write to
+ // the Free Software Foundation, 59 Temple Place - Suite 330,
+ // Boston, MA 02111-1307, USA.
+
+ // As a special exception, you may use this file as part of a free software
+ // library without restriction. Specifically, if other files instantiate
+ // templates or use macros or inline functions from this file, or you compile
+ // this file and link it with other files to produce an executable, this
+ // file does not by itself cause the resulting executable to be covered by
+ // the GNU General Public License. This exception does not however
+ // invalidate any other reasons why the executable file might be covered by
+ // the GNU General Public License.
+
+
+ #include "typeinfo"
+ #include "exception"
+ #include "unwind-cxx.h"
+
+ std::exception::~exception() throw() { }
+
+ std::bad_exception::~bad_exception() throw() { }
+
+ const char*
+ std::exception::what() const throw()
+ {
+ return typeid (*this).name ();
+ }
Index: libsupc++/eh_globals.cc
===================================================================
RCS file: eh_globals.cc
diff -N eh_globals.cc
*** /dev/null Tue May 5 13:32:27 1998
--- eh_globals.cc Wed Mar 28 01:55:15 2001
***************
*** 0 ****
--- 1,120 ----
+ // -*- C++ -*- Manage the thread-local exception globals.
+ // Copyright (C) 2001 Free Software Foundation, Inc.
+ //
+ // This file is part of GNU CC.
+ //
+ // GNU CC is free software; you can redistribute it and/or modify
+ // it under the terms of the GNU General Public License as published by
+ // the Free Software Foundation; either version 2, or (at your option)
+ // any later version.
+ //
+ // GNU CC is distributed in the hope that it will be useful,
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ // GNU General Public License for more details.
+ //
+ // You should have received a copy of the GNU General Public License
+ // along with GNU CC; see the file COPYING. If not, write to
+ // the Free Software Foundation, 59 Temple Place - Suite 330,
+ // Boston, MA 02111-1307, USA.
+
+ // As a special exception, you may use this file as part of a free software
+ // library without restriction. Specifically, if other files instantiate
+ // templates or use macros or inline functions from this file, or you compile
+ // this file and link it with other files to produce an executable, this
+ // file does not by itself cause the resulting executable to be covered by
+ // the GNU General Public License. This exception does not however
+ // invalidate any other reasons why the executable file might be covered by
+ // the GNU General Public License.
+
+
+ #include <exception>
+ #include "unwind-cxx.h"
+ #include "gthr.h"
+
+ using namespace __cxxabiv1;
+
+
+ // Single-threaded fallback buffer.
+ static __cxa_eh_globals globals_static;
+
+ #if __GTHREADS
+ static __gthread_key_t globals_key;
+ static int use_thread_key = -1;
+
+ static void
+ get_globals_dtor (void *ptr)
+ {
+ __gthread_key_dtor (globals_key, ptr);
+ if (ptr)
+ free (ptr);
+ }
+
+ static void
+ get_globals_init ()
+ {
+ use_thread_key =
+ (__gthread_key_create (&globals_key, get_globals_dtor) == 0);
+ }
+
+ static void
+ get_globals_init_once ()
+ {
+ static __gthread_once_t once = __GTHREAD_ONCE_INIT;
+ if (__gthread_once (&once, get_globals_init) != 0
+ || use_thread_key < 0)
+ use_thread_key = 0;
+ }
+ #endif
+
+ extern "C" __cxa_eh_globals *
+ __cxa_get_globals_fast ()
+ {
+ #if __GTHREADS
+ if (use_thread_key)
+ return (__cxa_eh_globals *) __gthread_getspecific (globals_key);
+ else
+ return &globals_static;
+ #else
+ return &globals_static;
+ #endif
+ }
+
+ extern "C" __cxa_eh_globals *
+ __cxa_get_globals ()
+ {
+ #if __GTHREADS
+ __cxa_eh_globals *g;
+
+ if (use_thread_key == 0)
+ return &globals_static;
+
+ if (use_thread_key < 0)
+ get_globals_init_once ();
+
+ g = (__cxa_eh_globals *) __gthread_getspecific (globals_key);
+ if (! g)
+ {
+ static __gthread_once_t once = __GTHREAD_ONCE_INIT;
+
+ // Make sure use_thread_key got initialized. Some systems have
+ // dummy thread routines in their libc that return a success.
+ if (__gthread_once (&once, eh_threads_initialize) != 0
+ || use_thread_key < 0)
+ {
+ use_thread_key = 0;
+ return &globals_static;
+ }
+
+ if ((g = malloc (sizeof (__cxa_eh_globals))) == 0
+ || __gthread_setspecific (eh_context_key, (void *) g) != 0)
+ std::terminate ();
+ g->caughtExceptions = 0;
+ g->uncaughtExceptions = 0;
+ }
+
+ return g;
+ #else
+ return &globals_static;
+ #endif
+ }
Index: libsupc++/eh_personality.cc
===================================================================
RCS file: eh_personality.cc
diff -N eh_personality.cc
*** /dev/null Tue May 5 13:32:27 1998
--- eh_personality.cc Wed Mar 28 01:55:15 2001
***************
*** 0 ****
--- 1,599 ----
+ // -*- C++ -*- The GNU C++ exception personality routine.
+ // Copyright (C) 2001 Free Software Foundation, Inc.
+ //
+ // This file is part of GNU CC.
+ //
+ // GNU CC is free software; you can redistribute it and/or modify
+ // it under the terms of the GNU General Public License as published by
+ // the Free Software Foundation; either version 2, or (at your option)
+ // any later version.
+ //
+ // GNU CC is distributed in the hope that it will be useful,
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ // GNU General Public License for more details.
+ //
+ // You should have received a copy of the GNU General Public License
+ // along with GNU CC; see the file COPYING. If not, write to
+ // the Free Software Foundation, 59 Temple Place - Suite 330,
+ // Boston, MA 02111-1307, USA.
+
+ // As a special exception, you may use this file as part of a free software
+ // library without restriction. Specifically, if other files instantiate
+ // templates or use macros or inline functions from this file, or you compile
+ // this file and link it with other files to produce an executable, this
+ // file does not by itself cause the resulting executable to be covered by
+ // the GNU General Public License. This exception does not however
+ // invalidate any other reasons why the executable file might be covered by
+ // the GNU General Public License.
+
+
+ #include <bits/c++config.h>
+ #include <cstdlib>
+ #include "unwind-cxx.h"
+
+ using namespace __cxxabiv1;
+
+
+
+ // ??? These ought to go somewhere else dwarf2 or dwarf2eh related.
+
+ // Pointer encodings.
+ #define DW_EH_PE_absptr 0x00
+ #define DW_EH_PE_omit 0xff
+
+ #define DW_EH_PE_uleb128 0x01
+ #define DW_EH_PE_udata2 0x02
+ #define DW_EH_PE_udata4 0x03
+ #define DW_EH_PE_udata8 0x04
+ #define DW_EH_PE_sleb128 0x09
+ #define DW_EH_PE_sdata2 0x0A
+ #define DW_EH_PE_sdata4 0x0B
+ #define DW_EH_PE_sdata8 0x0C
+ #define DW_EH_PE_signed 0x08
+
+ #define DW_EH_PE_pcrel 0x10
+ #define DW_EH_PE_textrel 0x20
+ #define DW_EH_PE_datarel 0x30
+ #define DW_EH_PE_funcrel 0x40
+
+ static unsigned int
+ size_of_encoded_value (unsigned char encoding)
+ {
+ switch (encoding & 0x07)
+ {
+ case DW_EH_PE_absptr:
+ return sizeof (void *);
+ case DW_EH_PE_udata2:
+ return 2;
+ case DW_EH_PE_udata4:
+ return 4;
+ case DW_EH_PE_udata8:
+ return 8;
+ }
+ abort ();
+ }
+
+ static const unsigned char *
+ read_encoded_value (_Unwind_Context *context, unsigned char encoding,
+ const unsigned char *p, _Unwind_Ptr *val)
+ {
+ union unaligned
+ {
+ void *ptr;
+ unsigned u2 __attribute__ ((mode (HI)));
+ unsigned u4 __attribute__ ((mode (SI)));
+ unsigned u8 __attribute__ ((mode (DI)));
+ signed s2 __attribute__ ((mode (HI)));
+ signed s4 __attribute__ ((mode (SI)));
+ signed s8 __attribute__ ((mode (DI)));
+ } __attribute__((__packed__));
+
+ union unaligned *u = (union unaligned *) p;
+ _Unwind_Ptr result;
+
+ switch (encoding & 0x0f)
+ {
+ case DW_EH_PE_absptr:
+ result = (_Unwind_Ptr) u->ptr;
+ p += sizeof (void *);
+ break;
+
+ case DW_EH_PE_uleb128:
+ {
+ unsigned int shift = 0;
+ unsigned char byte;
+
+ result = 0;
+ do
+ {
+ byte = *p++;
+ result |= (_Unwind_Ptr)(byte & 0x7f) << shift;
+ shift += 7;
+ }
+ while (byte & 0x80);
+ }
+ break;
+
+ case DW_EH_PE_sleb128:
+ {
+ unsigned int shift = 0;
+ unsigned char byte;
+
+ result = 0;
+ do
+ {
+ byte = *p++;
+ result |= (_Unwind_Ptr)(byte & 0x7f) << shift;
+ shift += 7;
+ }
+ while (byte & 0x80);
+
+ if (shift < 8 * sizeof(result) && (byte & 0x40) != 0)
+ result |= -(1L << shift);
+ }
+ break;
+
+ case DW_EH_PE_udata2:
+ result = u->u2;
+ p += 2;
+ break;
+ case DW_EH_PE_udata4:
+ result = u->u4;
+ p += 4;
+ break;
+ case DW_EH_PE_udata8:
+ result = u->u8;
+ p += 8;
+ break;
+
+ case DW_EH_PE_sdata2:
+ result = u->s2;
+ p += 2;
+ break;
+ case DW_EH_PE_sdata4:
+ result = u->s4;
+ p += 4;
+ break;
+ case DW_EH_PE_sdata8:
+ result = u->s8;
+ p += 8;
+ break;
+
+ default:
+ abort ();
+ }
+
+ if (result != 0)
+ switch (encoding & 0xf0)
+ {
+ case DW_EH_PE_absptr:
+ break;
+
+ case DW_EH_PE_pcrel:
+ // Define as relative to the beginning of the pointer.
+ result += (_Unwind_Ptr) u;
+ break;
+
+ case DW_EH_PE_textrel:
+ case DW_EH_PE_datarel:
+ // FIXME.
+ abort ();
+
+ case DW_EH_PE_funcrel:
+ result += _Unwind_GetRegionStart (context);
+ break;
+
+ default:
+ abort ();
+ }
+
+ *val = result;
+ return p;
+ }
+
+ static inline const unsigned char *
+ read_uleb128 (const unsigned char *p, _Unwind_Ptr *val)
+ {
+ return read_encoded_value (0, DW_EH_PE_uleb128, p, val);
+ }
+
+ static inline const unsigned char *
+ read_sleb128 (const unsigned char *p, _Unwind_Ptr *val)
+ {
+ return read_encoded_value (0, DW_EH_PE_sleb128, p, val);
+ }
+
+
+ struct lsda_header_info
+ {
+ _Unwind_Ptr Start;
+ _Unwind_Ptr LPStart;
+ const unsigned char *TType;
+ const unsigned char *action_table;
+ unsigned char ttype_encoding;
+ unsigned char call_site_encoding;
+ };
+
+ static const unsigned char *
+ parse_lsda_header (_Unwind_Context *context, const unsigned char *p,
+ lsda_header_info *info)
+ {
+ _Unwind_Ptr tmp;
+ unsigned char lpstart_encoding;
+
+ info->Start = (context ? _Unwind_GetRegionStart (context) : 0);
+
+ // Find @LPStart, the base to which landing pad offsets are relative.
+ lpstart_encoding = *p++;
+ if (lpstart_encoding != DW_EH_PE_omit)
+ p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart);
+ else
+ info->LPStart = info->Start;
+
+ // Find @TType, the base of the handler and exception spec type data.
+ info->ttype_encoding = *p++;
+ if (info->ttype_encoding != DW_EH_PE_omit)
+ {
+ p = read_uleb128 (p, &tmp);
+ info->TType = p + tmp;
+ }
+ else
+ info->TType = 0;
+
+ // The encoding and length of the call-site table; the action table
+ // immediately follows.
+ info->call_site_encoding = *p++;
+ p = read_uleb128 (p, &tmp);
+ info->action_table = p + tmp;
+
+ return p;
+ }
+
+ static const std::type_info *
+ get_ttype_entry (_Unwind_Context *context, lsda_header_info *info, long i)
+ {
+ _Unwind_Ptr ptr;
+
+ i *= size_of_encoded_value (info->ttype_encoding);
+ read_encoded_value (context, info->ttype_encoding, info->TType - i, &ptr);
+
+ return reinterpret_cast<const std::type_info *>(ptr);
+ }
+
+ static bool
+ check_exception_spec (_Unwind_Context *context, lsda_header_info *info,
+ const std::type_info *throw_type, long filter_value)
+ {
+ const unsigned char *e = info->TType - filter_value - 1;
+
+ while (1)
+ {
+ const std::type_info *catch_type;
+ _Unwind_Ptr tmp;
+ void *dummy;
+
+ e = read_uleb128 (e, &tmp);
+
+ // Zero signals the end of the list. If we've not found
+ // a match by now, then we've failed the specification.
+ if (tmp == 0)
+ return false;
+
+ // Match a ttype entry.
+ catch_type = get_ttype_entry (context, info, tmp);
+ if (catch_type->__do_catch (throw_type, &dummy, 1))
+ return true;
+ }
+ }
+
+ // Using a different personality function name causes link failures
+ // when trying to mix code using different exception handling models.
+ #ifdef _GLIBCPP_SJLJ_EXCEPTIONS
+ #define PERSONALITY_FUNCTION __gxx_personality_sj0
+ #define __builtin_eh_return_data_regno(x) x
+ #else
+ #define PERSONALITY_FUNCTION __gxx_personality_v0
+ #endif
+
+ extern "C" _Unwind_Reason_Code
+ PERSONALITY_FUNCTION (int version,
+ _Unwind_Action actions,
+ _Unwind_Exception_Class exception_class,
+ struct _Unwind_Exception *ue_header,
+ struct _Unwind_Context *context)
+ {
+ __cxa_exception *xh = __get_exception_header_from_ue (ue_header);
+
+ enum found_handler_type
+ {
+ found_nothing,
+ found_terminate,
+ found_cleanup,
+ found_handler
+ } found_type;
+
+ lsda_header_info info;
+ const unsigned char *language_specific_data;
+ const unsigned char *action_record;
+ const unsigned char *p;
+ _Unwind_Ptr landing_pad, ip;
+ int handler_switch_value;
+ void *adjusted_ptr = xh + 1;
+
+ // Interface version check.
+ if (version != 1)
+ return _URC_FATAL_PHASE1_ERROR;
+
+ // Shortcut for phase 2 found handler for domestic exception.
+ if (actions == (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME)
+ && exception_class == __gxx_exception_class)
+ {
+ handler_switch_value = xh->handlerSwitchValue;
+ landing_pad = (_Unwind_Ptr) xh->catchTemp;
+ found_type = (landing_pad == 0 ? found_terminate : found_handler);
+ goto install_context;
+ }
+
+ language_specific_data = (const unsigned char *)
+ _Unwind_GetLanguageSpecificData (context);
+
+ // If no LSDA, then there are no handlers or cleanups.
+ if (! language_specific_data)
+ return _URC_CONTINUE_UNWIND;
+
+ // Parse the LSDA header.
+ p = parse_lsda_header (context, language_specific_data, &info);
+ ip = _Unwind_GetIP (context) - 1;
+ landing_pad = 0;
+ action_record = 0;
+ handler_switch_value = 0;
+
+ #ifdef _GLIBCPP_SJLJ_EXCEPTIONS
+ // The given "IP" is an index into the call-site table, with two
+ // exceptions -- -1 means no-action, and 0 means terminate. But
+ // since we're using uleb128 values, we've not got random access
+ // to the array.
+ if ((int) ip < 0)
+ return _URC_CONTINUE_UNWIND;
+ else if (ip == 0)
+ {
+ // Fall through to set found_terminate.
+ }
+ else
+ {
+ _Unwind_Ptr cs_lp, cs_action;
+ do
+ {
+ p = read_uleb128 (p, &cs_lp);
+ p = read_uleb128 (p, &cs_action);
+ }
+ while (--ip);
+
+ // Can never have null landing pad for sjlj -- that would have
+ // been indicated by a -1 call site index.
+ landing_pad = cs_lp + 1;
+ if (cs_action)
+ action_record = info.action_table + cs_action - 1;
+ goto found_something;
+ }
+ #else
+ // Search the call-site table for the action associated with this IP.
+ while (p < info.action_table)
+ {
+ _Unwind_Ptr cs_start, cs_len, cs_lp, cs_action;
+
+ // Note that all call-site encodings are "absolute" displacements.
+ p = read_encoded_value (0, info.call_site_encoding, p, &cs_start);
+ p = read_encoded_value (0, info.call_site_encoding, p, &cs_len);
+ p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp);
+ p = read_uleb128 (p, &cs_action);
+
+ // The table is sorted, so if we've passed the ip, stop.
+ if (ip < info.Start + cs_start)
+ p = info.action_table;
+ else if (ip < info.Start + cs_start + cs_len)
+ {
+ if (cs_lp)
+ landing_pad = info.LPStart + cs_lp;
+ if (cs_action)
+ action_record = info.action_table + cs_action - 1;
+ goto found_something;
+ }
+ }
+ #endif // _GLIBCPP_SJLJ_EXCEPTIONS
+
+ // If ip is not present in the table, call terminate. This is for
+ // a destructor inside a cleanup, or a library routine the compiler
+ // was not expecting to throw.
+ found_type = (actions & _UA_FORCE_UNWIND ? found_nothing : found_terminate);
+ goto do_something;
+
+ found_something:
+ if (landing_pad == 0)
+ {
+ // If ip is present, and has a null landing pad, there are
+ // no cleanups or handlers to be run.
+ found_type = found_nothing;
+ }
+ else if (action_record == 0)
+ {
+ // If ip is present, has a non-null landing pad, and a null
+ // action table offset, then there are only cleanups present.
+ // Cleanups use a zero switch value, as set above.
+ found_type = found_cleanup;
+ }
+ else
+ {
+ // Otherwise we have a catch handler or exception specification.
+
+ signed long ar_filter, ar_disp;
+ const std::type_info *throw_type, *catch_type;
+ bool saw_cleanup = false;
+ bool saw_handler = false;
+
+ // During forced unwinding, we only run cleanups. With a foreign
+ // exception class, there's no exception type.
+ // ??? What to do about GNU Java and GNU Ada exceptions.
+
+ if ((actions & _UA_FORCE_UNWIND)
+ || exception_class != __gxx_exception_class)
+ throw_type = 0;
+ else
+ throw_type = xh->exceptionType;
+
+ while (1)
+ {
+ _Unwind_Ptr tmp;
+
+ p = action_record;
+ p = read_sleb128 (p, &tmp); ar_filter = tmp;
+ read_sleb128 (p, &tmp); ar_disp = tmp;
+
+ if (ar_filter == 0)
+ {
+ // Zero filter values are cleanups.
+ saw_cleanup = true;
+ }
+ else if (ar_filter > 0)
+ {
+ // Positive filter values are handlers.
+ catch_type = get_ttype_entry (context, &info, ar_filter);
+ adjusted_ptr = xh + 1;
+
+ // Null catch type is a catch-all handler. We can catch
+ // foreign exceptions with this.
+ if (! catch_type)
+ {
+ if (!(actions & _UA_FORCE_UNWIND))
+ {
+ saw_handler = true;
+ break;
+ }
+ }
+ else if (throw_type)
+ {
+ // Pointer types need to adjust the actual pointer, not
+ // the pointer to pointer that is the exception object.
+ // This also has the effect of passing pointer types
+ // "by value" through the __cxa_begin_catch return value.
+ if (throw_type->__is_pointer_p ())
+ adjusted_ptr = *(void **) adjusted_ptr;
+
+ if (catch_type->__do_catch (throw_type, &adjusted_ptr, 1))
+ {
+ saw_handler = true;
+ break;
+ }
+ }
+ }
+ else
+ {
+ // Negative filter values are exception specifications.
+ // ??? How do foreign exceptions fit in? As far as I can
+ // see we can't match because there's no __cxa_exception
+ // object to stuff bits in for __cxa_call_unexpected to use.
+ if (throw_type
+ && ! check_exception_spec (context, &info, throw_type,
+ ar_filter))
+ {
+ saw_handler = true;
+ break;
+ }
+ }
+
+ if (ar_disp == 0)
+ break;
+ action_record = p + ar_disp;
+ }
+
+ if (saw_handler)
+ {
+ handler_switch_value = ar_filter;
+ found_type = found_handler;
+ }
+ else
+ found_type = (saw_cleanup ? found_cleanup : found_nothing);
+ }
+
+ do_something:
+ if (found_type == found_nothing)
+ return _URC_CONTINUE_UNWIND;
+
+ if (actions & _UA_SEARCH_PHASE)
+ {
+ if (found_type == found_cleanup)
+ return _URC_CONTINUE_UNWIND;
+
+ // For domestic exceptions, we cache data from phase 1 for phase 2.
+ if (exception_class == __gxx_exception_class)
+ {
+ xh->handlerSwitchValue = handler_switch_value;
+ xh->actionRecord = action_record;
+ xh->languageSpecificData = language_specific_data;
+ xh->adjustedPtr = adjusted_ptr;
+
+ // ??? Completely unknown what this field is supposed to be for.
+ // ??? Need to cache TType encoding base for call_unexpected.
+ xh->catchTemp = (void *) (_Unwind_Ptr) landing_pad;
+ }
+ return _URC_HANDLER_FOUND;
+ }
+
+ install_context:
+ if (found_type == found_terminate)
+ {
+ __cxa_begin_catch (&xh->unwindHeader);
+ __terminate (xh->terminateHandler);
+ }
+
+ _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
+ (_Unwind_Ptr) &xh->unwindHeader);
+ _Unwind_SetGR (context, __builtin_eh_return_data_regno (1),
+ handler_switch_value);
+ _Unwind_SetIP (context, landing_pad);
+ return _URC_INSTALL_CONTEXT;
+ }
+
+ extern "C" void
+ __cxa_call_unexpected (_Unwind_Exception *exc_obj)
+ {
+ __cxa_begin_catch (exc_obj);
+
+ // This function is a handler for our exception argument. If we exit
+ // by throwing a different exception, we'll need the original cleaned up.
+ struct end_catch_protect
+ {
+ end_catch_protect() { }
+ ~end_catch_protect() { __cxa_end_catch(); }
+ } end_catch_protect_obj;
+
+ __cxa_exception *xh = __get_exception_header_from_ue (exc_obj);
+
+ try {
+ __unexpected (xh->unexpectedHandler);
+ } catch (...) {
+ // Get the exception thrown from unexpected.
+ // ??? Foreign exceptions can't be stacked this way.
+
+ __cxa_eh_globals *globals = __cxa_get_globals_fast ();
+ __cxa_exception *new_xh = globals->caughtExceptions;
+
+ // We don't quite have enough stuff cached; re-parse the LSDA.
+ lsda_header_info info;
+ parse_lsda_header (0, xh->languageSpecificData, &info);
+
+ // If this new exception meets the exception spec, allow it.
+ if (check_exception_spec (0, &info, new_xh->exceptionType,
+ xh->handlerSwitchValue))
+ throw;
+
+ // If the exception spec allows std::bad_exception, throw that.
+ const std::type_info &bad_exc = typeid (std::bad_exception);
+ if (check_exception_spec (0, &info, &bad_exc, xh->handlerSwitchValue))
+ throw std::bad_exception ();
+
+ // Otherwise, die.
+ __terminate(xh->terminateHandler);
+ }
+ }
Index: libsupc++/eh_terminate.cc
===================================================================
RCS file: eh_terminate.cc
diff -N eh_terminate.cc
*** /dev/null Tue May 5 13:32:27 1998
--- eh_terminate.cc Wed Mar 28 01:55:15 2001
***************
*** 0 ****
--- 1,87 ----
+ // -*- C++ -*- std::terminate, std::unexpected and friends.
+ // Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+ // Free Software Foundation
+ //
+ // This file is part of GNU CC.
+ //
+ // GNU CC is free software; you can redistribute it and/or modify
+ // it under the terms of the GNU General Public License as published by
+ // the Free Software Foundation; either version 2, or (at your option)
+ // any later version.
+ //
+ // GNU CC is distributed in the hope that it will be useful,
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ // GNU General Public License for more details.
+ //
+ // You should have received a copy of the GNU General Public License
+ // along with GNU CC; see the file COPYING. If not, write to
+ // the Free Software Foundation, 59 Temple Place - Suite 330,
+ // Boston, MA 02111-1307, USA.
+
+ // As a special exception, you may use this file as part of a free software
+ // library without restriction. Specifically, if other files instantiate
+ // templates or use macros or inline functions from this file, or you compile
+ // this file and link it with other files to produce an executable, this
+ // file does not by itself cause the resulting executable to be covered by
+ // the GNU General Public License. This exception does not however
+ // invalidate any other reasons why the executable file might be covered by
+ // the GNU General Public License.
+
+ #include "typeinfo"
+ #include "exception"
+ #include <cstdlib>
+ #include "unwind-cxx.h"
+ #include "exception_defines.h"
+
+ using namespace __cxxabiv1;
+
+ /* The current installed user handlers. */
+ std::terminate_handler __cxxabiv1::__terminate_handler = abort;
+ std::unexpected_handler __cxxabiv1::__unexpected_handler = std::terminate;
+
+ void
+ __cxxabiv1::__terminate (std::terminate_handler handler)
+ {
+ try {
+ handler ();
+ abort ();
+ } catch (...) {
+ abort ();
+ }
+ }
+
+ void
+ std::terminate ()
+ {
+ __terminate (__terminate_handler);
+ }
+
+ void
+ __cxxabiv1::__unexpected (std::unexpected_handler handler)
+ {
+ handler();
+ std::terminate ();
+ }
+
+ void
+ std::unexpected ()
+ {
+ __unexpected (__unexpected_handler);
+ }
+
+ std::terminate_handler
+ std::set_terminate (std::terminate_handler func) throw()
+ {
+ std::terminate_handler old = __terminate_handler;
+ __terminate_handler = func;
+ return old;
+ }
+
+ std::unexpected_handler
+ std::set_unexpected (std::unexpected_handler func) throw()
+ {
+ std::unexpected_handler old = __unexpected_handler;
+ __unexpected_handler = func;
+ return old;
+ }
Index: libsupc++/eh_throw.cc
===================================================================
RCS file: eh_throw.cc
diff -N eh_throw.cc
*** /dev/null Tue May 5 13:32:27 1998
--- eh_throw.cc Wed Mar 28 01:55:15 2001
***************
*** 0 ****
--- 1,102 ----
+ // -*- C++ -*- Exception handling routines for throwing.
+ // Copyright (C) 2001 Free Software Foundation, Inc.
+ //
+ // This file is part of GNU CC.
+ //
+ // GNU CC is free software; you can redistribute it and/or modify
+ // it under the terms of the GNU General Public License as published by
+ // the Free Software Foundation; either version 2, or (at your option)
+ // any later version.
+ //
+ // GNU CC is distributed in the hope that it will be useful,
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ // GNU General Public License for more details.
+ //
+ // You should have received a copy of the GNU General Public License
+ // along with GNU CC; see the file COPYING. If not, write to
+ // the Free Software Foundation, 59 Temple Place - Suite 330,
+ // Boston, MA 02111-1307, USA.
+
+ // As a special exception, you may use this file as part of a free software
+ // library without restriction. Specifically, if other files instantiate
+ // templates or use macros or inline functions from this file, or you compile
+ // this file and link it with other files to produce an executable, this
+ // file does not by itself cause the resulting executable to be covered by
+ // the GNU General Public License. This exception does not however
+ // invalidate any other reasons why the executable file might be covered by
+ // the GNU General Public License.
+
+
+ #include <bits/c++config.h>
+ #include "unwind-cxx.h"
+
+
+ using namespace __cxxabiv1;
+
+
+ static void
+ __gxx_exception_cleanup (_Unwind_Reason_Code code, _Unwind_Exception *exc)
+ {
+ __cxa_exception *header = __get_exception_header_from_ue (exc);
+
+ // If we havn't been caught by a foreign handler, then this is
+ // some sort of unwind error. In that case just die immediately.
+ if (code != _URC_FOREIGN_EXCEPTION_CAUGHT)
+ __terminate (header->terminateHandler);
+
+ if (header->exceptionDestructor)
+ header->exceptionDestructor (header + 1);
+
+ __cxa_free_exception (header + 1);
+ }
+
+
+ extern "C" void
+ __cxa_throw (void *obj, std::type_info *tinfo, void (*dest) (void *))
+ {
+ __cxa_exception *header = __get_exception_header_from_obj (obj);
+ header->exceptionType = tinfo;
+ header->exceptionDestructor = dest;
+ header->unexpectedHandler = __unexpected_handler;
+ header->terminateHandler = __terminate_handler;
+ header->unwindHeader.exception_class = __gxx_exception_class;
+ header->unwindHeader.exception_cleanup = __gxx_exception_cleanup;
+
+ __cxa_eh_globals *globals = __cxa_get_globals ();
+ globals->uncaughtExceptions += 1;
+
+ #ifdef _GLIBCPP_SJLJ_EXCEPTIONS
+ _Unwind_SjLj_RaiseException (&header->unwindHeader);
+ #else
+ _Unwind_RaiseException (&header->unwindHeader);
+ #endif
+
+ // Some sort of unwinding error. Note that terminate is a handler.
+ __cxa_begin_catch (&header->unwindHeader);
+ std::terminate ();
+ }
+
+ extern "C" void
+ __cxa_rethrow ()
+ {
+ __cxa_eh_globals *globals = __cxa_get_globals ();
+ __cxa_exception *header = globals->caughtExceptions;
+
+ // Watch for luser rethrowing with no active exception.
+ if (header)
+ {
+ // Tell __cxa_end_catch this is a rethrow.
+ header->handlerCount = -header->handlerCount;
+
+ #ifdef _GLIBCPP_SJLJ_EXCEPTIONS
+ _Unwind_SjLj_RaiseException (&header->unwindHeader);
+ #else
+ _Unwind_RaiseException (&header->unwindHeader);
+ #endif
+
+ // Some sort of unwinding error. Note that terminate is a handler.
+ __cxa_begin_catch (&header->unwindHeader);
+ }
+ std::terminate ();
+ }
Index: libsupc++/pure.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/libsupc++/pure.cc,v
retrieving revision 1.7
diff -c -p -d -r1.7 pure.cc
*** pure.cc 2001/02/16 01:26:14 1.7
--- pure.cc 2001/03/28 09:55:15
***************
*** 28,33 ****
--- 28,34 ----
// the GNU General Public License.
#include <bits/c++config.h>
+ #include "unwind-cxx.h"
#ifdef _GLIBCPP_HAVE_UNISTD_H
# include <unistd.h>
***************
*** 41,56 ****
# include <stdio.h>
# define writestr(str) fputs(str, stderr)
#endif
-
- extern "C" {
! extern void __terminate(void) __attribute__ ((__noreturn__));
!
! void
__cxa_pure_virtual (void)
{
writestr ("pure virtual method called\n");
! __terminate ();
! }
!
}
--- 42,51 ----
# include <stdio.h>
# define writestr(str) fputs(str, stderr)
#endif
! extern "C" void
__cxa_pure_virtual (void)
{
writestr ("pure virtual method called\n");
! std::terminate ();
}
Index: libsupc++/tinfo2.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/libsupc++/tinfo2.cc,v
retrieving revision 1.5
diff -c -p -d -r1.5 tinfo2.cc
*** tinfo2.cc 2001/02/16 01:26:14 1.5
--- tinfo2.cc 2001/03/28 09:55:15
*************** __pointer_catch (const __pbase_type_info
*** 165,195 ****
}
} // namespace std
-
- // Entry points for the compiler.
-
- /* Low level match routine used by compiler to match types of catch
- variables and thrown objects. */
-
- extern "C" int
- __throw_type_match_rtti_2 (const void *catch_type_r, const void *throw_type_r,
- void *objptr, void **valp)
- {
- const type_info &catch_type = *(const type_info *)catch_type_r;
- const type_info &throw_type = *(const type_info *)throw_type_r;
-
- *valp = objptr;
-
- return catch_type.__do_catch (&throw_type, valp, 1);
- }
-
- /* Called from __cp_pop_exception. Is P the type_info node for a pointer
- of some kind? */
-
- bool
- __is_pointer (void *p)
- {
- const type_info *t = reinterpret_cast <const type_info *>(p);
- return t->__is_pointer_p ();
- }
-
--- 165,167 ----
Index: libsupc++/unwind-cxx.h
===================================================================
RCS file: unwind-cxx.h
diff -N unwind-cxx.h
*** /dev/null Tue May 5 13:32:27 1998
--- unwind-cxx.h Wed Mar 28 01:55:15 2001
***************
*** 0 ****
--- 1,163 ----
+ // -*- C++ -*- Exception handling and frame unwind runtime interface routines.
+ // Copyright (C) 2001 Free Software Foundation, Inc.
+ //
+ // This file is part of GNU CC.
+ //
+ // GNU CC is free software; you can redistribute it and/or modify
+ // it under the terms of the GNU General Public License as published by
+ // the Free Software Foundation; either version 2, or (at your option)
+ // any later version.
+ //
+ // GNU CC is distributed in the hope that it will be useful,
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ // GNU General Public License for more details.
+ //
+ // You should have received a copy of the GNU General Public License
+ // along with GNU CC; see the file COPYING. If not, write to
+ // the Free Software Foundation, 59 Temple Place - Suite 330,
+ // Boston, MA 02111-1307, USA.
+
+ // This is derived from the C++ ABI for IA-64. Where we diverge
+ // for cross-architecture compatibility are noted with "@@@".
+
+ #ifndef __UNWIND_CXX_H
+ #define __UNWIND_CXX_H 1
+
+ // Level 2: C++ ABI
+
+ #include <typeinfo>
+ #include <exception>
+ #include <cstddef>
+ #include "unwind.h"
+
+ namespace __cxxabiv1
+ {
+
+ // A C++ exception object consists of a header, which is a wrapper around
+ // an unwind object header with additional C++ specific information,
+ // followed by the exception object itself.
+
+ struct __cxa_exception
+ {
+ // Manage the exception object itself.
+ std::type_info *exceptionType;
+ void (*exceptionDestructor)(void *);
+
+ // The C++ standard has entertaining rules wrt calling set_terminate
+ // and set_unexpected in the middle of the exception cleanup process.
+ std::unexpected_handler unexpectedHandler;
+ std::terminate_handler terminateHandler;
+
+ // The caught exception stack threads through here.
+ __cxa_exception *nextException;
+
+ // How many nested handlers have caught this exception. A negated
+ // value is a signal that this object has been rethrown.
+ int handlerCount;
+
+ // Cache parsed handler data from the personality routine Phase 1
+ // for Phase 2 and __cxa_call_unexpected.
+ int handlerSwitchValue;
+ const unsigned char *actionRecord;
+ const unsigned char *languageSpecificData;
+ void *catchTemp;
+ void *adjustedPtr;
+
+ // The generic exception header. Must be last.
+ _Unwind_Exception unwindHeader;
+ };
+
+ // Each thread in a C++ program has access to a __cxa_eh_globals object.
+ struct __cxa_eh_globals
+ {
+ __cxa_exception *caughtExceptions;
+ unsigned int uncaughtExceptions;
+ };
+
+
+ // The __cxa_eh_globals for the current thread can be obtained by using
+ // either of the following functions. The "fast" version assumes at least
+ // one prior call of __cxa_get_globals has been made from the current
+ // thread, so no initialization is necessary.
+ extern "C" __cxa_eh_globals *__cxa_get_globals () throw();
+ extern "C" __cxa_eh_globals *__cxa_get_globals_fast () throw();
+
+ // Allocate memory for the exception plus the thown object.
+ extern "C" void *__cxa_allocate_exception(std::size_t thrown_size) throw();
+
+ // Free the space allocated for the exception.
+ extern "C" void __cxa_free_exception(void *thrown_exception) throw();
+
+ // Throw the exception.
+ extern "C" void __cxa_throw (void *thrown_exception,
+ std::type_info *tinfo,
+ void (*dest) (void *))
+ __attribute__((noreturn));
+
+ // Used to implement exception handlers.
+ extern "C" void *__cxa_begin_catch (_Unwind_Exception *) throw();
+ extern "C" void __cxa_end_catch ();
+ extern "C" void __cxa_rethrow () __attribute__((noreturn));
+
+ // These facilitate code generation for recurring situations.
+ extern "C" void __cxa_bad_cast ();
+ extern "C" void __cxa_bad_typeid ();
+
+ // @@@ These are not directly specified by the IA-64 C++ ABI.
+
+ // Handles re-checking the exception specification if unexpectedHandler
+ // throws, and if bad_exception needs to be thrown. Called from the
+ // compiler.
+ extern "C" void __cxa_call_unexpected (_Unwind_Exception *)
+ __attribute__((noreturn));
+
+ // Invokes given handler, dying appropriately if the user handler was
+ // so inconsiderate as to return.
+ extern void __terminate(std::terminate_handler) __attribute__((noreturn));
+ extern void __unexpected(std::unexpected_handler) __attribute__((noreturn));
+
+ // The current installed user handlers.
+ extern std::terminate_handler __terminate_handler;
+ extern std::unexpected_handler __unexpected_handler;
+
+ // These are explicitly GNU C++ specific.
+
+ // This is the exception class we report -- "GNUCC++\0".
+ const _Unwind_Exception_Class __gxx_exception_class
+ = ((((((((_Unwind_Exception_Class) 'G'
+ << 8 | (_Unwind_Exception_Class) 'N')
+ << 8 | (_Unwind_Exception_Class) 'U')
+ << 8 | (_Unwind_Exception_Class) 'C')
+ << 8 | (_Unwind_Exception_Class) 'C')
+ << 8 | (_Unwind_Exception_Class) '+')
+ << 8 | (_Unwind_Exception_Class) '+')
+ << 8 | (_Unwind_Exception_Class) '\0');
+
+ // GNU C++ personality routine, Version 0.
+ extern "C" _Unwind_Reason_Code __gxx_personality_v0
+ (int, _Unwind_Action, _Unwind_Exception_Class,
+ struct _Unwind_Exception *, struct _Unwind_Context *);
+
+ // GNU C++ sjlj personality routine, Version 0.
+ extern "C" _Unwind_Reason_Code __gxx_personality_sj0
+ (int, _Unwind_Action, _Unwind_Exception_Class,
+ struct _Unwind_Exception *, struct _Unwind_Context *);
+
+ // Acquire the C++ exception header from the C++ object.
+ static inline __cxa_exception *
+ __get_exception_header_from_obj (void *ptr)
+ {
+ return reinterpret_cast<__cxa_exception *>(ptr) - 1;
+ }
+
+ // Acquire the C++ exception header from the generic exception header.
+ static inline __cxa_exception *
+ __get_exception_header_from_ue (_Unwind_Exception *exc)
+ {
+ return reinterpret_cast<__cxa_exception *>(exc + 1) - 1;
+ }
+
+ } /* namespace __cxxabiv1 */
+
+ #endif // __UNWIND_CXX_H
Index: libsupc++/vec.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/libsupc++/vec.cc,v
retrieving revision 1.7
diff -c -p -d -r1.7 vec.cc
*** vec.cc 2001/03/20 16:59:44 1.7
--- vec.cc 2001/03/28 09:55:15
***************
*** 35,41 ****
#include <exception>
#include <exception_defines.h>
! #include "exception_support.h"
namespace __cxxabiv1
{
--- 35,41 ----
#include <exception>
#include <exception_defines.h>
! #include "unwind-cxx.h"
namespace __cxxabiv1
{
*************** namespace __cxxabiv1
*** 43,53 ****
{
struct uncatch_exception
{
! uncatch_exception () { p = __uncatch_exception (); }
! ~uncatch_exception () { __recatch_exception (p); }
! cp_eh_info *p;
};
}
// Allocate and construct array.
--- 43,63 ----
{
struct uncatch_exception
{
! uncatch_exception ();
! ~uncatch_exception () { __cxa_begin_catch (&p->unwindHeader); }
! __cxa_exception *p;
};
+
+ uncatch_exception::uncatch_exception ()
+ {
+ __cxa_eh_globals *globals = __cxa_get_globals_fast ();
+
+ p = globals->caughtExceptions;
+ p->handlerCount -= 1;
+ globals->caughtExceptions = p->nextException;
+ globals->uncaughtExceptions += 1;
+ }
}
// Allocate and construct array.