Skip to content

Commit

Permalink
Fix Windows Arm64 unwinding (dotnet#102258)
Browse files Browse the repository at this point in the history
* Fix Windows Arm64 unwinding

There was an issue with unwinding native code functions in case of calls
to no-return function placed at an end of a function code block. The
return address was not in range of the function code, so
RtlLookupFunctionEntry was not finding anything, we were thinking that
it was a leaf function due to that and tried to unwind using LR only,
which was wrong and resulted in staying on the same instruction. Thus
the unwinding ended up in an infinite loop for those cases.
The fix, that matches what RtlUnwind does, is to adjust the instruction
pointer at call sites back. This is arm64 specific.

Close dotnet#101921

* Modify the ifdef from CONTEXT_UNWOUND_TO_CALL to TARGET_ARM64
  • Loading branch information
janvorli authored and Ruihan-Yin committed May 30, 2024
1 parent 5822546 commit c831d37
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 56 deletions.
5 changes: 0 additions & 5 deletions src/coreclr/inc/clrconfigvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,12 +259,7 @@ RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_legacyCorruptedStateExceptionsPolicy, W("le
CONFIG_DWORD_INFO(INTERNAL_SuppressLostExceptionTypeAssert, W("SuppressLostExceptionTypeAssert"), 0, "")
RETAIL_CONFIG_DWORD_INFO(INTERNAL_UseEntryPointFilter, W("UseEntryPointFilter"), 0, "")
RETAIL_CONFIG_DWORD_INFO(INTERNAL_Corhost_Swallow_Uncaught_Exceptions, W("Corhost_Swallow_Uncaught_Exceptions"), 0, "")
#if defined(HOST_WINDOWS) && defined(TARGET_ARM64)
// disable new exception handling for Windows ARM64
RETAIL_CONFIG_DWORD_INFO(EXTERNAL_LegacyExceptionHandling, W("LegacyExceptionHandling"), 1, "Enable legacy exception handling.");
#else
RETAIL_CONFIG_DWORD_INFO(EXTERNAL_LegacyExceptionHandling, W("LegacyExceptionHandling"), 0, "Enable legacy exception handling.");
#endif // defined(WINDOWS) && defined(TARGET_ARM64)

///
/// Garbage collector
Expand Down
73 changes: 24 additions & 49 deletions src/coreclr/vm/stackwalk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,13 @@ PCODE Thread::VirtualUnwindCallFrame(T_CONTEXT* pContext,
UINT_PTR uImageBase;
PT_RUNTIME_FUNCTION pFunctionEntry;

#if !defined(TARGET_UNIX) && defined(TARGET_ARM64)
if ((pContext->ContextFlags & CONTEXT_UNWOUND_TO_CALL) != 0)
{
uControlPc -= STACKWALK_CONTROLPC_ADJUST_OFFSET;
}
#endif // !TARGET_UNIX && TARGET_ARM64

if (pCodeInfo == NULL)
{
#ifndef TARGET_UNIX
Expand Down Expand Up @@ -592,7 +599,23 @@ PCODE Thread::VirtualUnwindCallFrame(T_CONTEXT* pContext,

if (pFunctionEntry)
{
uControlPc = VirtualUnwindNonLeafCallFrame(pContext, pContextPointers, pFunctionEntry, uImageBase);
#ifdef HOST_64BIT
UINT64 EstablisherFrame;
#else // HOST_64BIT
DWORD EstablisherFrame;
#endif // HOST_64BIT
PVOID HandlerData;

RtlVirtualUnwind(0,
uImageBase,
uControlPc,
pFunctionEntry,
pContext,
&HandlerData,
&EstablisherFrame,
pContextPointers);

uControlPc = GetIP(pContext);
}
else
{
Expand Down Expand Up @@ -661,54 +684,6 @@ PCODE Thread::VirtualUnwindLeafCallFrame(T_CONTEXT* pContext)
return uControlPc;
}

// static
PCODE Thread::VirtualUnwindNonLeafCallFrame(T_CONTEXT* pContext, KNONVOLATILE_CONTEXT_POINTERS* pContextPointers,
PT_RUNTIME_FUNCTION pFunctionEntry, UINT_PTR uImageBase)
{
CONTRACTL
{
NOTHROW;
GC_NOTRIGGER;
PRECONDITION(CheckPointer(pContext, NULL_NOT_OK));
PRECONDITION(CheckPointer(pContextPointers, NULL_OK));
PRECONDITION(CheckPointer(pFunctionEntry, NULL_OK));
}
CONTRACTL_END;

PCODE uControlPc = GetIP(pContext);
#ifdef HOST_64BIT
UINT64 EstablisherFrame;
#else // HOST_64BIT
DWORD EstablisherFrame;
#endif // HOST_64BIT
PVOID HandlerData;

if (NULL == pFunctionEntry)
{
#ifndef TARGET_UNIX
pFunctionEntry = RtlLookupFunctionEntry(uControlPc,
ARM_ONLY((DWORD*))(&uImageBase),
NULL);
#endif
if (NULL == pFunctionEntry)
{
return (PCODE)NULL;
}
}

RtlVirtualUnwind(0,
uImageBase,
uControlPc,
pFunctionEntry,
pContext,
&HandlerData,
&EstablisherFrame,
pContextPointers);

uControlPc = GetIP(pContext);
return uControlPc;
}

extern void* g_hostingApiReturnAddress;

// static
Expand Down
2 changes: 0 additions & 2 deletions src/coreclr/vm/threads.h
Original file line number Diff line number Diff line change
Expand Up @@ -2369,8 +2369,6 @@ class Thread
static UINT_PTR VirtualUnwindCallFrame(PREGDISPLAY pRD, EECodeInfo * pCodeInfo = NULL);
#ifndef DACCESS_COMPILE
static PCODE VirtualUnwindLeafCallFrame(T_CONTEXT* pContext);
static PCODE VirtualUnwindNonLeafCallFrame(T_CONTEXT* pContext, T_KNONVOLATILE_CONTEXT_POINTERS* pContextPointers = NULL,
PT_RUNTIME_FUNCTION pFunctionEntry = NULL, UINT_PTR uImageBase = 0);
static UINT_PTR VirtualUnwindToFirstManagedCallFrame(T_CONTEXT* pContext);
#endif // DACCESS_COMPILE
#endif // FEATURE_EH_FUNCLETS
Expand Down

0 comments on commit c831d37

Please sign in to comment.