Implement ICorDebugManagedCallback4::DataBreakpoint
authorTom McDonald <tommcdon@microsoft.com>
Wed, 16 May 2018 18:31:34 +0000 (11:31 -0700)
committerAndrew Au <cshung@gmail.com>
Wed, 7 Nov 2018 02:34:47 +0000 (18:34 -0800)
12 files changed:
src/debug/di/divalue.cpp
src/debug/di/process.cpp
src/debug/di/rsmain.cpp
src/debug/di/rspriv.h
src/debug/di/shimcallback.cpp
src/debug/di/shimpriv.h
src/debug/ee/controller.cpp
src/debug/ee/controller.h
src/debug/ee/debugger.cpp
src/inc/cordebug.idl
src/pal/prebuilt/idl/cordebug_i.cpp
src/pal/prebuilt/inc/cordebug.h

index 0ecb30ce2015866d798638f189a2380d7ffb56b5..e8975ecadded0a050586b09d0aa5c837877e20f3 100644 (file)
@@ -377,18 +377,9 @@ ULONG32 CordbValue::GetSizeForType(CordbType * pType, BoxedValue boxing)
 
 HRESULT CordbValue::CreateBreakpoint(ICorDebugValueBreakpoint **ppBreakpoint)
 {
-    //PUBLIC_API_ENTRY(this);
-    //FAIL_IF_NEUTERED(this);
-    //ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
     VALIDATE_POINTER_TO_OBJECT(ppBreakpoint, ICorDebugValueBreakpoint **);
 
-    //ICorDebugHandleValue** ppHandleValue = nullptr;
-    //if (SUCCEEDED(InternalCreateHandle((CorDebugHandleType)3, ppHandleValue)))
-    //{
-        return GetProcess()->CreateBreakpoint((CORDB_ADDRESS)this->m_id, ppBreakpoint);
-    //}
-
-    //return E_NOTIMPL;
+    return E_NOTIMPL;
 } // CordbValue::CreateBreakpoint
 
 // gets the exact type of a value
index 46429376fd8bf6eab4e39d8b381510cb78948549..3b5f5fb3472ce278b63bbc3df8a773a87d625587 100644 (file)
@@ -2559,143 +2559,6 @@ COM_METHOD CordbProcess::GetContainerObject(CORDB_ADDRESS interiorPointer, ICorD
     return hr;
 }
 
-COM_METHOD CordbProcess::CreateBreakpoint(CORDB_ADDRESS address, ICorDebugValueBreakpoint **ppBreakpoint)
-{
-    HRESULT hr = S_OK;
-    PUBLIC_API_ENTRY(this);
-    FAIL_IF_NEUTERED(this);
-    ATT_REQUIRE_STOPPED_MAY_FAIL(this);
-
-    RSLockHolder lockHolder(GetProcessLock());
-    HASHFIND hashFind;
-    CordbThread * pThread;
-
-    for (pThread = m_userThreads.FindFirst(&hashFind);
-        pThread != NULL;
-        pThread = m_userThreads.FindNext(&hashFind))
-    {
-        HRESULT hr = S_OK;
-        HANDLE hTemp;
-        EX_TRY
-        {
-            pThread->InternalGetHandle(&hTemp);    // throws on error
-        }
-        EX_CATCH_HRESULT(hr);
-
-        DWORD dwDesiredAccess = THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION | THREAD_SET_CONTEXT | THREAD_SET_INFORMATION | THREAD_SUSPEND_RESUME | THREAD_TERMINATE;
-
-        HANDLE hThread;
-        hr = ::DuplicateHandle(GetCurrentProcess(), hTemp, GetCurrentProcess(), &hThread, dwDesiredAccess, FALSE, 0);
-
-        if (SUCCEEDED(hr))
-        {
-            DWORD dwSuspendCount = ::SuspendThread(hThread);
-
-            CONTEXT context;
-            context.ContextFlags = CONTEXT_CONTROL | CONTEXT_DEBUG_REGISTERS;
-
-            BOOL result = ::GetThreadContext(hThread, &context);
-
-            if (result == TRUE)
-            {
-#ifdef DBG_TARGET_X86
-                if (m_dataBreakpoints.GetCount() == 0)
-                {
-                    context.Dr0 = (uint32_t)address;
-                    PDR7 pdr7 = (PDR7)&(context.Dr7);
-                    pdr7->Len0 = 2;
-                    pdr7->Rwe0 = 0x01;
-                    pdr7->L0 = 0x01;
-                }
-                else if (m_dataBreakpoints.GetCount() == 1)
-                {
-                    context.Dr1 = (uint32_t)address;
-                    PDR7 pdr7 = (PDR7)&(context.Dr7);
-                    pdr7->Len1 = 2;
-                    pdr7->Rwe1 = 0x01;
-                    pdr7->L1 = 0x01;
-                }
-                else if (m_dataBreakpoints.GetCount() == 2)
-                {
-                    context.Dr2 = (uint32_t)address;
-                    PDR7 pdr7 = (PDR7)&(context.Dr7);
-                    pdr7->Len2 = 2;
-                    pdr7->Rwe2 = 0x01;
-                    pdr7->L2 = 0x01;
-                }
-                else if (m_dataBreakpoints.GetCount() == 3)
-                {
-                    context.Dr3 = (uint32_t)address;
-                    PDR7 pdr7 = (PDR7)&(context.Dr7);
-                    pdr7->Len3 = 2;
-                    pdr7->Rwe3 = 0x01;
-                    pdr7->L3 = 0x01;
-                }
-                else
-                {
-                    return E_FAIL;
-                }
-#endif
-#ifdef DBG_TARGET_AMD64
-                if (m_dataBreakpoints.GetCount() == 0)
-                {
-                    context.Dr0 = address;
-                    PDR7 pdr7 = (PDR7)&(context.Dr7);
-                    pdr7->Len0 = 2;
-                    pdr7->Rwe0 = 0x01;
-                    pdr7->L0 = 0x01;
-                }
-                else if (m_dataBreakpoints.GetCount() == 1)
-                {
-                    context.Dr1 = address;
-                    PDR7 pdr7 = (PDR7)&(context.Dr7);
-                    pdr7->Len1 = 2;
-                    pdr7->Rwe1 = 0x01;
-                    pdr7->L1 = 0x01;
-                }
-                else if (m_dataBreakpoints.GetCount() == 2)
-                {
-                    context.Dr2 = address;
-                    PDR7 pdr7 = (PDR7)&(context.Dr7);
-                    pdr7->Len2 = 2;
-                    pdr7->Rwe2 = 0x01;
-                    pdr7->L2 = 0x01;
-                }
-                else if (m_dataBreakpoints.GetCount() == 3)
-                {
-                    context.Dr3 = address;
-                    PDR7 pdr7 = (PDR7)&(context.Dr7);
-                    pdr7->Len3 = 2;
-                    pdr7->Rwe3 = 0x01;
-                    pdr7->L3 = 0x01;
-                }
-                else
-                {
-                    return E_FAIL;
-                }
-#endif
-            }
-            result = ::SetThreadContext(hThread, &context);
-            ::ResumeThread(hThread);
-        }
-    }
-
-    EX_TRY
-    {
-        RSInitHolder<CordbValueBreakpoint> pValueBreakpoint(new CordbValueBreakpoint(m_dataBreakpoints.GetCount(), nullptr, this));
-
-        if (pValueBreakpoint)
-        {
-            hr = pValueBreakpoint->QueryInterface(IID_ICorDebugValueBreakpoint, (void**)ppBreakpoint);
-        }
-
-        pValueBreakpoint.TransferOwnershipToHash(&m_dataBreakpoints);
-    }
-    EX_CATCH_HRESULT(hr);
-
-    return hr;
-}
-
 #ifdef FEATURE_LEGACYNETCF_DBG_HOST_CONTROL
 
 COM_METHOD CordbProcess::InvokePauseCallback()
@@ -5067,23 +4930,9 @@ void CordbProcess::RawDispatchEvent(
 
     case DB_IPCE_DATA_BREAKPOINT:
         {
-            _ASSERTE(pThread != NULL);
-            _ASSERTE(pAppDomain != NULL);
-
-            HASHFIND hashFind;
-            CordbValueBreakpoint* pBreakpoint;
-
-            for (pBreakpoint = m_dataBreakpoints.FindFirst(&hashFind);
-                 pBreakpoint != NULL;
-                 pBreakpoint = m_dataBreakpoints.FindNext(&hashFind))
-            {
-                if (pBreakpoint->GetIndex() == pEvent->DataBreakpointData.index)
-                {
-                    PUBLIC_CALLBACK_IN_THIS_SCOPE2(this, pLockHolder, pEvent, "thread=0x%p, bp=0x%p", pThread, pBreakpoint);
-                    pCallback1->Breakpoint(pAppDomain, pThread, CordbBreakpointToInterface(pBreakpoint));
-                    break;
-                }
-            }
+            PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
+            pCallback4->DataBreakpoint(static_cast<ICorDebugProcess*>(this));
+            break;
         }
         break;
     case DB_IPCE_USER_BREAKPOINT:
index 42cf8f8f9b500802bb3d0b07042f563a010f1cbf..254a2b759e7167e32c931da58e1215deb86ea8a6 100644 (file)
@@ -870,6 +870,7 @@ namespace
         virtual ULONG STDMETHODCALLTYPE Release();
         COM_METHOD BeforeGarbageCollection(ICorDebugProcess* pProcess);
         COM_METHOD AfterGarbageCollection(ICorDebugProcess* pProcess);
+        COM_METHOD DataBreakpoint(ICorDebugProcess* pProcess);
     private:
         // not implemented
         DefaultManagedCallback4(const DefaultManagedCallback4&);
@@ -941,6 +942,16 @@ namespace
         pProcess->Continue(false);
         return S_OK;
     }
