Allow the unwind functions int libgcc_s to interact correctly with libthr.
_Unwind_ForcedUnwind in libgcc_s takes as one of it's parameters a stop function to tell it when to stop unwinding. One of the stop function's parameters is a _Unwind_Exception_Class. On most architectures this is an int64_t, however on ARM EABI the gcc developers have made this a char array with 8 items. While both of these take the same space they are passed into the stop function differently, an int64_t is passed in in registers r2 and r3, while the char[8] is passed in as a pointer to the first item in register r2. Because libthr expects the value to be an int64_t we would get incorrect results when it passes a function that take an int64_t but libgcc passes in a pointer to a char array including crashing. The fix is to update libgcc_s to make it pass an int64_t to the stop function and to libstdc++ as it expects _Unwind_Exception_Class to be an array.
This commit is contained in:
parent
42fe3ad9b1
commit
93c7e89712
@ -87,7 +87,7 @@ extern "C" {
|
||||
|
||||
struct _Unwind_Control_Block
|
||||
{
|
||||
char exception_class[8];
|
||||
unsigned exception_class __attribute__((__mode__(__DI__)));
|
||||
void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block *);
|
||||
/* Unwinder cache, private fields for the unwinder's use */
|
||||
struct
|
||||
@ -186,7 +186,7 @@ extern "C" {
|
||||
|
||||
/* Support functions for the PR. */
|
||||
#define _Unwind_Exception _Unwind_Control_Block
|
||||
typedef char _Unwind_Exception_Class[8];
|
||||
typedef unsigned _Unwind_Exception_Class __attribute__((__mode__(__DI__)));
|
||||
|
||||
void * _Unwind_GetLanguageSpecificData (_Unwind_Context *);
|
||||
_Unwind_Ptr _Unwind_GetRegionStart (_Unwind_Context *);
|
||||
|
@ -173,7 +173,7 @@ __get_exception_header_from_ue (_Unwind_Exception *exc)
|
||||
return reinterpret_cast<__cxa_exception *>(exc + 1) - 1;
|
||||
}
|
||||
|
||||
#ifdef __ARM_EABI_UNWINDER__
|
||||
#if defined(__ARM_EABI_UNWINDER__) && !defined(__FreeBSD__)
|
||||
static inline bool
|
||||
__is_gxx_exception_class(_Unwind_Exception_Class c)
|
||||
{
|
||||
@ -200,13 +200,7 @@ __GXX_INIT_EXCEPTION_CLASS(_Unwind_Exception_Class c)
|
||||
c[6] = '+';
|
||||
c[7] = '\0';
|
||||
}
|
||||
|
||||
static inline void*
|
||||
__gxx_caught_object(_Unwind_Exception* eo)
|
||||
{
|
||||
return (void*)eo->barrier_cache.bitpattern[0];
|
||||
}
|
||||
#else // !__ARM_EABI_UNWINDER__
|
||||
#else // !__ARM_EABI_UNWINDER__ || __FreeBSD__
|
||||
// This is the exception class we report -- "GNUCC++\0".
|
||||
const _Unwind_Exception_Class __gxx_exception_class
|
||||
= ((((((((_Unwind_Exception_Class) 'G'
|
||||
@ -223,8 +217,16 @@ __is_gxx_exception_class(_Unwind_Exception_Class c)
|
||||
{
|
||||
return c == __gxx_exception_class;
|
||||
}
|
||||
|
||||
#define __GXX_INIT_EXCEPTION_CLASS(c) c = __gxx_exception_class
|
||||
#endif
|
||||
|
||||
#ifdef __ARM_EABI_UNWINDER__
|
||||
static inline void*
|
||||
__gxx_caught_object(_Unwind_Exception* eo)
|
||||
{
|
||||
return (void*)eo->barrier_cache.bitpattern[0];
|
||||
}
|
||||
#else // !__ARM_EABI_UNWINDER__
|
||||
|
||||
// GNU C++ personality routine, Version 0.
|
||||
extern "C" _Unwind_Reason_Code __gxx_personality_v0
|
||||
|
Loading…
Reference in New Issue
Block a user