The GC events are now working, somewhat ...
authorAndrew Au <andrewau@microsoft.com>
Thu, 10 May 2018 21:49:39 +0000 (14:49 -0700)
committerAndrew Au <cshung@gmail.com>
Wed, 7 Nov 2018 02:34:47 +0000 (18:34 -0800)
Commit migrated from https://github.com/dotnet/coreclr/commit/c6d26187c8ce8fc68829f262a79996f00b1e1a85

12 files changed:
src/coreclr/src/debug/di/process.cpp
src/coreclr/src/debug/di/rsmain.cpp
src/coreclr/src/debug/di/shimcallback.cpp
src/coreclr/src/debug/di/shimpriv.h
src/coreclr/src/debug/ee/debugger.cpp
src/coreclr/src/debug/ee/debugger.h
src/coreclr/src/debug/inc/dbgipceventtypes.h
src/coreclr/src/inc/cordebug.idl
src/coreclr/src/pal/prebuilt/idl/cordebug_i.cpp
src/coreclr/src/pal/prebuilt/inc/cordebug.h
src/coreclr/src/vm/dbginterface.h
src/coreclr/src/vm/gcenv.ee.cpp

index a49addc..18e0ac7 100644 (file)
@@ -3,7 +3,7 @@
 // See the LICENSE file in the project root for more information.
 //*****************************************************************************
 // File: process.cpp
-// 
+//
 
 //
 //*****************************************************************************
@@ -11,7 +11,7 @@
 #include "primitives.h"
 #include "safewrap.h"
 
-#include "check.h" 
+#include "check.h"
 
 #ifndef SM_REMOTESESSION
 #define SM_REMOTESESSION 0x1000
@@ -34,7 +34,7 @@
 // Keep this around for retail debugging. It's very very useful because
 // it's global state that we can always find, regardless of how many locals the compiler
 // optimizes away ;)
-struct RSDebuggingInfo; 
+struct RSDebuggingInfo;
 extern RSDebuggingInfo * g_pRSDebuggingInfo;
 
 //---------------------------------------------------------------------------------------
@@ -56,20 +56,20 @@ extern RSDebuggingInfo * g_pRSDebuggingInfo;
 // Assumptions:
 //
 // Notes:
-//    The outgoing process object can be cleaned up by calling Detach (which 
-//    will reset the Attach bit.) 
+//    The outgoing process object can be cleaned up by calling Detach (which
+//    will reset the Attach bit.)
 //    @dbgtodo attach-bit: need to determine fate of attach bit.
 //
 //---------------------------------------------------------------------------------------
 STDAPI OpenVirtualProcessImpl(
-    ULONG64 clrInstanceId, 
+    ULONG64 clrInstanceId,
     IUnknown * pDataTarget,
     HMODULE hDacModule,
     CLR_DEBUGGING_VERSION * pMaxDebuggerSupportedVersion,
     REFIID riid,
     IUnknown ** ppInstance,
     CLR_DEBUGGING_PROCESS_FLAGS* pFlagsOut)
-{    
+{
     HRESULT hr = S_OK;
     RSExtSmartPtr<CordbProcess> pProcess;
     PUBLIC_API_ENTRY(NULL);
@@ -95,7 +95,7 @@ STDAPI OpenVirtualProcessImpl(
         }
 
         // This process object is intended to be used for the V3 pipeline, and so
-        // much of the process from V2 is not being used. For example, 
+        // much of the process from V2 is not being used. For example,
         // - there is no ShimProcess object
         // - there is no w32et thread (all threads are effectively an event thread)
         // - the stop state is 'live', which corresponds to CordbProcess not knowing what
@@ -104,8 +104,8 @@ STDAPI OpenVirtualProcessImpl(
             clrInstanceId,
             pDataTarget,  // takes a reference
             hDacModule,
-            NULL, // Cordb        
-            (DWORD) 0, // 0 for V3 cases (pShim == NULL). 
+            NULL, // Cordb
+            (DWORD) 0, // 0 for V3 cases (pShim == NULL).
             NULL, // no Shim in V3 cases
             &pProcess));
 
@@ -123,7 +123,7 @@ STDAPI OpenVirtualProcessImpl(
             }
         }
 
-        // 
+        //
         // Check to make sure the debugger supports debugging this version
         // Note that it's important that we still store the flags (above) in this case
         //
@@ -191,17 +191,17 @@ STDAPI OpenVirtualProcessImpl2(
 //---------------------------------------------------------------------------------------
 // DEPRECATED - use OpenVirtualProcessImpl
 // OpenVirtualProcess method used by the shim in CLR v4 Beta1
-// We'd like a beta1 shim/VS to still be able to open dumps using a CLR v4 Beta2+ mscordbi.dll, 
+// We'd like a beta1 shim/VS to still be able to open dumps using a CLR v4 Beta2+ mscordbi.dll,
 // so we'll leave this in place (at least until after Beta2 is in wide use).
 //---------------------------------------------------------------------------------------
 STDAPI OpenVirtualProcess2(
-    ULONG64 clrInstanceId, 
+    ULONG64 clrInstanceId,
     IUnknown * pDataTarget,
     HMODULE hDacModule,
     REFIID riid,
     IUnknown ** ppInstance,
     CLR_DEBUGGING_PROCESS_FLAGS* pFlagsOut)
-{    
+{
     CLR_DEBUGGING_VERSION maxVersion = {0};
     maxVersion.wMajor = 4;
     return OpenVirtualProcessImpl(clrInstanceId, pDataTarget, hDacModule, &maxVersion, riid, ppInstance, pFlagsOut);
@@ -213,11 +213,11 @@ STDAPI OpenVirtualProcess2(
 // Used directly in CLR v4 pre Beta1 - can probably be safely removed now
 //---------------------------------------------------------------------------------------
 STDAPI OpenVirtualProcess(
-    ULONG64 clrInstanceId, 
+    ULONG64 clrInstanceId,
     IUnknown * pDataTarget,
     REFIID riid,
     IUnknown ** ppInstance)
-{    
+{
     return OpenVirtualProcess2(clrInstanceId, pDataTarget, NULL, riid, ppInstance, NULL);
 };
 
@@ -329,7 +329,7 @@ IMDInternalImport * CordbProcess::LookupMetaData(VMPTR_PEFile vmPEFile, bool &is
 
     // There may be perf issues here. The DAC may make a lot of metadata requests, and so
     // this may be an area for potential perf optimizations if we find things running slow.
-    
+
     // enumerate through all Modules
     for (CordbAppDomain * pAppDomain = m_appDomains.FindFirst(&hashFindAppDomain);
          pAppDomain != NULL;
@@ -530,12 +530,12 @@ IMDInternalImport * CordbProcess::LookupMetaDataFromDebuggerForSingleFile(
 //
 // Notes:
 //    Since this function is a callback from DAC, it must not take the process lock.
-//    If it does, we may deadlock between the DD lock and the process lock.  
+//    If it does, we may deadlock between the DD lock and the process lock.
 //    If we really need to take the process lock for whatever reason, we must take it in the DBI functions
 //    which call the DAC API that ends up calling this function.
 //    See code:InternalDacCallbackHolder for more information.
 //
+
 void * CordbProcess::Alloc(SIZE_T lenBytes)
 {
     return new BYTE[lenBytes]; // throws
@@ -550,15 +550,15 @@ void * CordbProcess::Alloc(SIZE_T lenBytes)
 //
 // Notes:
 //    Since this function is a callback from DAC, it must not take the process lock.
-//    If it does, we may deadlock between the DD lock and the process lock.  
+//    If it does, we may deadlock between the DD lock and the process lock.
 //    If we really need to take the process lock for whatever reason, we must take it in the DBI functions
 //    which call the DAC API that ends up calling this function.
 //    See code:InternalDacCallbackHolder for more information.
 //
+
 void CordbProcess::Free(void * p)
 {
-    // This shouldn't throw. 
+    // This shouldn't throw.
     delete [] ((BYTE *) p);
 }
 
@@ -566,38 +566,38 @@ void CordbProcess::Free(void * p)
 //---------------------------------------------------------------------------------------
 //
 // #DBIVersionChecking
-// 
+//
 // There are a few checks we need to do to make sure we are using the matching DBI and DAC for a particular
 // version of the runtime.
-// 
+//
 // 1. Runtime vs. DBI
 //     - Desktop
 //         This is done by making sure that the CorDebugInterfaceVersion passed to code:CreateCordbObject is
 //         compatible with the version of the DBI.
-//         
+//
 //     - Windows CoreCLR
 //         This is done by dbgshim.dll.  It checks whether the runtime DLL and the DBI DLL have the same
 //         product version.  See CreateDebuggingInterfaceForVersion() in dbgshim.cpp.
-//         
+//
 //     - Remote transport (Mac CoreCLR + CoreSystem CoreCLR)
 //         Since there is no dbgshim.dll for a remote CoreCLR, we have to do this check in some other place.
-//         We do this in code:CordbProcess::CreateDacDbiInterface, by calling 
-//         code:DacDbiInterfaceImpl::CheckDbiVersion right after we have created the DDMarshal.  
+//         We do this in code:CordbProcess::CreateDacDbiInterface, by calling
+//         code:DacDbiInterfaceImpl::CheckDbiVersion right after we have created the DDMarshal.
 //         The IDacDbiInterface implementation on remote device checks the product version of the device
 //         coreclr by:
 //             mac - looking at the Info.plist file in the CoreCLR bundle.
 //             CoreSystem - this check is skipped at the moment, but should be implemented if we release it
-//         
+//
 //         The one twist here is that the DBI needs to communicate with the IDacDbiInterface
 //         implementation on the device BEFORE it can verify the product versions.  This means that we need to
-//         have one IDacDbiInterface API which is consistent across all versions of the IDacDbiInterface.  
+//         have one IDacDbiInterface API which is consistent across all versions of the IDacDbiInterface.
 //         This puts two constraints on CheckDbiVersion():
-//         
+//
 //             1.  It has to be the first API on the IDacDbiInterface.
-//             - Otherwise, a wrong version of the DBI may end up calling a different API on the 
+//             - Otherwise, a wrong version of the DBI may end up calling a different API on the
 //               IDacDbiInterface and getting random results. (Really what matters is that it is
 //               protocol message id 0, at present the source code position implies the message id)
-//               
+//
 //             2.  Its parameters cannot change.
 //             - Otherwise, we may run into random errors when we marshal/unmarshal the arguments for the
 //               call to CheckDbiVersion().  Debugging will still fail, but we won't get the
@@ -624,7 +624,7 @@ void CordbProcess::Free(void * p)
 //
 //      - Remote transport (Mac CoreCLR and CoreSystem CoreCLR)
 //          Because the transport exists between DBI and DAC it becomes much more important to do a versioning check
-//         
+//
 //          Mac - currently does a tightly bound version check between DBI and the runtime (CheckDbiVersion() above),
 //             which transitively gives a tightly bound check to DAC. In same function there is also a check that is
 //             logically a DAC DBI protocol check, verifying that the m_dwProtocolBreakingChangeCounter of DbiVersion
@@ -645,20 +645,20 @@ void CordbProcess::Free(void * p)
 //                case would be changing the DDMarshal proxy generation code. In addition to the hashes we also
 //                embed timestamps when the auto-generated code was produced. However this isn't used for version
 //                matching, only as a hint to indicate which of two mismatched versions is newer.
-//                
-//         
+//
+//
 // 3. Runtime vs. DAC
 //     - Desktop, Windows CoreCLR, CoreSystem CoreCLR
 //         In both cases we check this by matching the timestamp in the debug directory of the runtime image
-//         and the timestamp we store in the DAC table when we generate the DAC dll.  This is done in 
+//         and the timestamp we store in the DAC table when we generate the DAC dll.  This is done in
 //         code:ClrDataAccess::VerifyDlls.
-//         
+//
 //     - Mac CoreCLR
-//         On Mac, we don't have a timestamp in the runtime image.  Instead, we rely on checking the 16-byte 
-//         UUID in the image.  This UUID is used to check whether a symbol file matches the image, so 
-//         conceptually it's the same as the timestamp we use on Windows.  This is also done in 
+//         On Mac, we don't have a timestamp in the runtime image.  Instead, we rely on checking the 16-byte
+//         UUID in the image.  This UUID is used to check whether a symbol file matches the image, so
+//         conceptually it's the same as the timestamp we use on Windows.  This is also done in
 //         code:ClrDataAccess::VerifyDlls.
-// 
+//
 //---------------------------------------------------------------------------------------
 //
 // Instantiates a DacDbi Interface object in a live-debugging scenario that matches
@@ -681,7 +681,7 @@ CordbProcess::CreateDacDbiInterface()
 {
     _ASSERTE(m_pDACDataTarget != NULL);
     _ASSERTE(m_pDacPrimitives == NULL); // don't double-init
-    
+
     // Caller has already determined which CLR in the target is being debugged.
     _ASSERTE(m_clrInstanceId != 0);
 
@@ -699,7 +699,7 @@ CordbProcess::CreateDacDbiInterface()
     }
 
     //
-    // Get the access interface, passing our callback interfaces (data target, allocator and metadata lookup) 
+    // Get the access interface, passing our callback interfaces (data target, allocator and metadata lookup)
     //
 
     IDacDbiInterface::IAllocator * pAllocator = this;
@@ -707,10 +707,10 @@ CordbProcess::CreateDacDbiInterface()
 
 
     typedef HRESULT (STDAPICALLTYPE * PFN_DacDbiInterfaceInstance)(
-        ICorDebugDataTarget *, 
+        ICorDebugDataTarget *,
         CORDB_ADDRESS,
-        IDacDbiInterface::IAllocator *, 
-        IDacDbiInterface::IMetaDataLookup *, 
+        IDacDbiInterface::IAllocator *,
+        IDacDbiInterface::IMetaDataLookup *,
         IDacDbiInterface **);
 
     IDacDbiInterface* pInterfacePtr = NULL;
@@ -724,7 +724,7 @@ CordbProcess::CreateDacDbiInterface()
     IfFailThrow(hrStatus);
 
     // We now have a resource, pInterfacePtr, that needs to be freed.
-    m_pDacPrimitives = pInterfacePtr;   
+    m_pDacPrimitives = pInterfacePtr;
 
     // Setup DAC target consistency checking based on what we're using for DBI
     m_pDacPrimitives->DacSetTargetConsistencyChecks( m_fAssertOnTargetInconsistency );
@@ -732,7 +732,7 @@ CordbProcess::CreateDacDbiInterface()
 
 //---------------------------------------------------------------------------------------
 //
-// Is the DAC/DBI interface initialized? 
+// Is the DAC/DBI interface initialized?
 //
 // Return Value:
 //    TRUE iff init.
@@ -749,14 +749,14 @@ BOOL CordbProcess::IsDacInitialized()
 
 //---------------------------------------------------------------------------------------
 //
-// Get the DAC interface. 
+// Get the DAC interface.
 //
 // Return Value:
 //    the Dac/Dbi interface pointer to the process.
 //    Never returns NULL.
 //
 // Assumptions:
-//    Caller is responsible for ensuring Data-Target is safe to access (eg, not 
+//    Caller is responsible for ensuring Data-Target is safe to access (eg, not
 //    currently running).
 //    Caller is responsible for ensuring DAC-cache is flushed. Call code:CordbProcess::ForceDacFlush
 //    as needed.
@@ -778,7 +778,7 @@ IDacDbiInterface * CordbProcess::GetDAC()
 
 //---------------------------------------------------------------------------------------
 // Get the Data-Target
-// 
+//
 // Returns:
 //     pointer to the data-target. Should be non-null.
 //     Lifetime of the pointer is until this process object is neutered.
@@ -793,9 +793,9 @@ ICorDebugDataTarget * CordbProcess::GetDataTarget()
 //
 // Arguments:
 //     pDataTarget - abstracts access to the debuggee.
-//     clrInstanceId - identifies the CLR instance within the debuggee. (This is the 
+//     clrInstanceId - identifies the CLR instance within the debuggee. (This is the
 //         base address of mscorwks)
-//     pCordb - Pointer to the implementation of the owning Cordb object implementing the 
+//     pCordb - Pointer to the implementation of the owning Cordb object implementing the
 //         owning ICD interface.
 //         This should go away - we can get the functionality from the pShim.
 //         If this is null, then pShim must be null too.
@@ -814,13 +814,13 @@ ICorDebugDataTarget * CordbProcess::GetDataTarget()
 //
 //---------------------------------------------------------------------------------------
 
-// static 
+// static
 HRESULT CordbProcess::OpenVirtualProcess(
-    ULONG64 clrInstanceId, 
+    ULONG64 clrInstanceId,
     IUnknown * pDataTarget,
     HMODULE hDacModule,
-    Cordb* pCordb,     
-    DWORD dwProcessID, 
+    Cordb* pCordb,
+    DWORD dwProcessID,
     ShimProcess * pShim,
     CordbProcess ** ppProcess)
 {
@@ -863,9 +863,9 @@ HRESULT CordbProcess::OpenVirtualProcess(
     // This will bump reference count.
     if (pShim != NULL)
     {
-        pShim->SetProcess(pProcess);    
+        pShim->SetProcess(pProcess);
 
-        _ASSERTE(pShim->GetProcess() == pThis);        
+        _ASSERTE(pShim->GetProcess() == pThis);
         _ASSERTE(pShim->GetWin32EventThread() != NULL);
     }
 
@@ -889,7 +889,7 @@ HRESULT CordbProcess::OpenVirtualProcess(
 
         // In failure case, pProcess's dtor will do the final release.
     }
-    
+
 
     return hr;
 }
@@ -898,16 +898,16 @@ HRESULT CordbProcess::OpenVirtualProcess(
 // CordbProcess constructor
 //
 // Arguments:
-//     pDataTarget - Pointer to an implementation of ICorDebugDataTarget 
+//     pDataTarget - Pointer to an implementation of ICorDebugDataTarget
 //         (or ICorDebugMutableDataTarget), which virtualizes access to the process.
 //     clrInstanceId - representation of the CLR to debug in the process.  Must be specified
 //         (non-zero) if pShim is NULL.  If 0, use the first CLR that we see.
-//     pCordb - Pointer to the implementation of the owning Cordb object implementing the 
+//     pCordb - Pointer to the implementation of the owning Cordb object implementing the
 //         owning ICD interface.
 //     pW32 - Pointer to the Win32 event thread to use when processing events for this
 //         process.
-//     dwProcessID - For V3, 0. 
-//         Else for shim codepaths, the processID of the process this object will represent. 
+//     dwProcessID - For V3, 0.
+//         Else for shim codepaths, the processID of the process this object will represent.
 //     pShim - Pointer to the shim for handling V2 debuggers on the V3 architecture.
 //
 //---------------------------------------------------------------------------------------
@@ -920,13 +920,13 @@ CordbProcess::CordbProcess(ULONG64 clrInstanceId,
                            ShimProcess * pShim)
   : CordbBase(NULL, dwProcessID, enumCordbProcess),
     m_fDoDelayedManagedAttached(false),
-    m_cordb(pCordb), 
-    m_handle(NULL),    
-    m_detached(false), 
+    m_cordb(pCordb),
+    m_handle(NULL),
+    m_detached(false),
     m_uninitializedStop(false),
     m_exiting(false),
     m_terminated(false),
-    m_unrecoverableError(false), 
+    m_unrecoverableError(false),
     m_specialDeferment(false),
     m_helperThreadDead(false),
     m_loaderBPReceived(false),
@@ -939,7 +939,7 @@ CordbProcess::CordbProcess(ULONG64 clrInstanceId,
     m_pShim(pShim),
     m_userThreads(11),
     m_dataBreakpoints(4),
-    m_oddSync(false), 
+    m_oddSync(false),
 #ifdef FEATURE_INTEROP_DEBUGGING
     m_unmanagedThreads(11),
 #endif
@@ -951,7 +951,7 @@ CordbProcess::CordbProcess(ULONG64 clrInstanceId,
     m_leftSideEventAvailable(NULL),
     m_leftSideEventRead(NULL),
 #if defined(FEATURE_INTEROP_DEBUGGING)
-    m_leftSideUnmanagedWaitEvent(NULL),    
+    m_leftSideUnmanagedWaitEvent(NULL),
 #endif // FEATURE_INTEROP_DEBUGGING
     m_initialized(false),
     m_stopRequested(false),
@@ -965,7 +965,7 @@ CordbProcess::CordbProcess(ULONG64 clrInstanceId,
     m_lastDispatchedIBEvent(NULL),
     m_dispatchingUnmanagedEvent(false),
     m_dispatchingOOBEvent(false),
-    m_doRealContinueAfterOOBBlock(false),   
+    m_doRealContinueAfterOOBBlock(false),
     m_state(0),
 #endif // FEATURE_INTEROP_DEBUGGING
     m_helperThreadId(0),
@@ -1007,8 +1007,8 @@ CordbProcess::CordbProcess(ULONG64 clrInstanceId,
     m_pProcess.Assign(this);
 
 #ifdef _DEBUG
-    // On Debug builds, we'll ASSERT by default whenever the target appears to be corrupt or 
-    // otherwise inconsistent (both in DAC and DBI).  But we also need the ability to 
+    // On Debug builds, we'll ASSERT by default whenever the target appears to be corrupt or
+    // otherwise inconsistent (both in DAC and DBI).  But we also need the ability to
     // explicitly test corrupt targets.
     // Tests should set COMPlus_DbgIgnoreInconsistentTarget=1 to suppress these asserts
     // Note that this controls two things:
@@ -1077,19 +1077,19 @@ CordbProcess::~CordbProcess()
 
     // We shouldn't still be in Cordb's list of processes. Unfortunately, our root Cordb object
     // may have already been deleted b/c we're at the mercy of ref-counting, so we can't check.
-    
+
        _ASSERTE(m_sharedAppDomain == NULL);
-        
+
     m_processMutex.Destroy();
     m_StopGoLock.Destroy();
 
     // These handles were cleared in neuter
-    _ASSERTE(m_handle == NULL); 
+    _ASSERTE(m_handle == NULL);
 #if defined(FEATURE_INTEROP_DEBUGGING)
     _ASSERTE(m_leftSideUnmanagedWaitEvent == NULL);
 #endif // FEATURE_INTEROP_DEBUGGING
     _ASSERTE(m_stopWaitEvent == NULL);
-    
+
     // Set this to mark that we really did cleanup.
 }
 
@@ -1100,7 +1100,7 @@ CordbProcess::~CordbProcess()
 // the Cordb object.
 //
 // Arguments:
-//     pCordb - Pointer to the implementation of the owning Cordb object implementing the 
+//     pCordb - Pointer to the implementation of the owning Cordb object implementing the
 //         owning ICD interface.
 //     szProgramName - Name of the program to execute.
 //     szProgramArgs - Command line arguments for the process.
@@ -1151,7 +1151,7 @@ HRESULT ShimProcess::CreateProcess(
         hr = pShim->CreateAndStartWin32ET(pCordb);
         IfFailThrow(hr);
 
-        // Call out to newly created Win32-event Thread to create the process. 
+        // Call out to newly created Win32-event Thread to create the process.
         // If this succeeds, new CordbProcess will add a ref to the ShimProcess
         hr = pShim->GetWin32EventThread()->SendCreateProcessEvent(pShim->GetMachineInfo(),
                                                                   szProgramName,
@@ -1211,7 +1211,7 @@ HRESULT ShimProcess::DebugActiveProcess(
 
         // Indicate that this process was attached to, asopposed to being started under the debugger.
         pShim->m_attached = true;
-       
+
         hr = pShim->CreateAndStartWin32ET(pCordb);
         IfFailThrow(hr);
 
@@ -1232,7 +1232,7 @@ HRESULT ShimProcess::DebugActiveProcess(
         // after DebugActiveProcess completes which means we must wait here long enough to have set the debuggee
         // bit indicating managed attach is coming.
         // However in interop debugging we can't do that because there are debug events which come before the
-        // loader breakpoint (which is how far we need to get to set the debuggee bit). If we blocked 
+        // loader breakpoint (which is how far we need to get to set the debuggee bit). If we blocked
         // DebugActiveProcess there then the debug events would be refering to an ICorDebugProcess that hasn't
         // yet been returned to the caller of DebugActiveProcess. Instead, for interop debugging we force the
         // native debugger to wait until it gets the loader breakpoint to set the event. Note we can't converge
@@ -1259,7 +1259,7 @@ HRESULT ShimProcess::DebugActiveProcess(
 #endif //!FEATURE_DBGIPC_TRANSPORT_DI
     }
     EX_CATCH_HRESULT(hr);
-    
+
     // If this succeeds, then process takes ownership of thread. Else we need to kill it.
     if (FAILED(hr))
     {
@@ -1268,7 +1268,7 @@ HRESULT ShimProcess::DebugActiveProcess(
             pShim->Dispose();
         }
     }
-    
+
     // Always release our ref to ShimProcess. If the Process was created, then it takes a reference.
 
     return hr;
@@ -1285,29 +1285,29 @@ HRESULT ShimProcess::DebugActiveProcess(
 //   code:CordbProcess::IsReadyForDetach)
 //   3. Caller did code:CordbProcess::NeuterLeftSideResources first
 //   to clean up left-side resources.
-//   
+//
 // Notes:
 //   This could be called multiple times (code:CordbProcess::FlushAll), so
 //   be sure to null out any potential dangling pointers. State may be rebuilt
 //   up after each time.
 void CordbProcess::NeuterChildren()
-{   
+{
     _ASSERTE(GetProcessLock()->HasLock());
-    
+
     // Frees left-side resources. See assumptions above.
     m_LeftSideResourceCleanupList.NeuterAndClear(this);
 
 
-    m_EvalTable.Clear();    
-    
+    m_EvalTable.Clear();
+
 
-    // Sweep neuter lists.    
+    // Sweep neuter lists.
     m_ExitNeuterList.NeuterAndClear(this);
     m_ContinueNeuterList.NeuterAndClear(this);
     m_dataBreakpoints.NeuterAndClear(GetProcessLock());
 
     m_userThreads.NeuterAndClear(GetProcessLock());
-    
+
     m_pDefaultAppDomain = NULL;
 
     // Frees per-appdomain left-side resources. See assumptions above.
@@ -1349,10 +1349,10 @@ void CordbProcess::Neuter()
     // Take the process lock.
     RSLockHolder lockHolder(GetProcessLock());
 
-    
+
     NeuterChildren();
 
-    // Release the metadata interfaces    
+    // Release the metadata interfaces
     m_pMetaDispenser.Clear();
 
 
@@ -1379,7 +1379,7 @@ void CordbProcess::Neuter()
             // W23ET.
             if (m_pShim != NULL)
             {
-                m_pShim->Dispose();            
+                m_pShim->Dispose();
                 m_pShim.Clear();
             }
         }
@@ -1398,24 +1398,24 @@ void CordbProcess::Neuter()
         m_pEventChannel->Delete();
         m_pEventChannel = NULL;
     }
-    
-    // Need process lock to clear the patch table    
+
+    // Need process lock to clear the patch table
     ClearPatchTable();
-    
+
     CordbProcess::CloseIPCHandles();
 
     CordbBase::Neuter();
-        
+
     m_cordb.Clear();
 
     // Need to release this reference to ourselves. Other leaf objects may still hold
     // strong references back to this CordbProcess object.
     _ASSERTE(m_pProcess == this);
-    m_pProcess.Clear();    
+    m_pProcess.Clear();
 }
 
 // Wrapper to return metadata dispenser.
-// 
+//
 // Notes:
 //    Does not adjust reference count of dispenser.
 //    Dispenser is destroyed in code:CordbProcess::Neuter
@@ -1484,7 +1484,7 @@ void CordbProcess::CloseIPCHandles()
 //     S_OK on success.
 //-----------------------------------------------------------------------------
 HRESULT ShimProcess::CreateAndStartWin32ET(Cordb * pCordb)
-{   
+{
 
     //
     // Create the win32 event listening thread
@@ -1524,13 +1524,13 @@ HRESULT ShimProcess::CreateAndStartWin32ET(Cordb * pCordb)
 //
 // Return Value:
 //    TRUE  - DAC is initialized.
-//    FALSE  - Not initialized, but can try again later. Common case if 
+//    FALSE  - Not initialized, but can try again later. Common case if
 //          target has not yet loaded the runtime.
 //    Throws exception - fatal.
 //
 // Assumptions:
 //    Target is stopped by OS, so we can safely inspect it without it moving on us.
-// 
+//
 // Notes:
 //    This can be called eagerly to sniff if the LS is initialized.
 //
@@ -1545,9 +1545,9 @@ BOOL CordbProcess::TryInitializeDac()
 
     // Target is stopped by OS, so we can safely inspect it without it moving on us.
 
-    // We want to avoid exceptions in the normal case, so we do some pre-checks 
+    // We want to avoid exceptions in the normal case, so we do some pre-checks
     // to detect failure without relying on exceptions.
-    // Can't initialize DAC until mscorwks is loaded. So that's a sanity test.    
+    // Can't initialize DAC until mscorwks is loaded. So that's a sanity test.
     HRESULT hr = EnsureClrInstanceIdSet();
     if (FAILED(hr))
     {
@@ -1568,7 +1568,7 @@ BOOL CordbProcess::TryInitializeDac()
 // Load & Init DAC, expecting to succeed.
 //
 // Return Value:
-//    Throws on failure. 
+//    Throws on failure.
 //
 // Assumptions:
 //    Caller invokes this at a point where they can expect it to succeed.
@@ -1578,7 +1578,7 @@ BOOL CordbProcess::TryInitializeDac()
 // Notes:
 //    This needs to succeed, and should always succeed (baring a bad installation)
 //    so we assert on failure paths.
-//    This may be called mutliple times. 
+//    This may be called mutliple times.
 //
 //---------------------------------------------------------------------------------------
 void CordbProcess::InitializeDac()
@@ -1601,8 +1601,8 @@ void CordbProcess::InitializeDac()
     {
         LOG((LF_CORDB, LL_INFO1000, "Dac already loaded, 0x%p\n", (HMODULE)m_hDacModule));
     }
-    
-    // Always flush dac.    
+
+    // Always flush dac.
     ForceDacFlush();
 }
 
@@ -1611,7 +1611,7 @@ void CordbProcess::InitializeDac()
 // Free DAC resources
 //
 // Notes:
-//    This should clean up state such that code:CordbProcess::InitializeDac could be called again. 
+//    This should clean up state such that code:CordbProcess::InitializeDac could be called again.
 //
 //---------------------------------------------------------------------------------------
 void CordbProcess::FreeDac()
@@ -1645,12 +1645,12 @@ IEventChannel * CordbProcess::GetEventChannel()
 // Mark that the process is being interop-debugged.
 //
 // Notes:
-//   @dbgtodo shim: this should eventually move into the shim or go away. 
+//   @dbgtodo shim: this should eventually move into the shim or go away.
 //   It's only to support V2 legacy interop-debugging.
 //   Called after code:CordbProcess::Init if we want to enable interop debugging.
 //   This allows us to separate out Interop-debugging flags from the core initialization,
 //   and paves the way for us to eventually remove it.
-//   
+//
 //   Since we're always on the naitve-pipeline, the Enabling interop debugging just changes
 //   how the native debug events are being handled. So this must be called after Init, but
 //   before any events are actually handled.
@@ -1672,7 +1672,7 @@ void CordbProcess::EnableInteropDebugging()
     m_state |= PS_WIN32_ATTACHED;
     if (GetDCB() != NULL)
     {
-        GetDCB()->m_rightSideIsWin32Debugger = true; 
+        GetDCB()->m_rightSideIsWin32Debugger = true;
         UpdateLeftSideDCBField(&(GetDCB()->m_rightSideIsWin32Debugger), sizeof(GetDCB()->m_rightSideIsWin32Debugger));
     }
 
@@ -1702,7 +1702,7 @@ void CordbProcess::EnableInteropDebugging()
 HRESULT CordbProcess::Init()
 {
     INTERNAL_API_ENTRY(this);
-    
+
     HRESULT hr = S_OK;
     BOOL fIsLSStarted = FALSE; // see meaning below.
 
@@ -1735,13 +1735,13 @@ HRESULT CordbProcess::Init()
 
         m_pMetaDataLocator.Clear();
         hr = m_pDACDataTarget->QueryInterface(IID_ICorDebugMetaDataLocator, reinterpret_cast<void **>(&m_pMetaDataLocator));
-        
-        // Get the metadata dispenser.        
+
+        // Get the metadata dispenser.
         hr = InternalCreateMetaDataDispenser(IID_IMetaDataDispenserEx, (void **)&m_pMetaDispenser);
 
-        // We statically link in the dispenser. We expect it to succeed, except for OOM, which 
+        // We statically link in the dispenser. We expect it to succeed, except for OOM, which
         // debugger doesn't yet handle.
-        SIMPLIFYING_ASSUMPTION_SUCCEEDED(hr); 
+        SIMPLIFYING_ASSUMPTION_SUCCEEDED(hr);
         IfFailThrow(hr);
 
         _ASSERTE(m_pMetaDispenser != NULL);
@@ -1764,9 +1764,9 @@ HRESULT CordbProcess::Init()
         // Managed debugging is built on the native-pipeline, and that will detect against double-attaches.
 
         // @dbgtodo shim: In V2, LSEA + LSER were used by the LS's helper thread. Now with the V3 pipeline,
-        // that helper-thread uses native-debug events. The W32ET gets those events and then uses LSEA, LSER to 
+        // that helper-thread uses native-debug events. The W32ET gets those events and then uses LSEA, LSER to
         // signal existing RS infrastructure. Eventually get rid of LSEA, LSER completely.
-        // 
+        //
 
         m_leftSideEventAvailable = WszCreateEvent(NULL, FALSE, FALSE, NULL);
         if (m_leftSideEventAvailable == NULL)
@@ -1813,11 +1813,11 @@ HRESULT CordbProcess::Init()
         // This means there's an overlap: if we catch it at phase 5, we'll just get
         // an extra Startup exception from phase 6, which is safe. This overlap is good
         // because it means there's no bad window to do an attach in.
-        
+
         // fIsLSStarted means before phase 6 (eg, RS should expect a startup exception)
 
         // Determines if the LS is started.
-        
+
         {
             BOOL fReady = TryInitializeDac();
 
@@ -1827,7 +1827,7 @@ HRESULT CordbProcess::Init()
                 _ASSERTE(m_pDacPrimitives != NULL);
                 fIsLSStarted = m_pDacPrimitives->IsLeftSideInitialized();
             }
-            else 
+            else
             {
                 _ASSERTE(m_pDacPrimitives == NULL);
 
@@ -1836,8 +1836,8 @@ HRESULT CordbProcess::Init()
                 _ASSERTE(!fIsLSStarted);
             }
         }
-        
-        
+
+
         if (fIsLSStarted)
         {
             // Left-side has started up. This is common for Attach cases when managed-code is already running.
@@ -1857,7 +1857,7 @@ HRESULT CordbProcess::Init()
             }
             else
             {
-                // In the V3 pipeline case, if we have the DD-interface, then the runtime is loaded 
+                // In the V3 pipeline case, if we have the DD-interface, then the runtime is loaded
                 // and we consider it initialized.
                 if (IsDacInitialized())
                 {
@@ -1937,11 +1937,11 @@ void CordbProcess::QueueManagedAttachIfNeeded()
 
 //---------------------------------------------------------------------------------------
 // Hook from Shim to request a managed attach IPC event
-// 
+//
 // Notes:
-//   Called by shim after the loader-breakpoint is handled. 
+//   Called by shim after the loader-breakpoint is handled.
 //   @dbgtodo sync: ths should go away once the shim can initiate
-//   a sync 
+//   a sync
 void CordbProcess::QueueManagedAttachIfNeededWorker()
 {
     HRESULT hrQueue = S_OK;
@@ -1949,16 +1949,16 @@ void CordbProcess::QueueManagedAttachIfNeededWorker()
     // m_fDoDelayedManagedAttached ensures that we only send an Attach event if the LS is actually present.
     if (m_fDoDelayedManagedAttached && GetShim()->GetAttached())
     {
-        RSLockHolder lockHolder(&this->m_processMutex);            
-        GetDAC()->MarkDebuggerAttachPending();                            
+        RSLockHolder lockHolder(&this->m_processMutex);
+        GetDAC()->MarkDebuggerAttachPending();
 
         hrQueue = this->QueueManagedAttach();
-    } 
-    
+    }
+
     if (m_pShim != NULL)
         m_pShim->SetMarkAttachPendingEvent();
-    
-    IfFailThrow(hrQueue); 
+
+    IfFailThrow(hrQueue);
 }
 
 //---------------------------------------------------------------------------------------
@@ -1984,19 +1984,19 @@ HRESULT CordbProcess::QueueManagedAttach()
 
     // We don't know what Queue it.
     SendAttachProcessWorkItem * pItem = new (nothrow) SendAttachProcessWorkItem(this);
-    
+
     if (pItem == NULL)
     {
         return E_OUTOFMEMORY;
     }
-    
+
     this->m_cordb->m_rcEventThread->QueueAsyncWorkItem(pItem);
-    
+
     return S_OK;
 }
 
 // However, we still want to synchronize.
-// @dbgtodo sync: when we hoist attaching, we can send an DB_IPCE_ASYNC_BREAK event instead or Attach 
+// @dbgtodo sync: when we hoist attaching, we can send an DB_IPCE_ASYNC_BREAK event instead or Attach
 // (for V2 semantics, we still need to synchronize the process)?
 void SendAttachProcessWorkItem::Do()
 {
@@ -2006,10 +2006,10 @@ void SendAttachProcessWorkItem::Do()
     RSLockHolder ch(this->GetProcess()->GetStopGoLock());
 
     DebuggerIPCEvent *event = (DebuggerIPCEvent*) _alloca(CorDBIPC_BUFFER_SIZE);
-    
+
     // This just acts like an async-break, which will kick off things.
     // This will not induce any faked attach events from the VM (like it did in V2).
-    // The Left-side will still slip foward allowing the async-break to happen, so 
+    // The Left-side will still slip foward allowing the async-break to happen, so
     // we may get normal debug events in addition to the sync-complete.
     //
     // 1. In the common attach case, we should just get a sync-complete.
@@ -2017,12 +2017,12 @@ void SendAttachProcessWorkItem::Do()
     GetProcess()->InitAsyncIPCEvent(event, DB_IPCE_ATTACHING, VMPTR_AppDomain::NullPtr());
 
     // This should result in a sync-complete from the Left-side, which will be raised as an exception
-    // that the debugger passes into Filter and then internally goes through code:CordbProcess::TriageSyncComplete 
+    // that the debugger passes into Filter and then internally goes through code:CordbProcess::TriageSyncComplete
     // and that triggers code:CordbRCEventThread::FlushQueuedEvents to be called on the RCET.
     // We already pre-queued a fake CreateProcess event.
 
-    // The left-side will also mark itself as attached in response to this event. 
-    // We explicitly don't mark it as attached from the right-side because we want to let the left-side 
+    // The left-side will also mark itself as attached in response to this event.
+    // We explicitly don't mark it as attached from the right-side because we want to let the left-side
     // synchronize first (to stop all running threads) before marking the debugger as attached.
     LOG((LF_CORDB, LL_INFO1000, "[%x] CP::S: sending attach.\n", GetCurrentThreadId()));
 
@@ -2042,7 +2042,7 @@ void SendAttachProcessWorkItem::Do()
 //
 // Notes:
 //     This does not create the thread object if it's not cached. Caching is unpredictable,
-//     and so this may appear to randomly return NULL. 
+//     and so this may appear to randomly return NULL.
 //     Callers should prefer code:CordbProcess::LookupOrCreateThread unless they expicitly
 //     want to check RS state.
 CordbThread * CordbProcess::TryLookupThread(VMPTR_Thread vmThread)
@@ -2063,7 +2063,7 @@ CordbThread * CordbProcess::TryLookupThread(VMPTR_Thread vmThread)
 //
 // Notes:
 //      OS Thread ID is not fiber-safe, so this is a dangerous function to call.
-//      Avoid this as much as possible. Prefer using VMPTR_Thread and 
+//      Avoid this as much as possible. Prefer using VMPTR_Thread and
 //      code:CordbProcess::LookupOrCreateThread instead of OS thread IDs.
 //      See code:CordbThread::GetID for details.
 CordbThread * CordbProcess::TryLookupOrCreateThreadByVolatileOSId(DWORD dwThreadId)
@@ -2073,7 +2073,7 @@ CordbThread * CordbProcess::TryLookupOrCreateThreadByVolatileOSId(DWORD dwThread
 }
 
 //---------------------------------------------------------------------------------------
-// Lookup a cached CordbThread object by the tid. Returns null if not in the cache (which 
+// Lookup a cached CordbThread object by the tid. Returns null if not in the cache (which
 // includes unmanged thread)
 //
 // Arguments:
@@ -2089,7 +2089,7 @@ CordbThread * CordbProcess::TryLookupOrCreateThreadByVolatileOSId(DWORD dwThread
 //   * OS Thread ID is not fiber-safe, so this is a dangerous function to call.
 //   * This is juts a Lookup, not LookupOrCreate, so it should only be used by methods
 //    that care about the RS state (instead of just LS state).
-//   Prefer using VMPTR_Thread and code:CordbProcess::LookupOrCreateThread 
+//   Prefer using VMPTR_Thread and code:CordbProcess::LookupOrCreateThread
 //
 CordbThread * CordbProcess::TryLookupThreadByVolatileOSId(DWORD dwThreadId)
 {
@@ -2109,7 +2109,7 @@ CordbThread * CordbProcess::TryLookupThreadByVolatileOSId(DWORD dwThreadId)
     }
 
     // This OS thread ID does not match any managed thread id.
-    return NULL; 
+    return NULL;
 }
 
 //---------------------------------------------------------------------------------------
@@ -2209,12 +2209,12 @@ HRESULT CordbProcess::QueryInterface(REFIID id, void **pInterface)
 HRESULT CordbProcess::ProcessStateChanged(CorDebugStateChange eChange)
 {
     HRESULT hr = S_OK;
-    PUBLIC_API_BEGIN(this)            
-    {        
+    PUBLIC_API_BEGIN(this)
+    {
         switch(eChange)
         {
-        case PROCESS_RUNNING:            
-            FlushProcessRunning();                
+        case PROCESS_RUNNING:
+            FlushProcessRunning();
             break;
 
         case FLUSH_ALL:
@@ -2235,11 +2235,11 @@ HRESULT CordbProcess::EnumerateHeap(ICorDebugHeapEnum **ppObjects)
 {
     if (!ppObjects)
         return E_POINTER;
-    
+
     HRESULT hr = S_OK;
     PUBLIC_API_ENTRY(this);
     ATT_REQUIRE_STOPPED_MAY_FAIL(this);
-    
+
     EX_TRY
     {
         if (m_pDacPrimitives->AreGCStructuresValid())
@@ -2252,9 +2252,9 @@ HRESULT CordbProcess::EnumerateHeap(ICorDebugHeapEnum **ppObjects)
         {
             hr = CORDBG_E_GC_STRUCTURES_INVALID;
         }
-    } 
+    }
     EX_CATCH_HRESULT(hr);
-    
+
     return hr;
 }
 
@@ -2262,17 +2262,17 @@ HRESULT CordbProcess::GetGCHeapInformation(COR_HEAPINFO *pHeapInfo)
 {
     if (!pHeapInfo)
         return E_INVALIDARG;
-        
+
     HRESULT hr = S_OK;
     PUBLIC_API_ENTRY(this);
     ATT_REQUIRE_STOPPED_MAY_FAIL(this);
-    
+
     EX_TRY
     {
         GetDAC()->GetGCHeapInformation(pHeapInfo);
     }
     EX_CATCH_HRESULT(hr);
-    
+
     return hr;
 }
 
@@ -2284,12 +2284,12 @@ HRESULT CordbProcess::EnumerateHeapRegions(ICorDebugHeapSegmentEnum **ppRegions)
     HRESULT hr = S_OK;
     PUBLIC_API_ENTRY(this);
     ATT_REQUIRE_STOPPED_MAY_FAIL(this);
-    
+
     EX_TRY
     {
         DacDbiArrayList<COR_SEGMENT> segments;
         hr = GetDAC()->GetHeapSegments(&segments);
-        
+
         if (SUCCEEDED(hr))
         {
             if (!segments.IsEmpty())
@@ -2305,17 +2305,17 @@ HRESULT CordbProcess::EnumerateHeapRegions(ICorDebugHeapSegmentEnum **ppRegions)
         }
     }
     EX_CATCH_HRESULT(hr);
-    
+
     return hr;
 }
 
 HRESULT CordbProcess::GetObject(CORDB_ADDRESS addr, ICorDebugObjectValue **pObject)
 {
     HRESULT hr = S_OK;
-    
+
     PUBLIC_REENTRANT_API_ENTRY(this);
     ATT_REQUIRE_STOPPED_MAY_FAIL(this);
-    
+
     EX_TRY
     {
         if (!m_pDacPrimitives->IsValidObject(addr))
@@ -2330,22 +2330,22 @@ HRESULT CordbProcess::GetObject(CORDB_ADDRESS addr, ICorDebugObjectValue **pObje
         {
             RSLockHolder ch(GetProcess()->GetStopGoLock());
             RSLockHolder procLock(this->GetProcess()->GetProcessLock());
-            
+
             CordbAppDomain *cdbAppDomain = NULL;
             CordbType *pType = NULL;
             hr = GetTypeForObject(addr, &pType, &cdbAppDomain);
-            
+
             if (SUCCEEDED(hr))
             {
                 _ASSERTE(pType != NULL);
                 _ASSERTE(cdbAppDomain != NULL);
-                
+
                 DebuggerIPCE_ObjectData objData;
                 m_pDacPrimitives->GetBasicObjectInfo(addr, ELEMENT_TYPE_CLASS, cdbAppDomain->GetADToken(), &objData);
-                
+
                 NewHolder<CordbObjectValue> pNewObjectValue(new CordbObjectValue(cdbAppDomain, pType, TargetBuffer(addr, (ULONG)objData.objSize), &objData));
                 hr = pNewObjectValue->Init();
-                
+
                 if (SUCCEEDED(hr))
                 {
                     hr = pNewObjectValue->QueryInterface(__uuidof(ICorDebugObjectValue), (void**)pObject);
@@ -2365,11 +2365,11 @@ HRESULT CordbProcess::EnumerateGCReferences(BOOL enumerateWeakReferences, ICorDe
 {
     if (!ppEnum)
         return E_POINTER;
-        
+
     HRESULT hr = S_OK;
     PUBLIC_API_ENTRY(this);
     ATT_REQUIRE_STOPPED_MAY_FAIL(this);
-    
+
     EX_TRY
     {
         CordbRefEnum *pRefEnum = new CordbRefEnum(this, enumerateWeakReferences);
@@ -2384,11 +2384,11 @@ HRESULT CordbProcess::EnumerateHandles(CorGCReferenceType types, ICorDebugGCRefe
 {
     if (!ppEnum)
         return E_POINTER;
-        
+
     HRESULT hr = S_OK;
     PUBLIC_API_ENTRY(this);
     ATT_REQUIRE_STOPPED_MAY_FAIL(this);
-    
+
     EX_TRY
     {
         CordbRefEnum *pRefEnum = new CordbRefEnum(this, types);
@@ -2396,7 +2396,7 @@ HRESULT CordbProcess::EnumerateHandles(CorGCReferenceType types, ICorDebugGCRefe
         hr = pRefEnum->QueryInterface(IID_ICorDebugGCReferenceEnum, (void**)ppEnum);
     }
     EX_CATCH_HRESULT(hr);
-    
+
     return hr;
 }
 
@@ -2410,17 +2410,17 @@ HRESULT CordbProcess::GetTypeID(CORDB_ADDRESS obj, COR_TYPEID *pId)
 {
     if (pId == NULL)
         return E_POINTER;
-        
+
     HRESULT hr = S_OK;
     PUBLIC_API_ENTRY(this);
     ATT_REQUIRE_STOPPED_MAY_FAIL(this);
-    
+
     EX_TRY
     {
         hr = GetProcess()->GetDAC()->GetTypeID(obj, pId);
     }
     EX_CATCH_HRESULT(hr);
-    
+
     return hr;
 }
 
@@ -2428,13 +2428,13 @@ HRESULT CordbProcess::GetTypeForTypeID(COR_TYPEID id, ICorDebugType **ppType)
 {
     if (ppType == NULL)
         return E_POINTER;
-        
+
     HRESULT hr = S_OK;
-    
+
     PUBLIC_API_ENTRY(this);
     RSLockHolder stopGoLock(this->GetProcess()->GetStopGoLock());
     RSLockHolder procLock(this->GetProcess()->GetProcessLock());
-    
+
     EX_TRY
     {
         DebuggerIPCE_ExpandedTypeData data;
@@ -2445,7 +2445,7 @@ HRESULT CordbProcess::GetTypeForTypeID(COR_TYPEID id, ICorDebugType **ppType)
 
         if (SUCCEEDED(hr))
             hr = type->QueryInterface(IID_ICorDebugType, (void**)ppType);
-    } 
+    }
     EX_CATCH_HRESULT(hr);
 
     return hr;
@@ -2456,12 +2456,12 @@ COM_METHOD CordbProcess::GetArrayLayout(COR_TYPEID id, COR_ARRAY_LAYOUT *pLayout
 {
     if (pLayout == NULL)
         return E_POINTER;
-        
+
     HRESULT hr = S_OK;
     PUBLIC_API_BEGIN(this);
 
     hr = GetProcess()->GetDAC()->GetArrayLayout(id, pLayout);
-    
+
     PUBLIC_API_END(hr);
     return hr;
 }
@@ -2470,12 +2470,12 @@ COM_METHOD CordbProcess::GetTypeLayout(COR_TYPEID id, COR_TYPE_LAYOUT *pLayout)
 {
     if (pLayout == NULL)
         return E_POINTER;
-        
+
     HRESULT hr = S_OK;
     PUBLIC_API_BEGIN(this);
-    
+
     hr = GetProcess()->GetDAC()->GetTypeLayout(id, pLayout);
-    
+
     PUBLIC_API_END(hr);
     return hr;
 }
@@ -2484,9 +2484,9 @@ COM_METHOD CordbProcess::GetTypeFields(COR_TYPEID id, ULONG32 celt, COR_FIELD fi
 {
     HRESULT hr = S_OK;
     PUBLIC_API_BEGIN(this);
-    
+
     hr = GetProcess()->GetDAC()->GetObjectFields(id, celt, fields, pceltNeeded);
-    
+
     PUBLIC_API_END(hr);
     return hr;
 }
@@ -2495,7 +2495,7 @@ COM_METHOD CordbProcess::SetWriteableMetadataUpdateMode(WriteableMetadataUpdateM
 {
     HRESULT hr = S_OK;
     PUBLIC_API_BEGIN(this);
-    
+
     if(flags != LegacyCompatPolicy &&
        flags != AlwaysShowUpdates)
     {
@@ -2513,7 +2513,7 @@ COM_METHOD CordbProcess::SetWriteableMetadataUpdateMode(WriteableMetadataUpdateM
     {
         m_writableMetadataUpdateMode = flags;
     }
-    
+
     PUBLIC_API_END(hr);
     return hr;
 }
@@ -2653,7 +2653,7 @@ COM_METHOD CordbProcess::CreateBreakpoint(CORDB_ADDRESS address, ICorDebugValueB
     EX_TRY
     {
         RSInitHolder<CordbValueBreakpoint> pValueBreakpoint(new CordbValueBreakpoint(m_dataBreakpoints.GetCount(), nullptr, this));
-        
+
         if (pValueBreakpoint)
         {
             hr = pValueBreakpoint->QueryInterface(IID_ICorDebugValueBreakpoint, (void**)ppBreakpoint);
@@ -2685,20 +2685,20 @@ HRESULT CordbProcess::GetTypeForObject(CORDB_ADDRESS addr, CordbType **ppType, C
     VMPTR_AppDomain appDomain;
     VMPTR_Module mod;
     VMPTR_DomainFile domainFile;
-    
+
     HRESULT hr = E_FAIL;
     if (GetDAC()->GetAppDomainForObject(addr, &appDomain, &mod, &domainFile))
     {
         CordbAppDomain *cdbAppDomain = appDomain.IsNull() ? GetSharedAppDomain() : LookupOrCreateAppDomain(appDomain);
-        
+
         _ASSERTE(cdbAppDomain);
-        
+
         DebuggerIPCE_ExpandedTypeData data;
         GetDAC()->GetObjectExpandedTypeInfo(AllBoxed, appDomain, addr, &data);
 
         CordbType *type = 0;
         hr = CordbType::TypeDataToType(cdbAppDomain, &data, &type);
-        
+
         if (SUCCEEDED(hr))
         {
             *ppType = type;
@@ -2706,7 +2706,7 @@ HRESULT CordbProcess::GetTypeForObject(CORDB_ADDRESS addr, CordbType **ppType, C
                 *pAppDomain = cdbAppDomain;
         }
     }
-    
+
     return hr;
 }
 
@@ -2738,10 +2738,10 @@ void CordbRefEnum::Neuter()
     }
     EX_CATCH
     {
-        _ASSERTE(!"Hit an error freeing a ref walk."); 
+        _ASSERTE(!"Hit an error freeing a ref walk.");
     }
     EX_END_CATCH(SwallowAllExceptions)
-    
+
     CordbBase::Neuter();
 }
 
@@ -2749,7 +2749,7 @@ HRESULT CordbRefEnum::QueryInterface(REFIID riid, void **ppInterface)
 {
     if (ppInterface == NULL)
         return E_INVALIDARG;
-        
+
     if (riid == IID_ICorDebugGCReferenceEnum)
     {
         *ppInterface = static_cast<ICorDebugGCReferenceEnum*>(this);
@@ -2786,7 +2786,7 @@ HRESULT CordbRefEnum::Reset()
         }
     }
     EX_CATCH_HRESULT(hr);
-    
+
     return hr;
 }
 
@@ -2807,52 +2807,52 @@ HRESULT CordbRefEnum::Next(ULONG celt, COR_GC_REFERENCE refs[], ULONG *pceltFetc
 {
     if (refs == NULL || pceltFetched == NULL)
         return E_POINTER;
-    
+
     CordbProcess *process = GetProcess();
     HRESULT hr = S_OK;
-    
+
     PUBLIC_API_ENTRY(this);
     FAIL_IF_NEUTERED(this);
     ATT_REQUIRE_STOPPED_MAY_FAIL(process);
-    
+
     RSLockHolder procLockHolder(process->GetProcessLock());
-    
+
     EX_TRY
     {
         if (!mRefHandle)
             hr = process->GetDAC()->CreateRefWalk(&mRefHandle, mEnumStacksFQ, mEnumStacksFQ, mHandleMask);
-            
+
         if (SUCCEEDED(hr))
         {
             DacGcReference dacRefs[32];
             ULONG toFetch = _countof(dacRefs);
             ULONG total = 0;
-            
+
             for (ULONG c = 0; SUCCEEDED(hr) && c < (celt/_countof(dacRefs) + 1); ++c)
             {
                 // Fetch 32 references at a time, the last time, only fetch the remainder (that is, if
                 // the user didn't fetch a multiple of 32).
                 if (c == celt/_countof(dacRefs))
                     toFetch = celt % _countof(dacRefs);
-                    
+
                 ULONG fetched = 0;
                 hr = process->GetDAC()->WalkRefs(mRefHandle, toFetch, dacRefs, &fetched);
-                
+
                 if (SUCCEEDED(hr))
                 {
                     for (ULONG i = 0; i < fetched; ++i)
                     {
                         CordbAppDomain *pDomain = process->LookupOrCreateAppDomain(dacRefs[i].vmDomain);
-                        
+
                         ICorDebugAppDomain *pAppDomain;
                         ICorDebugValue *pOutObject = NULL;
                         if (dacRefs[i].pObject & 1)
                         {
                             dacRefs[i].pObject &= ~1;
                             ICorDebugObjectValue *pObjValue = NULL;
-                            
+
                             hr = process->GetObject(dacRefs[i].pObject, &pObjValue);
-                            
+
                             if (SUCCEEDED(hr))
                             {
                                 hr = pObjValue->QueryInterface(IID_ICorDebugValue, (void**)&pOutObject);
@@ -2865,32 +2865,32 @@ HRESULT CordbRefEnum::Next(ULONG celt, COR_GC_REFERENCE refs[], ULONG *pceltFetc
                             IfFailThrow(CordbReferenceValue::BuildFromGCHandle(pDomain,
                                                                    dacRefs[i].objHnd,
                                                                    &tmpValue));
-                            
+
                             if (SUCCEEDED(hr))
                             {
                                 hr = tmpValue->QueryInterface(IID_ICorDebugValue, (void**)&pOutObject);
                                 tmpValue->Release();
                             }
                         }
-                        
+
                         if (SUCCEEDED(hr) && pDomain)
                         {
                             hr = pDomain->QueryInterface(IID_ICorDebugAppDomain, (void**)&pAppDomain);
                         }
-                        
+
                         if (FAILED(hr))
                             break;
-                        
+
                         refs[total].Domain = pAppDomain;
                         refs[total].Location = pOutObject;
                         refs[total].Type = (CorGCReferenceType)dacRefs[i].dwType;
                         refs[total].ExtraData = dacRefs[i].i64ExtraData;
-                        
+
                         total++;
                     }
                 }
             }
-            
+
             *pceltFetched = total;
         }
     }
@@ -2912,7 +2912,7 @@ HRESULT CordbHeapEnum::QueryInterface(REFIID riid, void **ppInterface)
 {
     if (ppInterface == NULL)
         return E_INVALIDARG;
-        
+
     if (riid == IID_ICorDebugHeapEnum)
     {
         *ppInterface = static_cast<ICorDebugHeapEnum*>(this);
@@ -2954,7 +2954,7 @@ void CordbHeapEnum::Clear()
     }
     EX_CATCH
     {
-        _ASSERTE(!"Hit an error freeing the heap walk."); 
+        _ASSERTE(!"Hit an error freeing the heap walk.");
     }
     EX_END_CATCH(SwallowAllExceptions)
 }
@@ -2989,17 +2989,17 @@ HRESULT CordbHeapEnum::Next(ULONG celt, COR_HEAPOBJECT objects[], ULONG *pceltFe
             hr = GetProcess()->GetDAC()->WalkHeap(mHeapHandle, celt, objects, &fetched);
             _ASSERTE(fetched <= celt);
         }
-        
+
         if (SUCCEEDED(hr))
         {
             // Return S_FALSE if we've reached the end of the enum.
             if (fetched < celt)
                 hr = S_FALSE;
         }
-    } 
+    }
     EX_CATCH_HRESULT(hr);
 
-    // Set the fetched parameter to reflect the number of elements (if any) 
+    // Set the fetched parameter to reflect the number of elements (if any)
     // that were successfully saved to "objects"
     if (pceltFetched)
         *pceltFetched = fetched;
@@ -3009,33 +3009,33 @@ HRESULT CordbHeapEnum::Next(ULONG celt, COR_HEAPOBJECT objects[], ULONG *pceltFe
 
 //---------------------------------------------------------------------------------------
 // Flush state for when the process starts running.
-// 
+//
 // Notes:
 //   Helper for code:CordbProcess::ProcessStateChanged.
-//   Since ICD Arrowhead does not own the eventing pipeline, it needs the debugger to 
+//   Since ICD Arrowhead does not own the eventing pipeline, it needs the debugger to
 //   notifying it of when the process is running again.  This is like the counterpart
 //   to code:CordbProcess::Filter
 void CordbProcess::FlushProcessRunning()
 {
     _ASSERTE(GetProcessLock()->HasLock());
-    
+
     // Update the continue counter.
     m_continueCounter++;
 
     // Safely dispose anything that should be neutered on continue.
-    MarkAllThreadsDirty();    
+    MarkAllThreadsDirty();
     ForceDacFlush();
 }
 
 //---------------------------------------------------------------------------------------
 // Flush all cached state and bring us back to "cold startup"
-// 
+//
 // Notes:
 //   Helper for code:CordbProcess::ProcessStateChanged.
 //   This is used if the data-target changes underneath us in a way that is
 //   not consistent with the process running forward. For example, if for
 //   a time-travel debugger, the data-target may flow "backwards" in time.
-//   
+//
 void CordbProcess::FlushAll()
 {
     CONTRACTL
@@ -3054,7 +3054,7 @@ void CordbProcess::FlushAll()
     hr = IsReadyForDetach();
     IfFailThrow(hr);
 
-    // Check for outstanding CordbHandle values. 
+    // Check for outstanding CordbHandle values.
     if (OutstandingHandles())
     {
         ThrowHR(CORDBG_E_DETACH_FAILED_OUTSTANDING_TARGET_RESOURCES);
@@ -3066,7 +3066,7 @@ void CordbProcess::FlushAll()
 
     // If we detach before the CLR is loaded into the debuggee, then we can no-op a lot of work.
     // We sure can't be sending IPC events to the LS before it exists.
-    NeuterChildren();    
+    NeuterChildren();
 }
 
 //---------------------------------------------------------------------------------------
@@ -3090,14 +3090,14 @@ void CordbProcess::FlushAll()
 //    in V3, especially w.r.t to an attach bit.
 //---------------------------------------------------------------------------------------
 HRESULT CordbProcess::Detach()
-{   
+{
     PUBLIC_API_ENTRY(this);
 
     FAIL_IF_NEUTERED(this);
 
     if (IsInteropDebugging())
     {
-        return CORDBG_E_INTEROP_NOT_SUPPORTED; 
+        return CORDBG_E_INTEROP_NOT_SUPPORTED;
     }
 
 
@@ -3108,7 +3108,7 @@ HRESULT CordbProcess::Detach()
     // @todo-  why can't we enforce that the managed event Q is drained?
     ATT_REQUIRE_SYNCED_OR_NONINIT_MAY_FAIL(this);
 
-    
+
     hr = IsReadyForDetach();
     if (FAILED(hr))
     {
@@ -3121,13 +3121,13 @@ HRESULT CordbProcess::Detach()
     RSSmartPtr<CordbProcess> pRef(this);
 
 
-    
+
     LOG((LF_CORDB, LL_INFO1000, "CP::Detach - beginning\n"));
     if (m_pShim == NULL) // This API is moved off to the shim
     {
-        
-        // This is still invasive. 
-        // Ignore failures. This will fail for a non-invasive target. 
+
+        // This is still invasive.
+        // Ignore failures. This will fail for a non-invasive target.
         if (IsDacInitialized())
         {
             HRESULT hrIgnore = S_OK;
@@ -3139,10 +3139,10 @@ HRESULT CordbProcess::Detach()
         }
     }
     else
-    {         
+    {
         EX_TRY
         {
-            DetachShim();       
+            DetachShim();
         }
         EX_CATCH_HRESULT(hr);
     }
@@ -3156,7 +3156,7 @@ HRESULT CordbProcess::Detach()
 }
 
 // Free up key left-side resources
-// 
+//
 // Called on detach
 // This does key neutering of objects that hold left-side resources and require
 // preemptively freeing the resources.
@@ -3164,24 +3164,24 @@ HRESULT CordbProcess::Detach()
 void CordbProcess::NeuterChildrenLeftSideResources()
 {
     _ASSERTE(GetStopGoLock()->HasLock());
-    
+
     _ASSERTE(!GetProcessLock()->HasLock());
     RSLockHolder lockHolder(GetProcessLock());
 
-    
+
     // Need process-lock to operate on hashtable, but can't yet Neuter under process-lock,
     // so we have to copy the contents to an auxilary list which we can then traverse outside the lock.
     RSPtrArray<CordbAppDomain> listAppDomains;
     m_appDomains.CopyToArray(&listAppDomains);
-    
-    
+
+
 
     // Must not hold process lock so that we can be safe to send IPC events
     // to cleanup left-side resources.
     lockHolder.Release();
     _ASSERTE(!GetProcessLock()->HasLock());
 
-    // Frees left-side resources. This may send IPC events. 
+    // Frees left-side resources. This may send IPC events.
     // This will make normal neutering a nop.
     m_LeftSideResourceCleanupList.NeuterLeftSideResourcesAndClear(this);
 
@@ -3191,20 +3191,20 @@ void CordbProcess::NeuterChildrenLeftSideResources()
 
         // CordbHandleValue is in the appdomain exit list, and that needs
         // to send an IPC event to cleanup and release the handle from
-        // the GCs handle table. 
+        // the GCs handle table.
         pAppDomain->GetSweepableExitNeuterList()->NeuterLeftSideResourcesAndClear(this);
     }
     listAppDomains.Clear();
-    
+
 }
 
 //---------------------------------------------------------------------------------------
 // Detach the Debugger from the LS process for the V2 case
-// 
+//
 // Assumptions:
 //      This will NeuterChildren(), caller will do the real Neuter()
 //      Caller has already ensured that detach is safe.
-// 
+//
 //   @dbgtodo attach-bit: this should be moved into the shim; need
 //   to figure out semantics for freeing left-side resources (especially GC
 //   handles) on detach.
@@ -3217,7 +3217,7 @@ void CordbProcess::DetachShim()
     // If we detach before the CLR is loaded into the debuggee, then we can no-op a lot of work.
     // We sure can't be sending IPC events to the LS before it exists.
     if (m_initialized)
-    {   
+    {
         // The managed event queue is not necessarily drained. Cordbg could call detach between any callback.
         // While the process is still stopped, neuter all of our children.
         // This will make our Neuter() a nop and saves the W32ET from having to do dangerous work.
@@ -3238,7 +3238,7 @@ void CordbProcess::DetachShim()
     else
     {
         // @dbgtodo attach-bit: push this up, once detach IPC event is hoisted.
-        RSLockHolder lockHolder(GetProcessLock()); 
+        RSLockHolder lockHolder(GetProcessLock());
 
         // Shouldn't have any appdomains.
         (void)hashFind; //prevent "unused variable" error from GCC
@@ -3267,7 +3267,7 @@ void CordbProcess::DetachShim()
         m_detached = true;
     }
     IfFailThrow(hr);
-    
+
 
     // Now that all complicated cleanup is done, caller can do a final neuter.
     // This will implicitly stop our Win32 event thread as well.
@@ -3361,7 +3361,7 @@ HRESULT CordbProcess::Terminate(unsigned int exitCode)
 
 
     // @dbgtodo shutdown: eventually, all of Terminate() will be in the Shim.
-    // Free all the remaining events. Since this will call into the shim, do this outside of any locks. 
+    // Free all the remaining events. Since this will call into the shim, do this outside of any locks.
     // (ATT_ takes locks).
     DeleteQueuedEvents();
 
@@ -3401,7 +3401,7 @@ HRESULT CordbProcess::Terminate(unsigned int exitCode)
     //
     // Note that on Windows, the process isn't really terminated until we receive the EXIT_PROCESS_DEBUG_EVENT.
     // Before then, we can still still access the debuggee's address space.  On the other, for Mac debugging,
-    // the process can die any time after this call, and so we can no longer call into the DAC.  
+    // the process can die any time after this call, and so we can no longer call into the DAC.
     GetShim()->GetNativePipeline()->TerminateProcess(exitCode);
 
     // We just call Continue() so that the debugger doesn't have to. (It's arguably odd
@@ -3431,8 +3431,8 @@ HRESULT CordbProcess::GetID(DWORD *pdwProcessId)
     {
         // This shouldn't be used in V3 paths. Normally, we can enforce that by checking against
         // m_pShim. However, this API can be called after being neutered, in which case m_pShim is cleared.
-        // So check against 0 instead.    
-        if (m_id == 0) 
+        // So check against 0 instead.
+        if (m_id == 0)
         {
             *pdwProcessId = 0;
             ThrowHR(E_NOTIMPL);
@@ -3512,11 +3512,11 @@ HRESULT CordbProcess::StopInternal(DWORD dwTimeout, VMPTR_AppDomain pAppDomainTo
     // Stop + Continue are executed under the Stop-Go lock. This makes them atomic.
     // We'll toggle the process-lock (b/c we communicate w/ the W32et, so just the process-lock is
     // not sufficient to make this atomic).
-    // It's ok to take this lock before checking if the CordbProcess has been neutered because 
+    // It's ok to take this lock before checking if the CordbProcess has been neutered because
     // the lock is destroyed in the dtor after neutering.
     RSLockHolder ch(&m_StopGoLock);
 
-    // Check if this CordbProcess has been neutered under the SG lock.  
+    // Check if this CordbProcess has been neutered under the SG lock.
     // Otherwise it's possible to race with Detach() and Terminate().
     FAIL_IF_NEUTERED(this);
     CORDBFailIfOnWin32EventThread(this);
@@ -3756,7 +3756,7 @@ HRESULT CordbProcess::Continue(BOOL fIsOutOfBand)
     if (m_pShim == NULL) // This API is moved off to the shim
     {
         // bias towards failing with CORDBG_E_NUETERED.
-        FAIL_IF_NEUTERED(this); 
+        FAIL_IF_NEUTERED(this);
         return E_NOTIMPL;
     }
 
@@ -3985,7 +3985,7 @@ HRESULT CordbProcess::ContinueInternal(BOOL fIsOutOfBand)
         SetSynchronized(false);
 
         // If the callback queue is not empty, then the LS is not actually continuing, and so our cached
-        // state is still valid. 
+        // state is still valid.
 
         // If we're in the middle of dispatching a managed event, then simply return. This indicates to HandleRCEvent
         // that the user called Continue and HandleRCEvent will dispatch the next queued event. But if Continue was
@@ -4032,7 +4032,7 @@ HRESULT CordbProcess::ContinueInternal(BOOL fIsOutOfBand)
         // may send events.
         Unlock();
 
-        // This may send IPC events. 
+        // This may send IPC events.
         // This will make normal neutering a nop.
         // This will toggle the process lock.
         m_LeftSideResourceCleanupList.SweepNeuterLeftSideResources(this);
@@ -4055,9 +4055,9 @@ HRESULT CordbProcess::ContinueInternal(BOOL fIsOutOfBand)
 
             // CordbHandleValue is in the appdomain exit list, and that needs
             // to send an IPC event to cleanup and release the handle from
-            // the GCs handle table. 
+            // the GCs handle table.
             // This will toggle the process lock.
-            pAppDomain->GetSweepableExitNeuterList()->SweepNeuterLeftSideResources(this); 
+            pAppDomain->GetSweepableExitNeuterList()->SweepNeuterLeftSideResources(this);
         }
         listAppDomains.Clear();
 
@@ -4178,7 +4178,7 @@ HRESULT CordbProcess::ContinueInternal(BOOL fIsOutOfBand)
         SetSynchronized(false);
         SetSyncCompleteRecv(false);
 
-        // we're no longer in a callback, so set flags to indicate that we've finished. 
+        // we're no longer in a callback, so set flags to indicate that we've finished.
         GetShim()->NotifyOnContinue();
 
         // Flush will update state, including continue counter and marking
@@ -4325,7 +4325,7 @@ HRESULT CordbProcess::HasQueuedCallbacks(ICorDebugThread *pThread,
         *pbQueued = m_pShim->GetManagedEventQueue()->HasQueuedCallbacks(pThread);
         return S_OK;
     }
-    return E_NOTIMPL; // Not implemented in V3. 
+    return E_NOTIMPL; // Not implemented in V3.
 }
 
 //
@@ -4373,7 +4373,7 @@ class ShimAssemblyCallbackData
 {
 public:
     // Ctor to intialize callback data
-    // 
+    //
     // Arguments:
     //   pAppDomain - appdomain that the assemblies are in.
     //   pAssemblies - preallocated array of smart pointers to hold assemblies
@@ -4397,10 +4397,10 @@ public:
         {
             pAssemblies[i].Clear();
         }
-    }   
+    }
 
     // Dtor
-    // 
+    //
     // Notes:
     //   This can assert end-of-enumeration invariants.
     ~ShimAssemblyCallbackData()
@@ -4408,13 +4408,13 @@ public:
         // Ensure that we went through all assemblies.
         _ASSERTE(m_index == m_countElements);
     }
-    
+
     // Callback invoked from DAC enumeration.
-    // 
+    //
     // arguments:
     //    vmDomainAssembly - VMPTR for assembly
     //    pData - a 'this' pointer
-    //  
+    //
     static void Callback(VMPTR_DomainAssembly vmDomainAssembly, void * pData)
     {
         ShimAssemblyCallbackData * pThis = static_cast<ShimAssemblyCallbackData *> (pData);
@@ -4426,7 +4426,7 @@ public:
     }
 
     // Set the current index in the table and increment the cursor.
-    // 
+    //
     // Arguments:
     //    pAssembly - assembly from DAC enumerator
     void SetAndMoveNext(CordbAssembly * pAssembly)
@@ -4436,8 +4436,8 @@ public:
         if (m_index >= m_countElements)
         {
             // Enumerating the assemblies in the target should be fixed since
-            // the target is not running. 
-            // We should never get here unless the target is unstable. 
+            // the target is not running.
+            // We should never get here unless the target is unstable.
             // The caller (the shim) pre-allocated the table of assemblies.
             m_pProcess->TargetConsistencyCheck(!"Target changed assembly count");
             return;
@@ -4457,31 +4457,31 @@ protected:
 
 //---------------------------------------------------------------------------------------
 // Shim Helper to enumerate the assemblies in the load-order
-// 
+//
 // Arguments:
 //    pAppdomain - non-null appdomain to enumerate assemblies.
 //    pAssemblies - caller pre-allocated array to hold assemblies
 //    countAssemblies - size of the array.
-//    
+//
 // Notes:
 //    Caller preallocated array (likely from ICorDebugAssemblyEnum::GetCount),
 //    and now this function fills in the assemblies in the order they were
 //    loaded.
-//    
+//
 //    The target should be stable, such that the number of assemblies in the
 //    target is stable, and therefore countAssemblies as determined by the
 //    shim via ICorDebugAssemblyEnum::GetCount should match the number of
-//    assemblies enumerated here. 
-//    
-//    Called by code:ShimProcess::QueueFakeAttachEvents. 
+//    assemblies enumerated here.
+//
+//    Called by code:ShimProcess::QueueFakeAttachEvents.
 //    This provides the assemblies in load-order. In contrast,
 //    ICorDebugAppDomain::EnumerateAssemblies is a random order. The shim needs
 //    load-order to match Whidbey semantics for dispatching fake load-assembly
 //    callbacks on attach. The debugger then uses the order
 //    in its module display window.
-//    
+//
 void CordbProcess::GetAssembliesInLoadOrder(
-    ICorDebugAppDomain * pAppDomain, 
+    ICorDebugAppDomain * pAppDomain,
     RSExtSmartPtr<ICorDebugAssembly>* pAssemblies,
     ULONG countAssemblies)
 {
@@ -4500,7 +4500,7 @@ void CordbProcess::GetAssembliesInLoadOrder(
         ShimAssemblyCallbackData::Callback,
         &data); // user data
 
-    // pAssemblies array has now been updated. 
+    // pAssemblies array has now been updated.
 }
 
 // Callback data for code:CordbProcess::GetModulesInLoadOrder
@@ -4508,7 +4508,7 @@ class ShimModuleCallbackData
 {
 public:
     // Ctor to intialize callback data
-    // 
+    //
     // Arguments:
     //   pAssembly - assembly that the Modules are in.
     //   pModules - preallocated array of smart pointers to hold Modules
@@ -4532,10 +4532,10 @@ public:
         {
             pModules[i].Clear();
         }
-    }   
+    }
 
     // Dtor
-    // 
+    //
     // Notes:
     //   This can assert end-of-enumeration invariants.
     ~ShimModuleCallbackData()
@@ -4543,13 +4543,13 @@ public:
         // Ensure that we went through all Modules.
         _ASSERTE(m_index == m_countElements);
     }
-    
+
     // Callback invoked from DAC enumeration.
-    // 
+    //
     // arguments:
     //    vmDomainFile - VMPTR for Module
     //    pData - a 'this' pointer
-    //  
+    //
     static void Callback(VMPTR_DomainFile vmDomainFile, void * pData)
     {
         ShimModuleCallbackData * pThis = static_cast<ShimModuleCallbackData *> (pData);
@@ -4561,7 +4561,7 @@ public:
     }
 
     // Set the current index in the table and increment the cursor.
-    // 
+    //
     // Arguments:
     //    pModule - Module from DAC enumerator
     void SetAndMoveNext(CordbModule * pModule)
@@ -4571,8 +4571,8 @@ public:
         if (m_index >= m_countElements)
         {
             // Enumerating the Modules in the target should be fixed since
-            // the target is not running. 
-            // We should never get here unless the target is unstable. 
+            // the target is not running.
+            // We should never get here unless the target is unstable.
             // The caller (the shim) pre-allocated the table of Modules.
             m_pProcess->TargetConsistencyCheck(!"Target changed Module count");
             return;
@@ -4592,22 +4592,22 @@ protected:
 
 //---------------------------------------------------------------------------------------
 // Shim Helper to enumerate the Modules in the load-order
-// 
+//
 // Arguments:
 //    pAppdomain - non-null appdomain to enumerate Modules.
 //    pModules - caller pre-allocated array to hold Modules
 //    countModules - size of the array.
-//    
+//
 // Notes:
 //    Caller preallocated array (likely from ICorDebugModuleEnum::GetCount),
 //    and now this function fills in the Modules in the order they were
 //    loaded.
-//    
+//
 //    The target should be stable, such that the number of Modules in the
 //    target is stable, and therefore countModules as determined by the
 //    shim via ICorDebugModuleEnum::GetCount should match the number of
-//    Modules enumerated here. 
-//    
+//    Modules enumerated here.
+//
 //    Called by code:ShimProcess::QueueFakeAssemblyAndModuleEvent.
 //    This provides the Modules in load-order. In contrast,
 //    ICorDebugAssembly::EnumerateModules is a random order. The shim needs
@@ -4616,21 +4616,21 @@ protected:
 //    gets a LodModule callback before any secondary modules.  For dynamic
 //    modules, this is necessary for operations on the secondary module
 //    that rely on manifest metadata (eg. GetSimpleName).
-//    
-//    @dbgtodo : This is almost identical to GetAssembliesInLoadOrder, and 
-//    (together wih the CallbackData classes) seems a HUGE amount of code and 
+//
+//    @dbgtodo : This is almost identical to GetAssembliesInLoadOrder, and
+//    (together wih the CallbackData classes) seems a HUGE amount of code and
 //    complexity for such a simple thing.  We also have extra code to order
 //    AppDomains and Threads.  We should try and rip all of this extra complexity
 //    out, and replace it with better data structures for storing these items.
-//    Eg., if we used std::map, we could have efficient lookups and ordered 
+//    Eg., if we used std::map, we could have efficient lookups and ordered
 //    enumerations.  However, we do need to be careful about exposing new invariants
 //    through ICorDebug that customers may depend on, which could place a long-term
 //    compatibility burden on us.  We could have a simple generic data structure
 //    (eg. built on std::hash_map and std::list) which provided efficient look-up
 //    and both in-order and random enumeration.
-//    
+//
 void CordbProcess::GetModulesInLoadOrder(
-    ICorDebugAssembly * pAssembly, 
+    ICorDebugAssembly * pAssembly,
     RSExtSmartPtr<ICorDebugModule>* pModules,
     ULONG countModules)
 {
@@ -4649,13 +4649,13 @@ void CordbProcess::GetModulesInLoadOrder(
         ShimModuleCallbackData::Callback,
         &data); // user data
 
-    // pModules array has now been updated. 
+    // pModules array has now been updated.
 }
 
 
 //---------------------------------------------------------------------------------------
 // Callback to count the number of enumerations in a process.
-// 
+//
 // Arguments:
 //     id - the connection id.
 //     pName - name of the connection
@@ -4664,14 +4664,14 @@ void CordbProcess::GetModulesInLoadOrder(
 // Notes:
 //    Helper function for code:CordbProcess::QueueFakeConnectionEvents
 //
-// static 
+// static
 void CordbProcess::CountConnectionsCallback(DWORD id, LPCWSTR pName, void * pUserData)
 {
 }
 
 //---------------------------------------------------------------------------------------
 // Callback to enumerate all the connections in a process.
-// 
+//
 // Arguments:
 //     id - the connection id.
 //     pName - name of the connection
@@ -4680,7 +4680,7 @@ void CordbProcess::CountConnectionsCallback(DWORD id, LPCWSTR pName, void * pUse
 // Notes:
 //    Helper function for code:CordbProcess::QueueFakeConnectionEvents
 //
-// static  
+// static
 void CordbProcess::EnumerateConnectionsCallback(DWORD id, LPCWSTR pName, void * pUserData)
 {
 }
@@ -4755,9 +4755,9 @@ void CordbProcess::DispatchRCEvent()
     // This gives us delayed continues w/ no extra state flags.
 
 
-    // The debugger may call Detach() immediately after it returns from the callback, but before this thread returns 
+    // The debugger may call Detach() immediately after it returns from the callback, but before this thread returns
     // from this function.  Thus after we execute the callbacks, it's possible the CordbProcess object has been neutered.
-    
+
     // Since we're already sycned, the Stop from the holder here is practically a nop that just bumps up a count.
     // Create an extra scope for the StopContinueHolder.
     {
@@ -4769,13 +4769,13 @@ void CordbProcess::DispatchRCEvent()
         }
 
         HRESULT hrCallback = S_OK;
-        // It's possible a ICorDebugProcess::Detach() may have occurred by now. 
+        // It's possible a ICorDebugProcess::Detach() may have occurred by now.
         {
             // @dbgtodo shim: eventually the entire RCET should be considered outside the RS.
-            PUBLIC_CALLBACK_IN_THIS_SCOPE0_NO_LOCK(this); 
+            PUBLIC_CALLBACK_IN_THIS_SCOPE0_NO_LOCK(this);
 
 
-            // Snag the first event off the queue.    
+            // Snag the first event off the queue.
             // Holder will call Delete, which will invoke virtual Dtor that will release ICD objects.
             // Since these are external refs, we want to do it while "outside" the RS.
             NewHolder<ManagedEvent> pEvent(pShim->DequeueManagedEvent());
@@ -4796,7 +4796,7 @@ void CordbProcess::DispatchRCEvent()
                     m_pDBGLastIPCEventType = pEvent->GetDebugCookie();
 #endif
 
-                    ManagedEvent::DispatchArgs args(m_cordb->m_managedCallback, m_cordb->m_managedCallback2, m_cordb->m_managedCallback3, m_cordb->m_managedCallback4);        
+                    ManagedEvent::DispatchArgs args(m_cordb->m_managedCallback, m_cordb->m_managedCallback2, m_cordb->m_managedCallback3, m_cordb->m_managedCallback4);
 
                     {
                         // Release lock around the dispatch of the event
@@ -4807,7 +4807,7 @@ void CordbProcess::DispatchRCEvent()
                             // This dispatches almost directly into the user's callbacks.
                             // It does not update any RS state.
                             hrCallback = pEvent->Dispatch(args);
-                        } 
+                        }
                         EX_CATCH_HRESULT(hrCallback);
                     }
                 }
@@ -4819,18 +4819,18 @@ void CordbProcess::DispatchRCEvent()
         {
             ContinueInternal(FALSE);
         }
-        
-           
+
+
     } // forces Continue to be called
 
-    Lock();  
+    Lock();
 
 };
 
 #ifdef _DEBUG
 //---------------------------------------------------------------------------------------
 // Debug-only callback to ensure that an appdomain is not available after the ExitAppDomain event.
-// 
+//
 // Arguments:
 //    vmAppDomain - appdomain from enumeration
 //    pUserData - pointer to a DbgAssertAppDomainDeletedData which contains the VMAppDomain that was just deleted.
@@ -4842,23 +4842,23 @@ void CordbProcess::DbgAssertAppDomainDeletedCallback(VMPTR_AppDomain vmAppDomain
     INTERNAL_DAC_CALLBACK(pCallbackData->m_pThis);
 
     VMPTR_AppDomain vmAppDomainDeleted = pCallbackData->m_vmAppDomainDeleted;
-    CONSISTENCY_CHECK_MSGF((vmAppDomain != vmAppDomainDeleted), 
-        ("An ExitAppDomain event was sent for appdomain, but it still shows up in the enumeration.\n vmAppDomain=%p\n", 
+    CONSISTENCY_CHECK_MSGF((vmAppDomain != vmAppDomainDeleted),
+        ("An ExitAppDomain event was sent for appdomain, but it still shows up in the enumeration.\n vmAppDomain=%p\n",
         VmPtrToCookie(vmAppDomainDeleted)));
 }
 
 //---------------------------------------------------------------------------------------
 // Debug-only helper to Assert that VMPTR is actually removed.
-// 
+//
 // Arguments:
-//    vmAppDomainDeleted - vmptr of appdomain that we just got exit event for. 
+//    vmAppDomainDeleted - vmptr of appdomain that we just got exit event for.
 //       This should not be discoverable from the RS.
-//       
+//
 // Notes:
 //   See code:IDacDbiInterface#Enumeration for rules that we're asserting.
 //   Once the exit appdomain event is dispatched, the appdomain should not be discoverable by the RS.
-//   Else the RS may use the AppDomain* after it's deleted. 
-//   This asserts that the AppDomain* is not discoverable. 
+//   Else the RS may use the AppDomain* after it's deleted.
+//   This asserts that the AppDomain* is not discoverable.
 //
 //   Since this is a debug-only function, it should have no side-effects.
 void CordbProcess::DbgAssertAppDomainDeleted(VMPTR_AppDomain vmAppDomainDeleted)
@@ -4882,24 +4882,24 @@ void CordbProcess::DbgAssertAppDomainDeleted(VMPTR_AppDomain vmAppDomainDeleted)
 //    pCallback1 - callback object to dispatch on (for V1 callbacks)
 //    pCallback2 - 2nd callback object to dispatch on (for new V2 callbacks)
 //    pCallback3 - 3rd callback object to dispatch on (for new V4 callbacks)
-//       
+//
 //
 // Returns:
-//    Nothing. Throws on error. 
-//       
+//    Nothing. Throws on error.
+//
 // Notes:
 //    Generally, this will dispatch exactly 1 callback. It may dispatch 0 callbacks if there is an error
-//    or in other corner cases (documented within the dispatch code below). 
+//    or in other corner cases (documented within the dispatch code below).
 //    Errors could occur because:
 //    - the event is corrupted (exceptional case)
 //    - the RS is corrupted / OOM (exceptional case)
 //    Exception errors here will propogate back to the Filter() call, and there's not really anything
 //    a debugger can do about an error here (perhaps report it to the user).
-//    Errors must leave IcorDebug in a consistent state. 
+//    Errors must leave IcorDebug in a consistent state.
 //
 //    This is dispatched directly on the Win32Event Thread in response to calling Filter.
 //    Therefore, this can't send any IPC events (Not an issue once everything is DAC-ized).
-//    A V2 shim can provide a proxy calllack that takes these events and queues them and 
+//    A V2 shim can provide a proxy calllack that takes these events and queues them and
 //    does the real dispatch to the user to emulate V2 semantics.
 //
 #ifdef _PREFAST_
@@ -4907,9 +4907,9 @@ void CordbProcess::DbgAssertAppDomainDeleted(VMPTR_AppDomain vmAppDomainDeleted)
 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
 #endif
 void CordbProcess::RawDispatchEvent(
-    DebuggerIPCEvent *          pEvent, 
+    DebuggerIPCEvent *          pEvent,
     RSLockHolder *              pLockHolder,
-    ICorDebugManagedCallback *  pCallback1, 
+    ICorDebugManagedCallback *  pCallback1,
     ICorDebugManagedCallback2 * pCallback2,
     ICorDebugManagedCallback3 * pCallback3,
     ICorDebugManagedCallback4 * pCallback4)
@@ -4936,17 +4936,17 @@ void CordbProcess::RawDispatchEvent(
     // so if this flag is set, EP will wait on the miscWaitEvent (which will
     // get set in FlushQueuedEvents when we return from here) and let us finish here.
     //
-    StartEventDispatch(pEvent->type); 
+    StartEventDispatch(pEvent->type);
 
     // Keep strong references to these objects in case a callback deletes them from underneath us.
     RSSmartPtr<CordbAppDomain> pAppDomain;
     CordbThread * pThread = NULL;
 
-   
+
     // Get thread that this event is on. In attach scenarios, this may be the first time ICorDebug has seen this thread.
     if (!pEvent->vmThread.IsNull())
     {
-        pThread = LookupOrCreateThread(pEvent->vmThread); 
+        pThread = LookupOrCreateThread(pEvent->vmThread);
     }
 
     if (!pEvent->vmAppDomain.IsNull())
@@ -4955,7 +4955,7 @@ void CordbProcess::RawDispatchEvent(
     }
 
     DWORD dwVolatileThreadId = 0;
-    if (pThread != NULL) 
+    if (pThread != NULL)
     {
         dwVolatileThreadId = pThread->GetUniqueId();
     }
@@ -4968,7 +4968,7 @@ void CordbProcess::RawDispatchEvent(
     {
         // It shouldn't be possible for us to see an exited AppDomain here
         _ASSERTE( !pAppDomain->IsNeutered() );
-        
+
          pThread->m_pAppDomain = pAppDomain;
     }
 
@@ -4976,7 +4976,7 @@ void CordbProcess::RawDispatchEvent(
     _ASSERTE(pCallback1 != NULL);
     _ASSERTE(pCallback2 != NULL);
     _ASSERTE(pCallback3 != NULL);
-    
+    _ASSERTE(pCallback4 != NULL);
 
     STRESS_LOG1(LF_CORDB, LL_EVERYTHING, "Pre-Dispatch IPC event: %s\n", IPCENames::GetName(pEvent->type));
 
@@ -4994,11 +4994,11 @@ void CordbProcess::RawDispatchEvent(
             _ASSERTE(pThread != NULL);
             _ASSERTE(pAppDomain != NULL);
 
-            // Find the breakpoint object on this side.            
+            // Find the breakpoint object on this side.
             CordbBreakpoint *pBreakpoint = NULL;
 
             // We've found cases out in the wild where we get this event on a thread we don't recognize.
-            // We're not sure how this happens. Add a runtime check to protect ourselves to avoid the 
+            // We're not sure how this happens. Add a runtime check to protect ourselves to avoid the
             // an AV. We still assert because this should not be happening.
             // It likely means theres some issue where we failed to send a CreateThread notification.
             TargetConsistencyCheck(pThread != NULL);
@@ -5017,11 +5017,20 @@ void CordbProcess::RawDispatchEvent(
         }
         break;
 
-    case DB_IPCE_SOME_WORK:
+    case DB_IPCE_BEFORE_GARBAGE_COLLECTION:
+        {
+            {
+                PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
+                pCallback4->BeforeGarbageCollection(static_cast<ICorDebugController*>(this));
+            }
+            break;
+        }
+
+    case DB_IPCE_AFTER_GARBAGE_COLLECTION:
         {
             {
                 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
-                pCallback4->SomeWork(pThread, pAppDomain);
+                pCallback4->AfterGarbageCollection(static_cast<ICorDebugController*>(this));
             }
             break;
         }
@@ -5107,9 +5116,9 @@ void CordbProcess::RawDispatchEvent(
             // even executed jitted code on the thread. We may have not received a CreateThread yet.
             // In V2, we detected this and sent a LogMessage on a random thread.
             // In V3, we lazily create the CordbThread objects (possibly before the CreateThread event),
-            // and so we know we should have one.            
+            // and so we know we should have one.
             _ASSERTE(pThread != NULL);
-            
+
             pThread->SetExInfo(pEvent->Exception.vmExceptionHandle);
 
             _ASSERTE(pThread->m_pAppDomain != NULL);
@@ -5154,7 +5163,7 @@ void CordbProcess::RawDispatchEvent(
 
                 _ASSERTE(pAppDomain != NULL);
 
-                // A thread is reported as dead before we get the exit event.                
+                // A thread is reported as dead before we get the exit event.
                 // See code:IDacDbiInterface#IsThreadMarkedDead for the invariant being asserted here.
                 TargetConsistencyCheck(pThread->IsThreadDead());
 
@@ -5189,9 +5198,9 @@ void CordbProcess::RawDispatchEvent(
     case DB_IPCE_LOAD_MODULE:
         {
             _ASSERTE (pAppDomain != NULL);
-            CordbModule * pModule = pAppDomain->LookupOrCreateModule(pEvent->LoadModuleData.vmDomainFile);                        
-            
-            {         
+            CordbModule * pModule = pAppDomain->LookupOrCreateModule(pEvent->LoadModuleData.vmDomainFile);
+
+            {
                 pModule->SetLoadEventContinueMarker();
 
                 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
@@ -5213,7 +5222,7 @@ void CordbProcess::RawDispatchEvent(
                 this,
                 pEvent->CreateConnection.connectionId,
                 const_cast<WCHAR*> (pEvent->CreateConnection.wzConnectionName.GetString()));
-        }   
+        }
         break;
 
     case DB_IPCE_DESTROY_CONNECTION:
@@ -5245,7 +5254,7 @@ void CordbProcess::RawDispatchEvent(
                  VmPtrToCookie(pEvent->vmAppDomain));
 
             PREFIX_ASSUME (pAppDomain != NULL);
-            
+
             CordbModule *module = pAppDomain->LookupOrCreateModule(pEvent->UnloadModuleData.vmDomainFile);
 
             if (module == NULL)
@@ -5266,7 +5275,7 @@ void CordbProcess::RawDispatchEvent(
                 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
                 pCallback1->UnloadModule(pAppDomain, module);
             }
-            
+
             pAppDomain->m_modules.RemoveBase(VmPtrToCookie(pEvent->UnloadModuleData.vmDomainFile));
         }
         break;
@@ -5418,14 +5427,14 @@ void CordbProcess::RawDispatchEvent(
 
 
             // determine first whether custom notifications for this type are enabled -- if not
-            // we just return without doing anything. 
-            CordbClass * pNotificationClass = LookupClass(pAppDomain, 
-                                                          pEvent->CustomNotification.vmDomainFile, 
+            // we just return without doing anything.
+            CordbClass * pNotificationClass = LookupClass(pAppDomain,
+                                                          pEvent->CustomNotification.vmDomainFile,
                                                           pEvent->CustomNotification.classToken);
 
             // if the class is NULL, that means the debugger never enabled notifications for it. Otherwise,
-            // the CordbClass instance would already have been created when the notifications were 
-            // enabled. 
+            // the CordbClass instance would already have been created when the notifications were
+            // enabled.
             if ((pNotificationClass != NULL) && pNotificationClass->CustomNotificationsEnabled())
 
             {
@@ -5445,13 +5454,13 @@ void CordbProcess::RawDispatchEvent(
 
 
             // Enumerate may have prepopulated the appdomain, so check if it already exists.
-            // Either way, still send the CreateEvent. (We don't want to skip the Create event 
+            // Either way, still send the CreateEvent. (We don't want to skip the Create event
             // just because the debugger did an enumerate)
             // We remove AppDomains from the hash as soon as they are exited.
             pAppDomain.Assign(LookupOrCreateAppDomain(pEvent->AppDomainData.vmAppDomain));
             _ASSERTE(pAppDomain != NULL); // throws on failure
 
-            {   
+            {
                 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
                 hr = pCallback1->CreateAppDomain(this, pAppDomain);
             }
@@ -5488,11 +5497,11 @@ void CordbProcess::RawDispatchEvent(
                 m_pDefaultAppDomain = NULL;
             }
 
-            // Update any threads which were last seen in this AppDomain.  We don't 
+            // Update any threads which were last seen in this AppDomain.  We don't
             // get any notification when a thread leaves an AppDomain, so our idea
             // of what AppDomain the thread is in may be out of date.
             UpdateThreadsForAdUnload( pAppDomain );
-            
+
             // This will still maintain weak references so we could call Continue.
             AddToNeuterOnContinueList(pAppDomain);
 
@@ -5508,7 +5517,7 @@ void CordbProcess::RawDispatchEvent(
 
             // Remove this app domain. This means any attempt to lookup the AppDomain
             // will fail (which we do at the top of this method).  Since any threads (incorrectly) referring
-            // to this AppDomain have been moved to the default AppDomain, no one should be 
+            // to this AppDomain have been moved to the default AppDomain, no one should be
             // interested in looking this AppDomain up anymore.
             m_appDomains.RemoveBase(VmPtrToCookie(pEvent->vmAppDomain));
         }
@@ -5548,7 +5557,7 @@ void CordbProcess::RawDispatchEvent(
             _ASSERTE (pAppDomain != NULL);
 
             CordbAssembly * pAssembly = pAppDomain->LookupOrCreateAssembly(pEvent->AssemblyData.vmDomainAssembly);
-            
+
             if (pAssembly == NULL)
             {
                 // No assembly. This could happen if we attach right before an unload event is sent.
@@ -5711,7 +5720,7 @@ void CordbProcess::RawDispatchEvent(
             if (symFormat == IDacDbiInterface::kSymbolFormatPDB)
             {
                 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
-                
+
                 _ASSERTE(pStream != NULL); // Shouldn't send the event if we don't have a stream.
 
                 pCallback1->UpdateModuleSymbols(pAppDomain, pModule, pStream);
@@ -5737,7 +5746,7 @@ void CordbProcess::RawDispatchEvent(
                 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
 
                 pCallback2->MDANotification(
-                    this, 
+                    this,
                     pThread, // may be null
                     pExternalMDARef);
 
@@ -5878,21 +5887,21 @@ void CordbProcess::RawDispatchEvent(
             if (pThread == NULL)
             {
                 // We've found cases out in the wild where we get this event on a thread we don't recognize.
-                // We're not sure how this happens. Add a runtime check to protect ourselves to avoid the 
+                // We're not sure how this happens. Add a runtime check to protect ourselves to avoid the
                 // an AV. We still assert because this should not be happening.
                 // It likely means theres some issue where we failed to send a CreateThread notification.
-                STRESS_LOG1(LF_CORDB, LL_INFO1000, "BreakpointSetError on unrecognized thread. %p\n", pBreakpoint);                
+                STRESS_LOG1(LF_CORDB, LL_INFO1000, "BreakpointSetError on unrecognized thread. %p\n", pBreakpoint);
 
                 _ASSERTE(!"Missing thread on bp set error");
                 break;
-            }   
-            
+            }
+
             pBreakpoint = pAppDomain->m_breakpoints.GetBase(LsPtrToCookie(pEvent->BreakpointSetErrorData.breakpointToken));
 
             if (pBreakpoint != NULL)
             {
                 ICorDebugBreakpoint * pIBreakpoint = CordbBreakpointToInterface(pBreakpoint);
-                _ASSERTE(pIBreakpoint != NULL);            
+                _ASSERTE(pIBreakpoint != NULL);
             {
                     PUBLIC_CALLBACK_IN_THIS_SCOPE2(this, pLockHolder, pEvent, "thread=0x%p, bp=0x%p", pThread, pBreakpoint);
                     pCallback1->BreakpointSetError(pAppDomain, pThread, pIBreakpoint, 0);
@@ -5915,8 +5924,8 @@ void CordbProcess::RawDispatchEvent(
 
             if (pThread == NULL)
             {
-                // We've got an exception on a thread we don't know about.  This could be a thread that 
-                // has never run any managed code, so let's just ignore the exception.  We should have 
+                // We've got an exception on a thread we don't know about.  This could be a thread that
+                // has never run any managed code, so let's just ignore the exception.  We should have
                 // already sent a log message about this situation for the EXCEPTION callback above.
                 _ASSERTE( pEvent->ExceptionCallback2.eventType == DEBUG_EXCEPTION_UNHANDLED );
                 break;
@@ -5934,12 +5943,12 @@ void CordbProcess::RawDispatchEvent(
             {
                 // The interface forces us to to pass a FramePointer via an ICorDebugFrame.
                 // However, we can't get a real ICDFrame without a stackwalk, and we don't
-                // want to do a stackwalk now. so pass a netuered proxy frame. The shim 
+                // want to do a stackwalk now. so pass a netuered proxy frame. The shim
                 // can map this to a real frame.
                 // See comments at CordbPlaceHolderFrame class for details.
                 pFrame.Assign(new CordbPlaceholderFrame(this, fp));
             }
-           
+
             CorDebugExceptionCallbackType type = pEvent->ExceptionCallback2.eventType;
             {
                 PUBLIC_CALLBACK_IN_THIS_SCOPE3(this, pLockHolder, pEvent, "pThread=0x%p, frame=%p, type=%d", pThread, (ICorDebugFrame*) pFrame, type);
@@ -6000,7 +6009,7 @@ void CordbProcess::RawDispatchEvent(
             }
 
             //
-            // Tell the debugger that the exception has been intercepted.  This is similar to the 
+            // Tell the debugger that the exception has been intercepted.  This is similar to the
             // notification we give when we start unwinding for a non-intercepted exception, except that the
             // interception has been completed at this point, which means that we are conceptually at the end
             // of the second pass.
@@ -6008,9 +6017,9 @@ void CordbProcess::RawDispatchEvent(
             {
                 PUBLIC_CALLBACK_IN_THIS_SCOPE1(this, pLockHolder, pEvent, "pThread=0x%p", pThread);
                 hr = pCallback2->ExceptionUnwind(
-                    pThread->m_pAppDomain, 
-                    pThread, 
-                    DEBUG_EXCEPTION_INTERCEPTED, 
+                    pThread->m_pAppDomain,
+                    pThread,
+                    DEBUG_EXCEPTION_INTERCEPTED,
                     0);
             }
         }
@@ -6036,7 +6045,7 @@ void CordbProcess::RawDispatchEvent(
             }
             else // the lock was already held
             {
-                // see if we threw because the lock was held 
+                // see if we threw because the lock was held
                 _ASSERTE(hr == CORDBG_E_PROCESS_NOT_SYNCHRONIZED);
                 if (hr != CORDBG_E_PROCESS_NOT_SYNCHRONIZED)
                 {
@@ -6047,7 +6056,7 @@ void CordbProcess::RawDispatchEvent(
 
         }
         break;
-        
+
     case DB_IPCE_TEST_RWLOCK:
         {
             EX_TRY
@@ -6068,7 +6077,7 @@ void CordbProcess::RawDispatchEvent(
             }
             else // the lock was already held
             {
-                // see if we threw because the lock was held 
+                // see if we threw because the lock was held
                 _ASSERTE(hr == CORDBG_E_PROCESS_NOT_SYNCHRONIZED);
                 if (hr != CORDBG_E_PROCESS_NOT_SYNCHRONIZED)
                 {
@@ -6096,7 +6105,7 @@ void CordbProcess::RawDispatchEvent(
 
 //---------------------------------------------------------------------------------------
 // Callback for prepopulating threads.
-// 
+//
 // Arugments:
 //    vmThread - thread as part of the eunmeration.
 //    pUserData - data supplied with callback. It's a CordbProcess* object.
@@ -6128,7 +6137,7 @@ void CordbProcess::PrepopulateThreadsOrThrow()
 
 //---------------------------------------------------------------------------------------
 // Create a Thread enumerator
-// 
+//
 // Arguments:
 //     pOwnerObj - object (a CordbProcess or CordbThread) that will own the enumerator.
 //     pOwnerList - the neuter list that the enumerator will live on
@@ -6137,8 +6146,8 @@ void CordbProcess::PrepopulateThreadsOrThrow()
 void CordbProcess::BuildThreadEnum(CordbBase * pOwnerObj, NeuterList * pOwnerList, RSInitHolder<CordbHashTableEnum> * pHolder)
 {
     CordbHashTableEnum::BuildOrThrow(
-        pOwnerObj, 
-        pOwnerList, 
+        pOwnerObj,
+        pOwnerList,
         &m_userThreads,
         IID_ICorDebugThreadEnum,
         pHolder);
@@ -6153,7 +6162,7 @@ HRESULT CordbProcess::EnumerateThreads(ICorDebugThreadEnum **ppThreads)
         if (m_detached)
         {
             // #Detach_Check:
-            // 
+            //
             // FUTURE: Consider adding this IF block to the PUBLIC_API macros so that
             // typical public APIs fail quickly if we're trying to do a detach.  For
             // now, I'm hand-adding this check only to the few problematic APIs that get
@@ -6204,7 +6213,7 @@ HRESULT CordbProcess::GetThread(DWORD dwThreadId, ICorDebugThread **ppThread)
             // See code:CordbProcess::EnumerateThreads#Detach_Check
             ThrowHR(CORDBG_E_PROCESS_DETACHED);
         }
-        CordbThread * pThread = TryLookupOrCreateThreadByVolatileOSId(dwThreadId); 
+        CordbThread * pThread = TryLookupOrCreateThreadByVolatileOSId(dwThreadId);
         if (pThread == NULL)
         {
             // This is a common case because we may be looking up an unmanaged thread.
@@ -6292,22 +6301,22 @@ HRESULT CordbProcess::SetAllThreadsDebugState(CorDebugThreadState state,
     }
     CordbThread * pCordbExceptThread = static_cast<CordbThread *> (pExceptThread);
 
-    LOG((LF_CORDB, LL_INFO1000, "CP::SATDS: except thread=0x%08x 0x%x\n", 
-         pExceptThread, 
+    LOG((LF_CORDB, LL_INFO1000, "CP::SATDS: except thread=0x%08x 0x%x\n",
+         pExceptThread,
          (pCordbExceptThread != NULL) ? pCordbExceptThread->m_id : 0));
 
     // Send one event to the Left Side to twiddle each thread's state.
     DebuggerIPCEvent event;
-    
+
     InitIPCEvent(&event, DB_IPCE_SET_ALL_DEBUG_STATE, true, VMPTR_AppDomain::NullPtr());
-    
-    event.SetAllDebugState.vmThreadToken = ((pCordbExceptThread != NULL) ? 
+
+    event.SetAllDebugState.vmThreadToken = ((pCordbExceptThread != NULL) ?
                                             pCordbExceptThread->m_vmThreadToken : VMPTR_Thread::NullPtr());
-    
+
     event.SetAllDebugState.debugState = state;
 
     HRESULT hr = SendIPCEvent(&event, sizeof(DebuggerIPCEvent));
-    
+
     hr = WORST_HR(hr, event.hr);
 
     // If that worked, then loop over all the threads on this side and set their states.
@@ -6318,8 +6327,8 @@ HRESULT CordbProcess::SetAllThreadsDebugState(CorDebugThreadState state,
         CordbThread * pThread;
 
         // We don't need to prepopulate here (to collect LS state) because we're just updating RS state.
-        for (pThread = m_userThreads.FindFirst(&hashFind); 
-              pThread != NULL; 
+        for (pThread = m_userThreads.FindFirst(&hashFind);
+              pThread != NULL;
               pThread = m_userThreads.FindNext(&hashFind))
         {
             if (pThread != pCordbExceptThread)
@@ -6345,7 +6354,7 @@ HRESULT CordbProcess::EnumerateObjects(ICorDebugObjectEnum **ppObjects)
 
 //---------------------------------------------------------------------------------------
 //
-// Determines if the target address is a "CLR transition stub". 
+// Determines if the target address is a "CLR transition stub".
 //
 // Arguments:
 //     address - The address of an instruction to check in the target address space.
@@ -6402,7 +6411,7 @@ HRESULT CordbProcess::IsTransitionStub(CORDB_ADDRESS address, BOOL *pfTransition
 
         // Check against DAC primitives
         {
-            BOOL fIsStub2 = GetDAC()->IsTransitionStub(address);            
+            BOOL fIsStub2 = GetDAC()->IsTransitionStub(address);
             (void)fIsStub2; //prevent "unused variable" error from GCC
             CONSISTENCY_CHECK_MSGF(*pfTransitionStub == fIsStub2, ("IsStub2 failed, DAC2:%d, IPC:%d, addr:0x%p", (int) fIsStub2, (int) *pfTransitionStub, CORDB_ADDRESS_TO_PTR(address)));
 
@@ -6480,7 +6489,7 @@ HRESULT CordbProcess::SafeReadThreadContext(LSPTR_CONTEXT pContext, DT_CONTEXT *
 
         // At a minimum we have room for a whole context up to the extended registers.
     #if defined(DT_CONTEXT_EXTENDED_REGISTERS)
-        ULONG32 minContextSize = offsetof(DT_CONTEXT, ExtendedRegisters);    
+        ULONG32 minContextSize = offsetof(DT_CONTEXT, ExtendedRegisters);
     #else
         ULONG32 minContextSize = sizeof(DT_CONTEXT);
     #endif
@@ -6488,7 +6497,7 @@ HRESULT CordbProcess::SafeReadThreadContext(LSPTR_CONTEXT pContext, DT_CONTEXT *
         // Read the minimum part.
         TargetBuffer tbMin = tbFull.SubBuffer(0, minContextSize);
         SafeReadBuffer(tbMin, (BYTE*) pCtx);
-        
+
     #if defined(DT_CONTEXT_EXTENDED_REGISTERS)
         void *pCurExtReg = (void*)((UINT_PTR)pCtx + minContextSize);
         TargetBuffer tbExtended = tbFull.SubBuffer(minContextSize);
@@ -6535,7 +6544,7 @@ HRESULT CordbProcess::SafeWriteThreadContext(LSPTR_CONTEXT pContext, const DT_CO
     }
 #endif
 
-// 64 bit windows puts space for the first 6 stack parameters in the CONTEXT structure so that 
+// 64 bit windows puts space for the first 6 stack parameters in the CONTEXT structure so that
 // kernel to usermode transitions don't have to allocate a CONTEXT and do a seperate sub rsp
 // to allocate stack spill space for the arguments. This means that writing to P1Home - P6Home
 // will overwrite the arguments of some function higher on the stack, very bad. Conceptually you
@@ -6555,7 +6564,7 @@ HRESULT CordbProcess::SafeWriteThreadContext(LSPTR_CONTEXT pContext, const DT_CO
         SafeWriteBuffer(tb, (const BYTE*) pCtxSource);
     }
     EX_CATCH_HRESULT(hr);
-    
+
     return hr;
 }
 
@@ -6599,7 +6608,7 @@ HRESULT CordbProcess::GetThreadContext(DWORD threadID, ULONG32 contextSize, BYTE
 }
 
 // Public implementation of ICorDebugProcess::SetThreadContext.
-// @dbgtodo interop-debugging: this should go away in V3. Use the data-target instead. This is 
+// @dbgtodo interop-debugging: this should go away in V3. Use the data-target instead. This is
 // interop-debugging aware (and cooperates with hijacks)
 HRESULT CordbProcess::SetThreadContext(DWORD threadID, ULONG32 contextSize, BYTE context[])
 {
@@ -6648,8 +6657,8 @@ HRESULT CordbProcess::SetThreadContext(DWORD threadID, ULONG32 contextSize, BYTE
         {
             // Find the managed thread.  Returns NULL if thread is not managed.
             // If we don't have a thread prveiously cached, then there's no state to update.
-            CordbThread * pThread = TryLookupThreadByVolatileOSId(threadID); 
-            
+            CordbThread * pThread = TryLookupThreadByVolatileOSId(threadID);
+
             if (pThread != NULL)
             {
                 // In V2, we used to update the CONTEXT of the leaf chain if the chain is an unmanaged chain.
@@ -6761,9 +6770,9 @@ LExit:
 // if we've written over them. And put the int3 back in for write-memory.
 //
 // Note: If we're writing memory over top of a patch, then it must be JITted or stub code.
-// Writing over JITed or Stub code can be dangerous since the CLR may not expect it 
+// Writing over JITed or Stub code can be dangerous since the CLR may not expect it
 // (eg. JIT data structures about the code layout may be incorrect), but in certain
-// narrow cases it may be safe (eg. replacing a constant).  VS says they wouldn't expect 
+// narrow cases it may be safe (eg. replacing a constant).  VS says they wouldn't expect
 // this to work, but we'll keep the support in for legacy reasons.
 //
 // address, size - describe buffer in LS memory
@@ -6838,7 +6847,7 @@ HRESULT CordbProcess::AdjustBuffer( CORDB_ADDRESS address,
                 _ASSERTE( pbUpdatePatchTable != NULL );
                 _ASSERTE( bufferCopy != NULL );
 
-                //There can be multiple patches at the same address: we don't want 2nd+ patches to get the 
+                //There can be multiple patches at the same address: we don't want 2nd+ patches to get the
                 // break opcode, so we read from the unmodified copy.
                 m_rgUncommitedOpcode[iNextFree] =
                     CORDbgGetInstructionEx(*bufferCopy, address, patchAddress, opcode, size);
@@ -6861,7 +6870,7 @@ HRESULT CordbProcess::AdjustBuffer( CORDB_ADDRESS address,
         delete [] *bufferCopy;
         *bufferCopy = NULL;
     }
-    
+
     return S_OK;
 }
 
@@ -6984,14 +6993,14 @@ HRESULT CordbProcess::RefreshPatchTable(CORDB_ADDRESS address, SIZE_T size, BYTE
             LOG((LF_CORDB, LL_INFO10000, "Wont refresh patch table because its not valid now.\n"));
             return S_OK;
         }
-        
+
         EX_TRY
         {
             rgb = new BYTE[cbTableSlice]; // throws
 
             TargetBuffer tbSlice((BYTE*)m_runtimeOffsets.m_pPatches + offStart, cbTableSlice);
             this->SafeReadBuffer(tbSlice, rgb); // Throws;
-            
+
             // Note that rgData is a pointer in the left side address space
             m_rgData = *(BYTE**)(rgb + m_runtimeOffsets.m_offRgData - offStart);
             m_cPatch = *(ULONG*)(rgb + m_runtimeOffsets.m_offCData - offStart);
@@ -7013,7 +7022,7 @@ HRESULT CordbProcess::RefreshPatchTable(CORDB_ADDRESS address, SIZE_T size, BYTE
 
             TargetBuffer tb(m_rgData, cbPatchTable);
             this->SafeReadBuffer(tb, m_pPatchTable); // Throws
-            
+
             //As we go through the patch table we do a number of things:
             //
             // 1. collect min,max address seen for quick fail check
@@ -7092,7 +7101,7 @@ LExit:
         EX_CATCH_HRESULT(hr);
     }
 
+
     if (rgb != NULL )
     {
         delete [] rgb;
@@ -7108,7 +7117,7 @@ LExit:
 
 //---------------------------------------------------------------------------------------
 //
-// Given an address, see if there is a patch in the patch table that matches it and return 
+// Given an address, see if there is a patch in the patch table that matches it and return
 // if its an unmanaged patch or not.
 //
 // Arguments:
@@ -7116,14 +7125,14 @@ LExit:
 //     pfPatchFound - Space to store the result, TRUE if the address belongs to a
 //         patch, FALSE if not.  Only valid if this method returns a success code.
 //     pfPatchIsUnmanaged - Space to store the result, TRUE if the address is a patch
-//         and the patch is unmanaged, FALSE if not.  Only valid if this method returns a 
+//         and the patch is unmanaged, FALSE if not.  Only valid if this method returns a
 //         success code.
 //
 // Return Value:
 //     Typical HRESULT symantics, nothing abnormal.
 //
-// Note: this method is pretty in-efficient. It refreshes the patch table, then scans it. 
-//     Refreshing the patch table involves a scan, too, so this method could be folded 
+// Note: this method is pretty in-efficient. It refreshes the patch table, then scans it.
+//     Refreshing the patch table involves a scan, too, so this method could be folded
 //     with that.
 //
 //---------------------------------------------------------------------------------------
@@ -7267,13 +7276,13 @@ HRESULT CordbProcess::WriteMemory(CORDB_ADDRESS address, DWORD size,
                 "(This assert is only enabled under the COM+ knob DbgCheckInt3.)\n",
                 CORDB_ADDRESS_TO_PTR(address)));
         }
-#endif // DBG_TARGET_X86 || DBG_TARGET_AMD64   
+#endif // DBG_TARGET_X86 || DBG_TARGET_AMD64
 
         // check if we're replaced an opcode.
         if (size == 1)
         {
             RSLockHolder ch(&this->m_processMutex);
-            
+
             NativePatch * p = GetNativePatch(CORDB_ADDRESS_TO_PTR(address));
             if (p != NULL)
             {
@@ -7304,7 +7313,7 @@ HRESULT CordbProcess::WriteMemory(CORDB_ADDRESS address, DWORD size,
     if (m_initialized)
     {
         RSLockHolder ch(&this->m_processMutex);
-        
+
         if (m_pPatchTable == NULL )
         {
             if (!SUCCEEDED( hr = RefreshPatchTable() ) )
@@ -7340,7 +7349,7 @@ HRESULT CordbProcess::WriteMemory(CORDB_ADDRESS address, DWORD size,
         else
             hrSaved = hr;
     }
-    
+
 
     LOG((LF_CORDB, LL_INFO100000, "CP::WM: wrote %d bytes at 0x%08x, first byte is 0x%x\n",
          *written, (DWORD)address, buffer[0]));
@@ -7489,7 +7498,7 @@ CordbUnmanagedThread *CordbProcess::HandleUnmanagedCreateThread(DWORD dwThreadId
 // Note: Throws on error
 //-----------------------------------------------------------------------------
 void CordbProcess::InitDac()
-{        
+{
     // Go-Go DAC power!!
     HRESULT hr = S_OK;
     EX_TRY
@@ -7506,7 +7515,7 @@ void CordbProcess::InitDac()
         // - a CLR dev built mscorwks but didn't build DAC.
         SIMPLIFYING_ASSUMPTION_MSGF(false, ("Failed to load DAC while for debugging. hr=0x%08x", hr));
         ThrowHR(hr);
-    }   
+    }
 } //CordbProcess::InitDac
 
 // Update the entire RS copy of the debugger control block by reading the LS copy. The RS copy is treated as
@@ -7515,8 +7524,8 @@ void CordbProcess::InitDac()
 // update everything for simplicity; any perf hit we take by doing this instead of updating the individual
 // fields we want at any given point isn't significant, particularly if we are updating multiple fields.
 
-// Arguments: 
-//     none, but reads process memory from the LS debugger control block 
+// Arguments:
+//     none, but reads process memory from the LS debugger control block
 // Return Value: none (copies from LS DCB to RS buffer GetDCB())
 // Note: throws if SafeReadBuffer fails
 void CordbProcess::UpdateRightSideDCB()
@@ -7526,7 +7535,7 @@ void CordbProcess::UpdateRightSideDCB()
 
 // Update a single field with a value stored in the RS copy of the DCB. We can't update the entire LS DCB
 // because in some cases, the LS and RS are simultaneously initializing the DCB. If we initialize a field on
-// the RS and write back the whole thing, we may overwrite something the LS has initialized in the interim. 
+// the RS and write back the whole thing, we may overwrite something the LS has initialized in the interim.
 
 // Arguments:
 //     input: rsFieldAddr - the address of the field in the RS copy of the DCB that we want to write back to
@@ -7545,28 +7554,28 @@ void CordbProcess::UpdateLeftSideDCBField(void * rsFieldAddr, SIZE_T size)
 //-----------------------------------------------------------------------------
 // Gets the remote address of the event block for the Target and verifies that it's valid.
 // We use this address when we need to read from or write to the debugger control block.
-// Also allocates the RS buffer used for temporary storage for information from the DCB and 
+// Also allocates the RS buffer used for temporary storage for information from the DCB and
 // copies the LS DCB into the RS buffer.
 // Arguments:
 //     output: pfBlockExists - true iff the LS DCB has been successfully allocated.  Note that
-//             we need this information even if the function throws, so we can't simply send it back 
+//             we need this information even if the function throws, so we can't simply send it back
 //             as a return value.
 // Return value:
-//     None, but allocates GetDCB() on success. If the LS DCB has not  
-//     been successfully initialized or if this throws, GetDCB() will be NULL. 
+//     None, but allocates GetDCB() on success. If the LS DCB has not
+//     been successfully initialized or if this throws, GetDCB() will be NULL.
 //
 // Notes:
 //     Throws on error
 //
 //-----------------------------------------------------------------------------
 void CordbProcess::GetEventBlock(BOOL * pfBlockExists)
-{    
+{
     if (GetDCB() == NULL) // we only need to do this once
     {
         _ASSERTE(m_pShim != NULL);
         _ASSERTE(ThreadHoldsProcessLock());
 
-        // This will Initialize the DAC/DBI interface.     
+        // This will Initialize the DAC/DBI interface.
         BOOL fDacReady = TryInitializeDac();
 
         if (fDacReady)
@@ -7581,11 +7590,11 @@ void CordbProcess::GetEventBlock(BOOL * pfBlockExists)
             if (pLeftSideDCB == NULL)
             {
                 *pfBlockExists = false;
-                ThrowHR(CORDBG_E_DEBUGGING_NOT_POSSIBLE); 
+                ThrowHR(CORDBG_E_DEBUGGING_NOT_POSSIBLE);
             }
 
-            IfFailThrow(NewEventChannelForThisPlatform(pLeftSideDCB, 
-                                                       m_pMutableDataTarget, 
+            IfFailThrow(NewEventChannelForThisPlatform(pLeftSideDCB,
+                                                       m_pMutableDataTarget,
                                                        GetPid(),
                                                        m_pShim->GetMachineInfo(),
                                                        &m_pEventChannel));
@@ -7595,12 +7604,12 @@ void CordbProcess::GetEventBlock(BOOL * pfBlockExists)
             UpdateRightSideDCB();
 
             // Verify that the control block is valid.
-            // This  will throw on error. 
-            VerifyControlBlock();   
-            
+            // This  will throw on error.
+            VerifyControlBlock();
+
             *pfBlockExists = true;
         }
-        else 
+        else
         {
             // we can't initialize the DAC, so we can't get the block
             *pfBlockExists = false;
@@ -7635,7 +7644,7 @@ void CordbProcess::VerifyControlBlock()
     UpdateLeftSideDCBField(&(GetDCB()->m_rightSideProtocolCurrent), sizeof(GetDCB()->m_rightSideProtocolCurrent));
 
     GetDCB()->m_rightSideProtocolMinSupported = CorDB_RightSideProtocolMinSupported;
-    UpdateLeftSideDCBField(&(GetDCB()->m_rightSideProtocolMinSupported), 
+    UpdateLeftSideDCBField(&(GetDCB()->m_rightSideProtocolMinSupported),
                            sizeof(GetDCB()->m_rightSideProtocolMinSupported));
 
     // For Telesto, Dbi and Wks have a more flexible versioning allowed, as described by the Debugger
@@ -7650,7 +7659,7 @@ void CordbProcess::VerifyControlBlock()
     // But just in case the installation is corrupted, we'll check it.
     if (GetDCB()->m_DCBSize != sizeof(DebuggerIPCControlBlock))
     {
-        CONSISTENCY_CHECK_MSGF(false, ("DCB in LS is %d bytes, in RS is %d bytes. Version mismatch!!\n", 
+        CONSISTENCY_CHECK_MSGF(false, ("DCB in LS is %d bytes, in RS is %d bytes. Version mismatch!!\n",
                                GetDCB()->m_DCBSize, sizeof(DebuggerIPCControlBlock)));
         ThrowHR(CORDBG_E_INCOMPATIBLE_PROTOCOL);
     }
@@ -7740,7 +7749,7 @@ HRESULT CordbProcess::GetRuntimeOffsets()
 
     // get the remote address of the runtime offsets structure and read the structure itself
     HRESULT hrRead = SafeReadStruct(PTR_TO_CORDB_ADDRESS(GetDCB()->m_pRuntimeOffsets), &m_runtimeOffsets);
-    
+
     if (FAILED(hrRead))
     {
         return hrRead;
@@ -7824,7 +7833,7 @@ HRESULT CordbProcess::GetRuntimeOffsets()
             m_runtimeOffsets.m_excepNotForRuntimeBPAddr,
             m_runtimeOffsets.m_notifyRSOfSyncCompleteBPAddr,
         };
-        
+
         const int NumFlares = NumItems(flares);
 
         // Ensure that all of the flares are unique.
@@ -7971,7 +7980,7 @@ void CordbProcess::QueueUnmanagedEvent(CordbUnmanagedThread *pUThread, const DEB
         // the event then it did not.
         _ASSERTE(ue->IsEventContinuedUnhijacked());
         LOG((LF_CORDB, LL_INFO10000, "CP::QUE: A previously seen event is being discarded 0x%x 0x%p\n",
-         ue->m_currentDebugEvent.u.Exception.ExceptionRecord.ExceptionCode, 
+         ue->m_currentDebugEvent.u.Exception.ExceptionRecord.ExceptionCode,
          ue->m_currentDebugEvent.u.Exception.ExceptionRecord.ExceptionAddress));
         DequeueUnmanagedEvent(ue->m_owner);
     }
@@ -8418,12 +8427,12 @@ HRESULT CordbProcess::StartSyncFromWin32Stop(BOOL * pfAsyncBreakSent)
     // The process can be running free as far as Win32 events are concerned, but still not synchronized as far as the
     // Runtime is concerned. This can happen in a lot of cases where we end up with the Runtime not sync'd but with the
     // process running free due to hijacking, etc...
-    if (((m_state & CordbProcess::PS_WIN32_STOPPED) && (m_outOfBandEventQueue == NULL)) || 
+    if (((m_state & CordbProcess::PS_WIN32_STOPPED) && (m_outOfBandEventQueue == NULL)) ||
         (!GetSynchronized() && IsInteropDebugging()))
     {
         Lock();
 
-        if (((m_state & CordbProcess::PS_WIN32_STOPPED) && (m_outOfBandEventQueue == NULL)) || 
+        if (((m_state & CordbProcess::PS_WIN32_STOPPED) && (m_outOfBandEventQueue == NULL)) ||
             (!GetSynchronized() && IsInteropDebugging()))
         {
             // This can't be the win32 ET b/c we need that thread to be alive and pumping win32 DE so that
@@ -8575,17 +8584,17 @@ void CordbProcess::UnrecoverableError(HRESULT errorHR,
     // debugger while inside CordbProcess::DispatchRCEvent() (as that function deliberately
     // calls Unlock() while calling into the Shim).  Detect such cases here & bail before we
     // try to access invalid fields on this CordbProcess.
-    // 
+    //
     // Normally, we'd need to take the cordb process lock around the IsNeutered check
     // (and the code that follows).  And perhaps this is a good thing to do in the
     // future.  But for now we're not for two reasons:
-    // 
+    //
     // 1) It's scary.  We're in UnrecoverableError() for gosh sake.  I don't know all
     // the possible bad states we can be in to get here.  Will taking the process lock
     // have ordering issues?  Will the process lock even be valid to take here (or might
     // we AV)?  Since this is error handling, we should probably be as light as we can
     // not to cause more errors.
-    // 
+    //
     // 2) It's unnecessary.  For the Watson dump I investigated that caused this fix in
     // the first place, we already detached before entering UnrecoverableError()
     // (indeed, the only reason we're in UnrecoverableError is that we already detached
@@ -8605,7 +8614,7 @@ void CordbProcess::UnrecoverableError(HRESULT errorHR,
         // @dbgtodo - , shim: Once everything is hoisted, we can remove
         // this code.
         // In the v3 case, we should never get an unrecoverable error. Instead, the HR should be propogated
-        // and returned at the top-level public API. 
+        // and returned at the top-level public API.
         _ASSERTE(!"Unrecoverable error dispatched in V3 case.");
     }
 
@@ -8639,7 +8648,7 @@ void CordbProcess::UnrecoverableError(HRESULT errorHR,
         }
         EX_CATCH
         {
-            _ASSERTE(!"Writing process memory failed, perhaps due to an unexpected disconnection from the target."); 
+            _ASSERTE(!"Writing process memory failed, perhaps due to an unexpected disconnection from the target.");
         }
         EX_END_CATCH(SwallowAllExceptions);
     }
@@ -8664,7 +8673,7 @@ HRESULT CordbProcess::CheckForUnrecoverableError()
 {
     HRESULT hr = S_OK;
 
-    if (GetDCB() != NULL) 
+    if (GetDCB() != NULL)
     {
         // be sure we have the latest information
         UpdateRightSideDCB();
@@ -8743,11 +8752,11 @@ COM_METHOD CordbProcess::ModifyLogSwitch(__in_z WCHAR *pLogSwitchName, LONG lLev
 //    cbSize - the size of local buffer
 //
 // Exceptions
-//    On error throws the result of WriteVirtual unless a short write is performed, 
+//    On error throws the result of WriteVirtual unless a short write is performed,
 //    in which case throws ERROR_PARTIAL_COPY
 //
-void CordbProcess::SafeWriteBuffer(TargetBuffer tb, 
-                                   const BYTE * pLocalBuffer) 
+void CordbProcess::SafeWriteBuffer(TargetBuffer tb,
+                                   const BYTE * pLocalBuffer)
 {
     _ASSERTE(m_pMutableDataTarget != NULL);
     HRESULT hr = m_pMutableDataTarget->WriteVirtual(tb.pAddress,
@@ -8778,10 +8787,10 @@ HRESULT CordbProcess::SafeReadBuffer(TargetBuffer tb, BYTE * pLocalBuffer, BOOL
     ULONG32 cbRead;
     HRESULT hr = m_pDACDataTarget->ReadVirtual(tb.pAddress,
         pLocalBuffer,
-        tb.cbSize, 
+        tb.cbSize,
         &cbRead);
 
-    if (FAILED(hr)) 
+    if (FAILED(hr))
     {
         if (throwOnError)
             ThrowHR(CORDBG_E_READVIRTUAL_FAILURE);
@@ -8807,12 +8816,12 @@ HRESULT CordbProcess::SafeReadBuffer(TargetBuffer tb, BYTE * pLocalBuffer, BOOL
 //     vmAppDomain - CLR appdomain to lookup
 //
 // Returns:
-//     Instance of CordbAppDomain for the given appdomain. This is a cached instance. 
-//     If the CordbAppDomain does not yet exist, it will be created and added to the cache. 
+//     Instance of CordbAppDomain for the given appdomain. This is a cached instance.
+//     If the CordbAppDomain does not yet exist, it will be created and added to the cache.
 //     Never returns NULL. Throw on error.
 CordbAppDomain * CordbProcess::LookupOrCreateAppDomain(VMPTR_AppDomain vmAppDomain)
 {
-    CordbAppDomain * pAppDomain = m_appDomains.GetBase(VmPtrToCookie(vmAppDomain));    
+    CordbAppDomain * pAppDomain = m_appDomains.GetBase(VmPtrToCookie(vmAppDomain));
     if (pAppDomain != NULL)
     {
         return pAppDomain;
@@ -8831,7 +8840,7 @@ CordbAppDomain * CordbProcess::GetSharedAppDomain()
         }
                m_sharedAppDomain->InternalAddRef();
     }
-    
+
     return m_sharedAppDomain;
 }
 
@@ -8843,12 +8852,12 @@ CordbAppDomain * CordbProcess::GetSharedAppDomain()
 //      vmAppDomain - appdomain to add.
 //
 // Return Value:
-//    Pointer to newly created appdomain, which should be the normal case. 
+//    Pointer to newly created appdomain, which should be the normal case.
 //    Throws on failure. Never returns null.
 //
 // Assumptions:
 //    Caller ensure the appdomain is not already cached.
-//    Caller should have stop-go lock, which provides thread-safety. 
+//    Caller should have stop-go lock, which provides thread-safety.
 //
 // Notes:
 //    This sets unrecoverable error on failure.
@@ -8862,8 +8871,8 @@ CordbAppDomain * CordbProcess::CacheAppDomain(VMPTR_AppDomain vmAppDomain)
 
     RSInitHolder<CordbAppDomain> pAppDomain;
     pAppDomain.Assign(new CordbAppDomain(this, vmAppDomain));  // throws
-  
-    // Add to the hash. This will addref the pAppDomain. 
+
+    // Add to the hash. This will addref the pAppDomain.
     // Caller ensures we're not already cached.
     // The cache will take ownership.
     m_appDomains.AddBaseOrThrow(pAppDomain);
@@ -8898,7 +8907,7 @@ CordbAppDomain * CordbProcess::CacheAppDomain(VMPTR_AppDomain vmAppDomain)
 //
 //
 // Assumptions:
-//    Invoked as callback from code:CordbProcess::PrepopulateAppDomains 
+//    Invoked as callback from code:CordbProcess::PrepopulateAppDomains
 //
 //
 //---------------------------------------------------------------------------------------
@@ -8943,8 +8952,8 @@ void CordbProcess::PrepopulateAppDomainsOrThrow()
     CONTRACTL_END;
 
     INTERNAL_API_ENTRY(this);
-    
-    if (!IsDacInitialized()) 
+
+    if (!IsDacInitialized())
     {
         return;
     }
@@ -8966,7 +8975,7 @@ void CordbProcess::PrepopulateAppDomainsOrThrow()
 //    S_OK on success.
 //
 // Assumptions:
-//    
+//
 //
 // Notes:
 //    This operation is non-invasive target.
@@ -8980,16 +8989,16 @@ HRESULT CordbProcess::EnumerateAppDomains(ICorDebugAppDomainEnum **ppAppDomains)
         ValidateOrThrow(ppAppDomains);
 
         // Ensure list is populated.
-        PrepopulateAppDomainsOrThrow(); 
-        
+        PrepopulateAppDomainsOrThrow();
+
         RSInitHolder<CordbHashTableEnum> pEnum;
         CordbHashTableEnum::BuildOrThrow(
-            this, 
-            GetContinueNeuterList(), 
+            this,
+            GetContinueNeuterList(),
             &m_appDomains,
             IID_ICorDebugAppDomainEnum,
             pEnum.GetAddr());
-        
+
         *ppAppDomains = static_cast<ICorDebugAppDomainEnum*> (pEnum);
         pEnum->ExternalAddRef();
 
@@ -9015,7 +9024,7 @@ HRESULT CordbProcess::GetObject(ICorDebugValue **ppObject)
 
 //---------------------------------------------------------------------------------------
 //
-// Given a taskid, finding the corresponding thread. The function can fail if we do not 
+// Given a taskid, finding the corresponding thread. The function can fail if we do not
 // find any thread with the given taskid
 //
 // Arguments:
@@ -9042,7 +9051,7 @@ HRESULT CordbProcess::GetThreadForTaskID(TASKID taskId, ICorDebugThread2 ** ppTh
             ThrowHR(E_INVALIDARG);
         }
 
-        // On initialization, the task ID of every thread is INVALID_TASK_ID, unless a host is present and 
+        // On initialization, the task ID of every thread is INVALID_TASK_ID, unless a host is present and
         // the host calls IClrTask::SetTaskIdentifier().  So we need to explicitly check for INVALID_TASK_ID
         // here and return NULL if necessary.  We return S_FALSE because that's the return value for the case
         // where we can't find a thread for the specified task ID.
@@ -9054,12 +9063,12 @@ HRESULT CordbProcess::GetThreadForTaskID(TASKID taskId, ICorDebugThread2 ** ppTh
         else
         {
             PrepopulateThreadsOrThrow();
-            
+
             // now find the ICorDebugThread corresponding to it
             CordbThread * pThread;
             HASHFIND hashFind;
 
-            
+
             for (pThread  = m_userThreads.FindFirst(&hashFind);
                  pThread != NULL;
                  pThread  = m_userThreads.FindNext(&hashFind))
@@ -9068,7 +9077,7 @@ HRESULT CordbProcess::GetThreadForTaskID(TASKID taskId, ICorDebugThread2 ** ppTh
                 {
                     break;
                 }
-            }    
+            }
 
             if (pThread == NULL)
             {
@@ -9113,7 +9122,7 @@ CordbProcess::GetVersion(COR_VERSION* pVersion)
 NativePatch * CordbProcess::GetNativePatch(const void * pAddress)
 {
     _ASSERTE(ThreadHoldsProcessLock());
-    
+
     int cTotal = m_NativePatchList.Count();
     NativePatch * pTable = m_NativePatchList.Table();
     if (pTable == NULL)
@@ -9147,8 +9156,8 @@ bool CordbProcess::IsBreakOpcodeAtAddress(const void * address)
 #endif
 
     HRESULT hr = SafeReadStruct(PTR_TO_CORDB_ADDRESS(address), &opcodeTest);
-    SIMPLIFYING_ASSUMPTION_SUCCEEDED(hr); 
-    
+    SIMPLIFYING_ASSUMPTION_SUCCEEDED(hr);
+
     return (opcodeTest == CORDbg_BREAK_INSTRUCTION);
 }
 #endif // FEATURE_INTEROP_DEBUGGING
@@ -9289,7 +9298,7 @@ CordbProcess::ClearUnmanagedBreakpoint(CORDB_ADDRESS address)
     PUBLIC_API_ENTRY(this);
     FAIL_IF_NEUTERED(this);
     FAIL_IF_MANAGED_ONLY(this);
-    
+
     _ASSERTE(!ThreadHoldsProcessLock());
 
     HRESULT hr = S_OK;
@@ -9418,7 +9427,7 @@ void CordbProcess::SetSyncCompleteRecv(bool fSyncRecv)
 
 // This can be used if we ever need the RS to emulate old behavior of previous versions.
 // This can not be used in QIs to deny queries for new interfaces.
-// QIs must be consistent across the lifetime of an object. Say CordbThread used this in a QI 
+// QIs must be consistent across the lifetime of an object. Say CordbThread used this in a QI
 // do deny returning a ICorDebugThread2 interface when emulating v1.1. Once that Thread is neutered,
 // it no longer has a pointer to the process, and it no longer knows if it should be denying
 // the v2.0 query. An object's QI can't start returning new interfaces onces its neutered.
@@ -9431,12 +9440,12 @@ bool CordbProcess::SupportsVersion(CorDebugInterfaceVersion featureVersion)
 
 //---------------------------------------------------------------------------------------
 // Add an object to the process's Left-Side resource cleanup list
-// 
+//
 // Arguments:
 //    pObject - non-null object to be added
-//    
+//
 // Notes:
-//    This list tracks objects with process-scope that hold left-side 
+//    This list tracks objects with process-scope that hold left-side
 //    resources (like func-eval).
 //    See code:CordbAppDomain::GetSweepableExitNeuterList for per-appdomain
 //    objects with left-side resources.
@@ -9444,7 +9453,7 @@ void CordbProcess::AddToLeftSideResourceCleanupList(CordbBase * pObject)
 {
     INTERNAL_API_ENTRY(this);
     _ASSERTE(pObject != NULL);
-    
+
     m_LeftSideResourceCleanupList.Add(this, pObject);
 }
 
@@ -9453,12 +9462,12 @@ void CordbProcess::AddToNeuterOnExitList(CordbBase *pObject)
 {
     INTERNAL_API_ENTRY(this);
     _ASSERTE(pObject != NULL);
-    
+
     HRESULT hr = S_OK;
     EX_TRY
     {
         this->m_ExitNeuterList.Add(this, pObject);
-    } 
+    }
     EX_CATCH_HRESULT(hr);
     SetUnrecoverableIfFailed(GetProcess(), hr);
 }
@@ -9469,7 +9478,7 @@ void CordbProcess::AddToNeuterOnContinueList(CordbBase *pObject)
     INTERNAL_API_ENTRY(this);
     _ASSERTE(pObject != NULL);
 
-    m_ContinueNeuterList.Add(this, pObject); // throws 
+    m_ContinueNeuterList.Add(this, pObject); // throws
 }
 
 
@@ -9548,7 +9557,7 @@ void CordbProcess::DuplicateHandleToLocalProcess(HANDLE * pLocalHandle, RemoteHA
     {
         BOOL fSuccess = pRemoteHandle->DuplicateToLocalProcess(m_handle, pLocalHandle);
         if (!fSuccess)
-        {            
+        {
             ThrowLastError();
         }
     }
@@ -9602,7 +9611,7 @@ void CordbProcess::FinishInitializeIPCChannelWorker()
         LOG((LF_CORDB, LL_INFO1000, "[%x] RCET::HFRCE: first event..., process %p\n", GetCurrentThreadId(), this));
 
         BOOL fBlockExists;
-        GetEventBlock(&fBlockExists); // throws on error   
+        GetEventBlock(&fBlockExists); // throws on error
 
         LOG((LF_CORDB, LL_EVERYTHING, "Size of CdbP is %d\n", sizeof(CordbProcess)));
 
@@ -9611,7 +9620,7 @@ void CordbProcess::FinishInitializeIPCChannelWorker()
 #if defined(FEATURE_INTEROP_DEBUGGING)
         DuplicateHandleToLocalProcess(&m_leftSideUnmanagedWaitEvent, &GetDCB()->m_leftSideUnmanagedWaitEvent);
 #endif // FEATURE_INTEROP_DEBUGGING
-        
+
         // Read the Runtime Offsets struct out of the debuggee.
         hr = GetRuntimeOffsets();
         IfFailThrow(hr);
@@ -9619,11 +9628,11 @@ void CordbProcess::FinishInitializeIPCChannelWorker()
         // we need to be careful here. The LS will have a thread running free that may be initializing
         // fields of the DCB (specifically it may be setting up the helper thread), so we need to make sure
         // we don't overwrite any fields that the LS is writing. We need to be sure we only write to RS
-        // status fields. 
+        // status fields.
         m_initialized = true;
         GetDCB()->m_rightSideIsWin32Debugger = IsInteropDebugging();
         UpdateLeftSideDCBField(&(GetDCB()->m_rightSideIsWin32Debugger), sizeof(GetDCB()->m_rightSideIsWin32Debugger));
-            
+
         LOG((LF_CORDB, LL_INFO1000, "[%x] RCET::HFRCE: ...went fine\n", GetCurrentThreadId()));
         _ASSERTE(SUCCEEDED(hr));
 
@@ -9636,7 +9645,7 @@ void CordbProcess::FinishInitializeIPCChannelWorker()
     // We only land here on failure cases.
     // We must have jumped to this label. Maybe we didn't set HR, so check now.
     STRESS_LOG1(LF_CORDB, LL_INFO1000, "HFCR: FAILED hr=0x%08x\n", hr);
-        
+
     CloseIPCHandles();
 
     // Rethrow
@@ -9653,10 +9662,10 @@ void CordbProcess::FinishInitializeIPCChannelWorker()
 // Throws on error
 void Ls_Rs_BaseBuffer::CopyLSDataToRSWorker(ICorDebugDataTarget * pTarget)
 {
-    // 
+    //
     const DWORD cbCacheSize = m_cbSize;
-    
-    // SHOULD not happen for more than once in well-behaved case.    
+
+    // SHOULD not happen for more than once in well-behaved case.
     if (m_pbRS != NULL)
     {
         SIMPLIFYING_ASSUMPTION(!"m_pbRS is non-null; is this a corrupted event?");
@@ -9664,7 +9673,7 @@ void Ls_Rs_BaseBuffer::CopyLSDataToRSWorker(ICorDebugDataTarget * pTarget)
     }
 
     NewHolder<BYTE> pData(new BYTE[cbCacheSize]);
-    
+
     ULONG32 cbRead;
     HRESULT hrRead = pTarget->ReadVirtual(PTR_TO_CORDB_ADDRESS(m_pbLS), pData, cbCacheSize , &cbRead);
 
@@ -9672,7 +9681,7 @@ void Ls_Rs_BaseBuffer::CopyLSDataToRSWorker(ICorDebugDataTarget * pTarget)
     {
         hrRead = CORDBG_E_READVIRTUAL_FAILURE;
     }
-    
+
     if (SUCCEEDED(hrRead) && (cbCacheSize != cbRead))
     {
         hrRead = HRESULT_FROM_WIN32(ERROR_PARTIAL_COPY);
@@ -9681,7 +9690,7 @@ void Ls_Rs_BaseBuffer::CopyLSDataToRSWorker(ICorDebugDataTarget * pTarget)
 
     // Now do Transfer
     m_pbRS = pData;
-    pData.SuppressRelease();   
+    pData.SuppressRelease();
 }
 
 //---------------------------------------------------------------------------------------
@@ -9704,20 +9713,20 @@ void Ls_Rs_ByteBuffer::CopyLSDataToRS(ICorDebugDataTarget * pTarget)
 //
 // Throws on error
 void Ls_Rs_StringBuffer::CopyLSDataToRS(ICorDebugDataTarget * pTarget)
-{        
+{
     CopyLSDataToRSWorker(pTarget);
-    
+
     // Ensure we're a valid, well-formed string.
     // @dbgtodo - this should only happen in corrupted scenarios. Perhaps a better HR here?
     // - null terminated.
     // - no embedded nulls.
-    
+
     const WCHAR * pString = GetString();
     SIZE_T dwExpectedLenWithNull = m_cbSize / sizeof(WCHAR);
-    
+
     // Should at least have 1 character for the null-terminator.
     if (dwExpectedLenWithNull == 0)
-    {        
+    {
         ThrowHR(CORDBG_E_TARGET_INCONSISTENT);
     }
 
@@ -9749,17 +9758,17 @@ void Ls_Rs_StringBuffer::CopyLSDataToRS(ICorDebugDataTarget * pTarget)
 //
 // Assumptions:
 //    Target is currently stopped and inspectable.
-//    After the event is marshalled, it has resources that must be cleaned up 
+//    After the event is marshalled, it has resources that must be cleaned up
 //    by calling code:DeleteIPCEventHelper.
-// 
+//
 // Notes:
 //     Call a Copy function (CopyManagedEventFromTarget, CopyRCEventFromIPCBlock)to
 //     get the event to marshal.
 //     This will marshal args from the target into the host.
-//     The debug event is fixed size. But since the debuggee is stopped, this can copy 
-//     arbitrary-length buffers out of of the debuggee. 
+//     The debug event is fixed size. But since the debuggee is stopped, this can copy
+//     arbitrary-length buffers out of of the debuggee.
 //
-//     This could be rolled into code:CordbProcess::RawDispatchEvent 
+//     This could be rolled into code:CordbProcess::RawDispatchEvent
 //---------------------------------------------------------------------------------------
 void CordbProcess::MarshalManagedEvent(DebuggerIPCEvent * pManagedEvent)
 {
@@ -9799,7 +9808,7 @@ void CordbProcess::MarshalManagedEvent(DebuggerIPCEvent * pManagedEvent)
             break;
     }
 
-    
+
 }
 
 
@@ -9815,37 +9824,37 @@ void CordbProcess::MarshalManagedEvent(DebuggerIPCEvent * pManagedEvent)
 //    loaded into the target and all sending events wit the same exception code.
 //    * False if this does not belong to this instance of ICorDebug. (perhaps it's an event
 //    intended for another instance of the CLR in the target, or some rogue user code happening
-//    to use our exception code).  
+//    to use our exception code).
 //    In either case, the event can still be cleaned up via code:DeleteIPCEventHelper.
 //
 //    Throws on error. In the error case, the contents of pLocalManagedEvent are undefined.
-//    They may have been partially copied from the target. The local managed event does not own 
+//    They may have been partially copied from the target. The local managed event does not own
 //    any resources until it's marshalled, so the buffer can be ignored if this function fails.
 //
 // Assumptions:
 //
 // Notes:
 //    The events are sent form the target via code:Debugger::SendRawEvent
-//    This just does a raw Byte copy, but does not do any Marshalling. 
-//    This should always succeed in the well-behaved case. However, A bad debuggee can 
+//    This just does a raw Byte copy, but does not do any Marshalling.
+//    This should always succeed in the well-behaved case. However, A bad debuggee can
 //    always send a poor-formed debug event.
 //    We don't distinguish between a badly formed event and an event that's not ours.
 //    The event still needs to be Marshaled before being used. (see code:CordbProcess::MarshalManagedEvent)
 //
 //---------------------------------------------------------------------------------------
-#if defined(_MSC_VER) && defined(_TARGET_ARM_) 
+#if defined(_MSC_VER) && defined(_TARGET_ARM_)
 // This is a temporary workaround for an ARM specific MS C++ compiler bug (internal LKG build 18.1).
 // Branch < if (ptrRemoteManagedEvent == NULL) > was always taken and the function always returned false.
 // TODO: It should be removed once the bug is fixed.
 #pragma optimize("", off)
 #endif
 bool CordbProcess::CopyManagedEventFromTarget(
-    const EXCEPTION_RECORD * pRecord, 
+    const EXCEPTION_RECORD * pRecord,
     DebuggerIPCEvent * pLocalManagedEvent)
 {
     _ASSERTE(pRecord != NULL);
     _ASSERTE(pLocalManagedEvent != NULL);
-    
+
     // Initialize the event enough such backout code can call code:DeleteIPCEventHelper.
     pLocalManagedEvent->type = DB_IPCE_DEBUGGER_INVALID;
 
@@ -9875,40 +9884,40 @@ bool CordbProcess::CopyManagedEventFromTarget(
     // For Mac remote debugging the address returned above is actually a local address.
     // Also, we need to copy the entire buffer because once a debug event is read from the debugger
     // transport, it won't be available afterwards.
-    memcpy(reinterpret_cast<BYTE *>(pLocalManagedEvent), 
-           CORDB_ADDRESS_TO_PTR(ptrRemoteManagedEvent), 
+    memcpy(reinterpret_cast<BYTE *>(pLocalManagedEvent),
+           CORDB_ADDRESS_TO_PTR(ptrRemoteManagedEvent),
            CorDBIPC_BUFFER_SIZE);
     hr = S_OK;
-#endif 
-    SIMPLIFYING_ASSUMPTION(SUCCEEDED(hr)); 
+#endif
+    SIMPLIFYING_ASSUMPTION(SUCCEEDED(hr));
     IfFailThrow(hr);
 
     return true;
 }
-#if defined(_MSC_VER) && defined(_TARGET_ARM_) 
+#if defined(_MSC_VER) && defined(_TARGET_ARM_)
 #pragma optimize("", on)
 #endif
 
 //---------------------------------------------------------------------------------------
 // EnsureClrInstanceIdSet - Ensure we have a CLR Instance ID to debug
-// 
+//
 // In Arrowhead scenarios, the debugger is required to pass a valid CLR instance ID
-// to us in OpenVirtualProcess.  In V2 scenarios, for compatibility, we'll allow a 
+// to us in OpenVirtualProcess.  In V2 scenarios, for compatibility, we'll allow a
 // CordbProcess object to exist for a process that doesn't yet have the CLR loaded.
 // In this case the CLR instance ID will start off as 0, but be filled in when we see the
 // startup exception indicating the CLR has been loaded.
 //
 // If we don't already have an instance ID, this function sets it to the only CLR in the
 // target process.  This requires that a CLR be loaded in the target process.
-// 
+//
 // Return Value:
 //    S_OK - if m_clrInstanceId was already set, or is now set to a valid CLR instance ID
-//    an error HRESULT - if m_clrInstanceId was 0, and cannot be set to a valid value 
+//    an error HRESULT - if m_clrInstanceId was 0, and cannot be set to a valid value
 //                       (i.e. because we cannot find a CLR in the target process).
-//    
-//    Note that we need to probe for this on attach, and it's common to attach before the 
+//
+//    Note that we need to probe for this on attach, and it's common to attach before the
 //    CLR has been loaded, so we avoid using exceptions for this common case.
-//    
+//
 HRESULT CordbProcess::EnsureClrInstanceIdSet()
 {
     // If we didn't expect a specific CLR, then attempt to attach to any.
@@ -9935,7 +9944,7 @@ HRESULT CordbProcess::EnsureClrInstanceIdSet()
             _ASSERTE(m_clrInstanceId == 0);
             return hr;
         }
-    }    
+    }
 
     // We've (now) got a valid CLR instance id
     return S_OK;
@@ -9955,7 +9964,7 @@ HRESULT CordbProcess::EnsureClrInstanceIdSet()
 //
 // Notes:
 //    This is copying from a shared-memory block, which is treated as local memory.
-//    This just does a raw Byte copy, but does not do any Marshalling. 
+//    This just does a raw Byte copy, but does not do any Marshalling.
 //    This does no validation on the event.
 //    The event still needs to be Marshaled before being used. (see code:CordbProcess::MarshalManagedEvent)
 //
@@ -9975,9 +9984,9 @@ bool CordbRCEventThread::IsRCEventThread()
 
 //---------------------------------------------------------------------------------------
 // Runtime assert, throws CORDBG_E_TARGET_INCONSISTENT if the expression is not true.
-// 
+//
 // Arguments:
-//     fExpression - assert parameter. If true, this function is a nop. If false, 
+//     fExpression - assert parameter. If true, this function is a nop. If false,
 //             this will throw a CORDBG_E_TARGET_INCONSISTENT error.
 //
 // Notes:
@@ -9987,7 +9996,7 @@ bool CordbRCEventThread::IsRCEventThread()
 void CordbProcess::TargetConsistencyCheck(bool fExpression)
 {
     if (!fExpression)
-    {        
+    {
         STRESS_LOG0(LF_CORDB, LL_INFO10000, "Target consistency check failed");
 
         // When debugging possibly corrupt targets, this failure may be expected.  For debugging purposes,
@@ -10135,7 +10144,7 @@ HRESULT CordbRCEventThread::SendIPCEvent(CordbProcess* process,
         return CORDBG_E_PROCESS_TERMINATED;
     }
 
-    // If the helper thread has died, we can't send an IPC event (and it's never coming back either). 
+    // If the helper thread has died, we can't send an IPC event (and it's never coming back either).
     // Although we do wait on the thread's handle, there are strange windows where the thread's handle
     // is not yet signaled even though we've continued from the exit-thread event for the helper.
     if (process->m_helperThreadDead)
@@ -10321,8 +10330,8 @@ HRESULT CordbRCEventThread::SendIPCEvent(CordbProcess* process,
 
         }
     }
-            
-    process->ForceDacFlush();    
+
+    process->ForceDacFlush();
 
     // The hr and hrEvent are 2 very different things.
     // hr tells us whether the event was sent successfully.
@@ -10351,7 +10360,7 @@ HRESULT CordbRCEventThread::SendIPCEvent(CordbProcess* process,
 void CordbRCEventThread::FlushQueuedEvents(CordbProcess* process)
 {
     CONTRACTL
-    {        
+    {
         NOTHROW; // This is happening on the RCET thread, so there's no place to propogate an error back up.
     }
     CONTRACTL_END;
@@ -10376,9 +10385,9 @@ void CordbRCEventThread::FlushQueuedEvents(CordbProcess* process)
     // ShimProcess now, while we still hold the process lock.  Once we release the lock,
     // GetShim() may not work.
     RSExtSmartPtr<ShimProcess> pShim(process->GetShim());
-    
+
     // Release lock before we call out to shim to Queue fake events.
-    {        
+    {
         RSInverseLockHolder inverseLockHolder(process->GetProcessLock());
         {
             PUBLIC_CALLBACK_IN_THIS_SCOPE0_NO_LOCK(pProcess);
@@ -10443,7 +10452,7 @@ void CordbRCEventThread::FlushQueuedEvents(CordbProcess* process)
 //    None. Throws on error. On error, caller still owns the pManagedEvent and must free it.
 //
 // Assumptions:
-//    This should be called once a notification event is received from the target. 
+//    This should be called once a notification event is received from the target.
 //
 // Notes:
 //    HandleRCEvent -- handle an IPC event received from the runtime controller.
@@ -10451,8 +10460,8 @@ void CordbRCEventThread::FlushQueuedEvents(CordbProcess* process)
 //
 //---------------------------------------------------------------------------------------
 void CordbProcess::HandleRCEvent(
-    DebuggerIPCEvent *         pManagedEvent, 
-    RSLockHolder *             pLockHolder, 
+    DebuggerIPCEvent *         pManagedEvent,
+    RSLockHolder *             pLockHolder,
     ICorDebugManagedCallback * pCallback)
 {
     CONTRACTL
@@ -10470,23 +10479,23 @@ void CordbProcess::HandleRCEvent(
     }
 
     // Marshals over some standard data from event.
-    MarshalManagedEvent(pManagedEvent);                    
+    MarshalManagedEvent(pManagedEvent);
 
     STRESS_LOG4(LF_CORDB, LL_INFO1000, "RCET::TP: Got %s for AD 0x%x, proc 0x%x(%d)\n",
         IPCENames::GetName(pManagedEvent->type), VmPtrToCookie(pManagedEvent->vmAppDomain), this->m_id, this->m_id);
 
     RSExtSmartPtr<ICorDebugManagedCallback2> pCallback2;
-    pCallback->QueryInterface(IID_ICorDebugManagedCallback2, reinterpret_cast<void **> (&pCallback2));   
+    pCallback->QueryInterface(IID_ICorDebugManagedCallback2, reinterpret_cast<void **> (&pCallback2));
 
     RSExtSmartPtr<ICorDebugManagedCallback3> pCallback3;
-    pCallback->QueryInterface(IID_ICorDebugManagedCallback3, reinterpret_cast<void **> (&pCallback3));   
+    pCallback->QueryInterface(IID_ICorDebugManagedCallback3, reinterpret_cast<void **> (&pCallback3));
 
     RSExtSmartPtr<ICorDebugManagedCallback4> pCallback4;
     pCallback->QueryInterface(IID_ICorDebugManagedCallback4, reinterpret_cast<void **> (&pCallback4));
 
     // Dispatch directly. May not necessarily dispatch an event.
     // Toggles the lock to dispatch callbacks.
-    RawDispatchEvent(pManagedEvent, pLockHolder, pCallback, pCallback2, pCallback3, pCallback4);    
+    RawDispatchEvent(pManagedEvent, pLockHolder, pCallback, pCallback2, pCallback3, pCallback4);
 }
 
 //
@@ -10506,7 +10515,7 @@ void CordbRCEventThread::ProcessStateChanged()
 
 
 //---------------------------------------------------------------------------------------
-// Primary loop of the Runtime Controller event thread.  This routine loops during the 
+// Primary loop of the Runtime Controller event thread.  This routine loops during the
 // debug session taking IPC events from the IPC block and calling out to process them.
 //
 // Arguments:
@@ -10594,7 +10603,7 @@ void CordbRCEventThread::ThreadProc()
             for (pProcess =  pHashTable->FindFirst(&hashFind); pProcess != NULL; pProcess = pHashTable->FindNext(&hashFind))
             {
                 _ASSERTE(waitCount < MAXIMUM_WAIT_OBJECTS);
-                
+
                 if( waitCount >= MAXIMUM_WAIT_OBJECTS )
                 {
                     break;
@@ -10608,7 +10617,7 @@ void CordbRCEventThread::ThreadProc()
                 // per-process mutex when checking the process's synchronized flag here.
                 if (!pProcess->GetSynchronized() && pProcess->IsSafeToSendEvents())
                 {
-                    STRESS_LOG2(LF_CORDB, LL_INFO1000, "RCET::TP: listening to process 0x%x(%d)\n", 
+                    STRESS_LOG2(LF_CORDB, LL_INFO1000, "RCET::TP: listening to process 0x%x(%d)\n",
                                 pProcess->m_id, pProcess->m_id);
 
                     waitSet[waitCount] = pProcess->m_leftSideEventAvailable;
@@ -10640,7 +10649,7 @@ void CordbRCEventThread::ThreadProc()
                 // Flush the queue if necessary. Note, we only do this if we've actually received a SyncComplete message
                 // from this process. If we haven't received a SyncComplete yet, then we don't attempt to drain any
                 // queued events yet. They'll be drained when the SyncComplete event is actually received.
-                if (pProcess->GetSyncCompleteRecv() && 
+                if (pProcess->GetSyncCompleteRecv() &&
                     (pProcess->GetShim() != NULL) &&
                     !pProcess->GetSynchronized())
                 {
@@ -10650,7 +10659,7 @@ void CordbRCEventThread::ThreadProc()
                         // handling an event.  We can get here if the event raised by the LS is a duplicate
                         // creation event, which the shim discards without adding it to the event queue.
                         // See code:ShimProcess::IsDuplicateCreationEvent.
-                        // 
+                        //
                         // To continue, we need to increment the stop count first.  Also, we can't call
                         // Continue() while holding the process lock.
                         pProcess->SetSynchronized(true);
@@ -10722,7 +10731,7 @@ void CordbRCEventThread::ThreadProc()
 // This is the thread's real thread proc. It simply calls to the
 // thread proc on the given object.
 //
-/*static*/ 
+/*static*/
 DWORD WINAPI CordbRCEventThread::ThreadProc(LPVOID parameter)
 {
     CordbRCEventThread * pThread = (CordbRCEventThread *) parameter;
@@ -10838,7 +10847,7 @@ void CordbRCEventThread::DrainWorkerQueue()
 //    S_OK on success. else failure.
 //
 // Assumptions:
-//    Caller allocates 
+//    Caller allocates
 //
 // Notes:
 //   WaitForIPCEventFromProcess waits for an event from just the specified
@@ -10847,8 +10856,8 @@ void CordbRCEventThread::DrainWorkerQueue()
 //   process's event, too, which would get confusing.
 //
 //   @dbgtodo - this function should eventually be obsolete once everything
-//   is using DAC calls instead of helper-thread. 
-//   
+//   is using DAC calls instead of helper-thread.
+//
 //---------------------------------------------------------------------------------------
 HRESULT CordbRCEventThread::WaitForIPCEventFromProcess(CordbProcess * pProcess,
                                                        CordbAppDomain * pAppDomain,
@@ -10861,7 +10870,7 @@ HRESULT CordbRCEventThread::WaitForIPCEventFromProcess(CordbProcess * pProcess,
 
     do
     {
-        dwStatus = SafeWaitForSingleObject(pProcess, 
+        dwStatus = SafeWaitForSingleObject(pProcess,
                                            pProcess->m_leftSideEventAvailable,
                                            CordbGetWaitTimeout());
 
@@ -10884,9 +10893,9 @@ HRESULT CordbRCEventThread::WaitForIPCEventFromProcess(CordbProcess * pProcess,
             pProcess->MarshalManagedEvent(pEvent);
 
             STRESS_LOG4(LF_CORDB, LL_INFO1000, "CRCET::SIPCE: Got %s for AD 0x%x, proc 0x%x(%d)\n",
-                        IPCENames::GetName(pEvent->type), 
-                        VmPtrToCookie(pEvent->vmAppDomain), 
-                        pProcess->m_id, 
+                        IPCENames::GetName(pEvent->type),
+                        VmPtrToCookie(pEvent->vmAppDomain),
+                        pProcess->m_id,
                         pProcess->m_id);
 
         }
@@ -10939,11 +10948,11 @@ HRESULT CordbRCEventThread::Start()
         return E_INVALIDARG;
     }
 
-    m_thread = CreateThread(NULL, 
-                            0, 
+    m_thread = CreateThread(NULL,
+                            0,
                             &CordbRCEventThread::ThreadProc,
-                            (LPVOID) this, 
-                            0, 
+                            (LPVOID) this,
+                            0,
                             &m_threadId);
 
     if (m_thread == NULL)
@@ -11007,7 +11016,7 @@ enum
 //
 //---------------------------------------------------------------------------------------
 CordbWin32EventThread::CordbWin32EventThread(
-    Cordb * pCordb, 
+    Cordb * pCordb,
     ShimProcess * pShim
     ) :
     m_thread(NULL), m_threadControlEvent(NULL),
@@ -11088,7 +11097,7 @@ void CordbWin32EventThread::ThreadProc()
     DbgRSThread::GetThread()->TakeVirtualLock(RSLock::LL_WIN32_EVENT_THREAD);
 #endif
 
-    // In V2, the debuggee decides what to do if the debugger rudely exits / detaches. (This is 
+    // In V2, the debuggee decides what to do if the debugger rudely exits / detaches. (This is
     // handled by host policy). With the OS native-debuggging pipeline, the debugger by default
     // kills the debuggee if it exits. To emulate V2 behavior, we need to override that default.
     BOOL fOk = m_pNativePipeline->DebugSetProcessKillOnExit(FALSE);
@@ -11115,7 +11124,7 @@ typedef DeleteIPCEventHolderHelper<DebuggerIPCEvent>  DeleteIPCEventHolder;
 // This must be called after an event is marshalled via code:CordbProcess::MarshalManagedEvent
 //
 // Arguments:
-//     pManagedEvent - managed event to delete. 
+//     pManagedEvent - managed event to delete.
 //
 // Notes:
 //     This can delete a partially marshalled event.
@@ -11168,8 +11177,8 @@ void DeleteIPCEventHelper(DebuggerIPCEvent *pManagedEvent)
 // Notes:
 //    This is called after caller does WaitForDebugEvent.
 //    Any exception this Filter does not recognize is treated as kNotClr.
-//    Currently, this includes both managed-exceptions and unmanaged ones. 
-//    For interop-debugging, the interop logic will handle all kNotClr and triage if 
+//    Currently, this includes both managed-exceptions and unmanaged ones.
+//    For interop-debugging, the interop logic will handle all kNotClr and triage if
 //    it's really a non-CLR exception.
 //
 //---------------------------------------------------------------------------------------
@@ -11177,7 +11186,7 @@ void CordbProcess::FilterClrNotification(
     DebuggerIPCEvent * pManagedEvent,
     RSLockHolder * pLockHolder,
     ICorDebugManagedCallback * pCallback)
-{   
+{
     CONTRACTL
     {
         THROWS;
@@ -11192,7 +11201,7 @@ void CordbProcess::FilterClrNotification(
     //       we need to set LSEA/wait on LSER.
     // 2) Sync-Complete (kind of like a special notification)
     //       Ping the helper
-    // 3) Notifications (eg, Module-load): 
+    // 3) Notifications (eg, Module-load):
     //       these are dispatched immediately.
     // 4) Left-side Startup event
 
@@ -11200,13 +11209,13 @@ void CordbProcess::FilterClrNotification(
     // IF we're synced, then we must be getting a "Reply".
     bool fReply = this->GetSynchronized();
 
-    LOG((LF_CORDB, LL_INFO10000, "CP::FCN - Received event %s; fReply: %d\n", 
+    LOG((LF_CORDB, LL_INFO10000, "CP::FCN - Received event %s; fReply: %d\n",
          IPCENames::GetName(pManagedEvent->type),
          fReply));
 
-    if (fReply)    
-    {   
-        // 
+    if (fReply)
+    {
+        //
         _ASSERTE(m_pShim != NULL);
         //
         // Case 1: Reply
@@ -11219,7 +11228,7 @@ void CordbProcess::FilterClrNotification(
         GetEventChannel()->SaveEventFromLeftSide(pManagedEvent);
         SetEvent(this->m_leftSideEventAvailable);
 
-        // Some other thread called code:CordbRCEventThread::WaitForIPCEventFromProcess, and 
+        // Some other thread called code:CordbRCEventThread::WaitForIPCEventFromProcess, and
         // that will respond here and set the event.
 
         DWORD dwResult = WaitForSingleObject(this->m_leftSideEventRead, CordbGetWaitTimeout());
@@ -11227,7 +11236,7 @@ void CordbProcess::FilterClrNotification(
         if (dwResult != WAIT_OBJECT_0)
         {
             // The wait failed.  This is probably WAIT_TIMEOUT which suggests a deadlock/assert on
-            // the RCEventThread.  
+            // the RCEventThread.
             CONSISTENCY_CHECK_MSGF(false, ("WaitForSingleObject failed: %d", dwResult));
             ThrowHR(CORDBG_E_TIMEOUT);
         }
@@ -11240,12 +11249,12 @@ void CordbProcess::FilterClrNotification(
             // Case 4: Left-side startup event. We'll mark that we're attached from oop.
             //
 
-            // Now that LS is started, we should definitely be able to instantiate DAC. 
+            // Now that LS is started, we should definitely be able to instantiate DAC.
             InitializeDac();
-            
+
             // @dbgtodo 'attach-bit': we don't want the debugger automatically invading the process.
-            GetDAC()->MarkDebuggerAttached(TRUE);                            
-        }         
+            GetDAC()->MarkDebuggerAttached(TRUE);
+        }
         else if (pManagedEvent->type == DB_IPCE_SYNC_COMPLETE)
         {
             // Since V3 doesn't request syncs, it shouldn't get sync-complete.
@@ -11268,7 +11277,7 @@ void CordbProcess::FilterClrNotification(
             HandleRCEvent(pManagedEvent, pLockHolder, pCallback);
 
         } // end Notification
-    }    
+    }
 }
 
 
@@ -11284,10 +11293,10 @@ void CordbProcess::FilterClrNotification(
 //
 // Notes:
 //     This is called from shim to emulate being synchronized at an unhandled
-//     exception. 
+//     exception.
 //     Other ICorDebug operations could calls this (eg, func-eval at 2nd chance).
 BOOL CordbProcess::HijackThreadForUnhandledExceptionIfNeeded(DWORD dwThreadId)
-{    
+{
     PUBLIC_API_ENTRY(this); // from Shim
 
     BOOL fHijacked = FALSE;
@@ -11297,13 +11306,13 @@ BOOL CordbProcess::HijackThreadForUnhandledExceptionIfNeeded(DWORD dwThreadId)
         RSLockHolder lockHolder(GetProcessLock());
 
         // OS will not execute the Unhandled Exception Filter under native debugger, so
-        // we need to hijack the thread to get it to execute the UEF, which will then do 
+        // we need to hijack the thread to get it to execute the UEF, which will then do
         // work for unhandled managed exceptions.
         CordbThread * pThread = TryLookupOrCreateThreadByVolatileOSId(dwThreadId);
         if (pThread != NULL)
-        {   
+        {
             // If the thread has a managed exception, then we should have a pThread object.
-            
+
             if (pThread->HasUnhandledNativeException())
             {
                 _ASSERTE(pThread->IsThreadExceptionManaged()); // should have been marked earlier
@@ -11329,12 +11338,12 @@ BOOL CordbProcess::HijackThreadForUnhandledExceptionIfNeeded(DWORD dwThreadId)
 //
 // Returns:
 //    A type-safe exception record from the raw buffer.
-// 
+//
 // Notes:
 //   This is a helper for code:CordbProcess::Filter.
 //   This can do consistency checks on the incoming parameters such as:
 //    * verify countBytes matches the expected size for the given format.
-//    * verify the format is supported. 
+//    * verify the format is supported.
 //
 //   If we let a given ICD understand multiple formats (eg, have x86 understand both Exr32 and
 //    Exr64), this would be the spot to allow the conversion.
@@ -11362,14 +11371,14 @@ const EXCEPTION_RECORD * CordbProcess::ValidateExceptionRecord(
         ThrowHR(E_INVALIDARG);
     }
 #endif
-    
+
     // @dbgtodo cross-plat: once we do cross-plat, need to use correct EXCEPTION_RECORD variant.
     if (countBytes != sizeof(EXCEPTION_RECORD))
     {
         ThrowHR(E_INVALIDARG);
     }
 
-    
+
     const EXCEPTION_RECORD * pRecord = reinterpret_cast<const EXCEPTION_RECORD *> (pRawRecord);
 
     return pRecord;
@@ -11385,21 +11394,21 @@ HRESULT CordbProcess::SetEnableCustomNotification(ICorDebugClass * pClass, BOOL
 
     ((CordbClass *)pClass)->SetCustomNotifications(fEnable);
 
-    PUBLIC_API_END(hr); 
+    PUBLIC_API_END(hr);
     return hr;
 } // CordbProcess::SetEnableCustomNotification
 
 //---------------------------------------------------------------------------------------
 // Public implementation of ICDProcess4::Filter
 //
-// Arguments: 
+// Arguments:
 //    pRawRecord - non-null raw bytes of the exception
 //    countBytes - number of bytes in pRawRecord buffer.
 //    format - format of pRawRecord
 //    dwFlags - flags providing auxillary info for exception record.
 //    dwThreadId - thread that exception occurred on.
 //    pCallback - callback to dispatch potential managed events on.
-//    pContinueStatus - Continuation status for exception. This dictates what 
+//    pContinueStatus - Continuation status for exception. This dictates what
 //         to pass to kernel32!ContinueDebugEvent().
 //
 // Return Value:
@@ -11410,19 +11419,19 @@ HRESULT CordbProcess::SetEnableCustomNotification(ICorDebugClass * pClass, BOOL
 //
 // Notes:
 //    The exception could be anything, including:
-//    - a CLR notification, 
+//    - a CLR notification,
 //    - a random managed exception (both from managed code or the runtime),
 //    - a non-CLR exception
 //
 //    This is cross-platform. The {pRawRecord, countBytes, format} describe events
 //    on an arbitrary target architecture. On windows, this will be an EXCEPTION_RECORD.
-// 
+//
 HRESULT CordbProcess::Filter(
         const BYTE pRawRecord[],
         DWORD countBytes,
         CorDebugRecordFormat format,
-        DWORD dwFlags, 
-        DWORD dwThreadId, 
+        DWORD dwFlags,
+        DWORD dwThreadId,
         ICorDebugManagedCallback * pCallback,
         DWORD * pContinueStatus
 )
@@ -11443,7 +11452,7 @@ HRESULT CordbProcess::Filter(
         DWORD dwFirstChance = (dwFlags & IS_FIRST_CHANCE);
 
         //
-        // Deal with 2nd-chance exceptions. Don't actually hijack now (that's too invasive), 
+        // Deal with 2nd-chance exceptions. Don't actually hijack now (that's too invasive),
         // but mark that we have the exception in case a future operation (eg, func-eval) needs to hijack.
         //
         if (!dwFirstChance)
@@ -11451,16 +11460,16 @@ HRESULT CordbProcess::Filter(
             CordbThread * pThread = TryLookupOrCreateThreadByVolatileOSId(dwThreadId);
 
             // If we don't have a managed-thread object, then it certainly can't have a throwable.
-            // It's possible this is still an exception from the native portion of the runtime, 
+            // It's possible this is still an exception from the native portion of the runtime,
             // but that's ok, we'll just treat it as a native exception.
             // This could be expensive, don't want to do it often... (definitely not on every Filter).
 
 
             // OS will not execute the Unhandled Exception Filter under native debugger, so
-            // we need to hijack the thread to get it to execute the UEF, which will then do 
+            // we need to hijack the thread to get it to execute the UEF, which will then do
             // work for unhandled managed exceptions.
             if ((pThread != NULL) && pThread->IsThreadExceptionManaged())
-            {                
+            {
                 // Copy exception record for future use in case we decide to hijack.
                 pThread->SetUnhandledNativeException(pRecord);
             }
@@ -11475,30 +11484,30 @@ HRESULT CordbProcess::Filter(
             //
             // This may not be for us, or we may not have a managed thread object:
             // 1. Anybody can raise an exception with this exception code, so can't assume this belongs to us yet.
-            // 2. Notifications may come on unmanaged threads if they're coming from MDAs or CLR internal events 
+            // 2. Notifications may come on unmanaged threads if they're coming from MDAs or CLR internal events
             //    fired before the thread is created.
             //
             BYTE * pManagedEventBuffer = new BYTE[CorDBIPC_BUFFER_SIZE];
             DeleteIPCEventHolder pManagedEvent(reinterpret_cast<DebuggerIPCEvent *>(pManagedEventBuffer));
-        
+
             bool fOwner = CopyManagedEventFromTarget(pRecord, pManagedEvent);
             if (fOwner)
             {
                 // This toggles the lock if it dispatches callbacks
                 FilterClrNotification(pManagedEvent, GET_PUBLIC_LOCK_HOLDER(), pCallback);
-                
+
                 // Cancel any notification events from target. These are just supposed to notify ICD and not
                 // actually be real exceptions in the target.
                 // Canceling here also prevents a VectoredExceptionHandler in the target from picking
                 // up exceptions for the CLR.
-                *pContinueStatus = DBG_CONTINUE;             
+                *pContinueStatus = DBG_CONTINUE;
             }
 
             // holder will invoke DeleteIPCEventHelper(pManagedEvent).
         }
 
-    }    
-    PUBLIC_API_END(hr); 
+    }
+    PUBLIC_API_END(hr);
     // we may not find the correct mscordacwks so fail gracefully
     _ASSERTE(SUCCEEDED(hr) || (hr != HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND)));
 
@@ -11516,20 +11525,20 @@ HRESULT CordbProcess::Filter(
 //
 // Notes:
 //   Initial continue status is returned from code:CordbProcess::Filter.
-//   Some operations (mainly hijacking on a 2nd-chance exception), may need to 
+//   Some operations (mainly hijacking on a 2nd-chance exception), may need to
 //   override that continue status.
 //   ICorDebug operations invoke a callback on the data-target to notify the debugger
 //   of a change in status. Debugger may fail the request.
 //
 void CordbProcess::ContinueStatusChanged(DWORD dwThreadId, CORDB_CONTINUE_STATUS dwContinueStatus)
-{        
+{
     HRESULT hr = m_pMutableDataTarget->ContinueStatusChanged(dwThreadId, dwContinueStatus);
     IfFailThrow(hr);
 }
 
 //---------------------------------------------------------------------------------------
 // Request a synchronization to occur after a debug event is dispatched.
-// 
+//
 // Note:
 //    This is called in response to a managed debug event, and so we know that we have
 //    a worker thread in the process (the one that just sent the event!)
@@ -11552,7 +11561,7 @@ void CordbProcess::RequestSyncAtEvent()
 //    None.
 //
 // Notes:
-//    This is it, you've found it, the main guy.  This function loops as long as the 
+//    This is it, you've found it, the main guy.  This function loops as long as the
 //    debugger is around calling the OS WaitForDebugEvent() API.  It takes the OS Debug
 //    Event and filters it thru the right-side, continuing the process if not recognized.
 //
@@ -11567,7 +11576,7 @@ void CordbWin32EventThread::Win32EventLoop()
 
 
     DEBUG_EVENT event;
-    
+
     // Allow the timeout for WFDE to be adjustable. Default to 25 ms based off perf numbers (see issue VSWhidbey 132368).
     DWORD dwWFDETimeout = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_DbgWFDETimeout);
 
@@ -11597,7 +11606,7 @@ void CordbWin32EventThread::Win32EventLoop()
         if (m_pProcess != NULL)
         {
             // Process is always built on Native debugging pipeline, so it needs to always be prepared to call WFDE
-            // As an optimization, if the target is stopped, then we can avoid calling WFDE.            
+            // As an optimization, if the target is stopped, then we can avoid calling WFDE.
             {
 #ifndef FEATURE_INTEROP_DEBUGGING
                 // Managed-only, never win32 stopped, so always check for an event.
@@ -11611,7 +11620,7 @@ void CordbWin32EventThread::Win32EventLoop()
 
                 const bool fIsInteropDebugging = m_pProcess->IsInteropDebugging();
                 (void)fIsInteropDebugging; //prevent "unused variable" error from GCC
-                
+
                 // Assert checks
                 _ASSERTE(fIsInteropDebugging == m_pShim->IsInteropDebugging());
 
@@ -11620,14 +11629,14 @@ void CordbWin32EventThread::Win32EventLoop()
                     dwWaitTimeout = 0;
                     fEventAvailable = m_pNativePipeline->WaitForDebugEvent(&event, dwWFDETimeout, m_pProcess);
                 }
-                else 
+                else
                 {
                     // If we're managed-only debugging, then the process should always be running,
                     // which means we always need to be calling WFDE to pump potential debug events.
                     // If we're interop-debugging, then the process can be stopped at a native-debug event,
                     // in which case we don't have to call WFDE until we resume it again.
-                    // So we can only skip the WFDE when we're interop-debugging. 
-                    _ASSERTE(fIsInteropDebugging); 
+                    // So we can only skip the WFDE when we're interop-debugging.
+                    _ASSERTE(fIsInteropDebugging);
                 }
 #endif // FEATURE_INTEROP_DEBUGGING
             }
@@ -11732,17 +11741,17 @@ void CordbWin32EventThread::Win32EventLoop()
 
         // Must flush the dac cache since we were just running.
         m_pProcess->ForceDacFlush();
-        
+
         // So we've filtered out CLR events.
         // Let the shim handle the remaining events. This will call back into Filter() if appropriate.
         // This will also ensure the debug event gets continued.
         HRESULT hrShim = S_OK;
         {
             PUBLIC_CALLBACK_IN_THIS_SCOPE0_NO_LOCK(NULL);
-            hrShim = m_pShim->HandleWin32DebugEvent(&event); 
+            hrShim = m_pShim->HandleWin32DebugEvent(&event);
         }
         // Any errors from the shim (eg. failure to load DAC) are unrecoverable
-        SetUnrecoverableIfFailed(m_pProcess, hrShim);  
+        SetUnrecoverableIfFailed(m_pProcess, hrShim);
 
     } // loop
 
@@ -11767,13 +11776,13 @@ bool CordbProcess::IsWin32EventThread()
 
 //---------------------------------------------------------------------------------------
 // Call when the sync complete event is received and can be processed.
-// 
+//
 // Notes:
 //    This is called when the RS gets the sync-complete from the LS and can process it.
-//    
+//
 //    This has a somewhat elaborate contract to fill between Interop-debugging, Async-Break, draining the
 //    managed event-queue, and coordinating with the dispatch thread (RCET).
-//    
+//
 //    @dbgtodo - this should eventually get hoisted into the shim.
 void CordbProcess::HandleSyncCompleteRecieved()
 {
@@ -11784,7 +11793,7 @@ void CordbProcess::HandleSyncCompleteRecieved()
     // If some thread is waiting for the process to sync, notify that it can go now.
     if (this->m_stopRequested)
     {
-        this->SetSynchronized(true); 
+        this->SetSynchronized(true);
         SetEvent(this->m_stopWaitEvent);
     }
     else
@@ -11817,7 +11826,7 @@ void CordbProcess::HandleSyncCompleteRecieved()
 //
 //
 // Notes:
-//    Thread may be newly allocated, or may be existing. CordbProcess holds 
+//    Thread may be newly allocated, or may be existing. CordbProcess holds
 //    list of all CordbUnmanagedThreads, and will handle freeing memory.
 //
 //---------------------------------------------------------------------------------------
@@ -11833,25 +11842,25 @@ CordbUnmanagedThread * CordbProcess::GetUnmanagedThreadFromEvent(const DEBUG_EVE
     {
         // We absolutely should have an unmanaged callback by this point.
         // That means that the client debugger should have called ICorDebug::SetUnmanagedHandler by now.
-        // However, we can't actually enforce that (see comment  in ICorDebug::SetUnmanagedHandler for details), 
-        // so we do a runtime check to check this. 
+        // However, we can't actually enforce that (see comment  in ICorDebug::SetUnmanagedHandler for details),
+        // so we do a runtime check to check this.
         // This is an extremely gross API misuse and an issue in the client if the callback is not set yet.
-        // Without the unmanaged callback, we absolutely can't do interop-debugging. We assert (checked builds) and 
+        // Without the unmanaged callback, we absolutely can't do interop-debugging. We assert (checked builds) and
         // dispatch unrecoverable error (retail builds) to avoid an AV.
 
 
         if (this->m_cordb->m_unmanagedCallback == NULL)
         {
-            CONSISTENCY_CHECK_MSGF((this->m_cordb->m_unmanagedCallback != NULL), 
-                ("GROSS API misuse!!\nNo unmanaged callback set by the time we've received CreateProcess debug event for proces 0x%x.\n", 
+            CONSISTENCY_CHECK_MSGF((this->m_cordb->m_unmanagedCallback != NULL),
+                ("GROSS API misuse!!\nNo unmanaged callback set by the time we've received CreateProcess debug event for proces 0x%x.\n",
                 pEvent->dwProcessId));
-                
+
             CORDBSetUnrecoverableError(this, CORDBG_E_INTEROP_NOT_SUPPORTED, 0);
 
             // Returning NULL will tell caller not to dispatch event to client. We have no callback object to dispatch upon.
             return NULL;
         }
-        
+
         pUnmanagedThread = this->HandleUnmanagedCreateThread(pEvent->dwThreadId,
                                                              pEvent->u.CreateProcessInfo.hThread,
                                                              pEvent->u.CreateProcessInfo.lpThreadLocalBase);
@@ -11875,7 +11884,7 @@ CordbUnmanagedThread * CordbProcess::GetUnmanagedThreadFromEvent(const DEBUG_EVE
             // If we have the debugger control block, and if that control block has the address of the thread proc for
             // the helper thread, then we're initialized enough on the Left Side to recgonize the helper thread based on
             // its thread proc's address.
-            if (this->GetDCB() != NULL) 
+            if (this->GetDCB() != NULL)
             {
                 // get the latest LS DCB information
                 UpdateRightSideDCB();
@@ -11896,7 +11905,7 @@ CordbUnmanagedThread * CordbProcess::GetUnmanagedThreadFromEvent(const DEBUG_EVE
         EX_CATCH_HRESULT(hr)
         {
             if (fBlockExists && FAILED(hr))
-            {                        
+            {
                 _ASSERTE(IsLegalFatalError(hr));
                 // Send up the DebuggerError event
                 this->UnrecoverableError(hr, 0, NULL, 0);
@@ -11905,7 +11914,7 @@ CordbUnmanagedThread * CordbProcess::GetUnmanagedThreadFromEvent(const DEBUG_EVE
                 // RS will pump events until we LS process exits.
                 TerminateProcess(this->m_handle, hr);
 
-                return pUnmanagedThread;            
+                return pUnmanagedThread;
             }
         }
     }
@@ -12218,7 +12227,7 @@ Reaction CordbProcess::Triage1stChanceNonSpecial(CordbUnmanagedThread * pUnmanag
     }
     else if (dwExCode == EXCEPTION_MSVC)
     {
-        // The runtime may use C++ exceptions internally. We can still report these 
+        // The runtime may use C++ exceptions internally. We can still report these
         // to the debugger as long as we're outside of a can't-stop region.
         if (pUnmanagedThread->IsCantStop())
         {
@@ -12268,7 +12277,7 @@ Reaction CordbProcess::Triage1stChanceNonSpecial(CordbUnmanagedThread * pUnmanag
         else
         {
             return REACTION(cInband);
-        }        
+        }
     }
 
     UNREACHABLE();
@@ -12290,12 +12299,12 @@ Reaction CordbProcess::Triage1stChanceNonSpecial(CordbUnmanagedThread * pUnmanag
 //
 // Notes:
 //    A 1st-chance event has a wide spectrum of possibility including:
-//    - It may be unmanaged or managed. 
-//    - Or it may be an execution control exception for managed-exceution 
+//    - It may be unmanaged or managed.
+//    - Or it may be an execution control exception for managed-exceution
 //    - thread skipping an OOB event.
 //
 //---------------------------------------------------------------------------------------
-Reaction CordbProcess::TriageExcep1stChanceAndInit(CordbUnmanagedThread * pUnmanagedThread, 
+Reaction CordbProcess::TriageExcep1stChanceAndInit(CordbUnmanagedThread * pUnmanagedThread,
                                                    const DEBUG_EVENT * pEvent)
 {
     _ASSERTE(ThreadHoldsProcessLock());
@@ -12422,8 +12431,8 @@ Reaction CordbProcess::TriageExcep1stChanceAndInit(CordbUnmanagedThread * pUnman
     {
         // If we Single-Step over an exception, then the OS never gives us the single-step event.
         // Thus if we're skipping a native patch, we don't care what exception event we got.
-        LOG((LF_CORDB, LL_INFO100000, "Done skipping native patch. Ex=0x%x\n, IsSS=%d", 
-             dwExCode, 
+        LOG((LF_CORDB, LL_INFO100000, "Done skipping native patch. Ex=0x%x\n, IsSS=%d",
+             dwExCode,
              (dwExCode == STATUS_SINGLE_STEP)));
 
         // This is the 2nd half of skipping a native patch.
@@ -12440,9 +12449,9 @@ Reaction CordbProcess::TriageExcep1stChanceAndInit(CordbUnmanagedThread * pUnman
         CONSISTENCY_CHECK_MSGF(dwExCode != STATUS_SINGLE_STEP, (
                 "Single-Step exception on helper thread (tid=0x%x/%d) in debuggee process (pid=0x%x/%d).\n"
                 "For more information, attach a debuggee non-invasively to the LS to get the callstack.\n",
-                pUnmanagedThread->m_id, 
-                pUnmanagedThread->m_id, 
-                this->m_id, 
+                pUnmanagedThread->m_id,
+                pUnmanagedThread->m_id,
+                this->m_id,
                 this->m_id));
 
         // We ignore any first chance exceptions from the helper thread. There are lots of places
@@ -12465,9 +12474,9 @@ Reaction CordbProcess::TriageExcep1stChanceAndInit(CordbUnmanagedThread * pUnman
             CONSISTENCY_CHECK_MSGF((dwExCode != STATUS_BREAKPOINT), (
                 "Assert on helper thread (tid=0x%x/%d) in debuggee process (pid=0x%x/%d).\n"
                 "For more information, attach a debuggee non-invasively to the LS to get the callstack.\n",
-                pUnmanagedThread->m_id, 
-                pUnmanagedThread->m_id, 
-                this->m_id, 
+                pUnmanagedThread->m_id,
+                pUnmanagedThread->m_id,
+                this->m_id,
                 this->m_id));
 
             // These breakpoint and single step exceptions have to be dispatched to the debugger as
@@ -12528,13 +12537,13 @@ Reaction CordbProcess::TriageExcep1stChanceAndInit(CordbUnmanagedThread * pUnman
                 return REACTION(cOOB);
             }
 
-            // If generichijacked and its not a flare, and the address referenced is on the stack then we've 
-            // got our special stack overflow case. Take off generic hijacked, mark that the helper thread 
+            // If generichijacked and its not a flare, and the address referenced is on the stack then we've
+            // got our special stack overflow case. Take off generic hijacked, mark that the helper thread
             // is dead, throw this event on the floor, and pop anyone in SendIPCEvent out of their wait.
             pUnmanagedThread->ClearState(CUTS_GenericHijacked);
-            
+
             this->m_helperThreadDead = true;
-            
+
             // This only works on Windows, not on Mac.  We don't support interop-debugging on Mac anyway.
             SetEvent(m_pEventChannel->GetRightSideEventAckHandle());
 
@@ -12591,8 +12600,8 @@ Reaction CordbProcess::TriageExcep1stChanceAndInit(CordbUnmanagedThread * pUnman
 //    Called when receiving a debug event when the process is stopped.
 //
 // Notes:
-//    We already hijacked 2nd-chance managed exceptions, so this is just handling 
-//    some V2 Interop corner cases. 
+//    We already hijacked 2nd-chance managed exceptions, so this is just handling
+//    some V2 Interop corner cases.
 //    @dbgtodo interop: this should eventually completely go away with the V3 design.
 //
 //---------------------------------------------------------------------------------------
@@ -12651,7 +12660,7 @@ Reaction CordbProcess::TriageExcep2ndChanceAndInit(CordbUnmanagedThread * pUnman
         // from them and hope for the best.
         return REACTION(cCLR);
     }
-    
+
     if(pUnmanagedThread->IsCantStop())
     {
         return REACTION(cOOB);
@@ -12848,8 +12857,8 @@ void CordbProcess::HandleDebugEventForInteropDebugging(const DEBUG_EVENT * pEven
     {
         // Note: we use ContinueDebugEvent directly here since our continue is very simple and all of our other
         // continue mechanisms rely on having an UnmanagedThread object to play with ;)
-        STRESS_LOG2(LF_CORDB, LL_INFO1000, "W32ET::W32EL: Continuing without thread on tid 0x%x, code=0x%x\n", 
-                    pEvent->dwThreadId, 
+        STRESS_LOG2(LF_CORDB, LL_INFO1000, "W32ET::W32EL: Continuing without thread on tid 0x%x, code=0x%x\n",
+                    pEvent->dwThreadId,
                     pEvent->dwDebugEventCode);
 
         this->m_state &= ~CordbProcess::PS_WIN32_STOPPED;
@@ -12862,13 +12871,13 @@ void CordbProcess::HandleDebugEventForInteropDebugging(const DEBUG_EVENT * pEven
     }
 
     // There's an innate race such that we can get a Debug Event even after we've suspended a thread.
-    // This can happen if the thread has already dispatched the debug event but we haven't called WFDE to pick it up 
+    // This can happen if the thread has already dispatched the debug event but we haven't called WFDE to pick it up
     // yet. This is sufficiently goofy that we want to stress log it.
     if (pUnmanagedThread->IsSuspended())
     {
         STRESS_LOG1(LF_CORDB, LL_INFO1000, "W32ET::W32EL: Thread 0x%x is suspended\n", pEvent->dwThreadId);
     }
-    
+
     // For debugging crazy races in retail, we'll keep a rolling queue of win32 debug events.
     this->DebugRecordWin32Event(pEvent, pUnmanagedThread);
 
@@ -12914,9 +12923,9 @@ void CordbProcess::HandleDebugEventForInteropDebugging(const DEBUG_EVENT * pEven
 
     // Stress-log the reaction.
 #ifdef _DEBUG
-    STRESS_LOG3(LF_CORDB, LL_INFO1000, "Reaction: %d (%s), line=%d\n", 
-                reaction.GetType(), 
-                reaction.GetReactionName(), 
+    STRESS_LOG3(LF_CORDB, LL_INFO1000, "Reaction: %d (%s), line=%d\n",
+                reaction.GetType(),
+                reaction.GetReactionName(),
                 reaction.GetLine());
 #else
     STRESS_LOG1(LF_CORDB, LL_INFO1000, "Reaction: %d\n", reaction.GetType());
@@ -12950,13 +12959,13 @@ void CordbProcess::HandleDebugEventForInteropDebugging(const DEBUG_EVENT * pEven
 
         // Shouldn't be suspending in the first place with outstanding flares.
         _ASSERTE(!pUnmanagedThread->IsSuspended());
-        
+
         pW32EventThread->ForceDbgContinue(this, pUnmanagedThread, DBG_CONTINUE, false);
         goto LDone;
 
     case Reaction::cCLR:
         // Don't care if thread is suspended here. We'll just let the thread continue whatever it's doing.
-        
+
         this->m_DbgSupport.m_TotalCLR++;
 
         // If this is for the CLR, then we just continue unhandled and know that the CLR has
@@ -12986,8 +12995,8 @@ void CordbProcess::HandleDebugEventForInteropDebugging(const DEBUG_EVENT * pEven
 
         // CLR internal exceptions should be sent back to the CLR and never treated as inband events.
         // If this assert fires, the event was triaged wrong.
-        CONSISTENCY_CHECK_MSGF((pEvent->u.Exception.ExceptionRecord.ExceptionCode != EXCEPTION_COMPLUS), 
-            ("Attempting to dispatch a CLR internal exception as an Inband event. Reaction line=%d\n", 
+        CONSISTENCY_CHECK_MSGF((pEvent->u.Exception.ExceptionRecord.ExceptionCode != EXCEPTION_COMPLUS),
+            ("Attempting to dispatch a CLR internal exception as an Inband event. Reaction line=%d\n",
              reaction.GetLine()));
 
 
@@ -13001,16 +13010,16 @@ void CordbProcess::HandleDebugEventForInteropDebugging(const DEBUG_EVENT * pEven
         // 2) If the process is synchronized (since that means we've already dispatched a managed event).
         // 3) If we've received a SyncComplete event, but aren't yet Sync.  This will almost always be the same as
         //    whether we're synced, but has a distict quality. It's always set by the w32 event thread in Interop,
-        //    and so it's guaranteed to be serialized against this check here (also on the w32et). 
+        //    and so it's guaranteed to be serialized against this check here (also on the w32et).
         // 4) Special deferment - This covers the region where we're sending a Stop/Continue IPC event across.
         //    We defer it here to keep the Helper thread alive so that it can handle these IPC events.
         // Queued events will be dispatched when continue is called.
         BOOL fHasUserUncontinuedNativeEvents = HasUserUncontinuedNativeEvents();
         bool fDeferInbandEvent = (fHasUserUncontinuedNativeEvents ||
-                                  GetSynchronized() || 
+                                  GetSynchronized() ||
                                   GetSyncCompleteRecv() ||
                                   m_specialDeferment);
-                                         
+
         // If we've got a new event, queue it.
         if (fNewEvent)
         {
@@ -13036,14 +13045,14 @@ void CordbProcess::HandleDebugEventForInteropDebugging(const DEBUG_EVENT * pEven
         {
             // No need to defer the dispatch, do it now
             this->DispatchUnmanagedInBandEvent();
+
             goto LDone;
         }
         UNREACHABLE();
     }
-    
+
     case Reaction::cFirstChanceHijackStarted:
-    {   
+    {
         // determine the logical event we are handling, if any
         CordbUnmanagedEvent* pUnmanagedEvent = NULL;
         if(pUnmanagedThread->HasIBEvent())
@@ -13065,7 +13074,7 @@ void CordbProcess::HandleDebugEventForInteropDebugging(const DEBUG_EVENT * pEven
         {
             // there should be an event we hijacked in this case
             _ASSERTE(pUnmanagedEvent != NULL);
-            
+
             // block that event
             LOG((LF_CORDB, LL_INFO100000, "W32ET::W32EL: blocking\n"));
             fcd.action = HIJACK_ACTION_WAIT;
@@ -13088,7 +13097,7 @@ void CordbProcess::HandleDebugEventForInteropDebugging(const DEBUG_EVENT * pEven
     case Reaction::cInbandHijackComplete:
     {
         // We now execute the hijack worker even when not actually hijacked
-        // so can't assert this 
+        // so can't assert this
         //_ASSERTE(pUnmanagedThread->IsFirstChanceHijacked());
 
         // we should not be stepping at the end of hijacks
@@ -13246,9 +13255,9 @@ void CordbProcess::HandleDebugEventForInteropDebugging(const DEBUG_EVENT * pEven
         {
             pUnmanagedThread->EndStepping();
         }
-        pW32EventThread->ForceDbgContinue(this, pUnmanagedThread, 
+        pW32EventThread->ForceDbgContinue(this, pUnmanagedThread,
             pUnmanagedEvent->IsExceptionCleared() ? DBG_CONTINUE : DBG_EXCEPTION_NOT_HANDLED, false);
-        
+
         // We've handled this event. Skip further processing.
         goto LDone;
     }
@@ -13257,7 +13266,7 @@ void CordbProcess::HandleDebugEventForInteropDebugging(const DEBUG_EVENT * pEven
     {
         // Don't care if this thread claimed to be suspended or not. Dispatch event anyways. After all,
         // OOB events can come at *any* time.
-        
+
         // This thread may be suspended. We don't care.
         this->m_DbgSupport.m_TotalOOB++;
 
@@ -13369,13 +13378,13 @@ bool CordbProcess::ExceptionIsFlare(DWORD exceptionCode, const void *exceptionAd
 #endif // FEATURE_INTEROP_DEBUGGING
 
 // Allocate a buffer in the target and copy data into it.
-// 
+//
 // Arguments:
-//    pDomain - an appdomain associated with the allocation request. 
+//    pDomain - an appdomain associated with the allocation request.
 //    bufferSize - size of the buffer in bytes
 //    bufferFrom - local buffer of data (bufferSize bytes) to copy data from.
 //    ppRes - address into target of allocated buffer
-//    
+//
 // Returns:
 //    S_OK on success, else error.
 HRESULT CordbProcess::GetAndWriteRemoteBuffer(CordbAppDomain *pDomain, unsigned int bufferSize, const void *bufferFrom, void **ppRes)
@@ -13389,7 +13398,7 @@ HRESULT CordbProcess::GetAndWriteRemoteBuffer(CordbAppDomain *pDomain, unsigned
     {
         TargetBuffer tbTarget = GetRemoteBuffer(bufferSize); // throws
         SafeWriteBuffer(tbTarget, (const BYTE*) bufferFrom); // throws
-        
+
         // Succeeded.
         *ppRes = CORDB_ADDRESS_TO_PTR(tbTarget.pAddress);
     }
@@ -13522,7 +13531,7 @@ void EnableDebugTrace(CordbUnmanagedThread *ut)
 #endif // _DEBUG
 
 //-----------------------------------------------------------------------------
-// DoDbgContinue 
+// DoDbgContinue
 //
 // Continues from a specific Win32 DEBUG_EVENT.
 //
@@ -13531,7 +13540,7 @@ void EnableDebugTrace(CordbUnmanagedThread *ut)
 //    pUnmanagedEvent - The event to continue.
 //
 //-----------------------------------------------------------------------------
-void CordbWin32EventThread::DoDbgContinue(CordbProcess *pProcess, 
+void CordbWin32EventThread::DoDbgContinue(CordbProcess *pProcess,
                                           CordbUnmanagedEvent *pUnmanagedEvent)
 {
     _ASSERTE(pProcess->ThreadHoldsProcessLock());
@@ -13586,7 +13595,7 @@ void CordbWin32EventThread::DoDbgContinue(CordbProcess *pProcess,
             _ASSERTE(!pUnmanagedEvent->IsEventContinuedUnhijacked());
             pUnmanagedEvent->SetState(CUES_EventContinuedUnhijacked);
             dwContType = pUnmanagedEvent->IsExceptionCleared() ? GetDbgContinueFlag() : DBG_EXCEPTION_NOT_HANDLED;
-            
+
             // The event was never hijacked and so will never need to retrigger, get rid
             // of it right now. If it had been hijacked then we would dequeue it either after the
             // hijack complete flare or one instruction after that when it has had a chance to retrigger
@@ -13638,11 +13647,11 @@ void CordbWin32EventThread::DoDbgContinue(CordbProcess *pProcess,
             {
                 LOG((LF_CORDB, LL_INFO1000, "W32ET::DDC: Continuing from LdrBp, doing managed attach.\n"));
                 pProcess->QueueManagedAttachIfNeededWorker();
-            } 
+            }
             EX_CATCH_HRESULT(hrIgnore);
             SIMPLIFYING_ASSUMPTION(SUCCEEDED(hrIgnore));
         }
-    }        
+    }
 
     STRESS_LOG4(LF_CORDB, LL_INFO1000,
         "W32ET::DDC: calling ContinueDebugEvent(0x%x, 0x%x, 0x%x), process state=0x%x\n",
@@ -13810,7 +13819,7 @@ HRESULT CordbWin32EventThread::SendCreateProcessEvent(
     {
       DWORD ret = WaitForSingleObject(m_actionTakenEvent, INFINITE);
 
-        LOG((LF_CORDB, LL_EVERYTHING, "Process Handle is: %x, m_threadControlEvent is %x\n", 
+        LOG((LF_CORDB, LL_EVERYTHING, "Process Handle is: %x, m_threadControlEvent is %x\n",
              (UINT_PTR)m_actionData.createData.lpProcessInformation->hProcess, (UINT_PTR)m_threadControlEvent));
 
         if (ret == WAIT_OBJECT_0)
@@ -13833,7 +13842,7 @@ HRESULT CordbWin32EventThread::SendCreateProcessEvent(
 //
 // Assumptions:
 //    This occurs on the win32 event thread. It is invokved via
-//    a message sent from code:CordbWin32EventThread::SendCreateProcessEvent 
+//    a message sent from code:CordbWin32EventThread::SendCreateProcessEvent
 //
 // Notes:
 //    Create a new process. This is called in the context of the Win32
@@ -13853,7 +13862,7 @@ void CordbWin32EventThread::CreateProcess()
     // Win32 debugging this process. Otherwise, we have to create
     // suspended to give us time to setup up our side of the IPC
     // channel.
-    BOOL fInteropDebugging   = 
+    BOOL fInteropDebugging   =
 #if defined(FEATURE_INTEROP_DEBUGGING)
         (dwCreationFlags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS));
 #else
@@ -13896,17 +13905,17 @@ void CordbWin32EventThread::CreateProcess()
 
         // Remember the process in the global list of processes.
         if (SUCCEEDED(hr))
-        {   
+        {
             EX_TRY
             {
                 // Mark if we're interop-debugging
                 if (fInteropDebugging)
                 {
-                    pProcess->EnableInteropDebugging(); 
+                    pProcess->EnableInteropDebugging();
                 }
 
                 m_cordb->AddProcess(pProcess); // will take ref if it succeeds
-            } 
+            }
             EX_CATCH_HRESULT(hr);
         }
 
@@ -13916,7 +13925,7 @@ void CordbWin32EventThread::CreateProcess()
         if (SUCCEEDED(hr))
         {
             _ASSERTE(m_pProcess == NULL);
-            m_pProcess.Assign(pProcess);   
+            m_pProcess.Assign(pProcess);
         }
     }
 
@@ -14030,7 +14039,7 @@ void CordbProcess::CleanupHalfBakedLeftSide()
         }
         EX_CATCH
         {
-            _ASSERTE(!"Writing process memory failed, perhaps due to an unexpected disconnection from the target."); 
+            _ASSERTE(!"Writing process memory failed, perhaps due to an unexpected disconnection from the target.");
         }
         EX_END_CATCH(SwallowAllExceptions);
     }
@@ -14039,10 +14048,10 @@ void CordbProcess::CleanupHalfBakedLeftSide()
     CloseIPCHandles();
 
     m_cordb.Clear();
-    
+
     // This process object is Dead-On-Arrival, so it doesn't really have anything to neuter.
     // But for safekeeping, we'll mark it as neutered.
-    UnsafeNeuterDeadObject(); 
+    UnsafeNeuterDeadObject();
 }
 
 
@@ -14052,8 +14061,8 @@ void CordbProcess::CleanupHalfBakedLeftSide()
 //
 //
 // Assumptions:
-//    Called on W32Event Thread, in response to event sent by 
-//    code:CordbWin32EventThread::SendDebugActiveProcessEvent 
+//    Called on W32Event Thread, in response to event sent by
+//    code:CordbWin32EventThread::SendDebugActiveProcessEvent
 //
 // Notes:
 //    Attach to a process. This is called in the context of the Win32
@@ -14079,8 +14088,8 @@ void CordbWin32EventThread::AttachProcess()
 
     // Always do OS attach to the target.
     // By this point, the pid should be valid (because OpenProcess above), pending some race where the process just exited.
-    // The OS will enforce that only 1 debugger is attached. 
-    // Common failure paths here would be: access denied, double-attach    
+    // The OS will enforce that only 1 debugger is attached.
+    // Common failure paths here would be: access denied, double-attach
     {
         hr = m_pNativePipeline->DebugActiveProcess(m_actionData.attachData.machineInfo,
                                                    dwProcessId);
@@ -14091,7 +14100,7 @@ void CordbWin32EventThread::AttachProcess()
         fNativeAttachSucceeded = true;
     }
 
-    
+
     hr = m_pShim->InitializeDataTarget(m_actionData.attachData.processId);
     if (FAILED(hr))
     {
@@ -14100,17 +14109,17 @@ void CordbWin32EventThread::AttachProcess()
 
     // To emulate V2 semantics, we pass 0 for the clrInstanceID into
     // OpenVirtualProcess. This will then connect to the first CLR
-    // loaded.    
+    // loaded.
     {
         const ULONG64 cFirstClrLoaded = 0;
-        hr = CordbProcess::OpenVirtualProcess(cFirstClrLoaded, m_pShim->GetDataTarget(), NULL, m_cordb, dwProcessId, m_pShim, &pProcess);   
+        hr = CordbProcess::OpenVirtualProcess(cFirstClrLoaded, m_pShim->GetDataTarget(), NULL, m_cordb, dwProcessId, m_pShim, &pProcess);
         if (FAILED(hr))
         {
             goto LExit;
         }
     }
 
-    // Remember the process in the global list of processes.    
+    // Remember the process in the global list of processes.
     // The caller back in code:Cordb::DebugActiveProcess will then get this by fetching it from the list.
 
     EX_TRY
@@ -14129,7 +14138,7 @@ void CordbWin32EventThread::AttachProcess()
             PUBLIC_CALLBACK_IN_THIS_SCOPE0_NO_LOCK(pProcess);
             m_pShim->BeginQueueFakeAttachEvents();
         }
-    } 
+    }
     EX_CATCH_HRESULT(hr);
     if (FAILED(hr))
     {
@@ -14146,7 +14155,7 @@ void CordbWin32EventThread::AttachProcess()
 
 LExit:
     if (FAILED(hr))
-    {        
+    {
         // If we succeed to do a native-attach, but then failed elsewhere, try to native-detach.
         if (fNativeAttachSucceeded)
         {
@@ -14389,7 +14398,7 @@ doRealContinue:
             // This is either the Frozen -> Running transition or a
             // Synced -> Running transition
             _ASSERTE(pProcess->m_outOfBandEventQueue == NULL);
-            
+
 
             pProcess->m_doRealContinueAfterOOBBlock = false;
 
@@ -14414,7 +14423,7 @@ doRealContinue:
                     if(pProcess->m_state & CordbProcess::PS_WIN32_STOPPED)
                     {
                         DoDbgContinue(pProcess, pProcess->m_lastDispatchedIBEvent);
-                        
+
                         // This if should not be necessary, I am just being extra careful because this
                         // fix is going in late - see issue 818301
                         _ASSERTE(pProcess->m_lastDispatchedIBEvent != NULL);
@@ -14434,7 +14443,7 @@ doRealContinue:
                 {
                     // free all the hijacked threads that hit native debug events
                     pProcess->ResumeHijackedThreads();
-                    
+
                     // after continuing the here the process should be running completely
                     // free... no hijacks, no suspended threads, and of course not frozen
                     if(pProcess->m_state & CordbProcess::PS_WIN32_STOPPED)
@@ -14497,7 +14506,7 @@ void ExitProcessWorkItem::Do()
 
     // There is a race condition here where the debuggee process is killed while we are processing a process
     // detach.  We queue the process exit event for the Win32 event thread before queueing the process detach
-    // event.  By the time this function is executed, we may have neutered the CordbProcess already as a 
+    // event.  By the time this function is executed, we may have neutered the CordbProcess already as a
     // result of code:CordbProcess::Detach.  Detect that case here under the SG lock.
     {
         RSLockHolder ch(GetProcess()->GetStopGoLock());
@@ -14522,7 +14531,7 @@ void ExitProcessWorkItem::Do()
     // This CordbProcess object now has no reservations against a client calling ICorDebug::Terminate.
     // That call may race against the CordbProcess::Neuter below, but since we already neutered the children,
     // that neuter call will not do anything interesting that will conflict with Terminate.
-    
+
     LOG((LF_CORDB, LL_INFO1000,"W32ET::EP: returned from ExitProcess callback\n"));
 
     {
@@ -14760,10 +14769,10 @@ HRESULT CordbWin32EventThread::Stop()
 
 
 // Allocate a buffer of cbBuffer bytes in the target.
-// 
+//
 // Arguments:
 //     cbBuffer - count of bytes for the buffer.
-//     
+//
 // Returns:
 //     a TargetBuffer describing the new memory region in the target.
 //     Throws on error.
@@ -14789,7 +14798,7 @@ TargetBuffer CordbProcess::GetRemoteBuffer(ULONG cbBuffer)
     IfFailThrow(event.GetBufferResult.hr);
 
     // The request succeeded. Return the newly allocated range.
-    return TargetBuffer(event.GetBufferResult.pBuffer, cbBuffer);    
+    return TargetBuffer(event.GetBufferResult.pBuffer, cbBuffer);
 }
 
 /*
@@ -14841,7 +14850,7 @@ HRESULT CordbProcess::SetDesiredNGENCompilerFlags(DWORD dwFlags)
         hr = pProcess->GetDAC()->SetNGENCompilerFlags(dwFlags);
         if (!SUCCEEDED(hr) && GetShim() != NULL)
         {
-            // Emulate V2 error semantics. 
+            // Emulate V2 error semantics.
             hr = GetShim()->FilterSetNgenHresult(hr);
         }
     }
@@ -14895,7 +14904,7 @@ HRESULT CordbProcess::GetReferenceValueFromGCHandle(
         {
             ThrowHR(CORDBG_E_BAD_REFERENCE_VALUE);
         }
-        
+
         IDacDbiInterface* pDAC = GetProcess()->GetDAC();
         VMPTR_OBJECTHANDLE vmObjHandle = pDAC->GetVmObjectHandle(gcHandle);
         if(!pDAC->IsVmObjectHandleValid(vmObjHandle))
@@ -15036,25 +15045,25 @@ HRESULT CordbProcess::IsReadyForDetach()
         if (hKernel32 == NULL)
             return HRESULT_FROM_GetLastError();
         typedef BOOL (*DebugActiveProcessStopSig) (DWORD);
-        DebugActiveProcessStopSig pDebugActiveProcessStop = 
+        DebugActiveProcessStopSig pDebugActiveProcessStop =
             reinterpret_cast<DebugActiveProcessStopSig>(GetProcAddress(hKernel32, "DebugActiveProcessStop"));
         if (pDebugActiveProcessStop == NULL)
             return COR_E_PLATFORMNOTSUPPORTED;
 #endif
-    }    
+    }
 
     return S_OK;
 }
 
 
 /*
- * Look for any thread which was last seen in the specified AppDomain.  
+ * Look for any thread which was last seen in the specified AppDomain.
  * The CordbAppDomain object is about to be neutered due to an AD Unload
  * So the thread must no longer be considered to be in that domain.
- * Note that this is a workaround due to the existance of the (possibly incorrect) 
+ * Note that this is a workaround due to the existance of the (possibly incorrect)
  * cached AppDomain value.  Ideally we would remove the cached value entirely
  * and there would be no need for this.
- * 
+ *
  * @dbgtodo: , appdomain: We should remove CordbThread::m_pAppDomain in the V3 architecture.
  * If we need the thread's current domain, we should get it accurately with DAC.
  */
@@ -15062,13 +15071,13 @@ void CordbProcess::UpdateThreadsForAdUnload(CordbAppDomain * pAppDomain)
 {
     INTERNAL_API_ENTRY(this);
 
-    // If we're doing an AD unload then we should have already seen the ATTACH 
+    // If we're doing an AD unload then we should have already seen the ATTACH
     // notification for the default domain.
     //_ASSERTE( m_pDefaultAppDomain != NULL );
     // @dbgtodo appdomain: fix Default domain invariants with DAC-izing Appdomain work.
-    
+
     RSLockHolder lockHolder(GetProcessLock());
-    
+
     CordbThread* t;
     HASHFIND find;
 
@@ -15079,7 +15088,7 @@ void CordbProcess::UpdateThreadsForAdUnload(CordbAppDomain * pAppDomain)
     {
         if( t->GetAppDomain() == pAppDomain )
         {
-            // This thread cannot actually be in this AppDomain anymore (since it's being 
+            // This thread cannot actually be in this AppDomain anymore (since it's being
             // unloaded).  Reset it to point to the default AppDomain
             t->m_pAppDomain = m_pDefaultAppDomain;
         }
@@ -15087,7 +15096,7 @@ void CordbProcess::UpdateThreadsForAdUnload(CordbAppDomain * pAppDomain)
 }
 
 // CordbProcess::LookupClass
-// Looks up a previously constructed CordbClass instance without creating. May return NULL if the 
+// Looks up a previously constructed CordbClass instance without creating. May return NULL if the
 // CordbClass instance doesn't exist.
 // Argument: (in) vmDomainFile - pointer to the domainfile for the module
 //           (in) mdTypeDef    - metadata token for the class
@@ -15108,39 +15117,39 @@ CordbClass * CordbProcess::LookupClass(ICorDebugAppDomain * pAppDomain, VMPTR_Do
 } // CordbProcess::LookupClass
 
 //---------------------------------------------------------------------------------------
-// Look for a specific module in the process. 
+// Look for a specific module in the process.
 //
 // Arguments:
 //    vmDomainFile - non-null module to lookup
-// 
+//
 // Returns:
 //    a CordbModule object for the given cookie. Object may be from the cache, or created
-//    lazily. 
+//    lazily.
 //    Never returns null.  Throws on error.
 //
 // Notes:
 //    A VMPTR_DomainFile has appdomain affinity, but is ultimately scoped to a process.
 //    So if we get a raw VMPTR_DomainFile (eg, from the stackwalker or from some other
-//    lookup function), then we need to do a process wide lookup since we don't know which 
+//    lookup function), then we need to do a process wide lookup since we don't know which
 //    appdomain it's in. If you know the appdomain, you can use code:CordbAppDomain::LookupOrCreateModule.
-//    
+//
 CordbModule * CordbProcess::LookupOrCreateModule(VMPTR_DomainFile vmDomainFile)
 {
     INTERNAL_API_ENTRY(this);
-    
+
     RSLockHolder lockHolder(GetProcess()->GetProcessLock());
     _ASSERTE(!vmDomainFile.IsNull());
 
     DomainFileInfo data;
     GetDAC()->GetDomainFileData(vmDomainFile, &data); // throws
-    
+
     CordbAppDomain * pAppDomain = LookupOrCreateAppDomain(data.vmAppDomain);
     return pAppDomain->LookupOrCreateModule(vmDomainFile);
 }
 
 //---------------------------------------------------------------------------------------
 // Determine if the process has any in-band queued events which have not been dispatched
-// 
+//
 // Returns:
 //    TRUE iff there are undispatched IB events
 //
@@ -15148,7 +15157,7 @@ CordbModule * CordbProcess::LookupOrCreateModule(VMPTR_DomainFile vmDomainFile)
 BOOL CordbProcess::HasUndispatchedNativeEvents()
 {
     INTERNAL_API_ENTRY(this);
-    
+
     CordbUnmanagedEvent* pEvent = m_unmanagedEventQueue;
     while(pEvent != NULL && pEvent->IsDispatched())
     {
@@ -15161,7 +15170,7 @@ BOOL CordbProcess::HasUndispatchedNativeEvents()
 
 //---------------------------------------------------------------------------------------
 // Determine if the process has any in-band queued events which have not been user continued
-// 
+//
 // Returns:
 //    TRUE iff there are user uncontinued IB events
 //
@@ -15169,7 +15178,7 @@ BOOL CordbProcess::HasUndispatchedNativeEvents()
 BOOL CordbProcess::HasUserUncontinuedNativeEvents()
 {
     INTERNAL_API_ENTRY(this);
-    
+
     CordbUnmanagedEvent* pEvent = m_unmanagedEventQueue;
     while(pEvent != NULL && pEvent->IsEventUserContinued())
     {
@@ -15183,7 +15192,7 @@ BOOL CordbProcess::HasUserUncontinuedNativeEvents()
 //---------------------------------------------------------------------------------------
 // Hijack the thread which had this event. If the thread is already hijacked this method
 // has no effect.
-// 
+//
 // Arguments:
 //    pUnmanagedEvent - the debug event which requires us to hijack
 //
@@ -15197,7 +15206,7 @@ HRESULT CordbProcess::HijackIBEvent(CordbUnmanagedEvent * pUnmanagedEvent)
     _ASSERTE(!pUnmanagedEvent->IsEventContinuedHijacked());
     // Can only hijack IB events
     _ASSERTE(pUnmanagedEvent->IsIBEvent());
-    
+
     // If we already hijacked the event then there is nothing left to do
     if(pUnmanagedEvent->m_owner->IsFirstChanceHijacked() ||
         pUnmanagedEvent->m_owner->IsGenericHijacked())
@@ -15241,7 +15250,7 @@ HRESULT CordbProcess::GetAttachStateFlags(CLR_DEBUGGING_PROCESS_FLAGS *pFlags)
 // Determine if this version of ICorDebug is compatibile with the ICorDebug in the specified major CLR version
 bool CordbProcess::IsCompatibleWith(DWORD clrMajorVersion)
 {
-    // The debugger versioning policy is that debuggers generally need to opt-in to supporting major new 
+    // The debugger versioning policy is that debuggers generally need to opt-in to supporting major new
     // versions of the CLR.  Often new versions of the CLR violate some invariant that previous debuggers assume
     // (eg. hot/cold splitting in Whidbey, multiple CLRs in a process in CLR v4), and neither VS or the CLR
     // teams generally want the support burden of forward compatibility.
@@ -15251,17 +15260,17 @@ bool CordbProcess::IsCompatibleWith(DWORD clrMajorVersion)
     // number of the clr.dll has changed. This assert is here to remind you to do a bit of other
     // work you may not have realized you needed to do so that our versioning works smoothly
     // for debugging. You probably want to contact the CLR DST team if you are a
-    // non-debugger person hitting this. DON'T JUST DELETE THIS ASSERT!!! 
+    // non-debugger person hitting this. DON'T JUST DELETE THIS ASSERT!!!
     //
     // 1) You should ensure new versions of all ICorDebug users in DevDiv (VS Debugger, MDbg, etc.)
-    //    are using a creation path that explicitly specifies that they support this new major 
+    //    are using a creation path that explicitly specifies that they support this new major
     //    version of the CLR.
     // 2) You should file an issue to track blocking earlier debuggers from targetting this
     //    version of the CLR (i.e. update requiredVersion to the new CLR major
     //    version).  To enable a smooth internal transition, this often isn't done until absolutely
     //    necessary (sometimes as late as Beta2).
     // 3) You can consider updating the CLR_ID guid used by the shim to recognize a CLR, but only
-    //    if it's important to completely hide newer CLRs from the shim.  The expectation now 
+    //    if it's important to completely hide newer CLRs from the shim.  The expectation now
     //    is that we won't need to do this (i.e. we'd like VS to give a nice error message about
     //    needed a newer version of the debugger, rather than just acting as if a process has no CLR).
     // 4) Update this assert so that it no longer fires for your new CLR version or any of
@@ -15271,8 +15280,8 @@ bool CordbProcess::IsCompatibleWith(DWORD clrMajorVersion)
     _ASSERTE_MSG(clrMajorVersion <= 4,
         "Found major CLR version greater than 4 in mscordbi.dll from CLRv4 - contact CLRDST");
 
-    // This knob lets us enable forward compatibility for internal scenarios, and also simulate new 
-    // versions of the runtime for testing the failure user-experience in a version of the debugger 
+    // This knob lets us enable forward compatibility for internal scenarios, and also simulate new
+    // versions of the runtime for testing the failure user-experience in a version of the debugger
     // before it is shipped.
     // We don't want to risk customers getting this, so for RTM builds this must be CHK-only.
     // To aid in internal transition, we may temporarily enable this in RET builds, but when
@@ -15308,7 +15317,7 @@ bool CordbProcess::IsThreadSuspendedOrHijacked(ICorDebugThread * pICorDebugThrea
     // its entire duration. As a result, this needs to be considered a reentrant API. See
     // comments above code:PrivateShimCallbackHolder for more info.
     PUBLIC_REENTRANT_API_ENTRY_FOR_SHIM(this);
-    
+
     CordbThread * pCordbThread = static_cast<CordbThread *> (pICorDebugThread);
     return GetDAC()->IsThreadSuspendedOrHijacked(pCordbThread->m_vmThreadToken);
 }
index 39ac60d..d9f25e6 100644 (file)
@@ -3,7 +3,7 @@
 // See the LICENSE file in the project root for more information.
 //*****************************************************************************
 // File: RsMain.cpp
-// 
+//
 
 // Random RS utility stuff, plus root ICorCordbug implementation
 //
@@ -102,7 +102,7 @@ void DbgRSThread::NotifyTakeLock(RSLock * pLock)
     {
         return;
     }
-    
+
     int iLevel = pLock->GetLevel();
 
     // Is it safe to take this lock?
@@ -132,7 +132,7 @@ void DbgRSThread::NotifyReleaseLock(RSLock * pLock)
     {
         return;
     }
-    
+
     int iLevel = pLock->GetLevel();
     m_cLocks[iLevel]--;
     _ASSERTE(m_cLocks[iLevel] == 0);
@@ -207,9 +207,9 @@ LONG Cordb::s_DbgMemOutstandingObjectMax = 0;
 
 // Default implementation for neutering left-side resources.
 void CordbBase::NeuterLeftSideResources()
-{ 
-    LIMITED_METHOD_CONTRACT;   
-    
+{
+    LIMITED_METHOD_CONTRACT;
+
     RSLockHolder lockHolder(GetProcess()->GetProcessLock());
     Neuter();
 }
@@ -221,14 +221,14 @@ void CordbBase::Neuter()
     // Neutering occurs under the process lock. Neuter can be called twice
     // and so locking protects against races in double-delete.
     // @dbgtodo - , some CordbBase objects (Cordb, CordbProcessEnum),
-    // don't have process affinity these should eventually be hoisted to the shim, 
+    // don't have process affinity these should eventually be hoisted to the shim,
     // and then we can enforce.
     CordbProcess * pProcess = GetProcess();
     if (pProcess != NULL)
     {
         _ASSERTE(pProcess->ThreadHoldsProcessLock());
     }
-    CordbCommonBase::Neuter(); 
+    CordbCommonBase::Neuter();
 }
 
 //-----------------------------------------------------------------------------
@@ -247,7 +247,7 @@ NeuterList::~NeuterList()
     CONSISTENCY_CHECK_MSGF(m_pHead == NULL, ("NeuterList not empty on shutdown. this=0x%p", this));
 }
 
-// Wrapper around code:NeuterList::UnsafeAdd 
+// Wrapper around code:NeuterList::UnsafeAdd
 void NeuterList::Add(CordbProcess * pProcess, CordbBase * pObject)
 {
     CONTRACTL
@@ -268,7 +268,7 @@ void NeuterList::Add(CordbProcess * pProcess, CordbBase * pObject)
 //
 // Returns:
 //     Throws on error.
-//  
+//
 // Notes:
 //     This will add it to the list and maintain an internal reference to it.
 //     This will take the process lock.
@@ -276,13 +276,13 @@ void NeuterList::Add(CordbProcess * pProcess, CordbBase * pObject)
 void NeuterList::UnsafeAdd(CordbProcess * pProcess, CordbBase * pObject)
 {
     _ASSERTE(pObject != NULL);
-    
-    // Lock if needed. 
+
+    // Lock if needed.
     RSLock * pLock = (pProcess != NULL) ? pProcess->GetProcessLock() : NULL;
     RSLockHolder lockHolder(pLock, FALSE);
     if (pLock != NULL) lockHolder.Acquire();
 
-    
+
     Node * pNode = new Node(); // throws on error.
     pNode->m_pObject.Assign(pObject);
     pNode->m_pNext = m_pHead;
@@ -303,10 +303,10 @@ void NeuterList::UnsafeAdd(CordbProcess * pProcess, CordbBase * pObject)
 //     This will release all internal references and empty the list.
 void NeuterList::NeuterAndClear(CordbProcess * pProcess)
 {
-    RSLock * pLock = (pProcess != NULL) ? pProcess->GetProcessLock() : NULL;        
+    RSLock * pLock = (pProcess != NULL) ? pProcess->GetProcessLock() : NULL;
     (void)pLock; //prevent "unused variable" error from GCC
     _ASSERTE((pLock == NULL) || pLock->HasLock());
-        
+
     while (m_pHead != NULL)
     {
         Node * pTemp = m_pHead;
@@ -351,7 +351,7 @@ void NeuterList::SweepAllNeuterAtWillObjects(CordbProcess * pProcess)
 
 //-----------------------------------------------------------------------------
 // Neuters all objects in the list and empties the list.
-// 
+//
 // Notes:
 //    See also code:LeftSideResourceCleanupList::SweepNeuterLeftSideResources,
 //    which only neuters objects that have been marked as NeuterAtWill (external
@@ -360,9 +360,9 @@ void LeftSideResourceCleanupList::NeuterLeftSideResourcesAndClear(CordbProcess *
 {
     // Traversal protected under Process-lock.
     // SG-lock must already be held to do neutering.
-    // Stop-Go lock is bigger than Process-lock. 
+    // Stop-Go lock is bigger than Process-lock.
     // Neutering requires the Stop-Go lock (until we get rid of IPC events)
-    // But we want to be able to add to the Neuter list under the Process-lock. 
+    // But we want to be able to add to the Neuter list under the Process-lock.
     // So we just need to protected m_pHead under process-lock.
 
     // "Privatize" the list under the lock.
@@ -378,7 +378,7 @@ void LeftSideResourceCleanupList::NeuterLeftSideResourcesAndClear(CordbProcess *
 
     // @dbgtodo - eventually everything can be under the process lock.
     _ASSERTE(!pLock->HasLock()); // Can't hold Process lock while calling NeuterLeftSideResources
-    
+
     // Now we're operating on local data, so traversing doesn't need to be under the lock.
     while (pCur != NULL)
     {
@@ -388,17 +388,17 @@ void LeftSideResourceCleanupList::NeuterLeftSideResourcesAndClear(CordbProcess *
         pTemp->m_pObject->NeuterLeftSideResources();
         delete pTemp; // will implicitly release
     }
-  
+
 }
 
 //-----------------------------------------------------------------------------
 // Only neuter objects that are marked. Removes neutered objects from the list.
-// 
+//
 // Arguments:
 //    pProcess - non-null process owning the objects in the list
-//    
+//
 // Notes:
-//    this cleans up left-side resources held by objects in the list. 
+//    this cleans up left-side resources held by objects in the list.
 //    It may send IPC events to do this.
 void LeftSideResourceCleanupList::SweepNeuterLeftSideResources(CordbProcess * pProcess)
 {
@@ -413,12 +413,12 @@ void LeftSideResourceCleanupList::SweepNeuterLeftSideResources(CordbProcess * pP
     // Lock while we "privatize" the head.
     RSLockHolder lockHolder(pLock);
     Node * pHead = m_pHead;
-    m_pHead = NULL; 
+    m_pHead = NULL;
     lockHolder.Release();
 
     Node ** ppLast = &pHead;
     Node * pCur = pHead;
-    
+
     // Can't hold the process-lock while calling Neuter.
     while (pCur != NULL)
     {
@@ -444,7 +444,7 @@ void LeftSideResourceCleanupList::SweepNeuterLeftSideResources(CordbProcess * pP
 
     // Now link back in. m_pHead may have changed while we were unlocked.
     // The list does not need to be ordered.
-        
+
     lockHolder.Acquire();
     *ppLast = m_pHead;
     m_pHead = pHead;
@@ -465,7 +465,7 @@ void CordbCommonBase::InitializeCommon()
     {
         return;
     }
-    
+
 #ifdef STRESS_LOG
     {
         bool fStressLog = false;
@@ -503,14 +503,14 @@ void CordbCommonBase::InitializeCommon()
 
     // Add debug privilege. This will let us call OpenProcess() on anything, regardless of ACL.
     AddDebugPrivilege();
-        
+
     IsInitialized = true;
 }
 
 // Adjust the permissions of this process to ensure that we have
 // the debugging priviledge. If we can't make the adjustment, it
 // only means that we won't be able to attach to a service under
-// NT, so we won't treat that as a critical failure. 
+// NT, so we won't treat that as a critical failure.
 // This also will let us call OpenProcess() on anything, regardless of DACL. This allows an
 // Admin debugger to attach to a debuggee in the guest account.
 // Ideally, the debugger would set this (and we wouldn't mess with privileges at all). However, we've been
@@ -526,14 +526,14 @@ void CordbCommonBase::AddDebugPrivilege()
 
     fSucc = LookupPrivilegeValueW(NULL, SE_DEBUG_NAME, &SeDebugLuid);
     DWORD err = GetLastError();
-    
+
     if (!fSucc)
     {
         STRESS_LOG1(LF_CORDB, LL_INFO1000, "Unable to adjust permissions of this process to include SE_DEBUG. Lookup failed %d\n", err);
         return;
     }
-    
-    
+
+
     // Retrieve a handle of the access token
     fSucc = OpenProcessToken(GetCurrentProcess(),
                              TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
@@ -555,7 +555,7 @@ void CordbCommonBase::AddDebugPrivilege()
         // The return value of AdjustTokenPrivileges cannot be tested.
         if (err != ERROR_SUCCESS)
         {
-            STRESS_LOG1(LF_CORDB, LL_INFO1000, 
+            STRESS_LOG1(LF_CORDB, LL_INFO1000,
                 "Unable to adjust permissions of this process to include SE_DEBUG. Adjust failed %d\n", err);
         }
         else
@@ -565,7 +565,7 @@ void CordbCommonBase::AddDebugPrivilege()
         CloseHandle(hToken);
     }
 #endif
-} 
+}
 
 
 namespace
@@ -868,7 +868,8 @@ namespace
         virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** pInterface);
         virtual ULONG STDMETHODCALLTYPE AddRef();
         virtual ULONG STDMETHODCALLTYPE Release();
-        COM_METHOD SomeWork(ICorDebugThread * pThread, ICorDebugAppDomain * pAppDomain);
+        COM_METHOD BeforeGarbageCollection(ICorDebugController* pController);
+        COM_METHOD AfterGarbageCollection(ICorDebugController* pController);
     private:
         // not implemented
         DefaultManagedCallback4(const DefaultManagedCallback4&);
@@ -922,12 +923,22 @@ namespace
     }
 
     HRESULT
-        DefaultManagedCallback4::SomeWork(ICorDebugThread * pThread, ICorDebugAppDomain * pAppDomain)
+        DefaultManagedCallback4::BeforeGarbageCollection(ICorDebugController* pController)
     {
         //
         // Just ignore and continue the process.
         //
-        pAppDomain->Continue(false);
+        pController->Continue(false);
+        return S_OK;
+    }
+
+    HRESULT
+        DefaultManagedCallback4::AfterGarbageCollection(ICorDebugController* pController)
+    {
+        //
+        // Just ignore and continue the process.
+        //
+        pController->Continue(false);
         return S_OK;
     }
 }
@@ -968,13 +979,13 @@ void Cordb::Neuter()
         return;
     }
 
-    
+
     RSLockHolder lockHolder(&m_processListMutex);
     m_pProcessEnumList.NeuterAndClear(NULL);
-    
+
 
     HRESULT hr = S_OK;
-    EX_TRY // @dbgtodo push this up. 
+    EX_TRY // @dbgtodo push this up.
     {
         // Iterating needs to be done under the processList lock (small), while neutering
         // needs to be able to take the process lock (big).
@@ -983,13 +994,13 @@ void Cordb::Neuter()
 
         // can't hold list lock while calling CordbProcess::Neuter (which
         // will take the Process-lock).
-        lockHolder.Release(); 
+        lockHolder.Release();
 
         list.NeuterAndClear();
         // List dtor calls release on each element
-    }    
+    }
     EX_CATCH_HRESULT(hr);
-    SIMPLIFYING_ASSUMPTION_SUCCEEDED(hr); 
+    SIMPLIFYING_ASSUMPTION_SUCCEEDED(hr);
 
     CordbCommonBase::Neuter();
 
@@ -1044,7 +1055,7 @@ HRESULT Cordb::Terminate()
 
     FAIL_IF_NEUTERED(this);
 
-    // We can't terminate the debugging services from within a callback. 
+    // We can't terminate the debugging services from within a callback.
     // Caller is supposed to be out of all callbacks when they call this.
     // This also avoids a deadlock because we'll shutdown the RCET, which would block if we're
     // in the RCET.
@@ -1188,7 +1199,7 @@ HRESULT Cordb::Initialize(void)
     if (!m_initialized)
     {
         CordbCommonBase::InitializeCommon();
-        
+
         // Since logging wasn't active when we called CordbBase, do it now.
         LOG((LF_CORDB, LL_EVERYTHING, "Memory: CordbBase object allocated: this=%p, count=%d, RootObject\n", this, s_TotalObjectCount));
         LOG((LF_CORDB, LL_INFO10, "Initializing ICorDebug...\n"));
@@ -1404,7 +1415,7 @@ HRESULT Cordb::SetTargetCLR(HMODULE hmodTargetCLR)
     CoreClrCallbacks cccallbacks;
     cccallbacks.m_hmodCoreCLR               = hmodTargetCLR;
     cccallbacks.m_pfnIEE                    = NULL;
-    cccallbacks.m_pfnGetCORSystemDirectory  = NULL;    
+    cccallbacks.m_pfnGetCORSystemDirectory  = NULL;
     cccallbacks.m_pfnGetCLRFunction         = NULL;
     InitUtilcode(cccallbacks);
 
@@ -1501,7 +1512,7 @@ bool Cordb::IsCreateProcessSupported()
 {
 #if !defined(FEATURE_DBGIPC_TRANSPORT_DI)
     return false;
-#else 
+#else
     return true;
 #endif
 }
@@ -1535,7 +1546,7 @@ bool Cordb::IsInteropDebuggingSupported()
 // Creates a process.
 //
 // Arguments:
-//    The following arguments are passed thru unmodified to the OS CreateProcess API and 
+//    The following arguments are passed thru unmodified to the OS CreateProcess API and
 //       are defined by that API.
 //           lpApplicationName
 //           lpCommandLine
@@ -1850,13 +1861,13 @@ HRESULT Cordb::DebugActiveProcessCommon(ICorDebugRemoteTarget * pRemoteTarget,
         }
 
 #if defined(FEATURE_DBGIPC_TRANSPORT_DI)
-        // This is where we queue the managed attach event in Whidbey.  In the new architecture, the Windows 
-        // pipeline gets a loader breakpoint when native attach is completed, and that's where we queue the 
+        // This is where we queue the managed attach event in Whidbey.  In the new architecture, the Windows
+        // pipeline gets a loader breakpoint when native attach is completed, and that's where we queue the
         // managed attach event.  See how we handle the loader breakpoint in code:ShimProcess::DefaultEventHandler.
         // However, the Mac debugging transport gets no such breakpoint, and so we need to do this here.
-        // 
-        // @dbgtodo  Mac - Ideally we should hide this in our pipeline implementation, or at least move 
-        // this to the shim.  
+        //
+        // @dbgtodo  Mac - Ideally we should hide this in our pipeline implementation, or at least move
+        // this to the shim.
         _ASSERTE(!fWin32Attach);
         {
             pProcess->Lock();
@@ -1864,7 +1875,7 @@ HRESULT Cordb::DebugActiveProcessCommon(ICorDebugRemoteTarget * pRemoteTarget,
             pProcess->Unlock();
         }
 #endif // FEATURE_DBGIPC_TRANSPORT_DI
-        
+
         *ppProcess = (ICorDebugProcess*) pProcess;
     }
 
@@ -1883,23 +1894,23 @@ void Cordb::CheckCompatibility()
         clrMajor = 2;
     else if (debuggerVersion <= CorDebugVersion_4_0)
         clrMajor = 4;
-    else 
+    else
         clrMajor = 5;   // some unrecognized future version
 
     if(!CordbProcess::IsCompatibleWith(clrMajor))
     {
         // Carefully choose our error-code to get an appropriate error-message from VS 2008
         // If GetDebuggerVersion is >= 4, we could consider using the more-appropriate (but not
-        // added until V4) HRESULT CORDBG_E_UNSUPPORTED_FORWARD_COMPAT that is used by 
+        // added until V4) HRESULT CORDBG_E_UNSUPPORTED_FORWARD_COMPAT that is used by
         // OpenVirtualProcess, but it's probably simpler to keep ICorDebug APIs returning
         // consistent error codes.
         ThrowHR(CORDBG_E_INCOMPATIBLE_PROTOCOL);
     }
 }
 
-HRESULT Cordb::DebugActiveProcessEx(ICorDebugRemoteTarget * pRemoteTarget, 
-                                    DWORD dwProcessId, 
-                                    BOOL fWin32Attach, 
+HRESULT Cordb::DebugActiveProcessEx(ICorDebugRemoteTarget * pRemoteTarget,
+                                    DWORD dwProcessId,
+                                    BOOL fWin32Attach,
                                     ICorDebugProcess ** ppProcess)
 {
     if (pRemoteTarget == NULL)
@@ -1956,12 +1967,12 @@ HRESULT Cordb::EnumerateProcesses(ICorDebugProcessEnum **ppProcesses)
 
         RSInitHolder<CordbHashTableEnum> pEnum;
         CordbHashTableEnum::BuildOrThrow(
-            this, 
-            &m_pProcessEnumList, 
+            this,
+            &m_pProcessEnumList,
             GetProcessList(),
             IID_ICorDebugProcessEnum,
             pEnum.GetAddr());
-        
+
 
         pEnum.TransferOwnershipExternal(ppProcesses);
     }
@@ -1995,7 +2006,7 @@ HRESULT Cordb::CanLaunchOrAttach(DWORD dwProcessId, BOOL fWin32DebuggingEnabled)
     EX_TRY
     {
         EnsureCanLaunchOrAttach(fWin32DebuggingEnabled);
-    } 
+    }
     EX_CATCH_HRESULT(hr);
 
     return hr;
@@ -2095,12 +2106,12 @@ CordbEnumFilter::CordbEnumFilter(CordbBase * pOwnerObj, NeuterList * pOwnerList)
     m_iCount (0)
 {
     _ASSERTE(m_pOwnerNeuterList != NULL);
-    
+
     HRESULT hr = S_OK;
     EX_TRY
     {
         m_pOwnerNeuterList->Add(pOwnerObj->GetProcess(), this);
-    } 
+    }
     EX_CATCH_HRESULT(hr);
     SetUnrecoverableIfFailed(GetProcess(), hr);
 
@@ -2114,15 +2125,15 @@ CordbEnumFilter::CordbEnumFilter(CordbEnumFilter *src)
     m_pCurrent (NULL)
 {
     _ASSERTE(m_pOwnerNeuterList != NULL);
-    
+
     HRESULT hr = S_OK;
     EX_TRY
     {
         m_pOwnerNeuterList->Add(src->GetProcess(), this);
-    } 
+    }
     EX_CATCH_HRESULT(hr);
     SetUnrecoverableIfFailed(GetProcess(), hr);
-    
+
 
 
     int iCountSanityCheck = 0;
@@ -2214,10 +2225,10 @@ void CordbEnumFilter::Neuter()
 HRESULT CordbEnumFilter::QueryInterface(REFIID id, void **ppInterface)
 {
     // if we QI with the IID of the base type, we can't just return a pointer ICorDebugEnum directly, because
-    // the cast is ambiguous. This happens because CordbEnumFilter implements both ICorDebugModuleEnum and 
+    // the cast is ambiguous. This happens because CordbEnumFilter implements both ICorDebugModuleEnum and
     // ICorDebugThreadEnum, both of which derive in turn from ICorDebugEnum. This produces a diamond inheritance
-    // graph. Thus we need a double cast. It doesn't really matter whether we pick ICorDebugThreadEnum or 
-    // ICorDebugModuleEnum, because it will be backed by the same object regardless. 
+    // graph. Thus we need a double cast. It doesn't really matter whether we pick ICorDebugThreadEnum or
+    // ICorDebugModuleEnum, because it will be backed by the same object regardless.
     if (id == IID_ICorDebugEnum)
         *ppInterface = static_cast<ICorDebugEnum *>(static_cast<ICorDebugThreadEnum *>(this));
     else if (id == IID_ICorDebugModuleEnum)
@@ -2557,7 +2568,7 @@ HRESULT CordbEnumFilter::Init (ICorDebugThreadEnum *pThreadEnum, CordbAppDomain
         {
             goto Error;
         }
-       
+
         if (pThreadDomain == pAppDomain)
         {
             pElement = new (nothrow) EnumElement;
index 35e9f38..00501da 100644 (file)
@@ -3,7 +3,7 @@
 // See the LICENSE file in the project root for more information.
 //*****************************************************************************
 // File: ShimCallback.cpp
-// 
+//
 
 //
 // The V3 ICD debugging APIs have a lower abstraction level than V2.
@@ -13,7 +13,7 @@
 #include "stdafx.h"
 
 #include "safewrap.h"
-#include "check.h" 
+#include "check.h"
 
 #include <limits.h>
 #include "shimpriv.h"
@@ -78,22 +78,22 @@ HRESULT ShimProxyCallback::QueryInterface(REFIID riid, void **ppInterface)
 
 //
 // Map from an old frame to a new one.
-// 
+//
 // Arguments:
 //   pThread - thread that frame is on
 //   pOldFrame - old frame before the continue, may have gotten neutered.
-//   
+//
 // Returns:
 //   a new, non-neutered frame that matches the old frame.
-//   
+//
 // Notes:
 //   Called by event handlers below (which are considered Outside the RS).
 //   No adjust of reference, Thread already has reference.
-//   @dbgtodo shim-stackwalks: this is used for exception callbacks, which may change for V3. 
+//   @dbgtodo shim-stackwalks: this is used for exception callbacks, which may change for V3.
 ICorDebugFrame * UpdateFrame(ICorDebugThread * pThread, ICorDebugFrame * pOldFrame)
 {
-    PUBLIC_API_ENTRY_FOR_SHIM(NULL); 
-    
+    PUBLIC_API_ENTRY_FOR_SHIM(NULL);
+
     RSExtSmartPtr<ICorDebugFrame> pNewFrame;
 
     EX_TRY
@@ -102,16 +102,16 @@ ICorDebugFrame * UpdateFrame(ICorDebugThread * pThread, ICorDebugFrame * pOldFra
         if (pFrame != NULL)
         {
             FramePointer fp = pFrame->GetFramePointer();
-            
+
             CordbThread * pThread2 = static_cast<CordbThread *> (pThread);
             pThread2->FindFrame(&pNewFrame, fp);
-            
-            // 
+
+            //
         }
     }
     EX_CATCH
     {
-        // Do not throw out of this function.  Doing so means that the debugger never gets a chance to 
+        // Do not throw out of this function.  Doing so means that the debugger never gets a chance to
         // continue the debuggee process.  This will lead to a hang.  Instead, try to make a best effort to
         // continue with a NULL ICDFrame.  VS is able to handle this gracefully.
         pNewFrame.Assign(NULL);
@@ -140,7 +140,7 @@ HRESULT ShimProxyCallback::Breakpoint(ICorDebugAppDomain * pAppDomain, ICorDebug
 
     public:
         // Ctor
-        BreakpointEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugBreakpoint * pBreakpoint) : 
+        BreakpointEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugBreakpoint * pBreakpoint) :
              ManagedEvent(pThread)
         {
             this->m_pAppDomain.Assign(pAppDomain);
@@ -173,7 +173,7 @@ HRESULT ShimProxyCallback::StepComplete(ICorDebugAppDomain * pAppDomain, ICorDeb
 
     public:
         // Ctor
-        StepCompleteEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugStepper * pStepper, CorDebugStepReason reason) : 
+        StepCompleteEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugStepper * pStepper, CorDebugStepReason reason) :
              ManagedEvent(pThread)
         {
             this->m_pAppDomain.Assign(pAppDomain);
@@ -205,7 +205,7 @@ HRESULT ShimProxyCallback::Break(ICorDebugAppDomain * pAppDomain, ICorDebugThrea
 
     public:
         // Ctor
-        BreakEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread) : 
+        BreakEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread) :
              ManagedEvent(pThread)
         {
             this->m_pAppDomain.Assign(pAppDomain);
@@ -236,7 +236,7 @@ HRESULT ShimProxyCallback::Exception(ICorDebugAppDomain * pAppDomain, ICorDebugT
 
     public:
         // Ctor
-        ExceptionEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, BOOL fUnhandled) : 
+        ExceptionEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, BOOL fUnhandled) :
              ManagedEvent(pThread)
         {
             this->m_pAppDomain.Assign(pAppDomain);
@@ -268,7 +268,7 @@ HRESULT ShimProxyCallback::EvalComplete(ICorDebugAppDomain * pAppDomain, ICorDeb
 
     public:
         // Ctor
-        EvalCompleteEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugEval * pEval) : 
+        EvalCompleteEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugEval * pEval) :
              ManagedEvent(pThread)
         {
             this->m_pAppDomain.Assign(pAppDomain);
@@ -300,7 +300,7 @@ HRESULT ShimProxyCallback::EvalException(ICorDebugAppDomain * pAppDomain, ICorDe
 
     public:
         // Ctor
-        EvalExceptionEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugEval * pEval) : 
+        EvalExceptionEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugEval * pEval) :
              ManagedEvent(pThread)
         {
             this->m_pAppDomain.Assign(pAppDomain);
@@ -320,10 +320,10 @@ HRESULT ShimProxyCallback::EvalException(ICorDebugAppDomain * pAppDomain, ICorDe
 
 
 // Implementation of ICorDebugManagedCallback::CreateProcess
-// This will only be called for a Real create-process event. 
+// This will only be called for a Real create-process event.
 HRESULT ShimProxyCallback::CreateProcess(ICorDebugProcess * pProcess)
 {
-    m_pShim->PreDispatchEvent(true); 
+    m_pShim->PreDispatchEvent(true);
     QueueCreateProcess(pProcess);
     return S_OK;
 }
@@ -337,7 +337,7 @@ void ShimProxyCallback::QueueCreateProcess(ICorDebugProcess * pProcess)
 
     public:
         // Ctor
-        CreateProcessEvent(ICorDebugProcess * pProcess, ShimProcess * pShim) : 
+        CreateProcessEvent(ICorDebugProcess * pProcess, ShimProcess * pShim) :
              ManagedEvent(),
              m_pShim(pShim)
         {
@@ -351,9 +351,9 @@ void ShimProxyCallback::QueueCreateProcess(ICorDebugProcess * pProcess)
             return args.GetCallback1()->CreateProcess(m_pProcess);
         }
 
-        // we need access to the shim in Dispatch so we can set the InCreateProcess flag to keep track of 
+        // we need access to the shim in Dispatch so we can set the InCreateProcess flag to keep track of
         // when we are actually in the callback. We need this information to be able to emulate
-        // the hresult logic in v2.0. 
+        // the hresult logic in v2.0.
         ShimProcess * m_pShim;
     }; // end class CreateProcessEvent
 
@@ -375,7 +375,7 @@ HRESULT ShimProxyCallback::ExitProcess(ICorDebugProcess * pProcess)
 
     public:
         // Ctor
-        ExitProcessEvent(ICorDebugProcess * pProcess) : 
+        ExitProcessEvent(ICorDebugProcess * pProcess) :
              ManagedEvent()
         {
             this->m_pProcess.Assign(pProcess);
@@ -405,7 +405,7 @@ HRESULT ShimProxyCallback::CreateThread(ICorDebugAppDomain * pAppDomain, ICorDeb
 
     public:
         // Ctor
-        CreateThreadEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread) : 
+        CreateThreadEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread) :
              ManagedEvent(pThread)
         {
             this->m_pAppDomain.Assign(pAppDomain);
@@ -438,7 +438,7 @@ HRESULT ShimProxyCallback::ExitThread(ICorDebugAppDomain * pAppDomain, ICorDebug
 
     public:
         // Ctor
-        ExitThreadEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread) : 
+        ExitThreadEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread) :
              ManagedEvent(pThread)
         {
             this->m_pAppDomain.Assign(pAppDomain);
@@ -461,13 +461,13 @@ HRESULT ShimProxyCallback::ExitThread(ICorDebugAppDomain * pAppDomain, ICorDebug
 //
 // Arguments:
 //   pAppDomain - appdomain for the LoadModule debug event
-//   pModule - module being loaded. 
+//   pModule - module being loaded.
 //
 // Notes:
 //   See code:ShimProcess::QueueFakeAttachEvents
 //   This is the fake version of code:ShimProxyCallback::LoadModule.
-//   It sends an IPC event to go in process to collect information that we can't yet get via 
-//   DAC from out-of-proc. 
+//   It sends an IPC event to go in process to collect information that we can't yet get via
+//   DAC from out-of-proc.
 void ShimProxyCallback::FakeLoadModule(ICorDebugAppDomain *pAppDomain, ICorDebugModule *pModule)
 {
     class FakeLoadModuleEvent  : public ManagedEvent
@@ -478,7 +478,7 @@ void ShimProxyCallback::FakeLoadModule(ICorDebugAppDomain *pAppDomain, ICorDebug
 
     public:
         // Ctor
-        FakeLoadModuleEvent(ICorDebugAppDomain * pAppDomain, ICorDebugModule * pModule, ShimProcess * pShim) : 
+        FakeLoadModuleEvent(ICorDebugAppDomain * pAppDomain, ICorDebugModule * pModule, ShimProcess * pShim) :
              ManagedEvent(),
              m_pShim(pShim)
         {
@@ -487,15 +487,15 @@ void ShimProxyCallback::FakeLoadModule(ICorDebugAppDomain *pAppDomain, ICorDebug
         }
 
         HRESULT Dispatch(DispatchArgs args)
-        {            
+        {
             // signal that we are in the callback--this will be cleared in code:CordbProcess::ContinueInternal
-            m_pShim->SetInLoadModule(true);           
+            m_pShim->SetInLoadModule(true);
             return args.GetCallback1()->LoadModule(m_pAppDomain, m_pModule);
         }
 
-        // we need access to the shim in Dispatch so we can set the InLoadModule flag to keep track 
+        // we need access to the shim in Dispatch so we can set the InLoadModule flag to keep track
         // when we are actually in the callback. We need this information to be able to emulate
-        // the hresult logic in v2.0. 
+        // the hresult logic in v2.0.
         ShimProcess * m_pShim;
     }; // end class LoadModuleEvent
 
@@ -515,7 +515,7 @@ HRESULT ShimProxyCallback::LoadModule(ICorDebugAppDomain * pAppDomain, ICorDebug
 
     public:
         // Ctor
-        LoadModuleEvent(ICorDebugAppDomain * pAppDomain, ICorDebugModule * pModule) : 
+        LoadModuleEvent(ICorDebugAppDomain * pAppDomain, ICorDebugModule * pModule) :
              ManagedEvent()
         {
             this->m_pAppDomain.Assign(pAppDomain);
@@ -523,7 +523,7 @@ HRESULT ShimProxyCallback::LoadModule(ICorDebugAppDomain * pAppDomain, ICorDebug
         }
 
         HRESULT Dispatch(DispatchArgs args)
-        {            
+        {
             return args.GetCallback1()->LoadModule(m_pAppDomain, m_pModule);
         }
     }; // end class LoadModuleEvent
@@ -548,7 +548,7 @@ HRESULT ShimProxyCallback::UnloadModule(ICorDebugAppDomain * pAppDomain, ICorDeb
 
     public:
         // Ctor
-        UnloadModuleEvent(ICorDebugAppDomain * pAppDomain, ICorDebugModule * pModule) : 
+        UnloadModuleEvent(ICorDebugAppDomain * pAppDomain, ICorDebugModule * pModule) :
              ManagedEvent()
         {
             this->m_pAppDomain.Assign(pAppDomain);
@@ -579,7 +579,7 @@ HRESULT ShimProxyCallback::LoadClass(ICorDebugAppDomain * pAppDomain, ICorDebugC
 
     public:
         // Ctor
-        LoadClassEvent(ICorDebugAppDomain * pAppDomain, ICorDebugClass * pClass) : 
+        LoadClassEvent(ICorDebugAppDomain * pAppDomain, ICorDebugClass * pClass) :
              ManagedEvent()
         {
             this->m_pAppDomain.Assign(pAppDomain);
@@ -609,7 +609,7 @@ HRESULT ShimProxyCallback::UnloadClass(ICorDebugAppDomain * pAppDomain, ICorDebu
 
     public:
         // Ctor
-        UnloadClassEvent(ICorDebugAppDomain * pAppDomain, ICorDebugClass * pClass) : 
+        UnloadClassEvent(ICorDebugAppDomain * pAppDomain, ICorDebugClass * pClass) :
              ManagedEvent()
         {
             this->m_pAppDomain.Assign(pAppDomain);
@@ -640,7 +640,7 @@ HRESULT ShimProxyCallback::DebuggerError(ICorDebugProcess * pProcess, HRESULT er
 
     public:
         // Ctor
-        DebuggerErrorEvent(ICorDebugProcess * pProcess, HRESULT errorHR, DWORD errorCode) : 
+        DebuggerErrorEvent(ICorDebugProcess * pProcess, HRESULT errorHR, DWORD errorCode) :
              ManagedEvent()
         {
             this->m_pProcess.Assign(pProcess);
@@ -674,7 +674,7 @@ HRESULT ShimProxyCallback::LogMessage(ICorDebugAppDomain * pAppDomain, ICorDebug
 
     public:
         // Ctor
-        LogMessageEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, LONG lLevel, LPCWSTR pLogSwitchName, LPCWSTR pMessage) : 
+        LogMessageEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, LONG lLevel, LPCWSTR pLogSwitchName, LPCWSTR pMessage) :
              ManagedEvent(pThread)
         {
             this->m_pAppDomain.Assign(pAppDomain);
@@ -711,7 +711,7 @@ HRESULT ShimProxyCallback::LogSwitch(ICorDebugAppDomain * pAppDomain, ICorDebugT
 
     public:
         // Ctor
-        LogSwitchEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, LONG lLevel, ULONG ulReason, LPCWSTR pLogSwitchName, LPCWSTR pParentName) : 
+        LogSwitchEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, LONG lLevel, ULONG ulReason, LPCWSTR pLogSwitchName, LPCWSTR pParentName) :
              ManagedEvent(pThread)
         {
             this->m_pAppDomain.Assign(pAppDomain);
@@ -745,7 +745,7 @@ HRESULT ShimProxyCallback::CreateAppDomain(ICorDebugProcess * pProcess, ICorDebu
 
     public:
         // Ctor
-        CreateAppDomainEvent(ICorDebugProcess * pProcess, ICorDebugAppDomain * pAppDomain) : 
+        CreateAppDomainEvent(ICorDebugProcess * pProcess, ICorDebugAppDomain * pAppDomain) :
              ManagedEvent()
         {
             this->m_pProcess.Assign(pProcess);
@@ -778,7 +778,7 @@ HRESULT ShimProxyCallback::ExitAppDomain(ICorDebugProcess * pProcess, ICorDebugA
 
     public:
         // Ctor
-        ExitAppDomainEvent(ICorDebugProcess * pProcess, ICorDebugAppDomain * pAppDomain) : 
+        ExitAppDomainEvent(ICorDebugProcess * pProcess, ICorDebugAppDomain * pAppDomain) :
              ManagedEvent()
         {
             this->m_pProcess.Assign(pProcess);
@@ -809,7 +809,7 @@ HRESULT ShimProxyCallback::LoadAssembly(ICorDebugAppDomain * pAppDomain, ICorDeb
 
     public:
         // Ctor
-        LoadAssemblyEvent(ICorDebugAppDomain * pAppDomain, ICorDebugAssembly * pAssembly) : 
+        LoadAssemblyEvent(ICorDebugAppDomain * pAppDomain, ICorDebugAssembly * pAssembly) :
              ManagedEvent()
         {
             this->m_pAppDomain.Assign(pAppDomain);
@@ -842,7 +842,7 @@ HRESULT ShimProxyCallback::UnloadAssembly(ICorDebugAppDomain * pAppDomain, ICorD
 
     public:
         // Ctor
-        UnloadAssemblyEvent(ICorDebugAppDomain * pAppDomain, ICorDebugAssembly * pAssembly) : 
+        UnloadAssemblyEvent(ICorDebugAppDomain * pAppDomain, ICorDebugAssembly * pAssembly) :
              ManagedEvent()
         {
             this->m_pAppDomain.Assign(pAppDomain);
@@ -872,7 +872,7 @@ HRESULT ShimProxyCallback::ControlCTrap(ICorDebugProcess * pProcess)
 
     public:
         // Ctor
-        ControlCTrapEvent(ICorDebugProcess * pProcess) : 
+        ControlCTrapEvent(ICorDebugProcess * pProcess) :
              ManagedEvent()
         {
             this->m_pProcess.Assign(pProcess);
@@ -901,7 +901,7 @@ HRESULT ShimProxyCallback::NameChange(ICorDebugAppDomain * pAppDomain, ICorDebug
 
     public:
         // Ctor
-        NameChangeEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread) : 
+        NameChangeEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread) :
              ManagedEvent(pThread)
         {
             this->m_pAppDomain.Assign(pAppDomain);
@@ -932,7 +932,7 @@ HRESULT ShimProxyCallback::UpdateModuleSymbols(ICorDebugAppDomain * pAppDomain,
 
     public:
         // Ctor
-        UpdateModuleSymbolsEvent(ICorDebugAppDomain * pAppDomain, ICorDebugModule * pModule, IStream * pSymbolStream) : 
+        UpdateModuleSymbolsEvent(ICorDebugAppDomain * pAppDomain, ICorDebugModule * pModule, IStream * pSymbolStream) :
              ManagedEvent()
         {
             this->m_pAppDomain.Assign(pAppDomain);
@@ -965,7 +965,7 @@ HRESULT ShimProxyCallback::EditAndContinueRemap(ICorDebugAppDomain * pAppDomain,
 
     public:
         // Ctor
-        EditAndContinueRemapEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugFunction * pFunction, BOOL fAccurate) : 
+        EditAndContinueRemapEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugFunction * pFunction, BOOL fAccurate) :
              ManagedEvent(pThread)
         {
             this->m_pAppDomain.Assign(pAppDomain);
@@ -999,7 +999,7 @@ HRESULT ShimProxyCallback::BreakpointSetError(ICorDebugAppDomain * pAppDomain, I
 
     public:
         // Ctor
-        BreakpointSetErrorEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugBreakpoint * pBreakpoint, DWORD dwError) : 
+        BreakpointSetErrorEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugBreakpoint * pBreakpoint, DWORD dwError) :
              ManagedEvent(pThread)
         {
             this->m_pAppDomain.Assign(pAppDomain);
@@ -1034,7 +1034,7 @@ HRESULT ShimProxyCallback::FunctionRemapOpportunity(ICorDebugAppDomain * pAppDom
 
     public:
         // Ctor
-        FunctionRemapOpportunityEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugFunction * pOldFunction, ICorDebugFunction * pNewFunction, ULONG32 oldILOffset) : 
+        FunctionRemapOpportunityEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugFunction * pOldFunction, ICorDebugFunction * pNewFunction, ULONG32 oldILOffset) :
              ManagedEvent(pThread)
         {
             this->m_pAppDomain.Assign(pAppDomain);
@@ -1068,7 +1068,7 @@ HRESULT ShimProxyCallback::CreateConnection(ICorDebugProcess * pProcess, CONNID
 
     public:
         // Ctor
-        CreateConnectionEvent(ICorDebugProcess * pProcess, CONNID dwConnectionId, LPCWSTR pConnectionName) : 
+        CreateConnectionEvent(ICorDebugProcess * pProcess, CONNID dwConnectionId, LPCWSTR pConnectionName) :
              ManagedEvent()
         {
             this->m_pProcess.Assign(pProcess);
@@ -1099,7 +1099,7 @@ HRESULT ShimProxyCallback::ChangeConnection(ICorDebugProcess * pProcess, CONNID
 
     public:
         // Ctor
-        ChangeConnectionEvent(ICorDebugProcess * pProcess, CONNID dwConnectionId) : 
+        ChangeConnectionEvent(ICorDebugProcess * pProcess, CONNID dwConnectionId) :
              ManagedEvent()
         {
             this->m_pProcess.Assign(pProcess);
@@ -1129,7 +1129,7 @@ HRESULT ShimProxyCallback::DestroyConnection(ICorDebugProcess * pProcess, CONNID
 
     public:
         // Ctor
-        DestroyConnectionEvent(ICorDebugProcess * pProcess, CONNID dwConnectionId) : 
+        DestroyConnectionEvent(ICorDebugProcess * pProcess, CONNID dwConnectionId) :
              ManagedEvent()
         {
             this->m_pProcess.Assign(pProcess);
@@ -1164,7 +1164,7 @@ HRESULT ShimProxyCallback::Exception(ICorDebugAppDomain * pAppDomain, ICorDebugT
 
     public:
         // Ctor
-        ExceptionEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugFrame * pFrame, ULONG32 nOffset, CorDebugExceptionCallbackType dwEventType, DWORD dwFlags) : 
+        ExceptionEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugFrame * pFrame, ULONG32 nOffset, CorDebugExceptionCallbackType dwEventType, DWORD dwFlags) :
              ManagedEvent(pThread)
         {
             this->m_pAppDomain.Assign(pAppDomain);
@@ -1200,7 +1200,7 @@ HRESULT ShimProxyCallback::ExceptionUnwind(ICorDebugAppDomain * pAppDomain, ICor
 
     public:
         // Ctor
-        ExceptionUnwindEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, CorDebugExceptionUnwindCallbackType dwEventType, DWORD dwFlags) : 
+        ExceptionUnwindEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, CorDebugExceptionUnwindCallbackType dwEventType, DWORD dwFlags) :
              ManagedEvent(pThread)
         {
             this->m_pAppDomain.Assign(pAppDomain);
@@ -1233,7 +1233,7 @@ HRESULT ShimProxyCallback::FunctionRemapComplete(ICorDebugAppDomain * pAppDomain
 
     public:
         // Ctor
-        FunctionRemapCompleteEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugFunction * pFunction) : 
+        FunctionRemapCompleteEvent(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugFunction * pFunction) :
              ManagedEvent(pThread)
         {
             this->m_pAppDomain.Assign(pAppDomain);
@@ -1265,7 +1265,7 @@ HRESULT ShimProxyCallback::MDANotification(ICorDebugController * pController, IC
 
     public:
         // Ctor
-        MDANotificationEvent(ICorDebugController * pController, ICorDebugThread * pThread, ICorDebugMDA * pMDA) : 
+        MDANotificationEvent(ICorDebugController * pController, ICorDebugThread * pThread, ICorDebugMDA * pMDA) :
              ManagedEvent(pThread)
         {
             this->m_pController.Assign(pController);
@@ -1300,7 +1300,7 @@ HRESULT ShimProxyCallback::CustomNotification(ICorDebugThread * pThread, ICorDeb
 
     public:
         // Ctor
-        CustomNotificationEvent(ICorDebugThread * pThread, ICorDebugAppDomain * pAppDomain) : 
+        CustomNotificationEvent(ICorDebugThread * pThread, ICorDebugAppDomain * pAppDomain) :
           ManagedEvent(pThread)
           {
               this->m_pAppDomain.Assign(pAppDomain);
@@ -1317,39 +1317,68 @@ HRESULT ShimProxyCallback::CustomNotification(ICorDebugThread * pThread, ICorDeb
     return S_OK;
 }
 
-// Implementation of ICorDebugManagedCallback4::SomeWork
+// Implementation of ICorDebugManagedCallback4::BeforeGarbageCollection
 // Arguments:
 //      input:
-//          pThread    - thread on which the notification occurred
-//          pAppDomain - appDomain in which the notification occurred
+//          pController - controller in which the notification occurred
 // Return value: S_OK
-HRESULT ShimProxyCallback::SomeWork(ICorDebugThread * pThread, ICorDebugAppDomain * pAppDomain)
+HRESULT ShimProxyCallback::BeforeGarbageCollection(ICorDebugController* pController)
 {
     m_pShim->PreDispatchEvent();
-    class SomeWorkEvent : public ManagedEvent
+    class BeforeGarbageCollectionEvent : public ManagedEvent
     {
         // callbacks parameters. These are strong references
-        RSExtSmartPtr<ICorDebugAppDomain > m_pAppDomain;
-        RSExtSmartPtr<ICorDebugThread > m_pThread;
+        RSExtSmartPtr<ICorDebugController > m_pController;
 
     public:
         // Ctor
-        SomeWorkEvent(ICorDebugThread * pThread, ICorDebugAppDomain * pAppDomain) :
-            ManagedEvent(pThread)
+        BeforeGarbageCollectionEvent(ICorDebugController* pController) :
+            ManagedEvent()
         {
-            this->m_pAppDomain.Assign(pAppDomain);
-            this->m_pThread.Assign(pThread);
+            this->m_pController.Assign(pController);
+        }
+
+        HRESULT Dispatch(DispatchArgs args)
+        {
+            return args.GetCallback4()->BeforeGarbageCollection(m_pController);
+        }
+    }; // end class BeforeGarbageCollectionEvent
+
+    m_pShim->GetManagedEventQueue()->QueueEvent(new BeforeGarbageCollectionEvent(pController));
+    return S_OK;
+}
+
+// Implementation of ICorDebugManagedCallback4::AfterGarbageCollection
+// Arguments:
+//      input:
+//          pController - controller in which the notification occurred
+// Return value: S_OK
+HRESULT ShimProxyCallback::AfterGarbageCollection(ICorDebugController* pController)
+{
+    m_pShim->PreDispatchEvent();
+    class AfterGarbageCollectionEvent : public ManagedEvent
+    {
+        // callbacks parameters. These are strong references
+        RSExtSmartPtr<ICorDebugController > m_pController;
+
+    public:
+        // Ctor
+        AfterGarbageCollectionEvent(ICorDebugController* pController) :
+            ManagedEvent()
+        {
+            this->m_pController.Assign(pController);
         }
 
         HRESULT Dispatch(DispatchArgs args)
         {
-            return args.GetCallback4()->SomeWork(m_pThread, m_pAppDomain);
+            return args.GetCallback4()->AfterGarbageCollection(m_pController);
         }
-    }; // end class SomeWorkEvent
+    }; // end class AfterGarbageCollectionEvent
 
-    m_pShim->GetManagedEventQueue()->QueueEvent(new SomeWorkEvent(pThread, pAppDomain));
+    m_pShim->GetManagedEventQueue()->QueueEvent(new AfterGarbageCollectionEvent(pController));
     return S_OK;
 }
 
 
 
+
index acd3ef5..0f2d803 100644 (file)
@@ -3,9 +3,9 @@
 // See the LICENSE file in the project root for more information.
 //*****************************************************************************
 // shimprivate.h
-// 
+//
 
-// 
+//
 // private header for RS shim which bridges from V2 to V3.
 //*****************************************************************************
 
@@ -58,14 +58,14 @@ typedef SHash<DuplicateCreationEventsHashTableTraits> DuplicateCreationEventsHas
 //
 // Callback that shim provides, which then queues up the events.
 //
-class ShimProxyCallback : 
+class ShimProxyCallback :
     public ICorDebugManagedCallback,
-    public ICorDebugManagedCallback2, 
+    public ICorDebugManagedCallback2,
     public ICorDebugManagedCallback3,
     public ICorDebugManagedCallback4
 {
     ShimProcess * m_pShim; // weak reference
-    LONG m_cRef; 
+    LONG m_cRef;
 
 public:
     ShimProxyCallback(ShimProcess * pShim);
@@ -83,7 +83,7 @@ public:
     COM_METHOD Breakpoint( ICorDebugAppDomain *pAppDomain,
         ICorDebugThread *pThread,
         ICorDebugBreakpoint *pBreakpoint);
-    
+
     COM_METHOD StepComplete( ICorDebugAppDomain *pAppDomain,
         ICorDebugThread *pThread,
         ICorDebugStepper *pStepper,
@@ -143,7 +143,7 @@ public:
         ICorDebugAppDomain *pAppDomain);
 
     COM_METHOD ExitAppDomain(ICorDebugProcess *pProcess,
-        ICorDebugAppDomain *pAppDomain); 
+        ICorDebugAppDomain *pAppDomain);
 
     COM_METHOD LoadAssembly(ICorDebugAppDomain *pAppDomain,
         ICorDebugAssembly *pAssembly);
@@ -215,8 +215,11 @@ public:
     /// Implementation of ICorDebugManagedCallback4
     ///
 
-    // Implementation of ICorDebugManagedCallback4::SomeWork
-    COM_METHOD SomeWork(ICorDebugThread * pThread, ICorDebugAppDomain * pAppDomain);
+    // Implementation of ICorDebugManagedCallback4::BeforeGarbageCollection
+    COM_METHOD ShimProxyCallback::BeforeGarbageCollection(ICorDebugController* pController);
+
+    // Implementation of ICorDebugManagedCallback4::AfterGarbageCollection
+    COM_METHOD ShimProxyCallback::AfterGarbageCollection(ICorDebugController* pController);
 };
 
 
@@ -268,7 +271,7 @@ protected:
 
     // Ctor for events without thread affinity.
     ManagedEvent();
-    
+
     friend class ManagedEventQueue;
     ManagedEvent * m_pNext;
 
@@ -285,9 +288,9 @@ class ManagedEventQueue
 public:
     ManagedEventQueue();
 
-    
+
     void Init(RSLock * pLock);
-    
+
     // Remove event from the top. Caller then takes ownership of Event and will call Delete on it.
     // Caller checks IsEmpty() first.
     ManagedEvent * Dequeue();
@@ -311,7 +314,7 @@ public:
     void RestoreSuspendedQueue();
 
 protected:
-    // The lock to be used for synchronizing all access to the queue 
+    // The lock to be used for synchronizing all access to the queue
     RSLock * m_pLock;
 
     // If empty,  First + Last are both NULL.
@@ -332,10 +335,10 @@ protected:
 class ShimProcess
 {
     // Delete via Ref count semantics.
-    ~ShimProcess();  
+    ~ShimProcess();
 public:
     // Initialize ref count is 0.
-    ShimProcess();    
+    ShimProcess();
 
     // Lifetime semantics handled by reference counting.
     void AddRef();
@@ -346,7 +349,7 @@ public:
 
     // Initialization phases.
     // 1. allocate new ShimProcess(). This lets us spin up a Win32 EventThread, which can then
-    //    be used to 
+    //    be used to
     // 2. Call ShimProcess::CreateProcess/DebugActiveProcess. This will call CreateAndStartWin32ET to
     //     craete the w32et.
     // 3. Create OS-debugging pipeline. This establishes the physical OS process and gets us a pid/handle
@@ -388,7 +391,7 @@ public:
 
     //
     // Functions used by CordbProcess
-    // 
+    //
 
     // Determine if the calling thread is the win32 event thread.
     bool IsWin32EventThread();
@@ -400,7 +403,7 @@ public:
     // Accessor wrapper to mark whether we're interop-debugging.
     void SetIsInteropDebugging(bool fIsInteropDebugging);
 
-    // Handle a debug event. 
+    // Handle a debug event.
     HRESULT HandleWin32DebugEvent(const DEBUG_EVENT * pEvent);
 
     ManagedEventQueue * GetManagedEventQueue();
@@ -432,18 +435,18 @@ public:
     // Expose m_attached to CordbProcess.
     bool GetAttached();
 
-    // We need to know whether we are in the CreateProcess callback to be able to 
-    // return the v2.0 hresults from code:CordbProcess::SetDesiredNGENCompilerFlags 
+    // We need to know whether we are in the CreateProcess callback to be able to
+    // return the v2.0 hresults from code:CordbProcess::SetDesiredNGENCompilerFlags
     // when we are using the shim.
-    // 
+    //
     // Expose m_fInCreateProcess
     bool GetInCreateProcess();
     void SetInCreateProcess(bool value);
 
-    // We need to know whether we are in the FakeLoadModule callback to be able to 
+    // We need to know whether we are in the FakeLoadModule callback to be able to
     // return the v2.0 hresults from code:CordbModule::SetJITCompilerFlags when
     // we are using the shim.
-    // 
+    //
     // Expose m_fInLoadModule
     bool GetInLoadModule();
     void SetInLoadModule(bool value);
@@ -469,7 +472,7 @@ public:
     // Clear all ShimStackWalks and flush all the caches.
     void            ClearAllShimStackWalk();
 
-    // Get the corresponding ICDProcess object. 
+    // Get the corresponding ICDProcess object.
     ICorDebugProcess * GetProcess();
 
     // Get the data target to access the debuggee.
@@ -487,7 +490,7 @@ public:
     void PreDispatchEvent(bool fRealCreateProcessEvent = false);
 
     // Look for a CLR in the process and if found, return it's instance ID
-    HRESULT FindLoadedCLR(CORDB_ADDRESS * pClrInstanceId);    
+    HRESULT FindLoadedCLR(CORDB_ADDRESS * pClrInstanceId);
 
     // Retrieve the IP address and the port number of the debugger proxy.
     MachineInfo GetMachineInfo();
@@ -495,7 +498,7 @@ public:
     // Add an entry in the duplicate creation event hash table for the specified key.
     void AddDuplicateCreationEvent(void * pKey);
 
-    // Check if a duplicate creation event entry exists for the specified key.  If so, remove it.  
+    // Check if a duplicate creation event entry exists for the specified key.  If so, remove it.
     bool RemoveDuplicateCreationEventIfPresent(void * pKey);
 
     void SetMarkAttachPendingEvent();
@@ -515,13 +518,13 @@ protected:
     HRESULT CreateAndStartWin32ET(Cordb * pCordb);
 
     //
-    // Synchronization events to ensure that AttachPending bit is marked before DebugActiveProcess 
+    // Synchronization events to ensure that AttachPending bit is marked before DebugActiveProcess
     // returns or debugger is detaching
-    // 
+    //
     HANDLE  m_markAttachPendingEvent;
     HANDLE  m_terminatingEvent;
 
-    // Finds the base address of [core]clr.dll 
+    // Finds the base address of [core]clr.dll
     CORDB_ADDRESS GetCLRInstanceBaseAddress();
 
     //
@@ -529,12 +532,12 @@ protected:
     //
 
     // Shim maintains event queue to emulate V2 semantics.
-    // In V2, IcorDebug internally queued debug events and dispatched them 
-    // once the debuggee was synchronized. In V3, ICorDebug dispatches events immediately. 
+    // In V2, IcorDebug internally queued debug events and dispatched them
+    // once the debuggee was synchronized. In V3, ICorDebug dispatches events immediately.
     // The event queue is moved into the shim to build V2 semantics of V3 behavior.
     ManagedEventQueue m_eventQueue;
-    
-    // Lock to protect Shim data structures. This is currently a small lock that 
+
+    // Lock to protect Shim data structures. This is currently a small lock that
     // protects leaf-level structures, but it may grow to protect larger things.
     RSLock m_ShimLock;
 
@@ -559,21 +562,21 @@ protected:
 
     // True iff we are in the shim's CreateProcess callback. This is used to determine which hresult to
     // return from code:CordbProcess::SetDesiredNGENCompilerFlags so we correctly emulate the behavior of v2.0.
-    // This is set at the beginning of the callback and cleared in code:CordbProcess::ContinueInternal. 
+    // This is set at the beginning of the callback and cleared in code:CordbProcess::ContinueInternal.
     bool m_fInCreateProcess;
 
     // True iff we are in the shim's FakeLoadModule callback. This is used to determine which hresult to
     // return from code:CordbModule::SetJITCompilerFlags so we correctly emulate the behavior of v2.0.
-    // This is set at the beginning of the callback and cleared in code:CordbProcess::ContinueInternal. 
+    // This is set at the beginning of the callback and cleared in code:CordbProcess::ContinueInternal.
     bool m_fInLoadModule;
     //
     // Data
     //
 
-    // Pointer to CordbProcess. 
+    // Pointer to CordbProcess.
     // @dbgtodo shim: We'd like this to eventually go through public interfaces (ICorDebugProcess)
     IProcessShimHooks * m_pProcess; // Reference is kept by m_pIProcess;
-    RSExtSmartPtr<ICorDebugProcess> m_pIProcess; 
+    RSExtSmartPtr<ICorDebugProcess> m_pIProcess;
 
     // Win32EvenThread, which is the thread that uses the native debug API.
     CordbWin32EventThread * m_pWin32EventThread;
@@ -604,10 +607,10 @@ protected:
     void DefaultEventHandler(const DEBUG_EVENT * pEvent, DWORD * pdwContinueStatus);
 
     // Given a debug event, track the file handles.
-    void TrackFileHandleForDebugEvent(const DEBUG_EVENT * pEvent);   
+    void TrackFileHandleForDebugEvent(const DEBUG_EVENT * pEvent);
 
     // Have we gotten the loader breakpoint yet?
-    // A Debugger needs to do special work to skip the loader breakpoint, 
+    // A Debugger needs to do special work to skip the loader breakpoint,
     // and that's also when it should dispatch the faked managed attach events.
     bool m_loaderBPReceived;
 
@@ -616,7 +619,7 @@ protected:
 
     // Real worker to update ContinueStatusChangedData
     HRESULT ContinueStatusChangedWorker(DWORD dwThreadId, CORDB_CONTINUE_STATUS dwContinueStatus);
-    
+
     struct ContinueStatusChangedData
     {
         void Clear();
@@ -640,8 +643,8 @@ protected:
 
 //---------------------------------------------------------------------------------------
 //
-// This is the container class of ShimChains, ICorDebugFrames, ShimChainEnums, and ShimFrameEnums.   
-// It has a 1:1 relationship  with ICorDebugThreads.  Upon creation, this class walks the entire stack and 
+// This is the container class of ShimChains, ICorDebugFrames, ShimChainEnums, and ShimFrameEnums.
+// It has a 1:1 relationship  with ICorDebugThreads.  Upon creation, this class walks the entire stack and
 // caches all the stack frames and chains.  The enumerators are created on demand.
 //
 
@@ -693,7 +696,7 @@ private:
     //
     // This is a helper class used to store the information of a chain during a stackwalk.  A chain is marked
     // by the CONTEXT on the leaf boundary and a FramePointer on the root boundary.  Also, notice that we
-    // are keeping two CONTEXTs.  This is because some chain types may cancel a previous unmanaged chain.  
+    // are keeping two CONTEXTs.  This is because some chain types may cancel a previous unmanaged chain.
     // For example, a CHAIN_FUNC_EVAL chain cancels any CHAIN_ENTER_UNMANAGED chain immediately preceding
     // it.  In this case, the leaf boundary of the CHAIN_FUNC_EVAL chain is marked by the CONTEXT of the
     // previous CHAIN_ENTER_MANAGED, not the previous CHAIN_ENTER_UNMANAGED.
@@ -746,7 +749,7 @@ private:
         // Check whether we are skipping frames because of a child frame.
         BOOL IsSkippingFrame();
 
-        // Indicates whether we are dealing with a converted frame.  
+        // Indicates whether we are dealing with a converted frame.
         // See code:CordbThread::ConvertFrameForILMethodWithoutMetadata.
         BOOL HasConvertedFrame();
 
@@ -757,7 +760,7 @@ private:
         // Store the converted frame, if any.
         RSExtSmartPtr<ICorDebugInternalFrame2> m_pConvertedInternalFrame2;
 
-        // Store the array of internal frames.  This is an array of RSExtSmartPtrs, and so each element 
+        // Store the array of internal frames.  This is an array of RSExtSmartPtrs, and so each element
         // is protected, and we only need to call Clear() to release each element and free all the memory.
         RSExtPtrArray<ICorDebugInternalFrame2> m_ppInternalFrame2;
 
@@ -772,10 +775,10 @@ private:
         bool m_fExhaustedAllStackFrames;
 
         // Indicate whether we are processing an internal frame or a stack frame.
-        bool m_fProcessingInternalFrame;    
+        bool m_fProcessingInternalFrame;
 
-        // Indicate whether we should skip the current chain because it's a chain derived from a leaf frame 
-        // of type TYPE_INTERNAL.  This is the behaviour in V2.  
+        // Indicate whether we should skip the current chain because it's a chain derived from a leaf frame
+        // of type TYPE_INTERNAL.  This is the behaviour in V2.
         // See code:DebuggerWalkStackProc.
         bool m_fSkipChain;
 
@@ -838,7 +841,7 @@ private:
     BOOL IsILFrameWithoutMetadata(ICorDebugFrame * pFrame);
 
     CDynArray<ShimChain *>      m_stackChains;  // growable ordered array of chains and frames
-    CDynArray<ICorDebugFrame *> m_stackFrames; 
+    CDynArray<ICorDebugFrame *> m_stackFrames;
 
     ShimChainEnum * m_pChainEnumList;           // linked list of ShimChainEnum and ShimFrameEnum
     ShimFrameEnum * m_pFrameEnumList;
@@ -918,16 +921,16 @@ private:
     FramePointer        m_fpRoot;           // the root end of the chain
 
     ShimStackWalk *     m_pStackWalk;       // the owning ShimStackWalk
-    Volatile<ULONG>     m_refCount; 
+    Volatile<ULONG>     m_refCount;
 
     // The 0-based index of this chain in the ShimStackWalk's chain array (m_pStackWalk->m_stackChains).
     UINT32              m_chainIndex;
 
-    // The 0-based index of the first frame owned by this chain in the ShimStackWalk's frame array 
+    // The 0-based index of the first frame owned by this chain in the ShimStackWalk's frame array
     // (m_pStackWalk->m_stackFrames).  See code::ShimChain::GetFirstFrameIndex().
     UINT32              m_frameStartIndex;
 
-    // The 0-based index of the last frame owned by this chain in the ShimStackWalk's frame array 
+    // The 0-based index of the last frame owned by this chain in the ShimStackWalk's frame array
     // (m_pStackWalk->m_stackFrames).  This index is exlusive.  See code::ShimChain::GetLastFrameIndex().
     UINT32              m_frameEndIndex;
 
@@ -978,7 +981,7 @@ public:
 
     //
     // accessors
-    // 
+    //
 
     // used to link ShimChainEnums in a list
     ShimChainEnum * GetNext();
@@ -994,7 +997,7 @@ private:
     UINT32          m_currentChainIndex;    // the index of the current ShimChain being enumerated
     Volatile<ULONG> m_refCount;
     BOOL            m_fIsNeutered;
-    
+
     RSLock *        m_pShimLock;            // shim lock from ShimProcess to protect neuteredness checks
 };
 
@@ -1038,7 +1041,7 @@ public:
 
     //
     // accessors
-    // 
+    //
 
     // used to link ShimChainEnums in a list
     ShimFrameEnum * GetNext();
index cdb7380..096c0d2 100644 (file)
@@ -63,7 +63,7 @@ GPTR_IMPL(Debugger,         g_pDebugger);
 GPTR_IMPL(EEDebugInterface, g_pEEInterface);
 SVAL_IMPL_INIT(BOOL, Debugger, s_fCanChangeNgenFlags, TRUE);
 
-// This is a public export so debuggers can read and determine if the coreclr 
+// This is a public export so debuggers can read and determine if the coreclr
 // process is waiting for JIT debugging attach.
 GVAL_IMPL_INIT(ULONG, CLRJitAttachState, 0);
 
@@ -195,7 +195,7 @@ void DoCompileTimeCheckOnDbgIpcEventTypes()
 //-----------------------------------------------------------------------------
 // Ctor for AtSafePlaceHolder
 AtSafePlaceHolder::AtSafePlaceHolder(Thread * pThread)
-{   
+{
     _ASSERTE(pThread != NULL);
     if (!g_pDebugger->IsThreadAtSafePlace(pThread))
     {
@@ -223,7 +223,7 @@ bool AtSafePlaceHolder::IsAtUnsafePlace()
 }
 
 //-----------------------------------------------------------------------------
-// Clear the holder. 
+// Clear the holder.
 // Notes:
 //    This can be called multiple times.
 //    Calling this makes the dtor a nop.
@@ -317,7 +317,7 @@ HelperCanary * Debugger::GetCanary()
 {
     return g_pRCThread->GetCanary();
 }
-    
+
 // IMPORTANT!!!!!
 // Do not call Lock and Unlock directly. Because you might not unlock
 // if exception takes place. Use DebuggerLockHolder instead!!!
@@ -472,15 +472,15 @@ void Debugger::DoNotCallDirectlyPrivateUnlock(void)
 // ---------------------------------------------------------------------------------
 
 // Send an event to the RS to signal that it should test to determine if a crst is held.
-// This is for testing purposes only. 
+// This is for testing purposes only.
 // Arguments:
 //     input:  pCrst     - the lock to test
 //             fOkToTake - true iff the LS does NOT currently hold the lock
-//     output: none 
+//     output: none
 // Notes: The RS will throw if the lock is held. The code that tests the lock will catch the
-//        exception and assert if throwing was not the correct thing to do (determined via the 
+//        exception and assert if throwing was not the correct thing to do (determined via the
 //        boolean). See the case for DB_IPCE_TEST_CRST in code:CordbProcess::RawDispatchEvent.
-// 
+//
 void DataTest::SendDbgCrstEvent(Crst * pCrst, bool fOkToTake)
 {
     DebuggerIPCEvent * pLockEvent = g_pDebugger->m_pRCThread->GetIPCEventSendBuffer();
@@ -495,15 +495,15 @@ void DataTest::SendDbgCrstEvent(Crst * pCrst, bool fOkToTake)
 } // DataTest::SendDbgCrstEvent
 
 // Send an event to the RS to signal that it should test to determine if a SimpleRWLock is held.
-// This is for testing purposes only. 
+// This is for testing purposes only.
 // Arguments:
 //     input:  pRWLock   - the lock to test
 //             fOkToTake - true iff the LS does NOT currently hold the lock
-//     output: none 
+//     output: none
 // Note:  The RS will throw if the lock is held. The code that tests the lock will catch the
-//        exception and assert if throwing was not the correct thing to do (determined via the 
+//        exception and assert if throwing was not the correct thing to do (determined via the
 //        boolean). See the case for DB_IPCE_TEST_RWLOCK in code:CordbProcess::RawDispatchEvent.
-// 
+//
 void DataTest::SendDbgRWLockEvent(SimpleRWLock * pRWLock, bool okToTake)
 {
     DebuggerIPCEvent * pLockEvent = g_pDebugger->m_pRCThread->GetIPCEventSendBuffer();
@@ -516,17 +516,17 @@ void DataTest::SendDbgRWLockEvent(SimpleRWLock * pRWLock, bool okToTake)
     g_pDebugger->SendRawEvent(pLockEvent);
 } // DataTest::SendDbgRWLockEvent
 
-// Takes a series of locks in various ways and signals the RS to test the locks at interesting 
-// points to ensure we reliably detect when the LS holds a lock. If in the course of inspection, the 
-// DAC needs to execute a code path where the LS holds a lock, we assume that the locked data is in 
+// Takes a series of locks in various ways and signals the RS to test the locks at interesting
+// points to ensure we reliably detect when the LS holds a lock. If in the course of inspection, the
+// DAC needs to execute a code path where the LS holds a lock, we assume that the locked data is in
 // an inconsistent state. In this situation, we don't want to report information about this data, so
-// we throw an exception. 
-// This is for testing purposes only. 
-// 
+// we throw an exception.
+// This is for testing purposes only.
+//
 // Arguments: none
 // Return Value: none
 // Notes: See code:CordbProcess::RawDispatchEvent for the RS part of this test and code:Debugger::Startup
-//        for the LS invocation of the test. 
+//        for the LS invocation of the test.
 //        The environment variable TestDataConsistency must be set to 1 to make this test run.
 void DataTest::TestDataSafety()
 {
@@ -983,7 +983,7 @@ Debugger::Debugger()
     // Metadata data structure version numbers
     //
     // 1 - initial state of the layouts ( .Net 4.5.2 )
-    // 
+    //
     // as data structure layouts change, add a new version number
     // and comment the changes
     m_mdDataStructureVersion = 1;
@@ -1005,7 +1005,7 @@ Debugger::~Debugger()
     CONTRACTL_END;
 
     // We explicitly leak the debugger object on shutdown. See Debugger::StopDebugger for details.
-    _ASSERTE(!"Debugger dtor should not be called.");   
+    _ASSERTE(!"Debugger dtor should not be called.");
 }
 
 #if defined(FEATURE_HIJACK) && !defined(PLATFORM_UNIX)
@@ -1020,7 +1020,7 @@ inline MemoryRange GetMemoryRangeForFunction(PFN_HIJACK_FUNCTION pfnStart, PFN_H
 }
 
 // static
-MemoryRange Debugger::s_hijackFunction[kMaxHijackFunctions] = 
+MemoryRange Debugger::s_hijackFunction[kMaxHijackFunctions] =
     {GetMemoryRangeForFunction(ExceptionHijack, ExceptionHijackEnd),
      GetMemoryRangeForFunction(RedirectedHandledJITCaseForGCThreadControl_Stub,
                                RedirectedHandledJITCaseForGCThreadControl_StubEnd),
@@ -1036,7 +1036,7 @@ MemoryRange Debugger::s_hijackFunction[kMaxHijackFunctions] =
     };
 #endif // FEATURE_HIJACK && !PLATFORM_UNIX
 
-// Save the necessary information for the debugger to recognize an IP in one of the thread redirection 
+// Save the necessary information for the debugger to recognize an IP in one of the thread redirection
 // functions.
 void Debugger::InitializeHijackFunctionAddress()
 {
@@ -1387,7 +1387,7 @@ ULONG DebuggerMethodInfoTable::CheckDmiTable(void)
 
 //---------------------------------------------------------------------------------------
 //
-// Class constructor for DebuggerEval.  This is the supporting data structure for 
+// Class constructor for DebuggerEval.  This is the supporting data structure for
 // func-eval tracking.
 //
 // Arguments:
@@ -1415,8 +1415,8 @@ DebuggerEval::DebuggerEval(CONTEXT * pContext, DebuggerIPCE_FuncEvalInfo * pEval
     m_classToken = pEvalInfo->funcClassMetadataToken;
 
     // Note: we can't rely on just the DebuggerModule* or AppDomain* because the AppDomain
-    // could get unloaded between now and when the funceval actually starts.  So we stash an 
-    // AppDomain ID which is safe to use after the AD is unloaded.  It's only safe to 
+    // could get unloaded between now and when the funceval actually starts.  So we stash an
+    // AppDomain ID which is safe to use after the AD is unloaded.  It's only safe to
     // use the DebuggerModule* after we've verified the ADID is still valid (i.e. by entering that domain).
     m_debuggerModule = g_pDebugger->LookupOrCreateModule(pEvalInfo->vmDomainFile);
 
@@ -1424,7 +1424,7 @@ DebuggerEval::DebuggerEval(CONTEXT * pContext, DebuggerIPCE_FuncEvalInfo * pEval
     {
         // We have no associated code.
         _ASSERTE((m_evalType == DB_IPCE_FET_NEW_STRING) || (m_evalType == DB_IPCE_FET_NEW_ARRAY));
-        
+
         // We'll just do the creation in whatever domain the thread is already in.
         // It's conceivable that we might want to allow the caller to specify a specific domain, but
         // ICorDebug provides the debugger with no was to specify the domain.
@@ -1510,7 +1510,7 @@ DebuggerEval::DebuggerEval(CONTEXT * pContext, Thread * pThread, Thread::ThreadA
     m_rethrowAbortException = false;
     m_retValueBoxing = Debugger::NoValueTypeBoxing;
     m_requester = requester;
-    
+
     if (pContext == NULL)
     {
         memset(&m_context, 0, sizeof(m_context));
@@ -1670,7 +1670,7 @@ DebuggerHeap * Debugger::GetInteropSafeHeap_NoThrow()
         _ASSERTE(!"InteropSafe Heap should have already been initialized in LazyInit");
 
         // Just in case we miss it in retail, convert to OOM here:
-        return NULL;        
+        return NULL;
     }
     return &m_heap;
 }
@@ -1713,7 +1713,7 @@ DebuggerHeap * Debugger::GetInteropSafeExecutableHeap_NoThrow()
         _ASSERTE(!"InteropSafe Executable Heap should have already been initialized in LazyInit");
 
         // Just in case we miss it in retail, convert to OOM here:
-        return NULL;        
+        return NULL;
     }
     return &m_executableHeap;
 }
@@ -1727,14 +1727,14 @@ DebuggerHeap * Debugger::GetInteropSafeExecutableHeap_NoThrow()
 //    Called during startup path
 //
 // Notes:
-//    If no debugger is attached, this does nothing. 
+//    If no debugger is attached, this does nothing.
 //
 //---------------------------------------------------------------------------------------
 void Debugger::RaiseStartupNotification()
 {
     // Right-side will read this field from OOP via DAC-primitive to determine attach or launch case.
     // We do an interlocked increment to gaurantee this is an atomic memory write, and to ensure
-    // that it's flushed from any CPU cache into memory. 
+    // that it's flushed from any CPU cache into memory.
     InterlockedIncrement(&m_fLeftSideInitialized);
 
 #ifndef FEATURE_DBGIPC_TRANSPORT_VM
@@ -1742,7 +1742,7 @@ void Debugger::RaiseStartupNotification()
     // listening, and we will fail.  However, we still want to initialize the variable above.
     DebuggerIPCEvent startupEvent;
     InitIPCEvent(&startupEvent, DB_IPCE_LEFTSIDE_STARTUP, NULL, VMPTR_AppDomain::NullPtr());
-         
+
     SendRawEvent(&startupEvent);
 
     // RS will set flags from OOP while we're stopped at the event if it wants to attach.
@@ -1788,13 +1788,13 @@ void Debugger::SendRawEvent(const DebuggerIPCEvent * pManagedEvent)
     // We get to send an array of ULONG_PTRs as data with the notification.
     // The debugger can then use ReadProcessMemory to read through this array.
     ULONG_PTR rgData [] = {
-        CLRDBG_EXCEPTION_DATA_CHECKSUM, 
-        (ULONG_PTR) g_pMSCorEE, 
+        CLRDBG_EXCEPTION_DATA_CHECKSUM,
+        (ULONG_PTR) g_pMSCorEE,
         (ULONG_PTR) pManagedEvent
     };
 
     // If no debugger attached, then don't bother raising a 1st-chance exception because nobody will sniff it.
-    // @dbgtodo iDNA: in iDNA case, the recorder may sniff it. 
+    // @dbgtodo iDNA: in iDNA case, the recorder may sniff it.
     if (!IsDebuggerPresent())
     {
         return;
@@ -1810,14 +1810,14 @@ void Debugger::SendRawEvent(const DebuggerIPCEvent * pManagedEvent)
         const DWORD dwFlags = 0; // continuable (eg, Debugger can continue GH)
         RaiseException(CLRDBG_NOTIFICATION_EXCEPTION_CODE, dwFlags, NumItems(rgData), rgData);
 
-        // If debugger continues "GH" (DBG_CONTINUE), then we land here. 
+        // If debugger continues "GH" (DBG_CONTINUE), then we land here.
         // This is the expected path for a well-behaved ICorDebug debugger.
     }
     EX_CATCH
     {
         // If no debugger is attached, or if the debugger continues "GN" (DBG_EXCEPTION_NOT_HANDLED), then we land here.
         // A naive (not-ICorDebug aware) native-debugger won't handle the exception and so land us here.
-        // We may also get here if a debugger detaches at the Exception notification 
+        // We may also get here if a debugger detaches at the Exception notification
         // (and thus implicitly continues GN).
     }
     EX_END_CATCH(SwallowAllExceptions);
@@ -1835,25 +1835,25 @@ void Debugger::SendRawEvent(const DebuggerIPCEvent * pManagedEvent)
 //    This will start a synchronization.
 //
 // Notes:
-//    In V2, this also gives the RS a chance to intialize the IPC protocol.    
+//    In V2, this also gives the RS a chance to intialize the IPC protocol.
 //    Spefically, this needs to be sent before the LS can send a sync-complete.
 //---------------------------------------------------------------------------------------
 void Debugger::SendCreateProcess(DebuggerLockHolder * pDbgLockHolder)
 {
     pDbgLockHolder->Release();
-    
+
     // Encourage helper thread to spin up so that we're in a consistent state.
     PollWaitingForHelper();
 
-    // we don't need to use SENDIPCEVENT_BEGIN/END macros that perform the debug-suspend aware checks, 
+    // we don't need to use SENDIPCEVENT_BEGIN/END macros that perform the debug-suspend aware checks,
     // as this code executes on the startup path...
     SENDIPCEVENT_RAW_BEGIN(pDbgLockHolder);
 
-    // Send a CreateProcess event. 
+    // Send a CreateProcess event.
     // @dbgtodo  pipeline - eliminate these reasons for needing a CreateProcess event (part of pipeline feature crew)
     // This will let the RS know that the IPC block is up + ready, and then the RS can read it.
     // The RS will then update the DCB with enough information so that we can send the sync-complete.
-    // (such as letting us know whether we're interop-debugging or not).        
+    // (such as letting us know whether we're interop-debugging or not).
     DebuggerIPCEvent event;
     InitIPCEvent(&event, DB_IPCE_CREATE_PROCESS, NULL, VMPTR_AppDomain::NullPtr());
     SendRawEvent(&event);
@@ -1865,8 +1865,8 @@ void Debugger::SendCreateProcess(DebuggerLockHolder * pDbgLockHolder)
     TrapAllRuntimeThreads();
 
     // Must have a thread object so that we ensure that we will actually block here.
-    // This ensures the debuggee is actually stopped at startup, and 
-    // this gives the debugger a chance to call SetDesiredNGENFlags before we 
+    // This ensures the debuggee is actually stopped at startup, and
+    // this gives the debugger a chance to call SetDesiredNGENFlags before we
     // set s_fCanChangeNgenFlags to FALSE.
     _ASSERTE(GetThread() != NULL);
     SENDIPCEVENT_RAW_END;
@@ -1879,8 +1879,8 @@ void Debugger::SendCreateProcess(DebuggerLockHolder * pDbgLockHolder)
 HANDLE g_hContinueStartupEvent = INVALID_HANDLE_VALUE;
 
 CLR_ENGINE_METRICS g_CLREngineMetrics = {
-    sizeof(CLR_ENGINE_METRICS), 
-    CorDebugVersion_4_0, 
+    sizeof(CLR_ENGINE_METRICS),
+    CorDebugVersion_4_0,
     &g_hContinueStartupEvent};
 
 #define StartupNotifyEventNamePrefix W("TelestoStartupEvent_")
@@ -2027,7 +2027,7 @@ HRESULT Debugger::Startup(void)
         // Must be done before the RC thread is initialized.
         // @dbgtodo  - In V2, LS was lazily initialized; but was eagerly pre-initialized if launched by debugger.
         // (This was for perf reasons). But we don't want Launch vs. Attach checks in the LS, so we now always
-        // init. As we move more to OOP, this init will become cheaper.    
+        // init. As we move more to OOP, this init will become cheaper.
         {
             LazyInit();
             DebuggerController::Initialize();
@@ -2036,7 +2036,11 @@ HRESULT Debugger::Startup(void)
         InitializeHijackFunctionAddress();
 
         // Also initialize the AppDomainEnumerationIPCBlock
+    #if !defined(FEATURE_IPCMAN) || defined(FEATURE_DBGIPC_TRANSPORT_VM)
         m_pAppDomainCB = new (nothrow) AppDomainEnumerationIPCBlock();
+    #else
+        m_pAppDomainCB = g_pIPCManagerInterface->GetAppDomainBlock();
+    #endif
 
         if (m_pAppDomainCB == NULL)
         {
@@ -2047,7 +2051,7 @@ HRESULT Debugger::Startup(void)
         hr = InitAppDomainIPC();
         _ASSERTE(SUCCEEDED(hr)); // throws on error.
 
-        // Allows the debugger (and profiler) diagnostics to be disabled so resources like 
+        // Allows the debugger (and profiler) diagnostics to be disabled so resources like
         // the named pipes and semaphores are not created.
         if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_EnableDiagnostics) == 0)
         {
@@ -2099,7 +2103,7 @@ HRESULT Debugger::Startup(void)
         }
 
     #ifdef TEST_DATA_CONSISTENCY
-        // if we have set the environment variable TestDataConsistency, run the data consistency test. 
+        // if we have set the environment variable TestDataConsistency, run the data consistency test.
         // See code:DataTest::TestDataSafety for more information
         if ((g_pConfig != NULL) && (g_pConfig->TestDataConsistency() == true))
         {
@@ -2110,14 +2114,14 @@ HRESULT Debugger::Startup(void)
     }
 
 #ifdef FEATURE_PAL
-    // Signal the debugger (via dbgshim) and wait until it is ready for us to 
+    // Signal the debugger (via dbgshim) and wait until it is ready for us to
     // continue. This needs to be outside the lock and after the transport is
     // initialized.
     if (PAL_NotifyRuntimeStarted())
     {
         // The runtime was successfully launched and attached so mark it now
-        // so no notifications are missed especially the initial module load 
-        // which would cause debuggers problems with reliable setting breakpoints 
+        // so no notifications are missed especially the initial module load
+        // which would cause debuggers problems with reliable setting breakpoints
         // in startup code or Main.
        MarkDebuggerAttachedInternal();
     }
@@ -2137,7 +2141,7 @@ HRESULT Debugger::Startup(void)
 //    pThread - the current thread. Must be non-null
 //
 // Notes:
-//    Most debugger initialization is done in code:Debugger.Startup, 
+//    Most debugger initialization is done in code:Debugger.Startup,
 //    However, debugger can't block on synchronization without a Thread object,
 //    so sending IPC events must wait until after we have a thread object.
 //---------------------------------------------------------------------------------------
@@ -2195,7 +2199,7 @@ HRESULT Debugger::StartupPhase2(Thread * pThread)
             // Remove the env var from our process so that the debugger we spin up won't inherit it.
             // Else, if the debugger is managed, we'll have an infinite recursion.
             BOOL fOk = WszSetEnvironmentVariable(DBG_ATTACH_ON_STARTUP_ENV_VAR, NULL);
-            
+
             if (fOk)
             {
                 // We've already created the helper thread (which can service the attach request)
@@ -2231,7 +2235,7 @@ HRESULT Debugger::StartupPhase2(Thread * pThread)
 // controlled point in time. This is useful for those callers into the debugger (e.g.,
 // ETW rundown) that know they will need the lazy data initialized but cannot afford to
 // have it initialized unpredictably or inside a lock.
-// 
+//
 // This may be called more than once, and will know to initialize the lazy data only
 // once.
 //
@@ -2457,7 +2461,7 @@ DebuggerLazyInit::~DebuggerLazyInit()
 //
 // RequestFavor can be called in stack-overflow scenarios and thus explicitly
 // avoids any lazy initialization.
-// It blocks until the favor callback completes. 
+// It blocks until the favor callback completes.
 //
 // Parameters:
 //   fp    - a non-null Favour callback function
@@ -2465,7 +2469,7 @@ DebuggerLazyInit::~DebuggerLazyInit()
 //
 // Return values:
 //   S_OK if the function succeeds, else a failure HRESULT
-//   
+//
 
 HRESULT Debugger::RequestFavor(FAVORCALLBACK fp, void * pData)
 {
@@ -2477,12 +2481,12 @@ HRESULT Debugger::RequestFavor(FAVORCALLBACK fp, void * pData)
         PRECONDITION(fp != NULL);
     }
     CONTRACTL_END;
-    
-    if (m_pRCThread == NULL || 
+
+    if (m_pRCThread == NULL ||
         m_pRCThread->GetRCThreadId() == GetCurrentThreadId())
     {
         // Since favors are only used internally, we know that the helper should alway be up and ready
-        // to handle them. Also, since favors can be used in low-stack scenarios, there's not any 
+        // to handle them. Also, since favors can be used in low-stack scenarios, there's not any
         // extra initialization needed for them.
         _ASSERTE(!"Helper not initialized for favors.");
         return E_UNEXPECTED;
@@ -2521,8 +2525,8 @@ void Debugger::StopDebugger(void)
         GC_NOTRIGGER;
     }
     CONTRACTL_END;
-   
-    // Leak almost everything on process exit. The OS will clean it up anyways and trying to 
+
+    // Leak almost everything on process exit. The OS will clean it up anyways and trying to
     // clean it up ourselves is just one more place we may AV / deadlock.
 
 #if defined(FEATURE_DBGIPC_TRANSPORT_VM)
@@ -2539,12 +2543,12 @@ void Debugger::StopDebugger(void)
     TerminateAppDomainIPC ();
 
     //
-    // Tell the VM to clear out all references to the debugger before we start cleaning up, 
+    // Tell the VM to clear out all references to the debugger before we start cleaning up,
     // so that nothing will reference (accidentally) through the partially cleaned up debugger.
     //
-    // NOTE: we cannot clear out g_pDebugger before the delete call because the 
+    // NOTE: we cannot clear out g_pDebugger before the delete call because the
     // stuff in delete (particularly deleteinteropsafe) needs to look at it.
-    // 
+    //
     g_pEEInterface->ClearAllDebugInterfaceReferences();
     g_pDebugger = NULL;
 }
@@ -2800,7 +2804,7 @@ DebuggerJitInfo *Debugger::GetJitInfo(MethodDesc *fd, const BYTE *pbAddr, Debugg
     CONTRACTL_END;
 
     // Address should be non-null and in range of MethodDesc. This lets us tell which EnC version.
-    _ASSERTE(pbAddr != NULL); 
+    _ASSERTE(pbAddr != NULL);
 
     return GetJitInfoWorker(fd, pbAddr, pMethInfo);
 
@@ -3061,7 +3065,7 @@ HRESULT Debugger::GetILToNativeMapping(PCODE pNativeCodeStartAddress, ULONG32 cM
     return (S_OK);
 #else
     return E_NOTIMPL;
-#endif 
+#endif
 }
 
 
@@ -3108,10 +3112,10 @@ HRESULT Debugger::GetILToNativeMapping(PCODE pNativeCodeStartAddress, ULONG32 cM
 
 HRESULT Debugger::GetILToNativeMappingIntoArrays(
     MethodDesc * pMethodDesc,
-    PCODE pCode, 
-    USHORT cMapMax, 
+    PCODE pCode,
+    USHORT cMapMax,
     USHORT * pcMap,
-    UINT ** prguiILOffset, 
+    UINT ** prguiILOffset,
     UINT ** prguiNativeOffset)
 {
     CONTRACTL
@@ -3121,7 +3125,7 @@ HRESULT Debugger::GetILToNativeMappingIntoArrays(
         GC_NOTRIGGER;
     }
     CONTRACTL_END;
-    
+
     _ASSERTE(pcMap != NULL);
     _ASSERTE(prguiILOffset != NULL);
     _ASSERTE(prguiNativeOffset != NULL);
@@ -3300,7 +3304,7 @@ void Debugger::getBoundariesHelper(MethodDesc * md,
                     // instrumented IL map if one exists.
                     if (dmi->HasInstrumentedILMap())
                     {
-                        InstrumentedILOffsetMapping mapping = 
+                        InstrumentedILOffsetMapping mapping =
                             dmi->GetRuntimeModule()->GetInstrumentedILOffsetMapping(dmi->m_token);
 
                         for (SIZE_T i = 0; i < n; i++)
@@ -3542,8 +3546,8 @@ Exit:
 
 #ifndef DACCESS_COMPILE
 
-// If we have a varargs function, we can't set the IP (we don't know how to pack/unpack the arguments), so if we 
-// call SetIP with fCanSetIPOnly = true, we need to check for that. 
+// If we have a varargs function, we can't set the IP (we don't know how to pack/unpack the arguments), so if we
+// call SetIP with fCanSetIPOnly = true, we need to check for that.
 // Arguments:
 //     input:  nEntries      - number of entries in varNativeInfo
 //             varNativeInfo - array of entries describing the args and locals for the function
@@ -3558,7 +3562,7 @@ BOOL Debugger::IsVarArgsFunction(unsigned int nEntries, PTR_NativeVarInfo varNat
         }
     }
     return FALSE;
-}            
+}
 
 // We want to keep the 'worst' HRESULT - if one has failed (..._E_...) & the
 // other hasn't, take the failing one.  If they've both/neither failed, then
@@ -3856,7 +3860,7 @@ HRESULT Debugger::SetIP( bool fCanSetIPOnly, Thread *thread,Module *module,
         // have garbage left over in them, and we don't want the GC to try and dereference them
         // as object references.  However, we can't easily tell here which of the callee-saved regs
         // are used in this method and therefore safe to clear.
-        // 
+        //
 
         hr = ShuffleVariablesSet(dji,
                             offsetNatTo,
@@ -4129,7 +4133,7 @@ GetSetFrameHelper::GetSetFrameHelper() : m_pMD(NULL), m_rgSize(NULL), m_rgElemTy
 //
 // return value: S_OK or E_OUTOFMEMORY
 //
-HRESULT 
+HRESULT
 GetSetFrameHelper::Init(MethodDesc *pMD)
 {
     CONTRACTL
@@ -4141,16 +4145,16 @@ GetSetFrameHelper::Init(MethodDesc *pMD)
         PRECONDITION(CheckPointer(pMD));
     }
     CONTRACTL_END;
-    
+
     HRESULT hr = S_OK;
     COR_ILMETHOD* pILHeader = NULL;
     m_pMD = pMD;
     MetaSig *pLocSig = NULL;
     MetaSig *pArgSig = NULL;
-    
+
     m_rgSize = NULL;
     m_rgElemType = NULL;
-    
+
     // Initialize decoderOldIL before checking the method argument signature.
     EX_TRY
     {
@@ -4159,39 +4163,39 @@ GetSetFrameHelper::Init(MethodDesc *pMD)
     EX_CATCH_HRESULT(hr);
     if (FAILED(hr))
         return hr;
-    
+
     COR_ILMETHOD_DECODER decoderOldIL(pILHeader);
     mdSignature mdLocalSig = (decoderOldIL.GetLocalVarSigTok()) ? (decoderOldIL.GetLocalVarSigTok()):
                                                                   (mdSignatureNil);
-    
+
     PCCOR_SIGNATURE pCallSig;
     DWORD cbCallSigSize;
-    
+
     pMD->GetSig(&pCallSig, &cbCallSigSize);
-    
+
     if (pCallSig != NULL)
     {
         // Yes, we do need to pass in the text because this might be generic function!
         SigTypeContext tmpContext(pMD);
-        
+
         pArgSig = new (interopsafe, nothrow) MetaSig(pCallSig,
                                                      cbCallSigSize,
                                                      pMD->GetModule(),
                                                      &tmpContext,
                                                      MetaSig::sigMember);
-        
+
         if (pArgSig == NULL)
         {
             IfFailGo(E_OUTOFMEMORY);
         }
-        
+
         m_numArgs = pArgSig->NumFixedArgs();
-        
+
         if (pArgSig->HasThis())
         {
             m_numArgs++;
         }
-        
+
         // <TODO>
         // What should we do in this case?
         // </TODO>
@@ -4200,7 +4204,7 @@ GetSetFrameHelper::Init(MethodDesc *pMD)
             m_numArgs++;
         */
     }
-    
+
     // allocation of pArgSig succeeded
     ULONG cbSig;
     PCCOR_SIGNATURE pLocalSig;
@@ -4217,21 +4221,21 @@ GetSetFrameHelper::Init(MethodDesc *pMD)
                                                      pMD->GetModule(),
                                                      &tmpContext,
                                                      MetaSig::sigLocalVars);
-        
+
         if (pLocSig == NULL)
         {
             IfFailGo(E_OUTOFMEMORY);
         }
     }
-    
+
     // allocation of pLocalSig succeeded
     m_numTotalVars = m_numArgs + (pLocSig != NULL ? pLocSig->NumFixedArgs() : 0);
-    
+
     if (m_numTotalVars > 0)
     {
         m_rgSize     = new (interopsafe, nothrow) SIZE_T[m_numTotalVars];
         m_rgElemType = new (interopsafe, nothrow) CorElementType[m_numTotalVars];
-        
+
         if ((m_rgSize == NULL) || (m_rgElemType == NULL))
         {
             IfFailGo(E_OUTOFMEMORY);
@@ -4251,20 +4255,20 @@ GetSetFrameHelper::Init(MethodDesc *pMD)
                 {
                     pCur = pLocSig;
                 }
-                
+
                 // The "this" argument isn't stored in the signature, so we have to
                 // check for it manually.
                 if (i == 0 && pCur->HasThis())
                 {
                     _ASSERTE(pCur == pArgSig);
-                    
+
                     m_rgElemType[i] = ELEMENT_TYPE_CLASS;
                     m_rgSize[i]     = sizeof(SIZE_T);
                 }
                 else
                 {
                     m_rgElemType[i] = pCur->NextArg();
-                    
+
                     if (m_rgElemType[i] == ELEMENT_TYPE_VALUETYPE)
                     {
                         m_rgSize[i] = GetValueClassSize(pCur);
@@ -4273,39 +4277,39 @@ GetSetFrameHelper::Init(MethodDesc *pMD)
                     {
                         m_rgSize[i] = GetSetFrameHelper::GetSizeOfElement(m_rgElemType[i]);
                     }
-                    
+
                     LOG((LF_CORDB, LL_INFO10000, "GSFH::I: var 0x%x is of type %x, size:0x%x\n",
                          i, m_rgElemType[i], m_rgSize[i]));
                 }
             }
         } // allocation of m_rgSize and m_rgElemType succeeded
     }   // if there are variables to take care of
-    
+
 ErrExit:
     // clean up
     if (pArgSig != NULL)
     {
         DeleteInteropSafe(pArgSig);
     }
-    
+
     if (pLocSig != NULL)
     {
         DeleteInteropSafe(pLocSig);
     }
-    
+
     if (FAILED(hr))
     {
         if (m_rgSize != NULL)
         {
             DeleteInteropSafe(m_rgSize);
         }
-        
+
         if (m_rgElemType != NULL)
         {
             DeleteInteropSafe((int*)m_rgElemType);
         }
     }
-    
+
     return hr;
 } // GetSetFrameHelper::Init
 
@@ -4491,7 +4495,7 @@ bool GetSetFrameHelper::GetValueClassSizeOfVar(int varNum, ICorDebugInfo::VarLoc
 
         *pSize = sizeof(LPVOID);
         return false;
-    } 
+    }
 
     // This check is only safe after we make sure that varNum is not negative.
     if ((UINT)varNum >= m_numTotalVars)
@@ -4606,21 +4610,21 @@ HRESULT Debugger::GetVariablesFromOffset(MethodDesc  *pMD,
     for (UINT i = 0; i< varNativeInfoCount;i++)
     {
         // Ignore variables not live at offsetFrom
-        // 
+        //
         // #VarLife
-        // 
+        //
         // The condition below is a little strange. If a var is alive when this is true:
-        // 
+        //
         // startOffset <= offsetFrom < endOffset
-        // 
+        //
         // Then you'd expect the negated expression below to be:
-        // 
+        //
         // startOffset > offsetFrom || endOffset <= offsetFrom
-        // 
+        //
         // instead of what we're doing ("<" instead of "<="):
-        // 
+        //
         // startOffset > offsetFrom || endOffset < offsetFrom
-        // 
+        //
         // I'm not sure if the condition below is a mistake, or if it's intentionally
         // mirroring a workaround from FindNativeInfoInILVariableArray() (Debug\DI\module.cpp)
         // to deal with optimized code. So I'm leaving it alone for now. See
@@ -4769,7 +4773,7 @@ HRESULT Debugger::SetVariablesAtOffset(MethodDesc  *pMD,
     for (UINT i = 0;i< varNativeInfoCount;i++)
     {
         // Ignore variables not live at offsetTo
-        // 
+        //
         // If this IF condition looks wrong to you, see
         // code:Debugger::GetVariablesFromOffset#VarLife for more info
         if ((varNativeInfo[i].startOffset > offsetTo) ||
@@ -4856,7 +4860,7 @@ HRESULT Debugger::SetVariablesAtOffset(MethodDesc  *pMD,
     return hr;
 }
 
-BOOL IsDuplicatePatch(SIZE_T *rgEntries, 
+BOOL IsDuplicatePatch(SIZE_T *rgEntries,
                       ULONG cEntries,
                       SIZE_T Entry )
 {
@@ -5077,12 +5081,12 @@ HRESULT Debugger::MapAndBindFunctionPatches(DebuggerJitInfo *djiNew,
     LOG((LF_CORDB,LL_INFO10000, "D::MABFP: Unlocked patch table\n"));
 
 
-    // Now send any Breakpoint bind error events. 
+    // Now send any Breakpoint bind error events.
     if (listUnbindablePatches.Count() > 0)
     {
         LockAndSendBreakpointSetError(&listUnbindablePatches);
     }
-    
+
     return hr;
 }
 
@@ -5236,7 +5240,7 @@ void Debugger::SendSyncCompleteIPCEvent()
     }
 
     // If we're not marked as attached yet, then do that now.
-    // This can be safely called multiple times. 
+    // This can be safely called multiple times.
     // This can happen in the normal attach case. The Right-side sends an async-break,
     // but we don't want to be considered attach until we've actually gotten our first synchronization.
     // Else threads may slip forward during attach and send debug events while we're tyring to attach.
@@ -5279,16 +5283,16 @@ void Debugger::SendSyncCompleteIPCEvent()
 
 //
 // Lookup or create a DebuggerModule for the given pDomainFile.
-// 
+//
 // Arguments:
 //    pDomainFile - non-null domain file.
-//    
+//
 // Returns:
 //   DebuggerModule instance for the given domain file. May be lazily created.
 //
 // Notes:
 //  @dbgtodo JMC - this should go away when we get rid of DebuggerModule.
-//  
+//
 
 DebuggerModule * Debugger::LookupOrCreateModule(DomainFile * pDomainFile)
 {
@@ -5303,15 +5307,15 @@ DebuggerModule * Debugger::LookupOrCreateModule(DomainFile * pDomainFile)
 }
 
 // Overloaded Wrapper around for VMPTR_DomainFile-->DomainFile*
-// 
+//
 // Arguments:
 //    vmDomainFile - VMPTR cookie for a domain file. This can be NullPtr().
-//    
+//
 // Returns:
 //    Debugger Module instance for the given domain file. May be lazily created.
-//    
+//
 // Notes:
-//    VMPTR comes from IPC events 
+//    VMPTR comes from IPC events
 DebuggerModule * Debugger::LookupOrCreateModule(VMPTR_DomainFile vmDomainFile)
 {
     DomainFile * pDomainFile = vmDomainFile.GetRawPtr();
@@ -5323,14 +5327,14 @@ DebuggerModule * Debugger::LookupOrCreateModule(VMPTR_DomainFile vmDomainFile)
 }
 
 // Lookup or create a DebuggerModule for the given (Module, AppDomain) pair.
-// 
+//
 // Arguments:
 //    pModule - required runtime module. May be domain netural.
 //    pAppDomain - required appdomain that the module is in.
-//    
+//
 // Returns:
 //    Debugger Module isntance for the given domain file. May be lazily created.
-//    
+//
 DebuggerModule* Debugger::LookupOrCreateModule(Module* pModule, AppDomain *pAppDomain)
 {
     CONTRACTL
@@ -5343,11 +5347,11 @@ DebuggerModule* Debugger::LookupOrCreateModule(Module* pModule, AppDomain *pAppD
 
     LOG((LF_CORDB, LL_INFO1000, "D::LOCM m=0x%x ad=0x%x\n", pModule, pAppDomain));
 
-    // DebuggerModules are relative to a specific AppDomain so we should always be looking up a module / 
+    // DebuggerModules are relative to a specific AppDomain so we should always be looking up a module /
     // AppDomain pair.
     _ASSERTE( pModule != NULL );
     _ASSERTE( pAppDomain != NULL );
-    
+
     // This is called from all over. We just need to lock in order to lookup. We don't need
     // the lock when actually using the DebuggerModule (since it won't be unloaded as long as there is a thread
     // in that appdomain). Many of our callers already have this lock, many don't.
@@ -5372,7 +5376,7 @@ DebuggerModule* Debugger::LookupOrCreateModule(Module* pModule, AppDomain *pAppD
         }
         else
         {
-            dmod = m_pModules->GetModule(pModule);    
+            dmod = m_pModules->GetModule(pModule);
         }
     }
 
@@ -5387,24 +5391,24 @@ DebuggerModule* Debugger::LookupOrCreateModule(Module* pModule, AppDomain *pAppD
             dmod = AddDebuggerModule(pDomainFile); // throws
         }
         EX_CATCH_HRESULT(hr);
-        SIMPLIFYING_ASSUMPTION(dmod != NULL); // may not be true in OOM cases; but LS doesn't handle OOM.        
+        SIMPLIFYING_ASSUMPTION(dmod != NULL); // may not be true in OOM cases; but LS doesn't handle OOM.
     }
 
     // The module must be in the AppDomain that was requested
     _ASSERTE( (dmod == NULL) || (dmod->GetAppDomain() == pAppDomain) );
 
     LOG((LF_CORDB, LL_INFO1000, "D::LOCM m=0x%x ad=0x%x -> dm=0x%x\n", pModule, pAppDomain, dmod));
-    return dmod;    
+    return dmod;
 }
 
 // Create a new DebuggerModule object
-// 
+//
 // Arguments:
 //    pDomainFile-  runtime domain file to create debugger module object around
-//    
+//
 // Returns:
 //    New instnace of a DebuggerModule. Throws on failure.
-//    
+//
 DebuggerModule* Debugger::AddDebuggerModule(DomainFile * pDomainFile)
 {
     CONTRACTL
@@ -5413,7 +5417,7 @@ DebuggerModule* Debugger::AddDebuggerModule(DomainFile * pDomainFile)
         GC_NOTRIGGER;
     }
     CONTRACTL_END;
-   
+
     LOG((LF_CORDB, LL_INFO1000, "D::ADM df=0x%x\n", pDomainFile));
     DebuggerDataLockHolder chInfo(this);
 
@@ -5442,7 +5446,7 @@ DebuggerModule* Debugger::AddDebuggerModule(DomainFile * pDomainFile)
 // soon as possible. It also sets the EE up so that Runtime threads that
 // are outside of the EE will trap when they try to re-enter.
 //
-// @TODO:: 
+// @TODO::
 // Neither pDbgLockHolder nor pAppDomain are used.
 void Debugger::TrapAllRuntimeThreads()
 {
@@ -5465,7 +5469,7 @@ void Debugger::TrapAllRuntimeThreads()
     */
 
 #if !defined(FEATURE_DBGIPC_TRANSPORT_VM)
-    // Only sync if RS requested it. 
+    // Only sync if RS requested it.
     if (!m_RSRequestedSync)
     {
         return;
@@ -5770,15 +5774,15 @@ void Debugger::TraceCall(const BYTE *code)
 
     if (!CORDBUnrecoverableError(this))
     {
-        // There are situations where our callers can't tolerate us throwing.  
+        // There are situations where our callers can't tolerate us throwing.
         EX_TRY
         {
-            // Since we have a try catch and the debugger code can deal properly with 
+            // Since we have a try catch and the debugger code can deal properly with
             // faults occuring inside DebuggerController::DispatchTraceCall, we can safely
             // establish a FAULT_NOT_FATAL region. This is required since some callers can't
             // tolerate faults.
             FAULT_NOT_FATAL();
-            
+
             DebuggerController::DispatchTraceCall(pCurThread, code);
         }
         EX_CATCH
@@ -5992,7 +5996,40 @@ bool Debugger::ThreadsAtUnsafePlaces(void)
     return (m_threadsAtUnsafePlaces != 0);
 }
 
-void Debugger::SomeWork()
+void Debugger::BeforeGarbageCollection()
+{
+    CONTRACTL
+    {
+        NOTHROW;
+        GC_NOTRIGGER;
+    }
+    CONTRACTL_END;
+
+    if (!CORDebuggerAttached())
+    {
+        return;
+    }
+
+    Thread* pThread = GetThread();
+
+    SENDIPCEVENT_BEGIN(this, pThread)
+
+    if (CORDBUnrecoverableError(this))
+        return;
+
+    // Send an event to the Right Side
+    DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
+    InitIPCEvent(ipce,
+        DB_IPCE_BEFORE_GARBAGE_COLLECTION,
+        pThread,
+        pThread->GetDomain());
+
+    SendSimpleIPCEventAndBlock();
+
+    SENDIPCEVENT_END;
+}
+
+void Debugger::AfterGarbageCollection()
 {
     CONTRACTL
     {
@@ -6001,7 +6038,13 @@ void Debugger::SomeWork()
     }
     CONTRACTL_END;
 
-    // DebuggerLockHolder lockHolder(this);
+    CONTRACT_VIOLATION(GCViolation);
+
+    if (!CORDebuggerAttached())
+    {
+        return;
+    }
+
     Thread* pThread = GetThread();
 
     SENDIPCEVENT_BEGIN(this, pThread)
@@ -6012,7 +6055,7 @@ void Debugger::SomeWork()
     // Send an event to the Right Side
     DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
     InitIPCEvent(ipce,
-        DB_IPCE_SOME_WORK,
+        DB_IPCE_AFTER_GARBAGE_COLLECTION,
         pThread,
         pThread->GetDomain());
 
@@ -6121,15 +6164,15 @@ void Debugger::SendBreakpoint(Thread *thread, CONTEXT *context,
 // Notes:
 //     Can't assume that a debugger is attached (since it may detach before we get the lock).
 void Debugger::SendUserBreakpointAndSynchronize(Thread * pThread)
-{    
+{
     AtSafePlaceHolder unsafePlaceHolder(pThread);
 
     SENDIPCEVENT_BEGIN(this, pThread);
-    
+
     // Actually send the event
     if (CORDebuggerAttached())
     {
-        SendRawUserBreakpoint(pThread);    
+        SendRawUserBreakpoint(pThread);
         TrapAllRuntimeThreads();
     }
 
@@ -6170,7 +6213,7 @@ void Debugger::SendRawUserBreakpoint(Thread * pThread)
 
     LOG((LF_CORDB, LL_INFO10000, "D::SRUB: user breakpoint\n"));
 
-    
+
 
     // Send a breakpoint event to the Right Side
     DebuggerIPCEvent* pEvent = m_pRCThread->GetIPCEventSendBuffer();
@@ -6258,9 +6301,9 @@ void Debugger::SendStep(Thread *thread, CONTEXT *context,
 // Send an EnC remap opportunity and block until it is continued.
 //
 // dji - current method information
-// currentIP - IL offset within that method 
+// currentIP - IL offset within that method
 // resumeIP - address of a SIZE_T that the RS will write to cross-process if they take the
-//  remap opportunity. *resumeIP is untouched if the RS does not remap. 
+//  remap opportunity. *resumeIP is untouched if the RS does not remap.
 //-------------------------------------------------------------------------------------------------
 void Debugger::LockAndSendEnCRemapEvent(DebuggerJitInfo * dji, SIZE_T currentIP, SIZE_T *resumeIP)
 {
@@ -6396,10 +6439,10 @@ void Debugger::LockAndSendEnCRemapCompleteEvent(MethodDesc *pFD)
 // At this point, the EE is already stopped for handling an EnC ApplyChanges operation, so no need
 // to take locks etc.
 //
-void Debugger::SendEnCUpdateEvent(DebuggerIPCEventType eventType, 
-                                  Module * pModule, 
-                                  mdToken memberToken, 
-                                  mdTypeDef classToken, 
+void Debugger::SendEnCUpdateEvent(DebuggerIPCEventType eventType,
+                                  Module * pModule,
+                                  mdToken memberToken,
+                                  mdTypeDef classToken,
                                   SIZE_T enCVersion)
 {
     CONTRACTL
@@ -6451,7 +6494,7 @@ void Debugger::SendEnCUpdateEvent(DebuggerIPCEventType eventType,
 // Send a BreakpointSetError event to the Right Side if the given patch is for a breakpoint. Note: we don't care if this
 // fails, there is nothing we can do about it anyway, and the breakpoint just wont hit.
 //
-void Debugger::LockAndSendBreakpointSetError(PATCH_UNORDERED_ARRAY * listUnbindablePatches) 
+void Debugger::LockAndSendBreakpointSetError(PATCH_UNORDERED_ARRAY * listUnbindablePatches)
 {
     CONTRACTL
     {
@@ -6461,14 +6504,14 @@ void Debugger::LockAndSendBreakpointSetError(PATCH_UNORDERED_ARRAY * listUnbinda
     CONTRACTL_END;
 
     _ASSERTE(listUnbindablePatches != NULL);
-    
+
     if (CORDBUnrecoverableError(this))
         return;
 
 
     ULONG count = listUnbindablePatches->Count();
     _ASSERTE(count > 0); // must send at least 1 event.
-    
+
 
     Thread *thread = g_pEEInterface->GetThread();
     // Note that the debugger lock is reentrant, so we may or may not hold it already.
@@ -6477,7 +6520,7 @@ void Debugger::LockAndSendBreakpointSetError(PATCH_UNORDERED_ARRAY * listUnbinda
     DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
 
     for(ULONG i =  0; i < count; i++)
-    {        
+    {
         DebuggerControllerPatch *patch = listUnbindablePatches->Table()[i];
         _ASSERTE(patch != NULL);
 
@@ -6622,7 +6665,7 @@ void Debugger::SyncAllThreads(DebuggerLockHolder *dbgLockHolder)
 // Notes:
 //    This function doesn't try to stop the launched native debugger by calling DebugBreak().
 //    It sends a breakpoint event only for managed debuggers.
-//    
+//
 HRESULT Debugger::LaunchDebuggerForUser(Thread * pThread, EXCEPTION_POINTERS * pExceptionInfo,
                                         BOOL useManagedBPForManagedAttach, BOOL explicitUserRequest)
 {
@@ -6633,7 +6676,7 @@ HRESULT Debugger::LaunchDebuggerForUser(Thread * pThread, EXCEPTION_POINTERS * p
     //
     // Initiate a jit attach
     //
-    JitAttach(pThread, pExceptionInfo, useManagedBPForManagedAttach, explicitUserRequest); 
+    JitAttach(pThread, pExceptionInfo, useManagedBPForManagedAttach, explicitUserRequest);
 
     if (useManagedBPForManagedAttach)
     {
@@ -6659,7 +6702,7 @@ HRESULT Debugger::LaunchDebuggerForUser(Thread * pThread, EXCEPTION_POINTERS * p
         //
         DebugBreak();
     }
-    
+
     if (!IsDebuggerPresent())
     {
         LOG((LF_CORDB, LL_ERROR, "D::LDFU: Failed to launch the debugger.\n"));
@@ -6677,9 +6720,9 @@ EXCEPTION_RECORD Debugger::s_DebuggerLaunchJitInfoExceptionRecord = {0};
 CONTEXT          Debugger::s_DebuggerLaunchJitInfoContext = {0};
 
 //----------------------------------------------------------------------------
-// 
+//
 // InitDebuggerLaunchJitInfo - initialize JDI structure on Vista
-// 
+//
 // Arguments:
 //    pThread - the managed thread with the unhandled excpetion
 //    pExceptionInfo - unhandled exception info
@@ -6692,7 +6735,7 @@ void Debugger::InitDebuggerLaunchJitInfo(Thread * pThread, EXCEPTION_POINTERS *
 {
     LIMITED_METHOD_CONTRACT;
 
-    _ASSERTE((pExceptionInfo != NULL) && 
+    _ASSERTE((pExceptionInfo != NULL) &&
              (pExceptionInfo->ContextRecord != NULL) &&
              (pExceptionInfo->ExceptionRecord != NULL));
 
@@ -6705,7 +6748,7 @@ void Debugger::InitDebuggerLaunchJitInfo(Thread * pThread, EXCEPTION_POINTERS *
     s_DebuggerLaunchJitInfoContext = *pExceptionInfo->ContextRecord;
 
     s_DebuggerLaunchJitInfo.dwSize = sizeof(s_DebuggerLaunchJitInfo);
-    s_DebuggerLaunchJitInfo.dwThreadID = pThread == NULL ? GetCurrentThreadId() : pThread->GetOSThreadId();  
+    s_DebuggerLaunchJitInfo.dwThreadID = pThread == NULL ? GetCurrentThreadId() : pThread->GetOSThreadId();
     s_DebuggerLaunchJitInfo.lpExceptionRecord = reinterpret_cast<ULONG64>(&s_DebuggerLaunchJitInfoExceptionRecord);
     s_DebuggerLaunchJitInfo.lpContextRecord = reinterpret_cast<ULONG64>(&s_DebuggerLaunchJitInfoContext);
     s_DebuggerLaunchJitInfo.lpExceptionAddress = s_DebuggerLaunchJitInfoExceptionRecord.ExceptionAddress != NULL ?
@@ -6727,9 +6770,9 @@ void Debugger::InitDebuggerLaunchJitInfo(Thread * pThread, EXCEPTION_POINTERS *
 
 
 //----------------------------------------------------------------------------
-// 
+//
 // GetDebuggerLaunchJitInfo - retrieve the initialized JDI structure on Vista
-// 
+//
 // Arguments:
 //    None
 //
@@ -6815,7 +6858,7 @@ DebuggerLaunchSetting Debugger::GetDbgJITDebugLaunchSetting()
         setting = DLS_ATTACH_DEBUGGER;
     }
 #endif // FEATURE_PAL
-    
+
     return setting;
 }
 
@@ -6848,7 +6891,7 @@ bool Debugger::GetCompleteDebuggerLaunchString(SString * pStrArgsBuf)
     }
     CONTRACTL_END;
 
-#ifndef FEATURE_PAL    
+#ifndef FEATURE_PAL
     DWORD pid = GetCurrentProcessId();
 
     SString ssDebuggerString;
@@ -6860,16 +6903,16 @@ bool Debugger::GetCompleteDebuggerLaunchString(SString * pStrArgsBuf)
         return false;
     }
 
-    // There is no security concern to expect that the debug string we retrieve from HKLM follows a certain 
-    // format because changing HKLM keys requires admin priviledge.  Padding with zeros is not a security mitigation, 
-    // but rather a forward looking compability measure.  If future verions of Windows introduces more parameters for 
+    // There is no security concern to expect that the debug string we retrieve from HKLM follows a certain
+    // format because changing HKLM keys requires admin priviledge.  Padding with zeros is not a security mitigation,
+    // but rather a forward looking compability measure.  If future verions of Windows introduces more parameters for
     // JIT debugger launch, it is preferrable to pass zeros than other random values for those unsupported parameters.
     pStrArgsBuf->Printf(ssDebuggerString, pid, GetUnmanagedAttachEvent(), GetDebuggerLaunchJitInfo(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 
     return true;
 #else // !FEATURE_PAL
     return false;
-#endif // !FEATURE_PAL     
+#endif // !FEATURE_PAL
 }
 
 // Proxy code for EDA
@@ -6940,7 +6983,7 @@ HRESULT Debugger::EDAHelper(PROCESS_INFORMATION *pProcessInfo)
     }
     CONTRACTL_END;
 
-#ifndef FEATURE_PAL    
+#ifndef FEATURE_PAL
     LOG((LF_CORDB, LL_INFO10000, "D::EDA: thread 0x%x is launching the debugger.\n", GetCurrentThreadId()));
 
     _ASSERTE(HasLazyData());
@@ -7019,7 +7062,7 @@ HRESULT Debugger::EDAHelper(PROCESS_INFORMATION *pProcessInfo)
 //  willSendManagedEvent - indicates whether or not we plan to send a managed debug event after the jit attach
 //  explicitUserRequest - TRUE if this attach is caused by a call to the Debugger.Launch() API.
 //
-// Returns 
+// Returns
 //    TRUE - if some other thread already has jit attach in progress -> this thread should block until that is complete
 //    FALSE - this is the first thread to jit attach -> this thread should launch the debugger
 //
@@ -7046,7 +7089,7 @@ BOOL Debugger::PreJitAttach(BOOL willSendManagedEvent, BOOL willLaunchDebugger,
         //        the ThreadStore lock.  The DebuggerMutex has to be broken into two smaller locks
         //        so that you can take that lock here when holding the ThreadStore lock.
         DebuggerLockHolder dbgLockHolder(this);
-        
+
         if (!m_jitAttachInProgress)
         {
             m_jitAttachInProgress = TRUE;
@@ -7156,7 +7199,7 @@ HRESULT Debugger::LaunchJitDebuggerAndNativeAttach(Thread * pThread, EXCEPTION_P
     // Indicate to the caller that the attach was aborted
     if (res == WAIT_OBJECT_0 + 1)
     {
-        LOG((LF_CORDB, LL_INFO10000, "D::LJDANA: Debugger process is unexpectedly terminated!\n"));          
+        LOG((LF_CORDB, LL_INFO10000, "D::LJDANA: Debugger process is unexpectedly terminated!\n"));
         return E_FAIL;
     }
 
@@ -7243,19 +7286,19 @@ void Debugger::PostJitAttach()
 //    explicitUserRequest - TRUE if this attach is caused by a call to the Debugger.Launch() API.
 //
 // Returns:
-//     None. Callers can requery if a debugger is attached. 
+//     None. Callers can requery if a debugger is attached.
 //
 // Assumptions:
 //     This may be called by multiple threads, each firing their own debug events. This function will handle locking.
 //     Thus this could block for an arbitrary length of time:
-//     - may need to prompt the user to decide if an attach occurs. 
+//     - may need to prompt the user to decide if an attach occurs.
 //     - may block waiting for a debugger to attach.
-//      
+//
 // Notes:
 //     The launch string is retrieved from code:GetDebuggerSettingInfo.
 //     This will not do a sync-complete. Instead, the caller can send a debug event (the jit-attach
-//     event, such as a User-breakpoint or unhandled exception) and that can send a sync-complete, 
-//     just as if the debugger was always attached. This ensures that the jit-attach event is in the 
+//     event, such as a User-breakpoint or unhandled exception) and that can send a sync-complete,
+//     just as if the debugger was always attached. This ensures that the jit-attach event is in the
 //     same callback queue as any faked-up events that the Right-side Shim creates.
 //
 void Debugger::JitAttach(Thread * pThread, EXCEPTION_POINTERS * pExceptionInfo, BOOL willSendManagedEvent, BOOL explicitUserRequest)
@@ -7287,7 +7330,7 @@ void Debugger::JitAttach(Thread * pThread, EXCEPTION_POINTERS * pExceptionInfo,
 //    pExceptionInfo - the unhandled exception info
 //    willSendManagedEvent - true if after getting (or staying) attached we will send
 //                           a managed debug event
-//    explicitUserRequest - true if this attach is caused by a call to the 
+//    explicitUserRequest - true if this attach is caused by a call to the
 //                          Debugger.Launch() API.
 //
 // Returns:
@@ -7299,7 +7342,7 @@ void Debugger::JitAttach(Thread * pThread, EXCEPTION_POINTERS * pExceptionInfo,
 //   - JIT-atttach debugger spawned, and attached successfully.
 //   - JIT-attach debugger spawned, but declined to attach.
 //   - Failed to spawn jit-attach debugger.
-//  
+//
 //   Ultimately, the only thing that matters at the end is whether a debugger
 //   is now attached, which is retreived via CORDebuggerAttached().
 //-----------------------------------------------------------------------------
@@ -7408,7 +7451,7 @@ struct SendExceptionOnHelperThreadParams
 //   exceptionHandle : handle to the managed exception object (usually
 //       something derived from System.Exception)
 //   fContinuable : true iff continuable
-//   framePointer : frame pointer associated with callback. 
+//   framePointer : frame pointer associated with callback.
 //   nOffset : il offset associated with callback.
 //   eventType : type of callback
 //   dwFlags : additional flags (see CorDebugExceptionFlags).
@@ -7417,8 +7460,8 @@ struct SendExceptionOnHelperThreadParams
 //    S_OK on sucess. Else some error. May also throw.
 //
 // Notes:
-//    This is a helper for code:Debugger.SendExceptionEventsWorker. 
-//    See code:Debugger.SendException for more details about parameters. 
+//    This is a helper for code:Debugger.SendExceptionEventsWorker.
+//    See code:Debugger.SendException for more details about parameters.
 //    This is always called on a managed thread (never the helper thread)
 //    This will synchronize and block.
 //**************************************************************************
@@ -7488,7 +7531,7 @@ HRESULT Debugger::SendExceptionHelperAndBlock(
     }
 
     _ASSERTE(SUCCEEDED(hr) && "D::SE: Send ExceptionCallback2 event failed.");
-    
+
     if (SUCCEEDED(hr))
     {
         // Stop all Runtime threads
@@ -7505,7 +7548,7 @@ HRESULT Debugger::SendExceptionHelperAndBlock(
 // Send various first-chance / unhandled exception events.
 //
 // Assumptions:
-//    Caller has already determined that we want to send exception events. 
+//    Caller has already determined that we want to send exception events.
 //
 // Notes:
 //    This is a helper function for code:Debugger.SendException
@@ -7513,7 +7556,7 @@ void Debugger::SendExceptionEventsWorker(
     Thread * pThread,
     bool fFirstChance,
     bool fIsInterceptable,
-    bool fContinuable, 
+    bool fContinuable,
     SIZE_T currentIP,
     FramePointer framePointer,
     bool atSafePlace)
@@ -7525,7 +7568,7 @@ void Debugger::SendExceptionEventsWorker(
     // Figure out parameters to the IPC events.
     //
     const BYTE *ip;
-               
+
     SIZE_T nOffset = (SIZE_T)ICorDebugInfo::NO_MAPPING;
     DebuggerMethodInfo *pDebugMethodInfo = NULL;
 
@@ -7561,7 +7604,7 @@ void Debugger::SendExceptionEventsWorker(
             }
         }
     }
-    
+
     DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
 
     if (fFirstChance)
@@ -7574,7 +7617,7 @@ void Debugger::SendExceptionEventsWorker(
         //
         // Send the first chance exception if we have not already and if it is not suppressed
         //
-        if (m_sendExceptionsOutsideOfJMC && !pExState->GetFlags()->SentDebugFirstChance()) 
+        if (m_sendExceptionsOutsideOfJMC && !pExState->GetFlags()->SentDebugFirstChance())
         {
             // Blocking here is especially important so that the debugger can mark any code as JMC.
             hr = SendExceptionHelperAndBlock(
@@ -7614,8 +7657,8 @@ void Debugger::SendExceptionEventsWorker(
         //
         // If this is a JMC function, then we send a USER's first chance as well.
         //
-        if ((pDebugMethodInfo != NULL) && 
-            pDebugMethodInfo->IsJMCFunction() && 
+        if ((pDebugMethodInfo != NULL) &&
+            pDebugMethodInfo->IsJMCFunction() &&
             !pExState->GetFlags()->SentDebugUserFirstChance())
         {
             SENDIPCEVENT_BEGIN(this, pThread);
@@ -7685,7 +7728,7 @@ void Debugger::SendExceptionEventsWorker(
 
 //
 // SendException is called by Runtime threads to send that they've hit an Managed exception to the Right Side.
-// This may block this thread and suspend the debuggee, and let the debugger inspect us. 
+// This may block this thread and suspend the debuggee, and let the debugger inspect us.
 //
 // The thread's throwable should be set so that the debugger can inspect the current exception.
 // It does not report native exceptions in native code (which is consistent because those don't have a
@@ -7695,22 +7738,22 @@ void Debugger::SendExceptionEventsWorker(
 // is yet involved.
 //
 // Parameters:
-//    pThread - the thread throwing the exception. 
+//    pThread - the thread throwing the exception.
 //    fFirstChance - true if this is a first chance exception. False if this is an unhandled exception.
-//    currentIP - absolute native address of the exception if it is from managed code. If this is 0, we try to find it 
+//    currentIP - absolute native address of the exception if it is from managed code. If this is 0, we try to find it
 //                based off the thread's current exception state.
 //    currentSP - stack pointer of the exception. This will get converted into a FramePointer and then used by the debugger
 //                to identify which stack frame threw the exception.
 //    currentBSP - additional information for IA64 only to identify the stack frame.
 //    fContinuable - not used.
-//    fAttaching - true iff this exception may initiate a jit-attach. In the common case, if this is true, then 
+//    fAttaching - true iff this exception may initiate a jit-attach. In the common case, if this is true, then
 //                 CorDebuggerAttached() is false. However, since a debugger can attach at any time, it's possible
 //                 for another debugger to race against the jit-attach and win. Thus this may err on the side of being true.
-//    fForceNonInterceptable - This is used to determine if the exception is continuable (ie "Interceptible", 
+//    fForceNonInterceptable - This is used to determine if the exception is continuable (ie "Interceptible",
 //                  we can handle a DB_IPCE_INTERCEPT_EXCEPTION event for it). If true, then the exception can not be continued.
-//                  If false, we get continuation status from the exception properties of the current thread. 
+//                  If false, we get continuation status from the exception properties of the current thread.
 //
-// Returns: 
+// Returns:
 //    S_OK on success (common case by far).
 //    propogates other errors.
 //
@@ -7773,7 +7816,7 @@ HRESULT Debugger::SendException(Thread *pThread,
     if (fAttaching)
     {
         JitAttach(pThread, pExceptionInfo, managedEventNeeded, FALSE);
-        // If the jit-attach occurred, CORDebuggerAttached() may now be true and we can 
+        // If the jit-attach occurred, CORDebuggerAttached() may now be true and we can
         // just act as if a debugger was always attached.
     }
 
@@ -7782,10 +7825,10 @@ HRESULT Debugger::SendException(Thread *pThread,
         {
             // We have to send enabled, so enable now.
             GCX_PREEMP_EEINTERFACE();
-            
+
             // Send the exception events. Even in jit-attach case, we should now be fully attached.
             if (CORDebuggerAttached())
-            {                    
+            {
                 // Initialize frame-pointer associated with exception notification.
                 LPVOID stackPointer;
                 if ((currentSP == 0) && (pExState->GetContextRecord() != NULL))
@@ -7797,18 +7840,18 @@ HRESULT Debugger::SendException(Thread *pThread,
                     stackPointer = (LPVOID)currentSP;
                 }
                 FramePointer framePointer = FramePointer::MakeFramePointer(stackPointer);
-                    
+
 
                 // Do the real work of sending the events
                 SendExceptionEventsWorker(
                     pThread,
                     fFirstChance,
                     fIsInterceptable,
-                    fContinuable, 
+                    fContinuable,
                     currentIP,
                     framePointer,
                     !unsafePlaceHolder.IsAtUnsafePlace());
-            } 
+            }
             else
             {
                 LOG((LF_CORDB,LL_INFO100, "D:SE: Skipping SendIPCEvent because not supposed to send anything, or RS detached.\n"));
@@ -7877,7 +7920,7 @@ void Debugger::ProcessAnyPendingEvals(Thread *pThread)
     // FuncEvalComplete event, so if the user asks for another func eval then there will be a new pending eval when we
     // loop and check again.
     //
-    DebuggerPendingFuncEval *pfe;    
+    DebuggerPendingFuncEval *pfe;
 
     while (GetPendingEvals() != NULL && (pfe = GetPendingEvals()->GetPendingEval(pThread)) != NULL)
     {
@@ -7890,18 +7933,18 @@ void Debugger::ProcessAnyPendingEvals(Thread *pThread)
         // that we can do another nested eval properly.
         GetPendingEvals()->RemovePendingEval(pThread);
 
-        // Go ahead and do the pending func eval. pDE is invalid after this. 
+        // Go ahead and do the pending func eval. pDE is invalid after this.
         void *ret;
         ret = ::FuncEvalHijackWorker(pDE);
 
 
         // The return value should be NULL when FuncEvalHijackWorker is called as part of an exception.
-        _ASSERTE(ret == NULL);                
+        _ASSERTE(ret == NULL);
     }
 
     // If we need to re-throw a ThreadAbortException, go ahead and do it now.
-    if (GetThread()->m_StateNC & Thread::TSNC_DebuggerReAbort)    
-    {    
+    if (GetThread()->m_StateNC & Thread::TSNC_DebuggerReAbort)
+    {
         // Now clear the bit else we'll see it again when we process the Exception notification
         // from this upcoming UserAbort exception.
         pThread->ResetThreadStateNC(Thread::TSNC_DebuggerReAbort);
@@ -8002,14 +8045,14 @@ void Debugger::FirstChanceManagedExceptionCatcherFound(Thread *pThread,
     DWORD nOffset = (DWORD)(SIZE_T)ICorDebugInfo::NO_MAPPING;
     DebuggerMethodInfo *pDebugMethodInfo = NULL;
     DebuggerJitInfo *pDebugJitInfo = NULL;
-    bool isInJMCFunction = false; 
+    bool isInJMCFunction = false;
 
     if (pMD != NULL)
     {
         _ASSERTE(!pMD->IsILStub());
 
         pDebugJitInfo = GetJitInfo(pMD, (const BYTE *) pMethodAddr, &pDebugMethodInfo);
-        if (pDebugMethodInfo != NULL) 
+        if (pDebugMethodInfo != NULL)
         {
             isInJMCFunction = pDebugMethodInfo->IsJMCFunction();
         }
@@ -8017,9 +8060,9 @@ void Debugger::FirstChanceManagedExceptionCatcherFound(Thread *pThread,
 
     // Here we check if debugger opted-out of receiving exception related events from outside of JMC methods
     // or this exception ever crossed JMC frame (in this case we have already sent user first chance event)
-    if (m_sendExceptionsOutsideOfJMC || 
-        isInJMCFunction || 
-        pThread->GetExceptionState()->GetFlags()->SentDebugUserFirstChance()) 
+    if (m_sendExceptionsOutsideOfJMC ||
+        isInJMCFunction ||
+        pThread->GetExceptionState()->GetFlags()->SentDebugUserFirstChance())
     {
         if (pDebugJitInfo != NULL)
         {
@@ -8417,7 +8460,7 @@ FramePointer GetHandlerFramePointer(BYTE *pStack)
 {
     FramePointer handlerFP;
 
-#if !defined(_TARGET_ARM_) && !defined(_TARGET_ARM64_) 
+#if !defined(_TARGET_ARM_) && !defined(_TARGET_ARM64_)
     // Refer to the comment in DispatchUnwind() to see why we have to add
     // sizeof(LPVOID) to the handler ebp.
     handlerFP = FramePointer::MakeFramePointer(LPVOID(pStack + sizeof(void*)));
@@ -8605,7 +8648,7 @@ void LazyInitFavor(void *)
     hr = g_pDebugger->LazyInitWrapper();
     (void)hr; //prevent "unused variable" error from GCC
 
-    // On checked builds, warn that we're hitting a scenario that debugging doesn't support.    
+    // On checked builds, warn that we're hitting a scenario that debugging doesn't support.
     _ASSERTE(SUCCEEDED(hr) || !"Couldn't initialize lazy data for LastChanceManagedException");
 }
 
@@ -8691,21 +8734,21 @@ LONG Debugger::LastChanceManagedException(EXCEPTION_POINTERS * pExceptionInfo,
         // using this thread's stack space.
         if (jitAttachRequested)
         {
-            m_pRCThread->DoFavor((FAVORCALLBACK) LazyInitFavor, NULL);                
+            m_pRCThread->DoFavor((FAVORCALLBACK) LazyInitFavor, NULL);
         }
-        
-        // The only way we don't have lazy data at this point is in an OOM scenario, which 
+
+        // The only way we don't have lazy data at this point is in an OOM scenario, which
         // the debugger doesn't support.
         if (!HasLazyData())
         {
-            return ExceptionContinueSearch;            
+            return ExceptionContinueSearch;
         }
 
 
-        // In Whidbey, we used to set the filter CONTEXT when we hit an unhandled exception while doing 
-        // mixed-mode debugging.  This helps the debugger walk the stack since it can skip the leaf 
-        // portion of the stack (including stack frames in the runtime) and start the stackwalk at the 
-        // faulting stack frame.  The code to set the filter CONTEXT is in a hijack function which is only 
+        // In Whidbey, we used to set the filter CONTEXT when we hit an unhandled exception while doing
+        // mixed-mode debugging.  This helps the debugger walk the stack since it can skip the leaf
+        // portion of the stack (including stack frames in the runtime) and start the stackwalk at the
+        // faulting stack frame.  The code to set the filter CONTEXT is in a hijack function which is only
         // used during mixed-mode debugging.
         if (m_pRCThread->GetDCB()->m_rightSideIsWin32Debugger)
         {
@@ -8796,7 +8839,7 @@ int Debugger::NotifyUserOfFault(bool userBreakpoint, DebuggerLaunchSetting dls)
             // lock is very small.
             SUPPRESS_ALLOCATION_ASSERTS_IN_THIS_SCOPE;
 
-            result = MessageBox(resIDMessage, IDS_DEBUG_SERVICE_CAPTION, 
+            result = MessageBox(resIDMessage, IDS_DEBUG_SERVICE_CAPTION,
                 flags, TRUE, TRUE, pid, pid, tid, tid);
         }
     }
@@ -8859,7 +8902,7 @@ Debugger::ATTACH_ACTION Debugger::ShouldAttachDebuggerProxy(bool fIsUserBreakpoi
 
 //---------------------------------------------------------------------------------------
 // Do policy to determine if we should attach a debugger.
-// 
+//
 // Arguments:
 //    fIsUserBreakpoint - true iff this is in response to a user-breakpoint, else false.
 //
@@ -8904,7 +8947,7 @@ Debugger::ATTACH_ACTION Debugger::ShouldAttachDebugger(bool fIsUserBreakpoint)
 
         // This lock is also part of the above workaround.
         // Must go to preemptive to take this lock since we'll trigger down the road.
-        GCX_PREEMP();       
+        GCX_PREEMP();
         DebuggerLockHolder lockHolder(this);
 
         // We always want to ask about user breakpoints!
@@ -8916,7 +8959,7 @@ Debugger::ATTACH_ACTION Debugger::ShouldAttachDebugger(bool fIsUserBreakpoint)
             // While we could theoretically run into a deadlock if another thread
             // which acquires the debugger lock in cooperative GC mode is blocked
             // on this thread while it is running arbitrary user code out of the
-            // MessageBox message pump, given that this codepath will only be used 
+            // MessageBox message pump, given that this codepath will only be used
             // on Win9x and that the chances of this happenning are quite slim,
             // for Whidbey a GCViolation is acceptable.
             CONTRACT_VIOLATION(GCViolation);
@@ -8957,7 +9000,7 @@ Debugger::ATTACH_ACTION Debugger::ShouldAttachDebugger(bool fIsUserBreakpoint)
 //
 //    This may trigger a Jit attach.
 //    If the debugger is already attached, this will issue a step-out so that the UserBreakpoint
-//    appears to come from the callsite. 
+//    appears to come from the callsite.
 void Debugger::SendUserBreakpoint(Thread * thread)
 {
     CONTRACTL
@@ -9012,12 +9055,12 @@ void Debugger::SendUserBreakpoint(Thread * thread)
     ATTACH_ACTION dbgAction = ShouldAttachDebugger(true);
 
     // No debugger is attached. Consider a JIT attach.
-    // This will do ShouldAttachDebugger() and wait for the results. 
-    // - It may terminate if the user requested that. 
-    // - It may do a full jit-attach. 
+    // This will do ShouldAttachDebugger() and wait for the results.
+    // - It may terminate if the user requested that.
+    // - It may do a full jit-attach.
     if (dbgAction == ATTACH_YES)
     {
-        JitAttach(thread, NULL, TRUE, FALSE); 
+        JitAttach(thread, NULL, TRUE, FALSE);
     }
     else if (dbgAction == ATTACH_TERMINATE)
     {
@@ -9032,11 +9075,11 @@ void Debugger::SendUserBreakpoint(Thread * thread)
     {
         _ASSERTE(dbgAction == ATTACH_NO);
     }
-    
+
     if (CORDebuggerAttached())
     {
-        // On jit-attach, we just send the UserBreak event. Don't do an extra step-out. 
-        SendUserBreakpointAndSynchronize(thread);        
+        // On jit-attach, we just send the UserBreak event. Don't do an extra step-out.
+        SendUserBreakpointAndSynchronize(thread);
     }
     else if (IsDebuggerPresent())
     {
@@ -9077,7 +9120,7 @@ void Debugger::ThreadCreated(Thread* pRuntimeThread)
     // Sanity check the thread.
     _ASSERTE(pRuntimeThread != NULL);
     _ASSERTE(pRuntimeThread->GetThreadId() != 0);
-    
+
 
     // Create a thread starter and enable its WillEnterManaged code
     // callback. This will cause the starter to trigger once the
@@ -9202,7 +9245,7 @@ void Debugger::DetachThread(Thread *pRuntimeThread)
     {
         // Send a detach thread event to the Right Side.
         DebuggerIPCEvent * pEvent = m_pRCThread->GetIPCEventSendBuffer();
-        
+
         InitIPCEvent(pEvent,
                      DB_IPCE_THREAD_DETACH,
                      pRuntimeThread,
@@ -9468,7 +9511,7 @@ void Debugger::LoadAssembly(DomainAssembly * pDomainAssembly)
     Thread *pThread = g_pEEInterface->GetThread();
     SENDIPCEVENT_BEGIN(this, pThread)
 
-    
+
     if (CORDebuggerAttached())
     {
         // Send a load assembly event to the Right Side.
@@ -9570,15 +9613,15 @@ void Debugger::LoadModule(Module* pRuntimeModule,
     if (CORDBUnrecoverableError(this))
         return;
 
-    // If this is a dynamic module, then it's part of a multi-module assembly. The manifest 
-    // module within the assembly contains metadata for all the module names in the assembly. 
+    // If this is a dynamic module, then it's part of a multi-module assembly. The manifest
+    // module within the assembly contains metadata for all the module names in the assembly.
     // When a new dynamic module is created, the manifest module's metadata is updated to
-    // include the new module (see code:Assembly.CreateDynamicModule). 
-    // So we need to update the RS's copy of the metadata. One place the manifest module's 
+    // include the new module (see code:Assembly.CreateDynamicModule).
+    // So we need to update the RS's copy of the metadata. One place the manifest module's
     // metadata gets used is in code:DacDbiInterfaceImpl.GetModuleSimpleName
-    // 
+    //
     // See code:ReflectionModule.CaptureModuleMetaDataToMemory for why we send the metadata-refresh here.
-    if (pRuntimeModule->IsReflection() && !pRuntimeModule->IsManifest() && !fAttaching) 
+    if (pRuntimeModule->IsReflection() && !pRuntimeModule->IsManifest() && !fAttaching)
     {
         HRESULT hr = S_OK;
         EX_TRY
@@ -9597,12 +9640,12 @@ void Debugger::LoadModule(Module* pRuntimeModule,
 
             // Raise the debug event.
             // This still tells the debugger that the manifest module metadata is invalid and needs to
-            // be refreshed. 
+            // be refreshed.
             DebuggerIPCEvent eventMetadataUpdate;
             InitIPCEvent(&eventMetadataUpdate, DB_IPCE_METADATA_UPDATE, NULL, pAppDomain);
 
             eventMetadataUpdate.MetadataUpdateData.vmDomainFile.SetRawPtr(pManifestDomainFile);
-                 
+
             SendRawEvent(&eventMetadataUpdate);
         }
         EX_CATCH_HRESULT(hr);
@@ -9655,7 +9698,7 @@ void Debugger::LoadModule(Module* pRuntimeModule,
         {
             TrapAllRuntimeThreads();
         }
-        EX_CATCH_HRESULT(hr); // @dbgtodo  synchronization - catch exception and go on to restore state. 
+        EX_CATCH_HRESULT(hr); // @dbgtodo  synchronization - catch exception and go on to restore state.
         // Synchronization feature crew needs to figure out what happens to TrapAllRuntimeThreads().
     }
 
@@ -9673,7 +9716,7 @@ void Debugger::LoadModule(Module* pRuntimeModule,
         {
             SendUpdateModuleSymsEventAndBlock(pRuntimeModule, pAppDomain);
         }
-        EX_CATCH_HRESULT(hr); 
+        EX_CATCH_HRESULT(hr);
     }
 
     // Now that we're done with the load module event, can no longer change Jit flags.
@@ -9810,7 +9853,7 @@ void Debugger::LoadModuleFinished(Module * pRuntimeModule, AppDomain * pAppDomai
 // Notes:
 //   This is just a ping event. Debugger must query for actual symbol contents.
 //   This keeps the launch + attach cases identical.
-//   This just sends the raw event and does not synchronize the runtime. 
+//   This just sends the raw event and does not synchronize the runtime.
 //   Use code:Debugger.SendUpdateModuleSymsEventAndBlock for that.
 void Debugger::SendRawUpdateModuleSymsEvent(Module *pRuntimeModule, AppDomain *pAppDomain)
 {
@@ -9832,7 +9875,7 @@ void Debugger::SendRawUpdateModuleSymsEvent(Module *pRuntimeModule, AppDomain *p
     if (CORDBUnrecoverableError(this))
         return;
 
-    // This event is used to trigger the ICorDebugManagedCallback::UpdateModuleSymbols 
+    // This event is used to trigger the ICorDebugManagedCallback::UpdateModuleSymbols
     // callback.  That callback is defined to pass a PDB stream, and so we still use this
     // only for legacy compatibility reasons when we've actually got PDB symbols.
     // New clients know they must request a new symbol reader after ClassLoad events.
@@ -9844,8 +9887,8 @@ void Debugger::SendRawUpdateModuleSymsEvent(Module *pRuntimeModule, AppDomain *p
 
     DebuggerIPCEvent* ipce = NULL;
     ipce = m_pRCThread->GetIPCEventSendBuffer();
-    InitIPCEvent(ipce, DB_IPCE_UPDATE_MODULE_SYMS, 
-                 g_pEEInterface->GetThread(), 
+    InitIPCEvent(ipce, DB_IPCE_UPDATE_MODULE_SYMS,
+                 g_pEEInterface->GetThread(),
                  pAppDomain);
 
     ipce->UpdateModuleSymsData.vmDomainFile.SetRawPtr((module ? module->GetDomainFile() : NULL));
@@ -9856,17 +9899,17 @@ void Debugger::SendRawUpdateModuleSymsEvent(Module *pRuntimeModule, AppDomain *p
 //
 // UpdateModuleSyms is called when the symbols for a module need to be
 // sent to the Right Side because they've changed.
-// 
+//
 // Arguments:
 //   pRuntimeModule - required, module to send symbols for. May be domain neutral.
 //   pAppDomain - required, appdomain that module is in.
-//     
-//     
-// Notes: 
+//
+//
+// Notes:
 //    This will send the event (via code:Debugger.SendRawUpdateModuleSymsEvent) and then synchronize
 //    the runtime waiting for a continue.
-//   
-//    This should only be called in cases where we reasonably expect to send symbols. 
+//
+//    This should only be called in cases where we reasonably expect to send symbols.
 //    However, this may not send symbols if the symbols aren't available.
 void Debugger::SendUpdateModuleSymsEventAndBlock(Module* pRuntimeModule, AppDomain *pAppDomain)
 {
@@ -9897,7 +9940,7 @@ void Debugger::SendUpdateModuleSymsEventAndBlock(Module* pRuntimeModule, AppDoma
     // Actually send the event
     if (CORDebuggerAttached())
     {
-        SendRawUpdateModuleSymsEvent(pRuntimeModule, pAppDomain);    
+        SendRawUpdateModuleSymsEvent(pRuntimeModule, pAppDomain);
         TrapAllRuntimeThreads();
     }
 
@@ -9909,7 +9952,7 @@ void Debugger::SendUpdateModuleSymsEventAndBlock(Module* pRuntimeModule, AppDoma
 // UnloadModule is called by the Runtime for each module (including shared ones)
 // in an AppDomain that is being unloaded, when a debugger is attached.
 // In the EE, a module may be domain-neutral and therefore shared across all AppDomains.
-// We abstract this detail away in the Debugger and consider each such EE module to correspond 
+// We abstract this detail away in the Debugger and consider each such EE module to correspond
 // to multiple "Debugger Module" instances (one per AppDomain).
 // Therefore, this doesn't necessarily mean the runtime is unloading the module, just
 // that the Debugger should consider it's (per-AppDomain) DebuggerModule to be unloaded.
@@ -9957,7 +10000,7 @@ void Debugger::UnloadModule(Module* pRuntimeModule,
             pRuntimeModule, pAppDomain, pRuntimeModule->IsIStream());
 
         // Note: the appdomain the module was loaded in must match the appdomain we're unloading it from. If it doesn't,
-        // then we've either found the wrong DebuggerModule in LookupModule or we were passed bad data.        
+        // then we've either found the wrong DebuggerModule in LookupModule or we were passed bad data.
         _ASSERTE(module->GetAppDomain() == pAppDomain);
 
         // Send the unload module event to the Right Side.
@@ -10006,7 +10049,7 @@ void Debugger::UnloadModule(Module* pRuntimeModule,
             }
             LOG((LF_CORDB, LL_EVERYTHING, "Done clearing JMC methods!\n"));
         }
-    
+
         // Delete the Left Side representation of the module.
         if (m_pModules != NULL)
         {
@@ -10026,12 +10069,12 @@ LExit:
     SENDIPCEVENT_END;
 }
 
-// Called when this module is completely gone from ALL AppDomains, regardless of 
-// whether a debugger is attached.  
-// Note that this doesn't get called until after the ADUnload is complete, which happens 
+// Called when this module is completely gone from ALL AppDomains, regardless of
+// whether a debugger is attached.
+// Note that this doesn't get called until after the ADUnload is complete, which happens
 // asyncronously in Whidbey (and won't happen at all if the process shuts down first).
 // This is normally not called only domain-neutral assemblies because they can't be unloaded.
-// However, it may be called if the loader fails to completely load a domain-neutral assembly. 
+// However, it may be called if the loader fails to completely load a domain-neutral assembly.
 void Debugger::DestructModule(Module *pModule)
 {
     CONTRACTL
@@ -10051,7 +10094,7 @@ void Debugger::DestructModule(Module *pModule)
     DebuggerLockHolder dbgLockHolder(this);
 
     // We should have removed all patches at AD unload time (or detach time if the
-    // debugger detached).   
+    // debugger detached).
     _ASSERTE( !DebuggerController::ModuleHasPatches(pModule) );
 
     // Do module clean-up that applies even when no debugger is attached.
@@ -10098,7 +10141,7 @@ void Debugger::RemoveModuleReferences( Module* pModule )
 
             // DebuggerDataLockHolder out of scope - release implied
         }
-    } 
+    }
 }
 
 //---------------------------------------------------------------------------------------
@@ -10106,7 +10149,7 @@ void Debugger::RemoveModuleReferences( Module* pModule )
 // SendClassLoadUnloadEvent - notify the RS of a class either loading or unloading.
 //
 // Arguments:
-//    
+//
 //    fAttaching - true if a debugger is in the process of attaching
 //
 // Return Value:
@@ -10131,9 +10174,9 @@ void Debugger::SendClassLoadUnloadEvent (mdTypeDef classMetadataToken,
         classMetadataToken, fIsLoadEvent, pClassDebuggerModule, pAppDomain));
 
     DebuggerIPCEvent * pEvent = m_pRCThread->GetIPCEventSendBuffer();
-    
+
     BOOL fIsReflection = pClassDebuggerModule->GetRuntimeModule()->IsReflection();
-    
+
     if (fIsLoadEvent == TRUE)
     {
         // We need to update Metadata before Symbols (since symbols depend on metadata)
@@ -10263,10 +10306,10 @@ BOOL  Debugger::LoadClass(TypeHandle th,
         return FALSE;
 
     // Note that pAppDomain may be null.  The AppDomain isn't used here, and doesn't make a lot of sense since
-    // we may be delivering the notification for a class in an assembly which is loaded into multiple AppDomains.  We 
-    // handle this in SendSystemClassLoadUnloadEvent below by looping through all AppDomains and dispatching 
+    // we may be delivering the notification for a class in an assembly which is loaded into multiple AppDomains.  We
+    // handle this in SendSystemClassLoadUnloadEvent below by looping through all AppDomains and dispatching
     // events for each that contain this assembly.
-    
+
     LOG((LF_CORDB, LL_INFO10000, "D::LC: load class Tok:%#08x Mod:%#08x AD:%#08x classMod:%#08x modName:%ls\n",
          classMetadataToken, (pAppDomain == NULL) ? NULL : LookupOrCreateModule(classModule, pAppDomain),
          pAppDomain, classModule, classModule->GetDebugName()));
@@ -10383,20 +10426,20 @@ void Debugger::FuncEvalComplete(Thread* pThread, DebuggerEval *pDE)
     if (pDE->m_rethrowAbortException)
     {
         pThread->SetThreadStateNC(Thread::TSNC_DebuggerReAbort);
-    }        
+    }
 
 
     //
     // Get the domain that the result is valid in. The RS will cache this in the ICorDebugValue
-    // Note: it's possible that the AppDomain has (or is about to be) unloaded, which could lead to a 
-    // crash when we use the DebuggerModule.  Ideally we'd only be using AppDomain IDs here. 
+    // Note: it's possible that the AppDomain has (or is about to be) unloaded, which could lead to a
+    // crash when we use the DebuggerModule.  Ideally we'd only be using AppDomain IDs here.
     // We can't easily convert our ADID to an AppDomain* (SystemDomain::GetAppDomainFromId)
-    // because we can't proove that that the AppDomain* would be valid (not unloaded). 
+    // because we can't proove that that the AppDomain* would be valid (not unloaded).
     //
     AppDomain *pDomain = pThread->GetDomain();
     AppDomain *pResultDomain = ((pDE->m_debuggerModule == NULL) ? pDomain : pDE->m_debuggerModule->GetAppDomain());
     _ASSERTE( pResultDomain->GetId() == pDE->m_appDomainId );
-    
+
     // Send a func eval complete event to the Right Side.
     DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
     InitIPCEvent(ipce, DB_IPCE_FUNC_EVAL_COMPLETE, pThread, pDomain);
@@ -10418,10 +10461,10 @@ void Debugger::FuncEvalComplete(Thread* pThread, DebuggerEval *pDE)
     _ASSERTE(ipce->FuncEvalComplete.resultType.elementType != ELEMENT_TYPE_VALUETYPE);
 
     // We must adjust the result address to point to the right place
-    ipce->FuncEvalComplete.resultAddr = ArgSlotEndianessFixup((ARG_SLOT*)ipce->FuncEvalComplete.resultAddr, 
+    ipce->FuncEvalComplete.resultAddr = ArgSlotEndianessFixup((ARG_SLOT*)ipce->FuncEvalComplete.resultAddr,
         GetSizeForCorElementType(ipce->FuncEvalComplete.resultType.elementType));
 
-    LOG((LF_CORDB, LL_INFO1000, "D::FEC: returned el %04x resultAddr %p\n", 
+    LOG((LF_CORDB, LL_INFO1000, "D::FEC: returned el %04x resultAddr %p\n",
         ipce->FuncEvalComplete.resultType.elementType, ipce->FuncEvalComplete.resultAddr));
 
     m_pRCThread->SendIPCEvent();
@@ -10551,7 +10594,7 @@ BYTE* Debugger::SerializeModuleMetaData(Module * pModule, DWORD * countBytes)
         ThrowHR(hr);
     }
     _ASSERTE(pInternalEmitter != NULL);
-        
+
     hr = pInternalEmitter->SetMDUpdateMode(MDUpdateExtension, &originalUpdateMode);
     if(FAILED(hr))
     {
@@ -10559,7 +10602,7 @@ BYTE* Debugger::SerializeModuleMetaData(Module * pModule, DWORD * countBytes)
         ThrowHR(hr);
     }
     _ASSERTE(originalUpdateMode == MDUpdateFull);
-       
+
     hr = pEmitter->GetSaveSize(cssQuick, countBytes);
     if(FAILED(hr))
     {
@@ -10580,7 +10623,7 @@ BYTE* Debugger::SerializeModuleMetaData(Module * pModule, DWORD * countBytes)
     }
     EX_END_CATCH(SwallowAllExceptions);
     _ASSERTE(metadataBuffer != NULL); // allocation would throw first
-    
+
     // Caller ensures serialization that guarantees that the metadata doesn't grow underneath us.
     hr = pEmitter->SaveToMemory(metadataBuffer, *countBytes);
     if(FAILED(hr))
@@ -10590,7 +10633,7 @@ BYTE* Debugger::SerializeModuleMetaData(Module * pModule, DWORD * countBytes)
         pInternalEmitter->SetMDUpdateMode(originalUpdateMode, NULL);
         ThrowHR(hr);
     }
-    
+
     pInternalEmitter->SetMDUpdateMode(originalUpdateMode, NULL);
     LOG((LF_CORDB, LL_INFO10000, "Debugger::SMMD exiting\n"));
     return metadataBuffer;
@@ -10635,7 +10678,7 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent)
     {
         THROWS;
         if (g_pEEInterface->GetThread() != NULL) { GC_TRIGGERS; } else { GC_NOTRIGGER; }
-        
+
         PRECONDITION(ThisIsHelperThreadWorker());
 
         if (m_stopped)
@@ -10701,14 +10744,14 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent)
     switch (pEvent->type & DB_IPCE_TYPE_MASK)
     {
 
-    case DB_IPCE_ATTACHING:       
+    case DB_IPCE_ATTACHING:
         // In V3, Attach is atomic, meaning that there isn't a complex handshake back and forth between LS + RS.
         // the RS sends a single-attaching event and attaches at the first response from the Left-side.
         StartCanaryThread();
-        
+
         // In V3 after attaching event was handled we iterate throughout all ADs and made shadow copies of PDBs in the BIN directories.
         // After all AppDomain, DomainAssembly and modules iteration was available in out-of-proccess model in V4 the code that enables
-        // PDBs to be copied was not called at attach time. 
+        // PDBs to be copied was not called at attach time.
         // Eliminating PDBs copying side effect is an issue: Dev10 #927143
         EX_TRY
         {
@@ -10717,12 +10760,12 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent)
         EX_CATCH_HRESULT(hr); // ignore failures
 
         if (m_jitAttachInProgress)
-        { 
-            // For jit-attach, mark that we're attached now. 
-            // This lets callers to code:Debugger.JitAttach check the flag and 
+        {
+            // For jit-attach, mark that we're attached now.
+            // This lets callers to code:Debugger.JitAttach check the flag and
             // send the jit-attach event just like a normal event.
             MarkDebuggerAttachedInternal();
-            
+
             // set the managed attach event so that waiting threads can continue
             VERIFY(SetEvent(GetAttachEvent()));
             break;
@@ -10764,7 +10807,7 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent)
     case DB_IPCE_CONTINUE:
         {
             GetCanary()->ClearCache();
-        
+
             fContinue = ResumeThreads(pEvent->vmAppDomain.GetRawPtr());
 
                 //
@@ -10793,7 +10836,7 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent)
             Module * pModule = pDebuggerModule->GetRuntimeModule();
             DebuggerMethodInfo * pDMI = GetOrCreateMethodInfo(pModule, pEvent->BreakpointData.funcMetadataToken);
             MethodDesc * pMethodDesc = pEvent->BreakpointData.nativeCodeMethodDescToken.UnWrap();
-        
+
             DebuggerJitInfo * pDJI =  NULL;
             if ((pMethodDesc != NULL) && (pDMI != NULL))
             {
@@ -10832,14 +10875,14 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent)
             }
 
             LOG((LF_CORDB,LL_INFO10000,"\tBP Add: BPTOK:"
-                "0x%x, tok=0x%08x, offset=0x%x, isIL=%d dm=0x%x m=0x%x\n", 
+                "0x%x, tok=0x%08x, offset=0x%x, isIL=%d dm=0x%x m=0x%x\n",
                  pDebuggerBP,
                  pEvent->BreakpointData.funcMetadataToken,
                  pEvent->BreakpointData.offset,
                  pEvent->BreakpointData.isIL,
                  pDebuggerModule,
                  pModule));
-        
+
             //
             // We're using a two-way event here, so we place the
             // result event into the _receive_ buffer, not the send
@@ -10968,7 +11011,7 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent)
             else
             {
                 DebuggerStepper * pStepper;
-                 
+
                 if (pEvent->StepData.IsJMCStop)
                 {
                     pStepper = new (interopsafe, nothrow) DebuggerJMCStepper(pThread,
@@ -11035,8 +11078,8 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent)
             CorDebugThreadState debugState = pEvent->SetAllDebugState.debugState;
 
             LOG((LF_CORDB,LL_INFO10000,"HandleIPCE: SetAllDebugState: except thread 0x%08x (ID:0x%x) to state 0x%x\n",
-                 pThread, 
-                 (pThread != NULL) ? GetThreadIdHelper(pThread) : 0, 
+                 pThread,
+                 (pThread != NULL) ? GetThreadIdHelper(pThread) : 0,
                  debugState));
 
             if (!g_fProcessDetach)
@@ -11130,13 +11173,13 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent)
             DebuggerModule *pDebuggerModule = LookupOrCreateModule(pEvent->SetClassLoad.vmDomainFile);
 
             _ASSERTE(pDebuggerModule != NULL);
-            
+
             LOG((LF_CORDB, LL_INFO10000,
                  "D::HIPCE: class load flag is %d for module 0x%p\n",
-                 pEvent->SetClassLoad.flag, 
+                 pEvent->SetClassLoad.flag,
                  pDebuggerModule));
 
-            pDebuggerModule->EnableClassLoadCallbacks((BOOL)pEvent->SetClassLoad.flag);            
+            pDebuggerModule->EnableClassLoadCallbacks((BOOL)pEvent->SetClassLoad.flag);
         }
         break;
 
@@ -11184,8 +11227,8 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent)
                 DebuggerJitInfo * pDJI = NULL;
                 if (pDMI != NULL)
                 {
-                    // In the EnC case, if we look for an older version, we need to find the DJI by starting 
-                    // address, rather than just by MethodDesc. In the case of generics, we may need to create a DJI, so we 
+                    // In the EnC case, if we look for an older version, we need to find the DJI by starting
+                    // address, rather than just by MethodDesc. In the case of generics, we may need to create a DJI, so we
                     pDJI = pDMI->FindOrCreateInitAndAddJitInfo(pEvent->SetIP.vmMethodDesc.GetRawPtr(),
                                                                PINSTRToPCODE((TADDR)pEvent->SetIP.startAddress));
                 }
@@ -11194,7 +11237,7 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent)
                 {
                     CHECK_IF_CAN_TAKE_HELPER_LOCKS_IN_THIS_SCOPE(&(pIPCResult->hr), GetCanary());
 
-                    if (SUCCEEDED(pIPCResult->hr))                    
+                    if (SUCCEEDED(pIPCResult->hr))
                     {
                         pIPCResult->hr = SetIP(pEvent->SetIP.fCanSetIPOnly,
                                           pThread,
@@ -11229,7 +11272,7 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent)
         // Note that we'd like to be able to do this assert here
         //      _ASSERTE(DebuggerController::GetNumberOfPatches() == 0);
         // However controllers may get queued for deletion if there is outstanding
-        // work and so we can't gaurentee the deletion will complete now.  
+        // work and so we can't gaurentee the deletion will complete now.
         // @dbgtodo  inspection: This shouldn't be an issue in the complete V3 architecture
 
         MarkDebuggerUnattachedInternal();
@@ -11412,7 +11455,7 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent)
                      pEvent->CreateHandleResult.vmObjectHandle.SetRawPtr(objectHandle);
                  }
              }
-             
+
              m_pRCThread->SendIPCReply();
              break;
         }
@@ -11486,7 +11529,7 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent)
 
     case DB_IPCE_CONTROL_C_EVENT_RESULT:
         {
-            // store the result of whether the event has been handled by the debugger and 
+            // store the result of whether the event has been handled by the debugger and
             // wake up the thread waiting for the result
             SetDebuggerHandlingCtrlC(pEvent->hr == S_OK);
             VERIFY(SetEvent(GetCtrlCMutex()));
@@ -11626,7 +11669,7 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent)
 
             Module * pModule = pEvent->MetadataUpdateRequest.vmModule.GetRawPtr();
             LOG((LF_CORDB, LL_INFO100000, "D::HIPCE Got module 0x%x\n", pModule));
-            
+
             DWORD countBytes = 0;
 
             // This will allocate memory. Debugger will then copy from here and send a
@@ -11636,7 +11679,7 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent)
             {
                 LOG((LF_CORDB, LL_INFO100000, "D::HIPCE Calling SerializeModuleMetaData\n"));
                 pData = SerializeModuleMetaData(pModule, &countBytes);
-                
+
             }
             EX_CATCH_HRESULT(hr);
 
@@ -11644,12 +11687,12 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent)
 
             DebuggerIPCEvent * pResult = m_pRCThread->GetIPCEventReceiveBuffer();
             InitIPCEvent(pResult, DB_IPCE_RESOLVE_UPDATE_METADATA_1_RESULT, NULL, NULL);
-            
+
             pResult->MetadataUpdateRequest.pMetadataStart = pData;
             pResult->MetadataUpdateRequest.nMetadataSize = countBytes;
             pResult->hr = hr;
             LOG((LF_CORDB, LL_INFO1000000, "D::HIPCE metadataStart=0x%x, nMetadataSize=0x%x\n", pData, countBytes));
-            
+
             m_pRCThread->SendIPCReply();
             LOG((LF_CORDB, LL_INFO1000000, "D::HIPCE reply sent\n"));
         }
@@ -11739,18 +11782,18 @@ HRESULT Debugger::GetAndSendInterceptCommand(DebuggerIPCEvent *event)
             {
                 //
                 // If the target frame is below the point where the current exception was
-                // thrown from, then we should reject this interception command.  This 
+                // thrown from, then we should reject this interception command.  This
                 // can happen in a func-eval during an exception callback, or during a
                 // breakpoint in a filter function.  Or it can just be a user error.
                 //
                 CONTEXT* pContext = pExState->GetContextRecord();
 
-                // This is an approximation on IA64, where we should use the caller SP instead of 
-                // the current SP.  However, if the targetFramePointer is valid, the comparison should 
-                // still work.  targetFramePointer should be valid because it ultimately comes from a 
+                // This is an approximation on IA64, where we should use the caller SP instead of
+                // the current SP.  However, if the targetFramePointer is valid, the comparison should
+                // still work.  targetFramePointer should be valid because it ultimately comes from a
                 // full stackwalk.
                 FramePointer excepFramePointer = FramePointer::MakeFramePointer(GetSP(pContext));
-                
+
                 if (IsCloserToRoot(excepFramePointer, targetFramePointer))
                 {
                     hr = CORDBG_E_CURRENT_EXCEPTION_IS_OUTSIDE_CURRENT_EXECUTION_SCOPE;
@@ -11767,7 +11810,7 @@ HRESULT Debugger::GetAndSendInterceptCommand(DebuggerIPCEvent *event)
                 //
                 if (pExState->GetContextRecord() != NULL)
                 {
-                    // If the faulting instruction is not in managed code, then the interception frame 
+                    // If the faulting instruction is not in managed code, then the interception frame
                     // must be non-leaf.
                     if (!g_pEEInterface->IsManagedNativeCode((BYTE *)(GetIP(pExState->GetContextRecord()))))
                     {
@@ -11802,7 +11845,7 @@ HRESULT Debugger::GetAndSendInterceptCommand(DebuggerIPCEvent *event)
 #if defined(WIN64EXCEPTIONS)
                     int funcletIndex = PARENT_METHOD_INDEX;
 
-                    // For funclets, we need to make sure that the stack empty sequence point we use is 
+                    // For funclets, we need to make sure that the stack empty sequence point we use is
                     // in the same funclet as the current offset.
                     if (csi.m_activeFrame.IsFuncletFrame())
                     {
@@ -12073,10 +12116,10 @@ void Debugger::TypeHandleToBasicTypeInfo(AppDomain *pAppDomain, TypeHandle th, D
     case ELEMENT_TYPE_CLASS:
     case ELEMENT_TYPE_VALUETYPE:
         {
-            res->vmTypeHandle = th.HasInstantiation() ? WrapTypeHandle(th) : VMPTR_TypeHandle::NullPtr(); 
+            res->vmTypeHandle = th.HasInstantiation() ? WrapTypeHandle(th) : VMPTR_TypeHandle::NullPtr();
                                                                              // only set if instantiated
             res->metadataToken = th.GetCl();
-            DebuggerModule * pDModule = LookupOrCreateModule(th.GetModule(), pAppDomain);            
+            DebuggerModule * pDModule = LookupOrCreateModule(th.GetModule(), pAppDomain);
             res->vmDomainFile.SetRawPtr((pDModule ? pDModule->GetDomainFile() : NULL));
             break;
         }
@@ -12127,8 +12170,8 @@ void Debugger::TypeHandleToExpandedTypeInfo(AreValueTypesBoxed boxed,
     case ELEMENT_TYPE_SZARRAY:
         _ASSERTE(th.IsArray());
         res->ArrayTypeData.arrayRank = th.AsArray()->GetRank();
-        TypeHandleToBasicTypeInfo(pAppDomain, 
-                                  th.AsArray()->GetArrayElementTypeHandle(), 
+        TypeHandleToBasicTypeInfo(pAppDomain,
+                                  th.AsArray()->GetArrayElementTypeHandle(),
                                   &(res->ArrayTypeData.arrayTypeArg));
         break;
 
@@ -12140,8 +12183,8 @@ void Debugger::TypeHandleToExpandedTypeInfo(AreValueTypesBoxed boxed,
             goto treatAllValuesAsBoxed;
         }
         _ASSERTE(th.IsTypeDesc());
-        TypeHandleToBasicTypeInfo(pAppDomain, 
-                                  th.AsTypeDesc()->GetTypeParam(), 
+        TypeHandleToBasicTypeInfo(pAppDomain,
+                                  th.AsTypeDesc()->GetTypeParam(),
                                   &(res->UnaryTypeData.unaryTypeArg));
         break;
 
@@ -12230,7 +12273,7 @@ HRESULT Debugger::BasicTypeInfoToTypeHandle(DebuggerIPCE_BasicTypeData *data, Ty
             }
             break;
         }
-    
+
     case ELEMENT_TYPE_FNPTR:
         {
             _ASSERTE(!data->vmTypeHandle.IsNull());
@@ -12323,7 +12366,7 @@ TypeHandle Debugger::TypeDataWalk::ReadTypeHandle()
             th = ReadInstantiation(pDebuggerModule->GetRuntimeModule(), data->data.ClassTypeData.metadataToken, data->numTypeArgs);
             break;
         }
-    
+
     case ELEMENT_TYPE_FNPTR:
         {
             SIZE_T cbAllocSize;
@@ -12439,7 +12482,7 @@ HRESULT Debugger::AllocateRemoteBuffer( ULONG bufSize, void **ppBuffer )
     if (pBuffer == NULL)
             {
         return E_OUTOFMEMORY;
-        }            
+        }
 
     // Track the allocation so we can free it later
     void **ppNextBlob = GetMemBlobs()->Append();
@@ -12522,7 +12565,7 @@ HRESULT Debugger::ReleaseRemoteBuffer(void *pBuffer, bool removeFromBlobList)
         }
 
         // We should have found a match.  All buffers passed to ReleaseRemoteBuffer
-        // should have been allocated with AllocateRemoteBuffer and not yet freed. 
+        // should have been allocated with AllocateRemoteBuffer and not yet freed.
         _ASSERTE( i < cBlobs );
     }
 
@@ -12799,7 +12842,7 @@ void Debugger::GetVarInfo(MethodDesc *       fd,   // [IN] method of interest
 
 //---------------------------------------------------------------------------------------
 //
-// Apply an EnC edit to the CLR datastructures and send the result event to the 
+// Apply an EnC edit to the CLR datastructures and send the result event to the
 // debugger right-side.
 //
 // Arguments:
@@ -12816,7 +12859,7 @@ void Debugger::GetVarInfo(MethodDesc *       fd,   // [IN] method of interest
 // Notes:
 //
 // This is just the first half of processing an EnC request (hot swapping).  This updates
-// the metadata and other CLR data structures to reflect the edit, but does not directly 
+// the metadata and other CLR data structures to reflect the edit, but does not directly
 // affect code which is currently running.  In order to achieve on-stack replacement
 // (remap of running code), we mine all old methods with "EnC remap breakpoints"
 // (instances of DebuggerEnCBreakpoint) at many sequence points.  When one of those
@@ -12905,7 +12948,7 @@ private:
 // is a valid Remap Breakpoint location (not in a special offset, must be empty stack, and not in a handler.
 //
 EnCSequencePointHelper::EnCSequencePointHelper(DebuggerJitInfo *pJitInfo)
-    : m_pOffsetToHandlerInfo(NULL), 
+    : m_pOffsetToHandlerInfo(NULL),
       m_pJitInfo(pJitInfo)
 {
     CONTRACTL
@@ -12925,9 +12968,9 @@ EnCSequencePointHelper::EnCSequencePointHelper(DebuggerJitInfo *pJitInfo)
     for (unsigned int i = 0; i < m_pJitInfo->GetSequenceMapCount(); i++)
     {
         // By default this slot is unused.  We want the indexes in m_pOffsetToHandlerInfo
-        // to correspond to the indexes of m_pJitInfo->GetSequenceMapCount, so we rely 
+        // to correspond to the indexes of m_pJitInfo->GetSequenceMapCount, so we rely
         // on a -1 offset to indicate that a DebuggerOffsetToHandlerInfo is unused.
-        // However, it would be cleaner and permit a simpler API to the EE if we just 
+        // However, it would be cleaner and permit a simpler API to the EE if we just
         // had an array mapping the offsets instead.
         m_pOffsetToHandlerInfo[i].offset = (SIZE_T) -1;
         m_pOffsetToHandlerInfo[i].isInFilterOrHandler = FALSE;
@@ -12944,7 +12987,7 @@ EnCSequencePointHelper::EnCSequencePointHelper(DebuggerJitInfo *pJitInfo)
             continue;
         }
 
-        // Skip duplicate sequence points 
+        // Skip duplicate sequence points
         if (i >=1 && offset == pJitInfo->GetSequenceMap()[i-1].nativeStartOffset)
         {
             LOG((LF_ENC, LL_INFO10000,
@@ -12966,7 +13009,7 @@ EnCSequencePointHelper::EnCSequencePointHelper(DebuggerJitInfo *pJitInfo)
             continue;
         }
 
-        // So far this sequence point looks good, so store it's native offset so we can get 
+        // So far this sequence point looks good, so store it's native offset so we can get
         // EH information about it from the EE.
         LOG((LF_ENC, LL_INFO10000,
              "D::UF: possibly placing E&C breakpoint at offset "
@@ -13061,10 +13104,10 @@ HRESULT Debugger::UpdateFunction(MethodDesc* pMD, SIZE_T encVersion)
     Module *pModule = g_pEEInterface->MethodDescGetModule(pMD);
     _ASSERTE(pModule != NULL);
     mdToken methodDef = pMD->GetMemberDef();
-    SendEnCUpdateEvent(DB_IPCE_ENC_UPDATE_FUNCTION, 
-                       pModule, 
-                       methodDef, 
-                       pMD->GetMethodTable()->GetCl(), 
+    SendEnCUpdateEvent(DB_IPCE_ENC_UPDATE_FUNCTION,
+                       pModule,
+                       methodDef,
+                       pMD->GetMethodTable()->GetCl(),
                        encVersion);
 
     DebuggerMethodInfo *dmi = GetOrCreateMethodInfo(pModule, methodDef);
@@ -13129,8 +13172,8 @@ HRESULT Debugger::UpdateFunction(MethodDesc* pMD, SIZE_T encVersion)
         DebuggerEnCBreakpoint *bp;
 
         // Create and activate a new EnC remap breakpoint here in the old version of the method
-        bp = new (interopsafe) DebuggerEnCBreakpoint( offset, 
-                                                      pJitInfo, 
+        bp = new (interopsafe) DebuggerEnCBreakpoint( offset,
+                                                      pJitInfo,
                                                       DebuggerEnCBreakpoint::REMAP_PENDING,
                                                      (AppDomain *)pModule->GetDomain());
 
@@ -13185,8 +13228,8 @@ HRESULT Debugger::UpdateNotYetLoadedFunction(mdMethodDef token, Module * pModule
 }
 
 // Called to add a new function when the type has been loaded already.
-// This is effectively the same as above, except that we're given a 
-// MethodDesc instead of a module and token.  
+// This is effectively the same as above, except that we're given a
+// MethodDesc instead of a module and token.
 // This should probably be merged into a single method since the caller
 // should always have a module and token available in both cases.
 HRESULT Debugger::AddFunction(MethodDesc* pMD, SIZE_T encVersion)
@@ -13201,7 +13244,7 @@ HRESULT Debugger::AddFunction(MethodDesc* pMD, SIZE_T encVersion)
     }
     CONTRACTL_END;
 
-    DebuggerDataLockHolder debuggerDataLockHolder(this);    
+    DebuggerDataLockHolder debuggerDataLockHolder(this);
 
     LOG((LF_CORDB, LL_INFO10000, "D::AF: adding "
          "%s::%s to version %d\n", pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName, encVersion));
@@ -13212,10 +13255,10 @@ HRESULT Debugger::AddFunction(MethodDesc* pMD, SIZE_T encVersion)
     mdToken methodDef = pMD->GetMemberDef();
 
     // tell the RS that this function has been added so that it can create new CorDBFunction
-    SendEnCUpdateEvent( DB_IPCE_ENC_ADD_FUNCTION, 
-                        pModule, 
-                        methodDef, 
-                        pMD->GetMethodTable()->GetCl(), 
+    SendEnCUpdateEvent( DB_IPCE_ENC_ADD_FUNCTION,
+                        pModule,
+                        methodDef,
+                        pMD->GetMethodTable()->GetCl(),
                         encVersion);
 
     DebuggerMethodInfo *dmi = CreateMethodInfo(pModule, methodDef);
@@ -13242,10 +13285,10 @@ HRESULT Debugger::AddField(FieldDesc* pFD, SIZE_T encVersion)
          "%8.8d::%8.8d to version %d\n", pFD->GetApproxEnclosingMethodTable()->GetCl(), pFD->GetMemberDef(), encVersion));
 
     // tell the RS that this field has been added so that it can update it's structures
-    SendEnCUpdateEvent( DB_IPCE_ENC_ADD_FIELD, 
-                        pFD->GetModule(), 
-                        pFD->GetMemberDef(), 
-                        pFD->GetApproxEnclosingMethodTable()->GetCl(), 
+    SendEnCUpdateEvent( DB_IPCE_ENC_ADD_FIELD,
+                        pFD->GetModule(),
+                        pFD->GetMemberDef(),
+                        pFD->GetApproxEnclosingMethodTable()->GetCl(),
                         encVersion);
 
     return S_OK;
@@ -13292,14 +13335,14 @@ HRESULT Debugger::RemapComplete(MethodDesc* pMD, TADDR addr, SIZE_T nativeOffset
         return E_OUTOFMEMORY;
     }
     _ASSERTE(pJitInfo->m_addrOfCode + nativeOffset == addr);
-    
+
     DebuggerEnCBreakpoint *bp;
 
     // Create and activate a new REMAP_COMPLETE EnC breakpoint to let us know when
     // the EE has completed the remap process.
     // This will be deleted when the patch is hit.
-    bp = new (interopsafe, nothrow) DebuggerEnCBreakpoint( nativeOffset, 
-                                                           pJitInfo, 
+    bp = new (interopsafe, nothrow) DebuggerEnCBreakpoint( nativeOffset,
+                                                           pJitInfo,
                                                            DebuggerEnCBreakpoint::REMAP_COMPLETE,
                                        (AppDomain *)pMD->GetModule()->GetDomain());
     if (bp == NULL)
@@ -13313,7 +13356,7 @@ HRESULT Debugger::RemapComplete(MethodDesc* pMD, TADDR addr, SIZE_T nativeOffset
 //-----------------------------------------------------------------------------
 // Called by EnC stuff to map an IL offset to a native offset for the given
 // method described by (pMD, nativeFnxStart).
-// 
+//
 // pMD - methoddesc for method being remapped
 // ilOffset - incoming offset in old method to remap.
 // nativeFnxStart - address of new function. This can be used to find the DJI
@@ -13346,7 +13389,7 @@ HRESULT Debugger::MapILInfoToCurrentNative(MethodDesc *pMD,
     *nativeOffset = 0;
     DebuggerJitInfo *djiTo = GetJitInfo( pMD, (const BYTE *)nativeFnxStart);
     if (djiTo == NULL)
-    {        
+    {
         _ASSERTE(!"No DJI in EnC case: should only happen on oom. Debugger doesn't support OOM.");
         return E_FAIL;
     }
@@ -13364,7 +13407,7 @@ HRESULT Debugger::MapILInfoToCurrentNative(MethodDesc *pMD,
 //
 // Arguments:
 //     pContext - context from which we were hijacked. Always non-null.
-//     pRecord - exception record if hijacked from an exception event. 
+//     pRecord - exception record if hijacked from an exception event.
 //              Else null (if hijacked from a managed IP).
 //     reason - hijack reason. Use this to delegate to the proper hijack stub.
 //     pData   - arbitrary data for the hijack to use. (eg, such as a DebuggerEval object)
@@ -13374,14 +13417,14 @@ HRESULT Debugger::MapILInfoToCurrentNative(MethodDesc *pMD,
 //
 // Assumptions:
 //     If hijacked at an exception event, the debugger must have cleared the exception.
-//     
+//
 // Notes:
 //     The debugger hijacked the thread to get us here via the DacDbi Hijack primitive.
 //     This is called from a hand coded asm stub.
 //
 void STDCALL ExceptionHijackWorker(
-    CONTEXT * pContext, 
-    EXCEPTION_RECORD * pRecord, 
+    CONTEXT * pContext,
+    EXCEPTION_RECORD * pRecord,
     EHijackReason::EHijackReason reason,
     void * pData)
 {
@@ -13392,12 +13435,12 @@ void STDCALL ExceptionHijackWorker(
     {
         case EHijackReason::kUnhandledException:
             STRESS_LOG0(LF_CORDB,LL_INFO10, "D::EHW: Calling g_pDebugger->UnhandledHijackWorker()\n");
-            _ASSERTE(pData == NULL); 
+            _ASSERTE(pData == NULL);
             g_pDebugger->UnhandledHijackWorker(pContext, pRecord);
             break;
 #ifdef FEATURE_INTEROP_DEBUGGING
     case EHijackReason::kM2UHandoff:
-            _ASSERTE(pData == NULL); 
+            _ASSERTE(pData == NULL);
             g_pDebugger->M2UHandoffHijackWorker(pContext, pRecord);
             break;
     case EHijackReason::kFirstChanceSuspend:
@@ -13416,8 +13459,8 @@ void STDCALL ExceptionHijackWorker(
     // Currently, no Hijack actually returns yet.
     UNREACHABLE();
 
-    // If we return to this point, then we'll restore ourselves.    
-    // We've got the context that we were hijacked from, so we should be able to just 
+    // If we return to this point, then we'll restore ourselves.
+    // We've got the context that we were hijacked from, so we should be able to just
     // call SetThreadContext on ourself to fix us.
 }
 
@@ -13427,8 +13470,8 @@ void STDCALL ExceptionHijackWorker(
 // ----------------------------------------------------------------------------
 // EmptyPersonalityRoutine
 //
-// Description: 
-//    This personality routine is used to work around a limitation of the OS unwinder when we return 
+// Description:
+//    This personality routine is used to work around a limitation of the OS unwinder when we return
 //    ExceptionCollidedUnwind.
 //    See code:ExceptionHijackPersonalityRoutine for more information.
 //
@@ -13465,24 +13508,24 @@ EXCEPTION_DISPOSITION EmptyPersonalityRoutine(IN     PEXCEPTION_RECORD   pExcept
 //
 // Notes:
 //    We just need 1 personality routine for the tiny assembly hijack stub.
-//    All the C++ code invoked by the stub is ok. 
+//    All the C++ code invoked by the stub is ok.
 //
-//    This needs to fetch the original context that this thread was hijacked from 
+//    This needs to fetch the original context that this thread was hijacked from
 //    (which the hijack pushed onto the stack) and pass that back to the OS. This lets
 //    ths OS unwind out of the hijack.
-//    
+//
 //    This function should only be executed if an unhandled exception is intercepted by a managed debugger.
 //    Otherwise there should never be a 2nd pass exception dispatch crossing the hijack stub.
-//    
+//
 //    The basic idea here is straightforward.  The OS does an exception dispatch and hit our hijack stub.
 //    Since the hijack stub is not unwindable, we need a personality routine to restore the CONTEXT and
 //    tell the OS to continue the dispatch with that CONTEXT by returning ExceptionCollidedUnwind.
-//    
-//    However, empricially, the OS expects that when we return ExceptionCollidedUnwind, the function 
-//    represented by the CONTEXT has a personality routine.  The OS will actually AV if we return a NULL 
-//    personality routine.  
-//    
-//    On AMD64, we work around this by using an empty personality routine. 
+//
+//    However, empricially, the OS expects that when we return ExceptionCollidedUnwind, the function
+//    represented by the CONTEXT has a personality routine.  The OS will actually AV if we return a NULL
+//    personality routine.
+//
+//    On AMD64, we work around this by using an empty personality routine.
 
 EXTERN_C EXCEPTION_DISPOSITION
 ExceptionHijackPersonalityRoutine(IN     PEXCEPTION_RECORD   pExceptionRecord
@@ -13507,7 +13550,7 @@ ExceptionHijackPersonalityRoutine(IN     PEXCEPTION_RECORD   pExceptionRecord
     // DacDbiInterfaceImpl::Hijack. This works because ExceptionHijack
     // allocates exactly 4 stack slots.
     pHijackContext = *reinterpret_cast<CONTEXT **>(pDispatcherContext->EstablisherFrame + 0x20);
-    
+
     // This copies pHijackContext into pDispatcherContext, which the OS can then
     // use to walk the stack.
     FixupDispatcherContext(pDispatcherContext, pHijackContext, pContextRecord, (PEXCEPTION_ROUTINE)EmptyPersonalityRoutine);
@@ -13534,21 +13577,21 @@ LONG InternalUnhandledExceptionFilter_Worker(EXCEPTION_POINTERS *pExceptionInfo)
 //     pRecord - exception record of the exception that this was hijacked at.
 //     pData - random data.
 // Notes:
-// When under a native-debugger, the OS does not invoking the Unhandled Exception Filter (UEF). 
+// When under a native-debugger, the OS does not invoking the Unhandled Exception Filter (UEF).
 // It dispatches a 2nd-chance Exception event instead.
 // However, the CLR's UEF does lots of useful work (like dispatching the 2nd-chance managed exception,
-// allowing func-eval on 2nd-chance, and allowing intercepting unhandled exceptions). 
+// allowing func-eval on 2nd-chance, and allowing intercepting unhandled exceptions).
 // So we'll emulate the OS behavior here by invoking the CLR's UEF directly.
 //
 void Debugger::UnhandledHijackWorker(CONTEXT * pContext, EXCEPTION_RECORD * pRecord)
-{   
+{
     CONTRACTL
     {
         // The ultimate protection shield is that this hijack can be executed under the same circumstances
         // as a top-level UEF that pinvokes into managed code
         // - That means we're GC-triggers safe
         // - that means that we can crawl the stack. (1st-pass EH logic ensures this).
-        // We need to be GC-triggers because this may invoke a func-eval. 
+        // We need to be GC-triggers because this may invoke a func-eval.
         GC_TRIGGERS;
 
         // Don't throw out of a hijack! There's nobody left to catch this.
@@ -13557,7 +13600,7 @@ void Debugger::UnhandledHijackWorker(CONTEXT * pContext, EXCEPTION_RECORD * pRec
         // We expect to always be in preemptive here by the time we get this unhandled notification.
         // We know this is true because a native UEF is preemptive.
         // More detail:
-        //   1) If we got here from a software exception (eg, Throw from C#), then the jit helper 
+        //   1) If we got here from a software exception (eg, Throw from C#), then the jit helper
         //       toggled us to preemptive before calling RaiseException().
         //   2) If we got here from a hardware exception in managed code, then the 1st-pass already did
         //       some magic to get us into preemptive. On x86, this is magic. On 64-bit, it did some magic
@@ -13581,7 +13624,7 @@ void Debugger::UnhandledHijackWorker(CONTEXT * pContext, EXCEPTION_RECORD * pRec
 
     BOOL fSOException = FALSE;
 
-    if ((pRecord != NULL) && 
+    if ((pRecord != NULL) &&
         (pRecord->ExceptionCode == STATUS_STACK_OVERFLOW))
     {
         fSOException = TRUE;
@@ -13594,10 +13637,10 @@ void Debugger::UnhandledHijackWorker(CONTEXT * pContext, EXCEPTION_RECORD * pRec
     PostJitAttach();
 
     // On Win7 WatsonLastChance returns CONTINUE_SEARCH for unhandled exceptions execpt stack overflow, and
-    // lets OS launch debuggers for us.  Before the unhandled exception reaches the OS, CLR UEF has already 
+    // lets OS launch debuggers for us.  Before the unhandled exception reaches the OS, CLR UEF has already
     // processed this unhandled exception.  Thus, we should not call into CLR UEF again if it is the case.
-    if (pThread && 
-        (pThread->HasThreadStateNC(Thread::TSNC_ProcessedUnhandledException) || 
+    if (pThread &&
+        (pThread->HasThreadStateNC(Thread::TSNC_ProcessedUnhandledException) ||
          pThread->HasThreadStateNC(Thread::TSNC_AppDomainContainUnhandled) ||
          fSOException))
     {
@@ -13614,15 +13657,15 @@ void Debugger::UnhandledHijackWorker(CONTEXT * pContext, EXCEPTION_RECORD * pRec
             // exception.  Our hijack code runs in the exception context, and overwrites the stack space
             // after SO excpetion, so this frame was popped out before invoking RaiseFailFast.  We need to
             // put it back here for running func-eval code.
-            // This cumbersome code should be removed once SO synchronization is moved to be completely 
-            // out-of-process. 
+            // This cumbersome code should be removed once SO synchronization is moved to be completely
+            // out-of-process.
             fef.InitAndLink(pContext);
         }
 
         STRESS_LOG0(LF_CORDB, LL_INFO10, "D::EHW: Calling NotifyDebuggerLastChance\n");
         NotifyDebuggerLastChance(pThread, &exceptionInfo, TRUE);
 
-        // Continuing from a second chance managed exception causes the process to exit.    
+        // Continuing from a second chance managed exception causes the process to exit.
         TerminateProcess(GetCurrentProcess(), 0);
     }
 
@@ -13640,8 +13683,8 @@ void Debugger::UnhandledHijackWorker(CONTEXT * pContext, EXCEPTION_RECORD * pRec
 
     // If intercepted, then this never returns. It will manually invoke the unwinders and fix the context.
 
-    // InternalUnhandledExceptionFilter_Worker has a throws contract, but should not be throwing in any 
-    // conditions we care about. This hijack should never throw, so catch everything.  
+    // InternalUnhandledExceptionFilter_Worker has a throws contract, but should not be throwing in any
+    // conditions we care about. This hijack should never throw, so catch everything.
     HRESULT hrIgnore;
     EX_TRY
     {
@@ -13649,7 +13692,7 @@ void Debugger::UnhandledHijackWorker(CONTEXT * pContext, EXCEPTION_RECORD * pRec
     }
     EX_CATCH_HRESULT(hrIgnore);
 
-    // Continuing from a second chance managed exception causes the process to exit.    
+    // Continuing from a second chance managed exception causes the process to exit.
     TerminateProcess(GetCurrentProcess(), 0);
 }
 
@@ -13692,7 +13735,7 @@ VOID Debugger::M2UHandoffHijackWorker(CONTEXT *pContext,
     SO_NOT_MAINLINE_FUNCTION;
 
 
-    LOG((LF_CORDB, LL_INFO1000, "D::M2UHHW: Context=0x%p exception record=0x%p\n", 
+    LOG((LF_CORDB, LL_INFO1000, "D::M2UHHW: Context=0x%p exception record=0x%p\n",
         pContext, pExceptionRecord));
 
     // We should only be here for a BP
@@ -13747,7 +13790,7 @@ VOID Debugger::M2UHandoffHijackWorker(CONTEXT *pContext,
 }
 
 //-----------------------------------------------------------------------------
-// This hijack is run after receiving an IB event that we don't know how the 
+// This hijack is run after receiving an IB event that we don't know how the
 // debugger will want to continue. Under the covers we clear the event and divert
 // execution here where we block until the debugger decides whether or not to clear
 // the event. At that point we exit this hijack and the LS diverts execution back
@@ -13798,7 +13841,7 @@ LONG Debugger::FirstChanceSuspendHijackWorker(CONTEXT *pContext,
 #endif
 
     // This memory is used as IPC during the hijack. We will place a pointer to this in
-    // the EE debugger word (a TLS slot that works even on the debugger break-in thread) 
+    // the EE debugger word (a TLS slot that works even on the debugger break-in thread)
     // and then the RS can write info into the memory.
     DebuggerIPCFirstChanceData fcd;
 
@@ -13830,7 +13873,7 @@ LONG Debugger::FirstChanceSuspendHijackWorker(CONTEXT *pContext,
         SPEW(fprintf(stderr, "0x%x D::FCHF: Signaling hijack started.\n", tid));
         SignalHijackStarted();
         SPEW(fprintf(stderr, "0x%x D::FCHF: Signaling hijack started complete. DebugCounter=0x%x\n", tid, pFcd->debugCounter));
-        
+
         if (pFcd->action == HIJACK_ACTION_WAIT)
         {
             // This exception does NOT belong to the CLR.
@@ -13902,7 +13945,7 @@ LONG Debugger::FirstChanceSuspendHijackWorker(CONTEXT *pContext,
         _ASSERTE(pFcd->action == HIJACK_ACTION_EXIT_UNHANDLED);
         return EXCEPTION_CONTINUE_SEARCH;
     }
-} 
+}
 
 #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_)
 void GenericHijackFuncHelper()
@@ -14469,8 +14512,8 @@ void Debugger::SendMDANotification(
             // - S_OK if we do a jit-attach,
             // - S_FALSE if a debugger is already attached.
             // - Error in other cases..
-            
-            JitAttach(pThread, NULL, TRUE, FALSE); 
+
+            JitAttach(pThread, NULL, TRUE, FALSE);
         }
 
         // Debugger may be attached now...
@@ -14531,9 +14574,9 @@ void Debugger::SendLogMessage(int iLevel,
 
     // Send Log message event to the Right Side
     SendRawLogMessage(
-        pThread, 
-        pAppDomain, 
-        iLevel, 
+        pThread,
+        pAppDomain,
+        iLevel,
         pSwitchName,
         pMessage);
 
@@ -14556,7 +14599,7 @@ void Debugger::SendRawLogMessage(
     AppDomain                                 *pAppDomain,
     int                                        iLevel,
     SString *   pCategory,
-    SString *   pMessage 
+    SString *   pMessage
 )
 {
     DebuggerIPCEvent* ipce;
@@ -14654,7 +14697,7 @@ void Debugger::SendLogSwitchSetting(int iLevel,
 //     input: pThread    - thread on which the notification occurred
 //            pDomain    - domain file for the domain in which the notification occurred
 //            classToken - metadata token for the type of the notification object
-void Debugger::SendCustomDebuggerNotification(Thread * pThread, 
+void Debugger::SendCustomDebuggerNotification(Thread * pThread,
                                               DomainFile * pDomain,
                                               mdTypeDef classToken)
 {
@@ -14691,7 +14734,7 @@ void Debugger::SendCustomDebuggerNotification(Thread * pThread,
         ipce->CustomNotification.classToken = classToken;
         ipce->CustomNotification.vmDomainFile = vmDomainFile;
 
+
         m_pRCThread->SendIPCEvent();
 
         // Stop all Runtime threads
@@ -14804,7 +14847,7 @@ LErrExit:
         // UnLock the list
         m_pAppDomainCB->Unlock();
 
-        // Send event to debugger if one is attached.  
+        // Send event to debugger if one is attached.
         if (CORDebuggerAttached())
         {
             SendCreateAppDomainEvent(pAppDomain);
@@ -14816,7 +14859,7 @@ LErrExit:
 
 
 /******************************************************************************
- * Remove the AppDomain from the list stored in the IPC block and send an ExitAppDomain 
+ * Remove the AppDomain from the list stored in the IPC block and send an ExitAppDomain
  * event to the debugger if attached.
  ******************************************************************************/
 HRESULT Debugger::RemoveAppDomainFromIPC (AppDomain *pAppDomain)
@@ -15003,7 +15046,7 @@ HRESULT Debugger::IterateAppDomainsForPdbs()
                 CopyModulePdb(pDomainAssembly->GetModule());
             }
         }
-        
+
         // Get the next appdomain in the list
         pADInfo = m_pAppDomainCB->FindNext(pADInfo);
     }
@@ -15101,7 +15144,7 @@ HRESULT Debugger::InitAppDomainIPC(void)
     dwStrLen = WszGetModuleFileName(NULL,
                                     szExeName);
 
-    
+
     // If we couldn't get the name, then use a nice default.
     if (dwStrLen == 0)
     {
@@ -15194,7 +15237,7 @@ HRESULT Debugger::TerminateAppDomainIPC(void)
 
     // We're done. release and close the mutex.  Note that this must be done
     // after we clear it out above to ensure there is no race condition.
-    if( m != NULL ) 
+    if( m != NULL )
     {
         VERIFY(ReleaseMutex(m));
         m.Close();
@@ -15336,7 +15379,7 @@ HRESULT Debugger::FuncEvalSetup(DebuggerIPCE_FuncEvalInfo *pEvalInfo,
         //
         // To prevent GCs until the func-eval gets a chance to run, we increment the counter here.
         // We only need to do this if we have changed the filter CONTEXT, since the stack will be unwalkable
-        // in this case. 
+        // in this case.
         //
         g_pDebugger->IncThreadsAtUnsafePlaces();
     }
@@ -15465,7 +15508,7 @@ Debugger::FuncEvalAbort(
 
     DebuggerEval *pDE = (DebuggerEval*) debuggerEvalKey;
     HRESULT hr = S_OK;
-    CHECK_IF_CAN_TAKE_HELPER_LOCKS_IN_THIS_SCOPE(&hr, GetCanary());    
+    CHECK_IF_CAN_TAKE_HELPER_LOCKS_IN_THIS_SCOPE(&hr, GetCanary());
     if (FAILED(hr))
     {
         return hr;
@@ -15527,7 +15570,7 @@ Debugger::FuncEvalRudeAbort(
     CONTRACTL_END;
 
     HRESULT hr = S_OK;
-    CHECK_IF_CAN_TAKE_HELPER_LOCKS_IN_THIS_SCOPE(&hr, GetCanary());    
+    CHECK_IF_CAN_TAKE_HELPER_LOCKS_IN_THIS_SCOPE(&hr, GetCanary());
     if (FAILED(hr))
     {
         return hr;
@@ -15535,7 +15578,7 @@ Debugger::FuncEvalRudeAbort(
 
 
     DebuggerEval *pDE = debuggerEvalKey;
-    
+
 
     if (!(pDE->m_aborting & DebuggerEval::FE_ABORT_RUDE))
     {
@@ -15917,15 +15960,15 @@ void Debugger::DoHelperThreadDuty()
 
 // This function is called from the EE to notify the right side
 // whenever the name of a thread or AppDomain changes
-//   
+//
 // Notes:
 //   This just sends a ping event to notify that the name has been changed.
 //   It does not send the actual updated name. Instead, the debugger can query for the name.
-//   
+//
 //   For an AppDomain name change:
 //   - pAppDoamin != NULL
 //   - name retrieved via ICorDebugAppDomain::GetName
-//   
+//
 //   For a Thread name change:
 //   - pAppDomain == NULL, pThread != NULL
 //   - name retrieved via a func-eval of Thread::get_Name
@@ -15947,8 +15990,8 @@ HRESULT Debugger::NameChangeEvent(AppDomain *pAppDomain, Thread *pThread)
     if (g_pEEInterface->GetThread() == NULL)
         return S_OK;
 
-    // Skip if thread doesn't yet have native ID. 
-    // This can easily happen if an app sets Thread.Name before it calls Thread.Start. 
+    // Skip if thread doesn't yet have native ID.
+    // This can easily happen if an app sets Thread.Name before it calls Thread.Start.
     // Since this is just a ping-event, it's ignorable. The debugger can query the thread name at Thread.Start in this case.
     // This emulates whidbey semantics.
     if (pThread != NULL)
@@ -15982,7 +16025,7 @@ HRESULT Debugger::NameChangeEvent(AppDomain *pAppDomain, Thread *pThread)
         }
         else
         {
-            // Thread Name 
+            // Thread Name
             ipce->NameChange.eventType = THREAD_NAME_CHANGE;
             _ASSERTE (pThread);
             ipce->NameChange.vmThread.SetRawPtr(pThread);
@@ -16177,8 +16220,8 @@ BOOL Debugger::IsThreadContextInvalid(Thread *pThread)
         }
         EX_END_CATCH(SwallowAllExceptions);
 #else // _TARGET_X86_
-        // Non-x86 can detect whether the thread is suspended after an exception is hit but before 
-        // the kernel has dispatched the exception to user mode by trap frame reporting.  
+        // Non-x86 can detect whether the thread is suspended after an exception is hit but before
+        // the kernel has dispatched the exception to user mode by trap frame reporting.
         // See Thread::IsContextSafeToRedirect().
 #endif // _TARGET_X86_
     }
@@ -16454,15 +16497,15 @@ void Debugger::ReleaseDebuggerDataLock(Debugger *pDebugger)
 #else // DACCESS_COMPILE
 
 // determine whether the LS holds the data lock. If it does, we will assume the locked data is in an
-// inconsistent state and will throw an exception. The DAC will execute this if we are executing code 
-// that takes the lock. 
+// inconsistent state and will throw an exception. The DAC will execute this if we are executing code
+// that takes the lock.
 // Arguments: input: pDebugger - the LS debugger data structure
 /* static */
 void Debugger::AcquireDebuggerDataLock(Debugger *pDebugger)
 {
     SUPPORTS_DAC;
 
-    if (pDebugger->GetDebuggerDataLock()->GetEnterCount() != 0) 
+    if (pDebugger->GetDebuggerDataLock()->GetEnterCount() != 0)
     {
         ThrowHR(CORDBG_E_PROCESS_NOT_SYNCHRONIZED);
     }
@@ -16689,7 +16732,7 @@ HRESULT DebuggerHeap::Init(BOOL fExecutable)
     m_fExecutable = fExecutable;
 
 #ifdef USE_INTEROPSAFE_HEAP
-    // If already inited, then we're done. 
+    // If already inited, then we're done.
     // We normally don't double-init. However, we may oom between when we allocate the heap and when we do other initialization.
     // We don't worry about backout code to free the heap. Rather, we'll just leave it alive and nop if we try to allocate it again.
     if (IsInit())
@@ -16946,7 +16989,7 @@ int Debugger::MessageBox(
                   UINT uText,       // Resource Identifier for Text message
                   UINT uCaption,    // Resource Identifier for Caption
                   UINT uType,       // Style of MessageBox
-                  BOOL displayForNonInteractive,    // Display even if the process is running non interactive 
+                  BOOL displayForNonInteractive,    // Display even if the process is running non interactive
                   BOOL showFileNameInTitle,         // Flag to show FileName in Caption
                   ...)              // Additional Arguments
 {
@@ -17032,7 +17075,7 @@ void Debugger::StartCanaryThread()
 {
      // we need to already have the rcthread running and the pointer stored
     _ASSERTE(m_pRCThread != NULL && g_pRCThread == m_pRCThread);
-    _ASSERTE(m_pRCThread->GetDCB() != NULL); 
+    _ASSERTE(m_pRCThread->GetDCB() != NULL);
     _ASSERTE(GetCanary() != NULL);
 
     GetCanary()->Init();
index 0b1cbac..97f9832 100644 (file)
@@ -126,7 +126,7 @@ public:
     // Clear the holder.
     ~AtSafePlaceHolder();
 
-    // True if the holder is acquired. 
+    // True if the holder is acquired.
     bool IsAtUnsafePlace();
 
     // Clear the holder (call DecThreadsAtUnsafePlaces if needed)
@@ -148,12 +148,12 @@ public:
 };
 
 #ifndef DACCESS_COMPILE
-template<BOOL TOGGLE, BOOL IFTHREAD> 
+template<BOOL TOGGLE, BOOL IFTHREAD>
 class GCHolderEEInterface<TRUE, TOGGLE, IFTHREAD>
 {
 private:
     bool startInCoop;
-    
+
 public:
     DEBUG_NOINLINE GCHolderEEInterface()
     {
@@ -173,8 +173,8 @@ public:
             startInCoop = true;
         }
         else
-        {            
-            // we're starting in PREEMP, need to switch to COOP    
+        {
+            // we're starting in PREEMP, need to switch to COOP
             startInCoop = false;
             g_pEEInterface->DisablePreemptiveGC();
         }
@@ -193,7 +193,7 @@ public:
 
         if (TOGGLE)
         {
-            // We're in COOP, toggle to PREEMPTIVE and back to COOP 
+            // We're in COOP, toggle to PREEMPTIVE and back to COOP
             // for synch purposes.
             g_pEEInterface->EnablePreemptiveGC();
             g_pEEInterface->DisablePreemptiveGC();
@@ -206,7 +206,7 @@ public:
         }
         else
         {
-            // If we started in PREEMPTIVE switch back    
+            // If we started in PREEMPTIVE switch back
             if (!startInCoop)
             {
                 g_pEEInterface->EnablePreemptiveGC();
@@ -215,13 +215,13 @@ public:
     };
 };
 
-template<BOOL TOGGLE, BOOL IFTHREAD> 
+template<BOOL TOGGLE, BOOL IFTHREAD>
 class GCHolderEEInterface<FALSE, TOGGLE, IFTHREAD>
 {
 private:
     bool startInCoop;
     bool conditional;
-    
+
     void EnterInternal(bool bStartInCoop, bool bConditional)
     {
         startInCoop = bStartInCoop;
@@ -262,8 +262,8 @@ private:
             // If we started in PREEMPTIVE switch back to PREEMPTIVE
             if (!startInCoop)
             {
-                g_pEEInterface->EnablePreemptiveGC();            
-            }    
+                g_pEEInterface->EnablePreemptiveGC();
+            }
         }
         else
         {
@@ -307,7 +307,7 @@ public:
 
 #define GCX_COOP_EEINTERFACE()                                          \
     GCHolderEEInterface<TRUE, FALSE, FALSE> __gcCoop_onlyOneAllowedPerScope
-    
+
 #define GCX_PREEMP_EEINTERFACE()                                        \
     GCHolderEEInterface<FALSE, FALSE, FALSE> __gcCoop_onlyOneAllowedPerScope
 
@@ -474,8 +474,8 @@ CONTEXT * GetManagedLiveCtx(Thread * pThread);
 
 // Once a module / appdomain is unloaded, all Right-side objects (such as breakpoints)
 // in that appdomain will get neutered and will thus be prevented from accessing
-// the unloaded appdomain. 
-// 
+// the unloaded appdomain.
+//
 // @dbgtodo jmc - This is now purely relegated to the LS. Eventually completely get rid of this
 // by moving fields off to Module or getting rid of the fields completely.
 typedef DPTR(class DebuggerModule) PTR_DebuggerModule;
@@ -520,9 +520,9 @@ class DebuggerModule
     // workaround to facilitate the removal of DebuggerModule.
     // </TODO>
     DebuggerModule * GetPrimaryModule();
-    DomainFile * GetDomainFile() 
+    DomainFile * GetDomainFile()
     {
-        LIMITED_METHOD_DAC_CONTRACT; 
+        LIMITED_METHOD_DAC_CONTRACT;
         return m_pRuntimeDomainFile;
     }
 
@@ -609,7 +609,7 @@ class HelperThreadFavor
     HelperThreadFavor();
     // No dtor because we intentionally leak all shutdown.
     void Init();
-    
+
 protected:
     // Stuff for having the helper thread do function calls for a thread
     // that blew its stack
@@ -657,12 +657,12 @@ protected:
 
     DebuggerPendingFuncEvalTable *m_pPendingEvals;
 
-    // The "debugger data lock" is a very small leaf lock used to protect debugger internal data structures (such 
+    // The "debugger data lock" is a very small leaf lock used to protect debugger internal data structures (such
     // as DJIs, DMIs, module table). It is a GC-unsafe-anymode lock and so it can't trigger a GC while being held.
-    // It also can't issue any callbacks into the EE or anycode that it does not directly control. 
+    // It also can't issue any callbacks into the EE or anycode that it does not directly control.
     // This is a separate lock from the the larger Debugger-lock / Controller lock, which allows regions under those
-    // locks to access debugger datastructures w/o blocking each other. 
-    Crst                  m_DebuggerDataLock;    
+    // locks to access debugger datastructures w/o blocking each other.
+    Crst                  m_DebuggerDataLock;
     HANDLE                m_CtrlCMutex;
     HANDLE                m_exAttachEvent;
     HANDLE                m_exUnmanagedAttachEvent;
@@ -671,7 +671,7 @@ protected:
 
     // Used by MapAndBindFunctionBreakpoints.  Note that this is thread-safe
     // only b/c we access it from within the DebuggerController::Lock
-    SIZE_T_UNORDERED_ARRAY m_BPMappingDuplicates; 
+    SIZE_T_UNORDERED_ARRAY m_BPMappingDuplicates;
 
     UnorderedPtrArray     m_pMemBlobs;
 
@@ -813,7 +813,7 @@ public:
     void RightSideDetach(void);
 
     //
-    // 
+    //
     //
     void ThreadProc(void);
     static DWORD WINAPI ThreadProcStatic(LPVOID parameter);
@@ -857,9 +857,9 @@ private:
     FAVORCALLBACK GetFavorFnPtr()           { return m_favorData.m_fpFavor; }
     void * GetFavorData()                   { return m_favorData.m_pFavorData; }
 
-    void SetFavorFnPtr(FAVORCALLBACK fp, void * pData)    
-    { 
-        m_favorData.m_fpFavor = fp; 
+    void SetFavorFnPtr(FAVORCALLBACK fp, void * pData)
+    {
+        m_favorData.m_fpFavor = fp;
         m_favorData.m_pFavorData = pData;
     }
     Crst * GetFavorLock()                   { return &m_favorData.m_FavorLock; }
@@ -867,8 +867,8 @@ private:
     HANDLE GetFavorReadEvent()              { return m_favorData.m_FavorReadEvent; }
     HANDLE GetFavorAvailableEvent()         { return m_favorData.m_FavorAvailableEvent; }
 
-    HelperThreadFavor m_favorData;  
-    
+    HelperThreadFavor m_favorData;
+
 
     HelperCanary * GetCanary()              { return &GetLazyData()->m_Canary; }
 
@@ -1038,7 +1038,7 @@ public:
     bool HasInstrumentedILMap() {return m_fHasInstrumentedILMap; }
 
     // TranslateToInstIL will take offOrig, and translate it to the
-    // correct IL offset if this code happens to be instrumented 
+    // correct IL offset if this code happens to be instrumented
     ULONG32 TranslateToInstIL(const InstrumentedILOffsetMapping * pMapping, ULONG32 offOrig, bool fOrigToInst);
 
 
@@ -1135,7 +1135,7 @@ static_assert(sizeof(DebuggerHeapExecutableMemoryChunk) == 64, "DebuggerHeapExec
 // We allocate the size of DebuggerHeapExecutableMemoryPage each time we need
 // more memory and divide each page into DebuggerHeapExecutableMemoryChunks for
 // use. The pages are self describing; the first chunk contains information
-// about which of the other chunks are used/free as well as a pointer to 
+// about which of the other chunks are used/free as well as a pointer to
 // the next page.
 // ------------------------------------------------------------------------ */
 struct DECLSPEC_ALIGN(4096) DebuggerHeapExecutableMemoryPage
@@ -1185,7 +1185,7 @@ private:
 
 // ------------------------------------------------------------------------ */
 // DebuggerHeapExecutableMemoryAllocator class
-// Handles allocation and freeing (and all necessary bookkeeping) for 
+// Handles allocation and freeing (and all necessary bookkeeping) for
 // executable memory that the DebuggerHeap class needs. This is especially
 // useful on systems (like SELinux) where having executable code on the
 // heap is explicity disallowed for security reasons.
@@ -1272,8 +1272,8 @@ public:
         SUPPORTS_DAC;
     }
 
-    static CodeRegionInfo GetCodeRegionInfo(DebuggerJitInfo      * dji, 
-                                            MethodDesc           * md = NULL, 
+    static CodeRegionInfo GetCodeRegionInfo(DebuggerJitInfo      * dji,
+                                            MethodDesc           * md = NULL,
                                             PTR_CORDB_ADDRESS_TYPE addr = PTR_NULL);
 
     // Fills in the CodeRegoinInfo fields from the start address.
@@ -1418,7 +1418,7 @@ class DebuggerJitInfo
 public:
     PTR_MethodDesc           m_fd;
 
-    // Loader module is used to control life-time of DebufferJitInfo. Ideally, we would refactor the code to use LoaderAllocator here 
+    // Loader module is used to control life-time of DebufferJitInfo. Ideally, we would refactor the code to use LoaderAllocator here
     // instead because of it is what the VM actually uses to track the life time. It would make the debugger interface less chatty.
     PTR_Module               m_pLoaderModule;
 
@@ -1454,7 +1454,7 @@ protected:
     unsigned int             m_varNativeInfoCount;
 
     bool                     m_fAttemptInit;
-    
+
 #ifndef DACCESS_COMPILE
     void LazyInitBounds();
 #else
@@ -1478,15 +1478,15 @@ public:
         LazyInitBounds();
         return m_sequenceMap;
     }
-    
+
     unsigned int GetCallsiteMapCount()
     {
         SUPPORTS_DAC;
-        
+
         LazyInitBounds();
         return m_callsiteMapCount;
     }
-    
+
     PTR_DebuggerILToNativeMap GetCallSiteMap()
     {
         SUPPORTS_DAC;
@@ -1643,7 +1643,7 @@ public:
 };
 
 #if !defined(DACCESS_COMPILE)
-// @dbgtodo Microsoft inspection: get rid of this class when IPC events are eliminated. It's been copied to 
+// @dbgtodo Microsoft inspection: get rid of this class when IPC events are eliminated. It's been copied to
 // dacdbistructures
 /*
  * class MapSortIL:  A template class that will sort an array of DebuggerILToNativeMap.
@@ -1675,7 +1675,7 @@ class MapSortIL : public CQuickSort<DebuggerILToNativeMap>
                 DebuggerILToNativeMap *second)
     {
         LIMITED_METHOD_CONTRACT;
-        
+
         const DWORD call_inst = (DWORD)ICorDebugInfo::CALL_INSTRUCTION;
 
         //PROLOGs go first
@@ -1804,7 +1804,7 @@ public:
 #ifndef DACCESS_COMPILE
     Debugger();
     virtual ~Debugger();
-#else    
+#else
     virtual ~Debugger() {}
 #endif
 
@@ -1870,7 +1870,7 @@ public:
                 UINT uText,       // Resource Identifier for Text message
                 UINT uCaption,    // Resource Identifier for Caption
                 UINT uType,       // Style of MessageBox
-                BOOL displayForNonInteractive,      // Display even if the process is running non interactive 
+                BOOL displayForNonInteractive,      // Display even if the process is running non interactive
                 BOOL showFileNameInTitle,           // Flag to show FileName in Caption
                 ...);             // Additional Arguments
 
@@ -1896,7 +1896,7 @@ public:
                     DWORD dwModuleName,
                     Assembly *pAssembly,
                     AppDomain *pAppDomain,
-                    DomainFile * pDomainFile, 
+                    DomainFile * pDomainFile,
                     BOOL fAttaching);
     void LoadModuleFinished(Module* pRuntimeModule, AppDomain * pAppDomain);
     DebuggerModule * AddDebuggerModule(DomainFile * pDomainFile);
@@ -2031,10 +2031,10 @@ public:
 
     HRESULT GetILToNativeMappingIntoArrays(
         MethodDesc * pMethodDesc,
-        PCODE pCode, 
-        USHORT cMapMax, 
+        PCODE pCode,
+        USHORT cMapMax,
         USHORT * pcMap,
-        UINT ** prguiILOffset, 
+        UINT ** prguiILOffset,
         UINT ** prguiNativeOffset);
 
     PRD_TYPE GetPatchedOpcode(CORDB_ADDRESS_TYPE *ip);
@@ -2164,10 +2164,10 @@ public:
 
     void LockAndSendEnCRemapEvent(DebuggerJitInfo * dji, SIZE_T currentIP, SIZE_T *resumeIP);
     void LockAndSendEnCRemapCompleteEvent(MethodDesc *pFD);
-    void SendEnCUpdateEvent(DebuggerIPCEventType eventType, 
-                            Module * pModule, 
-                            mdToken memberToken, 
-                            mdTypeDef classToken, 
+    void SendEnCUpdateEvent(DebuggerIPCEventType eventType,
+                            Module * pModule,
+                            mdToken memberToken,
+                            mdTypeDef classToken,
                             SIZE_T enCVersion);
     void LockAndSendBreakpointSetError(PATCH_UNORDERED_ARRAY * listUnbindablePatches);
 
@@ -2176,7 +2176,7 @@ public:
         Thread * pThread,
         bool firstChance,
         bool fIsInterceptable,
-        bool continuable, 
+        bool continuable,
         SIZE_T currentIP,
         FramePointer framePointer,
         bool atSafePlace);
@@ -2200,7 +2200,7 @@ public:
     // Just send the actual event.
     void SendRawUserBreakpoint(Thread *thread);
 
-    
+
 
     void SendInterceptExceptionComplete(Thread *thread);
 
@@ -2383,11 +2383,11 @@ public:
 
 #ifdef FEATURE_INTEROP_DEBUGGING
     static VOID M2UHandoffHijackWorker(
-                             T_CONTEXT *pContext,                   
+                             T_CONTEXT *pContext,
                              EXCEPTION_RECORD *pExceptionRecord);
 
     LONG FirstChanceSuspendHijackWorker(
-                             T_CONTEXT *pContext,                   
+                             T_CONTEXT *pContext,
                              EXCEPTION_RECORD *pExceptionRecord);
     static void GenericHijackFunc(void);
     static void SecondChanceHijackFunc(void);
@@ -2472,9 +2472,9 @@ public:
                    BOOL fIsIL);
 
     // Helper routines used by Debugger::SetIP
-    
-    // If we have a varargs function, we can't set the IP (we don't know how to pack/unpack the arguments), so if we 
-    // call SetIP with fCanSetIPOnly = true, we need to check for that. 
+
+    // If we have a varargs function, we can't set the IP (we don't know how to pack/unpack the arguments), so if we
+    // call SetIP with fCanSetIPOnly = true, we need to check for that.
     BOOL IsVarArgsFunction(unsigned int nEntries, PTR_NativeVarInfo varNativeInfo);
 
     HRESULT ShuffleVariablesGet(DebuggerJitInfo  *dji,
@@ -2589,8 +2589,8 @@ public:
 
 #else // DACCESS_COMPILE
     // determine whether the LS holds the data lock. If it does, we will assume the locked data is in an
-    // inconsistent state and will throw an exception. The DAC will execute this if we are executing code 
-    // that takes the lock. 
+    // inconsistent state and will throw an exception. The DAC will execute this if we are executing code
+    // that takes the lock.
     static void AcquireDebuggerDataLock(Debugger *pDebugger);
 
     // unimplemented--nothing to do here
@@ -2643,8 +2643,8 @@ public:
 
 private:
     DebuggerJitInfo *GetJitInfoWorker(MethodDesc *fd, const BYTE *pbAddr, DebuggerMethodInfo **pMethInfo);
-    
-    // Save the necessary information for the debugger to recognize an IP in one of the thread redirection 
+
+    // Save the necessary information for the debugger to recognize an IP in one of the thread redirection
     // functions.
     void InitializeHijackFunctionAddress();
 
@@ -2827,10 +2827,10 @@ private:
 
 
     // This is the main debugger lock. It is a large lock and used to synchronize complex operations
-    // such as sending IPC events, debugger sycnhronization, and attach / detach. 
+    // such as sending IPC events, debugger sycnhronization, and attach / detach.
     // The debugger effectively can't make any radical state changes without holding this lock.
-    // 
-    //     
+    //
+    //
     Crst                  m_mutex; // The main debugger lock.
 
     // Flag to track if the debugger Crst needs to go into "Shutdown for Finalizer" mode.
@@ -2861,13 +2861,13 @@ private:
     LONG                  m_dClassLoadCallbackCount;
 
     // Lazily initialized array of debugger modules
-    // @dbgtodo module - eventually, DebuggerModule should go away, 
+    // @dbgtodo module - eventually, DebuggerModule should go away,
     // and all such information should be stored in either the VM's module class or in the RS.
     DebuggerModuleTable          *m_pModules;
-    
+
     // DacDbiInterfaceImpl needs to be able to write to private fields in the debugger class.
     friend class DacDbiInterfaceImpl;
-    
+
     // Set OOP by RS to request a sync after a debug event.
     // Clear by LS when we sync.
     Volatile<BOOL>  m_RSRequestedSync;
@@ -2905,20 +2905,20 @@ public:
     // There are currently three cases where we set this field to true:
     //
     // 1) NotifyOfCHFFilter()
-    //      - If the CHF filter is the first handler we encounter in the first pass, then there is no 
+    //      - If the CHF filter is the first handler we encounter in the first pass, then there is no
     //        managed stack frame at which we can intercept the exception anyway.
     //
     // 2) LastChanceManagedException()
     //      - If Watson is launched for an unhandled exception, then the exception cannot be intercepted.
     //
     // 3) SecondChanceHijackFuncWorker()
-    //      - The RS hijack the thread to this function to prevent the OS from killing the process at 
+    //      - The RS hijack the thread to this function to prevent the OS from killing the process at
     //        the end of the first pass.  (When a debugger is attached, the OS does not run a second pass.)
     //        This function ensures that the debugger gets a second chance notification.
     BOOL                          m_forceNonInterceptable;
 
-    // When we are doing an early attach, the RS shim should not queue all the fake attach events for 
-    // the process, the appdomain, and the thread.  Otherwise we'll get duplicate events when these 
+    // When we are doing an early attach, the RS shim should not queue all the fake attach events for
+    // the process, the appdomain, and the thread.  Otherwise we'll get duplicate events when these
     // entities are actually created.  This flag is used to mark whether we are doing an early attach.
     // There are still time windows where we can get duplicate events, but this flag closes down the
     // most common scenario.
@@ -2952,7 +2952,8 @@ public:
     DWORD m_defines;
     DWORD m_mdDataStructureVersion;
 #ifndef DACCESS_COMPILE
-    virtual void SomeWork();
+    virtual void BeforeGarbageCollection();
+    virtual void AfterGarbageCollection();
 #endif
 };
 
@@ -3042,7 +3043,7 @@ public:
         void *p;
 
         DebuggerHeap* pHeap = g_pDebugger->GetInteropSafeHeap_NoThrow();
-        _ASSERTE(pHeap != NULL); // should already exist 
+        _ASSERTE(pHeap != NULL); // should already exist
 
         PREFIX_ASSUME( iCurSize >= 0 );
         S_UINT32 iNewSize = S_UINT32( iCurSize ) + S_UINT32( GrowSize(iCurSize) );
@@ -3106,7 +3107,7 @@ class DebuggerPendingFuncEvalTable : private CHashTableAndData<CNewZeroData>
     }
 
     ULONG HASH(Thread* pThread)
-    { 
+    {
         LIMITED_METHOD_CONTRACT;
         return (ULONG)((SIZE_T)pThread);   // only use low 32-bits if 64-bit
     }
@@ -3188,7 +3189,7 @@ class DebuggerModuleTable : private CHashTableAndData<CNewZeroData>
 #endif // DACCESS_COMPILE
 
         Module * pModule1 = reinterpret_cast<Module *>(k1);
-        Module * pModule2 = 
+        Module * pModule2 =
             dac_cast<PTR_DebuggerModuleEntry>(const_cast<HASHENTRY *>(pc2))->module->GetRuntimeModule();
 
         return (pModule1 != pModule2);
@@ -3244,8 +3245,8 @@ public:
 // struct DebuggerMethodInfoKey:   Key for each of the method info hash table entries.
 // Module * m_pModule:  This and m_token make up the key
 // mdMethodDef m_token:  This and m_pModule make up the key
-// 
-// Note: This is used for hashing, so the structure must be totally blittable. 
+//
+// Note: This is used for hashing, so the structure must be totally blittable.
 typedef DPTR(struct DebuggerMethodInfoKey) PTR_DebuggerMethodInfoKey;
 struct DebuggerMethodInfoKey
 {
@@ -3339,7 +3340,7 @@ public:
     HRESULT AddMethodInfo(Module *pModule,
                        mdMethodDef token,
                        DebuggerMethodInfo *mi);
-                       
+
     HRESULT OverwriteMethodInfo(Module *pModule,
                              mdMethodDef token,
                              DebuggerMethodInfo *mi,
@@ -3352,7 +3353,7 @@ public:
     // (b) Perf: don't waste the memory!
     void ClearMethodsOfModule(Module *pModule);
     void DeleteEntryDMI(DebuggerMethodInfoEntry *entry);
-    
+
 #endif // #ifndef DACCESS_COMPILE
 
     DebuggerMethodInfo *GetMethodInfo(Module *pModule, mdMethodDef token);
@@ -3367,11 +3368,11 @@ public:
 class DebuggerEvalBreakpointInfoSegment
 {
 public:
-    // DebuggerEvalBreakpointInfoSegment contains just the breakpoint 
+    // DebuggerEvalBreakpointInfoSegment contains just the breakpoint
     // instruction and a pointer to the associated DebuggerEval. It makes
     // it easy to go from the instruction to the corresponding DebuggerEval
-    // object. It has been separated from the rest of the DebuggerEval 
-    // because it needs to be in a section of memory that's executable, 
+    // object. It has been separated from the rest of the DebuggerEval
+    // because it needs to be in a section of memory that's executable,
     // while the rest of DebuggerEval does not. By having it separate, we
     // don't need to have the DebuggerEval contents in executable memory.
     BYTE          m_breakpointInstruction[CORDbg_BREAK_INSTRUCTION_SIZE];
@@ -3509,7 +3510,7 @@ public:
         // Set flags to strategic values in case we access deleted memory.
         m_completed = false;
         m_rethrowAbortException = true;
-#endif        
+#endif
     }
 };
 
index 49bf156..7721115 100644 (file)
@@ -2,13 +2,13 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
-// 
+//
 // Events that go both ways
 IPC_EVENT_TYPE0(DB_IPCE_INVALID_EVENT                ,0x0000)
 IPC_EVENT_TYPE0(DB_IPCE_TYPE_MASK                    ,0x0FFF)
 
 // Some rules:
-// 1. Type0 is for marking sections in the id range. 
+// 1. Type0 is for marking sections in the id range.
 //    Type1 is for events that go L->R, Type2 is for events that go R<-L.
 // 2. All non-type 0 events should have a unique identifier & value
 // 3. All type 1 events values should be in range [DB_IPCE_RUNTIME_FIRST, DB_IPCE_RUNTIME_LAST)
@@ -16,7 +16,7 @@ IPC_EVENT_TYPE0(DB_IPCE_TYPE_MASK                    ,0x0FFF)
 // 4. All event values should be monotonically increasing, though we can skip values.
 // 5. All values should be a subset of the bits specified by DB_IPCE_TYPE_MASK.
 //
-// These rules are enforced by a bunch of compile time checks (C_ASSERT) in 
+// These rules are enforced by a bunch of compile time checks (C_ASSERT) in
 // the function DoCompileTimeCheckOnDbgIpcEventTypes.
 // If you get compiler errors in this file, you are probably violating the rules above.
 
@@ -43,7 +43,7 @@ IPC_EVENT_TYPE1(DB_IPCE_APPLY_CHANGES_RESULT         ,0x0118)
 IPC_EVENT_TYPE1(DB_IPCE_CUSTOM_NOTIFICATION          ,0x011B)
 IPC_EVENT_TYPE1(DB_IPCE_USER_BREAKPOINT              ,0x011C)
 IPC_EVENT_TYPE1(DB_IPCE_FIRST_LOG_MESSAGE            ,0x011D)
-// DB_IPCE_CONTINUED_LOG_MESSAGE = 0x11E, used to be here in v1.1, 
+// DB_IPCE_CONTINUED_LOG_MESSAGE = 0x11E, used to be here in v1.1,
 // But we've removed that remove the v2.0 protocol
 IPC_EVENT_TYPE1(DB_IPCE_LOGSWITCH_SET_MESSAGE        ,0x011F)
 IPC_EVENT_TYPE1(DB_IPCE_CREATE_APP_DOMAIN            ,0x0120)
@@ -91,8 +91,9 @@ IPC_EVENT_TYPE1(DB_IPCE_METADATA_UPDATE              ,0x015D)
 IPC_EVENT_TYPE1(DB_IPCE_RESOLVE_UPDATE_METADATA_1_RESULT,0x015E)
 IPC_EVENT_TYPE1(DB_IPCE_RESOLVE_UPDATE_METADATA_2_RESULT,0x015F)
 IPC_EVENT_TYPE1(DB_IPCE_DATA_BREAKPOINT              ,0x0160)
-IPC_EVENT_TYPE1(DB_IPCE_SOME_WORK                    , 0x0161)
-IPC_EVENT_TYPE0(DB_IPCE_RUNTIME_LAST                 ,0x0162)   // The last event from runtime
+IPC_EVENT_TYPE1(DB_IPCE_BEFORE_GARBAGE_COLLECTION    , 0x0161)
+IPC_EVENT_TYPE1(DB_IPCE_AFTER_GARBAGE_COLLECTION     , 0x0162)
+IPC_EVENT_TYPE0(DB_IPCE_RUNTIME_LAST                 ,0x0163)   // The last event from runtime
 
 
 
index cbe7788..69be972 100644 (file)
@@ -225,19 +225,19 @@ typedef struct CorDebugGuidToTypeMapping
 
 /*
  * Callback interface for providing access to a particular target process. The
- * debugging services will call functions on this interface to access memory 
- * and other data in the target process.  The debugger client must implement 
+ * debugging services will call functions on this interface to access memory
+ * and other data in the target process.  The debugger client must implement
  * this interface as appropriate for the particular target (for example, a live
  * process or a memory dump).  The DataTarget will only be invoked from within
- * the implementation of other ICorDebug APIs (i.e. the debugger client has 
- * control over which thread it is invoked on, and when) 
+ * the implementation of other ICorDebug APIs (i.e. the debugger client has
+ * control over which thread it is invoked on, and when)
  *
  * Error HRESULTS returned by DataTarget APIs will propagate up and be returned
  * by the active ICorDebug API call.
  *
  * The DataTarget implementation must always return up-to-date information
- * about the target.  The target process should be stopped (not changing 
- * in any way) while ICorDebug APIs (and hence DataTarget APIs) are being 
+ * about the target.  The target process should be stopped (not changing
+ * in any way) while ICorDebug APIs (and hence DataTarget APIs) are being
  * called.  If the target is a live process and it's state changes,
  * OpenVirtualProcess needs to be called again to provide a replacement
  * ICorDebugProcess instance.
@@ -251,18 +251,18 @@ typedef struct CorDebugGuidToTypeMapping
 interface ICorDebugDataTarget : IUnknown
 {
     /*
-     * GetPlatform returns the processor architecture and operating system on 
-     * which the target process is (or was) running.  
+     * GetPlatform returns the processor architecture and operating system on
+     * which the target process is (or was) running.
      *
-     * This is used by ICorDebug to determine details of the target process 
-     * such as its pointer size, address space layout, register set, 
+     * This is used by ICorDebug to determine details of the target process
+     * such as its pointer size, address space layout, register set,
      * instruction format, context layout, and calling conventions, etc.
      * This platforms in this list are the only ones supported by this version
      * of ICorDebug, but more may be added in future versions.
      *
-     * Note that this may actually indicate the platform which is being 
+     * Note that this may actually indicate the platform which is being
      * emulated for the target, not the actual hardware in use.  For example,
-     * a process running in the WOW on Windows x64 should use 
+     * a process running in the WOW on Windows x64 should use
      * CORDB_PLATFORM_WINDOWS_X86.
      *
      * Implementations should be sure to describe what the platform of the
@@ -282,7 +282,7 @@ interface ICorDebugDataTarget : IUnknown
         CORDB_PLATFORM_WINDOWS_ARM64,     // Windows on ARM64
 
         CORDB_PLATFORM_POSIX_AMD64,       // Posix supporting OS on Intel x64
-        CORDB_PLATFORM_POSIX_X86,         // Posix supporting OS on Intel x86        
+        CORDB_PLATFORM_POSIX_X86,         // Posix supporting OS on Intel x86
         CORDB_PLATFORM_POSIX_ARM,         // Posix supporting OS on ARM32
         CORDB_PLATFORM_POSIX_ARM64        // Posix supporting OS on ARM64
     } CorDebugPlatform;
@@ -292,13 +292,13 @@ interface ICorDebugDataTarget : IUnknown
     /*
      * ReadVirtual - Read virtual memory from the target process.
      *
-     * Requests contiguous memory starting at the specified target address to 
-     * be read from the target process into the supplied buffer.  If at least 
-     * the first byte (at the specified start address) can be read, the call 
+     * Requests contiguous memory starting at the specified target address to
+     * be read from the target process into the supplied buffer.  If at least
+     * the first byte (at the specified start address) can be read, the call
      * should return success (to support efficient reading of data structures
      * with self-describing length, like null-terminated strings).
      *
-     * On success, the actual number of bytes read must be stored into 
+     * On success, the actual number of bytes read must be stored into
      * pBytesRead.
      */
     HRESULT ReadVirtual([in] CORDB_ADDRESS address,
@@ -309,12 +309,12 @@ interface ICorDebugDataTarget : IUnknown
     /*
      * GetThreadContext - Get the thread context (register values) for a thread.
      *
-     * Requests the current thread context for the specified (operating-system 
-     * defined) thread identifier.  The size and format of the context record 
-     * is platform dependant, and is determined by the result of the call to 
-     * GetPlatform.  
-     * 
-     * The context flags specify, in a platform-dependent manor, which portions 
+     * Requests the current thread context for the specified (operating-system
+     * defined) thread identifier.  The size and format of the context record
+     * is platform dependant, and is determined by the result of the call to
+     * GetPlatform.
+     *
+     * The context flags specify, in a platform-dependent manor, which portions
      * of the context should be read.  contextSize specifies the size of the
      * supplied buffer, but the function is free to not fill the whole buffer
      * if it is possible to determine the actual size from the context.
@@ -488,7 +488,7 @@ interface ICorDebugMergedAssemblyRecord : IUnknown
      *                 These names do not include qualifiers such as file extensions, culture, version, or public key token
      */
     HRESULT GetSimpleName([in] ULONG32 cchName, [out] ULONG32 *pcchName, [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]);
-    
+
     /*
      * GetVersion - Gives the assembly version information
      */
@@ -507,7 +507,7 @@ interface ICorDebugMergedAssemblyRecord : IUnknown
     /*
      * GetPublicKeyToken - Gives the assembly public key token (the last 8 bytes of a SHA1 hash of the public key)
      */
-    HRESULT GetPublicKeyToken([in] ULONG32 cbPublicKeyToken, [out] ULONG32 *pcbPublicKeyToken, 
+    HRESULT GetPublicKeyToken([in] ULONG32 cbPublicKeyToken, [out] ULONG32 *pcbPublicKeyToken,
         [out, size_is(cbPublicKeyToken), length_is(*pcbPublicKeyToken)] BYTE pbPublicKeyToken[]);
 
     /*
@@ -696,7 +696,7 @@ interface ICorDebugVirtualUnwinder : IUnknown
                        [out] ULONG32* contextSize,
                        [out, size_is(cbContextBuf)] BYTE contextBuf[]);
 
-    /* 
+    /*
      * Advances to the callers context.
      *
      * If a failing HRESULT is returned ICorDebug APIs will return CORDBG_E_DATA_TARGET_ERROR.
@@ -812,7 +812,7 @@ interface ICorDebugDataTarget3 : IUnknown
 };
 
 /*
- * Data target that knows how to obtain debugee's process id. 
+ * Data target that knows how to obtain debugee's process id.
  * Debugee is not necessarily a living process at that time or on the same machine.
  */
 [
@@ -832,20 +832,20 @@ interface ICorDebugDataTarget4 : IUnknown
 };
 
 /*
- * Mutable extension to the data target.  This version of ICorDebugDataTarget 
- * can be implemented by targets that wish to support modification of the target 
+ * Mutable extension to the data target.  This version of ICorDebugDataTarget
+ * can be implemented by targets that wish to support modification of the target
  * process (such as for live invasive debugging).
  *
- * All of these APIs are optional in the sense that no core inspection-based 
+ * All of these APIs are optional in the sense that no core inspection-based
  * debugging functionality will be lost by not implementing this interface or
  * by the failure of these methods.  Any failure HRESULT from these APIs will
  * propagate out as the HRESULT from the ICorDebug API call.
  *
  * Note that a single ICorDebug API call may result in multiple mutations,
- * and there is no mechanism for ensuring related mutations are applied 
+ * and there is no mechanism for ensuring related mutations are applied
  * transactionally (all-or-none).  This means that if a mutation fails after
  * others (for the same ICorDebug call) have succeeded, the target process may
- * be left in an inconsistent state and debugging may become unreliable.  
+ * be left in an inconsistent state and debugging may become unreliable.
   */
 [
     object,
@@ -879,7 +879,7 @@ interface ICorDebugMutableDataTarget : ICorDebugDataTarget
                              [in] ULONG32 contextSize,
                              [in, size_is(contextSize)] const BYTE * pContext);
 
-    /* 
+    /*
      * Invoke to change the continue-status for the outstanding debug-event on
      * the specified thread.
      *
@@ -887,7 +887,7 @@ interface ICorDebugMutableDataTarget : ICorDebugDataTarget
      *        dwThreadId - OS Thread Id of the debug event
      *    continueStatus - New continue status being requested.  See the
      *                     definition of CORDB_CONTINUE_STATUS for details.
-     * 
+     *
      * This API is used when the Debugger makes an ICorDebug API request
      * which requires the current debug event to be handled in a way that is
      * potentially different from which it would be otherwise.  For example,
@@ -902,8 +902,8 @@ interface ICorDebugMutableDataTarget : ICorDebugDataTarget
 
 
 /*
- * Interface used by the data access services layer to locate metadata 
- * of assemblies in a target. 
+ * Interface used by the data access services layer to locate metadata
+ * of assemblies in a target.
  *
  * The API client must implement this interface as appropriate for the
  * particular target (for example, a live process or a memory dump).
@@ -1131,7 +1131,7 @@ interface ICorDebugManagedCallback : IUnknown
                          [in] ICorDebugThread *thread);
 
     /*
-     * ExitThread is called when a thread which has run managed code exits. 
+     * ExitThread is called when a thread which has run managed code exits.
      * Once this callback is fired, the thread no longer will appear in thread enumerations.
      */
 
@@ -1289,14 +1289,14 @@ interface ICorDebugManagedCallback : IUnknown
                        [in] ICorDebugThread *pThread);
 
     /*
-     * UpdateModuleSymbols is called when PDB debug symbols are available for an 
-     * in-memory module. This is a debugger's chance to load the symbols 
+     * UpdateModuleSymbols is called when PDB debug symbols are available for an
+     * in-memory module. This is a debugger's chance to load the symbols
      * (using ISymUnmanagedBinder::GetReaderForStream), and bind source-level
      * breakpoints for the module.
-     * 
+     *
      * This callback is no longer dispatched for dynamic modules.  Instead,
      * debuggers should call ICorDebugModule3::CreateReaderForInMemorySymbols
-     * to obtain a symbol reader for a dynamic module.  
+     * to obtain a symbol reader for a dynamic module.
      */
     HRESULT UpdateModuleSymbols([in] ICorDebugAppDomain *pAppDomain,
                                 [in] ICorDebugModule *pModule,
@@ -1335,17 +1335,17 @@ interface ICorDebugManagedCallback : IUnknown
 interface ICorDebugManagedCallback3 : IUnknown
 {
     /* Callback indicating an enabled custom debugger notification has been
-     * raised. pThread points to the thread that issued the notification. 
-     * A subsequent call to GetCurrentCustomDebuggerNotification will retrieve the object that was passed to 
+     * raised. pThread points to the thread that issued the notification.
+     * A subsequent call to GetCurrentCustomDebuggerNotification will retrieve the object that was passed to
      * System.Diagnostics.Debugger.CustomNotification, whose type will be one
      * that has been enabled via SetEnableCustomNotification.
-     * Note that this will return non-null if and only if we are currently inside a CustomNotification 
-     * callback. 
+     * Note that this will return non-null if and only if we are currently inside a CustomNotification
+     * callback.
      * The debugger can read type-specific parameters from fields of the data
-     * object, and store responses into fields. 
+     * object, and store responses into fields.
      * ICorDebug imposes no policy on the types of notifications or their
      * contents, and their semantics are strictly a contract between
-     * debuggers and applications/frameworks.   
+     * debuggers and applications/frameworks.
      */
     HRESULT CustomNotification([in] ICorDebugThread * pThread, [in] ICorDebugAppDomain * pAppDomain);
 }
@@ -1359,7 +1359,8 @@ interface ICorDebugManagedCallback3 : IUnknown
 
 interface ICorDebugManagedCallback4 : IUnknown
 {
-    HRESULT SomeWork([in] ICorDebugThread * pThread, [in] ICorDebugAppDomain * pAppDomain);
+    HRESULT BeforeGarbageCollection(ICorDebugController* pController);
+    HRESULT AfterGarbageCollection(ICorDebugController* pController);
 }
 
 
@@ -1454,7 +1455,7 @@ interface ICorDebugManagedCallback2 : IUnknown
 
 
     /*
-     * For non-intercepted exceptions, ExceptionUnwind is called at the beginning of the second pass 
+     * For non-intercepted exceptions, ExceptionUnwind is called at the beginning of the second pass
      * when we start to unwind the stack.  For intercepted exceptions, ExceptionUnwind is called when
      * the interception is complete, conceptually at the end of the second pass.
      *
@@ -1647,15 +1648,15 @@ interface ICorDebug : IUnknown
      *
      * This should be set after Initialize and before any calls to CreateProcess or DebugActiveProcess.
      *
-     * However, for legacy purposes, it is not absolutely required to set this until 
-     * before the first native debug event is fired. Specifically, if CreateProcess has the 
+     * However, for legacy purposes, it is not absolutely required to set this until
+     * before the first native debug event is fired. Specifically, if CreateProcess has the
      * CREATE_SUSPENDED flag, native debug events will not be dispatched until the main thread
      * is resumed.
-     * DebugActiveProcess will dispatch native debug events immediately, and so the unmanaged callback 
+     * DebugActiveProcess will dispatch native debug events immediately, and so the unmanaged callback
      * must be set before DebugActiveProcess is called.
      *
-     * Returns: 
-     *    S_OK if callback pointer is successfully updated. 
+     * Returns:
+     *    S_OK if callback pointer is successfully updated.
      *    failure on any failure.
      *
      */
@@ -1742,7 +1743,7 @@ interface ICorDebug : IUnknown
 #pragma warning(pop)
 
 /*
- * A debugger can implement this interface and pass it to ICorDebugRemote to specify the host name of the 
+ * A debugger can implement this interface and pass it to ICorDebugRemote to specify the host name of the
  * target machine in Mac remote debugging scenarios.  This is only supported on Silverlight.
  */
 [
@@ -1755,26 +1756,26 @@ interface ICorDebugRemoteTarget : IUnknown
 {
     /*
      * Return the host name of the target machine.  The host name can either be a fully qualified domain name or
-     * an IPv4 address.  If cchHostName is 0 and szHostName is NULL, this function just returns the number of 
+     * an IPv4 address.  If cchHostName is 0 and szHostName is NULL, this function just returns the number of
      * characters including the NULL character in the host name.
      *
-     * cchHostName is the number of characters in the buffer szHostName.  If this is 0, then szHostName must 
+     * cchHostName is the number of characters in the buffer szHostName.  If this is 0, then szHostName must
      * be NULL.  If it is not 0, then szHostName must be non-NULL.
-     * 
-     * pcchHostName returns the number of characters including the NULL character in the host name.  This can 
+     *
+     * pcchHostName returns the number of characters including the NULL character in the host name.  This can
      * be NULL.
-     * 
+     *
      * szHostName is the buffer for returning the host name.
      */
 
     HRESULT GetHostName([in]  ULONG32 cchHostName,
                         [out, annotation("_Out_")] ULONG32 * pcchHostName,
-                        [out, size_is(cchHostName), length_is(*pcchHostName), annotation("_Out_writes_to_opt_(cchHostName, *pcchHostName)")] 
+                        [out, size_is(cchHostName), length_is(*pcchHostName), annotation("_Out_writes_to_opt_(cchHostName, *pcchHostName)")]
                                                      WCHAR szHostName[]);
 }
 
 /*
- * A debugger can QI for this interface from an ICorDebug interface in order to specify a target machine in 
+ * A debugger can QI for this interface from an ICorDebug interface in order to specify a target machine in
  * Mac remote debugging scenarios.  This is only supported on Silverlight.
  */
 [
@@ -1923,7 +1924,7 @@ interface ICorDebug2 : IUnknown
         ver_ICorDebugAppDomain3 = CorDebugVersion_4_5,
         ver_ICorDebugCode3 = CorDebugVersion_4_5,
         ver_ICorDebugILFrame3 = CorDebugVersion_4_5,
-        
+
         CorDebugLatestVersion = CorDebugVersion_4_5
 
     } CorDebugInterfaceVersion;
@@ -2076,7 +2077,7 @@ interface ICorDebugController : IUnknown
      *
      * Note that currently if unmanaged debugging is enabled this call will
      * fail due to OS limitations.
-     * 
+     *
      * Returns S_OK on success.
      *
      */
@@ -2184,13 +2185,13 @@ interface ICorDebugAppDomain : ICorDebugController
      *   callers know the full size of buffer they'd need to allocate to get the full string.
      *
      * if (cchName == 0) then we're in "query" mode:
-     *     This fails if szName is non-null or pcchName is null 
+     *     This fails if szName is non-null or pcchName is null
      *     Else this function will set pcchName to let the caller know how large of a buffer to allocate
      *     and return S_OK.
      *
-     * if (cchName != 0) then 
+     * if (cchName != 0) then
      *     This fails if szName is null.
-     *     Else this copies as much as can fit into szName (it will always null terminate szName) and returns S_OK. 
+     *     Else this copies as much as can fit into szName (it will always null terminate szName) and returns S_OK.
      *     pcchName can be null. If it's non-null, we set it.
      *
      * The expected usage pattern is that a client will call once to get the size of a buffer needed for the name,
@@ -2215,7 +2216,7 @@ interface ICorDebugAppDomain : ICorDebugController
 
     HRESULT GetObject([out] ICorDebugValue **ppObject);
 
-    /* 
+    /*
      * DEPRECATED.  This does nothing in V3.  Attaching is process-wide.
      */
 
@@ -2372,7 +2373,7 @@ interface ICorDebugAssembly : IUnknown
     /*
      * GetName returns the full path and filename of the assembly.
      * If the assembly has no filename (i.e. it is in-memory only),
-     * S_FALSE is returned, and a fabricated string is stored into szName. 
+     * S_FALSE is returned, and a fabricated string is stored into szName.
      */
 
     HRESULT GetName([in] ULONG32 cchName,
@@ -2417,7 +2418,7 @@ interface ICorDebugAssembly3 : IUnknown
     /*
      * Gets an enumeration for all the assemblies contained within this assembly
      * If the assembly isn't a container, the result is S_FALSE and the enumeration
-     * will be empty. Symbols are needed to compute this result; if they aren't 
+     * will be empty. Symbols are needed to compute this result; if they aren't
      * present an error will be returned and no enumeration provided.
      */
     HRESULT EnumerateContainedAssemblies(ICorDebugAssemblyEnum **ppAssemblies);
@@ -2553,7 +2554,7 @@ typedef struct COR_GC_REFERENCE
     ICorDebugAppDomain *Domain;         // The AppDomain of the handle/object, may be null.
     ICorDebugValue *Location;           // A reference to the object
     CorGCReferenceType Type;            // Where the root came from.
-    
+
     /*
         DependentSource - for HandleDependent
         RefCount - for HandleStrongRefCount
@@ -2582,13 +2583,13 @@ cpp_quote("#define _DEF_COR_ARRAY_LAYOUT_")
 typedef struct COR_ARRAY_LAYOUT
 {
     COR_TYPEID componentID; // The type of objects the array contains
-    
+
     CorElementType componentType;  // Whether the component itself is a GC reference, value class, or primitive
-    
+
     ULONG32 firstElementOffset; // The offset to the first element
     ULONG32 elementSize;     // The size of each element
     ULONG32 countOffset;     // The offset to the number of elements in the array.
-    
+
     // For multidimensional arrays (works with normal arrays too).
     ULONG32 rankSize;       // The size of the rank
     ULONG32 numRanks;       // The number of ranks in the array (1 for array, N for multidimensional array)
@@ -2617,7 +2618,7 @@ typedef struct COR_FIELD
     mdFieldDef token;   // FieldDef token to get the field info
     ULONG32 offset;     // Offset in object of data.
     COR_TYPEID id;      // TYPEID of the field
-    
+
     CorElementType fieldType;
 } COR_FIELD;
 cpp_quote("#endif // _DEF_COR_FIELD_")
@@ -2951,15 +2952,15 @@ interface ICorDebugProcess2 : IUnknown
 interface ICorDebugProcess3 : IUnknown
 {
     /*  Enables (or disables) custom debugger notifications of a specified
-     *  type (which implements ICustomDebuggerNotification).  
+     *  type (which implements ICustomDebuggerNotification).
      *  When this has been enabled, calls to
      *  System.Diagnostics.Debugger.CustomNotification with a data argument
      *  of the specified class will trigger a CustomNotification callback.
      *  Notifications are disabled by default and the debugger must opt-into
      *  any notification types it knows of and wishes to handle.
-     *  Since ICorDebugClass is scoped by appdomains, the debugger needs to 
-     *  call this API for every appdomain in the process if it's interested in 
-     *  receiving the notification across the entire process. 
+     *  Since ICorDebugClass is scoped by appdomains, the debugger needs to
+     *  call this API for every appdomain in the process if it's interested in
+     *  receiving the notification across the entire process.
      */
 
     HRESULT SetEnableCustomNotification(ICorDebugClass * pClass, BOOL fEnable);
@@ -2979,14 +2980,14 @@ interface ICorDebugProcess5 : IUnknown
     HRESULT GetObject([in] CORDB_ADDRESS addr, [out] ICorDebugObjectValue **pObject);
     HRESULT EnumerateGCReferences([in] BOOL enumerateWeakReferences, [out] ICorDebugGCReferenceEnum **ppEnum);
     HRESULT EnumerateHandles([in] CorGCReferenceType types, [out] ICorDebugGCReferenceEnum **ppEnum);
-    
+
     HRESULT GetTypeID([in] CORDB_ADDRESS obj, [out] COR_TYPEID *pId);
     HRESULT GetTypeForTypeID([in] COR_TYPEID id, [out] ICorDebugType **ppType);
-    
+
     HRESULT GetArrayLayout([in] COR_TYPEID id, [out] COR_ARRAY_LAYOUT *pLayout);
     HRESULT GetTypeLayout([in] COR_TYPEID id, [out] COR_TYPE_LAYOUT *pLayout);
     HRESULT GetTypeFields([in] COR_TYPEID id, ULONG32 celt, COR_FIELD fields[], ULONG32 *pceltNeeded);
-    
+
     /*
      *  Enables the specified policy.
      */
@@ -2997,12 +2998,12 @@ interface ICorDebugProcess5 : IUnknown
 // Describes formats of pRecord byte blob in DecodeEvent.
 // This is dependent on the target architecture.
 typedef enum CorDebugRecordFormat
-{        
+{
     FORMAT_WINDOWS_EXCEPTIONRECORD32 = 1,
     FORMAT_WINDOWS_EXCEPTIONRECORD64 = 2,
 } CorDebugRecordFormat;
 
-// dwFlags in DecodeEvent is dependent on the target architecture. 
+// dwFlags in DecodeEvent is dependent on the target architecture.
 // Definition of DecodeEvent flags on Windows.
 typedef enum CorDebugDecodeEventFlagsWindows
 {
@@ -3020,13 +3021,13 @@ typedef enum CorDebugDebugEventKind
     DEBUG_EVENT_KIND_MANAGED_EXCEPTION_UNHANDLED = 6
 } CorDebugDebugEventKind;
 
-// Describes what amount of cached data must be discarded based on changes to the   
+// Describes what amount of cached data must be discarded based on changes to the
 // process
 typedef enum CorDebugStateChange
 {
-    PROCESS_RUNNING = 0x0000001, // The process reached a new memory state via 
-                                 // forward execution.    
-    FLUSH_ALL       = 0x0000002, // The process' memory might be arbitrarily 
+    PROCESS_RUNNING = 0x0000001, // The process reached a new memory state via
+                                 // forward execution.
+    FLUSH_ALL       = 0x0000002, // The process' memory might be arbitrarily
                                  // different than it was before.
 } CorDebugStateChange;
 
@@ -3070,7 +3071,7 @@ typedef enum CorDebugCodeInvokePurpose
     CODE_INVOKE_PURPOSE_NONE,
     CODE_INVOKE_PURPOSE_NATIVE_TO_MANAGED_TRANSITION,  // The managed code will run any managed entrypoint
                                                        // such as a reverse p-invoke. Any more detailed purpose
-                                                       // is unknown by the runtime. 
+                                                       // is unknown by the runtime.
     CODE_INVOKE_PURPOSE_CLASS_INIT,                    // The managed code will run a static constructor
     CODE_INVOKE_PURPOSE_INTERFACE_DISPATCH,            // The managed code will run the implementation for
                                                        // some interface method that was called
@@ -3084,20 +3085,20 @@ typedef enum CorDebugCodeInvokePurpose
 ]
 interface ICorDebugProcess6 : IUnknown
 {
-    //Decodes managed debug events which have been encapsulated in the payload of    
+    //Decodes managed debug events which have been encapsulated in the payload of
     //specially crafted native exception debug events
     HRESULT DecodeEvent(
         [in, length_is(countBytes), size_is(countBytes)]  const BYTE pRecord[],
         [in] DWORD countBytes,
         [in] CorDebugRecordFormat format,
-        [in] DWORD dwFlags, 
-        [in] DWORD dwThreadId, 
+        [in] DWORD dwFlags,
+        [in] DWORD dwThreadId,
         [out] ICorDebugDebugEvent **ppEvent);
 
     // Debugger calls this to notify ICorDebug that the process is running.
     //
     // Notes:
-    //  ProcessStateChanged(PROCESS_RUNNING) has similar semantics to  
+    //  ProcessStateChanged(PROCESS_RUNNING) has similar semantics to
     //  ICorDebugProcess::Continue();
     HRESULT ProcessStateChanged([in] CorDebugStateChange change);
 
@@ -3110,13 +3111,13 @@ interface ICorDebugProcess6 : IUnknown
     // various ICorDebug APIs described below.
     //
     // Terminology
-    // The aggregate modules are called containers, the modules inside are called 
-    // sub-modules or virtual modules. Both container modules and sub-modules are 
-    // represented with the ICorDebugModule interface, however the behavior of the 
+    // The aggregate modules are called containers, the modules inside are called
+    // sub-modules or virtual modules. Both container modules and sub-modules are
+    // represented with the ICorDebugModule interface, however the behavior of the
     // interface is slightly different in each case, as described below.
-    // In addition there may still be modules loaded that weren't merged during build. 
+    // In addition there may still be modules loaded that weren't merged during build.
     // These modules, called regular modules, are neither container modules nor
-    // sub-modules. 
+    // sub-modules.
     //
     // Modules and assemblies
     // Multi-module assemblies are not supported for assembly merging scenarios
@@ -3139,7 +3140,7 @@ interface ICorDebugProcess6 : IUnknown
     //     -have a reduced set of metadata that corresponds only to the original
     //      assembly that was merged in.
     //     -The metadata names have no mangling.
-    //     -Metadata tokens are unlikely to match with the tokens in the original 
+    //     -Metadata tokens are unlikely to match with the tokens in the original
     //      assembly before it was merged in the build process
     //     -ICorDebugModule.GetName() returns the assembly name (not a file path)
     //     -ICorDebug.GetSize() returns the original unmerged image size.
@@ -3169,7 +3170,7 @@ interface ICorDebugProcess6 : IUnknown
     //     Disabled - Returns a list of container assemblies + regular assemblies
     //                (no sub-assemblies are shown)
     //     Enabled - Returns the list of sub-assemblies + regular assemblies
-    //                (no container assemblies are shown). 
+    //                (no container assemblies are shown).
     //                Note: If any container assembly is missing symbols, none of its
     //                sub-assemblies will be enumerated. If any regular assembly is
     //                missing symbols it may or may not be enumerated.
@@ -3190,10 +3191,10 @@ interface ICorDebugProcess6 : IUnknown
     HRESULT EnableVirtualModuleSplitting(BOOL enableSplitting);
 
     // Changes internal state of the debuggee so that the System.Debugger.IsAttached API in the BCL
-    // returns true. 
+    // returns true.
     //
     // Returns
-    //   S_OK - debuggee is succesfully updated 
+    //   S_OK - debuggee is succesfully updated
     //   CORDBG_E_MODULE_NOT_LOADED - assembly containing System.Debugger.IsAttached API is not loaded
     //   or some other error is preventing it from being recognized such as missing metadata. This error
     //   is common and benign - it is recommended to try the call again when future assemblies load.
@@ -3217,7 +3218,7 @@ interface ICorDebugProcess6 : IUnknown
     HRESULT GetExportStepInfo([in]LPCWSTR pszExportName, [out]CorDebugCodeInvokeKind* pInvokeKind, [out]CorDebugCodeInvokePurpose* pInvokePurpose);
 }
 
-typedef enum WriteableMetadataUpdateMode 
+typedef enum WriteableMetadataUpdateMode
 {
    LegacyCompatPolicy,
    AlwaysShowUpdates
@@ -3250,7 +3251,7 @@ interface ICorDebugProcess8 : IUnknown
     * EnableExceptionCallbacksOutsideOfMyCode enables/disables certain types of exception callback to ICorDebugManagedCallback2.
     * If the flag is FALSE:
     * 1) DEBUG_EXCEPTION_FIRST_CHANCE callbacks won't called in the debugger.
-    * 2) DEBUG_EXCEPTION_CATCH_HANDLER_FOUND callbacks won't be called if an exception never escapes into user code. 
+    * 2) DEBUG_EXCEPTION_CATCH_HANDLER_FOUND callbacks won't be called if an exception never escapes into user code.
     * (i.e. a path from an exception origin to an exception handler has no methods marked as JMC)
     *
     * Default value of this flag is TRUE.
@@ -3287,23 +3288,23 @@ interface ICorDebugModuleDebugEvent : ICorDebugDebugEvent
 ]
 interface ICorDebugExceptionDebugEvent : ICorDebugDebugEvent
 {
-    // The meaning of this stack pointer varies based on event type (available from  
+    // The meaning of this stack pointer varies based on event type (available from
     // ICorDebugDebugEvent.GetEventType())
     //
     // MANAGED_EXCEPTION_FIRST_CHANCE -> The stack pointer for the frame that threw the exception
-    // MANAGED_EXCEPTION_USER_FIRST_CHANCE -> The stack pointer for the user-code frame closest to the point of 
+    // MANAGED_EXCEPTION_USER_FIRST_CHANCE -> The stack pointer for the user-code frame closest to the point of
     // the thrown exception
     // MANAGED_EXCEPTION_CATCH_HANDLER_FOUND -> The stack pointer for the frame that contains the catch handler
     // MANAGED_EXCEPTION_UNHANDLED -> *pStackPointer will be NULL
     HRESULT GetStackPointer([out]CORDB_ADDRESS *pStackPointer);
 
-    // The meaning of the IP varies based on event type (available from  
+    // The meaning of the IP varies based on event type (available from
     // ICorDebugDebugEvent.GetEventType())
     //
     // MANAGED_EXCEPTION_FIRST_CHANCE -> The address of the faulting instruction
-    // MANAGED_EXCEPTION_USER_FIRST_CHANCE -> Within the frame indicated by GetStackPointer(), 
-    // this is the code address where execution would resume if no exception had been 
-    // raised. The exception may or may not cause different code to be executed in this 
+    // MANAGED_EXCEPTION_USER_FIRST_CHANCE -> Within the frame indicated by GetStackPointer(),
+    // this is the code address where execution would resume if no exception had been
+    // raised. The exception may or may not cause different code to be executed in this
     // frame such as a catch of finally clause.
     // MANAGED_EXCEPTION_CATCH_HANDLER_FOUND -> Within the frame indicated by GetStackPointer(),
     // this is the code address where catch handler execution will start
@@ -3747,7 +3748,7 @@ interface ICorDebugRegisterSet : IUnknown
         REGISTER_ARM_D31,
 
         // ARM64 registers
-            
+
         REGISTER_ARM64_PC = 0,
         REGISTER_ARM64_SP,
         REGISTER_ARM64_FP,
@@ -4004,7 +4005,7 @@ interface ICorDebugThread : IUnknown
      * If the thread's user state includes USER_UNSAFE_POINT, then the thread may block a GC.
      * This means the suspended thread has a mcuh higher chance of causing a deadlock.
      *
-     * This may not affect debug events already queued. Thus a debugger should drain the entire 
+     * This may not affect debug events already queued. Thus a debugger should drain the entire
      * event queue (via calling HasQueuedCallbacks) before suspending or resuming threads. Else it
      * may get events on a thread that it believes it has already suspended.
      *
@@ -4255,7 +4256,7 @@ interface ICorDebugThread4 : IUnknown
 {
     /*
      * Returns S_OK if ICorDebugThread::GetCurrentException() is non-NULL and the exception
-     * it refers to has completed the first pass of exception handling without locating 
+     * it refers to has completed the first pass of exception handling without locating
      * a catch clause.
      * Returns S_FALSE if there is no exception, it hasn't completed first pass handling,
      * or a catch handler was located
@@ -4264,13 +4265,13 @@ interface ICorDebugThread4 : IUnknown
     HRESULT HasUnhandledException();
 
     HRESULT GetBlockingObjects([out] ICorDebugBlockingObjectEnum **ppBlockingObjectEnum);
-    /* 
+    /*
      * Gets the current CustomNotification object on the current thread. This could be NULL if no
      * current notification object exists. If we aren't currently inside a CustomNotification callback,
      * this will always return NULL.
-     * A debugger can examine this object to determine how to handle the notification. 
-     * See ICorDebugManagedCallback3::CustomNotification for more information about 
-     * custom notifications. 
+     * A debugger can examine this object to determine how to handle the notification.
+     * See ICorDebugManagedCallback3::CustomNotification for more information about
+     * custom notifications.
      */
     HRESULT GetCurrentCustomDebuggerNotification([out] ICorDebugValue ** ppNotificationObject);
 };
@@ -4292,11 +4293,11 @@ interface ICorDebugStackWalk : IUnknown
         SET_CONTEXT_FLAG_UNWIND_FRAME = 0x2,
     } CorDebugSetContextFlag;
 
-    /* 
+    /*
      * Get the current context of this stack frame.
-     * 
-     * The CONTEXT is retrieved from the ICorDebugStackWalk.  As unwinding may only restore a subset of the 
-     * registers, such as only non-volatile registers, the context may not exactly match the register state at 
+     *
+     * The CONTEXT is retrieved from the ICorDebugStackWalk.  As unwinding may only restore a subset of the
+     * registers, such as only non-volatile registers, the context may not exactly match the register state at
      * the time of the actual call.
      */
     HRESULT GetContext([in] ULONG32 contextFlags,
@@ -4304,14 +4305,14 @@ interface ICorDebugStackWalk : IUnknown
                        [out] ULONG32* contextSize,
                        [out, size_is(contextBufSize)] BYTE contextBuf[]);
 
-    /* 
+    /*
      * Change the current context of this stack walk, allowing the
      * debugger to move it to an arbitrary context. Does not actually
      * alter the current context of the thread whose stack is being walked.
      *
      * The CONTEXT has to be a valid CONTEXT of a stack frame on the thread.
      * If the CONTEXT is outside of the current thread's stack range, we'll
-     * return a failure HRESULT.  Otherwise, in the case of an invalid CONTEXT, 
+     * return a failure HRESULT.  Otherwise, in the case of an invalid CONTEXT,
      * the result is undefined.
      */
     HRESULT SetContext([in] CorDebugSetContextFlag flag,
@@ -4319,11 +4320,11 @@ interface ICorDebugStackWalk : IUnknown
                        [in, size_is(contextSize)] BYTE context[]);
 
     /*
-     * Attempt to advance the stackwalk to the next frame.  
+     * Attempt to advance the stackwalk to the next frame.
      * If the current frame type is a native stack frame, Next() will not advance to the caller frame.
      * Instead, Next() will advance to the next managed stack frame or the next internal frame marker.
      *
-     * If a debugger wants to unwind unmanaged stack frames, it needs to start from the 
+     * If a debugger wants to unwind unmanaged stack frames, it needs to start from the
      * native stack frame itself.  It can seed the unwind by calling GetContext().
      *
      * This function will return CORDBG_S_AT_END_OF_STACK when there are no more frames.
@@ -4366,7 +4367,7 @@ interface ICorDebugChain : IUnknown
      * call chain.  Note that you cannot make any assumptions about
      * what is actually stored on the stack - the numeric range is to compare
      * stack frame locations only.
-     * The start of a stack range is the leafmost boundary of the chain, and 
+     * The start of a stack range is the leafmost boundary of the chain, and
      * the end of a stack range is the rootmost boundary of the chain.
      */
 
@@ -4498,9 +4499,9 @@ interface ICorDebugFrame : IUnknown
     HRESULT GetCode([out] ICorDebugCode **ppCode);
 
     /*
-     * GetFunction returns the function for the code which this stack 
-     * frame is running.  
-     * For ICorDebugInternalFrames, this may point to a method the 
+     * GetFunction returns the function for the code which this stack
+     * frame is running.
+     * For ICorDebugInternalFrames, this may point to a method the
      * frame is associated with (which may be in a different AppDomain
      * from the frame itself), or may fail if the frame doesn't relate to any
      * particular function.
@@ -4511,7 +4512,7 @@ interface ICorDebugFrame : IUnknown
     /*
      * GetFunctionToken is a convenience routine to return the token for the
      * function for the code which this stack frame is running.
-     * The scope to resolve the token can be gotten from the ICorDebugFunction 
+     * The scope to resolve the token can be gotten from the ICorDebugFunction
      * associated with this frame.
      */
 
@@ -4524,7 +4525,7 @@ interface ICorDebugFrame : IUnknown
      * cannot make any assumptions about what is actually stored on
      * the stack - the numeric range is to compare stack frame
      * locations only.
-     * The start of a stack range is the leafmost boundary of the frame, and 
+     * The start of a stack range is the leafmost boundary of the frame, and
      * the end of a stack range is the rootmost boundary of the frame.
      */
 
@@ -4628,7 +4629,7 @@ interface ICorDebugInternalFrame2 : IUnknown
 /*
      * Check if an internal frame is closer to the leaf than pFrameToCompare.
      */
-    HRESULT IsCloserToLeaf([in] ICorDebugFrame * pFrameToCompare, 
+    HRESULT IsCloserToLeaf([in] ICorDebugFrame * pFrameToCompare,
                            [out] BOOL * pIsCloser);
 };
 
@@ -4727,7 +4728,7 @@ interface ICorDebugILFrame : ICorDebugFrame
     /*
      * EnumerateArguments returns a list of the arguments available in the
      * frame.  Note that this will include varargs arguments as well as
-     * arguments declared by the function signature (inlucding the implicit 
+     * arguments declared by the function signature (inlucding the implicit
      * "this" argument if any).
      */
 
@@ -4783,8 +4784,8 @@ interface ICorDebugILFrame2 : IUnknown
 {
     /*
      * Performs an on-stack replacement for an outstanding function remap opportunity.
-     * This is used to update execution of an edited function to the latest version, 
-     * preserving the current frame state (such as the values of all locals). 
+     * This is used to update execution of an edited function to the latest version,
+     * preserving the current frame state (such as the values of all locals).
      * This can only be called when a FunctionRemapOpportunity callback has been delivered
      * for this leaf frame, and the callback has not yet been continued.  newILOffset
      * is the offset into the new function at which execution should continue.
@@ -4857,7 +4858,7 @@ interface ICorDebugILFrame4 : IUnknown
     *    instrumented IL. If the IL is not instrumented the enumeration will
     *    be empty and S_OK is returned.
     */
-    
+
     HRESULT EnumerateLocalVariablesEx([in] ILCodeKind flags, [out] ICorDebugValueEnum **ppValueEnum);
 
     /*
@@ -4894,7 +4895,7 @@ interface ICorDebugILFrame4 : IUnknown
 };
 
 /*
- * ICorDebugNativeFrame is a specialized interface of ICorDebugFrame for jitted frames, i.e. 
+ * ICorDebugNativeFrame is a specialized interface of ICorDebugFrame for jitted frames, i.e.
  * native frames for managed methods.
  * (Note that jitted frames implement both ICorDebugILFrame and ICorDebugNativeFrame.)
  */
@@ -5046,7 +5047,7 @@ interface ICorDebugNativeFrame2 : IUnknown
 interface ICorDebugModule3 : IUnknown
 {
     /*
-     * CreateReaderForInMemorySymbols creates a debug symbol reader object (eg. 
+     * CreateReaderForInMemorySymbols creates a debug symbol reader object (eg.
      * ISymUnmanagedReader) for a dynamic module.  This symbol reader becomes stale
      * and is usually discarded whenever a LoadClass callback is delivered for the
      * module.
@@ -5063,7 +5064,7 @@ interface ICorDebugModule3 : IUnknown
      *      yet available.
      *
      * Notes:
-     *   This API can also be used to create a symbol reader object for in-memory 
+     *   This API can also be used to create a symbol reader object for in-memory
      *   (non-dynamic) modules, but only after the symbols are first available
      *   (indicated by the UpdateModuleSymbols callback).
      *
@@ -5072,7 +5073,7 @@ interface ICorDebugModule3 : IUnknown
      *   the underlying data may have changed (i.e. a LoadClass event).
      *
      *   Dynamic modules do not have any symbols available until the first type has been
-     *   loaded into them (as indicated by the LoadClass callback).  
+     *   loaded into them (as indicated by the LoadClass callback).
      */
     HRESULT CreateReaderForInMemorySymbols([in] REFIID riid,
                                            [out][iid_is(riid)] void **ppObj);
@@ -5082,7 +5083,7 @@ interface ICorDebugModule3 : IUnknown
  * ICorDebugRuntimeUnwindableFrame is a specialized interface of ICorDebugFrame for unmanaged methods
  * which requires special knowledge to unwind.  They are not jitted code.  When the debugger sees this type
  * of frames, it should use ICorDebugStackWalk::Next() to unwind, but it should do inspection itself.
- * The debugger can call ICorDebugStackWalk::GetContext() to retrieve the CONTEXT of the frame when it gets 
+ * The debugger can call ICorDebugStackWalk::GetContext() to retrieve the CONTEXT of the frame when it gets
  * an ICorDebugRuntimeUnwindableFrame.
  */
 
@@ -5135,8 +5136,8 @@ interface ICorDebugModule : IUnknown
     /*
      * GetName returns a name identifying the module.
      *
-     * For on-disk modules this is a full path.  For dynamic modules this 
-     * is just the filename if one was provided.  Otherwise, and for other 
+     * For on-disk modules this is a full path.  For dynamic modules this
+     * is just the filename if one was provided.  Otherwise, and for other
      * in-memory modules, this is just the simple name stored in the module's
      * metadata.
      */
@@ -5455,7 +5456,7 @@ ICorDebugFunction3 is a logical extension to ICorDebugFunction.
 interface ICorDebugFunction3 : IUnknown
 {
     /*
-     * If this function has an active rejit request it will be returned in 
+     * If this function has an active rejit request it will be returned in
      * pRejitedILCode.
      * If there is no active request (a common case) then *ppRejitedILCode = NULL
      *
@@ -5463,7 +5464,7 @@ interface ICorDebugFunction3 : IUnknown
      * ICorProfilerCallback4::GetReJITParameters(). It may not yet be jitted
      * and threads may still be executing in the original version of the code.
      *
-     * A rejit request becomes inactive during the profiler's call to 
+     * A rejit request becomes inactive during the profiler's call to
      * ICorProfInfo::RequestRevert. Even after being reverted a thread can still
      * be executing in the rejited code.
      */
@@ -5482,20 +5483,20 @@ ICorDebugFunction4 is a logical extension to ICorDebugFunction.
 interface ICorDebugFunction4 : IUnknown
 {
     /*
-     * Sets a breakpoint at offset 0 of any current or future jitted methods. 
+     * Sets a breakpoint at offset 0 of any current or future jitted methods.
      */
     HRESULT CreateNativeBreakpoint(ICorDebugFunctionBreakpoint **ppBreakpoint);
 };
 
 /*
     ICorDebugCode represents an IL or native code blob.
+
     For methods that take offsets, the units are the same as the units on the CordbCode object.
     (eg, IL offsets for an IL code object, and native offsets for a native code object)
+
     V2 allows multiple code-regions. CordbCode presents an abstraction where these
     are merged together in a single linear, continuous space. So if the code is split
-    with 0x5 bytes at address 0x1000, and 0x10 bytes at address 0x2000, 
+    with 0x5 bytes at address 0x1000, and 0x10 bytes at address 0x2000,
     then:
     - GetAddress() yields a start address of 0x1000.
     - GetSize() is the size of the merged regions = 0x5+ 0x10 = 0x15 bytes.
@@ -5543,7 +5544,7 @@ interface ICorDebugCode : IUnknown
 
     /*
      * CreateBreakpoint creates a breakpoint in the function at the
-     * given offset. 
+     * given offset.
      *
      * If this code is IL code, and there is a jitted native version
      * of the code, the breakpoint will be applied in the jitted code
@@ -5741,25 +5742,25 @@ interface ICorDebugILCode2 : IUnknown
 
 /*
  ICorDebugClass represents a Class (mdTypeDef) in the IL image.
- For generic types, it represents the generic type definition (eg. List<T>) not any of 
- the specific instantiations (eg. List<int>). 
+ For generic types, it represents the generic type definition (eg. List<T>) not any of
+ the specific instantiations (eg. List<int>).
+
  Use ICorDebugClass2::GetParameterizedType to build an ICorDebugType from an
  ICorDebugClass and type parameters.
 
- Classes live in a module and are uniquely identified by a mdTypeDef. 
+ Classes live in a module and are uniquely identified by a mdTypeDef.
  In other words, you can round-trip a class like so:
     ICorDebugClass * pClass1 = ...; // some initial class
-    
-    ICorDebugModule * pModule = NULL;    
+
+    ICorDebugModule * pModule = NULL;
     pClass1->GetModule(&pModule);
 
     mdTypeDef token;
     pClass1->GetToken(&token);
-    
+
     ICorDebugClass * pClass2;
-    pModule->GetClassFromToken(token, &pClass2); 
-    // Now: pClass1 == pClass2 
+    pModule->GetClassFromToken(token, &pClass2);
+    // Now: pClass1 == pClass2
 
 */
 [
@@ -5791,12 +5792,12 @@ interface ICorDebugClass : IUnknown
      * Note that if the class accepts type parameters, then you should
      * use GetStaticField on an appropriate ICorDebugType rather than on the
      * ICorDebugClass.
-     * 
+     *
      * Returns:
      *  S_OK on success.
      *  CORDBG_E_FIELD_NOT_STATIC if the field is not static.
      *  CORDBG_E_STATIC_VAR_NOT_AVAILABLE if field is not yet available (storage for statics
-     *    may be lazily allocated). 
+     *    may be lazily allocated).
      *  CORDBG_E_VARIABLE_IS_ACTUALLY_LITERAL if the field is actually a metadata literal. In this
      *    case, the debugger should get the value from the metadata.
      *  error on other errors.
@@ -5894,7 +5895,7 @@ interface ICorDebugEval : IUnknown
      * CallFunction sets up a function call.  Note that if the function
      * is virtual, this will perform virtual dispatch.  If the function is
      * not static, then the first argument must be the "this" object.
-     * If the function is in an a different AppDomain, a transition will 
+     * If the function is in an a different AppDomain, a transition will
      * occur (but all arguments must also be in the target AppDomain)
      */
 
@@ -6176,7 +6177,7 @@ interface ICorDebugValue3 : IUnknown
 {
     /*
      * GetSize returns the size of the value in bytes. It has the same
-     * semantics as ICorDebugValue::GetSize except that it works 
+     * semantics as ICorDebugValue::GetSize except that it works
      * for arrays >4GB.
      */
 
@@ -6342,7 +6343,7 @@ interface ICorDebugHeapValue2 : IUnknown
 interface ICorDebugHeapValue3 : IUnknown
 {
 
-    /* 
+    /*
      * Gets the owning thread for a monitor lock
      */
     HRESULT GetThreadOwningMonitorLock([out] ICorDebugThread **ppThread, [out] DWORD *pAcquisitionCount);
@@ -6585,7 +6586,7 @@ interface ICorDebugVariableHome : IUnknown
      * Returns E_FAIL if the variable is a function argument.
      */
     HRESULT GetSlotIndex([out] ULONG32 *pSlotIndex);
-    
+
     /*
      * GetArgumentIndex - gives the argument index of a function argument.
      * The argument index can be used to retrieve the metadata for this
@@ -6610,7 +6611,7 @@ interface ICorDebugVariableHome : IUnknown
                                   // location
         VLT_INVALID
     } VariableLocationType;
-    
+
     /*
      * GetLocationType - gives the type of native location. See
      * VariableLocationType.
@@ -6627,7 +6628,7 @@ interface ICorDebugVariableHome : IUnknown
      * register-relative location.
      */
     HRESULT GetRegister([out] CorDebugRegister *pRegister);
-    
+
     /*
      * GetOffset - gives the offset from the base register for a variable.
      * Returns E_FAIL if the variable is not in a register-relative memory
@@ -6638,7 +6639,7 @@ interface ICorDebugVariableHome : IUnknown
 
 
 
-/* 
+/*
  * ICorDebugHandleValue represents a reference value that the debugger has
  * explicitly created a GC handle to. It does not represent GC Handles in the debuggee process,
 
@@ -6709,18 +6710,18 @@ interface ICorDebugComObjectValue : IUnknown
      * that are cached by the COM object.
      */
     HRESULT GetCachedInterfaceTypes(
-                        [in] BOOL bIInspectableOnly, 
+                        [in] BOOL bIInspectableOnly,
                         [out] ICorDebugTypeEnum **ppInterfacesEnum);
 
     /*
      * GetCachedInterfacePointers returns at most celt values of the
      * interface pointer values cached by the COM object. It fills
-     * pcEltFetched with the actual number of fetched elements. 
+     * pcEltFetched with the actual number of fetched elements.
      * When called with NULL for ptrs, and 0 for celt, it simply returns
      * the number of elements it needs.
      */
     HRESULT GetCachedInterfacePointers(
-                        [in] BOOL bIInspectableOnly, 
+                        [in] BOOL bIInspectableOnly,
                         [in] ULONG32 celt,
                         [out] ULONG32 *pcEltFetched,
                         [out, size_is(celt), length_is(*pcEltFetched)] CORDB_ADDRESS * ptrs);
@@ -6969,7 +6970,7 @@ interface ICorDebugVariableHomeEnum : ICorDebugEnum
                      ICorDebugVariableHome *homes[],
                  [out] ULONG *pceltFetched);
 };
-    
+
 [
     object,
     local,
@@ -7018,7 +7019,7 @@ interface ICorDebugTypeEnum : ICorDebugEnum
  * represent instantiated generic types (Eg, List<int>)
  * Use the metadata interfaces to get static (Compile-time) information about the type.
  *
- * A type (and all of its type parameters) lives in an single AppDomain and becomes 
+ * A type (and all of its type parameters) lives in an single AppDomain and becomes
  * invalid once the containing ICorDebugAppDomain is unloaded.
  *
  * Types may be lazily loaded, so if the debugger queries for a type that hasn't been
@@ -7277,7 +7278,7 @@ interface ICorDebugMDA : IUnknown
     // Get the flags associated w/ the MDA. New flags may be added in future versions.
     typedef enum CorDebugMDAFlags
     {
-       // If this flag is high, then the thread may have slipped since the MDA was fired. 
+       // If this flag is high, then the thread may have slipped since the MDA was fired.
        MDA_FLAG_SLIP = 0x2
     } CorDebugMDAFlags;
     HRESULT GetFlags([in] CorDebugMDAFlags * pFlags);
index 26dcc00..69d03ac 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 C:/Dev/coreclr/src/inc/cordebug.idl:
+/* Compiler settings for F:/Dev/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 66eaf20..fd61bd1 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 C:/Dev/coreclr/src/inc/cordebug.idl:
+/* Compiler settings for F:/Dev/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 
@@ -3773,9 +3773,11 @@ EXTERN_C const IID IID_ICorDebugManagedCallback4;
     ICorDebugManagedCallback4 : public IUnknown
     {
     public:
-        virtual HRESULT STDMETHODCALLTYPE SomeWork( 
-            /* [in] */ ICorDebugThread *pThread,
-            /* [in] */ ICorDebugAppDomain *pAppDomain) = 0;
+        virtual HRESULT STDMETHODCALLTYPE BeforeGarbageCollection( 
+            ICorDebugController *pController) = 0;
+        
+        virtual HRESULT STDMETHODCALLTYPE AfterGarbageCollection( 
+            ICorDebugController *pController) = 0;
         
     };
     
@@ -3798,10 +3800,13 @@ EXTERN_C const IID IID_ICorDebugManagedCallback4;
         ULONG ( STDMETHODCALLTYPE *Release )( 
             ICorDebugManagedCallback4 * This);
         
-        HRESULT ( STDMETHODCALLTYPE *SomeWork )( 
+        HRESULT ( STDMETHODCALLTYPE *BeforeGarbageCollection )( 
             ICorDebugManagedCallback4 * This,
-            /* [in] */ ICorDebugThread *pThread,
-            /* [in] */ ICorDebugAppDomain *pAppDomain);
+            ICorDebugController *pController);
+        
+        HRESULT ( STDMETHODCALLTYPE *AfterGarbageCollection )( 
+            ICorDebugManagedCallback4 * This,
+            ICorDebugController *pController);
         
         END_INTERFACE
     } ICorDebugManagedCallback4Vtbl;
@@ -3826,8 +3831,11 @@ EXTERN_C const IID IID_ICorDebugManagedCallback4;
     ( (This)->lpVtbl -> Release(This) ) 
 
 
-#define ICorDebugManagedCallback4_SomeWork(This,pThread,pAppDomain)    \
-    ( (This)->lpVtbl -> SomeWork(This,pThread,pAppDomain) ) 
+#define ICorDebugManagedCallback4_BeforeGarbageCollection(This,pController)    \
+    ( (This)->lpVtbl -> BeforeGarbageCollection(This,pController) ) 
+
+#define ICorDebugManagedCallback4_AfterGarbageCollection(This,pController)     \
+    ( (This)->lpVtbl -> AfterGarbageCollection(This,pController) ) 
 
 #endif /* COBJMACROS */
 
index 71af1b4..a855a10 100644 (file)
@@ -59,19 +59,19 @@ public:
 
     virtual void DetachThread(Thread *pRuntimeThread) = 0;
 
-    // Called when a module is being loaded into an AppDomain.  
+    // Called when a module is being loaded into an AppDomain.
     // This includes when a domain neutral module is loaded into a new AppDomain.
-    // This is called only when a debugger is attached, and will occur after the 
-    // related LoadAssembly and AddAppDomainToIPCBlock calls and before any 
+    // This is called only when a debugger is attached, and will occur after the
+    // related LoadAssembly and AddAppDomainToIPCBlock calls and before any
     // LoadClass calls for this module.
     virtual void LoadModule(Module *     pRuntimeModule,  // the module being loaded
                             LPCWSTR      psModuleName,    // module file name
                             DWORD        dwModuleName,    // number of characters in file name excludign null
                             Assembly *   pAssembly,       // the assembly the module belongs to
                             AppDomain *  pAppDomain,      // the AppDomain the module is being loaded into
-                            DomainFile * pDomainFile, 
-                            BOOL         fAttaching) = 0; // true if this notification is due to a debugger 
-                                                          // being attached to the process 
+                            DomainFile * pDomainFile,
+                            BOOL         fAttaching) = 0; // true if this notification is due to a debugger
+                                                          // being attached to the process
 
     // Called AFTER LoadModule, and after the module has reached FILE_LOADED. This lets
     // dbgapi do any processing that needs to wait until the FILE_LOADED stage (e.g.,
@@ -87,7 +87,7 @@ public:
     virtual void UnloadModule(Module* pRuntimeModule, AppDomain *pAppDomain) = 0;
 
     // Called when a Module* is being destroyed.
-    // Specifically, the Module has completed unloading (which may have been done asyncronously), all resources 
+    // Specifically, the Module has completed unloading (which may have been done asyncronously), all resources
     // associated are being freed, and the Module* is about to become invalid.  The debugger should remove all
     // references to this Module*.
     // NOTE: This is called REGARDLESS of whether a debugger is attached or not, and will occur after any other
@@ -157,7 +157,7 @@ public:
     //
     // RequestFavor ensures that the helper thread has been initialized to
     // execute favors and then calls Debugger:DoFavor. It blocks until the
-    // favor callback completes. 
+    // favor callback completes.
     //
     // Parameters:
     //   fp    - Favour callback function
@@ -165,7 +165,7 @@ public:
     //
     // Return values:
     //   S_OK if the function succeeds, else a failure HRESULT
-    //   
+    //
     virtual HRESULT RequestFavor(FAVORCALLBACK fp, void * pData) = 0;
 
 #endif // #ifndef DACCESS_COMPILE
@@ -247,7 +247,7 @@ public:
                                 SString * pMessage) = 0;
 
     // send a custom notification from the target to the RS. This will become an ICorDebugThread and
-    // ICorDebugAppDomain on the RS. 
+    // ICorDebugAppDomain on the RS.
     virtual void SendCustomDebuggerNotification(Thread * pThread, DomainFile * pDomainFile, mdTypeDef classToken) = 0;
 
     // Send an MDA notification. This ultimately translates to an ICorDebugMDA object on the Right-Side.
@@ -286,12 +286,12 @@ public:
 
     virtual HRESULT GetILToNativeMappingIntoArrays(
         MethodDesc * pMethodDesc,
-        PCODE pCode, 
-        USHORT cMapMax, 
+        PCODE pCode,
+        USHORT cMapMax,
         USHORT * pcMap,
-        UINT ** prguiILOffset, 
+        UINT ** prguiILOffset,
         UINT ** prguiNativeOffset) = 0;
-    
+
     virtual DWORD GetHelperThreadID(void ) = 0;
 
     // Called whenever a new AppDomain is created, regardless of whether a debugger is attached.
@@ -304,9 +304,9 @@ public:
 
     virtual HRESULT UpdateAppDomainEntryInIPC (AppDomain *pAppDomain) = 0;
 
-    // Called when an assembly is being loaded into an AppDomain.  
+    // Called when an assembly is being loaded into an AppDomain.
     // This includes when a domain neutral assembly is loaded into a new AppDomain.
-    // This is called only when a debugger is attached, and will occur after the 
+    // This is called only when a debugger is attached, and will occur after the
     // related AddAppDomainToIPCBlock call and before any LoadModule or
     // LoadClass calls for this assembly.
     virtual void LoadAssembly(DomainAssembly * pDomainAssembly) = 0; // the assembly being loaded
@@ -409,7 +409,8 @@ public:
     virtual void EnumMemoryRegionsIfFuncEvalFrame(CLRDataEnumMemoryFlags flags, Frame * pFrame) = 0;
 #endif
 #ifndef DACCESS_COMPILE
-    virtual void SomeWork() = 0;
+    virtual void BeforeGarbageCollection() = 0;
+    virtual void AfterGarbageCollection() = 0;
 #endif
 };
 
index 41814d8..99b0817 100644 (file)
@@ -3,7 +3,7 @@
 // See the LICENSE file in the project root for more information.
 
 /*
- * GCENV.EE.CPP 
+ * GCENV.EE.CPP
  *
  * GCToEEInterface implementation
  *
@@ -21,7 +21,7 @@ void GCToEEInterface::SuspendEE(SUSPEND_REASON reason)
     _ASSERTE(reason == SUSPEND_FOR_GC || reason == SUSPEND_FOR_GC_PREP);
 
     // TODO, between the time when the debug event is sent and the EE is suspended, there is a small window that the data breakpoint could have already hit
-    g_pDebugInterface->SomeWork();
+    g_pDebugInterface->BeforeGarbageCollection();
 
     ThreadSuspend::SuspendEE((ThreadSuspend::SUSPEND_REASON)reason);
 }
@@ -31,6 +31,9 @@ void GCToEEInterface::RestartEE(bool bFinishedGC)
     WRAPPER_NO_CONTRACT;
 
     ThreadSuspend::RestartEE(bFinishedGC, TRUE);
+
+    // TODO, between the time when the debug event is sent and the EE is suspended, there is a small window that the data breakpoint could have already hit
+    g_pDebugInterface->AfterGarbageCollection();
 }
 
 VOID GCToEEInterface::SyncBlockCacheWeakPtrScan(HANDLESCANPROC scanProc, uintptr_t lp1, uintptr_t lp2)
@@ -46,8 +49,8 @@ VOID GCToEEInterface::SyncBlockCacheWeakPtrScan(HANDLESCANPROC scanProc, uintptr
 }
 
 
-//EE can perform post stack scanning action, while the 
-// user threads are still suspended 
+//EE can perform post stack scanning action, while the
+// user threads are still suspended
 VOID GCToEEInterface::AfterGcScanRoots (int condemned, int max_gen,
                                    ScanContext* sc)
 {
@@ -74,7 +77,7 @@ VOID GCToEEInterface::AfterGcScanRoots (int condemned, int max_gen,
 /*
  * Scan all stack roots
  */
+
 static void ScanStackRoots(Thread * pThread, promote_func* fn, ScanContext* sc)
 {
     GCCONTEXT   gcctx;
@@ -92,19 +95,19 @@ static void ScanStackRoots(Thread * pThread, promote_func* fn, ScanContext* sc)
     _ASSERTE(dbgOnly_IsSpecialEEThread() ||
                 GetThread() == NULL ||
                 // this is for background GC threads which always call this when EE is suspended.
-                IsGCSpecialThread() || 
+                IsGCSpecialThread() ||
                 (GetThread() == ThreadSuspend::GetSuspensionThread() && ThreadStore::HoldingThreadStore()));
 
     pThread->SetHasPromotedBytes();
 
     Frame* pTopFrame = pThread->GetFrame();
     Object ** topStack = (Object **)pTopFrame;
-    if ((pTopFrame != ((Frame*)-1)) 
+    if ((pTopFrame != ((Frame*)-1))
         && (pTopFrame->GetVTablePtr() == InlinedCallFrame::GetMethodFrameVPtr())) {
         // It is an InlinedCallFrame. Get SP from it.
         InlinedCallFrame* pInlinedFrame = (InlinedCallFrame*)pTopFrame;
         topStack = (Object **)pInlinedFrame->GetCallSiteSP();
-    } 
+    }
 
     sc->stack_limit = (uintptr_t)topStack;
 
@@ -144,11 +147,11 @@ static void ScanStackRoots(Thread * pThread, promote_func* fn, ScanContext* sc)
     }
     else
 #endif
-    {    
+    {
         unsigned flagsStackWalk = ALLOW_ASYNC_STACK_WALK | ALLOW_INVALID_OBJECTS;
-#if defined(WIN64EXCEPTIONS)            
+#if defined(WIN64EXCEPTIONS)
         flagsStackWalk |= GC_FUNCLET_REFERENCE_REPORTING;
-#endif // defined(WIN64EXCEPTIONS)                        
+#endif // defined(WIN64EXCEPTIONS)
         pThread->StackWalkFrames( GcStackCrawlCallBack, &gcctx, flagsStackWalk);
     }
 }
@@ -213,11 +216,11 @@ void GCToEEInterface::GcStartWork (int condemned, int max_gen)
     // Jupiter will
     // 1. Report reference from RCW to CCW based on native reference in Jupiter
     // 2. Identify the subset of CCWs that needs to be rooted
-    // 
+    //
     // We'll build the references from RCW to CCW using
     // 1. Preallocated arrays
     // 2. Dependent handles
-    // 
+    //
     RCWWalker::OnGCStarted(condemned);
 #endif // FEATURE_COMINTEROP
 
@@ -239,7 +242,7 @@ void GCToEEInterface::GcDone(int condemned)
 #ifdef FEATURE_COMINTEROP
     //
     // Tell Jupiter GC has finished
-    // 
+    //
     RCWWalker::OnGCFinished(condemned);
 #endif // FEATURE_COMINTEROP
 }
@@ -311,13 +314,13 @@ uint32_t GCToEEInterface::GetActiveSyncBlockCount()
     }
     CONTRACTL_END;
 
-    return SyncBlockCache::GetSyncBlockCache()->GetActiveCount();   
+    return SyncBlockCache::GetSyncBlockCache()->GetActiveCount();
 }
 
 gc_alloc_context * GCToEEInterface::GetAllocContext()
 {
     WRAPPER_NO_CONTRACT;
-    
+
     Thread* pThread = ::GetThread();
     assert(pThread != nullptr);
     return pThread->GetAllocContext();
@@ -494,7 +497,7 @@ void ProfScanRootsHelper(Object** ppObject, ScanContext *pSC, uint32_t dwFlags)
 
 // Returns TRUE if GC profiling is enabled and the profiler
 // should scan dependent handles, FALSE otherwise.
-BOOL ProfilerShouldTrackConditionalWeakTableElements() 
+BOOL ProfilerShouldTrackConditionalWeakTableElements()
 {
 #if defined(GC_PROFILING)
     return CORProfilerTrackConditionalWeakTableElements();
@@ -516,7 +519,7 @@ void ProfilerEndConditionalWeakTableElementReferences(void* heapId)
 
 // If GC profiling is enabled, informs the profiler that we are done
 // tracing root references.
-void ProfilerEndRootReferences2(void* heapId) 
+void ProfilerEndRootReferences2(void* heapId)
 {
 #if defined (GC_PROFILING)
     g_profControlBlock.pProfInterface->EndRootReferences2(heapId);
@@ -556,7 +559,7 @@ void ScanHandleForProfilerAndETW(Object** pRef, Object* pSec, uint32_t flags, Sc
                 (uint8_t *)*pRef,
                 kEtwGCRootKindHandle,
                 (EtwGCRootFlags)flags,
-                pRef, 
+                pRef,
                 &pSC->pHeapId);
             END_PIN_PROFILER();
         }
@@ -586,7 +589,7 @@ void ScanHandleForProfilerAndETW(Object** pRef, Object* pSec, uint32_t flags, Sc
             0,              // dwGCFlags,
             flags);     // ETW handle flags
     }
-#endif // defined(FEATURE_EVENT_TRACE) 
+#endif // defined(FEATURE_EVENT_TRACE)
 }
 
 // This is called only if we've determined that either:
@@ -677,7 +680,7 @@ void GCProfileWalkHeap()
 #ifdef FEATURE_EVENT_TRACE
     if (ETW::GCLog::ShouldWalkStaticsAndCOMForEtw())
         ETW::GCLog::WalkStaticsAndCOMForETW();
-    
+
     BOOL fShouldWalkHeapRootsForEtw = ETW::GCLog::ShouldWalkHeapRootsForEtw();
     BOOL fShouldWalkHeapObjectsForEtw = ETW::GCLog::ShouldWalkHeapObjectsForEtw();
 #else // !FEATURE_EVENT_TRACE
@@ -730,7 +733,7 @@ void GCToEEInterface::DiagGCStart(int gen, bool isInduced)
         END_PIN_PROFILER();
     }
 
-#endif // GC_PROFILING    
+#endif // GC_PROFILING
 }
 
 void GCToEEInterface::DiagUpdateGenerationBounds()
@@ -768,9 +771,9 @@ void GCToEEInterface::DiagWalkFReachableObjects(void* gcContext)
 // Note on last parameter: when calling this for bgc, only ETW
 // should be sending these events so that existing profapi profilers
 // don't get confused.
-void WalkMovedReferences(uint8_t* begin, uint8_t* end, 
+void WalkMovedReferences(uint8_t* begin, uint8_t* end,
                          ptrdiff_t reloc,
-                         void* context, 
+                         void* context,
                          bool fCompacting,
                          bool fBGC)
 {
@@ -855,7 +858,7 @@ void GCToEEInterface::StompWriteBarrier(WriteBarrierParameters* args)
         // We need to make sure that other threads executing checked write barriers
         // will see the g_card_table update before g_lowest/highest_address updates.
         // Otherwise, the checked write barrier may AV accessing the old card table
-        // with address that it does not cover. 
+        // with address that it does not cover.
         //
         // Even x86's total store ordering is insufficient here because threads reading
         // g_card_table do so via the instruction cache, whereas g_lowest/highest_address
@@ -931,7 +934,7 @@ void GCToEEInterface::StompWriteBarrier(WriteBarrierParameters* args)
         assert(g_card_bundle_table == nullptr);
         g_card_bundle_table = args->card_bundle_table;
 #endif
-        
+
         g_lowest_address = args->lowest_address;
         g_highest_address = args->highest_address;
         stompWBCompleteActions |= ::StompWriteBarrierResize(true, false);
@@ -968,13 +971,13 @@ void GCToEEInterface::StompWriteBarrier(WriteBarrierParameters* args)
     default:
         assert(!"unknown WriteBarrierOp enum");
     }
-    if (stompWBCompleteActions & SWB_ICACHE_FLUSH) 
+    if (stompWBCompleteActions & SWB_ICACHE_FLUSH)
     {
         ::FlushWriteBarrierInstructionCache();
     }
-    if (stompWBCompleteActions & SWB_EE_RESTART) 
+    if (stompWBCompleteActions & SWB_EE_RESTART)
     {
-        assert(!args->is_runtime_suspended && 
+        assert(!args->is_runtime_suspended &&
             "if runtime was suspended in patching routines then it was in running state at begining");
         ThreadSuspend::RestartEE(FALSE, TRUE);
     }
@@ -1137,7 +1140,7 @@ bool GCToEEInterface::GetStringConfigValue(const char* key, const char** value)
         return false;
     }
 
-    if (WideCharToMultiByte(CP_ACP, 0, out, -1 /* out is null-terminated */, 
+    if (WideCharToMultiByte(CP_ACP, 0, out, -1 /* out is null-terminated */,
           configResult.GetValue(), MaxConfigKeyLength, nullptr, nullptr) == 0)
     {
         // this should only happen if the config subsystem gives us a string that's not valid