Commit c4bca01b by Jakub Jelinek Committed by Jakub Jelinek

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
parent 1f93f687
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
......
// -*- 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));
}
......
// -*- 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;
......
// -*- 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 ();
}
......
// -*- 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)
{
......
// 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 ();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment