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

Update stepping through MulticastDelegate under the Debugger #108414

126 changes: 118 additions & 8 deletions src/coreclr/debug/ee/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include "../../vm/methoditer.h"
#include "../../vm/tailcallhelp.h"
#include "../../vm/stubhelpers.h"
mikelle-rogers marked this conversation as resolved.
Show resolved Hide resolved

const char *GetTType( TraceType tt);

Expand Down Expand Up @@ -943,7 +944,8 @@ DebuggerController::DebuggerController(Thread * pThread, AppDomain * pAppDomain)
m_unwindFP(LEAF_MOST_FRAME),
m_eventQueuedCount(0),
m_deleted(false),
m_fEnableMethodEnter(false)
m_fEnableMethodEnter(false),
m_multicastDelegateHelper(false)
{
CONTRACTL
{
Expand Down Expand Up @@ -1133,6 +1135,8 @@ void DebuggerController::DisableAll()
DisableTraceCall();
if (m_fEnableMethodEnter)
DisableMethodEnter();
if (m_multicastDelegateHelper)
DisableMultiCastDelegate();
}
}

Expand Down Expand Up @@ -2279,6 +2283,7 @@ static bool _AddrIsJITHelper(PCODE addr)
// method & return true.
//
// Return true if we set a patch, else false
#ifndef DACCESS_COMPILE
bool DebuggerController::PatchTrace(TraceDestination *trace,
FramePointer fp,
bool fStopInUnmanaged)
Expand Down Expand Up @@ -2373,14 +2378,20 @@ bool DebuggerController::PatchTrace(TraceDestination *trace,
return true;

case TRACE_MGR_PUSH:
LOG((LF_CORDB, LL_INFO10000,
if (trace->GetAddress() == GetEEFuncEntryPoint(StubHelpers::MulticastDebuggerTraceHelper))
mikelle-rogers marked this conversation as resolved.
Show resolved Hide resolved
{
EnableMultiCastDelegate();
}
else
{
LOG((LF_CORDB, LL_INFO10000,
"Setting frame patch (TRACE_MGR_PUSH) at 0x%p(%p)\n",
trace->GetAddress(), fp.GetSPValue()));

dcp = AddAndActivateNativePatchForAddress((CORDB_ADDRESS_TYPE *)trace->GetAddress(),
LEAF_MOST_FRAME, // But Mgr_push can't have fp affinity!
TRUE,
DPT_DEFAULT_TRACE_TYPE); // TRACE_OTHER
dcp = AddAndActivateNativePatchForAddress((CORDB_ADDRESS_TYPE *)trace->GetAddress(),
LEAF_MOST_FRAME, // But Mgr_push can't have fp affinity!
TRUE,
DPT_DEFAULT_TRACE_TYPE); // TRACE_OTHER
}
// Now copy over the trace field since TriggerPatch will expect this
// to be set for this case.
if (dcp != NULL)
Expand All @@ -2400,6 +2411,7 @@ bool DebuggerController::PatchTrace(TraceDestination *trace,
return false;
}
}
#endif

//-----------------------------------------------------------------------------
// Checks if the patch matches the context + thread.
Expand Down Expand Up @@ -3879,6 +3891,75 @@ void DebuggerController::DispatchMethodEnter(void * pIP, FramePointer fp)

}

void DebuggerController::EnableMultiCastDelegate()
{
CONTRACTL
{
NOTHROW;
GC_NOTRIGGER;
}
CONTRACTL_END;

ControllerLockHolder chController;
Debugger::DebuggerDataLockHolder chInfo(g_pDebugger);
mikelle-rogers marked this conversation as resolved.
Show resolved Hide resolved
if (!m_multicastDelegateHelper)
{
LOG((LF_CORDB, LL_INFO1000000, "DC::EnableMultiCastDel, this=%p, previously disabled\n", this));
m_multicastDelegateHelper = true;
}
else
{
LOG((LF_CORDB, LL_INFO1000000, "DC::EnableMultiCastDel, this=%p, already set\n", this));
}
}

void DebuggerController::DisableMultiCastDelegate()
{
CONTRACTL
{
NOTHROW;
GC_NOTRIGGER;
}
CONTRACTL_END;

ControllerLockHolder chController;
Debugger::DebuggerDataLockHolder chInfo(g_pDebugger);
mikelle-rogers marked this conversation as resolved.
Show resolved Hide resolved

if (m_multicastDelegateHelper)
{
LOG((LF_CORDB, LL_INFO10000, "DC::DisableMultiCastDel, this=%p, previously set\n", this));
m_multicastDelegateHelper = false;
}
else
{
LOG((LF_CORDB, LL_INFO10000, "DC::DisableMultiCastDel, this=%p, already disabled\n", this));
mikelle-rogers marked this conversation as resolved.
Show resolved Hide resolved
}
}

// Loop through controllers and dispatch TriggerMulticastDelegate
void DebuggerController::DispatchMulticastDelegate(BYTE* pbDel, INT32 countDel)
{
LOG((LF_CORDB, LL_INFO10000, "DC::DispatchMulticastDelegate\n"));

Thread * pThread = g_pEEInterface->GetThread();
_ASSERTE(pThread != NULL);

ControllerLockHolder lockController;

DebuggerController *p = g_controllers;
while (p != NULL)
{
if (p->m_multicastDelegateHelper)
{
if ((p->GetThread() == NULL) || (p->GetThread() == pThread))
mikelle-rogers marked this conversation as resolved.
Show resolved Hide resolved
{
p->TriggerMulticastDelegate(pbDel, countDel);
p->DisableMultiCastDelegate();
mikelle-rogers marked this conversation as resolved.
Show resolved Hide resolved
}
}
p = p->m_next;
}
}
//
// AddProtection adds page protection to (at least) the given range of
// addresses
Expand Down Expand Up @@ -4023,6 +4104,10 @@ void DebuggerController::DispatchFuncEvalExit(Thread * thread)


}
void DebuggerController::TriggerMulticastDelegate(BYTE* pDel, INT32 delegateCount)
{
LOG((LF_CORDB, LL_INFO10000, "DC::TMD: in default TriggerMulticastDelegate\n"));
mikelle-rogers marked this conversation as resolved.
Show resolved Hide resolved
}


