Skip to content

Commit

Permalink
Port NativeAOT exception handling to CoreCLR (#88034)
Browse files Browse the repository at this point in the history
* Port NativeAOT exception handling to CoreCLR

This change ports NativeAOT exception handling to CoreCLR, resulting in
3.5..4 times speedup in exception handling. Due to time constraints and
various complexities, thread abort and debugger support is not
completed yet, so this change is enabled only when
`DOTNET_EnableNewExceptionHandling` env variable is set. By default,
the old way is used.
This change supports all OSes and targets we support except of x86
Windows. That may be doable too in the future, but the difference in
exception handling on x86 Windows adds quite a lot of complexity into
the picture.

Notes for the PR:
* I have left the `ExceptionHandling.cs` and `StackFrameIterator.cs` in
  the nativeaot folder to simplify the review. I can move it to some
  common location after the change is reviewed. Also it was not clear to
  me where that should be, so advise would be welcome here.
* Naming of the native helpers like `RhpCallCatchFunclet` was left the
  same as in the NativeAOT for now.
* There are still some little things I'd like to eventually clean up,
  like `ExInfo` encapsulation and possibly moving `REGDISPLAY` and
  `CONTEXT` it uses into the `ExInfo` itself or moving debug members of
  `StackFrameIterator` and `REGDISPLAY` to the end of those structures
  so that the `AsmOffsets.cs` can be simplified. It also may be possible
  to unify the exception handling callback that's used for ObjectiveC to
  use the managed version. I've tried and there were some ugly
  complications, so I've left it separated.
* There are two bug fixes for bugs unrelated to this PR and a removal of
  unused parameter in existing code that could be made as separate PRs
  before this PR.
  * `ProfilerEnter` and `ProfilerLeave` for the case of
    `UnmanagedCallersOnly` method were being called in preemptive mode.
  * NativeAOT code for rethrowing exception was incorrectly calling
    `DispatchEx` with last argument set to `activeExInfo._idxCurClause`
    to start at the last clause processed when the rethrown exception
    was originally thrown instead of starting from the first one again.
    I have a accidentally came with a simple test that discovered this
    bug and causes failures in  the original NativeAOT too.
* Changes in  the stackwalk.cpp add support for
  * Usage of `ExInfo` instead of `ExceptionTracker`
  * Handling of case when GC runs while finally funclet is on the stack
    and then again when the code is back in the new exception handling
    code in managed code before other finally or catch funclet is
    called. The NativeAOT solves that by disabling GC for the 2nd pass
    of EH, for this change it would not be reasonable.
  * Handling the GC reporting when funclet is found while walking the
    stack. It needs to scan frames of the managed code that handles the
    exception too,  since it contains live references. The old EH way
    doesn't have this case.
* I needed to add `GCFrame::Remove` method that can remove the `GCFrame`
  from any location in the chain. There is a managed runtime method that
  calls `GCReporting::Unregister` that was popping it with my changes
  out of order due to the exception handling code being managed.

Fix context initialization after rebase

* Remove Rhp prefix from the native helpers

* Fix handling of exceptions from JIT

The `UNINSTALL_UNWIND_AND_CONTINUE_HANDLER_NO_PROBE` in the
`EE_TO_JIT_TRANSITION` needs to rethrow an exception (if any) using native
exception handling mechanism instead of calling the new managed
exception handling, as the native exception needs to propagate through
some native code layers from there.
This change adds parameter to the
`UNINSTALL_UNWIND_AND_CONTINUE_HANDLER_NO_PROBE` macro to select whether
to rethrow the exception as native or to invoke the new managed
exception handling.

This problem didn't show up until I ran the coreclr tests with tiered
compilation disabled.

* Update UNINSTALL_UNWIND_AND_CONTINUE_HANDLER usage

There were three places where the UNINSTALL_UNWIND_AND_CONTINUE_HANDLER
needed to be replaced by
UNINSTALL_UNWIND_AND_CONTINUE_HANDLER_NO_PROBE(true).

* Rename INSTALL_UNWIND_AND_CONTINUE_HANDLER_NO_PROBE

To INSTALL_UNWIND_AND_CONTINUE_HANDLER_EX, as the old name is obsolete
  • Loading branch information
janvorli authored Aug 24, 2023
1 parent 445f01d commit f8d9b3c
Show file tree
Hide file tree
Showing 57 changed files with 2,716 additions and 157 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,11 @@
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\RuntimeHelpers.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\ControlledExecution.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\DependentHandle.cs" />
<Compile Include="$(MSBuildThisFileDirectory)..\nativeaot\Runtime.Base\src\System\Runtime\ExceptionHandling.cs" Condition="('$(Platform)' != 'x86' or '$(TargetsWindows)' != 'true')"/>
<Compile Include="$(MSBuildThisFileDirectory)..\nativeaot\Runtime.Base\src\System\Runtime\ExceptionIDs.cs" Condition="('$(Platform)' != 'x86' or '$(TargetsWindows)' != 'true')"/>
<Compile Include="$(MSBuildThisFileDirectory)..\nativeaot\Runtime.Base\src\System\Runtime\StackFrameIterator.cs" Condition="('$(Platform)' != 'x86' or '$(TargetsWindows)' != 'true')"/>
<Compile Include="$(BclSourcesRoot)\System\Runtime\ExceptionServices\AsmOffsets.cs" Condition="('$(Platform)' != 'x86' or '$(TargetsWindows)' != 'true')"/>
<Compile Include="$(BclSourcesRoot)\System\Runtime\ExceptionServices\InternalCalls.cs" Condition="('$(Platform)' != 'x86' or '$(TargetsWindows)' != 'true')"/>
<Compile Include="$(BclSourcesRoot)\System\Runtime\GCSettings.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\JitInfo.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComTypes\IEnumerable.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

// NOTE: This file is included also during native runtime compilation by the C++ compiler for verification purposes.
// The static asserts at the end are compiled only when this file is included in native build by c++ compiler. They
// provide compile time verification that all the sizes and offsets match between the managed and native code.

#if !__cplusplus
internal static
#endif
class AsmOffsets
{

// Offsets / sizes that are different in Release / Debug builds
#if DEBUG
// Debug build offsets
#if TARGET_AMD64
#if TARGET_UNIX
public const int SIZEOF__REGDISPLAY = 0x1a90;
public const int OFFSETOF__REGDISPLAY__SP = 0x1a78;
public const int OFFSETOF__REGDISPLAY__ControlPC = 0x1a80;
#else // TARGET_UNIX
public const int SIZEOF__REGDISPLAY = 0xbf0;
public const int OFFSETOF__REGDISPLAY__SP = 0xbd8;
public const int OFFSETOF__REGDISPLAY__ControlPC = 0xbe0;
#endif // TARGET_UNIX
#elif TARGET_ARM64
public const int SIZEOF__REGDISPLAY = 0x940;
public const int OFFSETOF__REGDISPLAY__SP = 0x898;
public const int OFFSETOF__REGDISPLAY__ControlPC = 0x8a0;
#elif TARGET_ARM
public const int SIZEOF__REGDISPLAY = 0x410;
public const int OFFSETOF__REGDISPLAY__SP = 0x3ec;
public const int OFFSETOF__REGDISPLAY__ControlPC = 0x3f0;
#elif TARGET_X86
public const int SIZEOF__REGDISPLAY = 0x5fc;
public const int OFFSETOF__REGDISPLAY__SP = 0x5f0;
public const int OFFSETOF__REGDISPLAY__ControlPC = 0x5f4;
#elif TARGET_RISCV64
public const int SIZEOF__REGDISPLAY = 0x6C0;
public const int OFFSETOF__REGDISPLAY__SP = 0x628;
public const int OFFSETOF__REGDISPLAY__ControlPC = 0x630;
#elif TARGET_LOONGARCH64
public const int SIZEOF__REGDISPLAY = 0x6C0;
public const int OFFSETOF__REGDISPLAY__SP = 0x628;
public const int OFFSETOF__REGDISPLAY__ControlPC = 0x630;
#endif

#if TARGET_64BIT
public const int OFFSETOF__REGDISPLAY__m_pCurrentContext = 0x8;
public const int SIZEOF__StackFrameIterator = 0x370;
public const int OFFSETOF__StackFrameIterator__m_isRuntimeWrappedExceptions = 0x352;
public const int OFFSETOF__StackFrameIterator__m_AdjustedControlPC = 0x368;
#else // TARGET_64BIT
public const int OFFSETOF__REGDISPLAY__m_pCurrentContext = 0x4;
public const int SIZEOF__StackFrameIterator = 0x2d8;
public const int OFFSETOF__StackFrameIterator__m_isRuntimeWrappedExceptions = 0x2c2;
public const int OFFSETOF__StackFrameIterator__m_AdjustedControlPC = 0x2d0;
#endif // TARGET_64BIT

#else // DEBUG
// Release build offsets
#if TARGET_AMD64
#if TARGET_UNIX
public const int SIZEOF__REGDISPLAY = 0x1a80;
public const int OFFSETOF__REGDISPLAY__SP = 0x1a70;
public const int OFFSETOF__REGDISPLAY__ControlPC = 0x1a78;
#else // TARGET_UNIX
public const int SIZEOF__REGDISPLAY = 0xbe0;
public const int OFFSETOF__REGDISPLAY__SP = 0xbd0;
public const int OFFSETOF__REGDISPLAY__ControlPC = 0xbd8;
#endif // TARGET_UNIX
#elif TARGET_ARM64
public const int SIZEOF__REGDISPLAY = 0x930;
public const int OFFSETOF__REGDISPLAY__SP = 0x890;
public const int OFFSETOF__REGDISPLAY__ControlPC = 0x898;
#elif TARGET_ARM
public const int SIZEOF__REGDISPLAY = 0x408;
public const int OFFSETOF__REGDISPLAY__SP = 0x3e8;
public const int OFFSETOF__REGDISPLAY__ControlPC = 0x3ec;
#elif TARGET_X86
public const int SIZEOF__REGDISPLAY = 0x5f8;
public const int OFFSETOF__REGDISPLAY__SP = 0x5ec;
public const int OFFSETOF__REGDISPLAY__ControlPC = 0x5f0;
#elif TARGET_RISCV64
public const int SIZEOF__REGDISPLAY = 0x6B0;
public const int OFFSETOF__REGDISPLAY__SP = 0x620;
public const int OFFSETOF__REGDISPLAY__ControlPC = 0x628;
#elif TARGET_LOONGARCH64
public const int SIZEOF__REGDISPLAY = 0x6B0;
public const int OFFSETOF__REGDISPLAY__SP = 0x620;
public const int OFFSETOF__REGDISPLAY__ControlPC = 0x628;
#endif

#if TARGET_64BIT
public const int OFFSETOF__REGDISPLAY__m_pCurrentContext = 0x8;
public const int SIZEOF__StackFrameIterator = 0x370;
public const int OFFSETOF__StackFrameIterator__m_isRuntimeWrappedExceptions = 0x34a;
public const int OFFSETOF__StackFrameIterator__m_AdjustedControlPC = 0x360;
#else // TARGET_64BIT
public const int OFFSETOF__REGDISPLAY__m_pCurrentContext = 0x4;
public const int SIZEOF__StackFrameIterator = 0x2d0;
public const int OFFSETOF__StackFrameIterator__m_isRuntimeWrappedExceptions = 0x2ba;
public const int OFFSETOF__StackFrameIterator__m_AdjustedControlPC = 0x2c8;
#endif // TARGET_64BIT

#endif // DEBUG

#if TARGET_AMD64
#if TARGET_UNIX
public const int SIZEOF__PAL_LIMITED_CONTEXT = 0xc20;
#else // TARGET_UNIX
public const int SIZEOF__PAL_LIMITED_CONTEXT = 0x4d0;
#endif // TARGET_UNIx
#elif TARGET_ARM64
public const int SIZEOF__PAL_LIMITED_CONTEXT = 0x390;
#elif TARGET_ARM
public const int SIZEOF__PAL_LIMITED_CONTEXT = 0x1a0;
#elif TARGET_X86
public const int SIZEOF__PAL_LIMITED_CONTEXT = 0x2cc;
#elif TARGET_RISCV64
public const int SIZEOF__PAL_LIMITED_CONTEXT = 0x220;
#elif TARGET_LOONGARCH64
public const int SIZEOF__PAL_LIMITED_CONTEXT = 0x220;
#endif

#if TARGET_AMD64
public const int OFFSETOF__PAL_LIMITED_CONTEXT__IP = 0xf8;
public const int OFFSETOF__PAL_LIMITED_CONTEXT__FP = 0xa0;
#elif TARGET_ARM64
public const int OFFSETOF__PAL_LIMITED_CONTEXT__IP = 0x108;
public const int OFFSETOF__PAL_LIMITED_CONTEXT__FP = 0xf0;
#elif TARGET_ARM
public const int OFFSETOF__PAL_LIMITED_CONTEXT__IP = 0x40;
public const int OFFSETOF__PAL_LIMITED_CONTEXT__FP = 0x30;
#elif TARGET_X86
public const int OFFSETOF__PAL_LIMITED_CONTEXT__IP = 0xb8;
public const int OFFSETOF__PAL_LIMITED_CONTEXT__FP = 0xb4;
#elif TARGET_RISCV64
public const int OFFSETOF__PAL_LIMITED_CONTEXT__IP = 0x108;
public const int OFFSETOF__PAL_LIMITED_CONTEXT__FP = 0x48;
#elif TARGET_LOONGARCH64
public const int OFFSETOF__PAL_LIMITED_CONTEXT__IP = 0x108;
public const int OFFSETOF__PAL_LIMITED_CONTEXT__FP = 0x48;
#endif

// Offsets / sizes that are different in 64 / 32 bit mode

#if TARGET_64BIT
public const int SIZEOF__EHEnum = 0x20;
public const int OFFSETOF__StackFrameIterator__m_pRegDisplay = 0x228;
public const int OFFSETOF__ExInfo__m_pPrevExInfo = 0;
public const int OFFSETOF__ExInfo__m_pExContext = 8;
public const int OFFSETOF__ExInfo__m_exception = 0x10;
public const int OFFSETOF__ExInfo__m_kind = 0x18;
public const int OFFSETOF__ExInfo__m_passNumber = 0x19;
public const int OFFSETOF__ExInfo__m_idxCurClause = 0x1c;
public const int OFFSETOF__ExInfo__m_frameIter = 0x20;
public const int OFFSETOF__ExInfo__m_notifyDebuggerSP = OFFSETOF__ExInfo__m_frameIter + SIZEOF__StackFrameIterator;
#else // TARGET_64BIT
public const int SIZEOF__EHEnum = 0x10;
public const int OFFSETOF__StackFrameIterator__m_pRegDisplay = 0x218;
public const int OFFSETOF__ExInfo__m_pPrevExInfo = 0;
public const int OFFSETOF__ExInfo__m_pExContext = 4;
public const int OFFSETOF__ExInfo__m_exception = 8;
public const int OFFSETOF__ExInfo__m_kind = 0xC;
public const int OFFSETOF__ExInfo__m_passNumber = 0xD;
public const int OFFSETOF__ExInfo__m_idxCurClause = 0x10;
public const int OFFSETOF__ExInfo__m_frameIter = 0x18;
public const int OFFSETOF__ExInfo__m_notifyDebuggerSP = OFFSETOF__ExInfo__m_frameIter + SIZEOF__StackFrameIterator;
#endif // TARGET_64BIT

#if __cplusplus
static_assert_no_msg(sizeof(CONTEXT) == AsmOffsets::SIZEOF__PAL_LIMITED_CONTEXT);
#if TARGET_AMD64
static_assert_no_msg(offsetof(CONTEXT, Rip) == AsmOffsets::OFFSETOF__PAL_LIMITED_CONTEXT__IP);
static_assert_no_msg(offsetof(CONTEXT, Rbp) == AsmOffsets::OFFSETOF__PAL_LIMITED_CONTEXT__FP);
#elif TARGET_ARM64
static_assert_no_msg(offsetof(CONTEXT, Pc) == AsmOffsets::OFFSETOF__PAL_LIMITED_CONTEXT__IP);
static_assert_no_msg(offsetof(CONTEXT, Fp) == AsmOffsets::OFFSETOF__PAL_LIMITED_CONTEXT__FP);
#elif TARGET_ARM
static_assert_no_msg(offsetof(CONTEXT, Pc) == AsmOffsets::OFFSETOF__PAL_LIMITED_CONTEXT__IP);
static_assert_no_msg(offsetof(CONTEXT, R11) == AsmOffsets::OFFSETOF__PAL_LIMITED_CONTEXT__FP);
#elif TARGET_X86
static_assert_no_msg(offsetof(CONTEXT, Eip) == AsmOffsets::OFFSETOF__PAL_LIMITED_CONTEXT__IP);
static_assert_no_msg(offsetof(CONTEXT, Ebp) == AsmOffsets::OFFSETOF__PAL_LIMITED_CONTEXT__FP);
#elif TARGET_RISCV64
static_assert_no_msg(offsetof(CONTEXT, Pc) == AsmOffsets::OFFSETOF__PAL_LIMITED_CONTEXT__IP);
static_assert_no_msg(offsetof(CONTEXT, Fp) == AsmOffsets::OFFSETOF__PAL_LIMITED_CONTEXT__FP);
#endif
static_assert_no_msg(sizeof(REGDISPLAY) == AsmOffsets::SIZEOF__REGDISPLAY);
static_assert_no_msg(offsetof(REGDISPLAY, SP) == AsmOffsets::OFFSETOF__REGDISPLAY__SP);
static_assert_no_msg(offsetof(REGDISPLAY, ControlPC) == AsmOffsets::OFFSETOF__REGDISPLAY__ControlPC);
static_assert_no_msg(offsetof(REGDISPLAY, pCurrentContext) == AsmOffsets::OFFSETOF__REGDISPLAY__m_pCurrentContext);
static_assert_no_msg(sizeof(StackFrameIterator) == AsmOffsets::SIZEOF__StackFrameIterator);
static_assert_no_msg(offsetof(StackFrameIterator, m_crawl) + offsetof(CrawlFrame, pRD) == OFFSETOF__StackFrameIterator__m_pRegDisplay);
static_assert_no_msg(offsetof(StackFrameIterator, m_isRuntimeWrappedExceptions) == OFFSETOF__StackFrameIterator__m_isRuntimeWrappedExceptions);
static_assert_no_msg(offsetof(StackFrameIterator, m_AdjustedControlPC) == OFFSETOF__StackFrameIterator__m_AdjustedControlPC);
static_assert_no_msg(sizeof(ExtendedEHClauseEnumerator) == AsmOffsets::SIZEOF__EHEnum);
static_assert_no_msg(offsetof(ExInfo, m_pPrevExInfo) == OFFSETOF__ExInfo__m_pPrevExInfo);
static_assert_no_msg(offsetof(ExInfo, m_pExContext) == OFFSETOF__ExInfo__m_pExContext);
static_assert_no_msg(offsetof(ExInfo, m_exception) == OFFSETOF__ExInfo__m_exception);
static_assert_no_msg(offsetof(ExInfo, m_kind) == OFFSETOF__ExInfo__m_kind);
static_assert_no_msg(offsetof(ExInfo, m_passNumber) == OFFSETOF__ExInfo__m_passNumber);
static_assert_no_msg(offsetof(ExInfo, m_idxCurClause) == OFFSETOF__ExInfo__m_idxCurClause);
static_assert_no_msg(offsetof(ExInfo, m_frameIter) == OFFSETOF__ExInfo__m_frameIter);
static_assert_no_msg(offsetof(ExInfo, m_notifyDebuggerSP) == OFFSETOF__ExInfo__m_notifyDebuggerSP);
#endif

}
#if __cplusplus
;
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

//
// This is where we group together all the internal calls.
//

using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;

namespace System.Runtime.ExceptionServices
{
internal static partial class InternalCalls
{
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "SfiInit")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static unsafe partial bool RhpSfiInit(ref StackFrameIterator pThis, void* pStackwalkCtx, [MarshalAs(UnmanagedType.Bool)] bool instructionFault);

[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "SfiNext")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static unsafe partial bool RhpSfiNext(ref StackFrameIterator pThis, uint* uExCollideClauseIdx, bool* fUnwoundReversePInvoke);

#pragma warning disable CS8500
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "CallCatchFunclet")]
internal static unsafe partial IntPtr RhpCallCatchFunclet(
ObjectHandleOnStack exceptionObj, byte* pHandlerIP, void* pvRegDisplay, EH.ExInfo* exInfo);

