2 // Copyright (c) Microsoft. All rights reserved.
3 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
5 //*****************************************************************************
10 // Common include file for right-side of debugger.
11 //*****************************************************************************
32 #include "xcordebug.h"
33 #include "cordbpriv.h"
36 #include <cordbpriv.h>
37 #include <dbgipcevents.h>
39 #if !defined(FEATURE_DBGIPC_TRANSPORT_DI)
40 #include <ipcmanagerinterface.h>
41 #endif // !FEATURE_DBGIPC_TRANSPORT_DI
44 #include "primitives.h"
46 #include "dacdbiinterface.h"
52 #include "nativepipeline.h"
53 #include "stringcopyholder.h"
56 #include "eventchannel.h"
59 #define CRASH(x) _ASSERTE(!x)
60 #define ASSERT(x) _ASSERTE(x)
62 // We want to keep the 'worst' HRESULT - if one has failed (..._E_...) & the
63 // other hasn't, take the failing one. If they've both/neither failed, then
64 // it doesn't matter which we take.
65 // Note that this macro favors retaining the first argument
66 #define WORST_HR(hr1,hr2) (FAILED(hr1)?hr1:hr2)
69 // Forbid usage of OS APIs that we should be using the data-target for
70 #define ReadProcessMemory DONT_USE_READPROCESS_MEMORY
71 #define WriteProcessMemory DONT_USE_WRITEPROCESS_MEMORY
74 /* ------------------------------------------------------------------------- *
75 * Forward class declarations
76 * ------------------------------------------------------------------------- */
85 class CordbJITILFrame;
86 class CordbInternalFrame;
90 #ifdef FEATURE_INTEROP_DEBUGGING
91 class CordbUnmanagedThread;
92 struct CordbUnmanagedEvent;
98 class CordbBreakpoint;
101 class CordbEnCSnapshot;
102 class CordbWin32EventThread;
103 class CordbRCEventThread;
104 class CordbRegisterSet;
105 class CordbNativeFrame;
106 class CordbObjectValue;
107 class CordbEnCErrorInfo;
108 class CordbEnCErrorInfoEnum;
111 class CordbNativeCode;
113 class CordbReJitILCode;
120 class CorpubAppDomain;
121 class CorpubProcessEnum;
122 class CorpubAppDomainEnum;
128 class IDacDbiInterface;
130 #if defined(FEATURE_DBGIPC_TRANSPORT_DI)
131 class DbgTransportTarget;
132 class DbgTransportSession;
133 #endif // FEATURE_DBGIPC_TRANSPORT_DI
135 // @dbgtodo private shim hook - the RS has private hooks into the shim to help bridge the V2/V3 gap.
136 // This helps provide a working dogfooding story throughout our transition.
137 // These hooks must be removed before shipping.
141 extern HINSTANCE GetModuleInst();
145 class CordbSafeHashTable;
148 //---------------------------------------------------------------------------------------
150 // This is an encapsulation of the information necessary to connect to the debugger proxy on a remote machine.
151 // It includes the IP address and the port number. The IP address can be set via the env var
152 // COMPlus_DbgTransportProxyAddress, and the port number is fixed when Mac debugging is configured.
158 void Init(DWORD dwIPAddress, USHORT usPort)
160 m_dwIPAddress = dwIPAddress;
170 DWORD GetIPAddress() {return m_dwIPAddress;};
171 USHORT GetPort() {return m_usPort;};
178 #define forDbi (*(forDbiWorker *)NULL)
180 // for dbi we just default to new, but we need to have these defined for both dac and dbi
181 inline void * operator new(size_t lenBytes, const forDbiWorker &)
183 void * result = new BYTE[lenBytes];
191 inline void * operator new[](size_t lenBytes, const forDbiWorker &)
193 void * result = new BYTE[lenBytes];
201 // Helper to delete memory used with the IDacDbiInterface::IAllocator interface.
202 template<class T> inline
203 void DeleteDbiMemory(T *p)
210 //---------------------------------------------------------------------------------------
212 // Simple array of holders (either RSSmartPtrs or RSExtSmartPtrs).
213 // Holds a reference to each element.
216 // T is the base type and HOLDER_T is the type of the holder. All functions implemented on this base
217 // class must work for both RSSmartPtrs and RSExtSmartPtrs. For example, there is no concept of neutering
218 // for RSExtSmartPtrs.
221 template<typename T, typename HOLDER_T>
231 // Is the array emtpy?
234 return (m_pArray == NULL);
237 // Allocate an array of ptrs.
238 // Returns false if not enough memory; else true.
239 bool Alloc(unsigned int cElements)
241 // Caller should have already Neutered
244 // It's legal to allocate 0 items. We'll succeed the allocation, but still claim that IsEmpty() == true.
250 // RSSmartPtr ctor will ensure all elements are null initialized.
251 m_pArray = new (nothrow) HOLDER_T [cElements];
252 if (m_pArray == NULL)
257 m_cElements = cElements;
261 // Allocate an array of ptrs.
263 void AllocOrThrow(unsigned int cElements)
265 if (!Alloc(cElements))
271 // Release each element and empty the array.
274 // this Invoke dtors on each element which will release each element
281 // Array lookup. Caller gaurantees this is in range.
283 T* operator [] (unsigned int index) const
285 _ASSERTE(m_pArray != NULL);
286 CONSISTENCY_CHECK_MSGF((index <= m_cElements), ("Index out of range. Index=%u, Max=%u\n", index, m_cElements));
288 return m_pArray[index];
291 // Assign a given index to the given value. The array holder will increment the internal reference on the value.
292 void Assign(unsigned int index, T* pValue)
294 _ASSERTE(m_pArray != NULL);
295 CONSISTENCY_CHECK_MSGF((index <= m_cElements), ("Index out of range. Index=%u, Max=%u\n", index, m_cElements));
297 m_pArray[index].Assign(pValue);
300 // Get lenght of array in elements.
301 unsigned int Length() const
306 // Some things need to get the address of an element in the table.
307 // For example, CordbThreads have an array of CordbFrame objects, and then CordbChains describe a range
308 // or frames via pointers into the CordbThread's array.
309 // This is a dangerous operation because it lets us side-step reference counting and protection.
310 T ** UnsafeGetAddrOfIndex(unsigned int index)
312 return m_pArray[index].UnsafeGetAddr();
316 // Raw array of values.
319 // Number of elements in m_pArray. Note the following is always true: (m_cElements == 0) == (m_pArray == NULL);
320 unsigned int m_cElements;
324 //-----------------------------------------------------------------------------
326 // Simple array holder of RSSmartPtrs (internal pointers).
327 // Holds a reference to each element.
330 // This derived class adds the concept of neutering to the base pointer array.
331 // Allows automatic Clear()ing; do not use this unless it is safe to do so in
332 // all cases - e.g. you're holding a local.
335 template< typename T, typename HOLDER_T = RSSmartPtr<T> > // We need to use HOLDER_T to make gcc happy.
336 class RSPtrArray : public BaseRSPtrArray<T, HOLDER_T>
339 typedef BaseRSPtrArray<T, HOLDER_T> Super;
343 RSPtrArray() : m_autoClear(FALSE)
355 // Caller should have already Neutered
356 _ASSERTE(Super::IsEmpty());
360 void EnableAutoClear()
365 // Neuter all elements in the array.
366 void NeuterAndClear()
368 for(unsigned int i = 0; i < Super::m_cElements; i++)
370 if (Super::m_pArray[i] != NULL)
372 Super::m_pArray[i]->Neuter();
381 //-----------------------------------------------------------------------------
383 // Simple array holder of RSExtSmartPtrs (external pointers).
384 // Holds a reference to each element.
387 // This derived class clears the array in its destructor.
390 template< typename T, typename HOLDER_T = RSExtSmartPtr<T> > // We need to use HOLDER_T to make gcc happy.
391 class RSExtPtrArray : public BaseRSPtrArray<T, HOLDER_T>
394 typedef BaseRSPtrArray<T, HOLDER_T> Super;
405 //-----------------------------------------------------------------------------
407 // This lets us map cookies <--> RSPTR_*,
408 // Then we just put the cookie in the IPC block instead of the raw RSPTR.
409 // This will also adjust the internal-reference count on the T* object.
410 // This isolates the RS from bugs in the LS.
411 // We templatize by type for type safety.
412 // Caller must syncrhonize all access (preferably w/ the stop-go lock).
413 //-----------------------------------------------------------------------------
429 for(UINT i = 0; i < m_cEntries; i++)
433 m_pTable[i]->InternalRelease();
441 // Add a value into table. Value can't be NULL.
442 // Returns 0 on failure (such as oom),
443 // Returns a non-zero cookie on success.
446 _ASSERTE(pValue != NULL);
447 // skip 0 because it's an invalid handle.
448 for(UINT i = 1; ; i++)
450 // If we've run out of space, allocate new space
451 if( i >= m_cEntries )
455 return 0; // failed to grow
457 _ASSERTE( i < m_cEntries );
458 _ASSERTE( m_pTable[i] == NULL );
459 // Since we grew, the next slot should now be open.
462 if (m_pTable[i] == NULL)
464 m_pTable[i] = pValue;
465 pValue->InternalAddRef();
472 // Lookup the value based off the cookie, which was obtained via "Add".
473 // return NULL on error.
474 T* Lookup(UINT cookie)
476 _ASSERTE(cookie != 0);
477 if (cookie >= m_cEntries)
479 CONSISTENCY_CHECK_MSGF(false, ("Cookie out of range.Cookie=0x%x. Size=0x%x.\n", cookie, m_cEntries));
482 T* p = m_pTable[cookie];
485 CONSISTENCY_CHECK_MSGF(false, ("Cookie is for empty slot.Cookie=0x%x.\n", cookie));
486 return NULL; // empty!
491 T* LookupAndRemove(UINT cookie)
493 _ASSERTE(cookie != 0);
494 T* p = Lookup(cookie);
497 m_pTable[cookie] = NULL;
498 p->InternalRelease();
504 // Resize the m_pTable array.
507 if (m_pTable == NULL)
509 _ASSERTE(m_cEntries == 0);
511 m_pTable = new (nothrow) T*[cSize];
512 if (m_pTable == NULL)
517 ZeroMemory(m_pTable, sizeof(T*) * m_cEntries);
520 size_t cNewSize = (m_cEntries * 3 / 2) + 1;
521 _ASSERTE(cNewSize > m_cEntries);
522 T** p = new (nothrow) T*[cNewSize];
527 ZeroMemory(p, sizeof(T*) * cNewSize);
530 // Copy over old stuff
531 memcpy(p, m_pTable, sizeof(T*) * m_cEntries);
535 m_cEntries = cNewSize;
545 //-----------------------------------------------------------------------------
546 // Simple Holder for RS object intialization to cooperate with Neutering
548 // The ctor will do an addref.
549 // The dtor (invoked in exception) will neuter and release the object. This
550 // release will likely be the final release to cause a delete.
551 // If the object is created successfully, caller should do a SuppressRelease()
552 // to avoid it getting neutered.
555 // RSInitHolder<CordbFoo> pFoo(new CordbFoo(x,y,z));
556 // pFoo->InitMore(a,b,c);
557 // GiveOwnershipToSomebodyElse(pFoo); // now somebody else owns and will clean up
558 // pFoo.ClearAndMarkDontNeuter(); // we no longer need to
560 // So if an exception is thrown before ClearAndMarkDontNeuter(), the dtor is invoked
561 // and the object is properly destroyed (deleted and neutered).
563 // Another common pattern is when initializing an object to hand off to an external:
564 // RSInitHolder<CordbFoo> pFoo(new CordbFoo(x,y,z));
565 // pFoo->InitMore(a,b,c);
566 // pFoo.TransferOwnershipExternal(ppOutParameter);
567 // TransferOwnershipExternal will assign to ppOutParameter, inc external ref, and
568 // call ClearAndMarkDontNeuter()
569 //-----------------------------------------------------------------------------
574 // Default ctor. Must call Assign() later.
578 RSInitHolder(T * pObject)
583 void Assign(T * pObject)
585 _ASSERTE(m_pObject == NULL); // only assign once.
586 m_pObject.Assign(pObject);
590 FORCEINLINE operator T *() const
595 FORCEINLINE T * operator->()
600 // This will null out m_pObject such that the dtor will not neuter it.
601 // This will also release the ref we took in the ctor.
602 // This will clear the current pointer.
603 void ClearAndMarkDontNeuter()
609 // Transfer ownership to a pointer
612 // ppOutParam - pointer to get ownership. External Reference is incremented.
613 // this pointer should do an external release.
616 // This calls ClearAndMarkDontNeuter(). This holder is Empty after this.
617 template <class TOther>
618 void TransferOwnershipExternal(TOther ** ppOutParam)
620 *ppOutParam = static_cast<TOther*> (m_pObject);
621 m_pObject->ExternalAddRef();
623 ClearAndMarkDontNeuter();
628 // Transfer the ownership of the wrapped object to the given hash table.
631 // pHashTable - hash table to take ownership.
634 // the contianing object for convenience. Throws on error (particularly
635 // if it fails adding to the hash).
638 // This calls ClearAndMarkDontNeuter(). This holder is Empty after this.
639 T* TransferOwnershipToHash(CordbSafeHashTable<T> * pHashtable)
641 T* pObject = m_pObject;
642 pHashtable->AddBaseOrThrow(m_pObject);
643 ClearAndMarkDontNeuter();
648 // Used to pass into a function that will assign to us.
651 // Address of this holder. This is like the & operator.
652 // This is provided for consistency with other holders which
653 // override the &operator.
654 RSInitHolder<T> * GetAddr()
661 RSSmartPtr<T> m_pObject;
666 //-----------------------------------------------------------------------------
667 // Have the extra level of indirection is useful for catching Cordbg errors.
668 //-----------------------------------------------------------------------------
670 // On debug, we have an opportunity to catch failing hresults during reproes.
671 #define ErrWrapper(hr) ErrWrapperHelper(hr, __FILE__, __LINE__)
673 inline HRESULT ErrWrapperHelper(HRESULT hr, const char * szFile, int line)
677 DWORD dwErr = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgBreakOnErr);
680 CONSISTENCY_CHECK_MSGF(false, ("Dbg Error break, hr=0x%08x, '%s':%d", hr, szFile, line));
686 // On release, it's just an identity function
687 #define ErrWrapper(hr) (hr)
690 //-----------------------------------------------------------------------------
691 // Quick helpers for threading semantics
692 //-----------------------------------------------------------------------------
694 bool IsWin32EventThread(CordbProcess* p);
695 bool IsRCEventThread(Cordb* p);
697 /* ------------------------------------------------------------------------- *
699 * ------------------------------------------------------------------------- */
701 typedef void* REMOTE_PTR;
704 //-----------------------------------------------------------------------------
705 // Wrapper class for locks. This is like Crst on the LS
706 //-----------------------------------------------------------------------------
711 // Attrs, can be bitwise-or together.
714 cLockUninit = 0x00000000,
715 cLockReentrant = 0x00000001,
716 cLockFlat = 0x00000002,
718 // (unusual). Not considered a debug API lock, for purposes of deciding whether
719 // to count this lock in m_cTotalDbgApiLocks, which is asserted to be 0 on entry
720 // to public APIs. Example of such a lock: LL_SHIM_PROCESS_DISPOSE_LOCK
721 cLockNonDbgApi = 0x00000004,
724 // To prevent deadlocks, we order all locks.
725 // A thread must acquire higher-numbered locks before lower numbered locks.
726 // These are used as indices into an array, so number them accordingly!
729 // Size of the array..
732 // The Stop-Go lock is used to make Stop + Continue be atomic operations.
733 // These methods will toggle the Process-lock b/c they go between multiple threads.
734 // This lock can never be taken on the Win32 ET.
737 // The win32-event-thread behaves as if it held a lock at this level.
738 LL_WIN32_EVENT_THREAD = 4,
740 // This held for the duration of ShimProcess::Dispose(), and protects
741 // ShimProcess::m_fIsDisposed, so that other ShimProcess functions can
742 // safely execute serially with ShimProcess::Dispose(). This needs to be
743 // a high-level lock, since ShimProcess methods that take this lock also
744 // call into CorDb* objects which take many of the other locks. In contrast,
745 // LL_SHIM_LOCK must remain low-level, as there exists at least one place where
746 // LL_SHIM_LOCK is taken while the CorDbProcess lock is also held (see
747 // CordbThread::GetActiveFunctions which takes the CorDbProcess lock while
748 // calling GetProcess()->GetShim()->LookupOrCreateShimStackWalk(this), which
749 // takes LL_SHIM_LOCK).
750 LL_SHIM_PROCESS_DISPOSE_LOCK = 3,
752 // The process lock is the primary lock for a CordbProcess object. It synchronizes
753 // between RCET, W32ET, and user threads.
756 #if defined(FEATURE_DBGIPC_TRANSPORT_DI)
757 LL_DBG_TRANSPORT_MANAGER_LOCK = 1,
759 LL_DBG_TRANSPORT_TARGET_LOCK = 0,
761 LL_DD_MARSHAL_LOCK = 0,
762 #endif // FEATURE_DBGIPC_TRANSPORT_DI
764 // These are all leaf locks (they don't take any other lock once they're held).
765 LL_PROCESS_LIST_LOCK = 0,
767 // Win32 send lock is shared by all processes accessing a single w32et.
768 LL_WIN32_SEND_LOCK = 0,
770 // Small lock around sending IPC events to support workarounds in func-eval abort.
771 // See code:CordbEval::Abort for details.
772 LL_FUNC_EVAL_ABORT_HACK_LOCK = 0,
774 // Leaf-level lock used in the shim.
778 // Initialize a lock w/ debugging info. szTag must be a string literal.
779 void Init(const char * szTag, int eAttr, ERSLockLevel level);
786 // Accessors for holders.
787 static void HolderEnter(RSLock * pLock)
791 static void HolderLeave(RSLock * pLock)
797 CRITICAL_SECTION m_lock;
804 const char * Name() { return m_szTag; }
806 // Returns true if this thread has the lock.
809 // Returns true if this is safe to take on this thread (ie, this thread
810 // doesn't already hold bigger locks).
811 // bool IsSafeToTake();
813 ERSLockLevel GetLevel() { return m_level; }
815 // If we're inited, we must have either cLockReentrant or cLockFlat specified.
816 bool IsInit() { return m_eAttr != 0; }
817 bool IsReentrant() { return (m_eAttr & cLockReentrant) == cLockReentrant; }
818 bool IsDbgApiLock() { return ((m_eAttr & cLockNonDbgApi) == 0); }
821 ERSLockLevel m_level;
822 int m_eAttr; // Bitwise combination of ELockAttr values
825 const char * m_szTag;
830 typedef Holder<RSLock *, RSLock::HolderEnter, RSLock::HolderLeave> RSLockHolder;
831 typedef Holder<RSLock *, RSLock::HolderLeave, RSLock::HolderEnter> RSInverseLockHolder;
835 typedef RSLock::RSLockHolder RSLockHolder;
836 typedef RSLock::RSInverseLockHolder RSInverseLockHolder;
838 // In the RS, we should be using RSLocks instead of raw critical sections.
839 #define CRITICAL_SECTION USE_RSLOCK_INSTEAD_OF_CRITICAL_SECTION
842 /* ------------------------------------------------------------------------- *
843 * Helper macros. Use the ATT_* macros below instead of these.
844 * ------------------------------------------------------------------------- */
846 // This serves as glue for exceptions. Eventually, we shouldn't have unrecoverable
847 // error, and instead, errors should just propogate up.
848 #define SetUnrecoverableIfFailed(__p, __hr) \
851 CORDBSetUnrecoverableError(__p, __hr, 0); \
854 #define CORDBSetUnrecoverableError(__p, __hr, __code) \
855 ((__p)->UnrecoverableError((__hr), (__code), __FILE__, __LINE__))
857 #define _CORDBCheckProcessStateOK(__p) \
858 (!((__p)->m_unrecoverableError) && !((__p)->m_terminated) && !((__p)->m_detached))
860 #define _CORDBCheckProcessStateOKAndSync(__p, __c) \
861 (!((__p)->m_unrecoverableError) && !((__p)->m_terminated) && !((__p)->m_detached) && \
862 (__p)->GetSynchronized())
864 // Worker to get failure HR from given state. If not in a failure state, it yields __defaultHR.
865 // If a caller knows that we're in a failure state, it can pass in a failure value for __defaultHR.
866 #define CORDBHRFromProcessStateWorker(__p, __c, __defaultHR) \
867 ((__p)->m_unrecoverableError ? CORDBG_E_UNRECOVERABLE_ERROR : \
868 ((__p)->m_detached ? CORDBG_E_PROCESS_DETACHED : \
869 ((__p)->m_terminated ? CORDBG_E_PROCESS_TERMINATED : \
870 (!(__p)->GetSynchronized() ? CORDBG_E_PROCESS_NOT_SYNCHRONIZED \
873 #define CORDBHRFromProcessState(__p, __c) \
874 CORDBHRFromProcessStateWorker(__p, __c, S_OK) \
877 // Have a set of helper macros to check the process state and return a failure code.
878 // These only should be used at public interface boundaries, in which case we should
879 // not be holding the process lock. But we have enough places where we use them internally,
880 // so we can't really assert that we're not holding the lock.
882 // We're very restricted in what APIs we can call on the w32et. Have
883 // a convenient check for this.
884 // If we have no shim, then nop this check because everything becomes like the w32-event-thread.
885 #define CORDBFailOrThrowIfOnWin32EventThread(__p, errorAction) \
887 if (((__p)->GetShim() != NULL) && (__p)->IsWin32EventThread()) \
889 _ASSERTE(!"Don't call on this thread"); \
890 errorAction(ErrWrapper(CORDBG_E_CANT_CALL_ON_THIS_THREAD)); \
894 #define CORDBFailIfOnWin32EventThread(__p) CORDBFailOrThrowIfOnWin32EventThread(__p, return)
896 #define CORDBRequireProcessStateOK(__p) { \
897 if (!_CORDBCheckProcessStateOK(__p)) \
898 return ErrWrapper(CORDBHRFromProcessState(__p, NULL)); }
900 // If we need to be synced, then we shouldn't be on the win32 Event-Thread.
901 #define CORDBRequireProcessStateOKAndSync(__p,__c) { \
902 CORDBFailIfOnWin32EventThread(__p); \
903 if (!_CORDBCheckProcessStateOKAndSync(__p, __c)) \
904 return ErrWrapper(CORDBHRFromProcessState(__p, __c)); }
906 #define CORDBRequireProcessSynchronized(__p, __c) { \
907 CORDBFailIfOnWin32EventThread(__p); \
908 if (!(__p)->GetSynchronized()) return ErrWrapper(CORDBG_E_PROCESS_NOT_SYNCHRONIZED);}
913 //-----------------------------------------------------------------------------
914 // All public APIS fall into 2 categories regarding their API Threading Type (ATT)
915 // We use a standard set of macros to define & enforce each type.
917 // (1) ATT_REQUIRE_STOPPED
918 // We must be stopped (either synced or at a win32 event) to call this API.
919 // - We'll fail if we're not stopped.
920 // - If we're stopped, we'll sync. Thus after this API, we're always synced,
921 // and Cordbg must call Continue to resume the process.
922 // - We'll take the Stop-Go-lock. This prevents another thread from continuing underneath us.
923 // - We may send IPC events.
924 // Common for APIs like Stacktracing
926 // (2) ATT_ALLOW_LIVE
927 // We do not have to be stopped to call this API.
928 // - We can be live, thus we can not take the stop-go lock (unless it's from a SC-holder).
929 // - If we're going to send IPC events, we must use a Stop-Continue holder.
930 // - Our stop-status is the same after this API as it was before.
931 // Common usage: read-only APIs.
933 // (2b) ATT_ALLOW_LIVE_DO_STOPGO.
934 // - shortcut macro to do #2, but throw in a stop-continue holder. These really
935 // should be in camp #1, but that would require an interface change.
936 //-----------------------------------------------------------------------------
938 // Helper macros for the ATT stuff
940 // Do checks that need to be done before we take the SG lock. These include checks
941 // where if we fail them, taking the SG lock could deadlock (such as being on win32 thread).
942 #define DO_PRE_STOP_GO_CHECKS(errorAction) \
943 CORDBFailOrThrowIfOnWin32EventThread(__proc_for_ATT, errorAction) \
944 if ((__proc_for_ATT)->m_unrecoverableError) { errorAction(CORDBG_E_UNRECOVERABLE_ERROR); } \
946 // Do checks after we take the SG lock. These include checks that rely on state protected
948 #define DO_POST_STOP_GO_CHECKS(errorAction) \
949 _ASSERTE((this->GetProcess() == __proc_for_ATT) || this->IsNeutered()); \
950 if (this->IsNeutered()) { errorAction(CORDBG_E_OBJECT_NEUTERED); } \
953 // The exact details here are rocket-science.
954 // We cache the __proc value to a local variable (__proc_for_ATT) so that we don't re-evaluate __proc. (It also forces type-safety).
955 // This is essential in case __proc is something like "this->GetProcess()" and which can start returning NULL if 'this'
956 // gets neutered underneath us. Caching guarantees that we'll be able to make it to the StopGo-lock.
958 // We explicitily check some things before taking the Stop-Go lock:
959 // - CORDBG_E_UNRECOVERABLE_ERROR before the lock because if that's set,
960 // we may have leaked locks to the outside world, so taking the StopGo lock later could fail.
961 // - Are we on the W32et - can't take sg lock if on W32et
962 // Then we immediately take the stop-go lock to prevent another thread from continuing underneath us.
963 // Then, if we're stopped, we ensure that we're also synced.
966 // - fake win32-stopped. Eg, between SuspendUnmanagedThreads & ResumeUnmanagedThreads
967 // (one way to get here is getting debug events during the special-deferment region)
969 // If we're not stopped, then we fail. This macro must never return S_OK.
971 // If not-shimmed (using V3 pipeline), then skip all checks about stop-state.
972 #define ATT_REQUIRE_STOPPED_MAY_FAIL_OR_THROW(__proc, errorAction) \
973 CordbProcess * __proc_for_ATT = (__proc); \
974 DO_PRE_STOP_GO_CHECKS(errorAction); \
975 RSLockHolder __ch(__proc_for_ATT->GetStopGoLock()); \
976 DO_POST_STOP_GO_CHECKS(errorAction); \
977 if ((__proc_for_ATT)->GetShim() != NULL) { \
978 if (!__proc_for_ATT->m_initialized) { errorAction(CORDBG_E_NOTREADY); } \
979 if ((__proc_for_ATT)->IsStopped()) { \
980 HRESULT _hr2 = (__proc_for_ATT)->StartSyncFromWin32Stop(NULL); \
981 if (FAILED(_hr2)) errorAction(_hr2); \
983 if (!_CORDBCheckProcessStateOKAndSync(__proc_for_ATT, NULL)) \
984 errorAction(CORDBHRFromProcessStateWorker(__proc_for_ATT, NULL, E_FAIL)); \
987 #define ATT_REQUIRE_STOPPED_MAY_FAIL(__proc)ATT_REQUIRE_STOPPED_MAY_FAIL_OR_THROW(__proc, return)
989 // #1b - allows it to be non-inited. This should look just like ATT_REQUIRE_STOPPED_MAY_FAIL_OR_THROW
990 // except it doesn't do SSFW32Stop and doesn't have the m_initialized check.
991 #define ATT_REQUIRE_SYNCED_OR_NONINIT_MAY_FAIL(__proc) \
992 CordbProcess * __proc_for_ATT = (__proc); \
993 DO_PRE_STOP_GO_CHECKS(return); \
994 RSLockHolder __ch(__proc_for_ATT->GetStopGoLock()); \
995 DO_POST_STOP_GO_CHECKS(return); \
996 if ((__proc_for_ATT)->GetShim() != NULL) { \
997 if (!_CORDBCheckProcessStateOKAndSync(__proc_for_ATT, NULL)) \
998 return CORDBHRFromProcessStateWorker(__proc_for_ATT, NULL, E_FAIL); \
1003 // Gross variant on #1.
1004 // This is a very dangerous ATT contract; but we need to support it for backwards compat.
1005 // Some APIs, like ICDProcess:EnumerateThreads can be used before the process is actually
1006 // initialized (kind of for interop-debugging).
1007 // These can't check the m_initialized flag b/c that may not be set yet.
1008 // They also can't sync the runtime.
1009 // This should only be used for non-blocking leaf activity.
1010 #define ATT_EVERETT_HACK_REQUIRE_STOPPED_ALLOW_NONINIT(__proc) \
1011 CordbProcess * __proc_for_ATT = (__proc); \
1012 DO_PRE_STOP_GO_CHECKS(return); \
1013 RSLockHolder __ch(__proc_for_ATT->GetStopGoLock()); \
1014 DO_POST_STOP_GO_CHECKS(return); \
1015 if (((__proc_for_ATT)->GetShim() != NULL) && !(__proc_for_ATT)->IsStopped()) { return CORDBG_E_PROCESS_NOT_SYNCHRONIZED; } \
1018 // #2 - caller may think debuggee is live, but throw in a Stop-Continue holder.
1019 #define ATT_ALLOW_LIVE_DO_STOPGO(__proc) \
1020 CordbProcess * __proc_for_ATT = (__proc); \
1021 DO_PRE_STOP_GO_CHECKS(return); \
1022 CORDBRequireProcessStateOK(__proc_for_ATT); \
1023 RSLockHolder __ch(__proc_for_ATT->GetStopGoLock()); \
1024 DO_POST_STOP_GO_CHECKS(return); \
1025 StopContinueHolder __hStopGo; \
1026 if ((__proc_for_ATT)->GetShim() != NULL) \
1028 HRESULT _hr2 = __hStopGo.Init(__proc_for_ATT); \
1029 if (FAILED(_hr2)) return _hr2; \
1030 _ASSERTE((__proc_for_ATT)->GetSynchronized()); \
1036 //-----------------------------------------------------------------------------
1037 // StopContinueHolder. Ensure that we're synced during a certain region.
1038 // (Particularly when sending an IPCEvent)
1039 // Calls ICorDebugProcess::Stop & IMDArocess::Continue.
1043 // StopContinueHolder h;
1044 // IfFailRet(h.Init(process))
1046 // } // continue automatically called.
1047 //-----------------------------------------------------------------------------
1050 class StopContinueHolder
1053 StopContinueHolder() : m_p(NULL) { };
1055 HRESULT Init(CordbProcess * p);
1056 ~StopContinueHolder();
1063 /* ------------------------------------------------------------------------- *
1065 * ------------------------------------------------------------------------- */
1067 #define COM_METHOD HRESULT STDMETHODCALLTYPE
1070 enumCordbUnknown, // 0
1071 enumCordb, // 1 1 [1]x1
1072 enumCordbProcess, // 2 1 [1]x1
1073 enumCordbAppDomain, // 3 1 [1]x1
1074 enumCordbAssembly, // 4
1075 enumCordbModule, // 5 15 [27-38,55-57]x1
1076 enumCordbClass, // 6
1077 enumCordbFunction, // 7
1078 enumCordbThread, // 8 2 [4,7]x1
1080 enumCordbChain, // 10
1081 enumCordbChainEnum, // 11
1082 enumCordbContext, // 12
1083 enumCordbFrame, // 13
1084 enumCordbFrameEnum, // 14
1085 enumCordbValueEnum, // 15
1086 enumCordbRegisterSet, // 16
1087 enumCordbJITILFrame, // 17
1088 enumCordbBreakpoint, // 18
1089 enumCordbStepper, // 19
1090 enumCordbValue, // 20
1091 enumCordbEnCSnapshot, // 21
1092 enumCordbEval, // 22
1093 enumCordbUnmanagedThread,// 23
1094 enumCorpubPublish, // 24
1095 enumCorpubProcess, // 25
1096 enumCorpubAppDomain, // 26
1097 enumCorpubProcessEnum, // 27
1098 enumCorpubAppDomainEnum,// 28
1099 enumCordbEnumFilter, // 29
1100 enumCordbEnCErrorInfo, // 30
1101 enumCordbEnCErrorInfoEnum,//31
1102 enumCordbUnmanagedEvent,// 32
1103 enumCordbWin32EventThread,//33
1104 enumCordbRCEventThread, // 34
1105 enumCordbNativeFrame, // 35
1106 enumCordbObjectValue, // 36
1107 enumCordbType, // 37
1108 enumCordbNativeCode, // 38
1109 enumCordbILCode, // 39
1110 enumCordbEval2, // 40
1112 enumCordbHashTableEnum, // 42
1113 enumCordbCodeEnum, // 43
1114 enumCordbStackWalk, // 44
1115 enumCordbEnumerator, // 45
1116 enumCordbHeap, // 48
1117 enumCordbHeapSegments, // 47
1124 //-----------------------------------------------------------------------------
1125 // Support for Native Breakpoints
1126 //-----------------------------------------------------------------------------
1129 void * pAddress; // pointer into the LS address space.
1130 PRD_TYPE opcode; // opcode to restore with.
1132 inline bool operator==(NativePatch p2)
1134 return memcmp(this, &p2, sizeof(p2)) == 0;
1138 //-----------------------------------------------------------------------------
1139 // Cross-platform patch operations
1140 //-----------------------------------------------------------------------------
1142 // Remove the int3 from the remote address
1143 HRESULT RemoveRemotePatch(CordbProcess * pProcess, const void * pRemoteAddress, PRD_TYPE opcode);
1145 // This flavor is assuming our caller already knows the opcode.
1146 HRESULT ApplyRemotePatch(CordbProcess * pProcess, const void * pRemoteAddress);
1148 // Apply the patch and get the opcode that we're replacing.
1149 HRESULT ApplyRemotePatch(CordbProcess * pProcess, const void * pRemoteAddress, PRD_TYPE * pOpcode);
1152 class CordbHashTable;
1154 #define CORDB_COMMON_BASE_SIGNATURE 0x0d00d96a
1155 #define CORDB_COMMON_BASE_SIGNATURE_DEAD 0x0dead0b1
1157 // Common base for both CorPublish + CorDebug objects.
1158 class CordbCommonBase : public IUnknown
1161 // GENERIC: made this private as I'm changing the use of m_id for CordbClass, and
1162 // I want to make sure I catch all the places where m_id is used directly and cast
1163 // to/from tokens and/or (void*).
1167 static LONG m_saDwInstance[enumMaxDerived]; // instance x this
1168 static LONG m_saDwAlive[enumMaxDerived];
1169 static PVOID m_sdThis[enumMaxDerived][enumMaxThis];
1171 enumCordbDerived m_type;
1177 DWORD m_signature : 30;
1179 // Sticky bit set when we neuter an object. All methods (besides AddRef,Release,QI)
1180 // should check this bit and fail via the FAIL_IF_NEUTERED macro.
1181 DWORD m_fIsNeutered : 1;
1183 // Mark that this object can be "neutered at will". NeuterList::SweepAllNeuterAtWillObjects
1184 // looks at this bit.
1185 // For some objects, we don't explicitly mark when the lifetime is up. The only way
1186 // we know is when external count goes to 0. This avoids forcing us to do cleanup
1187 // in the dtor (which may come at a bad time). Sticky bit set in BaseRelease().
1188 DWORD m_fNeuterAtWill : 1;
1191 static LONG s_CordbObjectUID; // Unique ID for each object.
1192 static LONG s_TotalObjectCount; // total number of outstanding objects.
1195 void ValidateObject()
1197 if( !IsValidObject() )
1199 STRESS_LOG1(LF_ASSERT, LL_ALWAYS, "CordbCommonBase::IsValidObject() failed: %x\n", this);
1200 _ASSERTE(!"CordbCommonBase::IsValidObject() failed");
1201 FreeBuildDebugBreak();
1205 bool IsValidObject()
1207 return (m_signature == CORDB_COMMON_BASE_SIGNATURE);
1210 CordbCommonBase(UINT_PTR id, enumCordbDerived type)
1215 CordbCommonBase(UINT_PTR id)
1217 init(id, enumCordbUnknown);
1220 void init(UINT_PTR id, enumCordbDerived type)
1222 // To help us track object leaks, we want to log when we create & destory CordbBase objects.
1224 InterlockedIncrement(&s_TotalObjectCount);
1225 InterlockedIncrement(&s_CordbObjectUID);
1227 LOG((LF_CORDB, LL_EVERYTHING, "Memory: CordbBase object allocated: this=%p, count=%d, id=%p, Type=%d\n", this, s_CordbObjectUID, id, type));
1230 m_signature = CORDB_COMMON_BASE_SIGNATURE;
1231 m_fNeuterAtWill = 0;
1239 //m_dwInstance = CordbBase::m_saDwInstance[m_type];
1240 //InterlockedIncrement(&CordbBase::m_saDwInstance[m_type]);
1241 //InterlockedIncrement(&CordbBase::m_saDwAlive[m_type]);
1242 //if (m_dwInstance < enumMaxThis)
1244 // m_sdThis[m_type][m_dwInstance] = this;
1249 virtual ~CordbCommonBase()
1251 // If we're deleting, we really should have released any outstanding reference.
1252 // If we call Release() on a deleted object, we'll av (especially b/c Release
1253 // may call delete again).
1254 CONSISTENCY_CHECK_MSGF(m_RefCount == 0, ("Deleting w/ non-zero ref count. 0x%08x", m_RefCount));
1257 //InterlockedDecrement(&CordbBase::m_saDwAlive[m_type]);
1258 //if (m_dwInstance < enumMaxThis)
1260 // m_sdThis[m_type][m_dwInstance] = NULL;
1263 // To help us track object leaks, we want to log when we create & destory CordbBase objects.
1264 LOG((LF_CORDB, LL_EVERYTHING, "Memory: CordbBase object deleted: this=%p, id=%p, Refcount=0x%x\n", this, m_id, m_RefCount));
1267 InterlockedDecrement(&s_TotalObjectCount);
1268 _ASSERTE(s_TotalObjectCount >= 0);
1271 // Don't shutdown logic until everybody is done with it.
1272 // If we leak objects, this may mean that we never shutdown logging at all!
1273 #if defined(_DEBUG) && defined(LOGGING)
1274 if (s_TotalObjectCount == 0)
1282 Member function behavior of a neutered COM object:
1284 1. AddRef(), Release(), QueryInterface() work as normal.
1285 a. This gives folks who are responsible for pairing a Release() with
1286 an AddRef() a chance to dereference their pointer and call Release()
1287 when they are informed, explicitly or implicitly, that the object is neutered.
1289 2. Any other member function will return an error code unless documented.
1290 a. If a member function returns information when the COM object is
1291 neutered then the semantics of that function need to be documented.
1292 (ie. If an AppDomain is unloaded and you have a reference to the COM
1293 object representing the AppDomain, how _should_ it behave? That behavior
1294 should be documented)
1297 Postcondions of Neuter():
1299 1. All circular references (aka back-pointers) are "broken". They are broken
1300 by calling Release() on all "Weak References" to the object. If you're a purist,
1301 these pointers should also be NULLed out.
1302 a. Weak References/Strong References:
1303 i. If any objects are not "reachable" from the root (ie. stack or from global pointers)
1304 they should be reclaimed. If they are not, they are leaked and there is an issue.
1305 ii. There must be a partial order on the objects such that if A < B then:
1306 1. A has a reference to B. This reference is a "strong reference"
1307 2. A, and thus B, is reachable from the root
1308 iii. If a reference belongs in the partial order then it is a "strong reference" else
1309 it is a weak reference.
1310 *** 2. Sufficient conditions to ensure no COM objects are leaked: ***
1311 a. When Neuter() is invoked:
1312 i. Calles Release on all its weak references.
1313 ii. Then, for each strong reference:
1316 iii. If it's derived from a CordbXXX class, call Neuter() on the base class.
1317 1. Sense Neuter() is virtual, use the scope specifier Cordb[BaseClass]::Neuter().
1318 3. All members return error codes, except:
1319 a. Members of IUknown, AddRef(), Release(), QueryInterfac()
1320 b. Those documented to have functionality when the object is neutered.
1321 i. Neuter() still works w/o error. If it is invoke a second time it will have already
1322 released all its strong and weak references so it could just return.
1325 Alternate design ideas:
1327 DESIGN: Note that it's possible for object B to have two parents in the partial order
1328 and it must be documented which one is responsible for calling Neuter() on B.
1329 1. For example, CordbCode could reasonably be a sibling of CordbFunction and CordbNativeFrame.
1330 Which one should call Release()? For now we have CordbFunction call Release() on CordbCode.
1332 DESIGN: It is not a necessary condition in that Neuter() invoke Release() on all
1333 it's strong references. Instead, it would be sufficient to ensure all object are released, that
1334 each object call Release() on all its strong pointers in its destructor.
1335 1. This might be done if its necessary for some member to return "tombstone"
1336 information after the object has been netuered() which involves the siblings (wrt poset)
1337 of the object. However, no sibling could access a parent (wrt poset) because
1338 Neuter called Release() on all its weak pointers.
1340 DESIGN: Rename Neuter() to some name that more accurately reflect the semantics.
1341 1. The three operations are:
1342 a. ReleaseWeakPointers()
1343 b. NeuterStrongPointers()
1344 c. ReleaseStrongPointers()
1345 1. Assert that it's done after NeuterStrongPointers()
1346 2. That would introduce a bunch of functions... but it would be clear.
1348 DESIGN: CordbBase could provide a function to register strong and weak references. That way CordbBase
1349 could implement a general version of ReleaseWeak/ReleaseStrong/NeuterStrongPointers(). This
1350 would provide a very error resistant framework for extending the object model plus it would
1351 be very explicit about what is going on.
1352 One thing that might trip this is idea up is that if an object has two parents,
1353 like the CordbCode might, then either both objects call Neuter or one is reference
1359 The graph formed by the strong references must remain acyclic.
1360 It's up to the developer (YOU!) to ensure that each Neuter
1361 function maintains that invariant.
1363 Here is the current Partial Order on CordbXXX objects. (All these classes
1364 eventually chain to CordbBase.Neuter() for completeness.)
1374 CordbCode (Can we assert a thread will not reference
1375 the same CordbCode as a CordbFunction?)
1378 CordbNativeFrame -> CordbFrame (Chain to baseClass)
1382 <TODO>TODO: Some Neuter functions have not yet been implemented due to time restrictions.</TODO>
1384 <TODO>TODO: Some weak references never have AddRef() called on them. If that's cool then
1385 it should be stated in the documentation. Else it should be changed.</TODO>
1388 virtual void Neuter();
1390 // Unsafe neuter for an object that's already dead.
1391 void UnsafeNeuterDeadObject();
1395 // For debugging (asserts, logging, etc) provide a pretty name (this is 1:1 w/ the VTable)
1396 // We provide a default impl in the base object in case this gets called from a dtor (virtuals
1397 // called from dtors use the base version, not the derived). A pure call would AV in that case.
1398 virtual const char * DbgGetName() { return "CordbBase"; };
1401 bool IsNeutered() const {LIMITED_METHOD_CONTRACT; return m_fIsNeutered == 1; }
1402 bool IsNeuterAtWill() const { LIMITED_METHOD_CONTRACT; return m_fNeuterAtWill == 1; }
1403 void MarkNeuterAtWill() { LIMITED_METHOD_CONTRACT; m_fNeuterAtWill = 1; }
1405 //-----------------------------------------------------------
1407 //----------------------------------------------------------
1410 // We maintain both an internal + external refcount. This allows us to catch
1411 // if an external caller has too many releases.
1412 // low bits are internal count, high bits are external count
1413 // so Total count = (m_RefCount & CordbBase_InternalRefCountMask) + (m_RefCount >> CordbBase_ExternalRefCountShift);
1414 typedef LONGLONG MixedRefCountSigned;
1415 typedef ULONGLONG MixedRefCountUnsigned;
1416 typedef LONG ExternalRefCount;
1417 MixedRefCountUnsigned m_RefCount;
1420 // Adjust the internal ref count.
1421 // These aren't available to the external world, so only internal code can manipulate the internal count.
1422 void InternalAddRef();
1423 void InternalRelease();
1425 // Derived versions of AddRef / Release will call these.
1426 // External AddRef & Release
1427 // These do not have any additional Asserts to enforce that we're not manipulating the external count
1429 ULONG STDMETHODCALLTYPE BaseAddRef();
1430 ULONG STDMETHODCALLTYPE BaseRelease();
1432 // External ref count versions, with extra debug count to enforce that this is done externally.
1433 // When derive classes use these versions, it Asserts that we're not adjusting external counts from inside.
1434 // Thus we can be confident that we're *never* leaking external refs to these objects.
1435 // @todo - eventually everything should use these.
1436 ULONG STDMETHODCALLTYPE BaseAddRefEnforceExternal();
1437 ULONG STDMETHODCALLTYPE BaseReleaseEnforceExternal();
1439 // Do an AddRef against the External count. This is a semantics issue.
1440 // We use this when an internal component Addrefs out-parameters (which Cordbg will call Release on).
1441 // This just does a regular external AddRef().
1442 void ExternalAddRef();
1446 static void InitializeCommon();
1449 static void AddDebugPrivilege();
1452 #define CordbBase_ExternalRefCountShift 32
1453 #define CordbBase_InternalRefCountMask 0xFFFFFFFF
1454 #define CordbBase_InternalRefCountMax 0x7FFFFFFF
1457 // Does the given Cordb object type have affinity to a CordbProcess object?
1458 // This is only used for certain asserts.
1459 inline bool DoesCordbObjectTypeHaveProcessPtr(enumCordbDerived type)
1462 (type != enumCordbCodeEnum) &&
1463 (type != enumCordb) &&
1464 (type != enumCordbHashTableEnum);
1468 // Base class specifically for CorDebug objects
1469 class CordbBase : public CordbCommonBase
1472 CordbBase(CordbProcess * pProcess, UINT_PTR id, enumCordbDerived type) : CordbCommonBase(id, type)
1474 // CordbProcess can't pass 'this' to base class, per error C4355. So we pass null and set later.
1475 _ASSERTE((pProcess != NULL) ||
1476 ((type) == enumCordbProcess) ||
1477 !DoesCordbObjectTypeHaveProcessPtr(type));
1479 m_pProcess.Assign(pProcess);
1482 CordbBase(CordbProcess * pProcess, UINT_PTR id) : CordbCommonBase(id)
1484 _ASSERTE(pProcess != NULL);
1485 m_pProcess.Assign(pProcess);
1488 virtual ~CordbBase()
1490 // Derived classes should not have cleared out our pointer.
1491 // CordbProcess's Neuter explicitly nulls out its pointer to avoid circular reference.
1492 _ASSERTE(m_pProcess!= NULL ||
1493 (CordbCommonBase::m_type == enumCordbProcess) ||
1494 !DoesCordbObjectTypeHaveProcessPtr(CordbCommonBase::m_type));
1496 // Ideally, all CorDebug objects to be neutered by the time their dtor is called.
1497 // @todo - we're still working out neutering semantics for a few remaining objects, so we exclude
1498 // those from the assert.
1499 _ASSERTE(IsNeutered() ||
1500 (m_type == enumCordbBreakpoint) ||
1501 (m_type == enumCordbStepper));
1504 // Neuter just the right-side state.
1505 virtual void Neuter();
1507 // Neuter both left-side state and right-side state.
1508 virtual void NeuterLeftSideResources();
1510 // Get the CordbProcess object that this CordbBase object is associated with (or NULL if there's none).
1511 CordbProcess * GetProcess() const
1516 // All objects need a strong pointer back to the process so that they can get access to key locks
1517 // held by the process (StopGo lock) so that they can synchronize their operations against neutering.
1518 // This pointer is cleared in our dtor, and not when we're neutered. Since we can't control when the
1519 // dtor is called (it's controlled by external references), we classify this as an external reference too.
1521 // This is the only "strong" reference backpointer that objects need have. All other backpointers can be weak references
1522 // because when a parent object is neutered, it will null out all weak reference pointers in all of its children.
1523 // That will also break any potential cycles.
1524 RSUnsafeExternalSmartPtr<CordbProcess> m_pProcess;
1532 //-----------------------------------------------------------------------------
1533 // Macro to check if a CordbXXX object is neutered, and return a standard
1534 // error code if it is.
1535 // We pass the 'this' pointer of the object in because it gives us some extra
1536 // flexibility and lets us log debug info.
1537 // It is an API breach to access a neutered object.
1538 //-----------------------------------------------------------------------------
1539 #define FAIL_IF_NEUTERED(pThis) \
1540 int _____Neuter_Status_Already_Marked; \
1541 _____Neuter_Status_Already_Marked = 0; \
1543 if (pThis->IsNeutered()) { \
1544 LOG((LF_CORDB, LL_ALWAYS, "Accessing a neutered object at %p\n", pThis)); \
1545 return ErrWrapper(CORDBG_E_OBJECT_NEUTERED); \
1549 //-----------------------------------------------------------------------------
1550 // Macro to check if a CordbXXX object is neutered, and return a standard
1551 // error code if it is.
1552 // We pass the 'this' pointer of the object in because it gives us some extra
1553 // flexibility and lets us log debug info.
1554 // It is an API breach to access a neutered object.
1555 //-----------------------------------------------------------------------------
1556 #define THROW_IF_NEUTERED(pThis) \
1557 int _____Neuter_Status_Already_Marked; \
1558 _____Neuter_Status_Already_Marked = 0; \
1560 if (pThis->IsNeutered()) { \
1561 LOG((LF_CORDB, LL_ALWAYS, "Accessing a neutered object at %p\n", pThis)); \
1562 ThrowHR(CORDBG_E_OBJECT_NEUTERED); \
1566 // We have an OK_IF_NEUTERED macro to say that this method can be safely
1567 // called if we're neutered. Mostly for semantic benefits.
1568 // Also, if a method is marked OK, then somebody won't go and add a 'fail'
1569 // This is an extremely dangerous quality because:
1570 // 1) it means that we have no synchronization (can't take the Stop-Go lock)
1571 // 2) none of our backpointers are usable (they may be nulled out at anytime by another thread).
1572 // - this also means we absolutely can't send IPC events (since that requires a CordbProcess)
1573 // 3) The only safe data are blittalbe embedded fields (eg, a pid or stack range)
1575 // Any usage of this macro should clearly specify why this is safe.
1576 #define OK_IF_NEUTERED(pThis) \
1577 int _____Neuter_Status_Already_Marked; \
1578 _____Neuter_Status_Already_Marked = 0;
1581 //-------------------------------------------------------------------------------
1582 // Simple COM enumerator pattern on a fixed list of items
1583 //--------------------------------------------------------------------------------
1584 template< typename ElemType,
1585 typename ElemPublicType,
1586 typename EnumInterfaceType,
1587 ElemPublicType (*GetPublicType)(ElemType)>
1588 class CordbEnumerator : public CordbBase, EnumInterfaceType
1591 // the list of items being enumerated over
1593 // the number of items in the list
1595 // the index of the next item to be returned in the enumeration
1599 // makes a copy of the elements in the "items" array
1600 CordbEnumerator(CordbProcess* pProcess, ElemType *items, DWORD elemCount);
1601 // assumes ownership of the elements in the "*items" array.
1602 // this avoids an extra allocation + copy
1603 CordbEnumerator(CordbProcess* pProcess, ElemType **items, DWORD elemCount);
1606 // IUnknown interface
1607 virtual COM_METHOD QueryInterface(REFIID riid, VOID** ppInterface);
1608 virtual ULONG __stdcall AddRef();
1609 virtual ULONG __stdcall Release();
1611 // ICorDebugEnum interface
1612 virtual COM_METHOD Clone(ICorDebugEnum **ppEnum);
1613 virtual COM_METHOD GetCount(ULONG *pcelt);
1614 virtual COM_METHOD Reset();
1615 virtual COM_METHOD Skip(ULONG celt);
1617 // ICorDebugXXXEnum interface
1618 virtual COM_METHOD Next(ULONG celt, ElemPublicType items[], ULONG *pceltFetched);
1620 // CordbBase overrides
1621 virtual VOID Neuter();
1624 // Converts T to U* by using QueryInterface
1625 template<typename T, typename U>
1626 U* QueryInterfaceConvert(T obj);
1628 // No conversion, just returns the argument
1629 template<typename T>
1630 T IdentityConvert(T obj);
1632 // CorDebugGuidToTypeMapping-adapter used by CordbGuidToTypeEnumerator
1633 // in the CordbEnumerator pattern
1634 struct RsGuidToTypeMapping
1637 RSSmartPtr<CordbType> spType;
1641 CorDebugGuidToTypeMapping GuidToTypeMappingConvert(RsGuidToTypeMapping m)
1643 CorDebugGuidToTypeMapping result;
1645 result.pType = (ICorDebugType*)(m.spType.GetValue());
1646 result.pType->AddRef();
1651 // Some useful enumerators
1653 typedef CordbEnumerator<RSSmartPtr<CordbThread>,
1655 ICorDebugThreadEnum,
1656 QueryInterfaceConvert<RSSmartPtr<CordbThread>, ICorDebugThread> > CordbThreadEnumerator;
1658 typedef CordbEnumerator<CorDebugBlockingObject,
1659 CorDebugBlockingObject,
1660 ICorDebugBlockingObjectEnum,
1661 IdentityConvert<CorDebugBlockingObject> > CordbBlockingObjectEnumerator;
1663 // Template classes must be fully defined rather than just declared in the header
1664 #include "rsenumerator.hpp"
1667 typedef CordbEnumerator<COR_SEGMENT,
1669 ICorDebugHeapSegmentEnum,
1670 IdentityConvert<COR_SEGMENT> > CordbHeapSegmentEnumerator;
1672 typedef CordbEnumerator<CorDebugExceptionObjectStackFrame,
1673 CorDebugExceptionObjectStackFrame,
1674 ICorDebugExceptionObjectCallStackEnum,
1675 IdentityConvert<CorDebugExceptionObjectStackFrame> > CordbExceptionObjectCallStackEnumerator;
1677 typedef CordbEnumerator<RsGuidToTypeMapping,
1678 CorDebugGuidToTypeMapping,
1679 ICorDebugGuidToTypeEnum,
1680 GuidToTypeMappingConvert > CordbGuidToTypeEnumerator;
1682 // ----------------------------------------------------------------------------
1683 // Hash table for CordbBase objects.
1684 // - Uses Internal AddRef/Release (not external)
1685 // - Templatize for type-safety w/ Cordb objects
1686 // - Many hashtables are implicitly protected by a lock. For debug-only, we
1687 // explicitly associate w/ an optional RSLock and assert that lock is held on access.
1688 // ----------------------------------------------------------------------------
1690 struct CordbHashEntry
1692 FREEHASHENTRY entry;
1696 class CordbHashTable : private CHashTableAndData<CNewDataNoThrow>
1702 BOOL Cmp(SIZE_T k1, const HASHENTRY * pc2)
1704 LIMITED_METHOD_CONTRACT;
1706 return ((ULONG_PTR)k1) != (reinterpret_cast<const CordbHashEntry *>(pc2))->pBase->m_id;
1709 ULONG HASH(ULONG_PTR id)
1714 SIZE_T KEY(UINT_PTR id)
1720 bool IsInitialized();
1722 #ifndef DACCESS_COMPILE
1723 CordbHashTable(ULONG size)
1724 : CHashTableAndData<CNewDataNoThrow>(size), m_initialized(false), m_count(0)
1728 m_dbgChangeCount = 0;
1731 virtual ~CordbHashTable();
1734 // CordbHashTables may be protected by a lock. For debug-builds, we can associate
1735 // the hash w/ that lock and then assert if it's not held.
1736 void DebugSetRSLock(RSLock * pLock)
1740 int GetChangeCount() { return m_dbgChangeCount; }
1742 void AssertIsProtected();
1744 // Increment the Change count. This can be used to check if the hashtable changes while being enumerated.
1745 void DbgIncChangeCount() { m_dbgChangeCount++; }
1747 int m_dbgChangeCount;
1748 RSLock * m_pDbgLock;
1750 // RSLock association is a no-op on free builds.
1751 void AssertIsProtected() { };
1752 void DbgIncChangeCount() { };
1762 return ((ULONG32)m_count);
1765 // These operators are unsafe b/c they have no typesafety.
1766 // Use a derived CordbSafeHashTable<T> instead.
1767 HRESULT UnsafeAddBase(CordbBase *pBase);
1768 HRESULT UnsafeSwapBase(CordbBase* pBaseOld, CordbBase* pBaseNew);
1769 CordbBase *UnsafeGetBase(ULONG_PTR id, BOOL fFab = TRUE);
1770 CordbBase *UnsafeRemoveBase(ULONG_PTR id);
1772 CordbBase *UnsafeFindFirst(HASHFIND *find);
1773 CordbBase *UnsafeFindNext(HASHFIND *find);
1775 // Unlocked versions don't assert that the lock us held.
1776 CordbBase *UnsafeUnlockedFindFirst(HASHFIND *find);
1777 CordbBase *UnsafeUnlockedFindNext(HASHFIND *find);
1782 // Typesafe wrapper around a normal hash table
1783 // T is expected to be a derived clas of CordbBase
1784 // Note that this still isn't fully typesafe. Ideally we'd take a strongly-typed key
1785 // instead of UINT_PTR (the type could have a fixed relationship to T, or could be
1786 // an additional template argument like standard template hash tables like std::hash_map<K,V>)
1788 class CordbSafeHashTable : public CordbHashTable
1791 #ifndef DACCESS_COMPILE
1792 CordbSafeHashTable<T>(ULONG size) : CordbHashTable(size)
1796 // Typesafe wrappers
1797 HRESULT AddBase(T * pBase) { return UnsafeAddBase(pBase); }
1799 // Either add (eg, future cals to GetBase will succeed) or throw.
1800 void AddBaseOrThrow(T * pBase)
1802 HRESULT hr = AddBase(pBase);
1805 HRESULT SwapBase(T* pBaseOld, T* pBaseNew) { return UnsafeSwapBase(pBaseOld, pBaseNew); }
1806 // Move the function definition of GetBase to rspriv.inl to work around gcc 2.9.5 warnings
1807 T* GetBase(ULONG_PTR id, BOOL fFab = TRUE);
1808 T* GetBaseOrThrow(ULONG_PTR id, BOOL fFab = TRUE);
1810 T* RemoveBase(ULONG_PTR id) { return static_cast<T*>(UnsafeRemoveBase(id)); }
1812 T* FindFirst(HASHFIND *find) { return static_cast<T*>(UnsafeFindFirst(find)); }
1813 T* FindNext(HASHFIND *find) { return static_cast<T*>(UnsafeFindNext(find)); }
1815 // Neuter all items and clear
1816 void NeuterAndClear(RSLock * pLock);
1818 void CopyToArray(RSPtrArray<T> * pArray);
1819 void TransferToArray(RSPtrArray<T> * pArray);
1823 class CordbHashTableEnum : public CordbBase,
1824 public ICorDebugProcessEnum,
1825 public ICorDebugBreakpointEnum,
1826 public ICorDebugStepperEnum,
1827 public ICorDebugThreadEnum,
1828 public ICorDebugModuleEnum,
1829 public ICorDebugAppDomainEnum,
1830 public ICorDebugAssemblyEnum
1832 // Private ctors. Use build function to access.
1834 CordbBase * pOwnerObj,
1835 NeuterList * pOwnerList,
1836 CordbHashTable *table,
1840 static void BuildOrThrow(
1841 CordbBase * pOwnerObj,
1842 NeuterList * pOwnerList,
1843 CordbHashTable *table,
1845 RSInitHolder<CordbHashTableEnum> * pHolder);
1847 CordbHashTableEnum(CordbHashTableEnum *cloneSrc);
1849 ~CordbHashTableEnum();
1850 virtual void Neuter();
1854 // For debugging (asserts, logging, etc) provide a pretty name (this is 1:1 w/ the VTable)
1855 virtual const char * DbgGetName() { return "CordbHashTableEnum"; };
1859 HRESULT Next(ULONG celt, CordbBase *bases[], ULONG *pceltFetched);
1861 //-----------------------------------------------------------
1863 //-----------------------------------------------------------
1865 ULONG STDMETHODCALLTYPE AddRef()
1867 return (BaseAddRef());
1869 ULONG STDMETHODCALLTYPE Release()
1871 return (BaseRelease());
1873 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
1875 //-----------------------------------------------------------
1877 //-----------------------------------------------------------
1879 COM_METHOD Skip(ULONG celt);
1881 COM_METHOD Clone(ICorDebugEnum **ppEnum);
1882 COM_METHOD GetCount(ULONG *pcelt);
1884 //-----------------------------------------------------------
1885 // ICorDebugProcessEnum
1886 //-----------------------------------------------------------
1888 COM_METHOD Next(ULONG celt, ICorDebugProcess *processes[],
1889 ULONG *pceltFetched)
1891 VALIDATE_POINTER_TO_OBJECT_ARRAY(processes, ICorDebugProcess *,
1893 VALIDATE_POINTER_TO_OBJECT(pceltFetched, ULONG *);
1895 return (Next(celt, (CordbBase **)processes, pceltFetched));
1898 //-----------------------------------------------------------
1899 // ICorDebugBreakpointEnum
1900 //-----------------------------------------------------------
1902 COM_METHOD Next(ULONG celt, ICorDebugBreakpoint *breakpoints[],
1903 ULONG *pceltFetched)
1905 VALIDATE_POINTER_TO_OBJECT_ARRAY(breakpoints, ICorDebugBreakpoint *,
1907 VALIDATE_POINTER_TO_OBJECT(pceltFetched, ULONG *);
1909 return (Next(celt, (CordbBase **)breakpoints, pceltFetched));
1912 //-----------------------------------------------------------
1913 // ICorDebugStepperEnum
1914 //-----------------------------------------------------------
1916 COM_METHOD Next(ULONG celt, ICorDebugStepper *steppers[],
1917 ULONG *pceltFetched)
1919 VALIDATE_POINTER_TO_OBJECT_ARRAY(steppers, ICorDebugStepper *,
1921 VALIDATE_POINTER_TO_OBJECT(pceltFetched, ULONG *);
1923 return (Next(celt, (CordbBase **)steppers, pceltFetched));
1926 //-----------------------------------------------------------
1927 // ICorDebugThreadEnum
1928 //-----------------------------------------------------------
1930 COM_METHOD Next(ULONG celt, ICorDebugThread *threads[],
1931 ULONG *pceltFetched)
1933 VALIDATE_POINTER_TO_OBJECT_ARRAY(threads, ICorDebugThread *,
1935 VALIDATE_POINTER_TO_OBJECT(pceltFetched, ULONG *);
1937 return (Next(celt, (CordbBase **)threads, pceltFetched));
1940 //-----------------------------------------------------------
1941 // ICorDebugModuleEnum
1942 //-----------------------------------------------------------
1944 COM_METHOD Next(ULONG celt, ICorDebugModule *modules[],
1945 ULONG *pceltFetched)
1947 VALIDATE_POINTER_TO_OBJECT_ARRAY(modules, ICorDebugModule *,
1949 VALIDATE_POINTER_TO_OBJECT(pceltFetched, ULONG *);
1951 return (Next(celt, (CordbBase **)modules, pceltFetched));
1954 //-----------------------------------------------------------
1955 // ICorDebugAppDomainEnum
1956 //-----------------------------------------------------------
1958 COM_METHOD Next(ULONG celt, ICorDebugAppDomain *appdomains[],
1959 ULONG *pceltFetched)
1961 VALIDATE_POINTER_TO_OBJECT_ARRAY(appdomains, ICorDebugAppDomain *,
1963 VALIDATE_POINTER_TO_OBJECT(pceltFetched, ULONG *);
1965 return (Next(celt, (CordbBase **)appdomains, pceltFetched));
1967 //-----------------------------------------------------------
1968 // ICorDebugAssemblyEnum
1969 //-----------------------------------------------------------
1971 COM_METHOD Next(ULONG celt, ICorDebugAssembly *assemblies[],
1972 ULONG *pceltFetched)
1974 VALIDATE_POINTER_TO_OBJECT_ARRAY(assemblies, ICorDebugAssembly *,
1976 VALIDATE_POINTER_TO_OBJECT(pceltFetched, ULONG *);
1978 return (Next(celt, (CordbBase **)assemblies, pceltFetched));
1981 // Owning object is our link to the CordbProcess* tree. Never null until we're neutered.
1982 // NeuterList is related to the owning object. Need to cache it so that we can pass it on
1984 CordbBase * m_pOwnerObj; // provides us w/ a CordbProcess*
1985 NeuterList * m_pOwnerNeuterList;
1988 CordbHashTable *m_table;
1991 HASHFIND m_hashfind;
1998 // timestampt of hashtable when we start enumerating it. Useful for detecting if the table
1999 // changes underneath us.
2000 int m_DbgChangeCount;
2003 void AssertValid() { }
2007 //These factor code between Next & Skip
2008 HRESULT PrepForEnum(CordbBase **pBase);
2010 // Note that the set of types advanced by Pre & by Post are disjoint, and
2011 // that the union of these two sets are all possible types enuerated by
2012 // the CordbHashTableEnum.
2013 HRESULT AdvancePreAssign(CordbBase **pBase);
2014 HRESULT AdvancePostAssign(CordbBase **pBase,
2018 // This factors some code that initializes the module enumerator.
2019 HRESULT SetupModuleEnum();
2024 //-----------------------------------------------------------------------------
2026 // Dtors can be called at any time (whenever Cordbg calls Release, which is outside
2027 // of our control), so we never want to do significant work in a dtor
2028 // (this includes sending IPC events + neutering).
2029 // So objects can queue themselves up to be neutered at a safe time.
2031 // Items in a NeuterList should only contain state in the Right-Side.
2032 // If the item holds resources in the left-side, it should be placed on a
2033 // code:LeftSideResourceCleanupList
2034 //-----------------------------------------------------------------------------
2041 // Add an object to be neutered.
2042 // Anybody calls this to add themselves to the list.
2043 // This will add it to the list and maintain an internal reference to it.
2044 void Add(CordbProcess * pProcess, CordbBase * pObject);
2046 // Add w/o checking for safety. Should only be used by Process-list enum.
2047 void UnsafeAdd(CordbProcess * pProcess, CordbBase * pObject);
2049 // Neuter everything on the list.
2050 // This should only be called by the "owner", but we can't really enforce that.
2051 // This will release all internal references and empty the list.
2052 void NeuterAndClear(CordbProcess * pProcess);
2054 // Sweep for all objects that are marked as 'm_fNeuterAtWill'.
2055 // Neuter and remove these.
2056 void SweepAllNeuterAtWillObjects(CordbProcess * pProcess);
2061 RSSmartPtr<CordbBase> m_pObject;
2065 // Manipulating the list is done under the Process lock.
2069 //-----------------------------------------------------------------------------
2070 // This list is for objects that hold left-side resources.
2071 // If the object does not hold left-side resources, it can be placed on a
2073 //-----------------------------------------------------------------------------
2074 class LeftSideResourceCleanupList : public NeuterList
2077 // dispose everything contained in the list by calling SafeDispose() on each element
2078 void SweepNeuterLeftSideResources(CordbProcess * pProcess);
2079 void NeuterLeftSideResourcesAndClear(CordbProcess * pProcess);
2082 //-------------------------------------------------------------------------
2085 // Stores a value along with a bit indicating whether the value is valid.
2087 // This is particularly useful for LS data read via DAC. We need to gracefully
2088 // handle missing data, and we may want to track independent pieces of data
2089 // separately (often with lazy initialization). It's essential that we can't
2090 // easily lose track of whether the data has been cached yet or not. So
2091 // rather than have extra "isValid" bools everywhere, we use this class to
2092 // encapsulate the validity bit in with the data, and ASSERT that it is true
2093 // whenever reading out the data.
2094 // Note that the client must still remember to call GetValue only when HasValue
2095 // is true. Since C++ doesn't have type-safe sum types, we can't enforce this
2096 // explicitly at compile time (ML-style datatypes and pattern matching is perfect
2099 // Note that we could consider adding some operator overloads to make using
2100 // instances of this class more transparent. Experience will tell if this
2101 // is a good idea or not.
2103 template <typename T>
2107 // By default, initialize to invalid
2108 Optional() : m_fHasValue(false), m_value(T()) {}
2110 // Allow implicit initialization from a value (for copyable T)
2111 Optional(const T& val) : m_fHasValue(true), m_value(val) {}
2113 // Returns true if a value has been stored
2114 bool HasValue() const { return m_fHasValue; }
2116 // Extract the value. Can only be called when HasValue is true.
2117 const T& GetValue() { _ASSERTE(m_fHasValue); return m_value; }
2119 // Get a writable pointer to the value structure, for filling in uncopyable data structures
2120 T * GetValueAddr() { return &m_value; }
2122 // Explicitly mark this object as having a value (for use after writing to it directly using
2123 // GetValueAddr. Not necessary for simple/primitive types).
2124 void SetHasValue() { m_fHasValue = true; }
2126 // Also gets compiler-default copy constructor and assignment operator if T has them
2134 /* ------------------------------------------------------------------------- *
2136 * ------------------------------------------------------------------------- */
2138 class Cordb : public CordbBase, public ICorDebug, public ICorDebugRemote
2141 Cordb(CorDebugInterfaceVersion iDebuggerVersion);
2143 virtual void Neuter();
2148 virtual const char * DbgGetName() { return "Cordb"; }
2150 // Under Debug, we keep some extra state for tracking leaks. The goal is that
2151 // we can assert that we aren't leaking internal refs. We'd like to assert that
2152 // we're not leaking external refs, but since we can't force Cordbg to release,
2153 // we can't really assert that.
2154 // So the idea is that when Cordbg has released its last Cordb object, that
2155 // all internal references have been released.
2156 // Unfortunately, certain CordbBase objects are unrooted and thus we have no
2157 // good time to neuter them and clean up any internal references they may hold.
2158 // So we keep count of those guys too.
2159 static LONG s_DbgMemTotalOutstandingCordb;
2160 static LONG s_DbgMemTotalOutstandingInternalRefs;
2164 // Turn this on to enable an array which will contain all objects that have
2165 // not been completely released.
2167 // #define TRACK_OUTSTANDING_OBJECTS 1
2169 #ifdef TRACK_OUTSTANDING_OBJECTS
2171 #define MAX_TRACKED_OUTSTANDING_OBJECTS 256
2172 static void *Cordb::s_DbgMemOutstandingObjects[MAX_TRACKED_OUTSTANDING_OBJECTS];
2173 static LONG Cordb::s_DbgMemOutstandingObjectMax;
2177 //-----------------------------------------------------------
2179 //-----------------------------------------------------------
2181 ULONG STDMETHODCALLTYPE AddRef()
2183 return (BaseAddRef());
2185 ULONG STDMETHODCALLTYPE Release()
2187 return (BaseRelease());
2189 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
2191 //-----------------------------------------------------------
2193 //-----------------------------------------------------------
2195 #ifdef FEATURE_CORECLR
2196 HRESULT SetTargetCLR(HMODULE hmodTargetCLR);
2197 #endif // FEATURE_CORECLR
2199 COM_METHOD Initialize();
2200 COM_METHOD Terminate();
2201 COM_METHOD SetManagedHandler(ICorDebugManagedCallback *pCallback);
2202 COM_METHOD SetUnmanagedHandler(ICorDebugUnmanagedCallback *pCallback);
2203 COM_METHOD CreateProcess(LPCWSTR lpApplicationName,
2204 __in_z LPWSTR lpCommandLine,
2205 LPSECURITY_ATTRIBUTES lpProcessAttributes,
2206 LPSECURITY_ATTRIBUTES lpThreadAttributes,
2207 BOOL bInheritHandles,
2208 DWORD dwCreationFlags,
2209 PVOID lpEnvironment,
2210 LPCWSTR lpCurrentDirectory,
2211 LPSTARTUPINFOW lpStartupInfo,
2212 LPPROCESS_INFORMATION lpProcessInformation,
2213 CorDebugCreateProcessFlags debuggingFlags,
2214 ICorDebugProcess **ppProcess);
2215 COM_METHOD DebugActiveProcess(DWORD dwProcessId, BOOL fWin32Attach, ICorDebugProcess **ppProcess);
2216 COM_METHOD EnumerateProcesses(ICorDebugProcessEnum **ppProcess);
2217 COM_METHOD GetProcess(DWORD dwProcessId, ICorDebugProcess **ppProcess);
2218 COM_METHOD CanLaunchOrAttach(DWORD dwProcessId, BOOL win32DebuggingEnabled);
2220 //-----------------------------------------------------------
2222 //-----------------------------------------------------------
2224 static COM_METHOD CreateObjectV1(REFIID id, void **object);
2225 #if defined(FEATURE_DBGIPC_TRANSPORT_DI)
2226 static COM_METHOD CreateObjectTelesto(REFIID id, void ** pObject);
2227 #endif // FEATURE_DBGIPC_TRANSPORT_DI
2228 static COM_METHOD CreateObject(CorDebugInterfaceVersion iDebuggerVersion, REFIID id, void **object);
2230 //-----------------------------------------------------------
2232 //-----------------------------------------------------------
2234 COM_METHOD CreateProcessEx(ICorDebugRemoteTarget * pRemoteTarget,
2235 LPCWSTR lpApplicationName,
2236 __in_z LPWSTR lpCommandLine,
2237 LPSECURITY_ATTRIBUTES lpProcessAttributes,
2238 LPSECURITY_ATTRIBUTES lpThreadAttributes,
2239 BOOL bInheritHandles,
2240 DWORD dwCreationFlags,
2241 PVOID lpEnvironment,
2242 LPCWSTR lpCurrentDirectory,
2243 LPSTARTUPINFOW lpStartupInfo,
2244 LPPROCESS_INFORMATION lpProcessInformation,
2245 CorDebugCreateProcessFlags debuggingFlags,
2246 ICorDebugProcess ** ppProcess);
2248 COM_METHOD DebugActiveProcessEx(ICorDebugRemoteTarget * pRemoteTarget,
2251 ICorDebugProcess ** ppProcess);
2254 //-----------------------------------------------------------
2255 // Methods not exposed via a COM interface.
2256 //-----------------------------------------------------------
2258 HRESULT CreateProcessCommon(ICorDebugRemoteTarget * pRemoteTarget,
2259 LPCWSTR lpApplicationName,
2260 __in_z LPWSTR lpCommandLine,
2261 LPSECURITY_ATTRIBUTES lpProcessAttributes,
2262 LPSECURITY_ATTRIBUTES lpThreadAttributes,
2263 BOOL bInheritHandles,
2264 DWORD dwCreationFlags,
2265 PVOID lpEnvironment,
2266 LPCWSTR lpCurrentDirectory,
2267 LPSTARTUPINFOW lpStartupInfo,
2268 LPPROCESS_INFORMATION lpProcessInformation,
2269 CorDebugCreateProcessFlags debuggingFlags,
2270 ICorDebugProcess **ppProcess);
2272 HRESULT DebugActiveProcessCommon(ICorDebugRemoteTarget * pRemoteTarget, DWORD id, BOOL win32Attach, ICorDebugProcess **ppProcess);
2274 void EnsureCanLaunchOrAttach(BOOL fWin32DebuggingEnabled);
2276 void EnsureAllowAnotherProcess();
2277 void AddProcess(CordbProcess* process);
2278 void RemoveProcess(CordbProcess* process);
2279 CordbSafeHashTable<CordbProcess> *GetProcessList();
2281 void LockProcessList();
2282 void UnlockProcessList();
2285 bool ThreadHasProcessListLock();
2289 HRESULT SendIPCEvent(CordbProcess * pProcess,
2290 DebuggerIPCEvent * pEvent,
2293 void ProcessStateChanged();
2295 HRESULT WaitForIPCEventFromProcess(CordbProcess* process,
2296 CordbAppDomain *appDomain,
2297 DebuggerIPCEvent* event);
2299 //-----------------------------------------------------------
2301 //-----------------------------------------------------------
2304 RSExtSmartPtr<ICorDebugManagedCallback> m_managedCallback;
2305 RSExtSmartPtr<ICorDebugManagedCallback2> m_managedCallback2;
2306 RSExtSmartPtr<ICorDebugManagedCallback3> m_managedCallback3;
2307 RSExtSmartPtr<ICorDebugUnmanagedCallback> m_unmanagedCallback;
2309 CordbRCEventThread* m_rcEventThread;
2311 CorDebugInterfaceVersion GetDebuggerVersion() const;
2313 #ifdef FEATURE_CORESYSTEM
2314 HMODULE GetTargetCLR() { return m_targetCLR; }
2318 bool IsCreateProcessSupported();
2319 bool IsInteropDebuggingSupported();
2320 void CheckCompatibility();
2322 CordbSafeHashTable<CordbProcess> m_processes;
2324 // List to track outstanding CordbProcessEnum objects.
2325 NeuterList m_pProcessEnumList;
2327 RSLock m_processListMutex;
2330 // This is the version of the ICorDebug APIs that the debugger believes it's consuming.
2331 CorDebugInterfaceVersion m_debuggerSpecifiedVersion;
2333 //Note - this code could be useful outside coresystem, but keeping the change localized
2334 // because we are late in the win8 release
2335 #ifdef FEATURE_CORESYSTEM
2336 HMODULE m_targetCLR;
2343 /* ------------------------------------------------------------------------- *
2345 * ------------------------------------------------------------------------- */
2347 // Provides the implementation for ICorDebugAppDomain, ICorDebugAppDomain2,
2348 // and ICorDebugAppDomain3
2349 class CordbAppDomain : public CordbBase,
2350 public ICorDebugAppDomain,
2351 public ICorDebugAppDomain2,
2352 public ICorDebugAppDomain3,
2353 public ICorDebugAppDomain4
2356 // Create a CordbAppDomain object based on a pointer to the AppDomain instance in the CLR
2357 CordbAppDomain(CordbProcess * pProcess,
2358 VMPTR_AppDomain vmAppDomain);
2360 virtual ~CordbAppDomain();
2362 virtual void Neuter();
2364 using CordbBase::GetProcess;
2367 virtual const char * DbgGetName() { return "CordbAppDomain"; }
2371 //-----------------------------------------------------------
2373 //-----------------------------------------------------------
2375 ULONG STDMETHODCALLTYPE AddRef()
2377 return (BaseAddRef());
2379 ULONG STDMETHODCALLTYPE Release()
2381 return (BaseRelease());
2383 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
2385 //-----------------------------------------------------------
2386 // ICorDebugController
2387 //-----------------------------------------------------------
2389 COM_METHOD Stop(DWORD dwTimeout);
2390 COM_METHOD Continue(BOOL fIsOutOfBand);
2391 COM_METHOD IsRunning(BOOL * pbRunning);
2392 COM_METHOD HasQueuedCallbacks(ICorDebugThread * pThread,
2394 COM_METHOD EnumerateThreads(ICorDebugThreadEnum ** ppThreads);
2395 COM_METHOD SetAllThreadsDebugState(CorDebugThreadState state, ICorDebugThread * pExceptThisThread);
2397 // Deprecated, returns E_NOTIMPL
2398 COM_METHOD Detach();
2400 COM_METHOD Terminate(unsigned int exitCode);
2402 COM_METHOD CanCommitChanges(
2404 ICorDebugEditAndContinueSnapshot * pSnapshots[],
2405 ICorDebugErrorInfoEnum ** pError);
2407 COM_METHOD CommitChanges(
2409 ICorDebugEditAndContinueSnapshot * pSnapshots[],
2410 ICorDebugErrorInfoEnum ** pError);
2412 //-----------------------------------------------------------
2413 // ICorDebugAppDomain
2414 //-----------------------------------------------------------
2416 * GetProcess returns the process containing the app domain
2419 COM_METHOD GetProcess(ICorDebugProcess ** ppProcess);
2422 * EnumerateAssemblies enumerates all assemblies in the app domain
2425 COM_METHOD EnumerateAssemblies(ICorDebugAssemblyEnum ** ppAssemblies);
2427 COM_METHOD GetModuleFromMetaDataInterface(IUnknown * pIMetaData,
2428 ICorDebugModule ** ppModule);
2430 * EnumerateBreakpoints returns an enum of all active breakpoints
2431 * in the app domain. This includes all types of breakpoints :
2432 * function breakpoints, data breakpoints, etc.
2435 COM_METHOD EnumerateBreakpoints(ICorDebugBreakpointEnum ** ppBreakpoints);
2438 * EnumerateSteppers returns an enum of all active steppers in the app domain.
2441 COM_METHOD EnumerateSteppers(ICorDebugStepperEnum ** ppSteppers);
2443 // Deprecated, always returns true.
2444 COM_METHOD IsAttached(BOOL * pfAttached);
2446 // Returns the friendly name of the AppDomain
2447 COM_METHOD GetName(ULONG32 cchName,
2449 __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[]);
2452 * GetObject returns the runtime app domain object.
2453 * Note: This method is not yet implemented.
2456 COM_METHOD GetObject(ICorDebugValue ** ppObject);
2458 // Deprecated, does nothing
2459 COM_METHOD Attach();
2460 COM_METHOD GetID(ULONG32 * pId);
2462 //-----------------------------------------------------------
2463 // ICorDebugAppDomain2 APIs
2464 //-----------------------------------------------------------
2465 COM_METHOD GetArrayOrPointerType(CorElementType elementType,
2467 ICorDebugType * pTypeArg,
2468 ICorDebugType ** ppResultType);
2470 COM_METHOD GetFunctionPointerType(ULONG32 cTypeArgs,
2471 ICorDebugType * rgpTypeArgs[],
2472 ICorDebugType ** ppResultType);
2474 //-----------------------------------------------------------
2475 // ICorDebugAppDomain3 APIs
2476 //-----------------------------------------------------------
2477 COM_METHOD GetCachedWinRTTypesForIIDs(
2480 ICorDebugTypeEnum * * ppTypesEnum);
2482 COM_METHOD GetCachedWinRTTypes(
2483 ICorDebugGuidToTypeEnum * * ppType);
2485 //-----------------------------------------------------------
2486 // ICorDebugAppDomain4
2487 //-----------------------------------------------------------
2488 COM_METHOD GetObjectForCCW(CORDB_ADDRESS ccwPointer, ICorDebugValue **ppManagedObject);
2490 // Get the VMPTR for this appdomain.
2491 VMPTR_AppDomain GetADToken() { return m_vmAppDomain; }
2493 // Given a metadata interface, find the module in this appdomain that matches it.
2494 CordbModule * GetModuleFromMetaDataInterface(IUnknown *pIMetaData);
2496 // Lookup a module from the cache. Create and to the cache if needed.
2497 CordbModule * LookupOrCreateModule(VMPTR_Module vmModuleToken, VMPTR_DomainFile vmDomainFileToken);
2499 // Lookup a module from the cache. Create and to the cache if needed.
2500 CordbModule * LookupOrCreateModule(VMPTR_DomainFile vmDomainFileToken);
2502 // Callback from DAC for module enumeration
2503 static void ModuleEnumerationCallback(VMPTR_DomainFile vmModule, void * pUserData);
2505 // Use DAC to add any modules for this assembly.
2506 void PrepopulateModules();
2508 void InvalidateName() { m_strAppDomainName.Clear(); }
2511 ULONG m_AppDomainId;
2513 CordbAssembly * LookupOrCreateAssembly(VMPTR_DomainAssembly vmDomainAssembly);
2514 CordbAssembly * LookupOrCreateAssembly(VMPTR_Assembly vmAssembly);
2515 void RemoveAssemblyFromCache(VMPTR_DomainAssembly vmDomainAssembly);
2518 CordbSafeHashTable<CordbBreakpoint> m_breakpoints;
2520 // Unique objects that represent the use of some
2521 // basic ELEMENT_TYPE's as type parameters. These
2522 // are shared acrosss the entire process. We could
2523 // go and try to find the classes corresponding to these
2524 // element types but it seems simpler just to keep
2525 // them as special cases.
2526 CordbSafeHashTable<CordbType> m_sharedtypes;
2528 CordbAssembly * CacheAssembly(VMPTR_DomainAssembly vmDomainAssembly);
2529 CordbAssembly * CacheAssembly(VMPTR_Assembly vmAssembly);
2532 // Cache of modules in this appdomain. In the VM, modules live in an assembly.
2533 // This cache lives on the appdomain because we generally want to do appdomain (or process)
2535 // This is indexed by VMPTR_DomainFile, which has appdomain affinity.
2536 // This is populated by code:CordbAppDomain::LookupOrCreateModule (which may be invoked
2537 // anytime the RS gets hold of a VMPTR), and are removed at the unload event.
2538 CordbSafeHashTable<CordbModule> m_modules;
2540 // Cache of assemblies in this appdomain.
2541 // This is indexed by VMPTR_DomainAssembly, which has appdomain affinity.
2542 // This is populated by code:CordbAppDomain::LookupOrCreateAssembly (which may be invoked
2543 // anytime the RS gets hold of a VMPTR), and are removed at the unload event.
2544 CordbSafeHashTable<CordbAssembly> m_assemblies;
2546 static void AssemblyEnumerationCallback(VMPTR_DomainAssembly vmDomainAssembly, void * pThis);
2547 void PrepopulateAssembliesOrThrow();
2549 // Use DAC to refresh our name
2550 HRESULT RefreshName();
2552 StringCopyHolder m_strAppDomainName;
2554 NeuterList m_TypeNeuterList; // List of types owned by this AppDomain.
2556 // List of Sweepable objects owned by this AppDomain.
2557 // This includes some objects taht hold resources in the left-side (mainly
2558 // as CordbHandleValue, see code:CordbHandleValue::Dispose), as well as:
2559 // - Cordb*Value objects that survive across continues and have appdomain affinity.
2560 LeftSideResourceCleanupList m_SweepableNeuterList;
2562 VMPTR_AppDomain m_vmAppDomain;
2564 // The "Long" exit list is for items that don't get neutered until the appdomain exits.
2565 // The "Sweepable" exit list is for items that may be neuterable sooner than AD exit.
2566 // By splitting out the list, we can just try to sweep the "Sweepable" list and we
2567 // don't waste any time sweeping things on the "Long" list that aren't neuterable anyways.
2568 NeuterList * GetLongExitNeuterList() { return &m_TypeNeuterList; }
2569 LeftSideResourceCleanupList * GetSweepableExitNeuterList() { return &m_SweepableNeuterList; }
2571 void AddToTypeList(CordbBase *pObject);
2576 /* ------------------------------------------------------------------------- *
2578 * ------------------------------------------------------------------------- */
2580 class CordbAssembly : public CordbBase, public ICorDebugAssembly, ICorDebugAssembly2
2583 CordbAssembly(CordbAppDomain * pAppDomain,
2584 VMPTR_Assembly vmAssembly,
2585 VMPTR_DomainAssembly vmDomainAssembly);
2586 virtual ~CordbAssembly();
2587 virtual void Neuter();
2589 using CordbBase::GetProcess;
2592 virtual const char * DbgGetName() { return "CordbAssembly"; }
2596 //-----------------------------------------------------------
2598 //-----------------------------------------------------------
2600 ULONG STDMETHODCALLTYPE AddRef()
2602 return (BaseAddRef());
2604 ULONG STDMETHODCALLTYPE Release()
2606 return (BaseRelease());
2608 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
2610 //-----------------------------------------------------------
2611 // ICorDebugAssembly
2612 //-----------------------------------------------------------
2615 * GetProcess returns the process containing the assembly
2617 COM_METHOD GetProcess(ICorDebugProcess ** ppProcess);
2619 // Gets the AppDomain containing this assembly
2620 COM_METHOD GetAppDomain(ICorDebugAppDomain ** ppAppDomain);
2623 * EnumerateModules enumerates all modules in the assembly
2625 COM_METHOD EnumerateModules(ICorDebugModuleEnum ** ppModules);
2628 * GetCodeBase returns the code base used to load the assembly
2630 COM_METHOD GetCodeBase(ULONG32 cchName,
2632 __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[]);
2634 // returns the filename of the assembly, or "<unknown>" for in-memory assemblies
2635 COM_METHOD GetName(ULONG32 cchName,
2637 __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[]);
2640 //-----------------------------------------------------------
2641 // ICorDebugAssembly2
2642 //-----------------------------------------------------------
2645 * IsFullyTrusted returns a flag indicating whether the security system
2646 * has granted the assembly full trust.
2648 COM_METHOD IsFullyTrusted(BOOL * pbFullyTrusted);
2650 //-----------------------------------------------------------
2651 // internal accessors
2652 //-----------------------------------------------------------
2655 void DbgAssertAssemblyDeleted();
2657 static void DbgAssertAssemblyDeletedCallback(VMPTR_DomainAssembly vmDomainAssembly, void * pUserData);
2660 CordbAppDomain * GetAppDomain() { return m_pAppDomain; }
2662 VMPTR_DomainAssembly GetDomainAssemblyPtr() { return m_vmDomainAssembly; }
2664 VMPTR_Assembly m_vmAssembly;
2665 VMPTR_DomainAssembly m_vmDomainAssembly;
2666 CordbAppDomain * m_pAppDomain;
2668 StringCopyHolder m_strAssemblyFileName;
2669 Optional<BOOL> m_foptIsFullTrust;
2673 //-----------------------------------------------------------------------------
2674 // Describe what to do w/ a win32 debug event
2675 //-----------------------------------------------------------------------------
2681 // Inband events: Dispatch to Cordbg
2682 // safe for stopping the shell and communicating with the runtime
2685 // workaround. Inband event, but NewEvent =false
2686 cInband_NotNewEvent,
2688 // This is a debug event that corresponds with getting to the beginning
2689 // of a first chance hijack.
2690 cFirstChanceHijackStarted,
2692 // This is the debug event that corresponds with getting to the end of
2693 // a hijack. To continue we need to restore an unhijacked context
2694 cInbandHijackComplete,
2696 // This is a debug event which corresponds to re-hiting a previous
2697 // IB event after returning from the hijack. Now we have already dispatched it
2698 // so we know how the user wants it to be continued
2699 // Continue immediately with the previously determined
2700 cInbandExceptionRetrigger,
2702 // This debug event is a breakpoint in unmanaged code that we placed. It will need
2703 // the M2UHandoffHijack to run the in process breakpoint handling code.
2704 cBreakpointRequiringHijack,
2706 // Oob events: Dispatch to Cordbg
2707 // Not safe stopping events. They must be continued immediately.
2710 // CLR internal exception, Continue(not_handled), don't dispatch
2711 // The CLR expects this exception and will deal with it properly.
2714 // Don't dispatch. Continue(DBG_CONTINUE).
2715 // Common for flare.
2719 Type GetType() const { return m_type; };
2722 const char * GetReactionName()
2726 case cInband: return "cInband";
2727 case cInband_NotNewEvent: return "cInband_NotNewEvent";
2728 case cInbandHijackComplete: return "cInbandHijackComplete";
2729 case cInbandExceptionRetrigger: return "cInbandExceptionRetrigger";
2730 case cBreakpointRequiringHijack: return "cBreakpointRequiringHijack";
2731 case cOOB: return "cOOB";
2732 case cCLR: return "cCLR";
2733 case cIgnore: return "cIgnore";
2734 default: return "<unknown>";
2743 Reaction(Type t, int line) : m_type(t) {
2747 LOG((LF_CORDB, LL_EVERYTHING, "Reaction:%s (determined on line: %d)\n", GetReactionName(), line));
2751 void operator=(const Reaction & other)
2753 m_type = other.m_type;
2755 m_line = other.m_line;
2763 // Under a debug build, track the line # for where this came from.
2768 // Macro for creating a Reaction.
2769 #define REACTION(type) Reaction(Reaction::type, __LINE__)
2771 // Different forms of Unmanaged Continue
2772 enum EUMContinueType
2775 cInternalUMContinue,
2779 /* ------------------------------------------------------------------------- *
2781 * ------------------------------------------------------------------------- */
2785 // On debug, we can afford a larger native event queue..
2786 const int DEBUG_EVENTQUEUE_SIZE = 30;
2788 const int DEBUG_EVENTQUEUE_SIZE = 10;
2791 void DeleteIPCEventHelper(DebuggerIPCEvent *pDel);
2794 // Private interface on CordbProcess that ShimProcess needs to emulate V2 functionality.
2795 // The fact that we need private hooks means that V3 is not sufficiently finished to allow building
2796 // a V2 debugger. This interface should shrink over time (and eventually go away) as the functionality gets exposed
2798 // CordbProcess calls back into ShimProcess too, so the public surface of code:ShimProcess plus
2799 // the spots in CordbProcess that call them are additional surface area that may need to addressed
2800 // to make the shim public.
2801 class IProcessShimHooks
2804 // Get the OS Process ID of the target.
2805 virtual DWORD GetPid() = 0;
2807 // Request a synchronization for attach.
2808 // This essentially just sends an AsyncBreak to the left-side. Once the target is
2809 // synchronized, the Shim can use inspection to send all the various fake-attach events.
2811 // Once the shim has a way of requesting a synchronization from out-of-process for an
2812 // arbitrary running target that's not stopped at a managed debug event, we can
2814 virtual void QueueManagedAttachIfNeeded() = 0;
2816 // Hijack a thread at an unhandled exception to allow us to resume executing the target so
2817 // that the helper thread can run and service IPC requests. This is also needed to allow
2818 // func-eval at a 2nd-chance exception
2820 // This will require an architectural change to remove. Either:
2821 // - actions like func-eval / synchronization may call this directly themselves.
2822 // - the CLR's managed Unhandled-exception event is moved out of the native
2823 // unhandled-exception event, thus making native unhandled exceptions uninteresting to ICorDebug.
2824 // - everything is out-of-process, and so the CLR doesn't need to continue after an unhandled
2825 // native exception.
2826 virtual BOOL HijackThreadForUnhandledExceptionIfNeeded(DWORD dwThreadId) = 0;
2828 #ifdef FEATURE_INTEROP_DEBUGGING
2829 // Private hook to do the bulk of the interop-debugging goo. This includes hijacking inband
2830 // events and queueing them so that the helper-thread can run.
2832 // We can remove this once we kill the helper-thread, or after enough functionality is
2833 // out-of-process that the debugger doesn't need the helper thread when stopped at an event.
2834 virtual void HandleDebugEventForInteropDebugging(const DEBUG_EVENT * pEvent) = 0;
2835 #endif // FEATURE_INTEROP_DEBUGGING
2837 // Get the modules in the order that they were loaded. This is needed to send the fake-attach events
2838 // for module load in the right order.
2840 // This can be removed once ICorDebug's enumerations are ordered.
2841 virtual void GetModulesInLoadOrder(
2842 ICorDebugAssembly * pAssembly,
2843 RSExtSmartPtr<ICorDebugModule>* pModules,
2844 ULONG countModules) = 0;
2846 // Get the assemblies in the order that they were loaded. This is needed to send the fake-attach events
2847 // for assembly load in the right order.
2849 // This can be removed once ICorDebug's enumerations are ordered.
2850 virtual void GetAssembliesInLoadOrder(
2851 ICorDebugAppDomain * pAppDomain,
2852 RSExtSmartPtr<ICorDebugAssembly>* pAssemblies,
2853 ULONG countAssemblies) = 0;
2855 // Queue up fake connection events for attach.
2856 // ICorDebug doesn't expose any enumeration for connections, so the shim needs to call into a
2857 // private hook to enumerate them for attach.
2858 virtual void QueueFakeConnectionEvents() = 0;
2860 // This finishes initializing the IPC channel between the LS + RS, which includes duplicating
2861 // some handles and events.
2863 // This can be removed once the IPC channel is completely gone and all communication goes
2864 // soley through the data-target.
2865 virtual void FinishInitializeIPCChannel() = 0;
2867 // Called when stopped at a managed debug event to request a synchronization.
2868 // This can be replaced when we expose synchronization from ICorDebug.
2869 // The fact that the debuggee is at a managed debug event greatly simplifies the request here
2870 // (in contrast to QueueManagedAttachIfNeeded). It means that we can just flip a flag from
2871 // out-of-process, and when the debuggee thread resumes, it can check that flag and do the
2872 // synchronization from in-process.
2873 virtual void RequestSyncAtEvent()= 0;
2875 virtual bool IsThreadSuspendedOrHijacked(ICorDebugThread * pThread) = 0;
2879 // entry for the array of connections in EnumerateConnectionsData
2880 struct EnumerateConnectionsEntry
2883 StringCopyHolder m_pName; // name of the connection
2884 DWORD m_dwID; // ID of the connection
2887 // data structure used in the callback for enumerating connections (code:CordbProcess::QueueFakeConnectionEvents)
2888 struct EnumerateConnectionsData
2891 ~EnumerateConnectionsData()
2893 if (m_pEntryArray != NULL)
2895 delete [] m_pEntryArray;
2896 m_pEntryArray = NULL;
2900 CordbProcess * m_pThis; // the "this" process
2901 EnumerateConnectionsEntry * m_pEntryArray; // an array of connections to be filled in
2902 UINT32 m_uIndex; // the next entry in the array to be filled
2905 // data structure used in the callback for asserting that an appdomain has been deleted
2906 // (code:CordbProcess::DbgAssertAppDomainDeleted)
2907 struct DbgAssertAppDomainDeletedData
2910 CordbProcess * m_pThis;
2911 VMPTR_AppDomain m_vmAppDomainDeleted;
2914 class CordbProcess :
2916 public ICorDebugProcess,
2917 public ICorDebugProcess2,
2918 public ICorDebugProcess3,
2919 public ICorDebugProcess4,
2920 public ICorDebugProcess5,
2921 public ICorDebugProcess7,
2922 public ICorDebugProcess8,
2923 public IDacDbiInterface::IAllocator,
2924 public IDacDbiInterface::IMetaDataLookup,
2925 public IProcessShimHooks
2926 #ifdef FEATURE_LEGACYNETCF_DBG_HOST_CONTROL
2927 , public ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly
2930 // Ctor is private. Use OpenVirtualProcess instead.
2931 CordbProcess(ULONG64 clrInstanceId, IUnknown * pDataTarget, HMODULE hDacModule, Cordb * pCordb, DWORD dwProcessID, ShimProcess * pShim);
2935 virtual ~CordbProcess();
2936 virtual void Neuter();
2938 // Neuter left-side resources for all children
2939 void NeuterChildrenLeftSideResources();
2941 // Neuter all of all children, but not the actual process object.
2942 void NeuterChildren();
2945 // The way to instantiate a new CordbProcess object.
2946 // @dbgtodo managed pipeline - this is not fully active in all scenarios yet.
2947 static HRESULT OpenVirtualProcess(ULONG64 clrInstanceId,
2948 IUnknown * pDataTarget,
2952 ShimProcess * pShim,
2953 CordbProcess ** ppProcess);
2955 // Helper function to determine whether this ICorDebug is compatibile with a debugger
2956 // designed for the specified major version
2957 static bool IsCompatibleWith(DWORD clrMajorVersion);
2959 //-----------------------------------------------------------
2961 // -----------------------------------------------------------
2962 IMDInternalImport * LookupMetaData(VMPTR_PEFile vmPEFile, bool &isILMetaDataForNGENImage);
2964 // Helper functions for LookupMetaData implementation
2965 IMDInternalImport * LookupMetaDataFromDebugger(VMPTR_PEFile vmPEFile,
2966 bool &isILMetaDataForNGENImage,
2967 CordbModule * pModule);
2969 IMDInternalImport * LookupMetaDataFromDebuggerForSingleFile(CordbModule * pModule,
2970 LPCWSTR pwszImagePath,
2975 //-----------------------------------------------------------
2976 // IDacDbiInterface::IAllocator
2977 //-----------------------------------------------------------
2979 void * Alloc(SIZE_T lenBytes);
2980 void Free(void * p);
2983 virtual const char * DbgGetName() { return "CordbProcess"; }
2986 //-----------------------------------------------------------
2988 //-----------------------------------------------------------
2990 ULONG STDMETHODCALLTYPE AddRef()
2992 return BaseAddRefEnforceExternal();
2994 ULONG STDMETHODCALLTYPE Release()
2996 return BaseReleaseEnforceExternal();
2998 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
3000 //-----------------------------------------------------------
3001 // ICorDebugController
3002 //-----------------------------------------------------------
3004 COM_METHOD Stop(DWORD dwTimeout);
3005 COM_METHOD Deprecated_Continue();
3006 COM_METHOD IsRunning(BOOL *pbRunning);
3007 COM_METHOD HasQueuedCallbacks(ICorDebugThread *pThread, BOOL *pbQueued);
3008 COM_METHOD EnumerateThreads(ICorDebugThreadEnum **ppThreads);
3009 COM_METHOD SetAllThreadsDebugState(CorDebugThreadState state,
3010 ICorDebugThread *pExceptThisThread);
3011 COM_METHOD Detach();
3012 COM_METHOD Terminate(unsigned int exitCode);
3014 COM_METHOD CanCommitChanges(
3016 ICorDebugEditAndContinueSnapshot *pSnapshots[],
3017 ICorDebugErrorInfoEnum **pError);
3019 COM_METHOD CommitChanges(
3021 ICorDebugEditAndContinueSnapshot *pSnapshots[],
3022 ICorDebugErrorInfoEnum **pError);
3024 COM_METHOD Continue(BOOL fIsOutOfBand);
3025 COM_METHOD ThreadForFiberCookie(DWORD fiberCookie,
3026 ICorDebugThread **ppThread);
3027 COM_METHOD GetHelperThreadID(DWORD *pThreadID);
3029 //-----------------------------------------------------------
3031 //-----------------------------------------------------------
3033 COM_METHOD GetID(DWORD *pdwProcessId);
3034 COM_METHOD GetHandle(HANDLE *phProcessHandle);
3035 COM_METHOD EnableSynchronization(BOOL bEnableSynchronization);
3036 COM_METHOD GetThread(DWORD dwThreadId, ICorDebugThread **ppThread);
3037 COM_METHOD EnumerateBreakpoints(ICorDebugBreakpointEnum **ppBreakpoints);
3038 COM_METHOD EnumerateSteppers(ICorDebugStepperEnum **ppSteppers);
3039 COM_METHOD EnumerateObjects(ICorDebugObjectEnum **ppObjects);
3040 COM_METHOD IsTransitionStub(CORDB_ADDRESS address, BOOL *pbTransitionStub);
3041 COM_METHOD EnumerateModules(ICorDebugModuleEnum **ppModules);
3042 COM_METHOD GetModuleFromMetaDataInterface(IUnknown *pIMetaData,
3043 ICorDebugModule **ppModule);
3044 COM_METHOD SetStopState(DWORD threadID, CorDebugThreadState state);
3045 COM_METHOD IsOSSuspended(DWORD threadID, BOOL *pbSuspended);
3046 COM_METHOD GetThreadContext(DWORD threadID, ULONG32 contextSize,
3048 COM_METHOD SetThreadContext(DWORD threadID, ULONG32 contextSize,
3050 COM_METHOD ReadMemory(CORDB_ADDRESS address, DWORD size, BYTE buffer[],
3052 COM_METHOD WriteMemory(CORDB_ADDRESS address, DWORD size, BYTE buffer[],
3055 COM_METHOD ClearCurrentException(DWORD threadID);
3058 * EnableLogMessages enables/disables sending of log messages to the
3059 * debugger for logging.
3061 COM_METHOD EnableLogMessages(BOOL fOnOff);
3064 * ModifyLogSwitch modifies the specified switch's severity level.
3066 COM_METHOD ModifyLogSwitch(__in_z WCHAR *pLogSwitchName, LONG lLevel);
3068 COM_METHOD EnumerateAppDomains(ICorDebugAppDomainEnum **ppAppDomains);
3069 COM_METHOD GetObject(ICorDebugValue **ppObject);
3071 //-----------------------------------------------------------
3072 // ICorDebugProcess2
3073 //-----------------------------------------------------------
3075 COM_METHOD GetThreadForTaskID(TASKID taskId, ICorDebugThread2 ** ppThread);
3076 COM_METHOD GetVersion(COR_VERSION* pInfo);
3078 COM_METHOD SetUnmanagedBreakpoint(CORDB_ADDRESS address, ULONG32 bufsize, BYTE buffer[], ULONG32 * bufLen);
3079 COM_METHOD ClearUnmanagedBreakpoint(CORDB_ADDRESS address);
3080 COM_METHOD GetCodeAtAddress(CORDB_ADDRESS address, ICorDebugCode ** pCode, ULONG32 * offset);
3082 COM_METHOD SetDesiredNGENCompilerFlags(DWORD pdwFlags);
3083 COM_METHOD GetDesiredNGENCompilerFlags(DWORD *pdwFlags );
3085 COM_METHOD GetReferenceValueFromGCHandle(UINT_PTR handle, ICorDebugReferenceValue **pOutValue);
3087 //-----------------------------------------------------------
3088 // ICorDebugProcess3
3089 //-----------------------------------------------------------
3091 // enables or disables CustomNotifications of a given type
3092 COM_METHOD SetEnableCustomNotification(ICorDebugClass * pClass, BOOL fEnable);
3094 //-----------------------------------------------------------
3095 // ICorDebugProcess4
3096 //-----------------------------------------------------------
3098 const BYTE pRecord[],
3100 CorDebugRecordFormat format,
3103 ICorDebugManagedCallback *pCallback,
3104 DWORD * pContinueStatus);
3106 COM_METHOD ProcessStateChanged(CorDebugStateChange eChange);
3108 //-----------------------------------------------------------
3109 // ICorDebugProcess5
3110 //-----------------------------------------------------------
3111 COM_METHOD GetGCHeapInformation(COR_HEAPINFO *pHeapInfo);
3112 COM_METHOD EnumerateHeap(ICorDebugHeapEnum **ppObjects);
3113 COM_METHOD EnumerateHeapRegions(ICorDebugHeapSegmentEnum **ppRegions);
3114 COM_METHOD GetObject(CORDB_ADDRESS addr, ICorDebugObjectValue **pObject);
3115 COM_METHOD EnableNGENPolicy(CorDebugNGENPolicy ePolicy);
3116 COM_METHOD EnumerateGCReferences(BOOL enumerateWeakReferences, ICorDebugGCReferenceEnum **ppEnum);
3117 COM_METHOD EnumerateHandles(CorGCReferenceType types, ICorDebugGCReferenceEnum **ppEnum);
3118 COM_METHOD GetTypeID(CORDB_ADDRESS obj, COR_TYPEID *pId);
3119 COM_METHOD GetTypeForTypeID(COR_TYPEID id, ICorDebugType **ppType);
3120 COM_METHOD GetArrayLayout(COR_TYPEID id, COR_ARRAY_LAYOUT *pLayout);
3121 COM_METHOD GetTypeLayout(COR_TYPEID id, COR_TYPE_LAYOUT *pLayout);
3122 COM_METHOD GetTypeFields(COR_TYPEID id, ULONG32 celt, COR_FIELD fields[], ULONG32 *pceltNeeded);
3124 //-----------------------------------------------------------
3125 // ICorDebugProcess7
3126 //-----------------------------------------------------------
3127 COM_METHOD SetWriteableMetadataUpdateMode(WriteableMetadataUpdateMode flags);
3129 //-----------------------------------------------------------
3130 // ICorDebugProcess8
3131 //-----------------------------------------------------------
3132 COM_METHOD EnableExceptionCallbacksOutsideOfMyCode(BOOL enableExceptionsOutsideOfJMC);
3134 #ifdef FEATURE_LEGACYNETCF_DBG_HOST_CONTROL
3135 // ---------------------------------------------------------------
3136 // ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly
3137 // ---------------------------------------------------------------
3139 COM_METHOD InvokePauseCallback();
3140 COM_METHOD InvokeResumeCallback();
3144 //-----------------------------------------------------------
3145 // Methods not exposed via a COM interface.
3146 //-----------------------------------------------------------
3148 HRESULT ContinueInternal(BOOL fIsOutOfBand);
3149 HRESULT StopInternal(DWORD dwTimeout, VMPTR_AppDomain pAppDomainToken);
3151 // Sets an unmanaged breakpoint at the target address
3152 HRESULT SetUnmanagedBreakpointInternal(CORDB_ADDRESS address, ULONG32 bufsize, BYTE buffer[], ULONG32 * bufLen);
3154 // Allocate a buffer within the target and return the range. Throws on error.
3155 TargetBuffer GetRemoteBuffer(ULONG cbBuffer); // throws
3157 // Same as above except also copy-in the contents of a RS buffer using WriteProcessMemory
3158 HRESULT GetAndWriteRemoteBuffer(CordbAppDomain *pDomain, unsigned int bufferSize, const void *bufferFrom, void **ppBuffer);
3161 * This will release a previously allocated left side buffer.
3162 * Often they are deallocated by the LS itself.
3164 HRESULT ReleaseRemoteBuffer(void **ppBuffer);
3167 void TargetConsistencyCheck(bool fExpression);
3169 // Activate interop-debugging, after the process has initially been Init()
3170 void EnableInteropDebugging();
3173 void DeleteQueuedEvents();
3174 void CleanupHalfBakedLeftSide();
3175 void Terminating(BOOL fDetach);
3177 CordbThread * TryLookupThread(VMPTR_Thread vmThread);
3178 CordbThread * TryLookupOrCreateThreadByVolatileOSId(DWORD dwThreadId);
3179 CordbThread * TryLookupThreadByVolatileOSId(DWORD dwThreadId);
3180 CordbThread * LookupOrCreateThread(VMPTR_Thread vmThread);
3182 void QueueManagedAttachIfNeeded();
3183 void QueueManagedAttachIfNeededWorker();
3184 HRESULT QueueManagedAttach();
3188 // Flush for when the process is running.
3189 void FlushProcessRunning();
3194 BOOL HijackThreadForUnhandledExceptionIfNeeded(DWORD dwThreadId);
3196 // Filter a CLR notification (subset of exceptions).
3197 void FilterClrNotification(
3198 DebuggerIPCEvent * pManagedEvent,
3199 RSLockHolder * pLockHolder,
3200 ICorDebugManagedCallback * pCallback);
3202 // Wrapper to invoke IClrDataTarget4::ContinueStatusChanged
3203 void ContinueStatusChanged(DWORD dwThreadId, CORDB_CONTINUE_STATUS dwContinueStatus);
3206 // Request a synchronization to occur after a debug event is dispatched.
3207 void RequestSyncAtEvent();
3210 // Basic managed event plumbing
3213 // This is called on the first IPC event from the debuggee. It initializes state.
3214 void FinishInitializeIPCChannel();
3215 void FinishInitializeIPCChannelWorker();
3217 // This is called on each IPC event from the debuggee.
3218 void HandleRCEvent(DebuggerIPCEvent * pManagedEvent, RSLockHolder * pLockHolder, ICorDebugManagedCallback * pCallback);
3220 // Queue the RC event.
3221 void QueueRCEvent(DebuggerIPCEvent * pManagedEvent);
3223 // This marshals a managed debug event from the
3224 void MarshalManagedEvent(DebuggerIPCEvent * pManagedEvent);
3226 // This copies a managed debug event from the IPC block and to pManagedEvent.
3227 // The event still needs to be marshalled.
3228 void CopyRCEventFromIPCBlock(DebuggerIPCEvent * pManagedEvent);
3230 // This copies a managed debug event out of the Native-Debug event envelope.
3231 // The event still needs to be marshalled.
3232 bool CopyManagedEventFromTarget(const EXCEPTION_RECORD * pRecord, DebuggerIPCEvent * pLocalManagedEvent);
3234 // Helper for Filter() to verify parameters and return a type-safe exception record.
3235 const EXCEPTION_RECORD * ValidateExceptionRecord(
3236 const BYTE pRawRecord[],
3238 CorDebugRecordFormat format);
3240 // Helper to read a structure from the target.
3241 template<typename T>
3242 HRESULT SafeReadStruct(CORDB_ADDRESS pRemotePtr, T* pLocalBuffer);
3244 // Helper to write a structure into the target.
3245 template<typename T>
3246 HRESULT SafeWriteStruct(CORDB_ADDRESS pRemotePtr, const T* pLocalBuffer);
3248 // Reads a buffer from the target
3249 HRESULT SafeReadBuffer(TargetBuffer tb, BYTE * pLocalBuffer, BOOL throwOnError = TRUE);
3251 // Writes a buffer to the target
3252 void SafeWriteBuffer(TargetBuffer tb, const BYTE * pLocalBuffer);
3254 #if defined(FEATURE_INTEROP_DEBUGGING)
3255 void DuplicateHandleToLocalProcess(HANDLE * pLocalHandle, RemoteHANDLE * pRemoteHandle);
3256 #endif // FEATURE_INTEROP_DEBUGGING
3258 bool IsThreadSuspendedOrHijacked(ICorDebugThread * pICorDebugThread);
3260 // Helper to get PID internally.
3263 HRESULT GetRuntimeOffsets();
3265 // Are we blocked waiting fo ran OOB event to be continue?
3266 bool IsWaitingForOOBEvent()
3268 #ifdef FEATURE_INTEROP_DEBUGGING
3269 return m_outOfBandEventQueue != NULL;
3271 // If no interop, then we're never waiting for an OOB event.
3277 // Shim callbacks to simulate fake attach events.
3281 // Callback for Shim to get the assemblies in load order
3282 void GetAssembliesInLoadOrder(
3283 ICorDebugAppDomain * pAppDomain,
3284 RSExtSmartPtr<ICorDebugAssembly>* pAssemblies,
3285 ULONG countAssemblies);
3287 // Callback for Shim to get the modules in load order
3288 void GetModulesInLoadOrder(
3289 ICorDebugAssembly * pAssembly,
3290 RSExtSmartPtr<ICorDebugModule>* pModules,
3291 ULONG countModules);
3293 // Functions to queue fake Connection events on attach.
3294 static void CountConnectionsCallback(DWORD id, LPCWSTR pName, void * pUserData);
3295 static void EnumerateConnectionsCallback(DWORD id, LPCWSTR pName, void * pUserData);
3296 void QueueFakeConnectionEvents();
3300 void DispatchRCEvent();
3302 // Dispatch a single event via the callbacks.
3303 void RawDispatchEvent(
3304 DebuggerIPCEvent * pEvent,
3305 RSLockHolder * pLockHolder,
3306 ICorDebugManagedCallback * pCallback1,
3307 ICorDebugManagedCallback2 * pCallback2,
3308 ICorDebugManagedCallback3 * pCallback3);
3310 void MarkAllThreadsDirty();
3312 bool CheckIfLSExited();
3316 // Lock Hierarchy - shouldn't have List lock when taking/release the process lock.
3318 m_processMutex.Lock();
3319 LOG((LF_CORDB, LL_EVERYTHING, "P::Lock enter, this=0x%p\n", this));
3324 // Lock Hierarchy - shouldn't have List lock when taking/releasing the process lock.
3326 LOG((LF_CORDB, LL_EVERYTHING, "P::Lock leave, this=0x%p\n", this));
3327 m_processMutex.Unlock();
3331 bool ThreadHoldsProcessLock()
3333 return m_processMutex.HasLock();
3337 // Expose the process lock.
3338 // This is the main lock in V3.
3339 RSLock * GetProcessLock()
3341 return &m_processMutex;
3345 // @dbgtodo synchronization - the SG lock goes away in V3.
3346 // Expose the stop-go lock b/c varios Cordb objects in our process tree may need to take it.
3347 RSLock * GetStopGoLock()
3349 return &m_StopGoLock;
3353 void UnrecoverableError(HRESULT errorHR,
3354 unsigned int errorCode,
3355 const char *errorFile,
3356 unsigned int errorLine);
3357 HRESULT CheckForUnrecoverableError();
3358 void VerifyControlBlock();
3360 // The implementation of EnumerateThreads without the public API error checks
3361 VOID InternalEnumerateThreads(RSInitHolder<CordbHashTableEnum> * ppThreads);
3363 //-----------------------------------------------------------
3364 // Convenience routines
3365 //-----------------------------------------------------------
3367 // Is it safe to send events to the LS?
3368 bool IsSafeToSendEvents() { return !m_unrecoverableError && !m_terminated && !m_detached; }
3370 bool IsWin32EventThread();
3372 void HandleSyncCompleteRecieved();
3374 // Send a truly asynchronous IPC event.
3375 void SendAsyncIPCEvent(DebuggerIPCEventType t);
3377 HRESULT SendIPCEvent(DebuggerIPCEvent *event, SIZE_T eventSize)
3379 // @dbgtodo - eventually remove this when all IPC events are gone.
3380 // In V3 paths, we can't send IPC events.
3381 if (GetShim() == NULL)
3383 STRESS_LOG1(LF_CORDB, LL_INFO1000, "!! Can't send IPC event in V3. %s", IPCENames::GetName(event->type));
3386 _ASSERTE(m_cordb != NULL);
3387 return (m_cordb->SendIPCEvent(this, event, eventSize));
3390 void InitAsyncIPCEvent(DebuggerIPCEvent *ipce,
3391 DebuggerIPCEventType type,
3392 VMPTR_AppDomain vmAppDomain)
3394 // Async events only allowed for the following:
3395 _ASSERTE(type == DB_IPCE_ATTACHING);
3397 InitIPCEvent(ipce, type, false, vmAppDomain);
3398 ipce->asyncSend = true;
3401 void InitIPCEvent(DebuggerIPCEvent *ipce,
3402 DebuggerIPCEventType type,
3404 VMPTR_AppDomain vmAppDomain
3407 // zero out the event in case we try and use any uninitialized fields
3408 memset( ipce, 0, sizeof(DebuggerIPCEvent) );
3410 _ASSERTE((!vmAppDomain.IsNull()) ||
3411 type == DB_IPCE_GET_GCHANDLE_INFO ||
3412 type == DB_IPCE_ENABLE_LOG_MESSAGES ||
3413 type == DB_IPCE_MODIFY_LOGSWITCH ||
3414 type == DB_IPCE_ASYNC_BREAK ||
3415 type == DB_IPCE_CONTINUE ||
3416 type == DB_IPCE_GET_BUFFER ||
3417 type == DB_IPCE_RELEASE_BUFFER ||
3418 type == DB_IPCE_IS_TRANSITION_STUB ||
3419 type == DB_IPCE_ATTACHING ||
3420 type == DB_IPCE_APPLY_CHANGES ||
3421 type == DB_IPCE_CONTROL_C_EVENT_RESULT ||
3422 type == DB_IPCE_SET_REFERENCE ||
3423 type == DB_IPCE_SET_ALL_DEBUG_STATE ||
3424 type == DB_IPCE_GET_THREAD_FOR_TASKID ||
3425 type == DB_IPCE_DETACH_FROM_PROCESS ||
3426 type == DB_IPCE_INTERCEPT_EXCEPTION ||
3427 type == DB_IPCE_GET_NGEN_COMPILER_FLAGS ||
3428 type == DB_IPCE_SET_NGEN_COMPILER_FLAGS ||
3429 type == DB_IPCE_SET_VALUE_CLASS ||
3430 type == DB_IPCE_NETCF_HOST_CONTROL_PAUSE ||
3431 type == DB_IPCE_NETCF_HOST_CONTROL_RESUME);
3435 ipce->processId = 0;
3436 ipce->vmAppDomain = vmAppDomain;
3437 ipce->vmThread = VMPTR_Thread::NullPtr();
3438 ipce->replyRequired = twoWay;
3439 ipce->asyncSend = false;
3443 // Looks up a previously constructed CordbClass instance without creating. May return NULL if the
3444 // CordbClass instance doesn't exist.
3445 CordbClass * LookupClass(ICorDebugAppDomain * pAppDomain, VMPTR_DomainFile vmDomainFile, mdTypeDef classToken);
3447 CordbModule * LookupOrCreateModule(VMPTR_DomainFile vmDomainFile);
3449 #ifdef FEATURE_INTEROP_DEBUGGING
3450 CordbUnmanagedThread *GetUnmanagedThread(DWORD dwThreadId)
3452 _ASSERTE(ThreadHoldsProcessLock());
3453 return m_unmanagedThreads.GetBase(dwThreadId);
3455 #endif // FEATURE_INTEROP_DEBUGGING
3458 * This will cleanup the patch table, releasing memory,etc.
3460 void ClearPatchTable();
3463 * This will grab the patch table from the left side & go through
3464 * it to gather info needed for faster access. If address,size,buffer
3465 * are passed in, while going through the table we'll undo patches
3466 * in buffer at the same time
3468 HRESULT RefreshPatchTable(CORDB_ADDRESS address = NULL, SIZE_T size = NULL, BYTE buffer[] = NULL);
3470 // Find if a patch exists at a given address.
3471 HRESULT FindPatchByAddress(CORDB_ADDRESS address, bool *patchFound, bool *patchIsUnmanaged);
3480 * Once we've called RefreshPatchTable to get the patch table,
3481 * this routine will iterate through the patches & either apply
3482 * or unapply the patches to buffer. AB_READ => Replaces patches
3483 * in buffer with the original opcode, AB_WRTE => replace opcode
3484 * with breakpoint instruction, caller is responsible for
3485 * updating the patchtable back to the left side.
3487 * <TODO>@todo Perf Instead of a copy, undo the changes
3488 * Since the 'buffer' arg is an [in] param, we're not supposed to
3489 * change it. If we do, we'll allocate & copy it to bufferCopy
3490 * (we'll also set *pbUpdatePatchTable to true), otherwise we
3491 * don't manipuldate bufferCopy (so passing a NULL in for
3492 * reading is fine).</TODO>
3494 HRESULT AdjustBuffer(CORDB_ADDRESS address,
3499 BOOL *pbUpdatePatchTable = NULL);
3502 * AdjustBuffer, above, doesn't actually update the local patch table
3503 * if asked to do a write. It stores the changes alongside the table,
3504 * and this will cause the changes to be written to the table (for
3505 * a range of left-side addresses
3507 void CommitBufferAdjustments(CORDB_ADDRESS start,
3511 * Clear the stored changes, or they'll sit there until we
3512 * accidentally commit them
3514 void ClearBufferAdjustments();
3519 //-----------------------------------------------------------
3520 // Accessors for key synchronization fields.
3521 //-----------------------------------------------------------
3523 // If CAD is NULL, returns true if all appdomains (ie, the entire process)
3524 // is synchronized. Otherwise, returns true if the specified appdomain is
3526 bool GetSynchronized();
3527 void SetSynchronized(bool fSynch);
3529 void IncStopCount();
3530 void DecStopCount();
3532 // Gets the exact stop count. You need the Proecss lock for this.
3535 // Just gets whether we're stopped or not (m_stopped > 0).
3536 // You only need the StopGo lock for this.
3537 // This is biases towards returning false.
3540 bool GetSyncCompleteRecv();
3541 void SetSyncCompleteRecv(bool fSyncRecv);
3544 // Cordbg may not always continue during a callback; but we really shouldn't do meaningful
3545 // work after a callback has returned yet before they've called continue. Thus we may need
3546 // to remember some state at the time of dispatch so that we do stuff at continue.
3547 // Only example here is neutering... we'd like to Neuter an object X after the ExitX callback,
3548 // but we can't neuter it until Continue. So remember X when we dispatch, and neuter this at continue.
3549 // Use a smart ptr to keep it alive until we neuter it.
3551 // Add objects to various neuter lists.
3552 // NeuterOnContinue is for all objects that can be neutered once we continue.
3553 // NeuterOnExit is for all objects that can survive continues (but are neutered on process shutdown).
3554 // If an object's external ref count goes to 0, it gets promoted to the NeuterOnContinue list.
3555 void AddToNeuterOnExitList(CordbBase *pObject);
3556 void AddToNeuterOnContinueList(CordbBase *pObject);
3558 NeuterList * GetContinueNeuterList() { return &m_ContinueNeuterList; }
3559 NeuterList * GetExitNeuterList() { return &m_ExitNeuterList; }
3561 void AddToLeftSideResourceCleanupList(CordbBase * pObject);
3563 // Routines to read and write thread context records between the processes safely.
3564 HRESULT SafeReadThreadContext(LSPTR_CONTEXT pRemoteContext, DT_CONTEXT * pCtx);
3565 HRESULT SafeWriteThreadContext(LSPTR_CONTEXT pRemoteContext, const DT_CONTEXT * pCtx);
3567 #ifdef FEATURE_INTEROP_DEBUGGING
3568 // Record a win32 event for debugging purposes.
3569 void DebugRecordWin32Event(const DEBUG_EVENT * pEvent, CordbUnmanagedThread * pUThread);
3570 #endif // FEATURE_INTEROP_DEBUGGING
3572 //-----------------------------------------------------------
3574 //-----------------------------------------------------------
3576 // Get the DAC interface.
3577 IDacDbiInterface * GetDAC();
3579 // Get the data-target, which provides access to the debuggee.
3580 ICorDebugDataTarget * GetDataTarget();
3582 BOOL IsDacInitialized();
3584 void ForceDacFlush();
3587 #ifdef FEATURE_INTEROP_DEBUGGING
3588 // Deal with native debug events for the interop-debugging scenario.
3589 void HandleDebugEventForInteropDebugging(const DEBUG_EVENT * pEvent);
3591 void ResumeHijackedThreads();
3593 //@todo - We should try to make these all private
3594 CordbUnmanagedThread *HandleUnmanagedCreateThread(DWORD dwThreadId, HANDLE hThread, void *lpThreadLocalBase);
3596 HRESULT ContinueOOB();
3597 void QueueUnmanagedEvent(CordbUnmanagedThread *pUThread, const DEBUG_EVENT *pEvent);
3598 void DequeueUnmanagedEvent(CordbUnmanagedThread *pUThread);
3599 void QueueOOBUnmanagedEvent(CordbUnmanagedThread *pUThread, const DEBUG_EVENT *pEvent);
3600 void DequeueOOBUnmanagedEvent(CordbUnmanagedThread *pUThread);
3601 void DispatchUnmanagedInBandEvent();
3602 void DispatchUnmanagedOOBEvent();
3603 bool ExceptionIsFlare(DWORD exceptionCode, const void *exceptionAddress);
3605 bool IsSpecialStackOverflowCase(CordbUnmanagedThread *pUThread, const DEBUG_EVENT *pEvent);
3607 HRESULT SuspendUnmanagedThreads();
3608 HRESULT ResumeUnmanagedThreads();
3610 HRESULT HijackIBEvent(CordbUnmanagedEvent * pUnmanagedEvent);
3612 BOOL HasUndispatchedNativeEvents();
3613 BOOL HasUserUncontinuedNativeEvents();
3614 #endif // FEATURE_INTEROP_DEBUGGING
3616 HRESULT StartSyncFromWin32Stop(BOOL * pfAsyncBreakSent);
3619 // For interop attach, we first do native, and then once Cordbg continues from
3620 // the loader-bp, we kick off the managed attach. This field remembers that
3621 // whether we need the managed attach.
3622 // @dbgtodo managed pipeline - hoist to shim.
3623 bool m_fDoDelayedManagedAttached;
3627 // Table of CordbEval objects that we've sent over to the LS.
3628 // This is synced via the process lock.
3629 RsPtrTable<CordbEval> m_EvalTable;
3631 void PrepopulateThreadsOrThrow();
3633 // Lookup or create an appdomain.
3634 CordbAppDomain * LookupOrCreateAppDomain(VMPTR_AppDomain vmAppDomain);
3636 // Get the shared app domain.
3637 CordbAppDomain * GetSharedAppDomain();
3639 // Get metadata dispenser.
3640 IMetaDataDispenserEx * GetDispenser();
3642 // Sets a bitfield reflecting the managed debugging state at the time of
3644 HRESULT GetAttachStateFlags(CLR_DEBUGGING_PROCESS_FLAGS *pFlags);
3646 HRESULT GetTypeForObject(CORDB_ADDRESS obj, CordbType **ppType, CordbAppDomain **pAppDomain = NULL);
3648 WriteableMetadataUpdateMode GetWriteableMetadataUpdateMode() { return m_writableMetadataUpdateMode; }
3652 // Assert that vmAppDomainDeleted doesn't show up in dac enumerations
3653 void DbgAssertAppDomainDeleted(VMPTR_AppDomain vmAppDomainDeleted);
3655 // Callback helper for DbgAssertAppDomainDeleted.
3656 static void DbgAssertAppDomainDeletedCallback(VMPTR_AppDomain vmAppDomain, void * pUserData);
3659 static void ThreadEnumerationCallback(VMPTR_Thread vmThread, void * pUserData);
3662 // Callback for AppDomain enumeration
3663 static void AppDomainEnumerationCallback(VMPTR_AppDomain vmAppDomain, void * pUserData);
3665 // Helper to create a new CordbAppDomain around the vmptr and cache it
3666 CordbAppDomain * CacheAppDomain(VMPTR_AppDomain vmAppDomain);
3668 // Helper to traverse Appdomains in target and build up our cache.
3669 void PrepopulateAppDomainsOrThrow();
3672 void ProcessFirstLogMessage (DebuggerIPCEvent *event);
3673 void ProcessContinuedLogMessage (DebuggerIPCEvent *event);
3675 void CloseIPCHandles();
3676 void UpdateThreadsForAdUnload( CordbAppDomain* pAppDomain );
3678 #ifdef FEATURE_INTEROP_DEBUGGING
3679 // Each win32 debug event needs to be triaged to get a Reaction.
3680 Reaction TriageBreakpoint(CordbUnmanagedThread * pUnmanagedThread, const DEBUG_EVENT * pEvent);
3681 Reaction TriageSyncComplete();
3682 Reaction Triage1stChanceNonSpecial(CordbUnmanagedThread * pUnmanagedThread, const DEBUG_EVENT * pEvent);
3683 Reaction TriageExcep1stChanceAndInit(CordbUnmanagedThread * pUnmanagedThread, const DEBUG_EVENT * pEvent);
3684 Reaction TriageExcep2ndChanceAndInit(CordbUnmanagedThread * pUnmanagedThread, const DEBUG_EVENT * pEvent);
3685 Reaction TriageWin32DebugEvent(CordbUnmanagedThread * pUnmanagedThread, const DEBUG_EVENT * pEvent);
3686 #endif // FEATURE_INTEROP_DEBUGGING
3688 //-----------------------------------------------------------
3690 //-----------------------------------------------------------
3693 RSSmartPtr<Cordb> m_cordb;
3696 // OS process handle to live process.
3697 // @dbgtodo - , Move this into the Shim. This should only be needed in the live-process
3698 // case. Get rid of this since it breaks the data-target abstraction.
3699 // For Mac debugging, this handle is of course not the real process handle. This is just a handle to
3700 // wait on for process termination.
3704 // Wrapper to get the OS process handle. This is unsafe because it breaks the data-target abstraction.
3705 // The only things that need this should be calls to DuplicateHandle, and some shimming work.
3706 HANDLE UnsafeGetProcessHandle()
3711 // Set when code:CordbProcess::Detach is called.
3712 // Public APIs can check this and return CORDBG_E_PROCESS_DETACHED.
3713 // @dbgtodo managed pipeline - really could merge this with neuter.
3716 // True if we code:CordbProcess::Stop is called before the managed CreateProcess event.
3717 // In this case, m_initialized is false, and we can't send an AsyncBreak event to the LS.
3718 // (since the LS isn't going to send a SyncComplete event back since the CLR isn't loaded/ready).
3719 // @dbgtodo managed pipeline - move into shim, along with Stop/Continue.
3720 bool m_uninitializedStop;
3723 // m_exiting is true if we know the LS is starting to exit (if the
3724 // RS is telling the LS to exit) or if we know the LS has already exited.
3728 // m_terminated can only be set to true if we know 100% the LS has exited (ie, somebody
3729 // waited on the LS process handle).
3732 bool m_unrecoverableError;
3734 bool m_specialDeferment;
3735 bool m_helperThreadDead; // flag used for interop
3737 // This tracks if the loader breakpoint has been received during interop-debugging.
3738 // The Loader Breakpoint is an breakpoint event raised by the OS once the debugger is attached.
3739 // It comes in both Attach and Launch scenarios.
3740 // This is also used in fake-native debugging scenarios.
3741 bool m_loaderBPReceived;
3746 // MetaData dispenser.
3747 RSExtSmartPtr<IMetaDataDispenserEx> m_pMetaDispenser;
3750 // Count of the number of outstanding CordbEvals in the process.
3752 LONG m_cOutstandingEvals;
3754 // Number of oustanding code:CordbHandleValue objects containing
3755 // Left-side resources. This can be used to tell if ICorDebug needs to
3756 // cleanup gc handles.
3757 LONG m_cOutstandingHandles;
3759 // Pointer to the CordbModule instance that can currently change the Jit flags.
3760 // There can be at most one of these. It will represent a module that has just been loaded, before the
3761 // Continue is sent. See code:CordbProcess::RawDispatchEvent and code:CordbProcess::ContinueInternal.
3762 CordbModule * m_pModuleThatCanChangeJitFlags;
3765 LONG OutstandingEvalCount()
3767 return m_cOutstandingEvals;
3770 void IncrementOutstandingEvalCount()
3772 InterlockedIncrement(&m_cOutstandingEvals);
3775 void DecrementOutstandingEvalCount()
3777 InterlockedDecrement(&m_cOutstandingEvals);
3780 LONG OutstandingHandles();
3781 void IncrementOutstandingHandles();
3782 void DecrementOutstandingHandles();
3785 // Is it OK to detach at this time
3787 HRESULT IsReadyForDetach();
3791 // This is a target pointer that uniquely identifies the runtime in the target.
3792 // This lets ICD discriminate between multiple CLRs within a single process.
3793 // On windows, this is the base-address of mscorwks.dll in the target.
3794 // If this is 0, then we have V2 semantics where there was only 1 CLR in the target.
3795 // In that case, we can lazily initialize it in code:CordbProcess::CopyManagedEventFromTarget.
3796 // This is just used for backwards compat.
3797 CORDB_ADDRESS m_clrInstanceId;
3799 // List of things that get neutered on process exit and Continue respectively.
3800 NeuterList m_ExitNeuterList;
3801 NeuterList m_ContinueNeuterList;
3803 // List of objects that hold resources into the left-side.
3804 // This is currently for funceval, which cleans up resources in code:CordbEval::SendCleanup.
3805 // @dbgtodo - , (func-eval feature crew): we can get rid of this
3806 // list if we make func-eval not hold resources after it's complete.
3807 LeftSideResourceCleanupList m_LeftSideResourceCleanupList;
3809 // m_stopCount, m_synchronized, & m_syncCompleteReceived are key fields describing
3810 // the processes' sync status.
3813 // m_synchronized is the Debugger's view of SyncStatus. It will go high & low for each
3814 // callback. Continue() will set this to false.
3815 // This flag is true roughly from the time that we've dispatched a managed callback
3816 // until the time that it's continued.
3817 bool m_synchronized;
3819 // m_syncCompleteReceived tells us if the runtime is _actually_ sychronized. It goes
3820 // high once we get a SyncComplete, and it goes low once we actually send the continue.
3821 // This is always set by the thread that receives the sync-complete. In interop, that's the w32et.
3822 // Thus this is the most accurate indication of wether the Debuggee is _actually_ synchronized or not.
3823 bool m_syncCompleteReceived;
3826 // Back pointer to Shim process. This is used for hooks back into the shim.
3827 // If this is Non-null, then we're emulating the V2 case. If this is NULL, then it's the real V3 pipeline.
3828 RSExtSmartPtr<ShimProcess> m_pShim;
3830 CordbSafeHashTable<CordbThread> m_userThreads;
3833 ShimProcess* GetShim();
3838 void BuildThreadEnum(CordbBase * pOwnerObj, NeuterList * pOwnerList, RSInitHolder<CordbHashTableEnum> * pHolder);
3840 #ifdef FEATURE_INTEROP_DEBUGGING
3841 // List of unmanaged threads. This is only populated for interop-debugging.
3842 CordbSafeHashTable<CordbUnmanagedThread> m_unmanagedThreads;
3843 #endif // FEATURE_INTEROP_DEBUGGING
3845 CordbSafeHashTable<CordbAppDomain> m_appDomains;
3847 CordbAppDomain * m_sharedAppDomain;
3849 // Since a stepper can begin in one appdomain, and complete in another,
3850 // we put the hashtable here, rather than on specific appdomains.
3851 CordbSafeHashTable<CordbStepper> m_steppers;
3853 // Used to figure out if we have to refresh any reference objects
3854 // on the left side. Gets incremented each time a continue is called, or
3855 // global debugee state is modified in some other way.
3856 UINT m_continueCounter;
3858 // Used to track whether the DAC cache has been flushed.
3859 // We use this information to determine whether CordbStackWalk instances need to
3861 UINT m_flushCounter;
3863 // The DCB is essentially a buffer area used to temporarily hold information read from the debugger
3864 // control block residing on the LS helper thread. We make no assumptions about the validity of this
3865 // information over time, so before using a value from it on the RS, we will always update this buffer
3866 // with a call to UpdateRightSideDCB. This uses a ReadProcessMemory to get the current information from
3868 DebuggerIPCControlBlock * GetDCB() {return ((m_pEventChannel == NULL) ? NULL : m_pEventChannel->GetDCB());}
3871 DebuggerIPCRuntimeOffsets m_runtimeOffsets;
3872 HANDLE m_leftSideEventAvailable;
3873 HANDLE m_leftSideEventRead;
3874 #if defined(FEATURE_INTEROP_DEBUGGING)
3875 HANDLE m_leftSideUnmanagedWaitEvent;
3876 #endif // FEATURE_INTEROP_DEBUGGING
3879 // This becomes true when the RS receives its first managed event.
3880 // This goes false in shutdown cases.
3881 // If this is true, we can assume:
3882 // - the CLR is loaded.
3883 // - the IPC block is opened and initialized.
3884 // - DAC is initialized (see code:CordbProcess::IsDacInitialized)
3886 // If this is false, we can assume:
3887 // - the CLR may not be loaded into the target process.
3888 // - We can't send IPC events to the LS (because we can't expect a response)
3890 // Many APIs can check this bit and return CORDBG_E_NOTREADY if it's false.
3894 void * m_pDBGLastIPCEventType;
3897 bool m_stopRequested;
3898 HANDLE m_stopWaitEvent;
3899 RSLock m_processMutex;
3901 #ifdef FEATURE_INTEROP_DEBUGGING
3902 // The number of threads which are IsFirstChanceHijacked
3903 DWORD m_cFirstChanceHijackedThreads;
3905 CordbUnmanagedEvent *m_unmanagedEventQueue;
3906 CordbUnmanagedEvent *m_lastQueuedUnmanagedEvent;
3907 CordbUnmanagedEvent *m_lastQueuedOOBEvent;
3908 CordbUnmanagedEvent *m_outOfBandEventQueue;
3910 CordbUnmanagedEvent *m_lastDispatchedIBEvent;
3911 bool m_dispatchingUnmanagedEvent;
3912 bool m_dispatchingOOBEvent;
3913 bool m_doRealContinueAfterOOBBlock;
3917 PS_WIN32_STOPPED = 0x0001,
3918 PS_HIJACKS_IN_PLACE = 0x0002,
3919 PS_SOME_THREADS_SUSPENDED = 0x0004,
3920 PS_WIN32_ATTACHED = 0x0008,
3921 PS_WIN32_OUTOFBAND_STOPPED = 0x0010,
3924 unsigned int m_state;
3925 #endif // FEATURE_INTEROP_DEBUGGING
3927 // True if we're interop-debugging, else false.
3928 bool IsInteropDebugging();
3930 DWORD m_helperThreadId; // helper thread ID calculated from sniffing from UM thread-create events.
3932 // Is the given thread id a helper thread (real or worker?)
3933 bool IsHelperThreadWorked(DWORD tid);
3936 // We cache the LS patch table on the RS.
3939 // The array of entries. (The patchtable is a hash implemented as a single-array)
3940 // This array includes empty entries.
3941 // There is an auxillary bucket structure used to map hash codes to array indices.
3942 // We traverse the array, and we recognize an empty slot
3943 // if DebuggerControllerPatch::opcode == 0.
3944 // If we haven't gotten the table, then m_pPatchTable is NULL
3945 BYTE* m_pPatchTable;
3947 // The number of entries (both used & unused) in m_pPatchTable.
3950 // so we know where to write the changes patchtable back to
3951 // This has m_cPatch elements.
3954 // Cached value of iNext entries such that:
3955 // m_rgNextPatch[i] = ((DebuggerControllerPatch*)m_pPatchTable)[i]->iNext;
3956 // where 0 <= i < m_cPatch
3957 // This provides a linked list (via indices) to traverse the used entries of m_pPatchTable.
3958 // This has m_cPatch elements.
3959 ULONG *m_rgNextPatch;
3961 // This has m_cPatch elements.
3962 PRD_TYPE *m_rgUncommitedOpcode;
3964 // CORDB_ADDRESS's are UINT_PTR's (64 bit under _WIN64, 32 bit otherwise)
3965 #if defined(DBG_TARGET_WIN64)
3966 #define MAX_ADDRESS (_UI64_MAX)
3968 #define MAX_ADDRESS (ULONG_MAX)
3970 #define MIN_ADDRESS (0x0)
3971 CORDB_ADDRESS m_minPatchAddr; //smallest patch in table
3972 CORDB_ADDRESS m_maxPatchAddr;
3974 // <TODO>@todo port : if slots of CHashTable change, so should these</TODO>
3975 #define DPT_TERMINATING_INDEX (UINT32_MAX)
3976 // Index into m_pPatchTable of the first patch (first used entry).
3977 ULONG m_iFirstPatch;
3979 // Initializes the DAC
3982 // copy new data from LS DCB to RS buffer
3983 void UpdateRightSideDCB();
3985 // copy new data from RS DCB buffer to LS DCB
3986 void UpdateLeftSideDCBField(void * rsFieldAddr, SIZE_T size);
3988 // allocate and initialize the RS DCB buffer
3989 void GetEventBlock(BOOL * pfBlockExists);
3991 IEventChannel * GetEventChannel();
3993 bool SupportsVersion(CorDebugInterfaceVersion featureVersion);
3995 void StartEventDispatch(DebuggerIPCEventType event);
3996 void FinishEventDispatch();
3997 bool AreDispatchingEvent();
3999 HANDLE GetHelperThreadHandle() { return m_hHelperThread; }
4001 CordbAppDomain* GetDefaultAppDomain() { return m_pDefaultAppDomain; }
4003 #ifdef FEATURE_INTEROP_DEBUGGING
4004 // Lookup if there's a native BP at the given address. Return NULL not found.
4005 NativePatch * GetNativePatch(const void * pAddress);
4006 #endif // FEATURE_INTEROP_DEBUGGING
4008 bool IsBreakOpcodeAtAddress(const void * address);
4012 // handle to helper thread. Used for managed debugging.
4013 // Initialized only after we get the tid from the DCB.
4014 HANDLE m_hHelperThread;
4016 DebuggerIPCEventType m_dispatchedEvent; // what event are we currently dispatching?
4018 RSLock m_StopGoLock;
4020 // Each process has exactly one Default AppDomain
4021 // @dbgtodo appdomain : We should try and simplify things by removing this.
4022 // At the moment it's necessary for CordbProcess::UpdateThreadsForAdUnload.
4023 CordbAppDomain* m_pDefaultAppDomain; // owned by m_appDomains
4025 #ifdef FEATURE_INTEROP_DEBUGGING
4027 CordbUnmanagedThread * GetUnmanagedThreadFromEvent(const DEBUG_EVENT * pEvent);
4028 #endif // FEATURE_INTEROP_DEBUGGING
4030 // Ensure we have a CLR Instance ID to debug
4031 HRESULT EnsureClrInstanceIdSet();
4033 #ifdef FEATURE_INTEROP_DEBUGGING
4034 // // The full debug event is too large, so we just remember the important stuff.
4035 struct MiniDebugEvent
4037 BYTE code; // event code from the debug event
4038 CordbUnmanagedThread * pUThread; // unmanaged thread this was on.
4039 // @todo - we should have some misc data.
4043 void * pAddress; // address of an exception
4047 void * pBaseAddress; // for module load & unload
4052 // Group fields that are just used for debug support here.
4053 // Some are included even in retail builds to help debug retail failures.
4056 // For debugging, we keep a rolling queue of the last N Win32 debug events.
4057 MiniDebugEvent m_DebugEventQueue[DEBUG_EVENTQUEUE_SIZE];
4058 int m_DebugEventQueueIdx;
4059 int m_TotalNativeEvents;
4061 // Breakdown of different types of native events
4067 CUnorderedArray<NativePatch, 10> m_NativePatchList;
4068 #endif // FEATURE_INTEROP_DEBUGGING
4074 // Try to initalize DAC, may fail
4075 BOOL TryInitializeDac();
4077 // Expect DAC initialize to succeed.
4078 void InitializeDac();
4081 void CreateDacDbiInterface();
4087 HModuleHolder m_hDacModule;
4088 RSExtSmartPtr<ICorDebugDataTarget> m_pDACDataTarget;
4090 // The mutable version of the data target, or null if read-only
4091 RSExtSmartPtr<ICorDebugMutableDataTarget> m_pMutableDataTarget;
4093 RSExtSmartPtr<ICorDebugMetaDataLocator> m_pMetaDataLocator;
4095 IDacDbiInterface * m_pDacPrimitives;
4097 IEventChannel * m_pEventChannel;
4099 // If true, then we'll ASSERT if we detect the target is corrupt or inconsistent
4100 // This switch is for diagnostics purposes only and should always be false in retail builds.
4101 bool m_fAssertOnTargetInconsistency;
4103 // When a successful attempt to read runtime offsets from LS occurs, this flag is set.
4104 bool m_runtimeOffsetsInitialized;
4106 // controls how metadata updated in the target is handled
4107 WriteableMetadataUpdateMode m_writableMetadataUpdateMode;
4110 // Some IMDArocess APIs are supported as interop-only.
4111 #define FAIL_IF_MANAGED_ONLY(pProcess) \
4112 { CordbProcess * __Proc = pProcess; if (!__Proc->IsInteropDebugging()) return CORDBG_E_MUST_BE_INTEROP_DEBUGGING; }
4115 /* ------------------------------------------------------------------------- *
4117 * ------------------------------------------------------------------------- */
4119 class CordbModule : public CordbBase,
4120 public ICorDebugModule,
4121 public ICorDebugModule2,
4122 public ICorDebugModule3
4125 CordbModule(CordbProcess * process,
4126 VMPTR_Module vmModule,
4127 VMPTR_DomainFile vmDomainFile);
4129 virtual ~CordbModule();
4130 virtual void Neuter();
4132 using CordbBase::GetProcess;
4135 virtual const char * DbgGetName() { return "CordbModule"; }
4139 //-----------------------------------------------------------
4141 //-----------------------------------------------------------
4143 ULONG STDMETHODCALLTYPE AddRef()
4145 return (BaseAddRef());
4147 ULONG STDMETHODCALLTYPE Release()
4149 return (BaseRelease());
4151 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
4153 //-----------------------------------------------------------
4155 //-----------------------------------------------------------
4157 COM_METHOD GetProcess(ICorDebugProcess **ppProcess);
4158 COM_METHOD GetBaseAddress(CORDB_ADDRESS *pAddress);
4159 COM_METHOD GetAssembly(ICorDebugAssembly **ppAssembly);
4160 COM_METHOD GetName(ULONG32 cchName, ULONG32 *pcchName, __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[]);
4161 COM_METHOD EnableJITDebugging(BOOL bTrackJITInfo, BOOL bAllowJitOpts);
4162 COM_METHOD EnableClassLoadCallbacks(BOOL bClassLoadCallbacks);
4164 // Gets the latest version of a function given the methodDef token
4165 COM_METHOD GetFunctionFromToken(mdMethodDef methodDef,
4166 ICorDebugFunction **ppFunction);
4167 COM_METHOD GetFunctionFromRVA(CORDB_ADDRESS rva, ICorDebugFunction **ppFunction);
4168 COM_METHOD GetClassFromToken(mdTypeDef typeDef,
4169 ICorDebugClass **ppClass);
4170 COM_METHOD CreateBreakpoint(ICorDebugModuleBreakpoint **ppBreakpoint);
4172 // Not implemented - legacy
4173 COM_METHOD GetEditAndContinueSnapshot(
4174 ICorDebugEditAndContinueSnapshot **ppEditAndContinueSnapshot);
4176 COM_METHOD GetMetaDataInterface(REFIID riid, IUnknown **ppObj);
4177 COM_METHOD GetToken(mdModule *pToken);
4178 COM_METHOD IsDynamic(BOOL *pDynamic);
4179 COM_METHOD GetGlobalVariableValue(mdFieldDef fieldDef,
4180 ICorDebugValue **ppValue);
4181 COM_METHOD GetSize(ULONG32 *pcBytes);
4182 COM_METHOD IsInMemory(BOOL *pInMemory);
4184 //-----------------------------------------------------------
4186 //-----------------------------------------------------------
4187 COM_METHOD SetJMCStatus(
4192 // Applies an EnC edit to the module
4193 COM_METHOD ApplyChanges(
4199 // Resolve an assembly given an AssemblyRef token. Note that
4200 // this will not trigger the loading of assembly. If assembly is not yet loaded,
4201 // this will return an CORDBG_E_CANNOT_RESOLVE_ASSEMBLY error
4202 COM_METHOD ResolveAssembly(mdToken tkAssemblyRef,
4203 ICorDebugAssembly **ppAssembly);
4205 // Sets EnC and optimization flags
4206 COM_METHOD SetJITCompilerFlags(DWORD dwFlags);
4208 // Gets EnC and optimization flags
4209 COM_METHOD GetJITCompilerFlags(DWORD *pdwFlags);
4211 //-----------------------------------------------------------
4213 //-----------------------------------------------------------
4214 COM_METHOD CreateReaderForInMemorySymbols(REFIID riid,
4217 //-----------------------------------------------------------
4219 //-----------------------------------------------------------
4222 // Debug helper to ensure that module is no longer discoverable
4223 void DbgAssertModuleDeleted();
4226 // Internal help to get the "name" (filename or pretty name) of the module.
4227 HRESULT GetNameWorker(ULONG32 cchName, ULONG32 *pcchName, __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[]);
4229 // Marks that the module's metadata has become invalid and needs to be refetched.
4230 void RefreshMetaData();
4232 // Cache the current continue counter as the one that the LoadEvent is
4234 void SetLoadEventContinueMarker();
4236 // Return CORDBG_E_MUST_BE_IN_LOAD_MODULE if this module is not in its load callback.
4237 HRESULT EnsureModuleIsInLoadCallback();
4241 // Gets the latest version of the function for the methodDef, if any
4242 CordbFunction * LookupFunctionLatestVersion(mdMethodDef methodToken);
4244 // Gets the latest version of the function. Creates a new instance if none exists yet.
4245 CordbFunction* LookupOrCreateFunctionLatestVersion(mdMethodDef funcMetaDataToken);
4247 // Finds or creates a function for the first time (not for use on EnC if function doesn't exist yet)
4248 CordbFunction * LookupOrCreateFunction(mdMethodDef token, SIZE_T enCVersion);
4250 // Creates an CordbFunction instances for the first time (not for use on EnC)
4251 CordbFunction * CreateFunction(mdMethodDef token, SIZE_T enCVersion);
4253 // Creates a CordbFunction object to represent the specified EnC version
4254 HRESULT UpdateFunction(mdMethodDef token,
4255 SIZE_T newEnCVersion,
4256 CordbFunction** ppFunction);
4258 CordbClass* LookupClass(mdTypeDef classToken);
4259 HRESULT LookupOrCreateClass(mdTypeDef classToken, CordbClass** ppClass);
4260 HRESULT CreateClass(mdTypeDef classToken, CordbClass** ppClass);
4261 HRESULT LookupClassByToken(mdTypeDef token, CordbClass **ppClass);
4262 HRESULT ResolveTypeRef(mdTypeRef token, CordbClass **ppClass);
4263 HRESULT ResolveTypeRefOrDef(mdToken token, CordbClass **ppClass);
4265 // Sends the event to the left side to apply the changes to the debugee
4266 HRESULT ApplyChangesInternal(
4272 // Pulls new metadata if needed in order to ensure the availability of
4274 void UpdateMetaDataCacheIfNeeded(mdToken token);
4276 HRESULT InitPublicMetaDataFromFile(const WCHAR * pszFullPathName, DWORD dwOpenFlags, bool validateFileInfo);
4278 // Creates a CordbNativeCode (if it's not already created) and adds it to the
4279 // hash table of CordbNativeCodes belonging to the module.
4280 CordbNativeCode * LookupOrCreateNativeCode(mdMethodDef methodToken,
4281 VMPTR_MethodDesc methodDesc,
4282 CORDB_ADDRESS startAddress);
4285 // Set the metadata (both public and internal) for the module.
4286 void InitMetaData(TargetBuffer buffer, BOOL useFileMappingOptimization);
4288 // Checks if the given token is in the cached metadata
4289 BOOL CheckIfTokenInMetaData(mdToken token);
4291 // Update the public metadata given a buffer in the target.
4292 void UpdatePublicMetaDataFromRemote(TargetBuffer bufferRemoteMetaData);
4294 // Initialize just the public metadata by reading from an on-disk module
4295 HRESULT InitPublicMetaDataFromFile();
4296 // Initialize just the public metadata by reading new metadata from the buffer
4297 void InitPublicMetaData(TargetBuffer buffer);
4299 // Rebuild the internal metadata given the public one.
4300 void UpdateInternalMetaData();
4302 // Determines whether the on-disk metadata for this module is usable as the
4304 BOOL IsFileMetaDataValid();
4306 // Helper to copy metadata buffer from the Target to the host.
4307 void CopyRemoteMetaData(TargetBuffer buffer, CoTaskMemHolder<VOID> * pLocalBuffer);
4310 CordbAssembly * ResolveAssemblyInternal(mdToken tkAssemblyRef);
4314 //-----------------------------------------------------------
4315 // Convenience routines
4316 //-----------------------------------------------------------
4319 CordbAppDomain *GetAppDomain()
4321 return m_pAppDomain;
4324 CordbAssembly * GetCordbAssembly ();
4326 // Get the module filename, or NULL if none. Throws on error.
4327 const WCHAR * GetModulePath();
4329 const WCHAR * GetNGenImagePath();
4331 const VMPTR_DomainFile GetRuntimeDomainFile ()
4333 return m_vmDomainFile;
4336 const VMPTR_Module GetRuntimeModule()
4341 // Get symbol stream for in-memory modules.
4342 IDacDbiInterface::SymbolFormat GetInMemorySymbolStream(IStream ** ppStream);
4344 // accessor for PE file
4345 VMPTR_PEFile GetPEFile();
4348 IMetaDataImport * GetMetaDataImporter();
4350 // accessor for Internal MetaData importer.
4351 IMDInternalImport * GetInternalMD();
4353 //-----------------------------------------------------------
4355 //-----------------------------------------------------------
4358 CordbAssembly* m_pAssembly;
4359 CordbAppDomain* m_pAppDomain;
4360 CordbSafeHashTable<CordbClass> m_classes;
4362 // A collection, indexed by methodDef, of the latest version of functions in this module
4363 // The collection is filled lazily by LookupOrCreateFunction
4364 CordbSafeHashTable<CordbFunction> m_functions;
4366 // The real handle into the VM for a module. This is appdomain aware.
4367 // This is the primary VM counterpart for the CordbModule.
4368 VMPTR_DomainFile m_vmDomainFile;
4370 VMPTR_Module m_vmModule;
4383 // Base Address and size of this module in debuggee's process. Maybe null if unknown.
4384 TargetBuffer m_PEBuffer;
4386 BOOL m_fDynamic; // Dynamic modules can grow (like Reflection Emit)
4387 BOOL m_fInMemory; // In memory modules don't have file-backing.
4388 ILWinMDState m_isIlWinMD; // WinMD modules don't support all metadata interfaces
4390 // Indicates that the module must serialize its metadata in process as part of metadata
4391 // refresh. This is required for modules updated on the fly by the profiler
4392 BOOL m_fForceMetaDataSerialize;
4394 // Full path to module's image, if any. Empty if none, NULL if not yet set.
4395 StringCopyHolder m_strModulePath;
4397 // Full path to the ngen file. Empty if not ngenned, NULL if not yet set.
4398 // This isn't exposed publicly, but we may use it internally for loading metadata.
4399 StringCopyHolder m_strNGenImagePath;
4401 // "Global" class for this module. Global functions + vars exist in this class.
4402 RSSmartPtr<CordbClass> m_pClass;
4404 // Handle to PEFile, useful for metadata lookups.
4405 // this should always be non-null.
4406 VMPTR_PEFile m_vmPEFile;
4409 // Public metadata importer. This is lazily initialized and accessed from code:GetMetaDataImporter
4410 // This is handed out to debugger clients via code:CordbModule::GetMetaDataInterface
4411 // This is also tightly coupled to the internal metadata importer, m_pInternalMetaDataImport.
4412 RSExtSmartPtr<IMetaDataImport> m_pIMImport;
4414 // Internal metadata object. This is closely tied to the public metadata object (m_pIMImport).
4415 // They share the same backing storage, but expose different interfaces to that storage.
4416 // Debugger authors and tools use the public interfaces.
4417 // DAC-ized operations in the VM require an IMDInternalImport.
4418 // The public and internal must be updated together.
4419 // This ultimately gets handed back to DAC via code:CordbProcess::LookupMetaData
4420 RSExtSmartPtr<IMDInternalImport> m_pInternalMetaDataImport;
4422 // Continue counter of when the module was loaded.
4423 // See code:CordbModule::SetLoadEventContinueMarker for details
4424 UINT m_nLoadEventContinueCounter;
4426 // This is a table of all NativeCode objects in the module indexed
4428 // The collection is filled lazily by LookupOrCreateNativeCode
4429 CordbSafeHashTable<CordbNativeCode> m_nativeCodeTable;
4433 //-----------------------------------------------------------------------------
4434 // Cordb MDA notification
4435 //-----------------------------------------------------------------------------
4436 class CordbMDA : public CordbBase, public ICorDebugMDA
4439 CordbMDA(CordbProcess * pProc, DebuggerMDANotification * pData);
4442 virtual void Neuter();
4445 virtual const char * DbgGetName() { return "CordbMDA"; }
4448 //-----------------------------------------------------------
4450 //-----------------------------------------------------------
4452 ULONG STDMETHODCALLTYPE AddRef()
4454 return (BaseAddRefEnforceExternal());
4456 ULONG STDMETHODCALLTYPE Release()
4458 return (BaseReleaseEnforceExternal());
4460 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
4462 //-----------------------------------------------------------
4464 //-----------------------------------------------------------
4466 // Get the string for the type of the MDA. Never empty.
4467 // This is a convenient performant alternative to getting the XML stream and extracting
4468 // the type from that based off the schema.
4469 COM_METHOD GetName(ULONG32 cchName, ULONG32 * pcchName, __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[]);
4471 // Get a string description of the MDA. This may be empty (0-length).
4472 COM_METHOD GetDescription(ULONG32 cchName, ULONG32 * pcchName, __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[]);
4474 // Get the full associated XML for the MDA. This may be empty.
4475 // This could be a potentially expensive operation if the xml stream is large.
4476 // See the MDA documentation for the schema for this XML stream.
4477 COM_METHOD GetXML(ULONG32 cchName, ULONG32 * pcchName, __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[]);
4479 COM_METHOD GetFlags(CorDebugMDAFlags * pFlags);
4481 // Thread that the MDA is fired on. We use the os tid instead of an ICDThread in case an MDA is fired on a
4482 // native thread (or a managed thread that hasn't yet entered managed code and so we don't have a ICDThread
4483 // object for it yet)
4484 COM_METHOD GetOSThreadId(DWORD * pOsTid);
4487 NewArrayHolder<WCHAR> m_szName;
4488 NewArrayHolder<WCHAR> m_szDescription;
4489 NewArrayHolder<WCHAR> m_szXml;
4492 CorDebugMDAFlags m_flags;
4497 struct CordbHangingField
4499 FREEHASHENTRY entry;
4503 // A hashtable for storing EnC hanging field information
4504 // FieldData.m_fldMetadataToken is the key
4505 class CordbHangingFieldTable : public CHashTableAndData<CNewDataNoThrow>
4509 BOOL Cmp(SIZE_T k1, const HASHENTRY *pc2)
4511 LIMITED_METHOD_CONTRACT;
4512 return (ULONG)(UINT_PTR)(k1) !=
4513 (reinterpret_cast<const CordbHangingField *>(pc2))->data.m_fldMetadataToken;
4516 ULONG HASH(mdFieldDef fldToken)
4518 LIMITED_METHOD_CONTRACT;
4522 SIZE_T KEY(mdFieldDef fldToken)
4524 return (SIZE_T)fldToken;
4529 #ifndef DACCESS_COMPILE
4531 CordbHangingFieldTable() : CHashTableAndData<CNewDataNoThrow>(11)
4533 NewInit(11, sizeof(CordbHangingField), 11);
4536 FieldData * AddFieldInfo(FieldData * pInfo)
4538 _ASSERTE(pInfo != NULL);
4540 CordbHangingField *pEntry = (CordbHangingField *)Add(HASH(pInfo->m_fldMetadataToken));
4541 pEntry->data = *pInfo; // copy everything over
4543 // Return a pointer to the data
4544 return &(pEntry->data);
4547 void RemoveFieldInfo(mdFieldDef fldToken)
4549 CordbHangingField *entry = (CordbHangingField*)Find(HASH(fldToken), KEY(fldToken));
4550 _ASSERTE(entry != NULL);
4551 Delete(HASH(fldToken), (HASHENTRY*)entry);
4554 #endif // #ifndef DACCESS_COMPILE
4556 FieldData * GetFieldInfo(mdFieldDef fldToken)
4558 CordbHangingField * entry = (CordbHangingField *)Find(HASH(fldToken), KEY(fldToken));
4559 return (entry!=NULL?&(entry->data):NULL);
4564 /* ------------------------------------------------------------------------- *
4567 * This struct stores a set of type parameters. It is used in
4568 * the heap-allocated data structures CordbType and CordbNativeCode.
4570 * CordbType::m_inst. Stores the class type parameters if any,
4571 * or the solitary array type parameter, or the solitary parameter
4574 * CordbJITILFrame::m_genericArgs. Stores exact generic parameters for the generic method frame if available
4575 * Need not be identicial if code is shared between generic instantiations.
4576 * May be inexact if real instantiation has been optimized away off
4577 * the frame (nb this gets reported by the left side)
4579 * This is conceptually an array of Type-parameters, with the split (m_cClassTyPars) between
4580 * where the Type's type-parameters end and the Method's type-parameters begin.
4581 * ------------------------------------------------------------------------- */
4587 : m_cInst(0), m_ppInst(NULL), m_cClassTyPars (0)
4590 // Instantiation for Type. 0 Method type-parameters.
4591 Instantiation(unsigned int _cClassInst, CordbType **_ppClassInst)
4592 : m_cInst(_cClassInst), m_ppInst(_ppClassInst), m_cClassTyPars(_cClassInst)
4593 {LIMITED_METHOD_CONTRACT; }
4595 // Instantiation for Type + Function.
4596 Instantiation(unsigned int _cInst, CordbType **_ppInst, unsigned int numClassTyPars)
4597 : m_cInst(_cInst), m_ppInst(_ppInst),
4598 m_cClassTyPars (numClassTyPars)
4601 // Copy constructor.
4602 Instantiation(const Instantiation &inst)
4603 : m_cInst(inst.m_cInst), m_ppInst(inst.m_ppInst), m_cClassTyPars (inst.m_cClassTyPars)
4606 // Number of elements in array pointed to by m_ppInst
4607 unsigned int m_cInst;
4609 // Pointer to array of CordbType objects. Length of array is m_cInst.
4610 // Array is Class Type parameters followed by Function's Type parameters.
4611 // Eg, Instantiation for Class<Foo, Goo>::Func<Bar> would be {Foo, Goo, Bar}.
4612 // m_cInst = 3, m_cClassTyPars = 2.
4613 // In contrast, Instantiation for Class::Func<Foo, Goo, Bar> would have same
4614 // array, but m_cClassTyPars = 0.
4615 CordbType **m_ppInst;
4617 // Track the split between Type vs. Method type-params.
4618 unsigned int m_cClassTyPars;
4621 //------------------------------------------------------------------------
4622 // CordbType: replaces the use of signatures.
4624 // Left Side & Right Side
4625 // ---------------------------
4626 // CordbTypes may come from either the Right Side (via being built up from
4627 // ICorDebug), or from the Left-Side (being handed back from LS operations
4628 // like getting the type from an Object the LS handed back).
4629 // The RightSide CordbType corresponds to a Left-Side TypeHandle.
4630 // CordbTypes are communicated across the LS/RS boundary by marshalling
4631 // to BasicTypeData + ExpandedTypeData IPC events.
4634 // Invariants on CordbType
4635 // ---------------------------
4637 // The m_elementType is NEVER ELEMENT_TYPE_VAR or ELEMENT_TYPE_MVAR or ELEMENT_TYPE_GENERICINST
4638 // CordbTypes are always _ground_ types (fully instantiated generics or non-generic types). If
4639 // they represent an instantiated type like List<int> then m_inst will be non-empty.
4642 // !!!! The m_elementType is NEVER ELEMENT_TYPE_VALUETYPE !!!!
4643 // !!!! To find out if it is a value type call CordbType::IsValueType() !!!!
4645 // Where CordbTypes are stored
4646 // ---------------------------
4648 // Because we could have a significant number of different instantiations for a given templated type,
4649 // we need an efficient way to store and retrieve the CordbType instances for these instantiations.
4650 // For this reason, we use a tree-like scheme to hash-cons types. To implement this we use the following
4652 // - CordbTypes are created for "partially instantiated" types,
4653 // e.g. CordbTypes exist for "Dict" and "Dict<int>" even if the real
4654 // type being manipulated by the user is "Dict<int,string>"
4655 // - Subordinate types (E.g. Dict<int,string> is subordinate to Dict<int>,
4656 // which is itself subordinate to the type for Dict) get stored
4657 // in the m_spinetypes hash table of the parent type.
4658 // - In m_spinetypes the pointers of the CordbTypes themselves
4659 // are used for the unique ids for entries in the table.
4660 // Note that CordbType instances that are created for "partially instantiated" types
4661 // are never used for any purpose other than efficient hashing. Specifically, the debugger will
4662 // never have reason to expose a partially instantiated type outside of the hashing algorithm.
4664 // CordbTypes have object identity: if 2 CordbTypes represent the same type (in the same AppDomain),
4665 // then they will be the same CordbType instance.
4667 // Thus the representation for "Dict<class String,class Foo, class Foo* >" goes as follows:
4668 // 1. Assume the type Foo is represented by CordbClass *5678x
4669 // 1b. Assume the hashtable m_sharedtypes in the AppDomain maps E_T_STRING to the CordbType *0ABCx
4670 // Assume m_type in class Foo (i.e. CordbClass *5678x) is the CordbType *0DEFx
4671 // Assume m_type in class Foo maps E_T_PTR to the CordbType *0647x
4672 // 2. The hash table m_spinetypes in "Dict" maps "0ABCx" to a new CordbType
4673 // representing Dict<String> (a single type application)
4674 // 3. The hash table m_spinetypes in this new CordbType maps "0DEFx" to a
4675 // new CordbType representing Dict<class String,class Foo>
4676 // 3. The hash table m_spinetypes in this new CordbType maps "0647" to a
4677 // new CordbType representing Dict<class String,class Foo, class Foo*>
4679 // This lets us reuse the existing hash table scheme to build
4680 // up instantiated types of arbitrary size.
4682 // Array types are similar, excpet that they start with a head type
4683 // for the "type constructor", e.g. "_ []" is a type constructor with rank 1
4684 // and m_elementType = ELEMENT_TYPE_SZARRAY. These head constructors are
4685 // stored in the m_sharedtypes table in the appdomain. The actual instantiations
4686 // of the array types are then subordinate types to the array constructor type.
4688 // Other types are simpler, and have unique objects stored in the m_sharedtypes
4689 // table in the appdomain. This table is indexed by CORDBTYPE_ID in RsType.cpp
4692 // Memory Management of CordbTypes
4693 // ---------------------------
4694 // All CordbTypes are ultimately stored off the CordbAppDomain object.
4695 // The most common place is in the AppDomain's neuter-list.
4697 // See definition of ICorDebugType for further invariants on types.
4700 class CordbType : public CordbBase, public ICorDebugType
4703 CordbType(CordbAppDomain *appdomain, CorElementType ty, unsigned int rank);
4704 CordbType(CordbAppDomain *appdomain, CorElementType ty, CordbClass *c);
4705 CordbType(CordbType *tycon, CordbType *tyarg);
4706 virtual ~CordbType();
4707 virtual void Neuter();
4710 virtual const char * DbgGetName() { return "CordbType"; }
4713 // If you want to force the init to happen even if we think the class
4714 // is up to date, set fForceInit to TRUE
4715 HRESULT Init(BOOL fForceInit);
4717 //-----------------------------------------------------------
4719 //-----------------------------------------------------------
4721 ULONG STDMETHODCALLTYPE AddRef();
4722 ULONG STDMETHODCALLTYPE Release();
4723 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
4725 //-----------------------------------------------------------
4727 //-----------------------------------------------------------
4729 COM_METHOD GetType(CorElementType *ty);
4730 COM_METHOD GetClass(ICorDebugClass **ppClass);
4731 COM_METHOD EnumerateTypeParameters(ICorDebugTypeEnum **ppTyParEnum);
4732 COM_METHOD GetFirstTypeParameter(ICorDebugType **ppType);
4733 COM_METHOD GetBase(ICorDebugType **ppType);
4734 COM_METHOD GetStaticFieldValue(mdFieldDef fieldDef,
4735 ICorDebugFrame * pFrame,
4736 ICorDebugValue ** ppValue);
4737 COM_METHOD GetRank(ULONG32 *pnRank);
4739 //-----------------------------------------------------------
4741 //-----------------------------------------------------------
4743 //-----------------------------------------------------------
4744 // Basic constructor operations for the algebra of types.
4745 // These all create unique objects within an AppDomain.
4746 //-----------------------------------------------------------
4748 // This one is used to create simple types, e.g. int32, int64, typedbyref etc.
4749 static HRESULT MkType(CordbAppDomain * pAppDomain,
4750 CorElementType elementType,
4751 CordbType ** ppResultType);
4753 // This one is used to create array, pointer and byref types
4754 static HRESULT MkType(CordbAppDomain * pAppDomain,
4755 CorElementType elementType,
4758 CordbType ** ppResultType);
4760 // This one is used to create function pointer types. et must be ELEMENT_TYPE_FNPTR
4761 static HRESULT MkType(CordbAppDomain * pAppDomain,
4762 CorElementType elementType,
4763 const Instantiation * pInst,
4764 CordbType ** ppResultType);
4766 // This one is used to class and value class types, e.g. "class MyClass" or "class ArrayList<int>"
4767 static HRESULT MkType(CordbAppDomain * pAppDomain,
4768 CorElementType elementType,
4769 CordbClass * pClass,
4770 const Instantiation * pInst,
4771 CordbType ** ppResultType);
4773 // Some derived constructors... Use this one if the type is definitely not
4774 // a paramterized type, e.g. to implement functions on the API where types cannot
4775 // be parameterized.
4776 static HRESULT MkUnparameterizedType(CordbAppDomain *appdomain, CorElementType et, CordbClass *cl, CordbType **ppType);
4778 //-----------------------------------------------------------
4779 // Basic destructor operations over the algebra
4780 //-----------------------------------------------------------
4781 void DestUnaryType(CordbType **pRes) ;
4782 void DestConstructedType(CordbClass **pClass, Instantiation *pInst);
4783 void DestNaryType(Instantiation *pInst);
4785 CorElementType GetElementType() { return m_elementType; }
4786 VMPTR_DomainFile GetDomainFile();
4787 VMPTR_Module GetModule();
4789 // If this is a ptr type, get the CordbType that it points to.
4790 // Eg, for CordbType("Int*"), returns CordbType("Int").
4791 // If not a ptr type, returns null.
4792 // Since it's all internal, no reference counting.
4793 // This is effectively a specialized version of DestUnaryType.
4794 CordbType * GetPointerElementType();
4797 // Create a type from metadata
4798 static HRESULT SigToType(CordbModule * pModule, SigParser * pSigParser, const Instantiation * pInst, CordbType ** ppResultType);
4800 // Create a type from from the data received from the left-side
4801 static HRESULT TypeDataToType(CordbAppDomain *appdomain, DebuggerIPCE_ExpandedTypeData *data, CordbType **pRes);
4802 static HRESULT TypeDataToType(CordbAppDomain *appdomain, DebuggerIPCE_BasicTypeData *data, CordbType **pRes);
4803 static HRESULT InstantiateFromTypeHandle(CordbAppDomain * appdomain,
4804 VMPTR_TypeHandle vmTypeHandle,
4809 // Prepare data to send back to left-side during Init() and FuncEval. Fail if the the exact
4810 // type data is requested but was not fetched correctly during Init()
4811 HRESULT TypeToBasicTypeData(DebuggerIPCE_BasicTypeData *data);
4812 void TypeToExpandedTypeData(DebuggerIPCE_ExpandedTypeData *data);
4813 void TypeToTypeArgData(DebuggerIPCE_TypeArgData *data);
4815 void CountTypeDataNodes(unsigned int *count);
4816 static void CountTypeDataNodesForInstantiation(unsigned int genericArgsCount, ICorDebugType *genericArgs[], unsigned int *count);
4817 static void GatherTypeData(CordbType *type, DebuggerIPCE_TypeArgData **curr_tyargData);
4818 static void GatherTypeDataForInstantiation(unsigned int genericArgsCount, ICorDebugType *genericArgs[], DebuggerIPCE_TypeArgData **curr_tyargData);
4820 HRESULT GetParentType(CordbClass * baseClass, CordbType ** ppRes);
4822 // These are available after Init() has been called....
4823 HRESULT GetUnboxedObjectSize(ULONG32 *res);
4824 HRESULT GetFieldInfo(mdFieldDef fldToken, FieldData ** ppFieldData);
4826 CordbAppDomain *GetAppDomain() { return m_appdomain; }
4830 // Is this type a GC-root.
4833 #ifdef FEATURE_64BIT_ALIGNMENT
4834 // checks if the type requires 8-byte alignment.
4835 // this is not exposed via ICorDebug at present.
4836 HRESULT CordbType::RequiresAlign8(BOOL* isRequired);
4839 //-----------------------------------------------------------
4841 //-----------------------------------------------------------
4844 // Internal representation of the element type. This may not map exactly to the public element type.
4845 // Specifically, m_elementType is NEVER:
4846 // ELEMENT_TYPE_VAR, ELEMENT_TYPE_MVAR, ELEMENT_TYPE_GENERICINST,
4847 // or ELEMENT_TYPE_VALUETYPE.
4848 // To find out if this CordbType corresponds to a value type (instead of Reference type) call CordbType::IsValueType()
4849 CorElementType m_elementType;
4851 // The appdomain that this type lives in. Types (and their type-parameters) are all contained in a single appdomain.
4852 // (alhtough the types may be from different modules).
4853 // This is valid for all CordbType objects, regardless of m_elementType;
4854 CordbAppDomain * m_appdomain;
4856 // The matching class for this type.
4857 // Initially only set for E_T_CLASS, lazily computed for E_T_STRING and E_T_OBJECT if needed
4858 CordbClass * m_pClass;
4860 ULONG m_rank; // Only set for E_T_ARRAY etc.
4862 // Array of Type Parameters for this Type.
4863 Instantiation m_inst;
4865 // A unique mapping from CordbType objects that are type parameters to CordbType objects. Each mapping
4866 // represents the use of the containing type as type constructor. e.g. If the containing type
4867 // is CordbType(CordbClass "List") then the table here will map parameters such as (CordbType(CordbClass "String")) to
4868 // the constructed type CordbType(CordbClass "List", <CordbType(CordbClass "String")>)
4869 // @dbgtodo synchronization - this is currently protected by the Stop-Go lock. Transition to process-lock.
4870 CordbSafeHashTable<CordbType> m_spinetypes;
4872 // Valid after Init(), only for E_T_ARRAY etc.and E_T_CLASS when m_pClass->m_classInfo.m_genericArgsCount > 0.
4873 // m_typeHandleExact is the precise Runtime type handle for this type.
4874 VMPTR_TypeHandle m_typeHandleExact;
4876 // Valid after Init(), only for E_T_CLASS, and when m_pClass->m_classInfo.m_genericArgsCount > 0.
4877 // May not be set correctly if m_fieldInfoNeedsInit.
4878 SIZE_T m_objectSize;
4880 // DON'T KEEP POINTERS TO ELEMENTS OF m_pFields AROUND!!
4881 // This may be deleted if the class gets EnC'd.
4883 // Valid after Init(), only for E_T_CLASS, and when m_pClass->m_classInfo.m_genericArgsCount > 0
4884 // All fields will be valid if we have m_typeHandleExact.
4886 // Only some fields will be valid if we have called Init() but still have m_fieldInfoNeedsInit.
4887 DacDbiArrayList<FieldData> m_fieldList;
4889 HRESULT ReturnedByValue();
4892 static HRESULT MkTyAppType(CordbAppDomain * pAddDomain,
4894 const Instantiation * pInst,
4895 CordbType ** pResultType);
4897 BOOL m_fieldInfoNeedsInit;
4900 HRESULT InitInstantiationTypeHandle(BOOL fForceInit);
4901 HRESULT InitInstantiationFieldInfo(BOOL fForceInit);
4902 HRESULT InitStringOrObjectClass(BOOL fForceInit);
4905 /* ------------------------------------------------------------------------- *
4907 * ------------------------------------------------------------------------- */
4909 class CordbClass : public CordbBase, public ICorDebugClass, public ICorDebugClass2
4912 CordbClass(CordbModule* m, mdTypeDef token);
4913 virtual ~CordbClass();
4914 virtual void Neuter();
4916 using CordbBase::GetProcess;
4919 virtual const char * DbgGetName() { return "CordbClass"; }
4923 //-----------------------------------------------------------
4925 //-----------------------------------------------------------
4927 ULONG STDMETHODCALLTYPE AddRef()
4929 return (BaseAddRef());
4931 ULONG STDMETHODCALLTYPE Release()
4933 return (BaseRelease());
4935 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
4937 //-----------------------------------------------------------
4939 //-----------------------------------------------------------
4941 COM_METHOD GetStaticFieldValue(mdFieldDef fieldDef,
4942 ICorDebugFrame *pFrame,
4943 ICorDebugValue **ppValue);
4944 COM_METHOD GetModule(ICorDebugModule **pModule);
4945 COM_METHOD GetToken(mdTypeDef *pTypeDef);
4946 //-----------------------------------------------------------
4948 //-----------------------------------------------------------
4949 COM_METHOD GetParameterizedType(CorElementType elementType,
4951 ICorDebugType * rgpTypeArgs[],
4952 ICorDebugType ** ppType);
4954 COM_METHOD SetJMCStatus(BOOL fIsUserCode);
4956 //-----------------------------------------------------------
4957 // Convenience routines and Accessors
4958 //-----------------------------------------------------------
4960 // Helper to get containing module
4961 CordbModule * GetModule()
4966 // get the metadata token for this class
4967 mdTypeDef GetToken() { return m_token; }
4969 // Helper to get the AppDomain the class lives in.
4970 CordbAppDomain * GetAppDomain()
4972 return m_pModule->GetAppDomain();
4975 // This only very roughly resembles the CLASS_LOAD_LEVEL concept in the VM.
4976 // because DBI's needs are far more coarse grained. Also DBI
4977 // may contain more, equal, or less information than what is available in
4978 // native runtime data structures. We can have less when we are being lazy
4979 // and haven't yet fetched it. We can have more if use an independent data
4980 // source such as the metadata blob and then compute some type data ourselves
4983 // At this state the constructor has been run.
4984 // m_module and m_token will be valid
4987 // At this state we have additionally certain to have initialized
4988 // m_fIsValueClass and m_fHasTypeParams
4989 // Calls to IsValueClass() and HasTypeParams() are valid
4990 // This stage should be achievable as long as a runtime type handle
4991 // exists, even if it is unrestored
4994 //Everything is loaded, or at least anything created lazily from this
4995 //point on should be certain to succeed (ie m_type)
5000 ClassLoadLevel GetLoadLevel()
5005 // determine if a load event has been sent for this class
5006 BOOL LoadEventSent() { return m_fLoadEventSent; }
5008 // set value of m_fLoadEventSent
5009 void SetLoadEventSent(BOOL fEventSent) { m_fLoadEventSent = fEventSent; }
5011 // determine if the class has been unloaded
5012 BOOL HasBeenUnloaded() { return m_fHasBeenUnloaded; }
5014 // set value of m_fHasBeenUnloaded
5015 void SetHasBeenUnloaded(BOOL fUnloaded) { m_fHasBeenUnloaded = (fUnloaded == TRUE); }
5017 // determine if this is a value class
5018 BOOL IsValueClassNoInit() { return m_fIsValueClass; }
5020 // set value of m_fIsValueClass
5021 void SetIsValueClass(BOOL fIsValueClass) { m_fIsValueClass = (fIsValueClass == TRUE); }
5023 // determine if the value class is known
5024 BOOL IsValueClassKnown() { return m_fIsValueClassKnown; }
5026 // set value of m_fIsValueClassKnown
5027 void SetIsValueClassKnown(BOOL fIsValueClassKnown) { m_fIsValueClassKnown = (fIsValueClassKnown == TRUE); }
5029 // get value of m_type
5030 CordbType * GetType() { return m_type; }
5032 void SetType(CordbType * pType) { m_type.Assign(pType); }
5034 // get the type parameter count
5035 bool HasTypeParams() { _ASSERTE(m_loadLevel >= BasicInfo); return m_fHasTypeParams; }
5037 // get the object size
5038 SIZE_T ObjectSize() { return m_classInfo.m_objectSize; }
5040 // get the metadata token for this class
5041 mdTypeDef MDToken() { return m_token; }
5043 // get the number of fields
5044 unsigned int FieldCount() { return m_classInfo.m_fieldList.Count(); }
5046 //-----------------------------------------------------------
5047 // Functionality shared for CordbType and CordbClass
5048 //-----------------------------------------------------------
5050 static HRESULT SearchFieldInfo(CordbModule * module,
5051 DacDbiArrayList<FieldData> * pFieldList,
5052 mdTypeDef classToken,
5053 mdFieldDef fldToken,
5054 FieldData ** ppFieldData);
5056 static HRESULT GetStaticFieldValue2(CordbModule * pModule,
5057 FieldData * pFieldData,
5058 BOOL fEnCHangingField,
5059 const Instantiation * pInst,
5060 ICorDebugFrame * pFrame,
5061 ICorDebugValue ** ppValue);
5063 //-----------------------------------------------------------
5065 //-----------------------------------------------------------
5067 // Get information about a field that was added by EnC
5068 HRESULT GetEnCHangingField(mdFieldDef fldToken,
5069 FieldData ** ppFieldData,
5070 CordbObjectValue * pObject);
5073 // Get information via the DAC about a field added with Edit and Continue.
5074 FieldData * GetEnCFieldFromDac(BOOL fStatic,
5075 CordbObjectValue * pObject,
5076 mdFieldDef fieldToken);
5078 // Initialize an instance of EnCHangingFieldInfo.
5079 void InitEnCFieldInfo(EnCHangingFieldInfo * pEncField,
5081 CordbObjectValue * pObject,
5082 mdFieldDef fieldToken,
5083 mdTypeDef classToken);
5088 // set or clear the custom notifications flag to control whether we ignore custom debugger notifications
5089 void SetCustomNotifications(BOOL fEnable) { m_fCustomNotificationsEnabled = fEnable; }
5090 BOOL CustomNotificationsEnabled () { return m_fCustomNotificationsEnabled; }
5092 HRESULT GetFieldInfo(mdFieldDef fldToken, FieldData ** ppFieldData);
5094 // If you want to force the init to happen even if we think the class
5095 // is up to date, set fForceInit to TRUE
5096 void Init(ClassLoadLevel desiredLoadLevel = FullInfo);
5098 // determine if any fields for a type are unallocated statics
5099 BOOL GotUnallocatedStatic(DacDbiArrayList<FieldData> * pFieldList);
5101 bool IsValueClass();
5102 HRESULT GetThisType(const Instantiation * pInst, CordbType ** ppResultType);
5103 static HRESULT PostProcessUnavailableHRESULT(HRESULT hr,
5104 IMetaDataImport *pImport,
5105 mdFieldDef fieldDef);
5106 mdTypeDef GetTypeDef() { return (mdTypeDef)m_id; }
5108 #ifdef EnC_SUPPORTED
5109 // when we get an added field or method, mark the class to force re-init when we access it
5112 m_loadLevel = Constructed;
5114 #endif // EnC_SUPPORTED
5116 //-----------------------------------------------------------
5118 //-----------------------------------------------------------
5120 // contains information about the type: size and
5121 // field information
5122 ClassInfo m_classInfo;
5124 ClassLoadLevel m_loadLevel;
5126 // @dbgtodo managed pipeline - can we get rid of both of these fields?
5127 BOOL m_fLoadEventSent;
5128 bool m_fHasBeenUnloaded;
5130 // [m_type] is the type object for when this class is used
5131 // as a type. If the class is a value class then it can represent
5132 // either the boxed or unboxed type - it depends on the context where the
5133 // type is used. For example on a CordbBoxValue it represents the type of the
5134 // boxed VC, on a CordbVCObjectValue it represents the type of the unboxed VC.
5136 // The type field starts of NULL as there
5137 // is no need to create the type object until it is needed.
5138 RSSmartPtr<CordbType> m_type;
5140 // Module that this Class lives in. Valid at the Constructed type level.
5141 CordbModule * m_pModule;
5143 // the token for the type constructor - m_id cannot be used for constructed types
5144 // valid at the Constructed type level
5147 // Whether the class is a VC or not is discovered either by
5148 // seeing the class used in a signature after ELEMENT_TYPE_VALUETYPE
5149 // or ELEMENT_TYPE_CLASS or by going and asking the EE.
5150 bool m_fIsValueClassKnown;
5152 // Whether the class is a VC or not
5153 bool m_fIsValueClass;
5155 // Whether the class has generic type parameters in its definition
5156 bool m_fHasTypeParams;
5158 // Timestamp from GetProcess()->m_continueCounter, which we can use to tell if
5159 // the process has been continued since we last took a snapshot.
5160 UINT m_continueCounterLastSync;
5162 // if we add static fields with EnC after this class is loaded (in the debuggee),
5163 // their value will be hung off the FieldDesc. Hold information about such fields here.
5164 CordbHangingFieldTable m_hangingFieldsStatic;
5166 // this indicates whether we should send custom debugger notifications
5167 BOOL m_fCustomNotificationsEnabled;
5172 /* ------------------------------------------------------------------------- *
5173 * TypeParameter enumerator class
5174 * ------------------------------------------------------------------------- */
5176 class CordbTypeEnum : public CordbBase, public ICorDebugTypeEnum
5179 // Factory method: Create a new instance of this class. Returns NULL on out-of-memory.
5180 // On success, returns a new initialized instance of CordbTypeEnum with ref-count 0 (just like a ctor).
5181 // the life expectancy of the enumerator varies by caller so we require them to specify the applicable neuter list here.
5182 static CordbTypeEnum* Build(CordbAppDomain * pAppDomain, NeuterList * pNeuterList, unsigned int cTypars, CordbType **ppTypars);
5183 static CordbTypeEnum* Build(CordbAppDomain * pAppDomain, NeuterList * pNeuterList, unsigned int cTypars, RSSmartPtr<CordbType>*ppTypars);
5185 virtual ~CordbTypeEnum() ;
5187 virtual void Neuter();
5191 virtual const char * DbgGetName() { return "CordbTypeEnum"; }
5195 //-----------------------------------------------------------
5197 //-----------------------------------------------------------
5199 ULONG STDMETHODCALLTYPE AddRef()
5201 return (BaseAddRef());
5203 ULONG STDMETHODCALLTYPE Release()
5205 return (BaseRelease());
5207 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
5209 //-----------------------------------------------------------
5211 //-----------------------------------------------------------
5213 COM_METHOD Skip(ULONG celt);
5215 COM_METHOD Clone(ICorDebugEnum **ppEnum);
5216 COM_METHOD GetCount(ULONG *pcelt);
5218 //-----------------------------------------------------------
5219 // ICorDebugTypeEnum
5220 //-----------------------------------------------------------
5222 COM_METHOD Next(ULONG celt, ICorDebugType *Types[], ULONG *pceltFetched);
5225 // Private constructor, only partially initializes the object.
5226 // Clients should use the 'Build' factory method to create an instance of this class.
5227 CordbTypeEnum( CordbAppDomain * pAppDomain, NeuterList * pNeuterList );
5228 template<class T> static CordbTypeEnum* BuildImpl(CordbAppDomain * pAppDomain, NeuterList * pNeuterList, unsigned int cTypars, T* ppTypars );
5231 CordbAppDomain * m_pAppDomain;
5233 // Array of Types. We own the array, and share refs to the types.
5234 // @todo- since these are guaranteed to be kept alive as long as we're not neutered,
5235 // we don't need to keep refs to them.
5236 RSSmartPtr<CordbType> * m_ppTypars;
5241 /* ------------------------------------------------------------------------- *
5242 * Code enumerator class
5243 * ------------------------------------------------------------------------- */
5245 class CordbCodeEnum : public CordbBase, public ICorDebugCodeEnum
5248 CordbCodeEnum(unsigned int cCode, RSSmartPtr<CordbCode> * ppCode);
5249 virtual ~CordbCodeEnum() ;
5253 virtual const char * DbgGetName() { return "CordbCodeEnum"; }
5257 //-----------------------------------------------------------
5259 //-----------------------------------------------------------
5261 ULONG STDMETHODCALLTYPE AddRef()
5263 return (BaseAddRef());
5265 ULONG STDMETHODCALLTYPE Release()
5267 return (BaseRelease());
5269 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
5271 //-----------------------------------------------------------
5273 //-----------------------------------------------------------
5275 COM_METHOD Skip(ULONG celt);
5277 COM_METHOD Clone(ICorDebugEnum **ppEnum);
5278 COM_METHOD GetCount(ULONG *pcelt);
5280 //-----------------------------------------------------------
5281 // ICorDebugCodeEnum
5282 //-----------------------------------------------------------
5284 COM_METHOD Next(ULONG celt, ICorDebugCode *Codes[], ULONG *pceltFetched);
5287 // Ptr to an array of CordbCode*
5288 // We own the array.
5289 RSSmartPtr<CordbCode> * m_ppCodes;
5298 typedef CUnorderedArray<CordbCode*,11> UnorderedCodeArray;
5299 //<TODO>@todo port: different SIZE_T size/</TODO>
5300 const int DMI_VERSION_INVALID = 0;
5301 const int DMI_VERSION_MOST_RECENTLY_JITTED = 1;
5302 const int DMI_VERSION_MOST_RECENTLY_EnCED = 2;
5305 /* ------------------------------------------------------------------------- *
5308 * @review . The CordbFunction class now keeps a multiple MethodDescInfo
5309 * structures in a hash table indexed by tokens provided by the left-side.
5310 * In 99.9% of cases this hash table will only contain one entry - we only
5311 * use a hashtable to cover the case where we have multiple JITtings of
5312 * a single version of a function, in particular multiple JITtings of generic
5313 * code under different instantiations. This will increase space usage.
5314 * The way around it is to store one CordbNativeCode in-line in the CordbFunction
5315 * class, or at least store one such pointer so no hash table will normally
5316 * be needed. This is similar to other cases, e.g. the hash table in
5317 * CordbClass used to indicate different CordbTypes made from that class -
5318 * again in the normal case these tables will only contain one element.
5320 * However, for the moment I've focused on correctness and we can minimize
5321 * this space usage in due course.
5322 * ------------------------------------------------------------------------- */
5324 const BOOL bNativeCode = FALSE;
5325 const BOOL bILCode = TRUE;
5328 // Each E&C version gets its own function object. So the IL that a function
5329 // is associated w/ does not change.
5330 // B/C of generics, a single IL function may get jitted multiple times and
5331 // be associated w/ multiple native code blobs (CordbNativeCode).
5333 class CordbFunction : public CordbBase, public ICorDebugFunction, public ICorDebugFunction2, public ICorDebugFunction3
5336 //-----------------------------------------------------------
5337 // Create from scope and member objects.
5338 //-----------------------------------------------------------
5339 CordbFunction(CordbModule * m,
5342 virtual ~CordbFunction();
5343 virtual void Neuter();
5348 virtual const char * DbgGetName() { return "CordbFunction"; }
5352 //-----------------------------------------------------------
5354 //-----------------------------------------------------------
5356 ULONG STDMETHODCALLTYPE AddRef()
5358 return (BaseAddRef());
5360 ULONG STDMETHODCALLTYPE Release()
5362 return (BaseRelease());
5364 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
5366 //-----------------------------------------------------------
5367 // ICorDebugFunction
5368 //-----------------------------------------------------------
5369 COM_METHOD GetModule(ICorDebugModule **pModule);
5370 COM_METHOD GetClass(ICorDebugClass **ppClass);
5371 COM_METHOD GetToken(mdMethodDef *pMemberDef);
5372 COM_METHOD GetILCode(ICorDebugCode **ppCode);
5373 COM_METHOD GetNativeCode(ICorDebugCode **ppCode);
5374 COM_METHOD CreateBreakpoint(ICorDebugFunctionBreakpoint **ppBreakpoint);
5375 COM_METHOD GetLocalVarSigToken(mdSignature *pmdSig);
5376 COM_METHOD GetCurrentVersionNumber(ULONG32 *pnCurrentVersion);
5378 //-----------------------------------------------------------
5379 // ICorDebugFunction2
5380 //-----------------------------------------------------------
5381 COM_METHOD SetJMCStatus(BOOL fIsUserCode);
5382 COM_METHOD GetJMCStatus(BOOL * pfIsUserCode);
5383 COM_METHOD EnumerateNativeCode(ICorDebugCodeEnum **ppCodeEnum) { return E_NOTIMPL; }
5384 COM_METHOD GetVersionNumber(ULONG32 *pnCurrentVersion);
5386 //-----------------------------------------------------------
5387 // ICorDebugFunction3
5388 //-----------------------------------------------------------
5389 COM_METHOD GetActiveReJitRequestILCode(ICorDebugILCode **ppReJitedILCode);
5391 //-----------------------------------------------------------
5393 //-----------------------------------------------------------
5395 // Returns the function's ILCode and SigToken
5396 HRESULT GetILCodeAndSigToken();
5398 // Get the metadata token for the class to which a function belongs.
5399 mdTypeDef InitParentClassOfFunctionHelper(mdToken funcMetaDataToken);
5401 // Get information about one of the native code blobs for this function
5402 HRESULT InitNativeCodeInfo();
5406 // Get the class to which a given function belongs
5407 HRESULT InitParentClassOfFunction();
5409 void NotifyCodeCreated(CordbNativeCode* nativeCode);
5411 HRESULT GetSig(SigParser *pMethodSigParser,
5412 ULONG *pFunctionArgCount,
5413 BOOL *pFunctionIsStatic);
5415 HRESULT GetArgumentType(DWORD dwIndex, const Instantiation * pInst, CordbType ** ppResultType);
5418 //-----------------------------------------------------------
5419 // Internal routines
5420 //-----------------------------------------------------------
5422 // Get the existing IL code object
5423 HRESULT GetILCode(CordbILCode ** ppCode);
5425 // Finds or creates an ILCode for a given rejit request
5426 HRESULT LookupOrCreateReJitILCode(VMPTR_SharedReJitInfo vmSharedRejitInfo,
5427 CordbReJitILCode** ppILCode);
5430 #ifdef EnC_SUPPORTED
5434 //-----------------------------------------------------------
5436 //-----------------------------------------------------------
5438 // Get the AppDomain that this function lives in.
5439 CordbAppDomain * GetAppDomain()
5441 return (m_pModule->GetAppDomain());
5444 // Get the CordbModule that this Function lives in.
5445 CordbModule * GetModule()
5450 // Get the CordbClass this of which this function is a member
5451 CordbClass * GetClass()
5456 // Get the IL code blob corresponding to this function
5457 CordbILCode * GetILCode()
5462 // Get metadata token for this function
5463 mdMethodDef GetMetadataToken()
5468 SIZE_T GetEnCVersionNumber()
5470 return m_dwEnCVersionNumber;
5473 CordbFunction * GetPrevVersion()
5475 return m_pPrevVersion;
5478 void SetPrevVersion(CordbFunction * prevVersion)
5480 m_pPrevVersion.Assign(prevVersion);
5483 typedef enum {kNativeOnly, kHasIL, kUnknownImpl} ImplementationKind;
5484 ImplementationKind IsNativeImpl()
5486 return (m_fIsNativeImpl);
5489 // determine whether we have a native-only implementation
5490 void InitNativeImpl();
5493 //-----------------------------------------------------------
5495 //-----------------------------------------------------------
5498 // The module that this Function is contained in. It maintains a strong reference to this object
5499 // and will neuter this object.
5500 CordbModule * m_pModule;
5502 // The Class that this function is contained in.
5503 CordbClass * m_pClass;
5505 // We only have 1 IL blob associated with a given Function object.
5506 RSSmartPtr<CordbILCode> m_pILCode;
5509 // Generics allow a single IL method to be instantiated to multiple native
5510 // code blobs. So CordbFunction : CordbNativeCode is 1:n.
5511 // This pointer is to arbitrary one of those n code bodies.
5512 // Someday we may need to get access to all N of them but not today
5513 RSSmartPtr<CordbNativeCode> m_nativeCode;
5515 // Metadata Token for the IL function. Scoped to m_module.
5516 mdMethodDef m_MDToken;
5518 // EnC version number of this instance
5519 SIZE_T m_dwEnCVersionNumber;
5521 // link to previous version of this function
5522 RSSmartPtr<CordbFunction> m_pPrevVersion;
5524 // Is the function implemented natively in the runtime?? (eg, it has no IL, may be an Ecall/fcall)
5525 ImplementationKind m_fIsNativeImpl;
5527 // True if method signature (argument) values are cached.
5528 BOOL m_fCachedMethodValuesValid;
5530 // Cached SigParser for this Function's argument signature.
5531 // Only valid if m_fCachedMethodValuesValid is set.
5532 SigParser m_methodSigParserCached;
5534 // Cached Count of arguments in the argument signature.
5535 // Only valid if m_fCachedMethodValuesValid is set.
5536 ULONG m_argCountCached;
5538 // Cached boolean if method is static or instance (part of the argument signature).
5539 // Only valid if m_fCachedMethodValuesValid is set.
5540 BOOL m_fIsStaticCached;
5542 // A collection, indexed by VMPTR_SharedReJitInfo, of IL code for rejit requests
5543 // The collection is filled lazily by LookupOrCreateReJitILCode
5544 CordbSafeHashTable<CordbReJitILCode> m_reJitILCodes;
5547 //-----------------------------------------------------------------------------
5549 // Represents either IL or Native code blobs associated with a function.
5551 // See the comments at the ICorDebugCode definition for invariants about Code objects.
5553 //-----------------------------------------------------------------------------
5554 class CordbCode : public CordbBase, public ICorDebugCode
5557 CordbCode(CordbFunction * pFunction, UINT_PTR id, SIZE_T encVersion, BOOL fIsIL);
5560 virtual ~CordbCode();
5561 virtual void Neuter();
5564 virtual const char * DbgGetName() = 0;
5568 //-----------------------------------------------------------
5570 //-----------------------------------------------------------
5572 ULONG STDMETHODCALLTYPE AddRef()
5574 return (BaseAddRef());
5576 ULONG STDMETHODCALLTYPE Release()
5578 return (BaseRelease());
5580 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
5582 //-----------------------------------------------------------
5584 //-----------------------------------------------------------
5586 COM_METHOD IsIL(BOOL * pbIL);
5587 COM_METHOD GetFunction(ICorDebugFunction ** ppFunction);
5588 COM_METHOD GetAddress(CORDB_ADDRESS * pStart) = 0;
5589 COM_METHOD GetSize(ULONG32 * pcBytes);
5590 COM_METHOD CreateBreakpoint(ULONG32 offset,
5591 ICorDebugFunctionBreakpoint ** ppBreakpoint);
5592 COM_METHOD GetCode(ULONG32 startOffset, ULONG32 endOffset,
5593 ULONG32 cBufferAlloc,
5595 ULONG32 * pcBufferSize);
5596 COM_METHOD GetVersionNumber( ULONG32 * nVersion);
5597 COM_METHOD GetILToNativeMapping(ULONG32 cMap,
5599 COR_DEBUG_IL_TO_NATIVE_MAP map[]) = 0;
5600 COM_METHOD GetEnCRemapSequencePoints(ULONG32 cMap,
5604 //-----------------------------------------------------------
5605 // Accessors and convenience routines
5606 //-----------------------------------------------------------
5608 // get the CordbFunction instance for this code object
5609 CordbFunction * GetFunction();
5611 // get the actual code bytes for this function
5612 virtual HRESULT ReadCodeBytes() = 0;
5614 // get the size in bytes of this function
5615 virtual ULONG32 GetSize() = 0;
5618 // get the metadata token for this code object
5619 mdMethodDef GetMetadataToken()
5621 _ASSERTE(m_pFunction != NULL);
5622 return (m_pFunction->GetMetadataToken());
5625 // get the module this code object belongs to
5626 CordbModule * GetModule()
5628 _ASSERTE(m_pFunction != NULL);
5629 return (m_pFunction->GetModule());
5632 // get the function signature for this code blob or throw on failure
5633 void GetSig(SigParser *pMethodSigParser,
5634 ULONG *pFunctionArgCount,
5635 BOOL *pFunctionIsStatic)
5637 _ASSERTE(m_pFunction != NULL);
5638 IfFailThrow(m_pFunction->GetSig(pMethodSigParser, pFunctionArgCount, pFunctionIsStatic));
5641 // get the class to which this code blob belongs
5642 CordbClass * GetClass()
5644 _ASSERTE(m_pFunction != NULL);
5645 return (m_pFunction->GetClass());
5648 // Quick helper to get the AppDomain that this code object lives in.
5649 CordbAppDomain *GetAppDomain()
5651 _ASSERTE(m_pFunction != NULL);
5652 return (m_pFunction->GetAppDomain());
5655 // Get the EnC version of this blob
5656 SIZE_T GetVersion() { return m_nVersion; };
5658 // Return true if this is an IL code blob. Else return false.
5659 BOOL IsIL() { return m_fIsIL; }
5661 // convert to CordbNativeCode as long as m_fIsIl is false.
5662 CordbNativeCode * AsNativeCode()
5664 _ASSERTE(m_fIsIL == FALSE);
5665 return reinterpret_cast<CordbNativeCode *>(this);
5668 // convert to CordbILCode as long as m_fIsIl is true.
5669 CordbILCode * AsILCode()
5671 _ASSERTE(m_fIsIL == TRUE);
5672 return reinterpret_cast<CordbILCode *>(this);
5675 //-----------------------------------------------------------
5677 //-----------------------------------------------------------
5682 // EnC version number.
5686 // Our local copy of the code. It will be GetSize() bytes long.
5687 BYTE * m_rgbCode; // will be NULL if we can't fit it into memory
5689 UINT m_continueCounterLastSync;
5691 // Owning Function associated with this code.
5692 CordbFunction * m_pFunction;
5693 }; //class CordbCode
5699 /* ------------------------------------------------------------------------- *
5701 * This class represents an IL code blob for a particular EnC version. Thus it is
5702 * 1:1 with a given instantiation of CordbFunction. Provided functionality includes
5703 * methods to get the starting address and size of an IL code blob and to read
5704 * the actual bytes of IL into a buffer.
5705 * ------------------------------------------------------------------------- */
5707 class CordbILCode : public CordbCode
5710 // Initialize a new CordbILCode instance
5711 CordbILCode(CordbFunction *pFunction, TargetBuffer codeRegionInfo, SIZE_T nVersion, mdSignature localVarSigToken, UINT_PTR id = 0);
5714 const char * DbgGetName() { return "CordbILCode"; };
5717 COM_METHOD GetAddress(CORDB_ADDRESS * pStart);
5718 COM_METHOD GetILToNativeMapping(ULONG32 cMap,
5720 COR_DEBUG_IL_TO_NATIVE_MAP map[]);
5721 // Quick helper for internal access to: GetAddress(CORDB_ADDRESS *pStart);
5722 CORDB_ADDRESS GetAddress() { return m_codeRegionInfo.pAddress; }
5724 // get total size of the IL code
5725 ULONG32 GetSize() { return m_codeRegionInfo.cbSize; }
5727 #ifdef EnC_SUPPORTED
5729 #endif // EnC_SUPPORTED
5731 HRESULT GetLocalVarSig(SigParser *pLocalsSigParser, ULONG *pLocalVarCount);
5732 HRESULT GetLocalVariableType(DWORD dwIndex, const Instantiation * pInst, CordbType ** ppResultType);
5733 mdSignature GetLocalVarSigToken();
5736 // Read the actual bytes of IL code into the data member m_rgbCode.
5737 // Helper routine for GetCode
5738 HRESULT ReadCodeBytes();
5740 //-----------------------------------------------------------
5742 //-----------------------------------------------------------
5745 #ifdef EnC_SUPPORTED
5746 UINT m_fIsOld : 1; // marks this instance as an old EnC version
5747 bool m_encBreakpointsApplied;
5750 // derived types can init this
5752 TargetBuffer m_codeRegionInfo; // stores the starting address and size of the
5755 // Metadata token for local's signature.
5756 mdSignature m_localVarSigToken;
5758 }; // class CordbILCode
5760 /* ------------------------------------------------------------------------- *
5761 * CordbReJitILCode class
5762 * This class represents an IL code blob for a particular EnC version and
5763 * rejitID. Thus it is 1:N with a given instantiation of CordbFunction.
5764 * ------------------------------------------------------------------------- */
5766 class CordbReJitILCode : public CordbILCode, public ICorDebugILCode, public ICorDebugILCode2
5769 // Initialize a new CordbILCode instance
5770 CordbReJitILCode(CordbFunction *pFunction, SIZE_T encVersion, VMPTR_SharedReJitInfo vmSharedReJitInfo);
5772 //-----------------------------------------------------------
5774 //-----------------------------------------------------------
5775 ULONG STDMETHODCALLTYPE AddRef();
5776 ULONG STDMETHODCALLTYPE Release();
5777 COM_METHOD QueryInterface(REFIID riid, void** ppInterface);
5780 //-----------------------------------------------------------
5782 //-----------------------------------------------------------
5783 COM_METHOD GetEHClauses(ULONG32 cClauses, ULONG32 * pcClauses, CorDebugEHClause clauses[]);
5786 //-----------------------------------------------------------
5788 //-----------------------------------------------------------
5789 COM_METHOD GetLocalVarSigToken(mdSignature *pmdSig);
5790 COM_METHOD GetInstrumentedILMap(ULONG32 cMap, ULONG32 *pcMap, COR_IL_MAP map[]);
5793 HRESULT Init(DacSharedReJitInfo* pSharedReJitInfo);
5797 NewArrayHolder<CorDebugEHClause> m_pClauses;
5798 ULONG32 m_cbLocalIL;
5799 NewArrayHolder<BYTE> m_pLocalIL;
5801 NewArrayHolder<COR_IL_MAP> m_pILMap;
5804 /* ------------------------------------------------------------------------- *
5805 * CordbNativeCode class. These correspond to MethodDesc's on the left-side.
5806 * There may or may not be a DebuggerJitInfo associated with the MethodDesc.
5807 * At most one CordbNativeCode is created for each native code compilation of each method
5808 * that is seen by the right-side. Note that if each method were JITted only once
5809 * then this information could go in CordbFunction, however generics allow
5810 * methods to be compiled more than once.
5812 * The purpose of this class is to encapsulate details about a blob of jitted/ngen'ed
5813 * code, including an optional set of mappings from IL to offsets in the native Code.
5814 * ------------------------------------------------------------------------- */
5816 class CordbNativeCode : public CordbCode, public ICorDebugCode2, public ICorDebugCode3
5819 CordbNativeCode(CordbFunction * pFunction,
5820 const NativeCodeFunctionData * pJitData,
5821 BOOL fIsInstantiatedGeneric);
5823 const char * DbgGetName() { return "CordbNativeCode"; };
5826 ULONG STDMETHODCALLTYPE AddRef()
5828 return (BaseAddRef());
5830 ULONG STDMETHODCALLTYPE Release()
5832 return (BaseRelease());
5834 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
5836 //-----------------------------------------------------------
5838 //-----------------------------------------------------------
5839 COM_METHOD GetAddress(CORDB_ADDRESS * pStart);
5840 COM_METHOD GetILToNativeMapping(ULONG32 cMap,
5842 COR_DEBUG_IL_TO_NATIVE_MAP map[]);
5843 //-----------------------------------------------------------
5845 //-----------------------------------------------------------
5846 COM_METHOD GetCodeChunks(ULONG32 cbufSize, ULONG32 * pcnumChunks, CodeChunkInfo chunks[]);
5848 COM_METHOD GetCompilerFlags(DWORD * pdwFlags);
5850 //-----------------------------------------------------------
5852 //-----------------------------------------------------------
5853 COM_METHOD GetReturnValueLiveOffset(ULONG32 ILoffset, ULONG32 bufferSize, ULONG32 *pFetched, ULONG32 *pOffsets);
5856 //-----------------------------------------------------------
5858 //-----------------------------------------------------------
5860 HRESULT ILVariableToNative(DWORD dwIndex,
5862 const ICorDebugInfo::NativeVarInfo ** ppNativeInfo);
5863 void LoadNativeInfo();
5865 //-----------------------------------------------------------
5866 // Accessors and convenience routines
5867 //-----------------------------------------------------------
5869 // get the argument type for a generic
5870 void GetArgumentType(DWORD dwIndex,
5871 const Instantiation * pInst,
5872 CordbType ** ppResultType)
5874 CordbFunction * pFunction = GetFunction();
5875 _ASSERTE(pFunction != NULL);
5876 IfFailThrow(pFunction->GetArgumentType(dwIndex, pInst, ppResultType));
5879 // Quick helper for internall access to: GetAddress(CORDB_ADDRESS *pStart);
5880 CORDB_ADDRESS GetAddress() { return m_rgCodeRegions[kHot].pAddress; };
5882 VMPTR_MethodDesc GetVMNativeCodeMethodDescToken() { return m_vmNativeCodeMethodDescToken; };
5884 // Worker function for GetReturnValueLiveOffset.
5885 HRESULT GetReturnValueLiveOffsetImpl(Instantiation *currentInstantiation, ULONG32 ILoffset, ULONG32 bufferSize, ULONG32 *pFetched, ULONG32 *pOffsets);
5887 // get total size of the code including both hot and cold regions
5890 // get the size of the cold region(s) only
5891 ULONG32 GetColdSize();
5893 // Return true if the Code is split into hot + cold regions.
5894 bool HasColdRegion() { return m_rgCodeRegions[kCold].pAddress != NULL; }
5896 // Get the number of fixed arguments for this function (the "this"
5898 unsigned int GetFixedArgCount()
5900 return m_nativeVarData.GetFixedArgCount();
5903 // Get the number of all arguments for this function
5904 // ("this" pointer, fixed args and varargs)
5905 ULONG32 GetAllArgsCount()
5907 return m_nativeVarData.GetAllArgsCount();
5910 void SetAllArgsCount(ULONG32 count)
5912 m_nativeVarData.SetAllArgsCount(count);
5915 // Determine whether this is an instantiation of a generic function
5916 BOOL IsInstantiatedGeneric()
5918 return m_fIsInstantiatedGeneric != 0;
5921 // Determine whether we have initialized the native variable and
5922 // sequence point offsets
5923 BOOL IsNativeCodeValid ()
5925 return ((m_nativeVarData.IsInitialized() != 0) &&
5926 (m_sequencePoints.IsInitialized() != 0));
5929 SequencePoints * GetSequencePoints()
5931 return &m_sequencePoints;
5935 // Given an ILOffset in the current function, return the class token and function token of the IL call target at that
5936 // location. Also fill "methodSig" with the method's signature and "genericSig" with the method's generic signature.
5937 HRESULT GetCallSignature(ULONG32 ILOffset, mdToken *pClass, mdToken *pMDFunction, SigParser &methodSig, SigParser &genericSig);
5939 // Moves a method signature from the start of the signature to the location of the return value (passing out the
5940 // number of generic parameters in the method).
5941 static HRESULT SkipToReturn(SigParser &parser, ULONG *genArgCount = 0);
5944 // Read the actual bytes of native code into the data member m_rgbCode.
5945 // Helper routine for GetCode
5946 HRESULT ReadCodeBytes();
5948 // Returns a failure HRESULT if we cannot handle the return value of the given
5949 // methodref, methoddef, or methodspec token, otherwise S_OK. Does NOT return S_FALSE;
5950 HRESULT EnsureReturnValueAllowed(Instantiation *currentInstantiation, mdToken targetClass, SigParser &parser, SigParser &methodGenerics);
5951 HRESULT EnsureReturnValueAllowedWorker(Instantiation *currentInstantiation, mdToken targetClass, SigParser &parser, SigParser &methodGenerics, ULONG genCount);
5953 // Grabs the appropriate signature parser for a methodref, methoddef, methodspec.
5954 HRESULT GetSigParserFromFunction(mdToken mdFunction, mdToken *pClass, SigParser &methodSig, SigParser &genericSig);
5956 int GetCallInstructionLength(BYTE *buffer, ULONG32 len);
5958 //-----------------------------------------------------------
5960 //-----------------------------------------------------------
5962 // offset of the beginning of the last sequence point in the sequence point map
5965 // start address(es) and size(s) of hot and cold regions
5966 TargetBuffer m_rgCodeRegions[MAX_REGIONS];
5968 // LS data structure--method desc for this instantiation.
5969 VMPTR_MethodDesc m_vmNativeCodeMethodDescToken;
5971 bool m_fCodeAvailable; // true iff the code has been jitted but not pitched
5973 bool m_fIsInstantiatedGeneric; // true iff this is an instantiated generic
5975 // information in the following two classes tracks native offsets and is initialized on demand.
5977 // location and ID information for local variables. See code:NativeVarData for details.
5978 NativeVarData m_nativeVarData;
5980 // mapping between IL and native code sequence points.
5981 SequencePoints m_sequencePoints;
5983 }; //class CordbNativeCode
5985 //---------------------------------------------------------------------------------------
5987 // GetActiveInternalFramesData is used to enumerate internal frames on a specific thread.
5988 // It is used in conjunction with code:CordbThread::GetActiveInternalFramesCallback.
5989 // We store each internal frame in ppInternalFrames as we enumerate them.
5992 struct GetActiveInternalFramesData
5995 // the thread we are walking
5996 CordbThread * pThis;
5998 // an array to store the internal frames
5999 RSPtrArray<CordbInternalFrame> pInternalFrames;
6001 // next element in the array to be filled
6006 /* ------------------------------------------------------------------------- *
6008 * ------------------------------------------------------------------------- */
6010 class CordbThread : public CordbBase, public ICorDebugThread,
6011 public ICorDebugThread2,
6012 public ICorDebugThread3,
6013 public ICorDebugThread4
6016 CordbThread(CordbProcess * pProcess, VMPTR_Thread);
6018 virtual ~CordbThread();
6019 virtual void Neuter();
6021 using CordbBase::GetProcess;
6024 virtual const char * DbgGetName() { return "CordbThread"; }
6027 //-----------------------------------------------------------
6029 //-----------------------------------------------------------
6031 ULONG STDMETHODCALLTYPE AddRef()
6033 // there's an external add ref from within RS in CordbEnumFilter
6034 return (BaseAddRef());
6036 ULONG STDMETHODCALLTYPE Release()
6038 return (BaseRelease());
6040 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
6042 //-----------------------------------------------------------
6044 //-----------------------------------------------------------
6046 COM_METHOD GetProcess(ICorDebugProcess **ppProcess);
6047 COM_METHOD GetID(DWORD *pdwThreadId);
6048 COM_METHOD GetHandle(HANDLE * phThreadHandle);
6049 COM_METHOD GetAppDomain(ICorDebugAppDomain **ppAppDomain);
6050 COM_METHOD SetDebugState(CorDebugThreadState state);
6051 COM_METHOD GetDebugState(CorDebugThreadState *pState);
6052 COM_METHOD GetUserState(CorDebugUserState *pState);
6053 COM_METHOD GetCurrentException(ICorDebugValue ** ppExceptionObject);
6054 COM_METHOD ClearCurrentException();
6055 COM_METHOD CreateStepper(ICorDebugStepper **ppStepper);
6056 COM_METHOD EnumerateChains(ICorDebugChainEnum **ppChains);
6057 COM_METHOD GetActiveChain(ICorDebugChain **ppChain);
6058 COM_METHOD GetActiveFrame(ICorDebugFrame **ppFrame);
6059 COM_METHOD GetRegisterSet(ICorDebugRegisterSet **ppRegisters);
6060 COM_METHOD CreateEval(ICorDebugEval **ppEval);
6061 COM_METHOD GetObject(ICorDebugValue ** ppObject);
6064 COM_METHOD GetConnectionID(CONNID * pConnectionID);
6065 COM_METHOD GetTaskID(TASKID * pTaskID);
6066 COM_METHOD GetVolatileOSThreadID(DWORD * pdwTID);
6067 COM_METHOD GetActiveFunctions(ULONG32 cFunctions, ULONG32 * pcFunctions, COR_ACTIVE_FUNCTION pFunctions[]);
6068 // Intercept the current exception at the specified frame. pFrame must be a valid ICDFrame, possibly from
6069 // a previous stackwalk.
6070 COM_METHOD InterceptCurrentException(ICorDebugFrame * pFrame);
6075 COM_METHOD CreateStackWalk(ICorDebugStackWalk **ppStackWalk);
6077 COM_METHOD GetActiveInternalFrames(ULONG32 cInternalFrames,
6078 ULONG32 * pcInternalFrames,
6079 ICorDebugInternalFrame2 * ppInternalFrames[]);
6082 COM_METHOD HasUnhandledException();
6084 COM_METHOD GetBlockingObjects(ICorDebugBlockingObjectEnum **ppBlockingObjectEnum);
6086 // Gets the current CustomNotification object from the thread or NULL if no such object exists
6087 COM_METHOD GetCurrentCustomDebuggerNotification(ICorDebugValue ** ppNotificationObject);
6088 //-----------------------------------------------------------
6090 //-----------------------------------------------------------
6092 // callback used to enumerate the internal frames on a thread
6093 static void GetActiveInternalFramesCallback(const DebuggerIPCE_STRData * pFrameData,
6096 CorDebugUserState GetUserState();
6098 // Given a FramePointer, find the matching CordbFrame.
6099 HRESULT FindFrame(ICorDebugFrame ** ppFrame, FramePointer fp);
6101 // Get the task ID for this thread.
6104 void RefreshStack();
6105 void CleanupStack();
6106 void MarkStackFramesDirty();
6108 #if !defined(DBG_TARGET_ARM) // @ARMTODO
6110 #if defined(DBG_TARGET_X86)
6111 // Converts the values in the floating point register area of the context to real number values.
6112 void Get32bitFPRegisters(CONTEXT * pContext);
6114 #elif defined(DBG_TARGET_AMD64)
6115 // Converts the values in the floating point register area of the context to real number values.
6116 void Get64bitFPRegisters(FPRegister64 * rgContextFPRegisters, int start, int nRegisters);
6117 #endif // DBG_TARGET_X86
6119 // Initializes the float state members of this instance of CordbThread. This function gets the context and
6120 // converts the floating point values from their context representation to real number values.
6121 void LoadFloatState();
6123 #endif //!DBG_TARGET_ARM @ARMTODO
6125 HRESULT SetIP( bool fCanSetIPOnly,
6126 CordbNativeCode * pNativeCode,
6130 // Tells the LS to remap to the latest version of the function
6131 HRESULT SetRemapIP(SIZE_T offset);
6133 // Ask the left-side for the current (up-to-date) AppDomain of this thread's IP.
6134 // This should be preferred over using the cached value from GetAppDomain.
6135 HRESULT GetCurrentAppDomain(CordbAppDomain ** ppAppDomain);
6137 //-----------------------------------------------------------
6138 // Convenience routines
6139 //-----------------------------------------------------------
6141 // The last domain from which a debug event for this thread was sent.
6142 // This usually (but not always) the domain the thread is currently executing in.
6143 // Since this is a cache, it may sometimes be out-of-date. I believe all current
6144 // usage of this is OK (we pass AppDomains around a lot without really using them),
6145 // but no new code should rely on this value.
6146 // TODO: eliminate this and the m_pAppDomain field entirely
6147 CordbAppDomain *GetAppDomain()
6149 return (m_pAppDomain);
6152 DWORD GetVolatileOSThreadID();
6154 //////////////////////////////////////////////////////////////////////////
6158 // <TODO>TODO: Since Thread will share the memory with RegisterSets, how
6159 // do we know that the RegisterSets have relinquished all pointers
6160 // to the m_pContext structure?</TODO>
6162 // Returns: NULL if the thread's CONTEXT structure couldn't be obtained
6163 // A pointer to the CONTEXT otherwise.
6166 //////////////////////////////////////////////////////////////////////////
6167 HRESULT GetManagedContext( DT_CONTEXT ** ppContext );
6168 HRESULT SetManagedContext( DT_CONTEXT * pContext );
6170 // API to retrieve the thread handle from the LS.
6171 void InternalGetHandle(HANDLE * phThread);
6172 void RefreshHandle(HANDLE * phThread);
6174 // NeuterList that's executed when this Thread's stack is refreshed.
6175 // Chain + Frame + some Value enums can be held on this.
6176 NeuterList * GetRefreshStackNeuterList()
6178 return &m_RefreshStackNeuterList;
6181 DWORD GetUniqueId();
6184 // Hijack a thread at a 2nd-chance exception so that it can execute the CLR's UEF
6185 void HijackForUnhandledException();
6187 // check whether the specified frame lives on the stack of the current thread
6188 bool OwnsFrame(CordbFrame *pFrame);
6190 // Specify that there's an outstanding exception on this thread.
6191 void SetExInfo(VMPTR_OBJECTHANDLE vmExcepObjHandle);
6193 VMPTR_OBJECTHANDLE GetThreadExceptionRawObjectHandle() { return m_vmExcepObjHandle; }
6194 bool HasException() { return m_fException; }
6196 void SetUnhandledNativeException(const EXCEPTION_RECORD * pExceptionRecord);
6197 bool HasUnhandledNativeException();
6200 // Helper to assert that this thread no longer appears in dac-dbi enumerations
6201 void DbgAssertThreadDeleted();
6203 // Callback for DbgAssertThreadDeleted
6204 static void DbgAssertThreadDeletedCallback(VMPTR_Thread vmThread, void * pUserData);
6207 // Determine if the thread's current exception is managed or unmanaged.
6208 BOOL IsThreadExceptionManaged();
6210 // This is a private hook for the shim to create a CordbRegisterSet for a ShimChain.
6211 void CreateCordbRegisterSet(DT_CONTEXT * pContext,
6213 CorDebugChainReason reason,
6214 ICorDebugRegisterSet ** ppRegSet);
6216 // This is a private hook for the shim to convert an ICDFrame into an ICDInternalFrame for a dynamic
6217 // method. Refer to the function header for more information.
6218 BOOL ConvertFrameForILMethodWithoutMetadata(ICorDebugFrame * pFrame,
6219 ICorDebugInternalFrame2 ** ppInternalFrame2);
6221 // Gets/sets m_fCreationEventQueued
6222 bool CreateEventWasQueued();
6223 void SetCreateEventQueued();
6225 //-----------------------------------------------------------
6227 //-----------------------------------------------------------
6230 // RS Cache for LS context.
6231 // NULL if we haven't allocated memory for a Right side context
6232 DT_CONTEXT * m_pContext;
6234 // Set to the CONTEXT pointer in the LS if this LS thread is
6235 // stopped in managed code. This may be either stopped for execution control
6236 // (breakpoint / single-step exception) or hijacked w/ a redirected frame because
6237 // another thread synced the LS.
6238 // This context is used by the RS to set enregistered vars.
6239 VMPTR_CONTEXT m_vmLeftSideContext;
6241 // indicates whether m_pContext is up-to-date
6242 bool m_fContextFresh;
6244 // last domain we've seen this thread.
6245 // If the appdomain exits, it will clear out this value.
6246 CordbAppDomain *m_pAppDomain;
6248 // Handle to VM's Thread* object. This is the primary key for a CordbThread object
6249 // @dbgtodo ICDThread - merge with m_id;
6250 VMPTR_Thread m_vmThreadToken;
6252 // Unique ID for this thread. See code:CordbThread::GetID for semantics of this field.
6255 CorDebugThreadState m_debugState; // Note that this is for resume
6256 // purposes, NOT the current state of
6259 // The frames are all protected under the Stop-Go lock.
6260 // This field indicates whether the stack is valid (i.e. no update is necessary).
6261 bool m_fFramesFresh;
6263 // This is a cache of V3 ICDFrames. The cache is only used by two functions:
6264 // - code:CordbThread::GetActiveFunctions
6265 // - code:CordbThread::InterceptCurrentException.
6267 // We don't clear the cache in CleanupStack() because we don't refresh the cache every time we stop.
6268 // Instead, we mark m_fFramesFresh in CleanupStack() and clear the cache only when it is used next time.
6269 CDynArray<CordbFrame *> m_stackFrames;
6271 #if !defined(DBG_TARGET_ARM) // @ARMTODO
6272 bool m_fFloatStateValid;
6273 unsigned int m_floatStackTop;
6274 double m_floatValues[DebuggerIPCE_FloatCount];
6275 #endif // !DBG_TARGET_ARM @ARMTODO
6278 // True for the window after an Exception callback, but before it's been continued.
6279 // We dispatch two exception events in a row (ICDManagedCallback::Exception and ICDManagedCallback2::Exception),
6280 // and a debugger may normally just skip the first one knowing it can stop on the 2nd once.
6281 // Both events will set this bit high. Be careful not to reset this bit inbetween them.
6284 // True if a creation event has been queued for this thread
6285 // The event may or may not have been dispatched yet
6286 // Bugfix DevDiv2\DevDiv 77523 - this is only being set from ShimProcess::QueueFakeThreadAttachEventsNativeOrder
6287 bool m_fCreationEventQueued;
6289 // Object handle for Exception object in debuggee.
6290 VMPTR_OBJECTHANDLE m_vmExcepObjHandle;
6294 //Returns true if current user state of a thread is USER_WAIT_SLEEP_JOIN
6295 bool IsThreadWaitingOrSleeping();
6297 // Returns true if the thread is dead. See function header for definition.
6298 bool IsThreadDead();
6300 // Return CORDBG_E_BAD_THREAD_STATE if the thread is dead.
6301 HRESULT EnsureThreadIsAlive();
6303 // On a RemapBreakpoint, the debugger will eventually call RemapFunction and
6304 // we need to communicate the IP back to LS. So we stash the address of where
6305 // to store the IP here and stuff it in on RemapFunction.
6306 // If we're not at an outstanding RemapOpportunity, this will be NULL
6307 REMOTE_PTR m_EnCRemapFunctionIP;
6310 void ClearStackFrameCache();
6312 // True iff this thread has an unhandled exception on it.
6313 // Set high when Filter() gets noitifed of an unhandled exception.
6314 // Set Low if the thread is hijacked.
6315 bool m_fHasUnhandledException;
6317 // Exception record for last unhandled exception on this thread.
6318 // Lazily initialized.
6319 EXCEPTION_RECORD * m_pExceptionRecord;
6321 static const CorDebugUserState kInvalidUserState = CorDebugUserState(-1);
6322 CorDebugUserState m_userState; // This is the current state of the
6323 // thread, at the time that the
6324 // left side synchronized
6326 // NeuterList that's executed when this Thread's stack is refreshed.
6327 // This list is for everything related to stackwalking, i.e. everything which is invalidated
6328 // if the stack changes in any way. This list is cleared when any of the following is called:
6331 // 3) RemapFunction()
6332 // 4) ICDProcess::SetThreadContext()
6333 NeuterList m_RefreshStackNeuterList;
6335 // The following two data members are used for caching thread handles.
6336 // @dbgtodo - Remove in V3 (can't have local handles with data-target abstraction);
6337 // offload to the shim to support V2 scenarios.
6338 HANDLE m_hCachedThread;
6339 HANDLE m_hCachedOutOfProcThread;
6342 /* ------------------------------------------------------------------------- *
6344 * ------------------------------------------------------------------------- */
6346 class CordbStackWalk : public CordbBase, public ICorDebugStackWalk
6349 CordbStackWalk(CordbThread * pCordbThread);
6350 virtual ~CordbStackWalk();
6351 virtual void Neuter();
6353 // helper function for Neuter
6354 virtual void DeleteAll();
6356 using CordbBase::GetProcess;
6359 virtual const char * DbgGetName() { return "CordbStackWalk"; }
6362 //-----------------------------------------------------------
6364 //-----------------------------------------------------------
6366 ULONG STDMETHODCALLTYPE AddRef()
6368 return (BaseAddRef());
6370 ULONG STDMETHODCALLTYPE Release()
6372 return (BaseRelease());
6374 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
6376 //-----------------------------------------------------------
6377 // ICorDebugStackWalk
6378 //-----------------------------------------------------------
6380 COM_METHOD GetContext(ULONG32 contextFlags,
6381 ULONG32 contextBufSize,
6382 ULONG32 * pContextSize,
6383 BYTE pbContextBuf[]);
6384 COM_METHOD SetContext(CorDebugSetContextFlag flag, ULONG32 contextSize, BYTE context[]);
6386 COM_METHOD GetFrame(ICorDebugFrame **ppFrame);
6388 //-----------------------------------------------------------
6390 //-----------------------------------------------------------
6392 void SetContextWorker(CorDebugSetContextFlag flag, ULONG32 contextSize, BYTE context[]);
6393 HRESULT GetFrameWorker(ICorDebugFrame **ppFrame);
6395 //-----------------------------------------------------------
6397 //-----------------------------------------------------------
6403 // handle legacy V2 hijacking for unhandled hardware exceptions
6404 void CheckForLegacyHijackCase();
6406 // refresh the data for this instance of CordbStackWalk if we have had an IPC event followed by a
6407 // continue since we got the information.
6408 void RefreshIfNeeded();
6410 // unwind the frame and update m_context with the new context
6411 BOOL UnwindStackFrame();
6413 // the thread on which this CordbStackWalk is created
6414 CordbThread * m_pCordbThread;
6416 // This is the same iterator used by the runtime itself.
6417 IDacDbiInterface::StackWalkHandle m_pSFIHandle;
6419 // buffers used for stackwalking
6420 DT_CONTEXT m_context;
6422 // Used to figure out if we have to refresh any reference objects
6423 // on the left side. We set it to CordbProcess::m_flushCounter on
6424 // creation and will check it against that value when we call GetFrame or Next.
6425 // If it doesn't match, an IPC event has occurred and the values will need to be
6426 // refreshed via the DAC.
6427 UINT m_lastSyncFlushCounter;
6429 // cached flag used for refreshing a CordbStackWalk
6430 CorDebugSetContextFlag m_cachedSetContextFlag;
6432 // We unwind one frame ahead of time to get the FramePointer on x86.
6433 // These fields are used for the bookkeeping.
6434 RSSmartPtr<CordbFrame> m_pCachedFrame;
6436 bool m_fIsOneFrameAhead;
6440 class CordbContext : public CordbBase, public ICorDebugContext
6444 CordbContext() : CordbBase(NULL, 0, enumCordbContext) {}
6449 virtual const char * DbgGetName() { return "CordbContext"; }
6453 //-----------------------------------------------------------
6455 //-----------------------------------------------------------
6457 ULONG STDMETHODCALLTYPE AddRef()
6459 return (BaseAddRef());
6461 ULONG STDMETHODCALLTYPE Release()
6463 return (BaseRelease());
6465 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
6467 //-----------------------------------------------------------
6469 //-----------------------------------------------------------
6475 /* ------------------------------------------------------------------------- *
6477 * ------------------------------------------------------------------------- */
6479 class CordbFrame : public CordbBase, public ICorDebugFrame
6482 // Ctor to provide dummy frame that just wraps a frame-pointer
6483 CordbFrame(CordbProcess * pProcess, FramePointer fp);
6486 CordbFrame(CordbThread * pThread,
6489 CordbAppDomain * pCurrentAppDomain);
6491 virtual ~CordbFrame();
6492 virtual void Neuter();
6495 virtual const char * DbgGetName() { return "CordbFrame"; }
6498 //-----------------------------------------------------------
6500 //-----------------------------------------------------------
6502 ULONG STDMETHODCALLTYPE AddRef()
6504 return (BaseAddRef());
6506 ULONG STDMETHODCALLTYPE Release()
6508 return (BaseRelease());
6510 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
6512 //-----------------------------------------------------------
6514 //-----------------------------------------------------------
6516 COM_METHOD GetChain(ICorDebugChain **ppChain);
6518 // Derived versions of Frame will implement GetCode.
6519 COM_METHOD GetCode(ICorDebugCode **ppCode) = 0;
6521 COM_METHOD GetFunction(ICorDebugFunction **ppFunction);
6522 COM_METHOD GetFunctionToken(mdMethodDef *pToken);
6524 COM_METHOD GetStackRange(CORDB_ADDRESS *pStart, CORDB_ADDRESS *pEnd);
6525 COM_METHOD GetCaller(ICorDebugFrame **ppFrame);
6526 COM_METHOD GetCallee(ICorDebugFrame **ppFrame);
6527 COM_METHOD CreateStepper(ICorDebugStepper **ppStepper);
6529 //-----------------------------------------------------------
6530 // Convenience routines
6531 //-----------------------------------------------------------
6533 CordbAppDomain *GetCurrentAppDomain()
6535 return m_currentAppDomain;
6538 // Internal helper to get a CordbFunction for this frame.
6539 virtual CordbFunction *GetFunction() = 0;
6541 FramePointer GetFramePointer()
6546 //-----------------------------------------------------------
6548 //-----------------------------------------------------------
6550 // Accessors to return NULL or typesafe cast to derived frame
6551 virtual CordbInternalFrame * GetAsInternalFrame() { return NULL; }
6552 virtual CordbNativeFrame * GetAsNativeFrame() { return NULL; }
6554 // determine if the frame pointer is in the stack range owned by the frame
6555 bool IsContainedInFrame(FramePointer fp);
6557 // This is basically a complicated cast function. We are casting from an ICorDebugFrame to a CordbFrame.
6558 static CordbFrame* GetCordbFrameFromInterface(ICorDebugFrame *pFrame);
6560 virtual const DT_CONTEXT * GetContext() const { return NULL; }
6563 // this represents the IL offset for a CordbJITILFrame, the native offset for a CordbNativeFrame,
6564 // and 0 for a CordbInternalFrame
6567 CordbThread * m_pThread;
6569 CordbAppDomain *m_currentAppDomain;
6573 // indicates whether this frame is the leaf frame; lazily initialized
6574 mutable Optional<bool> m_optfIsLeafFrame;
6578 // For tracking down neutering bugs;
6579 UINT m_DbgContinueCounter;
6583 // Dummy frame that just wraps a frame pointer.
6584 // This is used to pass a FramePointer back in the Exception2 callback.
6585 // Currently, the callback passes back an ICorDebugFrame as a way of exposing a cross-platform
6586 // frame pointer. However passing back an ICDFrame means we need to do a stackwalk, and
6587 // that may not be possible in V3:
6588 // - the stackwalk is very chatty, and may be too much work just to give an exception notification.
6589 // - in 64-bit, we may not even be able to do the stackwalk ourselves.
6591 // The shim can take the framePointer and do the stackwalk and resolve it to a real frame,
6592 // so V2 emulation scenarios will continue to work.
6593 // @dbgtodo exception - resolve this when we iron out exceptions in V3.
6594 class CordbPlaceholderFrame : public CordbFrame
6597 // Ctor to provide dummy frame that just wraps a frame-pointer
6598 CordbPlaceholderFrame(CordbProcess * pProcess, FramePointer fp)
6599 : CordbFrame(pProcess, fp)
6604 virtual const char * DbgGetName() { return "CordbFrame"; }
6607 // Provide dummy implementation for some methods. These should never be called.
6608 COM_METHOD GetCode(ICorDebugCode **ppCode)
6610 _ASSERTE(!"Don't call this");
6613 virtual CordbFunction *GetFunction()
6615 _ASSERTE(!"Don't call this");
6620 class CordbInternalFrame : public CordbFrame, public ICorDebugInternalFrame, public ICorDebugInternalFrame2
6623 CordbInternalFrame(CordbThread * pThread,
6625 CordbAppDomain * pCurrentAppDomain,
6626 const DebuggerIPCE_STRData * pData);
6628 CordbInternalFrame(CordbThread * pThread,
6630 CordbAppDomain * pCurrentAppDomain,
6631 CorDebugInternalFrameType frameType,
6632 mdMethodDef funcMetadataToken,
6633 CordbFunction * pFunction,
6634 VMPTR_MethodDesc vmMethodDesc);
6636 virtual void Neuter();
6639 virtual const char * DbgGetName() { return "CordbInternalFrame"; }
6642 //-----------------------------------------------------------
6644 //-----------------------------------------------------------
6646 ULONG STDMETHODCALLTYPE AddRef()
6648 return (BaseAddRef());
6650 ULONG STDMETHODCALLTYPE Release()
6652 return (BaseRelease());
6654 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
6656 //-----------------------------------------------------------
6658 //-----------------------------------------------------------
6660 COM_METHOD GetChain(ICorDebugChain **ppChain)
6662 return (CordbFrame::GetChain(ppChain));
6665 // We don't expose a code-object for stubs.
6666 COM_METHOD GetCode(ICorDebugCode **ppCode)
6668 return CORDBG_E_CODE_NOT_AVAILABLE;
6671 COM_METHOD GetFunction(ICorDebugFunction **ppFunction)
6673 return (CordbFrame::GetFunction(ppFunction));
6675 COM_METHOD GetFunctionToken(mdMethodDef *pToken)
6677 return (CordbFrame::GetFunctionToken(pToken));
6680 COM_METHOD GetCaller(ICorDebugFrame **ppFrame)
6682 return (CordbFrame::GetCaller(ppFrame));
6684 COM_METHOD GetCallee(ICorDebugFrame **ppFrame)
6686 return (CordbFrame::GetCallee(ppFrame));
6688 COM_METHOD CreateStepper(ICorDebugStepper **ppStepper)
6693 COM_METHOD GetStackRange(CORDB_ADDRESS *pStart, CORDB_ADDRESS *pEnd);
6695 //-----------------------------------------------------------
6696 // ICorDebugInternalFrame
6697 //-----------------------------------------------------------
6699 // Get the type of internal frame. This will never be STUBFRAME_NONE.
6700 COM_METHOD GetFrameType(CorDebugInternalFrameType * pType)
6702 VALIDATE_POINTER_TO_OBJECT(pType, CorDebugInternalFrameType)
6703 *pType = m_eFrameType;
6707 //-----------------------------------------------------------
6708 // ICorDebugInternalFrame2
6709 //-----------------------------------------------------------
6711 COM_METHOD GetAddress(CORDB_ADDRESS * pAddress);
6712 COM_METHOD IsCloserToLeaf(ICorDebugFrame * pFrameToCompare,
6715 BOOL IsCloserToLeafWorker(ICorDebugFrame * pFrameToCompare);
6717 //-----------------------------------------------------------
6719 //-----------------------------------------------------------
6721 virtual CordbFunction *GetFunction();
6724 // Accessors to return NULL or typesafe cast to derived frame
6725 virtual CordbInternalFrame * GetAsInternalFrame() { return this; }
6727 // accessor for the shim private hook code:CordbThread::ConvertFrameForILMethodWithoutMetadata
6728 BOOL ConvertInternalFrameForILMethodWithoutMetadata(ICorDebugInternalFrame2 ** ppInternalFrame2);
6732 CorDebugInternalFrameType m_eFrameType;
6734 // the method token of the method (if any) associated with the internal frame
6735 mdMethodDef m_funcMetadataToken;
6737 // the method (if any) associated with the internal frame
6738 RSSmartPtr<CordbFunction> m_function;
6740 VMPTR_MethodDesc m_vmMethodDesc;
6743 //---------------------------------------------------------------------------------------
6745 // This class implements ICorDebugRuntimeUnwindableFrame. It is used to mark a native stack frame
6746 // which requires special unwinding and which doesn't correspond to any IL code. It is really
6747 // just a marker to tell the debugger to use the managed unwinder. The debugger is still responsible
6748 // to do all the inspection and symbol lookup. An example is the hijack stub.
6751 class CordbRuntimeUnwindableFrame : public CordbFrame, public ICorDebugRuntimeUnwindableFrame
6754 CordbRuntimeUnwindableFrame(CordbThread * pThread,
6756 CordbAppDomain * pCurrentAppDomain,
6757 DT_CONTEXT * pContext);
6759 virtual void Neuter();
6762 virtual const char * DbgGetName() { return "CordbRuntimeUnwindableFrame"; }
6765 //-----------------------------------------------------------
6767 //-----------------------------------------------------------
6769 ULONG STDMETHODCALLTYPE AddRef()
6771 return (BaseAddRef());
6774 ULONG STDMETHODCALLTYPE Release()
6776 return (BaseRelease());
6779 COM_METHOD QueryInterface(REFIID riid, void ** ppInterface);
6781 //-----------------------------------------------------------
6783 //-----------------------------------------------------------
6786 // Just return E_NOTIMPL for everything.
6787 // See the class comment.
6790 COM_METHOD GetChain(ICorDebugChain ** ppChain)
6795 COM_METHOD GetCode(ICorDebugCode ** ppCode)
6800 COM_METHOD GetFunction(ICorDebugFunction ** ppFunction)
6805 COM_METHOD GetFunctionToken(mdMethodDef * pToken)
6810 COM_METHOD GetCaller(ICorDebugFrame ** ppFrame)
6815 COM_METHOD GetCallee(ICorDebugFrame ** ppFrame)
6820 COM_METHOD CreateStepper(ICorDebugStepper ** ppStepper)
6825 COM_METHOD GetStackRange(CORDB_ADDRESS * pStart, CORDB_ADDRESS * pEnd)
6830 //-----------------------------------------------------------
6832 //-----------------------------------------------------------
6834 virtual CordbFunction * GetFunction()
6839 virtual const DT_CONTEXT * GetContext() const;
6842 DT_CONTEXT m_context;
6846 class CordbValueEnum : public CordbBase, public ICorDebugValueEnum
6849 enum ValueEnumMode {
6850 LOCAL_VARS_ORIGINAL_IL,
6851 LOCAL_VARS_REJIT_IL,
6855 CordbValueEnum(CordbNativeFrame *frame, ValueEnumMode mode);
6858 virtual void Neuter();
6861 virtual const char * DbgGetName() { return "CordbValueEnum"; }
6865 //-----------------------------------------------------------
6867 //-----------------------------------------------------------
6869 ULONG STDMETHODCALLTYPE AddRef()
6871 return (BaseAddRef());
6873 ULONG STDMETHODCALLTYPE Release()
6875 return (BaseRelease());
6877 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
6879 //-----------------------------------------------------------
6881 //-----------------------------------------------------------
6883 COM_METHOD Skip(ULONG celt);
6885 COM_METHOD Clone(ICorDebugEnum **ppEnum);
6886 COM_METHOD GetCount(ULONG *pcelt);
6888 //-----------------------------------------------------------
6889 // ICorDebugValueEnum
6890 //-----------------------------------------------------------
6892 COM_METHOD Next(ULONG celt, ICorDebugValue *values[], ULONG *pceltFetched);
6895 CordbNativeFrame* m_frame;
6896 ValueEnumMode m_mode;
6902 /* ------------------------------------------------------------------------- *
6903 * Misc Info for the Native Frame class
6904 * ------------------------------------------------------------------------- */
6906 struct CordbMiscFrame
6911 // new-style constructor
6912 CordbMiscFrame(DebuggerIPCE_JITFuncData * pJITFuncData);
6914 #if defined(DBG_TARGET_WIN64) || defined(DBG_TARGET_ARM)
6916 FramePointer fpParentOrSelf;
6917 bool fIsFilterFunclet;
6918 #endif // DBG_TARGET_WIN64 || DBG_TARGET_ARM
6922 /* ------------------------------------------------------------------------- *
6923 * Native Frame class
6924 * ------------------------------------------------------------------------- */
6926 class CordbNativeFrame : public CordbFrame, public ICorDebugNativeFrame, public ICorDebugNativeFrame2
6929 CordbNativeFrame(CordbThread * pThread,
6931 CordbNativeCode * pNativeCode,
6933 DebuggerREGDISPLAY * pDRD,
6934 TADDR addrAmbientESP,
6935 bool fQuicklyUnwound,
6936 CordbAppDomain * pCurrentAppDomain,
6937 CordbMiscFrame * pMisc = NULL,
6938 DT_CONTEXT * pContext = NULL);
6939 virtual ~CordbNativeFrame();
6940 virtual void Neuter();
6943 virtual const char * DbgGetName() { return "CordbNativeFrame"; }
6946 //-----------------------------------------------------------
6948 //-----------------------------------------------------------
6950 ULONG STDMETHODCALLTYPE AddRef()
6952 return (BaseAddRef());
6954 ULONG STDMETHODCALLTYPE Release()
6956 return (BaseRelease());
6958 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
6960 //-----------------------------------------------------------
6962 //-----------------------------------------------------------
6964 COM_METHOD GetChain(ICorDebugChain **ppChain)
6966 return (CordbFrame::GetChain(ppChain));
6968 COM_METHOD GetCode(ICorDebugCode **ppCode);
6969 COM_METHOD GetFunction(ICorDebugFunction **ppFunction)
6971 return (CordbFrame::GetFunction(ppFunction));
6973 COM_METHOD GetFunctionToken(mdMethodDef *pToken)
6975 return (CordbFrame::GetFunctionToken(pToken));
6977 COM_METHOD GetCaller(ICorDebugFrame **ppFrame)
6979 return (CordbFrame::GetCaller(ppFrame));
6981 COM_METHOD GetCallee(ICorDebugFrame **ppFrame)
6983 return (CordbFrame::GetCallee(ppFrame));
6985 COM_METHOD CreateStepper(ICorDebugStepper **ppStepper)
6987 return (CordbFrame::CreateStepper(ppStepper));
6990 COM_METHOD GetStackRange(CORDB_ADDRESS *pStart, CORDB_ADDRESS *pEnd);
6992 //-----------------------------------------------------------
6993 // ICorDebugNativeFrame
6994 //-----------------------------------------------------------
6996 COM_METHOD GetIP(ULONG32* pnOffset);
6997 COM_METHOD SetIP(ULONG32 nOffset);
6998 COM_METHOD GetRegisterSet(ICorDebugRegisterSet **ppRegisters);
6999 COM_METHOD GetLocalRegisterValue(CorDebugRegister reg,
7001 PCCOR_SIGNATURE pvSigBlob,
7002 ICorDebugValue ** ppValue);
7004 COM_METHOD GetLocalDoubleRegisterValue(CorDebugRegister highWordReg,
7005 CorDebugRegister lowWordReg,
7007 PCCOR_SIGNATURE pvSigBlob,
7008 ICorDebugValue ** ppValue);
7010 COM_METHOD GetLocalMemoryValue(CORDB_ADDRESS address,
7012 PCCOR_SIGNATURE pvSigBlob,
7013 ICorDebugValue ** ppValue);
7015 COM_METHOD GetLocalRegisterMemoryValue(CorDebugRegister highWordReg,
7016 CORDB_ADDRESS lowWordAddress,
7018 PCCOR_SIGNATURE pvSigBlob,
7019 ICorDebugValue ** ppValue);
7021 COM_METHOD GetLocalMemoryRegisterValue(CORDB_ADDRESS highWordAddress,
7022 CorDebugRegister lowWordRegister,
7024 PCCOR_SIGNATURE pvSigBlob,
7025 ICorDebugValue ** ppValue);
7027 COM_METHOD CanSetIP(ULONG32 nOffset);
7029 //-----------------------------------------------------------
7030 // ICorDebugNativeFrame2
7031 //-----------------------------------------------------------
7033 COM_METHOD IsChild(BOOL * pIsChild);
7035 COM_METHOD IsMatchingParentFrame(ICorDebugNativeFrame2 *pPotentialParentFrame,
7038 COM_METHOD GetStackParameterSize(ULONG32 * pSize);
7040 //-----------------------------------------------------------
7042 //-----------------------------------------------------------
7044 // Accessors to return NULL or typesafe cast to derived frame
7045 virtual CordbNativeFrame * GetAsNativeFrame() { return this; }
7047 CordbFunction * GetFunction();
7048 CordbNativeCode * GetNativeCode();
7049 virtual const DT_CONTEXT * GetContext() const;
7051 // Given the native variable information of a variable, return its value.
7052 // This function assumes that the value is either in a register or on the stack
7053 // (i.e. VLT_REG or VLT_STK).
7054 SIZE_T GetRegisterOrStackValue(const ICorDebugInfo::NativeVarInfo * pNativeVarInfo);
7056 HRESULT GetLocalRegisterValue(CorDebugRegister reg,
7058 ICorDebugValue **ppValue);
7059 HRESULT GetLocalDoubleRegisterValue(CorDebugRegister highWordReg,
7060 CorDebugRegister lowWordReg,
7062 ICorDebugValue **ppValue);
7063 HRESULT GetLocalMemoryValue(CORDB_ADDRESS address,
7065 ICorDebugValue **ppValue);
7066 HRESULT GetLocalByRefMemoryValue(CORDB_ADDRESS address,
7068 ICorDebugValue **ppValue);
7069 HRESULT GetLocalRegisterMemoryValue(CorDebugRegister highWordReg,
7070 CORDB_ADDRESS lowWordAddress,
7072 ICorDebugValue **ppValue);
7073 HRESULT GetLocalMemoryRegisterValue(CORDB_ADDRESS highWordAddress,
7074 CorDebugRegister lowWordRegister,
7076 ICorDebugValue **ppValue);
7077 UINT_PTR * GetAddressOfRegister(CorDebugRegister regNum) const;
7078 CORDB_ADDRESS GetLeftSideAddressOfRegister(CorDebugRegister regNum) const;
7079 #if !defined(DBG_TARGET_ARM) // @ARMTODO
7080 HRESULT GetLocalFloatingPointValue(DWORD index,
7082 ICorDebugValue **ppValue);
7083 #endif // !DBG_TARGET_ARM @ARMTODO
7086 CORDB_ADDRESS GetLSStackAddress(ICorDebugInfo::RegNum regNum, signed offset);
7088 bool IsLeafFrame() const;
7090 // Return the offset used for inspection purposes.
7091 // Refer to the comment at the beginning of the function definition in RsThread.cpp for more information.
7092 SIZE_T GetInspectionIP();
7094 ULONG32 GetIPOffset();
7096 // whether this is a funclet frame
7098 bool IsFilterFunclet();
7100 #if defined(DBG_TARGET_WIN64) || defined(DBG_TARGET_ARM)
7101 // return the offset of the parent method frame at which an exception occurs
7102 SIZE_T GetParentIP();
7103 #endif // DBG_TARGET_WIN64 || DBG_TARGET_ARM
7105 TADDR GetAmbientESP() { return m_taAmbientESP; }
7106 TADDR GetReturnRegisterValue();
7108 // accessor for the shim private hook code:CordbThread::ConvertFrameForILMethodWithoutMetadata
7109 BOOL ConvertNativeFrameForILMethodWithoutMetadata(ICorDebugInternalFrame2 ** ppInternalFrame2);
7111 //-----------------------------------------------------------
7113 //-----------------------------------------------------------
7117 DebuggerREGDISPLAY m_rd;
7119 // This field is only true for Enter-Managed chain. It means that the register set is invalid.
7120 bool m_quicklyUnwound;
7122 // each CordbNativeFrame corresponds to exactly one CordbJITILFrame and one CordbNativeCode
7123 RSSmartPtr<CordbJITILFrame> m_JITILFrame;
7124 RSSmartPtr<CordbNativeCode> m_nativeCode;
7126 // auxiliary information only used on 64-bit to find the parent stack pointer and offset for funclets
7127 CordbMiscFrame m_misc;
7130 // the ambient SP value only used on x86 to retrieve sp-relative local variables
7131 // (most likely in a frameless method)
7132 TADDR m_taAmbientESP;
7134 // @dbgtodo inspection - When we DACize the various Cordb*Value classes, we should consider getting rid of the
7135 // DebuggerREGDISPLAY and just use the CONTEXT. A lot of simplification can be done here.
7136 DT_CONTEXT m_context;
7140 /* ------------------------------------------------------------------------- *
7141 * CordbRegisterSet class
7143 * This can be obtained via GetRegisterSet from
7147 * ------------------------------------------------------------------------- */
7149 #define SETBITULONG64( x ) ( (ULONG64)1 << (x) )
7150 #define SET_BIT_MASK(_mask, _reg) (_mask[(_reg) >> 3] |= (1 << ((_reg) & 7)))
7151 #define RESET_BIT_MASK(_mask, _reg) (_mask[(_reg) >> 3] &= ~(1 << ((_reg) & 7)))
7152 #define IS_SET_BIT_MASK(_mask, _reg) (_mask[(_reg) >> 3] & (1 << ((_reg) & 7)))
7155 class CordbRegisterSet : public CordbBase, public ICorDebugRegisterSet, public ICorDebugRegisterSet2
7158 CordbRegisterSet(DebuggerREGDISPLAY * pRegDisplay,
7159 CordbThread * pThread,
7162 bool fTakeOwnershipOfDRD = false);
7165 ~CordbRegisterSet();
7169 virtual void Neuter();
7172 virtual const char * DbgGetName() { return "CordbRegisterSet"; }
7175 //-----------------------------------------------------------
7177 //-----------------------------------------------------------
7179 ULONG STDMETHODCALLTYPE AddRef()
7181 return (BaseAddRefEnforceExternal());
7183 ULONG STDMETHODCALLTYPE Release()
7185 return (BaseReleaseEnforceExternal());
7188 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
7192 //-----------------------------------------------------------
7193 // ICorDebugRegisterSet
7194 // More extensive explanation are in Src/inc/CorDebug.idl
7195 //-----------------------------------------------------------
7196 COM_METHOD GetRegistersAvailable(ULONG64 *pAvailable);
7198 COM_METHOD GetRegisters(ULONG64 mask,
7200 CORDB_REGISTER regBuffer[]);
7201 COM_METHOD SetRegisters( ULONG64 mask,
7203 CORDB_REGISTER regBuffer[])
7205 LIMITED_METHOD_CONTRACT;
7207 VALIDATE_POINTER_TO_OBJECT_ARRAY(regBuffer, CORDB_REGISTER,
7208 regCount, true, true);
7213 COM_METHOD GetThreadContext(ULONG32 contextSize, BYTE context[]);
7215 // SetThreadContexthad a very problematic implementation in v1.1.
7216 // We've ripped it out in V2.0 and E_NOTIMPL it. See V1.1 sources for what it used to look like
7217 // in case we ever want to re-add it.
7218 // If we ever re-implement it consider the following:
7219 // - must fail on non-leaf frames (just check m_active).
7220 // - must make sure that GetThreadContext() is fully accurate. If we don't have SetThCtx, then
7221 // GetThreadCtx bugs are much more benign.
7222 // - be sure to update any shared reg displays (what if a frame + chain have the same rd) and
7223 // also update any cached contexts (such as CordbThread::m_context).
7224 // - be sure to honor the context flags and only setting what we can set.
7226 // Friday, July 16, 2004. (This date will be useful for Source control history)
7227 COM_METHOD SetThreadContext(ULONG32 contextSize, BYTE context[])
7232 //-----------------------------------------------------------
7233 // ICorDebugRegisterSet2
7234 // More extensive explanation are in Src/inc/CorDebug.idl
7235 //-----------------------------------------------------------
7236 COM_METHOD GetRegistersAvailable(ULONG32 regCount,
7239 COM_METHOD GetRegisters(ULONG32 maskCount,
7242 CORDB_REGISTER regBuffer[]);
7244 COM_METHOD SetRegisters(ULONG32 maskCount,
7247 CORDB_REGISTER regBuffer[])
7249 LIMITED_METHOD_CONTRACT;
7251 VALIDATE_POINTER_TO_OBJECT_ARRAY(regBuffer, CORDB_REGISTER,
7252 regCount, true, true);
7258 // Platform specific helper for GetThreadContext.
7259 void InternalCopyRDToContext(DT_CONTEXT * pContext);
7261 // Adapters to impl v2.0 interfaces on top of v1.0 interfaces.
7262 HRESULT GetRegistersAvailableAdapter(ULONG32 regCount, BYTE pAvailable[]);
7263 HRESULT GetRegistersAdapter(ULONG32 maskCount, BYTE mask[], ULONG32 regCount, CORDB_REGISTER regBuffer[]);
7266 // This CordbRegisterSet is responsible to free this memory if m_fTakeOwnershipOfDRD is true. Otherwise,
7267 // this memory is freed by the CordbNativeFrame or CordbThread which creates this CordbRegisterSet.
7268 DebuggerREGDISPLAY *m_rd;
7269 CordbThread *m_thread;
7270 bool m_active; // true if we're the leafmost register set.
7273 // true if the CordbRegisterSet owns the DebuggerREGDISPLAY pointer and needs to free the memory
7274 bool m_fTakeOwnershipOfDRD;
7280 /* ------------------------------------------------------------------------- *
7281 * JIT-IL Frame class
7282 * ------------------------------------------------------------------------- */
7284 class CordbJITILFrame : public CordbBase, public ICorDebugILFrame, public ICorDebugILFrame2, public ICorDebugILFrame3, public ICorDebugILFrame4
7287 CordbJITILFrame(CordbNativeFrame * pNativeFrame,
7288 CordbILCode * pCode,
7290 CorDebugMappingResult mapping,
7291 GENERICS_TYPE_TOKEN exactGenericArgsToken,
7292 DWORD dwExactGenericArgsTokenIndex,
7294 CordbReJitILCode * pReJitCode);
7296 virtual ~CordbJITILFrame();
7297 virtual void Neuter();
7301 virtual const char * DbgGetName() { return "CordbJITILFrame"; }
7304 //-----------------------------------------------------------
7306 //-----------------------------------------------------------
7308 ULONG STDMETHODCALLTYPE AddRef()
7310 return (BaseAddRef());
7312 ULONG STDMETHODCALLTYPE Release()
7314 return (BaseRelease());
7316 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
7318 //-----------------------------------------------------------
7320 //-----------------------------------------------------------
7322 COM_METHOD GetChain(ICorDebugChain **ppChain);
7323 COM_METHOD GetCode(ICorDebugCode **ppCode);
7324 COM_METHOD GetFunction(ICorDebugFunction **ppFunction);
7325 COM_METHOD GetFunctionToken(mdMethodDef *pToken);
7326 COM_METHOD GetStackRange(CORDB_ADDRESS *pStart, CORDB_ADDRESS *pEnd);
7327 COM_METHOD CreateStepper(ICorDebugStepper **ppStepper);
7328 COM_METHOD GetCaller(ICorDebugFrame **ppFrame);
7329 COM_METHOD GetCallee(ICorDebugFrame **ppFrame);
7331 //-----------------------------------------------------------
7333 //-----------------------------------------------------------
7335 COM_METHOD GetIP(ULONG32* pnOffset, CorDebugMappingResult *pMappingResult);
7336 COM_METHOD SetIP(ULONG32 nOffset);
7337 COM_METHOD EnumerateLocalVariables(ICorDebugValueEnum **ppValueEnum);
7338 COM_METHOD GetLocalVariable(DWORD dwIndex, ICorDebugValue **ppValue);
7339 COM_METHOD EnumerateArguments(ICorDebugValueEnum **ppValueEnum);
7340 COM_METHOD GetArgument(DWORD dwIndex, ICorDebugValue ** ppValue);
7341 COM_METHOD GetStackDepth(ULONG32 *pDepth);
7342 COM_METHOD GetStackValue(DWORD dwIndex, ICorDebugValue **ppValue);
7343 COM_METHOD CanSetIP(ULONG32 nOffset);
7345 //-----------------------------------------------------------
7346 // ICorDebugILFrame2
7347 //-----------------------------------------------------------
7349 // Called at an EnC remap opportunity to remap to the latest version of a function
7350 COM_METHOD RemapFunction(ULONG32 nOffset);
7352 COM_METHOD EnumerateTypeParameters(ICorDebugTypeEnum **ppTyParEnum);
7354 //-----------------------------------------------------------
7355 // ICorDebugILFrame3
7356 //-----------------------------------------------------------
7358 COM_METHOD GetReturnValueForILOffset(ULONG32 ILoffset, ICorDebugValue** ppReturnValue);
7360 //-----------------------------------------------------------
7361 // ICorDebugILFrame4
7362 //-----------------------------------------------------------
7364 COM_METHOD EnumerateLocalVariablesEx(ILCodeKind flags, ICorDebugValueEnum **ppValueEnum);
7365 COM_METHOD GetLocalVariableEx(ILCodeKind flags, DWORD dwIndex, ICorDebugValue **ppValue);
7366 COM_METHOD GetCodeEx(ILCodeKind flags, ICorDebugCode **ppCode);
7368 //-----------------------------------------------------------
7370 //-----------------------------------------------------------
7372 CordbModule *GetModule();
7374 HRESULT GetNativeVariable(CordbType *type,
7375 const ICorDebugInfo::NativeVarInfo *pNativeVarInfo,
7376 ICorDebugValue **ppValue);
7378 CordbAppDomain *GetCurrentAppDomain();
7380 CordbFunction *GetFunction();
7382 // ILVariableToNative serves to let the frame intercept accesses
7383 // to var args variables.
7384 HRESULT ILVariableToNative(DWORD dwIndex,
7385 const ICorDebugInfo::NativeVarInfo ** ppNativeInfo);
7387 // Fills in our array of var args variables
7388 HRESULT FabricateNativeInfo(DWORD dwIndex,
7389 const ICorDebugInfo::NativeVarInfo ** ppNativeInfo);
7391 HRESULT GetArgumentType(DWORD dwIndex,
7392 CordbType ** ppResultType);
7394 // load the generics type and method arguments into a cache
7395 void LoadGenericArgs();
7397 HRESULT QueryInterfaceInternal(REFIID id, void** pInterface);
7399 // Builds an generic Instaniation object from the mdClass and generic signature
7400 // for what we are calling into.
7401 static HRESULT BuildInstantiationForCallsite(CordbModule *pModule, NewArrayHolder<CordbType*> &types, Instantiation &inst, Instantiation *currentInstantiation, mdToken targetClass, SigParser funcGenerics);
7403 CordbILCode* GetOriginalILCode();
7404 CordbReJitILCode* GetReJitILCode();
7407 void RefreshCachedVarArgSigParserIfNeeded();
7409 // Worker function for GetReturnValueForILOffset.
7410 HRESULT GetReturnValueForILOffsetImpl(ULONG32 ILoffset, ICorDebugValue** ppReturnValue);
7412 // Given pType, fills ppReturnValue with the correct value.
7413 HRESULT GetReturnValueForType(CordbType *pType, ICorDebugValue **ppReturnValue);
7415 //-----------------------------------------------------------
7417 //-----------------------------------------------------------
7420 // each CordbJITILFrame corresponds to exactly one CordbNativeFrame and one CordbILCode
7421 CordbNativeFrame * m_nativeFrame;
7422 CordbILCode * m_ilCode;
7424 // the IL offset and the mapping result for the offset
7426 CorDebugMappingResult m_mapping;
7428 // <vararg-specific fields>
7430 // whether this is a vararg function
7433 // the number of arguments, including the var args
7434 ULONG m_allArgsCount;
7436 // This byte array is used to store the signature for vararg methods.
7437 // It points to the underlying memory used by m_sigParserCached, and it enables us to easily delete
7438 // the underlying memory when the CordbJITILFrame is neutered.
7439 BYTE * m_rgbSigParserBuf;
7441 // Do not mutate this, instead make copies of it and use the copies, that way we are guaranteed to
7442 // start at the correct position in the signature each time.
7443 // The underlying memory used for the signature in the SigParser must not be in the DAC cache.
7444 // Otherwise it may be flushed underneath us, and we would AV when we try to access it.
7445 SigParser m_sigParserCached;
7447 // the address of the first arg; only used for vararg functions
7448 CORDB_ADDRESS m_FirstArgAddr;
7450 // This is an array of variable information for the arguments.
7451 // The variable information is fabricated by the RS.
7452 ICorDebugInfo::NativeVarInfo * m_rgNVI;
7454 // </vararg-specific fields>
7456 Instantiation m_genericArgs; // the generics type arguments
7457 BOOL m_genericArgsLoaded; // whether we have loaded and cached the generics type arguments
7459 // An extra token to help fetch information about any generic
7460 // parameters passed to the method, perhaps dynamically.
7461 // This is the so-called generics type context/token.
7463 // This token comes from the stackwalker and it may be NULL, in which case we need to retrieve the token
7464 // ourselves using m_dwFrameParamsTokenIndex and the variable lifetime information.
7465 GENERICS_TYPE_TOKEN m_frameParamsToken;
7467 // IL Variable index of the Generics Arg Token.
7468 DWORD m_dwFrameParamsTokenIndex;
7470 // if this frame is instrumented with rejit, this will point to the instrumented IL code
7471 RSSmartPtr<CordbReJitILCode> m_pReJitCode;
7474 /* ------------------------------------------------------------------------- *
7476 * ------------------------------------------------------------------------- */
7478 enum CordbBreakpointType
7485 class CordbBreakpoint : public CordbBase, public ICorDebugBreakpoint
7488 CordbBreakpoint(CordbProcess * pProcess, CordbBreakpointType bpType);
7489 virtual void Neuter();
7492 virtual const char * DbgGetName() { return "CordbBreakpoint"; }
7495 //-----------------------------------------------------------
7497 //-----------------------------------------------------------
7499 ULONG STDMETHODCALLTYPE AddRef()
7501 return (BaseAddRef());
7503 ULONG STDMETHODCALLTYPE Release()
7505 return (BaseRelease());
7507 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
7509 //-----------------------------------------------------------
7510 // ICorDebugBreakpoint
7511 //-----------------------------------------------------------
7513 COM_METHOD BaseIsActive(BOOL *pbActive);
7515 //-----------------------------------------------------------
7517 //-----------------------------------------------------------
7518 CordbBreakpointType GetBPType()
7523 virtual void Disconnect() {}
7525 CordbAppDomain *GetAppDomain()
7527 return m_pAppDomain;
7529 //-----------------------------------------------------------
7531 //-----------------------------------------------------------
7535 CordbAppDomain *m_pAppDomain;
7536 CordbBreakpointType m_type;
7539 /* ------------------------------------------------------------------------- *
7540 * Function Breakpoint class
7541 * ------------------------------------------------------------------------- */
7543 class CordbFunctionBreakpoint : public CordbBreakpoint,
7544 public ICorDebugFunctionBreakpoint
7547 CordbFunctionBreakpoint(CordbCode *code, SIZE_T offset);
7548 ~CordbFunctionBreakpoint();
7550 virtual void Neuter();
7552 virtual const char * DbgGetName() { return "CordbFunctionBreakpoint"; }
7556 //-----------------------------------------------------------
7558 //-----------------------------------------------------------
7560 ULONG STDMETHODCALLTYPE AddRef()
7562 return (BaseAddRef());
7564 ULONG STDMETHODCALLTYPE Release()
7566 return (BaseRelease());
7568 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
7570 //-----------------------------------------------------------
7571 // ICorDebugBreakpoint
7572 //-----------------------------------------------------------
7574 COM_METHOD GetFunction(ICorDebugFunction **ppFunction);
7575 COM_METHOD GetOffset(ULONG32 *pnOffset);
7576 COM_METHOD Activate(BOOL bActive);
7577 COM_METHOD IsActive(BOOL *pbActive)
7579 VALIDATE_POINTER_TO_OBJECT(pbActive, BOOL *);
7581 return BaseIsActive(pbActive);
7584 //-----------------------------------------------------------
7586 //-----------------------------------------------------------
7590 //-----------------------------------------------------------
7591 // Convenience routines
7592 //-----------------------------------------------------------
7595 //-----------------------------------------------------------
7597 //-----------------------------------------------------------
7599 // Get a point to the LS BP object.
7600 LSPTR_BREAKPOINT GetLsPtrBP();
7603 // We need to have a strong pointer because we may access the m_code object after we're neutered.
7604 // @todo - use external pointer b/c Breakpoints aren't yet rooted, and so this reference could be
7606 RSExtSmartPtr<CordbCode> m_code;
7610 /* ------------------------------------------------------------------------- *
7611 * Module Breakpoint class
7612 * ------------------------------------------------------------------------- */
7614 class CordbModuleBreakpoint : public CordbBreakpoint,
7615 public ICorDebugModuleBreakpoint
7618 CordbModuleBreakpoint(CordbModule *pModule);
7623 virtual const char * DbgGetName() { return "CordbModuleBreakpoint"; }
7627 //-----------------------------------------------------------
7629 //-----------------------------------------------------------
7631 ULONG STDMETHODCALLTYPE AddRef()
7633 return (BaseAddRef());
7635 ULONG STDMETHODCALLTYPE Release()
7637 return (BaseRelease());
7639 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
7641 //-----------------------------------------------------------
7642 // ICorDebugModuleBreakpoint
7643 //-----------------------------------------------------------
7645 COM_METHOD GetModule(ICorDebugModule **ppModule);
7646 COM_METHOD Activate(BOOL bActive);
7647 COM_METHOD IsActive(BOOL *pbActive)
7649 VALIDATE_POINTER_TO_OBJECT(pbActive, BOOL *);
7651 return BaseIsActive(pbActive);
7654 //-----------------------------------------------------------
7656 //-----------------------------------------------------------
7661 CordbModule *m_module;
7665 /* ------------------------------------------------------------------------- *
7667 * ------------------------------------------------------------------------- */
7669 class CordbStepper : public CordbBase, public ICorDebugStepper, public ICorDebugStepper2
7672 CordbStepper(CordbThread *thread, CordbFrame *frame = NULL);
7677 virtual const char * DbgGetName() { return "CordbStepper"; }
7681 //-----------------------------------------------------------
7683 //-----------------------------------------------------------
7685 ULONG STDMETHODCALLTYPE AddRef()
7687 return (BaseAddRef());
7689 ULONG STDMETHODCALLTYPE Release()
7691 return (BaseRelease());
7693 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
7695 //-----------------------------------------------------------
7697 //-----------------------------------------------------------
7699 COM_METHOD IsActive(BOOL *pbActive);
7700 COM_METHOD Deactivate();
7701 COM_METHOD SetInterceptMask(CorDebugIntercept mask);
7702 COM_METHOD SetUnmappedStopMask(CorDebugUnmappedStop mask);
7703 COM_METHOD Step(BOOL bStepIn);
7704 COM_METHOD StepRange(BOOL bStepIn,
7705 COR_DEBUG_STEP_RANGE ranges[],
7706 ULONG32 cRangeCount);
7707 COM_METHOD StepOut();
7708 COM_METHOD SetRangeIL(BOOL bIL);
7710 //-----------------------------------------------------------
7711 // ICorDebugStepper2
7712 //-----------------------------------------------------------
7713 COM_METHOD SetJMC(BOOL fIsJMCStepper);
7715 //-----------------------------------------------------------
7716 // Convenience routines
7717 //-----------------------------------------------------------
7719 CordbAppDomain *GetAppDomain()
7721 return (m_thread->GetAppDomain());
7724 LSPTR_STEPPER GetLsPtrStepper();
7726 //-----------------------------------------------------------
7728 //-----------------------------------------------------------
7730 CordbThread *m_thread;
7731 CordbFrame *m_frame;
7732 REMOTE_PTR m_stepperToken;
7735 bool m_fIsJMCStepper;
7736 CorDebugUnmappedStop m_rgfMappingStop;
7737 CorDebugIntercept m_rgfInterceptStop;
7740 #define REG_SIZE sizeof(SIZE_T)
7742 // class RegisterInfo: encapsulates information necessary to identify and access a specific register in a
7747 // constructor for an instance of RegisterInfo
7749 // input: kNumber - value from CorDebugRegister to identify the register
7750 // addr - address in remote register display that holds the value
7751 // output: no out parameters, but this instance of RegisterInfo has been initialized
7752 RegisterInfo(const CorDebugRegister kNumber, CORDB_ADDRESS addr, SIZE_T value):
7753 m_kRegNumber((CorDebugRegister)kNumber),
7761 // input: regInfo - register info from which the values for this instance will come
7762 // output: no out parameters, but this instance of RegisterInfo has been initialized
7763 RegisterInfo(const RegisterInfo * pRegInfo):
7764 m_kRegNumber(pRegInfo->m_kRegNumber),
7765 m_regAddr(pRegInfo->m_regAddr),
7766 m_regValue(pRegInfo->m_regValue)
7770 //-------------------------------------
7772 //-------------------------------------
7774 // enumeration value to identify the register, e.g., REGISTER_X86_EAX, or REGISTER_AMD64_XMM0
7775 CorDebugRegister m_kRegNumber;
7777 // address in a context or frame register display of the register value
7778 CORDB_ADDRESS m_regAddr;
7780 // the actual value of the register
7782 }; // class RegisterInfo
7784 // class EnregisteredValueHome: abstract class to encapsulate basic information for a register value, and
7785 // serve as a base class for values residing in register-based locations, such as a single register, a
7786 // register pair, or a register and memory location.
7787 class EnregisteredValueHome
7791 // constructor to initialize an instance of EnregisteredValueHome
7792 EnregisteredValueHome(const CordbNativeFrame * pFrame);
7794 // virtual "copy constructor" to make a copy of "this" to be owned by a different instance of
7795 // Cordb*Value. If an instance of CordbVCObjectValue represents an enregistered value class, it means
7796 // there is a single field. This implies that the register for the CordbVCObject instance is the same as
7797 // the register for its field. When we create a Cordb*Value to represent this field, we need to make a
7798 // copy of the EnregisteredValueHome belonging to the CordbVCObject instance to become the
7799 // EnregisteredValueHome of the Cord*Value representing the field.
7801 // a new cloned copy of this object, allocated on the heap.
7802 // Caller is responsible for deleting the memory (using the standard delete operator).
7804 // C++ allows derived implementations to differ on return type, thus allowing
7805 // derived impls to return the cloned copy as its actual derived type, and not just as a base type.
7810 EnregisteredValueHome * Clone() const = 0;
7812 // set a remote enregistered location to a new value
7814 // input: pNewValue - buffer containing the new value along with its size
7815 // pContext - context from which the value comes
7816 // fIsSigned - indicates whether the value is signed or not. The value provided may be smaller than
7817 // a register, in which case we'll need to extend it to a full register width. To do this
7818 // correctly, we need to know whether to sign extend or zero extend. Currently, only
7819 // the RegValueHome virtual function uses this, but we may need it if we introduce
7820 // types that don't completely occupy the size of two registers.
7821 // output: updates the remote enregistered value on success
7822 // Note: Throws E_FAIL for invalid input or various HRESULTs from an
7823 // unsuccessful call to WriteProcessMemory
7825 void SetEnregisteredValue(MemoryRange newValue, DT_CONTEXT * pContext, bool fIsSigned) = 0;
7827 // Gets an enregistered value and returns it to the caller
7829 // input: pValueOutBuffer - buffer in which to return the value, along with its size
7830 // output: pValueOutBuffer - filled with the value
7831 // Note: Throws E_NOTIMPL for attempts to get an enregistered value for a float register
7832 // (implementation for derived class FloatRegValueHome)
7834 void GetEnregisteredValue(MemoryRange valueOutBuffer) = 0;
7836 // initialize an instance of RemoteAddress for use in an IPC event buffer with values from this
7837 // instance of a derived class of EnregisteredValueHome
7838 // Arguments: input: none--uses fields of "this"
7839 // output: pRegAddr - address of an instance of RemoteAddress with field values set to corresponding
7840 // field values of "this"
7842 void CopyToIPCEType(RemoteAddress * pRegAddr) = 0;
7845 const CordbNativeFrame * GetFrame() const { return m_pFrame; };
7847 //-------------------------------------
7849 //-------------------------------------
7851 // The frame on which the value resides
7852 const CordbNativeFrame * m_pFrame;
7854 }; // class EnregisteredValueHome
7856 typedef NewHolder<EnregisteredValueHome> EnregisteredValueHomeHolder;
7858 // class RegValueHome: encapsulates basic information for a value that resides in a single register
7859 // and serves as a base class for values residing in a register pair.
7860 class RegValueHome: public EnregisteredValueHome
7864 // initializing constructor
7866 // input: pFrame - frame to which the value belongs
7867 // regNum - enumeration value corresponding to the particular hardware register in
7868 // which the value resides
7869 // regAddr - remote address within a register display (in a context or frame) of the
7871 // output: no out parameters, but the instance has been initialized
7872 RegValueHome(const CordbNativeFrame * pFrame,
7873 CorDebugRegister regNum):
7874 EnregisteredValueHome(pFrame),
7876 pFrame->GetLeftSideAddressOfRegister(regNum),
7877 *(pFrame->GetAddressOfRegister(regNum)))
7882 // input: pRemoteRegAddr - instance of a remote register address from which the values for this
7883 // instance will come
7884 // output: no out parameters, but the instance has been initialized
7885 RegValueHome(const RegValueHome * pRemoteRegAddr):
7886 EnregisteredValueHome(pRemoteRegAddr->m_pFrame),
7887 m_reg1Info(pRemoteRegAddr->m_reg1Info)
7890 // make a copy of this instance of RegValueHome
7892 RegValueHome * Clone() const { return new RegValueHome(*this); };
7894 // updates a register in a given context, and in the regdisplay of a given frame.
7895 void SetContextRegister(DT_CONTEXT * pContext,
7896 CorDebugRegister regNum,
7899 // set the value of a remote enregistered value
7901 void SetEnregisteredValue(MemoryRange newValue, DT_CONTEXT * pContext, bool fIsSigned);
7903 // Gets an enregistered value and returns it to the caller
7905 void GetEnregisteredValue(MemoryRange valueOutBuffer);
7906 // initialize an instance of RemoteAddress for use in an IPC event buffer with values from this
7907 // instance of a derived class of RegValueHome
7909 void CopyToIPCEType(RemoteAddress * pRegAddr);
7911 //-------------------------------------
7913 //-------------------------------------
7915 // The information for the register in which the value resides.
7916 const RegisterInfo m_reg1Info;
7917 }; // class RegValueHome
7919 // class RegRegValueHome
7920 // derived class to add a second register for values that live in a pair of registers
7921 class RegRegValueHome: public RegValueHome
7924 // initializing constructor
7926 // input: pFrame - frame to which the value belongs
7927 // reg1Num - enumeration value corresponding to the first particular hardware register in
7928 // which the value resides
7929 // reg1Addr - remote address within a register display (in a context or frame) of the
7931 // reg2Num - enumeration value corresponding to the second particular hardware register in
7932 // which the value resides
7933 // reg2Addr - remote address within a register display (in a context or frame) of the
7935 // output: no out parameters, but the instance has been initialized
7936 RegRegValueHome(const CordbNativeFrame * pFrame,
7937 CorDebugRegister reg1Num,
7938 CorDebugRegister reg2Num):
7939 RegValueHome(pFrame, reg1Num),
7941 pFrame->GetLeftSideAddressOfRegister(reg2Num),
7942 *(pFrame->GetAddressOfRegister(reg2Num)))
7947 // input: pRemoteRegAddr - instance of a remote register address from which the values for this
7948 // instance will come
7949 // output: no out parameters, but the instance has been initialized
7950 RegRegValueHome(const RegRegValueHome * pRemoteRegAddr):
7951 RegValueHome(pRemoteRegAddr),
7952 m_reg2Info(pRemoteRegAddr->m_reg2Info)
7955 // make a copy of this instance of RegRegValueHome
7957 RegRegValueHome * Clone() const { return new RegRegValueHome(*this); };
7959 // set the value of a remote enregistered value
7961 void SetEnregisteredValue(MemoryRange newValue, DT_CONTEXT * pContext, bool fIsSigned);
7963 // Gets an enregistered value and returns it to the caller
7965 void GetEnregisteredValue(MemoryRange valueOutBuffer);
7967 // initialize an instance of RemoteAddress for use in an IPC event buffer with values from this
7968 // instance of a derived class of EnregisteredValueHome
7969 void CopyToIPCEType(RemoteAddress * pRegAddr);
7971 //-------------------------------------
7973 //-------------------------------------
7976 // The information for the second of two registers in which the value resides.
7977 const RegisterInfo m_reg2Info;
7978 }; // class RegRegValueHome
7980 // class RegAndMemBaseValueHome
7981 // derived from RegValueHome, this class is also a base class for RegMemValueHome
7982 // and MemRegValueHome, which add a memory location for reg-mem or mem-reg values
7983 class RegAndMemBaseValueHome: public RegValueHome
7986 // initializing constructor
7988 // input: pFrame - frame to which the value belongs
7989 // reg1Num - enumeration value corresponding to the first particular hardware register in
7990 // which the value resides
7991 // reg1Addr - remote address within a register display (in a context or frame) of the
7992 // register component of the value
7993 // memAddr - remote address for the memory component of the value
7994 // output: no out parameters, but the instance has been initialized
7995 RegAndMemBaseValueHome(const CordbNativeFrame * pFrame,
7996 CorDebugRegister reg1Num,
7997 CORDB_ADDRESS memAddr):
7998 RegValueHome(pFrame, reg1Num),
8004 // input: pRemoteRegAddr - instance of a remote register address from which the values for this
8005 // instance will come
8006 // output: no out parameters, but the instance has been initialized
8007 RegAndMemBaseValueHome(const RegAndMemBaseValueHome * pRemoteRegAddr):
8008 RegValueHome(pRemoteRegAddr),
8012 // make a copy of this instance of RegRegValueHome
8014 RegAndMemBaseValueHome * Clone() const = 0;
8016 // set the value of a remote enregistered value
8018 void SetEnregisteredValue(MemoryRange newValue, DT_CONTEXT * DT_pContext, bool fIsSigned) = 0;
8020 // Gets an enregistered value and returns it to the caller
8022 void GetEnregisteredValue(MemoryRange valueOutBuffer) = 0;
8024 // initialize an instance of RemoteAddress for use in an IPC event buffer with values from this
8025 // instance of a derived class of EnregisteredValueHome
8027 void CopyToIPCEType(RemoteAddress * pRegAddr) = 0;
8029 //-------------------------------------
8031 //-------------------------------------
8034 // remote address for the memory component of the value
8035 CORDB_ADDRESS m_memAddr;
8037 }; // class RegAndMemBaseValueHome;
8039 // class RegMemValueHome
8040 // type derived from abstract class RegAndMemBaseValueHome to represent a Register/Memory location where the
8041 // high order part of the value is kept in a register, and the low order part is kept in memory
8042 class RegMemValueHome: public RegAndMemBaseValueHome
8046 // initializing constructor
8048 // input: pFrame - frame to which the value belongs
8049 // reg1Num - enumeration value corresponding to the first particular hardware register in
8050 // which the value resides
8051 // reg1Addr - remote address within a register display (in a context or frame) of the
8052 // register component of the value
8053 // memAddr - remote address for the memory component of the value
8054 // output: no out parameters, but the instance has been initialized
8055 RegMemValueHome(const CordbNativeFrame * pFrame,
8056 CorDebugRegister reg1Num,
8057 CORDB_ADDRESS memAddr):
8058 RegAndMemBaseValueHome(pFrame, reg1Num, memAddr)
8063 // input: pRemoteRegAddr - instance of a remote register address from which the values for this
8064 // instance will come
8065 // output: no out parameters, but the instance has been initialized
8066 RegMemValueHome(const RegMemValueHome * pRemoteRegAddr):
8067 RegAndMemBaseValueHome(pRemoteRegAddr)
8070 // make a copy of this instance of RegMemValueHome
8072 RegMemValueHome * Clone() const { return new RegMemValueHome(*this); };
8074 // set the value of a remote enregistered value
8076 void SetEnregisteredValue(MemoryRange newValue, DT_CONTEXT * pContext, bool fIsSigned);
8078 // Gets an enregistered value and returns it to the caller
8080 void GetEnregisteredValue(MemoryRange valueOutBuffer);
8082 // initialize an instance of RemoteAddress for use in an IPC event buffer with values from this
8083 // instance of a derived class of EnregisteredValueHome
8085 void CopyToIPCEType(RemoteAddress * pRegAddr);
8087 }; // class RegMemValueHome;
8089 // class MemRegValueHome
8090 // type derived from abstract class RegAndMemBaseValueHome to represent a Register/Memory location where the
8091 // low order part of the value is kept in a register, and the high order part is kept in memory
8092 class MemRegValueHome: public RegAndMemBaseValueHome
8096 // initializing constructor
8098 // input: pFrame - frame to which the value belongs
8099 // reg1Num - enumeration value corresponding to the first particular hardware register in
8100 // which the value resides
8101 // reg1Addr - remote address within a register display (in a context or frame) of the
8102 // register component of the value
8103 // memAddr - remote address for the memory component of the value
8104 // output: no out parameters, but the instance has been initialized
8105 MemRegValueHome(const CordbNativeFrame * pFrame,
8106 CorDebugRegister reg1Num,
8107 CORDB_ADDRESS memAddr):
8108 RegAndMemBaseValueHome(pFrame, reg1Num, memAddr)
8113 // input: pRemoteRegAddr - instance of a remote register address from which the values for this
8114 // instance will come
8115 // output: no out parameters, but the instance has been initialized
8116 MemRegValueHome(const MemRegValueHome * pRemoteRegAddr):
8117 RegAndMemBaseValueHome(pRemoteRegAddr)
8120 // make a copy of this instance of MemRegValueHome
8122 MemRegValueHome * Clone() const { return new MemRegValueHome(*this); };
8124 // set the value of a remote enregistered value
8126 void SetEnregisteredValue(MemoryRange newValue, DT_CONTEXT * pContext, bool fIsSigned);
8128 // Gets an enregistered value and returns it to the caller
8130 void GetEnregisteredValue(MemoryRange valueOutBuffer);
8132 // initialize an instance of RemoteAddress for use in an IPC event buffer with values from this
8133 // instance of a derived class of EnregisteredValueHome
8135 void CopyToIPCEType(RemoteAddress * pRegAddr);
8137 }; // class MemRegValueHome;
8139 // class FloatRegValueHome
8140 // derived class to add an index into the FP register stack for a floating point value
8141 class FloatRegValueHome: public EnregisteredValueHome
8144 // initializing constructor
8146 // input: pFrame - frame to which the value belongs
8147 // index - index into the floating point stack where the value resides
8148 // output: no out parameters, but the instance has been initialized
8149 FloatRegValueHome(const CordbNativeFrame * pFrame,
8151 EnregisteredValueHome(pFrame),
8157 // input: pRemoteRegAddr - instance of a remote register address from which the values for this
8158 // instance will come
8159 // output: no out parameters, but the instance has been initialized
8160 FloatRegValueHome(const FloatRegValueHome * pRemoteRegAddr):
8161 EnregisteredValueHome(pRemoteRegAddr->m_pFrame),
8162 m_floatIndex(pRemoteRegAddr->m_floatIndex)
8165 // make a copy of this instance of FloatRegValueHome
8167 FloatRegValueHome * Clone() const { return new FloatRegValueHome(*this); };
8169 // set the value of a remote enregistered value
8171 void SetEnregisteredValue(MemoryRange newValue, DT_CONTEXT * pContext, bool fIsSigned);
8173 // Gets an enregistered value and returns it to the caller
8175 void GetEnregisteredValue(MemoryRange valueOutBuffer);
8177 // initialize an instance of RemoteAddress for use in an IPC event buffer with values from this
8178 // instance of a derived class of EnregisteredValueHome
8180 void CopyToIPCEType(RemoteAddress * pRegAddr);
8182 //-------------------------------------
8184 //-------------------------------------
8187 // index into the FP registers for the register in which the floating point value resides
8188 const DWORD m_floatIndex;
8189 }; // class FloatRegValueHome
8191 // ----------------------------------------------------------------------------
8192 // Type hierarchy for value locations
8195 // ------------------ | -------------------
8197 // RemoteValueHome RegisterValueHome HandleValueHome
8201 // VCRemoteValueHome RefRemoteValueHome
8203 // ValueHome: abstract base class, provides remote read and write utilities
8204 // RemoteValueHome: used for CordbObjectValue, CordbArrayValue, and CordbBoxValue instances,
8205 // which have only remote locations, and for other ICDValues with a remote address
8206 // RegisterValueHome: used for CordbGenericValue and CordbReferenceValue instances with
8207 // only a register location
8208 // HandleValueHome: used for CordbReferenceValue instances with only an object handle
8209 // VCRemoteValueHome: used for CordbVCObjectValue instances to supply special operation CreateInternalValue for
8210 // value class objects with only a remote location
8211 // RefRemoteValueHome: used for CordbReferenceValue instances with only a remote location
8213 // In addition, we have a special type for the ValueHome field for CordbReferenceValue instances:
8214 // RefValueHome. This will have a field of type ValueHome and will implement extra operations only relevant
8215 // for object references.
8217 // ----------------------------------------------------------------------------
8222 ValueHome(CordbProcess * pProcess):
8223 m_pProcess(pProcess) { _ASSERTE(pProcess != NULL); };
8225 // releases resources as necessary
8229 // gets the remote address for the value or returns NULL if none exists
8231 CORDB_ADDRESS GetAddress() = 0;
8233 // Gets a value and returns it in dest
8235 // input: none (uses fields of the instance)
8236 // output: dest - buffer containing the value retrieved as long as the returned HRESULT doesn't
8237 // indicate an error.
8238 // Note: Throws errors from read process memory operation or GetThreadContext operation
8240 void GetValue(MemoryRange dest) = 0;
8242 // Sets a location to the value provided in src
8244 // input: src - buffer containing the new value to be set--memory for this buffer is owned by the caller
8245 // pType - type information about the value
8246 // output: none, but on success, changes m_remoteValue to hold the new value
8247 // Note: Throws errors from SafeWriteBuffer
8249 void SetValue(MemoryRange src, CordbType * pType) = 0;
8251 // creates an ICDValue for a field or array element or for the value type of a boxed object
8253 // input: pType - type of the internal value
8254 // offset - offset to the internal value
8255 // localAddress - address of thelogical buffer within the parent class' local cached
8256 // copy that holds the internal element
8257 // size - size of the internal value
8258 // output: ppValue - the newly created ICDValue instance
8259 // Note: Throws for a variety of possible failures: OOM, E_FAIL, errors from
8260 // ReadProcessMemory.
8262 void CreateInternalValue(CordbType * pType,
8264 void * localAddress,
8266 ICorDebugValue ** ppValue) = 0;
8268 // Gets the value of a field or element of an existing ICDValue instance and returns it in dest
8270 // input: offset - offset within the value to the internal field or element
8271 // output: dest - buffer to hold the value--memory for this buffer is owned by the caller
8272 // Note: Throws process memory write errors
8274 void GetInternalValue(MemoryRange dest, SIZE_T offset) = 0;
8276 // copies register information from this to a RemoteAddress instance for FuncEval
8278 // output: pRegAddr - copy of information in m_pRemoteRegAddr, converted to
8279 // an instance of RemoteAddress
8281 void CopyToIPCEType(RemoteAddress * pRegAddr) = 0;
8284 // unimplemented copy constructor to prevent passing by value
8285 ValueHome(ValueHome * pValHome);
8291 CordbProcess * m_pProcess;
8292 }; // class ValueHome
8294 // ============================================================================
8295 // RemoteValueHome class
8296 // ============================================================================
8297 // to be used for CordbObjectValue, CordbArrayValue, and CordbBoxValue, none of which ever have anything but
8299 class RemoteValueHome: public ValueHome
8303 // Note: It's possible that remoteValue.pAddress may be NULL--FuncEval makes
8304 // empty GenericValues for literals in which case we would have neither a remote address nor a
8306 RemoteValueHome(CordbProcess * pProcess, TargetBuffer remoteValue);
8308 // gets the remote address for the value
8310 CORDB_ADDRESS GetAddress() { return m_remoteValue.pAddress; };
8312 // releases resources as necessary
8316 // Gets a value and returns it in dest
8318 void GetValue(MemoryRange dest);
8320 // Sets a location to the value provided in src
8322 void SetValue(MemoryRange src, CordbType * pType);
8324 // creates an ICDValue for a field or array element or for the value type of a boxed object
8326 void CreateInternalValue(CordbType * pType,
8328 void * localAddress,
8330 ICorDebugValue ** ppValue);
8332 // Gets the value of a field or element of an existing ICDValue instance and returns it in dest
8334 void GetInternalValue(MemoryRange dest, SIZE_T offset);
8336 // copies register information from this to a RemoteAddress instance for FuncEval
8338 void CopyToIPCEType(RemoteAddress * pRegAddr);
8346 TargetBuffer m_remoteValue;
8347 }; // class RemoteValueHome
8349 // ============================================================================
8350 // RegisterValueHome class
8351 // ============================================================================
8352 // for values that may either have a remote location or be enregistered--
8353 // to be used for CordbGenericValue, and as base for CordbVCObjectValue and CordbReferenceValue
8354 class RegisterValueHome: public ValueHome
8358 RegisterValueHome(CordbProcess * pProcess,
8359 EnregisteredValueHomeHolder * ppRemoteRegAddr);
8361 // clean up resources
8365 // gets the remote address for the value or returns NULL if none exists
8367 CORDB_ADDRESS GetAddress() { return NULL; };
8369 // Gets a value and returns it in dest
8371 void GetValue(MemoryRange dest);
8373 // Sets a location to the value provided in src
8375 void SetValue(MemoryRange src, CordbType * pType);
8377 // creates an ICDValue for a field or array element or for the value type of a boxed object
8379 void CreateInternalValue(CordbType * pType,
8381 void * localAddress,
8383 ICorDebugValue ** ppValue);
8385 // Gets the value of a field or element of an existing ICDValue instance and returns it in dest
8387 void GetInternalValue(MemoryRange dest, SIZE_T offset);
8389 // copies the register information from this to a RemoteAddress instance
8391 void CopyToIPCEType(RemoteAddress * pRegAddr);
8395 // sets a remote enregistered location to a new value
8396 void SetEnregisteredValue(MemoryRange src, bool fIsSigned);
8398 // gets a value from an enregistered location
8399 void GetEnregisteredValue(MemoryRange dest);
8401 bool IsSigned(CorElementType elementType);
8408 // Left Side register location info for various kinds of (partly) enregistered values.
8409 EnregisteredValueHome * m_pRemoteRegAddr;
8411 }; // class RegisterValueHome
8413 // ============================================================================
8414 // HandleValueHome class
8415 // ============================================================================
8417 class HandleValueHome: public ValueHome
8422 // input: pProcess - process to which the value belongs
8423 // vmObjHandle - objectHandle holding the object address
8424 HandleValueHome(CordbProcess * pProcess, VMPTR_OBJECTHANDLE vmObjHandle):
8425 ValueHome(pProcess),
8426 m_vmObjectHandle(vmObjHandle) {};
8428 // releases resources as necessary
8432 // gets the remote address for the value or returns NULL if none exists
8434 CORDB_ADDRESS GetAddress();
8436 // Gets a value and returns it in dest
8438 void GetValue(MemoryRange dest);
8440 // Sets a location to the value provided in src
8442 void SetValue(MemoryRange src, CordbType * pType);
8444 // creates an ICDValue for a field or array element or for the value type of a boxed object
8446 void CreateInternalValue(CordbType * pType,
8448 void * localAddress,
8450 ICorDebugValue ** ppValue);
8452 // Gets the value of a field or element of an existing ICDValue instance and returns it in dest
8454 void GetInternalValue(MemoryRange dest, SIZE_T offset);
8456 // copies the register information from this to a RemoteAddress instance
8458 void CopyToIPCEType(RemoteAddress * pRegAddr);
8464 VMPTR_OBJECTHANDLE m_vmObjectHandle;
8465 }; // class HandleValueHome;
8467 // ============================================================================
8468 // VCRemoteValueHome class
8469 // ============================================================================
8470 // used only for CordbVCObjectValue
8471 class VCRemoteValueHome: public RemoteValueHome
8475 VCRemoteValueHome(CordbProcess * pProcess,
8476 TargetBuffer remoteValue):
8477 RemoteValueHome(pProcess, remoteValue) {};
8479 // Sets a location to the value provided in src
8481 void SetValue(MemoryRange src, CordbType * pType);
8483 }; // class VCRemoteValueHome
8485 // ============================================================================
8486 // RefRemoteValueHome class
8487 // ============================================================================
8489 // used only for CordbReferenceValue
8490 class RefRemoteValueHome: public RemoteValueHome
8495 RefRemoteValueHome(CordbProcess * pProcess,
8496 TargetBuffer remoteValue);
8498 // Sets a location to the value provided in src
8500 void SetValue(MemoryRange src, CordbType * pType);
8502 }; // class RefRemoteValueHome
8504 // ============================================================================
8505 // RefValueHome class
8506 // ============================================================================
8508 // abstract superclass for derivations RefRemoteValueHome and RefRegValueHome
8513 RefValueHome() { m_pHome = NULL; m_fNullObjHandle = true; };
8516 RefValueHome(CordbProcess * pProcess,
8517 TargetBuffer remoteValue,
8518 EnregisteredValueHomeHolder * ppRemoteRegAddr,
8519 VMPTR_OBJECTHANDLE vmObjHandle);
8521 // indicates whether the object handle is null
8522 bool ObjHandleIsNull() { return m_fNullObjHandle; };
8523 void SetObjHandleFlag(bool isNull) { m_fNullObjHandle = isNull; };
8528 // appropriate instantiation of ValueHome
8529 ValueHome * m_pHome;
8532 // true iff m_pHome is an instantiation of RemoteValueHome or RegisterValueHome
8533 bool m_fNullObjHandle;
8534 }; // class RefValueHome
8536 typedef enum {kUnboxed, kBoxed} BoxedValue;
8537 #define EMPTY_BUFFER TargetBuffer(PTR_TO_CORDB_ADDRESS((void *)NULL), 0)
8539 // for an inheritance graph of the ICDValue types, // See file:./ICorDebugValueTypes.vsd for a diagram of the types.
8540 /* ------------------------------------------------------------------------- *
8542 * ------------------------------------------------------------------------- */
8544 class CordbValue : public CordbBase
8547 //-----------------------------------------------------------
8548 // Constructor/destructor
8549 //-----------------------------------------------------------
8550 CordbValue(CordbAppDomain * appdomain,
8554 NeuterList * pList = NULL);
8556 virtual ~CordbValue();
8557 virtual void Neuter();
8559 //-----------------------------------------------------------
8561 //-----------------------------------------------------------
8563 ULONG STDMETHODCALLTYPE AddRef()
8565 return (BaseAddRef());
8567 ULONG STDMETHODCALLTYPE Release()
8569 return (BaseRelease());
8572 //-----------------------------------------------------------
8574 //-----------------------------------------------------------
8576 COM_METHOD GetType(CorElementType *pType)
8578 LIMITED_METHOD_CONTRACT;
8580 FAIL_IF_NEUTERED(this);
8581 VALIDATE_POINTER_TO_OBJECT(pType, CorElementType *);
8583 *pType = m_type->m_elementType;
8587 COM_METHOD GetSize(ULONG32 *pSize)
8589 LIMITED_METHOD_CONTRACT;
8591 FAIL_IF_NEUTERED(this);
8592 VALIDATE_POINTER_TO_OBJECT(pSize, ULONG32 *);
8594 if (m_size > ULONG_MAX)
8597 return (COR_E_OVERFLOW);
8600 *pSize = (ULONG)m_size;
8604 COM_METHOD CreateBreakpoint(ICorDebugValueBreakpoint **ppBreakpoint);
8606 //-----------------------------------------------------------
8608 //-----------------------------------------------------------
8610 COM_METHOD GetExactType(ICorDebugType **ppType);
8612 //-----------------------------------------------------------
8614 //-----------------------------------------------------------
8616 COM_METHOD GetSize64(ULONG64 *pSize)
8618 LIMITED_METHOD_CONTRACT;
8620 FAIL_IF_NEUTERED(this);
8621 VALIDATE_POINTER_TO_OBJECT(pSize, ULONG64 *);
8627 //-----------------------------------------------------------
8628 // Methods not exported through COM
8629 //-----------------------------------------------------------
8631 // Helper for code:CordbValue::CreateValueByType. Create a new instance of CordbGenericValue
8633 void CreateGenericValue(CordbAppDomain * pAppdomain,
8635 TargetBuffer remoteValue,
8636 MemoryRange localValue,
8637 EnregisteredValueHomeHolder * ppRemoteRegAddr,
8638 ICorDebugValue** ppValue);
8640 // Helper for code:CordbValue::CreateValueByType. Create a new instance of CordbVCObjectValue or
8641 // CordbReferenceValue
8643 void CreateVCObjOrRefValue(CordbAppDomain * pAppdomain,
8646 TargetBuffer remoteValue,
8647 MemoryRange localValue,
8648 EnregisteredValueHomeHolder * ppRemoteRegAddr,
8649 ICorDebugValue** ppValue);
8651 // Create the proper ICDValue instance based on the given element type.
8652 static void CreateValueByType(CordbAppDomain * appdomain,
8655 TargetBuffer remoteValue,
8656 MemoryRange localValue,
8657 EnregisteredValueHomeHolder * ppRemoteRegAddr,
8658 ICorDebugValue** ppValue);
8660 // Create the proper ICDValue instance based on the given remote heap object
8661 static ICorDebugValue* CreateHeapValue(CordbAppDomain* pAppDomain,
8662 VMPTR_Object vmObj);
8665 // Returns a pointer to the ValueHome field of this instance of CordbValue if one exists or NULL
8666 // otherwise. Therefore, this also tells us indirectly whether this instance of CordbValue is also an
8667 // instance of one of its derived types and thus has a ValueHome field.
8669 ValueHome * GetValueHome() { return NULL; };
8671 static ULONG32 GetSizeForType(CordbType * pType, BoxedValue boxing);
8673 virtual CordbAppDomain *GetAppDomain()
8678 HRESULT InternalCreateHandle(
8679 CorDebugHandleType handleType,
8680 ICorDebugHandleValue ** ppHandle);
8682 //-----------------------------------------------------------
8684 //-----------------------------------------------------------
8687 CordbAppDomain * m_appdomain;
8688 RSSmartPtr<CordbType> m_type;
8690 // size of the value
8693 // true if the value is a RS fabrication.
8698 /* ------------------------------------------------------------------------- *
8699 * Value Breakpoint class
8700 * ------------------------------------------------------------------------- */
8702 class CordbValueBreakpoint : public CordbBreakpoint,
8703 public ICorDebugValueBreakpoint
8706 CordbValueBreakpoint(CordbValue *pValue);
8710 virtual const char * DbgGetName() { return "CordbValueBreakpoint"; }
8713 //-----------------------------------------------------------
8715 //-----------------------------------------------------------
8717 ULONG STDMETHODCALLTYPE AddRef()
8719 return (BaseAddRef());
8721 ULONG STDMETHODCALLTYPE Release()
8723 return (BaseRelease());
8725 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
8727 //-----------------------------------------------------------
8728 // ICorDebugValueBreakpoint
8729 //-----------------------------------------------------------
8731 COM_METHOD GetValue(ICorDebugValue **ppValue);
8732 COM_METHOD Activate(BOOL bActive);
8733 COM_METHOD IsActive(BOOL *pbActive)
8735 VALIDATE_POINTER_TO_OBJECT(pbActive, BOOL *);
8737 return BaseIsActive(pbActive);
8740 //-----------------------------------------------------------
8742 //-----------------------------------------------------------
8747 CordbValue *m_value;
8750 /* ------------------------------------------------------------------------- *
8751 * Generic Value class
8752 * ------------------------------------------------------------------------- */
8754 class CordbGenericValue : public CordbValue, public ICorDebugGenericValue, public ICorDebugValue2, public ICorDebugValue3
8757 CordbGenericValue(CordbAppDomain * appdomain,
8759 TargetBuffer remoteValue,
8760 EnregisteredValueHomeHolder * ppRemoteRegAddr);
8762 CordbGenericValue(CordbType * pType);
8764 ~CordbGenericValue();
8767 virtual const char * DbgGetName() { return "CordbGenericValue"; }
8771 //-----------------------------------------------------------
8773 //-----------------------------------------------------------
8775 ULONG STDMETHODCALLTYPE AddRef()
8777 return (BaseAddRef());
8779 ULONG STDMETHODCALLTYPE Release()
8781 return (BaseRelease());
8783 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
8785 //-----------------------------------------------------------
8787 //-----------------------------------------------------------
8789 // gets the type of the value
8791 // output: pType - the type of the value. The caller must guarantee that pType is non-null.
8792 // Return Value: S_OK on success, E_INVALIDARG on failure
8793 COM_METHOD GetType(CorElementType *pType)
8795 return (CordbValue::GetType(pType));
8798 // gets the size of the value
8800 // output: pSize - the size of the value. The caller must guarantee that pSize is non-null.
8801 // Return Value: S_OK on success, E_INVALIDARG on failure
8802 COM_METHOD GetSize(ULONG32 *pSize)
8804 return (CordbValue::GetSize(pSize));
8806 COM_METHOD CreateBreakpoint(ICorDebugValueBreakpoint **ppBreakpoint)
8808 return (CordbValue::CreateBreakpoint(ppBreakpoint));
8811 // gets the remote (LS) address of the value. This may return NULL if the
8812 // value is a literal or resides in a register.
8814 // output: pAddress - the address of the value. The caller must guarantee is
8816 // Return Value: S_OK on success or E_INVALIDARG if pAddress is null
8817 COM_METHOD GetAddress(CORDB_ADDRESS *pAddress)
8819 LIMITED_METHOD_CONTRACT;
8821 FAIL_IF_NEUTERED(this);
8822 VALIDATE_POINTER_TO_OBJECT_OR_NULL(pAddress, CORDB_ADDRESS *);
8824 *pAddress = m_pValueHome ? m_pValueHome->GetAddress() : NULL;
8828 //-----------------------------------------------------------
8830 //-----------------------------------------------------------
8832 COM_METHOD GetExactType(ICorDebugType **ppType)
8834 return (CordbValue::GetExactType(ppType));
8837 //-----------------------------------------------------------
8839 //-----------------------------------------------------------
8841 COM_METHOD GetSize64(ULONG64 *pSize)
8843 return (CordbValue::GetSize64(pSize));
8846 //-----------------------------------------------------------
8847 // ICorDebugGenericValue
8848 //-----------------------------------------------------------
8850 COM_METHOD GetValue(void *pTo);
8851 COM_METHOD SetValue(void *pFrom);
8853 //-----------------------------------------------------------
8855 //-----------------------------------------------------------
8857 // initialize a generic value by copying the necessary data, either
8858 // from the remote process or from another value in this process.
8859 void Init(MemoryRange localValue);
8860 bool CopyLiteralData(BYTE *pBuffer);
8862 // Returns a pointer to the ValueHome field
8864 ValueHome * GetValueHome() { return m_pValueHome; };
8866 //-----------------------------------------------------------
8868 //-----------------------------------------------------------
8871 // hold copies of up to 64-bit values.
8872 BYTE m_pCopyOfData[8];
8874 // location information--remote or register address
8875 ValueHome * m_pValueHome;
8879 /* ------------------------------------------------------------------------- *
8880 * Reference Value class
8881 * ------------------------------------------------------------------------- */
8883 class CordbReferenceValue : public CordbValue, public ICorDebugReferenceValue, public ICorDebugValue2, public ICorDebugValue3
8886 CordbReferenceValue(CordbAppDomain * pAppdomain,
8888 MemoryRange localValue,
8889 TargetBuffer remoteValue,
8890 EnregisteredValueHomeHolder * ppRegAddr,
8891 VMPTR_OBJECTHANDLE vmObjectHandle);
8892 CordbReferenceValue(CordbType * pType);
8893 virtual ~CordbReferenceValue();
8894 virtual void Neuter();
8898 virtual const char * DbgGetName() { return "CordbReferenceValue"; }
8901 //-----------------------------------------------------------
8903 //-----------------------------------------------------------
8905 ULONG STDMETHODCALLTYPE AddRef()
8907 return (BaseAddRef());
8909 ULONG STDMETHODCALLTYPE Release()
8911 return (BaseRelease());
8913 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
8915 //-----------------------------------------------------------
8917 //-----------------------------------------------------------
8919 COM_METHOD GetType(CorElementType *pType);
8921 // get the size of the reference
8923 // output: pSize - the size of the value--this must be non-NULL
8924 // Return Value: S_OK on success or E_INVALIDARG
8925 COM_METHOD GetSize(ULONG32 *pSize)
8927 return (CordbValue::GetSize(pSize));
8930 COM_METHOD GetAddress(CORDB_ADDRESS *pAddress);
8931 COM_METHOD CreateBreakpoint(ICorDebugValueBreakpoint **ppBreakpoint)
8933 return (CordbValue::CreateBreakpoint(ppBreakpoint));
8936 //-----------------------------------------------------------
8938 //-----------------------------------------------------------
8940 COM_METHOD GetExactType(ICorDebugType **ppType)
8942 return (CordbValue::GetExactType(ppType));
8945 //-----------------------------------------------------------
8947 //-----------------------------------------------------------
8949 COM_METHOD GetSize64(ULONG64 *pSize)
8951 return (CordbValue::GetSize64(pSize));
8954 //-----------------------------------------------------------
8955 // ICorDebugReferenceValue
8956 //-----------------------------------------------------------
8958 COM_METHOD IsNull(BOOL * pfIsNull);
8959 COM_METHOD GetValue(CORDB_ADDRESS *pAddress);
8960 COM_METHOD SetValue(CORDB_ADDRESS address);
8961 COM_METHOD Dereference(ICorDebugValue **ppValue);
8962 COM_METHOD DereferenceStrong(ICorDebugValue **ppValue);
8964 //-----------------------------------------------------------
8966 //-----------------------------------------------------------
8968 // Helper function for SanityCheckPointer. Make an attempt to read memory at the address which is the
8969 // value of the reference.
8970 void TryDereferencingTarget();
8972 // Do a sanity check on the pointer which is the value of the object reference. We can't efficiently
8973 // ensure that the pointer is really good, so we settle for a quick check just to make sure the memory at
8974 // the address is readable. We're actually just checking that we can dereference the pointer.
8975 // If the address is invalid, this will throw.
8976 void SanityCheckPointer (CorElementType type);
8978 // get information about the reference when it's not an object address but another kind of pointer type:
8979 // ELEMENT_TYPE_BYREF, ELEMENT_TYPE_PTR or ELEMENT_TYPE_FNPTR
8980 void GetPointerData(CorElementType type, MemoryRange localValue);
8982 // get basic object specific data when a reference points to an object, plus extra data if the object is
8983 // an array or string
8985 void GetObjectData(CordbProcess * pProcess,
8986 void * objectAddress,
8987 CorElementType type,
8988 VMPTR_AppDomain vmAppdomain,
8989 DebuggerIPCE_ObjectData * pInfo);
8991 // get information about a TypedByRef object when the reference is the address of a TypedByRef structure.
8993 void GetTypedByRefData(CordbProcess * pProcess,
8994 CORDB_ADDRESS pTypedByRef,
8995 CorElementType type,
8996 VMPTR_AppDomain vmAppDomain,
8997 DebuggerIPCE_ObjectData * pInfo);
8999 // get the address of the object referenced
9000 void * GetObjectAddress(MemoryRange localValue);
9002 // update type information after initializing -- when we initialize, we may get more exact type
9003 // information than we previously had
9004 void UpdateTypeInfo();
9006 // Initialize this CordbReferenceValue. This may involve inspecting the LS to get information about the
9008 HRESULT InitRef(MemoryRange localValue);
9010 bool CopyLiteralData(BYTE *pBuffer);
9012 static HRESULT Build(CordbAppDomain * appdomain,
9014 TargetBuffer remoteValue,
9015 MemoryRange localValue,
9016 VMPTR_OBJECTHANDLE vmObjectHandle,
9017 EnregisteredValueHomeHolder * ppRemoteRegAddr,
9018 CordbReferenceValue** ppValue);
9020 static HRESULT BuildFromGCHandle(CordbAppDomain *pAppDomain, VMPTR_OBJECTHANDLE gcHandle, ICorDebugReferenceValue ** pOutRef);
9022 // Common dereference routine shared by both CordbReferenceValue + CordbHandleValue
9023 static HRESULT DereferenceCommon(CordbAppDomain * pAppDomain,
9025 CordbType * pRealTypeOfTypedByref,
9026 DebuggerIPCE_ObjectData * m_pInfo,
9027 ICorDebugValue ** ppValue);
9029 // Returns a pointer to the ValueHome field
9031 ValueHome * GetValueHome() { return m_valueHome.m_pHome; };
9033 //-----------------------------------------------------------
9035 //-----------------------------------------------------------
9038 DebuggerIPCE_ObjectData m_info;
9039 CordbType * m_realTypeOfTypedByref; // weak ref
9041 RefValueHome m_valueHome;
9043 // Indicates when we last syncronized our stored data (m_info) from the left side
9044 UINT m_continueCounterLastSync;
9047 /* ------------------------------------------------------------------------- *
9048 * Object Value class
9050 * Because of the oddness of string objects in the Runtime we have one
9051 * object that implements both ObjectValue and StringValue. There is a
9052 * definite string type, but its really just an object of the string
9053 * class. Furthermore, you can have a variable whose type is listed as
9054 * "class", but its an instance of the string class and therefore needs
9055 * to be treated like a string.
9056 * ------------------------------------------------------------------------- */
9058 class CordbObjectValue : public CordbValue,
9059 public ICorDebugObjectValue,
9060 public ICorDebugObjectValue2,
9061 public ICorDebugGenericValue,
9062 public ICorDebugStringValue,
9063 public ICorDebugValue2,
9064 public ICorDebugValue3,
9065 public ICorDebugHeapValue2,
9066 public ICorDebugHeapValue3,
9067 public ICorDebugExceptionObjectValue,
9068 public ICorDebugComObjectValue
9072 CordbObjectValue(CordbAppDomain * appdomain,
9074 TargetBuffer remoteValue,
9075 DebuggerIPCE_ObjectData * pObjectData );
9077 virtual ~CordbObjectValue();
9080 virtual void Neuter();
9082 virtual const char * DbgGetName() { return "CordbObjectValue"; }
9085 //-----------------------------------------------------------
9087 //-----------------------------------------------------------
9089 ULONG STDMETHODCALLTYPE AddRef()
9091 return (BaseAddRef());
9093 ULONG STDMETHODCALLTYPE Release()
9095 return (BaseRelease());
9097 COM_METHOD QueryInterface(REFIID riid, void ** ppInterface);
9099 //-----------------------------------------------------------
9101 //-----------------------------------------------------------
9103 COM_METHOD GetType(CorElementType * pType);
9104 COM_METHOD GetSize(ULONG32 * pSize);
9105 COM_METHOD GetAddress(CORDB_ADDRESS * pAddress);
9106 COM_METHOD CreateBreakpoint(ICorDebugValueBreakpoint ** ppBreakpoint);
9108 //-----------------------------------------------------------
9110 //-----------------------------------------------------------
9112 COM_METHOD GetExactType(ICorDebugType ** ppType)
9114 return (CordbValue::GetExactType(ppType));
9117 //-----------------------------------------------------------
9119 //-----------------------------------------------------------
9121 COM_METHOD GetSize64(ULONG64 *pSize);
9123 //-----------------------------------------------------------
9124 // ICorDebugHeapValue
9125 //-----------------------------------------------------------
9127 COM_METHOD IsValid(BOOL * pfIsValid);
9128 COM_METHOD CreateRelocBreakpoint(ICorDebugValueBreakpoint ** ppBreakpoint);
9130 //-----------------------------------------------------------
9131 // ICorDebugHeapValue2
9132 //-----------------------------------------------------------
9133 COM_METHOD CreateHandle(CorDebugHandleType type, ICorDebugHandleValue ** ppHandle);
9135 //-----------------------------------------------------------
9136 // ICorDebugHeapValue3
9137 //-----------------------------------------------------------
9138 COM_METHOD GetThreadOwningMonitorLock(ICorDebugThread **ppThread, DWORD *pAcquisitionCount);
9139 COM_METHOD GetMonitorEventWaitList(ICorDebugThreadEnum **ppThreadEnum);
9141 //-----------------------------------------------------------
9142 // ICorDebugObjectValue
9143 //-----------------------------------------------------------
9145 COM_METHOD GetClass(ICorDebugClass ** ppClass);
9146 COM_METHOD GetFieldValue(ICorDebugClass * pClass,
9147 mdFieldDef fieldDef,
9148 ICorDebugValue ** ppValue);
9149 COM_METHOD GetVirtualMethod(mdMemberRef memberRef,
9150 ICorDebugFunction **ppFunction);
9151 COM_METHOD GetContext(ICorDebugContext ** ppContext);
9152 COM_METHOD IsValueClass(BOOL * pfIsValueClass);
9153 COM_METHOD GetManagedCopy(IUnknown ** ppObject);
9154 COM_METHOD SetFromManagedCopy(IUnknown * pObject);
9156 COM_METHOD GetFieldValueForType(ICorDebugType * pType,
9157 mdFieldDef fieldDef,
9158 ICorDebugValue ** ppValue);
9160 COM_METHOD GetVirtualMethodAndType(mdMemberRef memberRef,
9161 ICorDebugFunction ** ppFunction,
9162 ICorDebugType ** ppType);
9164 //-----------------------------------------------------------
9165 // ICorDebugGenericValue
9166 //-----------------------------------------------------------
9168 COM_METHOD GetValue(void * pTo);
9169 COM_METHOD SetValue(void * pFrom);
9171 //-----------------------------------------------------------
9172 // ICorDebugStringValue
9173 //-----------------------------------------------------------
9174 COM_METHOD GetLength(ULONG32 * pcchString);
9175 COM_METHOD GetString(ULONG32 cchString,
9176 ULONG32 * ppcchStrin,
9177 __out_ecount_opt(cchString) WCHAR szString[]);
9179 //-----------------------------------------------------------
9180 // ICorDebugExceptionObjectValue
9181 //-----------------------------------------------------------
9182 COM_METHOD EnumerateExceptionCallStack(ICorDebugExceptionObjectCallStackEnum** ppCallStackEnum);
9184 //-----------------------------------------------------------
9185 // ICorDebugComObjectValue
9186 //-----------------------------------------------------------
9187 COM_METHOD GetCachedInterfaceTypes(BOOL bIInspectableOnly,
9188 ICorDebugTypeEnum** ppInterfacesEnum);
9190 COM_METHOD GetCachedInterfacePointers(BOOL bIInspectableOnly,
9192 ULONG32 *pcEltFetched,
9193 CORDB_ADDRESS * ptrs);
9195 //-----------------------------------------------------------
9197 //-----------------------------------------------------------
9201 DebuggerIPCE_ObjectData GetInfo() { return m_info; }
9202 CordbHangingFieldTable * GetHangingFieldTable() { return &m_hangingFieldsInstance; }
9204 // Returns a pointer to the ValueHome field
9206 RemoteValueHome * GetValueHome() { return &m_valueHome; };
9209 //-----------------------------------------------------------
9211 //-----------------------------------------------------------
9212 DebuggerIPCE_ObjectData m_info;
9213 BYTE * m_pObjectCopy; // local cached copy of the object
9214 BYTE * m_objectLocalVars; // var base in _this_ process
9215 // points _into_ m_pObjectCopy
9216 BYTE * m_stringBuffer; // points _into_ m_pObjectCopy
9218 // remote location information
9219 RemoteValueHome m_valueHome;
9221 // If instances fields are added by EnC, their storage will be off the objects
9222 // syncblock. Cache per-object information about such fields here.
9223 CordbHangingFieldTable m_hangingFieldsInstance;
9226 HRESULT IsExceptionObject();
9228 BOOL m_fIsExceptionObject;
9235 /* ------------------------------------------------------------------------- *
9236 * Value Class Object Value class
9237 * ------------------------------------------------------------------------- */
9239 class CordbVCObjectValue : public CordbValue,
9240 public ICorDebugObjectValue, public ICorDebugObjectValue2,
9241 public ICorDebugGenericValue, public ICorDebugValue2,
9242 public ICorDebugValue3
9245 CordbVCObjectValue(CordbAppDomain * pAppdomain,
9247 TargetBuffer remoteValue,
9248 EnregisteredValueHomeHolder * ppRemoteRegAddr);
9249 virtual ~CordbVCObjectValue();
9252 virtual const char * DbgGetName() { return "CordbVCObjectValue"; }
9255 //-----------------------------------------------------------
9257 //-----------------------------------------------------------
9259 ULONG STDMETHODCALLTYPE AddRef()
9261 return (BaseAddRef());
9263 ULONG STDMETHODCALLTYPE Release()
9265 return (BaseRelease());
9267 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
9269 //-----------------------------------------------------------
9271 //-----------------------------------------------------------
9273 COM_METHOD GetType(CorElementType *pType);
9275 COM_METHOD GetSize(ULONG32 *pSize)
9277 return (CordbValue::GetSize(pSize));
9279 COM_METHOD CreateBreakpoint(ICorDebugValueBreakpoint **ppBreakpoint)
9281 return (CordbValue::CreateBreakpoint(ppBreakpoint));
9284 COM_METHOD GetAddress(CORDB_ADDRESS *pAddress)
9286 LIMITED_METHOD_CONTRACT;
9288 FAIL_IF_NEUTERED(this);
9289 VALIDATE_POINTER_TO_OBJECT(pAddress, CORDB_ADDRESS *);
9291 *pAddress = m_pValueHome->GetAddress();
9295 //-----------------------------------------------------------
9297 //-----------------------------------------------------------
9299 COM_METHOD GetExactType(ICorDebugType **ppType)
9301 return (CordbValue::GetExactType(ppType));
9304 //-----------------------------------------------------------
9306 //-----------------------------------------------------------
9308 COM_METHOD GetSize64(ULONG64 *pSize)
9310 return (CordbValue::GetSize64(pSize));
9313 //-----------------------------------------------------------
9314 // ICorDebugObjectValue
9315 //-----------------------------------------------------------
9317 COM_METHOD GetClass(ICorDebugClass **ppClass);
9318 COM_METHOD GetFieldValue(ICorDebugClass *pClass,
9319 mdFieldDef fieldDef,
9320 ICorDebugValue **ppValue);
9321 COM_METHOD GetVirtualMethod(mdMemberRef memberRef,
9322 ICorDebugFunction **ppFunction);
9323 COM_METHOD GetContext(ICorDebugContext **ppContext);
9324 COM_METHOD IsValueClass(BOOL *pbIsValueClass);
9325 COM_METHOD GetManagedCopy(IUnknown **ppObject);
9326 COM_METHOD SetFromManagedCopy(IUnknown *pObject);
9327 COM_METHOD GetFieldValueForType(ICorDebugType * pType,
9328 mdFieldDef fieldDef,
9329 ICorDebugValue ** ppValue);
9330 COM_METHOD GetVirtualMethodAndType(mdMemberRef memberRef,
9331 ICorDebugFunction **ppFunction,
9332 ICorDebugType **ppType);
9334 //-----------------------------------------------------------
9335 // ICorDebugGenericValue
9336 //-----------------------------------------------------------
9338 COM_METHOD GetValue(void *pTo);
9339 COM_METHOD SetValue(void *pFrom);
9341 //-----------------------------------------------------------
9343 //-----------------------------------------------------------
9345 // Initializes the Right-Side's representation of a Value Class object.
9346 HRESULT Init(MemoryRange localValue);
9347 //HRESULT ResolveValueClass();
9348 CordbClass *GetClass();
9350 // Returns a pointer to the ValueHome field
9352 ValueHome * GetValueHome() { return m_pValueHome; };
9354 //-----------------------------------------------------------
9356 //-----------------------------------------------------------
9360 // local cached copy of the value class
9361 BYTE * m_pObjectCopy;
9363 // location information
9364 ValueHome * m_pValueHome;
9368 /* ------------------------------------------------------------------------- *
9370 * ------------------------------------------------------------------------- */
9372 class CordbBoxValue : public CordbValue,
9373 public ICorDebugBoxValue,
9374 public ICorDebugGenericValue,
9375 public ICorDebugValue2,
9376 public ICorDebugValue3,
9377 public ICorDebugHeapValue2,
9378 public ICorDebugHeapValue3
9381 CordbBoxValue(CordbAppDomain * appdomain,
9383 TargetBuffer remoteValue,
9385 SIZE_T offsetToVars);
9386 virtual ~CordbBoxValue();
9389 virtual const char * DbgGetName() { return "CordbBoxValue"; }
9392 //-----------------------------------------------------------
9394 //-----------------------------------------------------------
9396 ULONG STDMETHODCALLTYPE AddRef()
9398 return (BaseAddRef());
9400 ULONG STDMETHODCALLTYPE Release()
9402 return (BaseRelease());
9404 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
9406 //-----------------------------------------------------------
9408 //-----------------------------------------------------------
9410 COM_METHOD GetType(CorElementType *pType);
9412 COM_METHOD GetSize(ULONG32 *pSize)
9414 return (CordbValue::GetSize(pSize));
9416 COM_METHOD CreateBreakpoint(ICorDebugValueBreakpoint **ppBreakpoint)
9418 return (CordbValue::CreateBreakpoint(ppBreakpoint));
9421 COM_METHOD GetAddress(CORDB_ADDRESS *pAddress)
9423 LIMITED_METHOD_CONTRACT;
9425 FAIL_IF_NEUTERED(this);
9426 VALIDATE_POINTER_TO_OBJECT(pAddress, CORDB_ADDRESS *);
9428 *pAddress = m_valueHome.GetAddress();
9432 //-----------------------------------------------------------
9434 //-----------------------------------------------------------
9436 COM_METHOD GetExactType(ICorDebugType **ppType)
9438 return (CordbValue::GetExactType(ppType));
9441 //-----------------------------------------------------------
9443 //-----------------------------------------------------------
9445 COM_METHOD GetSize64(ULONG64 *pSize)
9447 return (CordbValue::GetSize64(pSize));
9450 //-----------------------------------------------------------
9451 // ICorDebugHeapValue
9452 //-----------------------------------------------------------
9454 COM_METHOD IsValid(BOOL *pbValid);
9455 COM_METHOD CreateRelocBreakpoint(ICorDebugValueBreakpoint **ppBreakpoint);
9457 //-----------------------------------------------------------
9458 // ICorDebugHeapValue2
9459 //-----------------------------------------------------------
9460 COM_METHOD CreateHandle(CorDebugHandleType type, ICorDebugHandleValue ** ppHandle);
9462 //-----------------------------------------------------------
9463 // ICorDebugHeapValue3
9464 //-----------------------------------------------------------
9465 COM_METHOD GetThreadOwningMonitorLock(ICorDebugThread **ppThread, DWORD *pAcquisitionCount);
9466 COM_METHOD GetMonitorEventWaitList(ICorDebugThreadEnum **ppThreadEnum);
9468 //-----------------------------------------------------------
9469 // ICorDebugGenericValue
9470 //-----------------------------------------------------------
9472 COM_METHOD GetValue(void *pTo);
9473 COM_METHOD SetValue(void *pFrom);
9475 //-----------------------------------------------------------
9476 // ICorDebugBoxValue
9477 //-----------------------------------------------------------
9478 COM_METHOD GetObject(ICorDebugObjectValue **ppObject);
9480 // Returns a pointer to the ValueHome field
9482 RemoteValueHome * GetValueHome() { return &m_valueHome; };
9484 //-----------------------------------------------------------
9486 //-----------------------------------------------------------
9489 SIZE_T m_offsetToVars;
9491 // remote location information
9492 RemoteValueHome m_valueHome;
9496 /* ------------------------------------------------------------------------- *
9498 * ------------------------------------------------------------------------- */
9500 class CordbArrayValue : public CordbValue,
9501 public ICorDebugArrayValue,
9502 public ICorDebugGenericValue,
9503 public ICorDebugValue2,
9504 public ICorDebugValue3,
9505 public ICorDebugHeapValue2,
9506 public ICorDebugHeapValue3
9509 CordbArrayValue(CordbAppDomain * appdomain,
9511 DebuggerIPCE_ObjectData * pObjectInfo,
9512 TargetBuffer remoteValue);
9513 virtual ~CordbArrayValue();
9516 virtual const char * DbgGetName() { return "CordbArrayValue"; }
9519 //-----------------------------------------------------------
9521 //-----------------------------------------------------------
9523 ULONG STDMETHODCALLTYPE AddRef()
9525 return (BaseAddRef());
9527 ULONG STDMETHODCALLTYPE Release()
9529 return (BaseRelease());
9531 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
9533 //-----------------------------------------------------------
9535 //-----------------------------------------------------------
9537 COM_METHOD GetType(CorElementType *pType)
9539 return (CordbValue::GetType(pType));
9541 COM_METHOD GetSize(ULONG32 *pSize)
9543 return (CordbValue::GetSize(pSize));
9545 COM_METHOD GetAddress(CORDB_ADDRESS *pAddress)
9547 VALIDATE_POINTER_TO_OBJECT(pAddress, CORDB_ADDRESS *);
9548 *pAddress = m_valueHome.GetAddress();
9551 COM_METHOD CreateBreakpoint(ICorDebugValueBreakpoint **ppBreakpoint)
9553 return (CordbValue::CreateBreakpoint(ppBreakpoint));
9556 //-----------------------------------------------------------
9558 //-----------------------------------------------------------
9560 COM_METHOD GetExactType(ICorDebugType **ppType)
9562 return (CordbValue::GetExactType(ppType));
9565 //-----------------------------------------------------------
9567 //-----------------------------------------------------------
9569 COM_METHOD GetSize64(ULONG64 *pSize)
9571 return (CordbValue::GetSize64(pSize));
9574 //-----------------------------------------------------------
9575 // ICorDebugHeapValue
9576 //-----------------------------------------------------------
9578 COM_METHOD IsValid(BOOL *pbValid);
9579 COM_METHOD CreateRelocBreakpoint(ICorDebugValueBreakpoint **ppBreakpoint);
9581 //-----------------------------------------------------------
9582 // ICorDebugHeapValue2
9583 //-----------------------------------------------------------
9584 COM_METHOD CreateHandle(CorDebugHandleType type, ICorDebugHandleValue ** ppHandle);
9586 //-----------------------------------------------------------
9587 // ICorDebugHeapValue3
9588 //-----------------------------------------------------------
9589 COM_METHOD GetThreadOwningMonitorLock(ICorDebugThread **ppThread, DWORD *pAcquisitionCount);
9590 COM_METHOD GetMonitorEventWaitList(ICorDebugThreadEnum **ppThreadEnum);
9592 //-----------------------------------------------------------
9593 // ICorDebugArrayValue
9594 //-----------------------------------------------------------
9596 COM_METHOD GetElementType(CorElementType * pType);
9597 COM_METHOD GetRank(ULONG32 * pnRank);
9598 COM_METHOD GetCount(ULONG32 * pnCount);
9599 COM_METHOD GetDimensions(ULONG32 cdim, ULONG32 dims[]);
9600 COM_METHOD HasBaseIndicies(BOOL * pbHasBaseIndices);
9601 COM_METHOD GetBaseIndicies(ULONG32 cdim, ULONG32 indices[]);
9602 COM_METHOD GetElement(ULONG32 cdim, ULONG32 indices[], ICorDebugValue ** ppValue);
9603 COM_METHOD GetElementAtPosition(ULONG32 nIndex, ICorDebugValue ** ppValue);
9605 //-----------------------------------------------------------
9606 // ICorDebugGenericValue
9607 //-----------------------------------------------------------
9609 COM_METHOD GetValue(void *pTo);
9610 COM_METHOD SetValue(void *pFrom);
9612 //-----------------------------------------------------------
9614 //-----------------------------------------------------------
9618 // Returns a pointer to the ValueHome field
9620 RemoteValueHome * GetValueHome() { return &m_valueHome; };
9622 //-----------------------------------------------------------
9624 //-----------------------------------------------------------
9627 // contains information about the array, such as rank, number of elements, element size, etc.
9628 DebuggerIPCE_ObjectData m_info;
9630 // type of the elements
9631 CordbType *m_elemtype;
9633 // consists of three parts: a vector containing the lower bounds for each dimension,
9634 // a vector containing the upper bounds for each dimension,
9635 // a local cached copy of (part of) the array--initialized lazily when we
9636 // request a particular element. If the array is large, we will store only
9637 // part of it, swapping out the cached segment as necessary to retrieve
9638 // requested elements.
9639 BYTE * m_pObjectCopy;
9641 // points to the beginning of the vector containing the lower bounds for each dimension in m_pObjectCopy
9642 DWORD * m_arrayLowerBase;
9644 // points to the beginning of the vector containing the lower bounds for each dimension in m_pObjectCopy
9645 DWORD * m_arrayUpperBase;
9646 // index of lower bound of data currently stored in m_pObjectCopy
9649 // index of upper bound of data currently stored in m_pObjectCopy
9652 // remote location information
9653 RemoteValueHome m_valueHome;
9657 class CordbHandleValue : public CordbValue, public ICorDebugHandleValue, public ICorDebugValue2, public ICorDebugValue3
9660 CordbHandleValue(CordbAppDomain *appdomain,
9662 CorDebugHandleType handleType);
9663 HRESULT Init(VMPTR_OBJECTHANDLE pHandle);
9665 virtual ~CordbHandleValue();
9667 virtual void Neuter();
9668 virtual void NeuterLeftSideResources();
9671 virtual const char * DbgGetName() { return "CordbHandleValue"; }
9675 //-----------------------------------------------------------
9677 //-----------------------------------------------------------
9679 ULONG STDMETHODCALLTYPE AddRef()
9681 return (BaseAddRef());
9683 ULONG STDMETHODCALLTYPE Release()
9685 return (BaseRelease());
9687 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
9689 //-----------------------------------------------------------
9690 // ICorDebugHandleValue interface
9691 //-----------------------------------------------------------
9692 COM_METHOD GetHandleType(CorDebugHandleType *pType);
9696 * The final release of the interface will also dispose of the handle. This
9697 * API provides the ability for client to early dispose the handle.
9700 COM_METHOD Dispose();
9702 //-----------------------------------------------------------
9703 // ICorDebugValue interface
9704 //-----------------------------------------------------------
9705 COM_METHOD GetType(CorElementType *pType);
9706 COM_METHOD GetSize(ULONG32 *pSize);
9707 COM_METHOD GetAddress(CORDB_ADDRESS *pAddress);
9708 COM_METHOD CreateBreakpoint(ICorDebugValueBreakpoint **ppBreakpoint);
9710 //-----------------------------------------------------------
9712 //-----------------------------------------------------------
9714 COM_METHOD GetExactType(ICorDebugType **ppType)
9716 FAIL_IF_NEUTERED(this);
9718 // If AppDomain is already unloaded, return error
9719 if (m_appdomain->IsNeutered() == TRUE)
9721 return COR_E_APPDOMAINUNLOADED;
9723 if (m_vmHandle.IsNull())
9725 return CORDBG_E_HANDLE_HAS_BEEN_DISPOSED;
9728 return (CordbValue::GetExactType(ppType));
9731 //-----------------------------------------------------------
9733 //-----------------------------------------------------------
9735 COM_METHOD GetSize64(ULONG64 *pSize);
9737 //-----------------------------------------------------------
9738 // ICorDebugReferenceValue interface
9739 //-----------------------------------------------------------
9741 COM_METHOD IsNull(BOOL *pbNull);
9742 COM_METHOD GetValue(CORDB_ADDRESS *pValue);
9743 COM_METHOD SetValue(CORDB_ADDRESS value);
9744 COM_METHOD Dereference(ICorDebugValue **ppValue);
9745 COM_METHOD DereferenceStrong(ICorDebugValue **ppValue);
9747 //-----------------------------------------------------------
9749 //-----------------------------------------------------------
9751 // Returns a pointer to the ValueHome field
9753 RemoteValueHome * GetValueHome() { return NULL; };
9756 //BOOL RefreshHandleValue(void **pObjectToken);
9757 HRESULT RefreshHandleValue();
9759 // EE object handle pointer. Can be casted to OBJECTHANDLE when go to LS
9760 // This instance owns the handle object and must call into the VM to release
9762 // If this is non-null, then we increment code:CordbProces::IncrementOutstandingHandles.
9763 // Once it goes null, we should decrement the count.
9764 // Use AssignHandle, ClearHandle to keep this in sync.
9765 VMPTR_OBJECTHANDLE m_vmHandle;
9768 void AssignHandle(VMPTR_OBJECTHANDLE handle);
9771 BOOL m_fCanBeValid; // true if object "can" be valid. False when object is no longer valid.
9772 CorDebugHandleType m_handleType; // handle type can be strong or weak
9773 DebuggerIPCE_ObjectData m_info;
9774 ; // ICORDebugClass of this object when we create the handle
9777 // This class actually has the implementation for ICorDebugHeap3 interfaces. Any value which implements
9778 // the interface just delegates to these static calls.
9779 class CordbHeapValue3Impl
9782 static HRESULT GetThreadOwningMonitorLock(CordbProcess* pProcess,
9783 CORDB_ADDRESS remoteObjAddress,
9784 ICorDebugThread **ppThread,
9785 DWORD *pAcquistionCount);
9786 static HRESULT GetMonitorEventWaitList(CordbProcess* pProcess,
9787 CORDB_ADDRESS remoteObjAddress,
9788 ICorDebugThreadEnum **ppThreadEnum);
9791 /* ------------------------------------------------------------------------- *
9793 * ------------------------------------------------------------------------- */
9795 class CordbEval : public CordbBase, public ICorDebugEval, public ICorDebugEval2
9798 CordbEval(CordbThread* pThread);
9799 virtual ~CordbEval();
9802 virtual const char * DbgGetName() { return "CordbEval"; }
9805 virtual void Neuter();
9806 virtual void NeuterLeftSideResources();
9808 //-----------------------------------------------------------
9810 //-----------------------------------------------------------
9812 ULONG STDMETHODCALLTYPE AddRef()
9814 return (BaseAddRef());
9816 ULONG STDMETHODCALLTYPE Release()
9818 return (BaseRelease());
9820 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
9822 //-----------------------------------------------------------
9824 //-----------------------------------------------------------
9826 COM_METHOD CallFunction(ICorDebugFunction *pFunction,
9828 ICorDebugValue *ppArgs[]);
9829 COM_METHOD NewObject(ICorDebugFunction *pConstructor,
9831 ICorDebugValue *ppArgs[]);
9832 COM_METHOD NewObjectNoConstructor(ICorDebugClass *pClass);
9833 COM_METHOD NewString(LPCWSTR string);
9834 COM_METHOD NewArray(CorElementType elementType,
9835 ICorDebugClass *pElementClass,
9838 ULONG32 lowBounds[]);
9839 COM_METHOD IsActive(BOOL *pbActive);
9841 COM_METHOD GetResult(ICorDebugValue **ppResult);
9842 COM_METHOD GetThread(ICorDebugThread **ppThread);
9843 COM_METHOD CreateValue(CorElementType elementType,
9844 ICorDebugClass *pElementClass,
9845 ICorDebugValue **ppValue);
9846 COM_METHOD NewStringWithLength(LPCWSTR wszString, UINT iLength);
9848 COM_METHOD CallParameterizedFunction(ICorDebugFunction * pFunction,
9850 ICorDebugType * rgpTypeArgs[],
9852 ICorDebugValue * rgpArgs[]);
9854 COM_METHOD CreateValueForType(ICorDebugType *pType,
9855 ICorDebugValue **ppValue);
9857 COM_METHOD NewParameterizedObject(ICorDebugFunction * pConstructor,
9859 ICorDebugType * rgpTypeArgs[],
9861 ICorDebugValue * rgpArgs[]);
9863 COM_METHOD NewParameterizedObjectNoConstructor(ICorDebugClass * pClass,
9865 ICorDebugType * rgpTypeArgs[]);
9867 COM_METHOD NewParameterizedArray(ICorDebugType * pElementType,
9870 ULONG32 lowBounds[]);
9872 //-----------------------------------------------------------
9874 //-----------------------------------------------------------
9876 COM_METHOD RudeAbort();
9878 //-----------------------------------------------------------
9880 //-----------------------------------------------------------
9881 HRESULT GatherArgInfo(ICorDebugValue *pValue,
9882 DebuggerIPCE_FuncEvalArgData *argData);
9883 HRESULT SendCleanup();
9885 // Create a RS literal for primitive type funceval result. In case the result is used as an argument for
9886 // another funceval, we need to make sure that we're not relying on the LS value, which will be freed and
9887 // thus unavailable.
9888 HRESULT CreatePrimitiveLiteral(CordbType * pType,
9889 ICorDebugValue ** ppValue);
9891 //-----------------------------------------------------------
9893 //-----------------------------------------------------------
9895 bool IsEvalDuringException() { return m_evalDuringException; }
9897 // We must keep a strong reference to the thread so we can properly fail out of SendCleanup if someone releases an
9898 // ICorDebugEval after the process has completely gone away.
9899 RSSmartPtr<CordbThread> m_thread;
9901 CordbFunction *m_function;
9902 CordbClass *m_class;
9903 DebuggerIPCE_FuncEvalType m_evalType;
9905 HRESULT SendFuncEval(unsigned int genericArgsCount, ICorDebugType *genericArgs[], void *argData1, unsigned int argData1Size, void *argData2, unsigned int argData2Size, DebuggerIPCEvent * event);
9906 HRESULT FilterHR(HRESULT hr);
9907 BOOL DoAppDomainsMatch( CordbAppDomain* pAppDomain, ULONG32 nTypes, ICorDebugType *pTypes[], ULONG32 nValues, ICorDebugValue *pValues[] );
9915 // This is an OBJECTHANDLE on the LS if func-eval creates a strong handle.
9916 // This is a resource in the left-side and must be cleaned up in the left-side.
9917 // This gets handled off to a CordbHandleValue (m_pHandleValue) once code:CordbEval::GetResult
9918 // and then the CordbHandle is responsible for releasing it in the left-side.
9919 // Issue!! This will be leaked if nobody calls GetResult().
9920 VMPTR_OBJECTHANDLE m_vmObjectHandle;
9922 // This is the corresponding cached CordbHandleValue for GetResult.
9923 // This takes ownership of the strong handle, m_objectHandle.
9924 // This is an External reference, which keeps the Value from being neutered
9925 // on a NeuterAtWill sweep.
9926 RSExtSmartPtr<CordbHandleValue> m_pHandleValue;
9928 DebuggerIPCE_ExpandedTypeData m_resultType;
9929 VMPTR_AppDomain m_resultAppDomainToken;
9931 // Left-side memory that needs to be freed.
9932 LSPTR_DEBUGGEREVAL m_debuggerEvalKey;
9935 // If we're evalling during a thread's exception, remember the info so that we can restore it when we're done.
9936 bool m_evalDuringException; // flag whether we're during the thread's exception.
9937 VMPTR_OBJECTHANDLE m_vmThreadOldExceptionHandle; // object handle for thread's managed exception object.
9940 // Func-eval should perturb the the thread's current appdomain. So we remember it at start
9941 // and then ensure that the func-eval complete restores it.
9942 CordbAppDomain * m_DbgAppDomainStarted;
9947 /* ------------------------------------------------------------------------- *
9948 * Win32 Event Thread class
9949 * ------------------------------------------------------------------------- */
9950 const unsigned int CW32ET_UNKNOWN_PROCESS_SLOT = 0xFFffFFff; // it's a managed process,
9951 //but we don't know which slot it's in - for Detach.
9953 //---------------------------------------------------------------------------------------
9955 // Dedicated thread for win32 debugging operations.
9958 // This is owned by the ShimProcess object. That will both create this and destroy it.
9959 // OS restriction is that all win32 debugging APIs (CreateProcess, DebugActiveProcess,
9960 // DebugActiveProcessStop, WaitForDebugEvent, ContinueDebugEvent, etc) are on the same thread.
9962 class CordbWin32EventThread
9964 friend class CordbProcess; //so that Detach can call ExitProcess
9966 CordbWin32EventThread(Cordb * pCordb, ShimProcess * pShim);
9967 virtual ~CordbWin32EventThread();
9970 // You create a new instance of this class, call Init() to set it up,
9971 // then call Start() start processing events. Stop() terminates the
9972 // thread and deleting the instance cleans all the handles and such
9979 HRESULT SendCreateProcessEvent(MachineInfo machineInfo,
9980 LPCWSTR programName,
9981 __in_z LPWSTR programArgs,
9982 LPSECURITY_ATTRIBUTES lpProcessAttributes,
9983 LPSECURITY_ATTRIBUTES lpThreadAttributes,
9984 BOOL bInheritHandles,
9985 DWORD dwCreationFlags,
9986 PVOID lpEnvironment,
9987 LPCWSTR lpCurrentDirectory,
9988 LPSTARTUPINFOW lpStartupInfo,
9989 LPPROCESS_INFORMATION lpProcessInformation,
9990 CorDebugCreateProcessFlags corDebugFlags);
9992 HRESULT SendDebugActiveProcessEvent(MachineInfo machineInfo,
9995 CordbProcess *pProcess);
9997 HRESULT SendDetachProcessEvent(CordbProcess *pProcess);
9999 #ifdef FEATURE_INTEROP_DEBUGGING
10000 HRESULT SendUnmanagedContinue(CordbProcess *pProcess,
10001 EUMContinueType eContType);
10002 HRESULT UnmanagedContinue(CordbProcess *pProcess,
10003 EUMContinueType eContType);
10004 void DoDbgContinue(CordbProcess * pProcess,
10005 CordbUnmanagedEvent * pUnmanagedEvent);
10006 void ForceDbgContinue(CordbProcess *pProcess,
10007 CordbUnmanagedThread *ut,
10011 #endif //FEATURE_INTEROP_DEBUGGING
10013 void LockSendToWin32EventThreadMutex()
10015 LOG((LF_CORDB, LL_INFO10000, "W32ET::LockSendToWin32EventThreadMutex\n"));
10016 m_sendToWin32EventThreadMutex.Lock();
10019 void UnlockSendToWin32EventThreadMutex()
10021 m_sendToWin32EventThreadMutex.Unlock();
10022 LOG((LF_CORDB, LL_INFO10000, "W32ET::UnlockSendToWin32EventThreadMutex\n"));
10025 bool IsWin32EventThread()
10027 return (m_threadId == GetCurrentThreadId());
10030 void Win32EventLoop();
10033 INativeEventPipeline * GetNativePipeline();
10036 static DWORD WINAPI ThreadProc(LPVOID parameter);
10038 void CreateProcess();
10041 INativeEventPipeline * m_pNativePipeline;
10044 void AttachProcess();
10046 void HandleUnmanagedContinue();
10048 void ExitProcess(bool fDetach);
10051 RSSmartPtr<Cordb> m_cordb;
10055 HANDLE m_threadControlEvent;
10056 HANDLE m_actionTakenEvent;
10059 // The process that we're 1:1 with.
10060 // This is set when we get a Create / Attach event.
10061 // This is only used on the W32ET, which guarantees it will free of races.
10062 RSSmartPtr<CordbProcess> m_pProcess;
10065 ShimProcess * m_pShim;
10067 // @todo - convert this into Stop-Go lock?
10068 RSLock m_sendToWin32EventThreadMutex;
10070 unsigned int m_action;
10071 HRESULT m_actionResult;
10076 MachineInfo machineInfo;
10077 LPCWSTR programName;
10078 LPWSTR programArgs;
10079 LPSECURITY_ATTRIBUTES lpProcessAttributes;
10080 LPSECURITY_ATTRIBUTES lpThreadAttributes;
10081 BOOL bInheritHandles;
10082 DWORD dwCreationFlags;
10083 PVOID lpEnvironment;
10084 LPCWSTR lpCurrentDirectory;
10085 LPSTARTUPINFOW lpStartupInfo;
10086 LPPROCESS_INFORMATION lpProcessInformation;
10087 CorDebugCreateProcessFlags corDebugFlags;
10092 MachineInfo machineInfo;
10094 #if !defined(FEATURE_DBGIPC_TRANSPORT_DI)
10097 CordbProcess *pProcess;
10099 // Wrapper to determine if we're interop-debugging.
10100 bool IsInteropDebugging()
10102 #if !defined(FEATURE_DBGIPC_TRANSPORT_DI)
10103 return fWin32Attach;
10112 CordbProcess *pProcess;
10117 CordbProcess *process;
10118 EUMContinueType eContType;
10124 // Thread-safe stack which.
10125 template <typename T>
10126 class InterlockedStack
10129 InterlockedStack();
10130 ~InterlockedStack();
10132 // Thread safe pushes + pops.
10133 // Many threads can push simultaneously.
10134 // Only 1 thread can pop.
10135 void Push(T * pItem);
10142 //-----------------------------------------------------------------------------
10143 // Workitem to be placed on RCET worker queue.
10144 // There's 1 RCET for to be shared by all processes.
10145 //-----------------------------------------------------------------------------
10150 // Item is executed and then removed from the list and deleted.
10151 virtual void Do() = 0;
10153 CordbProcess * GetProcess() { return m_pProcess; }
10156 RCETWorkItem(CordbProcess * pProcess)
10158 m_pProcess.Assign(pProcess);
10162 RSSmartPtr<CordbProcess> m_pProcess;
10164 // This field is accessed by the InterlockedStack.
10165 friend class InterlockedStack<RCETWorkItem>;
10166 RCETWorkItem * m_next;
10170 // Item to do Neutering work on ExitProcess.
10171 class ExitProcessWorkItem : public RCETWorkItem
10174 ExitProcessWorkItem(CordbProcess * pProc) : RCETWorkItem(pProc)
10181 // Item to do send Attach event.
10182 class SendAttachProcessWorkItem : public RCETWorkItem
10185 SendAttachProcessWorkItem(CordbProcess * pProc) : RCETWorkItem(pProc)
10193 /* ------------------------------------------------------------------------- *
10194 * Runtime Controller Event Thread class
10195 * ------------------------------------------------------------------------- */
10197 class CordbRCEventThread
10200 CordbRCEventThread(Cordb* cordb);
10201 virtual ~CordbRCEventThread();
10204 // You create a new instance of this class, call Init() to set it up,
10205 // then call Start() start processing events. Stop() terminates the
10206 // thread and deleting the instance cleans all the handles and such
10213 // RCET will take ownership of this item and delete it.
10214 void QueueAsyncWorkItem(RCETWorkItem * pItem);
10216 HRESULT SendIPCEvent(CordbProcess* process,
10217 DebuggerIPCEvent* event,
10220 void ProcessStateChanged();
10221 void FlushQueuedEvents(CordbProcess* process);
10223 HRESULT WaitForIPCEventFromProcess(CordbProcess* process,
10224 CordbAppDomain *pAppDomain,
10225 DebuggerIPCEvent* event);
10227 bool IsRCEventThread();
10230 void DrainWorkerQueue();
10233 static DWORD WINAPI ThreadProc(LPVOID parameter);
10237 InterlockedStack<class RCETWorkItem> m_WorkerStack;
10239 RSSmartPtr<Cordb> m_cordb;
10243 HANDLE m_threadControlEvent;
10244 BOOL m_processStateChanged;
10247 #ifdef FEATURE_INTEROP_DEBUGGING
10248 /* ------------------------------------------------------------------------- *
10249 * Unmanaged Event struct
10250 * ------------------------------------------------------------------------- */
10252 enum CordbUnmanagedEventState
10255 // The continued flags get set in one of a few patterns.
10256 // 1) The event is continued having never been hijacked =>
10257 // EventContinuedUnhijacked is set
10258 // 2) The event is continued having been hijacked and then the process terminates or
10259 // an error occurs before the hijack finishes =>
10260 // EventContinuedHijacked is set
10261 // 3) The event is continued having been hijacked, then the hijack completes and
10262 // execution resumes in the debuggee
10263 // EventContinuedHijacked is set
10264 // EventContinuedUnhijacked is set
10267 CUES_ExceptionCleared = 0x01,
10268 CUES_EventContinuedHijacked = 0x02,
10269 CUES_EventContinuedUnhijacked = 0x04,
10270 CUES_Dispatched = 0x08,
10271 CUES_ExceptionUnclearable = 0x10,
10273 // This is set when a user continues the event by calling
10275 CUES_UserContinued = 0x20,
10276 // This is true if the event is an IB event
10277 CUES_IsIBEvent = 0x40,
10280 struct CordbUnmanagedEvent
10283 BOOL IsExceptionCleared() { return m_state & CUES_ExceptionCleared; }
10284 BOOL IsEventContinuedHijacked() { return m_state & CUES_EventContinuedHijacked; }
10285 BOOL IsEventContinuedUnhijacked() { return m_state & CUES_EventContinuedUnhijacked; }
10286 BOOL IsEventUserContinued() { return m_state & CUES_UserContinued; }
10287 BOOL IsEventWaitingForContinue()
10289 return (!IsEventContinuedHijacked() && !IsEventContinuedUnhijacked());
10291 BOOL IsDispatched() { return m_state & CUES_Dispatched; }
10292 BOOL IsExceptionUnclearable() { return m_state & CUES_ExceptionUnclearable; }
10293 BOOL IsIBEvent() { return m_state & CUES_IsIBEvent; }
10295 void SetState(CordbUnmanagedEventState state) { m_state = (CordbUnmanagedEventState)(m_state | state); }
10296 void ClearState(CordbUnmanagedEventState state) { m_state = (CordbUnmanagedEventState)(m_state & ~state); }
10298 CordbUnmanagedThread *m_owner;
10299 CordbUnmanagedEventState m_state;
10300 DEBUG_EVENT m_currentDebugEvent;
10301 CordbUnmanagedEvent *m_next;
10305 /* ------------------------------------------------------------------------- *
10306 * Unmanaged Thread class
10307 * ------------------------------------------------------------------------- */
10309 enum CordbUnmanagedThreadState
10311 CUTS_None = 0x0000,
10312 CUTS_Deleted = 0x0001,
10313 CUTS_FirstChanceHijacked = 0x0002,
10314 // Set when interop debugging needs the SS flag to be enabled
10315 // regardless of what the user wants it to be
10316 CUTS_IsSSFlagNeeded = 0x0004,
10317 CUTS_GenericHijacked = 0x0008,
10318 // when the m_raiseExceptionEntryContext is valid
10319 CUTS_HasRaiseExceptionEntryCtx = 0x0010,
10320 CUTS_BlockingForSync = 0x0020,
10321 CUTS_Suspended = 0x0040,
10322 CUTS_IsSpecialDebuggerThread = 0x0080,
10323 // when the thread is re-executing RaiseException to retrigger an exception
10324 CUTS_IsRaiseExceptionHijacked = 0x0100,
10325 CUTS_HasIBEvent = 0x0200,
10326 CUTS_HasOOBEvent = 0x0400,
10327 CUTS_HasSpecialStackOverflowCase = 0x0800,
10329 CUTS_DEBUG_SingleStep = 0x1000,
10331 CUTS_SkippingNativePatch = 0x2000,
10332 CUTS_HasContextSet = 0x4000,
10333 // Set when interop debugging is making use of the single step flag
10334 // but the user has not set it
10335 CUTS_IsSSFlagHidden = 0x8000
10339 class CordbUnmanagedThread : public CordbBase
10342 CordbUnmanagedThread(CordbProcess *pProcess, DWORD dwThreadId, HANDLE hThread, void *lpThreadLocalBase);
10343 ~CordbUnmanagedThread();
10345 using CordbBase::GetProcess;
10348 virtual const char * DbgGetName() { return "CordbUnmanagedThread"; }
10351 // CordbUnmanagedThread is a purely internal object. It's not exposed via ICorDebug APIs and so
10352 // we should never use External AddRef.
10353 ULONG STDMETHODCALLTYPE AddRef() { _ASSERTE(!"Don't use external addref on a CordbUnmanagedThread"); return (BaseAddRef());}
10354 ULONG STDMETHODCALLTYPE Release() { _ASSERTE(!"Don't use external release on a CordbUnmanagedThread"); return (BaseRelease());}
10356 COM_METHOD QueryInterface(REFIID riid, void **ppInterface)
10358 _ASSERTE(!"Don't use QI on a CordbUnmanagedThread");
10359 // Not really used since we never expose this class. If we ever do expose this class via the ICorDebug API then
10360 // we should, of course, implement this.
10361 return E_NOINTERFACE;
10364 HRESULT LoadTLSArrayPtr();
10366 // Hijacks this thread to a hijack worker function which recieves the current
10367 // context and the provided exception record. The reason determines what code
10368 // the hijack worker executes
10369 HRESULT SetupFirstChanceHijack(EHijackReason::EHijackReason reason, const EXCEPTION_RECORD * pExceptionRecord);
10370 HRESULT SetupFirstChanceHijackForSync();
10372 HRESULT SetupGenericHijack(DWORD eventCode, const EXCEPTION_RECORD * pRecord);
10373 HRESULT FixupFromGenericHijack();
10375 HRESULT FixupAfterOOBException(CordbUnmanagedEvent * ue);
10377 void SetupForSkipBreakpoint(NativePatch * pNativePatch);
10378 void FixupForSkipBreakpoint();
10381 // These are wrappers for the OS calls which hide
10382 // the effects of hijacking and internal SS flag usage
10383 HRESULT GetThreadContext(DT_CONTEXT * pContext);
10384 HRESULT SetThreadContext(DT_CONTEXT * pContext);
10386 // Turns on and off the internal usage of the SS flag
10387 VOID BeginStepping();
10388 VOID EndStepping();
10390 // An accessor for &m_context, this value generally stores
10391 // a context we may need to restore after a hijack completes
10392 DT_CONTEXT * GetHijackCtx();
10395 CORDB_ADDRESS m_stackBase;
10396 CORDB_ADDRESS m_stackLimit;
10399 BOOL GetStackRange(CORDB_ADDRESS *pBase, CORDB_ADDRESS *pLimit);
10401 BOOL IsDeleted() {LIMITED_METHOD_CONTRACT; return m_state & CUTS_Deleted; }
10402 BOOL IsFirstChanceHijacked() {LIMITED_METHOD_CONTRACT; return m_state & CUTS_FirstChanceHijacked; }
10403 BOOL IsGenericHijacked() {LIMITED_METHOD_CONTRACT; return m_state & CUTS_GenericHijacked; }
10404 BOOL IsBlockingForSync() {LIMITED_METHOD_CONTRACT; return m_state & CUTS_BlockingForSync; }
10405 BOOL IsSuspended() {LIMITED_METHOD_CONTRACT; return m_state & CUTS_Suspended; }
10406 BOOL IsSpecialDebuggerThread() {LIMITED_METHOD_CONTRACT; return m_state & CUTS_IsSpecialDebuggerThread; }
10407 BOOL HasIBEvent() {LIMITED_METHOD_CONTRACT; return m_state & CUTS_HasIBEvent; }
10408 BOOL HasOOBEvent() { return m_state & CUTS_HasOOBEvent; }
10409 BOOL HasSpecialStackOverflowCase() {LIMITED_METHOD_CONTRACT; return m_state & CUTS_HasSpecialStackOverflowCase; }
10411 BOOL IsDEBUGTrace() { return m_state & CUTS_DEBUG_SingleStep; }
10413 BOOL IsSkippingNativePatch() { LIMITED_METHOD_CONTRACT; return m_state & CUTS_SkippingNativePatch; }
10414 BOOL IsContextSet() { LIMITED_METHOD_CONTRACT; return m_state & CUTS_HasContextSet; }
10415 BOOL IsSSFlagNeeded() { LIMITED_METHOD_CONTRACT; return m_state & CUTS_IsSSFlagNeeded; }
10416 BOOL IsSSFlagHidden() { LIMITED_METHOD_CONTRACT; return m_state & CUTS_IsSSFlagHidden; }
10417 BOOL HasRaiseExceptionEntryCtx() { LIMITED_METHOD_CONTRACT; return m_state & CUTS_HasRaiseExceptionEntryCtx; }
10418 BOOL IsRaiseExceptionHijacked() { LIMITED_METHOD_CONTRACT; return m_state & CUTS_IsRaiseExceptionHijacked; }
10420 void SetState(CordbUnmanagedThreadState state)
10422 LIMITED_METHOD_CONTRACT;
10423 m_state = (CordbUnmanagedThreadState)(m_state | state);
10424 _ASSERTE(!IsSuspended() || !IsBlockingForSync());
10425 _ASSERTE(!IsSuspended() || !IsFirstChanceHijacked());
10427 void ClearState(CordbUnmanagedThreadState state) {LIMITED_METHOD_CONTRACT; m_state = (CordbUnmanagedThreadState)(m_state & ~state); }
10429 void HijackToRaiseException();
10430 void RestoreFromRaiseExceptionHijack();
10431 void SaveRaiseExceptionEntryContext();
10432 void ClearRaiseExceptionEntryContext();
10433 BOOL IsExceptionFromLastRaiseException(const EXCEPTION_RECORD* pExceptionRecord);
10435 CordbUnmanagedEvent *IBEvent() {LIMITED_METHOD_CONTRACT; return &m_IBEvent; }
10436 CordbUnmanagedEvent *IBEvent2() {LIMITED_METHOD_CONTRACT; return &m_IBEvent2; }
10437 CordbUnmanagedEvent *OOBEvent() { return &m_OOBEvent; }
10441 return (DWORD) this->m_id;
10444 #ifdef DBG_TARGET_X86
10445 // Stores the thread's current leaf SEH handler
10446 HRESULT SaveCurrentLeafSeh();
10447 // Restores the thread's leaf SEH handler from the previously saved value
10448 HRESULT RestoreLeafSeh();
10451 // Logs basic data about a context to the debugging log
10452 static VOID LogContext(DT_CONTEXT* pContext);
10457 // @dbgtodo - the TLS reading is only used for interop hijacks; which goes away in Arrowhead.
10458 // Target address of the Thread Information Block (TIB).
10459 void *m_threadLocalBase;
10461 // Target address of the Thread Local Storage (TLS) array. This is for slots 0 -63.
10464 // Target Address of extended Thread local Storage array. These are for slots about 63.
10465 // This may be NULL if extended storage is not yet allocated.
10466 void *m_pTLSExtendedArray;
10469 CordbUnmanagedThreadState m_state;
10471 CordbUnmanagedEvent m_IBEvent;
10472 CordbUnmanagedEvent m_IBEvent2;
10473 CordbUnmanagedEvent m_OOBEvent;
10475 LSPTR_CONTEXT m_pLeftSideContext;
10476 void *m_originalHandler;
10479 // Spare context used for various purposes.
10480 // See CordbUnmanagedThread::GetThreadContext for details
10481 DT_CONTEXT m_context;
10483 // The context of the thread the last time it called into kernel32!RaiseException
10484 DT_CONTEXT m_raiseExceptionEntryContext;
10486 DWORD m_raiseExceptionExceptionCode;
10487 DWORD m_raiseExceptionExceptionFlags;
10488 DWORD m_raiseExceptionNumberParameters;
10489 ULONG_PTR m_raiseExceptionExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
10492 #ifdef DBG_TARGET_X86
10493 // the SEH handler which was the leaf when SaveCurrentSeh was called (prior to hijack)
10494 REMOTE_PTR m_pSavedLeafSeh;
10497 HRESULT EnableSSAfterBP();
10498 bool GetEEThreadCantStopHelper();
10500 DWORD_PTR GetTlsSlot(SIZE_T slot);
10501 REMOTE_PTR GetPreDefTlsSlot(SIZE_T slot, bool * pRead);
10503 void * m_pPatchSkipAddress;
10508 * This abstracts away an overload of the OS thread's TLS slot. In
10509 * particular the runtime may or may not have created a thread object for
10510 * a particular OS thread at any point.
10512 * If the runtime has created a thread object, then it stores a pointer to
10513 * that thread object in the thread's TLS slot.
10515 * If not, then interop-debugging uses that TLS slot to store temporary
10518 * To determine this, interop-debugging will set the low bit. Thus when
10519 * we read the TLS slot, if it is non-NULL, anything w/o the low bit set
10520 * is an EE thread object ptr. Anything with the low bit set is an
10521 * interop-debugging value. Any NULL is null, and an indicator that
10522 * there does not exist a runtime thread object for this thread yet.
10525 REMOTE_PTR m_pEEThread;
10526 REMOTE_PTR m_pdwTlsValue;
10527 BOOL m_fValidTlsData;
10529 UINT m_continueCountCached;
10531 void CacheEEDebuggerWord();
10532 HRESULT SetEEThreadValue(REMOTE_PTR EETlsValue);
10533 #ifdef FEATURE_IMPLICIT_TLS
10534 DWORD_PTR GetEEThreadValue();
10535 REMOTE_PTR GetClrModuleTlsDataAddress();
10536 REMOTE_PTR GetEETlsDataBlock();
10540 HRESULT GetEEDebuggerWord(REMOTE_PTR *pValue);
10541 HRESULT SetEEDebuggerWord(REMOTE_PTR value);
10542 HRESULT GetEEThreadPtr(REMOTE_PTR *ppEEThread);
10544 bool GetEEPGCDisabled();
10545 void GetEEState(bool *threadStepping, bool *specialManagedException);
10548 #endif // FEATURE_INTEROP_DEBUGGING
10551 //********************************************************************************
10552 //**************** App Domain Publishing Service API *****************************
10553 //********************************************************************************
10565 void SetData (void *pData) { m_pData = pData;}
10566 void *GetData () { return m_pData;}
10567 void SetNext (EnumElement *pNext) { m_pNext = pNext;}
10568 EnumElement *GetNext () { return m_pNext;}
10572 EnumElement *m_pNext;
10575 #if defined(FEATURE_DBG_PUBLISH)
10577 // Prototype of psapi!GetModuleFileNameEx.
10578 typedef DWORD FPGetModuleFileNameEx(HANDLE, HMODULE, LPTSTR, DWORD);
10581 class CorpubPublish : public CordbCommonBase, public ICorPublish
10585 virtual ~CorpubPublish();
10588 virtual const char * DbgGetName() { return "CordbPublish"; }
10591 //-----------------------------------------------------------
10593 //-----------------------------------------------------------
10595 ULONG STDMETHODCALLTYPE AddRef()
10597 return (BaseAddRef());
10599 ULONG STDMETHODCALLTYPE Release()
10601 return (BaseRelease());
10603 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
10605 //-----------------------------------------------------------
10607 //-----------------------------------------------------------
10609 COM_METHOD EnumProcesses(
10610 COR_PUB_ENUMPROCESS Type,
10611 ICorPublishProcessEnum **ppIEnum);
10613 COM_METHOD GetProcess(
10615 ICorPublishProcess **ppProcess);
10617 //-----------------------------------------------------------
10619 //-----------------------------------------------------------
10620 static COM_METHOD CreateObject(REFIID id, void **object)
10624 if (id != IID_IUnknown && id != IID_ICorPublish)
10625 return (E_NOINTERFACE);
10627 CorpubPublish *pCorPub = new (nothrow) CorpubPublish();
10629 if (pCorPub == NULL)
10630 return (E_OUTOFMEMORY);
10632 *object = (ICorPublish*)pCorPub;
10639 HRESULT GetProcessInternal( unsigned pid, CorpubProcess **ppProcess );
10641 // Cached information to get the process name. Not available on all platforms, so may be null.
10642 HModuleHolder m_hPSAPIdll;
10643 FPGetModuleFileNameEx * m_fpGetModuleFileNameEx;
10646 class CorpubProcess : public CordbCommonBase, public ICorPublishProcess
10649 CorpubProcess(DWORD dwProcessId,
10653 AppDomainEnumerationIPCBlock *pAD,
10654 #if !defined(FEATURE_DBGIPC_TRANSPORT_DI)
10655 IPCReaderInterface *pIPCReader,
10656 #endif // !FEATURE_DBGIPC_TRANSPORT_DI
10657 FPGetModuleFileNameEx * fpGetModuleFileNameEx);
10658 virtual ~CorpubProcess();
10661 virtual const char * DbgGetName() { return "CorpubProcess"; }
10665 //-----------------------------------------------------------
10667 //-----------------------------------------------------------
10669 ULONG STDMETHODCALLTYPE AddRef()
10671 return (BaseAddRef());
10673 ULONG STDMETHODCALLTYPE Release()
10675 return (BaseRelease());
10677 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
10679 //-----------------------------------------------------------
10680 // ICorPublishProcess
10681 //-----------------------------------------------------------
10682 COM_METHOD IsManaged(BOOL *pbManaged);
10685 * Enumerate the list of known application domains in the target process.
10687 COM_METHOD EnumAppDomains(ICorPublishAppDomainEnum **ppEnum);
10690 * Returns the OS ID for the process in question.
10692 COM_METHOD GetProcessID(unsigned *pid);
10695 * Get the display name for a process.
10697 COM_METHOD GetDisplayName(ULONG32 cchName,
10699 __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[]);
10701 CorpubProcess *GetNextProcess () { return m_pNext;}
10702 void SetNext (CorpubProcess *pNext) { m_pNext = pNext;}
10704 // Helper to tell if this process has exited
10708 DWORD m_dwProcessId;
10714 AppDomainEnumerationIPCBlock *m_AppDomainCB;
10715 #if !defined(FEATURE_DBGIPC_TRANSPORT_DI)
10716 IPCReaderInterface *m_pIPCReader; // controls the lifetime of the AppDomainEnumerationIPCBlock
10717 #endif // !FEATURE_DBGIPC_TRANSPORT_DI
10718 CorpubProcess *m_pNext; // pointer to the next process in the process list
10719 WCHAR *m_szProcessName;
10723 class CorpubAppDomain : public CordbCommonBase, public ICorPublishAppDomain
10726 CorpubAppDomain (__in LPWSTR szAppDomainName, ULONG Id);
10727 virtual ~CorpubAppDomain();
10730 virtual const char * DbgGetName() { return "CorpubAppDomain"; }
10733 //-----------------------------------------------------------
10735 //-----------------------------------------------------------
10737 ULONG STDMETHODCALLTYPE AddRef()
10739 return (BaseAddRef());
10741 ULONG STDMETHODCALLTYPE Release()
10743 return (BaseRelease());
10745 COM_METHOD QueryInterface (REFIID riid, void **ppInterface);
10747 //-----------------------------------------------------------
10748 // ICorPublishAppDomain
10749 //-----------------------------------------------------------
10752 * Get the name and ID for an application domain.
10754 COM_METHOD GetID (ULONG32 *pId);
10757 * Get the name for an application domain.
10759 COM_METHOD GetName (ULONG32 cchName,
10761 __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[]);
10763 CorpubAppDomain *GetNextAppDomain () { return m_pNext;}
10764 void SetNext (CorpubAppDomain *pNext) { m_pNext = pNext;}
10767 CorpubAppDomain *m_pNext;
10768 WCHAR *m_szAppDomainName;
10773 class CorpubProcessEnum : public CordbCommonBase, public ICorPublishProcessEnum
10776 CorpubProcessEnum(CorpubProcess *pFirst);
10777 virtual ~CorpubProcessEnum();
10780 virtual const char * DbgGetName() { return "CorpubProcessEnum"; }
10784 //-----------------------------------------------------------
10786 //-----------------------------------------------------------
10788 ULONG STDMETHODCALLTYPE AddRef()
10790 return (BaseAddRef());
10792 ULONG STDMETHODCALLTYPE Release()
10794 return (BaseRelease());
10796 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
10798 //-----------------------------------------------------------
10799 // ICorPublishProcessEnum
10800 //-----------------------------------------------------------
10802 COM_METHOD Skip(ULONG celt);
10803 COM_METHOD Reset();
10804 COM_METHOD Clone(ICorPublishEnum **ppEnum);
10805 COM_METHOD GetCount(ULONG *pcelt);
10806 COM_METHOD Next(ULONG celt,
10807 ICorPublishProcess *objects[],
10808 ULONG *pceltFetched);
10811 CorpubProcess *m_pFirst;
10812 CorpubProcess *m_pCurrent;
10816 class CorpubAppDomainEnum : public CordbCommonBase, public ICorPublishAppDomainEnum
10819 CorpubAppDomainEnum(CorpubAppDomain *pFirst);
10820 virtual ~CorpubAppDomainEnum();
10824 virtual const char * DbgGetName() { return "CordbAppDomainEnum"; }
10828 //-----------------------------------------------------------
10830 //-----------------------------------------------------------
10832 ULONG STDMETHODCALLTYPE AddRef()
10834 return (BaseAddRef());
10836 ULONG STDMETHODCALLTYPE Release()
10838 return (BaseRelease());
10840 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
10842 //-----------------------------------------------------------
10843 // ICorPublishAppDomainEnum
10844 //-----------------------------------------------------------
10845 COM_METHOD Skip(ULONG celt);
10846 COM_METHOD Reset();
10847 COM_METHOD Clone(ICorPublishEnum **ppEnum);
10848 COM_METHOD GetCount(ULONG *pcelt);
10850 COM_METHOD Next(ULONG celt,
10851 ICorPublishAppDomain *objects[],
10852 ULONG *pceltFetched);
10855 CorpubAppDomain *m_pFirst;
10856 CorpubAppDomain *m_pCurrent;
10860 #endif // defined(FEATURE_DBG_PUBLISH)
10862 class CordbHeapEnum : public CordbBase, public ICorDebugHeapEnum
10865 CordbHeapEnum(CordbProcess *proc);
10868 virtual const char * DbgGetName() { return "CordbHeapEnum"; }
10871 //-----------------------------------------------------------
10873 //-----------------------------------------------------------
10874 ULONG STDMETHODCALLTYPE AddRef()
10876 return (BaseAddRef());
10878 ULONG STDMETHODCALLTYPE Release()
10880 return (BaseRelease());
10882 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
10884 COM_METHOD Skip(ULONG celt);
10885 COM_METHOD Reset();
10886 COM_METHOD Clone(ICorDebugEnum **ppEnum);
10887 COM_METHOD GetCount(ULONG *pcelt);
10889 COM_METHOD Next(ULONG celt,
10890 COR_HEAPOBJECT objects[],
10891 ULONG *pceltFetched);
10893 virtual void Neuter()
10896 CordbBase::Neuter();
10902 IDacDbiInterface::HeapWalkHandle mHeapHandle;
10906 class CordbRefEnum : public CordbBase, public ICorDebugGCReferenceEnum
10909 CordbRefEnum(CordbProcess *proc, BOOL walkWeakRefs);
10910 CordbRefEnum(CordbProcess *proc, CorGCReferenceType types);
10913 virtual const char * DbgGetName() { return "CordbHeapEnum"; }
10916 //-----------------------------------------------------------
10918 //-----------------------------------------------------------
10919 ULONG STDMETHODCALLTYPE AddRef()
10921 return (BaseAddRef());
10923 ULONG STDMETHODCALLTYPE Release()
10925 return (BaseRelease());
10927 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
10929 COM_METHOD Skip(ULONG celt);
10930 COM_METHOD Reset();
10931 COM_METHOD Clone(ICorDebugEnum **ppEnum);
10932 COM_METHOD GetCount(ULONG *pcelt);
10934 COM_METHOD Next(ULONG celt,
10935 COR_GC_REFERENCE refs[],
10936 ULONG *pceltFetched);
10938 virtual void Neuter();
10941 RefWalkHandle mRefHandle;
10942 BOOL mEnumStacksFQ;
10943 UINT32 mHandleMask;
10946 // Since the hash table of modules is per app domain (and
10947 // threads is per process) (for fast lookup from the appdomain/process),
10948 // we need this wrapper
10949 // here which allows us to iterate through an assembly's
10950 // modules. Is basically filters out modules/threads that aren't
10951 // in the assembly/appdomain. This slow & awkward for assemblies, but fast
10952 // for the common case - appdomain lookup.
10953 class CordbEnumFilter : public CordbBase,
10954 public ICorDebugThreadEnum,
10955 public ICorDebugModuleEnum
10958 CordbEnumFilter(CordbBase * pOwnerObj, NeuterList * pOwnerList);
10959 CordbEnumFilter(CordbEnumFilter*src);
10960 virtual ~CordbEnumFilter();
10962 virtual void Neuter();
10966 virtual const char * DbgGetName() { return "CordbEnumFilter"; }
10970 //-----------------------------------------------------------
10972 //-----------------------------------------------------------
10974 ULONG STDMETHODCALLTYPE AddRef()
10976 return (BaseAddRef());
10978 ULONG STDMETHODCALLTYPE Release()
10980 return (BaseRelease());
10982 COM_METHOD QueryInterface(REFIID riid, void **ppInterface);
10984 //-----------------------------------------------------------
10986 //-----------------------------------------------------------
10987 COM_METHOD Skip(ULONG celt);
10988 COM_METHOD Reset();
10989 COM_METHOD Clone(ICorDebugEnum **ppEnum);
10990 COM_METHOD GetCount(ULONG *pcelt);
10991 //-----------------------------------------------------------
10992 // ICorDebugModuleEnum
10993 //-----------------------------------------------------------
10994 COM_METHOD Next(ULONG celt,
10995 ICorDebugModule *objects[],
10996 ULONG *pceltFetched);
10998 //-----------------------------------------------------------
10999 // ICorDebugThreadEnum
11000 //-----------------------------------------------------------
11001 COM_METHOD Next(ULONG celt,
11002 ICorDebugThread *objects[],
11003 ULONG *pceltFetched);
11005 HRESULT Init (ICorDebugModuleEnum *pModEnum, CordbAssembly *pAssembly);
11006 HRESULT Init (ICorDebugThreadEnum *pThreadEnum, CordbAppDomain *pAppDomain);
11010 HRESULT NextWorker(ULONG celt, ICorDebugModule *objects[], ULONG *pceltFetched);
11011 HRESULT NextWorker(ULONG celt,ICorDebugThread *objects[], ULONG *pceltFetched);
11013 // Owning object is our link to the CordbProcess* tree. Never null until we're neutered.
11014 // NeuterList is related to the owning object. Need to cache it so that we can pass it on
11016 CordbBase * m_pOwnerObj; // provides us w/ a CordbProcess*
11017 NeuterList * m_pOwnerNeuterList;
11020 EnumElement *m_pFirst;
11021 EnumElement *m_pCurrent;
11025 // Helpers to double-check the RS results against DAC.
11026 #if defined(_DEBUG)
11027 void CheckAgainstDAC(CordbFunction * pFunc, void * pIP, mdMethodDef mdExpected);
11030 HRESULT CopyOutString(const WCHAR * pInputString, ULONG32 cchName, ULONG32 * pcchName, __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[]);
11034 inline UINT AllocCookieCordbEval(CordbProcess *pProc, CordbEval* p)
11036 _ASSERTE(pProc->GetProcessLock()->HasLock());
11037 return pProc->m_EvalTable.Add(p);
11039 inline CordbEval * UnwrapCookieCordbEval(CordbProcess *pProc, UINT cookie)
11041 _ASSERTE(pProc->GetProcessLock()->HasLock());
11042 return pProc->m_EvalTable.LookupAndRemove(cookie);
11046 // We defined this at the top of the file - undef it now so that we don't pollute other files.
11047 #undef CRITICAL_SECTION
11052 //-----------------------------------------------------------------------------
11053 // For debug builds, we maintain some thread-state to track debug bits
11054 // to help us do some more aggressive asserts.
11055 //-----------------------------------------------------------------------------
11057 class PublicAPIHolder;
11058 class PublicReentrantAPIHolder;
11059 class PublicCallbackHolder;
11060 class PublicDebuggerErrorCallbackHolder;
11065 friend class PublicAPIHolder;
11066 friend class PublicReentrantAPIHolder;
11067 friend class PublicCallbackHolder;
11068 friend class PublicDebuggerErrorCallbackHolder;
11069 friend class PrivateShimCallbackHolder;
11073 // The TLS slot that we'll put this thread object in.
11074 static DWORD s_TlsSlot;
11076 static LONG s_Total; // Total count of thread objects
11078 // Get a thread object for the current thread via a TLS lookup.
11079 static DbgRSThread * GetThread();
11081 // Call during DllMain to release this.
11082 static DbgRSThread * Create()
11084 InterlockedIncrement(&s_Total);
11086 DbgRSThread * p = new (nothrow) DbgRSThread();
11087 BOOL f = TlsSetValue(s_TlsSlot, p);
11094 InterlockedDecrement(&s_Total);
11096 BOOL f = TlsSetValue(s_TlsSlot, NULL);
11102 // Return true if this thread is inside the RS.
11103 bool IsInRS() { return m_cInsideRS > 0; }
11106 // These will assert if the operation is unsafe.
11107 void NotifyTakeLock(RSLock * pLock);
11108 void NotifyReleaseLock(RSLock * pLock);
11110 // Used to map other resources (like thread access) into the lock hierachy.
11111 // Note this only effects lock leveling checks and doesn't effect HoldsAnyLock().
11112 void TakeVirtualLock(RSLock::ERSLockLevel level);
11113 void ReleaseVirtualLock(RSLock::ERSLockLevel level);
11115 // return true if this thread is holding any RS locks. Useful to check on Public API transition boundaries.
11116 bool HoldsAnyDbgApiLocks() { return m_cTotalDbgApiLocks > 0; }
11123 void SetThreadType(EThreadType e) { m_eThreadType = e; }
11125 bool IsWin32EventThread() { return m_eThreadType == cW32ET; }
11127 void SetUnrecoverableCallback(bool fIsUnrecoverableErrorCallback)
11130 _ASSERTE(m_fIsUnrecoverableErrorCallback != fIsUnrecoverableErrorCallback);
11132 m_fIsUnrecoverableErrorCallback = fIsUnrecoverableErrorCallback;
11135 inline void AssertThreadIsLockFree()
11137 // If we're in an unrecoverable callback, we may hold locks.
11138 _ASSERTE(m_fIsUnrecoverableErrorCallback
11139 || !HoldsAnyDbgApiLocks() ||
11140 !"Thread should not have locks on public/internal transition");
11144 EThreadType m_eThreadType;
11146 // More debugging tidbits - tid that we're on, and a sanity checking cookie.
11152 COOKIE_VALUE = 0x12345678
11156 // This tells us if the thread is currently in the scope of a PublicAPIHolder.
11159 // This tells us if a thread is currently being dispatched via a callback.
11160 bool m_fIsInCallback;
11162 // We explicitly track if this thread is in an unrecoverable error callback
11163 // b/c that will weaken some other asserts.
11164 // It would be nice to clean up the unrecoverable error callback and have it
11165 // behave like all the other callbacks. Then we can remove this.
11166 bool m_fIsUnrecoverableErrorCallback;
11168 // Locking context. Used to tell what levels of locks we hold so we can determine if a lock is safe to take.
11169 int m_cLocks[RSLock::LL_MAX];
11170 int m_cTotalDbgApiLocks;
11173 //-----------------------------------------------------------------------------
11174 // Mark when we enter / exit public APIs
11175 //-----------------------------------------------------------------------------
11177 // Holder for Non-reentrant Public API (this is the vast majority)
11178 class PublicAPIHolder
11184 DbgRSThread * pThread = DbgRSThread::GetThread();
11185 pThread->m_cInsideRS++;
11186 _ASSERTE(pThread->m_cInsideRS == 1 || !"Non-reentrant API being called re-entrantly");
11188 // Should never be in public w/ these locks
11189 pThread->AssertThreadIsLockFree();
11191 ~PublicAPIHolder() {
11193 DbgRSThread * pThread = DbgRSThread::GetThread();
11194 pThread->m_cInsideRS--;
11195 _ASSERTE(!pThread->IsInRS());
11197 // Should never be in public w/ these locks. If we assert here,
11198 // then we're leaking locks.
11199 pThread->AssertThreadIsLockFree();
11203 // Holder for reentrant public API
11204 class PublicReentrantAPIHolder
11207 PublicReentrantAPIHolder()
11210 DbgRSThread * pThread = DbgRSThread::GetThread();
11211 pThread->m_cInsideRS++;
11213 // Cache count now so that we can calidate it in the dtor.
11214 m_oldCount = pThread->m_cInsideRS;
11215 // Since a we may have been called from within the RS, we may hold locks
11217 ~PublicReentrantAPIHolder()
11221 DbgRSThread * pThread = DbgRSThread::GetThread();
11223 // Ensure that our children were balanced
11224 _ASSERTE(pThread->m_cInsideRS == m_oldCount);
11226 pThread->m_cInsideRS--;
11227 _ASSERTE(pThread->m_cInsideRS >= 0);
11229 // Since a we may have been called from within the RS, we may hold locks
11235 // Special holder for DebuggerError callback. This adjusts InsideRS count w/o
11236 // verifying locks. This is very dangerous. We allow this b/c the Debugger Error callback can come at any time.
11237 class PublicDebuggerErrorCallbackHolder
11240 PublicDebuggerErrorCallbackHolder()
11242 // Exiting from RS; entering Cordbg via a callback
11243 DbgRSThread * pThread = DbgRSThread::GetThread();
11245 // This callback is called from within the RS
11246 _ASSERTE(pThread->IsInRS());
11248 // Debugger error callback may be called from deep within the RS (after many nestings).
11249 // So immediately jump to outside. We'll restore this in dtor.
11250 m_oldCount = pThread->m_cInsideRS;
11251 pThread->m_cInsideRS = 0;
11253 _ASSERTE(!pThread->IsInRS());
11255 // We may be leaking locks for the unrecoverable callback. We mark that so that
11256 // the asserts about locking can be relaxed.
11257 pThread->SetUnrecoverableCallback(true);
11260 ~PublicDebuggerErrorCallbackHolder()
11262 // Re-entering RS from after a callback.
11263 DbgRSThread * pThread = DbgRSThread::GetThread();
11265 pThread->SetUnrecoverableCallback(false);
11266 pThread->m_cInsideRS = m_oldCount;
11268 // Our status of being "Inside the RS" is now restored.
11269 _ASSERTE(pThread->IsInRS());
11275 //---------------------------------------------------------------------------------------
11277 // This is the same as the PublicCallbackHolder, except that this class doesn't assert that we are not holding
11278 // any locks when we call out to the shim.
11281 // @dbgtodo shim, synchronization - We need to settle on one consistent relationshipo between the RS
11282 // and the shim. Then we can clean up the sychronization story. Right now some code considers the shim
11283 // to be outside of the RS, and so we cannot hold any locks when we call out to the shim. However, there
11284 // are cases where we must hold a lock when we call out to the shim. For example, when we call out to the
11285 // shim to do a V2-style stackwalk, we need to be holding the stop-go lock so that another thread can't
11286 // come in and call Continue(). Finally, when we fix this, we should fix
11287 // PUBLIC_REENTRANT_API_ENTRY_FOR_SHIM() as well.
11290 class PrivateShimCallbackHolder
11293 PrivateShimCallbackHolder()
11295 // Exiting from RS; entering Cordbg via a callback
11296 DbgRSThread * pThread = DbgRSThread::GetThread();
11298 // This callback is called from within the RS
11299 _ASSERTE(pThread->IsInRS());
11301 // Debugger error callback may be called from deep within the RS (after many nestings).
11302 // So immediately jump to outside. We'll restore this in dtor.
11303 m_oldCount = pThread->m_cInsideRS;
11304 pThread->m_cInsideRS = 0;
11306 _ASSERTE(!pThread->IsInRS());
11309 ~PrivateShimCallbackHolder()
11311 // Re-entering RS from after a callback.
11312 DbgRSThread * pThread = DbgRSThread::GetThread();
11314 pThread->m_cInsideRS = m_oldCount;
11316 // Our status of being "Inside the RS" is now restored.
11317 _ASSERTE(pThread->IsInRS());
11323 class InternalAPIHolder
11326 InternalAPIHolder()
11328 DbgRSThread * pThread = DbgRSThread::GetThread();
11330 // Internal APIs should already be inside the RS.
11331 _ASSERTE(pThread->IsInRS() ||!"Internal API being called directly from outside (there should be a public API on the stack)");
11336 //---------------------------------------------------------------------------------------
11338 // This is a simple holder to assert that the current thread is holding the process lock. The purpose of
11339 // having this holder is to enforce a lock ordering between the process lock in the RS and the DD lock in DAC.
11340 // If a thread needs to take the process lock, it must do so BEFORE taking the DD lock. Otherwise we could have
11341 // a deadlock between the process lock and the DD lock.
11343 // Normally we take the process lock before calling out to DAC, and every DAC API takes the DD lock on entry.
11344 // Moreover, normally DAC doesn't call back into the RS. The exceptions we currently have are:
11345 // 1) enumeration callbacks (e.g. code:CordbProcess::AppDomainEnumerationCallback)
11346 // 2) code:IDacDbiInterface::IMetaDataLookup
11347 // 3) code:IDacDbiInterface::IAllocator
11348 // 4) code:IStringHolder
11350 // Note that the last two are fine because they don't need to take the process lock. The first two categories
11351 // need to take the process lock before calling into DAC to avoid potential deadlocks.
11354 class InternalDacCallbackHolder
11357 InternalDacCallbackHolder(CordbProcess * pProcess)
11359 _ASSERTE(pProcess->ThreadHoldsProcessLock());
11363 // cotract that occurs at public builds.
11364 #define PUBLIC_CONTRACT \
11365 CONTRACTL { NOTHROW; } CONTRACTL_END;
11368 // Private hook for Shim to call into DBI.
11369 // Since Shim is considered outside DBI, we need to mark that we've re-entered.
11370 // Big difference is that we can throw across this boundary.
11371 // @dbgtodo private shim hook - Eventually, these will all go away since the shim will be fully public.
11372 #define PUBLIC_API_ENTRY_FOR_SHIM(_pThis) \
11373 PublicAPIHolder __pah;
11376 #define PUBLIC_API_UNSAFE_ENTRY_FOR_SHIM(_pThis) \
11377 PublicDebuggerErrorCallbackHolder __pahCallback;
11379 // @dbgtodo shim, synchronization - Because of the problem mentioned in the comments for
11380 // PrivateShimCallbackHolder, we need this macro so that we don't hit an assertion when we come back into
11381 // the RS from the shim.
11382 #define PUBLIC_REENTRANT_API_ENTRY_FOR_SHIM(_pThis) \
11383 PublicReentrantAPIHolder __pah;
11385 //-----------------------------------------------------------------------------
11386 // Declare whether an API is public or internal
11387 // Public APIs have the following:
11388 // - We may be called concurrently from multiple threads (ie, not thread safe)
11389 // - This thread does not hold any RS Locks while entering or leaving this function.
11390 // - May or May-not be reentrant.
11392 // - let us specifically mark that we're not a public API, and
11393 // - we're only being called through a public API.
11394 //-----------------------------------------------------------------------------
11395 #define PUBLIC_API_ENTRY(_pThis) \
11396 STRESS_LOG2(LF_CORDB, LL_INFO1000, "[Public API '%s', this=0x%p]\n", __FUNCTION__, _pThis); \
11398 PublicAPIHolder __pah;
11400 // Mark public APIs that are re-entrant.
11401 // Very few of our APIs should be re-entrant. Even for field access APIs (like GetXXX), the
11402 // public version is heavier (eg, checking the HRESULT) so we benefit from having a fast
11403 // internal version and calling that directly.
11404 #define PUBLIC_REENTRANT_API_ENTRY(_pThis) \
11405 STRESS_LOG2(LF_CORDB, LL_INFO1000, "[Public API (re) '%s', this=0x%p]\n", __FUNCTION__, _pThis); \
11407 PublicReentrantAPIHolder __pah;
11411 // Mark internal APIs.
11412 // All internal APIs are reentrant (duh)
11413 #define INTERNAL_API_ENTRY(_pThis) InternalAPIHolder __pah; __pah.dummy();
11415 // Mark an internal API from ATT_REQUIRE_STOP / ATT_ALLOW_LIVE_DO_STOP_GO.
11416 // This can assert that we're safe to send IPC events (that we're stopped and hold the SG lock)
11417 // @dbgtodo synchronization - in V2, this would assert that we were synced.
11418 // In V3, our definition of Sync is in flux. Need to resolve this with the synchronization feature crew.
11419 #define INTERNAL_SYNC_API_ENTRY(pProc) \
11420 CordbProcess * __pProc = (pProc); \
11421 _ASSERTE(__pProc->GetStopGoLock()->HasLock() || !"Must have stop go lock for internal-sync-api"); \
11422 InternalAPIHolder __pah; __pah.dummy();
11426 // Mark that a thread is owned by us. Thus the thread's "Inside RS" count > 0.
11427 #define INTERNAL_THREAD_ENTRY(_pThis) \
11428 STRESS_LOG1(LF_CORDB, LL_INFO1000, "[Internal thread started, this=0x%p]\n", _pThis); \
11430 PublicAPIHolder __pah;
11432 // @dbgtodo unrecoverable error - This sould be deprecated once we deprecate UnrecoverableError.
11433 #define PUBLIC_CALLBACK_IN_THIS_SCOPE_DEBUGGERERROR(_pThis) \
11434 PublicDebuggerErrorCallbackHolder __pahCallback;
11436 #define PRIVATE_SHIM_CALLBACK_IN_THIS_SCOPE0(_pThis) \
11437 PrivateShimCallbackHolder __pahCallback;
11439 // Mark places where DAC may call back into DBI. We need to assert that we are holding the process lock in
11440 // these places, since otherwise we could deadlock between the DD lock and the process lock.
11441 #define INTERNAL_DAC_CALLBACK(__pProcess) \
11442 InternalDacCallbackHolder __idch(__pProcess);
11445 // Helper to log debug events.
11446 inline void StressLogNativeDebugEvent(const DEBUG_EVENT * pDebugEvent, bool fOOB)
11448 if ((pDebugEvent)->dwDebugEventCode == EXCEPTION_DEBUG_EVENT)
11450 STRESS_LOG4(LF_CORDB, LL_EVERYTHING, "[Dispatching Win32 code=1 (EXCEPTION_DEBUG_EVENT, tid=%x, oob=%d, code=0x%x, 1st=%d]\n",
11451 pDebugEvent->dwThreadId,
11453 pDebugEvent->u.Exception.ExceptionRecord.ExceptionCode,
11454 pDebugEvent->u.Exception.dwFirstChance);
11458 STRESS_LOG3(LF_CORDB, LL_EVERYTHING, "[Dispatching Win32 code=%d, tid=%x, oob=%d.]\n",
11459 pDebugEvent->dwDebugEventCode, pDebugEvent->dwThreadId, fOOB);
11464 #define PUBLIC_WIN32_CALLBACK_IN_THIS_SCOPE(_pThis, _pDebugEvent, _fOOB) \
11465 StressLogNativeDebugEvent(_pDebugEvent, _fOOB); \
11466 PublicCallbackHolder __pahCallback(DB_IPCE_INVALID_EVENT);
11468 // Visisbility spec for dtors.
11469 // Currently, dtors are like public methods b/c they can be called from Release.
11470 // But they're also reentrant since they may be called from an internal-release.
11471 // @todo - we'd like to get all "useful" work out of the dtor; in which case we may
11472 // be able to change this to something more aggressive.
11473 #define DTOR_ENTRY(_pThis) PUBLIC_REENTRANT_API_ENTRY(_pThis)
11476 //-----------------------------------------------------------------------------
11477 // Typesafe bool for thread safety. This typesafety forces us to use
11478 // an specific reason for thread-safety, taken from a well-known list.
11479 // This is mostly concerned w/ being serialized.
11480 // Note that this assertion must be done on a per function basis and we
11481 // can't have any sort of 'ThreadSafetyReason CallerIsSafe()' b/c we can't
11482 // enforce that all of our callers are thread safe (only that our current caller is safe).
11483 //-----------------------------------------------------------------------------
11484 struct ThreadSafetyReason
11487 ThreadSafetyReason(bool f) { fIsSafe = f; }
11492 // Different valid reasons that we may be threads safe.
11493 inline ThreadSafetyReason HoldsLock(RSLock * pLock)
11495 _ASSERTE(pLock != NULL);
11496 return ThreadSafetyReason(pLock->HasLock());
11498 inline ThreadSafetyReason OnW32ET(CordbProcess * pProc)
11500 return ThreadSafetyReason(IsWin32EventThread(pProc));
11503 inline ThreadSafetyReason OnRCET(Cordb *pCordb)
11505 return ThreadSafetyReason (IsRCEventThread(pCordb));
11508 // We use this when we assume that a function is thread-safe (b/c it's serialized).
11509 // The reason also lets us assert that our assumption is true.
11510 // By using a function, we enforce typesafety and thus require a valid reason
11511 // (as opposed to an arbitrary bool)
11512 inline void AssertThreadSafeHelper(ThreadSafetyReason r) {
11513 _ASSERTE(r.fIsSafe);
11516 //-----------------------------------------------------------------------------
11517 // Assert that the given scope is always called on a single thread b/c of
11518 // xReason. Common reasons may be b/c we hold a lock or we're always
11519 // called on a specific thread (Eg w32et).
11520 // The only valid reasons are of type ThreadSafetyReason (thus forcing us to
11521 // choose from a well-known list of valid reasons).
11522 //-----------------------------------------------------------------------------
11523 #define ASSERT_SINGLE_THREAD_ONLY(xReason) \
11524 AssertThreadSafeHelper(xReason);
11528 //-----------------------------------------------------------------------------
11529 // Retail versions just nop. See the debug implementation for these
11530 // for their semantics.
11531 //-----------------------------------------------------------------------------
11533 #define PUBLIC_CONTRACT
11534 #define PUBLIC_API_ENTRY_FOR_SHIM(_pThis)
11535 #define PUBLIC_API_UNSAFE_ENTRY_FOR_SHIM(_pThis)
11536 #define PUBLIC_REENTRANT_API_ENTRY_FOR_SHIM(_pThis)
11537 #define PUBLIC_API_ENTRY(_pThis)
11538 #define PUBLIC_REENTRANT_API_ENTRY(_pThis)
11539 #define INTERNAL_API_ENTRY(_pThis)
11540 #define INTERNAL_SYNC_API_ENTRY(pProc)
11541 #define INTERNAL_THREAD_ENTRY(_pThis)
11542 #define PUBLIC_CALLBACK_IN_THIS_SCOPE_DEBUGGERERROR(_pThis)
11543 #define PRIVATE_SHIM_CALLBACK_IN_THIS_SCOPE0(_pThis)
11544 #define INTERNAL_DAC_CALLBACK(__pProcess)
11545 #define PUBLIC_WIN32_CALLBACK_IN_THIS_SCOPE(_pThis, _pDebugEvent, _fOOB)
11546 #define DTOR_ENTRY(_pThis)
11549 #define ASSERT_SINGLE_THREAD_ONLY(x)
11551 #endif // #if RSCONTRACTS
11554 class PublicCallbackHolder
11557 PublicCallbackHolder(RSLockHolder * pHolder, DebuggerIPCEventType type)
11559 m_pHolder = pHolder;
11560 _ASSERTE(!pHolder->IsNull()); // acquired
11562 // Release the lock. We'll reacquire it at the dtor.
11563 m_pHolder->Release();
11568 PublicCallbackHolder(DebuggerIPCEventType type)
11574 void Init(DebuggerIPCEventType type)
11578 #if defined(RSCONTRACTS)
11579 // Exiting from RS; entering Cordbg via a callback
11580 DbgRSThread * pThread = DbgRSThread::GetThread();
11582 // m_cInsideRS may be arbitrarily large if we're called from a PUBLIC_REENTRANT_API,
11583 // so just remember the current count and blast it back to 0.
11584 m_oldCount = pThread->m_cInsideRS;
11585 pThread->m_cInsideRS = 0;
11587 _ASSERTE(!pThread->IsInRS());
11589 // Should never be in public w/ these locks. (Even if we're re-entrant.)
11590 pThread->AssertThreadIsLockFree();
11591 #endif // RSCONTRACTS
11594 ~PublicCallbackHolder()
11596 #if defined(RSCONTRACTS)
11597 // Re-entering RS from after a callback.
11598 DbgRSThread * pThread = DbgRSThread::GetThread();
11599 _ASSERTE(!pThread->IsInRS());
11601 pThread->m_cInsideRS = m_oldCount;
11603 // Should never be in public w/ these locks. (Even if we're re-entrant.)
11604 pThread->AssertThreadIsLockFree();
11605 #endif // RSCONTRACTS
11607 // Reacquire the lock
11608 if (m_pHolder != NULL)
11610 m_pHolder->Acquire();
11615 DebuggerIPCEventType m_type;
11616 RSLockHolder * m_pHolder;
11620 // Mark that a thread is calling out via a callback. This will adjust the "Inside RS" counter.
11621 #define PUBLIC_CALLBACK_IN_THIS_SCOPE(_pThis, pLockHolder, event) \
11622 STRESS_LOG1(LF_CORDB, LL_EVERYTHING, "[Dispatching '%s']\n", IPCENames::GetName((event)->type)); \
11623 PublicCallbackHolder __pahCallback(pLockHolder, (event)->type);
11625 #define PUBLIC_CALLBACK_IN_THIS_SCOPE1(_pThis, pLockHolder, event, formatLiteralString, arg0) \
11626 STRESS_LOG2(LF_CORDB, LL_EVERYTHING, "[Dispatching '%s' " formatLiteralString "]\n", IPCENames::GetName((event)->type), arg0); \
11627 PublicCallbackHolder __pahCallback(pLockHolder, (event)->type);
11629 #define PUBLIC_CALLBACK_IN_THIS_SCOPE2(_pThis, pLockHolder, event, formatLiteralString, arg0, arg1) \
11630 STRESS_LOG3(LF_CORDB, LL_EVERYTHING, "[Dispatching '%s' " formatLiteralString "]\n", IPCENames::GetName((event)->type), arg0, arg1); \
11631 PublicCallbackHolder __pahCallback(pLockHolder, (event)->type);
11633 #define PUBLIC_CALLBACK_IN_THIS_SCOPE3(_pThis, pLockHolder, event, formatLiteralString, arg0, arg1, arg2) \
11634 STRESS_LOG4(LF_CORDB, LL_EVERYTHING, "[Dispatching '%s' " formatLiteralString "]\n", IPCENames::GetName((event)->type), arg0, arg1, arg2); \
11635 PublicCallbackHolder __pahCallback(pLockHolder, (event)->type);
11638 #define PUBLIC_CALLBACK_IN_THIS_SCOPE0_NO_LOCK(_pThis) \
11639 PublicCallbackHolder __pahCallback(DB_IPCE_INVALID_EVENT);
11641 #define PUBLIC_CALLBACK_IN_THIS_SCOPE0(_pThis, pLockHolder) \
11642 PublicCallbackHolder __pahCallback(pLockHolder, DB_IPCE_INVALID_EVENT);
11645 //-----------------------------------------------------------------------------
11647 inline void ValidateOrThrow(const void * p)
11651 ThrowHR(E_INVALIDARG);
11655 // aligns argBase on platforms that require it else it's a no-op
11656 inline void AlignAddressForType(CordbType* pArgType, CORDB_ADDRESS& argBase)
11658 #ifdef DBG_TARGET_ARM
11659 // TODO: review the following
11660 #ifdef FEATURE_64BIT_ALIGNMENT
11661 BOOL align = FALSE;
11662 HRESULT hr = pArgType->RequiresAlign8(&align);
11663 _ASSERTE(SUCCEEDED(hr));
11666 argBase = ALIGN_ADDRESS(argBase, 8);
11667 #endif // FEATURE_64BIT_ALIGNMENT
11668 #endif // DBG_TARGET_ARM
11671 //-----------------------------------------------------------------------------
11672 // Macros to mark public ICorDebug functions
11675 // HRESULT CordbXYZ:Function(...)
11677 // HRESULT hr = S_OK;
11678 // PUBLIC_API_BEGIN(this);
11679 // // body, may throw
11680 // PUBLIC_API_END(hr);
11683 #define PUBLIC_API_BEGIN(__this) \
11684 CordbBase * __pThis = (__this); \
11685 PUBLIC_API_ENTRY(__pThis); \
11687 RSLockHolder __lockHolder(__pThis->GetProcess()->GetProcessLock()); \
11688 THROW_IF_NEUTERED(__pThis); \
11690 // You should not use this in general. We're adding it as a temporary workaround for a
11691 // particular scenario until we do the synchronization feature crew
11692 #define PUBLIC_API_NO_LOCK_BEGIN(__this) \
11693 CordbBase * __pThis = (__this); \
11694 PUBLIC_API_ENTRY(__pThis); \
11696 THROW_IF_NEUTERED(__pThis); \
11698 // Some APIs (that invoke callbacks), need to toggle the lock.
11699 #define GET_PUBLIC_LOCK_HOLDER() (&__lockHolder)
11701 #define PUBLIC_API_END(__hr) \
11702 } EX_CATCH_HRESULT(__hr); \
11704 // @todo: clean up API constracts. Should we really be taking the Process lock for
11705 // reentrant APIS??
11706 #define PUBLIC_REENTRANT_API_BEGIN(__this) \
11707 CordbBase * __pThis = (__this); \
11708 PUBLIC_REENTRANT_API_ENTRY(__pThis); \
11710 RSLockHolder __lockHolder(__pThis->GetProcess()->GetProcessLock()); \
11711 THROW_IF_NEUTERED(__pThis); \
11713 #define PUBLIC_REENTRANT_API_END(__hr) \
11714 } EX_CATCH_HRESULT(__hr); \
11716 // If an API needs to take the stop/go lock as well as the process lock, the
11717 // stop/go lock has to be taken first. This is an alternative to PUBLIC_REENTRANT_API_BEGIN
11718 // that allows this, since it doesn't take the process lock. It should be closed with
11719 // PUBLIC_REENTRANT_API_END
11720 #define PUBLIC_REENTRANT_API_NO_LOCK_BEGIN(__this) \
11721 CordbBase * __pThis = (__this); \
11722 PUBLIC_REENTRANT_API_ENTRY(__pThis); \
11724 THROW_IF_NEUTERED(__pThis); \
11727 //-----------------------------------------------------------------------------
11728 // For debugging ease, cache some global values.
11729 // Include these in retail & free because that's where we need them the most!!
11730 // Optimized builds may not let us view locals & parameters. So Having these
11731 // cached as global values should let us inspect almost all of
11732 // the interesting parts of the RS even in a Retail build!
11733 //-----------------------------------------------------------------------------
11734 struct RSDebuggingInfo
11736 // There should only be 1 global Cordb object. Store it here.
11739 // We have lots of processes. Keep a pointer to the most recently touched
11740 // (subjective) process, as a hint about what our "current" process is.
11741 // If we're only debugging 1 process, this will be sufficient.
11742 CordbProcess * m_MRUprocess;
11744 CordbRCEventThread * m_RCET;
11747 #include "rspriv.inl"
11749 #endif // #if RSPRIV_H