Example #1
0
void DacDbiInterfaceImpl::EnumerateInternalFrames(VMPTR_Thread                           vmThread,
                                                  FP_INTERNAL_FRAME_ENUMERATION_CALLBACK fpCallback,
                                                  void *                                 pUserData)
{
    DD_ENTER_MAY_THROW;

    DebuggerIPCE_STRData frameData;

    Thread *    pThread    = vmThread.GetDacPtr();
    Frame *     pFrame     = pThread->GetFrame();
    AppDomain * pAppDomain = pThread->GetDomain(INDEBUG(TRUE));

    // This used to be only true for Enter-Managed chains.
    // Since we don't have chains anymore, this can always be false.
    frameData.quicklyUnwound = false;
    frameData.eType = DebuggerIPCE_STRData::cStubFrame;

    while (pFrame != FRAME_TOP)
    {
        // check if the internal frame is interesting
        frameData.stubFrame.frameType = GetInternalFrameType(pFrame);
        if (frameData.stubFrame.frameType != STUBFRAME_NONE)
        {
            frameData.fp = FramePointer::MakeFramePointer(PTR_HOST_TO_TADDR(pFrame));

            frameData.vmCurrentAppDomainToken.SetHostPtr(pAppDomain);

            MethodDesc * pMD = pFrame->GetFunction();
#if defined(FEATURE_COMINTEROP)
            if (frameData.stubFrame.frameType == STUBFRAME_U2M)
            {
                _ASSERTE(pMD == NULL);

                // U2M transition frame generally don't store the target MD because we know what the target
                // is by looking at the callee stack frame.  However, for reverse COM interop, we can try
                // to get the MD for the interface.
                // 
                // Note that some reverse COM interop cases don't have an intermediate interface MD, so
                // pMD may still be NULL.
                //
                // Even if there is an MD on the ComMethodFrame, it could be in a different appdomain than
                // the ComMethodFrame itself.  The only known scenario is a cross-appdomain reverse COM 
                // interop call.  We need to check for this case.  The end result is that GetFunction() and
                // GetFunctionToken() on ICDInternalFrame will return NULL.

                // Minidumps without full memory don't guarantee to capture the CCW since we can do without
                // it.  In this case, pMD will remain NULL.
                EX_TRY_ALLOW_DATATARGET_MISSING_MEMORY
                {
                    if (pFrame->GetVTablePtr() == ComMethodFrame::GetMethodFrameVPtr())
                    {
                        ComMethodFrame * pCOMFrame = dac_cast<PTR_ComMethodFrame>(pFrame);
                        PTR_VOID pUnkStackSlot     = pCOMFrame->GetPointerToArguments();
                        PTR_IUnknown pUnk          = dac_cast<PTR_IUnknown>(*dac_cast<PTR_TADDR>(pUnkStackSlot));
                        ComCallWrapper * pCCW      = ComCallWrapper::GetWrapperFromIP(pUnk);

                        if (!pCCW->NeedToSwitchDomains(pAppDomain->GetId()))
                        {
                            ComCallMethodDesc * pCMD = NULL;
                            pCMD = dac_cast<PTR_ComCallMethodDesc>(pCOMFrame->ComMethodFrame::GetDatum());
                            pMD  = pCMD->GetInterfaceMethodDesc();
                        }
                    }
                }
                EX_END_CATCH_ALLOW_DATATARGET_MISSING_MEMORY
            }
#endif // FEATURE_COMINTEROP

            Module *     pModule = (pMD ? pMD->GetModule() : NULL);
            DomainFile * pDomainFile = (pModule ? pModule->GetDomainFile(pAppDomain) : NULL);

            if (frameData.stubFrame.frameType == STUBFRAME_FUNC_EVAL)
            {
                FuncEvalFrame * pFEF = dac_cast<PTR_FuncEvalFrame>(pFrame);
                DebuggerEval *  pDE  = pFEF->GetDebuggerEval();

                frameData.stubFrame.funcMetadataToken = pDE->m_methodToken;
                frameData.stubFrame.vmDomainFile.SetHostPtr(
                    pDE->m_debuggerModule ? pDE->m_debuggerModule->GetDomainFile() : NULL);
                frameData.stubFrame.vmMethodDesc = VMPTR_MethodDesc::NullPtr();
            }
            else
            {
                frameData.stubFrame.funcMetadataToken = (pMD == NULL ? NULL : pMD->GetMemberDef());
                frameData.stubFrame.vmDomainFile.SetHostPtr(pDomainFile);
                frameData.stubFrame.vmMethodDesc.SetHostPtr(pMD);
            }

            // invoke the callback
            fpCallback(&frameData, pUserData);
        }