#ifdef _DEBUG
Expand Down Expand Up @@ -6283,7 +6368,7 @@ void DebuggerStepper::TrapStepOut(ControllerStackInfo *info, bool fForceTraditio
&& g_pEEInterface->FollowTrace(&trace)
&& PatchTrace(&trace, info->m_activeFrame.fp,
true))
break;
continue;
}
else if (info->m_activeFrame.md != nullptr && info->m_activeFrame.md->IsILStub() &&
info->m_activeFrame.md->AsDynamicMethodDesc()->GetILStubType() == DynamicMethodDesc::StubTailCallCallTarget)
Expand Down Expand Up @@ -7553,6 +7638,31 @@ void DebuggerStepper::TriggerUnwind(Thread *thread,
m_reason = unwindReason;
}

void DebuggerStepper::TriggerMulticastDelegate(BYTE* pDel, INT32 delegateCount)
mikelle-rogers marked this conversation as resolved.
Show resolved Hide resolved
{
TraceDestination trace;
FramePointer fp = LEAF_MOST_FRAME;

int totalDelegateCount = (int)*(size_t*)((BYTE*)pDel + DelegateObject::GetOffsetOfInvocationCount());
mikelle-rogers marked this conversation as resolved.
Show resolved Hide resolved
if (delegateCount == totalDelegateCount)
jkotas marked this conversation as resolved.
Show resolved Hide resolved
mikelle-rogers marked this conversation as resolved.
Show resolved Hide resolved
{
PCODE addr = NULL;
mikelle-rogers marked this conversation as resolved.
Show resolved Hide resolved
trace.InitForOther(addr);
LOG((LF_CORDB, LL_INFO10000, "DS::TMD this:0x%x, Fired all delegates\n", this));
mikelle-rogers marked this conversation as resolved.
Show resolved Hide resolved
}
else
{
BYTE *pbDelInvocationList = *(BYTE **)((BYTE*)pDel + DelegateObject::GetOffsetOfInvocationList());
mikelle-rogers marked this conversation as resolved.
Show resolved Hide resolved

BYTE* pbDel = *(BYTE**)( ((ArrayBase *)pbDelInvocationList)->GetDataPtr() +
((ArrayBase *)pbDelInvocationList)->GetComponentSize()*delegateCount);
_ASSERTE(pbDel);
StubLinkStubManager::TraceDelegateObject(pbDel, &trace);
}

g_pEEInterface->FollowTrace(&trace);
PatchTrace(&trace, fp, false); //Value of last bool only matters for the TRACE_UMNANAGED case, we are in the TRACE_MGR_PUSH case
mikelle-rogers marked this conversation as resolved.
Show resolved Hide resolved
}

