Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle HW exceptions on Windows without redirection #70428

Merged
merged 1 commit into from
Jun 15, 2022
Merged
Show file tree
Hide file tree
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
22 changes: 0 additions & 22 deletions src/coreclr/vm/amd64/RedirectedHandledJITCase.asm
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ include asmconstants.inc

Thread__GetAbortContext equ ?GetAbortContext@Thread@@QEAAPEAU_CONTEXT@@XZ

extern FixContextHandler:proc
extern LinkFrameAndThrow:proc
extern GetCurrentSavedRedirectContext:proc
extern Thread__GetAbortContext:proc
extern HijackHandler:proc
Expand Down Expand Up @@ -206,26 +204,6 @@ NESTED_END RedirectForThrowControl2, _TEXT
GenerateRedirectedStubWithFrame RedirectForThrowControl, HijackHandler, RedirectForThrowControl2


NAKED_THROW_HELPER_FRAME_SIZE = SIZEOF_MAX_OUTGOING_ARGUMENT_HOMES + 8

NESTED_ENTRY NakedThrowHelper2, _TEXT

; On entry
; rcx -> FaultingExceptionFrame

alloc_stack NAKED_THROW_HELPER_FRAME_SIZE
END_PROLOGUE

call LinkFrameAndThrow

; LinkFrameAndThrow doesn't return.
int 3

NESTED_END NakedThrowHelper2, _TEXT

GenerateRedirectedStubWithFrame NakedThrowHelper, FixContextHandler, NakedThrowHelper2


ifdef FEATURE_SPECIAL_USER_MODE_APC

extern ?ApcActivationCallback@Thread@@CAX_K@Z:proc
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/amd64/excepcpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(CONTEXT * pContext);

//
// Retrieves the FaultingExceptionFrame* from the stack frame of
// RedirectForThrowControl or NakedThrowHelper.
// RedirectForThrowControl.
//
FaultingExceptionFrame *GetFrameFromRedirectedStubStackFrame (DISPATCHER_CONTEXT *pDispatcherContext);

Expand Down
23 changes: 0 additions & 23 deletions src/coreclr/vm/arm/ehhelpers.asm
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@

#include "asmmacros.h"

IMPORT FixContextHandler
IMPORT LinkFrameAndThrow
IMPORT HijackHandler
IMPORT ThrowControlForThread

Expand Down Expand Up @@ -76,27 +74,6 @@ OFFSET_OF_FRAME SETA 4 + SIZEOF__GSCookie

MEND

; ------------------------------------------------------------------
;
; Helpers for async (NullRef, AccessViolation) exceptions
;

NESTED_ENTRY NakedThrowHelper2,,FixContextHandler
PROLOG_PUSH {r0, lr}

; On entry:
;
; R0 = Address of FaultingExceptionFrame
bl LinkFrameAndThrow

; Target should not return.
EMIT_BREAKPOINT

NESTED_END NakedThrowHelper2


GenerateRedirectedStubWithFrame NakedThrowHelper, NakedThrowHelper2

; ------------------------------------------------------------------
;
; Helpers for ThreadAbort exceptions
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/vm/arm/exceparm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_CONTEXT * pContext)
// 2) represents the current context in the second pass.
//
// Since R4 is a non-volatile register, this works for us since we setup the value of R4
// in the redirection helpers (e.g. NakedThrowHelper or RedirectForThreadAbort) but do not
// change it in their respective callee functions (e.g. NakedThrowHelper2 or RedirectForThreadAbort2)
// in the redirection helpers (e.g. RedirectForThreadAbort) but do not
// change it in their respective callee functions (e.g. RedirectForThreadAbort2)
// that have the personality routines associated with them (which perform the collided unwind and also
// invoke the two functions below).
//
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/arm/excepcpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_CONTEXT * pContext);

//
// Retrieves the FaultingExceptionFrame* from the stack frame of
// RedirectForThrowControl or NakedThrowHelper.
// RedirectForThrowControl.
//
FaultingExceptionFrame *GetFrameFromRedirectedStubStackFrame (T_DISPATCHER_CONTEXT *pDispatcherContext);

Expand Down
23 changes: 0 additions & 23 deletions src/coreclr/vm/arm64/asmhelpers.asm
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
IMPORT UMEntryPrestubUnwindFrameChainHandler
IMPORT TheUMEntryPrestubWorker
IMPORT GetCurrentSavedRedirectContext
IMPORT LinkFrameAndThrow
IMPORT FixContextHandler
IMPORT OnHijackWorker
#ifdef FEATURE_READYTORUN
IMPORT DynamicHelperWorker
Expand Down Expand Up @@ -1030,27 +1028,6 @@ FaultingExceptionFrame_FrameOffset SETA SIZEOF__GSCookie
MEND


; ------------------------------------------------------------------
;
; Helpers for async (NullRef, AccessViolation) exceptions
;

