diff options
author | David Chisnall <dchisnall@pathscale.com> | 2011-11-23 10:35:55 +0000 |
---|---|---|
committer | David Chisnall <dchisnall@pathscale.com> | 2011-11-23 11:11:43 +0000 |
commit | c5a86232b046313db9845de6a4c74e2733177927 (patch) | |
tree | 4931d9f9af75935703de28278b8d1cba1ce1ad43 | |
parent | f007779dc207227afd301fdc6270a42bf4e0a89f (diff) | |
download | libcxxrt-c5a86232b046313db9845de6a4c74e2733177927.tar.gz libcxxrt-c5a86232b046313db9845de6a4c74e2733177927.tar.bz2 libcxxrt-c5a86232b046313db9845de6a4c74e2733177927.tar.xz |
And remember to save the temporaries in the ARM EH header if required...
-rw-r--r-- | src/exception.cc | 77 |
1 files changed, 68 insertions, 9 deletions
diff --git a/src/exception.cc b/src/exception.cc index 0abf18c..1e60ee9 100644 --- a/src/exception.cc +++ b/src/exception.cc @@ -9,6 +9,67 @@ using namespace ABI_NAMESPACE; +/** + * Saves the result of the landing pad that we have found. For ARM, this is + * stored in the generic unwind structure, while on other platforms it is + * stored in the C++ exception. + */ +static void saveLandingPad(struct _Unwind_Context *context, + struct _Unwind_Exception *ucb, + struct __cxa_exception *ex, + int selector, + dw_eh_ptr_t landingPad) +{ +#ifdef __arm__ + // On ARM, we store the saved exception in the generic part of the structure + ucb->barrier_cache.sp = _Unwind_GetGR(context, 13); + ucb->barrier_cache.bitpattern[1] = (uint32_t)selector; + ucb->barrier_cache.bitpattern[3] = (uint32_t)landingPad; +#else + // Cache the results for the phase 2 unwind, if we found a handler + // and this is not a foreign exception. + if (ex) + { + ex->handlerSwitchValue = selector; + ex->catchTemp = landingPad; + } +#endif +} + +/** + * Loads the saved landing pad. Returns 1 on success, 0 on failure. + */ +static int loadLandingPad(struct _Unwind_Context *context, + struct _Unwind_Exception *ucb, + struct __cxa_exception *ex, + unsigned long *selector, + dw_eh_ptr_t *landingPad) +{ +#ifdef __arm__ + *selector = ucb->barrier_cache.bitpattern[1]; + *landingPad = (dw_eh_ptr_t)ucb->barrier_cache.bitpattern[3]; + return 1; +#else + if (ex) + { + *selector = ex->handlerSwitchValue; + *landingPad = (dw_eh_ptr_t)ex->catchTemp; + return 0; + } + return 0; +#endif +} + +static inline _Unwind_Reason_Code continueUnwinding(struct _Unwind_Exception *ex, + struct _Unwind_Context *context) +{ +#ifdef __arm__ + if (__gnu_unwind_frame(ex, context) != _URC_OK) { return _URC_FAILURE; } +#endif + return _URC_CONTINUE_UNWIND; +} + + extern "C" void __cxa_free_exception(void *thrown_exception); extern "C" void __cxa_free_dependent_exception(void *thrown_exception); extern "C" void* __dynamic_cast(const void *sub, @@ -892,7 +953,7 @@ BEGIN_PERSONALITY_FUNCTION(__gxx_personality_v0) (unsigned char*)_Unwind_GetLanguageSpecificData(context); // No LSDA implies no landing pads - try the next frame - if (0 == lsda_addr) { return _URC_CONTINUE_UNWIND; } + if (0 == lsda_addr) { return continueUnwinding(exceptionObject, context); } // These two variables define how the exception will be handled. dwarf_eh_action action = {0}; @@ -937,15 +998,14 @@ BEGIN_PERSONALITY_FUNCTION(__gxx_personality_v0) // and this is not a foreign exception. if (ex) { - ex->handlerSwitchValue = selector; - ex->actionRecord = (const char*)action.action_record; + saveLandingPad(context, exceptionObject, ex, selector, action.landing_pad); ex->languageSpecificData = (const char*)lsda_addr; - ex->catchTemp = action.landing_pad; + ex->actionRecord = (const char*)action.action_record; // ex->adjustedPtr is set when finding the action record. } return _URC_HANDLER_FOUND; } - return _URC_CONTINUE_UNWIND; + return continueUnwinding(exceptionObject, context); } @@ -958,11 +1018,11 @@ BEGIN_PERSONALITY_FUNCTION(__gxx_personality_v0) // cleanup struct dwarf_eh_lsda lsda = parse_lsda(context, lsda_addr); dwarf_eh_find_callsite(context, &lsda, &action); - if (0 == action.landing_pad) { return _URC_CONTINUE_UNWIND; } + if (0 == action.landing_pad) { return continueUnwinding(exceptionObject, context); } handler_type found_handler = check_action_record(context, &lsda, action.action_record, realEx, &selector, ex->adjustedPtr); // Ignore handlers this time. - if (found_handler != handler_cleanup) { return _URC_CONTINUE_UNWIND; } + if (found_handler != handler_cleanup) { return continueUnwinding(exceptionObject, context); } } else if (foreignException) { @@ -979,9 +1039,8 @@ BEGIN_PERSONALITY_FUNCTION(__gxx_personality_v0) else { // Restore the saved info if we saved some last time. - action.landing_pad = (dw_eh_ptr_t)ex->catchTemp; + loadLandingPad(context, exceptionObject, ex, &selector, &action.landing_pad); ex->catchTemp = 0; - selector = (unsigned long)ex->handlerSwitchValue; ex->handlerSwitchValue = 0; } |