1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 //*****************************************************************************
9 //*****************************************************************************
11 #include "primitives.h"
16 #ifndef SM_REMOTESESSION
17 #define SM_REMOTESESSION 0x1000
22 #include "../../dlls/mscorrc/resource.h"
27 // @dbgtodo shim: process has some private hooks into the shim.
30 #include "metadataexports.h"
31 #include "readonlydatatargetfacade.h"
34 // Keep this around for retail debugging. It's very very useful because
35 // it's global state that we can always find, regardless of how many locals the compiler
37 struct RSDebuggingInfo;
38 extern RSDebuggingInfo * g_pRSDebuggingInfo;
40 //---------------------------------------------------------------------------------------
42 // OpenVirtualProcessImpl method called by the shim to get an ICorDebugProcess4 instance
45 // clrInstanceId - target pointer identifying which CLR in the Target to debug.
46 // pDataTarget - data target abstraction.
47 // hDacModule - the handle of the appropriate DAC dll for this runtime
48 // riid - interface ID to query for.
49 // ppProcessOut - new object for target, interface ID matches riid.
50 // ppFlagsOut - currently only has 1 bit to indicate whether or not this runtime
51 // instance will send a managed event after attach
54 // S_OK on success. Else failure
59 // The outgoing process object can be cleaned up by calling Detach (which
60 // will reset the Attach bit.)
61 // @dbgtodo attach-bit: need to determine fate of attach bit.
63 //---------------------------------------------------------------------------------------
64 STDAPI OpenVirtualProcessImpl(
65 ULONG64 clrInstanceId,
66 IUnknown * pDataTarget,
68 CLR_DEBUGGING_VERSION * pMaxDebuggerSupportedVersion,
70 IUnknown ** ppInstance,
71 CLR_DEBUGGING_PROCESS_FLAGS* pFlagsOut)
74 RSExtSmartPtr<CordbProcess> pProcess;
75 PUBLIC_API_ENTRY(NULL);
79 if ( (pDataTarget == NULL) || (clrInstanceId == 0) || (pMaxDebuggerSupportedVersion == NULL) ||
80 ((pFlagsOut == NULL) && (ppInstance == NULL))
83 ThrowHR(E_INVALIDARG);
86 // We consider the top 8 bits of the struct version to be the only part that represents
87 // a breaking change. This gives us some freedom in the future to have the debugger
88 // opt into getting more data.
89 const WORD kMajorMask = 0xff00;
90 const WORD kMaxStructMajor = 0;
91 if ((pMaxDebuggerSupportedVersion->wStructVersion & kMajorMask) > kMaxStructMajor)
93 // Don't know how to interpret the version structure
94 ThrowHR(CORDBG_E_UNSUPPORTED_VERSION_STRUCT);
97 // This process object is intended to be used for the V3 pipeline, and so
98 // much of the process from V2 is not being used. For example,
99 // - there is no ShimProcess object
100 // - there is no w32et thread (all threads are effectively an event thread)
101 // - the stop state is 'live', which corresponds to CordbProcess not knowing what
102 // its stop state really is (because that is now controlled by the shim).
103 IfFailThrow(CordbProcess::OpenVirtualProcess(
105 pDataTarget, // takes a reference
108 (DWORD) 0, // 0 for V3 cases (pShim == NULL).
109 NULL, // no Shim in V3 cases
112 // CordbProcess::OpenVirtualProcess already did the external addref to pProcess.
113 // Since pProcess is a smart ptr, it will external release in this function.
114 // Living reference will be the one from the QI.
116 // get the managed debug event pending flag
117 if(pFlagsOut != NULL)
119 hr = pProcess->GetAttachStateFlags(pFlagsOut);
127 // Check to make sure the debugger supports debugging this version
128 // Note that it's important that we still store the flags (above) in this case
130 if (!CordbProcess::IsCompatibleWith(pMaxDebuggerSupportedVersion->wMajor))
132 // Not compatible - don't keep the process instance, and return this specific error-code
133 ThrowHR(CORDBG_E_UNSUPPORTED_FORWARD_COMPAT);
137 // Now Query for the requested interface
139 if(ppInstance != NULL)
141 IfFailThrow(pProcess->QueryInterface(riid, reinterpret_cast<void**> (ppInstance)));
144 // if you have to add code here that could fail make sure ppInstance gets released and NULL'ed at exit
146 EX_CATCH_HRESULT(hr);
148 if((FAILED(hr) || ppInstance == NULL) && pProcess != NULL)
150 // The process has a strong reference to itself which is only released by neutering it.
151 // Since we aren't handing out the ref then we need to clean it up
152 _ASSERTE(ppInstance == NULL || *ppInstance == NULL);
158 //---------------------------------------------------------------------------------------
159 // DEPRECATED - use OpenVirtualProcessImpl
160 // OpenVirtualProcess method used by the shim in CLR v4 Beta1
161 // We'd like a beta1 shim/VS to still be able to open dumps using a CLR v4 Beta2+ mscordbi.dll,
162 // so we'll leave this in place (at least until after Beta2 is in wide use).
163 //---------------------------------------------------------------------------------------
164 STDAPI OpenVirtualProcess2(
165 ULONG64 clrInstanceId,
166 IUnknown * pDataTarget,
169 IUnknown ** ppInstance,
170 CLR_DEBUGGING_PROCESS_FLAGS* pFlagsOut)
172 CLR_DEBUGGING_VERSION maxVersion = {0};
173 maxVersion.wMajor = 4;
174 return OpenVirtualProcessImpl(clrInstanceId, pDataTarget, hDacModule, &maxVersion, riid, ppInstance, pFlagsOut);
177 //---------------------------------------------------------------------------------------
178 // DEPRECATED - use OpenVirtualProcessImpl
179 // Public OpenVirtualProcess method to get an ICorDebugProcess4 instance
180 // Used directly in CLR v4 pre Beta1 - can probably be safely removed now
181 //---------------------------------------------------------------------------------------
182 STDAPI OpenVirtualProcess(
183 ULONG64 clrInstanceId,
184 IUnknown * pDataTarget,
186 IUnknown ** ppInstance)
188 return OpenVirtualProcess2(clrInstanceId, pDataTarget, NULL, riid, ppInstance, NULL);
191 //-----------------------------------------------------------------------------
192 // Most Hresults to Unrecoverable error indicate an internal error
193 // in the Right-Side.
194 // However, a few are legal (eg, "could actually happen in a retail scenario and
195 // not indicate an issue in mscorbi"). Track that here.
196 //-----------------------------------------------------------------------------
198 bool IsLegalFatalError(HRESULT hr)
201 (hr == CORDBG_E_INCOMPATIBLE_PROTOCOL) ||
202 (hr == CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS) ||
203 (hr == CORDBG_E_UNCOMPATIBLE_PLATFORMS) ||
204 (hr == CORDBG_E_MISMATCHED_CORWKS_AND_DACWKS_DLLS) ||
205 // This should only happen in the case of a security attack on us.
206 (hr == E_ACCESSDENIED) ||
210 //-----------------------------------------------------------------------------
211 // Safe wait. Use this anytime we're waiting on:
212 // - an event signaled by the helper thread.
213 // - something signaled by a thread that holds the process lock.
214 // Note that we must preserve GetLastError() semantics.
215 //-----------------------------------------------------------------------------
216 inline DWORD SafeWaitForSingleObject(CordbProcess * p, HANDLE h, DWORD dwTimeout)
218 // Can't hold process lock while blocking
219 _ASSERTE(!p->ThreadHoldsProcessLock());
221 return ::WaitForSingleObject(h, dwTimeout);
224 #define CORDB_WAIT_TIMEOUT 360000 // milliseconds
226 //---------------------------------------------------------------------------------------
228 // Get the timeout value used in waits.
231 // Number of milliseconds to waite or possible INFINITE (-1).
235 // Uses registry values for fine tuning.
239 static inline DWORD CordbGetWaitTimeout()
243 // 1 = Wait for CORDB_WAIT_TIMEOUT
244 // n = Wait for n milliseconds
245 static ConfigDWORD cordbWaitTimeout;
246 DWORD dwTimeoutVal = cordbWaitTimeout.val(CLRConfig::INTERNAL_DbgWaitTimeout);
247 if (dwTimeoutVal == 0)
249 else if (dwTimeoutVal != 1)
254 return CORDB_WAIT_TIMEOUT;
258 //----------------------------------------------------------------------------
259 // Implementation of IDacDbiInterface::IMetaDataLookup.
260 // lookup Internal Metadata Importer keyed by PEFile
261 // isILMetaDataForNGENImage is true iff the IMDInternalImport returned represents a pointer to
262 // metadata from an IL image when the module was an ngen'ed image.
263 IMDInternalImport * CordbProcess::LookupMetaData(VMPTR_PEFile vmPEFile, bool &isILMetaDataForNGENImage)
265 INTERNAL_DAC_CALLBACK(this);
267 HASHFIND hashFindAppDomain;
268 HASHFIND hashFindModule;
269 IMDInternalImport * pMDII = NULL;
270 isILMetaDataForNGENImage = false;
272 // Check to see if one of the cached modules has the metadata we need
273 // If not we will do a more exhaustive search below
274 for (CordbAppDomain * pAppDomain = m_appDomains.FindFirst(&hashFindAppDomain);
276 pAppDomain = m_appDomains.FindNext(&hashFindAppDomain))
278 for (CordbModule * pModule = pAppDomain->m_modules.FindFirst(&hashFindModule);
280 pModule = pAppDomain->m_modules.FindNext(&hashFindModule))
282 if (pModule->GetPEFile() == vmPEFile)
285 ALLOW_DATATARGET_MISSING_MEMORY(
286 pMDII = pModule->GetInternalMD();
294 // Cache didn't have it... time to search harder
295 PrepopulateAppDomainsOrThrow();
297 // There may be perf issues here. The DAC may make a lot of metadata requests, and so
298 // this may be an area for potential perf optimizations if we find things running slow.
300 // enumerate through all Modules
301 for (CordbAppDomain * pAppDomain = m_appDomains.FindFirst(&hashFindAppDomain);
303 pAppDomain = m_appDomains.FindNext(&hashFindAppDomain))
305 pAppDomain->PrepopulateModules();
307 for (CordbModule * pModule = pAppDomain->m_modules.FindFirst(&hashFindModule);
309 pModule = pAppDomain->m_modules.FindNext(&hashFindModule))
311 if (pModule->GetPEFile() == vmPEFile)
314 ALLOW_DATATARGET_MISSING_MEMORY(
315 pMDII = pModule->GetInternalMD();
320 // If we couldn't get metadata from the CordbModule, then we need to ask the
321 // debugger if it can find the metadata elsewhere.
322 // If this was live debugging, we should have just gotten the memory contents.
323 // Thus this code is for dump debugging, when you don't have the metadata in the dump.
324 pMDII = LookupMetaDataFromDebugger(vmPEFile, isILMetaDataForNGENImage, pModule);
335 IMDInternalImport * CordbProcess::LookupMetaDataFromDebugger(
336 VMPTR_PEFile vmPEFile,
337 bool &isILMetaDataForNGENImage,
338 CordbModule * pModule)
340 DWORD dwImageTimeStamp = 0;
341 DWORD dwImageSize = 0;
343 StringCopyHolder filePath;
344 IMDInternalImport * pMDII = NULL;
346 // First, see if the debugger can locate the exact metadata we want.
347 if (this->GetDAC()->GetMetaDataFileInfoFromPEFile(vmPEFile, dwImageTimeStamp, dwImageSize, isNGEN, &filePath))
349 _ASSERTE(filePath.IsSet());
351 // Since we track modules by their IL images, that presents a little bit of oddness here. The correct
352 // thing to do is preferentially load the NI content.
353 // We don't discriminate between timestamps & sizes becuase CLRv4 deterministic NGEN guarantees that the
354 // IL image and NGEN image have the same timestamp and size. Should that guarantee change, this code
355 // will be horribly broken.
357 // If we happen to have an NI file path, use it instead.
358 const WCHAR * pwszFilePath = pModule->GetNGenImagePath();
361 // Force the issue, regardless of the older codepath's opinion.
366 pwszFilePath = (WCHAR *)filePath;
369 ALLOW_DATATARGET_MISSING_MEMORY(
370 pMDII = LookupMetaDataFromDebuggerForSingleFile(pModule, pwszFilePath, dwImageTimeStamp, dwImageSize);
373 // If it's an ngen'ed image and the debugger couldn't find it, we can use the metadata from
374 // the corresponding IL image if the debugger can locate it.
376 if ((pMDII == NULL) &&
378 (this->GetDAC()->GetILImageInfoFromNgenPEFile(vmPEFile, dwImageTimeStamp, dwImageSize, &filePath)))
380 _ASSERTE(filePath.IsSet());
382 WCHAR *mutableFilePath = (WCHAR *)filePath;
384 #if defined(FEATURE_CORESYSTEM)
385 size_t pathLen = wcslen(mutableFilePath);
387 const wchar_t *nidll = W(".ni.dll");
388 const wchar_t *niexe = W(".ni.exe");
389 const size_t dllLen = wcslen(nidll); // used for ni.exe as well
391 const wchar_t *niwinmd = W(".ni.winmd");
392 const size_t winmdLen = wcslen(niwinmd);
394 if (pathLen > dllLen && _wcsicmp(mutableFilePath+pathLen-dllLen, nidll) == 0)
396 wcscpy_s(mutableFilePath+pathLen-dllLen, dllLen, W(".dll"));
398 else if (pathLen > dllLen && _wcsicmp(mutableFilePath+pathLen-dllLen, niexe) == 0)
400 wcscpy_s(mutableFilePath+pathLen-dllLen, dllLen, W(".exe"));
402 else if (pathLen > winmdLen && _wcsicmp(mutableFilePath+pathLen-winmdLen, niwinmd) == 0)
404 wcscpy_s(mutableFilePath+pathLen-winmdLen, winmdLen, W(".winmd"));
406 #endif//FEATURE_CORESYSTEM
408 ALLOW_DATATARGET_MISSING_MEMORY(
409 pMDII = LookupMetaDataFromDebuggerForSingleFile(pModule, mutableFilePath, dwImageTimeStamp, dwImageSize);
414 isILMetaDataForNGENImage = true;
421 // We do not know if the image being sent to us is an IL image or ngen image.
422 // CordbProcess::LookupMetaDataFromDebugger() has this knowledge when it looks up the file to hand off
424 // DacDbiInterfaceImpl::GetMDImport() has this knowledge in the isNGEN flag.
425 // The CLR v2 code that windbg used made a distinction whether the metadata came from
426 // the exact binary or not (i.e. were we getting metadata from the IL image and using
427 // it against the ngen image?) but that information was never used and so not brought forward.
428 // It would probably be more interesting generally to track whether the debugger gives us back
429 // a file that bears some relationship to the file we asked for, which would catch the NI/IL case
431 IMDInternalImport * CordbProcess::LookupMetaDataFromDebuggerForSingleFile(
432 CordbModule * pModule,
433 LPCWSTR pwszFilePath,
437 INTERNAL_DAC_CALLBACK(this);
439 ULONG32 cchLocalImagePath = MAX_LONGPATH;
440 ULONG32 cchLocalImagePathRequired;
441 NewArrayHolder<WCHAR> pwszLocalFilePath = NULL;
442 IMDInternalImport * pMDII = NULL;
444 const HRESULT E_NSF_BUFFER = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
445 HRESULT hr = E_NSF_BUFFER;
446 for(unsigned i=0; i<2 && hr == E_NSF_BUFFER; i++)
448 if (pwszLocalFilePath != NULL)
449 pwszLocalFilePath.Release();
451 if (NULL == (pwszLocalFilePath = new (nothrow) WCHAR[cchLocalImagePath+1]))
452 ThrowHR(E_OUTOFMEMORY);
454 cchLocalImagePathRequired = 0;
456 hr = m_pMetaDataLocator->GetMetaData(pwszFilePath,
460 &cchLocalImagePathRequired,
463 pwszLocalFilePath[cchLocalImagePath] = W('\0');
464 cchLocalImagePath = cchLocalImagePathRequired;
469 hr = pModule->InitPublicMetaDataFromFile(pwszLocalFilePath, ofReadOnly, false);
472 // While we're successfully returning a metadata reader, remember that there's
473 // absolutely no guarantee this metadata is an exact match for the vmPEFile.
474 // The debugger could literally send us back a path to any managed file with
475 // metadata content that is readable and we'll 'succeed'.
476 // For now, this is by-design. A debugger should be allowed to decide if it wants
477 // to take a risk by returning 'mostly matching' metadata to see if debugging is
478 // possible in the absense of a true match.
479 pMDII = pModule->GetInternalMD();
487 //---------------------------------------------------------------------------------------
489 // Implement IDacDbiInterface::IAllocator::Alloc
490 // Expected to throws on error.
493 // lenBytes - size of the byte array to allocate
496 // Return the newly allocated byte array, or throw on OOM
499 // Since this function is a callback from DAC, it must not take the process lock.
500 // If it does, we may deadlock between the DD lock and the process lock.
501 // If we really need to take the process lock for whatever reason, we must take it in the DBI functions
502 // which call the DAC API that ends up calling this function.
503 // See code:InternalDacCallbackHolder for more information.
506 void * CordbProcess::Alloc(SIZE_T lenBytes)
508 return new BYTE[lenBytes]; // throws
511 //---------------------------------------------------------------------------------------
513 // Implements IDacDbiInterface::IAllocator::Free
516 // p - pointer to the memory to be released
519 // Since this function is a callback from DAC, it must not take the process lock.
520 // If it does, we may deadlock between the DD lock and the process lock.
521 // If we really need to take the process lock for whatever reason, we must take it in the DBI functions
522 // which call the DAC API that ends up calling this function.
523 // See code:InternalDacCallbackHolder for more information.
526 void CordbProcess::Free(void * p)
528 // This shouldn't throw.
529 delete [] ((BYTE *) p);
533 //---------------------------------------------------------------------------------------
535 // #DBIVersionChecking
537 // There are a few checks we need to do to make sure we are using the matching DBI and DAC for a particular
538 // version of the runtime.
540 // 1. Runtime vs. DBI
542 // This is done by making sure that the CorDebugInterfaceVersion passed to code:CreateCordbObject is
543 // compatible with the version of the DBI.
546 // This is done by dbgshim.dll. It checks whether the runtime DLL and the DBI DLL have the same
547 // product version. See CreateDebuggingInterfaceForVersion() in dbgshim.cpp.
549 // - Remote transport (Mac CoreCLR + CoreSystem CoreCLR)
550 // Since there is no dbgshim.dll for a remote CoreCLR, we have to do this check in some other place.
551 // We do this in code:CordbProcess::CreateDacDbiInterface, by calling
552 // code:DacDbiInterfaceImpl::CheckDbiVersion right after we have created the DDMarshal.
553 // The IDacDbiInterface implementation on remote device checks the product version of the device
555 // mac - looking at the Info.plist file in the CoreCLR bundle.
556 // CoreSystem - this check is skipped at the moment, but should be implemented if we release it
558 // The one twist here is that the DBI needs to communicate with the IDacDbiInterface
559 // implementation on the device BEFORE it can verify the product versions. This means that we need to
560 // have one IDacDbiInterface API which is consistent across all versions of the IDacDbiInterface.
561 // This puts two constraints on CheckDbiVersion():
563 // 1. It has to be the first API on the IDacDbiInterface.
564 // - Otherwise, a wrong version of the DBI may end up calling a different API on the
565 // IDacDbiInterface and getting random results. (Really what matters is that it is
566 // protocol message id 0, at present the source code position implies the message id)
568 // 2. Its parameters cannot change.
569 // - Otherwise, we may run into random errors when we marshal/unmarshal the arguments for the
570 // call to CheckDbiVersion(). Debugging will still fail, but we won't get the
571 // version mismatch error. (Again, the protocol is what ultimately matters)
572 // - To mitigate the impact of this constraint, we use the code:DbiVersion structure.
573 // In addition to the DBI version, it also contains a format number (in case we decide to
574 // check something else in the future), a breaking change number so that we can force
575 // breaking changes between a DBI and a DAC, and space reserved for future use.
578 // - Desktop and Windows CoreCLR (old architecture)
579 // No verification is done. There is a transitive implication that if DBI matches runtime and DAC matches
580 // runtime then DBI matches DAC. Technically because the DBI only matches runtime on major version number
581 // runtime and DAC could be from different builds. However because we service all three binaries together
582 // and DBI always loads the DAC that is sitting in the same directory DAC and DBI generally get tight
583 // version coupling. A user with admin privleges could put different builds together and no version check
584 // would ever fail though.
586 // - Desktop and Windows CoreCLR (new architecture)
587 // No verification is done. Similar to above its implied that if DBI matches runtime and runtime matches
588 // DAC then DBI matches DAC. The only difference is that here both the DBI and DAC are provided by the
589 // debugger. We provide timestamp and filesize for both binaries which are relatively strongly bound hints,
590 // but there is no enforcement on the returned binaries beyond the runtime compat checking.
592 // - Remote transport (Mac CoreCLR and CoreSystem CoreCLR)
593 // Because the transport exists between DBI and DAC it becomes much more important to do a versioning check
595 // Mac - currently does a tightly bound version check between DBI and the runtime (CheckDbiVersion() above),
596 // which transitively gives a tightly bound check to DAC. In same function there is also a check that is
597 // logically a DAC DBI protocol check, verifying that the m_dwProtocolBreakingChangeCounter of DbiVersion
598 // matches. However this check should be weaker than the build version check and doesn't add anything here.
600 // CoreSystem - currently skips the tightly bound version check to make internal deployment and usage easier.
601 // We want to use old desktop side debugger components to target newer CoreCLR builds, only forcing a desktop
602 // upgrade when the protocol actually does change. To do this we use two checks:
603 // 1. The breaking change counter in CheckDbiVersion() whenever a dev knows they are breaking back
604 // compat and wants to be explicit about it. This is the same as mac above.
605 // 2. During the auto-generation of the DDMarshal classes we take an MD5 hash of IDacDbiInterface source
606 // code and embed it in two DDMarshal functions, one which runs locally and one that runs remotely.
607 // If both DBI and DAC were built from the same source then the local and remote hashes will match. If the
608 // hashes don't match then we assume there has been a been a breaking change in the protocol. Note
609 // this hash could have both false-positives and false-negatives. False positives could occur when
610 // IDacDbiInterface is changed in a trivial way, such as changing a comment. False negatives could
611 // occur when the semantics of the protocol are changed even though the interface is not. Another
612 // case would be changing the DDMarshal proxy generation code. In addition to the hashes we also
613 // embed timestamps when the auto-generated code was produced. However this isn't used for version
614 // matching, only as a hint to indicate which of two mismatched versions is newer.
617 // 3. Runtime vs. DAC
618 // - Desktop, Windows CoreCLR, CoreSystem CoreCLR
619 // In both cases we check this by matching the timestamp in the debug directory of the runtime image
620 // and the timestamp we store in the DAC table when we generate the DAC dll. This is done in
621 // code:ClrDataAccess::VerifyDlls.
624 // On Mac, we don't have a timestamp in the runtime image. Instead, we rely on checking the 16-byte
625 // UUID in the image. This UUID is used to check whether a symbol file matches the image, so
626 // conceptually it's the same as the timestamp we use on Windows. This is also done in
627 // code:ClrDataAccess::VerifyDlls.
629 //---------------------------------------------------------------------------------------
631 // Instantiates a DacDbi Interface object in a live-debugging scenario that matches
632 // the current instance of mscorwks in this process.
635 // Returns on success. Else throws.
638 // Client will code:CordbProcess::FreeDac when its done with the DacDbi interface.
639 // Caller has initialized clrInstanceId.
642 // This looks for the DAC next to this current DBI. This assumes that Dac and Dbi are both on
643 // the local file system. That assumption will break in zero-copy deployment scenarios.
645 //---------------------------------------------------------------------------------------
647 CordbProcess::CreateDacDbiInterface()
649 _ASSERTE(m_pDACDataTarget != NULL);
650 _ASSERTE(m_pDacPrimitives == NULL); // don't double-init
652 // Caller has already determined which CLR in the target is being debugged.
653 _ASSERTE(m_clrInstanceId != 0);
655 m_pDacPrimitives = NULL;
657 HRESULT hrStatus = S_OK;
659 // Non-marshalling path for live local dac.
660 // in the new arch we can get the module from OpenVirtualProcess2 but in the shim case
661 // and the deprecated OpenVirtualProcess case we must assume it comes from DAC in the
662 // same directory as DBI
663 if(m_hDacModule == NULL)
665 m_hDacModule.Assign(ShimProcess::GetDacModule());
669 // Get the access interface, passing our callback interfaces (data target, allocator and metadata lookup)
672 IDacDbiInterface::IAllocator * pAllocator = this;
673 IDacDbiInterface::IMetaDataLookup * pMetaDataLookup = this;
676 typedef HRESULT (STDAPICALLTYPE * PFN_DacDbiInterfaceInstance)(
677 ICorDebugDataTarget *,
679 IDacDbiInterface::IAllocator *,
680 IDacDbiInterface::IMetaDataLookup *,
681 IDacDbiInterface **);
683 IDacDbiInterface* pInterfacePtr = NULL;
684 PFN_DacDbiInterfaceInstance pfnEntry = (PFN_DacDbiInterfaceInstance)GetProcAddress(m_hDacModule, "DacDbiInterfaceInstance");
690 hrStatus = pfnEntry(m_pDACDataTarget, m_clrInstanceId, pAllocator, pMetaDataLookup, &pInterfacePtr);
691 IfFailThrow(hrStatus);
693 // We now have a resource, pInterfacePtr, that needs to be freed.
694 m_pDacPrimitives = pInterfacePtr;
696 // Setup DAC target consistency checking based on what we're using for DBI
697 m_pDacPrimitives->DacSetTargetConsistencyChecks( m_fAssertOnTargetInconsistency );
700 //---------------------------------------------------------------------------------------
702 // Is the DAC/DBI interface initialized?
708 // The RS will try to initialize DD as soon as it detects the runtime as loaded.
709 // If the DD interface has not initialized, then it very likely the runtime has not
710 // been loaded into the target.
712 BOOL CordbProcess::IsDacInitialized()
714 return m_pDacPrimitives != NULL;
717 //---------------------------------------------------------------------------------------
719 // Get the DAC interface.
722 // the Dac/Dbi interface pointer to the process.
723 // Never returns NULL.
726 // Caller is responsible for ensuring Data-Target is safe to access (eg, not
727 // currently running).
728 // Caller is responsible for ensuring DAC-cache is flushed. Call code:CordbProcess::ForceDacFlush
731 //---------------------------------------------------------------------------------------
732 IDacDbiInterface * CordbProcess::GetDAC()
734 // Since the DD primitives may throw, easiest way to model that is to make this throw.
741 // We should always have the DAC/DBI interface.
742 _ASSERTE(m_pDacPrimitives != NULL);
743 return m_pDacPrimitives;
746 //---------------------------------------------------------------------------------------
747 // Get the Data-Target
750 // pointer to the data-target. Should be non-null.
751 // Lifetime of the pointer is until this process object is neutered.
753 ICorDebugDataTarget * CordbProcess::GetDataTarget()
755 return m_pDACDataTarget;
758 //---------------------------------------------------------------------------------------
759 // Create a CordbProcess object around an existing OS process.
762 // pDataTarget - abstracts access to the debuggee.
763 // clrInstanceId - identifies the CLR instance within the debuggee. (This is the
764 // base address of mscorwks)
765 // pCordb - Pointer to the implementation of the owning Cordb object implementing the
766 // owning ICD interface.
767 // This should go away - we can get the functionality from the pShim.
768 // If this is null, then pShim must be null too.
769 // processID - OS process ID of target process. 0 if pShim == NULL.
770 // pShim - shim counter part object. This allows hooks back for v2 compat. This will
771 // go away once we no longer support V2 backwards compat.
772 // This must be non-null for any V2 paths (including non-DAC-ized code).
773 // If this is null, then we're in a V3 path.
774 // ppProcess - out parameter for new process object. This gets addreffed.
777 // S_OK on success, and *ppProcess set to newly created debuggee object. Else error.
780 // @dbgtodo - , shim: Cordb, and pShim will all eventually go away.
782 //---------------------------------------------------------------------------------------
785 HRESULT CordbProcess::OpenVirtualProcess(
786 ULONG64 clrInstanceId,
787 IUnknown * pDataTarget,
792 CordbProcess ** ppProcess)
794 _ASSERTE(pDataTarget != NULL);
796 // In DEBUG builds, verify that we do actually have an ICorDebugDataTarget (i.e. that
797 // someone hasn't messed up the COM interop marshalling, etc.).
801 HRESULT hrQi = pDataTarget->QueryInterface(IID_ICorDebugDataTarget, (void**)&pTempDt);
802 _ASSERTE_MSG(SUCCEEDED(hrQi), "OpenVirtualProcess was passed something that isn't actually an ICorDebugDataTarget");
807 // If we're emulating V2, then both pCordb and pShim are non-NULL.
808 // If we're doing a real V3 path, then they're both NULL.
809 // Either way, they should have the same null-status.
810 _ASSERTE((pCordb == NULL) == (pShim == NULL));
812 // If we're doing real V3, then we must have a real instance ID
813 _ASSERTE(!((pShim == NULL) && (clrInstanceId == 0)));
818 RSUnsafeExternalSmartPtr<CordbProcess> pProcess;
819 pProcess.Assign(new (nothrow) CordbProcess(clrInstanceId, pDataTarget, hDacModule, pCordb, dwProcessID, pShim));
821 if (pProcess == NULL)
823 return E_OUTOFMEMORY;
826 ICorDebugProcess * pThis = pProcess;
827 (void)pThis; //prevent "unused variable" error from GCC
829 // CordbProcess::Init may need shim hooks, so connect Shim now.
830 // This will bump reference count.
833 pShim->SetProcess(pProcess);
835 _ASSERTE(pShim->GetProcess() == pThis);
836 _ASSERTE(pShim->GetWin32EventThread() != NULL);
839 hr = pProcess->Init();
843 *ppProcess = pProcess;
844 pProcess->ExternalAddRef();
848 // handle failure path
849 pProcess->CleanupHalfBakedLeftSide();
853 // Shim still needs to be disposed to clean up other resources.
854 pShim->SetProcess(NULL);
857 // In failure case, pProcess's dtor will do the final release.
864 //---------------------------------------------------------------------------------------
865 // CordbProcess constructor
868 // pDataTarget - Pointer to an implementation of ICorDebugDataTarget
869 // (or ICorDebugMutableDataTarget), which virtualizes access to the process.
870 // clrInstanceId - representation of the CLR to debug in the process. Must be specified
871 // (non-zero) if pShim is NULL. If 0, use the first CLR that we see.
872 // pCordb - Pointer to the implementation of the owning Cordb object implementing the
873 // owning ICD interface.
874 // pW32 - Pointer to the Win32 event thread to use when processing events for this
876 // dwProcessID - For V3, 0.
877 // Else for shim codepaths, the processID of the process this object will represent.
878 // pShim - Pointer to the shim for handling V2 debuggers on the V3 architecture.
880 //---------------------------------------------------------------------------------------
882 CordbProcess::CordbProcess(ULONG64 clrInstanceId,
883 IUnknown * pDataTarget,
888 : CordbBase(NULL, dwProcessID, enumCordbProcess),
889 m_fDoDelayedManagedAttached(false),
893 m_uninitializedStop(false),
896 m_unrecoverableError(false),
897 m_specialDeferment(false),
898 m_helperThreadDead(false),
899 m_loaderBPReceived(false),
900 m_cOutstandingEvals(0),
901 m_cOutstandingHandles(0),
902 m_clrInstanceId(clrInstanceId),
904 m_synchronized(false),
905 m_syncCompleteReceived(false),
909 #ifdef FEATURE_INTEROP_DEBUGGING
910 m_unmanagedThreads(11),
913 m_sharedAppDomain(0),
915 m_continueCounter(1),
917 m_leftSideEventAvailable(NULL),
918 m_leftSideEventRead(NULL),
919 #if defined(FEATURE_INTEROP_DEBUGGING)
920 m_leftSideUnmanagedWaitEvent(NULL),
921 #endif // FEATURE_INTEROP_DEBUGGING
922 m_initialized(false),
923 m_stopRequested(false),
924 m_stopWaitEvent(NULL),
925 #ifdef FEATURE_INTEROP_DEBUGGING
926 m_cFirstChanceHijackedThreads(0),
927 m_unmanagedEventQueue(NULL),
928 m_lastQueuedUnmanagedEvent(NULL),
929 m_lastQueuedOOBEvent(NULL),
930 m_outOfBandEventQueue(NULL),
931 m_lastDispatchedIBEvent(NULL),
932 m_dispatchingUnmanagedEvent(false),
933 m_dispatchingOOBEvent(false),
934 m_doRealContinueAfterOOBBlock(false),
936 #endif // FEATURE_INTEROP_DEBUGGING
942 m_rgUncommitedOpcode(NULL),
943 m_minPatchAddr(MAX_ADDRESS),
944 m_maxPatchAddr(MIN_ADDRESS),
946 m_hHelperThread(NULL),
947 m_dispatchedEvent(DB_IPCE_DEBUGGER_INVALID),
948 m_pDefaultAppDomain(NULL),
949 m_hDacModule(hDacModule),
950 m_pDacPrimitives(NULL),
951 m_pEventChannel(NULL),
952 m_fAssertOnTargetInconsistency(false),
953 m_runtimeOffsetsInitialized(false),
954 m_writableMetadataUpdateMode(LegacyCompatPolicy)
956 _ASSERTE((m_id == 0) == (pShim == NULL));
958 HRESULT hr = pDataTarget->QueryInterface(IID_ICorDebugDataTarget, reinterpret_cast<void **>(&m_pDACDataTarget));
961 #ifdef FEATURE_INTEROP_DEBUGGING
962 m_DbgSupport.m_DebugEventQueueIdx = 0;
963 m_DbgSupport.m_TotalNativeEvents = 0;
964 m_DbgSupport.m_TotalIB = 0;
965 m_DbgSupport.m_TotalOOB = 0;
966 m_DbgSupport.m_TotalCLR = 0;
967 #endif // FEATURE_INTEROP_DEBUGGING
969 g_pRSDebuggingInfo->m_MRUprocess = this;
971 // This is a strong reference to ourselves.
972 // This is cleared in code:CordbProcess::Neuter
973 m_pProcess.Assign(this);
976 // On Debug builds, we'll ASSERT by default whenever the target appears to be corrupt or
977 // otherwise inconsistent (both in DAC and DBI). But we also need the ability to
978 // explicitly test corrupt targets.
979 // Tests should set COMPlus_DbgIgnoreInconsistentTarget=1 to suppress these asserts
980 // Note that this controls two things:
981 // 1) DAC behavior - see code:IDacDbiInterface::DacSetTargetConsistencyChecks
982 // 2) RS-only consistency asserts - see code:CordbProcess::TargetConsistencyCheck
983 if( !CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgDisableTargetConsistencyAsserts) )
985 m_fAssertOnTargetInconsistency = true;
991 A list of which resources owned by this object are accounted for.
995 CordbHashTable m_unmanagedThreads; // Released in CordbProcess but not removed from hash
996 DebuggerIPCEvent* m_lastQueuedEvent;
998 // CordbUnmannagedEvent is a struct which is not derrived from CordbBase.
999 // It contains a CordbUnmannagedThread which may need to be released.
1000 CordbUnmanagedEvent *m_unmanagedEventQueue;
1001 CordbUnmanagedEvent *m_lastQueuedUnmanagedEvent;
1002 CordbUnmanagedEvent *m_outOfBandEventQueue;
1003 CordbUnmanagedEvent *m_lastQueuedOOBEvent;
1005 BYTE* m_pPatchTable;
1007 void *m_pbRemoteBuf;
1011 CordbHashTable m_userThreads;
1012 CordbHashTable m_appDomains;
1014 // Cleaned up in ExitProcess
1015 DebuggerIPCEvent* m_queuedEventList;
1017 CordbHashTable m_steppers; // Closed in ~CordbProcess
1019 // Closed in CloseIPCEventHandles called from ~CordbProcess
1020 HANDLE m_leftSideEventAvailable;
1021 HANDLE m_leftSideEventRead;
1023 // Closed in ~CordbProcess
1025 HANDLE m_leftSideUnmanagedWaitEvent;
1026 HANDLE m_stopWaitEvent;
1028 // Deleted in ~CordbProcess
1029 CRITICAL_SECTION m_processMutex;
1034 CordbProcess::~CordbProcess()
1036 LOG((LF_CORDB, LL_INFO1000, "CP::~CP: deleting process 0x%08x\n", this));
1040 _ASSERTE(IsNeutered());
1042 _ASSERTE(m_cordb == NULL);
1044 // We shouldn't still be in Cordb's list of processes. Unfortunately, our root Cordb object
1045 // may have already been deleted b/c we're at the mercy of ref-counting, so we can't check.
1047 _ASSERTE(m_sharedAppDomain == NULL);
1049 m_processMutex.Destroy();
1050 m_StopGoLock.Destroy();
1052 // These handles were cleared in neuter
1053 _ASSERTE(m_handle == NULL);
1054 #if defined(FEATURE_INTEROP_DEBUGGING)
1055 _ASSERTE(m_leftSideUnmanagedWaitEvent == NULL);
1056 #endif // FEATURE_INTEROP_DEBUGGING
1057 _ASSERTE(m_stopWaitEvent == NULL);
1059 // Set this to mark that we really did cleanup.
1062 //-----------------------------------------------------------------------------
1063 // Static build helper.
1064 // This will create a process under the pCordb root, and add it to the list.
1065 // We don't return the process - caller gets the pid and looks it up under
1066 // the Cordb object.
1069 // pCordb - Pointer to the implementation of the owning Cordb object implementing the
1070 // owning ICD interface.
1071 // szProgramName - Name of the program to execute.
1072 // szProgramArgs - Command line arguments for the process.
1073 // lpProcessAttributes - OS-specific attributes for process creation.
1074 // lpThreadAttributes - OS-specific attributes for thread creation.
1075 // fInheritFlags - OS-specific flag for child process inheritance.
1076 // dwCreationFlags - OS-specific creation flags.
1077 // lpEnvironment - OS-specific environmental strings.
1078 // szCurrentDirectory - OS-specific string for directory to run in.
1079 // lpStartupInfo - OS-specific info on startup.
1080 // lpProcessInformation - OS-specific process information buffer.
1081 // corDebugFlags - What type of process to create, currently always managed.
1082 //-----------------------------------------------------------------------------
1083 HRESULT ShimProcess::CreateProcess(
1085 ICorDebugRemoteTarget * pRemoteTarget,
1086 LPCWSTR szProgramName,
1087 __in_z LPWSTR szProgramArgs,
1088 LPSECURITY_ATTRIBUTES lpProcessAttributes,
1089 LPSECURITY_ATTRIBUTES lpThreadAttributes,
1090 BOOL fInheritHandles,
1091 DWORD dwCreationFlags,
1092 PVOID lpEnvironment,
1093 LPCWSTR szCurrentDirectory,
1094 LPSTARTUPINFOW lpStartupInfo,
1095 LPPROCESS_INFORMATION lpProcessInformation,
1096 CorDebugCreateProcessFlags corDebugFlags
1099 _ASSERTE(pCordb != NULL);
1101 #if defined(FEATURE_DBGIPC_TRANSPORT_DI)
1102 // The transport cannot deal with creating a suspended process (it needs the debugger to start up and
1103 // listen for connections).
1104 _ASSERTE((dwCreationFlags & CREATE_SUSPENDED) == 0);
1105 #endif // FEATURE_DBGIPC_TRANSPORT_DI
1109 RSExtSmartPtr<ShimProcess> pShim;
1112 pShim.Assign(new ShimProcess());
1114 // Indicate that this process was started under the debugger as opposed to attaching later.
1115 pShim->m_attached = false;
1117 hr = pShim->CreateAndStartWin32ET(pCordb);
1120 // Call out to newly created Win32-event Thread to create the process.
1121 // If this succeeds, new CordbProcess will add a ref to the ShimProcess
1122 hr = pShim->GetWin32EventThread()->SendCreateProcessEvent(pShim->GetMachineInfo(),
1125 lpProcessAttributes,
1132 lpProcessInformation,
1136 EX_CATCH_HRESULT(hr);
1138 // If this succeeds, then process takes ownership of thread. Else we need to kill it.
1146 // Always release our ref to ShimProcess. If the Process was created, then it takes a reference.
1151 //-----------------------------------------------------------------------------
1152 // Static build helper for the attach case.
1153 // On success, this will add the process to the pCordb list, and then
1154 // callers can look it up there by pid.
1157 // pCordb - root under which this all lives
1158 // dwProcessID - OS process ID to attach to
1159 // fWin32Attach - are we interop debugging?
1160 //-----------------------------------------------------------------------------
1161 HRESULT ShimProcess::DebugActiveProcess(
1163 ICorDebugRemoteTarget * pRemoteTarget,
1168 _ASSERTE(pCordb != NULL);
1172 RSExtSmartPtr<ShimProcess> pShim;
1176 pShim.Assign(new ShimProcess());
1178 // Indicate that this process was attached to, asopposed to being started under the debugger.
1179 pShim->m_attached = true;
1181 hr = pShim->CreateAndStartWin32ET(pCordb);
1184 // If this succeeds, new CordbProcess will add a ref to the ShimProcess
1185 hr = pShim->GetWin32EventThread()->SendDebugActiveProcessEvent(pShim->GetMachineInfo(),
1187 fWin32Attach == TRUE,
1191 _ASSERTE(SUCCEEDED(hr));
1193 #if !defined(FEATURE_DBGIPC_TRANSPORT_DI)
1194 // Don't do this when we are remote debugging since we won't be getting the loader breakpoint.
1195 // We don't support JIT attach in remote debugging scenarios anyway.
1197 // When doing jit attach for pure managed debugging we allow the native attach event to be signaled
1198 // after DebugActiveProcess completes which means we must wait here long enough to have set the debuggee
1199 // bit indicating managed attach is coming.
1200 // However in interop debugging we can't do that because there are debug events which come before the
1201 // loader breakpoint (which is how far we need to get to set the debuggee bit). If we blocked
1202 // DebugActiveProcess there then the debug events would be refering to an ICorDebugProcess that hasn't
1203 // yet been returned to the caller of DebugActiveProcess. Instead, for interop debugging we force the
1204 // native debugger to wait until it gets the loader breakpoint to set the event. Note we can't converge
1205 // on that solution for the pure managed case because there is no loader breakpoint event. Hence pure
1206 // managed and interop debugging each require their own solution
1208 // See bugs Dev10 600873 and 595322 for examples of what happens if we wait in interop or don't wait
1209 // in pure managed respectively
1211 // Long term this should all go away because we won't need to set a managed attach pending bit because
1212 // there shouldn't be any IPC events involved in managed attach. There might not even be a notion of
1213 // being 'managed attached'
1214 if(!pShim->m_fIsInteropDebugging)
1216 DWORD dwHandles = 2;
1217 HANDLE arrHandles[2];
1219 arrHandles[0] = pShim->m_terminatingEvent;
1220 arrHandles[1] = pShim->m_markAttachPendingEvent;
1222 // Wait for the completion of marking pending attach bit or debugger detaching
1223 WaitForMultipleObjectsEx(dwHandles, arrHandles, FALSE, INFINITE, FALSE);
1225 #endif //!FEATURE_DBGIPC_TRANSPORT_DI
1227 EX_CATCH_HRESULT(hr);
1229 // If this succeeds, then process takes ownership of thread. Else we need to kill it.
1238 // Always release our ref to ShimProcess. If the Process was created, then it takes a reference.
1243 //-----------------------------------------------------------------------------
1244 // Neuter all of all children, but not the actual process object.
1247 // This clears Right-side state. Assumptions about left-side state are either:
1248 // 1. We're in a shutdown scenario, where all left-side state is already
1250 // 2. Caller already verified there are no left-side resources (eg, by calling
1251 // code:CordbProcess::IsReadyForDetach)
1252 // 3. Caller did code:CordbProcess::NeuterLeftSideResources first
1253 // to clean up left-side resources.
1256 // This could be called multiple times (code:CordbProcess::FlushAll), so
1257 // be sure to null out any potential dangling pointers. State may be rebuilt
1258 // up after each time.
1259 void CordbProcess::NeuterChildren()
1261 _ASSERTE(GetProcessLock()->HasLock());
1263 // Frees left-side resources. See assumptions above.
1264 m_LeftSideResourceCleanupList.NeuterAndClear(this);
1267 m_EvalTable.Clear();
1270 // Sweep neuter lists.
1271 m_ExitNeuterList.NeuterAndClear(this);
1272 m_ContinueNeuterList.NeuterAndClear(this);
1274 m_userThreads.NeuterAndClear(GetProcessLock());
1276 m_pDefaultAppDomain = NULL;
1278 // Frees per-appdomain left-side resources. See assumptions above.
1279 m_appDomains.NeuterAndClear(GetProcessLock());
1280 if (m_sharedAppDomain != NULL)
1282 m_sharedAppDomain->Neuter();
1283 m_sharedAppDomain->InternalRelease();
1284 m_sharedAppDomain = NULL;
1287 m_steppers.NeuterAndClear(GetProcessLock());
1289 #ifdef FEATURE_INTEROP_DEBUGGING
1290 m_unmanagedThreads.NeuterAndClear(GetProcessLock());
1291 #endif // FEATURE_INTEROP_DEBUGGING
1293 // Explicitly keep the Win32EventThread alive so that we can use it in the window
1294 // between NeuterChildren + Neuter.
1297 //-----------------------------------------------------------------------------
1300 // When the process dies, remove all the resources associated with this object.
1303 // Once we neuter ourself, we can no longer send IPC events. So this is useful
1304 // on detach. This will be called on FlushAll (which has Whidbey detach
1306 //-----------------------------------------------------------------------------
1307 void CordbProcess::Neuter()
1309 // Process's Neuter is at the top of the neuter tree. So we take the process-lock
1310 // here and then all child items (appdomains, modules, etc) will assert
1311 // that they hold the lock.
1312 _ASSERTE(!this->ThreadHoldsProcessLock());
1314 // Take the process lock.
1315 RSLockHolder lockHolder(GetProcessLock());
1320 // Release the metadata interfaces
1321 m_pMetaDispenser.Clear();
1324 if (m_hHelperThread != NULL)
1326 CloseHandle(m_hHelperThread);
1327 m_hHelperThread = NULL;
1331 lockHolder.Release();
1333 // We may still hold the Stop-Go lock.
1334 // @dbgtodo - left-side resources / shutdown, shim: Currently
1335 // the shim shutdown is too interwoven with CordbProcess to split
1336 // it out from the locks. Must fully hoist the W32ET and make
1337 // it safely outside the RS, and outside the protection of RS
1339 PUBLIC_API_UNSAFE_ENTRY_FOR_SHIM(this);
1341 // Now that all of our children are neutered, it should be safe to kill the W32ET.
1342 // Shutdown the shim, and this will also shutdown the W32ET.
1343 // Do this outside of the process-lock so that we can shutdown the
1345 if (m_pShim != NULL)
1352 lockHolder.Acquire();
1355 // Unload DAC, and then release our final data target references
1357 m_pDACDataTarget.Clear();
1358 m_pMutableDataTarget.Clear();
1359 m_pMetaDataLocator.Clear();
1361 if (m_pEventChannel != NULL)
1363 m_pEventChannel->Delete();
1364 m_pEventChannel = NULL;
1367 // Need process lock to clear the patch table
1370 CordbProcess::CloseIPCHandles();
1372 CordbBase::Neuter();
1376 // Need to release this reference to ourselves. Other leaf objects may still hold
1377 // strong references back to this CordbProcess object.
1378 _ASSERTE(m_pProcess == this);
1382 // Wrapper to return metadata dispenser.
1385 // Does not adjust reference count of dispenser.
1386 // Dispenser is destroyed in code:CordbProcess::Neuter
1387 // Dispenser is non-null.
1388 IMetaDataDispenserEx * CordbProcess::GetDispenser()
1390 _ASSERTE(m_pMetaDispenser != NULL);
1391 return m_pMetaDispenser;
1395 void CordbProcess::CloseIPCHandles()
1397 INTERNAL_API_ENTRY(this);
1399 // Close off Right Side's handles.
1400 if (m_leftSideEventAvailable != NULL)
1402 CloseHandle(m_leftSideEventAvailable);
1403 m_leftSideEventAvailable = NULL;
1406 if (m_leftSideEventRead != NULL)
1408 CloseHandle(m_leftSideEventRead);
1409 m_leftSideEventRead = NULL;
1412 if (m_handle != NULL)
1414 // @dbgtodo - We should probably add asserts to all calls to CloseHandles(), but this has been
1415 // a particularly problematic spot in the past for Mac debugging.
1416 BOOL fSuccess = CloseHandle(m_handle);
1417 (void)fSuccess; //prevent "unused variable" error from GCC
1423 #if defined(FEATURE_INTEROP_DEBUGGING)
1424 if (m_leftSideUnmanagedWaitEvent != NULL)
1426 CloseHandle(m_leftSideUnmanagedWaitEvent);
1427 m_leftSideUnmanagedWaitEvent = NULL;
1429 #endif // FEATURE_INTEROP_DEBUGGING
1431 if (m_stopWaitEvent != NULL)
1433 CloseHandle(m_stopWaitEvent);
1434 m_stopWaitEvent = NULL;
1439 //-----------------------------------------------------------------------------
1440 // Create new OS Thread for the Win32 Event Thread (the thread used in interop-debugging to sniff
1441 // native debug events). This is 1:1 w/ a CordbProcess object.
1442 // This will then be used to actuall create the CordbProcess object.
1443 // The process object will then take ownership of the thread.
1446 // pCordb - the root object that the process lives under
1450 //-----------------------------------------------------------------------------
1451 HRESULT ShimProcess::CreateAndStartWin32ET(Cordb * pCordb)
1455 // Create the win32 event listening thread
1457 CordbWin32EventThread * pWin32EventThread = new (nothrow) CordbWin32EventThread(pCordb, this);
1461 if (pWin32EventThread != NULL)
1463 hr = pWin32EventThread->Init();
1467 hr = pWin32EventThread->Start();
1472 delete pWin32EventThread;
1473 pWin32EventThread = NULL;
1481 m_pWin32EventThread = pWin32EventThread;
1482 return ErrWrapper(hr);
1486 //---------------------------------------------------------------------------------------
1488 // Try to initialize the DAC. Called in scenarios where it may fail.
1491 // TRUE - DAC is initialized.
1492 // FALSE - Not initialized, but can try again later. Common case if
1493 // target has not yet loaded the runtime.
1494 // Throws exception - fatal.
1497 // Target is stopped by OS, so we can safely inspect it without it moving on us.
1500 // This can be called eagerly to sniff if the LS is initialized.
1502 //---------------------------------------------------------------------------------------
1503 BOOL CordbProcess::TryInitializeDac()
1511 // Target is stopped by OS, so we can safely inspect it without it moving on us.
1513 // We want to avoid exceptions in the normal case, so we do some pre-checks
1514 // to detect failure without relying on exceptions.
1515 // Can't initialize DAC until mscorwks is loaded. So that's a sanity test.
1516 HRESULT hr = EnsureClrInstanceIdSet();
1522 // By this point, we know which CLR in the target to debug. That means there is a CLR
1523 // in the target, and it's safe to initialize DAC.
1524 _ASSERTE(m_clrInstanceId != 0);
1526 // Now expect it to succeed
1531 //---------------------------------------------------------------------------------------
1533 // Load & Init DAC, expecting to succeed.
1536 // Throws on failure.
1539 // Caller invokes this at a point where they can expect it to succeed.
1540 // This is called early in the startup path because DAC is needed for accessing
1541 // data in the target.
1544 // This needs to succeed, and should always succeed (baring a bad installation)
1545 // so we assert on failure paths.
1546 // This may be called mutliple times.
1548 //---------------------------------------------------------------------------------------
1549 void CordbProcess::InitializeDac()
1556 INTERNAL_API_ENTRY(this);
1558 // For Mac debugginger, m_hDacModule is not used, and it will always be NULL. To check whether DAC has
1559 // been initialized, we need to check something else, namely m_pDacPrimitives.
1560 if (m_pDacPrimitives == NULL)
1562 LOG((LF_CORDB, LL_INFO1000, "About to load DAC\n"));
1563 CreateDacDbiInterface(); // throws
1567 LOG((LF_CORDB, LL_INFO1000, "Dac already loaded, 0x%p\n", (HMODULE)m_hDacModule));
1570 // Always flush dac.
1574 //---------------------------------------------------------------------------------------
1576 // Free DAC resources
1579 // This should clean up state such that code:CordbProcess::InitializeDac could be called again.
1581 //---------------------------------------------------------------------------------------
1582 void CordbProcess::FreeDac()
1586 NOTHROW; // backout code.
1590 if (m_pDacPrimitives != NULL)
1592 m_pDacPrimitives->Destroy();
1593 m_pDacPrimitives = NULL;
1596 if (m_hDacModule != NULL)
1598 LOG((LF_CORDB, LL_INFO1000, "Unloading DAC\n"));
1599 m_hDacModule.Clear();
1603 IEventChannel * CordbProcess::GetEventChannel()
1605 _ASSERTE(m_pEventChannel != NULL);
1606 return m_pEventChannel;
1609 //---------------------------------------------------------------------------------------
1610 // Mark that the process is being interop-debugged.
1613 // @dbgtodo shim: this should eventually move into the shim or go away.
1614 // It's only to support V2 legacy interop-debugging.
1615 // Called after code:CordbProcess::Init if we want to enable interop debugging.
1616 // This allows us to separate out Interop-debugging flags from the core initialization,
1617 // and paves the way for us to eventually remove it.
1619 // Since we're always on the naitve-pipeline, the Enabling interop debugging just changes
1620 // how the native debug events are being handled. So this must be called after Init, but
1621 // before any events are actually handled.
1622 // This mus be calle on the win32 event thread to gaurantee that it's called before WFDE.
1623 void CordbProcess::EnableInteropDebugging()
1628 PRECONDITION(m_pShim != NULL);
1632 // Must be on W32ET to gaurantee that we're called after Init yet before WFDE (which
1633 // are both called on the W32et).
1634 _ASSERTE(IsWin32EventThread());
1635 #ifdef FEATURE_INTEROP_DEBUGGING
1637 m_state |= PS_WIN32_ATTACHED;
1638 if (GetDCB() != NULL)
1640 GetDCB()->m_rightSideIsWin32Debugger = true;
1641 UpdateLeftSideDCBField(&(GetDCB()->m_rightSideIsWin32Debugger), sizeof(GetDCB()->m_rightSideIsWin32Debugger));
1644 // Tell the Shim we're interop-debugging.
1645 m_pShim->SetIsInteropDebugging(true);
1647 ThrowHR(CORDBG_E_INTEROP_NOT_SUPPORTED);
1651 //---------------------------------------------------------------------------------------
1653 // Init -- create any objects that the process object needs to operate.
1661 // Called on Win32 Event Thread, after OS debugging pipeline is established but
1662 // before WaitForDebugEvent / ContinueDebugEvent. This means the target is stopped.
1665 // To enable interop-debugging, call code:CordbProcess::EnableInteropDebugging
1666 //---------------------------------------------------------------------------------------
1667 HRESULT CordbProcess::Init()
1669 INTERNAL_API_ENTRY(this);
1672 BOOL fIsLSStarted = FALSE; // see meaning below.
1674 FAIL_IF_NEUTERED(this);
1679 m_processMutex.Init("Process Lock", RSLock::cLockReentrant, RSLock::LL_PROCESS_LOCK);
1680 m_StopGoLock.Init("Stop-Go Lock", RSLock::cLockReentrant, RSLock::LL_STOP_GO_LOCK);
1683 m_appDomains.DebugSetRSLock(GetProcessLock());
1684 m_userThreads.DebugSetRSLock(GetProcessLock());
1685 #ifdef FEATURE_INTEROP_DEBUGGING
1686 m_unmanagedThreads.DebugSetRSLock(GetProcessLock());
1688 m_steppers.DebugSetRSLock(GetProcessLock());
1691 // See if the data target is mutable, and cache the mutable interface if it is
1692 // We must initialize this before we try to use the data target to access the memory in the target process.
1693 m_pMutableDataTarget.Clear(); // if we were called already, release
1694 hr = m_pDACDataTarget->QueryInterface(IID_ICorDebugMutableDataTarget, (void**)&m_pMutableDataTarget);
1697 // The data target doesn't support mutation. We'll fail any requests that require mutation.
1698 m_pMutableDataTarget.Assign(new ReadOnlyDataTargetFacade());
1701 m_pMetaDataLocator.Clear();
1702 hr = m_pDACDataTarget->QueryInterface(IID_ICorDebugMetaDataLocator, reinterpret_cast<void **>(&m_pMetaDataLocator));
1704 // Get the metadata dispenser.
1705 hr = InternalCreateMetaDataDispenser(IID_IMetaDataDispenserEx, (void **)&m_pMetaDispenser);
1707 // We statically link in the dispenser. We expect it to succeed, except for OOM, which
1708 // debugger doesn't yet handle.
1709 SIMPLIFYING_ASSUMPTION_SUCCEEDED(hr);
1712 _ASSERTE(m_pMetaDispenser != NULL);
1714 // In order to allow users to call the metadata reader from multiple threads we need to set
1715 // a flag on the dispenser to create threadsafe readers. This is done best-effort but
1716 // really shouldn't ever fail. See issue 696511.
1717 VARIANT optionValue;
1718 VariantInit(&optionValue);
1719 V_VT(&optionValue) = VT_UI4;
1720 V_UI4(&optionValue) = MDThreadSafetyOn;
1721 m_pMetaDispenser->SetOption(MetaDataThreadSafetyOptions, &optionValue);
1724 // Setup internal events.
1725 // @dbgtodo shim: these events should eventually be in the shim.
1729 // Managed debugging is built on the native-pipeline, and that will detect against double-attaches.
1731 // @dbgtodo shim: In V2, LSEA + LSER were used by the LS's helper thread. Now with the V3 pipeline,
1732 // that helper-thread uses native-debug events. The W32ET gets those events and then uses LSEA, LSER to
1733 // signal existing RS infrastructure. Eventually get rid of LSEA, LSER completely.
1736 m_leftSideEventAvailable = WszCreateEvent(NULL, FALSE, FALSE, NULL);
1737 if (m_leftSideEventAvailable == NULL)
1742 m_leftSideEventRead = WszCreateEvent(NULL, FALSE, FALSE, NULL);
1743 if (m_leftSideEventRead == NULL)
1748 m_stopWaitEvent = WszCreateEvent(NULL, TRUE, FALSE, NULL);
1749 if (m_stopWaitEvent == NULL)
1754 if (m_pShim != NULL)
1756 // Get a handle to the debuggee.
1757 // This is not needed in the V3 pipeline because we don't assume we have a live, local, process.
1758 m_handle = GetShim()->GetNativePipeline()->GetProcessHandle();
1760 if (m_handle == NULL)
1766 // The LS startup goes through the following phases:
1767 // 1) mscorwks not yet loaded (eg, any unmanaged app)
1768 // 2) mscorwks loaded (DAC can now be used)
1769 // 3) IPC Block created at OS level
1770 // 4) IPC block data initialized (so we can read meainingful data from it)
1771 // 5) LS marks that it's initialized (queryable by a DAC primitive) (may not be atomic)
1772 // 6) LS fires a "Startup" exception (sniffed by WFDE).
1774 // LS is currently stopped by OS debugging, so it's doesn't shift phases.
1775 // From the RS's perspective:
1776 // - after phase 5 is an attach
1777 // - before phase 6 is a launch.
1778 // This means there's an overlap: if we catch it at phase 5, we'll just get
1779 // an extra Startup exception from phase 6, which is safe. This overlap is good
1780 // because it means there's no bad window to do an attach in.
1782 // fIsLSStarted means before phase 6 (eg, RS should expect a startup exception)
1784 // Determines if the LS is started.
1787 BOOL fReady = TryInitializeDac();
1791 // Invoke DAC primitive.
1792 _ASSERTE(m_pDacPrimitives != NULL);
1793 fIsLSStarted = m_pDacPrimitives->IsLeftSideInitialized();
1797 _ASSERTE(m_pDacPrimitives == NULL);
1799 // DAC is not yet loaded, so we're at least before phase 2, which is before phase 6.
1800 // So leave fIsLSStarted = false. We'll get a startup exception later.
1801 _ASSERTE(!fIsLSStarted);
1808 // Left-side has started up. This is common for Attach cases when managed-code is already running.
1810 if (m_pShim != NULL)
1812 FinishInitializeIPCChannelWorker(); // throws
1814 // At this point, the control block is complete and all four
1815 // events are available and valid for the remote process.
1817 // Request that the process object send an Attach IPC event.
1818 // This is only used in an attach case.
1819 // @dbgtodo sync: this flag can go away once the
1820 // shim can use real sync APIs.
1821 m_fDoDelayedManagedAttached = true;
1825 // In the V3 pipeline case, if we have the DD-interface, then the runtime is loaded
1826 // and we consider it initialized.
1827 if (IsDacInitialized())
1829 m_initialized = true;
1835 // LS is not started yet. This would be common for "Launch" cases.
1836 // We will get a Startup Exception notification when it does start.
1839 EX_CATCH_HRESULT(hr);
1843 CleanupHalfBakedLeftSide();
1850 COM_METHOD CordbProcess::CanCommitChanges(ULONG cSnapshots,
1851 ICorDebugEditAndContinueSnapshot *pSnapshots[],
1852 ICorDebugErrorInfoEnum **pError)
1857 COM_METHOD CordbProcess::CommitChanges(ULONG cSnapshots,
1858 ICorDebugEditAndContinueSnapshot *pSnapshots[],
1859 ICorDebugErrorInfoEnum **pError)
1866 // Terminating -- places the process into the terminated state. This should
1867 // also get any blocking process functions unblocked so they'll return
1870 void CordbProcess::Terminating(BOOL fDetach)
1872 INTERNAL_API_ENTRY(this);
1874 LOG((LF_CORDB, LL_INFO1000,"CP::T: Terminating process 0x%x detach=%d\n", m_id, fDetach));
1875 m_terminated = true;
1877 m_cordb->ProcessStateChanged();
1879 // Set events that may be blocking stuff.
1880 // But don't set RSER unless we actually read the event. We don't block on RSER
1881 // since that wait also checks the leftside's process handle.
1882 SetEvent(m_leftSideEventRead);
1883 SetEvent(m_leftSideEventAvailable);
1884 SetEvent(m_stopWaitEvent);
1886 if (m_pShim != NULL)
1887 m_pShim->SetTerminatingEvent();
1889 if (fDetach && (m_pEventChannel != NULL))
1891 m_pEventChannel->Detach();
1896 // Wrapper to give shim access to code:CordbProcess::QueueManagedAttachIfNeededWorker
1897 void CordbProcess::QueueManagedAttachIfNeeded()
1899 PUBLIC_API_ENTRY_FOR_SHIM(this);
1900 QueueManagedAttachIfNeededWorker();
1903 //---------------------------------------------------------------------------------------
1904 // Hook from Shim to request a managed attach IPC event
1907 // Called by shim after the loader-breakpoint is handled.
1908 // @dbgtodo sync: ths should go away once the shim can initiate
1910 void CordbProcess::QueueManagedAttachIfNeededWorker()
1912 HRESULT hrQueue = S_OK;
1914 // m_fDoDelayedManagedAttached ensures that we only send an Attach event if the LS is actually present.
1915 if (m_fDoDelayedManagedAttached && GetShim()->GetAttached())
1917 RSLockHolder lockHolder(&this->m_processMutex);
1918 GetDAC()->MarkDebuggerAttachPending();
1920 hrQueue = this->QueueManagedAttach();
1923 if (m_pShim != NULL)
1924 m_pShim->SetMarkAttachPendingEvent();
1926 IfFailThrow(hrQueue);
1929 //---------------------------------------------------------------------------------------
1931 // QueueManagedAttach
1933 // Send a managed attach. This is asynchronous and will return immediately.
1938 //---------------------------------------------------------------------------------------
1939 HRESULT CordbProcess::QueueManagedAttach()
1941 INTERNAL_API_ENTRY(this);
1943 _ASSERTE(ThreadHoldsProcessLock());
1945 _ASSERTE(m_fDoDelayedManagedAttached);
1946 m_fDoDelayedManagedAttached = false;
1948 _ASSERTE(IsDacInitialized());
1950 // We don't know what Queue it.
1951 SendAttachProcessWorkItem * pItem = new (nothrow) SendAttachProcessWorkItem(this);
1955 return E_OUTOFMEMORY;
1958 this->m_cordb->m_rcEventThread->QueueAsyncWorkItem(pItem);
1963 // However, we still want to synchronize.
1964 // @dbgtodo sync: when we hoist attaching, we can send an DB_IPCE_ASYNC_BREAK event instead or Attach
1965 // (for V2 semantics, we still need to synchronize the process)?
1966 void SendAttachProcessWorkItem::Do()
1970 // This is being processed on the RCET, where it's safe to take the Stop-Go lock.
1971 RSLockHolder ch(this->GetProcess()->GetStopGoLock());
1973 DebuggerIPCEvent *event = (DebuggerIPCEvent*) _alloca(CorDBIPC_BUFFER_SIZE);
1975 // This just acts like an async-break, which will kick off things.
1976 // This will not induce any faked attach events from the VM (like it did in V2).
1977 // The Left-side will still slip foward allowing the async-break to happen, so
1978 // we may get normal debug events in addition to the sync-complete.
1980 // 1. In the common attach case, we should just get a sync-complete.
1981 // 2. In Jit-attach cases, the LS is sending an event, and so we'll get that event and then the sync-complete.
1982 GetProcess()->InitAsyncIPCEvent(event, DB_IPCE_ATTACHING, VMPTR_AppDomain::NullPtr());
1984 // This should result in a sync-complete from the Left-side, which will be raised as an exception
1985 // that the debugger passes into Filter and then internally goes through code:CordbProcess::TriageSyncComplete
1986 // and that triggers code:CordbRCEventThread::FlushQueuedEvents to be called on the RCET.
1987 // We already pre-queued a fake CreateProcess event.
1989 // The left-side will also mark itself as attached in response to this event.
1990 // We explicitly don't mark it as attached from the right-side because we want to let the left-side
1991 // synchronize first (to stop all running threads) before marking the debugger as attached.
1992 LOG((LF_CORDB, LL_INFO1000, "[%x] CP::S: sending attach.\n", GetCurrentThreadId()));
1994 hr = GetProcess()->SendIPCEvent(event, CorDBIPC_BUFFER_SIZE);
1996 LOG((LF_CORDB, LL_INFO1000, "[%x] CP::S: sent attach.\n", GetCurrentThreadId()));
1999 //---------------------------------------------------------------------------------------
2000 // Try to lookup a cached thread object
2003 // vmThread - vm identifier for thread.
2006 // Thread object if cached; null if not yet cached.
2009 // This does not create the thread object if it's not cached. Caching is unpredictable,
2010 // and so this may appear to randomly return NULL.
2011 // Callers should prefer code:CordbProcess::LookupOrCreateThread unless they expicitly
2012 // want to check RS state.
2013 CordbThread * CordbProcess::TryLookupThread(VMPTR_Thread vmThread)
2015 return m_userThreads.GetBase(VmPtrToCookie(vmThread));
2018 //---------------------------------------------------------------------------------------
2019 // Lookup (or create) a CordbThread object by the given volatile OS id. Returns null if not a manged thread
2022 // dwThreadId - os thread id that a managed thread may be using.
2025 // Thread instance if there is currently a managed thread scheduled to run on dwThreadId.
2026 // NULL if this tid is not a valid Managed thread. (This is considered a common case)
2030 // OS Thread ID is not fiber-safe, so this is a dangerous function to call.
2031 // Avoid this as much as possible. Prefer using VMPTR_Thread and
2032 // code:CordbProcess::LookupOrCreateThread instead of OS thread IDs.
2033 // See code:CordbThread::GetID for details.
2034 CordbThread * CordbProcess::TryLookupOrCreateThreadByVolatileOSId(DWORD dwThreadId)
2036 PrepopulateThreadsOrThrow();
2037 return TryLookupThreadByVolatileOSId(dwThreadId);
2040 //---------------------------------------------------------------------------------------
2041 // Lookup a cached CordbThread object by the tid. Returns null if not in the cache (which
2042 // includes unmanged thread)
2045 // dwThreadId - os thread id that a managed thread may be using.
2048 // Thread instance if there is currently a managed thread scheduled to run on dwThreadId.
2049 // NULL if this tid is not a valid Managed thread. (This is considered a common case)
2053 // Avoids this method:
2054 // * OS Thread ID is not fiber-safe, so this is a dangerous function to call.
2055 // * This is juts a Lookup, not LookupOrCreate, so it should only be used by methods
2056 // that care about the RS state (instead of just LS state).
2057 // Prefer using VMPTR_Thread and code:CordbProcess::LookupOrCreateThread
2059 CordbThread * CordbProcess::TryLookupThreadByVolatileOSId(DWORD dwThreadId)
2062 for (CordbThread * pThread = m_userThreads.FindFirst(&find);
2064 pThread = m_userThreads.FindNext(&find))
2066 _ASSERTE(pThread != NULL);
2068 // Get the OS tid. This returns 0 if the thread is switched out.
2069 DWORD dwThreadId2 = GetDAC()->TryGetVolatileOSThreadID(pThread->m_vmThreadToken);
2070 if (dwThreadId2 == dwThreadId)
2076 // This OS thread ID does not match any managed thread id.
2080 //---------------------------------------------------------------------------------------
2081 // Preferred CordbThread lookup routine.
2084 // vmThread - LS thread to lookup. Must be non-null.
2087 // CordbThread instance for given vmThread. May return a previously cached
2088 // instance or create a new instance. Never returns NULL.
2090 CordbThread * CordbProcess::LookupOrCreateThread(VMPTR_Thread vmThread)
2092 _ASSERTE(!vmThread.IsNull());
2094 // Return if we have an existing instance.
2095 CordbThread * pReturn = TryLookupThread(vmThread);
2096 if (pReturn != NULL)
2101 RSInitHolder<CordbThread> pThread(new CordbThread(this, vmThread)); // throws
2102 pReturn = pThread.TransferOwnershipToHash(&m_userThreads);
2110 HRESULT CordbProcess::QueryInterface(REFIID id, void **pInterface)
2112 if (id == IID_ICorDebugProcess)
2114 *pInterface = static_cast<ICorDebugProcess*>(this);
2116 else if (id == IID_ICorDebugController)
2118 *pInterface = static_cast<ICorDebugController*>(static_cast<ICorDebugProcess*>(this));
2120 else if (id == IID_ICorDebugProcess2)
2123 *pInterface = static_cast<ICorDebugProcess2*>(this);
2125 else if (id == IID_ICorDebugProcess3)
2127 *pInterface = static_cast<ICorDebugProcess3*>(this);
2129 else if (id == IID_ICorDebugProcess4)
2131 *pInterface = static_cast<ICorDebugProcess4*>(this);
2133 else if (id == IID_ICorDebugProcess5)
2135 *pInterface = static_cast<ICorDebugProcess5*>(this);
2137 else if (id == IID_ICorDebugProcess7)
2139 *pInterface = static_cast<ICorDebugProcess7*>(this);
2141 else if (id == IID_ICorDebugProcess8)
2143 *pInterface = static_cast<ICorDebugProcess8*>(this);
2145 #ifdef FEATURE_LEGACYNETCF_DBG_HOST_CONTROL
2146 else if (id == IID_ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly)
2148 *pInterface = static_cast<ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly*>(this);
2151 else if (id == IID_IUnknown)
2153 *pInterface = static_cast<IUnknown*>(static_cast<ICorDebugProcess*>(this));
2159 return E_NOINTERFACE;
2169 // Public implementation of ICorDebugProcess4::ProcessStateChanged
2170 HRESULT CordbProcess::ProcessStateChanged(CorDebugStateChange eChange)
2173 PUBLIC_API_BEGIN(this)
2177 case PROCESS_RUNNING:
2178 FlushProcessRunning();
2186 ThrowHR(E_INVALIDARG);
2195 HRESULT CordbProcess::EnumerateHeap(ICorDebugHeapEnum **ppObjects)
2201 PUBLIC_API_ENTRY(this);
2202 ATT_REQUIRE_STOPPED_MAY_FAIL(this);
2206 if (m_pDacPrimitives->AreGCStructuresValid())
2208 CordbHeapEnum *pHeapEnum = new CordbHeapEnum(this);
2209 GetContinueNeuterList()->Add(this, pHeapEnum);
2210 hr = pHeapEnum->QueryInterface(__uuidof(ICorDebugHeapEnum), (void**)ppObjects);
2214 hr = CORDBG_E_GC_STRUCTURES_INVALID;
2217 EX_CATCH_HRESULT(hr);
2222 HRESULT CordbProcess::GetGCHeapInformation(COR_HEAPINFO *pHeapInfo)
2225 return E_INVALIDARG;
2228 PUBLIC_API_ENTRY(this);
2229 ATT_REQUIRE_STOPPED_MAY_FAIL(this);
2233 GetDAC()->GetGCHeapInformation(pHeapInfo);
2235 EX_CATCH_HRESULT(hr);
2240 HRESULT CordbProcess::EnumerateHeapRegions(ICorDebugHeapSegmentEnum **ppRegions)
2243 return E_INVALIDARG;
2246 PUBLIC_API_ENTRY(this);
2247 ATT_REQUIRE_STOPPED_MAY_FAIL(this);
2251 DacDbiArrayList<COR_SEGMENT> segments;
2252 hr = GetDAC()->GetHeapSegments(&segments);
2256 if (!segments.IsEmpty())
2258 CordbHeapSegmentEnumerator *segEnum = new CordbHeapSegmentEnumerator(this, &segments[0], (DWORD)segments.Count());
2259 GetContinueNeuterList()->Add(this, segEnum);
2260 hr = segEnum->QueryInterface(__uuidof(ICorDebugHeapSegmentEnum), (void**)ppRegions);
2268 EX_CATCH_HRESULT(hr);
2273 HRESULT CordbProcess::GetObject(CORDB_ADDRESS addr, ICorDebugObjectValue **pObject)
2277 PUBLIC_REENTRANT_API_ENTRY(this);
2278 ATT_REQUIRE_STOPPED_MAY_FAIL(this);
2282 if (!m_pDacPrimitives->IsValidObject(addr))
2284 hr = CORDBG_E_CORRUPT_OBJECT;
2286 else if (pObject == NULL)
2292 RSLockHolder ch(GetProcess()->GetStopGoLock());
2293 RSLockHolder procLock(this->GetProcess()->GetProcessLock());
2295 CordbAppDomain *cdbAppDomain = NULL;
2296 CordbType *pType = NULL;
2297 hr = GetTypeForObject(addr, &pType, &cdbAppDomain);
2301 _ASSERTE(pType != NULL);
2302 _ASSERTE(cdbAppDomain != NULL);
2304 DebuggerIPCE_ObjectData objData;
2305 m_pDacPrimitives->GetBasicObjectInfo(addr, ELEMENT_TYPE_CLASS, cdbAppDomain->GetADToken(), &objData);
2307 NewHolder<CordbObjectValue> pNewObjectValue(new CordbObjectValue(cdbAppDomain, pType, TargetBuffer(addr, (ULONG)objData.objSize), &objData));
2308 hr = pNewObjectValue->Init();
2312 hr = pNewObjectValue->QueryInterface(__uuidof(ICorDebugObjectValue), (void**)pObject);
2314 pNewObjectValue.SuppressRelease();
2319 EX_CATCH_HRESULT(hr);
2325 HRESULT CordbProcess::EnumerateGCReferences(BOOL enumerateWeakReferences, ICorDebugGCReferenceEnum **ppEnum)
2331 PUBLIC_API_ENTRY(this);
2332 ATT_REQUIRE_STOPPED_MAY_FAIL(this);
2336 CordbRefEnum *pRefEnum = new CordbRefEnum(this, enumerateWeakReferences);
2337 GetContinueNeuterList()->Add(this, pRefEnum);
2338 hr = pRefEnum->QueryInterface(IID_ICorDebugGCReferenceEnum, (void**)ppEnum);
2340 EX_CATCH_HRESULT(hr);
2344 HRESULT CordbProcess::EnumerateHandles(CorGCReferenceType types, ICorDebugGCReferenceEnum **ppEnum)
2350 PUBLIC_API_ENTRY(this);
2351 ATT_REQUIRE_STOPPED_MAY_FAIL(this);
2355 CordbRefEnum *pRefEnum = new CordbRefEnum(this, types);
2356 GetContinueNeuterList()->Add(this, pRefEnum);
2357 hr = pRefEnum->QueryInterface(IID_ICorDebugGCReferenceEnum, (void**)ppEnum);
2359 EX_CATCH_HRESULT(hr);
2364 HRESULT CordbProcess::EnableNGENPolicy(CorDebugNGENPolicy ePolicy)
2370 HRESULT CordbProcess::GetTypeID(CORDB_ADDRESS obj, COR_TYPEID *pId)
2376 PUBLIC_API_ENTRY(this);
2377 ATT_REQUIRE_STOPPED_MAY_FAIL(this);
2381 hr = GetProcess()->GetDAC()->GetTypeID(obj, pId);
2383 EX_CATCH_HRESULT(hr);
2388 HRESULT CordbProcess::GetTypeForTypeID(COR_TYPEID id, ICorDebugType **ppType)
2395 PUBLIC_API_ENTRY(this);
2396 RSLockHolder stopGoLock(this->GetProcess()->GetStopGoLock());
2397 RSLockHolder procLock(this->GetProcess()->GetProcessLock());
2401 DebuggerIPCE_ExpandedTypeData data;
2402 GetDAC()->GetObjectExpandedTypeInfoFromID(AllBoxed, VMPTR_AppDomain::NullPtr(), id, &data);
2404 CordbType *type = 0;
2405 hr = CordbType::TypeDataToType(GetSharedAppDomain(), &data, &type);
2408 hr = type->QueryInterface(IID_ICorDebugType, (void**)ppType);
2410 EX_CATCH_HRESULT(hr);
2416 COM_METHOD CordbProcess::GetArrayLayout(COR_TYPEID id, COR_ARRAY_LAYOUT *pLayout)
2418 if (pLayout == NULL)
2422 PUBLIC_API_BEGIN(this);
2424 hr = GetProcess()->GetDAC()->GetArrayLayout(id, pLayout);
2430 COM_METHOD CordbProcess::GetTypeLayout(COR_TYPEID id, COR_TYPE_LAYOUT *pLayout)
2432 if (pLayout == NULL)
2436 PUBLIC_API_BEGIN(this);
2438 hr = GetProcess()->GetDAC()->GetTypeLayout(id, pLayout);
2444 COM_METHOD CordbProcess::GetTypeFields(COR_TYPEID id, ULONG32 celt, COR_FIELD fields[], ULONG32 *pceltNeeded)
2447 PUBLIC_API_BEGIN(this);
2449 hr = GetProcess()->GetDAC()->GetObjectFields(id, celt, fields, pceltNeeded);
2455 COM_METHOD CordbProcess::SetWriteableMetadataUpdateMode(WriteableMetadataUpdateMode flags)
2458 PUBLIC_API_BEGIN(this);
2460 if(flags != LegacyCompatPolicy &&
2461 flags != AlwaysShowUpdates)
2465 else if(m_pShim != NULL)
2467 if(flags != LegacyCompatPolicy)
2469 hr = CORDBG_E_UNSUPPORTED;
2475 m_writableMetadataUpdateMode = flags;
2482 COM_METHOD CordbProcess::EnableExceptionCallbacksOutsideOfMyCode(BOOL enableExceptionsOutsideOfJMC)
2485 PUBLIC_API_BEGIN(this);
2487 hr = GetProcess()->GetDAC()->SetSendExceptionsOutsideOfJMC(enableExceptionsOutsideOfJMC);
2493 #ifdef FEATURE_LEGACYNETCF_DBG_HOST_CONTROL
2495 COM_METHOD CordbProcess::InvokePauseCallback()
2500 COM_METHOD CordbProcess::InvokeResumeCallback()
2507 HRESULT CordbProcess::GetTypeForObject(CORDB_ADDRESS addr, CordbType **ppType, CordbAppDomain **pAppDomain)
2509 VMPTR_AppDomain appDomain;
2511 VMPTR_DomainFile domainFile;
2513 HRESULT hr = E_FAIL;
2514 if (GetDAC()->GetAppDomainForObject(addr, &appDomain, &mod, &domainFile))
2516 CordbAppDomain *cdbAppDomain = appDomain.IsNull() ? GetSharedAppDomain() : LookupOrCreateAppDomain(appDomain);
2518 _ASSERTE(cdbAppDomain);
2520 DebuggerIPCE_ExpandedTypeData data;
2521 GetDAC()->GetObjectExpandedTypeInfo(AllBoxed, appDomain, addr, &data);
2523 CordbType *type = 0;
2524 hr = CordbType::TypeDataToType(cdbAppDomain, &data, &type);
2530 *pAppDomain = cdbAppDomain;
2538 // ******************************************
2540 // ******************************************
2541 CordbRefEnum::CordbRefEnum(CordbProcess *proc, BOOL walkWeakRefs)
2542 : CordbBase(proc, 0, enumCordbHeap), mRefHandle(0), mEnumStacksFQ(TRUE),
2543 mHandleMask((UINT32)(walkWeakRefs ? CorHandleAll : CorHandleStrongOnly))
2547 CordbRefEnum::CordbRefEnum(CordbProcess *proc, CorGCReferenceType types)
2548 : CordbBase(proc, 0, enumCordbHeap), mRefHandle(0), mEnumStacksFQ(FALSE),
2549 mHandleMask((UINT32)types)
2553 void CordbRefEnum::Neuter()
2559 GetProcess()->GetDAC()->DeleteRefWalk(mRefHandle);
2565 _ASSERTE(!"Hit an error freeing a ref walk.");
2567 EX_END_CATCH(SwallowAllExceptions)
2569 CordbBase::Neuter();
2572 HRESULT CordbRefEnum::QueryInterface(REFIID riid, void **ppInterface)
2574 if (ppInterface == NULL)
2575 return E_INVALIDARG;
2577 if (riid == IID_ICorDebugGCReferenceEnum)
2579 *ppInterface = static_cast<ICorDebugGCReferenceEnum*>(this);
2581 else if (riid == IID_IUnknown)
2583 *ppInterface = static_cast<IUnknown*>(static_cast<ICorDebugGCReferenceEnum*>(this));
2587 *ppInterface = NULL;
2588 return E_NOINTERFACE;
2595 HRESULT CordbRefEnum::Skip(ULONG celt)
2600 HRESULT CordbRefEnum::Reset()
2602 PUBLIC_API_ENTRY(this);
2608 GetProcess()->GetDAC()->DeleteRefWalk(mRefHandle);
2612 EX_CATCH_HRESULT(hr);
2617 HRESULT CordbRefEnum::Clone(ICorDebugEnum **ppEnum)
2622 HRESULT CordbRefEnum::GetCount(ULONG *pcelt)
2630 HRESULT CordbRefEnum::Next(ULONG celt, COR_GC_REFERENCE refs[], ULONG *pceltFetched)
2632 if (refs == NULL || pceltFetched == NULL)
2635 CordbProcess *process = GetProcess();
2638 PUBLIC_API_ENTRY(this);
2639 FAIL_IF_NEUTERED(this);
2640 ATT_REQUIRE_STOPPED_MAY_FAIL(process);
2642 RSLockHolder procLockHolder(process->GetProcessLock());
2647 hr = process->GetDAC()->CreateRefWalk(&mRefHandle, mEnumStacksFQ, mEnumStacksFQ, mHandleMask);
2651 DacGcReference dacRefs[32];
2652 ULONG toFetch = _countof(dacRefs);
2655 for (ULONG c = 0; SUCCEEDED(hr) && c < (celt/_countof(dacRefs) + 1); ++c)
2657 // Fetch 32 references at a time, the last time, only fetch the remainder (that is, if
2658 // the user didn't fetch a multiple of 32).
2659 if (c == celt/_countof(dacRefs))
2660 toFetch = celt % _countof(dacRefs);
2663 hr = process->GetDAC()->WalkRefs(mRefHandle, toFetch, dacRefs, &fetched);
2667 for (ULONG i = 0; i < fetched; ++i)
2669 CordbAppDomain *pDomain = process->LookupOrCreateAppDomain(dacRefs[i].vmDomain);
2671 ICorDebugAppDomain *pAppDomain;
2672 ICorDebugValue *pOutObject = NULL;
2673 if (dacRefs[i].pObject & 1)
2675 dacRefs[i].pObject &= ~1;
2676 ICorDebugObjectValue *pObjValue = NULL;
2678 hr = process->GetObject(dacRefs[i].pObject, &pObjValue);
2682 hr = pObjValue->QueryInterface(IID_ICorDebugValue, (void**)&pOutObject);
2683 pObjValue->Release();
2688 ICorDebugReferenceValue *tmpValue = NULL;
2689 IfFailThrow(CordbReferenceValue::BuildFromGCHandle(pDomain,
2695 hr = tmpValue->QueryInterface(IID_ICorDebugValue, (void**)&pOutObject);
2696 tmpValue->Release();
2700 if (SUCCEEDED(hr) && pDomain)
2702 hr = pDomain->QueryInterface(IID_ICorDebugAppDomain, (void**)&pAppDomain);
2708 refs[total].Domain = pAppDomain;
2709 refs[total].Location = pOutObject;
2710 refs[total].Type = (CorGCReferenceType)dacRefs[i].dwType;
2711 refs[total].ExtraData = dacRefs[i].i64ExtraData;
2718 *pceltFetched = total;
2721 EX_CATCH_HRESULT(hr);
2727 // ******************************************
2729 // ******************************************
2730 CordbHeapEnum::CordbHeapEnum(CordbProcess *proc)
2731 : CordbBase(proc, 0, enumCordbHeap), mHeapHandle(0)
2735 HRESULT CordbHeapEnum::QueryInterface(REFIID riid, void **ppInterface)
2737 if (ppInterface == NULL)
2738 return E_INVALIDARG;
2740 if (riid == IID_ICorDebugHeapEnum)
2742 *ppInterface = static_cast<ICorDebugHeapEnum*>(this);
2744 else if (riid == IID_IUnknown)
2746 *ppInterface = static_cast<IUnknown*>(static_cast<ICorDebugHeapEnum*>(this));
2750 *ppInterface = NULL;
2751 return E_NOINTERFACE;
2758 HRESULT CordbHeapEnum::Skip(ULONG celt)
2763 HRESULT CordbHeapEnum::Reset()
2769 void CordbHeapEnum::Clear()
2775 GetProcess()->GetDAC()->DeleteHeapWalk(mHeapHandle);
2781 _ASSERTE(!"Hit an error freeing the heap walk.");
2783 EX_END_CATCH(SwallowAllExceptions)
2786 HRESULT CordbHeapEnum::Clone(ICorDebugEnum **ppEnum)
2791 HRESULT CordbHeapEnum::GetCount(ULONG *pcelt)
2796 HRESULT CordbHeapEnum::Next(ULONG celt, COR_HEAPOBJECT objects[], ULONG *pceltFetched)
2799 PUBLIC_API_ENTRY(this);
2800 RSLockHolder stopGoLock(this->GetProcess()->GetStopGoLock());
2801 RSLockHolder procLock(this->GetProcess()->GetProcessLock());
2806 if (mHeapHandle == 0)
2808 hr = GetProcess()->GetDAC()->CreateHeapWalk(&mHeapHandle);
2813 hr = GetProcess()->GetDAC()->WalkHeap(mHeapHandle, celt, objects, &fetched);
2814 _ASSERTE(fetched <= celt);
2819 // Return S_FALSE if we've reached the end of the enum.
2824 EX_CATCH_HRESULT(hr);
2826 // Set the fetched parameter to reflect the number of elements (if any)
2827 // that were successfully saved to "objects"
2829 *pceltFetched = fetched;
2834 //---------------------------------------------------------------------------------------
2835 // Flush state for when the process starts running.
2838 // Helper for code:CordbProcess::ProcessStateChanged.
2839 // Since ICD Arrowhead does not own the eventing pipeline, it needs the debugger to
2840 // notifying it of when the process is running again. This is like the counterpart
2841 // to code:CordbProcess::Filter
2842 void CordbProcess::FlushProcessRunning()
2844 _ASSERTE(GetProcessLock()->HasLock());
2846 // Update the continue counter.
2847 m_continueCounter++;
2849 // Safely dispose anything that should be neutered on continue.
2850 MarkAllThreadsDirty();
2854 //---------------------------------------------------------------------------------------
2855 // Flush all cached state and bring us back to "cold startup"
2858 // Helper for code:CordbProcess::ProcessStateChanged.
2859 // This is used if the data-target changes underneath us in a way that is
2860 // not consistent with the process running forward. For example, if for
2861 // a time-travel debugger, the data-target may flow "backwards" in time.
2863 void CordbProcess::FlushAll()
2872 _ASSERTE(GetProcessLock()->HasLock());
2875 // First, determine if it's safe to Flush
2878 hr = IsReadyForDetach();
2881 // Check for outstanding CordbHandle values.
2882 if (OutstandingHandles())
2884 ThrowHR(CORDBG_E_DETACH_FAILED_OUTSTANDING_TARGET_RESOURCES);
2887 // FlushAll is a superset of FlushProcessRunning.
2888 // This will also ensure we clear the DAC cache.
2889 FlushProcessRunning();
2891 // If we detach before the CLR is loaded into the debuggee, then we can no-op a lot of work.
2892 // We sure can't be sending IPC events to the LS before it exists.
2896 //---------------------------------------------------------------------------------------
2898 // Detach the Debugger from the LS process.
2902 // S_OK on successful detach. Else errror.
2905 // Target is stopped.
2908 // Once we're detached, the LS can resume running and exit.
2909 // So it's possible to get an ExitProcess callback in the middle of the Detach phase. If that happens,
2910 // we must return CORDBG_E_PROCESS_TERMINATED and pretend that the exit happened before we tried to detach.
2911 // Else if we detach successfully, return S_OK.
2913 // @dbgtodo attach-bit: need to figure out semantics of Detach
2914 // in V3, especially w.r.t to an attach bit.
2915 //---------------------------------------------------------------------------------------
2916 HRESULT CordbProcess::Detach()
2918 PUBLIC_API_ENTRY(this);
2920 FAIL_IF_NEUTERED(this);
2922 if (IsInteropDebugging())
2924 return CORDBG_E_INTEROP_NOT_SUPPORTED;
2929 // A very important note: we require that the process is synchronized before doing a detach. This ensures
2930 // that no events are on their way from the Left Side. We also require that the user has drained the
2931 // managed event queue, but there is currently no way to really enforce that here.
2932 // @todo- why can't we enforce that the managed event Q is drained?
2933 ATT_REQUIRE_SYNCED_OR_NONINIT_MAY_FAIL(this);
2936 hr = IsReadyForDetach();
2939 // Avoid neutering. Gives client a chance to fix detach issue and retry.
2943 // Since the detach may resume the LS and allow it to exit, which may invoke the EP callback
2944 // which may destroy this process object, be sure to protect us w/ an extra AddRef/Release
2945 RSSmartPtr<CordbProcess> pRef(this);
2949 LOG((LF_CORDB, LL_INFO1000, "CP::Detach - beginning\n"));
2950 if (m_pShim == NULL) // This API is moved off to the shim
2953 // This is still invasive.
2954 // Ignore failures. This will fail for a non-invasive target.
2955 if (IsDacInitialized())
2957 HRESULT hrIgnore = S_OK;
2960 GetDAC()->MarkDebuggerAttached(FALSE);
2962 EX_CATCH_HRESULT(hrIgnore);
2971 EX_CATCH_HRESULT(hr);
2974 // Either way, neuter everything.
2977 // Implicit release on pRef
2978 LOG((LF_CORDB, LL_INFO1000, "CP::Detach - returning w/ hr=0x%x\n", hr));
2982 // Free up key left-side resources
2985 // This does key neutering of objects that hold left-side resources and require
2986 // preemptively freeing the resources.
2987 // After this, code:CordbProcess::Neuter should only affect right-side state.
2988 void CordbProcess::NeuterChildrenLeftSideResources()
2990 _ASSERTE(GetStopGoLock()->HasLock());
2992 _ASSERTE(!GetProcessLock()->HasLock());
2993 RSLockHolder lockHolder(GetProcessLock());
2996 // Need process-lock to operate on hashtable, but can't yet Neuter under process-lock,
2997 // so we have to copy the contents to an auxilary list which we can then traverse outside the lock.
2998 RSPtrArray<CordbAppDomain> listAppDomains;
2999 m_appDomains.CopyToArray(&listAppDomains);
3003 // Must not hold process lock so that we can be safe to send IPC events
3004 // to cleanup left-side resources.
3005 lockHolder.Release();
3006 _ASSERTE(!GetProcessLock()->HasLock());
3008 // Frees left-side resources. This may send IPC events.
3009 // This will make normal neutering a nop.
3010 m_LeftSideResourceCleanupList.NeuterLeftSideResourcesAndClear(this);
3012 for(unsigned int idx = 0; idx < listAppDomains.Length(); idx++)
3014 CordbAppDomain * pAppDomain = listAppDomains[idx];
3016 // CordbHandleValue is in the appdomain exit list, and that needs
3017 // to send an IPC event to cleanup and release the handle from
3018 // the GCs handle table.
3019 pAppDomain->GetSweepableExitNeuterList()->NeuterLeftSideResourcesAndClear(this);
3021 listAppDomains.Clear();
3025 //---------------------------------------------------------------------------------------
3026 // Detach the Debugger from the LS process for the V2 case
3029 // This will NeuterChildren(), caller will do the real Neuter()
3030 // Caller has already ensured that detach is safe.
3032 // @dbgtodo attach-bit: this should be moved into the shim; need
3033 // to figure out semantics for freeing left-side resources (especially GC
3034 // handles) on detach.
3035 void CordbProcess::DetachShim()
3041 // If we detach before the CLR is loaded into the debuggee, then we can no-op a lot of work.
3042 // We sure can't be sending IPC events to the LS before it exists.
3045 // The managed event queue is not necessarily drained. Cordbg could call detach between any callback.
3046 // While the process is still stopped, neuter all of our children.
3047 // This will make our Neuter() a nop and saves the W32ET from having to do dangerous work.
3048 this->NeuterChildrenLeftSideResources();
3050 RSLockHolder lockHolder(GetProcessLock());
3051 this->NeuterChildren();
3054 // Go ahead and detach from the entire process now. This is like sending a "Continue".
3055 DebuggerIPCEvent * pIPCEvent = (DebuggerIPCEvent *) _alloca(CorDBIPC_BUFFER_SIZE);
3056 InitIPCEvent(pIPCEvent, DB_IPCE_DETACH_FROM_PROCESS, true, VMPTR_AppDomain::NullPtr());
3058 hr = m_cordb->SendIPCEvent(this, pIPCEvent, CorDBIPC_BUFFER_SIZE);
3059 hr = WORST_HR(hr, pIPCEvent->hr);
3064 // @dbgtodo attach-bit: push this up, once detach IPC event is hoisted.
3065 RSLockHolder lockHolder(GetProcessLock());
3067 // Shouldn't have any appdomains.
3068 (void)hashFind; //prevent "unused variable" error from GCC
3069 _ASSERTE(m_appDomains.FindFirst(&hashFind) == NULL);
3072 LOG((LF_CORDB, LL_INFO10000, "CP::Detach - got reply from LS\n"));
3074 // It's possible that the LS may exit after they reply to our detach_from_process, but
3075 // before we update our internal state that they're detached. So still have to check
3076 // failure codes here.
3077 hr = this->m_pShim->GetWin32EventThread()->SendDetachProcessEvent(this);
3080 // Since we're auto-continuing when we detach, we should set the stop count back to zero.
3081 // This (along w/ m_detached) prevents anyone from calling Continue on this process
3082 // after this call returns.
3085 if (hr != CORDBG_E_PROCESS_TERMINATED)
3087 // Remember that we've detached from this process object. This will prevent any further operations on
3088 // this process, just in case... :)
3089 // If LS exited, then don't set this flag because it overrides m_terminated when reporting errors;
3090 // and we want to provide a consistent story about whether we detached or whether the LS exited.
3096 // Now that all complicated cleanup is done, caller can do a final neuter.
3097 // This will implicitly stop our Win32 event thread as well.
3100 // Delete all events from the queue without dispatching. This is useful in shutdown.
3101 // An event that is currently dispatching is not on the queue.
3102 void CordbProcess::DeleteQueuedEvents()
3104 INTERNAL_API_ENTRY(this);
3105 // We must have the process lock to ensure that no one is trying to add an event
3106 _ASSERTE(!ThreadHoldsProcessLock());
3108 if (m_pShim != NULL)
3110 PUBLIC_CALLBACK_IN_THIS_SCOPE0_NO_LOCK(this);
3112 // DeleteAll() is part of the shim, and it will change external ref counts, so must really
3113 // be marked as outside the RS.
3114 m_pShim->GetManagedEventQueue()->DeleteAll();
3118 //---------------------------------------------------------------------------------------
3120 // Track that we're about to dispatch a managed event.
3123 // event - event being dispatched
3126 // This is used to support code:CordbProcess::AreDispatchingEvent
3127 // This is always called on the same thread as code:CordbProcess::FinishEventDispatch
3128 void CordbProcess::StartEventDispatch(DebuggerIPCEventType event)
3130 LIMITED_METHOD_CONTRACT;
3132 _ASSERTE(m_dispatchedEvent == DB_IPCE_DEBUGGER_INVALID);
3133 _ASSERTE(event != DB_IPCE_DEBUGGER_INVALID);
3134 m_dispatchedEvent = event;
3137 //---------------------------------------------------------------------------------------
3139 // Track that we're done dispatching a managed event.
3143 // This is always called on the same thread as code:CordbProcess::StartEventDispatch
3146 // @dbgtodo shim: eventually this goes into the shim when we hoist Continue
3147 void CordbProcess::FinishEventDispatch()
3149 LIMITED_METHOD_CONTRACT;
3151 _ASSERTE(m_dispatchedEvent != DB_IPCE_DEBUGGER_INVALID);
3152 m_dispatchedEvent = DB_IPCE_DEBUGGER_INVALID;
3155 //---------------------------------------------------------------------------------------
3157 // Are we in the middle of dispatching an event?
3160 // This is used by code::CordbProcess::ContinueInternal. Continue logic takes
3161 // a shortcut if the continue is called on the dispatch thread.
3162 // It doesn't matter which event is being dispatch; only that we're on the dispatch thread.
3163 // @dbgtodo shim: eventually this goes into the shim when we hoist Continue
3164 bool CordbProcess::AreDispatchingEvent()
3166 LIMITED_METHOD_CONTRACT;
3168 return m_dispatchedEvent != DB_IPCE_DEBUGGER_INVALID;
3175 // Terminate the app. We'll still dispatch an ExitProcess callback, so the app
3176 // must wait for that before calling Cordb::Terminate.
3177 // If this fails, the client can always call the OS's TerminateProcess command
3178 // to rudely kill the debuggee.
3179 HRESULT CordbProcess::Terminate(unsigned int exitCode)
3181 PUBLIC_API_ENTRY(this);
3183 LOG((LF_CORDB, LL_INFO1000, "CP::Terminate: with exitcode %u\n", exitCode));
3184 FAIL_IF_NEUTERED(this);
3187 // @dbgtodo shutdown: eventually, all of Terminate() will be in the Shim.
3188 // Free all the remaining events. Since this will call into the shim, do this outside of any locks.
3189 // (ATT_ takes locks).
3190 DeleteQueuedEvents();
3192 ATT_REQUIRE_SYNCED_OR_NONINIT_MAY_FAIL(this);
3194 // When we terminate the process, it's handle will become signaled and
3195 // Win32 Event Thread will leap into action and call CordbWin32EventThread::ExitProcess
3196 // Unfortunately, that may destroy this object if the ExitProcess callback
3197 // decides to call Release() on the process.
3200 // Indicate that the process is exiting so that (among other things) we don't try and
3201 // send messages to the left side while it's being deleted.
3204 // In case we're continuing from the loader bp, we don't want to try and kick off an attach. :)
3205 m_fDoDelayedManagedAttached = false;
3210 // We'd like to just take a lock around everything here, but that may deadlock us
3211 // since W32ET will wait on the lock, and Continue may wait on W32ET.
3212 // So we just do an extra AddRef/Release to make sure we're still around.
3213 // @todo - could we move this smartptr up so that it's well-nested w/ the lock?
3214 RSSmartPtr<CordbProcess> pRef(this);
3219 // At any point after this call, the w32 ET may run the ExitProcess code which will race w/ the continue call.
3220 // This call only posts a request that the process terminate and does not guarantee the process actually
3221 // terminates. In particular, the process can not exit until any outstanding IO requests are done (on cancelled).
3222 // It also can not exit if we have an outstanding not-continued native-debug event.
3223 // Fortunately, the interesting work in terminate is done in ExitProcessWorkItem::Do, which can take the Stop-Go lock.
3224 // Since we're currently holding the stop-go lock, that means we at least get some serialization.
3226 // Note that on Windows, the process isn't really terminated until we receive the EXIT_PROCESS_DEBUG_EVENT.
3227 // Before then, we can still still access the debuggee's address space. On the other, for Mac debugging,
3228 // the process can die any time after this call, and so we can no longer call into the DAC.
3229 GetShim()->GetNativePipeline()->TerminateProcess(exitCode);
3231 // We just call Continue() so that the debugger doesn't have to. (It's arguably odd
3232 // to call Continue() after Terminate).
3233 // We're stopped & Synced.
3234 // For interop-debugging this is very important because the Terminate may not really kill the process
3235 // until after we continue from the current native debug event.
3236 ContinueInternal(FALSE);
3238 // Implicit release on pRef here (since it's going out of scope)...
3239 // After this release, this object may be destroyed. So don't use any member functions
3240 // (including Locks) after here.
3246 // This can be called at any time, even if we're in an unrecoverable error state.
3247 HRESULT CordbProcess::GetID(DWORD *pdwProcessId)
3249 PUBLIC_REENTRANT_API_ENTRY(this);
3250 OK_IF_NEUTERED(this);
3251 VALIDATE_POINTER_TO_OBJECT(pdwProcessId, DWORD *);
3256 // This shouldn't be used in V3 paths. Normally, we can enforce that by checking against
3257 // m_pShim. However, this API can be called after being neutered, in which case m_pShim is cleared.
3258 // So check against 0 instead.
3264 *pdwProcessId = GetPid();
3266 EX_CATCH_HRESULT(hr);
3270 // Helper to get PID internally. We know we'll always succeed.
3271 // This is more convient for internal callers since they can just use it as an expression
3272 // without having to check HRESULTS.
3273 DWORD CordbProcess::GetPid()
3275 // This shouldn't be used in V3 paths, in which case it's set to 0. Only the shim should be
3276 // calling this. Assert to catch anybody else.
3277 _ASSERTE(m_id != 0);
3279 return (DWORD) m_id;
3283 HRESULT CordbProcess::GetHandle(HANDLE *phProcessHandle)
3285 PUBLIC_REENTRANT_API_ENTRY(this);
3286 FAIL_IF_NEUTERED(this); // Once we neuter the process, we close our OS handle to it.
3287 VALIDATE_POINTER_TO_OBJECT(phProcessHandle, HANDLE *);
3289 if (m_pShim == NULL)
3291 _ASSERTE(!"CordbProcess::GetHandle() should be not be called on the new architecture");
3292 *phProcessHandle = NULL;
3297 *phProcessHandle = m_handle;
3302 HRESULT CordbProcess::IsRunning(BOOL *pbRunning)
3304 PUBLIC_API_ENTRY(this);
3305 FAIL_IF_NEUTERED(this);
3306 VALIDATE_POINTER_TO_OBJECT(pbRunning, BOOL*);
3308 *pbRunning = !GetSynchronized();
3313 HRESULT CordbProcess::EnableSynchronization(BOOL bEnableSynchronization)
3316 PUBLIC_API_ENTRY(this);
3320 HRESULT CordbProcess::Stop(DWORD dwTimeout)
3322 PUBLIC_API_ENTRY(this);
3323 CORDBRequireProcessStateOK(this);
3325 HRESULT hr = StopInternal(dwTimeout, VMPTR_AppDomain::NullPtr());
3327 return ErrWrapper(hr);
3330 HRESULT CordbProcess::StopInternal(DWORD dwTimeout, VMPTR_AppDomain pAppDomainToken)
3332 LOG((LF_CORDB, LL_INFO1000, "CP::S: stopping process 0x%x(%d) with timeout %d\n", m_id, m_id, dwTimeout));
3334 INTERNAL_API_ENTRY(this);
3336 // Stop + Continue are executed under the Stop-Go lock. This makes them atomic.
3337 // We'll toggle the process-lock (b/c we communicate w/ the W32et, so just the process-lock is
3338 // not sufficient to make this atomic).
3339 // It's ok to take this lock before checking if the CordbProcess has been neutered because
3340 // the lock is destroyed in the dtor after neutering.
3341 RSLockHolder ch(&m_StopGoLock);
3343 // Check if this CordbProcess has been neutered under the SG lock.
3344 // Otherwise it's possible to race with Detach() and Terminate().
3345 FAIL_IF_NEUTERED(this);
3346 CORDBFailIfOnWin32EventThread(this);
3348 if (m_pShim == NULL) // Stop/Go is moved off to the shim
3354 DebuggerIPCEvent* event;
3357 STRESS_LOG2(LF_CORDB, LL_INFO1000, "CP::SI, timeout=%d, this=%p\n", dwTimeout, this);
3359 // Stop() is a syncronous (blocking) operation. Furthermore, we have no way to cancel the async-break request.
3360 // Thus if we returned early on a timeout, then we'll be in a random state b/c the LS may get stopped at any
3362 // One solution just require the param is INFINITE until we fix this and E_INVALIDARG if it's not.
3363 // But that could be a breaking change (what if a debugger passes in a really large value that's effectively
3365 // So we'll just ignore it and always treat it as infinite.
3366 dwTimeout = INFINITE;
3368 // Do the checks on the process state under the SG lock. This ensures that another thread cannot come in
3369 // after we do the checks and take the lock before we do. For example, Detach() can race with Stop() such
3371 // 1. Thread A calls CordbProcess::Detach() and takes the stop-go lock
3372 // 2. Thread B calls CordbProcess::Stop(), passes all the checks, and then blocks on the stop-go lock
3373 // 3. Thread A finishes the detach, invalides the process state, cleans all the resources, and then
3374 // releases the stop-go lock
3375 // 4. Thread B gets the lock, but everything has changed
3376 CORDBRequireProcessStateOK(this);
3380 ASSERT_SINGLE_THREAD_ONLY(HoldsLock(&m_StopGoLock));
3382 // Don't need to stop if the process hasn't even executed any managed code yet.
3385 LOG((LF_CORDB, LL_INFO1000, "CP::S: process isn't initialized yet.\n"));
3387 // Mark the process as synchronized so no events will be dispatched until the thing is continued.
3388 SetSynchronized(true);
3390 // Remember uninitialized stop...
3391 m_uninitializedStop = true;
3393 #ifdef FEATURE_INTEROP_DEBUGGING
3394 // If we're Win32 attached, then suspend all the unmanaged threads in the process.
3395 // We may or may not be stopped at a native debug event.
3396 if (IsInteropDebugging())
3398 SuspendUnmanagedThreads();
3400 #endif // FEATURE_INTEROP_DEBUGGING
3402 // Get the RC Event Thread to stop listening to the process.
3403 m_cordb->ProcessStateChanged();
3409 // Don't need to stop if the process is already synchronized.
3410 // @todo - Issue 129917. It's possible that we'll get a call to Stop when the LS is already stopped.
3411 // Sending an AsyncBreak would deadlock here (b/c the LS will ignore the frivilous request,
3412 // and thus never send a SyncComplete, and thus our Waiting on the SyncComplete will deadlock).
3413 // We avoid this case by checking m_syncCompleteReceived (which should roughly correspond to
3414 // the LS's m_stopped variable).
3415 // One window this can happen is after a Continue() pings the RCET but before the RCET actually sweeps + flushes.
3417 if (GetSynchronized() || GetSyncCompleteRecv())
3419 LOG((LF_CORDB, LL_INFO1000, "CP::S: process was already synchronized. m_syncCompleteReceived=%d\n", GetSyncCompleteRecv()));
3421 if (GetSyncCompleteRecv())
3423 // We must be in that window alluded to above (while the RCET is sweeping). Re-ping the RCET.
3424 SetSynchronized(true);
3425 m_cordb->ProcessStateChanged();
3431 STRESS_LOG0(LF_CORDB, LL_INFO1000, "CP::S: process not sync'd, requesting stop.\n");
3433 m_stopRequested = true;
3435 // We don't want to dispatch any Win32 debug events while we're trying to stop.
3436 // Setting m_specialDeferment=true means that any debug event we get will be queued and not dispatched.
3437 // We do this to avoid a nested call to Continue.
3438 // These defered events will get dispatched when somebody calls continue (and since they're calling
3439 // stop now, they must call continue eventually).
3440 // Note that if we got a Win32 debug event between when we took the Stop-Go lock above and now,
3441 // that even may have been dispatched. We're ok because SSFW32Stop will hijack that event and continue it,
3442 // and then all future events will be queued.
3443 m_specialDeferment = true;
3446 BOOL asyncBreakSent;
3448 // We need to ensure that the helper thread is alive.
3449 hr = this->StartSyncFromWin32Stop(&asyncBreakSent);
3461 m_stopRequested = false;
3466 // Send the async break event to the RC.
3467 event = (DebuggerIPCEvent*) _alloca(CorDBIPC_BUFFER_SIZE);
3468 InitIPCEvent(event, DB_IPCE_ASYNC_BREAK, false, pAppDomainToken);
3470 STRESS_LOG1(LF_CORDB, LL_INFO1000, "CP::S: sending async stop to appd 0x%x.\n", VmPtrToCookie(pAppDomainToken));
3472 hr = m_cordb->SendIPCEvent(this, event, CorDBIPC_BUFFER_SIZE);
3473 hr = WORST_HR(hr, event->hr);
3476 // We don't hold the lock so just return immediately. Don't adjust stop-count.
3477 _ASSERTE(!ThreadHoldsProcessLock());
3481 LOG((LF_CORDB, LL_INFO1000, "CP::S: sent async stop to appd 0x%x.\n", VmPtrToCookie(pAppDomainToken)));
3483 // Wait for the sync complete message to come in. Note: when the sync complete message arrives to the RCEventThread,
3484 // it will mark the process as synchronized and _not_ dispatch any events. Instead, it will set m_stopWaitEvent
3485 // which will let this function return. If the user wants to process any queued events, they will need to call
3487 STRESS_LOG0(LF_CORDB, LL_INFO1000, "CP::S: waiting for event.\n");
3490 ret = SafeWaitForSingleObject(this, m_stopWaitEvent, dwTimeout);
3492 STRESS_LOG1(LF_CORDB, LL_INFO1000, "CP::S: got event, %d.\n", ret);
3496 return CORDBG_E_PROCESS_TERMINATED;
3499 if (ret == WAIT_OBJECT_0)
3501 LOG((LF_CORDB, LL_INFO1000, "CP::S: process stopped.\n"));
3503 m_stopRequested = false;
3504 m_cordb->ProcessStateChanged();
3510 else if (ret == WAIT_TIMEOUT)
3512 hr = ErrWrapper(CORDBG_E_TIMEOUT);
3515 hr = HRESULT_FROM_GetLastError();
3517 // We came out of the wait, but we weren't signaled because a sync complete event came in. Re-check the process and
3518 // remove the stop requested flag.
3520 m_stopRequested = false;
3522 if (GetSynchronized())
3524 LOG((LF_CORDB, LL_INFO1000, "CP::S: process stopped.\n"));
3526 m_cordb->ProcessStateChanged();
3532 _ASSERTE(ThreadHoldsProcessLock());
3534 // Stop queuing any Win32 Debug events. We should be synchronized now.
3535 m_specialDeferment = false;
3542 STRESS_LOG2(LF_CORDB, LL_INFO1000, "CP::S: returning from Stop, hr=0x%08x, m_stopCount=%d.\n", hr, GetStopCount());
3549 //---------------------------------------------------------------------------------------
3550 // Clear all RS state on all CordbThread objects.
3553 // This clears all the thread-related state that the RS may have cached,
3554 // such as locals, frames, etc.
3555 // This would be called if the debugger is resuming execution.
3556 void CordbProcess::MarkAllThreadsDirty()
3558 INTERNAL_API_ENTRY(this);
3559 _ASSERTE(ThreadHoldsProcessLock());
3561 CordbThread * pThread;
3564 // We don't need to prepopulate here (to collect LS state) because we're just updating RS state.
3565 for (pThread = m_userThreads.FindFirst(&find);
3567 pThread = m_userThreads.FindNext(&find))
3569 _ASSERTE(pThread != NULL);
3570 pThread->MarkStackFramesDirty();
3576 HRESULT CordbProcess::Continue(BOOL fIsOutOfBand)
3578 PUBLIC_API_ENTRY(this);
3580 if (m_pShim == NULL) // This API is moved off to the shim
3582 // bias towards failing with CORDBG_E_NUETERED.
3583 FAIL_IF_NEUTERED(this);
3591 #ifdef FEATURE_INTEROP_DEBUGGING
3595 #endif // FEATURE_INTEROP_DEBUGGING
3599 hr = ContinueInternal(fIsOutOfBand);
3605 #ifdef FEATURE_INTEROP_DEBUGGING
3606 //---------------------------------------------------------------------------------------
3610 // Continue the Win32 event as an out-of-band event.
3613 // S_OK on successful continue. Else error.
3615 //---------------------------------------------------------------------------------------
3616 HRESULT CordbProcess::ContinueOOB()
3618 INTERNAL_API_ENTRY(this);
3619 FAIL_IF_NEUTERED(this);
3623 // If we're continuing from an out-of-band unmanaged event, then just go
3624 // ahead and get the Win32 event thread to continue the process. No other
3625 // work needs to be done (i.e., don't need to send a managed continue message
3626 // or dispatch any events) because any processing done due to the out-of-band
3627 // message can't alter the synchronized state of the process.
3630 _ASSERTE(m_outOfBandEventQueue != NULL);
3632 // Are we calling this from the unmanaged callback?
3633 if (m_dispatchingOOBEvent)
3635 STRESS_LOG0(LF_CORDB, LL_INFO1000, "CP::CI: continue while dispatching unmanaged out-of-band event.\n");
3636 // We don't know what thread we're on here.
3638 // Tell the Win32 event thread to continue when it returns from handling its unmanaged callback.
3639 m_dispatchingOOBEvent = false;
3645 STRESS_LOG0(LF_CORDB, LL_INFO1000, "CP::CI: continue outside of dispatching.\n");
3647 // If we're not dispatching this, then they shouldn't be on the win32 event thread.
3648 _ASSERTE(!this->IsWin32EventThread());
3652 // Send an event to the Win32 event thread to do the continue. This is an out-of-band continue.
3653 hr = this->m_pShim->GetWin32EventThread()->SendUnmanagedContinue(this, cOobUMContinue);
3660 #endif // FEATURE_INTEROP_DEBUGGING
3662 //---------------------------------------------------------------------------------------
3666 // Continue the Win32 event.
3669 // S_OK on success. Else error.
3671 //---------------------------------------------------------------------------------------
3672 HRESULT CordbProcess::ContinueInternal(BOOL fIsOutOfBand)
3674 INTERNAL_API_ENTRY(this);
3675 FAIL_IF_NEUTERED(this);
3677 // Continue has an ATT similar to ATT_REQUIRE_STOPPED_MAY_FAIL, but w/ some subtle differences.
3678 // - if we're stopped at a native DE, but not synchronized, we don't want to sync.
3679 // - We may get Debug events (especially native ones) at weird times, and thus we have to continue
3682 // External APIs should not have the process lock.
3683 _ASSERTE(!ThreadHoldsProcessLock());
3684 _ASSERTE(m_pShim != NULL);
3686 // OutOfBand should use ContinueOOB
3687 _ASSERTE(!fIsOutOfBand);
3689 // Since Continue is process-wide, just use a null appdomain pointer.
3690 VMPTR_AppDomain pAppDomainToken = VMPTR_AppDomain::NullPtr();
3694 if (m_unrecoverableError)
3696 return CORDBHRFromProcessState(this, NULL);
3700 // We can't call ContinueInternal for an inband event on the win32 event thread.
3701 // This is an issue in the CLR (or an API design decision, depending on your perspective).
3702 // Continue() may send an IPC event and we can't do that on the win32 event thread.
3704 CORDBFailIfOnWin32EventThread(this);
3706 STRESS_LOG1(LF_CORDB, LL_INFO1000, "CP::CI: continuing IB, this=0x%X\n", this);
3708 // Stop + Continue are executed under the Stop-Go lock. This makes them atomic.
3709 // We'll toggle the process-lock (b/c we communicate w/ the W32et, so that's not sufficient).
3710 RSLockHolder rsLockHolder(&m_StopGoLock);
3712 // Check for other failures (do these after we have the SG lock).
3715 return CORDBG_E_PROCESS_TERMINATED;
3719 return CORDBG_E_PROCESS_DETACHED;
3724 ASSERT_SINGLE_THREAD_ONLY(HoldsLock(&m_StopGoLock));
3725 _ASSERTE(fIsOutOfBand == FALSE);
3727 // If we've got multiple Stop calls, we need a Continue for each one. So, if the stop count > 1, just go ahead and
3728 // return without doing anything. Note: this is only for in-band or managed events. OOB events are still handled as
3730 _ASSERTE(GetStopCount() > 0);
3732 if (GetStopCount() == 0)
3735 _ASSERTE(!"Superflous Continue. ICorDebugProcess.Continue() called too many times");
3736 return CORDBG_E_SUPERFLOUS_CONTINUE;
3741 // We give managed events priority over unmanaged events. That way, the entire queued managed state can drain before
3742 // we let any other unmanaged events through.
3744 // Every stop or event must be matched by a corresponding Continue. m_stopCount counts outstanding stopping events
3745 // along with calls to Stop. If the count is high at this point, we simply return. This ensures that even if someone
3746 // calls Stop just as they're receiving an event that they can call Continue for that Stop and for that event
3747 // without problems.
3748 if (GetStopCount() > 0)
3750 STRESS_LOG1(LF_CORDB, LL_INFO1000, "CP::CI: m_stopCount=%d, Continue just returning S_OK...\n", GetStopCount());
3756 // We're no longer stopped, so reset the m_stopWaitEvent.
3757 ResetEvent(m_stopWaitEvent);
3759 // If we're continuing from an uninitialized stop, then we don't need to do much at all. No event need be sent to
3760 // the Left Side (duh, it isn't even there yet.) We just need to get the RC Event Thread to start listening to the
3761 // process again, and resume any unmanaged threads if necessary.
3762 if (m_uninitializedStop)
3764 STRESS_LOG0(LF_CORDB, LL_INFO1000, "CP::CI: continuing from uninitialized stop.\n");
3766 // No longer synchronized (it was a partial sync in the first place.)
3767 SetSynchronized(false);
3768 MarkAllThreadsDirty();
3770 // No longer in an uninitialized stop.
3771 m_uninitializedStop = false;
3773 // Notify the RC Event Thread.
3774 m_cordb->ProcessStateChanged();
3778 #ifdef FEATURE_INTEROP_DEBUGGING
3779 // We may or may not have a native debug event queued here.
3780 // If Cordbg called Stop() from a native debug event (to get the process Synchronized), then
3781 // we'll have a native debug event, and we need to continue it.
3782 // If Cordbg called Stop() to do an AsyncBreak, then there's no native-debug event.
3784 // If we're Win32 attached, resume all the unmanaged threads.
3785 if (IsInteropDebugging())
3787 if(m_lastDispatchedIBEvent != NULL)
3789 m_lastDispatchedIBEvent->SetState(CUES_UserContinued);
3792 // Send to the Win32 event thread to do the unmanaged continue for us.
3793 // If we're at a debug event, this will continue it.
3794 // Else it will degenerate into ResumeUnmanagedThreads();
3795 this->m_pShim->GetWin32EventThread()->SendUnmanagedContinue(this, cRealUMContinue);
3797 #endif // FEATURE_INTEROP_DEBUGGING
3803 // If there are more managed events, get them dispatched now.
3804 if (!m_pShim->GetManagedEventQueue()->IsEmpty() && GetSynchronized())
3806 STRESS_LOG0(LF_CORDB, LL_INFO1000, "CP::CI: managed event queued.\n");
3808 // Mark that we're not synchronized anymore.
3809 SetSynchronized(false);
3811 // If the callback queue is not empty, then the LS is not actually continuing, and so our cached
3812 // state is still valid.
3814 // If we're in the middle of dispatching a managed event, then simply return. This indicates to HandleRCEvent
3815 // that the user called Continue and HandleRCEvent will dispatch the next queued event. But if Continue was
3816 // called outside the managed callback, all we have to do is tell the RC event thread that something about the
3817 // process has changed and it will dispatch the next managed event.
3818 if (!AreDispatchingEvent())
3820 STRESS_LOG0(LF_CORDB, LL_INFO1000, "CP::CI: continuing while not dispatching managed event.\n");
3822 m_cordb->ProcessStateChanged();
3829 // Neuter if we have an outstanding object.
3830 // Only do this if we're really continuining the debuggee. So don't do this if our stop-count is high b/c we
3831 // shouldn't neuter until we're done w/ the current event. And don't do this until we drain the current callback queue.
3832 // Note that we can't hold the process lock while we do this b/c Neutering may send IPC events.
3833 // However, we're still under the StopGo lock b/c that may help us serialize things.
3835 // Sweep neuter list. This will catch anything that's marked as 'safe to neuter'. This includes
3836 // all objects added to the 'neuter-on-Continue'.
3837 // Only do this if we're synced- we don't want to do this if we're continuing from a Native Debug event.
3838 if (GetSynchronized())
3840 // Need process-lock to operate on hashtable, but can't yet Neuter under process-lock,
3841 // so we have to copy the contents to an auxilary list which we can then traverse outside the lock.
3842 RSPtrArray<CordbAppDomain> listAppDomains;
3843 HRESULT hrCopy = S_OK;
3844 EX_TRY // @dbgtodo cleanup: push this up
3846 m_appDomains.CopyToArray(&listAppDomains);
3848 EX_CATCH_HRESULT(hrCopy);
3849 SetUnrecoverableIfFailed(GetProcess(), hrCopy);
3851 m_ContinueNeuterList.NeuterAndClear(this);
3853 // @dbgtodo left-side resources: eventually (once
3854 // NeuterLeftSideResources is process-lock safe), do this all under the
3855 // lock. Can't hold process lock b/c neutering left-side resources
3859 // This may send IPC events.
3860 // This will make normal neutering a nop.
3861 // This will toggle the process lock.
3862 m_LeftSideResourceCleanupList.SweepNeuterLeftSideResources(this);
3865 // Many objects (especially CordbValue, FuncEval) don't have clear lifetime semantics and
3866 // so they must be put into an exit-neuter list (Process/AppDomain) for worst-case scenarios.
3867 // These objects are likely released early, and so we sweep them aggressively on each Continue (kind of like a mini-GC).
3869 // One drawback is that there may be a lot of useless sweeping if the debugger creates a lot of
3870 // objects that it holds onto. Consider instead of sweeping, have the object explicitly post itself
3871 // to a list that's guaranteed to be cleared. This would let us avoid sweeping not-yet-ready objects.
3872 // This will toggle the process lock
3873 m_ExitNeuterList.SweepAllNeuterAtWillObjects(this);
3876 for(unsigned int idx = 0; idx < listAppDomains.Length(); idx++)
3878 CordbAppDomain * pAppDomain = listAppDomains[idx];
3880 // CordbHandleValue is in the appdomain exit list, and that needs
3881 // to send an IPC event to cleanup and release the handle from
3882 // the GCs handle table.
3883 // This will toggle the process lock.
3884 pAppDomain->GetSweepableExitNeuterList()->SweepNeuterLeftSideResources(this);
3886 listAppDomains.Clear();
3892 // At this point, if the managed event queue is empty, m_synchronized may still be true if we had previously
3895 #ifdef FEATURE_INTEROP_DEBUGGING
3896 // Next, check for unmanaged events that may be queued. If there are some queued, then we need to get the Win32
3897 // event thread to go ahead and dispatch the next one. If there aren't any queued, then we can just fall through and
3898 // send the continue message to the left side. This works even if we have an outstanding ownership request, because
3899 // until that answer is received, its just like the event hasn't happened yet.
3901 // If we're terminated, then we've already continued from the last win32 event and so don't continue.
3902 // @todo - or we could ensure the PS_SOME_THREADS_SUSPENDED | PS_HIJACKS_IN_PLACE are removed.
3903 // Either way, we're just protecting against exit-process at strange times.
3904 bool fDoWin32Continue = !m_terminated && ((m_state & (PS_WIN32_STOPPED | PS_SOME_THREADS_SUSPENDED | PS_HIJACKS_IN_PLACE)) != 0);
3906 // We need to store this before marking the event user continued below
3907 BOOL fHasUserUncontinuedEvents = HasUserUncontinuedNativeEvents();
3909 if(m_lastDispatchedIBEvent != NULL)
3911 m_lastDispatchedIBEvent->SetState(CUES_UserContinued);
3914 if (fHasUserUncontinuedEvents)
3916 // ExitProcess is the last debug event we'll get. The Process Handle is not signaled until
3917 // after we continue from ExitProcess. m_terminated is only set once we know the process is signaled.
3918 // (This isn't 100% true for the detach case, but since you can't do interop detach, we don't care)
3919 //_ASSERTE(!m_terminated);
3921 STRESS_LOG1(LF_CORDB, LL_INFO1000, "CP::CI: there are queued uncontinued events. m_dispatchingUnmanagedEvent = %d\n", m_dispatchingUnmanagedEvent);
3923 // Are we being called while in the unmanaged event callback?
3924 if (m_dispatchingUnmanagedEvent)
3926 LOG((LF_CORDB, LL_INFO1000, "CP::CI: continue while dispatching.\n"));
3927 // The Win32ET could have made a cross-thread call to Continue while dispatching,
3928 // so we don't know if this is the win32 ET.
3930 // Tell the Win32 thread to continue when it returns from handling its unmanaged callback.
3931 m_dispatchingUnmanagedEvent = false;
3933 // If there are no more unmanaged events, then we fall through and continue the process for real. Otherwise,
3934 // we can simply return.
3935 if (HasUndispatchedNativeEvents())
3937 STRESS_LOG0(LF_CORDB, LL_INFO1000, "CP::CI: more unmanaged events need dispatching.\n");
3939 // Note: if we tried to access the Left Side while stopped but couldn't, then m_oddSync will be true. We
3940 // need to reset it to false since we're continuing now.
3948 // Also, if there are no more unmanaged events, then when DispatchUnmanagedInBandEvent sees that
3949 // m_dispatchingUnmanagedEvent is false, it will continue the process. So we set doWin32Continue to
3950 // false here so that we don't try to double continue the process below.
3951 STRESS_LOG0(LF_CORDB, LL_INFO1000, "CP::CI: no more unmanaged events to dispatch.\n");
3953 fDoWin32Continue = false;
3958 // after the DebugEvent callback returned the continue still had no been issued. Then later
3959 // on another thread the user called back to continue the event, which gets us to right here
3960 LOG((LF_CORDB, LL_INFO1000, "CP::CI: continue outside of dispatching.\n"));
3962 // This should be the common place to Dispatch an IB event that was hijacked for sync.
3964 // If we're not dispatching, this better not be the win32 event thread.
3965 _ASSERTE(!IsWin32EventThread());
3967 // If the event at the head of the queue is really the last event, or if the event at the head of the queue
3968 // hasn't been dispatched yet, then we simply fall through and continue the process for real. However, if
3969 // its not the last event, we send to the Win32 event thread and get it to continue, then we return.
3970 if (HasUndispatchedNativeEvents())
3972 STRESS_LOG0(LF_CORDB, LL_INFO1000, "CP::CI: more unmanaged events need dispatching.\n");
3974 // Note: if we tried to access the Left Side while stopped but couldn't, then m_oddSync will be true. We
3975 // need to reset it to false since we're continuing now.
3980 hr = this->m_pShim->GetWin32EventThread()->SendUnmanagedContinue(this, cRealUMContinue);
3986 #endif // FEATURE_INTEROP_DEBUGGING
3988 // Both the managed and unmanaged event queues are now empty. Go
3989 // ahead and continue the process for real.
3990 LOG((LF_CORDB, LL_INFO1000, "CP::CI: headed for true continue.\n"));
3992 // We need to check these while under the lock, but action must be
3993 // taked outside of the lock.
3994 bool fIsExiting = m_exiting;
3995 bool fWasSynchronized = GetSynchronized();
3997 // Mark that we're no longer synchronized.
3998 if (fWasSynchronized)
4000 LOG((LF_CORDB, LL_INFO1000, "CP::CI: process was synchronized.\n"));
4002 SetSynchronized(false);
4003 SetSyncCompleteRecv(false);
4005 // we're no longer in a callback, so set flags to indicate that we've finished.
4006 GetShim()->NotifyOnContinue();
4008 // Flush will update state, including continue counter and marking
4010 this->FlushProcessRunning();
4013 // Tell the RC event thread that something about this process has changed.
4014 m_cordb->ProcessStateChanged();
4017 m_continueCounter++;
4019 // If m_oddSync is set, then out last synchronization was due to us syncing the process because we were Win32
4020 // stopped. Therefore, while we do need to do most of the work to continue the process below, we don't actually have
4021 // to send the managed continue event. Setting wasSynchronized to false here helps us do that.
4024 fWasSynchronized = false;
4028 #ifdef FEATURE_INTEROP_DEBUGGING
4029 // We must ensure that all managed threads are suspended here. We're about to let all managed threads run free via
4030 // the managed continue message to the Left Side. If we don't suspend the managed threads, then they may start
4031 // slipping forward even if we receive an in-band unmanaged event. We have to hijack in-band unmanaged events while
4032 // getting the managed continue message over to the Left Side to keep the process running free. Otherwise, the
4033 // SendIPCEvent will hang below. But in doing so, we could let managed threads slip to far. So we ensure they're all
4036 // Note: we only do this suspension if the helper thread hasn't died yet. If the helper thread has died, then we
4037 // know that we're loosing the Runtime. No more managed code is going to run, so we don't bother trying to prevent
4038 // managed threads from slipping via the call below.
4040 // Note: we just remember here, under the lock, so we can unlock then wait for the syncing thread to free the
4041 // debugger lock. Otherwise, we may block here and prevent someone from continuing from an OOB event, which also
4042 // prevents the syncing thread from releasing the debugger lock like we want it to.
4043 bool fNeedSuspend = fWasSynchronized && fDoWin32Continue && !m_helperThreadDead;
4045 // If we receive a new in-band event once we unlock, we need to know to hijack it and keep going while we're still
4046 // trying to send the managed continue event to the process.
4047 if (fWasSynchronized && fDoWin32Continue && !fIsExiting)
4049 m_specialDeferment = true;
4054 // @todo - what does this actually accomplish? We already suspended everything when we first synced.
4056 // Any thread that may hold a lock blocking the helper is
4057 // inside of a can't stop region, and thus we won't suspend it.
4058 SuspendUnmanagedThreads();
4060 #endif // FEATURE_INTEROP_DEBUGGING
4064 // Although we've released the Process-lock, we still have the Stop-Go lock.
4065 _ASSERTE(m_StopGoLock.HasLock());
4067 // If we're processing an ExitProcess managed event, then we don't want to really continue the process, so just fall
4068 // thru. Note: we did let the unmanaged continue go through above for this case.
4071 LOG((LF_CORDB, LL_INFO1000, "CP::CI: continuing from exit case.\n"));
4073 else if (fWasSynchronized)
4075 LOG((LF_CORDB, LL_INFO1000, "CP::CI: Sending continue to AppD:0x%x.\n", VmPtrToCookie(pAppDomainToken)));
4076 #ifdef FEATURE_INTEROP_DEBUGGING
4077 STRESS_LOG2(LF_CORDB, LL_INFO1000, "Continue flags:special=%d, dowin32=%d\n", m_specialDeferment, fDoWin32Continue);
4079 // Send to the RC to continue the process.
4080 DebuggerIPCEvent * pEvent = (DebuggerIPCEvent *) _alloca(CorDBIPC_BUFFER_SIZE);
4082 InitIPCEvent(pEvent, DB_IPCE_CONTINUE, false, pAppDomainToken);
4084 hr = m_cordb->SendIPCEvent(this, pEvent, CorDBIPC_BUFFER_SIZE);
4086 // It is possible that we continue and then the process immediately exits before the helper
4087 // thread is finished continuing and can report success back to us. That's arguably a success
4088 // case sinceu the process did indeed continue, but since we didn't get the acknowledgement,
4089 // we can't be sure it's success. So we call it S_FALSE instead of S_OK.
4090 // @todo - how do we handle other failure here?
4091 if (hr == CORDBG_E_PROCESS_TERMINATED)
4095 _ASSERTE(SUCCEEDED(pEvent->hr));
4097 LOG((LF_CORDB, LL_INFO1000, "CP::CI: Continue sent to AppD:0x%x.\n", VmPtrToCookie(pAppDomainToken)));
4100 #ifdef FEATURE_INTEROP_DEBUGGING
4101 // If we're win32 attached to the Left side, then we need to win32 continue the process too (unless, of course, it's
4102 // already been done above.)
4104 // Note: we do this here because we want to get the Left Side to receive and ack our continue message above if we
4105 // were sync'd. If we were sync'd, then by definition the process (and the helper thread) is running anyway, so all
4106 // this continue is going to do is to let the threads that have been suspended go.
4107 if (fDoWin32Continue)
4111 // A little pause here extends the special deferment region and thus causes native-debug
4112 // events to get hijacked. This test some wildly different corner case paths.
4113 // See VSWhidbey bugs 131905, 168971
4114 static DWORD dwRace = -1;
4116 dwRace = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgRace);
4118 if ((dwRace & 1) == 1)
4125 STRESS_LOG0(LF_CORDB, LL_INFO1000, "CP::CI: sending unmanaged continue.\n");
4127 // Send to the Win32 event thread to do the unmanaged continue for us.
4128 hr = this->m_pShim->GetWin32EventThread()->SendUnmanagedContinue(this, cRealUMContinue);
4130 #endif // FEATURE_INTEROP_DEBUGGING
4132 STRESS_LOG0(LF_CORDB, LL_INFO1000, "CP::CI: continue done, returning.\n");
4137 HRESULT CordbProcess::HasQueuedCallbacks(ICorDebugThread *pThread,
4140 PUBLIC_REENTRANT_API_ENTRY(this);
4141 FAIL_IF_NEUTERED(this);
4142 VALIDATE_POINTER_TO_OBJECT_OR_NULL(pThread,ICorDebugThread *);
4143 VALIDATE_POINTER_TO_OBJECT(pbQueued,BOOL *);
4145 // Shim owns the event queue
4146 if (m_pShim != NULL)
4148 PUBLIC_CALLBACK_IN_THIS_SCOPE0_NO_LOCK(this); // Calling to shim, leaving RS.
4149 *pbQueued = m_pShim->GetManagedEventQueue()->HasQueuedCallbacks(pThread);
4152 return E_NOTIMPL; // Not implemented in V3.
4156 // A small helper function to convert a CordbBreakpoint to an ICorDebugBreakpoint based on its type.
4158 static ICorDebugBreakpoint *CordbBreakpointToInterface(CordbBreakpoint * pBreakpoint)
4160 _ASSERTE(pBreakpoint != NULL);
4163 // I really dislike this. We've got three subclasses of CordbBreakpoint, but we store them all into the same hash
4164 // (m_breakpoints), so when we get one out of the hash, we don't really know what type it is. But we need to know
4165 // what type it is because we need to cast it to the proper interface before passing it out. I.e., when we create a
4166 // function breakpoint, we return the breakpoint casted to an ICorDebugFunctionBreakpoint. But if we grab that same
4167 // breakpoint out of the hash as a CordbBreakpoint and pass it out as an ICorDebugBreakpoint, then that's a
4168 // different pointer, and its wrong. So I've added the type to the breakpoint so we can cast properly here. I'd love
4169 // to do this a different way, though...
4171 // -- Mon Dec 14 21:06:46 1998
4173 switch(pBreakpoint->GetBPType())
4176 return static_cast<ICorDebugFunctionBreakpoint *>(static_cast<CordbFunctionBreakpoint *> (pBreakpoint));
4180 return static_cast<ICorDebugModuleBreakpoint*>(static_cast<CordbModuleBreakpoint *> (pBreakpoint));
4184 return static_cast<ICorDebugValueBreakpoint *>(static_cast<CordbValueBreakpoint *> (pBreakpoint));
4188 _ASSERTE(!"Invalid breakpoint type!");
4195 // Callback data for code:CordbProcess::GetAssembliesInLoadOrder
4196 class ShimAssemblyCallbackData
4199 // Ctor to intialize callback data
4202 // pAppDomain - appdomain that the assemblies are in.
4203 // pAssemblies - preallocated array of smart pointers to hold assemblies
4204 // countAssemblies - size of pAssemblies in elements.
4205 ShimAssemblyCallbackData(
4206 CordbAppDomain * pAppDomain,
4207 RSExtSmartPtr<ICorDebugAssembly>* pAssemblies,
4208 ULONG countAssemblies)
4210 _ASSERTE(pAppDomain != NULL);
4211 _ASSERTE(pAssemblies != NULL);
4213 m_pProcess = pAppDomain->GetProcess();
4214 m_pAppDomain = pAppDomain;
4215 m_pAssemblies = pAssemblies;
4216 m_countElements = countAssemblies;
4219 // Just to be safe, clear them all out
4220 for(ULONG i = 0; i < countAssemblies; i++)
4222 pAssemblies[i].Clear();
4229 // This can assert end-of-enumeration invariants.
4230 ~ShimAssemblyCallbackData()
4232 // Ensure that we went through all assemblies.
4233 _ASSERTE(m_index == m_countElements);
4236 // Callback invoked from DAC enumeration.
4239 // vmDomainAssembly - VMPTR for assembly
4240 // pData - a 'this' pointer
4242 static void Callback(VMPTR_DomainAssembly vmDomainAssembly, void * pData)
4244 ShimAssemblyCallbackData * pThis = static_cast<ShimAssemblyCallbackData *> (pData);
4245 INTERNAL_DAC_CALLBACK(pThis->m_pProcess);
4247 CordbAssembly * pAssembly = pThis->m_pAppDomain->LookupOrCreateAssembly(vmDomainAssembly);
4249 pThis->SetAndMoveNext(pAssembly);
4252 // Set the current index in the table and increment the cursor.
4255 // pAssembly - assembly from DAC enumerator
4256 void SetAndMoveNext(CordbAssembly * pAssembly)
4258 _ASSERTE(pAssembly != NULL);
4260 if (m_index >= m_countElements)
4262 // Enumerating the assemblies in the target should be fixed since
4263 // the target is not running.
4264 // We should never get here unless the target is unstable.
4265 // The caller (the shim) pre-allocated the table of assemblies.
4266 m_pProcess->TargetConsistencyCheck(!"Target changed assembly count");
4270 m_pAssemblies[m_index].Assign(pAssembly);
4275 CordbProcess * m_pProcess;
4276 CordbAppDomain * m_pAppDomain;
4277 RSExtSmartPtr<ICorDebugAssembly>* m_pAssemblies;
4278 ULONG m_countElements;
4282 //---------------------------------------------------------------------------------------
4283 // Shim Helper to enumerate the assemblies in the load-order
4286 // pAppdomain - non-null appdmomain to enumerate assemblies.
4287 // pAssemblies - caller pre-allocated array to hold assemblies
4288 // countAssemblies - size of the array.
4291 // Caller preallocated array (likely from ICorDebugAssemblyEnum::GetCount),
4292 // and now this function fills in the assemblies in the order they were
4295 // The target should be stable, such that the number of assemblies in the
4296 // target is stable, and therefore countAssemblies as determined by the
4297 // shim via ICorDebugAssemblyEnum::GetCount should match the number of
4298 // assemblies enumerated here.
4300 // Called by code:ShimProcess::QueueFakeAttachEvents.
4301 // This provides the assemblies in load-order. In contrast,
4302 // ICorDebugAppDomain::EnumerateAssemblies is a random order. The shim needs
4303 // load-order to match Whidbey semantics for dispatching fake load-assembly
4304 // callbacks on attach. The debugger then uses the order
4305 // in its module display window.
4307 void CordbProcess::GetAssembliesInLoadOrder(
4308 ICorDebugAppDomain * pAppDomain,
4309 RSExtSmartPtr<ICorDebugAssembly>* pAssemblies,
4310 ULONG countAssemblies)
4312 PUBLIC_API_ENTRY_FOR_SHIM(this);
4313 RSLockHolder lockHolder(GetProcessLock());
4315 _ASSERTE(GetShim() != NULL);
4317 CordbAppDomain * pAppDomainInternal = static_cast<CordbAppDomain *> (pAppDomain);
4319 ShimAssemblyCallbackData data(pAppDomainInternal, pAssemblies, countAssemblies);
4321 // Enumerate through and fill out pAssemblies table.
4322 GetDAC()->EnumerateAssembliesInAppDomain(
4323 pAppDomainInternal->GetADToken(),
4324 ShimAssemblyCallbackData::Callback,
4325 &data); // user data
4327 // pAssemblies array has now been updated.
4330 // Callback data for code:CordbProcess::GetModulesInLoadOrder
4331 class ShimModuleCallbackData
4334 // Ctor to intialize callback data
4337 // pAssembly - assembly that the Modules are in.
4338 // pModules - preallocated array of smart pointers to hold Modules
4339 // countModules - size of pModules in elements.
4340 ShimModuleCallbackData(
4341 CordbAssembly * pAssembly,
4342 RSExtSmartPtr<ICorDebugModule>* pModules,
4345 _ASSERTE(pAssembly != NULL);
4346 _ASSERTE(pModules != NULL);
4348 m_pProcess = pAssembly->GetAppDomain()->GetProcess();
4349 m_pAssembly = pAssembly;
4350 m_pModules = pModules;
4351 m_countElements = countModules;
4354 // Just to be safe, clear them all out
4355 for(ULONG i = 0; i < countModules; i++)
4357 pModules[i].Clear();
4364 // This can assert end-of-enumeration invariants.
4365 ~ShimModuleCallbackData()
4367 // Ensure that we went through all Modules.
4368 _ASSERTE(m_index == m_countElements);
4371 // Callback invoked from DAC enumeration.
4374 // vmDomainFile - VMPTR for Module
4375 // pData - a 'this' pointer
4377 static void Callback(VMPTR_DomainFile vmDomainFile, void * pData)
4379 ShimModuleCallbackData * pThis = static_cast<ShimModuleCallbackData *> (pData);
4380 INTERNAL_DAC_CALLBACK(pThis->m_pProcess);
4382 CordbModule * pModule = pThis->m_pAssembly->GetAppDomain()->LookupOrCreateModule(vmDomainFile);
4384 pThis->SetAndMoveNext(pModule);
4387 // Set the current index in the table and increment the cursor.
4390 // pModule - Module from DAC enumerator
4391 void SetAndMoveNext(CordbModule * pModule)
4393 _ASSERTE(pModule != NULL);
4395 if (m_index >= m_countElements)
4397 // Enumerating the Modules in the target should be fixed since
4398 // the target is not running.
4399 // We should never get here unless the target is unstable.
4400 // The caller (the shim) pre-allocated the table of Modules.
4401 m_pProcess->TargetConsistencyCheck(!"Target changed Module count");
4405 m_pModules[m_index].Assign(pModule);
4410 CordbProcess * m_pProcess;
4411 CordbAssembly * m_pAssembly;
4412 RSExtSmartPtr<ICorDebugModule>* m_pModules;
4413 ULONG m_countElements;
4417 //---------------------------------------------------------------------------------------
4418 // Shim Helper to enumerate the Modules in the load-order
4421 // pAppdomain - non-null appdmomain to enumerate Modules.
4422 // pModules - caller pre-allocated array to hold Modules
4423 // countModules - size of the array.
4426 // Caller preallocated array (likely from ICorDebugModuleEnum::GetCount),
4427 // and now this function fills in the Modules in the order they were
4430 // The target should be stable, such that the number of Modules in the
4431 // target is stable, and therefore countModules as determined by the
4432 // shim via ICorDebugModuleEnum::GetCount should match the number of
4433 // Modules enumerated here.
4435 // Called by code:ShimProcess::QueueFakeAssemblyAndModuleEvent.
4436 // This provides the Modules in load-order. In contrast,
4437 // ICorDebugAssembly::EnumerateModules is a random order. The shim needs
4438 // load-order to match Whidbey semantics for dispatching fake load-Module
4439 // callbacks on attach. The most important thing is that the manifest module
4440 // gets a LodModule callback before any secondary modules. For dynamic
4441 // modules, this is necessary for operations on the secondary module
4442 // that rely on manifest metadata (eg. GetSimpleName).
4444 // @dbgtodo : This is almost identical to GetAssembliesInLoadOrder, and
4445 // (together wih the CallbackData classes) seems a HUGE amount of code and
4446 // complexity for such a simple thing. We also have extra code to order
4447 // AppDomains and Threads. We should try and rip all of this extra complexity
4448 // out, and replace it with better data structures for storing these items.
4449 // Eg., if we used std::map, we could have efficient lookups and ordered
4450 // enumerations. However, we do need to be careful about exposing new invariants
4451 // through ICorDebug that customers may depend on, which could place a long-term
4452 // compatibility burden on us. We could have a simple generic data structure
4453 // (eg. built on std::hash_map and std::list) which provided efficient look-up
4454 // and both in-order and random enumeration.
4456 void CordbProcess::GetModulesInLoadOrder(
4457 ICorDebugAssembly * pAssembly,
4458 RSExtSmartPtr<ICorDebugModule>* pModules,
4461 PUBLIC_API_ENTRY_FOR_SHIM(this);
4462 RSLockHolder lockHolder(GetProcessLock());
4464 _ASSERTE(GetShim() != NULL);
4466 CordbAssembly * pAssemblyInternal = static_cast<CordbAssembly *> (pAssembly);
4468 ShimModuleCallbackData data(pAssemblyInternal, pModules, countModules);
4470 // Enumerate through and fill out pModules table.
4471 GetDAC()->EnumerateModulesInAssembly(
4472 pAssemblyInternal->GetDomainAssemblyPtr(),
4473 ShimModuleCallbackData::Callback,
4474 &data); // user data
4476 // pModules array has now been updated.
4480 //---------------------------------------------------------------------------------------
4481 // Callback to count the number of enumerations in a process.
4484 // id - the connection id.
4485 // pName - name of the connection
4486 // pUserData - an EnumerateConnectionsData
4489 // Helper function for code:CordbProcess::QueueFakeConnectionEvents
4492 void CordbProcess::CountConnectionsCallback(DWORD id, LPCWSTR pName, void * pUserData)
4496 //---------------------------------------------------------------------------------------
4497 // Callback to enumerate all the connections in a process.
4500 // id - the connection id.
4501 // pName - name of the connection
4502 // pUserData - an EnumerateConnectionsData
4505 // Helper function for code:CordbProcess::QueueFakeConnectionEvents
4508 void CordbProcess::EnumerateConnectionsCallback(DWORD id, LPCWSTR pName, void * pUserData)
4512 //---------------------------------------------------------------------------------------
4513 // Callback from Shim to queue fake Connection events on attach.
4516 // See code:ShimProcess::QueueFakeAttachEvents
4517 void CordbProcess::QueueFakeConnectionEvents()
4519 PUBLIC_API_ENTRY_FOR_SHIM(this);
4524 // DispatchRCEvent -- dispatches a previously queued IPC event received
4525 // from the runtime controller. This represents the last amount of processing
4526 // the DI gets to do on an event before giving it to the user.
4528 void CordbProcess::DispatchRCEvent()
4530 INTERNAL_API_ENTRY(this);
4534 // This is happening on the RCET thread, so there's no place to propogate an error back up.
4539 _ASSERTE(m_pShim != NULL); // V2 case
4542 // Note: the current thread should have the process locked when it
4543 // enters this method.
4545 _ASSERTE(ThreadHoldsProcessLock());
4547 // Create/Launch paths already ensured that we had a callback.
4548 _ASSERTE(m_cordb != NULL);
4549 _ASSERTE(m_cordb->m_managedCallback != NULL);
4550 _ASSERTE(m_cordb->m_managedCallback2 != NULL);
4551 _ASSERTE(m_cordb->m_managedCallback3 != NULL);
4554 // Bump up the stop count. Either we'll dispatch a managed event,
4555 // or the logic below will decide not to dispatch one and call
4556 // Continue itself. Either way, the stop count needs to go up by
4558 _ASSERTE(this->GetSyncCompleteRecv());
4559 SetSynchronized(true);
4562 // As soon as we call Unlock(), we might get neutered and lose our reference to
4563 // the shim. Grab it now for use later.
4564 RSExtSmartPtr<ShimProcess> pShim(m_pShim);
4568 _ASSERTE(!ThreadHoldsProcessLock());
4571 // We want to stay synced until after the callbacks return. This is b/c we're on the RCET,
4572 // and we may deadlock if we send IPC events on the RCET if we're not synced (see SendIPCEvent for details).
4573 // So here, stopcount=1. The StopContinueHolder bumps it up to 2.
4574 // - If Cordbg calls continue in the callback, that bumps it back down to 1, but doesn't actually continue.
4575 // The holder dtor then bumps it down to 0, doing the real continue.
4576 // - If Cordbg doesn't call continue in the callback, then stopcount stays at 2, holder dtor drops it down to 1,
4577 // and then the holder was just a nop.
4578 // This gives us delayed continues w/ no extra state flags.
4581 // The debugger may call Detach() immediately after it returns from the callback, but before this thread returns
4582 // from this function. Thus after we execute the callbacks, it's possible the CordbProcess object has been neutered.
4584 // Since we're already sycned, the Stop from the holder here is practically a nop that just bumps up a count.
4585 // Create an extra scope for the StopContinueHolder.
4587 StopContinueHolder h;
4588 HRESULT hr = h.Init(this);
4591 CORDBSetUnrecoverableError(this, hr, 0);
4594 HRESULT hrCallback = S_OK;
4595 // It's possible a ICorDebugProcess::Detach() may have occurred by now.
4597 // @dbgtodo shim: eventually the entire RCET should be considered outside the RS.
4598 PUBLIC_CALLBACK_IN_THIS_SCOPE0_NO_LOCK(this);
4601 // Snag the first event off the queue.
4602 // Holder will call Delete, which will invoke virtual Dtor that will release ICD objects.
4603 // Since these are external refs, we want to do it while "outside" the RS.
4604 NewHolder<ManagedEvent> pEvent(pShim->DequeueManagedEvent());
4606 // Normally pEvent shouldn't be NULL, since this method is called when the queue is not empty.
4607 // But due to a race between CordbProcess::Terminate(), CordbWin32EventThread::ExitProcess() and this method
4608 // it is totally possible that the queue has already been cleaned up and we can't expect that event is always available.
4611 // Since we need to access a member (m_cordb), protect this block with a
4612 // lock and a check for Neutering (in case process detach has just
4613 // occurred). We'll release the lock around the dispatch later on.
4614 RSLockHolder lockHolder(GetProcessLock());
4618 // On a debug build, keep track of the last IPC event we dispatched.
4619 m_pDBGLastIPCEventType = pEvent->GetDebugCookie();
4622 ManagedEvent::DispatchArgs args(m_cordb->m_managedCallback, m_cordb->m_managedCallback2, m_cordb->m_managedCallback3);
4625 // Release lock around the dispatch of the event
4626 RSInverseLockHolder inverseLockHolder(GetProcessLock());
4630 // This dispatches almost directly into the user's callbacks.
4631 // It does not update any RS state.
4632 hrCallback = pEvent->Dispatch(args);
4634 EX_CATCH_HRESULT(hrCallback);
4639 } // we're now back inside the RS
4641 if (hrCallback == E_NOTIMPL)
4643 ContinueInternal(FALSE);
4647 } // forces Continue to be called
4654 //---------------------------------------------------------------------------------------
4655 // Debug-only callback to ensure that an appdomain is not available after the ExitAppDomain event.
4658 // vmAppDomain - appdomain from enumeration
4659 // pUserData - pointer to a DbgAssertAppDomainDeletedData which contains the VMAppDomain that was just deleted.
4661 // see code:CordbProcess::DbgAssertAppDomainDeleted for details.
4662 void CordbProcess::DbgAssertAppDomainDeletedCallback(VMPTR_AppDomain vmAppDomain, void * pUserData)
4664 DbgAssertAppDomainDeletedData * pCallbackData = reinterpret_cast<DbgAssertAppDomainDeletedData *>(pUserData);
4665 INTERNAL_DAC_CALLBACK(pCallbackData->m_pThis);
4667 VMPTR_AppDomain vmAppDomainDeleted = pCallbackData->m_vmAppDomainDeleted;
4668 CONSISTENCY_CHECK_MSGF((vmAppDomain != vmAppDomainDeleted),
4669 ("An ExitAppDomain event was sent for appdomain, but it still shows up in the enumeration.\n vmAppDomain=%p\n",
4670 VmPtrToCookie(vmAppDomainDeleted)));
4673 //---------------------------------------------------------------------------------------
4674 // Debug-only helper to Assert that VMPTR is actually removed.
4677 // vmAppDomainDeleted - vmptr of appdomain that we just got exit event for.
4678 // This should not be discoverable from the RS.
4681 // See code:IDacDbiInterface#Enumeration for rules that we're asserting.
4682 // Once the exit appdomain event is dispatched, the appdomain should not be discoverable by the RS.
4683 // Else the RS may use the AppDomain* after it's deleted.
4684 // This asserts that the AppDomain* is not discoverable.
4686 // Since this is a debug-only function, it should have no side-effects.
4687 void CordbProcess::DbgAssertAppDomainDeleted(VMPTR_AppDomain vmAppDomainDeleted)
4689 DbgAssertAppDomainDeletedData callbackData;
4690 callbackData.m_pThis = this;
4691 callbackData.m_vmAppDomainDeleted = vmAppDomainDeleted;
4693 GetDAC()->EnumerateAppDomains(
4694 CordbProcess::DbgAssertAppDomainDeletedCallback,
4700 //---------------------------------------------------------------------------------------
4701 // Update state and potentially Dispatch a single event.
4704 // pEvent - non-null pointer to debug event.
4705 // pCallback1 - callback object to dispatch on (for V1 callbacks)
4706 // pCallback2 - 2nd callback object to dispatch on (for new V2 callbacks)
4707 // pCallback3 - 3rd callback object to dispatch on (for new V4 callbacks)
4711 // Nothing. Throws on error.
4714 // Generally, this will dispatch exactly 1 callback. It may dispatch 0 callbacks if there is an error
4715 // or in other corner cases (documented within the dispatch code below).
4716 // Errors could occur because:
4717 // - the event is corrupted (exceptional case)
4718 // - the RS is corrupted / OOM (exceptional case)
4719 // Exception errors here will propogate back to the Filter() call, and there's not really anything
4720 // a debugger can do about an error here (perhaps report it to the user).
4721 // Errors must leave IcorDebug in a consistent state.
4723 // This is dispatched directly on the Win32Event Thread in response to calling Filter.
4724 // Therefore, this can't send any IPC events (Not an issue once everything is DAC-ized).
4725 // A V2 shim can provide a proxy calllack that takes these events and queues them and
4726 // does the real dispatch to the user to emulate V2 semantics.
4729 #pragma warning(push)
4730 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
4732 void CordbProcess::RawDispatchEvent(
4733 DebuggerIPCEvent * pEvent,
4734 RSLockHolder * pLockHolder,
4735 ICorDebugManagedCallback * pCallback1,
4736 ICorDebugManagedCallback2 * pCallback2,
4737 ICorDebugManagedCallback3 * pCallback3)
4746 // We start off with the lock, and we'll toggle it.
4747 _ASSERTE(ThreadHoldsProcessLock());
4751 // Call StartEventDispatch to true to guard against calls to Continue()
4752 // from within the user's callback. We need Continue() to behave a little
4753 // bit differently in such a case.
4755 // Also note that Win32EventThread::ExitProcess will take the lock and free all
4756 // events in the queue. (the current event is already off the queue, so
4757 // it will be ok). But we can't do the EP callback in the middle of this dispatch
4758 // so if this flag is set, EP will wait on the miscWaitEvent (which will
4759 // get set in FlushQueuedEvents when we return from here) and let us finish here.
4761 StartEventDispatch(pEvent->type);
4763 // Keep strong references to these objects in case a callback deletes them from underneath us.
4764 RSSmartPtr<CordbAppDomain> pAppDomain;
4765 CordbThread * pThread = NULL;
4768 // Get thread that this event is on. In attach scenarios, this may be the first time ICorDebug has seen this thread.
4769 if (!pEvent->vmThread.IsNull())
4771 pThread = LookupOrCreateThread(pEvent->vmThread);
4774 if (!pEvent->vmAppDomain.IsNull())
4776 pAppDomain.Assign(LookupOrCreateAppDomain(pEvent->vmAppDomain));
4779 DWORD dwVolatileThreadId = 0;
4780 if (pThread != NULL)
4782 dwVolatileThreadId = pThread->GetUniqueId();
4787 // Update the app domain that this thread lives in.
4789 if ((pThread != NULL) && (pAppDomain != NULL))
4791 // It shouldn't be possible for us to see an exited AppDomain here
4792 _ASSERTE( !pAppDomain->IsNeutered() );
4794 pThread->m_pAppDomain = pAppDomain;
4797 _ASSERTE(pEvent != NULL);
4798 _ASSERTE(pCallback1 != NULL);
4799 _ASSERTE(pCallback2 != NULL);
4800 _ASSERTE(pCallback3 != NULL);
4803 STRESS_LOG1(LF_CORDB, LL_EVERYTHING, "Pre-Dispatch IPC event: %s\n", IPCENames::GetName(pEvent->type));
4805 switch (pEvent->type & DB_IPCE_TYPE_MASK)
4807 case DB_IPCE_CREATE_PROCESS:
4809 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
4810 pCallback1->CreateProcess(static_cast<ICorDebugProcess*> (this));
4814 case DB_IPCE_BREAKPOINT:
4816 _ASSERTE(pThread != NULL);
4817 _ASSERTE(pAppDomain != NULL);
4819 // Find the breakpoint object on this side.
4820 CordbBreakpoint *pBreakpoint = NULL;
4822 // We've found cases out in the wild where we get this event on a thread we don't recognize.
4823 // We're not sure how this happens. Add a runtime check to protect ourselves to avoid the
4824 // an AV. We still assert because this should not be happening.
4825 // It likely means theres some issue where we failed to send a CreateThread notification.
4826 TargetConsistencyCheck(pThread != NULL);
4827 pBreakpoint = pAppDomain->m_breakpoints.GetBase(LsPtrToCookie(pEvent->BreakpointData.breakpointToken));
4829 if (pBreakpoint != NULL)
4831 ICorDebugBreakpoint * pIBreakpoint = CordbBreakpointToInterface(pBreakpoint);
4832 _ASSERTE(pIBreakpoint != NULL);
4835 PUBLIC_CALLBACK_IN_THIS_SCOPE2(this, pLockHolder, pEvent, "thread=0x%p, bp=0x%p", pThread, pBreakpoint);
4836 pCallback1->Breakpoint(pAppDomain, pThread, pIBreakpoint);
4842 case DB_IPCE_USER_BREAKPOINT:
4844 STRESS_LOG1(LF_CORDB, LL_INFO1000, "[%x] RCET::DRCE: user breakpoint.\n",
4845 GetCurrentThreadId());
4847 _ASSERTE(pThread != NULL);
4848 _ASSERTE(pAppDomain != NULL);
4849 _ASSERTE(pThread->m_pAppDomain != NULL);
4852 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
4853 pCallback1->Break(pThread->m_pAppDomain, pThread);
4859 case DB_IPCE_STEP_COMPLETE:
4861 STRESS_LOG1(LF_CORDB, LL_INFO1000, "[%x] RCET::DRCE: step complete.\n",
4862 GetCurrentThreadId());
4864 PREFIX_ASSUME(pThread != NULL);
4866 CordbStepper * pStepper = m_steppers.GetBase(LsPtrToCookie(pEvent->StepData.stepperToken));
4868 // It's possible the stepper is NULL if:
4869 // - event X & step-complete are both in the queue
4870 // - during dispatch for event X, Cordbg cancels the stepper (thus removing it from m_steppers)
4871 // - the Step-Complete still stays in the queue, and so we're here, but out stepper's been removed.
4872 // (This could happen for breakpoints too)
4873 // Don't dispatch a callback if the stepper is NULL.
4874 if (pStepper != NULL)
4876 RSSmartPtr<CordbStepper> pRef(pStepper);
4877 pStepper->m_active = false;
4878 m_steppers.RemoveBase((ULONG_PTR)pStepper->m_id);
4881 _ASSERTE(pThread->m_pAppDomain != NULL);
4882 PUBLIC_CALLBACK_IN_THIS_SCOPE2(this, pLockHolder, pEvent, "thrad=0x%p, stepper=0x%p", pThread, pStepper);
4883 pCallback1->StepComplete(pThread->m_pAppDomain, pThread, pStepper, pEvent->StepData.reason);
4886 // implicit Release on pRef
4891 case DB_IPCE_EXCEPTION:
4893 STRESS_LOG1(LF_CORDB, LL_INFO1000, "[%x] RCET::DRCE: exception.\n",
4894 GetCurrentThreadId());
4896 _ASSERTE(pAppDomain != NULL);
4898 // For some exceptions very early in startup (eg, TypeLoad), this may have occurred before we
4899 // even executed jitted code on the thread. We may have not received a CreateThread yet.
4900 // In V2, we detected this and sent a LogMessage on a random thread.
4901 // In V3, we lazily create the CordbThread objects (possibly before the CreateThread event),
4902 // and so we know we should have one.
4903 _ASSERTE(pThread != NULL);
4905 pThread->SetExInfo(pEvent->Exception.vmExceptionHandle);
4907 _ASSERTE(pThread->m_pAppDomain != NULL);
4910 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
4911 pCallback1->Exception(pThread->m_pAppDomain, pThread, !pEvent->Exception.firstChance);
4917 case DB_IPCE_SYNC_COMPLETE:
4918 _ASSERTE(!"Should have never queued a sync complete pEvent.");
4921 case DB_IPCE_THREAD_ATTACH:
4923 STRESS_LOG1(LF_CORDB, LL_INFO100, "RCET::DRCE: thread attach : ID=%x.\n", dwVolatileThreadId);
4925 TargetConsistencyCheck(pThread != NULL);
4927 PUBLIC_CALLBACK_IN_THIS_SCOPE1(this, pLockHolder, pEvent, "thread=0x%p", pThread);
4928 pCallback1->CreateThread(pAppDomain, pThread);
4933 case DB_IPCE_THREAD_DETACH:
4935 STRESS_LOG2(LF_CORDB, LL_INFO100, "[%x] RCET::HRCE: thread detach : ID=%x \n",
4936 GetCurrentThreadId(), dwVolatileThreadId);
4938 // If the runtime thread never entered managed code, there
4939 // won't be a CordbThread, and CreateThread was never
4940 // called, so don't bother calling ExitThread.
4941 if (pThread != NULL)
4943 AddToNeuterOnContinueList(pThread);
4945 RSSmartPtr<CordbThread> pRefThread(pThread);
4947 _ASSERTE(pAppDomain != NULL);
4949 // A thread is reported as dead before we get the exit event.
4950 // See code:IDacDbiInterface#IsThreadMarkedDead for the invariant being asserted here.
4951 TargetConsistencyCheck(pThread->IsThreadDead());
4953 // Enforce the enumeration invariants (see code:IDacDbiInterface#Enumeration)that the thread is not discoverable.
4954 INDEBUG(pThread->DbgAssertThreadDeleted());
4956 // Remove the thread from the hash. If we've removed it from the hash, we really should
4957 // neuter it ... but that causes test failures.
4958 // We'll neuter it in continue.
4959 m_userThreads.RemoveBase(VmPtrToCookie(pThread->m_vmThreadToken));
4962 LOG((LF_CORDB, LL_INFO1000, "[%x] RCET::HRCE: sending thread detach.\n", GetCurrentThreadId()));
4965 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
4966 pCallback1->ExitThread(pAppDomain, pThread);
4969 // Implicit release on thread & pAppDomain
4974 case DB_IPCE_METADATA_UPDATE:
4976 CordbModule * pModule = pAppDomain->LookupOrCreateModule(pEvent->MetadataUpdateData.vmDomainFile);
4977 pModule->RefreshMetaData();
4981 case DB_IPCE_LOAD_MODULE:
4983 _ASSERTE (pAppDomain != NULL);
4984 CordbModule * pModule = pAppDomain->LookupOrCreateModule(pEvent->LoadModuleData.vmDomainFile);
4987 pModule->SetLoadEventContinueMarker();
4989 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
4990 pCallback1->LoadModule(pAppDomain, pModule);
4996 case DB_IPCE_CREATE_CONNECTION:
4998 STRESS_LOG1(LF_CORDB, LL_INFO100,
4999 "RCET::HRCE: Connection change %d \n",
5000 pEvent->CreateConnection.connectionId);
5002 // pass back the connection id and the connection name.
5003 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
5004 pCallback2->CreateConnection(
5006 pEvent->CreateConnection.connectionId,
5007 const_cast<WCHAR*> (pEvent->CreateConnection.wzConnectionName.GetString()));
5011 case DB_IPCE_DESTROY_CONNECTION:
5013 STRESS_LOG1(LF_CORDB, LL_INFO100,
5014 "RCET::HRCE: Connection destroyed %d \n",
5015 pEvent->ConnectionChange.connectionId);
5016 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
5017 pCallback2->DestroyConnection(this, pEvent->ConnectionChange.connectionId);
5021 case DB_IPCE_CHANGE_CONNECTION:
5023 STRESS_LOG1(LF_CORDB, LL_INFO100,
5024 "RCET::HRCE: Connection changed %d \n",
5025 pEvent->ConnectionChange.connectionId);
5027 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
5028 pCallback2->ChangeConnection(this, pEvent->ConnectionChange.connectionId);
5032 case DB_IPCE_UNLOAD_MODULE:
5034 STRESS_LOG3(LF_CORDB, LL_INFO100, "RCET::HRCE: unload module on thread %#x Mod:0x%x AD:0x%08x\n",
5036 VmPtrToCookie(pEvent->UnloadModuleData.vmDomainFile),
5037 VmPtrToCookie(pEvent->vmAppDomain));
5039 PREFIX_ASSUME (pAppDomain != NULL);
5041 CordbModule *module = pAppDomain->LookupOrCreateModule(pEvent->UnloadModuleData.vmDomainFile);
5045 LOG((LF_CORDB, LL_INFO100, "Already unloaded Module - continue()ing!" ));
5048 _ASSERTE(module != NULL);
5049 INDEBUG(module->DbgAssertModuleDeleted());
5051 // The appdomain we're unloading in must be the appdomain we were loaded in. Otherwise, we've got mismatched
5052 // module and appdomain pointers. Bugs 65943 & 81728.
5053 _ASSERTE(pAppDomain == module->GetAppDomain());
5055 // Ensure the module gets neutered once we call continue.
5056 AddToNeuterOnContinueList(module); // throws
5058 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
5059 pCallback1->UnloadModule(pAppDomain, module);
5062 pAppDomain->m_modules.RemoveBase(VmPtrToCookie(pEvent->UnloadModuleData.vmDomainFile));
5066 case DB_IPCE_LOAD_CLASS:
5068 CordbClass *pClass = NULL;
5070 LOG((LF_CORDB, LL_INFO10000,
5071 "RCET::HRCE: load class on thread %#x Tok:0x%08x Mod:0x%08x Asm:0x%08x AD:0x%08x\n",
5073 pEvent->LoadClass.classMetadataToken,
5074 VmPtrToCookie(pEvent->LoadClass.vmDomainFile),
5075 LsPtrToCookie(pEvent->LoadClass.classDebuggerAssemblyToken),
5076 VmPtrToCookie(pEvent->vmAppDomain)));
5078 _ASSERTE (pAppDomain != NULL);
5080 CordbModule* pModule = pAppDomain->LookupOrCreateModule(pEvent->LoadClass.vmDomainFile);
5081 if (pModule == NULL)
5083 LOG((LF_CORDB, LL_INFO100, "Load Class on not-loaded Module - continue()ing!" ));
5086 _ASSERTE(pModule != NULL);
5088 BOOL fDynamic = pModule->IsDynamic();
5090 // If this is a class load in a dynamic module, the metadata has become invalid.
5093 pModule->RefreshMetaData();
5096 hr = pModule->LookupOrCreateClass(pEvent->LoadClass.classMetadataToken, &pClass);
5097 _ASSERTE(SUCCEEDED(hr) == (pClass != NULL));
5100 // Prevent class load from being sent twice.
5101 // @dbgtodo - Microsoft, cordbclass: this is legacy. Can this really happen? Investigate as we dac-ize CordbClass.
5102 if (pClass->LoadEventSent())
5104 // Dynamic modules are dynamic at the module level -
5105 // you can't add a new version of a class once the module
5107 // EnC adds completely new classes.
5108 // There shouldn't be any other way to send multiple
5109 // ClassLoad events.
5110 // Except that there are race conditions between loading
5111 // an appdomain, and loading a class, so if we get the extra
5112 // class load, we should ignore it.
5113 break; //out of the switch statement
5115 pClass->SetLoadEventSent(TRUE);
5120 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
5121 pCallback1->LoadClass(pAppDomain, pClass);
5126 case DB_IPCE_UNLOAD_CLASS:
5128 LOG((LF_CORDB, LL_INFO10000,
5129 "RCET::HRCE: unload class on thread %#x Tok:0x%08x Mod:0x%08x AD:0x%08x\n",
5131 pEvent->UnloadClass.classMetadataToken,
5132 VmPtrToCookie(pEvent->UnloadClass.vmDomainFile),
5133 VmPtrToCookie(pEvent->vmAppDomain)));
5135 // get the appdomain object
5136 _ASSERTE (pAppDomain != NULL);
5138 CordbModule *pModule = pAppDomain->LookupOrCreateModule(pEvent->UnloadClass.vmDomainFile);
5139 if (pModule == NULL)
5141 LOG((LF_CORDB, LL_INFO100, "Unload Class on not-loaded Module - continue()ing!" ));
5144 _ASSERTE(pModule != NULL);
5146 CordbClass *pClass = pModule->LookupClass(pEvent->UnloadClass.classMetadataToken);
5148 if (pClass != NULL && !pClass->HasBeenUnloaded())
5150 pClass->SetHasBeenUnloaded(true);
5152 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
5153 pCallback1->UnloadClass(pAppDomain, pClass);
5158 case DB_IPCE_FIRST_LOG_MESSAGE:
5160 _ASSERTE(pThread != NULL);
5161 _ASSERTE(pAppDomain != NULL);
5163 const WCHAR * pszContent = pEvent->FirstLogMessage.szContent.GetString();
5165 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
5166 pCallback1->LogMessage(
5169 pEvent->FirstLogMessage.iLevel,
5170 const_cast<WCHAR*> (pEvent->FirstLogMessage.szCategory.GetString()),
5171 const_cast<WCHAR*> (pszContent));
5176 case DB_IPCE_LOGSWITCH_SET_MESSAGE:
5179 LOG((LF_CORDB, LL_INFO10000,
5180 "[%x] RCET::DRCE: Log Switch Setting Message.\n",
5181 GetCurrentThreadId()));
5183 _ASSERTE(pThread != NULL);
5185 const WCHAR *pstrLogSwitchName = pEvent->LogSwitchSettingMessage.szSwitchName.GetString();
5186 const WCHAR *pstrParentName = pEvent->LogSwitchSettingMessage.szParentSwitchName.GetString();
5188 // from the thread object get the appdomain object
5189 _ASSERTE(pAppDomain == pThread->m_pAppDomain);
5190 _ASSERTE (pAppDomain != NULL);
5193 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
5194 pCallback1->LogSwitch(
5197 pEvent->LogSwitchSettingMessage.iLevel,
5198 pEvent->LogSwitchSettingMessage.iReason,
5199 const_cast<WCHAR*> (pstrLogSwitchName),
5200 const_cast<WCHAR*> (pstrParentName));
5206 case DB_IPCE_CUSTOM_NOTIFICATION:
5208 _ASSERTE(pThread != NULL);
5209 _ASSERTE(pAppDomain != NULL);
5212 // determine first whether custom notifications for this type are enabled -- if not
5213 // we just return without doing anything.
5214 CordbClass * pNotificationClass = LookupClass(pAppDomain,
5215 pEvent->CustomNotification.vmDomainFile,
5216 pEvent->CustomNotification.classToken);
5218 // if the class is NULL, that means the debugger never enabled notifications for it. Otherwise,
5219 // the CordbClass instance would already have been created when the notifications were
5221 if ((pNotificationClass != NULL) && pNotificationClass->CustomNotificationsEnabled())
5224 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
5225 pCallback3->CustomNotification(pThread, pAppDomain);
5231 case DB_IPCE_CREATE_APP_DOMAIN:
5233 STRESS_LOG2(LF_CORDB, LL_INFO100,
5234 "RCET::HRCE: create appdomain on thread %#x AD:0x%08x \n",
5236 VmPtrToCookie(pEvent->vmAppDomain));
5239 // Enumerate may have prepopulated the appdomain, so check if it already exists.
5240 // Either way, still send the CreateEvent. (We don't want to skip the Create event
5241 // just because the debugger did an enumerate)
5242 // We remove AppDomains from the hash as soon as they are exited.
5243 pAppDomain.Assign(LookupOrCreateAppDomain(pEvent->AppDomainData.vmAppDomain));
5244 _ASSERTE(pAppDomain != NULL); // throws on failure
5247 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
5248 hr = pCallback1->CreateAppDomain(this, pAppDomain);
5255 case DB_IPCE_EXIT_APP_DOMAIN:
5257 STRESS_LOG2(LF_CORDB, LL_INFO100, "RCET::HRCE: exit appdomain on thread %#x AD:0x%08x \n",
5259 VmPtrToCookie(pEvent->vmAppDomain));
5261 // In debug-only builds, assert that the appdomain is indeed deleted and not discoverable.
5262 INDEBUG(DbgAssertAppDomainDeleted(pEvent->vmAppDomain));
5264 // If we get an ExitAD message for which we have no AppDomain, then ignore it.
5265 // This can happen if an AD gets torn down very early (before the LS AD is to the
5266 // point that it can be published).
5267 // This could also happen if we attach a debugger right before the Exit event is sent.
5268 // In this case, the debuggee is no longer publishing the appdomain.
5269 if (pAppDomain == NULL)
5273 _ASSERTE (pAppDomain != NULL);
5275 // See if this is the default AppDomain exiting. This should only happen very late in
5276 // the shutdown cycle, and so we shouldn't do anything significant with m_pDefaultDomain==NULL.
5277 // We should try and remove m_pDefaultDomain entirely since we can't count on it always existing.
5278 if (pAppDomain == m_pDefaultAppDomain)
5280 m_pDefaultAppDomain = NULL;
5283 // Update any threads which were last seen in this AppDomain. We don't
5284 // get any notification when a thread leaves an AppDomain, so our idea
5285 // of what AppDomain the thread is in may be out of date.
5286 UpdateThreadsForAdUnload( pAppDomain );
5288 // This will still maintain weak references so we could call Continue.
5289 AddToNeuterOnContinueList(pAppDomain);
5292 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
5293 hr = pCallback1->ExitAppDomain(this, pAppDomain);
5296 // @dbgtodo appdomain: This should occur before the callback.
5297 // Even after ExitAppDomain, the outside world will want to continue calling
5298 // Continue (and thus they may need to call CordbAppDomain::GetProcess(), which Neutering
5299 // would clear). Thus we can't neuter yet.
5301 // Remove this app domain. This means any attempt to lookup the AppDomain
5302 // will fail (which we do at the top of this method). Since any threads (incorrectly) referring
5303 // to this AppDomain have been moved to the default AppDomain, no one should be
5304 // interested in looking this AppDomain up anymore.
5305 m_appDomains.RemoveBase(VmPtrToCookie(pEvent->vmAppDomain));
5310 case DB_IPCE_LOAD_ASSEMBLY:
5312 LOG((LF_CORDB, LL_INFO100,
5313 "RCET::HRCE: load assembly on thread %#x Asm:0x%08x AD:0x%08x \n",
5315 VmPtrToCookie(pEvent->AssemblyData.vmDomainAssembly),
5316 VmPtrToCookie(pEvent->vmAppDomain)));
5318 _ASSERTE (pAppDomain != NULL);
5320 // Determine if this Assembly is cached.
5321 CordbAssembly * pAssembly = pAppDomain->LookupOrCreateAssembly(pEvent->AssemblyData.vmDomainAssembly);
5322 _ASSERTE(pAssembly != NULL); // throws on error
5324 // If created, or have, an Assembly, notify callback.
5326 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
5327 hr = pCallback1->LoadAssembly(pAppDomain, pAssembly);
5333 case DB_IPCE_UNLOAD_ASSEMBLY:
5335 LOG((LF_CORDB, LL_INFO100, "RCET::DRCE: unload assembly on thread %#x Asm:0x%x AD:0x%x\n",
5337 VmPtrToCookie(pEvent->AssemblyData.vmDomainAssembly),
5338 VmPtrToCookie(pEvent->vmAppDomain)));
5340 _ASSERTE (pAppDomain != NULL);
5342 CordbAssembly * pAssembly = pAppDomain->LookupOrCreateAssembly(pEvent->AssemblyData.vmDomainAssembly);
5344 if (pAssembly == NULL)
5346 // No assembly. This could happen if we attach right before an unload event is sent.
5349 _ASSERTE(pAssembly != NULL);
5350 INDEBUG(pAssembly->DbgAssertAssemblyDeleted());
5352 // Ensure the assembly gets neutered when we call continue.
5353 AddToNeuterOnContinueList(pAssembly); // throws
5356 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
5357 hr = pCallback1->UnloadAssembly(pAppDomain, pAssembly);
5360 pAppDomain->RemoveAssemblyFromCache(pEvent->AssemblyData.vmDomainAssembly);
5365 case DB_IPCE_FUNC_EVAL_COMPLETE:
5367 LOG((LF_CORDB, LL_INFO1000, "RCET::DRCE: func eval complete.\n"));
5369 CordbEval *pEval = NULL;
5371 pEval = pEvent->FuncEvalComplete.funcEvalKey.UnWrapAndRemove(this);
5374 _ASSERTE(!"Bogus FuncEval handle in IPC block.");
5375 // Bogus handle in IPC block.
5379 _ASSERTE(pEval != NULL);
5381 _ASSERTE(pThread != NULL);
5382 _ASSERTE(pAppDomain != NULL);
5384 CONSISTENCY_CHECK_MSGF(pEval->m_DbgAppDomainStarted == pAppDomain,
5385 ("AppDomain changed from Func-Eval. Eval=%p, Started=%p, Now=%p\n",
5386 pEval, pEval->m_DbgAppDomainStarted, (void*) pAppDomain));
5388 // Hold the data about the result in the CordbEval for later.
5389 pEval->m_complete = true;
5390 pEval->m_successful = !!pEvent->FuncEvalComplete.successful;
5391 pEval->m_aborted = !!pEvent->FuncEvalComplete.aborted;
5392 pEval->m_resultAddr = pEvent->FuncEvalComplete.resultAddr;
5393 pEval->m_vmObjectHandle = pEvent->FuncEvalComplete.vmObjectHandle;
5394 pEval->m_resultType = pEvent->FuncEvalComplete.resultType;
5395 pEval->m_resultAppDomainToken = pEvent->FuncEvalComplete.vmAppDomain;
5397 CordbAppDomain *pResultAppDomain = LookupOrCreateAppDomain(pEvent->FuncEvalComplete.vmAppDomain);
5399 _ASSERTE(OutstandingEvalCount() > 0);
5400 DecrementOutstandingEvalCount();
5402 CONSISTENCY_CHECK_MSGF(pEval->m_DbgAppDomainStarted == pAppDomain,
5403 ("AppDomain changed from Func-Eval. Eval=%p, Started=%p, Now=%p\n",
5404 pEval, pEval->m_DbgAppDomainStarted, (void*) pAppDomain));
5406 // If we did this func eval with this thread stopped at an excpetion, then we need to pretend as if we
5407 // really didn't continue from the exception, since, of course, we really didn't on the Left Side.
5408 if (pEval->IsEvalDuringException())
5410 pThread->SetExInfo(pEval->m_vmThreadOldExceptionHandle);
5413 bool fEvalCompleted = pEval->m_successful || pEval->m_aborted;
5415 // If a CallFunction() is aborted, the LHS may not complete the abort
5416 // immediately and hence we cant do a SendCleanup() at that point. Also,
5417 // the debugger may (incorrectly) release the CordbEval before this
5418 // DB_IPCE_FUNC_EVAL_COMPLETE event is received. Hence, we maintain an
5419 // extra ref-count to determine when this can be done.
5420 // Note that this can cause a two-way DB_IPCE_FUNC_EVAL_CLEANUP event
5421 // to be sent. Hence, it has to be done before the Continue (see issue 102745).
5424 // Note that if the debugger has already (incorrectly) released the CordbEval,
5425 // pEval will be pointing to garbage and should not be used by the debugger.
5428 PUBLIC_CALLBACK_IN_THIS_SCOPE2(this, pLockHolder, pEvent, "thread=0x%p, eval=0x%p. (Complete)", pThread, pEval);
5429 pCallback1->EvalComplete(pResultAppDomain, pThread, pEval);
5433 PUBLIC_CALLBACK_IN_THIS_SCOPE2(this, pLockHolder, pEvent, "pThread=0x%p, eval=0x%p. (Exception)", pThread, pEval);
5434 pCallback1->EvalException(pResultAppDomain, pThread, pEval);
5437 // This release may send an DB_IPCE_FUNC_EVAL_CLEANUP IPC event. That's ok b/c
5438 // we're still synced even if if Continue was called inside the callback.
5439 // That's because the StopContinueHolder bumped up the stopcount.
5440 // Corresponding AddRef() in CallFunction().
5441 // @todo - this is leaked if we don't get an EvalComplete event (eg, process exits with
5442 // in middle of func-eval).
5448 case DB_IPCE_NAME_CHANGE:
5450 LOG((LF_CORDB, LL_INFO1000, "RCET::HRCE: Name Change %d 0x%p\n",
5452 VmPtrToCookie(pEvent->NameChange.vmAppDomain)));
5456 if (pEvent->NameChange.eventType == THREAD_NAME_CHANGE)
5458 // Lookup the CordbThread that matches this runtime thread.
5459 if (!pEvent->NameChange.vmThread.IsNull())
5461 pThread = LookupOrCreateThread(pEvent->NameChange.vmThread);
5466 _ASSERTE (pEvent->NameChange.eventType == APP_DOMAIN_NAME_CHANGE);
5467 pAppDomain.Assign(LookupOrCreateAppDomain(pEvent->NameChange.vmAppDomain));
5470 pAppDomain->InvalidateName();
5474 if (pThread || pAppDomain)
5476 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
5477 pCallback1->NameChange(pAppDomain, pThread);
5483 case DB_IPCE_UPDATE_MODULE_SYMS:
5485 RSExtSmartPtr<IStream> pStream;
5487 // Find the app domain the module lives in.
5488 _ASSERTE (pAppDomain != NULL);
5490 // Find the Right Side module for this module.
5491 CordbModule * pModule = pAppDomain->LookupOrCreateModule(pEvent->UpdateModuleSymsData.vmDomainFile);
5492 _ASSERTE(pModule != NULL);
5494 // This is a legacy event notification for updated PDBs.
5495 // Creates a new IStream object. Ownership is handed off via callback.
5496 IDacDbiInterface::SymbolFormat symFormat = pModule->GetInMemorySymbolStream(&pStream);
5498 // We shouldn't get this event if there aren't PDB symbols waiting. Specifically we don't want
5499 // to incur the cost of copying over ILDB symbols here without the debugger asking for them.
5500 // Eventually we may remove this callback as well and always rely on explicit requests.
5501 _ASSERTE(symFormat == IDacDbiInterface::kSymbolFormatPDB);
5503 if (symFormat == IDacDbiInterface::kSymbolFormatPDB)
5505 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
5507 _ASSERTE(pStream != NULL); // Shouldn't send the event if we don't have a stream.
5509 pCallback1->UpdateModuleSymbols(pAppDomain, pModule, pStream);
5515 case DB_IPCE_MDA_NOTIFICATION:
5517 RSInitHolder<CordbMDA> pMDA(new CordbMDA(this, &pEvent->MDANotification)); // throws
5519 // Ctor leaves both internal + ext Ref at 0, adding to neuter list bumps int-ref up to 1.
5520 // Neutering will dump it back down to zero.
5521 this->AddToNeuterOnExitList(pMDA);
5523 // We bump up and down the external ref so that even if the callback doensn't touch the refs,
5524 // our Ext-Release here will still cause a 1->0 ext-ref transition, which will get it
5525 // swept on the neuter list.
5526 RSExtSmartPtr<ICorDebugMDA> pExternalMDARef;
5527 pMDA.TransferOwnershipExternal(&pExternalMDARef);
5529 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
5531 pCallback2->MDANotification(
5533 pThread, // may be null
5536 // pExternalMDARef's dtor will do an external release,
5537 // which is very significant because it may be the one that does the 1->0 ext ref transition,
5538 // which may mean cause the "NeuterAtWill" bit to get flipped on this CordbMDA object.
5539 // Since this is an external release, do it in the PUBLIC_CALLBACK scope.
5540 pExternalMDARef.Clear();
5546 case DB_IPCE_CONTROL_C_EVENT:
5551 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
5552 hr = pCallback1->ControlCTrap((ICorDebugProcess*) this);
5556 RSLockHolder ch(this->GetStopGoLock());
5558 DebuggerIPCEvent eventControlCResult;
5560 InitIPCEvent(&eventControlCResult,
5561 DB_IPCE_CONTROL_C_EVENT_RESULT,
5563 VMPTR_AppDomain::NullPtr());
5565 // Indicate whether the debugger has handled the event.
5566 eventControlCResult.hr = hr;
5568 // Send the reply to the LS.
5569 SendIPCEvent(&eventControlCResult, sizeof(eventControlCResult));
5570 } // release SG lock
5575 // EnC Remap opportunity
5576 case DB_IPCE_ENC_REMAP:
5578 LOG((LF_CORDB, LL_INFO1000, "[%x] RCET::DRCE: EnC Remap!.\n",
5579 GetCurrentThreadId()));
5581 _ASSERTE(NULL != pAppDomain);
5583 CordbModule * pModule = pAppDomain->LookupOrCreateModule(pEvent->EnCRemap.vmDomainFile);
5584 PREFIX_ASSUME(pModule != NULL);
5586 CordbFunction * pCurFunction = NULL;
5587 CordbFunction * pResumeFunction = NULL;
5589 // lookup the version of the function that we are mapping from
5590 // this is the one that is currently running
5591 pCurFunction = pModule->LookupOrCreateFunction(
5592 pEvent->EnCRemap.funcMetadataToken, pEvent->EnCRemap.currentVersionNumber);
5594 // lookup the version of the function that we are mapping to
5595 // it will always be the most recent
5596 pResumeFunction = pModule->LookupOrCreateFunction(
5597 pEvent->EnCRemap.funcMetadataToken, pEvent->EnCRemap.resumeVersionNumber);
5599 _ASSERTE(pCurFunction->GetEnCVersionNumber() < pResumeFunction->GetEnCVersionNumber());
5601 RSSmartPtr<CordbFunction> pRefCurFunction(pCurFunction);
5602 RSSmartPtr<CordbFunction> pRefResumeFunction(pResumeFunction);
5604 // Verify we're not about to overwrite an outstanding remap IP
5605 // This should only be set while a remap opportunity is being handled,
5606 // and cleared (by CordbThread::MarkStackFramesDirty) on Continue.
5607 // We want to be absolutely sure we don't accidentally keep a stale pointer
5608 // around because it would point to arbitrary stack space in the CLR potentially
5609 // leading to stack corruption.
5610 _ASSERTE( pThread->m_EnCRemapFunctionIP == NULL );
5612 // Stash the address of the remap IP buffer. This indicates that calling
5613 // RemapFunction is valid and provides a communications channel between the RS
5614 // and LS for the remap IL offset.
5615 pThread->m_EnCRemapFunctionIP = pEvent->EnCRemap.resumeILOffset;
5618 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
5619 pCallback2->FunctionRemapOpportunity(
5624 (ULONG32)pEvent->EnCRemap.currentILOffset);
5627 // Implicit release on pCurFunction and pResumeFunction.
5631 // EnC Remap complete
5632 case DB_IPCE_ENC_REMAP_COMPLETE:
5634 LOG((LF_CORDB, LL_INFO1000, "[%x] RCET::DRCE: EnC Remap Complete!.\n",
5635 GetCurrentThreadId()));
5637 _ASSERTE(NULL != pAppDomain);
5639 CordbModule* pModule = pAppDomain->LookupOrCreateModule(pEvent->EnCRemap.vmDomainFile);
5640 PREFIX_ASSUME(pModule != NULL);
5642 // Find the function we're remapping to, which must be the latest version
5643 CordbFunction *pRemapFunction=
5644 pModule->LookupFunctionLatestVersion(pEvent->EnCRemapComplete.funcMetadataToken);
5645 PREFIX_ASSUME(pRemapFunction != NULL);
5647 // Dispatch the FunctionRemapComplete callback
5648 RSSmartPtr<CordbFunction> pRef(pRemapFunction);
5650 PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
5651 pCallback2->FunctionRemapComplete(pAppDomain, pThread, pRemapFunction);
5653 // Implicit release on pRemapFunction via holder
5657 case DB_IPCE_BREAKPOINT_SET_ERROR:
5659 LOG((LF_CORDB, LL_INFO1000, "RCET::DRCE: breakpoint set error.\n"));
5661 RSSmartPtr<CordbBreakpoint> pRef;
5663 _ASSERTE(pThread != NULL);
5664 _ASSERTE(pAppDomain != NULL);
5666 // Find the breakpoint object on this side.
5667 CordbBreakpoint * pBreakpoint = NULL;
5670 if (pThread == NULL)
5672 // We've found cases out in the wild where we get this event on a thread we don't recognize.
5673 // We're not sure how this happens. Add a runtime check to protect ourselves to avoid the
5674 // an AV. We still assert because this should not be happening.
5675 // It likely means theres some issue where we failed to send a CreateThread notification.
5676 STRESS_LOG1(LF_CORDB, LL_INFO1000, "BreakpointSetError on unrecognized thread. %p\n", pBreakpoint);
5678 _ASSERTE(!"Missing thread on bp set error");
5682 pBreakpoint = pAppDomain->m_breakpoints.GetBase(LsPtrToCookie(pEvent->BreakpointSetErrorData.breakpointToken));
5684 if (pBreakpoint != NULL)
5686 ICorDebugBreakpoint * pIBreakpoint = CordbBreakpointToInterface(pBreakpoint);
5687 _ASSERTE(pIBreakpoint != NULL);
5689 PUBLIC_CALLBACK_IN_THIS_SCOPE2(this, pLockHolder, pEvent, "thread=0x%p, bp=0x%p", pThread, pBreakpoint);
5690 pCallback1->BreakpointSetError(pAppDomain, pThread, pIBreakpoint, 0);
5693 // Implicit release on pRef.
5698 case DB_IPCE_EXCEPTION_CALLBACK2:
5700 STRESS_LOG4(LF_CORDB, LL_INFO100,
5701 "RCET::DRCE: Exception2 0x%p 0x%X 0x%X 0x%X\n",
5702 pEvent->ExceptionCallback2.framePointer.GetSPValue(),
5703 pEvent->ExceptionCallback2.nOffset,
5704 pEvent->ExceptionCallback2.eventType,
5705 pEvent->ExceptionCallback2.dwFlags
5708 if (pThread == NULL)
5710 // We've got an exception on a thread we don't know about. This could be a thread that
5711 // has never run any managed code, so let's just ignore the exception. We should have
5712 // already sent a log message about this situation for the EXCEPTION callback above.
5713 _ASSERTE( pEvent->ExceptionCallback2.eventType == DEBUG_EXCEPTION_UNHANDLED );
5717 pThread->SetExInfo(pEvent->ExceptionCallback2.vmExceptionHandle);
5720 // Send all the information back to the debugger.
5722 RSSmartPtr<CordbFrame> pFrame;
5724 FramePointer fp = pEvent->ExceptionCallback2.framePointer;
5725 if (fp != LEAF_MOST_FRAME)
5727 // The interface forces us to to pass a FramePointer via an ICorDebugFrame.
5728 // However, we can't get a real ICDFrame without a stackwalk, and we don't
5729 // want to do a stackwalk now. so pass a netuered proxy frame. The shim
5730 // can map this to a real frame.
5731 // See comments at CordbPlaceHolderFrame class for details.
5732 pFrame.Assign(new CordbPlaceholderFrame(this, fp));
5735 CorDebugExceptionCallbackType type = pEvent->ExceptionCallback2.eventType;
5737 PUBLIC_CALLBACK_IN_THIS_SCOPE3(this, pLockHolder, pEvent, "pThread=0x%p, frame=%p, type=%d", pThread, (ICorDebugFrame*) pFrame, type);
5738 hr = pCallback2->Exception(
5739 pThread->m_pAppDomain,
5742 (ULONG32)(pEvent->ExceptionCallback2.nOffset),
5744 pEvent->ExceptionCallback2.dwFlags);
5749 case DB_IPCE_EXCEPTION_UNWIND:
5751 STRESS_LOG2(LF_CORDB, LL_INFO100,
5752 "RCET::DRCE: Exception Unwind 0x%X 0x%X\n",
5753 pEvent->ExceptionCallback2.eventType,
5754 pEvent->ExceptionCallback2.dwFlags
5757 if (pThread == NULL)
5759 // We've got an exception on a thread we don't know about. This probably should never
5760 // happen (if it's unwinding, then we expect a managed frame on the stack, and so we should
5761 // know about the thread), but if it does fall back to ignoring the exception.
5762 _ASSERTE( !"Got unwind event for unknown exception" );
5767 // Send all the information back to the debugger.
5770 PUBLIC_CALLBACK_IN_THIS_SCOPE1(this, pLockHolder, pEvent, "pThread=0x%p", pThread);
5771 hr = pCallback2->ExceptionUnwind(
5772 pThread->m_pAppDomain,
5774 pEvent->ExceptionUnwind.eventType,
5775 pEvent->ExceptionUnwind.dwFlags);
5781 case DB_IPCE_INTERCEPT_EXCEPTION_COMPLETE:
5783 STRESS_LOG0(LF_CORDB, LL_INFO100, "RCET::DRCE: Exception Interception Complete.\n");
5785 if (pThread == NULL)
5787 // We've got an exception on a thread we don't know about. This probably should never
5788 // happen (if it's unwinding, then we expect a managed frame on the stack, and so we should
5789 // know about the thread), but if it does fall back to ignoring the exception.
5790 _ASSERTE( !"Got complete event for unknown exception" );
5795 // Tell the debugger that the exception has been intercepted. This is similar to the
5796 // notification we give when we start unwinding for a non-intercepted exception, except that the
5797 // interception has been completed at this point, which means that we are conceptually at the end
5798 // of the second pass.
5801 PUBLIC_CALLBACK_IN_THIS_SCOPE1(this, pLockHolder, pEvent, "pThread=0x%p", pThread);
5802 hr = pCallback2->ExceptionUnwind(
5803 pThread->m_pAppDomain,
5805 DEBUG_EXCEPTION_INTERCEPTED,
5810 #ifdef TEST_DATA_CONSISTENCY
5811 case DB_IPCE_TEST_CRST:
5815 // the left side has signaled that we should test whether pEvent->TestCrstData.vmCrst is held
5816 GetDAC()->TestCrst(pEvent->TestCrstData.vmCrst);
5818 EX_CATCH_HRESULT(hr);
5820 if (pEvent->TestCrstData.fOkToTake)
5822 _ASSERTE(hr == S_OK);
5825 // we want to catch this in retail builds too
5829 else // the lock was already held
5831 // see if we threw because the lock was held
5832 _ASSERTE(hr == CORDBG_E_PROCESS_NOT_SYNCHRONIZED);
5833 if (hr != CORDBG_E_PROCESS_NOT_SYNCHRONIZED)
5835 // we want to catch this in retail builds too
5843 case DB_IPCE_TEST_RWLOCK:
5847 // the left side has signaled that we should test whether pEvent->TestRWLockData.vmRWLock is held
5848 GetDAC()->TestRWLock(pEvent->TestRWLockData.vmRWLock);
5850 EX_CATCH_HRESULT(hr);
5852 if (pEvent->TestRWLockData.fOkToTake)
5854 _ASSERTE(hr == S_OK);
5857 // we want to catch this in retail builds too
5861 else // the lock was already held
5863 // see if we threw because the lock was held
5864 _ASSERTE(hr == CORDBG_E_PROCESS_NOT_SYNCHRONIZED);
5865 if (hr != CORDBG_E_PROCESS_NOT_SYNCHRONIZED)
5867 // we want to catch this in retail builds too
5876 _ASSERTE(!"Unknown event");
5877 LOG((LF_CORDB, LL_INFO1000,
5878 "[%x] RCET::HRCE: Unknown event: 0x%08x\n",
5879 GetCurrentThreadId(), pEvent->type));
5883 FinishEventDispatch();
5886 #pragma warning(pop)
5889 //---------------------------------------------------------------------------------------
5890 // Callback for prepopulating threads.
5893 // vmThread - thread as part of the eunmeration.
5894 // pUserData - data supplied with callback. It's a CordbProcess* object.
5898 void CordbProcess::ThreadEnumerationCallback(VMPTR_Thread vmThread, void * pUserData)
5900 CordbProcess * pThis = reinterpret_cast<CordbProcess *> (pUserData);
5901 INTERNAL_DAC_CALLBACK(pThis);
5903 STRESS_LOG0(LF_CORDB, LL_INFO1000, "ThreadEnumerationCallback()\n");
5905 // Do lookup / lazy-create.
5906 pThis->LookupOrCreateThread(vmThread);
5909 //---------------------------------------------------------------------------------------
5910 // Fully build up the CordbThread cache to match VM state.
5911 void CordbProcess::PrepopulateThreadsOrThrow()
5913 RSLockHolder lockHolder(GetProcessLock());
5914 if (IsDacInitialized())
5916 STRESS_LOG0(LF_CORDB, LL_INFO1000, "PrepopulateThreadsOrThrow()\n");
5917 GetDAC()->EnumerateThreads(ThreadEnumerationCallback, this);
5921 //---------------------------------------------------------------------------------------
5922 // Create a Thread enumerator
5925 // pOwnerObj - object (a CordbProcess or CordbThread) that will own the enumerator.
5926 // pOwnerList - the neuter list that the enumerator will live on
5927 // pHolder - an outparameter for the enumerator to be initialized.
5929 void CordbProcess::BuildThreadEnum(CordbBase * pOwnerObj, NeuterList * pOwnerList, RSInitHolder<CordbHashTableEnum> * pHolder)
5931 CordbHashTableEnum::BuildOrThrow(
5935 IID_ICorDebugThreadEnum,
5939 // Public implementation of ICorDebugProcess::EnumerateThreads
5940 HRESULT CordbProcess::EnumerateThreads(ICorDebugThreadEnum **ppThreads)
5943 PUBLIC_API_BEGIN(this);
5949 // FUTURE: Consider adding this IF block to the PUBLIC_API macros so that
5950 // typical public APIs fail quickly if we're trying to do a detach. For
5951 // now, I'm hand-adding this check only to the few problematic APIs that get
5952 // called while queuing the fake attach events. In these cases, it is not
5953 // enough to check if CordbProcess::IsNeutered(), as the detaching thread
5954 // may have begun the detaching and neutering process, but not be
5955 // finished--in which case m_detached is true, but
5956 // CordbProcess::IsNeutered() is still false.
5957 ThrowHR(CORDBG_E_PROCESS_DETACHED);
5960 ValidateOrThrow(ppThreads);
5962 RSInitHolder<CordbHashTableEnum> pEnum;
5963 InternalEnumerateThreads(pEnum.GetAddr());
5965 pEnum.TransferOwnershipExternal(ppThreads);
5971 // Internal implementation of EnumerateThreads
5972 VOID CordbProcess::InternalEnumerateThreads(RSInitHolder<CordbHashTableEnum> *ppThreads)
5974 INTERNAL_API_ENTRY(this);
5975 // Needs to prepopulate
5976 PrepopulateThreadsOrThrow();
5977 BuildThreadEnum(this, this->GetContinueNeuterList(), ppThreads);
5980 // Implementation of ICorDebugProcess::GetThread
5981 HRESULT CordbProcess::GetThread(DWORD dwThreadId, ICorDebugThread **ppThread)
5983 PUBLIC_API_ENTRY(this);
5984 VALIDATE_POINTER_TO_OBJECT(ppThread, ICorDebugThread **);
5986 // No good pre-existing ATT_* contract for this.
5987 // Because for legacy, we have to allow this on the win32 event thread.
5993 RSLockHolder lockHolder(GetProcessLock());
5996 // See code:CordbProcess::EnumerateThreads#Detach_Check
5997 ThrowHR(CORDBG_E_PROCESS_DETACHED);
5999 CordbThread * pThread = TryLookupOrCreateThreadByVolatileOSId(dwThreadId);
6000 if (pThread == NULL)
6002 // This is a common case because we may be looking up an unmanaged thread.
6007 *ppThread = static_cast<ICorDebugThread*> (pThread);
6008 pThread->ExternalAddRef();
6011 EX_CATCH_HRESULT(hr);
6013 LOG((LF_CORDB, LL_INFO10000, "CP::GT returns id=0x%x hr=0x%x ppThread=0x%p",
6014 dwThreadId, hr, *ppThread));
6018 HRESULT CordbProcess::ThreadForFiberCookie(DWORD fiberCookie,
6019 ICorDebugThread **ppThread)
6024 HRESULT CordbProcess::GetHelperThreadID(DWORD *pThreadID)
6026 PUBLIC_API_ENTRY(this);
6027 FAIL_IF_NEUTERED(this);
6029 _ASSERTE(m_pShim != NULL);
6030 if (pThreadID == NULL)
6032 return (E_INVALIDARG);
6036 // Return the ID of the current helper thread. There may be no thread in the process, or there may be a true helper
6038 if ((m_helperThreadId != 0) && !m_helperThreadDead)
6040 *pThreadID = m_helperThreadId;
6042 else if ((GetDCB() != NULL) && (GetDCB()->m_helperThreadId != 0))
6046 // be sure we have the latest information
6047 UpdateRightSideDCB();
6048 *pThreadID = GetDCB()->m_helperThreadId;
6050 EX_CATCH_HRESULT(hr);
6061 //---------------------------------------------------------------------------------------
6063 // Sends IPC event to set all the managed threads, except for the one given, to the given state
6066 // state - The state to set the threads to.
6067 // pExceptThread - The thread to not set. This is usually the thread that is currently
6068 // sending an IPC event to the RS, and should be excluded.
6071 // Typical HRESULT symantics, nothing abnormal.
6073 HRESULT CordbProcess::SetAllThreadsDebugState(CorDebugThreadState state,
6074 ICorDebugThread * pExceptThread)
6076 PUBLIC_REENTRANT_API_ENTRY(this);
6077 FAIL_IF_NEUTERED(this);
6078 VALIDATE_POINTER_TO_OBJECT_OR_NULL(pExceptThread, ICorDebugThread *);
6079 ATT_REQUIRE_STOPPED_MAY_FAIL(this);
6081 if (GetShim() == NULL)
6085 CordbThread * pCordbExceptThread = static_cast<CordbThread *> (pExceptThread);
6087 LOG((LF_CORDB, LL_INFO1000, "CP::SATDS: except thread=0x%08x 0x%x\n",
6089 (pCordbExceptThread != NULL) ? pCordbExceptThread->m_id : 0));
6091 // Send one event to the Left Side to twiddle each thread's state.
6092 DebuggerIPCEvent event;
6094 InitIPCEvent(&event, DB_IPCE_SET_ALL_DEBUG_STATE, true, VMPTR_AppDomain::NullPtr());
6096 event.SetAllDebugState.vmThreadToken = ((pCordbExceptThread != NULL) ?
6097 pCordbExceptThread->m_vmThreadToken : VMPTR_Thread::NullPtr());
6099 event.SetAllDebugState.debugState = state;
6101 HRESULT hr = SendIPCEvent(&event, sizeof(DebuggerIPCEvent));
6103 hr = WORST_HR(hr, event.hr);
6105 // If that worked, then loop over all the threads on this side and set their states.
6108 RSLockHolder lockHolder(GetProcessLock());
6110 CordbThread * pThread;
6112 // We don't need to prepopulate here (to collect LS state) because we're just updating RS state.
6113 for (pThread = m_userThreads.FindFirst(&hashFind);
6115 pThread = m_userThreads.FindNext(&hashFind))
6117 if (pThread != pCordbExceptThread)
6119 pThread->m_debugState = state;
6128 HRESULT CordbProcess::EnumerateObjects(ICorDebugObjectEnum **ppObjects)
6131 PUBLIC_API_ENTRY(this);
6132 FAIL_IF_NEUTERED(this);
6133 VALIDATE_POINTER_TO_OBJECT(ppObjects, ICorDebugObjectEnum **);
6138 //---------------------------------------------------------------------------------------
6140 // Determines if the target address is a "CLR transition stub".
6143 // address - The address of an instruction to check in the target address space.
6144 // pfTransitionStub - Space to store the result, TRUE if the address belongs to a
6145 // transition stub, FALSE if not. Only valid if this method returns a success code.
6148 // Typical HRESULT symantics, nothing abnormal.
6150 //---------------------------------------------------------------------------------------
6151 HRESULT CordbProcess::IsTransitionStub(CORDB_ADDRESS address, BOOL *pfTransitionStub)
6153 PUBLIC_API_ENTRY(this);
6154 FAIL_IF_NEUTERED(this);
6155 VALIDATE_POINTER_TO_OBJECT(pfTransitionStub, BOOL *);
6158 *pfTransitionStub = FALSE;
6160 if (this->m_helperThreadDead)
6165 // If we're not initialized, then it can't be a stub...
6171 ATT_REQUIRE_STOPPED_MAY_FAIL(this);
6176 DebuggerIPCEvent eventData;
6178 InitIPCEvent(&eventData, DB_IPCE_IS_TRANSITION_STUB, true, VMPTR_AppDomain::NullPtr());
6180 eventData.IsTransitionStub.address = CORDB_ADDRESS_TO_PTR(address);
6182 hr = SendIPCEvent(&eventData, sizeof(eventData));
6183 hr = WORST_HR(hr, eventData.hr);
6186 _ASSERTE(eventData.type == DB_IPCE_IS_TRANSITION_STUB_RESULT);
6188 *pfTransitionStub = eventData.IsTransitionStubResult.isStub;
6189 LOG((LF_CORDB, LL_INFO1000, "CP::ITS: addr=0x%p result=%d\n", address, *pfTransitionStub));
6190 // @todo - beware that IsTransitionStub has a very important sideeffect - it synchronizes the runtime!
6191 // This for example covers an OS bug where SetThreadContext may silently fail if we're not synchronized.
6192 // (See IMDArocess::SetThreadContext for details on that bug).
6193 // If we ever stop using IPC events here and only use DAC; we need to be aware of that.
6195 // Check against DAC primitives
6197 BOOL fIsStub2 = GetDAC()->IsTransitionStub(address);
6198 (void)fIsStub2; //prevent "unused variable" error from GCC
6199 CONSISTENCY_CHECK_MSGF(*pfTransitionStub == fIsStub2, ("IsStub2 failed, DAC2:%d, IPC:%d, addr:0x%p", (int) fIsStub2, (int) *pfTransitionStub, CORDB_ADDRESS_TO_PTR(address)));
6203 EX_CATCH_HRESULT(hr);
6206 LOG((LF_CORDB, LL_INFO1000, "CP::ITS: FAILED hr=0x%x\n", hr));
6212 HRESULT CordbProcess::SetStopState(DWORD threadID, CorDebugThreadState state)
6214 PUBLIC_API_ENTRY(this);
6215 FAIL_IF_NEUTERED(this);
6219 HRESULT CordbProcess::IsOSSuspended(DWORD threadID, BOOL *pbSuspended)
6221 PUBLIC_API_ENTRY(this);
6222 // Gotta have a place for the result!
6224 return E_INVALIDARG;
6226 FAIL_IF_NEUTERED(this);
6228 #ifdef FEATURE_INTEROP_DEBUGGING
6229 RSLockHolder lockHolder(GetProcessLock());
6231 // Have we seen this thread?
6232 CordbUnmanagedThread *ut = GetUnmanagedThread(threadID);
6234 // If we have, and if we've suspended it, then say so.
6235 if (ut && ut->IsSuspended())
6237 *pbSuspended = TRUE;
6241 *pbSuspended = FALSE;
6244 // Not interop-debugging, we never OS suspend.
6245 *pbSuspended = FALSE;
6251 // This routine reads a thread context from the process being debugged, taking into account the fact that the context
6252 // record may be a different size than the one we compiled with. On systems < NT5, then OS doesn't usually allocate
6253 // space for the extended registers. However, the CONTEXT struct that we compile with does have this space.
6255 HRESULT CordbProcess::SafeReadThreadContext(LSPTR_CONTEXT pContext, DT_CONTEXT * pCtx)
6259 INTERNAL_API_ENTRY(this);
6260 FAIL_IF_NEUTERED(this);
6265 void *pRemoteContext = pContext.UnsafeGet();
6266 TargetBuffer tbFull(pRemoteContext, sizeof(DT_CONTEXT));
6268 // The context may have 2 parts:
6269 // 1. Base register, which are always present.
6270 // 2. Optional extended registers, which are only present if CONTEXT_EXTENDED_REGISTERS is set
6273 // At a minimum we have room for a whole context up to the extended registers.
6274 #if defined(DT_CONTEXT_EXTENDED_REGISTERS)
6275 ULONG32 minContextSize = offsetof(DT_CONTEXT, ExtendedRegisters);
6277 ULONG32 minContextSize = sizeof(DT_CONTEXT);
6280 // Read the minimum part.
6281 TargetBuffer tbMin = tbFull.SubBuffer(0, minContextSize);
6282 SafeReadBuffer(tbMin, (BYTE*) pCtx);
6284 #if defined(DT_CONTEXT_EXTENDED_REGISTERS)
6285 void *pCurExtReg = (void*)((UINT_PTR)pCtx + minContextSize);
6286 TargetBuffer tbExtended = tbFull.SubBuffer(minContextSize);
6288 // Now, read the extended registers if the context contains them. If the context does not have extended registers,
6289 // just set them to zero.
6290 if (SUCCEEDED(hr) && (pCtx->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS)
6292 SafeReadBuffer(tbExtended, (BYTE*) pCurExtReg);
6296 memset(pCurExtReg, 0, tbExtended.cbSize);
6301 EX_CATCH_HRESULT(hr);
6306 // This routine writes a thread context to the process being debugged, taking into account the fact that the context
6307 // record may be a different size than the one we compiled with. On systems < NT5, then OS doesn't usually allocate
6308 // space for the extended registers. However, the CONTEXT struct that we compile with does have this space.
6310 HRESULT CordbProcess::SafeWriteThreadContext(LSPTR_CONTEXT pContext, const DT_CONTEXT * pCtx)
6312 INTERNAL_API_ENTRY(this);
6313 FAIL_IF_NEUTERED(this);
6316 DWORD sizeToWrite = sizeof(DT_CONTEXT);
6318 BYTE * pRemoteContext = (BYTE*) pContext.UnsafeGet();
6319 BYTE * pCtxSource = (BYTE*) pCtx;
6322 #if defined(DT_CONTEXT_EXTENDED_REGISTERS)
6323 // If our context has extended registers, then write the whole thing. Otherwise, just write the minimum part.
6324 if ((pCtx->ContextFlags & DT_CONTEXT_EXTENDED_REGISTERS) != DT_CONTEXT_EXTENDED_REGISTERS)
6326 sizeToWrite = offsetof(DT_CONTEXT, ExtendedRegisters);
6330 // 64 bit windows puts space for the first 6 stack parameters in the CONTEXT structure so that
6331 // kernel to usermode transitions don't have to allocate a CONTEXT and do a seperate sub rsp
6332 // to allocate stack spill space for the arguments. This means that writing to P1Home - P6Home
6333 // will overwrite the arguments of some function higher on the stack, very bad. Conceptually you
6334 // can think of these members as not being part of the context, ie they don't represent something
6335 // which gets saved or restored on context switches. They are just space we shouldn't overwrite.
6336 // See issue 630276 for more details.
6337 #if defined DBG_TARGET_AMD64
6338 pRemoteContext += offsetof(CONTEXT, ContextFlags); // immediately follows the 6 parameters P1-P6
6339 pCtxSource += offsetof(CONTEXT, ContextFlags);
6340 sizeToWrite -= offsetof(CONTEXT, ContextFlags);
6345 // Write the context.
6346 TargetBuffer tb(pRemoteContext, sizeToWrite);
6347 SafeWriteBuffer(tb, (const BYTE*) pCtxSource);
6349 EX_CATCH_HRESULT(hr);
6355 HRESULT CordbProcess::GetThreadContext(DWORD threadID, ULONG32 contextSize, BYTE context[])
6357 PUBLIC_REENTRANT_API_ENTRY(this);
6358 FAIL_IF_NEUTERED(this);
6359 FAIL_IF_MANAGED_ONLY(this);
6361 DT_CONTEXT * pContext;
6362 LOG((LF_CORDB, LL_INFO10000, "CP::GTC: thread=0x%x\n", threadID));
6364 RSLockHolder lockHolder(GetProcessLock());
6366 if (contextSize != sizeof(DT_CONTEXT))
6368 LOG((LF_CORDB, LL_INFO10000, "CP::GTC: thread=0x%x, context size is invalid.\n", threadID));
6369 return E_INVALIDARG;
6372 pContext = reinterpret_cast<DT_CONTEXT *>(context);
6374 VALIDATE_POINTER_TO_OBJECT_ARRAY(context, BYTE, contextSize, true, true);
6376 #if !defined(FEATURE_INTEROP_DEBUGGING)
6379 // Find the unmanaged thread
6380 CordbUnmanagedThread *ut = GetUnmanagedThread(threadID);
6384 LOG((LF_CORDB, LL_INFO10000, "CP::GTC: thread=0x%x, thread id is invalid.\n", threadID));
6386 return E_INVALIDARG;
6389 return ut->GetThreadContext((DT_CONTEXT*)context);
6390 #endif // FEATURE_INTEROP_DEBUGGING
6393 // Public implementation of ICorDebugProcess::SetThreadContext.
6394 // @dbgtodo interop-debugging: this should go away in V3. Use the data-target instead. This is
6395 // interop-debugging aware (and cooperates with hijacks)
6396 HRESULT CordbProcess::SetThreadContext(DWORD threadID, ULONG32 contextSize, BYTE context[])
6398 PUBLIC_REENTRANT_API_ENTRY(this);
6399 FAIL_IF_MANAGED_ONLY(this);
6401 #if !defined(FEATURE_INTEROP_DEBUGGING)
6406 RSLockHolder lockHolder(GetProcessLock());
6408 CordbUnmanagedThread *ut = NULL;
6410 if (contextSize != sizeof(DT_CONTEXT))
6412 LOG((LF_CORDB, LL_INFO10000, "CP::STC: thread=0x%x, context size is invalid.\n", threadID));
6417 // @todo - could we look at the context flags and return E_INVALIDARG if they're bad?
6418 FAIL_IF_NEUTERED(this);
6419 VALIDATE_POINTER_TO_OBJECT_ARRAY(context, BYTE, contextSize, true, true);
6421 // Find the unmanaged thread
6422 ut = GetUnmanagedThread(threadID);
6426 LOG((LF_CORDB, LL_INFO10000, "CP::STC: thread=0x%x, thread is invalid.\n", threadID));
6431 hr = ut->SetThreadContext((DT_CONTEXT*)context);
6434 // Update the register set for the leaf-unmanaged chain so that it's consistent w/ the context.
6435 // We may not necessarily be synchronized, and so these frames may be stale. Even so, no harm done.
6438 // @dbgtodo stackwalk: this should all disappear with V3 stackwalker and getting rid of SetThreadContext.
6441 // Find the managed thread. Returns NULL if thread is not managed.
6442 // If we don't have a thread prveiously cached, then there's no state to update.
6443 CordbThread * pThread = TryLookupThreadByVolatileOSId(threadID);
6445 if (pThread != NULL)
6447 // In V2, we used to update the CONTEXT of the leaf chain if the chain is an unmanaged chain.
6448 // In Arrowhead, we just force a cleanup of the stackwalk cache. This is a more correct
6449 // thing to do anyway, since the CONTEXT being set could be anything.
6450 pThread->CleanupStack();
6453 EX_CATCH_HRESULT(hr);
6457 return ErrWrapper(hr);
6459 #endif // FEATURE_INTEROP_DEBUGGING
6463 // @dbgtodo ICDProcess - When we DACize this function, we should use code:DacReplacePatches
6464 HRESULT CordbProcess::ReadMemory(CORDB_ADDRESS address,
6469 PUBLIC_REENTRANT_API_ENTRY(this);
6470 FAIL_IF_NEUTERED(this);
6472 // A read of 0 bytes is okay.
6476 VALIDATE_POINTER_TO_OBJECT_ARRAY(buffer, BYTE, size, true, true);
6477 VALIDATE_POINTER_TO_OBJECT(buffer, SIZE_T *);
6479 if (address == NULL)
6480 return E_INVALIDARG;
6482 // If no read parameter is supplied, we ignore it. This matches the semantics of kernel32!ReadProcessMemory.
6492 CORDBRequireProcessStateOK(this);
6494 // Grab the memory we want to read
6495 // Note that this will return success on a partial read
6497 hr = GetDataTarget()->ReadVirtual(address, buffer, size, &cbRead);
6500 hr = CORDBG_E_READVIRTUAL_FAILURE;
6504 // Read at least one byte
6505 *read = (SIZE_T) cbRead;
6507 // There seem to be strange cases where ReadProcessMemory will return a seemingly negative number into *read, which
6508 // is an unsigned value. So we check the sanity of *read by ensuring that its no bigger than the size we tried to
6510 if ((*read > 0) && (*read <= size))
6512 LOG((LF_CORDB, LL_INFO100000, "CP::RM: read %d bytes from 0x%08x, first byte is 0x%x\n",
6513 *read, (DWORD)address, buffer[0]));
6517 RSLockHolder ch(&this->m_processMutex);
6519 // If m_pPatchTable is NULL, then it's been cleaned out b/c of a Continue for the left side. Get the table
6520 // again. Only do this, of course, if the managed state of the process is initialized.
6521 if (m_pPatchTable == NULL)
6523 hr = RefreshPatchTable(address, *read, buffer);
6527 // The previously fetched table is still good, so run through it & see if any patches are applicable
6528 hr = AdjustBuffer(address, *read, buffer, NULL, AB_READ);
6536 RSLockHolder ch(&this->m_processMutex);
6539 else if (*read < size)
6541 // Unlike the DT api, our API is supposed to return an error on partial read
6542 hr = HRESULT_FROM_WIN32(ERROR_PARTIAL_COPY);
6547 // Update patches & buffer to make the left-side's usage of patches transparent
6548 // to our client. Behavior depends on AB_MODE:
6550 // - use the RS patch table structure to replace patch opcodes in buffer.
6552 // - update the RS patch table structure w/ new replace-opcode values
6553 // if we've written over them. And put the int3 back in for write-memory.
6555 // Note: If we're writing memory over top of a patch, then it must be JITted or stub code.
6556 // Writing over JITed or Stub code can be dangerous since the CLR may not expect it
6557 // (eg. JIT data structures about the code layout may be incorrect), but in certain
6558 // narrow cases it may be safe (eg. replacing a constant). VS says they wouldn't expect
6559 // this to work, but we'll keep the support in for legacy reasons.
6561 // address, size - describe buffer in LS memory
6562 // buffer - local copy of buffer that will be read/written from/to LS.
6563 // bufferCopy - for writeprocessmemory, copy of original buffer (w/o injected patches)
6564 // pbUpdatePatchTable - flag if patchtable got dirty and needs to be updated.
6565 HRESULT CordbProcess::AdjustBuffer( CORDB_ADDRESS address,
6570 BOOL *pbUpdatePatchTable)
6572 INTERNAL_API_ENTRY(this);
6574 _ASSERTE(m_initialized);
6575 _ASSERTE(this->ThreadHoldsProcessLock());
6577 if ( address == NULL
6580 || (mode != AB_READ && mode != AB_WRITE) )
6581 return E_INVALIDARG;
6583 if (pbUpdatePatchTable != NULL )
6584 *pbUpdatePatchTable = FALSE;
6586 // If we don't have a patch table loaded, then return S_OK since there are no patches to adjust
6587 if (m_pPatchTable == NULL)
6590 //is the requested memory completely out-of-range?
6591 if ((m_minPatchAddr > (address + (size - 1))) ||
6592 (m_maxPatchAddr < address))
6597 // Without runtime offsets, we can't adjust - this should only ever happen on dumps, where there's
6598 // no W32ET to get the offsets, and so they stay zeroed
6599 if (!m_runtimeOffsetsInitialized)
6602 LOG((LF_CORDB,LL_INFO10000, "CordbProcess::AdjustBuffer at addr 0x%p\n", address));
6604 if (mode == AB_WRITE)
6606 // We don't want to mess up the original copy of the buffer, so
6607 // for right now, just copy it wholesale.
6608 (*bufferCopy) = new (nothrow) BYTE[size];
6609 if (NULL == (*bufferCopy))
6610 return E_OUTOFMEMORY;
6612 memmove((*bufferCopy), buffer, size);
6615 ULONG iNextFree = m_iFirstPatch;
6616 while( iNextFree != DPT_TERMINATING_INDEX )
6618 BYTE *DebuggerControllerPatch = m_pPatchTable + m_runtimeOffsets.m_cbPatch*iNextFree;
6619 PRD_TYPE opcode = *(PRD_TYPE *)(DebuggerControllerPatch + m_runtimeOffsets.m_offOpcode);
6620 CORDB_ADDRESS patchAddress = PTR_TO_CORDB_ADDRESS(*(BYTE**)(DebuggerControllerPatch + m_runtimeOffsets.m_offAddr));
6622 if (IsPatchInRequestedRange(address, size, patchAddress))
6624 if (mode == AB_READ)
6626 CORDbgSetInstructionEx(buffer, address, patchAddress, opcode, size);
6628 else if (mode == AB_WRITE)
6630 _ASSERTE( pbUpdatePatchTable != NULL );
6631 _ASSERTE( bufferCopy != NULL );
6633 //There can be multiple patches at the same address: we don't want 2nd+ patches to get the
6634 // break opcode, so we read from the unmodified copy.
6635 m_rgUncommitedOpcode[iNextFree] =
6636 CORDbgGetInstructionEx(*bufferCopy, address, patchAddress, opcode, size);
6638 //put the breakpoint into the memory itself
6639 CORDbgInsertBreakpointEx(buffer, address, patchAddress, opcode, size);
6641 *pbUpdatePatchTable = TRUE;
6644 _ASSERTE( !"CordbProcess::AdjustBuffergiven non(Read|Write) mode!" );
6647 iNextFree = m_rgNextPatch[iNextFree];
6650 // If we created a copy of the buffer but didn't modify it, then free it now.
6651 if( ( mode == AB_WRITE ) && ( !*pbUpdatePatchTable ) )
6653 delete [] *bufferCopy;
6661 void CordbProcess::CommitBufferAdjustments( CORDB_ADDRESS start,
6664 INTERNAL_API_ENTRY(this);
6666 _ASSERTE(m_initialized);
6667 _ASSERTE(this->ThreadHoldsProcessLock());
6668 _ASSERTE(m_runtimeOffsetsInitialized);
6670 ULONG iPatch = m_iFirstPatch;
6671 while( iPatch != DPT_TERMINATING_INDEX )
6673 BYTE *DebuggerControllerPatch = m_pPatchTable +
6674 m_runtimeOffsets.m_cbPatch*iPatch;
6676 BYTE *patchAddress = *(BYTE**)(DebuggerControllerPatch + m_runtimeOffsets.m_offAddr);
6678 if (IsPatchInRequestedRange(start, (SIZE_T)(end - start), PTR_TO_CORDB_ADDRESS(patchAddress)) &&
6679 !PRDIsBreakInst(&(m_rgUncommitedOpcode[iPatch])))
6681 //copy this back to the copy of the patch table
6682 *(PRD_TYPE *)(DebuggerControllerPatch + m_runtimeOffsets.m_offOpcode) =
6683 m_rgUncommitedOpcode[iPatch];
6686 iPatch = m_rgNextPatch[iPatch];
6690 void CordbProcess::ClearBufferAdjustments( )
6692 INTERNAL_API_ENTRY(this);
6693 _ASSERTE(this->ThreadHoldsProcessLock());
6695 ULONG iPatch = m_iFirstPatch;
6696 while( iPatch != DPT_TERMINATING_INDEX )
6698 InitializePRDToBreakInst(&(m_rgUncommitedOpcode[iPatch]));
6699 iPatch = m_rgNextPatch[iPatch];
6703 void CordbProcess::ClearPatchTable(void )
6705 INTERNAL_API_ENTRY(this);
6706 _ASSERTE(this->ThreadHoldsProcessLock());
6708 if (m_pPatchTable != NULL )
6710 delete [] m_pPatchTable;
6711 m_pPatchTable = NULL;
6713 delete [] m_rgNextPatch;
6714 m_rgNextPatch = NULL;
6716 delete [] m_rgUncommitedOpcode;
6717 m_rgUncommitedOpcode = NULL;
6719 m_iFirstPatch = DPT_TERMINATING_INDEX;
6720 m_minPatchAddr = MAX_ADDRESS;
6721 m_maxPatchAddr = MIN_ADDRESS;
6727 HRESULT CordbProcess::RefreshPatchTable(CORDB_ADDRESS address, SIZE_T size, BYTE buffer[])
6735 INTERNAL_API_ENTRY(this);
6736 _ASSERTE(m_initialized);
6737 _ASSERTE(this->ThreadHoldsProcessLock());
6742 // All of m_runtimeOffsets will be zeroed out if there's been no call to code:CordbProcess::GetRuntimeOffsets.
6743 // Thus for things to work, we'd have to have a live target that went and got the real values.
6744 // For dumps, things are still all zeroed out because we don't have any events sent to the W32ET, don't
6745 // have a live process to investigate, etc.
6746 if (!m_runtimeOffsetsInitialized)
6749 _ASSERTE( m_runtimeOffsets.m_cbOpcode == sizeof(PRD_TYPE) );
6751 CORDBRequireProcessStateOK(this);
6753 if (m_pPatchTable == NULL )
6755 // First, check to be sure the patch table is valid on the Left Side. If its not, then we won't read it.
6756 BOOL fPatchTableValid = FALSE;
6758 hr = SafeReadStruct(PTR_TO_CORDB_ADDRESS(m_runtimeOffsets.m_pPatchTableValid), &fPatchTableValid);
6759 if (FAILED(hr) || !fPatchTableValid)
6761 LOG((LF_CORDB, LL_INFO10000, "Wont refresh patch table because its not valid now.\n"));
6765 SIZE_T offStart = 0;
6767 UINT cbTableSlice = 0;
6769 // Grab the patch table info
6770 offStart = min(m_runtimeOffsets.m_offRgData, m_runtimeOffsets.m_offCData);
6771 offEnd = max(m_runtimeOffsets.m_offRgData, m_runtimeOffsets.m_offCData) + sizeof(SIZE_T);
6772 cbTableSlice = (UINT)(offEnd - offStart);
6774 if (cbTableSlice == 0)
6776 LOG((LF_CORDB, LL_INFO10000, "Wont refresh patch table because its not valid now.\n"));
6782 rgb = new BYTE[cbTableSlice]; // throws
6784 TargetBuffer tbSlice((BYTE*)m_runtimeOffsets.m_pPatches + offStart, cbTableSlice);
6785 this->SafeReadBuffer(tbSlice, rgb); // Throws;
6787 // Note that rgData is a pointer in the left side address space
6788 m_rgData = *(BYTE**)(rgb + m_runtimeOffsets.m_offRgData - offStart);
6789 m_cPatch = *(ULONG*)(rgb + m_runtimeOffsets.m_offCData - offStart);
6791 // Grab the patch table
6792 UINT cbPatchTable = (UINT)(m_cPatch * m_runtimeOffsets.m_cbPatch);
6794 if (cbPatchTable == 0)
6796 LOG((LF_CORDB, LL_INFO10000, "Wont refresh patch table because its not valid now.\n"));
6797 _ASSERTE(hr == S_OK);
6798 goto LExit; // can't return since we're in a Try/Catch
6802 m_pPatchTable = new BYTE[ cbPatchTable ];
6803 m_rgNextPatch = new ULONG[m_cPatch];
6804 m_rgUncommitedOpcode = new PRD_TYPE[m_cPatch];
6806 TargetBuffer tb(m_rgData, cbPatchTable);
6807 this->SafeReadBuffer(tb, m_pPatchTable); // Throws
6809 //As we go through the patch table we do a number of things:
6811 // 1. collect min,max address seen for quick fail check
6813 // 2. Link all valid entries into a linked list, the first entry of which is m_iFirstPatch
6815 // 3. Initialize m_rgUncommitedOpcode, so that we can undo local patch table changes if WriteMemory can't write
6818 // 4. If the patch is in the memory we grabbed, unapply it.
6820 ULONG iDebuggerControllerPatchPrev = DPT_TERMINATING_INDEX;
6822 m_minPatchAddr = MAX_ADDRESS;
6823 m_maxPatchAddr = MIN_ADDRESS;
6824 m_iFirstPatch = DPT_TERMINATING_INDEX;
6826 for (ULONG iPatch = 0; iPatch < m_cPatch;iPatch++)
6828 // <REVISIT_TODO>@todo port: we're making assumptions about the size of opcodes,address pointers, etc</REVISIT_TODO>
6829 BYTE *DebuggerControllerPatch = m_pPatchTable + m_runtimeOffsets.m_cbPatch * iPatch;
6830 PRD_TYPE opcode = *(PRD_TYPE*)(DebuggerControllerPatch + m_runtimeOffsets.m_offOpcode);
6831 CORDB_ADDRESS patchAddress = PTR_TO_CORDB_ADDRESS(*(BYTE**)(DebuggerControllerPatch + m_runtimeOffsets.m_offAddr));
6833 // A non-zero opcode indicates to us that this patch is valid.
6834 if (!PRDIsEmpty(opcode))
6836 _ASSERTE( patchAddress != 0 );
6839 // Note that GetPatchEndAddr() returns the address immediately AFTER the patch,
6840 // so we have to subtract 1 from it below.
6841 if (m_minPatchAddr > patchAddress )
6842 m_minPatchAddr = patchAddress;
6843 if (m_maxPatchAddr < patchAddress )
6844 m_maxPatchAddr = GetPatchEndAddr(patchAddress) - 1;
6847 if ( m_iFirstPatch == DPT_TERMINATING_INDEX)
6849 m_iFirstPatch = iPatch;
6850 _ASSERTE( iPatch != DPT_TERMINATING_INDEX);
6853 if (iDebuggerControllerPatchPrev != DPT_TERMINATING_INDEX)
6855 m_rgNextPatch[iDebuggerControllerPatchPrev] = iPatch;
6858 iDebuggerControllerPatchPrev = iPatch;
6861 InitializePRDToBreakInst(&(m_rgUncommitedOpcode[iPatch]));
6864 if (IsPatchInRequestedRange(address, size, patchAddress))
6866 _ASSERTE( buffer != NULL );
6867 _ASSERTE( size != NULL );
6870 //unapply the patch here.
6871 CORDbgSetInstructionEx(buffer, address, patchAddress, opcode, size);
6877 if (iDebuggerControllerPatchPrev != DPT_TERMINATING_INDEX)
6879 m_rgNextPatch[iDebuggerControllerPatchPrev] = DPT_TERMINATING_INDEX;
6884 EX_CATCH_HRESULT(hr);
6901 //---------------------------------------------------------------------------------------
6903 // Given an address, see if there is a patch in the patch table that matches it and return
6904 // if its an unmanaged patch or not.
6907 // address - The address of an instruction to check in the target address space.
6908 // pfPatchFound - Space to store the result, TRUE if the address belongs to a
6909 // patch, FALSE if not. Only valid if this method returns a success code.
6910 // pfPatchIsUnmanaged - Space to store the result, TRUE if the address is a patch
6911 // and the patch is unmanaged, FALSE if not. Only valid if this method returns a
6915 // Typical HRESULT symantics, nothing abnormal.
6917 // Note: this method is pretty in-efficient. It refreshes the patch table, then scans it.
6918 // Refreshing the patch table involves a scan, too, so this method could be folded
6921 //---------------------------------------------------------------------------------------
6922 HRESULT CordbProcess::FindPatchByAddress(CORDB_ADDRESS address, bool *pfPatchFound, bool *pfPatchIsUnmanaged)
6924 INTERNAL_API_ENTRY(this);
6925 _ASSERTE(ThreadHoldsProcessLock());
6926 _ASSERTE((pfPatchFound != NULL) && (pfPatchIsUnmanaged != NULL));
6927 _ASSERTE(m_runtimeOffsetsInitialized);
6928 FAIL_IF_NEUTERED(this);
6930 *pfPatchFound = false;
6931 *pfPatchIsUnmanaged = false;
6933 // First things first. If the process isn't initialized, then there can be no patch table, so we know the breakpoint
6934 // doesn't belong to the Runtime.
6940 // This method is called from the main loop of the win32 event thread in response to a first chance breakpoint event
6941 // that we know is not a flare. The process has been runnning, and it may have invalidated the patch table, so we'll
6942 // flush it here before refreshing it to make sure we've got the right thing.
6944 // Note: we really should have the Left Side mark the patch table dirty to help optimize this.
6947 // Refresh the patch table.
6948 HRESULT hr = RefreshPatchTable();
6952 LOG((LF_CORDB, LL_INFO1000, "CP::FPBA: failed to refresh the patch table\n"));
6956 // If there is no patch table yet, then we know there is no patch at the given address, so return S_OK with
6957 // *patchFound = false.
6958 if (m_pPatchTable == NULL)
6960 LOG((LF_CORDB, LL_INFO1000, "CP::FPBA: no patch table\n"));
6964 // Scan the patch table for a matching patch.
6965 for (ULONG iNextPatch = m_iFirstPatch; iNextPatch != DPT_TERMINATING_INDEX; iNextPatch = m_rgNextPatch[iNextPatch])
6967 BYTE *patch = m_pPatchTable + (m_runtimeOffsets.m_cbPatch * iNextPatch);
6968 BYTE *patchAddress = *(BYTE**)(patch + m_runtimeOffsets.m_offAddr);
6969 DWORD traceType = *(DWORD*)(patch + m_runtimeOffsets.m_offTraceType);
6971 if (address == PTR_TO_CORDB_ADDRESS(patchAddress))
6973 *pfPatchFound = true;
6975 if (traceType == m_runtimeOffsets.m_traceTypeUnmanaged)
6977 *pfPatchIsUnmanaged = true;
6980 HRESULT hrDac = S_OK;
6983 // We should be able to double check w/ DAC that this really is outside of the runtime.
6984 IDacDbiInterface::AddressType addrType = GetDAC()->GetAddressType(address);
6985 CONSISTENCY_CHECK_MSGF(addrType == IDacDbiInterface::kAddressUnrecognized, ("Bad address type = %d", addrType));
6987 EX_CATCH_HRESULT(hrDac);
6988 CONSISTENCY_CHECK_MSGF(SUCCEEDED(hrDac), ("DAC::GetAddressType failed, hr=0x%08x", hrDac));
6996 // If we didn't find a patch, its actually still possible that this breakpoint exception belongs to us. There are
6997 // races with very large numbers of threads entering the Runtime through the same managed function. We will have
6998 // multiple threads adding and removing ref counts to an int 3 in the code stream. Sometimes, this count will go to
6999 // zero and the int 3 will be removed, then it will come back up and the int 3 will be replaced. The in-process
7000 // logic takes pains to ensure that such cases are handled properly, therefore we need to perform the same check
7001 // here to make the correct decision. Basically, the check is to see if there is indeed an int 3 at the exception
7002 // address. If there is _not_ an int 3 there, then we've hit this race. We will lie and say a managed patch was
7003 // found to cover this case. This is tracking the logic in DebuggerController::ScanForTriggers, where we call
7005 if (*pfPatchFound == false)
7007 // Read one instruction from the faulting address...
7008 #if defined(DBG_TARGET_ARM) || defined(DBG_TARGET_ARM64)
7009 PRD_TYPE TrapCheck = 0;
7014 HRESULT hr2 = SafeReadStruct(address, &TrapCheck);
7016 if (SUCCEEDED(hr2) && (TrapCheck != CORDbg_BREAK_INSTRUCTION))
7018 LOG((LF_CORDB, LL_INFO1000, "CP::FPBA: patchFound=true based on odd missing int 3 case.\n"));
7020 *pfPatchFound = true;
7024 LOG((LF_CORDB, LL_INFO1000, "CP::FPBA: patchFound=%d, patchIsUnmanaged=%d\n", *pfPatchFound, *pfPatchIsUnmanaged));
7029 HRESULT CordbProcess::WriteMemory(CORDB_ADDRESS address, DWORD size,
7030 BYTE buffer[], SIZE_T *written)
7032 PUBLIC_REENTRANT_API_ENTRY(this);
7033 FAIL_IF_NEUTERED(this);
7034 CORDBRequireProcessStateOK(this);
7035 _ASSERTE(m_runtimeOffsetsInitialized);
7038 if (size == 0 || address == NULL)
7039 return E_INVALIDARG;
7041 VALIDATE_POINTER_TO_OBJECT_ARRAY(buffer, BYTE, size, true, true);
7042 VALIDATE_POINTER_TO_OBJECT(written, SIZE_T *);
7045 #if defined(_DEBUG) && defined(FEATURE_INTEROP_DEBUGGING)
7046 // Shouldn't be using this to write int3. Use UM BP API instead.
7047 // This is technically legal (what if the '0xcc' is data or something), so we can't fail in retail.
7048 // But we can add this debug-only check to help VS migrate to the new API.
7049 static ConfigDWORD configCheckInt3;
7050 DWORD fCheckInt3 = configCheckInt3.val(CLRConfig::INTERNAL_DbgCheckInt3);
7053 #if defined(DBG_TARGET_X86) || defined(DBG_TARGET_AMD64)
7054 if (size == 1 && buffer[0] == 0xCC)
7056 CONSISTENCY_CHECK_MSGF(false,
7057 ("You're using ICorDebugProcess::WriteMemory() to write an 'int3' (1 byte 0xCC) at address 0x%p.\n"
7058 "If you're trying to set a breakpoint, you should be using ICorDebugProcess::SetUnmanagedBreakpoint() instead.\n"
7059 "(This assert is only enabled under the COM+ knob DbgCheckInt3.)\n",
7060 CORDB_ADDRESS_TO_PTR(address)));
7062 #endif // DBG_TARGET_X86 || DBG_TARGET_AMD64
7064 // check if we're replaced an opcode.
7067 RSLockHolder ch(&this->m_processMutex);
7069 NativePatch * p = GetNativePatch(CORDB_ADDRESS_TO_PTR(address));
7072 CONSISTENCY_CHECK_MSGF(false,
7073 ("You're using ICorDebugProcess::WriteMemory() to write an 'opcode (0x%x)' at address 0x%p.\n"
7074 "There's already a native patch at that address from ICorDebugProcess::SetUnmanagedBreakpoint().\n"
7075 "If you're trying to remove the breakpoint, use ICDProcess::ClearUnmanagedBreakpoint() instead.\n"
7076 "(This assert is only enabled under the COM+ knob DbgCheckInt3.)\n",
7077 (DWORD) (buffer[0]), CORDB_ADDRESS_TO_PTR(address)));
7081 #endif // _DEBUG && FEATURE_INTEROP_DEBUGGING
7087 HRESULT hrSaved = hr; // this will hold the 'real' hresult in case of a
7088 // partially completed operation
7089 HRESULT hrPartialCopy = HRESULT_FROM_WIN32(ERROR_PARTIAL_COPY);
7091 BOOL bUpdateOriginalPatchTable = FALSE;
7092 BYTE *bufferCopy = NULL;
7094 // Only update the patch table if the managed state of the process
7098 RSLockHolder ch(&this->m_processMutex);
7100 if (m_pPatchTable == NULL )
7102 if (!SUCCEEDED( hr = RefreshPatchTable() ) )
7108 if ( !SUCCEEDED( hr = AdjustBuffer( address,
7113 &bUpdateOriginalPatchTable)))
7119 //conveniently enough, SafeWriteBuffer will throw if it can't complete the entire operation
7122 TargetBuffer tb(address, size);
7123 SafeWriteBuffer(tb, buffer); // throws
7124 *written = tb.cbSize; // DT's Write does everything or fails.
7126 EX_CATCH_HRESULT(hr);
7130 if(hr != hrPartialCopy)
7137 LOG((LF_CORDB, LL_INFO100000, "CP::WM: wrote %d bytes at 0x%08x, first byte is 0x%x\n",
7138 *written, (DWORD)address, buffer[0]));
7140 if (bUpdateOriginalPatchTable == TRUE )
7143 RSLockHolder ch(&this->m_processMutex);
7145 //don't tweak patch table for stuff that isn't written to LeftSide
7146 CommitBufferAdjustments(address, address + *written);
7149 // The only way this should be able to fail is if
7150 //someone else fiddles with the memory protections on the
7151 //left side while it's frozen
7154 TargetBuffer tb(m_rgData, (ULONG) (m_cPatch*m_runtimeOffsets.m_cbPatch));
7155 SafeWriteBuffer(tb, m_pPatchTable);
7157 EX_CATCH_HRESULT(hr);
7158 SIMPLIFYING_ASSUMPTION_SUCCEEDED(hr);
7161 // Since we may have
7162 // overwritten anything (objects, code, etc), we should mark
7163 // everything as needing to be re-cached.
7164 m_continueCounter++;
7169 RSLockHolder ch(&this->m_processMutex);
7170 ClearBufferAdjustments( );
7173 //we messed up our local copy, so get a clean copy the next time
7175 if (bUpdateOriginalPatchTable==TRUE)
7177 if (bufferCopy != NULL)
7179 memmove(buffer, bufferCopy, size);
7186 //we messed up our local copy, so get a clean copy the next time
7188 if (bUpdateOriginalPatchTable==TRUE)
7190 RSLockHolder ch(&this->m_processMutex);
7194 else if( FAILED(hrSaved) )
7202 HRESULT CordbProcess::ClearCurrentException(DWORD threadID)
7204 #ifndef FEATURE_INTEROP_DEBUGGING
7205 return E_INVALIDARG;
7207 PUBLIC_API_ENTRY(this);
7209 RSLockHolder lockHolder(GetProcessLock());
7211 // There's something wrong if you're calling this an there are no queued unmanaged events.
7212 if ((m_unmanagedEventQueue == NULL) && (m_outOfBandEventQueue == NULL))
7213 return E_INVALIDARG;
7215 // Grab the unmanaged thread object.
7216 CordbUnmanagedThread *pUThread = GetUnmanagedThread(threadID);
7218 if (pUThread == NULL)
7219 return E_INVALIDARG;
7221 LOG((LF_CORDB, LL_INFO1000, "CP::CCE: tid=0x%x\n", threadID));
7223 // We clear both the IB and OOB event.
7224 if (pUThread->HasIBEvent() && !pUThread->IBEvent()->IsEventUserContinued())
7226 pUThread->IBEvent()->SetState(CUES_ExceptionCleared);
7229 if (pUThread->HasOOBEvent())
7231 // must decide exception status _before_ we continue the event.
7232 _ASSERTE(!pUThread->OOBEvent()->IsEventContinuedUnhijacked());
7233 pUThread->OOBEvent()->SetState(CUES_ExceptionCleared);
7236 // If the thread is hijacked, then set the thread's debugger word to 0 to indicate to it that the
7237 // exception has been cleared.
7238 if (pUThread->IsGenericHijacked())
7240 HRESULT hr = pUThread->SetEEDebuggerWord(0);
7241 _ASSERTE(SUCCEEDED(hr));
7245 #endif // FEATURE_INTEROP_DEBUGGING
7248 #ifdef FEATURE_INTEROP_DEBUGGING
7249 CordbUnmanagedThread *CordbProcess::HandleUnmanagedCreateThread(DWORD dwThreadId, HANDLE hThread, void *lpThreadLocalBase)
7251 INTERNAL_API_ENTRY(this);
7252 CordbUnmanagedThread *ut = new (nothrow) CordbUnmanagedThread(this, dwThreadId, hThread, lpThreadLocalBase);
7256 HRESULT hr = m_unmanagedThreads.AddBase(ut); // InternalAddRef, release on EXIT_THREAD events.
7263 LOG((LF_CORDB, LL_INFO10000, "Failed adding unmanaged thread to process!\n"));
7264 CORDBSetUnrecoverableError(this, hr, 0);
7269 LOG((LF_CORDB, LL_INFO10000, "New CordbThread failed!\n"));
7270 CORDBSetUnrecoverableError(this, E_OUTOFMEMORY, 0);
7275 #endif // FEATURE_INTEROP_DEBUGGING
7278 //-----------------------------------------------------------------------------
7279 // Initializes the DAC
7280 // Arguments: none--initializes the DAC for this CordbProcess instance
7281 // Note: Throws on error
7282 //-----------------------------------------------------------------------------
7283 void CordbProcess::InitDac()
7285 // Go-Go DAC power!!
7291 EX_CATCH_HRESULT(hr);
7293 // We Need DAC to debug for both Managed & Interop.
7296 // We assert here b/c we're trying to be friendly. Most likely, the cause is either:
7297 // - a bad installation
7298 // - a CLR dev built mscorwks but didn't build DAC.
7299 SIMPLIFYING_ASSUMPTION_MSGF(false, ("Failed to load DAC while for debugging. hr=0x%08x", hr));
7302 } //CordbProcess::InitDac
7304 // Update the entire RS copy of the debugger control block by reading the LS copy. The RS copy is treated as
7305 // a throw-away temporary buffer, rather than a true cache. That is, we make no assumptions about the
7306 // validity of the information over time. Thus, before using any of the values, we need to update it. We
7307 // update everything for simplicity; any perf hit we take by doing this instead of updating the individual
7308 // fields we want at any given point isn't significant, particularly if we are updating multiple fields.
7311 // none, but reads process memory from the LS debugger control block
7312 // Return Value: none (copies from LS DCB to RS buffer GetDCB())
7313 // Note: throws if SafeReadBuffer fails
7314 void CordbProcess::UpdateRightSideDCB()
7316 IfFailThrow(m_pEventChannel->UpdateRightSideDCB());
7317 } // CordbProcess::UpdateRightSideDCB
7319 // Update a single field with a value stored in the RS copy of the DCB. We can't update the entire LS DCB
7320 // because in some cases, the LS and RS are simultaneously initializing the DCB. If we initialize a field on
7321 // the RS and write back the whole thing, we may overwrite something the LS has initialized in the interim.
7324 // input: rsFieldAddr - the address of the field in the RS copy of the DCB that we want to write back to
7325 // the LS DCB. We use this to compute the offset of the field from the beginning of the
7326 // DCB and then add this offset to the starting address of the LS DCB to get the LS
7327 // address of the field we are updating
7328 // size - the size of the field we're updating.
7329 // Return value: none
7330 // Note: throws if SafeWriteBuffer fails
7331 void CordbProcess::UpdateLeftSideDCBField(void * rsFieldAddr, SIZE_T size)
7333 IfFailThrow(m_pEventChannel->UpdateLeftSideDCBField(rsFieldAddr, size));
7334 } // CordbProcess::UpdateRightSideDCB
7337 //-----------------------------------------------------------------------------
7338 // Gets the remote address of the event block for the Target and verifies that it's valid.
7339 // We use this address when we need to read from or write to the debugger control block.
7340 // Also allocates the RS buffer used for temporary storage for information from the DCB and
7341 // copies the LS DCB into the RS buffer.
7343 // output: pfBlockExists - true iff the LS DCB has been successfully allocated. Note that
7344 // we need this information even if the function throws, so we can't simply send it back
7345 // as a return value.
7347 // None, but allocates GetDCB() on success. If the LS DCB has not
7348 // been successfully initialized or if this throws, GetDCB() will be NULL.
7353 //-----------------------------------------------------------------------------
7354 void CordbProcess::GetEventBlock(BOOL * pfBlockExists)
7356 if (GetDCB() == NULL) // we only need to do this once
7358 _ASSERTE(m_pShim != NULL);
7359 _ASSERTE(ThreadHoldsProcessLock());
7361 // This will Initialize the DAC/DBI interface.
7362 BOOL fDacReady = TryInitializeDac();
7366 // Ensure that we have a DAC interface.
7367 _ASSERTE(m_pDacPrimitives != NULL);
7369 // This is not technically necessary for Mac debugging. The event channel doesn't rely on
7370 // knowing the target address of the DCB on the LS.
7371 CORDB_ADDRESS pLeftSideDCB = NULL;
7372 pLeftSideDCB = (GetDAC()->GetDebuggerControlBlockAddress());
7373 if (pLeftSideDCB == NULL)
7375 *pfBlockExists = false;
7376 ThrowHR(CORDBG_E_DEBUGGING_NOT_POSSIBLE);
7379 IfFailThrow(NewEventChannelForThisPlatform(pLeftSideDCB,
7380 m_pMutableDataTarget,
7382 m_pShim->GetMachineInfo(),
7384 _ASSERTE(m_pEventChannel != NULL);
7386 // copy information from left side DCB
7387 UpdateRightSideDCB();
7389 // Verify that the control block is valid.
7390 // This will throw on error.
7391 VerifyControlBlock();
7393 *pfBlockExists = true;
7397 // we can't initialize the DAC, so we can't get the block
7398 *pfBlockExists = false;
7401 else // we got the block before
7403 *pfBlockExists = true;
7406 } // CordbProcess::GetEventBlock()
7410 // Verify that the version info in the control block matches what we expect. The minimum supported protocol from the
7411 // Left Side must be greater or equal to the minimum required protocol of the Right Side. Note: its the Left Side's job
7412 // to conform to whatever protocol the Right Side requires, so long as minimum is supported.
7414 void CordbProcess::VerifyControlBlock()
7416 INTERNAL_API_ENTRY(this);
7417 _ASSERTE(m_pShim != NULL);
7419 if (GetDCB()->m_DCBSize == 0)
7421 // the LS is still initializing the DCB
7422 ThrowHR(CORDBG_E_DEBUGGING_NOT_POSSIBLE);
7425 // Fill in the protocol numbers for the Right Side and update the LS DCB.
7426 GetDCB()->m_rightSideProtocolCurrent = CorDB_RightSideProtocolCurrent;
7427 UpdateLeftSideDCBField(&(GetDCB()->m_rightSideProtocolCurrent), sizeof(GetDCB()->m_rightSideProtocolCurrent));
7429 GetDCB()->m_rightSideProtocolMinSupported = CorDB_RightSideProtocolMinSupported;
7430 UpdateLeftSideDCBField(&(GetDCB()->m_rightSideProtocolMinSupported),
7431 sizeof(GetDCB()->m_rightSideProtocolMinSupported));
7433 // For Telesto, Dbi and Wks have a more flexible versioning allowed, as described by the Debugger
7434 // Version Protocol String in DEBUGGER_PROTOCOL_STRING in DbgIpcEvents.h. This allows different build
7435 // numbers, but the other protocol numbers should still match.
7437 // These assertions verify that the debug manager is behaving correctly.
7438 // An assertion failure here means that the runtime version of the debuggee is different from the runtime version of
7439 // the debugger is capable of debugging.
7441 // The Debug Manager should properly match LS & RS, and thus guarantee that this assert should never fire.
7442 // But just in case the installation is corrupted, we'll check it.
7443 if (GetDCB()->m_DCBSize != sizeof(DebuggerIPCControlBlock))
7445 CONSISTENCY_CHECK_MSGF(false, ("DCB in LS is %d bytes, in RS is %d bytes. Version mismatch!!\n",
7446 GetDCB()->m_DCBSize, sizeof(DebuggerIPCControlBlock)));
7447 ThrowHR(CORDBG_E_INCOMPATIBLE_PROTOCOL);
7450 // The Left Side has to support at least our minimum required protocol.
7451 if (GetDCB()->m_leftSideProtocolCurrent < GetDCB()->m_rightSideProtocolMinSupported)
7453 _ASSERTE(GetDCB()->m_leftSideProtocolCurrent >= GetDCB()->m_rightSideProtocolMinSupported);
7454 ThrowHR(CORDBG_E_INCOMPATIBLE_PROTOCOL);
7457 // The Left Side has to be able to emulate at least our minimum required protocol.
7458 if (GetDCB()->m_leftSideProtocolMinSupported > GetDCB()->m_rightSideProtocolCurrent)
7460 _ASSERTE(GetDCB()->m_leftSideProtocolMinSupported <= GetDCB()->m_rightSideProtocolCurrent);
7461 ThrowHR(CORDBG_E_INCOMPATIBLE_PROTOCOL);
7465 char buf[MAX_LONGPATH];
7466 DWORD len = GetEnvironmentVariableA("CORDBG_NotCompatibleTest", buf, sizeof(buf));
7467 _ASSERTE(len < sizeof(buf));
7470 ThrowHR(CORDBG_E_INCOMPATIBLE_PROTOCOL);
7473 if (GetDCB()->m_bHostingInFiber)
7475 ThrowHR(CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS);
7478 _ASSERTE(!GetDCB()->m_rightSideShouldCreateHelperThread);
7479 } // CordbProcess::VerifyControlBlock
7481 //-----------------------------------------------------------------------------
7482 // This is the CordbProcess objects chance to inspect the DCB and intialize stuff
7485 // Typical HRESULT return values, nothing abnormal.
7486 // If succeeded, then the block exists and is valid.
7488 //-----------------------------------------------------------------------------
7489 HRESULT CordbProcess::GetRuntimeOffsets()
7491 INTERNAL_API_ENTRY(this);
7493 _ASSERTE(m_pShim != NULL);
7494 UpdateRightSideDCB();
7496 // Can't get a handle to the helper thread if the target is remote.
7498 // If we got this far w/o failing, then we should be able to get the helper thread handle.
7499 // RS will handle not having the helper-thread handle, so we just make a best effort here.
7500 DWORD dwHelperTid = GetDCB()->m_realHelperThreadId;
7501 _ASSERTE(dwHelperTid != 0);
7505 #if !defined FEATURE_CORESYSTEM
7506 // kernel32!OpenThread does not exist on all platforms (missing on Win98).
7507 // So we need to delay load it.
7508 typedef HANDLE (WINAPI *FPOPENTHREAD)(DWORD dwDesiredAccess,
7509 BOOL bInheritHandle,
7514 HMODULE mod = WszGetModuleHandle(W("kernel32.dll"));
7516 _ASSERTE(mod != NULL); // can't fail since Kernel32.dll is already loaded.
7518 const FPOPENTHREAD pfnOpenThread = (FPOPENTHREAD)GetProcAddress(mod, "OpenThread");
7520 if (pfnOpenThread != NULL)
7522 m_hHelperThread = pfnOpenThread(SYNCHRONIZE, FALSE, dwHelperTid);
7523 CONSISTENCY_CHECK_MSGF(m_hHelperThread != NULL, ("Failed to get helper-thread handle. tid=0x%x\n", dwHelperTid));
7526 m_hHelperThread = NULL; //RS is supposed to be able to live without a helper thread handle.
7528 m_hHelperThread = OpenThread(SYNCHRONIZE, FALSE, dwHelperTid);
7529 CONSISTENCY_CHECK_MSGF(m_hHelperThread != NULL, ("Failed to get helper-thread handle. tid=0x%x\n", dwHelperTid));
7533 // get the remote address of the runtime offsets structure and read the structure itself
7534 HRESULT hrRead = SafeReadStruct(PTR_TO_CORDB_ADDRESS(GetDCB()->m_pRuntimeOffsets), &m_runtimeOffsets);
7541 LOG((LF_CORDB, LL_INFO10000, "CP::GRO: got runtime offsets: \n"));
7543 #ifdef FEATURE_INTEROP_DEBUGGING
7544 LOG((LF_CORDB, LL_INFO10000, " m_genericHijackFuncAddr= 0x%p\n",
7545 m_runtimeOffsets.m_genericHijackFuncAddr));
7546 LOG((LF_CORDB, LL_INFO10000, " m_signalHijackStartedBPAddr= 0x%p\n",
7547 m_runtimeOffsets.m_signalHijackStartedBPAddr));
7548 LOG((LF_CORDB, LL_INFO10000, " m_excepNotForRuntimeBPAddr= 0x%p\n",
7549 m_runtimeOffsets.m_excepNotForRuntimeBPAddr));
7550 LOG((LF_CORDB, LL_INFO10000, " m_notifyRSOfSyncCompleteBPAddr= 0x%p\n",
7551 m_runtimeOffsets.m_notifyRSOfSyncCompleteBPAddr));
7552 LOG((LF_CORDB, LL_INFO10000, " m_raiseException= 0x%p\n",
7553 m_runtimeOffsets.m_raiseExceptionAddr));
7554 #endif // FEATURE_INTEROP_DEBUGGING
7556 LOG((LF_CORDB, LL_INFO10000, " m_TLSIndex= 0x%08x\n",
7557 m_runtimeOffsets.m_TLSIndex));
7558 LOG((LF_CORDB, LL_INFO10000, " m_EEThreadStateOffset= 0x%08x\n",
7559 m_runtimeOffsets.m_EEThreadStateOffset));
7560 LOG((LF_CORDB, LL_INFO10000, " m_EEThreadStateNCOffset= 0x%08x\n",
7561 m_runtimeOffsets.m_EEThreadStateNCOffset));
7562 LOG((LF_CORDB, LL_INFO10000, " m_EEThreadPGCDisabledOffset= 0x%08x\n",
7563 m_runtimeOffsets.m_EEThreadPGCDisabledOffset));
7564 LOG((LF_CORDB, LL_INFO10000, " m_EEThreadPGCDisabledValue= 0x%08x\n",
7565 m_runtimeOffsets.m_EEThreadPGCDisabledValue));
7566 LOG((LF_CORDB, LL_INFO10000, " m_EEThreadDebuggerWordOffset= 0x%08x\n",
7567 m_runtimeOffsets.m_EEThreadDebuggerWordOffset));
7568 LOG((LF_CORDB, LL_INFO10000, " m_EEThreadFrameOffset= 0x%08x\n",
7569 m_runtimeOffsets.m_EEThreadFrameOffset));
7570 LOG((LF_CORDB, LL_INFO10000, " m_EEThreadMaxNeededSize= 0x%08x\n",
7571 m_runtimeOffsets.m_EEThreadMaxNeededSize));
7572 LOG((LF_CORDB, LL_INFO10000, " m_EEThreadSteppingStateMask= 0x%08x\n",
7573 m_runtimeOffsets.m_EEThreadSteppingStateMask));
7574 LOG((LF_CORDB, LL_INFO10000, " m_EEMaxFrameValue= 0x%08x\n",
7575 m_runtimeOffsets.m_EEMaxFrameValue));
7576 LOG((LF_CORDB, LL_INFO10000, " m_EEThreadDebuggerFilterContextOffset= 0x%08x\n",
7577 m_runtimeOffsets.m_EEThreadDebuggerFilterContextOffset));
7578 LOG((LF_CORDB, LL_INFO10000, " m_EEThreadCantStopOffset= 0x%08x\n",
7579 m_runtimeOffsets.m_EEThreadCantStopOffset));
7580 LOG((LF_CORDB, LL_INFO10000, " m_EEFrameNextOffset= 0x%08x\n",
7581 m_runtimeOffsets.m_EEFrameNextOffset));
7582 LOG((LF_CORDB, LL_INFO10000, " m_EEIsManagedExceptionStateMask= 0x%08x\n",
7583 m_runtimeOffsets.m_EEIsManagedExceptionStateMask));
7584 LOG((LF_CORDB, LL_INFO10000, " m_pPatches= 0x%08x\n",
7585 m_runtimeOffsets.m_pPatches));
7586 LOG((LF_CORDB, LL_INFO10000, " m_offRgData= 0x%08x\n",
7587 m_runtimeOffsets.m_offRgData));
7588 LOG((LF_CORDB, LL_INFO10000, " m_offCData= 0x%08x\n",
7589 m_runtimeOffsets.m_offCData));
7590 LOG((LF_CORDB, LL_INFO10000, " m_cbPatch= 0x%08x\n",
7591 m_runtimeOffsets.m_cbPatch));
7592 LOG((LF_CORDB, LL_INFO10000, " m_offAddr= 0x%08x\n",
7593 m_runtimeOffsets.m_offAddr));
7594 LOG((LF_CORDB, LL_INFO10000, " m_offOpcode= 0x%08x\n",
7595 m_runtimeOffsets.m_offOpcode));
7596 LOG((LF_CORDB, LL_INFO10000, " m_cbOpcode= 0x%08x\n",
7597 m_runtimeOffsets.m_cbOpcode));
7598 LOG((LF_CORDB, LL_INFO10000, " m_offTraceType= 0x%08x\n",
7599 m_runtimeOffsets.m_offTraceType));
7600 LOG((LF_CORDB, LL_INFO10000, " m_traceTypeUnmanaged= 0x%08x\n",
7601 m_runtimeOffsets.m_traceTypeUnmanaged));
7603 #ifdef FEATURE_INTEROP_DEBUGGING
7604 // Flares are only used for interop debugging.
7606 // Do check that the flares are all at unique offsets.
7607 // Since this is determined at link-time, we need a run-time check (an
7608 // assert isn't good enough, since this would only happen in a super
7609 // optimized / bbt run).
7611 const void * flares[] = {
7612 m_runtimeOffsets.m_signalHijackStartedBPAddr,
7613 m_runtimeOffsets.m_excepForRuntimeHandoffStartBPAddr,
7614 m_runtimeOffsets.m_excepForRuntimeHandoffCompleteBPAddr,
7615 m_runtimeOffsets.m_signalHijackCompleteBPAddr,
7616 m_runtimeOffsets.m_excepNotForRuntimeBPAddr,
7617 m_runtimeOffsets.m_notifyRSOfSyncCompleteBPAddr,
7620 const int NumFlares = NumItems(flares);
7622 // Ensure that all of the flares are unique.
7623 for(int i = 0; i < NumFlares; i++)
7625 for(int j = i+1; j < NumFlares; j++)
7627 if (flares[i] == flares[j])
7629 // If we ever fail here, that means the LS build is busted.
7631 // This assert is useful if we drop a checked RS onto a retail
7632 // LS (that's legal).
7633 _ASSERTE(!"LS has matching Flares.");
7634 LOG((LF_CORDB, LL_ALWAYS, "Failing because of matching flares.\n"));
7635 return CORDBG_E_INCOMPATIBLE_PROTOCOL;
7641 #endif // FEATURE_INTEROP_DEBUGGING
7642 m_runtimeOffsetsInitialized = true;
7646 #ifdef FEATURE_INTEROP_DEBUGGING
7648 //-----------------------------------------------------------------------------
7649 // Resume hijacked threads.
7650 //-----------------------------------------------------------------------------
7651 void CordbProcess::ResumeHijackedThreads()
7653 INTERNAL_API_ENTRY(this);
7654 _ASSERTE(m_pShim != NULL);
7655 _ASSERTE(ThreadHoldsProcessLock());
7657 LOG((LF_CORDB, LL_INFO10000, "CP::RHT: entered\n"));
7658 if (this->m_state & (CordbProcess::PS_SOME_THREADS_SUSPENDED | CordbProcess::PS_HIJACKS_IN_PLACE))
7660 // On XP, This will also resume the threads suspended for Sync.
7661 this->ResumeUnmanagedThreads();
7664 // Hijacks send their ownership flares and then wait on this event. By setting this
7665 // we let the hijacks run free.
7666 if (this->m_leftSideUnmanagedWaitEvent != NULL)
7668 SetEvent(this->m_leftSideUnmanagedWaitEvent);
7672 // Only reason we expect to not have this event is if the CLR hasn't been loaded yet.
7673 // In that case, we won't hijack, so nobody's listening for this event either.
7674 _ASSERTE(!m_initialized);
7678 //-----------------------------------------------------------------------------
7679 // For debugging support, record the win32 events.
7680 // Note that although this is for debugging, we want it in retail because we'll
7681 // be debugging retail most of the time :(
7682 // pEvent - the win32 debug event we just received
7683 // pUThread - our unmanaged thread object for the event. We could look it up
7684 // from pEvent->dwThreadId, but passed in for perf reasons.
7685 //-----------------------------------------------------------------------------
7686 void CordbProcess::DebugRecordWin32Event(const DEBUG_EVENT * pEvent, CordbUnmanagedThread * pUThread)
7688 _ASSERTE(ThreadHoldsProcessLock());
7690 // Although we could look up the Unmanaged thread, it's faster to have it just passed in.
7691 // So here we do a consistency check.
7692 _ASSERTE(pUThread != NULL);
7693 _ASSERTE(pUThread->m_id == pEvent->dwThreadId);
7695 m_DbgSupport.m_TotalNativeEvents++; // bump up the counter.
7697 MiniDebugEvent * pMiniEvent = &m_DbgSupport.m_DebugEventQueue[m_DbgSupport.m_DebugEventQueueIdx];
7698 pMiniEvent->code = (BYTE) pEvent->dwDebugEventCode;
7699 pMiniEvent->pUThread = pUThread;
7701 DWORD tid = pEvent->dwThreadId;
7703 // Record debug-event specific data.
7704 switch(pEvent->dwDebugEventCode)
7706 case LOAD_DLL_DEBUG_EVENT:
7707 pMiniEvent->u.ModuleData.pBaseAddress = pEvent->u.LoadDll.lpBaseOfDll;
7708 STRESS_LOG2(LF_CORDB, LL_INFO1000, "Win32 Debug Event received: tid=0x%8x, Load Dll. Addr=%p\n",
7710 pEvent->u.LoadDll.lpBaseOfDll);
7712 case UNLOAD_DLL_DEBUG_EVENT:
7713 pMiniEvent->u.ModuleData.pBaseAddress = pEvent->u.UnloadDll.lpBaseOfDll;
7714 STRESS_LOG2(LF_CORDB, LL_INFO1000, "Win32 Debug Event received: tid=0x%8x, Unload Dll. Addr=%p\n",
7716 pEvent->u.UnloadDll.lpBaseOfDll);
7718 case EXCEPTION_DEBUG_EVENT:
7719 pMiniEvent->u.ExceptionData.pAddress = pEvent->u.Exception.ExceptionRecord.ExceptionAddress;
7720 pMiniEvent->u.ExceptionData.dwCode = pEvent->u.Exception.ExceptionRecord.ExceptionCode;
7722 STRESS_LOG3(LF_CORDB, LL_INFO1000, "Win32 Debug Event received: tid=%8x, (1) Exception. Code=0x%08x, Addr=%p\n",
7724 pMiniEvent->u.ExceptionData.dwCode,
7725 pMiniEvent->u.ExceptionData.pAddress
7729 STRESS_LOG2(LF_CORDB, LL_INFO1000, "Win32 Debug Event received tid=%8x, %d\n", tid, pEvent->dwDebugEventCode);
7734 // Go to the next entry in the queue.
7735 m_DbgSupport.m_DebugEventQueueIdx = (m_DbgSupport.m_DebugEventQueueIdx + 1) % DEBUG_EVENTQUEUE_SIZE;
7738 void CordbProcess::QueueUnmanagedEvent(CordbUnmanagedThread *pUThread, const DEBUG_EVENT *pEvent)
7740 INTERNAL_API_ENTRY(this);
7741 _ASSERTE(ThreadHoldsProcessLock());
7742 _ASSERTE(m_pShim != NULL);
7744 LOG((LF_CORDB, LL_INFO10000, "CP::QUE: queued unmanaged event %d for thread 0x%x\n",
7745 pEvent->dwDebugEventCode, pUThread->m_id));
7748 _ASSERTE(pEvent->dwDebugEventCode == EXCEPTION_DEBUG_EVENT);
7750 // Copy the event into the given thread
7751 CordbUnmanagedEvent *ue;
7753 // Use the primary IB event slot unless this is the special stack overflow event case.
7754 if (!pUThread->HasSpecialStackOverflowCase())
7755 ue = pUThread->IBEvent();
7757 ue = pUThread->IBEvent2();
7759 if(pUThread->HasIBEvent() && !pUThread->HasSpecialStackOverflowCase())
7761 // Any event being replaced should at least have been continued outside of the hijack
7762 // We don't track whether or not we expect the exception to retrigger but if we are replacing
7763 // the event then it did not.
7764 _ASSERTE(ue->IsEventContinuedUnhijacked());
7765 LOG((LF_CORDB, LL_INFO10000, "CP::QUE: A previously seen event is being discarded 0x%x 0x%p\n",
7766 ue->m_currentDebugEvent.u.Exception.ExceptionRecord.ExceptionCode,
7767 ue->m_currentDebugEvent.u.Exception.ExceptionRecord.ExceptionAddress));
7768 DequeueUnmanagedEvent(ue->m_owner);
7771 memcpy(&(ue->m_currentDebugEvent), pEvent, sizeof(DEBUG_EVENT));
7772 ue->m_state = CUES_IsIBEvent;
7775 // Enqueue the event.
7776 pUThread->SetState(CUTS_HasIBEvent);
7778 if (m_unmanagedEventQueue == NULL)
7779 m_unmanagedEventQueue = ue;
7781 m_lastQueuedUnmanagedEvent->m_next = ue;
7783 m_lastQueuedUnmanagedEvent = ue;
7786 void CordbProcess::DequeueUnmanagedEvent(CordbUnmanagedThread *ut)
7788 INTERNAL_API_ENTRY(this);
7790 _ASSERTE(m_unmanagedEventQueue != NULL);
7791 _ASSERTE(ut->HasIBEvent() || ut->HasSpecialStackOverflowCase());
7792 _ASSERTE(ThreadHoldsProcessLock());
7795 CordbUnmanagedEvent *ue;
7797 if (ut->HasIBEvent())
7801 ue = ut->IBEvent2();
7803 // Since we're dequeuing the special stack overflow event, we're no longer in the special stack overflow case.
7804 ut->ClearState(CUTS_HasSpecialStackOverflowCase);
7807 DWORD ec = ue->m_currentDebugEvent.dwDebugEventCode;
7808 LOG((LF_CORDB, LL_INFO10000, "CP::DUE: dequeue unmanaged event %d for thread 0x%x\n", ec, ut->m_id));
7810 _ASSERTE(ec == EXCEPTION_DEBUG_EVENT);
7812 CordbUnmanagedEvent **tmp = &m_unmanagedEventQueue;
7813 CordbUnmanagedEvent **prev = NULL;
7815 // Note: this supports out-of-order dequeing of unmanaged events. This is necessary because we queue events even if
7816 // we're not clear on the ownership question. When we get the answer, and if the event belongs to the Runtime, we go
7817 // ahead and yank the event out of the queue, wherever it may be.
7818 while (*tmp && *tmp != ue)
7821 tmp = &((*tmp)->m_next);
7824 _ASSERTE(*tmp == ue);
7826 *tmp = (*tmp)->m_next;
7828 if (m_unmanagedEventQueue == NULL)
7829 m_lastQueuedUnmanagedEvent = NULL;
7830 else if (m_lastQueuedUnmanagedEvent == ue)
7832 _ASSERTE(prev != NULL);
7833 m_lastQueuedUnmanagedEvent = *prev;
7836 ut->ClearState(CUTS_HasIBEvent);
7840 void CordbProcess::QueueOOBUnmanagedEvent(CordbUnmanagedThread *pUThread, const DEBUG_EVENT * pEvent)
7842 INTERNAL_API_ENTRY(this);
7843 _ASSERTE(ThreadHoldsProcessLock());
7844 _ASSERTE(!pUThread->HasOOBEvent());
7845 _ASSERTE(IsWin32EventThread());
7846 _ASSERTE(m_pShim != NULL);
7848 LOG((LF_CORDB, LL_INFO10000, "CP::QUE: queued OOB unmanaged event %d for thread 0x%x\n",
7849 pEvent->dwDebugEventCode, pUThread->m_id));
7851 // Copy the event into the given thread
7852 CordbUnmanagedEvent *ue = pUThread->OOBEvent();
7853 memcpy(&(ue->m_currentDebugEvent), pEvent, sizeof(DEBUG_EVENT));
7854 ue->m_state = CUES_None;
7857 // Enqueue the event.
7858 pUThread->SetState(CUTS_HasOOBEvent);
7860 if (m_outOfBandEventQueue == NULL)
7861 m_outOfBandEventQueue = ue;
7863 m_lastQueuedOOBEvent->m_next = ue;
7865 m_lastQueuedOOBEvent = ue;
7868 void CordbProcess::DequeueOOBUnmanagedEvent(CordbUnmanagedThread *ut)
7870 INTERNAL_API_ENTRY(this);
7871 _ASSERTE(m_outOfBandEventQueue != NULL);
7872 _ASSERTE(ut->HasOOBEvent());
7873 _ASSERTE(ThreadHoldsProcessLock());
7875 CordbUnmanagedEvent *ue = ut->OOBEvent();
7876 DWORD ec = ue->m_currentDebugEvent.dwDebugEventCode;
7878 LOG((LF_CORDB, LL_INFO10000, "CP::DUE: dequeue OOB unmanaged event %d for thread 0x%x\n", ec, ut->m_id));
7880 CordbUnmanagedEvent **tmp = &m_outOfBandEventQueue;
7881 CordbUnmanagedEvent **prev = NULL;
7883 // Note: this supports out-of-order dequeing of unmanaged events. This is necessary because we queue events even if
7884 // we're not clear on the ownership question. When we get the answer, and if the event belongs to the Runtime, we go
7885 // ahead and yank the event out of the queue, wherever it may be.
7886 while (*tmp && *tmp != ue)
7889 tmp = &((*tmp)->m_next);
7892 _ASSERTE(*tmp == ue);
7894 *tmp = (*tmp)->m_next;
7896 if (m_outOfBandEventQueue == NULL)
7897 m_lastQueuedOOBEvent = NULL;
7898 else if (m_lastQueuedOOBEvent == ue)
7900 _ASSERTE(prev != NULL);
7901 m_lastQueuedOOBEvent = *prev;
7904 ut->ClearState(CUTS_HasOOBEvent);
7907 HRESULT CordbProcess::SuspendUnmanagedThreads()
7909 INTERNAL_API_ENTRY(this);
7911 _ASSERTE(ThreadHoldsProcessLock());
7913 // Iterate over all unmanaged threads...
7914 CordbUnmanagedThread* ut;
7917 for (ut = m_unmanagedThreads.FindFirst(&find); ut != NULL; ut = m_unmanagedThreads.FindNext(&find))
7920 // Don't suspend any thread in a can't stop region. This includes cooperative mode threads & preemptive
7921 // threads that haven't pushed a NativeTransitionFrame. The ultimate problem here is that a thread
7922 // in this state is effectively inside the runtime, and thus may take a lock that blocks the helper thread.
7923 // IsCan'tStop also includes the helper thread & hijacked threads - which we shouldn't suspend anyways.
7925 // Only suspend those unmanaged threads that aren't already suspended by us and that aren't already hijacked by
7928 if (!ut->IsSuspended() &&
7930 !ut->IsCantStop() &&
7931 !ut->IsBlockingForSync()
7934 LOG((LF_CORDB, LL_INFO1000, "CP::SUT: suspending unmanaged thread 0x%x, handle 0x%x\n", ut->m_id, ut->m_handle));
7936 DWORD succ = SuspendThread(ut->m_handle);
7938 if (succ == 0xFFFFFFFF)
7940 // This is okay... the thread may be dying after an ExitThread event.
7941 LOG((LF_CORDB, LL_INFO1000, "CP::SUT: failed to suspend thread 0x%x\n", ut->m_id));
7945 m_state |= PS_SOME_THREADS_SUSPENDED;
7947 ut->SetState(CUTS_Suspended);
7955 HRESULT CordbProcess::ResumeUnmanagedThreads()
7957 INTERNAL_API_ENTRY(this);
7958 _ASSERTE(ThreadHoldsProcessLock());
7959 FAIL_IF_NEUTERED(this);
7961 // Iterate over all unmanaged threads...
7962 CordbUnmanagedThread* ut;
7965 for (ut = m_unmanagedThreads.FindFirst(&find); ut != NULL; ut = m_unmanagedThreads.FindNext(&find))
7967 // Only resume those unmanaged threads that were suspended by us.
7968 if (ut->IsSuspended())
7970 LOG((LF_CORDB, LL_INFO1000, "CP::RUT: resuming unmanaged thread 0x%x\n", ut->m_id));
7972 DWORD succ = ResumeThread(ut->m_handle);
7974 if (succ == 0xFFFFFFFF)
7976 LOG((LF_CORDB, LL_INFO1000, "CP::RUT: failed to resume thread 0x%x\n", ut->m_id));
7979 ut->ClearState(CUTS_Suspended);
7983 m_state &= ~PS_SOME_THREADS_SUSPENDED;
7988 //-----------------------------------------------------------------------------
7989 // DispatchUnmanagedInBandEvent
7991 // Handler for Win32 events already known to be Unmanaged and in-band.
7992 //-----------------------------------------------------------------------------
7993 void CordbProcess::DispatchUnmanagedInBandEvent()
7995 INTERNAL_API_ENTRY(this);
7996 _ASSERTE(ThreadHoldsProcessLock());
7998 // There should be no queued OOB events!!! If there are, then we have a breakdown in our protocol, since all OOB
7999 // events should be dispatched before attempting to really continue from any in-band event.
8000 _ASSERTE(m_outOfBandEventQueue == NULL);
8001 _ASSERTE(m_cordb != NULL);
8002 _ASSERTE(m_cordb->m_unmanagedCallback != NULL);
8003 _ASSERTE(!m_dispatchingUnmanagedEvent);
8005 CordbUnmanagedThread * pUnmanagedThread = NULL;
8006 CordbUnmanagedEvent * pUnmanagedEvent = m_unmanagedEventQueue;
8010 // get the next queued event that isn't dispatched yet
8011 while(pUnmanagedEvent != NULL && pUnmanagedEvent->IsDispatched())
8013 pUnmanagedEvent = pUnmanagedEvent->m_next;
8016 if(pUnmanagedEvent == NULL)
8019 // Get the thread for this event
8020 _ASSERTE(pUnmanagedThread == NULL);
8021 pUnmanagedThread = pUnmanagedEvent->m_owner;
8022 _ASSERTE(pUnmanagedThread != NULL);
8024 // We better not have dispatched it yet!
8025 _ASSERTE(!pUnmanagedEvent->IsDispatched());
8027 // We shouldn't be dispatching IB events on a thread that has exited.
8028 // Though it's possible that the thread may exit *after* the IB event has been dispatched
8029 // if it gets hijacked.
8030 _ASSERTE(!pUnmanagedThread->IsDeleted());
8032 // Make sure we keep the thread alive while we're playing with it.
8033 pUnmanagedThread->InternalAddRef();
8035 LOG((LF_CORDB, LL_INFO10000, "CP::DUE: dispatching unmanaged event %d for thread 0x%x\n",
8036 pUnmanagedEvent->m_currentDebugEvent.dwDebugEventCode, pUnmanagedThread->m_id));
8038 m_dispatchingUnmanagedEvent = true;
8040 // Add/Remove a reference which is scoped to the time that m_lastDispatchedIBEvent
8041 // is set to pUnmanagedEvent (it is an interior pointer)
8042 // see DevDiv issue 818301 for more details
8043 if(m_lastDispatchedIBEvent != NULL)
8045 m_lastDispatchedIBEvent->m_owner->InternalRelease();
8046 m_lastDispatchedIBEvent = NULL;
8048 pUnmanagedThread->InternalAddRef();
8049 m_lastDispatchedIBEvent = pUnmanagedEvent;
8050 pUnmanagedEvent->SetState(CUES_Dispatched);
8057 // Interface is semantically const, but does not include const in signature.
8058 DEBUG_EVENT * pEvent = const_cast<DEBUG_EVENT *> (&(pUnmanagedEvent->m_currentDebugEvent));
8059 PUBLIC_WIN32_CALLBACK_IN_THIS_SCOPE(this,pEvent, FALSE);
8060 m_cordb->m_unmanagedCallback->DebugEvent(pEvent, FALSE);
8065 // Calling IMDA::Continue() will set m_dispatchingUnmanagedEvent = false.
8066 // So if Continue() was called && we have more events, we'll loop and dispatch more events.
8067 // Else we'll break out of the while loop.
8068 if(m_dispatchingUnmanagedEvent)
8071 // Continue was called in the dispatch callback, but that continue path just
8072 // clears the dispatch flag and returns. The continue right here is the logical
8073 // completion of the user's continue request
8074 // Note it is sometimes the case that these events have already been continued because
8075 // they had defered dispatching. At the time of deferal they were immediately continued.
8076 // If the event is already continued then this continue becomes a no-op.
8077 m_pShim->GetWin32EventThread()->DoDbgContinue(this, pUnmanagedEvent);
8079 // Release our reference to the unmanaged thread that we dispatched
8080 // This event should have been continued long ago...
8081 _ASSERTE(!pUnmanagedThread->IBEvent()->IsEventWaitingForContinue());
8082 pUnmanagedThread->InternalRelease();
8083 pUnmanagedThread = NULL;
8086 m_dispatchingUnmanagedEvent = false;
8088 // Release our reference to the last thread that we dispatched now...
8089 if(pUnmanagedThread)
8091 pUnmanagedThread->InternalRelease();
8092 pUnmanagedThread = NULL;
8096 //-----------------------------------------------------------------------------
8097 // DispatchUnmanagedOOBEvent
8099 // Handler for Win32 events already known to be Unmanaged and out-of-band.
8100 //-----------------------------------------------------------------------------
8101 void CordbProcess::DispatchUnmanagedOOBEvent()
8103 INTERNAL_API_ENTRY(this);
8104 _ASSERTE(ThreadHoldsProcessLock());
8105 _ASSERTE(IsWin32EventThread());
8107 // There should be OOB events queued...
8108 _ASSERTE(m_outOfBandEventQueue != NULL);
8109 _ASSERTE(m_cordb->m_unmanagedCallback != NULL);
8113 // Get the first event in the OOB Queue...
8114 CordbUnmanagedEvent * pUnmanagedEvent = m_outOfBandEventQueue;
8115 CordbUnmanagedThread * pUnmanagedThread = pUnmanagedEvent->m_owner;
8117 // Make sure we keep the thread alive while we're playing with it.
8118 RSSmartPtr<CordbUnmanagedThread> pRef(pUnmanagedThread);
8120 LOG((LF_CORDB, LL_INFO10000, "[%x] CP::DUE: dispatching OOB unmanaged event %d for thread 0x%x\n",
8121 GetCurrentThreadId(), pUnmanagedEvent->m_currentDebugEvent.dwDebugEventCode, pUnmanagedThread->m_id));
8123 m_dispatchingOOBEvent = true;
8124 pUnmanagedEvent->SetState(CUES_Dispatched);
8128 // Interface is semantically const, but does not include const in signature.
8129 DEBUG_EVENT * pEvent = const_cast<DEBUG_EVENT *> (&(pUnmanagedEvent->m_currentDebugEvent));
8130 PUBLIC_WIN32_CALLBACK_IN_THIS_SCOPE(this, pEvent, TRUE);
8131 m_cordb->m_unmanagedCallback->DebugEvent(pEvent, TRUE);
8136 // If they called Continue from the callback, then continue the OOB event right now before dispatching the next
8138 if (!m_dispatchingOOBEvent)
8140 DequeueOOBUnmanagedEvent(pUnmanagedThread);
8142 // Should not have continued from this debug event yet.
8143 _ASSERTE(pUnmanagedEvent->IsEventWaitingForContinue());
8145 // Do a little extra work if that was an OOB exception event...
8146 HRESULT hr = pUnmanagedEvent->m_owner->FixupAfterOOBException(pUnmanagedEvent);
8147 _ASSERTE(SUCCEEDED(hr));
8149 // Go ahead and continue now...
8150 this->m_pShim->GetWin32EventThread()->DoDbgContinue(this, pUnmanagedEvent);
8153 // Implicit release of pUnmanagedThread via pRef
8155 while (!m_dispatchingOOBEvent && (m_outOfBandEventQueue != NULL));
8157 m_dispatchingOOBEvent = false;
8159 LOG((LF_CORDB, LL_INFO10000, "CP::DUE: done dispatching OOB events. Queue=0x%08x\n", m_outOfBandEventQueue));
8161 #endif // FEATURE_INTEROP_DEBUGGING
8163 //-----------------------------------------------------------------------------
8164 // StartSyncFromWin32Stop
8166 // Get the process from a Fozen state or a Live state to a Synchronized State.
8167 // Note that Process Exit is considered to be synchronized.
8168 // This is a nop if we're not Interop Debugging.
8169 // If this function succeeds, we're in a synchronized state.
8172 // pfAsyncBreakSent - returns if this method sent an async-break or not.
8175 // typical HRESULT return values, nothing sinister here.
8176 //-----------------------------------------------------------------------------
8177 HRESULT CordbProcess::StartSyncFromWin32Stop(BOOL * pfAsyncBreakSent)
8179 INTERNAL_API_ENTRY(this);
8180 if (m_pShim == NULL) // This API is moved off to the shim
8187 // Caller should have taken the stop-go lock. This prevents us from racing w/ a continue.
8188 _ASSERTE(m_StopGoLock.HasLock());
8190 // Process should be init before we try to sync it.
8191 _ASSERTE(this->m_initialized);
8193 // If nobody's listening for an AsyncBreak, and we're not stopped, then our caller
8194 // doesn't know if we're sending an AsyncBreak or not; and thus we may not continue.
8195 // Failing this assert means that we're stopping but we don't think we're going to get a continue
8196 // down the road, and thus we're headed for a deadlock.
8197 _ASSERTE((pfAsyncBreakSent != NULL) || (m_stopCount > 0));
8199 if (pfAsyncBreakSent)
8201 *pfAsyncBreakSent = FALSE;
8204 #ifdef FEATURE_INTEROP_DEBUGGING
8206 // If we're win32 stopped (but not out-of-band win32 stopped), or if we're running free on the Left Side but we're
8207 // just not synchronized (and we're win32 attached), then go ahead and do an internal continue and send an async
8208 // break event to get the Left Side sync'd up.
8210 // The process can be running free as far as Win32 events are concerned, but still not synchronized as far as the
8211 // Runtime is concerned. This can happen in a lot of cases where we end up with the Runtime not sync'd but with the
8212 // process running free due to hijacking, etc...
8213 if (((m_state & CordbProcess::PS_WIN32_STOPPED) && (m_outOfBandEventQueue == NULL)) ||
8214 (!GetSynchronized() && IsInteropDebugging()))
8218 if (((m_state & CordbProcess::PS_WIN32_STOPPED) && (m_outOfBandEventQueue == NULL)) ||
8219 (!GetSynchronized() && IsInteropDebugging()))
8221 // This can't be the win32 ET b/c we need that thread to be alive and pumping win32 DE so that
8222 // our Async Break can get across.
8223 // So nobody should ever be calling this on the w32 ET. But they could, since we do trickle in from
8224 // outside APIs. So we need a retail check.
8225 if (IsWin32EventThread())
8227 _ASSERTE(!"Don't call this API on the W32 Event Thread");
8230 return ErrWrapper(CORDBG_E_CANT_CALL_ON_THIS_THREAD);
8233 STRESS_LOG1(LF_CORDB, LL_INFO1000, "[%x] CP::SSFW32S: sending internal continue\n", GetCurrentThreadId());
8235 // Can't do this on the win32 event thread.
8236 _ASSERTE(!this->IsWin32EventThread());
8238 // If the helper thread is already dead, then we just return as if we sync'd the process.
8239 if (m_helperThreadDead)
8241 if (pfAsyncBreakSent)
8243 *pfAsyncBreakSent = TRUE;
8246 // Mark the process as synchronized so no events will be dispatched until the thing is
8247 // continued. However, the marking here is not a usual marking for synchronized. It has special
8248 // semantics when we're interop debugging. We use m_oddSync to remember this so that we can take special
8249 // action in Continue().
8250 SetSynchronized(true);
8253 // Get the RC Event Thread to stop listening to the process.
8254 m_cordb->ProcessStateChanged();
8261 m_stopRequested = true;
8263 // See ::Stop for why we defer this. The delayed events will be dispatched when some one calls continue.
8264 // And we know they'll call continue b/c (stopCount > 0) || (our caller knows we're sending an AsyncBreak).
8265 m_specialDeferment = true;
8269 // If the process gets synchronized between the Unlock() and here, then SendUnmanagedContinue() will end up
8270 // not doing anything at all since a) it holds the process lock when working and b) it gates everything on
8271 // if the process is sync'd or not. This is exactly what we want.
8272 hr = this->m_pShim->GetWin32EventThread()->SendUnmanagedContinue(this, cInternalUMContinue);
8274 LOG((LF_CORDB, LL_INFO1000, "[%x] CP::SSFW32S: internal continue returned\n", GetCurrentThreadId()));
8276 // Send an async break to the left side now that its running.
8277 DebuggerIPCEvent * pEvent = (DebuggerIPCEvent *) _alloca(CorDBIPC_BUFFER_SIZE);
8278 InitIPCEvent(pEvent, DB_IPCE_ASYNC_BREAK, false, VMPTR_AppDomain::NullPtr());
8280 LOG((LF_CORDB, LL_INFO1000, "[%x] CP::SSFW32S: sending async stop\n", GetCurrentThreadId()));
8282 // If the process gets synchronized between the Unlock() and here, then this message will do nothing (Left
8283 // Side catches it) and we'll never get a response, and it won't hurt anything.
8284 hr = m_cordb->SendIPCEvent(this, pEvent, CorDBIPC_BUFFER_SIZE);
8285 // @Todo- how do we handle a failure here?
8287 // If the send returns with the helper thread being dead, then we know we don't need to wait for the process
8289 if (!m_helperThreadDead)
8291 STRESS_LOG1(LF_CORDB, LL_INFO1000, "[%x] CP::SSFW32S: sent async stop, waiting for event\n", GetCurrentThreadId());
8293 // If we got synchronized between the Unlock() and here its okay since m_stopWaitEvent is still high
8294 // from the last sync.
8295 DWORD dwWaitResult = SafeWaitForSingleObject(this, m_stopWaitEvent, INFINITE);
8297 STRESS_LOG2(LF_CORDB, LL_INFO1000, "[%x] CP::SSFW32S: got event, %d\n", GetCurrentThreadId(), dwWaitResult);
8299 _ASSERTE(dwWaitResult == WAIT_OBJECT_0);
8304 m_specialDeferment = false;
8306 if (pfAsyncBreakSent)
8308 *pfAsyncBreakSent = TRUE;
8311 // If the helper thread died while we were trying to send an event to it, then we just do the same odd sync
8312 // logic we do above.
8313 if (m_helperThreadDead)
8315 SetSynchronized(true);
8320 m_stopRequested = false;
8321 m_cordb->ProcessStateChanged();
8326 #endif // FEATURE_INTEROP_DEBUGGING
8331 // Check if the left side has exited. If so, get the right-side
8332 // into shutdown mode. Only use this to avert us from going into
8333 // an unrecoverable error.
8334 bool CordbProcess::CheckIfLSExited()
8336 // Check by waiting on the handle with no timeout.
8337 if (WaitForSingleObject(m_handle, 0) == WAIT_OBJECT_0)
8340 m_terminated = true;
8345 LOG((LF_CORDB, LL_INFO10, "CP::IsLSExited() returning '%s'\n",
8346 m_exiting ? "true" : "false"));
8351 // Call this if something really bad happened and we can't do
8352 // anything meaningful with the CordbProcess.
8353 void CordbProcess::UnrecoverableError(HRESULT errorHR,
8354 unsigned int errorCode,
8355 const char *errorFile,
8356 unsigned int errorLine)
8358 LOG((LF_CORDB, LL_INFO10, "[%x] CP::UE: unrecoverable error 0x%08x "
8360 GetCurrentThreadId(),
8361 errorHR, errorCode, errorFile, errorLine));
8363 // We definitely want to know about any of these.
8364 STRESS_LOG3(LF_CORDB, LL_EVERYTHING, "Unrecoverable Error:0x%08x, File=%s, line=%d\n", errorHR, errorFile, errorLine);
8366 // It's possible for an unrecoverable error to occur if the user detaches the
8367 // debugger while inside CordbProcess::DispatchRCEvent() (as that function deliberately
8368 // calls Unlock() while calling into the Shim). Detect such cases here & bail before we
8369 // try to access invalid fields on this CordbProcess.
8371 // Normally, we'd need to take the cordb process lock around the IsNeutered check
8372 // (and the code that follows). And perhaps this is a good thing to do in the
8373 // future. But for now we're not for two reasons:
8375 // 1) It's scary. We're in UnrecoverableError() for gosh sake. I don't know all
8376 // the possible bad states we can be in to get here. Will taking the process lock
8377 // have ordering issues? Will the process lock even be valid to take here (or might
8378 // we AV)? Since this is error handling, we should probably be as light as we can
8379 // not to cause more errors.
8381 // 2) It's unnecessary. For the Watson dump I investigated that caused this fix in
8382 // the first place, we already detached before entering UnrecoverableError()
8383 // (indeed, the only reason we're in UnrecoverableError is that we already detached
8384 // and that caused a prior API to fail). Thus, there's no timing issue (in that
8385 // case, anyway), wrt to entering UnrecoverableError() and detaching / neutering.
8390 // Ping our error trapping logic
8392 hrDummy = ErrWrapper(errorHR);
8395 if (m_pShim == NULL)
8397 // @dbgtodo - , shim: Once everything is hoisted, we can remove
8399 // In the v3 case, we should never get an unrecoverable error. Instead, the HR should be propogated
8400 // and returned at the top-level public API.
8401 _ASSERTE(!"Unrecoverable error dispatched in V3 case.");
8404 CONSISTENCY_CHECK_MSGF(IsLegalFatalError(errorHR), ("Unrecoverable internal error: hr=0x%08x!", errorHR));
8406 if (!IsLegalFatalError(errorHR) || (errorHR != CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS))
8408 // This will throw everything into a Zombie state. The ATT_ macros will check this and fail immediately.
8409 m_unrecoverableError = true;
8412 // Mark the process as no longer synchronized.
8415 SetSynchronized(false);
8420 // Set the error flags in the process so that if parts of it are
8421 // still alive, it will realize that its in this mode and do the
8423 if (GetDCB() != NULL)
8425 GetDCB()->m_errorHR = errorHR;
8426 GetDCB()->m_errorCode = errorCode;
8429 UpdateLeftSideDCBField(&(GetDCB()->m_errorHR), sizeof(GetDCB()->m_errorHR));
8430 UpdateLeftSideDCBField(&(GetDCB()->m_errorCode), sizeof(GetDCB()->m_errorCode));
8434 _ASSERTE(!"Writing process memory failed, perhaps due to an unexpected disconnection from the target.");
8436 EX_END_CATCH(SwallowAllExceptions);
8440 // Let the user know that we've hit an unrecoverable error.
8442 if (m_cordb->m_managedCallback)
8444 // We are about to send DebuggerError call back. The state of RS is undefined.
8445 // So we use the special Public Callback. We may be holding locks and stuff.
8446 // We may also be deeply nested within the RS.
8447 PUBLIC_CALLBACK_IN_THIS_SCOPE_DEBUGGERERROR(this);
8448 m_cordb->m_managedCallback->DebuggerError((ICorDebugProcess*) this,
8455 HRESULT CordbProcess::CheckForUnrecoverableError()
8459 if (GetDCB() != NULL)
8461 // be sure we have the latest information
8462 UpdateRightSideDCB();
8464 if (GetDCB()->m_errorHR != S_OK)
8466 UnrecoverableError(GetDCB()->m_errorHR,
8467 GetDCB()->m_errorCode,
8468 __FILE__, __LINE__);
8470 hr = GetDCB()->m_errorHR;
8479 * EnableLogMessages enables/disables sending of log messages to the
8480 * debugger for logging.
8482 HRESULT CordbProcess::EnableLogMessages(BOOL fOnOff)
8484 PUBLIC_API_ENTRY(this);
8485 FAIL_IF_NEUTERED(this);
8486 ATT_REQUIRE_STOPPED_MAY_FAIL(this);
8489 DebuggerIPCEvent *event = (DebuggerIPCEvent*) _alloca(CorDBIPC_BUFFER_SIZE);
8490 InitIPCEvent(event, DB_IPCE_ENABLE_LOG_MESSAGES, false, VMPTR_AppDomain::NullPtr());
8491 event->LogSwitchSettingMessage.iLevel = (int)fOnOff;
8493 hr = m_cordb->SendIPCEvent(this, event, CorDBIPC_BUFFER_SIZE);
8494 hr = WORST_HR(hr, event->hr);
8496 LOG((LF_CORDB, LL_INFO10000, "[%x] CP::EnableLogMessages: EnableLogMessages=%d sent.\n",
8497 GetCurrentThreadId(), fOnOff));
8503 * ModifyLogSwitch modifies the specified switch's severity level.
8505 COM_METHOD CordbProcess::ModifyLogSwitch(__in_z WCHAR *pLogSwitchName, LONG lLevel)
8507 PUBLIC_API_ENTRY(this);
8508 FAIL_IF_NEUTERED(this);
8509 ATT_REQUIRE_STOPPED_MAY_FAIL(this);
8513 _ASSERTE (pLogSwitchName != NULL);
8515 DebuggerIPCEvent *event = (DebuggerIPCEvent*) _alloca(CorDBIPC_BUFFER_SIZE);
8516 InitIPCEvent(event, DB_IPCE_MODIFY_LOGSWITCH, false, VMPTR_AppDomain::NullPtr());
8517 event->LogSwitchSettingMessage.iLevel = lLevel;
8518 event->LogSwitchSettingMessage.szSwitchName.SetStringTruncate(pLogSwitchName);
8520 hr = m_cordb->SendIPCEvent(this, event, CorDBIPC_BUFFER_SIZE);
8521 hr = WORST_HR(hr, event->hr);
8523 LOG((LF_CORDB, LL_INFO10000, "[%x] CP::ModifyLogSwitch: ModifyLogSwitch sent.\n",
8524 GetCurrentThreadId()));
8529 //-----------------------------------------------------------------------------
8530 // Writes a buffer from the target and performs checks similar to SafeWriteStruct
8533 // tb - TargetBuffer which represents the target memory we want to write to
8534 // pLocalBuffer - local pointer into source buffer
8535 // cbSize - the size of local buffer
8538 // On error throws the result of WriteVirtual unless a short write is performed,
8539 // in which case throws ERROR_PARTIAL_COPY
8541 void CordbProcess::SafeWriteBuffer(TargetBuffer tb,
8542 const BYTE * pLocalBuffer)
8544 _ASSERTE(m_pMutableDataTarget != NULL);
8545 HRESULT hr = m_pMutableDataTarget->WriteVirtual(tb.pAddress,
8551 //-----------------------------------------------------------------------------
8552 // Reads a buffer from the target and performs checks similar to SafeWriteStruct
8555 // tb - TargetBuffer which represents the target memory to read from
8556 // pLocalBuffer - local pointer into source buffer
8557 // cbSize - the size of the remote buffer
8558 // throwOnError - determines whether the function throws exceptions or returns HRESULTs
8562 // If throwOnError is TRUE
8563 // On error always throws the special CORDBG_E_READVIRTUAL_FAILURE, unless a short write is performed
8564 // in which case throws ERROR_PARTIAL_COPY
8565 // If throwOnError is FALSE
8566 // No exceptions are thrown, and instead the same error codes are returned as HRESULTs
8568 HRESULT CordbProcess::SafeReadBuffer(TargetBuffer tb, BYTE * pLocalBuffer, BOOL throwOnError)
8571 HRESULT hr = m_pDACDataTarget->ReadVirtual(tb.pAddress,
8579 ThrowHR(CORDBG_E_READVIRTUAL_FAILURE);
8581 return CORDBG_E_READVIRTUAL_FAILURE;
8584 if (cbRead != tb.cbSize)
8587 ThrowWin32(ERROR_PARTIAL_COPY);
8589 return HRESULT_FROM_WIN32(ERROR_PARTIAL_COPY);
8595 //---------------------------------------------------------------------------------------
8596 // Lookup or create an appdomain.
8599 // vmAppDomain - CLR appdomain to lookup
8602 // Instance of CordbAppDomain for the given appdomain. This is a cached instance.
8603 // If the CordbAppDomain does not yet exist, it will be created and added to the cache.
8604 // Never returns NULL. Throw on error.
8605 CordbAppDomain * CordbProcess::LookupOrCreateAppDomain(VMPTR_AppDomain vmAppDomain)
8607 CordbAppDomain * pAppDomain = m_appDomains.GetBase(VmPtrToCookie(vmAppDomain));
8608 if (pAppDomain != NULL)
8612 return CacheAppDomain(vmAppDomain);
8615 CordbAppDomain * CordbProcess::GetSharedAppDomain()
8617 if (m_sharedAppDomain == NULL)
8619 CordbAppDomain *pAD = new CordbAppDomain(this, VMPTR_AppDomain::NullPtr());
8620 if (InterlockedCompareExchangeT<CordbAppDomain*>(&m_sharedAppDomain, pAD, NULL) != NULL)
8624 m_sharedAppDomain->InternalAddRef();
8627 return m_sharedAppDomain;
8630 //---------------------------------------------------------------------------------------
8632 // Add a new appdomain to the cache.
8635 // vmAppDomain - appdomain to add.
8638 // Pointer to newly created appdomain, which should be the normal case.
8639 // Throws on failure. Never returns null.
8642 // Caller ensure the appdomain is not already cached.
8643 // Caller should have stop-go lock, which provides thread-safety.
8646 // This sets unrecoverable error on failure.
8648 //---------------------------------------------------------------------------------------
8649 CordbAppDomain * CordbProcess::CacheAppDomain(VMPTR_AppDomain vmAppDomain)
8651 INTERNAL_API_ENTRY(GetProcess());
8653 _ASSERTE(GetProcessLock()->HasLock());
8655 RSInitHolder<CordbAppDomain> pAppDomain;
8656 pAppDomain.Assign(new CordbAppDomain(this, vmAppDomain)); // throws
8658 // Add to the hash. This will addref the pAppDomain.
8659 // Caller ensures we're not already cached.
8660 // The cache will take ownership.
8661 m_appDomains.AddBaseOrThrow(pAppDomain);
8663 // see if this is the default AppDomain
8664 IDacDbiInterface * pDac = m_pProcess->GetDAC();
8665 BOOL fIsDefaultDomain = FALSE;
8667 fIsDefaultDomain = pDac->IsDefaultDomain(vmAppDomain); // throws
8669 if (fIsDefaultDomain)
8671 // If this assert fires, then it likely means the target is corrupted.
8672 TargetConsistencyCheck(m_pDefaultAppDomain == NULL);
8673 m_pDefaultAppDomain = pAppDomain;
8676 CordbAppDomain * pReturn = pAppDomain;
8677 pAppDomain.ClearAndMarkDontNeuter();
8679 _ASSERTE(pReturn != NULL);
8683 //---------------------------------------------------------------------------------------
8685 // Callback for Appdomain enumeration.
8688 // vmAppDomain - new appdomain to add to enumeration
8689 // pUserData - data passed with callback (a 'this' ptr for CordbProcess)
8693 // Invoked as callback from code:CordbProcess::PrepopulateAppDomains
8696 //---------------------------------------------------------------------------------------
8699 void CordbProcess::AppDomainEnumerationCallback(VMPTR_AppDomain vmAppDomain, void * pUserData)
8707 CordbProcess * pProcess = static_cast<CordbProcess *> (pUserData);
8708 INTERNAL_DAC_CALLBACK(pProcess);
8710 pProcess->LookupOrCreateAppDomain(vmAppDomain);
8713 //---------------------------------------------------------------------------------------
8715 // Traverse appdomains in the target and build up our list.
8720 // returns on success.
8721 // Throws on error. AppDomain cache may be partially populated.
8724 // This is an non-invasive inspection operation called when the debuggee is stopped.
8727 // This can be called multiple times. If the list is non-empty, it will nop.
8728 //---------------------------------------------------------------------------------------
8729 void CordbProcess::PrepopulateAppDomainsOrThrow()
8737 INTERNAL_API_ENTRY(this);
8739 if (!IsDacInitialized())
8744 // DD-primitive that invokes a callback. This may throw.
8745 GetDAC()->EnumerateAppDomains(
8746 CordbProcess::AppDomainEnumerationCallback,
8750 //---------------------------------------------------------------------------------------
8752 // EnumerateAppDomains enumerates all app domains in the process.
8755 // ppAppDomains - get appdomain enumerator
8764 // This operation is non-invasive target.
8766 //---------------------------------------------------------------------------------------
8767 HRESULT CordbProcess::EnumerateAppDomains(ICorDebugAppDomainEnum **ppAppDomains)
8770 PUBLIC_API_BEGIN(this);
8772 ValidateOrThrow(ppAppDomains);
8774 // Ensure list is populated.
8775 PrepopulateAppDomainsOrThrow();
8777 RSInitHolder<CordbHashTableEnum> pEnum;
8778 CordbHashTableEnum::BuildOrThrow(
8780 GetContinueNeuterList(),
8782 IID_ICorDebugAppDomainEnum,
8785 *ppAppDomains = static_cast<ICorDebugAppDomainEnum*> (pEnum);
8786 pEnum->ExternalAddRef();
8788 pEnum.ClearAndMarkDontNeuter();
8795 * GetObject returns the runtime process object.
8796 * Note: This method is not yet implemented.
8798 HRESULT CordbProcess::GetObject(ICorDebugValue **ppObject)
8800 PUBLIC_API_ENTRY(this);
8801 FAIL_IF_NEUTERED(this);
8802 VALIDATE_POINTER_TO_OBJECT(ppObject, ICorDebugObjectValue **);
8808 //---------------------------------------------------------------------------------------
8810 // Given a taskid, finding the corresponding thread. The function can fail if we do not
8811 // find any thread with the given taskid
8814 // taskId - The task ID to look for.
8815 // ppThread - OUT: Space for storing the thread corresponding to the taskId given.
8818 // Typical HRESULT symantics, nothing abnormal.
8820 HRESULT CordbProcess::GetThreadForTaskID(TASKID taskId, ICorDebugThread2 ** ppThread)
8822 PUBLIC_API_ENTRY(this);
8823 FAIL_IF_NEUTERED(this);
8824 ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
8830 RSLockHolder lockHolder(GetProcessLock());
8832 if (ppThread == NULL)
8834 ThrowHR(E_INVALIDARG);
8837 // On initialization, the task ID of every thread is INVALID_TASK_ID, unless a host is present and
8838 // the host calls IClrTask::SetTaskIdentifier(). So we need to explicitly check for INVALID_TASK_ID
8839 // here and return NULL if necessary. We return S_FALSE because that's the return value for the case
8840 // where we can't find a thread for the specified task ID.
8841 if (taskId == INVALID_TASK_ID)
8848 PrepopulateThreadsOrThrow();
8850 // now find the ICorDebugThread corresponding to it
8851 CordbThread * pThread;
8855 for (pThread = m_userThreads.FindFirst(&hashFind);
8857 pThread = m_userThreads.FindNext(&hashFind))
8859 if (pThread->GetTaskID() == taskId)
8865 if (pThread == NULL)
8872 *ppThread = pThread;
8873 pThread->ExternalAddRef();
8877 EX_CATCH_HRESULT(hr);
8879 } // CordbProcess::GetThreadForTaskid
8882 CordbProcess::GetVersion(COR_VERSION* pVersion)
8884 if (NULL == pVersion)
8886 return E_INVALIDARG;
8890 // Because we require a matching version of mscordbi.dll to debug a certain version of the runtime,
8891 // we can just use constants found in this particular mscordbi.dll to determine the version of the left side.
8892 pVersion->dwMajor = VER_MAJORVERSION;
8893 pVersion->dwMinor = VER_MINORVERSION;
8894 pVersion->dwBuild = VER_PRODUCTBUILD;
8895 pVersion->dwSubBuild = VER_PRODUCTBUILD_QFE;
8900 #ifdef FEATURE_INTEROP_DEBUGGING
8901 //-----------------------------------------------------------------------------
8902 // Search for a native patch given the address. Return null if not found.
8903 // Since we return an address, this is only valid until the table is disturbed.
8904 //-----------------------------------------------------------------------------
8905 NativePatch * CordbProcess::GetNativePatch(const void * pAddress)
8907 _ASSERTE(ThreadHoldsProcessLock());
8909 int cTotal = m_NativePatchList.Count();
8910 NativePatch * pTable = m_NativePatchList.Table();
8916 for(int i = 0; i < cTotal; i++)
8918 if (pTable[i].pAddress == pAddress)
8926 //-----------------------------------------------------------------------------
8927 // Is there an break-opcode (int3 on x86) at the address in the debuggee?
8928 //-----------------------------------------------------------------------------
8929 bool CordbProcess::IsBreakOpcodeAtAddress(const void * address)
8931 // There should have been an int3 there already. Since we already put it in there,
8932 // we should be able to safely read it out.
8933 BYTE opcodeTest = 0;
8935 HRESULT hr = SafeReadStruct(PTR_TO_CORDB_ADDRESS(address), &opcodeTest);
8936 SIMPLIFYING_ASSUMPTION_SUCCEEDED(hr);
8938 return (opcodeTest == CORDbg_BREAK_INSTRUCTION);
8940 #endif // FEATURE_INTEROP_DEBUGGING
8942 //-----------------------------------------------------------------------------
8943 // CordbProcess::SetUnmanagedBreakpoint
8944 // Called by a native debugger to add breakpoints during Interop.
8945 // address - remote address into the debuggee
8946 // bufsize, buffer[] - initial size & buffer for the opcode that we're replacing.
8947 // buflen - size of the buffer that we write to.
8948 //-----------------------------------------------------------------------------
8950 CordbProcess::SetUnmanagedBreakpoint(CORDB_ADDRESS address, ULONG32 bufsize, BYTE buffer[], ULONG32 * bufLen)
8952 LOG((LF_CORDB, LL_INFO100, "CP::SetUnBP: pProcess=%x, address=%p.\n", this, CORDB_ADDRESS_TO_PTR(address)));
8953 #ifndef FEATURE_INTEROP_DEBUGGING
8956 PUBLIC_API_ENTRY(this);
8957 FAIL_IF_NEUTERED(this);
8958 FAIL_IF_MANAGED_ONLY(this);
8959 _ASSERTE(!ThreadHoldsProcessLock());
8961 HRESULT hr = SetUnmanagedBreakpointInternal(address, bufsize, buffer, bufLen);
8967 //-----------------------------------------------------------------------------
8968 // CordbProcess::SetUnmanagedBreakpointInternal
8969 // The worker behind SetUnmanagedBreakpoint, this function can set both public
8970 // breakpoints used by the debugger and internal breakpoints used for utility
8971 // purposes in interop debugging.
8972 // address - remote address into the debuggee
8973 // bufsize, buffer[] - initial size & buffer for the opcode that we're replacing.
8974 // buflen - size of the buffer that we write to.
8975 //-----------------------------------------------------------------------------
8977 CordbProcess::SetUnmanagedBreakpointInternal(CORDB_ADDRESS address, ULONG32 bufsize, BYTE buffer[], ULONG32 * bufLen)
8979 LOG((LF_CORDB, LL_INFO100, "CP::SetUnBPI: pProcess=%x, address=%p.\n", this, CORDB_ADDRESS_TO_PTR(address)));
8980 #ifndef FEATURE_INTEROP_DEBUGGING
8984 INTERNAL_API_ENTRY(this);
8985 FAIL_IF_NEUTERED(this);
8986 FAIL_IF_MANAGED_ONLY(this);
8987 _ASSERTE(ThreadHoldsProcessLock());
8991 NativePatch * p = NULL;
8992 #if defined(DBG_TARGET_X86) || defined(DBG_TARGET_AMD64)
8993 const BYTE patch = CORDbg_BREAK_INSTRUCTION;
8996 // Make sure args are good
8997 if ((buffer == NULL) || (bufsize < sizeof(patch)) || (bufLen == NULL))
9003 // Fail if there's already a patch at this address.
9004 if (GetNativePatch(CORDB_ADDRESS_TO_PTR(address)) != NULL)
9006 hr = CORDBG_E_NATIVE_PATCH_ALREADY_AT_ADDR;
9010 // Preallocate this now so that if are oom, we can fail before we get half-way through.
9011 p = m_NativePatchList.Append();
9019 // Read out opcode. 1 byte on x86
9021 hr = ApplyRemotePatch(this, CORDB_ADDRESS_TO_PTR(address), &p->opcode);
9025 // It's all successful, so now update our out-params & internal bookkeaping.
9026 opcode = (BYTE) p->opcode;
9028 *bufLen = sizeof(opcode);
9030 p->pAddress = CORDB_ADDRESS_TO_PTR(address);
9033 _ASSERTE(SUCCEEDED(hr));
9034 #elif defined(DBG_TARGET_WIN64)
9035 PORTABILITY_ASSERT("NYI: CordbProcess::SetUnmanagedBreakpoint, interop debugging NYI on this platform");
9041 #endif // DBG_TARGET_X8_
9045 // If we failed, then free the patch
9046 if (FAILED(hr) && (p != NULL))
9048 m_NativePatchList.Delete(*p);
9053 #endif // FEATURE_INTEROP_DEBUGGING
9057 //-----------------------------------------------------------------------------
9058 // CordbProcess::ClearUnmanagedBreakpoint
9059 // Called by a native debugger to remove breakpoints during Interop.
9060 // The patch is deleted even if the function fails.
9061 //-----------------------------------------------------------------------------
9063 CordbProcess::ClearUnmanagedBreakpoint(CORDB_ADDRESS address)
9065 LOG((LF_CORDB, LL_INFO100, "CP::ClearUnBP: pProcess=%x, address=%p.\n", this, CORDB_ADDRESS_TO_PTR(address)));
9066 #ifndef FEATURE_INTEROP_DEBUGGING
9069 PUBLIC_API_ENTRY(this);
9070 FAIL_IF_NEUTERED(this);
9071 FAIL_IF_MANAGED_ONLY(this);
9073 _ASSERTE(!ThreadHoldsProcessLock());
9080 // Make sure this is a valid patch.
9081 int cTotal = m_NativePatchList.Count();
9082 NativePatch * pTable = m_NativePatchList.Table();
9085 hr = CORDBG_E_NO_NATIVE_PATCH_AT_ADDR;
9090 for(i = 0; i < cTotal; i++)
9092 if (pTable[i].pAddress == CORDB_ADDRESS_TO_PTR(address))
9098 hr = CORDBG_E_NO_NATIVE_PATCH_AT_ADDR;
9102 // Found it! Remove it from our table. Note that this may shuffle table contents
9103 // around, so don't keep pointers into the table.
9104 opcode = pTable[i].opcode;
9106 m_NativePatchList.Delete(pTable[i]);
9107 _ASSERTE(m_NativePatchList.Count() == cTotal - 1);
9109 // Now remove the patch.
9113 // Just call through to Write ProcessMemory
9114 hr = RemoveRemotePatch(this, CORDB_ADDRESS_TO_PTR(address), opcode);
9119 // Our internal bookeaping was already updated to remove the patch, so now we're done.
9120 // If we had a failure, we should have already bailed.
9121 _ASSERTE(SUCCEEDED(hr));
9126 #endif // FEATURE_INTEROP_DEBUGGING
9130 //------------------------------------------------------------------------------------
9131 // StopCount, Sync, SyncReceived form our stop-status. This status is super-critical
9132 // to most hangs, so we stress log it.
9133 //------------------------------------------------------------------------------------
9134 void CordbProcess::SetSynchronized(bool fSynch)
9136 _ASSERTE(ThreadHoldsProcessLock() || !"Must have process lock to toggle SyncStatus");
9137 STRESS_LOG1(LF_CORDB, LL_INFO1000, "CP:: set sync=%d\n", fSynch);
9138 m_synchronized = fSynch;
9141 bool CordbProcess::GetSynchronized()
9143 // This can be accessed whether we're Locked or not. This means that the result
9144 // may change underneath us.
9145 return m_synchronized;
9148 void CordbProcess::IncStopCount()
9150 _ASSERTE(ThreadHoldsProcessLock());
9152 STRESS_LOG1(LF_CORDB, LL_INFO1000, "CP:: Inc StopCount=%d\n", m_stopCount);
9154 void CordbProcess::DecStopCount()
9156 // We can inc w/ just the process lock (b/c we can dispatch events from the W32ET)
9157 // But decrementing (eg, Continue), requires the stop-go lock.
9158 // This if an operation takes the SG lock, it ensures we don't continue from underneath it.
9159 ASSERT_SINGLE_THREAD_ONLY(HoldsLock(&m_StopGoLock));
9160 _ASSERTE(ThreadHoldsProcessLock());
9163 STRESS_LOG1(LF_CORDB, LL_INFO1000, "CP:: Dec StopCount=%d\n", m_stopCount);
9166 // Just gets whether we're stopped or not (m_stopped > 0).
9167 // You only need the StopGo lock for this.
9168 bool CordbProcess::IsStopped()
9170 // We don't require the process-lock, just the SG-lock.
9171 // Holding the SG lock prevents another thread from continuing underneath you.
9172 // (see DecStopCount()).
9173 // But you could still be running free, and have another thread stop-underneath you.
9174 // Thus IsStopped() leans towards returning false.
9175 ASSERT_SINGLE_THREAD_ONLY(HoldsLock(&m_StopGoLock));
9177 return (m_stopCount > 0);
9180 int CordbProcess::GetStopCount()
9182 _ASSERTE(ThreadHoldsProcessLock());
9186 bool CordbProcess::GetSyncCompleteRecv()
9188 _ASSERTE(ThreadHoldsProcessLock());
9189 return m_syncCompleteReceived;
9192 void CordbProcess::SetSyncCompleteRecv(bool fSyncRecv)
9194 _ASSERTE(ThreadHoldsProcessLock());
9195 STRESS_LOG1(LF_CORDB, LL_INFO1000, "CP:: set syncRecv=%d\n", fSyncRecv);
9196 m_syncCompleteReceived = fSyncRecv;
9199 // This can be used if we ever need the RS to emulate old behavior of previous versions.
9200 // This can not be used in QIs to deny queries for new interfaces.
9201 // QIs must be consistent across the lifetime of an object. Say CordbThread used this in a QI
9202 // do deny returning a ICorDebugThread2 interface when emulating v1.1. Once that Thread is neutered,
9203 // it no longer has a pointer to the process, and it no longer knows if it should be denying
9204 // the v2.0 query. An object's QI can't start returning new interfaces onces its neutered.
9205 bool CordbProcess::SupportsVersion(CorDebugInterfaceVersion featureVersion)
9207 _ASSERTE(featureVersion == CorDebugVersion_2_0);
9212 //---------------------------------------------------------------------------------------
9213 // Add an object to the process's Left-Side resource cleanup list
9216 // pObject - non-null object to be added
9219 // This list tracks objects with process-scope that hold left-side
9220 // resources (like func-eval).
9221 // See code:CordbAppDomain::GetSweepableExitNeuterList for per-appdomain
9222 // objects with left-side resources.
9223 void CordbProcess::AddToLeftSideResourceCleanupList(CordbBase * pObject)
9225 INTERNAL_API_ENTRY(this);
9226 _ASSERTE(pObject != NULL);
9228 m_LeftSideResourceCleanupList.Add(this, pObject);
9231 // This list will get actively swept (looking for objects w/ external ref = 0) between continues.
9232 void CordbProcess::AddToNeuterOnExitList(CordbBase *pObject)
9234 INTERNAL_API_ENTRY(this);
9235 _ASSERTE(pObject != NULL);
9240 this->m_ExitNeuterList.Add(this, pObject);
9242 EX_CATCH_HRESULT(hr);
9243 SetUnrecoverableIfFailed(GetProcess(), hr);
9246 // Mark that this object should be neutered the next time we Continue the process.
9247 void CordbProcess::AddToNeuterOnContinueList(CordbBase *pObject)
9249 INTERNAL_API_ENTRY(this);
9250 _ASSERTE(pObject != NULL);
9252 m_ContinueNeuterList.Add(this, pObject); // throws
9256 /* ------------------------------------------------------------------------- *
9257 * Runtime Controller Event Thread class
9258 * ------------------------------------------------------------------------- */
9263 CordbRCEventThread::CordbRCEventThread(Cordb* cordb)
9265 _ASSERTE(cordb != NULL);
9267 m_cordb.Assign(cordb);
9271 m_threadControlEvent = NULL;
9272 m_processStateChanged = FALSE;
9274 g_pRSDebuggingInfo->m_RCET = this;
9279 // Destructor. Cleans up all of the open handles and such.
9280 // This expects that the thread has been stopped and has terminated
9281 // before being called.
9283 CordbRCEventThread::~CordbRCEventThread()
9285 if (m_threadControlEvent != NULL)
9286 CloseHandle(m_threadControlEvent);
9288 if (m_thread != NULL)
9289 CloseHandle(m_thread);
9291 g_pRSDebuggingInfo->m_RCET = NULL;
9295 // Init sets up all the objects that the thread will need to run.
9297 HRESULT CordbRCEventThread::Init()
9299 if (m_cordb == NULL)
9300 return E_INVALIDARG;
9302 m_threadControlEvent = WszCreateEvent(NULL, FALSE, FALSE, NULL);
9304 if (m_threadControlEvent == NULL)
9305 return HRESULT_FROM_GetLastError();
9311 #if defined(FEATURE_INTEROP_DEBUGGING)
9313 // Helper to duplicate a handle or thorw
9316 // pLocalHandle - handle to duplicate into the remote process
9317 // pRemoteHandle - RemoteHandle structure in IPC block to hold the remote handle.
9319 // None. Throws on error.
9321 void CordbProcess::DuplicateHandleToLocalProcess(HANDLE * pLocalHandle, RemoteHANDLE * pRemoteHandle)
9323 _ASSERTE(m_pShim != NULL);
9325 // Dup RSEA and RSER into this process if we don't already have them.
9326 // On Launch, we don't have them yet, but on attach we do.
9327 if (*pLocalHandle == NULL)
9329 BOOL fSuccess = pRemoteHandle->DuplicateToLocalProcess(m_handle, pLocalHandle);
9337 #endif // FEATURE_INTEROP_DEBUGGING
9339 // Public entry wrapper for code:CordbProcess::FinishInitializeIPCChannelWorker
9340 void CordbProcess::FinishInitializeIPCChannel()
9342 // This is called directly from a shim callback.
9343 PUBLIC_API_ENTRY_FOR_SHIM(this);
9344 FinishInitializeIPCChannelWorker();
9348 // Initialize the IPC channel. After this, IPC events can flow in both ways.
9351 // Returns S_OK on success.
9354 // This will dispatch an UnrecoverableError callback if it fails.
9355 // This will also initialize key state in the CordbProcess object.
9357 // @dbgtodo remove helper-thread: this should eventually go away once we get rid of IPC events.
9359 void CordbProcess::FinishInitializeIPCChannelWorker()
9368 _ASSERTE(m_pShim != NULL);
9370 RSLockHolder lockHolder(&this->m_processMutex);
9372 // If it's already initialized, then nothing left to do.
9373 // this protects us if this function is called multiple times.
9376 _ASSERTE(GetDCB() != NULL);
9382 LOG((LF_CORDB, LL_INFO1000, "[%x] RCET::HFRCE: first event..., process %p\n", GetCurrentThreadId(), this));
9385 GetEventBlock(&fBlockExists); // throws on error
9387 LOG((LF_CORDB, LL_EVERYTHING, "Size of CdbP is %d\n", sizeof(CordbProcess)));
9389 m_pEventChannel->Init(m_handle);
9391 #if defined(FEATURE_INTEROP_DEBUGGING)
9392 DuplicateHandleToLocalProcess(&m_leftSideUnmanagedWaitEvent, &GetDCB()->m_leftSideUnmanagedWaitEvent);
9393 #endif // FEATURE_INTEROP_DEBUGGING
9395 // Read the Runtime Offsets struct out of the debuggee.
9396 hr = GetRuntimeOffsets();
9399 // we need to be careful here. The LS will have a thread running free that may be initializing
9400 // fields of the DCB (specifically it may be setting up the helper thread), so we need to make sure
9401 // we don't overwrite any fields that the LS is writing. We need to be sure we only write to RS
9403 m_initialized = true;
9404 GetDCB()->m_rightSideIsWin32Debugger = IsInteropDebugging();
9405 UpdateLeftSideDCBField(&(GetDCB()->m_rightSideIsWin32Debugger), sizeof(GetDCB()->m_rightSideIsWin32Debugger));
9407 LOG((LF_CORDB, LL_INFO1000, "[%x] RCET::HFRCE: ...went fine\n", GetCurrentThreadId()));
9408 _ASSERTE(SUCCEEDED(hr));
9410 } EX_CATCH_HRESULT(hr);
9416 // We only land here on failure cases.
9417 // We must have jumped to this label. Maybe we didn't set HR, so check now.
9418 STRESS_LOG1(LF_CORDB, LL_INFO1000, "HFCR: FAILED hr=0x%08x\n", hr);
9427 //---------------------------------------------------------------------------------------
9428 // Marshals over a string buffer in a managed event
9431 // pTarget - data-target for read the buffer from the LeftSide.
9434 void Ls_Rs_BaseBuffer::CopyLSDataToRSWorker(ICorDebugDataTarget * pTarget)
9437 const DWORD cbCacheSize = m_cbSize;
9439 // SHOULD not happen for more than once in well-behaved case.
9442 SIMPLIFYING_ASSUMPTION(!"m_pbRS is non-null; is this a corrupted event?");
9443 ThrowHR(E_INVALIDARG);
9446 NewHolder<BYTE> pData(new BYTE[cbCacheSize]);
9449 HRESULT hrRead = pTarget->ReadVirtual(PTR_TO_CORDB_ADDRESS(m_pbLS), pData, cbCacheSize , &cbRead);
9453 hrRead = CORDBG_E_READVIRTUAL_FAILURE;
9456 if (SUCCEEDED(hrRead) && (cbCacheSize != cbRead))
9458 hrRead = HRESULT_FROM_WIN32(ERROR_PARTIAL_COPY);
9460 IfFailThrow(hrRead);
9464 pData.SuppressRelease();
9467 //---------------------------------------------------------------------------------------
9468 // Marshals over a Byte buffer in a managed event
9471 // pTarget - data-target for read the buffer from the LeftSide.
9474 void Ls_Rs_ByteBuffer::CopyLSDataToRS(ICorDebugDataTarget * pTarget)
9476 CopyLSDataToRSWorker(pTarget);
9479 //---------------------------------------------------------------------------------------
9480 // Marshals over a string buffer in a managed event
9483 // pTarget - data-target for read the buffer from the LeftSide.
9486 void Ls_Rs_StringBuffer::CopyLSDataToRS(ICorDebugDataTarget * pTarget)
9488 CopyLSDataToRSWorker(pTarget);
9490 // Ensure we're a valid, well-formed string.
9491 // @dbgtodo - this should only happen in corrupted scenarios. Perhaps a better HR here?
9492 // - null terminated.
9493 // - no embedded nulls.
9495 const WCHAR * pString = GetString();
9496 SIZE_T dwExpectedLenWithNull = m_cbSize / sizeof(WCHAR);
9498 // Should at least have 1 character for the null-terminator.
9499 if (dwExpectedLenWithNull == 0)
9501 ThrowHR(CORDBG_E_TARGET_INCONSISTENT);
9504 // Ensure that there's a null where we expect it to be.
9505 if (pString[dwExpectedLenWithNull-1] != 0)
9507 ThrowHR(CORDBG_E_TARGET_INCONSISTENT);
9510 // Now we know it's safe to call wcslen. The buffer is local, so we know the pages are there.
9511 // And we know there's a null capping the max length of the string.
9512 SIZE_T dwActualLenWithNull = wcslen(pString) + 1;
9513 if (dwActualLenWithNull != dwExpectedLenWithNull)
9515 ThrowHR(CORDBG_E_TARGET_INCONSISTENT);
9519 //---------------------------------------------------------------------------------------
9520 // Marshals the arguments in a managed-debug event.
9523 // pManagedEvent - (IN/OUT) debug event to marshal. Events are not usable in the host process
9524 // until they are marshalled. This will marshal the event in-place, and may convert
9525 // some target addresses to host addresses.
9528 // S_OK on success. Else Error.
9531 // Target is currently stopped and inspectable.
9532 // After the event is marshalled, it has resources that must be cleaned up
9533 // by calling code:DeleteIPCEventHelper.
9536 // Call a Copy function (CopyManagedEventFromTarget, CopyRCEventFromIPCBlock)to
9537 // get the event to marshal.
9538 // This will marshal args from the target into the host.
9539 // The debug event is fixed size. But since the debuggee is stopped, this can copy
9540 // arbitrary-length buffers out of of the debuggee.
9542 // This could be rolled into code:CordbProcess::RawDispatchEvent
9543 //---------------------------------------------------------------------------------------
9544 void CordbProcess::MarshalManagedEvent(DebuggerIPCEvent * pManagedEvent)
9550 // Event has already been copied, now we do some quick Marshalling.
9551 // Thsi should be a private local copy, and not the one in the IPC block or Target.
9552 PRECONDITION(CheckPointer(pManagedEvent));
9556 IfFailThrow(pManagedEvent->hr);
9558 // This may throw part way through marshalling. But that's ok because
9559 // code:DeleteIPCEventHelper can cleanup a partially-marshalled event.
9561 // Do a pre-processing on the event
9562 switch (pManagedEvent->type & DB_IPCE_TYPE_MASK)
9564 case DB_IPCE_MDA_NOTIFICATION:
9566 pManagedEvent->MDANotification.szName.CopyLSDataToRS(this->m_pDACDataTarget);
9567 pManagedEvent->MDANotification.szDescription.CopyLSDataToRS(this->m_pDACDataTarget);
9568 pManagedEvent->MDANotification.szXml.CopyLSDataToRS(this->m_pDACDataTarget);
9572 case DB_IPCE_FIRST_LOG_MESSAGE:
9574 pManagedEvent->FirstLogMessage.szContent.CopyLSDataToRS(this->m_pDACDataTarget);
9586 //---------------------------------------------------------------------------------------
9587 // Copy a managed debug event from the target process into this local process
9590 // pRecord - native-debug event serving as the envelope for the managed event.
9591 // pLocalManagedEvent - (dst) required local buffer to hold managed event.
9594 // * True if the event belongs to this runtime. This is very useful when multiple CLRs are
9595 // loaded into the target and all sending events wit the same exception code.
9596 // * False if this does not belong to this instance of ICorDebug. (perhaps it's an event
9597 // intended for another instance of the CLR in the target, or some rogue user code happening
9598 // to use our exception code).
9599 // In either case, the event can still be cleaned up via code:DeleteIPCEventHelper.
9601 // Throws on error. In the error case, the contents of pLocalManagedEvent are undefined.
9602 // They may have been partially copied from the target. The local managed event does not own
9603 // any resources until it's marshalled, so the buffer can be ignored if this function fails.
9608 // The events are sent form the target via code:Debugger::SendRawEvent
9609 // This just does a raw Byte copy, but does not do any Marshalling.
9610 // This should always succeed in the well-behaved case. However, A bad debuggee can
9611 // always send a poor-formed debug event.
9612 // We don't distinguish between a badly formed event and an event that's not ours.
9613 // The event still needs to be Marshaled before being used. (see code:CordbProcess::MarshalManagedEvent)
9615 //---------------------------------------------------------------------------------------
9616 #if defined(_MSC_VER) && defined(_TARGET_ARM_)
9617 // This is a temporary workaround for an ARM specific MS C++ compiler bug (internal LKG build 18.1).
9618 // Branch < if (ptrRemoteManagedEvent == NULL) > was always taken and the function always returned false.
9619 // TODO: It should be removed once the bug is fixed.
9620 #pragma optimize("", off)
9622 bool CordbProcess::CopyManagedEventFromTarget(
9623 const EXCEPTION_RECORD * pRecord,
9624 DebuggerIPCEvent * pLocalManagedEvent)
9626 _ASSERTE(pRecord != NULL);
9627 _ASSERTE(pLocalManagedEvent != NULL);
9629 // Initialize the event enough such backout code can call code:DeleteIPCEventHelper.
9630 pLocalManagedEvent->type = DB_IPCE_DEBUGGER_INVALID;
9632 // Ensure we have a CLR instance ID by now. Either we had one already, or we're in
9633 // V2 mode and this is the startup event, and so we'll set it now.
9634 HRESULT hr = EnsureClrInstanceIdSet();
9636 _ASSERTE(m_clrInstanceId != 0);
9638 // Determine if the event is really a debug event, and for our instance.
9639 CORDB_ADDRESS ptrRemoteManagedEvent = IsEventDebuggerNotification(pRecord, m_clrInstanceId);
9641 if (ptrRemoteManagedEvent == NULL)
9646 // What we are doing on Windows here is dangerous. Any buffer for IPC events must be at least
9647 // CorDBIPC_BUFFER_SIZE big, but here we are only copying sizeof(DebuggerIPCEvent). Fortunately, the
9648 // only case where an IPC event is bigger than sizeof(DebuggerIPCEvent) is for the second category
9649 // described in the comment for code:IEventChannel. In this case, we are just transferring the IPC
9650 // event from the native pipeline to the event channel, and the event channel will read it directly from
9651 // the send buffer on the LS. See code:CordbRCEventThread::WaitForIPCEventFromProcess.
9652 #if !defined(FEATURE_DBGIPC_TRANSPORT_DI)
9653 hr = SafeReadStruct(ptrRemoteManagedEvent, pLocalManagedEvent);
9655 // For Mac remote debugging the address returned above is actually a local address.
9656 // Also, we need to copy the entire buffer because once a debug event is read from the debugger
9657 // transport, it won't be available afterwards.
9658 memcpy(reinterpret_cast<BYTE *>(pLocalManagedEvent),
9659 CORDB_ADDRESS_TO_PTR(ptrRemoteManagedEvent),
9660 CorDBIPC_BUFFER_SIZE);
9663 SIMPLIFYING_ASSUMPTION(SUCCEEDED(hr));
9668 #if defined(_MSC_VER) && defined(_TARGET_ARM_)
9669 #pragma optimize("", on)
9672 //---------------------------------------------------------------------------------------
9673 // EnsureClrInstanceIdSet - Ensure we have a CLR Instance ID to debug
9675 // In Arrowhead scenarios, the debugger is required to pass a valid CLR instance ID
9676 // to us in OpenVirtualProcess. In V2 scenarios, for compatibility, we'll allow a
9677 // CordbProcess object to exist for a process that doesn't yet have the CLR loaded.
9678 // In this case the CLR instance ID will start off as 0, but be filled in when we see the
9679 // startup exception indicating the CLR has been loaded.
9681 // If we don't already have an instance ID, this function sets it to the only CLR in the
9682 // target process. This requires that a CLR be loaded in the target process.
9685 // S_OK - if m_clrInstanceId was already set, or is now set to a valid CLR instance ID
9686 // an error HRESULT - if m_clrInstanceId was 0, and cannot be set to a valid value
9687 // (i.e. because we cannot find a CLR in the target process).
9689 // Note that we need to probe for this on attach, and it's common to attach before the
9690 // CLR has been loaded, so we avoid using exceptions for this common case.
9692 HRESULT CordbProcess::EnsureClrInstanceIdSet()
9694 // If we didn't expect a specific CLR, then attempt to attach to any.
9695 if (m_clrInstanceId == 0)
9698 #ifdef FEATURE_CORESYSTEM
9699 if(m_cordb->GetTargetCLR() != 0)
9701 m_clrInstanceId = PTR_TO_CORDB_ADDRESS(m_cordb->GetTargetCLR());
9706 // The only case in which we're allowed to request the "default" CLR instance
9707 // ID is when we're running in V2 mode. In V3, the client is required to pass
9708 // a non-zero value to OpenVirtualProcess.
9709 _ASSERTE(m_pShim != NULL);
9711 HRESULT hr = m_pShim->FindLoadedCLR(&m_clrInstanceId);
9714 // Couldn't find a loaded clr - no CLR instance ID yet
9715 _ASSERTE(m_clrInstanceId == 0);
9720 // We've (now) got a valid CLR instance id
9724 //---------------------------------------------------------------------------------------
9725 // // Copy event from IPC block into local.
9728 // pLocalManagedEvent - required local buffer to hold managed event.
9731 // None. Always succeeds.
9734 // The IPC block has already been opened and filled in with an event.
9737 // This is copying from a shared-memory block, which is treated as local memory.
9738 // This just does a raw Byte copy, but does not do any Marshalling.
9739 // This does no validation on the event.
9740 // The event still needs to be Marshaled before being used. (see code:CordbProcess::MarshalManagedEvent)
9742 //---------------------------------------------------------------------------------------
9743 void inline CordbProcess::CopyRCEventFromIPCBlock(DebuggerIPCEvent * pLocalManagedEvent)
9745 _ASSERTE(pLocalManagedEvent != NULL);
9747 IfFailThrow(m_pEventChannel->GetEventFromLeftSide(pLocalManagedEvent));
9750 // Return true if this is the RCEvent thread, else false.
9751 bool CordbRCEventThread::IsRCEventThread()
9753 return (m_threadId == GetCurrentThreadId());
9756 //---------------------------------------------------------------------------------------
9757 // Runtime assert, throws CORDBG_E_TARGET_INCONSISTENT if the expression is not true.
9760 // fExpression - assert parameter. If true, this function is a nop. If false,
9761 // this will throw a CORDBG_E_TARGET_INCONSISTENT error.
9764 // Use this for runtime checks to validate assumptions about the data-target.
9765 // IcorDebug can't trust that data from the debugee is consistent (perhaps it's
9767 void CordbProcess::TargetConsistencyCheck(bool fExpression)
9771 STRESS_LOG0(LF_CORDB, LL_INFO10000, "Target consistency check failed");
9773 // When debugging possibly corrupt targets, this failure may be expected. For debugging purposes,
9774 // assert if we're not expecting any target inconsistencies.
9775 CONSISTENCY_CHECK_MSG( !m_fAssertOnTargetInconsistency, "Target consistency check failed unexpectedly");
9777 ThrowHR(CORDBG_E_TARGET_INCONSISTENT);
9782 // SendIPCEvent -- send an IPC event to the runtime controller. All this
9783 // really does is copy the event into the process's send buffer and sets
9784 // the RSEA then waits on RSER.
9786 // Note: when sending a two-way event (replyRequired = true), the
9787 // eventSize must be large enough for both the event sent and the
9790 // Returns whether the event was sent successfully. This is different than event->eventHr.
9792 HRESULT CordbRCEventThread::SendIPCEvent(CordbProcess* process,
9793 DebuggerIPCEvent* event,
9797 _ASSERTE(process != NULL);
9798 _ASSERTE(event != NULL);
9799 _ASSERTE(process->GetShim() != NULL);
9802 // We need to be synchronized whenever we're sending an IPC Event.
9803 // This may require our callers' using a Stop-Continue holder.
9804 // Attach + AsyncBreak are the only (obvious) exceptions.
9805 // For continue, we set Sync-Status to false before sending, so we exclude that too.
9806 // Everybody else should only be sending events when synced. We should never ever ever
9807 // send an event from a CorbXYZ dtor (b/c that would be called at any random time). Instead,
9808 // use a NeuterList.
9809 switch (event->type)
9811 case DB_IPCE_ATTACHING:
9812 case DB_IPCE_ASYNC_BREAK:
9813 case DB_IPCE_CONTINUE:
9817 CONSISTENCY_CHECK_MSGF(process->GetSynchronized(), ("Must by synced while sending IPC event: %s (0x%x)",
9818 IPCENames::GetName(event->type), event->type));
9823 LOG((LF_CORDB, LL_EVERYTHING, "SendIPCEvent in CordbRCEventThread called\n"));
9825 // For simplicity sake, we have the following conservative invariants when sending IPC events:
9826 // - Always hold the Stop-Go lock.
9827 // - never on the W32ET.
9828 // - Never hold the Process-lock (this allows the w32et to take that lock to pump)
9830 // Must have the stop-go lock to send an IPC event.
9831 CONSISTENCY_CHECK_MSGF(process->GetStopGoLock()->HasLock(), ("Must have stop-go lock to send event. proc=%p, event=%s",
9832 process, IPCENames::GetName(event->type)));
9834 // The w32 ET will need to take the process lock. So if we're holding it here, then we'll
9835 // deadlock (since W32 ET is blocked on lock, which we would hold; and we're blocked on W32 ET
9837 _ASSERTE(!process->ThreadHoldsProcessLock() || !"Can't hold P-lock while sending blocking IPC event");
9840 // Can't be on the w32 ET, or we can't be pumping.
9841 // Although we can trickle in here from public APIs, our caller should have validated
9842 // that we weren't on the w32et, so the assert here is justified. But just in case there's something we missed,
9843 // we have a runtime check (as a final backstop against a deadlock).
9844 _ASSERTE(!process->IsWin32EventThread());
9845 CORDBFailIfOnWin32EventThread(process);
9848 // If this is an async event, then we expect it to be sent while the process is locked.
9849 if (event->asyncSend)
9851 // This may be on the w32et, so we can't hold the stop-go lock.
9852 _ASSERTE(event->type == DB_IPCE_ATTACHING); // only async event should be attaching.
9856 // This will catch us if we've detached or exited.
9857 // Note if we exited, then we should have been neutered and so shouldn't even be sending an IPC event,
9858 // but just in case, we'll check.
9859 CORDBRequireProcessStateOK(process);
9863 // We should never send an Async Break on the RCET. This will deadlock.
9864 // - if we're on the RCET, we should be stopped, and thus Stop() should just bump up a stop count,
9865 // and not actually send an AsyncBreak.
9866 // - Delayed-Continues help enforce this.
9867 // This is a special case of the deadlock check below.
9868 if (IsRCEventThread())
9870 _ASSERTE(event->type != DB_IPCE_ASYNC_BREAK);
9875 // This assert protects us against a deadlock.
9876 // 1) (RCET) blocked on (This function): If we're on the RCET, then the RCET is blocked until we return (duh).
9877 // 2) (LS) blocked on (RCET): If the LS is not synchronized, then it may be sending an event to the RCET, and thus blocked on the RCET.
9878 // 3) (Helper thread) blocked on (LS): That LS thread may be holding a lock that the helper thread needs, thus blocking the helper thread.
9879 // 4) (This function) blocked on (Helper Thread): We block until the helper thread can process our IPC event.
9880 // #4 is not true for async events.
9882 // If we hit this assert, it means we may get the deadlock above and we're calling SendIPCEvent at a time we shouldn't.
9883 // Note this race is as old as dirt.
9884 if (IsRCEventThread() && !event->asyncSend)
9886 // Note that w/ Continue & Attach, GetSynchronized() has a different meaning and the race above won't happen.
9887 BOOL fPossibleDeadlock = process->GetSynchronized() || (event->type == DB_IPCE_CONTINUE) || (event->type == DB_IPCE_ATTACHING);
9888 CONSISTENCY_CHECK_MSGF(fPossibleDeadlock, ("Possible deadlock while sending: '%s'\n", IPCENames::GetName(event->type)));
9894 // Cache this process into the MRU so that we can find it if we're debugging in retail.
9895 g_pRSDebuggingInfo->m_MRUprocess = process;
9898 HRESULT hrEvent = S_OK;
9899 _ASSERTE(event != NULL);
9901 // NOTE: the eventSize parameter is only so you can specify an event size that is SMALLER than the process send
9903 if (eventSize > CorDBIPC_BUFFER_SIZE)
9904 return E_INVALIDARG;
9906 STRESS_LOG4(LF_CORDB, LL_INFO1000, "CRCET::SIPCE: sending %s to AD 0x%x, proc 0x%x(%d)\n",
9907 IPCENames::GetName(event->type), VmPtrToCookie(event->vmAppDomain), process->m_id, process->m_id);
9909 // For 2-way events, this check is unnecessary (since we already check for LS exit)
9910 // But for async events, we need this.
9911 // So just check it up here and make everyone's life easier.
9912 if (process->m_terminated)
9914 STRESS_LOG0(LF_CORDB, LL_INFO10000, "CRCET::SIPCE: LS already terminated, shortcut exiting\n");
9915 return CORDBG_E_PROCESS_TERMINATED;
9918 // If the helper thread has died, we can't send an IPC event (and it's never coming back either).
9919 // Although we do wait on the thread's handle, there are strange windows where the thread's handle
9920 // is not yet signaled even though we've continued from the exit-thread event for the helper.
9921 if (process->m_helperThreadDead)
9923 STRESS_LOG0(LF_CORDB, LL_INFO10000, "CRCET::SIPCE: Helper-thread dead, shortcut exiting\n");
9924 return CORDBG_E_PROCESS_TERMINATED;
9927 BOOL fUnrecoverableError = TRUE;
9930 hr = process->GetEventChannel()->SendEventToLeftSide(event, eventSize);
9931 fUnrecoverableError = FALSE;
9933 EX_CATCH_HRESULT(hr);
9936 // If we're sending a Continue() event, then after this, the LS may run free.
9937 // If this is the last managed event before the LS exits, (which is the case
9938 // if we're responding to either an Exit-Thread or if we respond to a Detach)
9939 // the LS may exit at anytime from here on, so we need to be careful.
9942 if (fUnrecoverableError)
9944 _ASSERTE(FAILED(hr));
9945 CORDBSetUnrecoverableError(process, hr, 0);
9949 // Get a handle to the target process - this call always succeeds
9950 HANDLE hLSProcess = NULL;
9951 process->GetHandle(&hLSProcess);
9953 // We take locks to ensure that the CordbProcess object is still alive,
9954 // even if the OS process exited.
9955 _ASSERTE(hLSProcess != NULL);
9957 // Check if Sending the IPC event failed
9960 // The failure to send an event may be due to the target process terminating
9961 // (especially, but not exclusively, in the case of async events).
9962 // There is a race here - we can't rely on any check above SendEventToLeftSide
9963 // to tell us whether the process has exited yet.
9964 // Check for that case and return an accurate hresult.
9965 DWORD ret = WaitForSingleObject(hLSProcess, 0);
9966 if (ret == WAIT_OBJECT_0)
9968 return CORDBG_E_PROCESS_TERMINATED;
9971 // Some other failure sending the IPC event - just return it.
9975 STRESS_LOG0(LF_CORDB, LL_INFO1000, "CRCET::SIPCE: sent...\n");
9977 // If this is an async send, then don't wait for the left side to acknowledge that its read the event.
9978 _ASSERTE(!event->asyncSend || !event->replyRequired);
9980 if (process->GetEventChannel()->NeedToWaitForAck(event))
9982 STRESS_LOG0(LF_CORDB, LL_INFO1000,"CRCET::SIPCE: waiting for left side to read event. (on RSER)\n");
9986 // Wait for either a reply (common case) or the left side to go away.
9987 // We can't detach while waiting for a reply (because detach needs to send events).
9988 // All of the outcomes from this wait are completely disjoint.
9989 // It's possible for the LS to reply and then exit normally (Thread_Detach, Process_Detach)
9990 // and so ExitProcess may have been called, but it doesn't matter.
9993 ID_RSER = WAIT_OBJECT_0,
9998 // Only wait on the helper thread for cases where the process is stopped (and thus we don't expect it do exit on us).
9999 // If the process is running and we lose our helper thread, it ought to be during shutdown and we ough to
10000 // follow up with an exit.
10001 // This includes when we've dispatch Native events, and it includes the AsyncBreak sent to get us from a
10002 // win32 frozen state to a synchronized state).
10003 HANDLE hHelperThread = NULL;
10004 if (process->IsStopped())
10006 hHelperThread = process->GetHelperThreadHandle();
10010 // Note that in case of a tie (multiple handles signaled), WaitForMultipleObjects gives
10011 // priority to the handle earlier in the array.
10012 HANDLE waitSet[] = { process->GetEventChannel()->GetRightSideEventAckHandle(), hLSProcess, hHelperThread};
10013 DWORD cWaitSet = NumItems(waitSet);
10014 if (hHelperThread == NULL)
10021 ret = WaitForMultipleObjectsEx(cWaitSet, waitSet, FALSE, CordbGetWaitTimeout(), FALSE);
10022 // If we timeout because we're waiting for an uncontinued OOB event, we need to just keep waiting.
10023 } while ((ret == WAIT_TIMEOUT) && process->IsWaitingForOOBEvent());
10028 // Normal reply from LS.
10029 // This is set iff the LS replied to our event. The LS may have exited since it replied
10030 // but we don't care. We still have the reply and we'll pass it on.
10031 STRESS_LOG0(LF_CORDB, LL_INFO1000, "CRCET::SIPCE: left side read the event.\n");
10033 // If this was a two-way event, then the result is already ready for us. Simply copy the result back
10034 // over the original event that was sent. Otherwise, the left side has simply read the event and is
10035 // processing it...
10036 if (event->replyRequired)
10038 process->GetEventChannel()->GetReplyFromLeftSide(event, eventSize);
10039 hrEvent = event->hr;
10044 // Left side exited on us.
10045 // ExitProcess may or may not have been called here (since it's on a different thread).
10046 STRESS_LOG0(LF_CORDB, LL_INFO1000, "CRCET::SIPCE: left side exiting while RS was waiting for reply.\n");
10047 hr = CORDBG_E_PROCESS_TERMINATED;
10050 case ID_HELPERTHREAD:
10051 // We can only send most IPC events while the LS is synchronized. We shouldn't lose our helper thread
10052 // when synced under any sort of normal conditions.
10053 // This won't fire if the process already exited, because LSPROCESS gets higher priority in the wait
10054 // (since it was placed earlier).
10055 // Thus the only "legitimate" window where this could happen would be in a shutdown scenario after
10056 // the helper is dead but before the process has died. We shouldn't be synced in that scenario,
10057 // so we shouldn't be sending IPC events during it.
10058 STRESS_LOG0(LF_CORDB, LL_INFO1000, "CRCET::SIPCE: lost helper thread.\n");
10061 // Assert because we want to know if we ever actually hit this in any detectable scenario.
10062 // However, shutdown can occur in preemptive mode. Thus if the RS does an AsyncBreak late
10063 // enough, then the LS will appear to be stopped but may still shutdown.
10064 // Since the debuggee can exit asynchronously at any time (eg, suppose somebody forcefully
10065 // kills it with taskman), this doesn't introduce a new case.
10066 // That aside, it would be great to be able to assert this:
10067 //_ASSERTE(!"Potential deadlock - Randomly Lost helper thread");
10069 // We'll piggy back this on the terminated case.
10070 hr = CORDBG_E_PROCESS_TERMINATED;
10075 // If we timed out/failed, check the left side to see if it is in the unrecoverable error mode. If it is,
10076 // return the HR from the left side that caused the error. Otherwise, return that we timed out and that
10077 // we don't really know why.
10078 HRESULT realHR = (ret == WAIT_FAILED) ? HRESULT_FROM_GetLastError() : ErrWrapper(CORDBG_E_TIMEOUT);
10080 hr = process->CheckForUnrecoverableError();
10084 CORDBSetUnrecoverableError(process, realHR, 0);
10088 STRESS_LOG1(LF_CORDB, LL_INFO1000, "CRCET::SIPCE: left side timeout/fail while RS waiting for reply. hr = 0x%08x\n", hr);
10093 // If the LS picked up RSEA, it will be reset (since it's an auto event).
10094 // But in the case that the wait failed or that the LS exited, we need to explicitly reset RSEA
10097 process->GetEventChannel()->ClearEventForLeftSide();
10100 // Done waiting for reply.
10105 process->ForceDacFlush();
10107 // The hr and hrEvent are 2 very different things.
10108 // hr tells us whether the event was sent successfully.
10109 // hrEvent tells us how the LS responded to it.
10110 // if FAILED(hr), then hrEvent is useless b/c the LS never got it.
10111 // But if SUCCEEDED(hr), then hrEvent may still have failed and that could be
10112 // valuable information.
10117 //---------------------------------------------------------------------------------------
10118 // FlushQueuedEvents flushes a process's event queue.
10121 // pProcess - non-null process object whose queue will be drained
10124 // @dbgtodo shim: this should be part of the shim.
10125 // This dispatches events that are queued up. The queue is populated by
10126 // the shim's proxy callback (see code:ShimProxyCallback). This will dispatch events
10127 // to the 'real' callback supplied by the debugger. This will dispatch events
10128 // as long as the debugger keeps calling continue.
10130 // This requires that the process lock be held, although it will toggle the lock.
10131 void CordbRCEventThread::FlushQueuedEvents(CordbProcess* process)
10135 NOTHROW; // This is happening on the RCET thread, so there's no place to propogate an error back up.
10139 STRESS_LOG0(LF_CORDB,LL_INFO10000, "CRCET::FQE: Beginning to flush queue\n");
10141 _ASSERTE(process->GetShim() != NULL);
10143 // We should only call this is we already have queued events
10144 _ASSERTE(!process->GetShim()->GetManagedEventQueue()->IsEmpty());
10147 // Dispatch queued events so long as they keep calling Continue()
10148 // before returning from their callback. If they call Continue(),
10149 // process->m_synchronized will be false again and we know to
10150 // loop around and dispatch the next event.
10152 _ASSERTE(process->ThreadHoldsProcessLock());
10155 // Give shim a chance to queue any faked attach events. Grab a pointer to the
10156 // ShimProcess now, while we still hold the process lock. Once we release the lock,
10157 // GetShim() may not work.
10158 RSExtSmartPtr<ShimProcess> pShim(process->GetShim());
10160 // Release lock before we call out to shim to Queue fake events.
10162 RSInverseLockHolder inverseLockHolder(process->GetProcessLock());
10164 PUBLIC_CALLBACK_IN_THIS_SCOPE0_NO_LOCK(pProcess);
10166 // Because we've released the lock, at any point from here forward the
10167 // CorDbProcess may suddenly get neutered if the user detaches the debugger.
10169 pShim->QueueFakeAttachEventsIfNeeded(false);
10173 // Now that we're holding the process lock again, we can safely check whether
10174 // process has become neutered
10175 if (process->IsNeutered())
10182 // Main dispatch loop here. DispatchRCEvent will take events out of the
10183 // queue and invoke callbacks
10186 // DispatchRCEvent will mark the process as stopped before dispatching.
10187 process->DispatchRCEvent();
10189 LOG((LF_CORDB,LL_INFO10000, "CRCET::FQE: Finished w/ "
10190 "DispatchRCEvent\n"));
10192 while (process->GetSyncCompleteRecv() &&
10193 (process->GetSynchronized() == false) &&
10194 (process->GetShim() != NULL) && // may have lost Shim if we detached while dispatch
10195 (!process->GetShim()->GetManagedEventQueue()->IsEmpty()) &&
10196 (process->m_unrecoverableError == false));
10200 // If they returned from a callback without calling Continue() then
10201 // the process is still synchronized, so let the rc event thread
10202 // know that it need to update its process list and remove the
10203 // process's event.
10205 if (process->GetSynchronized())
10207 ProcessStateChanged();
10210 LOG((LF_CORDB,LL_INFO10000, "CRCET::FQE: finished\n"));
10213 //---------------------------------------------------------------------------------------
10214 // Preliminary Handle an Notification event from the target. This may queue the event,
10215 // but does not actually dispatch the event.
10218 // pManagedEvent - local managed-event. On success, this function assumes ownership of the
10219 // event and will delete its memory. Assumed that caller allocated via 'new'.
10220 // pCallback - callback obecjt to dispatch events on.
10223 // None. Throws on error. On error, caller still owns the pManagedEvent and must free it.
10226 // This should be called once a notification event is received from the target.
10229 // HandleRCEvent -- handle an IPC event received from the runtime controller.
10230 // This will update ICorDebug state and immediately dispatch the event.
10232 //---------------------------------------------------------------------------------------
10233 void CordbProcess::HandleRCEvent(
10234 DebuggerIPCEvent * pManagedEvent,
10235 RSLockHolder * pLockHolder,
10236 ICorDebugManagedCallback * pCallback)
10241 PRECONDITION(CheckPointer(pManagedEvent));
10242 PRECONDITION(CheckPointer(pCallback));
10243 PRECONDITION(ThreadHoldsProcessLock());
10247 if (!this->IsSafeToSendEvents() || this->m_exiting)
10252 // Marshals over some standard data from event.
10253 MarshalManagedEvent(pManagedEvent);
10255 STRESS_LOG4(LF_CORDB, LL_INFO1000, "RCET::TP: Got %s for AD 0x%x, proc 0x%x(%d)\n",
10256 IPCENames::GetName(pManagedEvent->type), VmPtrToCookie(pManagedEvent->vmAppDomain), this->m_id, this->m_id);
10258 RSExtSmartPtr<ICorDebugManagedCallback2> pCallback2;
10259 pCallback->QueryInterface(IID_ICorDebugManagedCallback2, reinterpret_cast<void **> (&pCallback2));
10261 RSExtSmartPtr<ICorDebugManagedCallback3> pCallback3;
10262 pCallback->QueryInterface(IID_ICorDebugManagedCallback3, reinterpret_cast<void **> (&pCallback3));
10264 // Dispatch directly. May not necessarily dispatch an event.
10265 // Toggles the lock to dispatch callbacks.
10266 RawDispatchEvent(pManagedEvent, pLockHolder, pCallback, pCallback2, pCallback3);
10270 // ProcessStateChanged -- tell the rc event thread that the ICorDebug's
10271 // process list has changed by setting its flag and thread control event.
10272 // This will cause the rc event thread to update its set of handles to wait
10275 void CordbRCEventThread::ProcessStateChanged()
10277 m_cordb->LockProcessList();
10278 STRESS_LOG0(LF_CORDB, LL_INFO100000, "CRCET::ProcessStateChanged\n");
10279 m_processStateChanged = TRUE;
10280 SetEvent(m_threadControlEvent);
10281 m_cordb->UnlockProcessList();
10285 //---------------------------------------------------------------------------------------
10286 // Primary loop of the Runtime Controller event thread. This routine loops during the
10287 // debug session taking IPC events from the IPC block and calling out to process them.
10296 // @dbgtodo shim: eventually hoist the entire RCET into the shim.
10297 //---------------------------------------------------------------------------------------
10298 void CordbRCEventThread::ThreadProc()
10300 HANDLE waitSet[MAXIMUM_WAIT_OBJECTS];
10301 CordbProcess * rgProcessSet[MAXIMUM_WAIT_OBJECTS];
10302 unsigned int waitCount;
10305 memset(&rgProcessSet, NULL, MAXIMUM_WAIT_OBJECTS * sizeof(CordbProcess *));
10306 memset(&waitSet, NULL, MAXIMUM_WAIT_OBJECTS * sizeof(HANDLE));
10310 // First event to wait on is always the thread control event.
10311 waitSet[0] = m_threadControlEvent;
10312 rgProcessSet[0] = NULL;
10317 DWORD dwStatus = WaitForMultipleObjectsEx(waitCount, waitSet, FALSE, 2000, FALSE);
10319 if (dwStatus == WAIT_FAILED)
10321 STRESS_LOG1(LF_CORDB, LL_INFO10000, "CordbRCEventThread::ThreadProc WaitFor"
10322 "MultipleObjects failed: 0x%x\n", GetLastError());
10325 else if ((dwStatus >= WAIT_OBJECT_0) && (dwStatus < WAIT_OBJECT_0 + waitCount) && m_run)
10327 // Got an event. Figure out which process it came from.
10328 unsigned int procNumber = dwStatus - WAIT_OBJECT_0;
10330 if (procNumber != 0)
10332 // @dbgtodo shim: rip all of this out. Leave the assert in for now to verify that we're not accidentally
10333 // going down this codepath. Once we rip this out, we can also simplify some of the code below.
10334 // Notification events (including Sync-complete) should be coming from Win32 event thread via
10336 _ASSERTE(!"Shouldn't be here");
10342 // Empty any queued work items.
10343 DrainWorkerQueue();
10345 // Check a flag to see if we need to update our list of processes to wait on.
10346 if (m_processStateChanged)
10348 STRESS_LOG0(LF_CORDB, LL_INFO1000, "RCET::TP: refreshing process list.\n");
10353 // free the old wait list
10355 for (i = 1; i < waitCount; i++)
10357 rgProcessSet[i]->InternalRelease();
10360 // Pass 1: iterate the hash of all processes and collect the unsynchronized ones into the wait list.
10361 // Note that Stop / Continue can still be called on a different thread while we're doing this.
10362 m_cordb->LockProcessList();
10363 m_processStateChanged = FALSE;
10367 CordbSafeHashTable<CordbProcess> * pHashTable = m_cordb->GetProcessList();
10369 CordbProcess * pProcess;
10371 for (pProcess = pHashTable->FindFirst(&hashFind); pProcess != NULL; pProcess = pHashTable->FindNext(&hashFind))
10373 _ASSERTE(waitCount < MAXIMUM_WAIT_OBJECTS);
10375 if( waitCount >= MAXIMUM_WAIT_OBJECTS )
10380 // Only listen to unsynchronized processes. Processes that are synchronized will not send events without
10381 // being asked by us first, so there is no need to async listen to them.
10383 // Note: if a process is not synchronized then there is no way for it to transition to the syncrhonized
10384 // state without this thread receiving an event and taking action. So there is no need to lock the
10385 // per-process mutex when checking the process's synchronized flag here.
10386 if (!pProcess->GetSynchronized() && pProcess->IsSafeToSendEvents())
10388 STRESS_LOG2(LF_CORDB, LL_INFO1000, "RCET::TP: listening to process 0x%x(%d)\n",
10389 pProcess->m_id, pProcess->m_id);
10391 waitSet[waitCount] = pProcess->m_leftSideEventAvailable;
10392 rgProcessSet[waitCount] = pProcess;
10393 rgProcessSet[waitCount]->InternalAddRef();
10398 m_cordb->UnlockProcessList();
10400 // Pass 2: for each process that we placed in the wait list, determine if there are any existing queued
10401 // events that need to be flushed.
10403 // Start i at 1 to skip the control event...
10406 while(i < waitCount)
10408 pProcess = rgProcessSet[i];
10410 // Take the process lock so we can check the queue safely
10413 // Now that we've just locked the processes, we can safely inspect it and dispatch events.
10414 // The process may have changed since when we first added it to the process list in Pass 1,
10415 // so we can't make any assumptions about whether it's sync, live, or exiting.
10417 // Flush the queue if necessary. Note, we only do this if we've actually received a SyncComplete message
10418 // from this process. If we haven't received a SyncComplete yet, then we don't attempt to drain any
10419 // queued events yet. They'll be drained when the SyncComplete event is actually received.
10420 if (pProcess->GetSyncCompleteRecv() &&
10421 (pProcess->GetShim() != NULL) &&
10422 !pProcess->GetSynchronized())
10424 if (pProcess->GetShim()->GetManagedEventQueue()->IsEmpty())
10426 // Effectively what we are doing here is to continue everything without actually
10427 // handling an event. We can get here if the event raised by the LS is a duplicate
10428 // creation event, which the shim discards without adding it to the event queue.
10429 // See code:ShimProcess::IsDuplicateCreationEvent.
10431 // To continue, we need to increment the stop count first. Also, we can't call
10432 // Continue() while holding the process lock.
10433 pProcess->SetSynchronized(true);
10434 pProcess->IncStopCount();
10435 pProcess->Unlock();
10436 pProcess->ContinueInternal(FALSE);
10441 // This may toggle the process-lock
10442 FlushQueuedEvents(pProcess);
10446 // Flushing could have left the process synchronized...
10447 // Common case is if the callback didn't call Continue().
10448 if (pProcess->GetSynchronized())
10450 // remove the process from the wait list by moving all the other processes down one.
10451 if ((i + 1) < waitCount)
10453 memcpy(&rgProcessSet[i], &(rgProcessSet[i+1]), sizeof(rgProcessSet[0]) * (waitCount - i - 1));
10454 memcpy(&waitSet[i], &waitSet[i+1], sizeof(waitSet[0]) * (waitCount - i - 1));
10457 // drop the count of processes to wait on
10460 pProcess->Unlock();
10462 // make sure to release the reference we added when the process was added to the wait list.
10463 pProcess->InternalRelease();
10465 // We don't have to increment i because we've copied the next element into
10466 // the current value at i.
10470 // Even after flushing, its still not syncd, so leave it in the wait list.
10471 pProcess->Unlock();
10473 // Increment i normally.
10477 } // end ProcessStateChanged
10481 // We intentionally return while leaking some CordbProcess objects inside
10482 // rgProcessSet, in some cases (e.g., I've seen this happen when detaching from a
10483 // debuggee almost immediately after attaching to it). In the future, we should
10484 // really consider not leaking these anymore. However, I'm unsure how safe it is to just
10485 // go and InternalRelease() those guys, as above we intentionally DON'T release them when
10486 // they're not synchronized. So for now, to make debug builds happy, exclude those
10487 // references when we run CheckMemLeaks() later on. In our next side-by-side release,
10488 // consider actually doing InternalRelease() on the remaining CordbProcesses on
10489 // retail, and then we can remove the following loop.
10490 for (UINT i=1; i < waitCount; i++)
10492 InterlockedDecrement(&Cordb::s_DbgMemTotalOutstandingInternalRefs);
10494 #endif //_DEBUG_IMPL
10499 // This is the thread's real thread proc. It simply calls to the
10500 // thread proc on the given object.
10503 DWORD WINAPI CordbRCEventThread::ThreadProc(LPVOID parameter)
10505 CordbRCEventThread * pThread = (CordbRCEventThread *) parameter;
10507 INTERNAL_THREAD_ENTRY(pThread);
10508 pThread->ThreadProc();
10512 template<typename T>
10513 InterlockedStack<T>::InterlockedStack()
10518 template<typename T>
10519 InterlockedStack<T>::~InterlockedStack()
10521 // This is an arbitrary choice. We expect the stacks be drained.
10522 _ASSERTE(m_pHead == NULL);
10525 // Thread safe pushes + pops.
10526 // Many threads can push simultaneously.
10527 // Only 1 thread can pop.
10528 template<typename T>
10529 void InterlockedStack<T>::Push(T * pItem)
10531 // InterlockedCompareExchangePointer(&dest, ex, comp).
10532 // Really behaves like:
10534 // if (*dest == comp) { *dest = ex; }
10537 // We can do a thread-safe assign { comp = dest; dest = ex } via:
10538 // do { comp = dest } while (ICExPtr(&dest, ex, comp) != comp));
10543 pItem->m_next = m_pHead;
10545 while(InterlockedCompareExchangeT(&m_pHead, pItem, pItem->m_next) != pItem->m_next);
10548 // Returns NULL on empty,
10549 // else returns the head of the list.
10550 template<typename T>
10551 T * InterlockedStack<T>::Pop()
10553 if (m_pHead == NULL)
10558 // This allows 1 thread to Pop() and race against N threads doing a Push().
10563 } while(InterlockedCompareExchangeT(&m_pHead, pItem->m_next, pItem) != pItem);
10569 // RCET will take ownership of this item and delete it.
10570 // This can be done w/o taking any locks (thus it can be called from any lock context)
10571 // This may race w/ the RCET draining the queue.
10572 void CordbRCEventThread::QueueAsyncWorkItem(RCETWorkItem * pItem)
10575 // Non-blocking insert into queue.
10577 _ASSERTE(pItem != NULL);
10579 m_WorkerStack.Push(pItem);
10581 // Ping the RCET so that it drains the queue.
10582 SetEvent(m_threadControlEvent);
10585 // Execute & delete all workitems in the queue.
10586 // This can be done w/o taking any locks. (though individual items may take locks).
10587 void CordbRCEventThread::DrainWorkerQueue()
10589 _ASSERTE(IsRCEventThread());
10593 RCETWorkItem* pCur = m_WorkerStack.Pop();
10605 //---------------------------------------------------------------------------------------
10606 // Wait for an reply from the debuggee.
10609 // pProcess - process for debuggee.
10610 // pAppDomain - not used.
10611 // pEvent - caller-allocated event to be filled out.
10612 // This is expected to be at least as big as CorDBIPC_BUFFER_SIZE.
10615 // S_OK on success. else failure.
10618 // Caller allocates
10621 // WaitForIPCEventFromProcess waits for an event from just the specified
10622 // process. This should only be called when the process is in a synchronized
10623 // state, which ensures that the RCEventThread isn't listening to the
10624 // process's event, too, which would get confusing.
10626 // @dbgtodo - this function should eventually be obsolete once everything
10627 // is using DAC calls instead of helper-thread.
10629 //---------------------------------------------------------------------------------------
10630 HRESULT CordbRCEventThread::WaitForIPCEventFromProcess(CordbProcess * pProcess,
10631 CordbAppDomain * pAppDomain,
10632 DebuggerIPCEvent * pEvent)
10634 CORDBRequireProcessStateOKAndSync(pProcess, pAppDomain);
10641 dwStatus = SafeWaitForSingleObject(pProcess,
10642 pProcess->m_leftSideEventAvailable,
10643 CordbGetWaitTimeout());
10645 if (pProcess->m_terminated)
10647 return CORDBG_E_PROCESS_TERMINATED;
10649 // If we timeout because we're waiting for an uncontinued OOB event, we need to just keep waiting.
10650 } while ((dwStatus == WAIT_TIMEOUT) && pProcess->IsWaitingForOOBEvent());
10655 if (dwStatus == WAIT_OBJECT_0)
10657 pProcess->CopyRCEventFromIPCBlock(pEvent);
10661 pProcess->MarshalManagedEvent(pEvent);
10663 STRESS_LOG4(LF_CORDB, LL_INFO1000, "CRCET::SIPCE: Got %s for AD 0x%x, proc 0x%x(%d)\n",
10664 IPCENames::GetName(pEvent->type),
10665 VmPtrToCookie(pEvent->vmAppDomain),
10670 EX_CATCH_HRESULT(hr)
10672 SetEvent(pProcess->m_leftSideEventRead);
10676 else if (dwStatus == WAIT_TIMEOUT)
10679 // If we timed out, check the left side to see if it is in the
10680 // unrecoverable error mode. If it is, return the HR from the
10681 // left side that caused the error. Otherwise, return that we timed
10682 // out and that we don't really know why.
10684 HRESULT realHR = ErrWrapper(CORDBG_E_TIMEOUT);
10686 hr = pProcess->CheckForUnrecoverableError();
10690 CORDBSetUnrecoverableError(pProcess, realHR, 0);
10698 _ASSERTE(dwStatus == WAIT_FAILED);
10700 hr = HRESULT_FROM_GetLastError();
10702 CORDBSetUnrecoverableError(pProcess, hr, 0);
10710 // Start actually creates and starts the thread.
10712 HRESULT CordbRCEventThread::Start()
10714 if (m_threadControlEvent == NULL)
10716 return E_INVALIDARG;
10719 m_thread = CreateThread(NULL,
10721 &CordbRCEventThread::ThreadProc,
10726 if (m_thread == NULL)
10728 return HRESULT_FROM_GetLastError();
10736 // Stop causes the thread to stop receiving events and exit. It
10737 // waits for it to exit before returning.
10739 HRESULT CordbRCEventThread::Stop()
10741 if (m_thread != NULL)
10743 LOG((LF_CORDB, LL_INFO100000, "CRCET::Stop\n"));
10747 SetEvent(m_threadControlEvent);
10749 DWORD ret = WaitForSingleObject(m_thread, INFINITE);
10751 if (ret != WAIT_OBJECT_0)
10753 return HRESULT_FROM_GetLastError();
10763 /* ------------------------------------------------------------------------- *
10764 * Win32 Event Thread class
10765 * ------------------------------------------------------------------------- */
10770 W32ETA_CREATE_PROCESS = 1,
10771 W32ETA_ATTACH_PROCESS = 2,
10772 W32ETA_CONTINUE = 3,
10778 //---------------------------------------------------------------------------------------
10782 // pCordb - Pointer to the owning cordb object for this event thread.
10783 // pShim - Pointer to the shim for supporting V2 debuggers on V3 architecture.
10785 //---------------------------------------------------------------------------------------
10786 CordbWin32EventThread::CordbWin32EventThread(
10788 ShimProcess * pShim
10790 m_thread(NULL), m_threadControlEvent(NULL),
10791 m_actionTakenEvent(NULL), m_run(TRUE),
10792 m_action(W32ETA_NONE)
10794 m_cordb.Assign(pCordb);
10795 _ASSERTE(pCordb != NULL);
10799 m_pNativePipeline = NULL;
10804 // Destructor. Cleans up all of the open handles and such.
10805 // This expects that the thread has been stopped and has terminated
10806 // before being called.
10808 CordbWin32EventThread::~CordbWin32EventThread()
10810 if (m_thread != NULL)
10811 CloseHandle(m_thread);
10813 if (m_threadControlEvent != NULL)
10814 CloseHandle(m_threadControlEvent);
10816 if (m_actionTakenEvent != NULL)
10817 CloseHandle(m_actionTakenEvent);
10819 if (m_pNativePipeline != NULL)
10821 m_pNativePipeline->Delete();
10822 m_pNativePipeline = NULL;
10825 m_sendToWin32EventThreadMutex.Destroy();
10830 // Init sets up all the objects that the thread will need to run.
10832 HRESULT CordbWin32EventThread::Init()
10834 if (m_cordb == NULL)
10835 return E_INVALIDARG;
10837 m_sendToWin32EventThreadMutex.Init("Win32-Send lock", RSLock::cLockFlat, RSLock::LL_WIN32_SEND_LOCK);
10839 m_threadControlEvent = WszCreateEvent(NULL, FALSE, FALSE, NULL);
10840 if (m_threadControlEvent == NULL)
10841 return HRESULT_FROM_GetLastError();
10843 m_actionTakenEvent = WszCreateEvent(NULL, FALSE, FALSE, NULL);
10844 if (m_actionTakenEvent == NULL)
10845 return HRESULT_FROM_GetLastError();
10847 m_pNativePipeline = NewPipelineWithDebugChecks();
10848 if (m_pNativePipeline == NULL)
10850 return E_OUTOFMEMORY;
10857 // Main function of the Win32 Event Thread
10859 void CordbWin32EventThread::ThreadProc()
10861 #if defined(RSCONTRACTS)
10862 DbgRSThread::GetThread()->SetThreadType(DbgRSThread::cW32ET);
10864 // The win32 ET conceptually holds a lock (all threads do).
10865 DbgRSThread::GetThread()->TakeVirtualLock(RSLock::LL_WIN32_EVENT_THREAD);
10868 // In V2, the debuggee decides what to do if the debugger rudely exits / detaches. (This is
10869 // handled by host policy). With the OS native-debuggging pipeline, the debugger by default
10870 // kills the debuggee if it exits. To emulate V2 behavior, we need to override that default.
10871 BOOL fOk = m_pNativePipeline->DebugSetProcessKillOnExit(FALSE);
10872 (void)fOk; //prevent "unused variable" error from GCC
10876 // Run the top-level event loop.
10879 #if defined(RSCONTRACTS)
10880 // The win32 ET conceptually holds a lock (all threads do).
10881 DbgRSThread::GetThread()->ReleaseVirtualLock(RSLock::LL_WIN32_EVENT_THREAD);
10885 // Define a holder that calls code:DeleteIPCEventHelper
10886 NEW_WRAPPER_TEMPLATE1(DeleteIPCEventHolderHelper, DeleteIPCEventHelper);
10887 typedef DeleteIPCEventHolderHelper<DebuggerIPCEvent> DeleteIPCEventHolder;
10889 //---------------------------------------------------------------------------------------
10891 // Helper to clean up IPCEvent before deleting it.
10892 // This must be called after an event is marshalled via code:CordbProcess::MarshalManagedEvent
10895 // pManagedEvent - managed event to delete.
10898 // This can delete a partially marshalled event.
10900 void DeleteIPCEventHelper(DebuggerIPCEvent *pManagedEvent)
10904 // This is backout code that shouldn't need to throw.
10908 if (pManagedEvent == NULL)
10912 switch (pManagedEvent->type & DB_IPCE_TYPE_MASK)
10914 // so far only this event need to cleanup.
10915 case DB_IPCE_MDA_NOTIFICATION:
10916 pManagedEvent->MDANotification.szName.CleanUp();
10917 pManagedEvent->MDANotification.szDescription.CleanUp();
10918 pManagedEvent->MDANotification.szXml.CleanUp();
10921 case DB_IPCE_FIRST_LOG_MESSAGE:
10922 pManagedEvent->FirstLogMessage.szContent.CleanUp();
10928 delete [] (BYTE *)pManagedEvent;
10931 //---------------------------------------------------------------------------------------
10932 // Handle a CLR specific notification event.
10935 // pManagedEvent - non-null pointer to a managed event.
10936 // pLockHolder - hold to process lock that gets toggled if this dispatches an event.
10937 // pCallback - callback to dispatch potential managed events.
10940 // Throws on error.
10943 // Target is stopped. Record was already determined to be a CLR event.
10946 // This is called after caller does WaitForDebugEvent.
10947 // Any exception this Filter does not recognize is treated as kNotClr.
10948 // Currently, this includes both managed-exceptions and unmanaged ones.
10949 // For interop-debugging, the interop logic will handle all kNotClr and triage if
10950 // it's really a non-CLR exception.
10952 //---------------------------------------------------------------------------------------
10953 void CordbProcess::FilterClrNotification(
10954 DebuggerIPCEvent * pManagedEvent,
10955 RSLockHolder * pLockHolder,
10956 ICorDebugManagedCallback * pCallback)
10961 PRECONDITION(CheckPointer(pManagedEvent));
10962 PRECONDITION(CheckPointer(pCallback));
10963 PRECONDITION(ThreadHoldsProcessLock());
10967 // There are 3 types of events from the LS:
10968 // 1) Replies (eg, corresponding to WaitForIPCEvent)
10969 // we need to set LSEA/wait on LSER.
10970 // 2) Sync-Complete (kind of like a special notification)
10972 // 3) Notifications (eg, Module-load):
10973 // these are dispatched immediately.
10974 // 4) Left-side Startup event
10977 // IF we're synced, then we must be getting a "Reply".
10978 bool fReply = this->GetSynchronized();
10980 LOG((LF_CORDB, LL_INFO10000, "CP::FCN - Received event %s; fReply: %d\n",
10981 IPCENames::GetName(pManagedEvent->type),
10987 _ASSERTE(m_pShim != NULL);
10992 pLockHolder->Release();
10993 _ASSERTE(!ThreadHoldsProcessLock());
10995 // Save the IPC event and wake up the thread which is waiting for it from the LS.
10996 GetEventChannel()->SaveEventFromLeftSide(pManagedEvent);
10997 SetEvent(this->m_leftSideEventAvailable);
10999 // Some other thread called code:CordbRCEventThread::WaitForIPCEventFromProcess, and
11000 // that will respond here and set the event.
11002 DWORD dwResult = WaitForSingleObject(this->m_leftSideEventRead, CordbGetWaitTimeout());
11003 pLockHolder->Acquire();
11004 if (dwResult != WAIT_OBJECT_0)
11006 // The wait failed. This is probably WAIT_TIMEOUT which suggests a deadlock/assert on
11007 // the RCEventThread.
11008 CONSISTENCY_CHECK_MSGF(false, ("WaitForSingleObject failed: %d", dwResult));
11009 ThrowHR(CORDBG_E_TIMEOUT);
11014 if (pManagedEvent->type == DB_IPCE_LEFTSIDE_STARTUP)
11017 // Case 4: Left-side startup event. We'll mark that we're attached from oop.
11020 // Now that LS is started, we should definitely be able to instantiate DAC.
11023 // @dbgtodo 'attach-bit': we don't want the debugger automatically invading the process.
11024 GetDAC()->MarkDebuggerAttached(TRUE);
11026 else if (pManagedEvent->type == DB_IPCE_SYNC_COMPLETE)
11028 // Since V3 doesn't request syncs, it shouldn't get sync-complete.
11029 // @dbgtodo sync: this changes when V3 can explicitly request an AsyncBreak.
11030 _ASSERTE(m_pShim != NULL);
11033 // Case 2: Sync Complete
11036 HandleSyncCompleteRecieved();
11041 // Case 3: Notification. This will dispatch the event immediately.
11044 // Toggles the process-lock if it dispatches callbacks.
11045 HandleRCEvent(pManagedEvent, pLockHolder, pCallback);
11047 } // end Notification
11054 // If the thread has an unhandled managed exception, hijack it.
11057 // dwThreadId - OS Thread id.
11060 // True if hijacked; false if not.
11063 // This is called from shim to emulate being synchronized at an unhandled
11065 // Other ICorDebug operations could calls this (eg, func-eval at 2nd chance).
11066 BOOL CordbProcess::HijackThreadForUnhandledExceptionIfNeeded(DWORD dwThreadId)
11068 PUBLIC_API_ENTRY(this); // from Shim
11070 BOOL fHijacked = FALSE;
11074 RSLockHolder lockHolder(GetProcessLock());
11076 // OS will not execute the Unhandled Exception Filter under native debugger, so
11077 // we need to hijack the thread to get it to execute the UEF, which will then do
11078 // work for unhandled managed exceptions.
11079 CordbThread * pThread = TryLookupOrCreateThreadByVolatileOSId(dwThreadId);
11080 if (pThread != NULL)
11082 // If the thread has a managed exception, then we should have a pThread object.
11084 if (pThread->HasUnhandledNativeException())
11086 _ASSERTE(pThread->IsThreadExceptionManaged()); // should have been marked earlier
11088 pThread->HijackForUnhandledException();
11093 EX_CATCH_HRESULT(hr);
11094 SIMPLIFYING_ASSUMPTION(SUCCEEDED(hr));
11099 //---------------------------------------------------------------------------------------
11100 // Validate the given exception record or throw.
11103 // pRawRecord - non-null raw bytes of the exception
11104 // countBytes - number of bytes in pRawRecord buffer.
11105 // format - format of pRawRecord
11108 // A type-safe exception record from the raw buffer.
11111 // This is a helper for code:CordbProcess::Filter.
11112 // This can do consistency checks on the incoming parameters such as:
11113 // * verify countBytes matches the expected size for the given format.
11114 // * verify the format is supported.
11116 // If we let a given ICD understand multiple formats (eg, have x86 understand both Exr32 and
11117 // Exr64), this would be the spot to allow the conversion.
11119 const EXCEPTION_RECORD * CordbProcess::ValidateExceptionRecord(
11120 const BYTE pRawRecord[],
11122 CorDebugRecordFormat format)
11124 ValidateOrThrow(pRawRecord);
11127 // Check format against expected platform.
11130 // @dbgtodo - , cross-plat: Once we do cross-plat, these should be based off target-architecture not host's.
11131 #if defined(_WIN64)
11132 if (format != FORMAT_WINDOWS_EXCEPTIONRECORD64)
11134 ThrowHR(E_INVALIDARG);
11137 if (format != FORMAT_WINDOWS_EXCEPTIONRECORD32)
11139 ThrowHR(E_INVALIDARG);
11143 // @dbgtodo cross-plat: once we do cross-plat, need to use correct EXCEPTION_RECORD variant.
11144 if (countBytes != sizeof(EXCEPTION_RECORD))
11146 ThrowHR(E_INVALIDARG);
11150 const EXCEPTION_RECORD * pRecord = reinterpret_cast<const EXCEPTION_RECORD *> (pRawRecord);
11155 // Return value: S_OK or indication that no more room exists for enabled types
11156 HRESULT CordbProcess::SetEnableCustomNotification(ICorDebugClass * pClass, BOOL fEnable)
11159 PUBLIC_API_BEGIN(this); // takes the lock
11161 ValidateOrThrow(pClass);
11163 ((CordbClass *)pClass)->SetCustomNotifications(fEnable);
11165 PUBLIC_API_END(hr);
11167 } // CordbProcess::SetEnableCustomNotification
11169 //---------------------------------------------------------------------------------------
11170 // Public implementation of ICDProcess4::Filter
11173 // pRawRecord - non-null raw bytes of the exception
11174 // countBytes - number of bytes in pRawRecord buffer.
11175 // format - format of pRawRecord
11176 // dwFlags - flags providing auxillary info for exception record.
11177 // dwThreadId - thread that exception occurred on.
11178 // pCallback - callback to dispatch potential managed events on.
11179 // pContinueStatus - Continuation status for exception. This dictates what
11180 // to pass to kernel32!ContinueDebugEvent().
11183 // S_OK on success.
11186 // Target is stopped.
11189 // The exception could be anything, including:
11190 // - a CLR notification,
11191 // - a random managed exception (both from managed code or the runtime),
11192 // - a non-CLR exception
11194 // This is cross-platform. The {pRawRecord, countBytes, format} describe events
11195 // on an arbitrary target architecture. On windows, this will be an EXCEPTION_RECORD.
11197 HRESULT CordbProcess::Filter(
11198 const BYTE pRawRecord[],
11200 CorDebugRecordFormat format,
11203 ICorDebugManagedCallback * pCallback,
11204 DWORD * pContinueStatus
11208 PUBLIC_API_BEGIN(this); // takes the lock
11211 // Validate parameters
11214 // If we don't care about the continue status, we leave it untouched.
11215 ValidateOrThrow(pContinueStatus);
11216 ValidateOrThrow(pCallback);
11218 const EXCEPTION_RECORD * pRecord = ValidateExceptionRecord(pRawRecord, countBytes, format);
11220 DWORD dwFirstChance = (dwFlags & IS_FIRST_CHANCE);
11223 // Deal with 2nd-chance exceptions. Don't actually hijack now (that's too invasive),
11224 // but mark that we have the exception in case a future operation (eg, func-eval) needs to hijack.
11226 if (!dwFirstChance)
11228 CordbThread * pThread = TryLookupOrCreateThreadByVolatileOSId(dwThreadId);
11230 // If we don't have a managed-thread object, then it certainly can't have a throwable.
11231 // It's possible this is still an exception from the native portion of the runtime,
11232 // but that's ok, we'll just treat it as a native exception.
11233 // This could be expensive, don't want to do it often... (definitely not on every Filter).
11236 // OS will not execute the Unhandled Exception Filter under native debugger, so
11237 // we need to hijack the thread to get it to execute the UEF, which will then do
11238 // work for unhandled managed exceptions.
11239 if ((pThread != NULL) && pThread->IsThreadExceptionManaged())
11241 // Copy exception record for future use in case we decide to hijack.
11242 pThread->SetUnhandledNativeException(pRecord);
11244 // we don't care about 2nd-chance exceptions, unless we decide to hijack it later.
11248 // Deal with CLR notifications
11250 else if (pRecord->ExceptionCode == CLRDBG_NOTIFICATION_EXCEPTION_CODE) // Special event code
11253 // This may not be for us, or we may not have a managed thread object:
11254 // 1. Anybody can raise an exception with this exception code, so can't assume this belongs to us yet.
11255 // 2. Notifications may come on unmanaged threads if they're coming from MDAs or CLR internal events
11256 // fired before the thread is created.
11258 BYTE * pManagedEventBuffer = new BYTE[CorDBIPC_BUFFER_SIZE];
11259 DeleteIPCEventHolder pManagedEvent(reinterpret_cast<DebuggerIPCEvent *>(pManagedEventBuffer));
11261 bool fOwner = CopyManagedEventFromTarget(pRecord, pManagedEvent);
11264 // This toggles the lock if it dispatches callbacks
11265 FilterClrNotification(pManagedEvent, GET_PUBLIC_LOCK_HOLDER(), pCallback);
11267 // Cancel any notification events from target. These are just supposed to notify ICD and not
11268 // actually be real exceptions in the target.
11269 // Canceling here also prevents a VectoredExceptionHandler in the target from picking
11270 // up exceptions for the CLR.
11271 *pContinueStatus = DBG_CONTINUE;
11274 // holder will invoke DeleteIPCEventHelper(pManagedEvent).
11278 PUBLIC_API_END(hr);
11279 // we may not find the correct mscordacwks so fail gracefully
11280 _ASSERTE(SUCCEEDED(hr) || (hr != HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND)));
11285 //---------------------------------------------------------------------------------------
11286 // Wrapper to invoke ICorDebugMutableDataTarget::ContinueStatusChanged
11289 // dwContinueStatus - new continue status
11292 // None. Throw on error.
11295 // Initial continue status is returned from code:CordbProcess::Filter.
11296 // Some operations (mainly hijacking on a 2nd-chance exception), may need to
11297 // override that continue status.
11298 // ICorDebug operations invoke a callback on the data-target to notify the debugger
11299 // of a change in status. Debugger may fail the request.
11301 void CordbProcess::ContinueStatusChanged(DWORD dwThreadId, CORDB_CONTINUE_STATUS dwContinueStatus)
11303 HRESULT hr = m_pMutableDataTarget->ContinueStatusChanged(dwThreadId, dwContinueStatus);
11307 //---------------------------------------------------------------------------------------
11308 // Request a synchronization to occur after a debug event is dispatched.
11311 // This is called in response to a managed debug event, and so we know that we have
11312 // a worker thread in the process (the one that just sent the event!)
11313 // This can not be called asynchronously.
11314 //---------------------------------------------------------------------------------------
11315 void CordbProcess::RequestSyncAtEvent()
11317 GetDAC()->RequestSyncAtEvent();
11320 //---------------------------------------------------------------------------------------
11322 // Primary loop of the Win32 debug event thread.
11332 // This is it, you've found it, the main guy. This function loops as long as the
11333 // debugger is around calling the OS WaitForDebugEvent() API. It takes the OS Debug
11334 // Event and filters it thru the right-side, continuing the process if not recognized.
11336 // @dbgtodo shim: this will become part of the shim.
11337 //---------------------------------------------------------------------------------------
11338 void CordbWin32EventThread::Win32EventLoop()
11340 // This must be called from the win32 event thread.
11341 _ASSERTE(IsWin32EventThread());
11343 LOG((LF_CORDB, LL_INFO1000, "W32ET::W32EL: entered win32 event loop\n"));
11348 // Allow the timeout for WFDE to be adjustable. Default to 25 ms based off perf numbers (see issue VSWhidbey 132368).
11349 DWORD dwWFDETimeout = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_DbgWFDETimeout);
11353 BOOL fEventAvailable = FALSE;
11355 // We should not have any locks right now.
11358 // Have to wait on 2 sources:
11359 // WaitForMultipleObjects - ping for messages (create, attach, Continue, detach) and also
11360 // process exits in the managed-only case.
11361 // Native Debug Events - This is a huge perf hit so we want to avoid it whenever we can.
11362 // Only wait on these if we're interop debugging and if the process is not frozen.
11363 // A frozen process can't send any debug events, so don't bother looking for them.
11366 unsigned int cWaitCount = 1;
11368 HANDLE rghWaitSet[2];
11370 rghWaitSet[0] = m_threadControlEvent;
11372 DWORD dwWaitTimeout = INFINITE;
11374 if (m_pProcess != NULL)
11376 // Process is always built on Native debugging pipeline, so it needs to always be prepared to call WFDE
11377 // As an optimization, if the target is stopped, then we can avoid calling WFDE.
11379 #ifndef FEATURE_INTEROP_DEBUGGING
11380 // Managed-only, never win32 stopped, so always check for an event.
11382 fEventAvailable = m_pNativePipeline->WaitForDebugEvent(&event, dwWFDETimeout, m_pProcess);
11384 // Wait for a Win32 debug event from any processes that we may be attached to as the Win32 debugger.
11385 const bool fIsWin32Stopped = (m_pProcess->m_state & CordbProcess::PS_WIN32_STOPPED) != 0;
11386 const bool fSkipWFDE = fIsWin32Stopped;
11389 const bool fIsInteropDebugging = m_pProcess->IsInteropDebugging();
11390 (void)fIsInteropDebugging; //prevent "unused variable" error from GCC
11393 _ASSERTE(fIsInteropDebugging == m_pShim->IsInteropDebugging());
11398 fEventAvailable = m_pNativePipeline->WaitForDebugEvent(&event, dwWFDETimeout, m_pProcess);
11402 // If we're managed-only debugging, then the process should always be running,
11403 // which means we always need to be calling WFDE to pump potential debug events.
11404 // If we're interop-debugging, then the process can be stopped at a native-debug event,
11405 // in which case we don't have to call WFDE until we resume it again.
11406 // So we can only skip the WFDE when we're interop-debugging.
11407 _ASSERTE(fIsInteropDebugging);
11409 #endif // FEATURE_INTEROP_DEBUGGING
11413 } // end m_pProcess != NULL
11415 #if defined(FEATURE_INTEROP_DEBUGGING)
11416 // While interop-debugging, the process may get killed rudely underneath us, even if we haven't
11417 // continued the last debug event. In such cases, The process object will get signalled normally.
11418 // If we didn't just get a native-exitProcess event, then listen on the process handle for exit.
11419 // (this includes all managed-only debugging)
11420 // It's very important to establish this before we go into the WaitForMutlipleObjects below
11421 // because the debuggee may exit while we're sitting in that loop (waiting for the debugger to call Continue).
11422 bool fDidNotJustGetExitProcessEvent = !fEventAvailable || (event.dwDebugEventCode != EXIT_PROCESS_DEBUG_EVENT);
11424 // In non-interop scenarios, we'll never get any native debug events, let alone an ExitProcess native event.
11425 bool fDidNotJustGetExitProcessEvent = true;
11426 #endif // FEATURE_INTEROP_DEBUGGING
11429 // The m_pProcess handle will get nulled out after we process the ExitProcess event, and
11430 // that will ensure that we only wait for an Exit event once.
11431 if ((m_pProcess != NULL) && fDidNotJustGetExitProcessEvent)
11433 rghWaitSet[1] = m_pProcess->UnsafeGetProcessHandle();
11437 // See if any process that we aren't attached to as the Win32 debugger have exited. (Note: this is a
11438 // polling action if we are also waiting for Win32 debugger events. We're also looking at the thread
11439 // control event here, too, to see if we're supposed to do something, like attach.
11440 DWORD dwStatus = WaitForMultipleObjectsEx(cWaitCount, rghWaitSet, FALSE, dwWaitTimeout, FALSE);
11442 _ASSERTE((dwStatus == WAIT_TIMEOUT) || (dwStatus < cWaitCount));
11446 _ASSERTE(m_action == W32ETA_NONE);
11450 LOG((LF_CORDB, LL_INFO100000, "W32ET::W32EL - got event , ret=%d, has w32 dbg event=%d\n",
11451 dwStatus, fEventAvailable));
11453 // If we haven't timed out, or if it wasn't the thread control event
11454 // that was set, then a process has
11456 if ((dwStatus != WAIT_TIMEOUT) && (dwStatus != WAIT_OBJECT_0))
11458 // Grab the process that exited.
11459 _ASSERTE((dwStatus - WAIT_OBJECT_0) == 1);
11460 ExitProcess(false); // not detach
11461 fEventAvailable = false;
11463 // Should we create a process?
11464 else if (m_action == W32ETA_CREATE_PROCESS)
11468 // Should we attach to a process?
11469 else if (m_action == W32ETA_ATTACH_PROCESS)
11473 // Should we detach from a process?
11474 else if (m_action == W32ETA_DETACH)
11476 ExitProcess(true); // detach case
11478 // Once we detach, we don't need to continue any outstanding event.
11479 // So act like we never got the event.
11480 fEventAvailable = false;
11481 PREFIX_ASSUME(m_pProcess == NULL); // W32 cleared process pointer
11484 #ifdef FEATURE_INTEROP_DEBUGGING
11485 // Should we continue the process?
11486 else if (m_action == W32ETA_CONTINUE)
11488 HandleUnmanagedContinue();
11490 #endif // FEATURE_INTEROP_DEBUGGING
11492 // We don't need to sweep the FCH threads since we never hijack a thread in cooperative mode.
11495 // Only process an event if one is available.
11496 if (!fEventAvailable)
11501 // The only ref we have is the one in the ProcessList hash;
11502 // If we dispatch an ExitProcess event, we may even lose that.
11503 // But since the CordbProcess is our parent object, we know it won't go away until
11504 // it neuters us, so we can safely proceed.
11505 // Find the process this event is for.
11506 PREFIX_ASSUME(m_pProcess != NULL);
11507 _ASSERTE(m_pProcess->m_id == GetProcessId(&event)); // should only get events for our proc
11508 g_pRSDebuggingInfo->m_MRUprocess = m_pProcess;
11510 // Must flush the dac cache since we were just running.
11511 m_pProcess->ForceDacFlush();
11513 // So we've filtered out CLR events.
11514 // Let the shim handle the remaining events. This will call back into Filter() if appropriate.
11515 // This will also ensure the debug event gets continued.
11516 HRESULT hrShim = S_OK;
11518 PUBLIC_CALLBACK_IN_THIS_SCOPE0_NO_LOCK(NULL);
11519 hrShim = m_pShim->HandleWin32DebugEvent(&event);
11521 // Any errors from the shim (eg. failure to load DAC) are unrecoverable
11522 SetUnrecoverableIfFailed(m_pProcess, hrShim);
11526 LOG((LF_CORDB, LL_INFO1000, "W32ET::W32EL: exiting event loop\n"));
11531 //---------------------------------------------------------------------------------------
11533 // Returns if the current thread is the win32 thread.
11536 // true iff this is the win32 event thread.
11538 //---------------------------------------------------------------------------------------
11539 bool CordbProcess::IsWin32EventThread()
11541 _ASSERTE((m_pShim != NULL) || !"Don't check win32 event thread in V3 cases");
11542 return m_pShim->IsWin32EventThread();
11545 //---------------------------------------------------------------------------------------
11546 // Call when the sync complete event is received and can be processed.
11549 // This is called when the RS gets the sync-complete from the LS and can process it.
11551 // This has a somewhat elaborate contract to fill between Interop-debugging, Async-Break, draining the
11552 // managed event-queue, and coordinating with the dispatch thread (RCET).
11554 // @dbgtodo - this should eventually get hoisted into the shim.
11555 void CordbProcess::HandleSyncCompleteRecieved()
11557 _ASSERTE(ThreadHoldsProcessLock());
11559 this->SetSyncCompleteRecv(true);
11561 // If some thread is waiting for the process to sync, notify that it can go now.
11562 if (this->m_stopRequested)
11564 this->SetSynchronized(true);
11565 SetEvent(this->m_stopWaitEvent);
11569 // Note: we set the m_stopWaitEvent all the time and leave it high while we're stopped. This
11570 // must be done after we've checked m_stopRequested.
11571 SetEvent(this->m_stopWaitEvent);
11573 // Otherwise, simply mark that the state of the process has changed and let the
11574 // managed event dispatch logic take over.
11576 // Note: process->m_synchronized remains false, which indicates to the RC event
11577 // thread that it can dispatch the next managed event.
11578 m_cordb->ProcessStateChanged();
11583 #ifdef FEATURE_INTEROP_DEBUGGING
11585 // Get a Thread's _user_ starting address (the real starting address may be some
11587 // This may return NULL for the Async-Break thread.
11588 void* GetThreadUserStartAddr(const DEBUG_EVENT* pCreateThreadEvent)
11590 // On Win7 and above, we can trust the lpStartAddress field of the CREATE_THREAD_DEBUG_EVENT
11591 // to be the user start address (the actual OS start address is an implementation detail that
11592 // doesn't need to be exposed to users). Note that we are assuming that the target process
11593 // is running on Win7 if mscordbi is. If we ever have some remoting scenario where the target
11594 // can run on a different windows machine with a different OS version we will need a way to
11595 // determine the target's OS version
11596 if(RunningOnWin7())
11598 return pCreateThreadEvent->u.CreateThread.lpStartAddress;
11601 // On pre-Win7 OSes, we rely on an OS implementation detail to get the real user thread start:
11602 // it exists in EAX at thread start time.
11603 // Note that for a brief period of time there was a GetThreadStartInformation API in Longhorn
11604 // we could use for this, but it was removed during the Longhorn reset.
11605 HANDLE hThread = pCreateThreadEvent->u.CreateThread.hThread;
11606 #if defined(DBG_TARGET_X86)
11607 // Grab the thread's context.
11609 c.ContextFlags = DT_CONTEXT_FULL;
11610 BOOL succ = DbiGetThreadContext(hThread, &c);
11614 return (void*) c.Eax;
11616 #elif defined(DBG_TARGET_AMD64)
11618 c.ContextFlags = DT_CONTEXT_FULL;
11619 BOOL succ = DbiGetThreadContext(hThread, &c);
11623 return (void*) c.Rcx;
11626 PORTABILITY_ASSERT("port GetThreadUserStartAddr");
11633 //---------------------------------------------------------------------------------------
11635 // Get (create if needed) the unmanaged thread for an unmanaged debug event.
11638 // event - native debug event.
11641 // Unmanaged thread corresponding to the native debug event.
11645 // Thread may be newly allocated, or may be existing. CordbProcess holds
11646 // list of all CordbUnmanagedThreads, and will handle freeing memory.
11648 //---------------------------------------------------------------------------------------
11649 CordbUnmanagedThread * CordbProcess::GetUnmanagedThreadFromEvent(const DEBUG_EVENT * pEvent)
11651 _ASSERTE(ThreadHoldsProcessLock());
11654 CordbUnmanagedThread * pUnmanagedThread = NULL;
11656 // Remember newly created threads.
11657 if (pEvent->dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
11659 // We absolutely should have an unmanaged callback by this point.
11660 // That means that the client debugger should have called ICorDebug::SetUnmanagedHandler by now.
11661 // However, we can't actually enforce that (see comment in ICorDebug::SetUnmanagedHandler for details),
11662 // so we do a runtime check to check this.
11663 // This is an extremely gross API misuse and an issue in the client if the callback is not set yet.
11664 // Without the unmanaged callback, we absolutely can't do interop-debugging. We assert (checked builds) and
11665 // dispatch unrecoverable error (retail builds) to avoid an AV.
11668 if (this->m_cordb->m_unmanagedCallback == NULL)
11670 CONSISTENCY_CHECK_MSGF((this->m_cordb->m_unmanagedCallback != NULL),
11671 ("GROSS API misuse!!\nNo unmanaged callback set by the time we've received CreateProcess debug event for proces 0x%x.\n",
11672 pEvent->dwProcessId));
11674 CORDBSetUnrecoverableError(this, CORDBG_E_INTEROP_NOT_SUPPORTED, 0);
11676 // Returning NULL will tell caller not to dispatch event to client. We have no callback object to dispatch upon.
11680 pUnmanagedThread = this->HandleUnmanagedCreateThread(pEvent->dwThreadId,
11681 pEvent->u.CreateProcessInfo.hThread,
11682 pEvent->u.CreateProcessInfo.lpThreadLocalBase);
11684 // Managed-attach won't start until after Cordbg continues from the loader-bp.
11686 else if (pEvent->dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT)
11688 pUnmanagedThread = this->HandleUnmanagedCreateThread(pEvent->dwThreadId,
11689 pEvent->u.CreateThread.hThread,
11690 pEvent->u.CreateThread.lpThreadLocalBase);
11692 BOOL fBlockExists = FALSE;
11696 // See if we have the debugger control block yet...
11698 this->GetEventBlock(&fBlockExists);
11700 // If we have the debugger control block, and if that control block has the address of the thread proc for
11701 // the helper thread, then we're initialized enough on the Left Side to recgonize the helper thread based on
11702 // its thread proc's address.
11703 if (this->GetDCB() != NULL)
11705 // get the latest LS DCB information
11706 UpdateRightSideDCB();
11707 if ((this->GetDCB()->m_helperThreadStartAddr != NULL) && (pUnmanagedThread != NULL))
11709 void * pStartAddr = GetThreadUserStartAddr(pEvent);
11711 if (pStartAddr == this->GetDCB()->m_helperThreadStartAddr)
11713 // Remember the ID of the helper thread.
11714 this->m_helperThreadId = pEvent->dwThreadId;
11716 LOG((LF_CORDB, LL_INFO1000, "W32ET::W32EL: Left Side Helper Thread is 0x%x\n", pEvent->dwThreadId));
11721 EX_CATCH_HRESULT(hr)
11723 if (fBlockExists && FAILED(hr))
11725 _ASSERTE(IsLegalFatalError(hr));
11726 // Send up the DebuggerError event
11727 this->UnrecoverableError(hr, 0, NULL, 0);
11729 // Kill the process.
11730 // RS will pump events until we LS process exits.
11731 TerminateProcess(this->m_handle, hr);
11733 return pUnmanagedThread;
11739 // Find the unmanaged thread that this event is for.
11740 pUnmanagedThread = this->GetUnmanagedThread(pEvent->dwThreadId);
11743 return pUnmanagedThread;
11746 //---------------------------------------------------------------------------------------
11748 // Handle a native-debug event representing a managed sync-complete event.
11752 // Reaction telling caller how to respond to the native-debug event.
11755 // Called within the Triage process after receiving a native-debug event.
11757 //---------------------------------------------------------------------------------------
11758 Reaction CordbProcess::TriageSyncComplete()
11760 _ASSERTE(ThreadHoldsProcessLock());
11762 STRESS_LOG0(LF_CORDB, LL_INFO1000, "CP::TSC: received 'sync complete' flare.\n");
11764 _ASSERTE(IsInteropDebugging());
11766 // Note: we really don't need to be suspending Runtime threads that we know have tripped
11767 // here. If we ever end up with a nice, quick way to know that about each unmanaged thread, then
11768 // we should put that to good use here.
11769 this->SuspendUnmanagedThreads();
11771 this->HandleSyncCompleteRecieved();
11773 // Let the process run free.
11774 return REACTION(cIgnore);
11776 // At this point, all managed threads are stopped at safe places and all unmanaged
11777 // threads are either suspended or hijacked. All stopped managed threads are also hard
11778 // suspended (due to the call to SuspendUnmanagedThreads above) except for the thread
11779 // that sent the sync complete flare.
11781 // We've handled this exception, so skip all further processing.
11785 //-----------------------------------------------------------------------------
11786 // Triage a breakpoint (non-flare) on a "normal" thread.
11787 //-----------------------------------------------------------------------------
11788 Reaction CordbProcess::TriageBreakpoint(CordbUnmanagedThread * pUnmanagedThread, const DEBUG_EVENT * pEvent)
11790 _ASSERTE(ThreadHoldsProcessLock());
11794 DWORD dwExCode = pEvent->u.Exception.ExceptionRecord.ExceptionCode;
11795 const void * pExAddress = pEvent->u.Exception.ExceptionRecord.ExceptionAddress;
11797 _ASSERTE(dwExCode == STATUS_BREAKPOINT);
11799 // There are three cases here:
11801 // 1. The breakpoint definetly belongs to the Runtime. (I.e., a BP in our patch table that
11802 // is in managed code.) In this case, we continue the process with
11803 // DBG_EXCEPTION_NOT_HANDLED, which lets the in-process exception logic kick in as if we
11806 // 2. The breakpoint is definetly not ours. (I.e., a BP that is not in our patch table.) We
11807 // pass these up as regular exception events, doing the can't stop check as usual.
11809 // 3. We're not sure. (I.e., a BP in our patch table, but set in unmangaed code.) In this
11810 // case, we hijack as usual, also with can't stop check as usual.
11812 bool fPatchFound = false;
11813 bool fPatchIsUnmanaged = false;
11815 hr = this->FindPatchByAddress(PTR_TO_CORDB_ADDRESS(pExAddress),
11817 &fPatchIsUnmanaged);
11824 // What if managed & native patch the same address? That could happen on a step out M --> U.
11826 NativePatch * pNativePatch = GetNativePatch(pExAddress);
11827 SIMPLIFYING_ASSUMPTION_MSGF(pNativePatch == NULL, ("Have Managed & native patch at 0x%p", pExAddress));
11831 // BP could be ours... if its unmanaged, then we still need to hijack, so fall
11832 // through to that logic. Otherwise, its ours.
11833 if (!fPatchIsUnmanaged)
11835 LOG((LF_CORDB, LL_INFO1000, "W32ET::W32EL: breakpoint exception "
11836 "belongs to runtime due to patch table match.\n"));
11838 return REACTION(cCLR);
11842 LOG((LF_CORDB, LL_INFO1000, "W32ET::W32EL: breakpoint exception "
11843 "matched in patch table, but its unmanaged so might hijack anyway.\n"));
11845 // If we're in cooperative mode, then we must have a inproc handler, and don't need to hijack
11846 // One way this can happen is the patch placed for a func-eval complete is hit in coop-mode.
11847 if (pUnmanagedThread->GetEEPGCDisabled())
11849 LOG((LF_CORDB, LL_INFO10000, "Already in coop-mode, don't need to hijack\n"));
11850 return REACTION(cCLR);
11854 return REACTION(cBreakpointRequiringHijack);
11860 else // Patch not found
11862 // If we're here, then we have a BP that's not in the managed patch table, and not
11863 // in the native patch list. This should be rare. Perhaps an int3 / DebugBreak() / Assert in
11864 // the native code stream.
11865 // Anyway, we don't know about this patch so we can't skip it. The only thing we can do
11866 // is chuck it up to Cordbg and hope they can help us. Note that this is the same case
11867 // we were in w. V1.
11869 // BP doesn't belong to CLR ... so dispatch it to Cordbg as either make it IB or OOB.
11870 // @todo - make the runtime 1 giant Can't stop region.
11871 bool fCantStop = pUnmanagedThread->IsCantStop();
11874 // We rarely expect a raw int3 here. Add a debug check that will assert.
11875 // Tests that know they don't have raw int3 can enable this regkey to get
11877 static DWORD s_fBreakOnRawInt3 = -1;
11879 if (s_fBreakOnRawInt3 == -1)
11880 s_fBreakOnRawInt3 = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgBreakOnRawInt3);
11882 if (s_fBreakOnRawInt3)
11884 CONSISTENCY_CHECK_MSGF(false, ("Unexpected Raw int3 at:%p on tid 0x%x (%d). CantStop=%d."
11885 "This assert is used by specific tests to get extra checks."
11886 "For normal cases it's ignorable and is enabled by setting DbgBreakOnRawInt3==1.",
11887 pExAddress, pEvent->dwThreadId, pEvent->dwThreadId, fCantStop));
11893 // If we're in a can't stop region, then its OOB no matter what at this point.
11894 return REACTION(cOOB);
11898 // PGC must be enabled if we're going to stop for an IB event.
11899 bool PGCDisabled = pUnmanagedThread->GetEEPGCDisabled();
11900 _ASSERTE(!PGCDisabled);
11902 // Bp is definitely not ours, and PGC is not disabled, so in-band exception.
11903 LOG((LF_CORDB, LL_INFO1000, "W32ET::W32EL: breakpoint exception "
11904 "does not belong to the runtime due to failed patch table match.\n"));
11906 return REACTION(cInband);
11916 // Patch table lookup failed? Only on OOM or if ReadProcessMemory fails...
11917 _ASSERTE(!"Patch table lookup failed!");
11918 CORDBSetUnrecoverableError(this, hr, 0);
11919 return REACTION(cOOB);
11925 //---------------------------------------------------------------------------------------
11927 // Triage a "normal" 1st chance exception on a "normal" thread.
11928 // Not hijacked, not the helper thread, not a flare, etc.. This is the common
11929 // case for a native exception from native code.
11932 // pUnmanagedThread - Pointer to the CordbUnmanagedThread object that we want to hijack.
11933 // pEvent - Pointer to the debug event which contains the exception code and address.
11936 // The Reaction tells if the event is in-band, out-of-band, CLR specific or ignorable.
11938 //---------------------------------------------------------------------------------------
11939 Reaction CordbProcess::Triage1stChanceNonSpecial(CordbUnmanagedThread * pUnmanagedThread, const DEBUG_EVENT * pEvent)
11941 _ASSERTE(ThreadHoldsProcessLock());
11950 DWORD dwExCode = pEvent->u.Exception.ExceptionRecord.ExceptionCode;
11951 const void * pExAddress = pEvent->u.Exception.ExceptionRecord.ExceptionAddress;
11953 // This had better not be a flare. If it is, that means we have some race that unmarked
11955 _ASSERTE(!ExceptionIsFlare(dwExCode, pExAddress));
11957 // Any first chance exception could belong to the Runtime, so long as the Runtime has actually been
11958 // initialized. Here we'll setup a first-chance hijack for this thread so that it can give us the
11959 // true answer that we need.
11961 // But none of those exceptions could possibly be ours unless we have a managed thread to go with
11962 // this unmanaged thread. A non-NULL EEThreadPtr tells us that there is indeed a managed thread for
11963 // this unmanaged thread, even if the Right Side hasn't received a managed ThreadCreate message yet.
11964 REMOTE_PTR pEEThread;
11965 hr = pUnmanagedThread->GetEEThreadPtr(&pEEThread);
11966 _ASSERTE(SUCCEEDED(hr));
11968 if (pEEThread == NULL)
11970 // No managed thread, so it can't possibly belong to the runtime!
11971 // But it may still be in a can't-stop region (think some goofy shutdown case).
11972 if (pUnmanagedThread->IsCantStop())
11974 return REACTION(cOOB);
11978 return REACTION(cInband);
11984 // We have to be careful here. A Runtime thread may be in a place where we cannot let an
11985 // unmanaged exception stop it. For instance, an unmanaged user breakpoint set on
11986 // WaitForSingleObject will prevent Runtime threads from sending events to the Right Side. So at
11987 // various points below, we check to see if this Runtime thread is in a place were we can't let
11988 // it stop, and if so then we jump over to the out-of-band dispatch logic and treat this
11989 // exception as out-of-band. The debugger is supposed to continue from the out-of-band event
11990 // properly and help us avoid this problem altogether.
11992 // Grab a few flags from the thread's state...
11993 bool fThreadStepping = false;
11994 bool fSpecialManagedException = false;
11996 pUnmanagedThread->GetEEState(&fThreadStepping, &fSpecialManagedException);
11998 // If we've got a single step exception, and if the Left Side has indicated that it was
11999 // stepping the thread, then the exception is ours.
12000 if (dwExCode == STATUS_SINGLE_STEP)
12002 if (fThreadStepping)
12004 // Yup, its the Left Side that was stepping the thread...
12005 STRESS_LOG0(LF_CORDB, LL_INFO1000, "W32ET::W32EL: single step exception belongs to the runtime.\n");
12007 return REACTION(cCLR);
12010 // Any single step that is triggered when the thread's state doesn't indicate that
12011 // we were stepping the thread automatically gets passed out as an unmanged event.
12012 STRESS_LOG0(LF_CORDB, LL_INFO1000, "W32ET::W32EL: single step exception "
12013 "does not belong to the runtime.\n");
12015 if (pUnmanagedThread->IsCantStop())
12017 return REACTION(cOOB);
12021 return REACTION(cInband);
12027 #ifdef CorDB_Short_Circuit_First_Chance_Ownership
12028 // If the runtime indicates that this is a special exception being thrown within the runtime,
12029 // then its ours no matter what.
12030 else if (fSpecialManagedException)
12032 STRESS_LOG0(LF_CORDB, LL_INFO1000, "W32ET::W32EL: exception belongs to the runtime due to "
12033 "special managed exception marking.\n");
12035 return REACTION(cCLR);
12037 else if ((dwExCode == EXCEPTION_COMPLUS) || (dwExCode == EXCEPTION_HIJACK))
12039 STRESS_LOG0(LF_CORDB, LL_INFO1000,
12040 "W32ET::W32EL: exception belongs to Runtime due to match on built in exception code\n");
12042 return REACTION(cCLR);
12044 else if (dwExCode == EXCEPTION_MSVC)
12046 // The runtime may use C++ exceptions internally. We can still report these
12047 // to the debugger as long as we're outside of a can't-stop region.
12048 if (pUnmanagedThread->IsCantStop())
12050 return REACTION(cCLR);
12054 return REACTION(cInband);
12057 else if (dwExCode == STATUS_BREAKPOINT)
12059 return TriageBreakpoint(pUnmanagedThread, pEvent);
12063 // It's not a breakpoint or single-step. Now it just comes down to the address from where
12064 // the exception is coming from. If it's managed, we give it back to the CLR. If it's
12065 // from native, then we dispatch to Cordbg.
12066 // We can use DAC to figure this out from Out-of-process.
12067 _ASSERTE(dwExCode != STATUS_BREAKPOINT); // BP were already handled.
12070 // Use DAC to decide if it's ours or not w/o going inproc.
12071 CORDB_ADDRESS address = PTR_TO_CORDB_ADDRESS(pExAddress);
12073 IDacDbiInterface::AddressType addrType;
12075 addrType = GetDAC()->GetAddressType(address);
12076 bool fIsCorCode =((addrType == IDacDbiInterface::kAddressManagedMethod) ||
12077 (addrType == IDacDbiInterface::kAddressRuntimeManagedCode) ||
12078 (addrType == IDacDbiInterface::kAddressRuntimeUnmanagedCode));
12080 STRESS_LOG2(LF_CORDB, LL_INFO1000, "W32ET::W32EL: IsCorCode(0x%I64p)=%d\n", address, fIsCorCode);
12085 return REACTION(cCLR);
12089 if (pUnmanagedThread->IsCantStop())
12091 return REACTION(cOOB);
12095 return REACTION(cInband);
12102 //---------------------------------------------------------------------------------------
12104 // Triage a 1st-chance exception when the CLR is initialized.
12107 // pUnmanagedThread - thread that the event has occurred on.
12108 // pEvent - native debug event for the exception that occurred that this is triaging.
12111 // Reaction for how to handle this event.
12114 // Called when receiving a debug event when the process is stopped.
12117 // A 1st-chance event has a wide spectrum of possibility including:
12118 // - It may be unmanaged or managed.
12119 // - Or it may be an execution control exception for managed-exceution
12120 // - thread skipping an OOB event.
12122 //---------------------------------------------------------------------------------------
12123 Reaction CordbProcess::TriageExcep1stChanceAndInit(CordbUnmanagedThread * pUnmanagedThread,
12124 const DEBUG_EVENT * pEvent)
12126 _ASSERTE(ThreadHoldsProcessLock());
12127 _ASSERTE(m_runtimeOffsetsInitialized);
12129 NativePatch * pNativePatch = NULL;
12130 DebuggerIPCRuntimeOffsets * pIPCRuntimeOffsets = &(this->m_runtimeOffsets);
12132 DWORD dwExCode = pEvent->u.Exception.ExceptionRecord.ExceptionCode;
12133 const void * pExAddress = pEvent->u.Exception.ExceptionRecord.ExceptionAddress;
12137 // Some Interop bugs involve threads that land at a crazy IP. Since we're interop-debugging, we can't
12138 // attach a debugger to the LS. So we have some debug mode where we enable the SS flag and thus
12139 // produce a trace of where a thread is going.
12140 if (pUnmanagedThread->IsDEBUGTrace() && (dwExCode == STATUS_SINGLE_STEP))
12142 pUnmanagedThread->ClearState(CUTS_DEBUG_SingleStep);
12143 LOG((LF_CORDB, LL_INFO10000, "DEBUG TRACE, thread %4x at IP: 0x%p\n", pUnmanagedThread->m_id, pExAddress));
12145 // Clear the exception and pretend this never happened.
12146 return REACTION(cIgnore);
12150 // If we were stepping for exception retrigger and got the single step and it should be hidden then just ignore it.
12151 // Anything that isn't cInbandExceptionRetrigger will cause the debug event to be dequeued, stepping turned off, and
12152 // it will count as not retriggering
12153 // TODO: I don't think the IsSSFlagNeeded() check is needed here though it doesn't break anything
12154 if (pUnmanagedThread->IsSSFlagNeeded() && pUnmanagedThread->IsSSFlagHidden() && (dwExCode == STATUS_SINGLE_STEP))
12156 LOG((LF_CORDB, LL_INFO10000, "CP::TE1stCAI: ignoring hidden single step\n"));
12157 return REACTION(cIgnore);
12160 // Is this a breakpoint indicating that the Left Side is now synchronized?
12161 if ((dwExCode == STATUS_BREAKPOINT) &&
12162 (pExAddress == pIPCRuntimeOffsets->m_notifyRSOfSyncCompleteBPAddr))
12164 return TriageSyncComplete();
12166 else if ((dwExCode == STATUS_BREAKPOINT) &&
12167 (pExAddress == pIPCRuntimeOffsets->m_excepForRuntimeHandoffCompleteBPAddr))
12169 _ASSERTE(!"This should be unused now");
12171 // This notification means that a thread that had been first-chance hijacked is now
12172 // finally leaving the hijack.
12173 STRESS_LOG0(LF_CORDB, LL_INFO1000, "CP::TE1stCAI: received 'first chance hijack handoff complete' flare.\n");
12175 // Let the process run.
12176 return REACTION(cIgnore);
12178 else if ((dwExCode == STATUS_BREAKPOINT) &&
12179 (pExAddress == pIPCRuntimeOffsets->m_signalHijackCompleteBPAddr))
12181 STRESS_LOG0(LF_CORDB, LL_INFO1000, "CP::TE1stCAI: received 'hijack complete' flare.\n");
12182 return REACTION(cInbandHijackComplete);
12184 else if ((dwExCode == STATUS_BREAKPOINT) &&
12185 (pExAddress == m_runtimeOffsets.m_signalHijackStartedBPAddr))
12187 STRESS_LOG0(LF_CORDB, LL_INFO1000, "CP::TE1stCAI: received 'hijack started' flare.\n");
12188 return REACTION(cFirstChanceHijackStarted);
12190 else if ((dwExCode == STATUS_BREAKPOINT) && ((pNativePatch = GetNativePatch(pExAddress)) != NULL) )
12192 // We hit a native BP placed by Cordbg. This could happen on any thread (including helper)
12193 bool fCantStop = pUnmanagedThread->IsCantStop();
12195 // REVISIT_TODO: if the user also set a breakpoint here then we should dispatch to the debugger
12196 // and rely on the debugger to get us past this. Should be a rare case though.
12199 // Need to skip it completely; never dispatch.
12200 pUnmanagedThread->SetupForSkipBreakpoint(pNativePatch);
12202 // Debuggee will single step over the patch, and fire a SS exception.
12203 // We'll then call FixupForSkipBreakpoint, and continue the process.
12204 return REACTION(cIgnore);
12208 // Native patch in native code. A very common scenario.
12209 // Dispatch as an IB event to Cordbg.
12210 STRESS_LOG1(LF_CORDB, LL_INFO10000, "Native patch in native code (at %p), dispatching as IB event.\n", pExAddress);
12211 return REACTION(cInband);
12217 else if ((dwExCode == STATUS_BREAKPOINT) && !IsBreakOpcodeAtAddress(pExAddress))
12219 // If we got an int3 exception, but there's not actually an int3 at the address, then just reset the IP
12220 // to the address. This can happen if the int 3 is cleared after the thread has dispatched it (in which case
12221 // WFDE will pick it up) but before we realize it's one of ours.
12222 STRESS_LOG2(LF_CORDB, LL_INFO1000, "CP::TE1stCAI: Phantom Int3: Tid=0x%x, addr=%p\n", pEvent->dwThreadId, pExAddress);
12224 DT_CONTEXT context;
12226 context.ContextFlags = DT_CONTEXT_FULL;
12228 BOOL fSuccess = DbiGetThreadContext(pUnmanagedThread->m_handle, &context);
12230 _ASSERTE(fSuccess);
12234 // Backup IP to point to the instruction we need to execute. Continuing from a breakpoint exception
12235 // continues execution at the instruction after the breakpoint, but we need to continue where the
12237 CORDbgSetIP(&context, (LPVOID) pExAddress);
12239 fSuccess = DbiSetThreadContext(pUnmanagedThread->m_handle, &context);
12240 _ASSERTE(fSuccess);
12243 return REACTION(cIgnore);
12245 else if (pUnmanagedThread->IsSkippingNativePatch())
12247 // If we Single-Step over an exception, then the OS never gives us the single-step event.
12248 // Thus if we're skipping a native patch, we don't care what exception event we got.
12249 LOG((LF_CORDB, LL_INFO100000, "Done skipping native patch. Ex=0x%x\n, IsSS=%d",
12251 (dwExCode == STATUS_SINGLE_STEP)));
12253 // This is the 2nd half of skipping a native patch.
12254 // This could happen on any thread (including helper)
12255 // We've already removed the opcode and now we just finished a single-step over it.
12256 // So put the patch back in, and continue the process.
12257 pUnmanagedThread->FixupForSkipBreakpoint();
12259 return REACTION(cIgnore);
12261 else if (this->IsHelperThreadWorked(pUnmanagedThread->GetOSTid()))
12263 // We should never ever get a single-step event from the helper thread.
12264 CONSISTENCY_CHECK_MSGF(dwExCode != STATUS_SINGLE_STEP, (
12265 "Single-Step exception on helper thread (tid=0x%x/%d) in debuggee process (pid=0x%x/%d).\n"
12266 "For more information, attach a debuggee non-invasively to the LS to get the callstack.\n",
12267 pUnmanagedThread->m_id,
12268 pUnmanagedThread->m_id,
12272 // We ignore any first chance exceptions from the helper thread. There are lots of places
12273 // on the left side where we attempt to dereference bad object refs and such that will be
12274 // handled by exception handlers already in place.
12276 // Note: we check this after checking for the sync complete notification, since that can
12277 // come from the helper thread.
12279 // Note: we do let single step and breakpoint exceptions go through to the debugger for processing.
12280 if ((dwExCode != STATUS_BREAKPOINT) && (dwExCode != STATUS_SINGLE_STEP))
12282 return REACTION(cCLR);
12286 // Since the helper thread is part of the "can't stop" region, we should have already
12287 // skipped any BPs on it.
12288 // However, any Assert on the helper thread will hit this case.
12289 CONSISTENCY_CHECK_MSGF((dwExCode != STATUS_BREAKPOINT), (
12290 "Assert on helper thread (tid=0x%x/%d) in debuggee process (pid=0x%x/%d).\n"
12291 "For more information, attach a debuggee non-invasively to the LS to get the callstack.\n",
12292 pUnmanagedThread->m_id,
12293 pUnmanagedThread->m_id,
12297 // These breakpoint and single step exceptions have to be dispatched to the debugger as
12298 // out-of-band events. This tells the debugger that they must continue from these events
12299 // immediatly, and that no interaction with the Left Side is allowed until they do so. This
12300 // makes sense, since these events are on the helper thread.
12301 return REACTION(cOOB);
12305 else if (pUnmanagedThread->IsFirstChanceHijacked() && this->ExceptionIsFlare(dwExCode, pExAddress))
12307 _ASSERTE(!"This should be unused now");
12309 else if (pUnmanagedThread->IsGenericHijacked())
12311 if (this->ExceptionIsFlare(dwExCode, pExAddress))
12313 STRESS_LOG0(LF_CORDB, LL_INFO1000, "CP::TE1stCAI: fixing up from generic hijack.\n");
12315 _ASSERTE(dwExCode == STATUS_BREAKPOINT);
12317 // Fixup the thread from the generic hijack.
12318 pUnmanagedThread->FixupFromGenericHijack();
12320 // We force continue from this flare, since its only purpose was to notify us that we had to
12321 // fixup the thread from a generic hijack.
12322 return REACTION(cIgnore);
12326 // We might reach here due to the stack overflow issue, due to target
12327 // memory corruption, or even due to an exception thrown during hijacking
12329 BOOL bStackOverflow = FALSE;
12331 if (dwExCode == STATUS_ACCESS_VIOLATION || dwExCode == STATUS_STACK_OVERFLOW)
12333 CORDB_ADDRESS stackLimit;
12334 CORDB_ADDRESS stackBase;
12335 if (pUnmanagedThread->GetStackRange(&stackBase, &stackLimit))
12337 TADDR addr = pEvent->u.Exception.ExceptionRecord.ExceptionInformation[1];
12338 if (stackLimit <= addr && addr < stackBase)
12339 bStackOverflow = TRUE;
12343 // to limit the impact of the change we'll consider failure to retrieve the stack
12344 // bounds as stack overflow as well
12345 bStackOverflow = TRUE;
12349 if (!bStackOverflow)
12351 // generic hijack means we're in CantStop, so return cOOB
12352 return REACTION(cOOB);
12355 // If generichijacked and its not a flare, and the address referenced is on the stack then we've
12356 // got our special stack overflow case. Take off generic hijacked, mark that the helper thread
12357 // is dead, throw this event on the floor, and pop anyone in SendIPCEvent out of their wait.
12358 pUnmanagedThread->ClearState(CUTS_GenericHijacked);
12360 this->m_helperThreadDead = true;
12362 // This only works on Windows, not on Mac. We don't support interop-debugging on Mac anyway.
12363 SetEvent(m_pEventChannel->GetRightSideEventAckHandle());
12365 // Note: we remember that this was a second chance event from one of the special stack overflow
12366 // cases with CUES_ExceptionUnclearable. This tells us to force the process to terminate when we
12367 // continue from the event. Since for some odd reason the OS decides to re-raise this exception
12368 // (first chance then second chance) infinitely.
12370 _ASSERTE(pUnmanagedThread->HasIBEvent());
12372 pUnmanagedThread->IBEvent()->SetState(CUES_ExceptionUnclearable);
12374 //newEvent = false;
12375 return REACTION(cInband_NotNewEvent);
12380 Reaction r(REACTION(cOOB));
12381 HRESULT hrCheck = S_OK;;
12384 r = Triage1stChanceNonSpecial(pUnmanagedThread, pEvent);
12386 EX_CATCH_HRESULT(hrCheck);
12387 SIMPLIFYING_ASSUMPTION(SUCCEEDED(hrCheck));
12388 SetUnrecoverableIfFailed(this, hrCheck);
12394 // At this point, any first-chance exceptions that could be special have been handled. Any
12395 // first-chance exception that we're still processing at this point is destined to be
12396 // dispatched as an unmanaged event.
12401 //---------------------------------------------------------------------------------------
12403 // Triage a 2nd-chance exception when the CLR is initialized.
12406 // pUnmanagedThread - thread that the event has occurred on.
12407 // pEvent - native debug event for the exception that occurred that this is triaging.
12410 // Reaction for how to handle this event.
12413 // Called when receiving a debug event when the process is stopped.
12416 // We already hijacked 2nd-chance managed exceptions, so this is just handling
12417 // some V2 Interop corner cases.
12418 // @dbgtodo interop: this should eventually completely go away with the V3 design.
12420 //---------------------------------------------------------------------------------------
12421 Reaction CordbProcess::TriageExcep2ndChanceAndInit(CordbUnmanagedThread * pUnmanagedThread, const DEBUG_EVENT * pEvent)
12423 _ASSERTE(ThreadHoldsProcessLock());
12425 DWORD dwExCode = pEvent->u.Exception.ExceptionRecord.ExceptionCode;
12428 // For debugging, add an extra knob that let us break on any 2nd chance exceptions.
12429 // Most tests don't throw 2nd-chance, so we could have this enabled most of the time and
12430 // catch bogus 2nd chance exceptions
12431 static DWORD dwNo2ndChance = -1;
12433 if (dwNo2ndChance == -1)
12435 dwNo2ndChance = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgNo2ndChance);
12440 CONSISTENCY_CHECK_MSGF(false, ("2nd chance exception occurred on LS thread=0x%x, code=0x%08x, address=0x%p\n"
12441 "This assert is firing b/c you explicitly requested it by having the 'DbgNo2ndChance' knob enabled.\n"
12442 "Disable it to avoid asserts on 2nd chance.",
12443 pUnmanagedThread->m_id,
12445 pEvent->u.Exception.ExceptionRecord.ExceptionAddress));
12450 // Second chance exception, Runtime initialized. It could belong to the Runtime, so we'll check. If it
12451 // does, then we'll hijack the thread. Otherwise, well just fall through and let it get
12452 // dispatched. Note: we do this so that the CLR's unhandled exception logic gets a chance to run even
12453 // though we've got a win32 debugger attached. But the unhandled exception logic never touches
12454 // breakpoint or single step exceptions, so we ignore those here, too.
12456 // There are strange cases with stack overflow exceptions. If a nieve application catches a stack
12457 // overflow exception and handles it, without resetting the guard page, then the app will get an AV when
12458 // it overflows the stack a second time. We will get the first chance AV, but when we continue from it the
12459 // OS won't run any SEH handlers, so our FCH won't actually work. Instead, we'll get the AV back on
12460 // second chance right away, and we'll end up right here.
12461 if (this->IsSpecialStackOverflowCase(pUnmanagedThread, pEvent))
12463 // IsSpecialStackOverflowCase will queue the event for us, so its no longer a "new event". Setting
12464 // newEvent = false here basically prevents us from playing with the event anymore and we fall down
12465 // to the dispatch logic below, which will get our already queued first chance AV dispatched for
12467 //newEvent = false;
12468 return REACTION(cInband_NotNewEvent);
12470 else if (this->IsHelperThreadWorked(pUnmanagedThread->GetOSTid()))
12472 // A second chance exception from the helper thread. This is pretty bad... we just force continue
12473 // from them and hope for the best.
12474 return REACTION(cCLR);
12477 if(pUnmanagedThread->IsCantStop())
12479 return REACTION(cOOB);
12483 return REACTION(cInband);
12488 //---------------------------------------------------------------------------------------
12490 // Triage a win32 Debug event to get a reaction
12493 // pUnmanagedThread - thread that the event has occurred on.
12494 // pEvent - native debug event for the exception that occurred that this is triaging.
12497 // Reaction for how to handle this event.
12500 // Called when receiving a debug event when the process is stopped.
12503 // This is the main triage routine for Win32 debug events, this delegates to the
12504 // 1st and 2nd chance routines above appropriately.
12506 //---------------------------------------------------------------------------------------
12507 Reaction CordbProcess::TriageWin32DebugEvent(CordbUnmanagedThread * pUnmanagedThread, const DEBUG_EVENT * pEvent)
12509 _ASSERTE(ThreadHoldsProcessLock());
12511 // Lots of special cases for exception events. The vast majority of hybrid debugging work that takes
12512 // place is in response to exception events. The work below will consider certian exception events
12513 // special cases and rather than letting them be queued and dispatched, they will be handled right
12515 if (pEvent->dwDebugEventCode == EXCEPTION_DEBUG_EVENT)
12517 STRESS_LOG4(LF_CORDB, LL_INFO1000, "CP::TW32DE: unmanaged exception on "
12518 "tid 0x%x, code 0x%08x, addr 0x%08x, chance %d\n",
12519 pEvent->dwThreadId,
12520 pEvent->u.Exception.ExceptionRecord.ExceptionCode,
12521 pEvent->u.Exception.ExceptionRecord.ExceptionAddress,
12522 2-pEvent->u.Exception.dwFirstChance);
12525 if (pEvent->u.Exception.ExceptionRecord.ExceptionCode == STATUS_ACCESS_VIOLATION)
12527 LOG((LF_CORDB, LL_INFO1000, "\t<%s> address 0x%08x\n",
12528 pEvent->u.Exception.ExceptionRecord.ExceptionInformation[0] ? "write to" : "read from",
12529 pEvent->u.Exception.ExceptionRecord.ExceptionInformation[1]));
12533 // Mark the loader bp for kicks. We won't start managed attach until native attach is finished.
12534 if (!this->m_loaderBPReceived)
12536 // If its a first chance breakpoint, and its the first one, then its the loader breakpoint.
12537 if (pEvent->u.Exception.dwFirstChance &&
12538 (pEvent->u.Exception.ExceptionRecord.ExceptionCode == STATUS_BREAKPOINT))
12540 LOG((LF_CORDB, LL_INFO1000, "CP::TW32DE: loader breakpoint received.\n"));
12542 // Remember that we've received the loader BP event.
12543 this->m_loaderBPReceived = true;
12545 // We never hijack the loader BP anymore (CLR 2.0+).
12546 // This is b/c w/ interop-attach, we don't start the managed-attach until _after_ Cordbg
12547 // continues from the loader-bp.
12549 } // end of loader bp.
12551 // This event might be the retriggering of an event we already saw but previously had to hijack
12552 if(pUnmanagedThread->HasIBEvent())
12554 const EXCEPTION_RECORD* pRecord1 = &(pEvent->u.Exception.ExceptionRecord);
12555 const EXCEPTION_RECORD* pRecord2 = &(pUnmanagedThread->IBEvent()->m_currentDebugEvent.u.Exception.ExceptionRecord);
12556 if(pRecord1->ExceptionCode == pRecord2->ExceptionCode &&
12557 pRecord1->ExceptionFlags == pRecord2->ExceptionFlags &&
12558 pRecord1->ExceptionAddress == pRecord2->ExceptionAddress)
12560 STRESS_LOG0(LF_CORDB, LL_INFO1000, "CP::TW32DE: event is continuation of previously hijacked event.\n");
12561 // if we continued from the hijack then we should have already dispatched this event
12562 _ASSERTE(pUnmanagedThread->IBEvent()->IsDispatched());
12563 return REACTION(cInbandExceptionRetrigger);
12567 // We only care about exception events if they are first chance events and if the Runtime is
12568 // initialized within the process. Otherwise, we don't do anything special with them.
12569 if (pEvent->u.Exception.dwFirstChance && this->m_initialized)
12571 return TriageExcep1stChanceAndInit(pUnmanagedThread, pEvent);
12573 else if (!pEvent->u.Exception.dwFirstChance && this->m_initialized)
12575 return TriageExcep2ndChanceAndInit(pUnmanagedThread, pEvent);
12579 // An exception event, but the Runtime hasn't been initialize. I.e., its an exception event
12580 // that we will never try to hijack.
12581 return REACTION(cInband);
12589 return REACTION(cOOB);
12594 //---------------------------------------------------------------------------------------
12596 // Top-level handler for a win32 debug event during Interop-debugging.
12599 // event - native debug event to handle.
12602 // The process just got a native debug event via WaitForDebugEvent
12605 // The function will Triage the excpetion and then handle it based on the
12606 // appropriate reaction (see: code:Reaction).
12608 // @dbgtodo interop: this should all go into the shim.
12609 //---------------------------------------------------------------------------------------
12610 void CordbProcess::HandleDebugEventForInteropDebugging(const DEBUG_EVENT * pEvent)
12612 PUBLIC_API_ENTRY_FOR_SHIM(this);
12613 _ASSERTE(IsInteropDebugging() || !"Only do this in real interop handling path");
12616 STRESS_LOG3(LF_CORDB, LL_INFO1000, "W32ET::W32EL: got unmanaged event %d on thread 0x%x, proc 0x%x\n",
12617 pEvent->dwDebugEventCode, pEvent->dwThreadId, pEvent->dwProcessId);
12620 _ASSERTE(!this->ThreadHoldsProcessLock());
12622 RSSmartPtr<CordbProcess> pRef(this); // make sure we're alive...
12624 RSLockHolder processLockHolder(&this->m_processMutex);
12626 // If we get a new Win32 Debug event, then we need to flush any cached oop data structures.
12627 // This includes refreshing DAC and our patch table.
12632 // We want to detect if we've deadlocked. Unfortunately, w/ interop debugging, there can be a lot of
12633 // deadtime since we need to wait for a debug event. Thus the CPU usage may appear to be at 0%, but
12634 // we're not deadlocked b/c we're still receiving debug events.
12635 // So ping every X debug events.
12636 static int s_cCount = 0;
12637 static int s_iPingLevel = -1;
12638 if (s_iPingLevel == -1)
12640 s_iPingLevel = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgPingInterop);
12642 if (s_iPingLevel != 0)
12645 if (s_cCount >= s_iPingLevel)
12650 // Refresh so we can adjust ping level midstream.
12651 s_iPingLevel = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgPingInterop);
12656 bool fNewEvent = true;
12658 // Mark the process as stopped.
12659 this->m_state |= CordbProcess::PS_WIN32_STOPPED;
12661 CordbUnmanagedThread * pUnmanagedThread = GetUnmanagedThreadFromEvent(pEvent);
12663 // In retail, if there is no unmanaged thread then we just continue and loop back around. UnrecoverableError has
12664 // already been set in this case. Note: there is an issue in the Win32 debugging API that can cause duplicate
12665 // ExitThread events. We therefore must handle not finding an unmanaged thread gracefully.
12667 _ASSERTE((pUnmanagedThread != NULL) || (pEvent->dwDebugEventCode == EXIT_THREAD_DEBUG_EVENT));
12669 if (pUnmanagedThread == NULL)
12671 // Note: we use ContinueDebugEvent directly here since our continue is very simple and all of our other
12672 // continue mechanisms rely on having an UnmanagedThread object to play with ;)
12673 STRESS_LOG2(LF_CORDB, LL_INFO1000, "W32ET::W32EL: Continuing without thread on tid 0x%x, code=0x%x\n",
12674 pEvent->dwThreadId,
12675 pEvent->dwDebugEventCode);
12677 this->m_state &= ~CordbProcess::PS_WIN32_STOPPED;
12679 BOOL fOk = ContinueDebugEvent(pEvent->dwProcessId, pEvent->dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
12681 _ASSERTE(fOk || !"ContinueDebugEvent failed when he have no thread. Debuggee is likely hung");
12686 // There's an innate race such that we can get a Debug Event even after we've suspended a thread.
12687 // This can happen if the thread has already dispatched the debug event but we haven't called WFDE to pick it up
12688 // yet. This is sufficiently goofy that we want to stress log it.
12689 if (pUnmanagedThread->IsSuspended())
12691 STRESS_LOG1(LF_CORDB, LL_INFO1000, "W32ET::W32EL: Thread 0x%x is suspended\n", pEvent->dwThreadId);
12694 // For debugging crazy races in retail, we'll keep a rolling queue of win32 debug events.
12695 this->DebugRecordWin32Event(pEvent, pUnmanagedThread);
12698 // Check to see if shutdown of the in-proc debugging services has begun. If it has, then we know we'll no longer
12699 // be running any managed code, and we know that we can stop hijacking threads. We remember this by setting
12700 // m_initialized to false, thus preventing most things from happening elsewhere.
12701 // Don't even bother checking the DCB fields until it's been verified (m_initialized == true)
12702 if (this->m_initialized && (this->GetDCB() != NULL))
12704 UpdateRightSideDCB();
12705 if (this->GetDCB()->m_shutdownBegun)
12707 STRESS_LOG0(LF_CORDB, LL_INFO1000, "W32ET::W32EL: shutdown begun...\n");
12708 this->m_initialized = false;
12713 //Verify that GetThreadContext agrees with the exception address
12714 if (pEvent->dwDebugEventCode == EXCEPTION_DEBUG_EVENT)
12716 DT_CONTEXT tempDebugContext;
12717 tempDebugContext.ContextFlags = DT_CONTEXT_FULL;
12718 DbiGetThreadContext(pUnmanagedThread->m_handle, &tempDebugContext);
12719 CordbUnmanagedThread::LogContext(&tempDebugContext);
12720 _ASSERTE(CORDbgGetIP(&tempDebugContext) == pEvent->u.Exception.ExceptionRecord.ExceptionAddress ||
12721 (DWORD)CORDbgGetIP(&tempDebugContext) == ((DWORD)pEvent->u.Exception.ExceptionRecord.ExceptionAddress)+1);
12725 // This call will decide what to do w/ the the win32 event we just got. It does a lot of work.
12726 Reaction reaction = TriageWin32DebugEvent(pUnmanagedThread, pEvent);
12729 // Stress-log the reaction.
12731 STRESS_LOG3(LF_CORDB, LL_INFO1000, "Reaction: %d (%s), line=%d\n",
12732 reaction.GetType(),
12733 reaction.GetReactionName(),
12734 reaction.GetLine());
12736 STRESS_LOG1(LF_CORDB, LL_INFO1000, "Reaction: %d\n", reaction.GetType());
12739 // Make sure the lock wasn't accidentally released.
12740 _ASSERTE(ThreadHoldsProcessLock());
12741 CordbWin32EventThread * pW32EventThread = this->m_pShim->GetWin32EventThread();
12742 _ASSERTE(pW32EventThread != NULL);
12744 // if we were waiting for a retriggered exception but recieved any other event then turn
12745 // off the single stepping and dequeue the IB event. Right now we only use the SS flag internally
12746 // for stepping during possible retrigger.
12747 if(reaction.GetType() != Reaction::cInbandExceptionRetrigger && pUnmanagedThread->IsSSFlagNeeded())
12749 _ASSERTE(pUnmanagedThread->HasIBEvent());
12750 CordbUnmanagedEvent* pUnmanagedEvent = pUnmanagedThread->IBEvent();
12751 _ASSERTE(pUnmanagedEvent->IsIBEvent());
12752 _ASSERTE(pUnmanagedEvent->IsEventContinuedUnhijacked());
12753 _ASSERTE(pUnmanagedEvent->IsDispatched());
12754 LOG((LF_CORDB, LL_INFO100000, "CP::HDEFID: IB event did not retrigger ue=0x%p\n", pUnmanagedEvent));
12756 DequeueUnmanagedEvent(pUnmanagedThread);
12757 pUnmanagedThread->EndStepping();
12760 switch(reaction.GetType())
12762 // Common for flares.
12763 case Reaction::cIgnore:
12765 // Shouldn't be suspending in the first place with outstanding flares.
12766 _ASSERTE(!pUnmanagedThread->IsSuspended());
12768 pW32EventThread->ForceDbgContinue(this, pUnmanagedThread, DBG_CONTINUE, false);
12771 case Reaction::cCLR:
12772 // Don't care if thread is suspended here. We'll just let the thread continue whatever it's doing.
12774 this->m_DbgSupport.m_TotalCLR++;
12776 // If this is for the CLR, then we just continue unhandled and know that the CLR has
12777 // a handler inplace to deal w/ this exception.
12778 pW32EventThread->ForceDbgContinue(this, pUnmanagedThread, DBG_EXCEPTION_NOT_HANDLED, false);
12782 case Reaction::cInband_NotNewEvent:
12785 // fall through to Inband case...
12787 case Reaction::cInband:
12789 this->m_DbgSupport.m_TotalIB++;
12791 // Hijack in-band events (exception events, exit threads) if there is already an event at the head
12792 // of the queue or if the process is currently synchronized. Of course, we only do this if the
12793 // process is initialized.
12795 // Note: we also hijack these left over in-band events if we're activley trying to send the
12796 // managed continue message to the Left Side. This is controlled by m_specialDeferment below.
12798 // Only exceptions can be IB events - everything else is OOB.
12799 _ASSERTE(pEvent->dwDebugEventCode == EXCEPTION_DEBUG_EVENT);
12801 // CLR internal exceptions should be sent back to the CLR and never treated as inband events.
12802 // If this assert fires, the event was triaged wrong.
12803 CONSISTENCY_CHECK_MSGF((pEvent->u.Exception.ExceptionRecord.ExceptionCode != EXCEPTION_COMPLUS),
12804 ("Attempting to dispatch a CLR internal exception as an Inband event. Reaction line=%d\n",
12805 reaction.GetLine()));
12808 _ASSERTE(!pUnmanagedThread->IsCantStop());
12810 // We need to decide whether or not to dispatch this event immediately
12811 // We defer it to enforce that we only dispatch 1 IB event at a time (managed events are
12812 // considered IB here).
12814 // 1) there's already an outstanding unmanaged inband event (an event the user has not continued from)
12815 // 2) If the process is synchronized (since that means we've already dispatched a managed event).
12816 // 3) If we've received a SyncComplete event, but aren't yet Sync. This will almost always be the same as
12817 // whether we're synced, but has a distict quality. It's always set by the w32 event thread in Interop,
12818 // and so it's guaranteed to be serialized against this check here (also on the w32et).
12819 // 4) Special deferment - This covers the region where we're sending a Stop/Continue IPC event across.
12820 // We defer it here to keep the Helper thread alive so that it can handle these IPC events.
12821 // Queued events will be dispatched when continue is called.
12822 BOOL fHasUserUncontinuedNativeEvents = HasUserUncontinuedNativeEvents();
12823 bool fDeferInbandEvent = (fHasUserUncontinuedNativeEvents ||
12824 GetSynchronized() ||
12825 GetSyncCompleteRecv() ||
12826 m_specialDeferment);
12828 // If we've got a new event, queue it.
12831 this->QueueUnmanagedEvent(pUnmanagedThread, pEvent);
12834 if (fNewEvent && this->m_initialized && fDeferInbandEvent)
12836 STRESS_LOG4(LF_CORDB, LL_INFO1000, "W32ET::W32EL: Needed to defer dispatching event: %d %d %d %d\n",
12837 fHasUserUncontinuedNativeEvents,
12839 GetSyncCompleteRecv(),
12840 m_specialDeferment);
12842 // this continues the IB debug event into the hijack
12843 // the process is now running again
12844 pW32EventThread->DoDbgContinue(this, pUnmanagedThread->IBEvent());
12846 // Since we've hijacked this event, we don't need to do any further processing.
12851 // No need to defer the dispatch, do it now
12852 this->DispatchUnmanagedInBandEvent();
12859 case Reaction::cFirstChanceHijackStarted:
12861 // determine the logical event we are handling, if any
12862 CordbUnmanagedEvent* pUnmanagedEvent = NULL;
12863 if(pUnmanagedThread->HasIBEvent())
12865 pUnmanagedEvent = pUnmanagedThread->IBEvent();
12867 LOG((LF_CORDB, LL_INFO100000, "W32ET::W32EL: IB hijack starting, ue=0x%p\n", pUnmanagedEvent));
12869 // fetch the LS memory set up for this hijack
12870 REMOTE_PTR pDebuggerWord = NULL;
12871 DebuggerIPCFirstChanceData fcd;
12872 pUnmanagedThread->GetEEDebuggerWord(&pDebuggerWord);
12873 SafeReadStruct(PTR_TO_CORDB_ADDRESS(pDebuggerWord), &fcd);
12875 LOG((LF_CORDB, LL_INFO100000, "W32ET::W32EL: old fcd DebugCounter=0x%x\n", fcd.debugCounter));
12877 // determine what action the LS should take
12878 if(pUnmanagedThread->IsBlockingForSync())
12880 // there should be an event we hijacked in this case
12881 _ASSERTE(pUnmanagedEvent != NULL);
12883 // block that event
12884 LOG((LF_CORDB, LL_INFO100000, "W32ET::W32EL: blocking\n"));
12885 fcd.action = HIJACK_ACTION_WAIT;
12886 fcd.debugCounter = 0x2;
12887 SafeWriteStruct(PTR_TO_CORDB_ADDRESS(pDebuggerWord), &fcd);
12891 // we don't need to block. We want the vectored handler to just exit
12892 // as if it wasn't there
12893 _ASSERTE(fcd.action == HIJACK_ACTION_EXIT_UNHANDLED);
12894 LOG((LF_CORDB, LL_INFO100000, "W32ET::W32EL: not blocking\n"));
12897 LOG((LF_CORDB, LL_INFO100000, "W32ET::W32EL: continuing from flare\n"));
12898 pW32EventThread->ForceDbgContinue(this, pUnmanagedThread, DBG_CONTINUE, false);
12902 case Reaction::cInbandHijackComplete:
12904 // We now execute the hijack worker even when not actually hijacked
12905 // so can't assert this
12906 //_ASSERTE(pUnmanagedThread->IsFirstChanceHijacked());
12908 // we should not be stepping at the end of hijacks
12909 _ASSERTE(!pUnmanagedThread->IsSSFlagHidden());
12910 _ASSERTE(!pUnmanagedThread->IsSSFlagNeeded());
12912 // if we were hijacked then clean up
12913 if(pUnmanagedThread->IsFirstChanceHijacked())
12915 LOG((LF_CORDB, LL_INFO100000, "W32ET::W32EL: hijack complete will restore context...\n"));
12916 DT_CONTEXT tempContext = { 0 };
12917 tempContext.ContextFlags = DT_CONTEXT_FULL;
12918 HRESULT hr = pUnmanagedThread->GetThreadContext(&tempContext);
12919 _ASSERTE(SUCCEEDED(hr));
12921 // The sync hijack returns normally but the m2uHandoff hijack needs to have the IP
12922 // deliberately restored
12923 if(!pUnmanagedThread->IsBlockingForSync())
12925 // restore the context to the current un-hijacked context
12926 BOOL succ = DbiSetThreadContext(pUnmanagedThread->m_handle, &tempContext);
12929 // Because hijacks don't return normally they might have pushed handlers without poping them
12930 // back off. To take care of that we explicitly restore the old SEH chain.
12931 #ifdef DBG_TARGET_X86
12932 hr = pUnmanagedThread->RestoreLeafSeh();
12933 _ASSERTE(SUCCEEDED(hr));
12938 _ASSERTE(pUnmanagedThread->HasIBEvent());
12939 CordbUnmanagedEvent* pUnmanagedEvent = pUnmanagedThread->IBEvent();
12940 LOG((LF_CORDB, LL_INFO100000, "W32ET::W32EL: IB hijack completing, continuing unhijacked ue=0x%p\n", pUnmanagedEvent));
12941 _ASSERTE(pUnmanagedEvent->IsEventContinuedHijacked());
12942 _ASSERTE(pUnmanagedEvent->IsDispatched());
12943 _ASSERTE(pUnmanagedEvent->IsEventUserContinued());
12944 _ASSERTE(!pUnmanagedEvent->IsEventContinuedUnhijacked());
12945 pUnmanagedEvent->SetState(CUES_EventContinuedUnhijacked);
12947 // fetch the LS memory set up for this hijack
12948 REMOTE_PTR pDebuggerWord = NULL;
12949 DebuggerIPCFirstChanceData fcd;
12950 pUnmanagedThread->GetEEDebuggerWord(&pDebuggerWord);
12951 SafeReadStruct(PTR_TO_CORDB_ADDRESS(pDebuggerWord), &fcd);
12953 LOG((LF_CORDB, LL_INFO10000, "W32ET::W32EL: pDebuggerWord is 0x%p\n", pDebuggerWord));
12955 //set the correct continuation action based upon the user's selection
12956 if(pUnmanagedEvent->IsExceptionCleared())
12958 LOG((LF_CORDB, LL_INFO10000, "W32ET::W32EL: exception cleared\n"));
12959 fcd.action = HIJACK_ACTION_EXIT_HANDLED;
12963 LOG((LF_CORDB, LL_INFO10000, "W32ET::W32EL: exception not cleared\n"));
12964 fcd.action = HIJACK_ACTION_EXIT_UNHANDLED;
12968 // LS context is restored here so that execution continues from next instruction that caused the hijack.
12969 // We shouldn't always restore the LS context though.
12970 // Consider the following case where this can cause issues:
12971 // Debuggee process hits an exception and calls KERNELBASE!RaiseException, debugger gets the notification and
12972 // prepares for first-chance hijack. Debugger(DBI) saves the current thread context (see SetupFirstChanceHijackForSync) which is restored
12973 // later below (see SafeWriteThreadContext call) when the process is in VEH (CLRVectoredExceptionHandlerShim->FirstChanceSuspendHijackWorker).
12974 // The thread context that got saved(by SetupFirstChanceHijackForSync) was for when the thread was executing RaiseException and when
12975 // this context gets restored in VEH, the thread resumes after the exception handler with a context that is not same as one with which
12976 // it entered. This inconsistency can lead to bad execution code-paths or even a debuggee crash.
12978 // Example case where we should definitely update the LS context:
12979 // After a DbgBreakPoint call, IP gets updated to point to the instruction after int 3 and this is the context saved by debugger.
12980 // The IP in context passed to VEH still points to int 3 though and if we don't update the LS context in VEH, the breakpoint
12981 // instruction will get executed again.
12983 // Here's a list of cases when we update the LS context:
12984 // * we know that context was explicitly updated during this hijack, OR
12985 // * if single-stepping flag was set on it originally, OR
12986 // * if this was a breakpoint event
12987 // Note that above list is a heuristic and it is possible that we need to add more such cases in future.
12989 BOOL isBreakPointEvent = (pUnmanagedEvent->m_currentDebugEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT &&
12990 pUnmanagedEvent->m_currentDebugEvent.u.Exception.ExceptionRecord.ExceptionCode == STATUS_BREAKPOINT);
12991 if (pUnmanagedThread->IsContextSet() || IsSSFlagEnabled(&tempContext) || isBreakPointEvent)
12993 _ASSERTE(fcd.pLeftSideContext != NULL);
12994 LOG((LF_CORDB, LL_INFO10000, "W32ET::W32EL: updating LS context at 0x%p\n", fcd.pLeftSideContext));
12995 // write the new context over the old one on the LS
12996 SafeWriteThreadContext(fcd.pLeftSideContext, &tempContext);
12999 // Write the new Fcd data to the LS
13000 fcd.debugCounter = 0x1;
13001 SafeWriteStruct(PTR_TO_CORDB_ADDRESS(pDebuggerWord), &fcd);
13003 fcd.debugCounter = 0;
13004 SafeReadStruct(PTR_TO_CORDB_ADDRESS(pDebuggerWord), &fcd);
13005 _ASSERTE(fcd.debugCounter == 1);
13007 DequeueUnmanagedEvent(pUnmanagedThread);
13010 _ASSERTE(m_cFirstChanceHijackedThreads > 0);
13011 m_cFirstChanceHijackedThreads--;
13012 if(m_cFirstChanceHijackedThreads == 0)
13014 m_state &= ~PS_HIJACKS_IN_PLACE;
13017 pUnmanagedThread->ClearState(CUTS_FirstChanceHijacked);
13018 pUnmanagedThread->ClearState(CUTS_BlockingForSync);
13020 // if the user set the context it either was already applied (m2uHandoff hijack)
13021 // or is about to be applied when the hijack returns (sync hijack).
13022 // There may still a small window where it won't appear accurate that
13023 // we just have to live with
13024 pUnmanagedThread->ClearState(CUTS_HasContextSet);
13027 pW32EventThread->ForceDbgContinue(this, pUnmanagedThread, DBG_CONTINUE, false);
13029 // We've handled this event. Skip further processing.
13033 case Reaction::cBreakpointRequiringHijack:
13035 HRESULT hr = pUnmanagedThread->SetupFirstChanceHijack(EHijackReason::kM2UHandoff, &(pEvent->u.Exception.ExceptionRecord));
13036 _ASSERTE(SUCCEEDED(hr));
13037 pW32EventThread->ForceDbgContinue(this, pUnmanagedThread, DBG_CONTINUE, false);
13041 case Reaction::cInbandExceptionRetrigger:
13043 // this should be unused now
13045 _ASSERTE(pUnmanagedThread->HasIBEvent());
13046 CordbUnmanagedEvent* pUnmanagedEvent = pUnmanagedThread->IBEvent();
13047 _ASSERTE(pUnmanagedEvent->IsIBEvent());
13048 _ASSERTE(pUnmanagedEvent->IsEventContinuedUnhijacked());
13049 _ASSERTE(pUnmanagedEvent->IsDispatched());
13050 LOG((LF_CORDB, LL_INFO100000, "W32ET::W32EL: IB event completing, continuing ue=0x%p\n", pUnmanagedEvent));
13052 DequeueUnmanagedEvent(pUnmanagedThread);
13053 // If this event came from RaiseException then flush the context to ensure we won't use it until we re-enter
13054 if(pUnmanagedEvent->m_owner->IsRaiseExceptionHijacked())
13056 pUnmanagedEvent->m_owner->RestoreFromRaiseExceptionHijack();
13057 pUnmanagedEvent->m_owner->ClearRaiseExceptionEntryContext();
13059 else // otherwise we should have been stepping
13061 pUnmanagedThread->EndStepping();
13063 pW32EventThread->ForceDbgContinue(this, pUnmanagedThread,
13064 pUnmanagedEvent->IsExceptionCleared() ? DBG_CONTINUE : DBG_EXCEPTION_NOT_HANDLED, false);
13066 // We've handled this event. Skip further processing.
13070 case Reaction::cOOB:
13072 // Don't care if this thread claimed to be suspended or not. Dispatch event anyways. After all,
13073 // OOB events can come at *any* time.
13075 // This thread may be suspended. We don't care.
13076 this->m_DbgSupport.m_TotalOOB++;
13078 // Not an inband event. This includes ALL non-exception events (including EXIT_THREAD) as
13079 // well as any exception that can't be hijacked (ex, an exception on the helper thread).
13081 // If this is an exit thread or exit process event, then we need to mark the unmanaged thread as
13082 // exited for later.
13083 if ((pEvent->dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) ||
13084 (pEvent->dwDebugEventCode == EXIT_THREAD_DEBUG_EVENT))
13086 pUnmanagedThread->SetState(CUTS_Deleted);
13089 // If we get an exit process or exit thread event on the helper thread, then we know we're loosing
13090 // the Left Side, so go ahead and remember that the helper thread has died.
13091 if (this->IsHelperThreadWorked(pUnmanagedThread->GetOSTid()))
13093 if ((pEvent->dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) ||
13094 (pEvent->dwDebugEventCode == EXIT_THREAD_DEBUG_EVENT))
13096 this->m_helperThreadDead = true;
13100 // Queue the current out-of-band event.
13101 this->QueueOOBUnmanagedEvent(pUnmanagedThread, pEvent);
13103 // Go ahead and dispatch the event if its the first one.
13104 if (this->m_outOfBandEventQueue == pUnmanagedThread->OOBEvent())
13106 // Set this to true to indicate to Continue() that we're in the unamnaged callback.
13107 CordbUnmanagedEvent * pUnmanagedEvent = pUnmanagedThread->OOBEvent();
13109 this->m_dispatchingOOBEvent = true;
13111 pUnmanagedEvent->SetState(CUES_Dispatched);
13115 // Handler should have been registered by now.
13116 _ASSERTE(this->m_cordb->m_unmanagedCallback != NULL);
13118 // Call the callback with fIsOutOfBand = TRUE.
13120 PUBLIC_WIN32_CALLBACK_IN_THIS_SCOPE(this, pEvent, TRUE);
13121 this->m_cordb->m_unmanagedCallback->DebugEvent(const_cast<DEBUG_EVENT*> (pEvent), TRUE);
13126 // If m_dispatchingOOBEvent is false, that means that the user called Continue() from within
13127 // the callback. We know that we can go ahead and continue the process now.
13128 if (this->m_dispatchingOOBEvent == false)
13130 // Note: this call will dispatch more OOB events if necessary.
13131 pW32EventThread->UnmanagedContinue(this, cOobUMContinue);
13135 // We're not dispatching anymore, so set this back to false.
13136 this->m_dispatchingOOBEvent = false;
13140 // We've handled this event. Skip further processing.
13143 } // end Switch on Reaction
13148 // Process Lock implicitly released by holder.
13150 STRESS_LOG0(LF_CORDB, LL_INFO1000, "W32ET::W32EL: done processing event.\n");
13156 // Returns true if the exception is a flare from the left side, false otherwise.
13158 bool CordbProcess::ExceptionIsFlare(DWORD exceptionCode, const void *exceptionAddress)
13160 _ASSERTE(m_runtimeOffsetsInitialized);
13162 // Can't have a flare if the left side isn't initialized
13165 DebuggerIPCRuntimeOffsets *pRO = &m_runtimeOffsets;
13167 // All flares are breakpoints...
13168 if (exceptionCode == STATUS_BREAKPOINT)
13170 // Does the breakpoint address match a flare address?
13171 if ((exceptionAddress == pRO->m_signalHijackStartedBPAddr) ||
13172 (exceptionAddress == pRO->m_excepForRuntimeHandoffStartBPAddr) ||
13173 (exceptionAddress == pRO->m_excepForRuntimeHandoffCompleteBPAddr) ||
13174 (exceptionAddress == pRO->m_signalHijackCompleteBPAddr) ||
13175 (exceptionAddress == pRO->m_excepNotForRuntimeBPAddr) ||
13176 (exceptionAddress == pRO->m_notifyRSOfSyncCompleteBPAddr))
13183 #endif // FEATURE_INTEROP_DEBUGGING
13185 // Allocate a buffer in the target and copy data into it.
13188 // pDomain - an appdomain associated with the allocation request.
13189 // bufferSize - size of the buffer in bytes
13190 // bufferFrom - local buffer of data (bufferSize bytes) to copy data from.
13191 // ppRes - address into target of allocated buffer
13194 // S_OK on success, else error.
13195 HRESULT CordbProcess::GetAndWriteRemoteBuffer(CordbAppDomain *pDomain, unsigned int bufferSize, const void *bufferFrom, void **ppRes)
13197 _ASSERTE(ppRes != NULL);
13204 TargetBuffer tbTarget = GetRemoteBuffer(bufferSize); // throws
13205 SafeWriteBuffer(tbTarget, (const BYTE*) bufferFrom); // throws
13208 *ppRes = CORDB_ADDRESS_TO_PTR(tbTarget.pAddress);
13210 EX_CATCH_HRESULT(hr);
13214 #ifdef FEATURE_INTEROP_DEBUGGING
13217 // Checks to see if the given second chance exception event actually signifies the death of the process due to a second
13218 // stack overflow special case.
13220 // There are strange cases with stack overflow exceptions. If a nieve application catches a stack overflow exception and
13221 // handles it, without resetting the guard page, then the app will get an AV when it overflows the stack a second time. We
13222 // will get the first chance AV, but when we continue from it the OS won't run any SEH handlers, so our FCH won't
13223 // actually work. Instead, we'll get the AV back on second chance right away.
13225 bool CordbProcess::IsSpecialStackOverflowCase(CordbUnmanagedThread *pUThread, const DEBUG_EVENT *pEvent)
13227 _ASSERTE(pEvent->dwDebugEventCode == EXCEPTION_DEBUG_EVENT);
13228 _ASSERTE(pEvent->u.Exception.dwFirstChance == 0);
13230 // If this is not an AV, it can't be our special case.
13231 if (pEvent->u.Exception.ExceptionRecord.ExceptionCode != STATUS_ACCESS_VIOLATION)
13234 // If the thread isn't already first chance hijacked, it can't be our special case.
13235 if (!pUThread->IsFirstChanceHijacked())
13238 // The first chance hijack didn't take, so we're not FCH anymore and we're not waiting for an answer
13239 // anymore... Note: by leaving this thread completely unhijacked, we'll report its true context, which is correct.
13240 pUThread->ClearState(CUTS_FirstChanceHijacked);
13242 // The process is techincally dead as a door nail here, so we'll mark that the helper thread is dead so our managed
13243 // API bails nicely.
13244 m_helperThreadDead = true;
13246 // Remember we're in our special case.
13247 pUThread->SetState(CUTS_HasSpecialStackOverflowCase);
13249 // Now, remember the second chance AV event in the second IB event slot for this thread and add it to the end of the
13251 QueueUnmanagedEvent(pUThread, pEvent);
13253 // Note: returning true will ensure that the queued first chance AV for this thread is dispatched.
13257 //-----------------------------------------------------------------------------
13258 // Longhorn broke ContinueDebugEvent.
13259 // In previous OS releases, DBG_CONTINUE would continue a non-continuable exception.
13260 // In longhorn, we need to pass the DBG_FORCE_CONTINUE flag to do that.
13261 // Note that all CLR exceptions are non-continuable.
13262 // Now instead of DBG_CONTINUE, we need to pass DBG_FORCE_CONTINUE.
13263 //-----------------------------------------------------------------------------
13265 // Currently we don't have headers for the longhorn winnt.h. So we need to privately declare
13266 // this here. We have a check such that if we do get headers, the value won't change underneath us.
13267 #define MY_DBG_FORCE_CONTINUE ((DWORD )0x00010003L)
13268 #ifndef DBG_FORCE_CONTINUE
13269 #define DBG_FORCE_CONTINUE MY_DBG_FORCE_CONTINUE
13271 static_assert_no_msg(DBG_FORCE_CONTINUE == MY_DBG_FORCE_CONTINUE);
13274 DWORD GetDbgContinueFlag()
13276 // Currently, default to not using the new DBG_FORCE_CONTINUE flag.
13277 static ConfigDWORD fNoFlagKey;
13278 bool fNoFlag = fNoFlagKey.val(CLRConfig::UNSUPPORTED_DbgNoForceContinue) != 0;
13283 return DBG_FORCE_CONTINUE;
13287 return DBG_CONTINUE;
13292 // Some Interop bugs involve threads that land at a crazy IP. Since we're interop-debugging, we can't
13293 // attach a debugger to the LS. So we have some debug mode where we enable the SS flag and thus
13294 // produce a trace of where a thread is going.
13296 void EnableDebugTrace(CordbUnmanagedThread *ut)
13298 // To enable, attach w/ a debugger and either set fTrace==true, or setip.
13299 static bool fTrace = false;
13303 // Give us a nop so that we can setip in the optimized case.
13304 #ifdef _TARGET_X86_
13311 CordbProcess *pProcess = ut->GetProcess();
13315 DT_CONTEXT context;
13316 context.ContextFlags = DT_CONTEXT_FULL;
13319 hr = pProcess->GetThreadContext((DWORD) ut->m_id, sizeof(context), (BYTE*)&context);
13323 // If the flag is already set, then don't set it again - that will just get confusing.
13324 if (IsSSFlagEnabled(&context))
13328 _ASSERTE(CORDbgGetIP(&context) != 0);
13329 SetSSFlag(&context);
13331 // If SS flag not set, enable it. And remeber that it's us so we know how to handle
13332 // it when we get the debug event.
13333 hr = pProcess->SetThreadContext((DWORD)ut->m_id, sizeof(context), (BYTE*)&context);
13334 ut->SetState(CUTS_DEBUG_SingleStep);
13338 //-----------------------------------------------------------------------------
13341 // Continues from a specific Win32 DEBUG_EVENT.
13344 // pProcess - The process to continue.
13345 // pUnmanagedEvent - The event to continue.
13347 //-----------------------------------------------------------------------------
13348 void CordbWin32EventThread::DoDbgContinue(CordbProcess *pProcess,
13349 CordbUnmanagedEvent *pUnmanagedEvent)
13351 _ASSERTE(pProcess->ThreadHoldsProcessLock());
13352 _ASSERTE(IsWin32EventThread());
13353 _ASSERTE(pUnmanagedEvent != NULL);
13354 _ASSERTE(!pUnmanagedEvent->IsEventContinuedUnhijacked());
13356 STRESS_LOG3(LF_CORDB, LL_INFO1000,
13357 "W32ET::DDC: continue with ue=0x%p, thread=0x%p, tid=0x%x\n",
13359 pUnmanagedEvent->m_owner,
13360 pUnmanagedEvent->m_owner->m_id);
13363 EnableDebugTrace(pUnmanagedEvent->m_owner);
13367 if (pUnmanagedEvent->IsEventContinuedHijacked())
13369 LOG((LF_CORDB, LL_INFO100000, "W32ET::DDC: Skiping DoDbgContinue because event was already"
13370 " continued hijacked, ue=0x%p\n", pUnmanagedEvent));
13374 BOOL threadIsHijacked = (pUnmanagedEvent->m_owner->IsFirstChanceHijacked() ||
13375 pUnmanagedEvent->m_owner->IsGenericHijacked());
13377 BOOL eventIsIB = (pUnmanagedEvent->m_owner->HasIBEvent() &&
13378 pUnmanagedEvent->m_owner->IBEvent() == pUnmanagedEvent);
13380 _ASSERTE((DWORD) pProcess->m_id == pUnmanagedEvent->m_currentDebugEvent.dwProcessId);
13381 _ASSERTE(pProcess->m_state & CordbProcess::PS_WIN32_STOPPED);
13387 // event was already hijacked
13388 if(threadIsHijacked)
13390 LOG((LF_CORDB, LL_INFO100000, "W32ET::DDC: Continuing IB, already hijacked, ue=0x%p\n", pUnmanagedEvent));
13391 pUnmanagedEvent->SetState(CUES_EventContinuedHijacked);
13392 dwContType = !pUnmanagedEvent->m_owner->IsBlockingForSync() ? GetDbgContinueFlag() : DBG_EXCEPTION_NOT_HANDLED;
13394 // event was not hijacked but has been dispatched
13395 else if(!threadIsHijacked && pUnmanagedEvent->IsDispatched())
13397 LOG((LF_CORDB, LL_INFO100000, "W32ET::DDC: Continuing IB, not hijacked, ue=0x%p\n", pUnmanagedEvent));
13398 _ASSERTE(pUnmanagedEvent->IsDispatched());
13399 _ASSERTE(pUnmanagedEvent->IsEventUserContinued());
13400 _ASSERTE(!pUnmanagedEvent->IsEventContinuedUnhijacked());
13401 pUnmanagedEvent->SetState(CUES_EventContinuedUnhijacked);
13402 dwContType = pUnmanagedEvent->IsExceptionCleared() ? GetDbgContinueFlag() : DBG_EXCEPTION_NOT_HANDLED;
13404 // The event was never hijacked and so will never need to retrigger, get rid
13405 // of it right now. If it had been hijacked then we would dequeue it either after the
13406 // hijack complete flare or one instruction after that when it has had a chance to retrigger
13407 pProcess->DequeueUnmanagedEvent(pUnmanagedEvent->m_owner);
13409 // event was not hijacked nor dispatched
13410 else // if(!threadIsHijacked && !pUnmanagedEvent->IsDispatched())
13412 LOG((LF_CORDB, LL_INFO100000, "W32ET::DDC: Continuing IB, now hijacked, ue=0x%p\n", pUnmanagedEvent));
13413 HRESULT hr = pProcess->HijackIBEvent(pUnmanagedEvent);
13414 _ASSERTE(SUCCEEDED(hr));
13415 pUnmanagedEvent->SetState(CUES_EventContinuedHijacked);
13416 dwContType = !pUnmanagedEvent->m_owner->IsBlockingForSync() ? GetDbgContinueFlag() : DBG_EXCEPTION_NOT_HANDLED;
13421 LOG((LF_CORDB, LL_INFO100000, "W32ET::DDC: Continuing OB, ue=0x%p\n", pUnmanagedEvent));
13422 // we might actually be hijacked here, but if we are it should be for a previous IB event
13423 // we just mark all OB events as continued unhijacked
13424 pUnmanagedEvent->SetState(CUES_EventContinuedUnhijacked);
13425 dwContType = pUnmanagedEvent->IsExceptionCleared() ? GetDbgContinueFlag() : DBG_EXCEPTION_NOT_HANDLED;
13428 // If the exception is marked as unclearable, then make sure the continue type is correct and force the process
13430 if (pUnmanagedEvent->IsExceptionUnclearable())
13432 TerminateProcess(pProcess->UnsafeGetProcessHandle(), pUnmanagedEvent->m_currentDebugEvent.u.Exception.ExceptionRecord.ExceptionCode);
13433 dwContType = DBG_EXCEPTION_NOT_HANDLED;
13436 // If we're continuing from the loader-bp, then send the managed attach here.
13437 // (Note this will only be set if the runtime was loaded when we first tried to attach).
13438 // We assume that the loader-bp is the 1st BP exception. This is naive,
13439 // since it's not 100% accurate (someone could CreateThread w/ a threadproc of DebugBreak).
13440 // But it's the best we can do.
13441 // Note that it's critical we do this BEFORE continuing the process. If this is mixed-mode, we've already
13442 // told VS about this breakpoint, and so it's set the attach-complete event. As soon as we continue this debug
13443 // event the process can start moving again, so the CLR needs to know to wait for a managed attach.
13444 DWORD dwEventCode = pUnmanagedEvent->m_currentDebugEvent.dwDebugEventCode;
13445 if (dwEventCode == EXCEPTION_DEBUG_EVENT)
13447 EXCEPTION_DEBUG_INFO * pDebugInfo = &pUnmanagedEvent->m_currentDebugEvent.u.Exception;
13448 if (pDebugInfo->dwFirstChance && pDebugInfo->ExceptionRecord.ExceptionCode == STATUS_BREAKPOINT)
13450 HRESULT hrIgnore = S_OK;
13453 LOG((LF_CORDB, LL_INFO1000, "W32ET::DDC: Continuing from LdrBp, doing managed attach.\n"));
13454 pProcess->QueueManagedAttachIfNeededWorker();
13456 EX_CATCH_HRESULT(hrIgnore);
13457 SIMPLIFYING_ASSUMPTION(SUCCEEDED(hrIgnore));
13461 STRESS_LOG4(LF_CORDB, LL_INFO1000,
13462 "W32ET::DDC: calling ContinueDebugEvent(0x%x, 0x%x, 0x%x), process state=0x%x\n",
13463 pProcess->m_id, pUnmanagedEvent->m_owner->m_id, dwContType, pProcess->m_state);
13465 // Actually continue the debug event
13466 pProcess->m_state &= ~CordbProcess::PS_WIN32_STOPPED;
13467 BOOL fSuccess = m_pNativePipeline->ContinueDebugEvent((DWORD)pProcess->m_id, (DWORD)pUnmanagedEvent->m_owner->m_id, dwContType);
13469 // ContinueDebugEvent may 'fail' if we force kill the debuggee while stopped at the exit-process event.
13470 if (!fSuccess && (dwEventCode != EXIT_PROCESS_DEBUG_EVENT))
13472 _ASSERTE(!"ContinueDebugEvent failed!");
13473 CORDBSetUnrecoverableError(pProcess, HRESULT_FROM_GetLastError(), 0);
13474 STRESS_LOG1(LF_CORDB, LL_INFO1000, "W32ET::DDC: Last error after ContinueDebugEvent is %d\n", GetLastError());
13477 // If this thread is marked for deletion (exit thread or exit process event on it), then we need to delete the
13478 // unmanaged thread object.
13479 if ((dwEventCode == EXIT_PROCESS_DEBUG_EVENT) || (dwEventCode == EXIT_THREAD_DEBUG_EVENT))
13481 CordbUnmanagedThread * pUnmanagedThread = pUnmanagedEvent->m_owner;
13482 _ASSERTE(pUnmanagedThread->IsDeleted());
13485 // Thread may have a hijacked inband event on it. Thus it's actually running free from the OS perspective,
13486 // and fair game to be terminated. In that case, we need to auto-dequeue the event.
13487 // This will just prevent the RS from making the underlying call to ContinueDebugEvent on this thread
13488 // for the inband event. Since we've already lost the thread, that's actually exactly what we want.
13489 if (pUnmanagedThread->HasIBEvent())
13491 pProcess->DequeueUnmanagedEvent(pUnmanagedThread);
13494 STRESS_LOG1(LF_CORDB, LL_INFO1000, "Removing thread 0x%x (%d) from process list\n", pUnmanagedThread->m_id);
13495 pProcess->m_unmanagedThreads.RemoveBase((ULONG_PTR)pUnmanagedThread->m_id);
13499 // If we just continued from an exit process event, then its time to do the exit processing.
13500 if (dwEventCode == EXIT_PROCESS_DEBUG_EVENT)
13502 pProcess->Unlock();
13503 ExitProcess(false); // not detach case
13509 //---------------------------------------------------------------------------------------
13511 // ForceDbgContinue continues from the last Win32 DEBUG_EVENT on the given thread, no matter what it was.
13514 // pProcess - process object to continue
13515 // pUnmanagedThread - unmanaged thread object (maybe null if we're doing a raw cotninue)
13516 // contType - continuation status (DBG_CONTINUE or DBG_EXCEPTION_NOT_HANDLED)
13517 // fContinueProcess - do we resume hijacks?
13519 void CordbWin32EventThread::ForceDbgContinue(CordbProcess *pProcess, CordbUnmanagedThread *pUnmanagedThread, DWORD contType,
13520 bool fContinueProcess)
13522 _ASSERTE(pProcess->ThreadHoldsProcessLock());
13523 _ASSERTE(pUnmanagedThread != NULL);
13524 STRESS_LOG4(LF_CORDB, LL_INFO1000,
13525 "W32ET::FDC: force continue with 0x%x (%s), contProcess=%d, tid=0x%x\n",
13527 (contType == DBG_CONTINUE) ? "DBG_CONTINUE" : "DBG_EXCEPTION_NOT_HANDLED",
13529 pUnmanagedThread->m_id);
13531 if (fContinueProcess)
13533 pProcess->ResumeHijackedThreads();
13536 if (contType == DBG_CONTINUE)
13538 contType = GetDbgContinueFlag();
13541 _ASSERTE(pProcess->m_state & CordbProcess::PS_WIN32_STOPPED);
13543 // Remove the Win32 stopped flag so long as the OOB event queue is empty. We're forcing a continue here, so by
13544 // definition this should be the case...
13545 _ASSERTE(pProcess->m_outOfBandEventQueue == NULL);
13547 pProcess->m_state &= ~CordbProcess::PS_WIN32_STOPPED;
13549 STRESS_LOG4(LF_CORDB, LL_INFO1000, "W32ET::FDC: calling ContinueDebugEvent(0x%x, 0x%x, 0x%x), process state=0x%x\n",
13550 pProcess->m_id, pUnmanagedThread->m_id, contType, pProcess->m_state);
13554 EnableDebugTrace(pUnmanagedThread);
13556 BOOL ret = m_pNativePipeline->ContinueDebugEvent((DWORD)pProcess->m_id, (DWORD)pUnmanagedThread->m_id, contType);
13560 // This could in theory fail from Process exit, but that really would only be on the DoDbgContinue path.
13561 _ASSERTE(!"ContinueDebugEvent failed #2!");
13562 STRESS_LOG1(LF_CORDB, LL_INFO1000, "W32ET::DDC: Last error after ContinueDebugEvent is %d\n", GetLastError());
13565 #endif // FEATURE_INTEROP_DEBUGGING
13568 // This is the thread's real thread proc. It simply calls to the
13569 // thread proc on the given object.
13571 /*static*/ DWORD WINAPI CordbWin32EventThread::ThreadProc(LPVOID parameter)
13573 CordbWin32EventThread* t = (CordbWin32EventThread*) parameter;
13574 INTERNAL_THREAD_ENTRY(t);
13581 // Send a CreateProcess event to the Win32 thread to have it create us
13584 HRESULT CordbWin32EventThread::SendCreateProcessEvent(
13585 MachineInfo machineInfo,
13586 LPCWSTR programName,
13587 __in_z LPWSTR programArgs,
13588 LPSECURITY_ATTRIBUTES lpProcessAttributes,
13589 LPSECURITY_ATTRIBUTES lpThreadAttributes,
13590 BOOL bInheritHandles,
13591 DWORD dwCreationFlags,
13592 PVOID lpEnvironment,
13593 LPCWSTR lpCurrentDirectory,
13594 LPSTARTUPINFOW lpStartupInfo,
13595 LPPROCESS_INFORMATION lpProcessInformation,
13596 CorDebugCreateProcessFlags corDebugFlags)
13600 LockSendToWin32EventThreadMutex();
13601 LOG((LF_CORDB, LL_EVERYTHING, "CordbWin32EventThread::SCPE Called\n"));
13602 m_actionData.createData.machineInfo = machineInfo;
13603 m_actionData.createData.programName = programName;
13604 m_actionData.createData.programArgs = programArgs;
13605 m_actionData.createData.lpProcessAttributes = lpProcessAttributes;
13606 m_actionData.createData.lpThreadAttributes = lpThreadAttributes;
13607 m_actionData.createData.bInheritHandles = bInheritHandles;
13608 m_actionData.createData.dwCreationFlags = dwCreationFlags;
13609 m_actionData.createData.lpEnvironment = lpEnvironment;
13610 m_actionData.createData.lpCurrentDirectory = lpCurrentDirectory;
13611 m_actionData.createData.lpStartupInfo = lpStartupInfo;
13612 m_actionData.createData.lpProcessInformation = lpProcessInformation;
13613 m_actionData.createData.corDebugFlags = corDebugFlags;
13615 // m_action is set last so that the win32 event thread can inspect
13616 // it and take action without actually having to take any
13617 // locks. The lock around this here is simply to prevent multiple
13618 // threads from making requests at the same time.
13619 m_action = W32ETA_CREATE_PROCESS;
13621 BOOL succ = SetEvent(m_threadControlEvent);
13625 DWORD ret = WaitForSingleObject(m_actionTakenEvent, INFINITE);
13627 LOG((LF_CORDB, LL_EVERYTHING, "Process Handle is: %x, m_threadControlEvent is %x\n",
13628 (UINT_PTR)m_actionData.createData.lpProcessInformation->hProcess, (UINT_PTR)m_threadControlEvent));
13630 if (ret == WAIT_OBJECT_0)
13631 hr = m_actionResult;
13633 hr = HRESULT_FROM_GetLastError();
13636 hr = HRESULT_FROM_GetLastError();
13638 UnlockSendToWin32EventThreadMutex();
13644 //---------------------------------------------------------------------------------------
13646 // Create a process
13649 // This occurs on the win32 event thread. It is invokved via
13650 // a message sent from code:CordbWin32EventThread::SendCreateProcessEvent
13653 // Create a new process. This is called in the context of the Win32
13654 // event thread to ensure that if we're Win32 debugging the process
13655 // that the same thread that waits for debugging events will be the
13656 // thread that creates the process.
13658 //---------------------------------------------------------------------------------------
13659 void CordbWin32EventThread::CreateProcess()
13661 m_action = W32ETA_NONE;
13664 DWORD dwCreationFlags = m_actionData.createData.dwCreationFlags;
13666 // If the creation flags has DEBUG_PROCESS in them, then we're
13667 // Win32 debugging this process. Otherwise, we have to create
13668 // suspended to give us time to setup up our side of the IPC
13670 BOOL fInteropDebugging =
13671 #if defined(FEATURE_INTEROP_DEBUGGING)
13672 (dwCreationFlags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS));
13674 false; // Interop not supported.
13677 // Have Win32 create the process...
13678 hr = m_pNativePipeline->CreateProcessUnderDebugger(
13679 m_actionData.createData.machineInfo,
13680 m_actionData.createData.programName,
13681 m_actionData.createData.programArgs,
13682 m_actionData.createData.lpProcessAttributes,
13683 m_actionData.createData.lpThreadAttributes,
13684 m_actionData.createData.bInheritHandles,
13686 m_actionData.createData.lpEnvironment,
13687 m_actionData.createData.lpCurrentDirectory,
13688 m_actionData.createData.lpStartupInfo,
13689 m_actionData.createData.lpProcessInformation);
13693 // Process ID is filled in after process is succesfully created.
13694 DWORD dwProcessId = m_actionData.createData.lpProcessInformation->dwProcessId;
13696 RSUnsafeExternalSmartPtr<CordbProcess> pProcess;
13697 hr = m_pShim->InitializeDataTarget(dwProcessId);
13701 // To emulate V2 semantics, we pass 0 for the clrInstanceID into
13702 // OpenVirtualProcess. This will then connect to the first CLR
13704 const ULONG64 cFirstClrLoaded = 0;
13705 hr = CordbProcess::OpenVirtualProcess(cFirstClrLoaded, m_pShim->GetDataTarget(), NULL, m_cordb, dwProcessId, m_pShim, &pProcess);
13708 // Shouldn't happen on a create, only an attach
13709 _ASSERTE(hr != CORDBG_E_DEBUGGER_ALREADY_ATTACHED);
13711 // Remember the process in the global list of processes.
13716 // Mark if we're interop-debugging
13717 if (fInteropDebugging)
13719 pProcess->EnableInteropDebugging();
13722 m_cordb->AddProcess(pProcess); // will take ref if it succeeds
13724 EX_CATCH_HRESULT(hr);
13727 // If we're Win32 attached to this process, then increment the
13728 // proper count, otherwise add this process to the wait set
13729 // and resume the process's main thread.
13732 _ASSERTE(m_pProcess == NULL);
13733 m_pProcess.Assign(pProcess);
13739 // Signal the hr to the caller.
13741 m_actionResult = hr;
13742 SetEvent(m_actionTakenEvent);
13747 // Send a DebugActiveProcess event to the Win32 thread to have it attach to
13750 HRESULT CordbWin32EventThread::SendDebugActiveProcessEvent(
13751 MachineInfo machineInfo,
13754 CordbProcess *pProcess)
13758 LockSendToWin32EventThreadMutex();
13760 m_actionData.attachData.machineInfo = machineInfo;
13761 m_actionData.attachData.processId = pid;
13762 #if !defined(FEATURE_DBGIPC_TRANSPORT_DI)
13763 m_actionData.attachData.fWin32Attach = fWin32Attach;
13765 m_actionData.attachData.pProcess = pProcess;
13767 // m_action is set last so that the win32 event thread can inspect
13768 // it and take action without actually having to take any
13769 // locks. The lock around this here is simply to prevent multiple
13770 // threads from making requests at the same time.
13771 m_action = W32ETA_ATTACH_PROCESS;
13773 BOOL succ = SetEvent(m_threadControlEvent);
13777 DWORD ret = WaitForSingleObject(m_actionTakenEvent, INFINITE);
13779 if (ret == WAIT_OBJECT_0)
13780 hr = m_actionResult;
13782 hr = HRESULT_FROM_GetLastError();
13785 hr = HRESULT_FROM_GetLastError();
13787 UnlockSendToWin32EventThreadMutex();
13792 //-----------------------------------------------------------------------------
13793 // Is the given thread id a helper thread (real or worker?)
13794 //-----------------------------------------------------------------------------
13795 bool CordbProcess::IsHelperThreadWorked(DWORD tid)
13797 // Check against the id gained by sniffing Thread-Create events.
13798 if (tid == this->m_helperThreadId)
13803 // Now check for potential datate in the IPC block. If not there,
13804 // then we know it can't be the helper.
13805 DebuggerIPCControlBlock * pDCB = this->GetDCB();
13812 // get the latest information from the LS DCB
13813 UpdateRightSideDCB();
13815 (tid == pDCB->m_realHelperThreadId) ||
13816 (tid == pDCB->m_temporaryHelperThreadId);
13820 //---------------------------------------------------------------------------------------
13822 // Cleans up the Left Side's DCB after a failed attach attempt.
13825 // Called when the left-site failed initialization
13828 // This can be called multiple times.
13829 //---------------------------------------------------------------------------------------
13830 void CordbProcess::CleanupHalfBakedLeftSide()
13832 if (GetDCB() != NULL)
13836 GetDCB()->m_rightSideIsWin32Debugger = false;
13837 UpdateLeftSideDCBField(&(GetDCB()->m_rightSideIsWin32Debugger), sizeof(GetDCB()->m_rightSideIsWin32Debugger));
13839 if (m_pEventChannel != NULL)
13841 m_pEventChannel->Delete();
13842 m_pEventChannel = NULL;
13847 _ASSERTE(!"Writing process memory failed, perhaps due to an unexpected disconnection from the target.");
13849 EX_END_CATCH(SwallowAllExceptions);
13852 // Close and null out the various handles and events, including our process handle m_handle.
13857 // This process object is Dead-On-Arrival, so it doesn't really have anything to neuter.
13858 // But for safekeeping, we'll mark it as neutered.
13859 UnsafeNeuterDeadObject();
13863 //---------------------------------------------------------------------------------------
13865 // Attach to an existing process.
13869 // Called on W32Event Thread, in response to event sent by
13870 // code:CordbWin32EventThread::SendDebugActiveProcessEvent
13873 // Attach to a process. This is called in the context of the Win32
13874 // event thread to ensure that if we're Win32 debugging the process
13875 // that the same thread that waits for debugging events will be the
13876 // thread that attaches the process.
13878 // @dbgtodo shim: this will be part of the shim
13879 //---------------------------------------------------------------------------------------
13880 void CordbWin32EventThread::AttachProcess()
13882 _ASSERTE(IsWin32EventThread());
13884 RSUnsafeExternalSmartPtr<CordbProcess> pProcess;
13886 m_action = W32ETA_NONE;
13890 DWORD dwProcessId = m_actionData.attachData.processId;
13891 bool fNativeAttachSucceeded = false;
13894 // Always do OS attach to the target.
13895 // By this point, the pid should be valid (because OpenProcess above), pending some race where the process just exited.
13896 // The OS will enforce that only 1 debugger is attached.
13897 // Common failure paths here would be: access denied, double-attach
13899 hr = m_pNativePipeline->DebugActiveProcess(m_actionData.attachData.machineInfo,
13905 fNativeAttachSucceeded = true;
13909 hr = m_pShim->InitializeDataTarget(m_actionData.attachData.processId);
13915 // To emulate V2 semantics, we pass 0 for the clrInstanceID into
13916 // OpenVirtualProcess. This will then connect to the first CLR
13919 const ULONG64 cFirstClrLoaded = 0;
13920 hr = CordbProcess::OpenVirtualProcess(cFirstClrLoaded, m_pShim->GetDataTarget(), NULL, m_cordb, dwProcessId, m_pShim, &pProcess);
13927 // Remember the process in the global list of processes.
13928 // The caller back in code:Cordb::DebugActiveProcess will then get this by fetching it from the list.
13932 // Mark interop-debugging
13933 if (m_actionData.attachData.IsInteropDebugging())
13935 pProcess->EnableInteropDebugging(); // Throwing
13938 m_cordb->AddProcess(pProcess); // will take ref if it succeeds
13941 // Queue fake Attach event for CreateProcess
13943 PUBLIC_CALLBACK_IN_THIS_SCOPE0_NO_LOCK(pProcess);
13944 m_pShim->BeginQueueFakeAttachEvents();
13947 EX_CATCH_HRESULT(hr);
13953 _ASSERTE(m_pProcess == NULL);
13954 m_pProcess.Assign(pProcess);
13955 pProcess.Clear(); // ownership transfered to m_pProcess
13957 // Should have succeeded if we got to this point.
13958 _ASSERTE(SUCCEEDED(hr));
13964 // If we succeed to do a native-attach, but then failed elsewhere, try to native-detach.
13965 if (fNativeAttachSucceeded)
13967 m_pNativePipeline->DebugActiveProcessStop(dwProcessId);
13970 if (pProcess != NULL)
13972 // Safe to call this even if the process wasn't added.
13973 m_cordb->RemoveProcess(pProcess);
13974 pProcess->CleanupHalfBakedLeftSide();
13977 m_pProcess.Clear();
13981 // Signal the hr to the caller.
13983 m_actionResult = hr;
13984 SetEvent(m_actionTakenEvent);
13988 // Note that the actual 'DetachProcess' method is really ExitProcess with CW32ET_UNKNOWN_PROCESS_SLOT ==
13990 HRESULT CordbWin32EventThread::SendDetachProcessEvent(CordbProcess *pProcess)
13992 LOG((LF_CORDB, LL_INFO1000, "W32ET::SDPE\n"));
13995 LockSendToWin32EventThreadMutex();
13997 m_actionData.detachData.pProcess = pProcess;
13999 // m_action is set last so that the win32 event thread can inspect it and take action without actually
14000 // having to take any locks. The lock around this here is simply to prevent multiple threads from making
14001 // requests at the same time.
14002 m_action = W32ETA_DETACH;
14004 BOOL succ = SetEvent(m_threadControlEvent);
14008 DWORD ret = WaitForSingleObject(m_actionTakenEvent, INFINITE);
14010 if (ret == WAIT_OBJECT_0)
14011 hr = m_actionResult;
14013 hr = HRESULT_FROM_GetLastError();
14016 hr = HRESULT_FROM_GetLastError();
14018 UnlockSendToWin32EventThreadMutex();
14023 #ifdef FEATURE_INTEROP_DEBUGGING
14025 // Send a UnmanagedContinue event to the Win32 thread to have it
14026 // continue from an unmanged debug event.
14028 HRESULT CordbWin32EventThread::SendUnmanagedContinue(CordbProcess *pProcess,
14029 EUMContinueType eContType)
14033 // If this were being called on the win32 EventThread, we'd deadlock.
14034 _ASSERTE(!IsWin32EventThread());
14036 // This can't hold the process lock, b/c we're making a cross-thread call,
14037 // and our target will need the process lock.
14038 _ASSERTE(!pProcess->ThreadHoldsProcessLock());
14040 LockSendToWin32EventThreadMutex();
14042 m_actionData.continueData.process = pProcess;
14043 m_actionData.continueData.eContType = eContType;
14045 // m_action is set last so that the win32 event thread can inspect
14046 // it and take action without actually having to take any
14047 // locks. The lock around this here is simply to prevent multiple
14048 // threads from making requests at the same time.
14049 m_action = W32ETA_CONTINUE;
14051 BOOL succ = SetEvent(m_threadControlEvent);
14055 DWORD ret = WaitForSingleObject(m_actionTakenEvent, INFINITE);
14057 if (ret == WAIT_OBJECT_0)
14058 hr = m_actionResult;
14060 hr = HRESULT_FROM_GetLastError();
14063 hr = HRESULT_FROM_GetLastError();
14065 UnlockSendToWin32EventThreadMutex();
14072 // Handle unmanaged continue. Continue an unmanaged debug
14073 // event. Deferes to UnmanagedContinue. This is called in the context
14074 // of the Win32 event thread to ensure that if we're Win32 debugging
14075 // the process that the same thread that waits for debugging events
14076 // will be the thread that continues the process.
14078 void CordbWin32EventThread::HandleUnmanagedContinue()
14080 _ASSERTE(IsWin32EventThread());
14082 m_action = W32ETA_NONE;
14085 // Continue the process
14086 CordbProcess *pProcess = m_actionData.continueData.process;
14088 // If we lost the process object, we must have exited.
14089 if (m_pProcess != NULL)
14091 _ASSERTE(m_pProcess != NULL);
14092 _ASSERTE(pProcess == m_pProcess);
14094 _ASSERTE(!pProcess->ThreadHoldsProcessLock());
14096 RSSmartPtr<CordbProcess> proc(pProcess);
14097 RSLockHolder ch(&pProcess->m_processMutex);
14099 hr = UnmanagedContinue(pProcess, m_actionData.continueData.eContType);
14102 // Signal the hr to the caller.
14103 m_actionResult = hr;
14104 SetEvent(m_actionTakenEvent);
14108 // Continue an unmanaged debug event. This is called in the context of the Win32 Event thread to ensure that the same
14109 // thread that waits for debug events will be the thread that continues the process.
14111 HRESULT CordbWin32EventThread::UnmanagedContinue(CordbProcess *pProcess,
14112 EUMContinueType eContType)
14114 _ASSERTE(pProcess->ThreadHoldsProcessLock());
14115 _ASSERTE(IsWin32EventThread());
14116 _ASSERTE(m_pShim != NULL);
14120 STRESS_LOG1(LF_CORDB, LL_INFO1000, "UM Continue. type=%d\n", eContType);
14122 if (eContType == cOobUMContinue)
14124 _ASSERTE(pProcess->m_outOfBandEventQueue != NULL);
14126 // Dequeue the OOB event.
14127 CordbUnmanagedEvent *ue = pProcess->m_outOfBandEventQueue;
14128 CordbUnmanagedThread *ut = ue->m_owner;
14129 pProcess->DequeueOOBUnmanagedEvent(ut);
14131 // Do a little extra work if that was an OOB exception event...
14132 hr = ue->m_owner->FixupAfterOOBException(ue);
14133 _ASSERTE(SUCCEEDED(hr));
14135 // Continue from the event.
14136 DoDbgContinue(pProcess, ue);
14138 // If there are more queued OOB events, dispatch them now.
14139 if (pProcess->m_outOfBandEventQueue != NULL)
14140 pProcess->DispatchUnmanagedOOBEvent();
14142 // Note: if we previously skipped letting the entire process go on an IB continue due to a blocking OOB event,
14143 // and if the OOB event queue is now empty, then go ahead and let the process continue now...
14144 if ((pProcess->m_doRealContinueAfterOOBBlock == true) &&
14145 (pProcess->m_outOfBandEventQueue == NULL))
14146 goto doRealContinue;
14148 else if (eContType == cInternalUMContinue)
14150 // We're trying to get into a synced state which means we need the process running (potentially
14151 // with some threads hijacked) in order to have the helper thread do the sync.
14152 LOG((LF_CORDB, LL_INFO1000, "W32ET::UC: internal continue.\n"));
14154 if (!pProcess->GetSynchronized())
14156 LOG((LF_CORDB, LL_INFO1000, "W32ET::UC: internal continue, !sync'd.\n"));
14157 pProcess->ResumeUnmanagedThreads();
14159 // the event we may need to hijack and continue;
14160 CordbUnmanagedEvent* pEvent = pProcess->m_lastQueuedUnmanagedEvent;
14162 // It is possible to be stopped at either an IB or an OOB event here. We only want to
14163 // continue from an IB event here though
14164 if(pProcess->m_state & CordbProcess::PS_WIN32_STOPPED && pEvent != NULL &&
14165 pEvent->IsEventWaitingForContinue())
14167 LOG((LF_CORDB, LL_INFO1000, "W32ET::UC: internal continue, frozen on IB event.\n"));
14169 // There should be a uncontinued IB event at the head of the queue
14170 _ASSERTE(pEvent->IsIBEvent());
14171 _ASSERTE(!pEvent->IsEventContinuedUnhijacked());
14172 _ASSERTE(!pEvent->IsEventContinuedHijacked());
14174 // Ensure that the event is hijacked now (it may not have been before) so that the
14175 // thread does not slip forward during the sync process. After that we can safely continue
14177 pProcess->HijackIBEvent(pEvent);
14178 m_pShim->GetWin32EventThread()->DoDbgContinue(pProcess, pEvent);
14182 LOG((LF_CORDB, LL_INFO1000, "W32ET::UC: internal continue, done.\n"));
14186 // If we're here, then we know 100% for sure that we've successfully gotten the managed continue event to the
14187 // Left Side, so we can stop force hijacking left over in-band events now. Note: if we had hijacked any such
14188 // events, they'll be dispatched below since they're properly queued.
14189 pProcess->m_specialDeferment = false;
14191 // We don't actually do any work if there is an outstanding out-of-band event. When we do continue from the
14192 // out-of-band event, we'll do this work, too.
14193 if (pProcess->m_outOfBandEventQueue != NULL)
14195 LOG((LF_CORDB, LL_INFO1000, "W32ET::UC: ignoring real continue due to block by out-of-band event(s).\n"));
14197 _ASSERTE(pProcess->m_doRealContinueAfterOOBBlock == false);
14198 pProcess->m_doRealContinueAfterOOBBlock = true;
14203 // This is either the Frozen -> Running transition or a
14204 // Synced -> Running transition
14205 _ASSERTE(pProcess->m_outOfBandEventQueue == NULL);
14208 pProcess->m_doRealContinueAfterOOBBlock = false;
14210 LOG((LF_CORDB, LL_INFO1000, "W32ET::UC: continuing the process.\n"));
14211 // Dispatch any more queued in-band events, or if there are none then just continue the process.
14213 // Note: don't dispatch more events if we've already sent up the ExitProcess event... those events are just
14215 if ((pProcess->HasUndispatchedNativeEvents()) && (pProcess->m_exiting == false))
14217 pProcess->DispatchUnmanagedInBandEvent();
14221 // If the unmanaged event queue is empty now, and the process is synchronized, and there are queued
14222 // managed events, then go ahead and get more managed events dispatched.
14224 // Note: don't dispatch more events if we've already sent up the ExitProcess event... those events are
14226 if (pProcess->GetSynchronized() && (!m_pShim->GetManagedEventQueue()->IsEmpty()) && (pProcess->m_exiting == false))
14228 if(pProcess->m_state & CordbProcess::PS_WIN32_STOPPED)
14230 DoDbgContinue(pProcess, pProcess->m_lastDispatchedIBEvent);
14232 // This if should not be necessary, I am just being extra careful because this
14233 // fix is going in late - see issue 818301
14234 _ASSERTE(pProcess->m_lastDispatchedIBEvent != NULL);
14235 if(pProcess->m_lastDispatchedIBEvent != NULL)
14237 pProcess->m_lastDispatchedIBEvent->m_owner->InternalRelease();
14238 pProcess->m_lastDispatchedIBEvent = NULL;
14242 // Now, get more managed events dispatched.
14243 pProcess->SetSynchronized(false);
14244 pProcess->MarkAllThreadsDirty();
14245 m_cordb->ProcessStateChanged();
14249 // free all the hijacked threads that hit native debug events
14250 pProcess->ResumeHijackedThreads();
14252 // after continuing the here the process should be running completely
14253 // free... no hijacks, no suspended threads, and of course not frozen
14254 if(pProcess->m_state & CordbProcess::PS_WIN32_STOPPED)
14256 DoDbgContinue(pProcess, pProcess->m_lastDispatchedIBEvent);
14257 // This if should not be necessary, I am just being extra careful because this
14258 // fix is going in late - see issue 818301
14259 _ASSERTE(pProcess->m_lastDispatchedIBEvent != NULL);
14260 if(pProcess->m_lastDispatchedIBEvent != NULL)
14262 pProcess->m_lastDispatchedIBEvent->m_owner->InternalRelease();
14263 pProcess->m_lastDispatchedIBEvent = NULL;
14269 // Implicit Release on UT
14275 #endif // FEATURE_INTEROP_DEBUGGING
14277 void ExitProcessWorkItem::Do()
14279 STRESS_LOG1(LF_CORDB, LL_INFO1000, "ExitProcessWorkItem proc=%p\n", GetProcess());
14281 // This is being called on the RCET.
14282 // That's the thread that dispatches managed events. Since it's calling us now, we know
14283 // it can't be dispatching a managed event, and so we don't need to both waiting for it
14286 // Get the SG lock here to coordinate against any other continues.
14287 RSLockHolder ch(GetProcess()->GetStopGoLock());
14288 RSLockHolder ch2(&(GetProcess()->m_processMutex));
14290 LOG((LF_CORDB, LL_INFO1000,"W32ET::EP: ExitProcess callback\n"));
14292 // We're synchronized now, so mark the process as such.
14293 GetProcess()->SetSynchronized(true);
14294 GetProcess()->IncStopCount();
14296 // By the time we release the SG + Process locks here, the process object has been
14297 // marked as exiting + terminated (by the w32et which queued us). Future attemps to
14298 // continue should fail, and thus we should remain synchronized.
14302 // Just to be safe, neuter any children before the exit process callback.
14304 RSLockHolder ch(GetProcess()->GetProcessLock());
14306 // Release the process.
14307 GetProcess()->NeuterChildren();
14310 RSSmartPtr<Cordb> pCordb(NULL);
14312 // There is a race condition here where the debuggee process is killed while we are processing a process
14313 // detach. We queue the process exit event for the Win32 event thread before queueing the process detach
14314 // event. By the time this function is executed, we may have neutered the CordbProcess already as a
14315 // result of code:CordbProcess::Detach. Detect that case here under the SG lock.
14317 RSLockHolder ch(GetProcess()->GetStopGoLock());
14318 if (!GetProcess()->IsNeutered())
14320 _ASSERTE(GetProcess()->m_cordb != NULL);
14321 pCordb.Assign(GetProcess()->m_cordb);
14325 // Move this into Shim?
14327 // Invoke the ExitProcess callback. This is very important since the a shell
14328 // may rely on it for proper shutdown and may hang if they don't get it.
14329 // We don't expect Cordbg to continue from this (we're certainly not going to wait for it).
14330 if ((pCordb != NULL) && (pCordb->m_managedCallback != NULL))
14332 PUBLIC_CALLBACK_IN_THIS_SCOPE0_NO_LOCK(GetProcess());
14333 pCordb->m_managedCallback->ExitProcess(GetProcess());
14336 // This CordbProcess object now has no reservations against a client calling ICorDebug::Terminate.
14337 // That call may race against the CordbProcess::Neuter below, but since we already neutered the children,
14338 // that neuter call will not do anything interesting that will conflict with Terminate.
14340 LOG((LF_CORDB, LL_INFO1000,"W32ET::EP: returned from ExitProcess callback\n"));
14343 RSLockHolder ch(GetProcess()->GetStopGoLock());
14345 // Release the process.
14346 GetProcess()->Neuter();
14349 // Our dtor will release the Process object.
14350 // This may be the final release on the process.
14354 //---------------------------------------------------------------------------------------
14356 // Handles process exiting and detach cases
14359 // fDetach - true if detaching, false if process is exiting.
14362 // The type of the next argument in the signature,
14366 // On exit, the process has already exited and we detected this by either an EXIT_PROCESS
14367 // native debug event, or by waiting on the process handle.
14368 // On detach, the process is stil live.
14371 // ExitProcess is called when a process exits or detaches.
14372 // This does our final cleanup and removes the process from our wait sets.
14373 // We're either here because we're detaching (fDetach == TRUE), or because the process has really exited,
14374 // and we're doing shutdown logic.
14376 //---------------------------------------------------------------------------------------
14377 void CordbWin32EventThread::ExitProcess(bool fDetach)
14379 INTERNAL_API_ENTRY(this);
14381 // Consider the following when you're modifying this function:
14382 // - The OS can kill the debuggee at any time.
14383 // - ExitProcess can race with detach.
14385 LOG((LF_CORDB, LL_INFO1000,"W32ET::EP: begin ExitProcess, detach=%d\n", fDetach));
14388 // For the Mac remote debugging transport, DebugActiveProcessStop() is a nop. The transport will be
14389 // shut down later when we neuter the CordbProcess.
14390 #if !defined(FEATURE_DBGIPC_TRANSPORT_DI)
14391 // @dbgtodo shim: this is a primitive workaround for interop-detach
14392 // Eventually, the Debugger owns the detach pipeline, so this won't be necessary.
14393 if (fDetach && (m_pProcess != NULL))
14395 HRESULT hr = m_pNativePipeline->DebugActiveProcessStop(m_pProcess->GetPid());
14397 // We don't expect detach to fail (we check earlier for common conditions that
14398 // may cause it to fail)
14399 SIMPLIFYING_ASSUMPTION(SUCCEEDED(hr));
14402 m_actionResult = hr;
14403 SetEvent(m_actionTakenEvent);
14407 #endif // !FEATURE_DBGIPC_TRANSPORT_DI
14410 // We don't really care if we're on the Win32 thread or not here. We just want to be sure that
14411 // the LS Exit case and the Detach case both occur on the same thread. This makes it much easier
14412 // to assert that if we exit while detaching, EP is only called once.
14413 // If we ever decide to make the RCET listen on the LS process handle for EP(exit), then we should also
14414 // make the EP(detach) handled on the RCET (via DoFavor() ).
14415 _ASSERTE(IsWin32EventThread());
14417 // So either the Exit case or Detach case must happen first.
14418 // 1) If Detach first, then LS process is removed from wait set and so EP(Exit) will never happen
14419 // because we check wait set after returning from EP(Detach).
14420 // 2) If Exit is first, m_pProcess gets set=NULL. EP(detach) will still get called, so explicitly check that.
14421 if (fDetach && ((m_pProcess == NULL) || m_pProcess->m_terminated))
14423 // m_terminated is only set after the LS exits.
14424 // So the only way (fDetach && m_terminated) is true is if the LS exited while detaching. In that case
14425 // we already called EP(exit) and we don't want to call it again for EP(detach). So return here.
14426 LOG((LF_CORDB, LL_INFO1000,"W32ET::EP: In EP(detach), but EP(exit) already called. Early failure\n"));
14428 m_actionResult = CORDBG_E_PROCESS_TERMINATED;
14429 SetEvent(m_actionTakenEvent);
14434 // We null m_pProcess at the end here, so
14435 // Only way we could get here w/ null process is if we're called twice. We can only be called
14436 // by detach or exit. Can't detach twice, can't exit twice, so must have been one of each.
14437 // If exit is first, we got removed from the wait set, so 2nd call must be detach and we'd catch
14438 // that above. If detach is first, we'd get removed from the wait set and so exit would never happen.
14439 _ASSERTE(m_pProcess != NULL);
14440 _ASSERTE(!m_pProcess->ThreadHoldsProcessLock());
14444 // Mark the process teminated. After this, the RCET will never call FlushQueuedEvents. It will
14445 // ignore all events it receives (including a SyncComplete) and the RCET also does not listen
14446 // to terminated processes (so ProcessStateChange() won't cause a FQE either).
14447 m_pProcess->Terminating(fDetach);
14449 // Take care of the race where the process exits right after the user calls Continue() from the last
14450 // managed event but before the handler has actually returned.
14452 // Also, To get through this lock means that either:
14453 // 1. FlushQueuedEvents is not currently executing and no one will call FQE.
14454 // 2. FQE is exiting but is in the middle of a callback (so AreDispatchingEvent = true)
14456 m_pProcess->Lock();
14458 m_pProcess->m_exiting = true;
14462 m_pProcess->SetSynchronized(false);
14465 // If we are exiting, we *must* dispatch the ExitProcess callback, but we will delete all the events
14466 // in the queue and not bother dispatching anything else. If (and only if) we are currently dispatching
14467 // an event, then we will wait while that event is finished before invoking ExitProcess.
14468 // (Note that a dispatched event has already been removed from the queue)
14470 // Remove the process from the global list of processes.
14471 m_cordb->RemoveProcess(m_pProcess);
14475 // Signal the hr to the caller.
14476 LOG((LF_CORDB, LL_INFO1000,"W32ET::EP: Detach: send result back!\n"));
14478 m_actionResult = S_OK;
14479 SetEvent(m_actionTakenEvent);
14482 m_pProcess->Unlock();
14484 // Delete all queued events
14485 m_pProcess->DeleteQueuedEvents();
14488 // If we're detaching, then the Detach already neutered everybody, so nothing here.
14489 // If we're exiting, then we still need to neuter things, but we can't do that on this thread,
14490 // so we queue it. We also need to dispatch an exit process callback. We'll queue that onto the RCET
14491 // and dispatch it inband w/the other callbacks.
14495 // Cleanup the transport pipe and semaphore files that might be left by the target (LS) process.
14496 m_pNativePipeline->CleanupTargetProcess();
14498 ExitProcessWorkItem * pItem = new (nothrow) ExitProcessWorkItem(m_pProcess);
14501 m_cordb->m_rcEventThread->QueueAsyncWorkItem(pItem);
14505 // This will remove the process from our wait lists (so that we don't send multiple ExitProcess events).
14506 m_pProcess.Clear();
14511 // Start actually creates and starts the thread.
14513 HRESULT CordbWin32EventThread::Start()
14516 if (m_threadControlEvent == NULL)
14517 return E_INVALIDARG;
14519 // Create the thread suspended to make sure that m_threadId is set
14520 // before CordbWin32EventThread::ThreadProc runs
14521 // Stack size = 0x80000 = 512KB
14522 m_thread = CreateThread(NULL, 0x80000, &CordbWin32EventThread::ThreadProc,
14523 (LPVOID) this, CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION, &m_threadId);
14525 if (m_thread == NULL)
14526 return HRESULT_FROM_GetLastError();
14528 DWORD succ = ResumeThread(m_thread);
14529 if (succ == (DWORD)-1)
14530 return HRESULT_FROM_GetLastError();
14536 // Stop causes the thread to stop receiving events and exit. It
14537 // waits for it to exit before returning.
14539 HRESULT CordbWin32EventThread::Stop()
14543 // m_pProcess may be NULL from CordbWin32EventThread::ExitProcess
14545 // Can't block on W32ET while holding the process-lock since the W32ET may need that to exit.
14546 // But since m_pProcess may be null, we can't enforce that.
14548 if (m_thread != NULL)
14550 LockSendToWin32EventThreadMutex();
14551 m_action = W32ETA_NONE;
14554 SetEvent(m_threadControlEvent);
14555 UnlockSendToWin32EventThreadMutex();
14557 DWORD ret = WaitForSingleObject(m_thread, INFINITE);
14559 if (ret != WAIT_OBJECT_0)
14560 hr = HRESULT_FROM_GetLastError();
14563 m_pProcess.Clear();
14576 // Allocate a buffer of cbBuffer bytes in the target.
14579 // cbBuffer - count of bytes for the buffer.
14582 // a TargetBuffer describing the new memory region in the target.
14583 // Throws on error.
14584 TargetBuffer CordbProcess::GetRemoteBuffer(ULONG cbBuffer)
14586 INTERNAL_SYNC_API_ENTRY(this); //
14588 // Create and initialize the event as synchronous
14589 DebuggerIPCEvent event;
14590 InitIPCEvent(&event,
14591 DB_IPCE_GET_BUFFER,
14593 VMPTR_AppDomain::NullPtr());
14595 // Indicate the buffer size wanted
14596 event.GetBuffer.bufSize = cbBuffer;
14598 // Make the request, which is synchronous
14599 HRESULT hr = SendIPCEvent(&event, sizeof(event));
14601 _ASSERTE(event.type == DB_IPCE_GET_BUFFER_RESULT);
14603 IfFailThrow(event.GetBufferResult.hr);
14605 // The request succeeded. Return the newly allocated range.
14606 return TargetBuffer(event.GetBufferResult.pBuffer, cbBuffer);
14610 * This will release a previously allocated left side buffer.
14612 HRESULT CordbProcess::ReleaseRemoteBuffer(void **ppBuffer)
14614 INTERNAL_SYNC_API_ENTRY(this); //
14616 _ASSERTE(m_pShim != NULL);
14618 // Create and initialize the event as synchronous
14619 DebuggerIPCEvent event;
14620 InitIPCEvent(&event,
14621 DB_IPCE_RELEASE_BUFFER,
14623 VMPTR_AppDomain::NullPtr());
14625 // Indicate the buffer to release
14626 event.ReleaseBuffer.pBuffer = (*ppBuffer);
14628 // Make the request, which is synchronous
14629 HRESULT hr = SendIPCEvent(&event, sizeof(event));
14630 TESTANDRETURNHR(hr);
14632 (*ppBuffer) = NULL;
14634 // Indicate success
14635 return event.ReleaseBufferResult.hr;
14638 HRESULT CordbProcess::SetDesiredNGENCompilerFlags(DWORD dwFlags)
14640 PUBLIC_API_ENTRY(this);
14641 FAIL_IF_NEUTERED(this);
14643 #if defined(FEATURE_PREJIT)
14644 if ((dwFlags != CORDEBUG_JIT_DEFAULT) && (dwFlags != CORDEBUG_JIT_DISABLE_OPTIMIZATION))
14646 return E_INVALIDARG;
14649 CordbProcess *pProcess = GetProcess();
14650 ATT_REQUIRE_STOPPED_MAY_FAIL(pProcess);
14654 // Left-side checks that this is a valid time to set the Ngen flags.
14655 hr = pProcess->GetDAC()->SetNGENCompilerFlags(dwFlags);
14656 if (!SUCCEEDED(hr) && GetShim() != NULL)
14658 // Emulate V2 error semantics.
14659 hr = GetShim()->FilterSetNgenHresult(hr);
14662 EX_CATCH_HRESULT(hr);
14665 #else // !FEATURE_PREJIT
14666 return CORDBG_E_NGEN_NOT_SUPPORTED;
14668 #endif // FEATURE_PREJIT
14671 HRESULT CordbProcess::GetDesiredNGENCompilerFlags(DWORD *pdwFlags )
14673 PUBLIC_API_ENTRY(this);
14674 FAIL_IF_NEUTERED(this);
14675 VALIDATE_POINTER_TO_OBJECT(pdwFlags, DWORD*);
14678 CordbProcess *pProcess = GetProcess();
14679 ATT_REQUIRE_STOPPED_MAY_FAIL(pProcess);
14683 hr = pProcess->GetDAC()->GetNGENCompilerFlags(pdwFlags);
14685 EX_CATCH_HRESULT(hr);
14689 //-----------------------------------------------------------------------------
14690 // Get an ICorDebugReference Value for the GC handle.
14691 // handle - raw bits for the GC handle.
14693 //-----------------------------------------------------------------------------
14694 HRESULT CordbProcess::GetReferenceValueFromGCHandle(
14696 ICorDebugReferenceValue **pOutValue)
14698 PUBLIC_API_ENTRY(this);
14699 FAIL_IF_NEUTERED(this);
14700 ATT_REQUIRE_STOPPED_MAY_FAIL(this);
14701 VALIDATE_POINTER_TO_OBJECT(pOutValue, ICorDebugReferenceValue*);
14708 if (gcHandle == NULL)
14710 ThrowHR(CORDBG_E_BAD_REFERENCE_VALUE);
14713 IDacDbiInterface* pDAC = GetProcess()->GetDAC();
14714 VMPTR_OBJECTHANDLE vmObjHandle = pDAC->GetVmObjectHandle(gcHandle);
14715 if(!pDAC->IsVmObjectHandleValid(vmObjHandle))
14717 ThrowHR(CORDBG_E_BAD_REFERENCE_VALUE);
14719 ULONG appDomainId = pDAC->GetAppDomainIdFromVmObjectHandle(vmObjHandle);
14720 VMPTR_AppDomain vmAppDomain = pDAC->GetAppDomainFromId(appDomainId);
14722 RSLockHolder lockHolder(GetProcessLock());
14723 CordbAppDomain * pAppDomain = LookupOrCreateAppDomain(vmAppDomain);
14724 lockHolder.Release();
14726 // Now that we finally have the AppDomain, we can go ahead and get a ReferenceValue
14727 // from the ObjectHandle.
14728 hr = CordbReferenceValue::BuildFromGCHandle(pAppDomain, vmObjHandle, pOutValue);
14729 _ASSERTE(SUCCEEDED(hr) == (*pOutValue != NULL));
14732 EX_CATCH_HRESULT(hr);
14736 //-----------------------------------------------------------------------------
14737 // Return count of outstanding GC handles held by CordbHandleValue objects
14738 LONG CordbProcess::OutstandingHandles()
14740 return m_cOutstandingHandles;
14743 //-----------------------------------------------------------------------------
14744 // Increment the outstanding handle count for code:CordbProces::OutstandingHandles
14745 // This is the inverse of code:CordbProces::DecrementOutstandingHandles
14746 void CordbProcess::IncrementOutstandingHandles()
14748 _ASSERTE(ThreadHoldsProcessLock());
14749 m_cOutstandingHandles++;
14752 //-----------------------------------------------------------------------------
14753 // Decrement the outstanding handle count for code:CordbProces::OutstandingHandles
14754 // This is the inverse of code:CordbProces::IncrementOutstandingHandles
14755 void CordbProcess::DecrementOutstandingHandles()
14757 _ASSERTE(ThreadHoldsProcessLock());
14758 m_cOutstandingHandles--;
14765 * This method encapsulates all logic for deciding if it is ok for a debugger to
14766 * detach from the process at this time.
14768 * Parameters: None.
14770 * Returns: S_OK if it is ok to detach, else a specific HRESULT describing why it
14771 * is not ok to detach.
14774 HRESULT CordbProcess::IsReadyForDetach()
14776 INTERNAL_API_ENTRY(this);
14778 // Always safe to detach in V3 case.
14779 if (m_pShim == NULL)
14784 // If not initialized yet, then there are no detach liabilities.
14785 if (!m_initialized)
14790 RSLockHolder lockHolder(&this->m_processMutex);
14793 // If there are any outstanding func-evals then fail the detach.
14795 if (OutstandingEvalCount() != 0)
14797 return CORDBG_E_DETACH_FAILED_OUTSTANDING_EVALS;
14800 // V2 didn't check outstanding handles (code:CordbProcess::OutstandingHandles)
14801 // because it could automatically clean those up on detach.
14804 // If there are any outstanding steppers then fail the detach.
14806 if (m_steppers.IsInitialized() && (m_steppers.GetCount() > 0))
14808 return CORDBG_E_DETACH_FAILED_OUTSTANDING_STEPPERS;
14812 // If there are any outstanding breakpoints then fail the detach.
14814 HASHFIND foundAppDomain;
14815 CordbAppDomain *pAppDomain = m_appDomains.FindFirst(&foundAppDomain);
14817 while (pAppDomain != NULL)
14819 if (pAppDomain->m_breakpoints.IsInitialized() && (pAppDomain->m_breakpoints.GetCount() > 0))
14821 return CORDBG_E_DETACH_FAILED_OUTSTANDING_BREAKPOINTS;
14824 // Check for any outstanding EnC modules.
14825 HASHFIND foundModule;
14826 CordbModule * pModule = pAppDomain->m_modules.FindFirst(&foundModule);
14827 while (pModule != NULL)
14829 if (pModule->m_EnCCount > 0)
14831 return CORDBG_E_DETACH_FAILED_ON_ENC;
14833 pModule = pAppDomain->m_modules.FindNext(&foundModule);
14837 pAppDomain = m_appDomains.FindNext(&foundAppDomain);
14840 // If we're using the shim, give a chance to early-out if the OS doesn't support detach
14841 // so that the user can continue to debug in that case.
14842 // Ideally we'd just rely on the failure from DebugActiveProcessStop, but by then it's too late
14843 // to recover. This function is our only chance to distinguish between graceful detach failures
14844 // and hard detach failures (after which the process object is neutered).
14845 if (m_pShim != NULL)
14847 #if !defined(FEATURE_CORESYSTEM) // CORESYSTEM TODO
14848 HModuleHolder hKernel32;
14849 hKernel32 = WszLoadLibrary(W("kernel32"));
14850 if (hKernel32 == NULL)
14851 return HRESULT_FROM_GetLastError();
14852 typedef BOOL (*DebugActiveProcessStopSig) (DWORD);
14853 DebugActiveProcessStopSig pDebugActiveProcessStop =
14854 reinterpret_cast<DebugActiveProcessStopSig>(GetProcAddress(hKernel32, "DebugActiveProcessStop"));
14855 if (pDebugActiveProcessStop == NULL)
14856 return COR_E_PLATFORMNOTSUPPORTED;
14865 * Look for any thread which was last seen in the specified AppDomain.
14866 * The CordbAppDomain object is about to be neutered due to an AD Unload
14867 * So the thread must no longer be considered to be in that domain.
14868 * Note that this is a workaround due to the existance of the (possibly incorrect)
14869 * cached AppDomain value. Ideally we would remove the cached value entirely
14870 * and there would be no need for this.
14872 * @dbgtodo: , appdomain: We should remove CordbThread::m_pAppDomain in the V3 architecture.
14873 * If we need the thread's current domain, we should get it accurately with DAC.
14875 void CordbProcess::UpdateThreadsForAdUnload(CordbAppDomain * pAppDomain)
14877 INTERNAL_API_ENTRY(this);
14879 // If we're doing an AD unload then we should have already seen the ATTACH
14880 // notification for the default domain.
14881 //_ASSERTE( m_pDefaultAppDomain != NULL );
14882 // @dbgtodo appdomain: fix Default domain invariants with DAC-izing Appdomain work.
14884 RSLockHolder lockHolder(GetProcessLock());
14889 // We don't need to prepopulate here (to collect LS state) because we're just updating RS state.
14890 for (t = m_userThreads.FindFirst(&find);
14892 t = m_userThreads.FindNext(&find))
14894 if( t->GetAppDomain() == pAppDomain )
14896 // This thread cannot actually be in this AppDomain anymore (since it's being
14897 // unloaded). Reset it to point to the default AppDomain
14898 t->m_pAppDomain = m_pDefaultAppDomain;
14903 // CordbProcess::LookupClass
14904 // Looks up a previously constructed CordbClass instance without creating. May return NULL if the
14905 // CordbClass instance doesn't exist.
14906 // Argument: (in) vmDomainFile - pointer to the domainfile for the module
14907 // (in) mdTypeDef - metadata token for the class
14908 // Return value: pointer to a previously created CordbClass instance or NULL in none exists
14909 CordbClass * CordbProcess::LookupClass(ICorDebugAppDomain * pAppDomain, VMPTR_DomainFile vmDomainFile, mdTypeDef classToken)
14911 _ASSERTE(ThreadHoldsProcessLock());
14913 if (pAppDomain != NULL)
14915 CordbModule * pModule = ((CordbAppDomain *)pAppDomain)->m_modules.GetBase(VmPtrToCookie(vmDomainFile));
14916 if (pModule != NULL)
14918 return pModule->LookupClass(classToken);
14922 } // CordbProcess::LookupClass
14924 //---------------------------------------------------------------------------------------
14925 // Look for a specific module in the process.
14928 // vmDomainFile - non-null module to lookup
14931 // a CordbModule object for the given cookie. Object may be from the cache, or created
14933 // Never returns null. Throws on error.
14936 // A VMPTR_DomainFile has appdomain affinity, but is ultimately scoped to a process.
14937 // So if we get a raw VMPTR_DomainFile (eg, from the stackwalker or from some other
14938 // lookup function), then we need to do a process wide lookup since we don't know which
14939 // appdomain it's in. If you know the appdomain, you can use code:CordbAppDomain::LookupOrCreateModule.
14941 CordbModule * CordbProcess::LookupOrCreateModule(VMPTR_DomainFile vmDomainFile)
14943 INTERNAL_API_ENTRY(this);
14945 RSLockHolder lockHolder(GetProcess()->GetProcessLock());
14946 _ASSERTE(!vmDomainFile.IsNull());
14948 DomainFileInfo data;
14949 GetDAC()->GetDomainFileData(vmDomainFile, &data); // throws
14951 CordbAppDomain * pAppDomain = LookupOrCreateAppDomain(data.vmAppDomain);
14952 return pAppDomain->LookupOrCreateModule(vmDomainFile);
14955 //---------------------------------------------------------------------------------------
14956 // Determine if the process has any in-band queued events which have not been dispatched
14959 // TRUE iff there are undispatched IB events
14961 #ifdef FEATURE_INTEROP_DEBUGGING
14962 BOOL CordbProcess::HasUndispatchedNativeEvents()
14964 INTERNAL_API_ENTRY(this);
14966 CordbUnmanagedEvent* pEvent = m_unmanagedEventQueue;
14967 while(pEvent != NULL && pEvent->IsDispatched())
14969 pEvent = pEvent->m_next;
14972 return pEvent != NULL;
14976 //---------------------------------------------------------------------------------------
14977 // Determine if the process has any in-band queued events which have not been user continued
14980 // TRUE iff there are user uncontinued IB events
14982 #ifdef FEATURE_INTEROP_DEBUGGING
14983 BOOL CordbProcess::HasUserUncontinuedNativeEvents()
14985 INTERNAL_API_ENTRY(this);
14987 CordbUnmanagedEvent* pEvent = m_unmanagedEventQueue;
14988 while(pEvent != NULL && pEvent->IsEventUserContinued())
14990 pEvent = pEvent->m_next;
14993 return pEvent != NULL;
14997 //---------------------------------------------------------------------------------------
14998 // Hijack the thread which had this event. If the thread is already hijacked this method
15002 // pUnmanagedEvent - the debug event which requires us to hijack
15005 // S_OK on success, failing HRESULT if the hijack could not be set up
15007 #ifdef FEATURE_INTEROP_DEBUGGING
15008 HRESULT CordbProcess::HijackIBEvent(CordbUnmanagedEvent * pUnmanagedEvent)
15010 // Can't hijack after the event has already been continued hijacked
15011 _ASSERTE(!pUnmanagedEvent->IsEventContinuedHijacked());
15012 // Can only hijack IB events
15013 _ASSERTE(pUnmanagedEvent->IsIBEvent());
15015 // If we already hijacked the event then there is nothing left to do
15016 if(pUnmanagedEvent->m_owner->IsFirstChanceHijacked() ||
15017 pUnmanagedEvent->m_owner->IsGenericHijacked())
15022 ResetEvent(this->m_leftSideUnmanagedWaitEvent);
15023 if (pUnmanagedEvent->m_currentDebugEvent.u.Exception.dwFirstChance)
15025 HRESULT hr = pUnmanagedEvent->m_owner->SetupFirstChanceHijackForSync();
15026 SIMPLIFYING_ASSUMPTION(SUCCEEDED(hr));
15029 else // Second chance exceptions must be generic hijacked.
15031 HRESULT hr = pUnmanagedEvent->m_owner->SetupGenericHijack(pUnmanagedEvent->m_currentDebugEvent.dwDebugEventCode, &pUnmanagedEvent->m_currentDebugEvent.u.Exception.ExceptionRecord);
15032 SIMPLIFYING_ASSUMPTION(SUCCEEDED(hr));
15038 // Sets a bitfield reflecting the managed debugging state at the time of
15040 HRESULT CordbProcess::GetAttachStateFlags(CLR_DEBUGGING_PROCESS_FLAGS *pFlags)
15043 PUBLIC_REENTRANT_API_BEGIN(this)
15048 *pFlags = GetDAC()->GetAttachStateFlags();
15050 PUBLIC_API_END(hr);
15055 // Determine if this version of ICorDebug is compatibile with the ICorDebug in the specified major CLR version
15056 bool CordbProcess::IsCompatibleWith(DWORD clrMajorVersion)
15058 // The debugger versioning policy is that debuggers generally need to opt-in to supporting major new
15059 // versions of the CLR. Often new versions of the CLR violate some invariant that previous debuggers assume
15060 // (eg. hot/cold splitting in Whidbey, multiple CLRs in a process in CLR v4), and neither VS or the CLR
15061 // teams generally want the support burden of forward compatibility.
15064 // If this assert is firing for you, its probably because the major version
15065 // number of the clr.dll has changed. This assert is here to remind you to do a bit of other
15066 // work you may not have realized you needed to do so that our versioning works smoothly
15067 // for debugging. You probably want to contact the CLR DST team if you are a
15068 // non-debugger person hitting this. DON'T JUST DELETE THIS ASSERT!!!
15070 // 1) You should ensure new versions of all ICorDebug users in DevDiv (VS Debugger, MDbg, etc.)
15071 // are using a creation path that explicitly specifies that they support this new major
15072 // version of the CLR.
15073 // 2) You should file an issue to track blocking earlier debuggers from targetting this
15074 // version of the CLR (i.e. update requiredVersion to the new CLR major
15075 // version). To enable a smooth internal transition, this often isn't done until absolutely
15076 // necessary (sometimes as late as Beta2).
15077 // 3) You can consider updating the CLR_ID guid used by the shim to recognize a CLR, but only
15078 // if it's important to completely hide newer CLRs from the shim. The expectation now
15079 // is that we won't need to do this (i.e. we'd like VS to give a nice error message about
15080 // needed a newer version of the debugger, rather than just acting as if a process has no CLR).
15081 // 4) Update this assert so that it no longer fires for your new CLR version or any of
15082 // the previous versions, but don't delete the assert...
15083 // the next CLR version after yours will probably need the same reminder
15085 _ASSERTE_MSG(clrMajorVersion <= 4,
15086 "Found major CLR version greater than 4 in mscordbi.dll from CLRv4 - contact CLRDST");
15088 // This knob lets us enable forward compatibility for internal scenarios, and also simulate new
15089 // versions of the runtime for testing the failure user-experience in a version of the debugger
15090 // before it is shipped.
15091 // We don't want to risk customers getting this, so for RTM builds this must be CHK-only.
15092 // To aid in internal transition, we may temporarily enable this in RET builds, but when
15093 // doing so must file a bug to track making it CHK only again before RTM.
15094 // For example, Dev10 Beta2 shipped with this knob, but it was made CHK-only at the start of RC.
15095 // In theory we might have a point release someday where we break debugger compat, but
15096 // it seems unlikely and since this knob is unsupported anyway we can always extend it
15097 // then (support reading a string value, etc.). So for now we just map the number
15098 // to the major CLR version number.
15099 DWORD requiredVersion = 0;
15101 requiredVersion = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_Debugging_RequiredVersion);
15104 // If unset (the only supported configuration), then we require a debugger designed for CLRv4
15105 // for desktop, where we do not allow forward compat.
15106 // For SL, we allow forward compat. Right now, that means SLv2+ debugger requests can be
15107 // honored for SLv4.
15108 if (requiredVersion <= 0)
15110 requiredVersion = 2;
15113 // Compare the version we were created for against the minimum required
15114 return (clrMajorVersion >= requiredVersion);
15117 bool CordbProcess::IsThreadSuspendedOrHijacked(ICorDebugThread * pICorDebugThread)
15119 // An RS lock can be held while this is called. Specifically,
15120 // CordbThread::EnumerateChains may be on the stack, and it uses
15121 // ATT_REQUIRE_STOPPED_MAY_FAIL, which holds the CordbProcess::m_StopGoLock lock for
15122 // its entire duration. As a result, this needs to be considered a reentrant API. See
15123 // comments above code:PrivateShimCallbackHolder for more info.
15124 PUBLIC_REENTRANT_API_ENTRY_FOR_SHIM(this);
15126 CordbThread * pCordbThread = static_cast<CordbThread *> (pICorDebugThread);
15127 return GetDAC()->IsThreadSuspendedOrHijacked(pCordbThread->m_vmThreadToken);