Skip to content

Commit 062fb45

Browse files
authored
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.
1 parent ff2acd0 commit 062fb45

File tree

1 file changed

+3
-22
lines changed

1 file changed

+3
-22
lines changed

src/coreclr/vm/excep.cpp

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6526,32 +6526,13 @@ AdjustContextForJITHelpers(
65266526

65276527
#if defined(USE_FEF) && !defined(TARGET_UNIX)
65286528

6529-
static void FixContextForFaultingExceptionFrame(
6530-
EXCEPTION_POINTERS* ep,
6531-
EXCEPTION_RECORD* pOriginalExceptionRecord,
6532-
CONTEXT* pOriginalExceptionContext)
6533-
{
6534-
WRAPPER_NO_CONTRACT;
6535-
6536-
// don't copy param args as have already supplied them on the throw
6537-
memcpy((void*) ep->ExceptionRecord,
6538-
(void*) pOriginalExceptionRecord,
6539-
offsetof(EXCEPTION_RECORD, ExceptionInformation)
6540-
);
6541-
6542-
ReplaceExceptionContextRecord(ep->ContextRecord, pOriginalExceptionContext);
6543-
6544-
GetThread()->ResetThreadStateNC(Thread::TSNC_DebuggerIsManagedException);
6545-
}
6546-
65476529
struct HandleManagedFaultFilterParam
65486530
{
65496531
// It's possible for our filter to be called more than once if some other first-pass
65506532
// handler lets an exception out. We need to make sure we only fix the context for
65516533
// the first exception we see. This flag takes care of that.
65526534
BOOL fFilterExecuted;
65536535
EXCEPTION_RECORD *pOriginalExceptionRecord;
6554-
CONTEXT *pOriginalExceptionContext;
65556536
};
65566537

65576538
static LONG HandleManagedFaultFilter(EXCEPTION_POINTERS* ep, LPVOID pv)
@@ -6562,7 +6543,8 @@ static LONG HandleManagedFaultFilter(EXCEPTION_POINTERS* ep, LPVOID pv)
65626543

65636544
if (!pParam->fFilterExecuted)
65646545
{
6565-
FixContextForFaultingExceptionFrame(ep, pParam->pOriginalExceptionRecord, pParam->pOriginalExceptionContext);
6546+
ep->ExceptionRecord->ExceptionAddress = pParam->pOriginalExceptionRecord->ExceptionAddress;
6547+
GetThread()->ResetThreadStateNC(Thread::TSNC_DebuggerIsManagedException);
65666548
pParam->fFilterExecuted = TRUE;
65676549
}
65686550

@@ -6584,15 +6566,14 @@ void HandleManagedFault(EXCEPTION_RECORD* pExceptionRecord, CONTEXT* pContext)
65846566
HandleManagedFaultFilterParam param;
65856567
param.fFilterExecuted = FALSE;
65866568
param.pOriginalExceptionRecord = pExceptionRecord;
6587-
param.pOriginalExceptionContext = pContext;
65886569

65896570
PAL_TRY(HandleManagedFaultFilterParam *, pParam, &param)
65906571
{
65916572
GetThread()->SetThreadStateNC(Thread::TSNC_DebuggerIsManagedException);
65926573

65936574
EXCEPTION_RECORD *pRecord = pParam->pOriginalExceptionRecord;
65946575

6595-
RaiseException(pRecord->ExceptionCode, pRecord->ExceptionFlags,
6576+
RaiseException(pRecord->ExceptionCode, 0,
65966577
pRecord->NumberParameters, pRecord->ExceptionInformation);
65976578
}
65986579
PAL_EXCEPT_FILTER(HandleManagedFaultFilter)

0 commit comments

Comments
 (0)