From df1e1ca1f21f5d0f74c905e5f64f0a4a308dbe43 Mon Sep 17 00:00:00 2001 From: Valerii Hiora Date: Fri, 23 May 2014 15:09:39 +0300 Subject: [PATCH] Support for SJ/LJ unwinding (arm) --- lib/builtins/gcc_personality_v0.c | 72 ++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 20 deletions(-) diff --git a/lib/builtins/gcc_personality_v0.c b/lib/builtins/gcc_personality_v0.c index 91a77f4441..3ccfd8396c 100644 --- a/lib/builtins/gcc_personality_v0.c +++ b/lib/builtins/gcc_personality_v0.c @@ -180,7 +180,7 @@ static uintptr_t readEncodedPointer(const uint8_t** data, uint8_t encoding) * on each frame as the stack is unwound during a C++ exception * throw through a C function compiled with -fexceptions. */ -#if __arm__ +#if defined(__USING_SJLJ_EXCEPTIONS__) // the setjump-longjump based exceptions personality routine has a different name COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_sj0(int version, _Unwind_Action actions, @@ -216,34 +216,66 @@ __gcc_personality_v0(int version, _Unwind_Action actions, if (ttypeEncoding != DW_EH_PE_omit) { readULEB128(&lsda); } - /* Walk call-site table looking for range that includes current PC. */ + + uintptr_t resumeIp = 0; uint8_t callSiteEncoding = *lsda++; uint32_t callSiteTableLength = readULEB128(&lsda); - const uint8_t* callSiteTableStart = lsda; - const uint8_t* callSiteTableEnd = callSiteTableStart + callSiteTableLength; - const uint8_t* p=callSiteTableStart; - while (p < callSiteTableEnd) { - uintptr_t start = readEncodedPointer(&p, callSiteEncoding); - uintptr_t length = readEncodedPointer(&p, callSiteEncoding); - uintptr_t landingPad = readEncodedPointer(&p, callSiteEncoding); - readULEB128(&p); /* action value not used for C code */ + const uint8_t* callSite = lsda; + +#if defined(__USING_SJLJ_EXCEPTIONS__) + (void)callSiteEncoding; + (void)callSiteTableLength; + /* The given "IP" is an index into the call-site table, with two + exceptions -- -1 means no-action, and 0 means terminate. But + since we're using uleb128 values, we've not got random access + to the array. */ + if ((int) pc <= 0) + return _URC_CONTINUE_UNWIND; + else { + uintptr_t csLp; + do { + csLp = readULEB128(&callSite); + readULEB128(&callSite); // skip cs action + } + while (--pc); + + /* Can never have null landing pad for sjlj -- that would have + been indicated by a -1 call site index. */ + resumeIp = csLp + 1; + } +#else + /* Walk call-site table looking for range that includes current PC. */ + uintptr_t funcStart = _Unwind_GetRegionStart(context); + uintptr_t pcOffset = pc - funcStart; + const uint8_t* callSiteTableEnd = callSite + callSiteTableLength; + + while (callSite < callSiteTableEnd) { + uintptr_t start = readEncodedPointer(&callSite, callSiteEncoding); + uintptr_t length = readEncodedPointer(&callSite, callSiteEncoding); + uintptr_t landingPad = readEncodedPointer(&callSite, callSiteEncoding); + readULEB128(&callSite); /* action value not used for C code */ if ( landingPad == 0 ) continue; /* no landing pad for this entry */ if ( (start <= pcOffset) && (pcOffset < (start+length)) ) { /* Found landing pad for the PC. - * Set Instruction Pointer to so we re-enter function + * Set Instruction Pointer to so we re-enter function * at landing pad. The landing pad is created by the compiler * to take two parameters in registers. - */ - _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), - (uintptr_t)exceptionObject); - _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), 0); - _Unwind_SetIP(context, funcStart+landingPad); - return _URC_INSTALL_CONTEXT; + */ + resumeIp = funcStart + landingPad; + break; } } - - /* No landing pad found, continue unwinding. */ - return _URC_CONTINUE_UNWIND; +#endif // SJ/LJ + + if (resumeIp == 0) + return _URC_CONTINUE_UNWIND; + else + { + _Unwind_SetGR(context, __builtin_eh_return_data_regno (0), (uintptr_t)exceptionObject); + _Unwind_SetGR(context, __builtin_eh_return_data_regno (1), 0); + _Unwind_SetIP(context, resumeIp); + return _URC_INSTALL_CONTEXT; + } }