Skip to content
This repository has been archived by the owner on May 21, 2019. It is now read-only.

Support of SJ/LJ unwinding (for iOS) #1

Closed
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 52 additions & 20 deletions lib/builtins/gcc_personality_v0.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
}
}