re PR libstdc++/38732 (Openoffice.org segfaults with runtime libs built from GCC trunk)
PR libstdc++/38732 * libsupc++/unwind-cxx.h (__cxxabiv1::__cxa_exception): Remove referenceCount field again. (__cxxabiv1::__cxa_refcounted_exception): New struct. (__cxxabiv1::__get_refcounted_exception_header_from_obj, __cxxabiv1::__get_refcounted_exception_header_from_ue): New static inline functions. * libsupc++/eh_alloc.cc (__cxxabiv1::__cxa_allocate_exception, __cxxabiv1::__cxa_free_exception): Use __cxa_refcounted_exception instead of __cxa_exception. * libsupc++/eh_throw.cc (__gxx_exception_cleanup, __cxxabiv1::__cxa_throw): Likewise. * libsupc++/eh_ptr.cc (std::rethrow_exception, std::__exception_ptr::exception_ptr::_M_addref, std::__exception_ptr::exception_ptr::_M_release, __gxx_dependent_exception_cleanup): Likewise. * testsuite/18_support/exception/38732.cc: New test. From-SVN: r143170
This commit is contained in:
parent
1f93f6871e
commit
c4bca01b27
6 changed files with 171 additions and 37 deletions
|
@ -1,5 +1,23 @@
|
|||
2009-01-07 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR libstdc++/38732
|
||||
* libsupc++/unwind-cxx.h (__cxxabiv1::__cxa_exception): Remove
|
||||
referenceCount field again.
|
||||
(__cxxabiv1::__cxa_refcounted_exception): New struct.
|
||||
(__cxxabiv1::__get_refcounted_exception_header_from_obj,
|
||||
__cxxabiv1::__get_refcounted_exception_header_from_ue): New static
|
||||
inline functions.
|
||||
* libsupc++/eh_alloc.cc (__cxxabiv1::__cxa_allocate_exception,
|
||||
__cxxabiv1::__cxa_free_exception): Use __cxa_refcounted_exception
|
||||
instead of __cxa_exception.
|
||||
* libsupc++/eh_throw.cc (__gxx_exception_cleanup,
|
||||
__cxxabiv1::__cxa_throw): Likewise.
|
||||
* libsupc++/eh_ptr.cc (std::rethrow_exception,
|
||||
std::__exception_ptr::exception_ptr::_M_addref,
|
||||
std::__exception_ptr::exception_ptr::_M_release,
|
||||
__gxx_dependent_exception_cleanup): Likewise.
|
||||
* testsuite/18_support/exception/38732.cc: New test.
|
||||
|
||||
PR libstdc++/38092
|
||||
* acinclude.m4 (HAVE_AS_SYMVER_DIRECTIVE): New test.
|
||||
* src/compatibility.cc: Don't use .symver directives if
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// -*- C++ -*- Allocate exception objects.
|
||||
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008
|
||||
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009
|
||||
// Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of GCC.
|
||||
|
@ -103,7 +103,7 @@ __cxxabiv1::__cxa_allocate_exception(std::size_t thrown_size) throw()
|
|||
{
|
||||
void *ret;
|
||||
|
||||
thrown_size += sizeof (__cxa_exception);
|
||||
thrown_size += sizeof (__cxa_refcounted_exception);
|
||||
ret = malloc (thrown_size);
|
||||
|
||||
if (! ret)
|
||||
|
@ -137,9 +137,9 @@ __cxxabiv1::__cxa_allocate_exception(std::size_t thrown_size) throw()
|
|||
__cxa_eh_globals *globals = __cxa_get_globals ();
|
||||
globals->uncaughtExceptions += 1;
|
||||
|
||||
memset (ret, 0, sizeof (__cxa_exception));
|
||||
memset (ret, 0, sizeof (__cxa_refcounted_exception));
|
||||
|
||||
return (void *)((char *)ret + sizeof (__cxa_exception));
|
||||
return (void *)((char *)ret + sizeof (__cxa_refcounted_exception));
|
||||
}
|
||||
|
||||
|
||||
|
@ -158,7 +158,7 @@ __cxxabiv1::__cxa_free_exception(void *vptr) throw()
|
|||
emergency_used &= ~((bitmask_type)1 << which);
|
||||
}
|
||||
else
|
||||
free (ptr - sizeof (__cxa_exception));
|
||||
free (ptr - sizeof (__cxa_refcounted_exception));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// -*- C++ -*- Implement the members of exception_ptr.
|
||||
// Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of GCC.
|
||||
//
|
||||
|
@ -84,8 +84,8 @@ std::__exception_ptr::exception_ptr::_M_addref() throw()
|
|||
{
|
||||
if (_M_exception_object)
|
||||
{
|
||||
__cxa_exception *eh =
|
||||
__get_exception_header_from_obj (_M_exception_object);
|
||||
__cxa_refcounted_exception *eh =
|
||||
__get_refcounted_exception_header_from_obj (_M_exception_object);
|
||||
__sync_add_and_fetch (&eh->referenceCount, 1);
|
||||
}
|
||||
}
|
||||
|
@ -96,12 +96,12 @@ std::__exception_ptr::exception_ptr::_M_release() throw()
|
|||
{
|
||||
if (_M_exception_object)
|
||||
{
|
||||
__cxa_exception *eh =
|
||||
__get_exception_header_from_obj (_M_exception_object);
|
||||
__cxa_refcounted_exception *eh =
|
||||
__get_refcounted_exception_header_from_obj (_M_exception_object);
|
||||
if (__sync_sub_and_fetch (&eh->referenceCount, 1) == 0)
|
||||
{
|
||||
if (eh->exceptionDestructor)
|
||||
eh->exceptionDestructor (_M_exception_object);
|
||||
if (eh->exc.exceptionDestructor)
|
||||
eh->exc.exceptionDestructor (_M_exception_object);
|
||||
|
||||
__cxa_free_exception (_M_exception_object);
|
||||
_M_exception_object = 0;
|
||||
|
@ -191,22 +191,22 @@ __gxx_dependent_exception_cleanup (_Unwind_Reason_Code code,
|
|||
{
|
||||
// This cleanup is set only for dependents.
|
||||
__cxa_dependent_exception *dep = __get_dependent_exception_from_ue (exc);
|
||||
__cxa_exception *header =
|
||||
__get_exception_header_from_obj (dep->primaryException);
|
||||
__cxa_refcounted_exception *header =
|
||||
__get_refcounted_exception_header_from_obj (dep->primaryException);
|
||||
|
||||
// We only want to be called through _Unwind_DeleteException.
|
||||
// _Unwind_DeleteException in the HP-UX IA64 libunwind library
|
||||
// returns _URC_NO_REASON and not _URC_FOREIGN_EXCEPTION_CAUGHT
|
||||
// like the GCC _Unwind_DeleteException function does.
|
||||
if (code != _URC_FOREIGN_EXCEPTION_CAUGHT && code != _URC_NO_REASON)
|
||||
__terminate (header->terminateHandler);
|
||||
__terminate (header->exc.terminateHandler);
|
||||
|
||||
__cxa_free_dependent_exception (dep);
|
||||
|
||||
if (__sync_sub_and_fetch (&header->referenceCount, 1) == 0)
|
||||
{
|
||||
if (header->exceptionDestructor)
|
||||
header->exceptionDestructor (header + 1);
|
||||
if (header->exc.exceptionDestructor)
|
||||
header->exc.exceptionDestructor (header + 1);
|
||||
|
||||
__cxa_free_exception (header + 1);
|
||||
}
|
||||
|
@ -217,7 +217,8 @@ void
|
|||
std::rethrow_exception(std::exception_ptr ep)
|
||||
{
|
||||
void *obj = ep._M_get();
|
||||
__cxa_exception *eh = __get_exception_header_from_obj (obj);
|
||||
__cxa_refcounted_exception *eh
|
||||
= __get_refcounted_exception_header_from_obj (obj);
|
||||
|
||||
__cxa_dependent_exception *dep = __cxa_allocate_dependent_exception ();
|
||||
dep->primaryException = obj;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// -*- C++ -*- Exception handling routines for throwing.
|
||||
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
||||
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||
// Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of GCC.
|
||||
|
@ -38,21 +38,22 @@ static void
|
|||
__gxx_exception_cleanup (_Unwind_Reason_Code code, _Unwind_Exception *exc)
|
||||
{
|
||||
// This cleanup is set only for primaries.
|
||||
__cxa_exception *header = __get_exception_header_from_ue (exc);
|
||||
__cxa_refcounted_exception *header
|
||||
= __get_refcounted_exception_header_from_ue (exc);
|
||||
|
||||
// We only want to be called through _Unwind_DeleteException.
|
||||
// _Unwind_DeleteException in the HP-UX IA64 libunwind library
|
||||
// returns _URC_NO_REASON and not _URC_FOREIGN_EXCEPTION_CAUGHT
|
||||
// like the GCC _Unwind_DeleteException function does.
|
||||
if (code != _URC_FOREIGN_EXCEPTION_CAUGHT && code != _URC_NO_REASON)
|
||||
__terminate (header->terminateHandler);
|
||||
__terminate (header->exc.terminateHandler);
|
||||
|
||||
#ifdef _GLIBCXX_ATOMIC_BUILTINS_4
|
||||
if (__sync_sub_and_fetch (&header->referenceCount, 1) == 0)
|
||||
{
|
||||
#endif
|
||||
if (header->exceptionDestructor)
|
||||
header->exceptionDestructor (header + 1);
|
||||
if (header->exc.exceptionDestructor)
|
||||
header->exc.exceptionDestructor (header + 1);
|
||||
|
||||
__cxa_free_exception (header + 1);
|
||||
#ifdef _GLIBCXX_ATOMIC_BUILTINS_4
|
||||
|
@ -66,23 +67,24 @@ __cxxabiv1::__cxa_throw (void *obj, std::type_info *tinfo,
|
|||
void (*dest) (void *))
|
||||
{
|
||||
// Definitely a primary.
|
||||
__cxa_exception *header = __get_exception_header_from_obj (obj);
|
||||
__cxa_refcounted_exception *header
|
||||
= __get_refcounted_exception_header_from_obj (obj);
|
||||
header->referenceCount = 1;
|
||||
header->exceptionType = tinfo;
|
||||
header->exceptionDestructor = dest;
|
||||
header->unexpectedHandler = __unexpected_handler;
|
||||
header->terminateHandler = __terminate_handler;
|
||||
__GXX_INIT_PRIMARY_EXCEPTION_CLASS(header->unwindHeader.exception_class);
|
||||
header->unwindHeader.exception_cleanup = __gxx_exception_cleanup;
|
||||
header->exc.exceptionType = tinfo;
|
||||
header->exc.exceptionDestructor = dest;
|
||||
header->exc.unexpectedHandler = __unexpected_handler;
|
||||
header->exc.terminateHandler = __terminate_handler;
|
||||
__GXX_INIT_PRIMARY_EXCEPTION_CLASS(header->exc.unwindHeader.exception_class);
|
||||
header->exc.unwindHeader.exception_cleanup = __gxx_exception_cleanup;
|
||||
|
||||
#ifdef _GLIBCXX_SJLJ_EXCEPTIONS
|
||||
_Unwind_SjLj_RaiseException (&header->unwindHeader);
|
||||
_Unwind_SjLj_RaiseException (&header->exc.unwindHeader);
|
||||
#else
|
||||
_Unwind_RaiseException (&header->unwindHeader);
|
||||
_Unwind_RaiseException (&header->exc.unwindHeader);
|
||||
#endif
|
||||
|
||||
// Some sort of unwinding error. Note that terminate is a handler.
|
||||
__cxa_begin_catch (&header->unwindHeader);
|
||||
__cxa_begin_catch (&header->exc.unwindHeader);
|
||||
std::terminate ();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// -*- C++ -*- Exception handling and frame unwind runtime interface routines.
|
||||
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
||||
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||
// Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of GCC.
|
||||
|
@ -53,9 +53,6 @@ namespace __cxxabiv1
|
|||
|
||||
struct __cxa_exception
|
||||
{
|
||||
// Manage this header.
|
||||
_Atomic_word referenceCount;
|
||||
|
||||
// Manage the exception object itself.
|
||||
std::type_info *exceptionType;
|
||||
void (*exceptionDestructor)(void *);
|
||||
|
@ -92,6 +89,14 @@ struct __cxa_exception
|
|||
_Unwind_Exception unwindHeader;
|
||||
};
|
||||
|
||||
struct __cxa_refcounted_exception
|
||||
{
|
||||
// Manage this header.
|
||||
_Atomic_word referenceCount;
|
||||
// __cxa_exception must be last, and no padding can be after it.
|
||||
__cxa_exception exc;
|
||||
};
|
||||
|
||||
// A dependent C++ exception object consists of a wrapper around an unwind
|
||||
// object header with additional C++ specific information, containing a pointer
|
||||
// to a primary exception object.
|
||||
|
@ -227,6 +232,21 @@ __get_exception_header_from_ue (_Unwind_Exception *exc)
|
|||
return reinterpret_cast<__cxa_exception *>(exc + 1) - 1;
|
||||
}
|
||||
|
||||
// Acquire the C++ refcounted exception header from the C++ object.
|
||||
static inline __cxa_refcounted_exception *
|
||||
__get_refcounted_exception_header_from_obj (void *ptr)
|
||||
{
|
||||
return reinterpret_cast<__cxa_refcounted_exception *>(ptr) - 1;
|
||||
}
|
||||
|
||||
// Acquire the C++ refcounted exception header from the generic exception
|
||||
// header.
|
||||
static inline __cxa_refcounted_exception *
|
||||
__get_refcounted_exception_header_from_ue (_Unwind_Exception *exc)
|
||||
{
|
||||
return reinterpret_cast<__cxa_refcounted_exception *>(exc + 1) - 1;
|
||||
}
|
||||
|
||||
static inline __cxa_dependent_exception *
|
||||
__get_dependent_exception_from_ue (_Unwind_Exception *exc)
|
||||
{
|
||||
|
|
93
libstdc++-v3/testsuite/18_support/exception/38732.cc
Normal file
93
libstdc++-v3/testsuite/18_support/exception/38732.cc
Normal file
|
@ -0,0 +1,93 @@
|
|||
// Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library 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.
|
||||
|
||||
// This library 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 this library; see the file COPYING. If not, write to the Free
|
||||
// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
// USA.
|
||||
|
||||
#include <typeinfo>
|
||||
#include <exception>
|
||||
#include <cstddef>
|
||||
#include "unwind.h"
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
// Before exception_ptr was introduced, some programs copied
|
||||
// part of unwind-cxx.h and used __cxa_get_globals to get at the
|
||||
// current exceptionType. __cxa_exception structure is described in the
|
||||
// C++ ABI, so they have the right to assume it works.
|
||||
// Ensure it is true.
|
||||
|
||||
struct __cxa_exception
|
||||
{
|
||||
std::type_info *exceptionType;
|
||||
void (*exceptionDestructor)(void *);
|
||||
std::unexpected_handler unexpectedHandler;
|
||||
std::terminate_handler terminateHandler;
|
||||
__cxa_exception *nextException;
|
||||
int handlerCount;
|
||||
#ifdef __ARM_EABI_UNWINDER__
|
||||
__cxa_exception* nextPropagatingException;
|
||||
int propagationCount;
|
||||
#else
|
||||
int handlerSwitchValue;
|
||||
const unsigned char *actionRecord;
|
||||
const unsigned char *languageSpecificData;
|
||||
_Unwind_Ptr catchTemp;
|
||||
void *adjustedPtr;
|
||||
#endif
|
||||
_Unwind_Exception unwindHeader;
|
||||
};
|
||||
|
||||
struct __cxa_eh_globals
|
||||
{
|
||||
__cxa_exception *caughtExceptions;
|
||||
unsigned int uncaughtExceptions;
|
||||
#ifdef __ARM_EABI_UNWINDER__
|
||||
__cxa_exception* propagatingExceptions;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern "C" __cxa_eh_globals *__cxa_get_globals () throw();
|
||||
|
||||
// PR libstdc++/38732
|
||||
void test01 ()
|
||||
{
|
||||
bool test __attribute__((unused)) = true;
|
||||
try {
|
||||
throw 0;
|
||||
} catch(...) {
|
||||
__cxa_exception *exc = __cxa_get_globals()->caughtExceptions;
|
||||
VERIFY ( exc != NULL );
|
||||
VERIFY ( typeid(int) == *exc->exceptionType );
|
||||
}
|
||||
try {
|
||||
throw 0LL;
|
||||
} catch(...) {
|
||||
__cxa_exception *exc = __cxa_get_globals()->caughtExceptions;
|
||||
VERIFY ( exc != NULL );
|
||||
VERIFY ( typeid(long long int) == *exc->exceptionType );
|
||||
}
|
||||
try {
|
||||
throw 0.0;
|
||||
} catch(...) {
|
||||
__cxa_exception *exc = __cxa_get_globals()->caughtExceptions;
|
||||
VERIFY ( exc != NULL );
|
||||
VERIFY ( typeid(double) == *exc->exceptionType );
|
||||
}
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
test01 ();
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue