diff options
author | Jan Vorlicek <janvorli@microsoft.com> | 2022-09-30 11:00:01 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-30 11:00:01 +0300 |
commit | 062fb4562f0c366e5d911b4bca22dbd3cb25a89a (patch) | |
tree | 2b2d3c8bede6331c7fcd7e2e3c9f4941242ed7ee /src | |
parent | ff2acd071797aefef9428c9e3fe4bc459df4c3f0 (diff) |
Fix edit and continue in VS with hardware exceptions (#76401)
There is a subtle bug in hardware exception handling in the runtime
that causes the debugged process to crash when a user tries to use the
"unwind to this frame" on the frame where the exception happened.
This issue was introduced by the recent changes that modified hardware
exception handling.
The problem turned out to be in how we update the exception and context
records in the HandleManagedFaultFilter when we re-raise the exception
using RaiseException from the VEH. Updating the context is both not
necessary and wrong. All we need to update is the `ExceptionAddress` in
the `EXCEPTION_RECORD`, since the RaiseException puts the address of
itself there and we need the address of the original access violation to
be there.
The context should stay untouched as we are unwinding from the
RaiseException.
The context copying was originally made to mimick the code in the
`NakedThrowHelper` used before the exception handling change. That one
needed the context update, as it was used to fix unwinding over the
NakedThrowHelper that was a hijack helper. In the current state, nothing
like that is needed.
With this fix, the VS debugger works as expected.
Diffstat (limited to 'src')
-rw-r--r-- | src/coreclr/vm/excep.cpp | 25 |
1 files changed, 3 insertions, 22 deletions
diff --git a/src/coreclr/vm/excep.cpp b/src/coreclr/vm/excep.cpp index 8af866c35c1..f45288afd54 100644 --- a/src/coreclr/vm/excep.cpp +++ b/src/coreclr/vm/excep.cpp @@ -6526,24 +6526,6 @@ AdjustContextForJITHelpers( #if defined(USE_FEF) && !defined(TARGET_UNIX) -static void FixContextForFaultingExceptionFrame( - EXCEPTION_POINTERS* ep, - EXCEPTION_RECORD* pOriginalExceptionRecord, - CONTEXT* pOriginalExceptionContext) -{ - WRAPPER_NO_CONTRACT; - - // don't copy param args as have already supplied them on the throw - memcpy((void*) ep->ExceptionRecord, - (void*) pOriginalExceptionRecord, - offsetof(EXCEPTION_RECORD, ExceptionInformation) - ); - - ReplaceExceptionContextRecord(ep->ContextRecord, pOriginalExceptionContext); - - GetThread()->ResetThreadStateNC(Thread::TSNC_DebuggerIsManagedException); -} - struct HandleManagedFaultFilterParam { // It's possible for our filter to be called more than once if some other first-pass @@ -6551,7 +6533,6 @@ struct HandleManagedFaultFilterParam // the first exception we see. This flag takes care of that. BOOL fFilterExecuted; EXCEPTION_RECORD *pOriginalExceptionRecord; - CONTEXT *pOriginalExceptionContext; }; static LONG HandleManagedFaultFilter(EXCEPTION_POINTERS* ep, LPVOID pv) @@ -6562,7 +6543,8 @@ static LONG HandleManagedFaultFilter(EXCEPTION_POINTERS* ep, LPVOID pv) if (!pParam->fFilterExecuted) { - FixContextForFaultingExceptionFrame(ep, pParam->pOriginalExceptionRecord, pParam->pOriginalExceptionContext); + ep->ExceptionRecord->ExceptionAddress = pParam->pOriginalExceptionRecord->ExceptionAddress; + GetThread()->ResetThreadStateNC(Thread::TSNC_DebuggerIsManagedException); pParam->fFilterExecuted = TRUE; } @@ -6584,7 +6566,6 @@ void HandleManagedFault(EXCEPTION_RECORD* pExceptionRecord, CONTEXT* pContext) HandleManagedFaultFilterParam param; param.fFilterExecuted = FALSE; param.pOriginalExceptionRecord = pExceptionRecord; - param.pOriginalExceptionContext = pContext; PAL_TRY(HandleManagedFaultFilterParam *, pParam, ¶m) { @@ -6592,7 +6573,7 @@ void HandleManagedFault(EXCEPTION_RECORD* pExceptionRecord, CONTEXT* pContext) EXCEPTION_RECORD *pRecord = pParam->pOriginalExceptionRecord; - RaiseException(pRecord->ExceptionCode, pRecord->ExceptionFlags, + RaiseException(pRecord->ExceptionCode, 0, pRecord->NumberParameters, pRecord->ExceptionInformation); } PAL_EXCEPT_FILTER(HandleManagedFaultFilter) |