NESTED_ENTRY NakedThrowHelper2,,FixContextHandler
PROLOG_SAVE_REG_PAIR fp,lr, #-16!

; On entry:
;
; X0 = Address of FaultingExceptionFrame
bl LinkFrameAndThrow

; Target should not return.
EMIT_BREAKPOINT

NESTED_END NakedThrowHelper2


GenerateRedirectedStubWithFrame NakedThrowHelper, NakedThrowHelper2

; ------------------------------------------------------------------
; ResolveWorkerChainLookupAsmStub
;
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/arm64/excepcpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_CONTEXT * pContext);

//
// Retrieves the FaultingExceptionFrame* from the stack frame of
// RedirectForThrowControl or NakedThrowHelper.
// RedirectForThrowControl.
//
FaultingExceptionFrame *GetFrameFromRedirectedStubStackFrame (T_DISPATCHER_CONTEXT *pDispatcherContext);

Expand Down
105 changes: 9 additions & 96 deletions src/coreclr/vm/excep.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6658,66 +6658,6 @@ struct SavedExceptionInfo
}
};

SavedExceptionInfo g_SavedExceptionInfo; // Globals are guaranteed zero-init;

void InitSavedExceptionInfo()
{
g_SavedExceptionInfo.Init();
}

EXTERN_C VOID FixContextForFaultingExceptionFrame (
EXCEPTION_RECORD* pExceptionRecord,
CONTEXT *pContextRecord)
{
WRAPPER_NO_CONTRACT;

// don't copy parm args as have already supplied them on the throw
memcpy((void*) pExceptionRecord,
(void*) &g_SavedExceptionInfo.m_ExceptionRecord,
offsetof(EXCEPTION_RECORD, ExceptionInformation)
);

ReplaceExceptionContextRecord(pContextRecord, &g_SavedExceptionInfo.m_ExceptionContext);

g_SavedExceptionInfo.Leave();

GetThread()->ResetThreadStateNC(Thread::TSNC_DebuggerIsManagedException);
}

EXTERN_C VOID __fastcall
LinkFrameAndThrow(FaultingExceptionFrame* pFrame)
{
WRAPPER_NO_CONTRACT;

*(TADDR*)pFrame = FaultingExceptionFrame::GetMethodFrameVPtr();
*pFrame->GetGSCookiePtr() = GetProcessGSCookie();

pFrame->InitAndLink(&g_SavedExceptionInfo.m_ExceptionContext);

GetThread()->SetThreadStateNC(Thread::TSNC_DebuggerIsManagedException);

ULONG argcount = g_SavedExceptionInfo.m_ExceptionRecord.NumberParameters;
ULONG flags = g_SavedExceptionInfo.m_ExceptionRecord.ExceptionFlags;
ULONG code = g_SavedExceptionInfo.m_ExceptionRecord.ExceptionCode;
ULONG_PTR* args = &g_SavedExceptionInfo.m_ExceptionRecord.ExceptionInformation[0];

RaiseException(code, flags, argcount, args);
}

void SetNakedThrowHelperArgRegistersInContext(CONTEXT* pContext)
{
#if defined(TARGET_AMD64)
pContext->Rcx = (UINT_PTR)GetIP(pContext);
#elif defined(TARGET_ARM) || defined(TARGET_ARM64)
// Save the original IP in LR
pContext->Lr = (DWORD)GetIP(pContext);
#else
PORTABILITY_WARNING("NakedThrowHelper argument not defined");
#endif
}

EXTERN_C VOID STDCALL NakedThrowHelper(VOID);

