summaryrefslogtreecommitdiff
path: root/src/debug/daccess/dacimpl.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/debug/daccess/dacimpl.h')
-rw-r--r--src/debug/daccess/dacimpl.h4015
1 files changed, 4015 insertions, 0 deletions
diff --git a/src/debug/daccess/dacimpl.h b/src/debug/daccess/dacimpl.h
new file mode 100644
index 0000000000..635be80232
--- /dev/null
+++ b/src/debug/daccess/dacimpl.h
@@ -0,0 +1,4015 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//*****************************************************************************
+// File: dacimpl.h
+//
+
+//
+// Central header file for external data access implementation.
+//
+//*****************************************************************************
+
+
+#ifndef __DACIMPL_H__
+#define __DACIMPL_H__
+
+#if defined(_TARGET_ARM_) || defined(FEATURE_CORESYSTEM) // @ARMTODO: STL breaks the build with current VC headers
+//---------------------------------------------------------------------------------------
+// Setting DAC_HASHTABLE tells the DAC to use the hand rolled hashtable for
+// storing code:DAC_INSTANCE . Otherwise, the DAC uses the STL unordered_map to.
+
+#define DAC_HASHTABLE
+#endif // _TARGET_ARM_|| FEATURE_CORESYSTEM
+
+#ifndef DAC_HASHTABLE
+#pragma push_macro("return")
+#undef return
+#include <unordered_map>
+#pragma pop_macro("return")
+#endif //DAC_HASHTABLE
+extern CRITICAL_SECTION g_dacCritSec;
+
+// Convert between CLRDATA_ADDRESS and TADDR.
+// Note that CLRDATA_ADDRESS is sign-extended (for compat with Windbg and OS conventions). Converting
+// from pointer-size values to CLRDATA_ADDRESS should ALWAYS use this TO_CDADDR macro to avoid bugs when
+// dealing with 3/4GB 32-bit address spaces. You must not rely on the compiler's implicit conversion
+// from ULONG32 to ULONG64 - it is incorrect. Ideally we'd use some compiler tricks or static analysis
+// to help detect such errors (they are nefarious since 3/4GB addresses aren't well tested) .
+//
+// Note: We're in the process of switching the implementation over to CORDB_ADDRESS instead, which is also
+// 64 bits, but 0-extended. This means that conversions between TADDR and CORDB_ADDRESS are simple and natural,
+// but as long as we have some legacy code, conversions involving CLRDATA_ADDRESS are a pain. Eventually we
+// should eliminate CLRDATA_ADDRESS entirely from the implementation, but that will require moving SOS off of
+// the old DAC stuff etc.
+//
+// Here are the possible conversions:
+// TADDR -> CLRDATA_ADDRESS: TO_CDADDR
+// CORDB_ADDRESS -> CLRDATA_ADDRESS: TO_CDADDR
+// CLRDATA_ADDRESS -> TADDR: CLRDATA_ADDRESS_TO_TADDR
+// CORDB_ADDRESS -> TADDR: CORDB_ADDRESS_TO_TADDR
+// TADDR -> CORDB_ADDRESS: implicit
+// CLRDATA_ADDRESS -> CORDB_ADDRESS: CLRDATA_ADDRESS_TO_TADDR
+//
+#define TO_CDADDR(taddr) ((CLRDATA_ADDRESS)(LONG_PTR)(taddr))
+
+// Convert a CLRDATA_ADDRESS (64-bit unsigned sign-extended target address) to a TADDR
+inline TADDR CLRDATA_ADDRESS_TO_TADDR(CLRDATA_ADDRESS cdAddr)
+{
+ SUPPORTS_DAC;
+#ifndef _WIN64
+ static_assert_no_msg(sizeof(TADDR)==sizeof(UINT));
+ INT64 iSignedAddr = (INT64)cdAddr;
+ if (iSignedAddr > INT_MAX || iSignedAddr < INT_MIN)
+ {
+ _ASSERTE_MSG(false, "CLRDATA_ADDRESS out of range for this platform");
+ DacError(E_INVALIDARG);
+ }
+#endif
+ return (TADDR)cdAddr;
+}
+
+// No throw, Convert a CLRDATA_ADDRESS (64-bit unsigned sign-extended target address) to a TADDR
+// Use this in places where we know windbg may pass in bad addresses
+inline HRESULT TRY_CLRDATA_ADDRESS_TO_TADDR(CLRDATA_ADDRESS cdAddr, TADDR* pOutTaddr)
+{
+ SUPPORTS_DAC;
+#ifndef _WIN64
+ static_assert_no_msg(sizeof(TADDR)==sizeof(UINT));
+ INT64 iSignedAddr = (INT64)cdAddr;
+ if (iSignedAddr > INT_MAX || iSignedAddr < INT_MIN)
+ {
+ *pOutTaddr = 0;
+ return E_INVALIDARG;
+ }
+#endif
+ *pOutTaddr = (TADDR)cdAddr;
+ return S_OK;
+}
+
+// Convert a CORDB_ADDRESS (64-bit unsigned 0-extended target address) to a TADDR
+inline TADDR CORDB_ADDRESS_TO_TADDR(CORDB_ADDRESS cdbAddr)
+{
+ SUPPORTS_DAC;
+#ifndef _WIN64
+ static_assert_no_msg(sizeof(TADDR)==sizeof(UINT));
+ if (cdbAddr > UINT_MAX)
+ {
+ _ASSERTE_MSG(false, "CORDB_ADDRESS out of range for this platform");
+ DacError(E_INVALIDARG);
+ }
+#endif
+ return (TADDR)cdbAddr;
+}
+
+// TO_TADDR is the old way of converting CLRDATA_ADDRESSes to TADDRs. Unfortunately,
+// this has been used in many places to also cast pointers (void* etc.) to TADDR, and
+// so we can't actually require the argument to be a valid CLRDATA_ADDRESS. New code
+// should use CLRDATA_ADDRESS_TO_TADDR instead.
+#define TO_TADDR(cdaddr) ((TADDR)(cdaddr))
+
+#define TO_CDENUM(ptr) ((CLRDATA_ENUM)(ULONG_PTR)(ptr))
+#define FROM_CDENUM(type, cdenum) ((type*)(ULONG_PTR)(cdenum))
+
+#define SIMPFRAME_ALL \
+ (CLRDATA_SIMPFRAME_UNRECOGNIZED | \
+ CLRDATA_SIMPFRAME_MANAGED_METHOD | \
+ CLRDATA_SIMPFRAME_RUNTIME_MANAGED_CODE | \
+ CLRDATA_SIMPFRAME_RUNTIME_UNMANAGED_CODE)
+
+enum DAC_USAGE_TYPE
+{
+ DAC_DPTR,
+ DAC_VPTR,
+ DAC_STRA,
+ DAC_STRW,
+};
+
+// mscordacwks's module handle
+extern HINSTANCE g_thisModule;
+
+class ReflectionModule;
+
+struct DAC_MD_IMPORT
+{
+ DAC_MD_IMPORT* next; // list link field
+ TADDR peFile; // a TADDR for a PEFile* or a ReflectionModule*
+ IMDInternalImport* impl; // Associated metadata interface
+ bool isAlternate; // for NGEN images set to true if the metadata corresponds to the IL image
+
+ DAC_MD_IMPORT(TADDR peFile_,
+ IMDInternalImport* impl_,
+ bool isAlt_ = false,
+ DAC_MD_IMPORT* next_ = NULL)
+ : next(next_)
+ , peFile(peFile_)
+ , impl(impl_)
+ , isAlternate(isAlt_)
+ {
+ SUPPORTS_DAC_HOST_ONLY;
+ }
+};
+
+
+// This class maintains a cache of IMDInternalImport* and their corresponding
+// source (a PEFile* or a ReflectionModule*), as a singly-linked list of
+// DAC_MD_IMPORT nodes. The cache is flushed whenever the process state changes
+// by calling its Flush() member function.
+class MDImportsCache
+{
+public:
+
+ MDImportsCache()
+ : m_head(NULL)
+ {}
+
+ ~MDImportsCache()
+ {
+ Flush();
+ }
+
+ FORCEINLINE
+ IMDInternalImport* Get(TADDR key) const
+ {
+ SUPPORTS_DAC;
+ for (DAC_MD_IMPORT* importList = m_head; importList; importList = importList->next)
+ {
+ if (importList->peFile == key)
+ {
+ return importList->impl;
+ }
+ }
+ return NULL;
+ }
+
+ FORCEINLINE
+ DAC_MD_IMPORT* Add(TADDR peFile, IMDInternalImport* impl, bool isAlt)
+ {
+ SUPPORTS_DAC;
+ DAC_MD_IMPORT* importList = new (nothrow) DAC_MD_IMPORT(peFile, impl, isAlt, m_head);
+ if (!importList)
+ {
+ return NULL;
+ }
+
+ m_head = importList;
+ return importList;
+ }
+
+ void Flush()
+ {
+ DAC_MD_IMPORT* importList;
+
+ while (m_head)
+ {
+ importList = m_head;
+ m_head = importList->next;
+ importList->impl->Release();
+ delete importList;
+ }
+ }
+
+private:
+
+ DAC_MD_IMPORT* m_head; // the beginning of the list of cached MD imports
+
+};
+
+struct METH_EXTENTS
+{
+ ULONG32 numExtents;
+ ULONG32 curExtent;
+ // Currently only one is needed.
+ CLRDATA_ADDRESS_RANGE extents[1];
+};
+
+HRESULT ConvertUtf8(__in LPCUTF8 utf8,
+ ULONG32 bufLen,
+ ULONG32* nameLen,
+ __out_ecount_part_opt(bufLen, *nameLen) PWSTR buffer);
+HRESULT AllocUtf8(__in_opt LPCWSTR wstr,
+ ULONG32 srcChars,
+ __deref_out LPUTF8* utf8);
+
+HRESULT GetFullClassNameFromMetadata(IMDInternalImport* mdImport,
+ mdTypeDef classToken,
+ ULONG32 bufferChars,
+ __inout_ecount(bufferChars) LPUTF8 buffer);
+HRESULT GetFullMethodNameFromMetadata(IMDInternalImport* mdImport,
+ mdMethodDef methodToken,
+ ULONG32 bufferChars,
+ __inout_ecount(bufferChars) LPUTF8 buffer);
+
+enum SplitSyntax
+{
+ SPLIT_METHOD,
+ SPLIT_TYPE,
+ SPLIT_FIELD,
+ SPLIT_NO_NAME,
+};
+
+HRESULT SplitFullName(__in_z __in PCWSTR fullName,
+ SplitSyntax syntax,
+ ULONG32 memberDots,
+ __deref_out_opt LPUTF8* namespaceName,
+ __deref_out_opt LPUTF8* typeName,
+ __deref_out_opt LPUTF8* memberName,
+ __deref_out_opt LPUTF8* params);
+
+int CompareUtf8(__in LPCUTF8 str1, __in LPCUTF8 str2, __in ULONG32 nameFlags);
+
+#define INH_STATIC \
+ (CLRDATA_VALUE_ALL_KINDS | \
+ CLRDATA_VALUE_IS_INHERITED | CLRDATA_VALUE_FROM_STATIC)
+
+HRESULT InitFieldIter(DeepFieldDescIterator* fieldIter,
+ TypeHandle typeHandle,
+ bool canHaveFields,
+ ULONG32 flags,
+ IXCLRDataTypeInstance* fromType);
+
+ULONG32 GetTypeFieldValueFlags(TypeHandle typeHandle,
+ FieldDesc* fieldDesc,
+ ULONG32 otherFlags,
+ bool isDeref);
+
+//----------------------------------------------------------------------------
+//
+// MetaEnum.
+//
+//----------------------------------------------------------------------------
+
+class MetaEnum
+{
+public:
+ MetaEnum(void)
+ : m_domainIter(FALSE)
+ {
+ Clear();
+ m_appDomain = NULL;
+ }
+ ~MetaEnum(void)
+ {
+ End();
+ }
+
+ void Clear(void)
+ {
+ m_mdImport = NULL;
+ m_kind = 0;
+ m_lastToken = mdTokenNil;
+ }
+
+ HRESULT Start(IMDInternalImport* mdImport, ULONG32 kind,
+ mdToken container);
+ void End(void);
+
+ HRESULT NextToken(mdToken* token,
+ __deref_opt_out_opt LPCUTF8* namespaceName,
+ __deref_opt_out_opt LPCUTF8* name);
+ HRESULT NextDomainToken(AppDomain** appDomain,
+ mdToken* token);
+ HRESULT NextTokenByName(__in_opt LPCUTF8 namespaceName,
+ __in_opt LPCUTF8 name,
+ ULONG32 nameFlags,
+ mdToken* token);
+ HRESULT NextDomainTokenByName(__in_opt LPCUTF8 namespaceName,
+ __in_opt LPCUTF8 name,
+ ULONG32 nameFlags,
+ AppDomain** appDomain, mdToken* token);
+
+ static HRESULT CdNextToken(CLRDATA_ENUM* handle,
+ mdToken* token)
+ {
+ MetaEnum* iter = FROM_CDENUM(MetaEnum, *handle);
+ if (!iter)
+ {
+ return S_FALSE;
+ }
+
+ return iter->NextToken(token, NULL, NULL);
+ }
+ static HRESULT CdNextDomainToken(CLRDATA_ENUM* handle,
+ AppDomain** appDomain,
+ mdToken* token)
+ {
+ MetaEnum* iter = FROM_CDENUM(MetaEnum, *handle);
+ if (!iter)
+ {
+ return S_FALSE;
+ }
+
+ return iter->NextDomainToken(appDomain, token);
+ }
+ static HRESULT CdEnd(CLRDATA_ENUM handle)
+ {
+ MetaEnum* iter = FROM_CDENUM(MetaEnum, handle);
+ if (iter)
+ {
+ delete iter;
+ return S_OK;
+ }
+ else
+ {
+ return E_INVALIDARG;
+ }
+ }
+
+ IMDInternalImport* m_mdImport;
+ ULONG32 m_kind;
+ HENUMInternal m_enum;
+ AppDomain* m_appDomain;
+ AppDomainIterator m_domainIter;
+ mdToken m_lastToken;
+
+ static HRESULT New(Module* mod,
+ ULONG32 kind,
+ mdToken container,
+ IXCLRDataAppDomain* pubAppDomain,
+ MetaEnum** metaEnum,
+ CLRDATA_ENUM* handle);
+};
+
+//----------------------------------------------------------------------------
+//
+// SplitName.
+//
+//----------------------------------------------------------------------------
+
+class SplitName
+{
+public:
+ // Type of name and splitting being done in this instance.
+ SplitSyntax m_syntax;
+ ULONG32 m_nameFlags;
+ ULONG32 m_memberDots;
+
+ // Split fields.
+ LPUTF8 m_namespaceName;
+ LPUTF8 m_typeName;
+ mdTypeDef m_typeToken;
+ LPUTF8 m_memberName;
+ mdMethodDef m_memberToken;
+ LPUTF8 m_params;
+ // XXX Microsoft - Translated signature.
+
+ // Arbitrary extra data.
+ Thread* m_tlsThread;
+ Module* m_module;
+ MetaEnum m_metaEnum;
+ DeepFieldDescIterator m_fieldEnum;
+ ULONG64 m_objBase;
+ FieldDesc* m_lastField;
+
+ SplitName(SplitSyntax syntax, ULONG32 nameFlags,
+ ULONG32 memberDots);
+ ~SplitName(void)
+ {
+ Delete();
+ }
+
+ void Delete(void);
+ void Clear(void);
+
+ HRESULT SplitString(__in_opt PCWSTR fullName);
+
+ bool FindType(IMDInternalImport* mdInternal);
+ bool FindMethod(IMDInternalImport* mdInternal);
+ bool FindField(IMDInternalImport* mdInternal);
+
+ int Compare(LPCUTF8 str1, LPCUTF8 str2)
+ {
+ return CompareUtf8(str1, str2, m_nameFlags);
+ }
+
+ static HRESULT AllocAndSplitString(__in_opt PCWSTR fullName,
+ SplitSyntax syntax,
+ ULONG32 nameFlags,
+ ULONG32 memberDots,
+ SplitName** split);
+
+ static HRESULT CdStartMethod(__in_opt PCWSTR fullName,
+ ULONG32 nameFlags,
+ Module* mod,
+ mdTypeDef typeToken,
+ AppDomain* appDomain,
+ IXCLRDataAppDomain* pubAppDomain,
+ SplitName** split,
+ CLRDATA_ENUM* handle);
+ static HRESULT CdNextMethod(CLRDATA_ENUM* handle,
+ mdMethodDef* token);
+ static HRESULT CdNextDomainMethod(CLRDATA_ENUM* handle,
+ AppDomain** appDomain,
+ mdMethodDef* token);
+
+ static HRESULT CdStartField(__in_opt PCWSTR fullName,
+ ULONG32 nameFlags,
+ ULONG32 fieldFlags,
+ IXCLRDataTypeInstance* fromTypeInst,
+ TypeHandle typeHandle,
+ Module* mod,
+ mdTypeDef typeToken,
+ ULONG64 objBase,
+ Thread* tlsThread,
+ IXCLRDataTask* pubTlsThread,
+ AppDomain* appDomain,
+ IXCLRDataAppDomain* pubAppDomain,
+ SplitName** split,
+ CLRDATA_ENUM* handle);
+ static HRESULT CdNextField(ClrDataAccess* dac,
+ CLRDATA_ENUM* handle,
+ IXCLRDataTypeDefinition** fieldType,
+ ULONG32* fieldFlags,
+ IXCLRDataValue** value,
+ ULONG32 nameBufRetLen,
+ ULONG32* nameLenRet,
+ __out_ecount_part_opt(nameBufRetLen, *nameLenRet) WCHAR nameBufRet[ ],
+ IXCLRDataModule** tokenScopeRet,
+ mdFieldDef* tokenRet);
+ static HRESULT CdNextDomainField(ClrDataAccess* dac,
+ CLRDATA_ENUM* handle,
+ IXCLRDataValue** value);
+
+ static HRESULT CdStartType(__in_opt PCWSTR fullName,
+ ULONG32 nameFlags,
+ Module* mod,
+ AppDomain* appDomain,
+ IXCLRDataAppDomain* pubAppDomain,
+ SplitName** split,
+ CLRDATA_ENUM* handle);
+ static HRESULT CdNextType(CLRDATA_ENUM* handle,
+ mdTypeDef* token);
+ static HRESULT CdNextDomainType(CLRDATA_ENUM* handle,
+ AppDomain** appDomain,
+ mdTypeDef* token);
+
+ static HRESULT CdEnd(CLRDATA_ENUM handle)
+ {
+ SplitName* split = FROM_CDENUM(SplitName, handle);
+ if (split)
+ {
+ delete split;
+ return S_OK;
+ }
+ else
+ {
+ return E_INVALIDARG;
+ }
+ }
+};
+
+//----------------------------------------------------------------------------
+//
+// ProcessModIter.
+//
+//----------------------------------------------------------------------------
+
+struct ProcessModIter
+{
+ AppDomainIterator m_domainIter;
+ bool m_nextDomain;
+ AppDomain::AssemblyIterator m_assemIter;
+ bool m_iterShared;
+#ifdef FEATURE_LOADER_OPTIMIZATION
+ SharedDomain::SharedAssemblyIterator m_sharedIter;
+#endif
+ Assembly* m_curAssem;
+ Assembly::ModuleIterator m_modIter;
+
+ ProcessModIter(void)
+ : m_domainIter(FALSE)
+ {
+ SUPPORTS_DAC;
+ m_nextDomain = true;
+ m_iterShared = false;
+ m_curAssem = NULL;
+ }
+
+ Assembly * NextAssem()
+ {
+ SUPPORTS_DAC;
+ while (!m_iterShared)
+ {
+ if (m_nextDomain)
+ {
+ if (!m_domainIter.Next())
+ {
+ m_iterShared = true;
+ break;
+ }
+
+ m_nextDomain = false;
+
+ m_assemIter = m_domainIter.GetDomain()->IterateAssembliesEx((AssemblyIterationFlags)(
+ kIncludeLoaded | kIncludeExecution));
+ }
+
+ CollectibleAssemblyHolder<DomainAssembly *> pDomainAssembly;
+ if (!m_assemIter.Next(pDomainAssembly.This()))
+ {
+ m_nextDomain = true;
+ continue;
+ }
+
+ // Note: DAC doesn't need to keep the assembly alive - see code:CollectibleAssemblyHolder#CAH_DAC
+ CollectibleAssemblyHolder<Assembly *> pAssembly = pDomainAssembly->GetLoadedAssembly();
+ if (!pAssembly->IsDomainNeutral())
+ {
+ // We've found a domain-specific assembly, so this is a unique element in the Assembly
+ // iteration.
+ return pAssembly;
+ }
+
+ // Found a shared assembly, which may be duplicated
+ // across app domains. Ignore it now and let
+ // it get picked up in the shared iteration where
+ // it'll only occur once.
+ }
+#ifdef FEATURE_LOADER_OPTIMIZATION
+ if (!m_sharedIter.Next())
+ {
+ return NULL;
+ }
+ return m_sharedIter.GetAssembly();
+#else
+ return NULL;
+#endif
+ }
+
+ Module* NextModule(void)
+ {
+ SUPPORTS_DAC;
+ for (;;)
+ {
+ if (!m_curAssem)
+ {
+ m_curAssem = NextAssem();
+ if (!m_curAssem)
+ {
+ return NULL;
+ }
+
+ m_modIter = m_curAssem->IterateModules();
+ }
+
+ if (!m_modIter.Next())
+ {
+ m_curAssem = NULL;
+ continue;
+ }
+
+ return m_modIter.GetModule();
+ }
+ }
+};
+
+//----------------------------------------------------------------------------
+//
+// DacInstanceManager.
+//
+//----------------------------------------------------------------------------
+
+// The data for an access may have special alignment needs and
+// the cache must provide similar semantics.
+#define DAC_INSTANCE_ALIGN 16
+
+#define DAC_INSTANCE_SIG 0xdac1
+
+// The instance manager allocates large blocks and then
+// suballocates those for particular instances.
+struct DAC_INSTANCE_BLOCK
+{
+ DAC_INSTANCE_BLOCK* next;
+ ULONG32 bytesUsed;
+ ULONG32 bytesFree;
+};
+
+#define DAC_INSTANCE_BLOCK_ALLOCATION 0x40000
+
+// Sufficient memory is allocated to guarantee storage of the
+// instance header plus room for alignment padding.
+// Once the aligned pointer is found, this structure is prepended to
+// the aligned pointer and therefore doesn't affect the alignment
+// of the actual instance data.
+struct DAC_INSTANCE
+{
+ DAC_INSTANCE* next;
+ TADDR addr;
+ ULONG32 size;
+ // Identifying marker to give a simple
+ // check for host->taddr validity.
+ ULONG32 sig:16;
+ // DPTR or VPTR. See code:DAC_USAGE_TYPE
+ ULONG32 usage:2;
+
+ // Marker that can be used to prevent reporting this memory to the callback
+ // object (via ICLRDataEnumMemoryRegionsCallback:EnumMemoryRegion)
+ // more than once. This bit is checked only by the DacEnumHost?PtrMem
+ // macros, so consistent use of those macros ensures that the memory is
+ // reported at most once
+ ULONG32 enumMem:1;
+
+ // Marker to prevent metadata gets reported to mini-dump
+ ULONG32 noReport:1;
+
+ // Marker to determine if EnumMemoryRegions has been called on
+ // a method descriptor
+ ULONG32 MDEnumed:1;
+
+#ifdef _WIN64
+ // Keep DAC_INSTANCE a multiple of DAC_INSTANCE_ALIGN
+ // bytes in size.
+ ULONG32 pad[2];
+#endif
+};
+
+struct DAC_INSTANCE_PUSH
+{
+ DAC_INSTANCE_PUSH* next;
+ DAC_INSTANCE_BLOCK* blocks;
+ ULONG64 blockMemUsage;
+ ULONG32 numInst;
+ ULONG64 instMemUsage;
+};
+
+// The runtime will want the best access locality possible,
+// so it's likely that many instances will be clustered.
+// The hash function needs to spread near addresses across
+// hash entries, so hash on the low bits of the target address.
+// Not all the way down to the LSB, though, as there generally
+// won't be individual accesses at the byte level. Assume that
+// most accesses will be natural-word aligned.
+#define DAC_INSTANCE_HASH_BITS 10
+#define DAC_INSTANCE_HASH_SHIFT 2
+
+#define DAC_INSTANCE_HASH(addr) \
+ (((ULONG32)(ULONG_PTR)(addr) >> DAC_INSTANCE_HASH_SHIFT) & \
+ ((1 << DAC_INSTANCE_HASH_BITS) - 1))
+#define DAC_INSTANCE_HASH_SIZE (1 << DAC_INSTANCE_HASH_BITS)
+
+
+struct DumpMemoryReportStatics
+{
+ TSIZE_T m_cbStack; // number of bytes that we report directly for stack walk
+ TSIZE_T m_cbNgen; // number of bytes that we report directly for ngen images
+ TSIZE_T m_cbModuleList; // number of bytes that we report for module list directly
+ TSIZE_T m_cbClrStatics; // number of bytes that we report for CLR statics
+ TSIZE_T m_cbClrHeapStatics; // number of bytes that we report for CLR heap statics
+ TSIZE_T m_cbImplicity; // number of bytes that we report implicitly
+};
+
+
+class DacInstanceManager
+{
+public:
+ DacInstanceManager(void);
+ ~DacInstanceManager(void);
+
+ DAC_INSTANCE* Add(DAC_INSTANCE* inst);
+
+ DAC_INSTANCE* Alloc(TADDR addr, ULONG32 size, DAC_USAGE_TYPE usage);
+ void ReturnAlloc(DAC_INSTANCE* inst);
+ DAC_INSTANCE* Find(TADDR addr);
+ HRESULT Write(DAC_INSTANCE* inst, bool throwEx);
+ void Supersede(DAC_INSTANCE* inst);
+ void Flush(void);
+ void Flush(bool fSaveBlock);
+ void ClearEnumMemMarker(void);
+
+ void AddSuperseded(DAC_INSTANCE* inst)
+ {
+ SUPPORTS_DAC;
+ inst->next = m_superseded;
+ m_superseded = inst;
+ }
+
+ UINT DumpAllInstances(ICLRDataEnumMemoryRegionsCallback *pCallBack);
+
+private:
+
+ DAC_INSTANCE_BLOCK* FindInstanceBlock(DAC_INSTANCE* inst);
+ void FreeAllBlocks(bool fSaveBlock);
+
+ void InitEmpty(void)
+ {
+ m_blocks = NULL;
+ // m_unusedBlock is not NULLed here; it can contain one block we will use after
+ // a flush is complete.
+ m_blockMemUsage = 0;
+ m_numInst = 0;
+ m_instMemUsage = 0;
+#ifdef DAC_HASHTABLE
+ ZeroMemory(m_hash, sizeof(m_hash));
+#endif
+ m_superseded = NULL;
+ m_instPushed = NULL;
+ }
+
+#if defined(DAC_HASHTABLE)
+
+ typedef struct _HashInstanceKey {
+ TADDR addr;
+ DAC_INSTANCE* instance;
+ } HashInstanceKey;
+
+ typedef struct _HashInstanceKeyBlock {
+ // Blocks are chained in reverse order of allocation so that the most recently allocated
+ // block is searched first.
+ _HashInstanceKeyBlock* next;
+
+ // Entries to a block are added from the max index on down so that recently added
+ // entries are at the start of the block.
+ DWORD firstElement;
+ HashInstanceKey instanceKeys[] ;
+ } HashInstanceKeyBlock;
+
+// The hashing function does a good job of distributing the entries across buckets. To handle a
+// SO on x86, we have under 250 entries in a bucket. A 4K block size allows 511 entries on x86 and
+// about half that on x64. On x64, the number of entries added to the hash table is significantly
+// smaller than on x86 (and the max recursion depth for default stack sizes is also far less), so
+// 4K is generally adequate.
+
+#define HASH_INSTANCE_BLOCK_ALLOC_SIZE (4 * 1024)
+#define HASH_INSTANCE_BLOCK_NUM_ELEMENTS ((HASH_INSTANCE_BLOCK_ALLOC_SIZE - offsetof(_HashInstanceKeyBlock, instanceKeys))/sizeof(HashInstanceKey))
+#endif // #if defined(DAC_HASHTABLE)
+
+ DAC_INSTANCE_BLOCK* m_blocks;
+ DAC_INSTANCE_BLOCK* m_unusedBlock;
+ ULONG64 m_blockMemUsage;
+ ULONG32 m_numInst;
+ ULONG64 m_instMemUsage;
+
+#if defined(DAC_HASHTABLE)
+ HashInstanceKeyBlock* m_hash[DAC_INSTANCE_HASH_SIZE];
+#else //DAC_HASHTABLE
+
+ // We're going to use the STL unordered_map for our instance hash.
+ // This has the benefit of scaling to different workloads appropriately (as opposed to having a
+ // fixed number of buckets).
+
+ class DacHashCompare : public std::hash_compare<TADDR>
+ {
+ public:
+ // Custom hash function
+ // The default hash function uses a pseudo-randomizing function to get a random
+ // distribution. In our case, we'd actually like a more even distribution to get
+ // better access locality (see comments for DAC_INSTANCE_HASH_BITS).
+ //
+ // Also, when enumerating the hash during dump generation, clustering nearby addresses
+ // together can have a significant positive impact on the performance of the minidump
+ // library (at least the un-optimized version 6.5 linked into our dw20.exe - on Vista+
+ // we use the OS's version 6.7+ with radically improved perf characteristics). Having
+ // a random distribution is actually the worst-case because it means most blocks won't
+ // be merged until near the end, and a large number of intermediate blocks will have to
+ // be searched with each call.
+ //
+ // The default pseudo-randomizing function also requires a call to ldiv which shows up as
+ // a 3%-5% perf hit in most perf-sensitive scenarios, so this should also always be
+ // faster.
+ inline size_t operator()(const TADDR& keyval) const
+ {
+ return (unsigned)(keyval >>DAC_INSTANCE_HASH_SHIFT);
+ }
+
+ // Explicitly bring in the two-argument comparison function from the base class (just less-than)
+ // This is necessary because once we override one form of operator() above, we don't automatically
+ // get the others by C++ inheritance rules.
+ using std::hash_compare<TADDR>::operator();
+
+#ifdef NIDUMP_CUSTOMIZED_DAC_HASH // not set
+ //this particular number is supposed to be roughly the same amount of
+ //memory as the old code (buckets * number of entries in the old
+ //blocks.)
+ //disabled for now. May tweak implementation later. It turns out that
+ //having a large number of initial buckets is excellent for nidump, but it
+ // is terrible for most other scenarios due to the cost of clearing them at
+ // every Flush. Once there is a better perf suite, we can tweak these values more.
+ static const size_t min_buckets = DAC_INSTANCE_HASH_SIZE * 256;
+#endif
+
+ };
+ typedef std::unordered_map<TADDR, DAC_INSTANCE*, DacHashCompare > DacInstanceHash;
+ typedef DacInstanceHash::value_type DacInstanceHashValue;
+ typedef DacInstanceHash::iterator DacInstanceHashIterator;
+ DacInstanceHash m_hash;
+#endif //DAC_HASHTABLE
+
+ DAC_INSTANCE* m_superseded;
+ DAC_INSTANCE_PUSH* m_instPushed;
+};
+
+
+#ifdef FEATURE_MINIMETADATA_IN_TRIAGEDUMPS
+
+class DacStreamManager;
+
+#endif // FEATURE_MINIMETADATA_IN_TRIAGEDUMPS
+
+
+//----------------------------------------------------------------------------
+//
+// ClrDataAccess.
+//
+//----------------------------------------------------------------------------
+
+class ClrDataAccess
+ : public IXCLRDataProcess2,
+ public ICLRDataEnumMemoryRegions,
+ public ISOSDacInterface,
+ public ISOSDacInterface2,
+ public ISOSDacInterface3,
+ public ISOSDacInterface4
+{
+public:
+ ClrDataAccess(ICorDebugDataTarget * pTarget, ICLRDataTarget * pLegacyTarget=0);
+ virtual ~ClrDataAccess(void);
+
+ // IUnknown.
+ STDMETHOD(QueryInterface)(THIS_
+ IN REFIID interfaceId,
+ OUT PVOID* iface);
+ STDMETHOD_(ULONG, AddRef)(THIS);
+ STDMETHOD_(ULONG, Release)(THIS);
+
+ //
+ // IXCLRDataProcess.
+ //
+
+ virtual HRESULT STDMETHODCALLTYPE Flush( void);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumTasks(
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumTask(
+ /* [in, out] */ CLRDATA_ENUM* handle,
+ /* [out] */ IXCLRDataTask **task);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumTasks(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE GetTaskByOSThreadID(
+ /* [in] */ ULONG32 OSThreadID,
+ /* [out] */ IXCLRDataTask **task);
+
+ virtual HRESULT STDMETHODCALLTYPE GetTaskByUniqueID(
+ /* [in] */ ULONG64 uniqueID,
+ /* [out] */ IXCLRDataTask **task);
+
+ virtual HRESULT STDMETHODCALLTYPE GetFlags(
+ /* [out] */ ULONG32 *flags);
+
+ virtual HRESULT STDMETHODCALLTYPE IsSameObject(
+ /* [in] */ IXCLRDataProcess *process);
+
+ virtual HRESULT STDMETHODCALLTYPE GetManagedObject(
+ /* [out] */ IXCLRDataValue **value);
+
+ virtual HRESULT STDMETHODCALLTYPE GetDesiredExecutionState(
+ /* [out] */ ULONG32 *state);
+
+ virtual HRESULT STDMETHODCALLTYPE SetDesiredExecutionState(
+ /* [in] */ ULONG32 state);
+
+ virtual HRESULT STDMETHODCALLTYPE GetAddressType(
+ /* [in] */ CLRDATA_ADDRESS address,
+ /* [out] */ CLRDataAddressType* type);
+
+ virtual HRESULT STDMETHODCALLTYPE GetRuntimeNameByAddress(
+ /* [in] */ CLRDATA_ADDRESS address,
+ /* [in] */ ULONG32 flags,
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_opt(bufLen) WCHAR nameBuf[ ],
+ /* [out] */ CLRDATA_ADDRESS* displacement);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumAppDomains(
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumAppDomain(
+ /* [in, out] */ CLRDATA_ENUM* handle,
+ /* [out] */ IXCLRDataAppDomain **appDomain);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumAppDomains(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE GetAppDomainByUniqueID(
+ /* [in] */ ULONG64 uniqueID,
+ /* [out] */ IXCLRDataAppDomain **appDomain);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumAssemblies(
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumAssembly(
+ /* [in, out] */ CLRDATA_ENUM* handle,
+ /* [out] */ IXCLRDataAssembly **assembly);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumAssemblies(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumModules(
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumModule(
+ /* [in, out] */ CLRDATA_ENUM* handle,
+ /* [out] */ IXCLRDataModule **mod);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumModules(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE GetModuleByAddress(
+ /* [in] */ CLRDATA_ADDRESS address,
+ /* [out] */ IXCLRDataModule** mod);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumMethodDefinitionsByAddress(
+ /* [in] */ CLRDATA_ADDRESS address,
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumMethodDefinitionByAddress(
+ /* [in] */ CLRDATA_ENUM* handle,
+ /* [out] */ IXCLRDataMethodDefinition **method);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumMethodDefinitionsByAddress(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumMethodInstancesByAddress(
+ /* [in] */ CLRDATA_ADDRESS address,
+ /* [in] */ IXCLRDataAppDomain* appDomain,
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumMethodInstanceByAddress(
+ /* [in] */ CLRDATA_ENUM* handle,
+ /* [out] */ IXCLRDataMethodInstance **method);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumMethodInstancesByAddress(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE GetDataByAddress(
+ /* [in] */ CLRDATA_ADDRESS address,
+ /* [in] */ ULONG32 flags,
+ /* [in] */ IXCLRDataAppDomain* appDomain,
+ /* [in] */ IXCLRDataTask* tlsTask,
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR nameBuf[ ],
+ /* [out] */ IXCLRDataValue **value,
+ /* [out] */ CLRDATA_ADDRESS *displacement);
+
+ virtual HRESULT STDMETHODCALLTYPE GetExceptionStateByExceptionRecord(
+ /* [in] */ EXCEPTION_RECORD64 *record,
+ /* [out] */ IXCLRDataExceptionState **exception);
+
+ virtual HRESULT STDMETHODCALLTYPE TranslateExceptionRecordToNotification(
+ /* [in] */ EXCEPTION_RECORD64 *record,
+ /* [in] */ IXCLRDataExceptionNotification *notify);
+
+ virtual HRESULT STDMETHODCALLTYPE CreateMemoryValue(
+ /* [in] */ IXCLRDataAppDomain* appDomain,
+ /* [in] */ IXCLRDataTask* tlsTask,
+ /* [in] */ IXCLRDataTypeInstance* type,
+ /* [in] */ CLRDATA_ADDRESS addr,
+ /* [out] */ IXCLRDataValue** value);
+
+ virtual HRESULT STDMETHODCALLTYPE SetAllTypeNotifications(
+ /* [in] */ IXCLRDataModule* mod,
+ /* [in] */ ULONG32 flags);
+
+ virtual HRESULT STDMETHODCALLTYPE SetAllCodeNotifications(
+ /* [in] */ IXCLRDataModule* mod,
+ /* [in] */ ULONG32 flags);
+
+ virtual HRESULT STDMETHODCALLTYPE GetTypeNotifications(
+ /* [in] */ ULONG32 numTokens,
+ /* [in, size_is(numTokens)] */ IXCLRDataModule* mods[],
+ /* [in] */ IXCLRDataModule* singleMod,
+ /* [in, size_is(numTokens)] */ mdTypeDef tokens[],
+ /* [out, size_is(numTokens)] */ ULONG32 flags[]);
+
+ virtual HRESULT STDMETHODCALLTYPE SetTypeNotifications(
+ /* [in] */ ULONG32 numTokens,
+ /* [in, size_is(numTokens)] */ IXCLRDataModule* mods[],
+ /* [in] */ IXCLRDataModule* singleMod,
+ /* [in, size_is(numTokens)] */ mdTypeDef tokens[],
+ /* [in, size_is(numTokens)] */ ULONG32 flags[],
+ /* [in] */ ULONG32 singleFlags);
+
+ virtual HRESULT STDMETHODCALLTYPE GetCodeNotifications(
+ /* [in] */ ULONG32 numTokens,
+ /* [in, size_is(numTokens)] */ IXCLRDataModule* mods[],
+ /* [in] */ IXCLRDataModule* singleMod,
+ /* [in, size_is(numTokens)] */ mdMethodDef tokens[],
+ /* [out, size_is(numTokens)] */ ULONG32 flags[]);
+
+ virtual HRESULT STDMETHODCALLTYPE SetCodeNotifications(
+ /* [in] */ ULONG32 numTokens,
+ /* [in, size_is(numTokens)] */ IXCLRDataModule* mods[],
+ /* [in] */ IXCLRDataModule* singleMod,
+ /* [in, size_is(numTokens)] */ mdMethodDef tokens[],
+ /* [in, size_is(numTokens)] */ ULONG32 flags[],
+ /* [in] */ ULONG32 singleFlags);
+
+ virtual HRESULT STDMETHODCALLTYPE GetOtherNotificationFlags(
+ /* [out] */ ULONG32* flags);
+
+ virtual HRESULT STDMETHODCALLTYPE SetOtherNotificationFlags(
+ /* [in] */ ULONG32 flags);
+
+ virtual HRESULT STDMETHODCALLTYPE FollowStub(
+ /* [in] */ ULONG32 inFlags,
+ /* [in] */ CLRDATA_ADDRESS inAddr,
+ /* [in] */ CLRDATA_FOLLOW_STUB_BUFFER* inBuffer,
+ /* [out] */ CLRDATA_ADDRESS* outAddr,
+ /* [out] */ CLRDATA_FOLLOW_STUB_BUFFER* outBuffer,
+ /* [out] */ ULONG32* outFlags);
+
+ virtual HRESULT STDMETHODCALLTYPE FollowStub2(
+ /* [in] */ IXCLRDataTask* task,
+ /* [in] */ ULONG32 inFlags,
+ /* [in] */ CLRDATA_ADDRESS inAddr,
+ /* [in] */ CLRDATA_FOLLOW_STUB_BUFFER* inBuffer,
+ /* [out] */ CLRDATA_ADDRESS* outAddr,
+ /* [out] */ CLRDATA_FOLLOW_STUB_BUFFER* outBuffer,
+ /* [out] */ ULONG32* outFlags);
+
+ virtual HRESULT STDMETHODCALLTYPE Request(
+ /* [in] */ ULONG32 reqCode,
+ /* [in] */ ULONG32 inBufferSize,
+ /* [size_is][in] */ BYTE *inBuffer,
+ /* [in] */ ULONG32 outBufferSize,
+ /* [size_is][out] */ BYTE *outBuffer);
+
+
+ //
+ // IXCLRDataProcess2.
+ //
+ STDMETHOD(GetGcNotification)(/* [out] */ GcEvtArgs* gcEvtArgs);
+ STDMETHOD(SetGcNotification)(/* [in] */ GcEvtArgs gcEvtArgs);
+
+ //
+ // ICLRDataEnumMemoryRegions.
+ //
+ virtual HRESULT STDMETHODCALLTYPE EnumMemoryRegions(
+ /* [in] */ ICLRDataEnumMemoryRegionsCallback *callback,
+ /* [in] */ ULONG32 miniDumpFlags,
+ /* [in] */ CLRDataEnumMemoryFlags clrFlags);
+
+
+ // ISOSDacInterface
+ virtual HRESULT STDMETHODCALLTYPE GetThreadStoreData(struct DacpThreadStoreData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetAppDomainStoreData(struct DacpAppDomainStoreData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetAppDomainList(unsigned int count, CLRDATA_ADDRESS values[], unsigned int *pNeeded);
+ virtual HRESULT STDMETHODCALLTYPE GetAppDomainData(CLRDATA_ADDRESS addr, struct DacpAppDomainData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetAppDomainName(CLRDATA_ADDRESS addr, unsigned int count, __out_z __inout_ecount(count) wchar_t *name, unsigned int *pNeeded);
+ virtual HRESULT STDMETHODCALLTYPE GetAssemblyList(CLRDATA_ADDRESS appDomain, int count, CLRDATA_ADDRESS values[], int *fetched);
+ virtual HRESULT STDMETHODCALLTYPE GetAssemblyData(CLRDATA_ADDRESS baseDomainPtr, CLRDATA_ADDRESS assembly, struct DacpAssemblyData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetAssemblyName(CLRDATA_ADDRESS assembly, unsigned int count, __out_z __inout_ecount(count) wchar_t *name, unsigned int *pNeeded);
+ virtual HRESULT STDMETHODCALLTYPE GetThreadData(CLRDATA_ADDRESS thread, struct DacpThreadData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetThreadFromThinlockID(UINT thinLockId, CLRDATA_ADDRESS *pThread);
+ virtual HRESULT STDMETHODCALLTYPE GetStackLimits(CLRDATA_ADDRESS threadPtr, CLRDATA_ADDRESS *lower, CLRDATA_ADDRESS *upper, CLRDATA_ADDRESS *fp);
+ virtual HRESULT STDMETHODCALLTYPE GetDomainFromContext(CLRDATA_ADDRESS context, CLRDATA_ADDRESS *domain);
+
+ virtual HRESULT STDMETHODCALLTYPE GetMethodDescData(CLRDATA_ADDRESS methodDesc, CLRDATA_ADDRESS ip, struct DacpMethodDescData *data, ULONG cRevertedRejitVersions, DacpReJitData * rgRevertedRejitData, ULONG * pcNeededRevertedRejitData);
+ virtual HRESULT STDMETHODCALLTYPE GetMethodDescPtrFromIP(CLRDATA_ADDRESS ip, CLRDATA_ADDRESS * ppMD);
+ virtual HRESULT STDMETHODCALLTYPE GetMethodDescName(CLRDATA_ADDRESS methodDesc, unsigned int count, __out_z __inout_ecount(count) wchar_t *name, unsigned int *pNeeded);
+ virtual HRESULT STDMETHODCALLTYPE GetMethodDescPtrFromFrame(CLRDATA_ADDRESS frameAddr, CLRDATA_ADDRESS * ppMD);
+ virtual HRESULT STDMETHODCALLTYPE GetCodeHeaderData(CLRDATA_ADDRESS ip, struct DacpCodeHeaderData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetThreadpoolData(struct DacpThreadpoolData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetWorkRequestData(CLRDATA_ADDRESS addrWorkRequest, struct DacpWorkRequestData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetObjectData(CLRDATA_ADDRESS objAddr, struct DacpObjectData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetObjectStringData(CLRDATA_ADDRESS obj, unsigned int count, __out_z __inout_ecount(count) wchar_t *stringData, unsigned int *pNeeded);
+ virtual HRESULT STDMETHODCALLTYPE GetObjectClassName(CLRDATA_ADDRESS obj, unsigned int count, __out_z __inout_ecount(count) wchar_t *className, unsigned int *pNeeded);
+ virtual HRESULT STDMETHODCALLTYPE GetMethodTableName(CLRDATA_ADDRESS mt, unsigned int count, __out_z __inout_ecount(count) wchar_t *mtName, unsigned int *pNeeded);
+ virtual HRESULT STDMETHODCALLTYPE GetMethodTableData(CLRDATA_ADDRESS mt, struct DacpMethodTableData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetMethodTableFieldData(CLRDATA_ADDRESS mt, struct DacpMethodTableFieldData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetMethodTableTransparencyData(CLRDATA_ADDRESS mt, struct DacpMethodTableTransparencyData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetMethodTableForEEClass(CLRDATA_ADDRESS eeClass, CLRDATA_ADDRESS *value);
+ virtual HRESULT STDMETHODCALLTYPE GetFieldDescData(CLRDATA_ADDRESS fieldDesc, struct DacpFieldDescData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetFrameName(CLRDATA_ADDRESS vtable, unsigned int count, __out_z __inout_ecount(count) wchar_t *frameName, unsigned int *pNeeded);
+ virtual HRESULT STDMETHODCALLTYPE GetModule(CLRDATA_ADDRESS addr, IXCLRDataModule **mod);
+ virtual HRESULT STDMETHODCALLTYPE GetModuleData(CLRDATA_ADDRESS moduleAddr, struct DacpModuleData *data);
+ virtual HRESULT STDMETHODCALLTYPE TraverseModuleMap(ModuleMapType mmt, CLRDATA_ADDRESS moduleAddr, MODULEMAPTRAVERSE pCallback, LPVOID token);
+ virtual HRESULT STDMETHODCALLTYPE GetMethodDescFromToken(CLRDATA_ADDRESS moduleAddr, mdToken token, CLRDATA_ADDRESS *methodDesc);
+ virtual HRESULT STDMETHODCALLTYPE GetPEFileBase(CLRDATA_ADDRESS addr, CLRDATA_ADDRESS *base);
+ virtual HRESULT STDMETHODCALLTYPE GetPEFileName(CLRDATA_ADDRESS addr, unsigned int count, __out_z __inout_ecount(count) wchar_t *fileName, unsigned int *pNeeded);
+ virtual HRESULT STDMETHODCALLTYPE GetAssemblyModuleList(CLRDATA_ADDRESS assembly, unsigned int count, CLRDATA_ADDRESS modules[], unsigned int *pNeeded);
+ virtual HRESULT STDMETHODCALLTYPE GetGCHeapData(struct DacpGcHeapData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetGCHeapList(unsigned int count, CLRDATA_ADDRESS heaps[], unsigned int *pNeeded);
+ virtual HRESULT STDMETHODCALLTYPE GetGCHeapDetails(CLRDATA_ADDRESS heap, struct DacpGcHeapDetails *details);
+ virtual HRESULT STDMETHODCALLTYPE GetGCHeapStaticData(struct DacpGcHeapDetails *data);
+ virtual HRESULT STDMETHODCALLTYPE GetHeapSegmentData(CLRDATA_ADDRESS seg, struct DacpHeapSegmentData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetDomainLocalModuleData(CLRDATA_ADDRESS addr, struct DacpDomainLocalModuleData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetDomainLocalModuleDataFromAppDomain(CLRDATA_ADDRESS appDomainAddr, int moduleID, struct DacpDomainLocalModuleData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetDomainLocalModuleDataFromModule(CLRDATA_ADDRESS moduleAddr, struct DacpDomainLocalModuleData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetSyncBlockData(unsigned int number, struct DacpSyncBlockData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetSyncBlockCleanupData(CLRDATA_ADDRESS addr, struct DacpSyncBlockCleanupData *data);
+ virtual HRESULT STDMETHODCALLTYPE TraverseRCWCleanupList(CLRDATA_ADDRESS cleanupListPtr, VISITRCWFORCLEANUP pCallback, LPVOID token);
+ virtual HRESULT STDMETHODCALLTYPE TraverseEHInfo(CLRDATA_ADDRESS ip, DUMPEHINFO pCallback, LPVOID token);
+ virtual HRESULT STDMETHODCALLTYPE GetStressLogAddress(CLRDATA_ADDRESS *stressLog);
+ virtual HRESULT STDMETHODCALLTYPE GetJitManagerList(unsigned int count, struct DacpJitManagerInfo managers[], unsigned int *pNeeded);
+ virtual HRESULT STDMETHODCALLTYPE GetJitHelperFunctionName(CLRDATA_ADDRESS ip, unsigned int count, __out_z __inout_ecount(count) char *name, unsigned int *pNeeded);
+ virtual HRESULT STDMETHODCALLTYPE GetJumpThunkTarget(T_CONTEXT *ctx, CLRDATA_ADDRESS *targetIP, CLRDATA_ADDRESS *targetMD);
+ virtual HRESULT STDMETHODCALLTYPE TraverseLoaderHeap(CLRDATA_ADDRESS loaderHeapAddr, VISITHEAP pCallback);
+ virtual HRESULT STDMETHODCALLTYPE GetCodeHeapList(CLRDATA_ADDRESS jitManager, unsigned int count, struct DacpJitCodeHeapInfo codeHeaps[], unsigned int *pNeeded);
+ virtual HRESULT STDMETHODCALLTYPE GetMethodTableSlot(CLRDATA_ADDRESS mt, unsigned int slot, CLRDATA_ADDRESS *value);
+ virtual HRESULT STDMETHODCALLTYPE TraverseVirtCallStubHeap(CLRDATA_ADDRESS pAppDomain, VCSHeapType heaptype, VISITHEAP pCallback);
+ virtual HRESULT STDMETHODCALLTYPE GetNestedExceptionData(CLRDATA_ADDRESS exception, CLRDATA_ADDRESS *exceptionObject, CLRDATA_ADDRESS *nextNestedException);
+ virtual HRESULT STDMETHODCALLTYPE GetUsefulGlobals(struct DacpUsefulGlobalsData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetILForModule(CLRDATA_ADDRESS moduleAddr, DWORD rva, CLRDATA_ADDRESS *il);
+ virtual HRESULT STDMETHODCALLTYPE GetClrWatsonBuckets(CLRDATA_ADDRESS thread, void *pGenericModeBlock);
+ virtual HRESULT STDMETHODCALLTYPE GetOOMData(CLRDATA_ADDRESS oomAddr, struct DacpOomData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetOOMStaticData(struct DacpOomData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetHeapAnalyzeData(CLRDATA_ADDRESS addr,struct DacpGcHeapAnalyzeData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetHeapAnalyzeStaticData(struct DacpGcHeapAnalyzeData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetMethodDescTransparencyData(CLRDATA_ADDRESS methodDesc, struct DacpMethodDescTransparencyData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetHillClimbingLogEntry(CLRDATA_ADDRESS addr, struct DacpHillClimbingLogEntry *data);
+ virtual HRESULT STDMETHODCALLTYPE GetThreadLocalModuleData(CLRDATA_ADDRESS thread, unsigned int index, struct DacpThreadLocalModuleData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetRCWData(CLRDATA_ADDRESS addr, struct DacpRCWData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetRCWInterfaces(CLRDATA_ADDRESS rcw, unsigned int count, struct DacpCOMInterfacePointerData interfaces[], unsigned int *pNeeded);
+ virtual HRESULT STDMETHODCALLTYPE GetCCWData(CLRDATA_ADDRESS ccw, struct DacpCCWData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetCCWInterfaces(CLRDATA_ADDRESS ccw, unsigned int count, struct DacpCOMInterfacePointerData interfaces[], unsigned int *pNeeded);
+ virtual HRESULT STDMETHODCALLTYPE GetTLSIndex(ULONG *pIndex);
+ virtual HRESULT STDMETHODCALLTYPE GetDacModuleHandle(HMODULE *phModule);
+
+ virtual HRESULT STDMETHODCALLTYPE GetFailedAssemblyList(CLRDATA_ADDRESS appDomain, int count, CLRDATA_ADDRESS values[], unsigned int *pNeeded);
+ virtual HRESULT STDMETHODCALLTYPE GetPrivateBinPaths(CLRDATA_ADDRESS appDomain, int count, __out_z __inout_ecount(count) wchar_t *paths, unsigned int *pNeeded);
+ virtual HRESULT STDMETHODCALLTYPE GetAssemblyLocation(CLRDATA_ADDRESS assembly, int count, __out_z __inout_ecount(count) wchar_t *location, unsigned int *pNeeded);
+ virtual HRESULT STDMETHODCALLTYPE GetAppDomainConfigFile(CLRDATA_ADDRESS appDomain, int count, __out_z __inout_ecount(count) wchar_t *configFile, unsigned int *pNeeded);
+ virtual HRESULT STDMETHODCALLTYPE GetApplicationBase(CLRDATA_ADDRESS appDomain, int count, __out_z __inout_ecount(count) wchar_t *base, unsigned int *pNeeded);
+
+ virtual HRESULT STDMETHODCALLTYPE GetFailedAssemblyData(CLRDATA_ADDRESS assembly, unsigned int *pContext, HRESULT *pResult);
+ virtual HRESULT STDMETHODCALLTYPE GetFailedAssemblyLocation(CLRDATA_ADDRESS assembly, unsigned int count, __out_z __inout_ecount(count) wchar_t *location, unsigned int *pNeeded);
+ virtual HRESULT STDMETHODCALLTYPE GetFailedAssemblyDisplayName(CLRDATA_ADDRESS assembly, unsigned int count, __out_z __inout_ecount(count) wchar_t *name, unsigned int *pNeeded);
+
+ virtual HRESULT STDMETHODCALLTYPE GetStackReferences(DWORD osThreadID, ISOSStackRefEnum **ppEnum);
+ virtual HRESULT STDMETHODCALLTYPE GetRegisterName(int regNum, unsigned int count, __out_z __inout_ecount(count) wchar_t *buffer, unsigned int *pNeeded);
+
+ virtual HRESULT STDMETHODCALLTYPE GetHandleEnum(ISOSHandleEnum **ppHandleEnum);
+ virtual HRESULT STDMETHODCALLTYPE GetHandleEnumForTypes(unsigned int types[], unsigned int count, ISOSHandleEnum **ppHandleEnum);
+ virtual HRESULT STDMETHODCALLTYPE GetHandleEnumForGC(unsigned int gen, ISOSHandleEnum **ppHandleEnum);
+
+ virtual HRESULT STDMETHODCALLTYPE GetThreadAllocData(CLRDATA_ADDRESS thread, struct DacpAllocData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetHeapAllocData(unsigned int count, struct DacpGenerationAllocData *data, unsigned int *pNeeded);
+
+ // ISOSDacInterface2
+ virtual HRESULT STDMETHODCALLTYPE GetObjectExceptionData(CLRDATA_ADDRESS objAddr, struct DacpExceptionObjectData *data);
+ virtual HRESULT STDMETHODCALLTYPE IsRCWDCOMProxy(CLRDATA_ADDRESS rcwAddr, BOOL* isDCOMProxy);
+
+ // ISOSDacInterface3
+ virtual HRESULT STDMETHODCALLTYPE GetGCInterestingInfoData(CLRDATA_ADDRESS interestingInfoAddr, struct DacpGCInterestingInfoData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetGCInterestingInfoStaticData(struct DacpGCInterestingInfoData *data);
+ virtual HRESULT STDMETHODCALLTYPE GetGCGlobalMechanisms(size_t* globalMechanisms);
+
+ // ISOSDacInterface4
+ virtual HRESULT STDMETHODCALLTYPE GetClrNotification(CLRDATA_ADDRESS arguments[], int count, int *pNeeded);
+
+ //
+ // ClrDataAccess.
+ //
+
+ HRESULT Initialize(void);
+
+ BOOL IsExceptionFromManagedCode(EXCEPTION_RECORD * pExceptionRecord);
+#ifndef FEATURE_PAL
+ HRESULT GetWatsonBuckets(DWORD dwThreadId, GenericModeBlock * pGM);
+#endif // FEATURE_PAL
+
+
+ Thread* FindClrThreadByTaskId(ULONG64 taskId);
+ HRESULT IsPossibleCodeAddress(IN TADDR address);
+
+ PCSTR GetJitHelperName(IN TADDR address,
+ IN bool dynamicHelpersOnly = false);
+ HRESULT GetFullMethodName(IN MethodDesc* methodDesc,
+ IN ULONG32 symbolChars,
+ IN ULONG32* symbolLen,
+ __out_ecount_part_opt(symbolChars, *symbolLen) LPWSTR symbol);
+ HRESULT RawGetMethodName(/* [in] */ CLRDATA_ADDRESS address,
+ /* [in] */ ULONG32 flags,
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_opt(bufLen) WCHAR nameBuf[ ],
+ /* [out] */ CLRDATA_ADDRESS* displacement);
+
+ HRESULT FollowStubStep(
+ /* [in] */ Thread* thread,
+ /* [in] */ ULONG32 inFlags,
+ /* [in] */ TADDR inAddr,
+ /* [in] */ union STUB_BUF* inBuffer,
+ /* [out] */ TADDR* outAddr,
+ /* [out] */ union STUB_BUF* outBuffer,
+ /* [out] */ ULONG32* outFlags);
+
+ DebuggerJitInfo* GetDebuggerJitInfo(MethodDesc* methodDesc,
+ TADDR addr)
+ {
+ if (g_pDebugger)
+ {
+ return g_pDebugger->GetJitInfo(methodDesc, (PBYTE)addr, NULL);
+ }
+
+ return NULL;
+ }
+
+ HRESULT GetMethodExtents(MethodDesc* methodDesc,
+ METH_EXTENTS** extents);
+ HRESULT GetMethodVarInfo(MethodDesc* methodDesc,
+ TADDR address,
+ ULONG32* numVarInfo,
+ ICorDebugInfo::NativeVarInfo** varInfo,
+ ULONG32* codeOffset);
+
+ // If the method has multiple copies of code (because of EnC or code-pitching),
+ // this returns the info corresponding to address.
+ // If 'address' and 'codeOffset' are both non-NULL, *codeOffset gets set to
+ // the offset of 'address' from the start of the method.
+ HRESULT GetMethodNativeMap(MethodDesc* methodDesc,
+ TADDR address,
+ ULONG32* numMap,
+ DebuggerILToNativeMap** map,
+ bool* mapAllocated,
+ CLRDATA_ADDRESS* codeStart,
+ ULONG32* codeOffset);
+
+ // Get the MethodDesc for a function
+ MethodDesc * FindLoadedMethodRefOrDef(Module* pModule, mdToken memberRef);
+
+#ifndef FEATURE_PAL
+ HRESULT GetClrWatsonBucketsWorker(Thread * pThread, GenericModeBlock * pGM);
+#endif // FEATURE_PAL
+
+ HRESULT ServerGCHeapDetails(CLRDATA_ADDRESS heapAddr,
+ DacpGcHeapDetails *detailsData);
+ HRESULT GetServerAllocData(unsigned int count, struct DacpGenerationAllocData *data, unsigned int *pNeeded);
+ HRESULT ServerOomData(CLRDATA_ADDRESS addr, DacpOomData *oomData);
+ HRESULT ServerGCInterestingInfoData(CLRDATA_ADDRESS addr, DacpGCInterestingInfoData *interestingInfoData);
+ HRESULT ServerGCHeapAnalyzeData(CLRDATA_ADDRESS heapAddr,
+ DacpGcHeapAnalyzeData *analyzeData);
+
+ //
+ // Memory enumeration.
+ //
+
+ HRESULT EnumMemoryRegionsWrapper(CLRDataEnumMemoryFlags flags);
+
+ // skinny minidump functions
+ HRESULT EnumMemoryRegionsWorkerSkinny(CLRDataEnumMemoryFlags flags);
+ // triage minidump functions
+ HRESULT EnumMemoryRegionsWorkerMicroTriage(CLRDataEnumMemoryFlags flags);
+ HRESULT EnumMemoryRegionsWorkerHeap(CLRDataEnumMemoryFlags flags);
+
+ HRESULT EnumMemWalkStackHelper(CLRDataEnumMemoryFlags flags, IXCLRDataStackWalk *pStackWalk, Thread * pThread);
+ HRESULT DumpManagedObject(CLRDataEnumMemoryFlags flags, OBJECTREF objRef);
+ HRESULT DumpManagedExcepObject(CLRDataEnumMemoryFlags flags, OBJECTREF objRef);
+ HRESULT DumpManagedStackTraceStringObject(CLRDataEnumMemoryFlags flags, STRINGREF orefStackTrace);
+#ifdef FEATURE_COMINTEROP
+ HRESULT DumpStowedExceptionObject(CLRDataEnumMemoryFlags flags, CLRDATA_ADDRESS ccwPtr);
+ HRESULT EnumMemStowedException(CLRDataEnumMemoryFlags flags);
+#endif
+
+ HRESULT EnumMemWriteDataSegment();
+
+ // Custom Dump
+ HRESULT EnumMemoryRegionsWorkerCustom();
+
+ // helper function for dump code
+ void EnumWksGlobalMemoryRegions(CLRDataEnumMemoryFlags flags);
+ void EnumSvrGlobalMemoryRegions(CLRDataEnumMemoryFlags flags);
+
+ HRESULT EnumMemCollectImages();
+ HRESULT EnumMemCLRStatic(CLRDataEnumMemoryFlags flags);
+ HRESULT EnumMemCLRHeapCrticalStatic(CLRDataEnumMemoryFlags flags);
+ HRESULT EnumMemDumpModuleList(CLRDataEnumMemoryFlags flags);
+ HRESULT EnumMemDumpAppDomainInfo(CLRDataEnumMemoryFlags flags);
+ HRESULT EnumMemDumpAllThreadsStack(CLRDataEnumMemoryFlags flags);
+ HRESULT EnumMemCLRMainModuleInfo();
+
+ bool ReportMem(TADDR addr, TSIZE_T size, bool fExpectSuccess = true);
+ bool DacUpdateMemoryRegion(TADDR addr, TSIZE_T bufferSize, BYTE* buffer);
+
+ void ClearDumpStats();
+ JITNotification* GetHostJitNotificationTable();
+ GcNotification* GetHostGcNotificationTable();
+
+ void* GetMetaDataFromHost(PEFile* peFile,
+ bool* isAlternate);
+
+ virtual
+ interface IMDInternalImport* GetMDImport(const PEFile* peFile,
+ const ReflectionModule* reflectionModule,
+ bool throwEx);
+
+ interface IMDInternalImport* GetMDImport(const PEFile* peFile,
+ bool throwEx)
+ {
+ return GetMDImport(peFile, NULL, throwEx);
+ }
+
+ interface IMDInternalImport* GetMDImport(const ReflectionModule* reflectionModule,
+ bool throwEx)
+ {
+ return GetMDImport(NULL, reflectionModule, throwEx);
+ }
+
+ //ClrDump support
+ HRESULT STDMETHODCALLTYPE DumpNativeImage(CLRDATA_ADDRESS loadedBase,
+ LPCWSTR name,
+ IXCLRDataDisplay *display,
+ IXCLRLibrarySupport *support,
+ IXCLRDisassemblySupport *dis);
+
+ // Set whether inconsistencies in the target should raise asserts.
+ void SetTargetConsistencyChecks(bool fEnableAsserts);
+
+ // Get whether inconsistencies in the target should raise asserts.
+ bool TargetConsistencyAssertsEnabled();
+
+ // Get the ICLRDataTarget2 instance, if any
+ ICLRDataTarget2 * GetLegacyTarget2() { return m_pLegacyTarget2; }
+
+ // Get the ICLRDataTarget3 instance, if any
+ ICLRDataTarget3 * GetLegacyTarget3() { return m_pLegacyTarget3; }
+
+ //
+ // Public Fields
+ // Note that it would be nice if all of these were made private. However, the visibility
+ // model of the DAC implementation is that the public surface area is declared in daccess.h
+ // (implemented in dacfn.cpp), and the private surface area (like ClrDataAccess) is declared
+ // in dacimpl.h which is only included by the DAC infrastructure. Therefore the DAC
+ // infrastructure agressively uses these fields, and we don't get a huge amount of benefit from
+ // reworking this model (since there is some form of encapsulation in place already).
+ //
+
+ // The underlying data target - always present (strong reference)
+ ICorDebugDataTarget * m_pTarget;
+
+ // Mutable version of the data target if any - optional (strong reference)
+ ICorDebugMutableDataTarget * m_pMutableTarget;
+
+ TADDR m_globalBase;
+ DacInstanceManager m_instances;
+ ULONG32 m_instanceAge;
+ bool m_debugMode;
+
+#ifdef FEATURE_MINIMETADATA_IN_TRIAGEDUMPS
+
+protected:
+ DacStreamManager * m_streams;
+
+public:
+ // Used to mark the point after which enumerated EE structs of interest
+ // will get their names cached in the triage/mini-dump
+ void InitStreamsForWriting(IN CLRDataEnumMemoryFlags flags);
+
+ // Used during triage/mini-dump collection to populate the map of
+ // pointers to EE struct (MethodDesc* for now) to their corresponding
+ // name.
+ bool MdCacheAddEEName(TADDR taEEStruct, const SString& name);
+
+ // Used to mark the end point for the name caching. Will update streams
+ // based on built caches
+ void EnumStreams(IN CLRDataEnumMemoryFlags flags);
+
+ // Used during triage/mini-dump analysis to retrieve the name associated
+ // with an EE struct pointer (MethodDesc* for now).
+ bool MdCacheGetEEName(TADDR taEEStruct, SString & eeName);
+
+#endif // FEATURE_MINIMETADATA_IN_TRIAGEDUMPS
+
+private:
+ // Read the DAC table and initialize g_dacGlobals
+ HRESULT GetDacGlobals();
+
+ // Verify the target mscorwks.dll matches the version expected
+ HRESULT VerifyDlls();
+
+ // Check whether a region of memory is fully readable.
+ bool IsFullyReadable(TADDR addr, TSIZE_T size);
+
+ // Legacy target interfaces - optional
+ ICLRDataTarget * m_pLegacyTarget;
+ ICLRDataTarget2 * m_pLegacyTarget2;
+ ICLRDataTarget3 * m_pLegacyTarget3;
+ IXCLRDataTarget3 * m_target3;
+ ICLRMetadataLocator * m_legacyMetaDataLocator;
+
+ LONG m_refs;
+ HRESULT m_memStatus;
+ MDImportsCache m_mdImports;
+ ICLRDataEnumMemoryRegionsCallback* m_enumMemCb;
+ ICLRDataEnumMemoryRegionsCallback2* m_updateMemCb;
+ CLRDataEnumMemoryFlags m_enumMemFlags;
+ JITNotification* m_jitNotificationTable;
+ GcNotification* m_gcNotificationTable;
+ TSIZE_T m_cbMemoryReported;
+ DumpMemoryReportStatics m_dumpStats;
+
+ // If true, inconsistencies in the target will cause ASSERTs to be raised in DEBUG builds
+ bool m_fEnableTargetConsistencyAsserts;
+
+#ifdef _DEBUG
+protected:
+ // If true, a mscorwks/mscordacwks mismatch will trigger a nice assert dialog
+ bool m_fEnableDllVerificationAsserts;
+private:
+#endif
+
+#ifdef FEATURE_COMINTEROP
+protected:
+ // Returns CCW pointer based on a target address.
+ PTR_ComCallWrapper DACGetCCWFromAddress(CLRDATA_ADDRESS addr);
+
+private:
+ // Returns COM interface pointer corresponding to a given CCW and internal vtable
+ // index. Returns NULL if the vtable is unused or not fully laid out.
+ PTR_IUnknown DACGetCOMIPFromCCW(PTR_ComCallWrapper pCCW, int vtableIndex);
+#endif
+
+ static LONG s_procInit;
+
+public:
+ // APIs for picking up the info needed for a debugger to look up an ngen image or IL image
+ // from it's search path.
+ static bool GetMetaDataFileInfoFromPEFile(PEFile *pPEFile,
+ DWORD &dwImageTimestamp,
+ DWORD &dwImageSize,
+ DWORD &dwDataSize,
+ DWORD &dwRvaHint,
+ bool &isNGEN,
+ __out_ecount(cchFilePath) LPWSTR wszFilePath,
+ DWORD cchFilePath);
+
+ static bool GetILImageInfoFromNgenPEFile(PEFile *peFile,
+ DWORD &dwTimeStamp,
+ DWORD &dwSize,
+ __out_ecount(cchPath) LPWSTR wszPath,
+ const DWORD cchPath);
+#if defined(FEATURE_CORESYSTEM)
+ static bool GetILImageNameFromNgenImage(LPCWSTR ilExtension,
+ __out_ecount(cchFilePath) LPWSTR wszFilePath,
+ const DWORD cchFilePath);
+#endif // FEATURE_CORESYSTEM
+};
+
+extern ClrDataAccess* g_dacImpl;
+
+/* DacHandleWalker.
+ *
+ * Iterates over the handle table, enumerating all handles of the requested type on the
+ * handle table. This also will report the handle type, whether the handle is a strong
+ * reference, the AppDomain the handle comes from, as well as the reference count (in
+ * the case of a RefCount handle). Optionally this class can also be used to filter
+ * based on GC generation that would be collected (that is, to emulate a GC scan of the
+ * handle table).
+ *
+ * General implementation details:
+ * We have four sets of variables:
+ * 1. Overhead variables needed to operate in the Dac.
+ * 2. Variables needed to walk the handle table. We walk the handle table one bucket
+ * at a time, filling the array the user gave us until we have either enumerated
+ * all handles, or filled the array.
+ * 3. Storage variables to hold the overflow. That is, we were walking the handle
+ * table, filled the array that the user gave us, then needed to store the extra
+ * handles the handle table continued to enumerate to us. This is implmeneted
+ * as a linked list of arrays (mHead, mHead.Next, etc).
+ * 4. Variables which store the location of where we are in the overflow data.
+ *
+ * Note that "mHead" is a HandleChunkHead where we stuff the user's array. Everything
+ * which follows mHead (mHead.Next, etc) is a HandleChunk containing overflow data.
+ *
+ * Lastly, note this does not do robust error handling. If we fail to allocate a
+ * HandleChunk while walking the handle table, we will miss handles and not report
+ * this to the user. Unfortunately this will have to be fixed in the next iteration
+ * when we add more robust error handling to SOS's interface.
+ */
+ template <class T>
+class DefaultCOMImpl : public T
+{
+public:
+ DefaultCOMImpl()
+ : mRef(0)
+ {
+ }
+
+ virtual ~DefaultCOMImpl() {}
+
+ ULONG STDMETHODCALLTYPE AddRef()
+ {
+ return ++mRef;
+ }
+
+ ULONG STDMETHODCALLTYPE Release()
+ {
+ ULONG res = mRef--;
+ if (res == 0)
+ delete this;
+ return res;
+ }
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppObj)
+ {
+ if (ppObj == NULL)
+ return E_INVALIDARG;
+
+ if (IsEqualIID(riid, IID_IUnknown))
+ {
+ AddRef();
+ *ppObj = static_cast<IUnknown*>(this);
+ return S_OK;
+ }
+ else if (IsEqualIID(riid, __uuidof(T)))
+ {
+ AddRef();
+ *ppObj = static_cast<T*>(this);
+ return S_OK;
+ }
+
+ *ppObj = NULL;
+ return E_NOINTERFACE;
+ }
+
+private:
+ ULONG mRef;
+};
+
+
+// A stuct representing a thread's allocation context.
+struct AllocInfo
+{
+ CORDB_ADDRESS Ptr;
+ CORDB_ADDRESS Limit;
+
+ AllocInfo()
+ : Ptr(0), Limit(0)
+ {
+ }
+};
+
+// A struct representing a segment in the heap.
+struct SegmentData
+{
+ CORDB_ADDRESS Start;
+ CORDB_ADDRESS End;
+
+ // Whether this segment is part of the large object heap.
+ int Generation;
+
+ SegmentData()
+ : Start(0), End(0), Generation(0)
+ {
+ }
+};
+
+// A struct representing a gc heap in the process.
+struct HeapData
+{
+ CORDB_ADDRESS YoungestGenPtr;
+ CORDB_ADDRESS YoungestGenLimit;
+
+ CORDB_ADDRESS Gen0Start;
+ CORDB_ADDRESS Gen0End;
+
+ CORDB_ADDRESS Gen1Start;
+ size_t EphemeralSegment;
+
+ size_t SegmentCount;
+ SegmentData *Segments;
+
+ HeapData();
+ ~HeapData();
+};
+
+/* This cache is used to read data from the target process if the reads are known
+ * to be sequential. This will object will read one page of memory out of the
+ * process at a time, aligned to the page boundary, to
+ */
+class LinearReadCache
+{
+public:
+ LinearReadCache();
+ ~LinearReadCache();
+
+ /* Reads an address out of the target process, caching the page of memory read.
+ * Params:
+ * addr - The address to read out of the target process.
+ * t - A pointer to the data to stuff it in. We will read sizeof(T) data
+ * from the process and write it into the location t points to. This
+ * parameter must be non-null.
+ * Returns:
+ * True if the read succeeded. False if it did not, usually as a result
+ * of the memory simply not being present in the target process.
+ * Note:
+ * The state of *t is undefined if this function returns false. We may
+ * have written partial data to it if we return false, so you must
+ * absolutely NOT use it if Read returns false.
+ */
+ template <class T>
+ bool Read(CORDB_ADDRESS addr, T *t)
+ {
+ _ASSERTE(t);
+
+ // Unfortunately the ctor can fail the alloc for the byte array. In this case
+ // we'll just fall back to non-cached reads.
+ if (mPage == NULL)
+ return MisalignedRead(addr, t);
+
+ // Is addr on the current page? If not read the page of memory addr is on.
+ // If this fails, we will fall back to a raw read out of the process (which
+ // is what MisalignedRead does).
+ if ((addr < mCurrPageStart) || (addr - mCurrPageStart > mCurrPageSize))
+ if (!MoveToPage(addr))
+ return MisalignedRead(addr, t);
+
+ // If MoveToPage succeeds, we MUST be on the right page.
+ _ASSERTE(addr >= mCurrPageStart);
+
+ // However, the amount of data requested may fall off of the page. In that case,
+ // fall back to MisalignedRead.
+ CORDB_ADDRESS offset = addr - mCurrPageStart;
+ if (offset + sizeof(T) > mCurrPageSize)
+ return MisalignedRead(addr, t);
+
+ // If we reach here we know we are on the right page of memory in the cache, and
+ // that the read won't fall off of the end of the page.
+ *t = *reinterpret_cast<T*>(mPage+offset);
+ return true;
+ }
+
+ // helper used to read the MethodTable
+ bool ReadMT(CORDB_ADDRESS addr, TADDR *mt)
+ {
+ if (!Read(addr, mt))
+ return false;
+
+ // clear the GC flag bits off the MethodTable
+ // equivalent to Object::GetGCSafeMethodTable()
+ *mt &= ~3;
+ return true;
+ }
+
+private:
+ /* Sets the cache to the page specified by addr, or false if we could not move to
+ * that page.
+ */
+ bool MoveToPage(CORDB_ADDRESS addr);
+
+ /* Attempts to read from the target process if the data is possibly hanging off
+ * the end of a page.
+ */
+ template<class T>
+ inline bool MisalignedRead(CORDB_ADDRESS addr, T *t)
+ {
+ return SUCCEEDED(DacReadAll(TO_TADDR(addr), t, sizeof(T), false));
+ }
+
+private:
+ CORDB_ADDRESS mCurrPageStart;
+ ULONG32 mPageSize, mCurrPageSize;
+ BYTE *mPage;
+};
+
+DWORD DacGetNumHeaps();
+
+/* The implementation of the dac heap walker. This class will enumerate all objects on
+ * the heap with three important caveats:
+ * - This class will skip all Free objects in the heap. Free objects are an
+ * implementation detail of the GC, and ICorDebug does not have a mechanism
+ * to expose them.
+ * - This class does NOT guarantee that all objects will be enumerated. In
+ * the event that we find heap corruption on a segment, or if the background
+ * GC is modifying a segment, the remainder of that segment will be skipped
+ * by design.
+ * - The GC heap must be in a walkable state before you attempt to use this
+ * class on it. The IDacDbiInterface::AreGCStructuresValid function will
+ * tell you whether it is safe to walk the heap or not.
+ */
+class DacHeapWalker
+{
+ static CORDB_ADDRESS HeapStart;
+ static CORDB_ADDRESS HeapEnd;
+
+public:
+ DacHeapWalker();
+ ~DacHeapWalker();
+
+ /* Initializes the heap walker. This must be called before Next or
+ * HasMoreObjects. Returns false if the initialization was not successful.
+ * (In practice this should only return false if we hit an OOM trying
+ * to allocate space for data structures.) Limits the heap walk to be in the range
+ * [start, end] (inclusive). Use DacHeapWalker::HeapStart, DacHeapWalker::HeapEnd
+ * as start or end to start from the beginning or end.
+ */
+ HRESULT Init(CORDB_ADDRESS start=HeapStart, CORDB_ADDRESS end=HeapEnd);
+
+ /* Returns a CORDB_ADDRESS which points to the next value on the heap.
+ * You must call HasMoreObjects on this class, and it must return true
+ * before calling Next.
+ */
+ HRESULT Next(CORDB_ADDRESS *pValue, CORDB_ADDRESS *pMT, ULONG64 *size);
+
+ /* Returns true if there are more objects on the heap, false otherwise.
+ */
+ inline bool HasMoreObjects() const
+ {
+ return mCurrHeap < mHeapCount;
+ }
+
+ HRESULT Reset(CORDB_ADDRESS start, CORDB_ADDRESS end);
+
+ static HRESULT InitHeapDataWks(HeapData *&pHeaps, size_t &count);
+ static HRESULT InitHeapDataSvr(HeapData *&pHeaps, size_t &count);
+
+ HRESULT GetHeapData(HeapData **ppHeapData, size_t *pNumHeaps);
+
+ SegmentData *FindSegment(CORDB_ADDRESS obj);
+
+ HRESULT ListNearObjects(CORDB_ADDRESS obj, CORDB_ADDRESS *pPrev, CORDB_ADDRESS *pContaining, CORDB_ADDRESS *pNext);
+
+private:
+ HRESULT MoveToNextObject();
+
+ bool GetSize(TADDR tMT, size_t &size);
+
+ inline static size_t Align(size_t size)
+ {
+ if (sizeof(TADDR) == 4)
+ return (size+3) & ~3;
+ else
+ return (size+7) & ~7;
+ }
+
+ inline static size_t AlignLarge(size_t size)
+ {
+ return (size + 7) & ~7;
+ }
+
+ template <class T>
+ static int GetSegmentCount(T seg_start)
+ {
+ int count = 0;
+ while (seg_start)
+ {
+ // If we find this many segments, something is seriously wrong.
+ if (count++ > 4096)
+ break;
+
+ seg_start = seg_start->next;
+ }
+
+ return count;
+ }
+
+ HRESULT NextSegment();
+ void CheckAllocAndSegmentRange();
+
+private:
+ int mThreadCount;
+ AllocInfo *mAllocInfo;
+
+ size_t mHeapCount;
+ HeapData *mHeaps;
+
+ CORDB_ADDRESS mCurrObj;
+ size_t mCurrSize;
+ TADDR mCurrMT;
+
+ size_t mCurrHeap;
+ size_t mCurrSeg;
+
+ CORDB_ADDRESS mStart;
+ CORDB_ADDRESS mEnd;
+
+ LinearReadCache mCache;
+ static CORDB_ADDRESS sFreeMT;
+};
+
+struct DacGcReference;
+struct SOSStackErrorList
+{
+ SOSStackRefError error;
+ SOSStackErrorList *pNext;
+
+ SOSStackErrorList()
+ : pNext(0)
+ {
+ }
+};
+
+class DacStackReferenceWalker;
+class DacStackReferenceErrorEnum : public DefaultCOMImpl<ISOSStackRefErrorEnum>
+{
+public:
+ DacStackReferenceErrorEnum(DacStackReferenceWalker *pEnum, SOSStackErrorList *pErrors);
+ ~DacStackReferenceErrorEnum();
+
+ HRESULT STDMETHODCALLTYPE Skip(unsigned int count);
+ HRESULT STDMETHODCALLTYPE Reset();
+ HRESULT STDMETHODCALLTYPE GetCount(unsigned int *pCount);
+ HRESULT STDMETHODCALLTYPE Next(unsigned int count, SOSStackRefError ref[], unsigned int *pFetched);
+
+private:
+ // The lifetime of the error list is tied to the enum, so we must addref/release it.
+ DacStackReferenceWalker *mEnum;
+ SOSStackErrorList *mHead;
+ SOSStackErrorList *mCurr;
+};
+
+// For GCCONTEXT
+#include "gcenv.h"
+
+ /* DacStackReferenceWalker.
+ */
+class DacStackReferenceWalker : public DefaultCOMImpl<ISOSStackRefEnum>
+{
+ struct DacScanContext : public ScanContext
+ {
+ DacStackReferenceWalker *pWalker;
+ Frame *pFrame;
+ TADDR sp, pc;
+ bool stop;
+ GCEnumCallback pEnumFunc;
+
+ DacScanContext()
+ : pWalker(NULL), pFrame(0), sp(0), pc(0), stop(false), pEnumFunc(0)
+ {
+ }
+ };
+
+ typedef struct _StackRefChunkHead
+ {
+ struct _StackRefChunkHead *next; // Next chunk
+ unsigned int count; // The count of how many StackRefs were written to pData
+ unsigned int size; // The capacity of pData (in bytes)
+ void *pData; // The overflow data
+
+ _StackRefChunkHead()
+ : next(0), count(0), size(0), pData(0)
+ {
+ }
+ } StackRefChunkHead;
+
+ // The actual struct used for storing overflow StackRefs
+ typedef struct _StackRefChunk : public StackRefChunkHead
+ {
+ SOSStackRefData data[64];
+
+ _StackRefChunk()
+ {
+ pData = data;
+ size = sizeof(data);
+ }
+ } StackRefChunk;
+public:
+ DacStackReferenceWalker(ClrDataAccess *dac, DWORD osThreadID);
+ virtual ~DacStackReferenceWalker();
+
+ HRESULT Init();
+
+ HRESULT STDMETHODCALLTYPE Skip(unsigned int count);
+ HRESULT STDMETHODCALLTYPE Reset();
+ HRESULT STDMETHODCALLTYPE GetCount(unsigned int *pCount);
+ HRESULT STDMETHODCALLTYPE Next(unsigned int count,
+ SOSStackRefData refs[],
+ unsigned int *pFetched);
+
+ // Dac-Dbi Functions
+ HRESULT Next(ULONG celt, DacGcReference roots[], ULONG *pceltFetched);
+ Thread *GetThread() const
+ {
+ return mThread;
+ }
+
+ HRESULT STDMETHODCALLTYPE EnumerateErrors(ISOSStackRefErrorEnum **ppEnum);
+
+private:
+ static StackWalkAction Callback(CrawlFrame *pCF, VOID *pData);
+ static void GCEnumCallbackSOS(LPVOID hCallback, OBJECTREF *pObject, uint32_t flags, DacSlotLocation loc);
+ static void GCReportCallbackSOS(PTR_PTR_Object ppObj, ScanContext *sc, uint32_t flags);
+ static void GCEnumCallbackDac(LPVOID hCallback, OBJECTREF *pObject, uint32_t flags, DacSlotLocation loc);
+ static void GCReportCallbackDac(PTR_PTR_Object ppObj, ScanContext *sc, uint32_t flags);
+
+ CLRDATA_ADDRESS ReadPointer(TADDR addr);
+
+ template <class StructType>
+ StructType *GetNextObject(DacScanContext *ctx)
+ {
+ SUPPORTS_DAC;
+
+ // If we failed on a previous call (OOM) don't keep trying to allocate, it's not going to work.
+ if (ctx->stop || !mCurr)
+ return NULL;
+
+ // We've moved past the size of the current chunk. We'll allocate a new chunk
+ // and stuff the references there. These are cleaned up by the destructor.
+ if (mCurr->count >= mCurr->size/sizeof(StructType))
+ {
+ if (mCurr->next == NULL)
+ {
+ StackRefChunk *next = new (nothrow) StackRefChunk;
+ if (next != NULL)
+ {
+ mCurr->next = next;
+ }
+ else
+ {
+ ctx->stop = true;
+ return NULL;
+ }
+ }
+
+ mCurr = mCurr->next;
+ }
+
+ // Fill the current ref.
+ StructType *pData = (StructType*)mCurr->pData;
+ return &pData[mCurr->count++];
+ }
+
+
+ template <class IntType, class StructType>
+ IntType WalkStack(IntType count, StructType refs[], promote_func promote, GCEnumCallback enumFunc)
+ {
+ _ASSERTE(mThread);
+ _ASSERTE(!mEnumerated);
+
+ // If this is the first time we were called, fill local data structures.
+ // This will fill out the user's handles as well.
+ _ASSERTE(mCurr == NULL);
+ _ASSERTE(mHead.next == NULL);
+
+ // Get the current thread's context and set that as the filter context
+ if (mThread->GetFilterContext() == NULL && mThread->GetProfilerFilterContext() == NULL)
+ {
+ T_CONTEXT ctx;
+ mDac->m_pTarget->GetThreadContext(mThread->GetOSThreadId(), CONTEXT_FULL, sizeof(ctx), (BYTE*)&ctx);
+ mThread->SetProfilerFilterContext(&ctx);
+ }
+
+ // Setup GCCONTEXT structs for the stackwalk.
+ GCCONTEXT gcctx;
+ DacScanContext dsc;
+ dsc.pWalker = this;
+ dsc.pEnumFunc = enumFunc;
+ gcctx.f = promote;
+ gcctx.sc = &dsc;
+
+ // Put the user's array/count in the
+ mHead.size = count*sizeof(StructType);
+ mHead.pData = refs;
+ mHead.count = 0;
+
+ mCurr = &mHead;
+
+ // Walk the stack, set mEnumerated to true to ensure we don't do it again.
+ unsigned int flagsStackWalk = ALLOW_INVALID_OBJECTS|ALLOW_ASYNC_STACK_WALK;
+#if defined(WIN64EXCEPTIONS)
+ flagsStackWalk |= GC_FUNCLET_REFERENCE_REPORTING;
+#endif // defined(WIN64EXCEPTIONS)
+
+ mEnumerated = true;
+ mThread->StackWalkFrames(DacStackReferenceWalker::Callback, &gcctx, flagsStackWalk);
+
+ // We have filled the user's array as much as we could. If there's more data than
+ // could fit, mHead.Next will contain a linked list of refs to enumerate.
+ mCurr = mHead.next;
+
+ // Return how many we put in the user's array.
+ return mHead.count;
+ }
+
+ template <class IntType, class StructType, promote_func PromoteFunc, GCEnumCallback EnumFunc>
+ HRESULT DoStackWalk(IntType count, StructType stackRefs[], IntType *pFetched)
+ {
+ HRESULT hr = S_OK;
+ IntType fetched = 0;
+ if (!mEnumerated)
+ {
+ // If this is the first time we were called, fill local data structures.
+ // This will fill out the user's handles as well.
+ fetched = (IntType)WalkStack((unsigned int)count, stackRefs, PromoteFunc, EnumFunc);
+ }
+
+ while (fetched < count)
+ {
+ if (mCurr == NULL)
+ {
+ // Case 1: We have no more refs to walk.
+ hr = S_FALSE;
+ break;
+ }
+ else if (mChunkIndex >= mCurr->count)
+ {
+ // Case 2: We have exhausted the current chunk.
+ mCurr = mCurr->next;
+ mChunkIndex = 0;
+ }
+ else
+ {
+ // Case 3: The last call to "Next" filled the user's array and had some ref
+ // data leftover. Walk the linked-list of arrays copying them into the user's
+ // buffer until we have either exhausted the user's array or the leftover data.
+ IntType toCopy = count - fetched; // Fill the user's buffer...
+
+ // ...unless that would go past the bounds of the current chunk.
+ if (toCopy + mChunkIndex > mCurr->count)
+ toCopy = mCurr->count - mChunkIndex;
+
+ memcpy(stackRefs+fetched, (StructType*)mCurr->pData+mChunkIndex, toCopy*sizeof(StructType));
+ mChunkIndex += toCopy;
+ fetched += toCopy;
+ }
+ }
+
+ *pFetched = fetched;
+
+ return hr;
+ }
+
+private:
+ // Dac variables required for entering/leaving the dac.
+ ClrDataAccess *mDac;
+ ULONG32 m_instanceAge;
+
+ // Operational variables
+ Thread *mThread;
+ SOSStackErrorList *mErrors;
+ bool mEnumerated;
+
+ // Storage variables
+ StackRefChunkHead mHead;
+ unsigned int mChunkIndex;
+
+ // Iterator variables
+ StackRefChunkHead *mCurr;
+ int mIteratorIndex;
+
+ // Heap. Used to resolve interior pointers.
+ DacHeapWalker mHeap;
+};
+
+
+
+struct DacGcReference;
+class DacHandleWalker : public DefaultCOMImpl<ISOSHandleEnum>
+{
+ typedef struct _HandleChunkHead
+ {
+ struct _HandleChunkHead *Next; // Next chunk
+ unsigned int Count; // The count of how many handles were written to pData
+ unsigned int Size; // The capacity of pData
+ void *pData; // The overflow data
+
+ _HandleChunkHead()
+ : Next(0), Count(0), Size(0), pData(0)
+ {
+ }
+ } HandleChunkHead;
+
+ // The actual struct used for storing overflow handles
+ typedef struct _HandleChunk : public HandleChunkHead
+ {
+ SOSHandleData Data[128];
+
+ _HandleChunk()
+ {
+ pData = Data;
+ Size = sizeof(Data);
+ }
+ } HandleChunk;
+
+ // Parameter used in HndEnumHandles callback.
+ struct DacHandleWalkerParam
+ {
+ HandleChunkHead *Curr; // The current chunk to write to
+ HRESULT Result; // HRESULT of the current enumeration
+ CLRDATA_ADDRESS AppDomain; // The AppDomain for the current bucket we are walking
+ unsigned int Type; // The type of handle we are currently walking
+
+ DacHandleWalkerParam(HandleChunk *curr)
+ : Curr(curr), Result(S_OK), AppDomain(0), Type(0)
+ {
+ }
+ };
+
+public:
+ DacHandleWalker();
+ virtual ~DacHandleWalker();
+
+ HRESULT Init(ClrDataAccess *dac, UINT types[], UINT typeCount);
+ HRESULT Init(ClrDataAccess *dac, UINT types[], UINT typeCount, int gen);
+ HRESULT Init(UINT32 typemask);
+
+ // SOS functions
+ HRESULT STDMETHODCALLTYPE Skip(unsigned int count);
+ HRESULT STDMETHODCALLTYPE Reset();
+ HRESULT STDMETHODCALLTYPE GetCount(unsigned int *pCount);
+ HRESULT STDMETHODCALLTYPE Next(unsigned int count,
+ SOSHandleData handles[],
+ unsigned int *pNeeded);
+
+ // Dac-Dbi Functions
+ HRESULT Next(ULONG celt, DacGcReference roots[], ULONG *pceltFetched);
+private:
+ static void CALLBACK EnumCallback(PTR_UNCHECKED_OBJECTREF pref, LPARAM *pExtraInfo, LPARAM userParam, LPARAM type);
+ static void GetRefCountedHandleInfo(
+ OBJECTREF oref, unsigned int uType,
+ unsigned int *pRefCount, unsigned int *pJupiterRefCount, BOOL *pIsPegged, BOOL *pIsStrong);
+ static UINT32 BuildTypemask(UINT types[], UINT typeCount);
+
+private:
+ static void CALLBACK EnumCallbackSOS(PTR_UNCHECKED_OBJECTREF pref, uintptr_t *pExtraInfo, uintptr_t userParam, uintptr_t type);
+ static void CALLBACK EnumCallbackDac(PTR_UNCHECKED_OBJECTREF pref, uintptr_t *pExtraInfo, uintptr_t userParam, uintptr_t type);
+
+ bool FetchMoreHandles(HANDLESCANPROC proc);
+ static inline bool IsAlwaysStrongReference(unsigned int type)
+ {
+ return type == HNDTYPE_STRONG || type == HNDTYPE_PINNED || type == HNDTYPE_ASYNCPINNED || type == HNDTYPE_SIZEDREF;
+ }
+
+ template <class StructType, class IntType, HANDLESCANPROC EnumFunc>
+ HRESULT DoHandleWalk(IntType celt, StructType handles[], IntType *pceltFetched)
+ {
+ SUPPORTS_DAC;
+
+ if (handles == NULL || pceltFetched == NULL)
+ return E_POINTER;
+
+ HRESULT hr = S_OK;
+ IntType fetched = 0;
+ bool done = false;
+
+ // On each iteration of the loop, either fetch more handles (filling in
+ // the user's data structure), or copy handles from previous calls to
+ // FetchMoreHandles which we could not store in the user's data (or simply
+ // advance the current chunk to the next chunk).
+ while (fetched < celt)
+ {
+ if (mCurr == NULL)
+ {
+ // Case 1: We have no overflow data. Stuff the user's array/size into
+ // mHead, fetch more handles. Additionally, if the previous call to
+ // FetchMoreHandles returned false (mMap == NULL), break.
+ if (mMap == NULL)
+ break;
+
+ mHead.pData = handles+fetched;
+ mHead.Size = (celt - fetched)*sizeof(StructType);
+
+ done = !FetchMoreHandles(EnumFunc);
+ fetched += mHead.Count;
+
+ // Sanity check to make sure we haven't overflowed. This should not happen.
+ _ASSERTE(fetched <= celt);
+ }
+ else if (mChunkIndex >= mCurr->Count)
+ {
+ // Case 2: We have overflow data, but the current index into the current
+ // chunk is past the bounds. Move to the next. This could set mCurr to
+ // null, which we'll catch on the next iteration.
+ mCurr = mCurr->Next;
+ mChunkIndex = 0;
+ }
+ else
+ {
+ // Case 3: The last call to "Next" filled the user's array and had some handle
+ // data leftover. Walk the linked-list of arrays copying them into the user's
+ // buffer until we have either exhausted the user's array or the leftover data.
+ unsigned int toCopy = celt - fetched; // Fill the user's buffer...
+
+ // ...unless that would go past the bounds of the current chunk.
+ if (toCopy + mChunkIndex > mCurr->Count)
+ toCopy = mCurr->Count - mChunkIndex;
+
+ memcpy(handles+fetched, ((StructType*)(mCurr->pData))+mChunkIndex, toCopy*sizeof(StructType));
+ mChunkIndex += toCopy;
+ fetched += toCopy;
+ }
+ }
+
+ if (fetched < celt)
+ hr = S_FALSE;
+
+ *pceltFetched = fetched;
+
+ return hr;
+ }
+
+private:
+ // Dac variables required for entering/leaving the dac.
+ ClrDataAccess *mDac;
+ ULONG32 m_instanceAge;
+
+ // Handle table walking variables.
+ HandleTableMap *mMap;
+ int mIndex;
+ UINT32 mTypeMask;
+ int mGenerationFilter;
+
+ // Storage variables
+ HandleChunk mHead;
+ unsigned int mChunkIndex;
+
+ // Iterator variables
+ HandleChunkHead *mCurr;
+ int mIteratorIndex;
+};
+
+
+//----------------------------------------------------------------------------
+//
+// ClrDataAppDomain.
+//
+//----------------------------------------------------------------------------
+
+class ClrDataAppDomain : public IXCLRDataAppDomain
+{
+public:
+ ClrDataAppDomain(ClrDataAccess* dac,
+ AppDomain* appDomain);
+ virtual ~ClrDataAppDomain(void);
+
+ // IUnknown.
+ STDMETHOD(QueryInterface)(THIS_
+ IN REFIID interfaceId,
+ OUT PVOID* iface);
+ STDMETHOD_(ULONG, AddRef)(THIS);
+ STDMETHOD_(ULONG, Release)(THIS);
+
+ //
+ // IXCLRDataAppDomain.
+ //
+
+ virtual HRESULT STDMETHODCALLTYPE GetProcess(
+ /* [out] */ IXCLRDataProcess **process);
+
+ virtual HRESULT STDMETHODCALLTYPE GetName(
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR name[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE GetUniqueID(
+ /* [out] */ ULONG64 *id);
+
+ virtual HRESULT STDMETHODCALLTYPE GetFlags(
+ /* [out] */ ULONG32 *flags);
+
+ virtual HRESULT STDMETHODCALLTYPE IsSameObject(
+ /* [in] */ IXCLRDataAppDomain *appDomain);
+
+ virtual HRESULT STDMETHODCALLTYPE GetManagedObject(
+ /* [out] */ IXCLRDataValue **value);
+
+ virtual HRESULT STDMETHODCALLTYPE Request(
+ /* [in] */ ULONG32 reqCode,
+ /* [in] */ ULONG32 inBufferSize,
+ /* [size_is][in] */ BYTE *inBuffer,
+ /* [in] */ ULONG32 outBufferSize,
+ /* [size_is][out] */ BYTE *outBuffer);
+
+ AppDomain* GetAppDomain(void)
+ {
+ SUPPORTS_DAC;
+ return m_appDomain;
+ }
+
+private:
+ LONG m_refs;
+ ClrDataAccess* m_dac;
+ ULONG32 m_instanceAge;
+ AppDomain* m_appDomain;
+};
+
+//----------------------------------------------------------------------------
+//
+// ClrDataAssembly.
+//
+//----------------------------------------------------------------------------
+
+class ClrDataAssembly : public IXCLRDataAssembly
+{
+public:
+ ClrDataAssembly(ClrDataAccess* dac,
+ Assembly* assembly);
+ virtual ~ClrDataAssembly(void);
+
+ // IUnknown.
+ STDMETHOD(QueryInterface)(THIS_
+ IN REFIID interfaceId,
+ OUT PVOID* iface);
+ STDMETHOD_(ULONG, AddRef)(THIS);
+ STDMETHOD_(ULONG, Release)(THIS);
+
+ //
+ // IXCLRDataAssembly.
+ //
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumModules(
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumModule(
+ /* [in, out] */ CLRDATA_ENUM* handle,
+ /* [out] */ IXCLRDataModule **mod);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumModules(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumAppDomains(
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumAppDomain(
+ /* [in, out] */ CLRDATA_ENUM* handle,
+ /* [out] */ IXCLRDataAppDomain **appDomain);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumAppDomains(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE GetName(
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR name[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE GetFileName(
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR name[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE GetDisplayName(
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR name[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE GetFlags(
+ /* [out] */ ULONG32 *flags);
+
+ virtual HRESULT STDMETHODCALLTYPE IsSameObject(
+ /* [in] */ IXCLRDataAssembly *assembly);
+
+ virtual HRESULT STDMETHODCALLTYPE Request(
+ /* [in] */ ULONG32 reqCode,
+ /* [in] */ ULONG32 inBufferSize,
+ /* [size_is][in] */ BYTE *inBuffer,
+ /* [in] */ ULONG32 outBufferSize,
+ /* [size_is][out] */ BYTE *outBuffer);
+
+private:
+ LONG m_refs;
+ ClrDataAccess* m_dac;
+ ULONG32 m_instanceAge;
+ Assembly* m_assembly;
+};
+
+//----------------------------------------------------------------------------
+//
+// ClrDataModule.
+//
+//----------------------------------------------------------------------------
+
+class ClrDataModule : public IXCLRDataModule, IXCLRDataModule2
+{
+public:
+ ClrDataModule(ClrDataAccess* dac,
+ Module* module);
+ virtual ~ClrDataModule(void);
+
+ // IUnknown.
+ STDMETHOD(QueryInterface)(THIS_
+ IN REFIID interfaceId,
+ OUT PVOID* iface);
+ STDMETHOD_(ULONG, AddRef)(THIS);
+ STDMETHOD_(ULONG, Release)(THIS);
+
+ //
+ // IXCLRDataModule.
+ //
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumAssemblies(
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumAssembly(
+ /* [in, out] */ CLRDATA_ENUM* handle,
+ /* [out] */ IXCLRDataAssembly **assembly);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumAssemblies(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumAppDomains(
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumAppDomain(
+ /* [in, out] */ CLRDATA_ENUM* handle,
+ /* [out] */ IXCLRDataAppDomain **appDomain);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumAppDomains(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumTypeDefinitions(
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumTypeDefinition(
+ /* [in, out] */ CLRDATA_ENUM* handle,
+ /* [out] */ IXCLRDataTypeDefinition **typeDefinition);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumTypeDefinitions(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumTypeInstances(
+ /* [in] */ IXCLRDataAppDomain* appDomain,
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumTypeInstance(
+ /* [in, out] */ CLRDATA_ENUM* handle,
+ /* [out] */ IXCLRDataTypeInstance **typeInstance);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumTypeInstances(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumTypeDefinitionsByName(
+ /* [in] */ LPCWSTR name,
+ /* [in] */ ULONG32 flags,
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumTypeDefinitionByName(
+ /* [out][in] */ CLRDATA_ENUM *handle,
+ /* [out] */ IXCLRDataTypeDefinition **type);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumTypeDefinitionsByName(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumTypeInstancesByName(
+ /* [in] */ LPCWSTR name,
+ /* [in] */ ULONG32 flags,
+ /* [in] */ IXCLRDataAppDomain *appDomain,
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumTypeInstanceByName(
+ /* [out][in] */ CLRDATA_ENUM *handle,
+ /* [out] */ IXCLRDataTypeInstance **type);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumTypeInstancesByName(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE GetTypeDefinitionByToken(
+ /* [in] */ mdTypeDef token,
+ /* [out] */ IXCLRDataTypeDefinition **typeDefinition);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumMethodDefinitionsByName(
+ /* [in] */ LPCWSTR name,
+ /* [in] */ ULONG32 flags,
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumMethodDefinitionByName(
+ /* [in] */ CLRDATA_ENUM* handle,
+ /* [out] */ IXCLRDataMethodDefinition **method);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumMethodDefinitionsByName(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumMethodInstancesByName(
+ /* [in] */ LPCWSTR name,
+ /* [in] */ ULONG32 flags,
+ /* [in] */ IXCLRDataAppDomain* appDomain,
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumMethodInstanceByName(
+ /* [in] */ CLRDATA_ENUM* handle,
+ /* [out] */ IXCLRDataMethodInstance **method);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumMethodInstancesByName(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE GetMethodDefinitionByToken(
+ /* [in] */ mdMethodDef token,
+ /* [out] */ IXCLRDataMethodDefinition **methodDefinition);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumDataByName(
+ /* [in] */ LPCWSTR name,
+ /* [in] */ ULONG32 flags,
+ /* [in] */ IXCLRDataAppDomain* appDomain,
+ /* [in] */ IXCLRDataTask* tlsTask,
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumDataByName(
+ /* [in] */ CLRDATA_ENUM* handle,
+ /* [out] */ IXCLRDataValue **value);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumDataByName(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE GetName(
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR name[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE GetFileName(
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part(bufLen, *nameLen) WCHAR name[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE GetVersionId(
+ /* [out] */ GUID* vid);
+
+ virtual HRESULT STDMETHODCALLTYPE GetFlags(
+ /* [out] */ ULONG32 *flags);
+
+ virtual HRESULT STDMETHODCALLTYPE IsSameObject(
+ /* [in] */ IXCLRDataModule *mod);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumExtents(
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumExtent(
+ /* [in, out] */ CLRDATA_ENUM* handle,
+ /* [out] */ CLRDATA_MODULE_EXTENT *extent);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumExtents(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE Request(
+ /* [in] */ ULONG32 reqCode,
+ /* [in] */ ULONG32 inBufferSize,
+ /* [size_is][in] */ BYTE *inBuffer,
+ /* [in] */ ULONG32 outBufferSize,
+ /* [size_is][out] */ BYTE *outBuffer);
+
+ HRESULT RequestGetModulePtr(IN ULONG32 inBufferSize,
+ IN BYTE* inBuffer,
+ IN ULONG32 outBufferSize,
+ OUT BYTE* outBuffer);
+
+ HRESULT RequestGetModuleData(IN ULONG32 inBufferSize,
+ IN BYTE* inBuffer,
+ IN ULONG32 outBufferSize,
+ OUT BYTE* outBuffer);
+
+ Module* GetModule(void)
+ {
+ return m_module;
+ }
+
+ //
+ // IXCLRDataModule2
+ //
+ virtual HRESULT STDMETHODCALLTYPE SetJITCompilerFlags(
+ /* [in] */ DWORD dwFlags );
+
+private:
+ // Returns an instance of IID_IMetaDataImport.
+ HRESULT GetMdInterface(PVOID* retIface);
+
+ LONG m_refs;
+ ClrDataAccess* m_dac;
+ ULONG32 m_instanceAge;
+ Module* m_module;
+ IMetaDataImport* m_mdImport;
+ bool m_setExtents;
+ CLRDATA_MODULE_EXTENT m_extents[2];
+ CLRDATA_MODULE_EXTENT* m_extentsEnd;
+};
+
+//----------------------------------------------------------------------------
+//
+// ClrDataTypeDefinition.
+//
+//----------------------------------------------------------------------------
+
+class ClrDataTypeDefinition : public IXCLRDataTypeDefinition
+{
+public:
+ ClrDataTypeDefinition(ClrDataAccess* dac,
+ Module* module,
+ mdTypeDef token,
+ TypeHandle typeHandle);
+ virtual ~ClrDataTypeDefinition(void);
+
+ // IUnknown.
+ STDMETHOD(QueryInterface)(THIS_
+ IN REFIID interfaceId,
+ OUT PVOID* iface);
+ STDMETHOD_(ULONG, AddRef)(THIS);
+ STDMETHOD_(ULONG, Release)(THIS);
+
+ //
+ // IXCLRDataTypeDefinition.
+ //
+
+ virtual HRESULT STDMETHODCALLTYPE GetModule(
+ /* [out] */ IXCLRDataModule **mod);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumMethodDefinitions(
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumMethodDefinition(
+ /* [in, out] */ CLRDATA_ENUM* handle,
+ /* [out] */ IXCLRDataMethodDefinition **methodDefinition);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumMethodDefinitions(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumMethodDefinitionsByName(
+ /* [in] */ LPCWSTR name,
+ /* [in] */ ULONG32 flags,
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumMethodDefinitionByName(
+ /* [in] */ CLRDATA_ENUM* handle,
+ /* [out] */ IXCLRDataMethodDefinition **method);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumMethodDefinitionsByName(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE GetMethodDefinitionByToken(
+ /* [in] */ mdMethodDef token,
+ /* [out] */ IXCLRDataMethodDefinition **methodDefinition);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumInstances(
+ /* [in] */ IXCLRDataAppDomain* appDomain,
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumInstance(
+ /* [out][in] */ CLRDATA_ENUM *handle,
+ /* [out] */ IXCLRDataTypeInstance **instance);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumInstances(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE GetNumFields(
+ /* [in] */ ULONG32 flags,
+ /* [out] */ ULONG32 *numFields);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumFields(
+ /* [in] */ ULONG32 flags,
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumField(
+ /* [out][in] */ CLRDATA_ENUM *handle,
+ /* [in] */ ULONG32 nameBufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part_opt(nameBufLen, *nameLen) WCHAR nameBuf[ ],
+ /* [out] */ IXCLRDataTypeDefinition **type,
+ /* [out] */ ULONG32 *flags,
+ /* [out] */ mdFieldDef *token);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumField2(
+ /* [out][in] */ CLRDATA_ENUM *handle,
+ /* [in] */ ULONG32 nameBufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part_opt(nameBufLen, *nameLen) WCHAR nameBuf[ ],
+ /* [out] */ IXCLRDataTypeDefinition **type,
+ /* [out] */ ULONG32 *flags,
+ /* [out] */ IXCLRDataModule** tokenScope,
+ /* [out] */ mdFieldDef *token);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumFields(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumFieldsByName(
+ /* [in] */ LPCWSTR name,
+ /* [in] */ ULONG32 nameFlags,
+ /* [in] */ ULONG32 fieldFlags,
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumFieldByName(
+ /* [out][in] */ CLRDATA_ENUM *handle,
+ /* [out] */ IXCLRDataTypeDefinition **type,
+ /* [out] */ ULONG32 *flags,
+ /* [out] */ mdFieldDef *token);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumFieldByName2(
+ /* [out][in] */ CLRDATA_ENUM *handle,
+ /* [out] */ IXCLRDataTypeDefinition **type,
+ /* [out] */ ULONG32 *flags,
+ /* [out] */ IXCLRDataModule** tokenScope,
+ /* [out] */ mdFieldDef *token);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumFieldsByName(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE GetFieldByToken(
+ /* [in] */ mdFieldDef token,
+ /* [in] */ ULONG32 nameBufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part_opt(nameBufLen, *nameLen) WCHAR nameBuf[ ],
+ /* [out] */ IXCLRDataTypeDefinition **type,
+ /* [out] */ ULONG32* flags);
+
+ virtual HRESULT STDMETHODCALLTYPE GetFieldByToken2(
+ /* [in] */ IXCLRDataModule* tokenScope,
+ /* [in] */ mdFieldDef token,
+ /* [in] */ ULONG32 nameBufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part_opt(nameBufLen, *nameLen) WCHAR nameBuf[ ],
+ /* [out] */ IXCLRDataTypeDefinition **type,
+ /* [out] */ ULONG32* flags);
+
+ virtual HRESULT STDMETHODCALLTYPE GetName(
+ /* [in] */ ULONG32 flags,
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR nameBuf[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE GetTokenAndScope(
+ /* [out] */ mdTypeDef *token,
+ /* [out] */ IXCLRDataModule **mod);
+
+ virtual HRESULT STDMETHODCALLTYPE GetCorElementType(
+ /* [out] */ CorElementType *type);
+
+ virtual HRESULT STDMETHODCALLTYPE GetFlags(
+ /* [out] */ ULONG32 *flags);
+
+ virtual HRESULT STDMETHODCALLTYPE GetBase(
+ /* [out] */ IXCLRDataTypeDefinition **base);
+
+ virtual HRESULT STDMETHODCALLTYPE IsSameObject(
+ /* [in] */ IXCLRDataTypeDefinition *type);
+
+ virtual HRESULT STDMETHODCALLTYPE Request(
+ /* [in] */ ULONG32 reqCode,
+ /* [in] */ ULONG32 inBufferSize,
+ /* [size_is][in] */ BYTE *inBuffer,
+ /* [in] */ ULONG32 outBufferSize,
+ /* [size_is][out] */ BYTE *outBuffer);
+
+ virtual HRESULT STDMETHODCALLTYPE GetArrayRank(
+ /* [out] */ ULONG32* rank);
+
+ virtual HRESULT STDMETHODCALLTYPE GetTypeNotification(
+ /* [out] */ ULONG32* flags);
+
+ virtual HRESULT STDMETHODCALLTYPE SetTypeNotification(
+ /* [in] */ ULONG32 flags);
+
+ static HRESULT NewFromModule(ClrDataAccess* dac,
+ Module* module,
+ mdTypeDef token,
+ ClrDataTypeDefinition** typeDef,
+ IXCLRDataTypeDefinition** pubTypeDef);
+
+ TypeHandle GetTypeHandle(void)
+ {
+ return m_typeHandle;
+ }
+
+private:
+ LONG m_refs;
+ ClrDataAccess* m_dac;
+ ULONG32 m_instanceAge;
+ Module* m_module;
+ mdTypeDef m_token;
+ TypeHandle m_typeHandle;
+};
+
+//----------------------------------------------------------------------------
+//
+// ClrDataTypeInstance.
+//
+//----------------------------------------------------------------------------
+
+class ClrDataTypeInstance : public IXCLRDataTypeInstance
+{
+public:
+ ClrDataTypeInstance(ClrDataAccess* dac,
+ AppDomain* appDomain,
+ TypeHandle typeHandle);
+ virtual ~ClrDataTypeInstance(void);
+
+ // IUnknown.
+ STDMETHOD(QueryInterface)(THIS_
+ IN REFIID interfaceId,
+ OUT PVOID* iface);
+ STDMETHOD_(ULONG, AddRef)(THIS);
+ STDMETHOD_(ULONG, Release)(THIS);
+
+ //
+ // IXCLRDataTypeInstance.
+ //
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumMethodInstances(
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumMethodInstance(
+ /* [in, out] */ CLRDATA_ENUM* handle,
+ /* [out] */ IXCLRDataMethodInstance **methodInstance);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumMethodInstances(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumMethodInstancesByName(
+ /* [in] */ LPCWSTR name,
+ /* [in] */ ULONG32 flags,
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumMethodInstanceByName(
+ /* [in] */ CLRDATA_ENUM* handle,
+ /* [out] */ IXCLRDataMethodInstance **method);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumMethodInstancesByName(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE GetNumStaticFields(
+ /* [out] */ ULONG32 *numFields);
+
+ virtual HRESULT STDMETHODCALLTYPE GetStaticFieldByIndex(
+ /* [in] */ ULONG32 index,
+ /* [in] */ IXCLRDataTask *tlsTask,
+ /* [out] */ IXCLRDataValue **field,
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR nameBuf[ ],
+ /* [out] */ mdFieldDef *token);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumStaticFieldsByName(
+ /* [in] */ LPCWSTR name,
+ /* [in] */ ULONG32 flags,
+ /* [in] */ IXCLRDataTask *tlsTask,
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumStaticFieldByName(
+ /* [out][in] */ CLRDATA_ENUM *handle,
+ /* [out] */ IXCLRDataValue **value);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumStaticFieldsByName(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE GetNumStaticFields2(
+ /* [in] */ ULONG32 flags,
+ /* [out] */ ULONG32 *numFields);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumStaticFields(
+ /* [in] */ ULONG32 flags,
+ /* [in] */ IXCLRDataTask *tlsTask,
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumStaticField(
+ /* [out][in] */ CLRDATA_ENUM *handle,
+ /* [out] */ IXCLRDataValue **value);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumStaticField2(
+ /* [out][in] */ CLRDATA_ENUM *handle,
+ /* [out] */ IXCLRDataValue **value,
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR nameBuf[ ],
+ /* [out] */ IXCLRDataModule** tokenScope,
+ /* [out] */ mdFieldDef *token);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumStaticFields(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumStaticFieldsByName2(
+ /* [in] */ LPCWSTR name,
+ /* [in] */ ULONG32 nameFlags,
+ /* [in] */ ULONG32 fieldFlags,
+ /* [in] */ IXCLRDataTask *tlsTask,
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumStaticFieldByName3(
+ /* [out][in] */ CLRDATA_ENUM *handle,
+ /* [out] */ IXCLRDataValue **value,
+ /* [out] */ IXCLRDataModule** tokenScope,
+ /* [out] */ mdFieldDef *token);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumStaticFieldByName2(
+ /* [out][in] */ CLRDATA_ENUM *handle,
+ /* [out] */ IXCLRDataValue **value);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumStaticFieldsByName2(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE GetStaticFieldByToken(
+ /* [in] */ mdFieldDef token,
+ /* [in] */ IXCLRDataTask *tlsTask,
+ /* [out] */ IXCLRDataValue **field,
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR nameBuf[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE GetStaticFieldByToken2(
+ /* [in] */ IXCLRDataModule* tokenScope,
+ /* [in] */ mdFieldDef token,
+ /* [in] */ IXCLRDataTask *tlsTask,
+ /* [out] */ IXCLRDataValue **field,
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR nameBuf[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE GetName(
+ /* [in] */ ULONG32 flags,
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR nameBuf[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE GetModule(
+ /* [out] */ IXCLRDataModule **mod);
+
+ virtual HRESULT STDMETHODCALLTYPE GetDefinition(
+ /* [out] */ IXCLRDataTypeDefinition **typeDefinition);
+
+ virtual HRESULT STDMETHODCALLTYPE GetFlags(
+ /* [out] */ ULONG32 *flags);
+
+ virtual HRESULT STDMETHODCALLTYPE GetBase(
+ /* [out] */ IXCLRDataTypeInstance **base);
+
+ virtual HRESULT STDMETHODCALLTYPE IsSameObject(
+ /* [in] */ IXCLRDataTypeInstance *type);
+
+ virtual HRESULT STDMETHODCALLTYPE GetNumTypeArguments(
+ /* [out] */ ULONG32 *numTypeArgs);
+
+ virtual HRESULT STDMETHODCALLTYPE GetTypeArgumentByIndex(
+ /* [in] */ ULONG32 index,
+ /* [out] */ IXCLRDataTypeInstance **typeArg);
+
+ virtual HRESULT STDMETHODCALLTYPE Request(
+ /* [in] */ ULONG32 reqCode,
+ /* [in] */ ULONG32 inBufferSize,
+ /* [size_is][in] */ BYTE *inBuffer,
+ /* [in] */ ULONG32 outBufferSize,
+ /* [size_is][out] */ BYTE *outBuffer);
+
+ static HRESULT NewFromModule(ClrDataAccess* dac,
+ AppDomain* appDomain,
+ Module* module,
+ mdTypeDef token,
+ ClrDataTypeInstance** typeInst,
+ IXCLRDataTypeInstance** pubTypeInst);
+
+ TypeHandle GetTypeHandle(void)
+ {
+ return m_typeHandle;
+ }
+
+private:
+ LONG m_refs;
+ ClrDataAccess* m_dac;
+ ULONG32 m_instanceAge;
+ AppDomain* m_appDomain;
+ TypeHandle m_typeHandle;
+};
+
+//----------------------------------------------------------------------------
+//
+// ClrDataMethodDefinition.
+//
+//----------------------------------------------------------------------------
+
+class ClrDataMethodDefinition : public IXCLRDataMethodDefinition
+{
+public:
+ ClrDataMethodDefinition(ClrDataAccess* dac,
+ Module* module,
+ mdMethodDef token,
+ MethodDesc* methodDesc);
+ virtual ~ClrDataMethodDefinition(void);
+
+ // IUnknown.
+ STDMETHOD(QueryInterface)(THIS_
+ IN REFIID interfaceId,
+ OUT PVOID* iface);
+ STDMETHOD_(ULONG, AddRef)(THIS);
+ STDMETHOD_(ULONG, Release)(THIS);
+
+ //
+ // IXCLRDataMethodDefinition.
+ //
+
+ virtual HRESULT STDMETHODCALLTYPE GetTypeDefinition(
+ /* [out] */ IXCLRDataTypeDefinition **typeDefinition);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumInstances(
+ /* [in] */ IXCLRDataAppDomain* appDomain,
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumInstance(
+ /* [out][in] */ CLRDATA_ENUM *handle,
+ /* [out] */ IXCLRDataMethodInstance **instance);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumInstances(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE GetName(
+ /* [in] */ ULONG32 flags,
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR name[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE GetTokenAndScope(
+ /* [out] */ mdMethodDef *token,
+ /* [out] */ IXCLRDataModule **mod);
+
+ virtual HRESULT STDMETHODCALLTYPE GetFlags(
+ /* [out] */ ULONG32 *flags);
+
+ virtual HRESULT STDMETHODCALLTYPE IsSameObject(
+ /* [in] */ IXCLRDataMethodDefinition *method);
+
+ virtual HRESULT STDMETHODCALLTYPE GetLatestEnCVersion(
+ /* [out] */ ULONG32* version);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumExtents(
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumExtent(
+ /* [out][in] */ CLRDATA_ENUM *handle,
+ /* [out] */ CLRDATA_METHDEF_EXTENT *extent);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumExtents(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE GetCodeNotification(
+ /* [out] */ ULONG32 *flags);
+
+ virtual HRESULT STDMETHODCALLTYPE SetCodeNotification(
+ /* [in] */ ULONG32 flags);
+
+ virtual HRESULT STDMETHODCALLTYPE GetRepresentativeEntryAddress(
+ /* [out] */ CLRDATA_ADDRESS* addr);
+
+ virtual HRESULT STDMETHODCALLTYPE HasClassOrMethodInstantiation(
+ /*[out]*/ BOOL* bGeneric);
+
+ virtual HRESULT STDMETHODCALLTYPE Request(
+ /* [in] */ ULONG32 reqCode,
+ /* [in] */ ULONG32 inBufferSize,
+ /* [size_is][in] */ BYTE *inBuffer,
+ /* [in] */ ULONG32 outBufferSize,
+ /* [size_is][out] */ BYTE *outBuffer);
+
+ COR_ILMETHOD* GetIlMethod(void);
+
+ static HRESULT NewFromModule(ClrDataAccess* dac,
+ Module* module,
+ mdMethodDef token,
+ ClrDataMethodDefinition** methDef,
+ IXCLRDataMethodDefinition** pubMethDef);
+
+ static HRESULT GetSharedMethodFlags(MethodDesc* methodDesc,
+ ULONG32* flags);
+
+ // We don't need this if we are able to form name using token
+ MethodDesc *GetMethodDesc() { return m_methodDesc;}
+private:
+ LONG m_refs;
+ ClrDataAccess* m_dac;
+ ULONG32 m_instanceAge;
+ Module* m_module;
+ mdMethodDef m_token;
+ MethodDesc* m_methodDesc;
+};
+
+//----------------------------------------------------------------------------
+//
+// ClrDataMethodInstance.
+//
+//----------------------------------------------------------------------------
+
+class ClrDataMethodInstance : public IXCLRDataMethodInstance
+{
+public:
+ ClrDataMethodInstance(ClrDataAccess* dac,
+ AppDomain* appDomain,
+ MethodDesc* methodDesc);
+ virtual ~ClrDataMethodInstance(void);
+
+ // IUnknown.
+ STDMETHOD(QueryInterface)(THIS_
+ IN REFIID interfaceId,
+ OUT PVOID* iface);
+ STDMETHOD_(ULONG, AddRef)(THIS);
+ STDMETHOD_(ULONG, Release)(THIS);
+
+ //
+ // IXCLRDataMethodInstance.
+ //
+
+ virtual HRESULT STDMETHODCALLTYPE GetTypeInstance(
+ /* [out] */ IXCLRDataTypeInstance **typeInstance);
+
+ virtual HRESULT STDMETHODCALLTYPE GetDefinition(
+ /* [out] */ IXCLRDataMethodDefinition **methodDefinition);
+
+ virtual HRESULT STDMETHODCALLTYPE GetTokenAndScope(
+ /* [out] */ mdMethodDef *token,
+ /* [out] */ IXCLRDataModule **mod);
+
+ virtual HRESULT STDMETHODCALLTYPE GetName(
+ /* [in] */ ULONG32 flags,
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part(bufLen, *nameLen) WCHAR name[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE GetFlags(
+ /* [out] */ ULONG32 *flags);
+
+ virtual HRESULT STDMETHODCALLTYPE IsSameObject(
+ /* [in] */ IXCLRDataMethodInstance *method);
+
+ virtual HRESULT STDMETHODCALLTYPE GetEnCVersion(
+ /* [out] */ ULONG32* version);
+
+ virtual HRESULT STDMETHODCALLTYPE GetNumTypeArguments(
+ /* [out] */ ULONG32 *numTypeArgs);
+
+ virtual HRESULT STDMETHODCALLTYPE GetTypeArgumentByIndex(
+ /* [in] */ ULONG32 index,
+ /* [out] */ IXCLRDataTypeInstance **typeArg);
+
+ virtual HRESULT STDMETHODCALLTYPE GetILOffsetsByAddress(
+ /* [in] */ CLRDATA_ADDRESS address,
+ /* [in] */ ULONG32 offsetsLen,
+ /* [out] */ ULONG32 *offsetsNeeded,
+ /* [size_is][out] */ ULONG32 ilOffsets[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE GetAddressRangesByILOffset(
+ /* [in] */ ULONG32 ilOffset,
+ /* [in] */ ULONG32 rangesLen,
+ /* [out] */ ULONG32 *rangesNeeded,
+ /* [size_is][out] */ CLRDATA_ADDRESS_RANGE addressRanges[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE GetILAddressMap(
+ /* [in] */ ULONG32 mapLen,
+ /* [out] */ ULONG32 *mapNeeded,
+ /* [size_is][out] */ CLRDATA_IL_ADDRESS_MAP maps[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumExtents(
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumExtent(
+ /* [out][in] */ CLRDATA_ENUM *handle,
+ /* [out] */ CLRDATA_ADDRESS_RANGE *extent);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumExtents(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE GetRepresentativeEntryAddress(
+ /* [out] */ CLRDATA_ADDRESS* addr);
+
+ virtual HRESULT STDMETHODCALLTYPE Request(
+ /* [in] */ ULONG32 reqCode,
+ /* [in] */ ULONG32 inBufferSize,
+ /* [size_is][in] */ BYTE *inBuffer,
+ /* [in] */ ULONG32 outBufferSize,
+ /* [size_is][out] */ BYTE *outBuffer);
+
+ static HRESULT NewFromModule(ClrDataAccess* dac,
+ AppDomain* appDomain,
+ Module* module,
+ mdMethodDef token,
+ ClrDataMethodInstance** methInst,
+ IXCLRDataMethodInstance** pubMethInst);
+
+private:
+ friend class ClrDataAccess;
+ LONG m_refs;
+ ClrDataAccess* m_dac;
+ ULONG32 m_instanceAge;
+ AppDomain* m_appDomain;
+ MethodDesc* m_methodDesc;
+};
+
+//----------------------------------------------------------------------------
+//
+// ClrDataTask.
+//
+//----------------------------------------------------------------------------
+
+class ClrDataTask : public IXCLRDataTask
+{
+public:
+ ClrDataTask(ClrDataAccess* dac,
+ Thread* Thread);
+ virtual ~ClrDataTask(void);
+
+ // IUnknown.
+ STDMETHOD(QueryInterface)(THIS_
+ IN REFIID interfaceId,
+ OUT PVOID* iface);
+ STDMETHOD_(ULONG, AddRef)(THIS);
+ STDMETHOD_(ULONG, Release)(THIS);
+
+ //
+ // IXCLRDataTask.
+ //
+
+ virtual HRESULT STDMETHODCALLTYPE GetProcess(
+ /* [out] */ IXCLRDataProcess **process);
+
+ virtual HRESULT STDMETHODCALLTYPE GetCurrentAppDomain(
+ /* [out] */ IXCLRDataAppDomain **appDomain);
+
+ virtual HRESULT STDMETHODCALLTYPE GetName(
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR name[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE GetUniqueID(
+ /* [out] */ ULONG64 *id);
+
+ virtual HRESULT STDMETHODCALLTYPE GetFlags(
+ /* [out] */ ULONG32 *flags);
+
+ virtual HRESULT STDMETHODCALLTYPE IsSameObject(
+ /* [in] */ IXCLRDataTask *task);
+
+ virtual HRESULT STDMETHODCALLTYPE GetManagedObject(
+ /* [out] */ IXCLRDataValue **value);
+
+ virtual HRESULT STDMETHODCALLTYPE GetDesiredExecutionState(
+ /* [out] */ ULONG32 *state);
+
+ virtual HRESULT STDMETHODCALLTYPE SetDesiredExecutionState(
+ /* [in] */ ULONG32 state);
+
+ virtual HRESULT STDMETHODCALLTYPE CreateStackWalk(
+ /* [in] */ ULONG32 flags,
+ /* [out] */ IXCLRDataStackWalk **stackWalk);
+
+ virtual HRESULT STDMETHODCALLTYPE GetOSThreadID(
+ /* [out] */ ULONG32 *id);
+
+ virtual HRESULT STDMETHODCALLTYPE GetContext(
+ /* [in] */ ULONG32 contextFlags,
+ /* [in] */ ULONG32 contextBufSize,
+ /* [out] */ ULONG32 *contextSize,
+ /* [size_is][out] */ BYTE contextBuf[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE SetContext(
+ /* [in] */ ULONG32 contextSize,
+ /* [size_is][in] */ BYTE context[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE GetCurrentExceptionState(
+ /* [out] */ IXCLRDataExceptionState **exception);
+
+ virtual HRESULT STDMETHODCALLTYPE GetLastExceptionState(
+ /* [out] */ IXCLRDataExceptionState **exception);
+
+ virtual HRESULT STDMETHODCALLTYPE Request(
+ /* [in] */ ULONG32 reqCode,
+ /* [in] */ ULONG32 inBufferSize,
+ /* [size_is][in] */ BYTE *inBuffer,
+ /* [in] */ ULONG32 outBufferSize,
+ /* [size_is][out] */ BYTE *outBuffer);
+
+ Thread* GetThread(void)
+ {
+ return m_thread;
+ }
+
+private:
+ LONG m_refs;
+ ClrDataAccess* m_dac;
+ ULONG32 m_instanceAge;
+ Thread* m_thread;
+};
+
+//----------------------------------------------------------------------------
+//
+// ClrDataStackWalk.
+//
+//----------------------------------------------------------------------------
+
+class ClrDataStackWalk : public IXCLRDataStackWalk
+{
+public:
+ ClrDataStackWalk(ClrDataAccess* dac,
+ Thread* Thread,
+ ULONG32 flags);
+ virtual ~ClrDataStackWalk(void);
+
+ // IUnknown.
+ STDMETHOD(QueryInterface)(THIS_
+ IN REFIID interfaceId,
+ OUT PVOID* iface);
+ STDMETHOD_(ULONG, AddRef)(THIS);
+ STDMETHOD_(ULONG, Release)(THIS);
+
+ //
+ // IXCLRDataStackWalk.
+ //
+
+ virtual HRESULT STDMETHODCALLTYPE GetContext(
+ /* [in] */ ULONG32 contextFlags,
+ /* [in] */ ULONG32 contextBufSize,
+ /* [out] */ ULONG32 *contextSize,
+ /* [size_is][out] */ BYTE contextBuf[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE SetContext(
+ /* [in] */ ULONG32 contextSize,
+ /* [size_is][in] */ BYTE context[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE Next( void);
+
+ virtual HRESULT STDMETHODCALLTYPE GetStackSizeSkipped(
+ /* [out] */ ULONG64 *stackSizeSkipped);
+
+ virtual HRESULT STDMETHODCALLTYPE GetFrameType(
+ /* [out] */ CLRDataSimpleFrameType *simpleType,
+ /* [out] */ CLRDataDetailedFrameType *detailedType);
+
+ virtual HRESULT STDMETHODCALLTYPE GetFrame(
+ /* [out] */ IXCLRDataFrame **frame);
+
+ virtual HRESULT STDMETHODCALLTYPE Request(
+ /* [in] */ ULONG32 reqCode,
+ /* [in] */ ULONG32 inBufferSize,
+ /* [size_is][in] */ BYTE *inBuffer,
+ /* [in] */ ULONG32 outBufferSize,
+ /* [size_is][out] */ BYTE *outBuffer);
+
+ virtual HRESULT STDMETHODCALLTYPE SetContext2(
+ /* [in] */ ULONG32 flags,
+ /* [in] */ ULONG32 contextSize,
+ /* [size_is][in] */ BYTE context[ ]);
+
+ HRESULT Init(void);
+
+private:
+ void FilterFrames(void);
+ void RawGetFrameType(
+ /* [out] */ CLRDataSimpleFrameType* simpleType,
+ /* [out] */ CLRDataDetailedFrameType* detailedType);
+
+ LONG m_refs;
+ ClrDataAccess* m_dac;
+ ULONG32 m_instanceAge;
+ Thread* m_thread;
+ ULONG32 m_walkFlags;
+ StackFrameIterator m_frameIter;
+ REGDISPLAY m_regDisp;
+ T_CONTEXT m_context;
+ TADDR m_stackPrev;
+
+ // This is part of a test hook for debugging. Unless you're code:ClrDataStackWalk::Next
+ // you should never do anything with this member.
+ INDEBUG( int m_framesUnwound; )
+
+};
+
+//----------------------------------------------------------------------------
+//
+// ClrDataFrame.
+//
+//----------------------------------------------------------------------------
+
+class ClrDataFrame : public IXCLRDataFrame,
+ IXCLRDataFrame2
+{
+ friend class ClrDataStackWalk;
+
+public:
+ ClrDataFrame(ClrDataAccess* dac,
+ CLRDataSimpleFrameType simpleType,
+ CLRDataDetailedFrameType detailedType,
+ AppDomain* appDomain,
+ MethodDesc* methodDesc);
+ virtual ~ClrDataFrame(void);
+
+ // IUnknown.
+ STDMETHOD(QueryInterface)(THIS_
+ IN REFIID interfaceId,
+ OUT PVOID* iface);
+ STDMETHOD_(ULONG, AddRef)(THIS);
+ STDMETHOD_(ULONG, Release)(THIS);
+
+ //
+ // IXCLRDataFrame.
+ //
+
+ virtual HRESULT STDMETHODCALLTYPE GetContext(
+ /* [in] */ ULONG32 contextFlags,
+ /* [in] */ ULONG32 contextBufSize,
+ /* [out] */ ULONG32 *contextSize,
+ /* [size_is][out] */ BYTE contextBuf[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE GetFrameType(
+ /* [out] */ CLRDataSimpleFrameType *simpleType,
+ /* [out] */ CLRDataDetailedFrameType *detailedType);
+
+ virtual HRESULT STDMETHODCALLTYPE GetAppDomain(
+ /* [out] */ IXCLRDataAppDomain **appDomain);
+
+ virtual HRESULT STDMETHODCALLTYPE GetNumArguments(
+ /* [out] */ ULONG32 *numParams);
+
+ virtual HRESULT STDMETHODCALLTYPE GetArgumentByIndex(
+ /* [in] */ ULONG32 index,
+ /* [out] */ IXCLRDataValue **arg,
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part(bufLen, *nameLen) WCHAR name[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE GetNumLocalVariables(
+ /* [out] */ ULONG32 *numLocals);
+
+ virtual HRESULT STDMETHODCALLTYPE GetLocalVariableByIndex(
+ /* [in] */ ULONG32 index,
+ /* [out] */ IXCLRDataValue **localVariable,
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part(bufLen, *nameLen) WCHAR name[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE GetNumTypeArguments(
+ /* [out] */ ULONG32 *numTypeArgs);
+
+ virtual HRESULT STDMETHODCALLTYPE GetTypeArgumentByIndex(
+ /* [in] */ ULONG32 index,
+ /* [out] */ IXCLRDataTypeInstance **typeArg);
+
+ virtual HRESULT STDMETHODCALLTYPE GetCodeName(
+ /* [in] */ ULONG32 flags,
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_opt(bufLen) WCHAR nameBuf[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE GetMethodInstance(
+ /* [out] */ IXCLRDataMethodInstance **method);
+
+ virtual HRESULT STDMETHODCALLTYPE Request(
+ /* [in] */ ULONG32 reqCode,
+ /* [in] */ ULONG32 inBufferSize,
+ /* [size_is][in] */ BYTE *inBuffer,
+ /* [in] */ ULONG32 outBufferSize,
+ /* [size_is][out] */ BYTE *outBuffer);
+
+ //
+ // IXCLRDataFrame2.
+ //
+
+ virtual HRESULT STDMETHODCALLTYPE GetExactGenericArgsToken(
+ /* [out] */ IXCLRDataValue ** genericToken);
+
+private:
+ HRESULT GetMethodSig(MetaSig** sig,
+ ULONG32* count);
+ HRESULT GetLocalSig(MetaSig** sig,
+ ULONG32* count);
+ HRESULT ValueFromDebugInfo(MetaSig* sig,
+ bool isArg,
+ DWORD sigIndex,
+ DWORD varInfoSlot,
+ IXCLRDataValue** value);
+
+ LONG m_refs;
+ ClrDataAccess* m_dac;
+ ULONG32 m_instanceAge;
+ CLRDataSimpleFrameType m_simpleType;
+ CLRDataDetailedFrameType m_detailedType;
+ AppDomain* m_appDomain;
+ MethodDesc* m_methodDesc;
+ REGDISPLAY m_regDisp;
+ T_CONTEXT m_context;
+ MetaSig* m_methodSig;
+ MetaSig* m_localSig;
+};
+
+//----------------------------------------------------------------------------
+//
+// ClrDataExceptionState.
+//
+//----------------------------------------------------------------------------
+
+#ifdef WIN64EXCEPTIONS
+typedef ExceptionTracker ClrDataExStateType;
+#else // WIN64EXCEPTIONS
+typedef ExInfo ClrDataExStateType;
+#endif // WIN64EXCEPTIONS
+
+
+class ClrDataExceptionState : public IXCLRDataExceptionState
+{
+public:
+ ClrDataExceptionState(ClrDataAccess* dac,
+ AppDomain* appDomain,
+ Thread* thread,
+ ULONG32 flags,
+ ClrDataExStateType* exInfo,
+ OBJECTHANDLE throwable,
+ ClrDataExStateType* prevExInfo);
+ virtual ~ClrDataExceptionState(void);
+
+ // IUnknown.
+ STDMETHOD(QueryInterface)(THIS_
+ IN REFIID interfaceId,
+ OUT PVOID* iface);
+ STDMETHOD_(ULONG, AddRef)(THIS);
+ STDMETHOD_(ULONG, Release)(THIS);
+
+ //
+ // IXCLRDataExceptionState.
+ //
+
+ virtual HRESULT STDMETHODCALLTYPE GetFlags(
+ /* [out] */ ULONG32 *flags);
+
+ virtual HRESULT STDMETHODCALLTYPE GetPrevious(
+ /* [out] */ IXCLRDataExceptionState **exState);
+
+ virtual HRESULT STDMETHODCALLTYPE GetManagedObject(
+ /* [out] */ IXCLRDataValue **value);
+
+ virtual HRESULT STDMETHODCALLTYPE GetBaseType(
+ /* [out] */ CLRDataBaseExceptionType *type);
+
+ virtual HRESULT STDMETHODCALLTYPE GetCode(
+ /* [out] */ ULONG32 *code);
+
+ virtual HRESULT STDMETHODCALLTYPE GetString(
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *strLen,
+ /* [size_is][out] */ __out_ecount_part(bufLen, *strLen) WCHAR str[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE IsSameState(
+ /* [in] */ EXCEPTION_RECORD64 *exRecord,
+ /* [in] */ ULONG32 contextSize,
+ /* [size_is][in] */ BYTE cxRecord[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE IsSameState2(
+ /* [in] */ ULONG32 flags,
+ /* [in] */ EXCEPTION_RECORD64 *exRecord,
+ /* [in] */ ULONG32 contextSize,
+ /* [size_is][in] */ BYTE cxRecord[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE GetTask(
+ /* [out] */ IXCLRDataTask** task);
+
+ virtual HRESULT STDMETHODCALLTYPE Request(
+ /* [in] */ ULONG32 reqCode,
+ /* [in] */ ULONG32 inBufferSize,
+ /* [size_is][in] */ BYTE *inBuffer,
+ /* [in] */ ULONG32 outBufferSize,
+ /* [size_is][out] */ BYTE *outBuffer);
+
+ static HRESULT NewFromThread(ClrDataAccess* dac,
+ Thread* thread,
+ ClrDataExceptionState** exception,
+ IXCLRDataExceptionState** pubException);
+
+ PTR_CONTEXT GetCurrentContextRecord();
+ PTR_EXCEPTION_RECORD GetCurrentExceptionRecord();
+
+friend class ClrDataAccess;
+private:
+ LONG m_refs;
+ ClrDataAccess* m_dac;
+ ULONG32 m_instanceAge;
+ AppDomain* m_appDomain;
+ Thread* m_thread;
+ ULONG32 m_flags;
+ ClrDataExStateType* m_exInfo;
+ OBJECTHANDLE m_throwable;
+ ClrDataExStateType* m_prevExInfo;
+};
+
+//----------------------------------------------------------------------------
+//
+// ClrDataValue.
+//
+//----------------------------------------------------------------------------
+
+class ClrDataValue : public IXCLRDataValue
+{
+public:
+ ClrDataValue(ClrDataAccess* dac,
+ AppDomain* appDomain,
+ Thread* thread,
+ ULONG32 flags,
+ TypeHandle typeHandle,
+ ULONG64 baseAddr,
+ ULONG32 numLocs,
+ NativeVarLocation* locs);
+ virtual ~ClrDataValue(void);
+
+ // IUnknown.
+ STDMETHOD(QueryInterface)(THIS_
+ IN REFIID interfaceId,
+ OUT PVOID* iface);
+ STDMETHOD_(ULONG, AddRef)(THIS);
+ STDMETHOD_(ULONG, Release)(THIS);
+
+ //
+ // IXCLRDataValue.
+ //
+
+ virtual HRESULT STDMETHODCALLTYPE GetFlags(
+ /* [out] */ ULONG32 *flags);
+
+ virtual HRESULT STDMETHODCALLTYPE GetAddress(
+ /* [out] */ CLRDATA_ADDRESS *address);
+
+ virtual HRESULT STDMETHODCALLTYPE GetSize(
+ /* [out] */ ULONG64 *size);
+
+ virtual HRESULT STDMETHODCALLTYPE GetBytes(
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *dataSize,
+ /* [size_is][out] */ BYTE buffer[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE SetBytes(
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *dataSize,
+ /* [size_is][in] */ BYTE buffer[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE GetType(
+ /* [out] */ IXCLRDataTypeInstance **typeInstance);
+
+ virtual HRESULT STDMETHODCALLTYPE GetNumFields(
+ /* [out] */ ULONG32 *numFields);
+
+ virtual HRESULT STDMETHODCALLTYPE GetFieldByIndex(
+ /* [in] */ ULONG32 index,
+ /* [out] */ IXCLRDataValue **field,
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR nameBuf[ ],
+ /* [out] */ mdFieldDef *token);
+
+ virtual HRESULT STDMETHODCALLTYPE GetNumFields2(
+ /* [in] */ ULONG32 flags,
+ /* [in] */ IXCLRDataTypeInstance *fromType,
+ /* [out] */ ULONG32 *numFields);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumFields(
+ /* [in] */ ULONG32 flags,
+ /* [in] */ IXCLRDataTypeInstance *fromType,
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumField(
+ /* [out][in] */ CLRDATA_ENUM *handle,
+ /* [out] */ IXCLRDataValue **field,
+ /* [in] */ ULONG32 nameBufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part_opt(nameBufLen, *nameLen) WCHAR nameBuf[ ],
+ /* [out] */ mdFieldDef *token);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumField2(
+ /* [out][in] */ CLRDATA_ENUM *handle,
+ /* [out] */ IXCLRDataValue **field,
+ /* [in] */ ULONG32 nameBufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part_opt(nameBufLen, *nameLen) WCHAR nameBuf[ ],
+ /* [out] */ IXCLRDataModule** tokenScope,
+ /* [out] */ mdFieldDef *token);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumFields(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE StartEnumFieldsByName(
+ /* [in] */ LPCWSTR name,
+ /* [in] */ ULONG32 nameFlags,
+ /* [in] */ ULONG32 fieldFlags,
+ /* [in] */ IXCLRDataTypeInstance *fromType,
+ /* [out] */ CLRDATA_ENUM *handle);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumFieldByName(
+ /* [out][in] */ CLRDATA_ENUM *handle,
+ /* [out] */ IXCLRDataValue **field,
+ /* [out] */ mdFieldDef *token);
+
+ virtual HRESULT STDMETHODCALLTYPE EnumFieldByName2(
+ /* [out][in] */ CLRDATA_ENUM *handle,
+ /* [out] */ IXCLRDataValue **field,
+ /* [out] */ IXCLRDataModule** tokenScope,
+ /* [out] */ mdFieldDef *token);
+
+ virtual HRESULT STDMETHODCALLTYPE EndEnumFieldsByName(
+ /* [in] */ CLRDATA_ENUM handle);
+
+ virtual HRESULT STDMETHODCALLTYPE GetFieldByToken(
+ /* [in] */ mdFieldDef token,
+ /* [out] */ IXCLRDataValue **field,
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR nameBuf[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE GetFieldByToken2(
+ /* [in] */ IXCLRDataModule* tokenScope,
+ /* [in] */ mdFieldDef token,
+ /* [out] */ IXCLRDataValue **field,
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *nameLen,
+ /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR nameBuf[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE GetAssociatedValue(
+ /* [out] */ IXCLRDataValue **assocValue);
+
+ virtual HRESULT STDMETHODCALLTYPE GetAssociatedType(
+ /* [out] */ IXCLRDataTypeInstance **assocType);
+
+ virtual HRESULT STDMETHODCALLTYPE GetString(
+ /* [in] */ ULONG32 bufLen,
+ /* [out] */ ULONG32 *strLen,
+ /* [size_is][out] */ __out_ecount_part(bufLen, *strLen) WCHAR str[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE GetArrayProperties(
+ /* [out] */ ULONG32 *rank,
+ /* [out] */ ULONG32 *totalElements,
+ /* [in] */ ULONG32 numDim,
+ /* [size_is][out] */ ULONG32 dims[ ],
+ /* [in] */ ULONG32 numBases,
+ /* [size_is][out] */ LONG32 bases[ ]);
+
+ virtual HRESULT STDMETHODCALLTYPE GetArrayElement(
+ /* [in] */ ULONG32 numInd,
+ /* [size_is][in] */ LONG32 indices[ ],
+ /* [out] */ IXCLRDataValue **value);
+
+ virtual HRESULT STDMETHODCALLTYPE GetNumLocations(
+ /* [out] */ ULONG32* numLocs);
+
+ virtual HRESULT STDMETHODCALLTYPE GetLocationByIndex(
+ /* [in] */ ULONG32 loc,
+ /* [out] */ ULONG32* flags,
+ /* [out] */ CLRDATA_ADDRESS* arg);
+
+ virtual HRESULT STDMETHODCALLTYPE Request(
+ /* [in] */ ULONG32 reqCode,
+ /* [in] */ ULONG32 inBufferSize,
+ /* [size_is][in] */ BYTE *inBuffer,
+ /* [in] */ ULONG32 outBufferSize,
+ /* [size_is][out] */ BYTE *outBuffer);
+
+ HRESULT GetRefAssociatedValue(IXCLRDataValue** assocValue);
+
+ static HRESULT NewFromFieldDesc(ClrDataAccess* dac,
+ AppDomain* appDomain,
+ ULONG32 flags,
+ FieldDesc* fieldDesc,
+ ULONG64 objBase,
+ Thread* tlsThread,
+ ClrDataValue** value,
+ IXCLRDataValue** pubValue,
+ ULONG32 nameBufRetLen,
+ ULONG32* nameLenRet,
+ __out_ecount_part_opt(nameBufRetLen, *nameLenRet) WCHAR nameBufRet[ ],
+ IXCLRDataModule** tokenScopeRet,
+ mdFieldDef* tokenRet);
+
+ HRESULT NewFromSubField(FieldDesc* fieldDesc,
+ ULONG32 flags,
+ ClrDataValue** value,
+ IXCLRDataValue** pubValue,
+ ULONG32 nameBufRetLen,
+ ULONG32* nameLenRet,
+ __out_ecount_part_opt(nameBufRetLen, *nameLenRet) WCHAR nameBufRet[ ],
+ IXCLRDataModule** tokenScopeRet,
+ mdFieldDef* tokenRet)
+ {
+ return ClrDataValue::NewFromFieldDesc(m_dac,
+ m_appDomain,
+ flags,
+ fieldDesc,
+ m_baseAddr,
+ m_thread,
+ value,
+ pubValue,
+ nameBufRetLen,
+ nameLenRet,
+ nameBufRet,
+ tokenScopeRet,
+ tokenRet);
+ }
+
+ bool CanHaveFields(void)
+ {
+ return (m_flags & CLRDATA_VALUE_IS_REFERENCE) == 0;
+ }
+
+ HRESULT IntGetBytes(
+ /* [in] */ ULONG32 bufLen,
+ /* [size_is][out] */ BYTE buffer[ ]);
+
+private:
+ LONG m_refs;
+ ClrDataAccess* m_dac;
+ ULONG32 m_instanceAge;
+ AppDomain* m_appDomain;
+ Thread* m_thread;
+ ULONG32 m_flags;
+ TypeHandle m_typeHandle;
+ ULONG64 m_totalSize;
+ ULONG64 m_baseAddr;
+ ULONG32 m_numLocs;
+ NativeVarLocation m_locs[MAX_NATIVE_VAR_LOCS];
+};
+
+//----------------------------------------------------------------------------
+//
+// EnumMethodDefinitions.
+//
+//----------------------------------------------------------------------------
+
+class EnumMethodDefinitions
+{
+public:
+ HRESULT Start(Module* mod,
+ bool useAddrFilter,
+ CLRDATA_ADDRESS addrFilter);
+ HRESULT Next(ClrDataAccess* dac,
+ IXCLRDataMethodDefinition **method);
+
+ static HRESULT CdStart(Module* mod,
+ bool useAddrFilter,
+ CLRDATA_ADDRESS addrFilter,
+ CLRDATA_ENUM* handle);
+ static HRESULT CdNext(ClrDataAccess* dac,
+ CLRDATA_ENUM* handle,
+ IXCLRDataMethodDefinition** method);
+ static HRESULT CdEnd(CLRDATA_ENUM handle);
+
+ Module* m_module;
+ bool m_useAddrFilter;
+ CLRDATA_ADDRESS m_addrFilter;
+ MetaEnum m_typeEnum;
+ mdToken m_typeToken;
+ bool m_needMethodStart;
+ MetaEnum m_methodEnum;
+};
+
+//----------------------------------------------------------------------------
+//
+// EnumMethodInstances.
+//
+//----------------------------------------------------------------------------
+
+class EnumMethodInstances
+{
+public:
+ EnumMethodInstances(MethodDesc* methodDesc,
+ IXCLRDataAppDomain* givenAppDomain);
+
+ HRESULT Next(ClrDataAccess* dac,
+ IXCLRDataMethodInstance **instance);
+
+ static HRESULT CdStart(MethodDesc* methodDesc,
+ IXCLRDataAppDomain* appDomain,
+ CLRDATA_ENUM* handle);
+ static HRESULT CdNext(ClrDataAccess* dac,
+ CLRDATA_ENUM* handle,
+ IXCLRDataMethodInstance** method);
+ static HRESULT CdEnd(CLRDATA_ENUM handle);
+
+ MethodDesc* m_methodDesc;
+ AppDomain* m_givenAppDomain;
+ bool m_givenAppDomainUsed;
+ AppDomainIterator m_domainIter;
+ AppDomain* m_appDomain;
+ LoadedMethodDescIterator m_methodIter;
+};
+
+//----------------------------------------------------------------------------
+//
+// Internal functions.
+//
+//----------------------------------------------------------------------------
+
+#define DAC_ENTER() \
+ EnterCriticalSection(&g_dacCritSec); \
+ ClrDataAccess* __prevDacImpl = g_dacImpl; \
+ g_dacImpl = this;
+
+// When entering a child object we validate that
+// the process's host instance cache hasn't been flushed
+// since the child was created.
+#define DAC_ENTER_SUB(dac) \
+ EnterCriticalSection(&g_dacCritSec); \
+ if (dac->m_instanceAge != m_instanceAge) \
+ { \
+ LeaveCriticalSection(&g_dacCritSec); \
+ return E_INVALIDARG; \
+ } \
+ ClrDataAccess* __prevDacImpl = g_dacImpl; \
+ g_dacImpl = (dac)
+
+#define DAC_LEAVE() \
+ g_dacImpl = __prevDacImpl; \
+ LeaveCriticalSection(&g_dacCritSec)
+
+
+#define SOSHelperEnter() \
+ DAC_ENTER_SUB(mDac); \
+ HRESULT hr = S_OK; \
+ EX_TRY \
+ {
+
+#define SOSHelperLeave() \
+ } \
+ EX_CATCH \
+ { \
+ if (!DacExceptionFilter(GET_EXCEPTION(), mDac, &hr)) \
+ { \
+ EX_RETHROW; \
+ } \
+ } \
+ EX_END_CATCH(SwallowAllExceptions) \
+ DAC_LEAVE();
+
+HRESULT DacGetHostVtPtrs(void);
+bool DacExceptionFilter(Exception* ex, ClrDataAccess* process,
+ HRESULT* status);
+Thread* __stdcall DacGetThread(ULONG32 osThread);
+BOOL DacGetThreadContext(Thread* thread, T_CONTEXT* context);
+
+// Imports from request_svr.cpp, to provide data we need from the SVR namespace
+int GCHeapCount();
+HRESULT GetServerHeapData(CLRDATA_ADDRESS addr, DacpHeapSegmentData *pSegment);
+HRESULT GetServerHeaps(CLRDATA_ADDRESS pGCHeaps[], ICorDebugDataTarget* pTarget);
+
+#if defined(DAC_MEASURE_PERF)
+
+#if defined(_TARGET_X86_)
+
+// Assume Pentium CPU
+
+#define CCNT_OVERHEAD_32 8
+#define CCNT_OVERHEAD 13
+
+#pragma warning( disable: 4035 ) /* Don't complain about lack of return value */
+
+__inline unsigned __int64 GetCycleCount ()
+{
+__asm _emit 0x0F
+__asm _emit 0x31 /* rdtsc */
+ // return EDX:EAX causes annoying warning
+};
+
+__inline unsigned GetCycleCount32 () // enough for about 40 seconds
+{
+ LIMITED_METHOD_CONTRACT;
+
+__asm push EDX
+__asm _emit 0x0F
+__asm _emit 0x31 /* rdtsc */
+__asm pop EDX
+ // return EAX causes annoying warning
+};
+
+#pragma warning( default: 4035 )
+
+#else // #if defined(_TARGET_X86_)
+
+#define CCNT_OVERHEAD 0 // Don't know
+
+__inline unsigned __int64 GetCycleCount()
+{
+ LIMITED_METHOD_CONTRACT;
+
+ LARGE_INTEGER qwTmp;
+ QueryPerformanceCounter(&qwTmp);
+ return qwTmp.QuadPart;
+}
+
+#endif // #if defined(_TARGET_X86_)
+
+extern unsigned __int64 g_nTotalTime;
+extern unsigned __int64 g_nStackTotalTime;
+extern unsigned __int64 g_nReadVirtualTotalTime;
+extern unsigned __int64 g_nFindTotalTime;
+extern unsigned __int64 g_nFindHashTotalTime;
+extern unsigned __int64 g_nFindHits;
+extern unsigned __int64 g_nFindCalls;
+extern unsigned __int64 g_nFindFails;
+extern unsigned __int64 g_nStackWalk;
+extern unsigned __int64 g_nFindStackTotalTime;
+
+#endif // #if defined(DAC_MEASURE_PERF)
+
+#endif // #ifndef __DACIMPL_H__