Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// The Debugger class is a part of the System.Diagnostics package
// and is used for communicating with a debugger.

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

Expand Down Expand Up @@ -93,5 +94,22 @@ static void NotifyOfCrossThreadDependencySlow()
[DebuggerStepThrough]
[DebuggerHidden]
internal static void UserBreakpoint() => Break();

[UnmanagedCallersOnly]
[StackTraceHidden]
[DebuggerHidden]
internal static unsafe void InvokeFunction(IntPtr methodHandle, IntPtr declaringTypeHandle, IntPtr* storage)
{
RuntimeType declaringType = RuntimeTypeHandle.GetRuntimeTypeFromHandle(declaringTypeHandle);
MethodBase? method = RuntimeType.GetMethodBase(declaringType, new RuntimeMethodHandleInternal(methodHandle));
Debug.Assert(method is RuntimeMethodInfo or RuntimeConstructorInfo);

MethodBaseInvoker invoker = method is RuntimeMethodInfo methodInfo
? methodInfo.Invoker
: ((RuntimeConstructorInfo)method!).Invoker;

// Exceptions must reach the native func-eval handler without introducing a managed catch site.
invoker.InvokeForDebugger(storage);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;
using System.Reflection.Emit;
using System.Threading;

namespace System.Reflection
{
internal partial class MethodBaseInvoker
{
private IntrinsicInvokeHelper.InvokeState _invokeState;
private InvokerEmitUtil.InvokeFunc_Debugger? _invokeFunc_Debugger;

internal unsafe MethodBaseInvoker(RuntimeMethodInfo method) : this(method, method.Signature.Arguments)
{
Expand Down Expand Up @@ -39,5 +42,22 @@ internal unsafe MethodBaseInvoker(DynamicMethod method, Signature signature) : t

return _invokeFunc_RefArgs!(obj, args);
}

[StackTraceHidden]
[DebuggerHidden]
internal unsafe void InvokeForDebugger(IntPtr* storage)
{
InvokerEmitUtil.InvokeFunc_Debugger? invoke = Volatile.Read(ref _invokeFunc_Debugger);
if (invoke is null)
{
using (AssemblyBuilder.ForceAllowDynamicCode())
{
invoke = InvokerEmitUtil.CreateInvokeDelegate_Debugger(_method);
}
invoke = Interlocked.CompareExchange(ref _invokeFunc_Debugger, invoke, null) ?? invoke;
}

invoke(storage);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ internal InvocationFlags InvocationFlags
}
}

private MethodBaseInvoker Invoker
internal MethodBaseInvoker Invoker
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
Expand Down
5 changes: 2 additions & 3 deletions src/coreclr/debug/ee/debugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1279,7 +1279,6 @@ DebuggerEval::DebuggerEval(CONTEXT * pContext, DebuggerIPCE_FuncEvalInfo * pEval
m_pAssembly = pEvalInfo->vmAssembly.GetRawPtr();
m_funcEvalKey = pEvalInfo->funcEvalKey;
m_argCount = pEvalInfo->argCount;
m_targetCodeAddr = (TADDR)NULL;
m_stringSize = pEvalInfo->stringSize;
m_arrayRank = pEvalInfo->arrayRank;
m_genericArgsCount = pEvalInfo->genericArgsCount;
Expand Down Expand Up @@ -14335,7 +14334,7 @@ Debugger::FuncEvalAbort(
CONTRACTL
{
THROWS;
GC_NOTRIGGER;
if (g_pEEInterface->GetThread() != nullptr) { GC_TRIGGERS; } else { GC_NOTRIGGER; }
}
CONTRACTL_END;

Expand Down Expand Up @@ -14398,7 +14397,7 @@ Debugger::FuncEvalRudeAbort(
CONTRACTL
{
THROWS;
GC_NOTRIGGER;
if (g_pEEInterface->GetThread() != nullptr) { GC_TRIGGERS; } else { GC_NOTRIGGER; }
}
CONTRACTL_END;

Expand Down
1 change: 0 additions & 1 deletion src/coreclr/debug/ee/debugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -3391,7 +3391,6 @@ class DebuggerEval
SIZE_T m_stringSize;
BYTE *m_argData;
MethodDesc *m_md;
PCODE m_targetCodeAddr;
ARG_SLOT m_result[NUMBER_RETURNVALUE_SLOTS];
TypeHandle m_resultType;
SIZE_T m_arrayRank;
Expand Down
Loading
Loading