From: Andrew Au Date: Thu, 10 May 2018 21:49:39 +0000 (-0700) Subject: The GC events are now working, somewhat ... X-Git-Tag: submit/tizen/20210909.063632~11030^2~3493 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8a2225b9c2d457cf27486d21ba5703c9d4d5f492;p=platform%2Fupstream%2Fdotnet%2Fruntime.git The GC events are now working, somewhat ... Commit migrated from https://github.com/dotnet/coreclr/commit/c6d26187c8ce8fc68829f262a79996f00b1e1a85 --- diff --git a/src/coreclr/src/debug/di/process.cpp b/src/coreclr/src/debug/di/process.cpp index a49addc..18e0ac7 100644 --- a/src/coreclr/src/debug/di/process.cpp +++ b/src/coreclr/src/debug/di/process.cpp @@ -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 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(&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 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 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 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(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(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 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 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 (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* 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 (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* 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 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 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(this)); + } + break; + } + + case DB_IPCE_AFTER_GARBAGE_COLLECTION: { { PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent); - pCallback4->SomeWork(pThread, pAppDomain); + pCallback4->AfterGarbageCollection(static_cast(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 (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 * 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 (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 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 pEnum; CordbHashTableEnum::BuildOrThrow( - this, - GetContinueNeuterList(), + this, + GetContinueNeuterList(), &m_appDomains, IID_ICorDebugAppDomainEnum, pEnum.GetAddr()); - + *ppAppDomains = static_cast (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 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(pLocalManagedEvent), - CORDB_ADDRESS_TO_PTR(ptrRemoteManagedEvent), + memcpy(reinterpret_cast(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 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 pCallback2; - pCallback->QueryInterface(IID_ICorDebugManagedCallback2, reinterpret_cast (&pCallback2)); + pCallback->QueryInterface(IID_ICorDebugManagedCallback2, reinterpret_cast (&pCallback2)); RSExtSmartPtr pCallback3; - pCallback->QueryInterface(IID_ICorDebugManagedCallback3, reinterpret_cast (&pCallback3)); + pCallback->QueryInterface(IID_ICorDebugManagedCallback3, reinterpret_cast (&pCallback3)); RSExtSmartPtr pCallback4; pCallback->QueryInterface(IID_ICorDebugManagedCallback4, reinterpret_cast (&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 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 (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(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(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 (pICorDebugThread); return GetDAC()->IsThreadSuspendedOrHijacked(pCordbThread->m_vmThreadToken); } diff --git a/src/coreclr/src/debug/di/rsmain.cpp b/src/coreclr/src/debug/di/rsmain.cpp index 39ac60d..d9f25e6 100644 --- a/src/coreclr/src/debug/di/rsmain.cpp +++ b/src/coreclr/src/debug/di/rsmain.cpp @@ -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 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(static_cast(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; diff --git a/src/coreclr/src/debug/di/shimcallback.cpp b/src/coreclr/src/debug/di/shimcallback.cpp index 35e9f38..00501da 100644 --- a/src/coreclr/src/debug/di/shimcallback.cpp +++ b/src/coreclr/src/debug/di/shimcallback.cpp @@ -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 #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 pNewFrame; EX_TRY @@ -102,16 +102,16 @@ ICorDebugFrame * UpdateFrame(ICorDebugThread * pThread, ICorDebugFrame * pOldFra if (pFrame != NULL) { FramePointer fp = pFrame->GetFramePointer(); - + CordbThread * pThread2 = static_cast (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 m_pAppDomain; - RSExtSmartPtr m_pThread; + RSExtSmartPtr 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 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; } + diff --git a/src/coreclr/src/debug/di/shimpriv.h b/src/coreclr/src/debug/di/shimpriv.h index acd3ef5..0f2d803 100644 --- a/src/coreclr/src/debug/di/shimpriv.h +++ b/src/coreclr/src/debug/di/shimpriv.h @@ -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 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 m_pIProcess; + RSExtSmartPtr 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 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 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 m_stackChains; // growable ordered array of chains and frames - CDynArray m_stackFrames; + CDynArray 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 m_refCount; + Volatile 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 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(); diff --git a/src/coreclr/src/debug/ee/debugger.cpp b/src/coreclr/src/debug/ee/debugger.cpp index cdb7380..096c0d2 100644 --- a/src/coreclr/src/debug/ee/debugger.cpp +++ b/src/coreclr/src/debug/ee/debugger.cpp @@ -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++; } - + // // What should we do in this case? // @@ -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(&s_DebuggerLaunchJitInfoExceptionRecord); s_DebuggerLaunchJitInfo.lpContextRecord = reinterpret_cast(&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(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(); diff --git a/src/coreclr/src/debug/ee/debugger.h b/src/coreclr/src/debug/ee/debugger.h index 0b1cbac..97f9832 100644 --- a/src/coreclr/src/debug/ee/debugger.h +++ b/src/coreclr/src/debug/ee/debugger.h @@ -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 +template class GCHolderEEInterface { 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 +template class GCHolderEEInterface { 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 __gcCoop_onlyOneAllowedPerScope - + #define GCX_PREEMP_EEINTERFACE() \ GCHolderEEInterface __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. // 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 *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 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 } 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 #endif // DACCESS_COMPILE Module * pModule1 = reinterpret_cast(k1); - Module * pModule2 = + Module * pModule2 = dac_cast(const_cast(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 } }; diff --git a/src/coreclr/src/debug/inc/dbgipceventtypes.h b/src/coreclr/src/debug/inc/dbgipceventtypes.h index 49bf156..7721115 100644 --- a/src/coreclr/src/debug/inc/dbgipceventtypes.h +++ b/src/coreclr/src/debug/inc/dbgipceventtypes.h @@ -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 diff --git a/src/coreclr/src/inc/cordebug.idl b/src/coreclr/src/inc/cordebug.idl index cbe77881..69be972 100644 --- a/src/coreclr/src/inc/cordebug.idl +++ b/src/coreclr/src/inc/cordebug.idl @@ -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) not any of - the specific instantiations (eg. List). - + For generic types, it represents the generic type definition (eg. List) not any of + the specific instantiations (eg. List). + 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) * 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); diff --git a/src/coreclr/src/pal/prebuilt/idl/cordebug_i.cpp b/src/coreclr/src/pal/prebuilt/idl/cordebug_i.cpp index 26dcc00..69d03ac 100644 --- a/src/coreclr/src/pal/prebuilt/idl/cordebug_i.cpp +++ b/src/coreclr/src/pal/prebuilt/idl/cordebug_i.cpp @@ -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 diff --git a/src/coreclr/src/pal/prebuilt/inc/cordebug.h b/src/coreclr/src/pal/prebuilt/inc/cordebug.h index 66eaf20..fd61bd1 100644 --- a/src/coreclr/src/pal/prebuilt/inc/cordebug.h +++ b/src/coreclr/src/pal/prebuilt/inc/cordebug.h @@ -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 */ diff --git a/src/coreclr/src/vm/dbginterface.h b/src/coreclr/src/vm/dbginterface.h index 71af1b4..a855a10 100644 --- a/src/coreclr/src/vm/dbginterface.h +++ b/src/coreclr/src/vm/dbginterface.h @@ -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 }; diff --git a/src/coreclr/src/vm/gcenv.ee.cpp b/src/coreclr/src/vm/gcenv.ee.cpp index 41814d8..99b0817 100644 --- a/src/coreclr/src/vm/gcenv.ee.cpp +++ b/src/coreclr/src/vm/gcenv.ee.cpp @@ -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