diff options
author | Richard Henderson <rth@redhat.com> | 2001-03-28 03:04:51 -0800 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2001-03-28 03:04:51 -0800 |
commit | 52a11cbfcf0cfb32628b6953588b6af4037ac0b6 (patch) | |
tree | a923c8785a06871784c5177530130063c4925f5a /libstdc++-v3/libsupc++ | |
parent | ce1c98ea459813570b4588427030daa03958fda6 (diff) | |
download | gcc-52a11cbfcf0cfb32628b6953588b6af4037ac0b6.zip gcc-52a11cbfcf0cfb32628b6953588b6af4037ac0b6.tar.gz gcc-52a11cbfcf0cfb32628b6953588b6af4037ac0b6.tar.bz2 |
IA-64 ABI Exception Handling.
From-SVN: r40924
Diffstat (limited to 'libstdc++-v3/libsupc++')
-rw-r--r-- | libstdc++-v3/libsupc++/Makefile.am | 9 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/Makefile.in | 57 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/eh_alloc.cc | 157 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/eh_aux_runtime.cc | 56 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/eh_catch.cc | 103 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/eh_exception.cc | 44 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/eh_globals.cc | 120 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/eh_personality.cc | 599 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/eh_terminate.cc | 87 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/eh_throw.cc | 102 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/exception_support.cc | 388 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/exception_support.h | 65 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/pure.cc | 11 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/tinfo2.cc | 28 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/unwind-cxx.h | 163 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/vec.cc | 18 |
16 files changed, 1472 insertions, 535 deletions
diff --git a/libstdc++-v3/libsupc++/Makefile.am b/libstdc++-v3/libsupc++/Makefile.am index 4694032..ad08c0e 100644 --- a/libstdc++-v3/libsupc++/Makefile.am +++ b/libstdc++-v3/libsupc++/Makefile.am @@ -75,7 +75,14 @@ sources = \ del_opnt.cc \ del_opv.cc \ del_opvnt.cc \ - exception_support.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 \ diff --git a/libstdc++-v3/libsupc++/Makefile.in b/libstdc++-v3/libsupc++/Makefile.in index 79fe2e9..bdc1316 100644 --- a/libstdc++-v3/libsupc++/Makefile.in +++ b/libstdc++-v3/libsupc++/Makefile.in @@ -127,13 +127,11 @@ OPTIMIZE_CXXFLAGS = @OPTIMIZE_CXXFLAGS@ # These bits are all figured out from configure. Look in acinclude.m4 # or configure.in to see how they are set. See GLIBCPP_EXPORT_FLAGS # NB: DEBUGFLAGS have to be at the end so that -O2 can be overridden. -CONFIG_CXXFLAGS = \ - @EXTRA_CXX_FLAGS@ @SECTION_FLAGS@ @CSHADOW_FLAGS@ @DEBUG_FLAGS@ +CONFIG_CXXFLAGS = @EXTRA_CXX_FLAGS@ @SECTION_FLAGS@ @CSHADOW_FLAGS@ @DEBUG_FLAGS@ # Warning flags to use. -WARN_CXXFLAGS = \ - @WARN_FLAGS@ $(WERROR) -fdiagnostics-show-location=once +WARN_CXXFLAGS = @WARN_FLAGS@ $(WERROR) -fdiagnostics-show-location=once # Use common includes from acinclude.m4/GLIBCPP_EXPORT_INCLUDES @@ -145,31 +143,13 @@ LIBSUPCXX_INCLUDES = @LIBSUPCXX_INCLUDES@ LIBIO_INCLUDES = @LIBIO_INCLUDES@ TOPLEVEL_INCLUDES = @TOPLEVEL_INCLUDES@ -INCLUDES = \ - -I$(toplevel_srcdir)/gcc -I$(toplevel_srcdir)/include \ - -I$(GLIBCPP_INCLUDE_DIR) $(CSTD_INCLUDES) -I$(top_builddir)/include \ - $(LIBSUPCXX_INCLUDES) +INCLUDES = -I$(toplevel_srcdir)/gcc -I$(toplevel_srcdir)/include -I$(GLIBCPP_INCLUDE_DIR) $(CSTD_INCLUDES) -I$(top_builddir)/include $(LIBSUPCXX_INCLUDES) -headers = \ - exception new typeinfo cxxabi.h exception_defines.h +headers = exception new typeinfo cxxabi.h exception_defines.h -sources = \ - del_op.cc \ - del_opnt.cc \ - del_opv.cc \ - del_opvnt.cc \ - exception_support.cc \ - new_handler.cc \ - new_op.cc \ - new_opnt.cc \ - new_opv.cc \ - new_opvnt.cc \ - pure.cc \ - tinfo.cc \ - tinfo2.cc \ - vec.cc +sources = del_op.cc 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 new_opv.cc new_opvnt.cc pure.cc tinfo.cc tinfo2.cc vec.cc libsupc___la_SOURCES = $(sources) @@ -187,12 +167,7 @@ LIBSUPCXX_CXXFLAGS = -prefer-pic # set this option because CONFIG_CXXFLAGS has to be after # OPTIMIZE_CXXFLAGS on the compile line so that -O2 can be overridden # as the occasion call for it. (ie, --enable-debug) -AM_CXXFLAGS = \ - -fno-implicit-templates \ - $(LIBSUPCXX_CXXFLAGS) \ - $(WARN_CXXFLAGS) \ - $(OPTIMIZE_CXXFLAGS) \ - $(CONFIG_CXXFLAGS) +AM_CXXFLAGS = -fno-implicit-templates $(LIBSUPCXX_CXXFLAGS) $(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS) # libstdc++ libtool notes @@ -216,9 +191,7 @@ AM_CXXFLAGS = \ # # We have to put --tag disable-shared after --tag CXX lest things # CXX undo the affect of disable-shared. -LTCXXCOMPILE = $(LIBTOOL) --tag CXX --tag disable-shared \ - --mode=compile $(CXX) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(AM_CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --tag CXX --tag disable-shared --mode=compile $(CXX) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(AM_CXXFLAGS) # 3) We'd have a problem when building the shared libstdc++ object if @@ -227,8 +200,7 @@ LTCXXCOMPILE = $(LIBTOOL) --tag CXX --tag disable-shared \ # course is problematic at this point. So, we get the top-level # directory to configure libstdc++-v3 to use gcc as the C++ # compilation driver. -CXXLINK = $(LIBTOOL) --tag CXX --mode=link $(CXX) \ - @OPT_LDFLAGS@ @SECTION_LDFLAGS@ $(AM_CXXFLAGS) $(LDFLAGS) -o $@ +CXXLINK = $(LIBTOOL) --tag CXX --mode=link $(CXX) @OPT_LDFLAGS@ @SECTION_LDFLAGS@ $(AM_CXXFLAGS) $(LDFLAGS) -o $@ CONFIG_HEADER = ../config.h CONFIG_CLEAN_FILES = @@ -242,13 +214,16 @@ LIBS = @LIBS@ libsupc__convenience_la_LDFLAGS = libsupc__convenience_la_LIBADD = libsupc__convenience_la_OBJECTS = del_op.lo del_opnt.lo del_opv.lo \ -del_opvnt.lo exception_support.lo new_handler.lo new_op.lo new_opnt.lo \ -new_opv.lo new_opvnt.lo pure.lo tinfo.lo tinfo2.lo vec.lo +del_opvnt.lo eh_alloc.lo eh_aux_runtime.lo eh_catch.lo eh_exception.lo \ +eh_globals.lo eh_personality.lo eh_terminate.lo eh_throw.lo \ +new_handler.lo new_op.lo new_opnt.lo new_opv.lo new_opvnt.lo pure.lo \ +tinfo.lo tinfo2.lo vec.lo libsupc___la_LDFLAGS = libsupc___la_LIBADD = libsupc___la_OBJECTS = del_op.lo del_opnt.lo del_opv.lo del_opvnt.lo \ -exception_support.lo new_handler.lo new_op.lo new_opnt.lo new_opv.lo \ -new_opvnt.lo pure.lo tinfo.lo tinfo2.lo vec.lo +eh_alloc.lo eh_aux_runtime.lo eh_catch.lo eh_exception.lo eh_globals.lo \ +eh_personality.lo eh_terminate.lo eh_throw.lo new_handler.lo new_op.lo \ +new_opnt.lo new_opv.lo new_opvnt.lo pure.lo tinfo.lo tinfo2.lo vec.lo CXXFLAGS = @CXXFLAGS@ CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) @@ -417,7 +392,7 @@ distdir: $(DISTFILES) @for file in $(DISTFILES); do \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ - cp -pr $$d/$$file $(distdir)/$$file; \ + cp -pr $$/$$file $(distdir)/$$file; \ else \ test -f $(distdir)/$$file \ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ diff --git a/libstdc++-v3/libsupc++/eh_alloc.cc b/libstdc++-v3/libsupc++/eh_alloc.cc new file mode 100644 index 0000000..61dc75d --- /dev/null +++ b/libstdc++-v3/libsupc++/eh_alloc.cc @@ -0,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)); +} diff --git a/libstdc++-v3/libsupc++/eh_aux_runtime.cc b/libstdc++-v3/libsupc++/eh_aux_runtime.cc new file mode 100644 index 0000000..b10a219 --- /dev/null +++ b/libstdc++-v3/libsupc++/eh_aux_runtime.cc @@ -0,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 +} diff --git a/libstdc++-v3/libsupc++/eh_catch.cc b/libstdc++-v3/libsupc++/eh_catch.cc new file mode 100644 index 0000000..4f55d68 --- /dev/null +++ b/libstdc++-v3/libsupc++/eh_catch.cc @@ -0,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; +} diff --git a/libstdc++-v3/libsupc++/eh_exception.cc b/libstdc++-v3/libsupc++/eh_exception.cc new file mode 100644 index 0000000..3c1a7a4 --- /dev/null +++ b/libstdc++-v3/libsupc++/eh_exception.cc @@ -0,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 (); +} diff --git a/libstdc++-v3/libsupc++/eh_globals.cc b/libstdc++-v3/libsupc++/eh_globals.cc new file mode 100644 index 0000000..a247b84 --- /dev/null +++ b/libstdc++-v3/libsupc++/eh_globals.cc @@ -0,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 +} diff --git a/libstdc++-v3/libsupc++/eh_personality.cc b/libstdc++-v3/libsupc++/eh_personality.cc new file mode 100644 index 0000000..5dfadc9 --- /dev/null +++ b/libstdc++-v3/libsupc++/eh_personality.cc @@ -0,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); + } +} diff --git a/libstdc++-v3/libsupc++/eh_terminate.cc b/libstdc++-v3/libsupc++/eh_terminate.cc new file mode 100644 index 0000000..11d5829 --- /dev/null +++ b/libstdc++-v3/libsupc++/eh_terminate.cc @@ -0,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; +} diff --git a/libstdc++-v3/libsupc++/eh_throw.cc b/libstdc++-v3/libsupc++/eh_throw.cc new file mode 100644 index 0000000..a8e9ba3 --- /dev/null +++ b/libstdc++-v3/libsupc++/eh_throw.cc @@ -0,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 (); +} diff --git a/libstdc++-v3/libsupc++/exception_support.cc b/libstdc++-v3/libsupc++/exception_support.cc deleted file mode 100644 index 48adafa..0000000 --- a/libstdc++-v3/libsupc++/exception_support.cc +++ /dev/null @@ -1,388 +0,0 @@ -// Functions for Exception Support for -*- C++ -*- - -// 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 "exception_support.h" -#include "exception_defines.h" - -/* Define terminate, unexpected, set_terminate, set_unexpected as - well as the default terminate func and default unexpected func. */ - -/* __terminate and __terminate_set_func, defined in libgcc2. */ -typedef void (*__terminate_func_ptr)(void) __attribute__ ((__noreturn__)); -extern "C" void __terminate (void) __attribute__ ((__noreturn__)); -extern "C" __terminate_func_ptr __terminate_set_func (__terminate_func_ptr); - -using std::terminate; - -void -std::terminate () -{ - __terminate (); -} - -void -__default_unexpected () -{ - terminate (); -} - -static std::unexpected_handler __unexpected_func __attribute__((__noreturn__)) - = __default_unexpected; - -std::terminate_handler -std::set_terminate (std::terminate_handler func) throw() -{ - return __terminate_set_func (func); -} - -std::unexpected_handler -std::set_unexpected (std::unexpected_handler func) throw() -{ - std::unexpected_handler old = __unexpected_func; - - __unexpected_func = func; - return old; -} - -void -std::unexpected () -{ - __unexpected_func (); -} - -/* Language-specific EH info pointer, defined in libgcc2. */ -extern "C" cp_eh_info **__get_eh_info (); // actually void ** -#define CP_EH_INFO ((cp_eh_info *) *__get_eh_info ()) - -/* Exception allocate and free, defined in libgcc2. */ -extern "C" void *__eh_alloc(std::size_t); -extern "C" void __eh_free(void *); - -/* Is P the type_info node for a pointer of some kind? */ -extern bool __is_pointer (void *); - - -#ifdef __EXCEPTIONS -/* OLD Compiler hook to return a pointer to the info for the current exception. - Used by get_eh_info (). This fudges the actualy returned value to - point to the beginning of what USE to be the cp_eh_info structure. - THis is so that old code that dereferences this pointer will find - things where it expects it to be.*/ -extern "C" void * -__cp_exception_info (void) -{ - return &((*__get_eh_info ())->value); -} - -/* Old Compiler hook to return a pointer to the info for the current exception. - Used by get_eh_info (). */ - -extern "C" cp_eh_info * -__cp_eh_info (void) -{ - cp_eh_info *p = CP_EH_INFO; - return p; -} - -/* Compiler hook to return a pointer to the info for the current exception, - Set the caught bit, and increment the number of handlers that are - looking at this exception. This makes handlers smaller. */ - -extern "C" cp_eh_info * -__start_cp_handler (void) -{ - cp_eh_info *p = CP_EH_INFO; - p->caught = 1; - p->handlers++; - return p; -} - -extern "C" int __throw_type_match_rtti_2 (const void *, const void *, - void *, void **); - -extern "C" void * -__cplus_type_matcher (__eh_info *info_, void *match_info, - exception_descriptor *exception_table) -{ - cp_eh_info *info = (cp_eh_info *)info_; - - /* No exception table implies the old style mechanism, so don't check. */ - if (exception_table != NULL - && exception_table->lang.language != EH_LANG_C_plus_plus) - return NULL; - - if (match_info == CATCH_ALL_TYPE) - return (void *)1; - - /* we don't worry about version info yet, there is only one version! */ - - void *match_type = match_info; - - if (__throw_type_match_rtti_2 (match_type, info->type, - info->original_value, &info->value)) - // Arbitrary non-null pointer. - return (void *)1; - else - return NULL; -} - -/* Compiler hook to push a new exception onto the stack. - Used by expand_throw(). */ - -extern "C" void -__cp_push_exception (void *value, void *type, cleanup_fn cleanup) -{ - cp_eh_info *p = (cp_eh_info *) __eh_alloc (sizeof (cp_eh_info)); - - p->value = value; - p->type = type; - p->cleanup = cleanup; - p->handlers = 0; - p->caught = false; - p->original_value = value; - - p->eh_info.match_function = __cplus_type_matcher; - p->eh_info.language = EH_LANG_C_plus_plus; - p->eh_info.version = 1; - - cp_eh_info **q = __get_eh_info (); - - p->next = *q; - *q = p; -} - -/* Compiler hook to pop an exception that has been finalized. Used by - push_eh_cleanup(). P is the info for the exception caught by the - current catch block. */ - -extern "C" void -__cp_pop_exception (void* p_) -{ - cp_eh_info *p = static_cast <cp_eh_info *> (p_); - cp_eh_info **stack = __get_eh_info (); - cp_eh_info **q = stack; - - --p->handlers; - - /* Do nothing if our exception is being rethrown (i.e. if the active - exception is our exception and it is uncaught). */ - if (p == *q && !p->caught) - return; - - /* Don't really pop if there are still active handlers for our exception; - rather, push it down past any uncaught exceptions. */ - if (p->handlers != 0) - { - if (p == *q && p->next && !p->next->caught) - { - q = &(p->next); - while (1) - { - if (*q == 0 || (*q)->caught) - break; - - q = &((*q)->next); - } - *stack = p->next; - p->next = *q; - *q = p; - } - return; - } - - for (; *q; q = &((*q)->next)) - if (*q == p) - break; - - if (! *q) - terminate (); - - *q = p->next; - - if (p->cleanup) - // value may have been adjusted. - CALL_CLEANUP (p->cleanup, p->original_value); - - if (! __is_pointer (p->type)) - __eh_free (p->original_value); // value may have been adjusted. - - __eh_free (p); -} - -/* We're doing a rethrow. Find the currently handled exception, mark it - uncaught, and move it to the top of the EH stack. */ - -extern "C" cp_eh_info * -__uncatch_exception (void) -{ - cp_eh_info **stack = __get_eh_info (); - cp_eh_info **q = stack; - cp_eh_info *p; - - while (1) - { - p = *q; - - if (p == 0) - terminate (); - if (p->caught) - break; - - q = &(p->next); - } - - if (q != stack) - { - *q = p->next; - p->next = *stack; - *stack = p; - } - - p->caught = false; - - return p; -} - -/* Mark P as caught after we previously marked it as uncaught. */ - -extern "C" void -__recatch_exception (cp_eh_info *p) -{ - p->caught = true; -} - -/* As per [except.unexpected]: - If an exception is thrown, we check it against the spec. If it doesn't - match, we call unexpected (). If unexpected () throws, we check that - exception against the spec. If it doesn't match, if the spec allows - bad_exception we throw that; otherwise we call terminate (). - - The compiler treats an exception spec as a try block with a generic - handler that just calls this function with a list of the allowed - exception types, so we have an active exception that can be rethrown. - - This function does not return. */ - -extern "C" void -__check_eh_spec (int n, const void **spec) -{ - cp_eh_info *p = CP_EH_INFO; - void *d; - - for (int i = 0; i < n; ++i) - { - if (__throw_type_match_rtti_2 (spec[i], p->type, p->value, &d)) - throw; - } - - try - { - std::unexpected (); - } - catch (...) - { - // __exception_info is an artificial var pushed into each catch block. - if (p != __exception_info) - { - p = __exception_info; - for (int i = 0; i < n; ++i) - { - if (__throw_type_match_rtti_2 (spec[i], p->type, p->value, &d)) - throw; - } - } - - const std::type_info &bad_exc = typeid (std::bad_exception); - for (int i = 0; i < n; ++i) - { - if (__throw_type_match_rtti_2 (spec[i], &bad_exc, p->value, &d)) - throw std::bad_exception (); - } - - terminate (); - } -} - -/* Special case of the above for throw() specs. */ - -extern "C" void -__check_null_eh_spec (void) -{ - __check_eh_spec (0, 0); -} -#endif //__EXCEPTIONS - -// Helpers for rtti. Although these don't return, we give them return types so -// that the type system is not broken. -extern "C" void * -__cxa_bad_cast () -{ -#ifdef __EXCEPTIONS - throw std::bad_cast(); -#else - std::abort(); -#endif - return 0; -} - -extern "C" std::type_info const & -__cxa_bad_typeid () -{ -#ifdef __EXCEPTIONS - throw std::bad_typeid(); -#else - std::abort(); -#endif - return typeid (void); -} - -/* Has the current exception been caught? */ -bool -std::uncaught_exception() throw() -{ - cp_eh_info *p = CP_EH_INFO; - return p && ! p->caught; -} - -std::exception::~exception() throw() { } - -std::bad_exception::~bad_exception() throw() { } - -const char* -std::exception::what() const throw() -{ return typeid (*this).name (); } - - - - diff --git a/libstdc++-v3/libsupc++/exception_support.h b/libstdc++-v3/libsupc++/exception_support.h deleted file mode 100644 index cc78119..0000000 --- a/libstdc++-v3/libsupc++/exception_support.h +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (C) 2000 Free Software Foundation, Inc. -// -// 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 "gansidecl.h" /* Needed to support macros used in eh-common.h. */ -#include "eh-common.h" - -/* The type of a function called to clean up an exception object. - (These will be destructors.) Under the old ABI, these take a - second argument (the `in-charge' argument), that indicates whether - or not do delete the object, and whether or not to destroy virtual - bases. Under the new ABI, there is no second argument. */ -#if !defined (__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100 -typedef void (*cleanup_fn)(void *, int); -/* The `2' is the value for the in-charge parameter that indicates - that virtual bases should be destroyed. */ -#define CALL_CLEANUP(FN, THIS) FN (THIS, 2) -#else -typedef void (*cleanup_fn)(void *); -#define CALL_CLEANUP(FN, THIS) FN (THIS) -#endif - -/* C++-specific state about the current exception. This must match - init_exception_processing(). - - Note that handlers and caught are not redundant; when rethrown, an - exception can have multiple active handlers and still be considered - uncaught. */ - -struct cp_eh_info -{ - __eh_info eh_info; - void *value; - void *type; - cleanup_fn cleanup; - bool caught; - cp_eh_info *next; - long handlers; - void *original_value; -}; - -extern "C" cp_eh_info *__uncatch_exception (void); -extern "C" void __recatch_exception (cp_eh_info *); diff --git a/libstdc++-v3/libsupc++/pure.cc b/libstdc++-v3/libsupc++/pure.cc index 7373cd1..5f9b3c8 100644 --- a/libstdc++-v3/libsupc++/pure.cc +++ b/libstdc++-v3/libsupc++/pure.cc @@ -28,6 +28,7 @@ // the GNU General Public License. #include <bits/c++config.h> +#include "unwind-cxx.h" #ifdef _GLIBCPP_HAVE_UNISTD_H # include <unistd.h> @@ -42,15 +43,9 @@ # define writestr(str) fputs(str, stderr) #endif -extern "C" { - -extern void __terminate(void) __attribute__ ((__noreturn__)); - -void +extern "C" void __cxa_pure_virtual (void) { writestr ("pure virtual method called\n"); - __terminate (); -} - + std::terminate (); } diff --git a/libstdc++-v3/libsupc++/tinfo2.cc b/libstdc++-v3/libsupc++/tinfo2.cc index a29d1d3..8f3d631 100644 --- a/libstdc++-v3/libsupc++/tinfo2.cc +++ b/libstdc++-v3/libsupc++/tinfo2.cc @@ -165,31 +165,3 @@ __pointer_catch (const __pbase_type_info *thr_type, } } // 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 (); -} - diff --git a/libstdc++-v3/libsupc++/unwind-cxx.h b/libstdc++-v3/libsupc++/unwind-cxx.h new file mode 100644 index 0000000..ce897b9 --- /dev/null +++ b/libstdc++-v3/libsupc++/unwind-cxx.h @@ -0,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 diff --git a/libstdc++-v3/libsupc++/vec.cc b/libstdc++-v3/libsupc++/vec.cc index 037d052..5bd8ec8 100644 --- a/libstdc++-v3/libsupc++/vec.cc +++ b/libstdc++-v3/libsupc++/vec.cc @@ -35,7 +35,7 @@ #include <exception> #include <exception_defines.h> -#include "exception_support.h" +#include "unwind-cxx.h" namespace __cxxabiv1 { @@ -43,11 +43,21 @@ namespace __cxxabiv1 { struct uncatch_exception { - uncatch_exception () { p = __uncatch_exception (); } - ~uncatch_exception () { __recatch_exception (p); } + uncatch_exception (); + ~uncatch_exception () { __cxa_begin_catch (&p->unwindHeader); } - cp_eh_info *p; + __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. |