// Prepare for sending an event.
// This is called 1:1 w/ SendEvent, but this method can be called in a GC_TRIGGERABLE context
Expand Down
8 changes: 7 additions & 1 deletion src/coreclr/debug/ee/controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -1089,6 +1089,7 @@ class DebuggerController
// pIP is the ip right after the prolog of the method we've entered.
// fp is the frame pointer for that method.
static void DispatchMethodEnter(void * pIP, FramePointer fp);
static void DispatchMulticastDelegate(BYTE* pbDel, INT32 countDel);


// Delete any patches that exist for a specific module and optionally a specific AppDomain.
Expand Down Expand Up @@ -1299,6 +1300,9 @@ class DebuggerController
void EnableMethodEnter();
void DisableMethodEnter();

void EnableMultiCastDelegate();
void DisableMultiCastDelegate();

void DisableAll();

virtual DEBUGGER_CONTROLLER_TYPE GetDCType( void )
Expand Down Expand Up @@ -1398,6 +1402,7 @@ class DebuggerController
const BYTE * ip,
FramePointer fp);

virtual void TriggerMulticastDelegate(BYTE* pDel, INT32 delegateCount);

// Send the managed debug event.
// This is called after TriggerPatch/TriggerSingleStep actually trigger.
Expand Down Expand Up @@ -1437,6 +1442,7 @@ class DebuggerController
int m_eventQueuedCount;
bool m_deleted;
bool m_fEnableMethodEnter;
bool m_multicastDelegateHelper;

#endif // !DACCESS_COMPILE
};
Expand Down Expand Up @@ -1638,7 +1644,7 @@ class DebuggerStepper : public DebuggerController


virtual void TriggerMethodEnter(Thread * thread, DebuggerJitInfo * dji, const BYTE * ip, FramePointer fp);

void TriggerMulticastDelegate(BYTE* pDel, INT32 delegateCount);

void ResetRange();

Expand Down
9 changes: 8 additions & 1 deletion src/coreclr/debug/ee/debugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "../../vm/dwreport.h"
#include "../../vm/eepolicy.h"
#include "../../vm/excep.h"
#include "../../vm/stubhelpers.h"
mikelle-rogers marked this conversation as resolved.
Show resolved Hide resolved
#if defined(FEATURE_DBGIPC_TRANSPORT_VM)
#include "dbgtransportsession.h"
#endif // FEATURE_DBGIPC_TRANSPORT_VM
Expand Down Expand Up @@ -12600,7 +12601,7 @@ bool Debugger::IsThreadAtSafePlace(Thread *thread)
// any thread handling a SO is not at a safe place.
// NOTE: don't check for thread->IsExceptionInProgress(), SO has special handling
// that directly sets the last thrown object without ever creating a tracker.
// (Tracker is what thread->IsExceptionInProgress() checks for)
// (Tracker is what thread->IsExceptionInProgress() checks for)
if (g_pEEInterface->GetThreadException(thread) == CLRException::GetPreallocatedStackOverflowExceptionHandle())
{
return false;
Expand Down Expand Up @@ -16787,6 +16788,12 @@ BOOL Debugger::IsOutOfProcessSetContextEnabled()
}
#endif // OUT_OF_PROCESS_SETTHREADCONTEXT
#endif // DACCESS_COMPILE
#ifndef DACCESS_COMPILE
void Debugger::MulticastTraceNextStep(BYTE* pbDel, INT32 count)
{
DebuggerController::DispatchMulticastDelegate(pbDel, count);
}
#endif //DACCESS_COMPILE

#endif //DEBUGGING_SUPPORTED

3 changes: 3 additions & 0 deletions src/coreclr/debug/ee/debugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -2613,6 +2613,9 @@ class Debugger : public DebugInterface
bool ThisIsHelperThread(void);

HRESULT ReDaclEvents(PSECURITY_DESCRIPTOR securityDescriptor);
#ifndef DACCESS_COMPILE
void MulticastTraceNextStep(BYTE* pbDel, INT32 count);
#endif

#ifdef DACCESS_COMPILE
virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/dbginterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ class DebugInterface
#ifndef DACCESS_COMPILE
virtual HRESULT DeoptimizeMethod(Module* pModule, mdMethodDef methodDef) = 0;
virtual HRESULT IsMethodDeoptimized(Module *pModule, mdMethodDef methodDef, BOOL *pResult) = 0;
virtual void MulticastTraceNextStep(BYTE* pbDel, INT32 count) = 0;
#endif //DACCESS_COMPILE
};

Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/vm/stubhelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "comdatetime.h"
#include "gcheaputilities.h"
#include "interoputil.h"
#include "../debug/ee/debugger.h"