+
+    HRESULT
+        DefaultManagedCallback4::DataBreakpoint(ICorDebugProcess* pProcess)
+    {
+        //
+        // Just ignore and continue the process.
+        //
+        pProcess->Continue(false);
+        return S_OK;
+    }
 }
 
 /* ------------------------------------------------------------------------- *
index d5a8e606d93ba833d486aa7fe2732875f422c3b4..1e01c5cde4716aeed712abccc89b1f8c227ccad2 100644 (file)
@@ -3167,8 +3167,6 @@ public:
     //-----------------------------------------------------------
     COM_METHOD GetContainerObject(CORDB_ADDRESS interiorPointer, ICorDebugObjectValue** ppContainerObject);
 
-    COM_METHOD CreateBreakpoint(CORDB_ADDRESS address, ICorDebugValueBreakpoint **ppBreakpoint);
-
 #ifdef FEATURE_LEGACYNETCF_DBG_HOST_CONTROL
     // ---------------------------------------------------------------
     // ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly
index 05fea352e3f39c5ea835a81d7dc223233e284438..078643f26d4e0be963cb3ffc01700bd493109495 100644 (file)
@@ -1379,6 +1379,36 @@ HRESULT ShimProxyCallback::AfterGarbageCollection(ICorDebugProcess* pProcess)
     return S_OK;
 }
 
+// Implementation of ICorDebugManagedCallback4::DataBreakpoint
+// Arguments:
+//      input:
+//          pProcess - process in which the notification occurred
+// Return value: S_OK
+HRESULT ShimProxyCallback::DataBreakpoint(ICorDebugProcess* pProcess)
+{
+    m_pShim->PreDispatchEvent();
+    class DataBreakpointEvent : public ManagedEvent
+    {
+        // callbacks parameters. These are strong references
+        RSExtSmartPtr<ICorDebugProcess > m_pProcess;
+
+    public:
+        // Ctor
+        DataBreakpointEvent(ICorDebugProcess* pProcess) :
+            ManagedEvent()
+        {
+            this->m_pProcess.Assign(pProcess);
+        }
+
+        HRESULT Dispatch(DispatchArgs args)
+        {
+            return args.GetCallback4()->DataBreakpoint(m_pProcess);
+        }
+    }; // end class AfterGarbageCollectionEvent
+
+    m_pShim->GetManagedEventQueue()->QueueEvent(new DataBreakpointEvent(pProcess));
+    return S_OK;
+}
 
 
 
index c936b9890f1b9347dbb2cc3a65c672ff68b1b53e..503ee3ef3d18452c27448b8e9b945f17ae49874f 100644 (file)
@@ -220,6 +220,9 @@ public:
 
     // Implementation of ICorDebugManagedCallback4::AfterGarbageCollection
     COM_METHOD ShimProxyCallback::AfterGarbageCollection(ICorDebugProcess* pProcess);
+
+    // Implementation of ICorDebugManagedCallback4::DataBreakpoint
+    COM_METHOD ShimProxyCallback::DataBreakpoint(ICorDebugProcess* pProcess);
 };
 
 
index 6c0914fd962d90db1fa0454cb511adc9aa1b4983..bee9739bba5d6722b537ab751b7205c902761007 100644 (file)
@@ -45,8 +45,7 @@ DebuggerController             *DebuggerController::g_controllers = NULL;
 DebuggerControllerPage         *DebuggerController::g_protections = NULL;
 CrstStatic                      DebuggerController::g_criticalSection;
 int                             DebuggerController::g_cTotalMethodEnter = 0;
-DebuggerDataBreakpoint         *DebuggerDataBreakpoint::g_DataBreakpoints[4];
-unsigned int                    DebuggerDataBreakpoint::g_DataBreakpointCount = 0;
+DebuggerDataBreakpoint          DebuggerDataBreakpoint::g_DebuggerDataBreakpoint;
 
 // Is this patch at a position at which it's safe to take a stack?
 bool DebuggerControllerPatch::IsSafeForStackTrace()
@@ -2728,17 +2727,10 @@ DPOSS_ACTION DebuggerController::ScanForTriggers(CORDB_ADDRESS_TYPE *address,
     }
 
     if (stWhat & ST_SINGLE_STEP &&
-        tpr != TPR_TRIGGER_ONLY_THIS && DebuggerDataBreakpoint::g_DataBreakpointCount > 0)
+        tpr != TPR_TRIGGER_ONLY_THIS && 
+        DebuggerDataBreakpoint::g_DebuggerDataBreakpoint.TriggerDataBreakpoint(thread, context))
     {
-        for (unsigned int i = 0; i < DebuggerDataBreakpoint::g_DataBreakpointCount; i++)
-        {
-            LOG((LF_CORDB, LL_INFO10000, "DC::SFT: Trigger data breakpoint controller\n"));
-
-            if (DebuggerDataBreakpoint::g_DataBreakpoints[i]->TriggerDataBreakpoint(thread, context))
-            {
-                pDcq->dcqEnqueue(DebuggerDataBreakpoint::g_DataBreakpoints[i], FALSE);
-            }
-        }
+        pDcq->dcqEnqueue(&DebuggerDataBreakpoint::g_DebuggerDataBreakpoint, FALSE);
     }
 
     if (stWhat & ST_SINGLE_STEP &&
@@ -3024,35 +3016,35 @@ DPOSS_ACTION DebuggerController::DispatchPatchOrSingleStep(Thread *thread, CONTE
         reabort = thread->m_StateNC & Thread::TSNC_DebuggerReAbort;
         SENDIPCEVENT_END;
 
-        CONTEXT c;
-        c.ContextFlags = CONTEXT_DEBUG_REGISTERS;
-        thread->GetThreadContext(&c);
-
-        context->Dr7 = c.Dr7;
-        context->Dr0 = c.Dr0;
-        context->Dr1 = c.Dr1;
-        context->Dr2 = c.Dr2;
-        context->Dr3 = c.Dr3;
-
-        if (context->Dr0 != NULL && DebuggerDataBreakpoint::g_DataBreakpointCount == 0)
-        {
-            DebuggerDataBreakpoint::CreateDebuggerDataBreakpoint(thread, thread->GetDomain(), context);
-        }
-
-        if (context->Dr1 != NULL && DebuggerDataBreakpoint::g_DataBreakpointCount == 1)
-        {
-            DebuggerDataBreakpoint::CreateDebuggerDataBreakpoint(thread, thread->GetDomain(), context);
-        }
-
-        if (context->Dr2 != NULL && DebuggerDataBreakpoint::g_DataBreakpointCount == 2)
-        {
-            DebuggerDataBreakpoint::CreateDebuggerDataBreakpoint(thread, thread->GetDomain(), context);
-        }
-
-        if (context->Dr3 != NULL && DebuggerDataBreakpoint::g_DataBreakpointCount == 3)
-        {
-            DebuggerDataBreakpoint::CreateDebuggerDataBreakpoint(thread, thread->GetDomain(), context);
-        }
+        //CONTEXT c;
+        //c.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+        //thread->GetThreadContext(&c);
+
+        //context->Dr7 = c.Dr7;
+        //context->Dr0 = c.Dr0;
+        //context->Dr1 = c.Dr1;
+        //context->Dr2 = c.Dr2;
+        //context->Dr3 = c.Dr3;
+
+        //if (context->Dr0 != NULL && DebuggerDataBreakpoint::g_DataBreakpointCount == 0)
+        //{
+        //    DebuggerDataBreakpoint::CreateDebuggerDataBreakpoint(thread, thread->GetDomain(), context);
+        //}
+
+        //if (context->Dr1 != NULL && DebuggerDataBreakpoint::g_DataBreakpointCount == 1)
+        //{
+        //    DebuggerDataBreakpoint::CreateDebuggerDataBreakpoint(thread, thread->GetDomain(), context);
+        //}
+
+        //if (context->Dr2 != NULL && DebuggerDataBreakpoint::g_DataBreakpointCount == 2)
+        //{
+        //    DebuggerDataBreakpoint::CreateDebuggerDataBreakpoint(thread, thread->GetDomain(), context);
+        //}
+
+        //if (context->Dr3 != NULL && DebuggerDataBreakpoint::g_DataBreakpointCount == 3)
+        //{
+        //    DebuggerDataBreakpoint::CreateDebuggerDataBreakpoint(thread, thread->GetDomain(), context);
+        //}
 
         if (!atSafePlace)
             g_pDebugger->DecThreadsAtUnsafePlaces();
index fc21cd4d542b8cf664f1ac10b8fdbc0ae0f79c76..e2680f125e7f0b34c278ab96e9ce18e2ad9b3c2e 100644 (file)
@@ -1774,19 +1774,9 @@ private:
 class DebuggerDataBreakpoint : public DebuggerController
 {
 public:
-    static void CreateDebuggerDataBreakpoint(Thread* pThread, AppDomain* pAppDomain, CONTEXT* context)
+    DebuggerDataBreakpoint() : DebuggerController(NULL, NULL)
     {
-        _ASSERTE(g_DataBreakpointCount < 5);
-
-        DebuggerDataBreakpoint* newDataBp = new DebuggerDataBreakpoint(g_DataBreakpointCount, pThread, pAppDomain, context);
-        g_DataBreakpoints[g_DataBreakpointCount++] = newDataBp;
-    }
-
-    DebuggerDataBreakpoint(unsigned int index, Thread* pThread, AppDomain* pAppDomain, CONTEXT* context) : DebuggerController(pThread, pAppDomain)
-    {
-        LOG((LF_CORDB, LL_INFO10000, "D::DDBP: New Data Breakpoint set for 0x%x\n", context->Dr0));
-        memcpy(&m_Context, context, sizeof(CONTEXT));
-        m_Index = index;
+        LOG((LF_CORDB, LL_INFO10000, "D:DDBP: Data Breakpoint event created\n"));
     }
     
     virtual DEBUGGER_CONTROLLER_TYPE GetDCType(void)
@@ -1827,47 +1817,10 @@ public:
         bool hitDataBp = false;
 
         PDR6 pdr6 = (PDR6)&(pContext->Dr6);
-        PDR7 pdr7 = (PDR7)&(pContext->Dr7);
-        
-        if (m_Index == 0)
-        {
-            if (pdr6->B0)
-            {
-                if (pContext->Dr0 == m_Context.Dr0 && pdr7->L0 != 0)
-                {
-                    hitDataBp = true;
-                }
-            }
-        }
-        else if (m_Index == 1)
-        {
-            if (pdr6->B1)
-            {
-                if (pContext->Dr1 == m_Context.Dr1 && pdr7->L1 != 0)
-                {
-                    hitDataBp = true;
-                }
-            }
-        }
-        else if (m_Index == 2)
-        {
-            if (pdr6->B2)
-            {
-                if (pContext->Dr2 == m_Context.Dr2 && pdr7->L2 != 0)
-                {
-                    hitDataBp = true;
-                }
-            }
-        }
-        else if (m_Index == 3)
+
+        if (pdr6->B0 || pdr6->B1 || pdr6->B2 || pdr6->B3)
         {
-            if (pdr6->B3)
-            {
-                if (pContext->Dr3 == m_Context.Dr3 && pdr7->L3 != 0)
-                {
-                    hitDataBp = true;
-                }
-            }
+            hitDataBp = true;
         }
 
         if (hitDataBp)
@@ -1882,16 +1835,7 @@ public:
         return hitDataBp;
     }
 
-    unsigned int GetIndex()
-    {
-        return m_Index;
-    }
-
-    static DebuggerDataBreakpoint* g_DataBreakpoints[4];
-    static unsigned int g_DataBreakpointCount;
-private:
-    CONTEXT m_Context;
-    unsigned int m_Index;
+    static DebuggerDataBreakpoint g_DebuggerDataBreakpoint;
 };
 
 
index f168819419f229580be4dc57db1bfdf79a353444..7cd88dedbdf7341237898a8f4ed36bbf07c5d088 100644 (file)
@@ -6103,7 +6103,7 @@ void Debugger::SendDataBreakpoint(Thread *thread, CONTEXT *context,
         DB_IPCE_DATA_BREAKPOINT,
         thread,
         thread->GetDomain());
-    ipce->DataBreakpointData.index = breakpoint->GetIndex();
+    //ipce->DataBreakpointData.index = breakpoint->GetIndex();
     _ASSERTE(breakpoint->m_pAppDomain == ipce->vmAppDomain.GetRawPtr());
 
     m_pRCThread->SendIPCEvent();
index 7f13bf680c92722796b66e84e0fa36f9b6f147d8..61fe60d458543a98f4a237d79a7c58f1a3d23903 100644 (file)
@@ -1359,8 +1359,9 @@ interface ICorDebugManagedCallback3 : IUnknown
 
 interface ICorDebugManagedCallback4 : IUnknown
 {
-    HRESULT BeforeGarbageCollection(ICorDebugProcess* pProcess);
-    HRESULT AfterGarbageCollection(ICorDebugProcess* pProcess);
+    HRESULT BeforeGarbageCollection([in] ICorDebugProcess* pProcess);
+    HRESULT AfterGarbageCollection([in] ICorDebugProcess* pProcess);
+    HRESULT DataBreakpoint([in] ICorDebugProcess* pProcess);
 }
 
 
index 15e25c899f6e6ea9acc011157eca38fa590c2ed8..e30649cdda3299b2c3e903e7d4f6595e3879c42f 100644 (file)
@@ -8,7 +8,7 @@
  /* File created by MIDL compiler version 8.01.0622 */
 /* at Mon Jan 18 19:14:07 2038
  */
