Repository: dotnet/runtime
File: src/coreclr/debug/ee/controller.cpp (C++)

Code before:
                LOG((LF_CORDB, LL_INFO10000, "DS::TP: Got TRACE_MGR_PUSH at current IP: 0x%p, calling TraceManager\n", currentPC));
                CONTRACT_VIOLATION(GCViolation);
                PTR_BYTE traceManagerRetAddr = NULL;
                traceOk = g_pEEInterface->TraceManager(
                    thread,
                    trace.GetStubManager(),
                    &trace,
                    context,
                    &traceManagerRetAddr);
                LOG((LF_CORDB, LL_INFO10000, "DS::TP: TraceManager=%d, trace type=%d\n",
                    traceOk, traceOk ? trace.GetTraceType() : -1));
            }

            if (traceOk && 
                g_pEEInterface->FollowTrace(&trace) &&
                PatchTrace(&trace, info.m_activeFrame.fp,
                           (m_rgfMappingStop & STOP_UNMANAGED) ? true : false))
            {
                // Successfully patched the real target, continue execution
                m_reason = STEP_CALL;
                EnableTraceCall(LEAF_MOST_FRAME);
                EnableUnwind(m_fp);
                return TPR_IGNORE;
            }
        }
    }

    LOG((LF_CORDB,LL_INFO10000, "DS: m_fp:0x%p, activeFP:0x%p fpExc:0x%p\n",
        m_fp.GetSPValue(), info.m_activeFrame.fp.GetSPValue(), m_fpException.GetSPValue()));

    if (IsInRange(offset, m_range, m_rangeCount, &info) ||
        ShouldContinueStep( &info, offset))
    {
        LOG((LF_CORDB, LL_INFO10000,
             "Intermediate step patch hit at 0x%x\n", offset));

        if (!TrapStep(&info, m_stepIn))
            TrapStepNext(&info);

        EnableUnwind(m_fp);
        return TPR_IGNORE;
    }
    else
    {
        LOG((LF_CORDB, LL_INFO10000, "Step patch hit at 0x%x\n", offset));

        // For a JMC stepper, we have an additional constraint:
        // skip non-user code. So if we're still in non-user code, then
        // we've got to keep going
        DebuggerMethodInfo * dmi = g_pDebugger->GetOrCreateMethodInfo(module, md);


Review comment (bug):
Hopefully this won't be needed any longer, but if it does stay then we should add comments spelling out why this is safe. These violations can trigger deadlocks from acquiring locks in the wrong order when not done very carefully.

Code after:
    // Replica patches do not contain a reference to the original trace so we can not rely
    // on the trace type == TRACE_UNJITTED_METHOD to identify this case.
    {
        PCODE currentPC = GetControlPC(&(info.m_activeFrame.registers));
        LOG((LF_CORDB, LL_INFO10000, "DS::TP: Checking stub at PC %p, IsStub=%d\n", currentPC, g_pEEInterface->IsStub((const BYTE*)currentPC)));
        if (g_pEEInterface->IsStub((const BYTE*)currentPC))
        {
            LOG((LF_CORDB, LL_INFO10000, "DS::TP: IsStub=true, calling TraceStub\n"));
            TraceDestination trace;
            bool traceOk;

            // Call TraceStub to get the trace destination
            traceOk = g_pEEInterface->TraceStub((const BYTE*)currentPC, &trace);
            LOG((LF_CORDB, LL_INFO10000, "DS::TP: TraceStub=%d, trace type=%d\n", traceOk, traceOk ? trace.GetTraceType() : -1));

            // Special case where TraceStub returns TRACE_MGR_PUSH at our current address.
            // We need to call TraceManager to resolve the real target as the patch at the current
            // address will not trigger due to being added to the beginning of the patch list.
            // This behavior is used by the AsyncThunkStubManager due to the CONTRACT in TraceStub
            // preventing it from triggering the GC.
            if (traceOk &&
                trace.GetTraceType() == TRACE_MGR_PUSH &&
                trace.GetAddress() == currentPC)
            {
                LOG((LF_CORDB, LL_INFO10000, "DS::TP: Got TRACE_MGR_PUSH at current IP: 0x%p, calling TraceManager\n", currentPC));
                CONTRACT_VIOLATION(GCViolation);
                PTR_BYTE traceManagerRetAddr = NULL;
                traceOk = g_pEEInterface->TraceManager(
                    thread,
                    trace.GetStubManager(),
                    &trace,
                    context,
                    &traceManagerRetAddr);
                LOG((LF_CORDB, LL_INFO10000, "DS::TP: TraceManager=%d, trace type=%d\n",
                    traceOk, traceOk ? trace.GetTraceType() : -1));
            }

            if (traceOk && 
                g_pEEInterface->FollowTrace(&trace) &&
                PatchTrace(&trace, info.m_activeFrame.fp,
                           (m_rgfMappingStop & STOP_UNMANAGED) ? true : false))
            {
                // Successfully patched the real target, continue execution
                m_reason = STEP_CALL;
                EnableTraceCall(LEAF_MOST_FRAME);
                EnableUnwind(m_fp);
                return TPR_IGNORE;
            }
        }
    }