#ifdef FEATURE_COMINTEROP
#include <oletls.h>
Expand Down Expand Up @@ -740,6 +741,7 @@ FCIMPL2(void, StubHelpers::MulticastDebuggerTraceHelper, Object* element, INT32
{
FCALL_CONTRACT;
FCUnique(0xa5);
mikelle-rogers marked this conversation as resolved.
Show resolved Hide resolved
g_pDebugger->MulticastTraceNextStep(reinterpret_cast<BYTE*>(element), count);
mikelle-rogers marked this conversation as resolved.
Show resolved Hide resolved
mikelle-rogers marked this conversation as resolved.
Show resolved Hide resolved
}
FCIMPLEND

Expand Down
37 changes: 1 addition & 36 deletions src/coreclr/vm/stubmgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1711,13 +1711,7 @@ BOOL ILStubManager::DoTraceStub(PCODE stubStartAddress,
MethodDesc* pStubMD = ExecutionManager::GetCodeMethodDesc(stubStartAddress);
if (pStubMD != NULL && pStubMD->AsDynamicMethodDesc()->IsMulticastStub())
{
#if defined(TARGET_ARM64) && defined(__APPLE__)
//On ARM64 Mac, we cannot put a breakpoint inside of MulticastDebuggerTraceHelper
LOG((LF_CORDB, LL_INFO10000, "ILSM::DoTraceStub: skipping on arm64-macOS\n"));
return FALSE;
#else
traceDestination = GetEEFuncEntryPoint(StubHelpers::MulticastDebuggerTraceHelper);
#endif //defined(TARGET_ARM64) && defined(__APPLE__)
}
else
{
Expand Down Expand Up @@ -1774,12 +1768,6 @@ BOOL ILStubManager::TraceManager(Thread *thread,
PCODE stubIP = GetIP(pContext);
*pRetAddr = (BYTE *)StubManagerHelpers::GetReturnAddress(pContext);

if (stubIP == GetEEFuncEntryPoint(StubHelpers::MulticastDebuggerTraceHelper))
{
stubIP = (PCODE)*pRetAddr;
*pRetAddr = (BYTE*)StubManagerHelpers::GetRetAddrFromMulticastILStubFrame(pContext);
}

DynamicMethodDesc *pStubMD = Entry2MethodDesc(stubIP, NULL)->AsDynamicMethodDesc();
TADDR arg = StubManagerHelpers::GetHiddenArg(pContext);
Object * pThis = StubManagerHelpers::GetThisPtr(pContext);
Expand All @@ -1789,30 +1777,7 @@ BOOL ILStubManager::TraceManager(Thread *thread,
// See code:ILStubCache.CreateNewMethodDesc for the code that sets flags on stub MDs
PCODE target = (PCODE)NULL;

if (pStubMD->IsMulticastStub())
{
_ASSERTE(GetIP(pContext) == GetEEFuncEntryPoint(StubHelpers::MulticastDebuggerTraceHelper));

int delegateCount = (int)StubManagerHelpers::GetSecondArg(pContext);
int totalDelegateCount = (int)*(size_t*)((BYTE*)pThis + DelegateObject::GetOffsetOfInvocationCount());
if (delegateCount == totalDelegateCount)
{
LOG((LF_CORDB, LL_INFO1000, "ILSM::TraceManager: Fired all delegates\n"));
return FALSE;
}
else
{
// We're going to execute stub delegateCount next, so go and grab it.
BYTE *pbDelInvocationList = *(BYTE **)((BYTE*)pThis + DelegateObject::GetOffsetOfInvocationList());

BYTE* pbDel = *(BYTE**)( ((ArrayBase *)pbDelInvocationList)->GetDataPtr() +
((ArrayBase *)pbDelInvocationList)->GetComponentSize()*delegateCount);

_ASSERTE(pbDel);
return StubLinkStubManager::TraceDelegateObject(pbDel, trace);
}
}
else if (pStubMD->IsReverseStub())
if (pStubMD->IsReverseStub())
mikelle-rogers marked this conversation as resolved.
Show resolved Hide resolved
{
if (pStubMD->IsStatic())
{
Expand Down
Loading
Loading