This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[csl-arm] Fix __cxa{begin,end}_cleanup
- From: Paul Brook <paul at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: libstdc++ at gcc dot gnu dot org,Daniel Jacobowitz <dan at codesourcery dot com>
- Date: Fri, 17 Dec 2004 17:57:06 +0000
- Subject: [csl-arm] Fix __cxa{begin,end}_cleanup
- Organization: CodeSourcery
I not must have been concentrating when I implemented
__cxa_{begin,end}_cleanup because I got the interface wrong.
These should maintain a stack of propagating exceptions so that that caller
does not need to pass the exception object to cxa_end_cleanup.
The attached patch rectifies this.
Tested with cross to arm-none-eabi and arm-unknown-elf.
Applied to csl-arm-branch.
Paul
2004-12-17 Paul Brook <paul@codesourcery.com>
* libsupc++/eh_arm.cc (__cxa_begin_cleanup): Add exception to list.
(cxa_end_cleanup): Call __gnu_end_cleanup.
(__gnu_end_cleanup): New function.
* libsupc++/unwind-cxx.h (struct __cxa_exception): Add field for
propagating exception stack.
(struct __cxa_exception): Add propagatingExceptions.
Index: libsupc++/eh_arm.cc
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/libstdc++-v3/libsupc++/Attic/eh_arm.cc,v
retrieving revision 1.1.2.3
diff -u -p -r1.1.2.3 eh_arm.cc
--- libsupc++/eh_arm.cc 17 Nov 2004 00:10:57 -0000 1.1.2.3
+++ libsupc++/eh_arm.cc 10 Dec 2004 12:56:50 -0000
@@ -83,16 +83,69 @@ __cxa_type_match(_Unwind_Exception* ue_h
return ctm_failed;
}
-extern "C" void
-__cxa_begin_cleanup(_Unwind_Exception* ue_header __attribute__((unused)))
+extern "C" bool
+__cxa_begin_cleanup(_Unwind_Exception* ue_header)
{
+ __cxa_eh_globals *globals = __cxa_get_globals();
+ __cxa_exception *header = __get_exception_header_from_ue(ue_header);
+
+ if (!__is_gxx_exception_class(header->unwindHeader.exception_class))
+ {
+ // TODO: cleanups with foreign exceptions.
+ return false;
+ }
+ header->propagationCount++;
+ // Add it to the chain if this is the first time we've seen this exception.
+ if (header->propagationCount == 1)
+ {
+ header->nextPropagatingException = globals->propagatingExceptions;
+ globals->propagatingExceptions = header;
+ }
+ return true;
+}
+
+/* Do the work for __cxa_end_cleanup. Returns the currently propagating
+ exception object. */
+extern "C" _Unwind_Exception *
+__gnu_end_cleanup(void)
+{
+ __cxa_exception *header;
+ __cxa_eh_globals *globals = __cxa_get_globals();
+
+ header = globals->propagatingExceptions;
+
+ // Check something hasn't gone horribly wrong.
+ if (!header)
+ std::terminate();
+
+ header->propagationCount--;
+ if (header->propagationCount == 0)
+ {
+ // Remove exception from chain.
+ globals->propagatingExceptions = header->nextPropagatingException;
+ header->nextPropagatingException = NULL;
+ }
+ return &header->unwindHeader;
}
-/* This needs to tailcall _Unwind_Resume without clobbering any registers,
- or altering the stack. */
+/* This needs to run the C++ semantics routine, then tailcall
+ _Unwind_Resume without clobbering any registers or altering the stack. */
extern "C" void __attribute__((naked))
-__cxa_end_cleanup (_Unwind_Exception* ue_header)
+__cxa_end_cleanup(void)
{
- _Unwind_Resume (ue_header);
+ /* We only need to save r1-r3. Push r4 to preserve stack alignment. */
+#ifdef __thumb__
+ asm volatile ("push\t{r1, r2, r3, r4}\n"
+ "bl\t__gnu_end_cleanup\n"
+ "pop\t{r1, r2, r3, r4}\n"
+ "bl\t_Unwind_Resume\n"
+ ::: "memory");
+#else
+ asm volatile ("stmfd\tsp!, {r1, r2, r3, r4}\n"
+ "bl\t__gnu_end_cleanup\n"
+ "ldmfd\tsp!, {r1, r2, r3, r4}\n"
+ "bl\t_Unwind_Resume\n"
+ ::: "memory");
+#endif
}
#endif
Index: libsupc++/unwind-cxx.h
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/libstdc++-v3/libsupc++/unwind-cxx.h,v
retrieving revision 1.6.8.3
diff -u -p -r1.6.8.3 unwind-cxx.h
--- libsupc++/unwind-cxx.h 17 Nov 2004 00:10:57 -0000 1.6.8.3
+++ libsupc++/unwind-cxx.h 17 Dec 2004 01:17:56 -0000
@@ -67,6 +67,14 @@ struct __cxa_exception
// value is a signal that this object has been rethrown.
int handlerCount;
+#ifdef __ARM_EABI_UNWINDER__
+ // Stack of exceptions in cleanups.
+ __cxa_exception *nextPropagatingException;
+
+ // The nuber of active cleanup handlers for this exception.
+ int propagationCount;
+#endif
+
// Cache parsed handler data from the personality routine Phase 1
// for Phase 2 and __cxa_call_unexpected.
int handlerSwitchValue;
@@ -84,6 +92,9 @@ struct __cxa_eh_globals
{
__cxa_exception *caughtExceptions;
unsigned int uncaughtExceptions;
+#ifdef __ARM_EABI_UNWINDER__
+ __cxa_exception *propagatingExceptions;
+#endif
};
@@ -133,7 +144,7 @@ typedef enum {
extern "C" bool __cxa_type_match(_Unwind_Exception*, const std::type_info*,
bool, void**);
extern "C" void __cxa_begin_cleanup (_Unwind_Exception*);
-extern "C" void __cxa_end_cleanup (_Unwind_Exception*);
+extern "C" void __cxa_end_cleanup (void);
#endif
// Invokes given handler, dying appropriately if the user handler was