[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "CallFinallyFunclet")]
internal static unsafe partial void RhpCallFinallyFunclet(byte* pHandlerIP, void* pvRegDisplay, EH.ExInfo* exInfo);

[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "CallFilterFunclet")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static unsafe partial bool RhpCallFilterFunclet(
ObjectHandleOnStack exceptionObj, byte* pFilterIP, void* pvRegDisplay);

[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AppendExceptionStackFrame")]
internal static unsafe partial void RhpAppendExceptionStackFrame(ObjectHandleOnStack exceptionObj, IntPtr ip, UIntPtr sp, int flags, EH.ExInfo* exInfo);
#pragma warning restore CS8500

[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "EHEnumInitFromStackFrameIterator")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static unsafe partial bool RhpEHEnumInitFromStackFrameIterator(ref StackFrameIterator pFrameIter, byte** pMethodStartAddress, void* pEHEnum);

[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "EHEnumNext")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static unsafe partial bool RhpEHEnumNext(void* pEHEnum, void* pEHClause);
}
}
5 changes: 5 additions & 0 deletions src/coreclr/clr.featuredefines.props
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@
<FeatureObjCMarshal>true</FeatureObjCMarshal>
</PropertyGroup>

<PropertyGroup Condition="!('$(TargetsWindows)' == 'true' AND '$(Platform)' == 'x86')">
<FeatureEHFunclets>true</FeatureEHFunclets>
</PropertyGroup>