-/* Compiler settings for F:/Dev/coreclr/src/inc/cordebug.idl:
+/* Compiler settings for D:/dotnet/coreclr/src/inc/cordebug.idl:
     Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.01.0622 
     protocol : dce , ms_ext, c_ext, robust
     error checks: allocation ref bounds_check enum stub_data 
index c8ad1616b01e2937e049f4da4f4c98ba51e8fdc2..4ed5bde38506145b0a632320059ab2d150f75f29 100644 (file)
@@ -6,7 +6,7 @@
  /* File created by MIDL compiler version 8.01.0622 */
 /* at Mon Jan 18 19:14:07 2038
  */
-/* Compiler settings for F:/Dev/coreclr/src/inc/cordebug.idl:
+/* Compiler settings for D:/dotnet/coreclr/src/inc/cordebug.idl:
     Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.01.0622 
     protocol : dce , ms_ext, c_ext, robust
     error checks: allocation ref bounds_check enum stub_data 
@@ -3781,10 +3781,13 @@ EXTERN_C const IID IID_ICorDebugManagedCallback4;
     {
     public:
         virtual HRESULT STDMETHODCALLTYPE BeforeGarbageCollection( 
-            ICorDebugProcess *pProcess) = 0;
+            /* [in] */ ICorDebugProcess *pProcess) = 0;
         
         virtual HRESULT STDMETHODCALLTYPE AfterGarbageCollection( 
-            ICorDebugProcess *pProcess) = 0;
+            /* [in] */ ICorDebugProcess *pProcess) = 0;
+        
+        virtual HRESULT STDMETHODCALLTYPE DataBreakpoint( 
+            /* [in] */ ICorDebugProcess *pProcess) = 0;
         
     };
     
