[libc++abi] Simplify scan_eh_tab
1. All `_URC_HANDLER_FOUND` return values need to set `landingPad` and its value does not matter for `_URC_CONTINUE_UNWIND`. So we can always set `landingPad` to unify code. 2. For an exception specification (`ttypeIndex < 0`), we can check `_UA_FORCE_UNWIND` first. 3. The so-called type 3 search (`actions & _UA_CLEANUP_PHASE && !(actions & _UA_HANDLER_FRAME)`) is actually conceptually wrong. For a catch handler or an unmatched dynamic exception specification, `_UA_HANDLER_FOUND` should be returned immediately. It still appeared to work because the `ttypeIndex==0` case would return `_UA_HANDLER_FOUND` at a later time. This patch fixes the conceptual error and simplifies the code by handling type 3 the same way as type 2 (which is also what libsupc++ does). The only difference between phase 1 and phase 2 is what to do with a cleanup (`actionEntry==0`, or a `ttypeIndex==0` is found in the action record chain): phase 1 returns `_URC_CONTINUE_UNWIND` while phase 2 returns `_URC_HANDLER_FOUND`. Reviewed By: #libc_abi, compnerd Differential Revision: https://reviews.llvm.org/D93190
This commit is contained in:
parent
d38be2ba0e
commit
cfe9ccbddd
|
@ -684,27 +684,21 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
landingPad = (uintptr_t)lpStart + landingPad;
|
landingPad = (uintptr_t)lpStart + landingPad;
|
||||||
|
results.landingPad = landingPad;
|
||||||
#else // __USING_SJLJ_EXCEPTIONS__
|
#else // __USING_SJLJ_EXCEPTIONS__
|
||||||
++landingPad;
|
++landingPad;
|
||||||
#endif // __USING_SJLJ_EXCEPTIONS__
|
#endif // __USING_SJLJ_EXCEPTIONS__
|
||||||
if (actionEntry == 0)
|
if (actionEntry == 0)
|
||||||
{
|
{
|
||||||
// Found a cleanup
|
// Found a cleanup
|
||||||
// If this is a type 1 or type 2 search, there are no handlers
|
results.reason = actions & _UA_SEARCH_PHASE
|
||||||
// If this is a type 3 search, you want to install the cleanup.
|
? _URC_CONTINUE_UNWIND
|
||||||
if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME))
|
: _URC_HANDLER_FOUND;
|
||||||
{
|
|
||||||
results.ttypeIndex = 0; // Redundant but clarifying
|
|
||||||
results.landingPad = landingPad;
|
|
||||||
results.reason = _URC_HANDLER_FOUND;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// No handler here
|
|
||||||
results.reason = _URC_CONTINUE_UNWIND;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Convert 1-based byte offset into
|
// Convert 1-based byte offset into
|
||||||
const uint8_t* action = actionTableStart + (actionEntry - 1);
|
const uint8_t* action = actionTableStart + (actionEntry - 1);
|
||||||
|
bool hasCleanup = false;
|
||||||
// Scan action entries until you find a matching handler, cleanup, or the end of action list
|
// Scan action entries until you find a matching handler, cleanup, or the end of action list
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
@ -720,27 +714,17 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
|
||||||
native_exception, unwind_exception);
|
native_exception, unwind_exception);
|
||||||
if (catchType == 0)
|
if (catchType == 0)
|
||||||
{
|
{
|
||||||
// Found catch (...) catches everything, including foreign exceptions
|
// Found catch (...) catches everything, including
|
||||||
// If this is a type 1 search save state and return _URC_HANDLER_FOUND
|
// foreign exceptions. This is search phase, cleanup
|
||||||
// If this is a type 2 search save state and return _URC_HANDLER_FOUND
|
// phase with foreign exception, or forced unwinding.
|
||||||
// If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1!
|
assert(actions & (_UA_SEARCH_PHASE | _UA_HANDLER_FRAME |
|
||||||
// If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan
|
_UA_FORCE_UNWIND));
|
||||||
if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME))
|
results.ttypeIndex = ttypeIndex;
|
||||||
{
|
results.actionRecord = actionRecord;
|
||||||
// Save state and return _URC_HANDLER_FOUND
|
results.adjustedPtr =
|
||||||
results.ttypeIndex = ttypeIndex;
|
get_thrown_object_ptr(unwind_exception);
|
||||||
results.actionRecord = actionRecord;
|
results.reason = _URC_HANDLER_FOUND;
|
||||||
results.landingPad = landingPad;
|
return;
|
||||||
results.adjustedPtr = get_thrown_object_ptr(unwind_exception);
|
|
||||||
results.reason = _URC_HANDLER_FOUND;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (!(actions & _UA_FORCE_UNWIND))
|
|
||||||
{
|
|
||||||
// It looks like the exception table has changed
|
|
||||||
// on us. Likely stack corruption!
|
|
||||||
call_terminate(native_exception, unwind_exception);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Else this is a catch (T) clause and will never
|
// Else this is a catch (T) clause and will never
|
||||||
// catch a foreign exception
|
// catch a foreign exception
|
||||||
|
@ -757,36 +741,25 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
|
||||||
}
|
}
|
||||||
if (catchType->can_catch(excpType, adjustedPtr))
|
if (catchType->can_catch(excpType, adjustedPtr))
|
||||||
{
|
{
|
||||||
// Found a matching handler
|
// Found a matching handler. This is either search
|
||||||
// If this is a type 1 search save state and return _URC_HANDLER_FOUND
|
// phase or forced unwinding.
|
||||||
// If this is a type 3 search and !_UA_FORCE_UNWIND, we should have found this in phase 1!
|
assert(actions &
|
||||||
// If this is a type 3 search and _UA_FORCE_UNWIND, ignore handler and continue scan
|
(_UA_SEARCH_PHASE | _UA_FORCE_UNWIND));
|
||||||
if (actions & _UA_SEARCH_PHASE)
|
results.ttypeIndex = ttypeIndex;
|
||||||
{
|
results.actionRecord = actionRecord;
|
||||||
// Save state and return _URC_HANDLER_FOUND
|
results.adjustedPtr = adjustedPtr;
|
||||||
results.ttypeIndex = ttypeIndex;
|
results.reason = _URC_HANDLER_FOUND;
|
||||||
results.actionRecord = actionRecord;
|
return;
|
||||||
results.landingPad = landingPad;
|
|
||||||
results.adjustedPtr = adjustedPtr;
|
|
||||||
results.reason = _URC_HANDLER_FOUND;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (!(actions & _UA_FORCE_UNWIND))
|
|
||||||
{
|
|
||||||
// It looks like the exception table has changed
|
|
||||||
// on us. Likely stack corruption!
|
|
||||||
call_terminate(native_exception, unwind_exception);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Scan next action ...
|
// Scan next action ...
|
||||||
}
|
}
|
||||||
else if (ttypeIndex < 0)
|
else if (ttypeIndex < 0)
|
||||||
{
|
{
|
||||||
// Found an exception spec. If this is a foreign exception,
|
// Found an exception specification.
|
||||||
// it is always caught.
|
if (actions & _UA_FORCE_UNWIND) {
|
||||||
if (native_exception)
|
// Skip if forced unwinding.
|
||||||
{
|
} else if (native_exception) {
|
||||||
// Does the exception spec catch this native exception?
|
// Does the exception spec catch this native exception?
|
||||||
__cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
|
__cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
|
||||||
void* adjustedPtr = get_thrown_object_ptr(unwind_exception);
|
void* adjustedPtr = get_thrown_object_ptr(unwind_exception);
|
||||||
|
@ -801,77 +774,38 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
|
||||||
ttypeEncoding, excpType,
|
ttypeEncoding, excpType,
|
||||||
adjustedPtr, unwind_exception))
|
adjustedPtr, unwind_exception))
|
||||||
{
|
{
|
||||||
// native exception caught by exception spec
|
// Native exception caught by exception
|
||||||
// If this is a type 1 search, save state and return _URC_HANDLER_FOUND
|
// specification.
|
||||||
// If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1!
|
assert(actions & _UA_SEARCH_PHASE);
|
||||||
// If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan
|
|
||||||
if (actions & _UA_SEARCH_PHASE)
|
|
||||||
{
|
|
||||||
// Save state and return _URC_HANDLER_FOUND
|
|
||||||
results.ttypeIndex = ttypeIndex;
|
|
||||||
results.actionRecord = actionRecord;
|
|
||||||
results.landingPad = landingPad;
|
|
||||||
results.adjustedPtr = adjustedPtr;
|
|
||||||
results.reason = _URC_HANDLER_FOUND;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (!(actions & _UA_FORCE_UNWIND))
|
|
||||||
{
|
|
||||||
// It looks like the exception table has changed
|
|
||||||
// on us. Likely stack corruption!
|
|
||||||
call_terminate(native_exception, unwind_exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// foreign exception caught by exception spec
|
|
||||||
// If this is a type 1 search, save state and return _URC_HANDLER_FOUND
|
|
||||||
// If this is a type 2 search, save state and return _URC_HANDLER_FOUND
|
|
||||||
// If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1!
|
|
||||||
// If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan
|
|
||||||
if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME))
|
|
||||||
{
|
|
||||||
// Save state and return _URC_HANDLER_FOUND
|
|
||||||
results.ttypeIndex = ttypeIndex;
|
results.ttypeIndex = ttypeIndex;
|
||||||
results.actionRecord = actionRecord;
|
results.actionRecord = actionRecord;
|
||||||
results.landingPad = landingPad;
|
results.adjustedPtr = adjustedPtr;
|
||||||
results.adjustedPtr = get_thrown_object_ptr(unwind_exception);
|
|
||||||
results.reason = _URC_HANDLER_FOUND;
|
results.reason = _URC_HANDLER_FOUND;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (!(actions & _UA_FORCE_UNWIND))
|
} else {
|
||||||
{
|
// foreign exception caught by exception spec
|
||||||
// It looks like the exception table has changed
|
|
||||||
// on us. Likely stack corruption!
|
|
||||||
call_terminate(native_exception, unwind_exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Scan next action ...
|
|
||||||
}
|
|
||||||
else // ttypeIndex == 0
|
|
||||||
{
|
|
||||||
// Found a cleanup
|
|
||||||
// If this is a type 1 search, ignore it and continue scan
|
|
||||||
// If this is a type 2 search, ignore it and continue scan
|
|
||||||
// If this is a type 3 search, save state and return _URC_HANDLER_FOUND
|
|
||||||
if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME))
|
|
||||||
{
|
|
||||||
// Save state and return _URC_HANDLER_FOUND
|
|
||||||
results.ttypeIndex = ttypeIndex;
|
results.ttypeIndex = ttypeIndex;
|
||||||
results.actionRecord = actionRecord;
|
results.actionRecord = actionRecord;
|
||||||
results.landingPad = landingPad;
|
results.adjustedPtr =
|
||||||
results.adjustedPtr = get_thrown_object_ptr(unwind_exception);
|
get_thrown_object_ptr(unwind_exception);
|
||||||
results.reason = _URC_HANDLER_FOUND;
|
results.reason = _URC_HANDLER_FOUND;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Scan next action ...
|
||||||
|
} else {
|
||||||
|
hasCleanup = true;
|
||||||
}
|
}
|
||||||
const uint8_t* temp = action;
|
const uint8_t* temp = action;
|
||||||
int64_t actionOffset = readSLEB128(&temp);
|
int64_t actionOffset = readSLEB128(&temp);
|
||||||
if (actionOffset == 0)
|
if (actionOffset == 0)
|
||||||
{
|
{
|
||||||
// End of action list, no matching handler or cleanup found
|
// End of action list. If this is phase 2 and we have found
|
||||||
results.reason = _URC_CONTINUE_UNWIND;
|
// a cleanup (ttypeIndex=0), return _URC_HANDLER_FOUND;
|
||||||
|
// otherwise return _URC_CONTINUE_UNWIND.
|
||||||
|
results.reason = hasCleanup && actions & _UA_CLEANUP_PHASE
|
||||||
|
? _URC_HANDLER_FOUND
|
||||||
|
: _URC_CONTINUE_UNWIND;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Go to next action
|
// Go to next action
|
||||||
|
|
Loading…
Reference in New Issue