<PropertyGroup>
<DefineConstants Condition="'$(FeatureArrayStubAsIL)' == 'true'">$(DefineConstants);FEATURE_ARRAYSTUB_AS_IL</DefineConstants>
<DefineConstants Condition="'$(FeatureMulticastStubAsIL)' == 'true'">$(DefineConstants);FEATURE_MULTICASTSTUB_AS_IL</DefineConstants>
Expand All @@ -59,6 +63,7 @@
<DefineConstants Condition="'$(FeatureBasicFreeze)' == 'true'">$(DefineConstants);FEATURE_BASICFREEZE</DefineConstants>
<DefineConstants Condition="'$(FeaturePortableShuffleThunks)' == 'true'">$(DefineConstants);FEATURE_PORTABLE_SHUFFLE_THUNKS</DefineConstants>
<DefineConstants Condition="'$(FeatureICastable)' == 'true'">$(DefineConstants);FEATURE_ICASTABLE</DefineConstants>
<DefineConstants Condition="'$(FeatureEHFunclets)' == 'true'">$(DefineConstants);FEATURE_EH_FUNCLETS</DefineConstants>

<DefineConstants Condition="'$(ProfilingSupportedBuild)' == 'true'">$(DefineConstants);PROFILING_SUPPORTED</DefineConstants>
<DefineConstants Condition="'$(FeatureProfAttach)' == 'true'">$(DefineConstants);FEATURE_PROFAPI_ATTACH_DETACH</DefineConstants>
Expand Down
44 changes: 44 additions & 0 deletions src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,22 @@ BOOL DacDbiInterfaceImpl::UnwindStackWalkFrame(StackWalkHandle pSFIHandle)
// Just continue onto the next managed stack frame.
continue;
}
#ifdef FEATURE_EH_FUNCLETS
else if (g_isNewExceptionHandlingEnabled && pIter->GetFrameState() == StackFrameIterator::SFITER_FRAMELESS_METHOD)
{
// Skip the new exception handling managed code, the debugger clients are not supposed to see them
MethodDesc *pMD = pIter->m_crawl.GetFunction();
PTR_MethodDesc ptrMD = dac_cast<PTR_MethodDesc>(pMD);

// EH.DispatchEx, EH.RhThrowEx, EH.RhThrowHwEx
if (ptrMD->GetMethodTable() == g_pEHClass)
{
continue;
}

fIsAtEndOfStack = FALSE;
}
#endif // FEATURE_EH_FUNCLETS
else
{
fIsAtEndOfStack = FALSE;
Expand Down Expand Up @@ -433,6 +449,20 @@ ULONG32 DacDbiInterfaceImpl::GetCountOfInternalFrames(VMPTR_Thread vmThread)
ULONG32 uCount = 0;
while (pFrame != FRAME_TOP)
{
#ifdef FEATURE_EH_FUNCLETS
if (g_isNewExceptionHandlingEnabled && InlinedCallFrame::FrameHasActiveCall(pFrame))
{
// Skip new exception handling helpers
InlinedCallFrame *pInlinedCallFrame = (InlinedCallFrame *)pFrame;
PTR_NDirectMethodDesc pMD = pInlinedCallFrame->m_Datum;
TADDR datum = dac_cast<TADDR>(pMD);
if ((datum & (TADDR)InlinedCallFrameMarker::Mask) == (TADDR)InlinedCallFrameMarker::ExceptionHandlingHelper)
{
pFrame = pFrame->Next();
continue;
}
}
#endif // FEATURE_EH_FUNCLETS
CorDebugInternalFrameType ift = GetInternalFrameType(pFrame);
if (ift != STUBFRAME_NONE)
{
Expand Down Expand Up @@ -472,6 +502,20 @@ void DacDbiInterfaceImpl::EnumerateInternalFrames(VMPTR_Thread

while (pFrame != FRAME_TOP)
{
#ifdef FEATURE_EH_FUNCLETS
if (g_isNewExceptionHandlingEnabled && InlinedCallFrame::FrameHasActiveCall(pFrame))
{
// Skip new exception handling helpers
InlinedCallFrame *pInlinedCallFrame = (InlinedCallFrame *)pFrame;
PTR_NDirectMethodDesc pMD = pInlinedCallFrame->m_Datum;
TADDR datum = dac_cast<TADDR>(pMD);
if ((datum & (TADDR)InlinedCallFrameMarker::Mask) == (TADDR)InlinedCallFrameMarker::ExceptionHandlingHelper)
{
pFrame = pFrame->Next();
continue;
}
}
#endif // FEATURE_EH_FUNCLETS
// check if the internal frame is interesting
frameData.stubFrame.frameType = GetInternalFrameType(pFrame);
if (frameData.stubFrame.frameType != STUBFRAME_NONE)
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/inc/clrconfigvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,8 @@ 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, "")
RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableNewExceptionHandling, W("EnableNewExceptionHandling"), 0, "Enable new exception handling.");


///
/// Garbage collector
Expand Down
5 changes: 5 additions & 0 deletions src/coreclr/inc/dacvars.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ DEFINE_DACVAR(DWORD, dac__g_debuggerWordTLSIndex, g_debuggerWordTLSIndex)
#endif
DEFINE_DACVAR(DWORD, dac__g_TlsIndex, g_TlsIndex)

#ifdef FEATURE_EH_FUNCLETS
DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pEHClass, ::g_pEHClass)
DEFINE_DACVAR(BOOL, dac__g_isNewExceptionHandlingEnabled, ::g_isNewExceptionHandlingEnabled)
#endif

DEFINE_DACVAR(PTR_SString, SString__s_Empty, SString::s_Empty)

DEFINE_DACVAR(INT32, ArrayBase__s_arrayBoundsZero, ArrayBase::s_arrayBoundsZero)
Expand Down
Loading

0 comments on commit f8d9b3c

Please sign in to comment.