@@ -3809,11 +3812,15 @@ EXTERN_C const IID IID_ICorDebugManagedCallback4;
         
         HRESULT ( STDMETHODCALLTYPE *BeforeGarbageCollection )( 
             ICorDebugManagedCallback4 * This,
-            ICorDebugProcess *pProcess);
+            /* [in] */ ICorDebugProcess *pProcess);
         
         HRESULT ( STDMETHODCALLTYPE *AfterGarbageCollection )( 
             ICorDebugManagedCallback4 * This,
-            ICorDebugProcess *pProcess);
+            /* [in] */ ICorDebugProcess *pProcess);
+        
+        HRESULT ( STDMETHODCALLTYPE *DataBreakpoint )( 
+            ICorDebugManagedCallback4 * This,
+            /* [in] */ ICorDebugProcess *pProcess);
         
         END_INTERFACE
     } ICorDebugManagedCallback4Vtbl;
@@ -3844,6 +3851,9 @@ EXTERN_C const IID IID_ICorDebugManagedCallback4;
 #define ICorDebugManagedCallback4_AfterGarbageCollection(This,pProcess)        \
     ( (This)->lpVtbl -> AfterGarbageCollection(This,pProcess) ) 
 
+#define ICorDebugManagedCallback4_DataBreakpoint(This,pProcess)        \
+    ( (This)->lpVtbl -> DataBreakpoint(This,pProcess) ) 
+
 #endif /* COBJMACROS */