void HandleManagedFault(EXCEPTION_RECORD* pExceptionRecord,
CONTEXT* pContext,
EXCEPTION_REGISTRATION_RECORD* pEstablisherFrame,
Expand All @@ -6726,37 +6666,16 @@ void HandleManagedFault(EXCEPTION_RECORD* pExceptionRecord,
WRAPPER_NO_CONTRACT;

// Ok. Now we have a brand new fault in jitted code.
if (!Thread::UseContextBasedThreadRedirection())
{
// Once this code path gets enough bake time, perhaps this path could always be used instead of the alternative path to
// redirect the thread
FrameWithCookie<FaultingExceptionFrame> frameWithCookie;
FaultingExceptionFrame *frame = &frameWithCookie;
#if defined(FEATURE_EH_FUNCLETS)
*frame->GetGSCookiePtr() = GetProcessGSCookie();
#endif // FEATURE_EH_FUNCLETS
frame->InitAndLink(pContext);

SEHException exception(pExceptionRecord);
OBJECTREF managedException = CLRException::GetThrowableFromException(&exception);
RaiseTheExceptionInternalOnly(managedException, FALSE);
}
else
{
g_SavedExceptionInfo.Enter();
g_SavedExceptionInfo.SaveExceptionRecord(pExceptionRecord);
g_SavedExceptionInfo.SaveContext(pContext);

SetNakedThrowHelperArgRegistersInContext(pContext);

SetIP(pContext, GetEEFuncEntryPoint(NakedThrowHelper));
}
}

#else // USE_FEF && !TARGET_UNIX
FrameWithCookie<FaultingExceptionFrame> frameWithCookie;
FaultingExceptionFrame *frame = &frameWithCookie;
#if defined(FEATURE_EH_FUNCLETS)
*frame->GetGSCookiePtr() = GetProcessGSCookie();
#endif // FEATURE_EH_FUNCLETS
frame->InitAndLink(pContext);

void InitSavedExceptionInfo()
{
SEHException exception(pExceptionRecord);
OBJECTREF managedException = CLRException::GetThrowableFromException(&exception);
RaiseTheExceptionInternalOnly(managedException, FALSE);
}

#endif // USE_FEF && !TARGET_UNIX
Expand Down Expand Up @@ -7084,12 +7003,6 @@ LONG WINAPI CLRVectoredExceptionHandlerPhase2(PEXCEPTION_POINTERS pExceptionInfo

if (action == VEH_EXECUTE_HANDLE_MANAGED_EXCEPTION)
{
//
// If the exception context was unwound by Phase3 then
// we'll jump here to save the managed context and resume execution at
// NakedThrowHelper. This needs to be done outside of any holder's
// scope, because HandleManagedFault may not return.
//
HandleManagedFault(pExceptionInfo->ExceptionRecord,
pExceptionInfo->ContextRecord,
NULL, // establisher frame (x86 only)
Expand Down
2 changes: 0 additions & 2 deletions src/coreclr/vm/excep.h
Original file line number Diff line number Diff line change
Expand Up @@ -742,8 +742,6 @@ void CPFH_AdjustContextForThreadSuspensionRace(T_CONTEXT *pContext, Thread *pThr
DWORD GetGcMarkerExceptionCode(LPVOID ip);
bool IsGcMarker(T_CONTEXT *pContext, EXCEPTION_RECORD *pExceptionRecord);

void InitSavedExceptionInfo();

bool ShouldHandleManagedFault(
EXCEPTION_RECORD* pExceptionRecord,
T_CONTEXT* pContext,
Expand Down
35 changes: 0 additions & 35 deletions src/coreclr/vm/exceptionhandling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,6 @@ void InitializeExceptionHandling()
{
EH_LOG((LL_INFO100, "InitializeExceptionHandling(): ExceptionTracker size: 0x%x bytes\n", sizeof(ExceptionTracker)));

InitSavedExceptionInfo();

CLRAddVectoredHandlers();

g_theTrackerAllocator.Init();
Expand Down Expand Up @@ -5739,39 +5737,6 @@ NOT_BIT64_ARG(IN ULONG MemoryStackFp),
}


EXTERN_C VOID FixContextForFaultingExceptionFrame (
EXCEPTION_RECORD* pExceptionRecord,
CONTEXT *pContextRecord);

EXTERN_C EXCEPTION_DISPOSITION
FixContextHandler(IN PEXCEPTION_RECORD pExceptionRecord
BIT64_ARG(IN ULONG64 MemoryStackFp)
NOT_BIT64_ARG(IN ULONG MemoryStackFp),
IN OUT PCONTEXT pContextRecord,
IN OUT PDISPATCHER_CONTEXT pDispatcherContext
)
{
CONTEXT* pNewContext = NULL;

if (FirstCallToHandler(pDispatcherContext, &pNewContext))
{
//
// We've pushed a Frame, but it is not initialized yet, so we
// must not be in preemptive mode
//
CONSISTENCY_CHECK(GetThread()->PreemptiveGCDisabled());

FixContextForFaultingExceptionFrame(pExceptionRecord, pNewContext);
}

FixupDispatcherContext(pDispatcherContext, pNewContext, pContextRecord);

// Returning ExceptionCollidedUnwind will cause the OS to take our new context record
// and dispatcher context and restart the exception dispatching on this call frame,
// which is exactly the behavior we want in order to restore our thread's unwindability
// (which was broken when we whacked the IP to get control over the thread)
return ExceptionCollidedUnwind;
}
#endif // !TARGET_UNIX

#ifdef _DEBUG
Expand Down
2 changes: 0 additions & 2 deletions src/coreclr/vm/i386/excepx86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1235,8 +1235,6 @@ void InitializeExceptionHandling()
{
WRAPPER_NO_CONTRACT;

InitSavedExceptionInfo();

CLRAddVectoredHandlers();

// Initialize the lock used for synchronizing access to the stacktrace in the exception object
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/loongarch64/excepcpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ PTR_CONTEXT GetCONTEXTFromRedirectedStubStackFrame(T_CONTEXT * pContext);

//
// Retrieves the FaultingExceptionFrame* from the stack frame of
// RedirectForThrowControl or NakedThrowHelper.
// RedirectForThrowControl.
//
FaultingExceptionFrame *GetFrameFromRedirectedStubStackFrame (T_DISPATCHER_CONTEXT *pDispatcherContext);

Expand Down