summaryrefslogtreecommitdiff
path: root/src/inc/dacprivate.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/inc/dacprivate.h')
-rw-r--r--src/inc/dacprivate.h940
1 files changed, 940 insertions, 0 deletions
diff --git a/src/inc/dacprivate.h b/src/inc/dacprivate.h
new file mode 100644
index 0000000000..e3bc4dcc2a
--- /dev/null
+++ b/src/inc/dacprivate.h
@@ -0,0 +1,940 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+//*****************************************************************************
+//
+// Internal data access functionality.
+//
+//*****************************************************************************
+
+#ifndef _DACPRIVATE_H_
+#define _DACPRIVATE_H_
+
+#include <cor.h>
+#include <clrdata.h>
+#include <xclrdata.h>
+#include <sospriv.h>
+
+#ifndef FEATURE_PAL
+// It is unfortunate having to include this header just to get the definition of GenericModeBlock
+#include <msodw.h>
+#endif // FEATURE_PAL
+
+//----------------------------------------------------------------------------
+//
+// Utility class to allow for zero initialization of our Dacp- structs.
+//
+//----------------------------------------------------------------------------
+
+template <class T>
+struct ZeroInit
+{
+ ZeroInit()
+ { memset(static_cast<T*>(this), 0, sizeof(T)); }
+};
+
+
+#include <livedatatarget.h>
+
+//----------------------------------------------------------------------------
+//
+// Internal CLRData requests.
+//
+//----------------------------------------------------------------------------
+
+
+// Private requests for DataModules
+enum
+{
+ DACDATAMODULEPRIV_REQUEST_GET_MODULEPTR = 0xf0000000
+};
+
+
+// Private requests for stack walkers.
+enum
+{
+ DACSTACKPRIV_REQUEST_FRAME_DATA = 0xf0000000
+};
+
+enum DacpObjectType { OBJ_STRING=0,OBJ_FREE,OBJ_OBJECT,OBJ_ARRAY,OBJ_OTHER };
+struct DacpObjectData : ZeroInit<DacpObjectData>
+{
+ CLRDATA_ADDRESS MethodTable;
+ DacpObjectType ObjectType;
+ ULONG64 Size;
+ CLRDATA_ADDRESS ElementTypeHandle;
+ CorElementType ElementType;
+ DWORD dwRank;
+ ULONG64 dwNumComponents;
+ ULONG64 dwComponentSize;
+ CLRDATA_ADDRESS ArrayDataPtr;
+ CLRDATA_ADDRESS ArrayBoundsPtr;
+ CLRDATA_ADDRESS ArrayLowerBoundsPtr;
+
+ CLRDATA_ADDRESS RCW;
+ CLRDATA_ADDRESS CCW;
+
+ HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
+ {
+ return sos->GetObjectData(addr, this);
+ }
+};
+
+struct DacpExceptionObjectData : ZeroInit<DacpExceptionObjectData>
+{
+ CLRDATA_ADDRESS Message;
+ CLRDATA_ADDRESS InnerException;
+ CLRDATA_ADDRESS StackTrace;
+ CLRDATA_ADDRESS WatsonBuckets;
+ CLRDATA_ADDRESS StackTraceString;
+ CLRDATA_ADDRESS RemoteStackTraceString;
+ INT32 HResult;
+ INT32 XCode;
+
+ HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
+ {
+ HRESULT hr;
+ ISOSDacInterface2 *psos2 = NULL;
+ if (SUCCEEDED(hr = sos->QueryInterface(__uuidof(ISOSDacInterface2), (void**) &psos2)))
+ {
+ hr = psos2->GetObjectExceptionData(addr, this);
+ psos2->Release();
+ }
+ return hr;
+ }
+};
+
+struct DacpUsefulGlobalsData : ZeroInit<DacpUsefulGlobalsData>
+{
+ CLRDATA_ADDRESS ArrayMethodTable;
+ CLRDATA_ADDRESS StringMethodTable;
+ CLRDATA_ADDRESS ObjectMethodTable;
+ CLRDATA_ADDRESS ExceptionMethodTable;
+ CLRDATA_ADDRESS FreeMethodTable;
+};
+
+struct DacpFieldDescData : ZeroInit<DacpFieldDescData>
+{
+ CorElementType Type;
+ CorElementType sigType; // ELEMENT_TYPE_XXX from signature. We need this to disply pretty name for String in minidump's case
+ CLRDATA_ADDRESS MTOfType; // NULL if Type is not loaded
+
+ CLRDATA_ADDRESS ModuleOfType;
+ mdTypeDef TokenOfType;
+
+ mdFieldDef mb;
+ CLRDATA_ADDRESS MTOfEnclosingClass;
+ DWORD dwOffset;
+ BOOL bIsThreadLocal;
+ BOOL bIsContextLocal;
+ BOOL bIsStatic;
+ CLRDATA_ADDRESS NextField;
+
+ HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
+ {
+ return sos->GetFieldDescData(addr, this);
+ }
+};
+
+struct DacpMethodTableFieldData : ZeroInit<DacpMethodTableFieldData>
+{
+ WORD wNumInstanceFields;
+ WORD wNumStaticFields;
+ WORD wNumThreadStaticFields;
+
+ CLRDATA_ADDRESS FirstField; // If non-null, you can retrieve more
+
+ WORD wContextStaticOffset;
+ WORD wContextStaticsSize;
+
+ HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
+ {
+ return sos->GetMethodTableFieldData(addr, this);
+ }
+};
+
+struct DacpMethodTableTransparencyData : ZeroInit<DacpMethodTableTransparencyData>
+{
+ BOOL bHasCriticalTransparentInfo;
+ BOOL bIsCritical;
+ BOOL bIsTreatAsSafe;
+
+ HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
+ {
+ return sos->GetMethodTableTransparencyData(addr, this);
+ }
+};
+
+struct DacpDomainLocalModuleData : ZeroInit<DacpDomainLocalModuleData>
+{
+ // These two parameters are used as input params when calling the
+ // no-argument form of Request below.
+ CLRDATA_ADDRESS appDomainAddr;
+ ULONG64 ModuleID;
+
+ CLRDATA_ADDRESS pClassData;
+ CLRDATA_ADDRESS pDynamicClassTable;
+ CLRDATA_ADDRESS pGCStaticDataStart;
+ CLRDATA_ADDRESS pNonGCStaticDataStart;
+
+ // Called when you have a pointer to the DomainLocalModule
+ HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
+ {
+ return sos->GetDomainLocalModuleData(addr, this);
+ }
+};
+
+
+struct DacpThreadLocalModuleData : ZeroInit<DacpThreadLocalModuleData>
+{
+ // These two parameters are used as input params when calling the
+ // no-argument form of Request below.
+ CLRDATA_ADDRESS threadAddr;
+ ULONG64 ModuleIndex;
+
+ CLRDATA_ADDRESS pClassData;
+ CLRDATA_ADDRESS pDynamicClassTable;
+ CLRDATA_ADDRESS pGCStaticDataStart;
+ CLRDATA_ADDRESS pNonGCStaticDataStart;
+};
+
+
+struct DacpModuleData : ZeroInit<DacpModuleData>
+{
+ CLRDATA_ADDRESS Address;
+ CLRDATA_ADDRESS File; // A PEFile addr
+ CLRDATA_ADDRESS ilBase;
+ CLRDATA_ADDRESS metadataStart;
+ ULONG64 metadataSize;
+ CLRDATA_ADDRESS Assembly; // Assembly pointer
+ BOOL bIsReflection;
+ BOOL bIsPEFile;
+ ULONG64 dwBaseClassIndex;
+ ULONG64 dwModuleID;
+
+ DWORD dwTransientFlags;
+
+ CLRDATA_ADDRESS TypeDefToMethodTableMap;
+ CLRDATA_ADDRESS TypeRefToMethodTableMap;
+ CLRDATA_ADDRESS MethodDefToDescMap;
+ CLRDATA_ADDRESS FieldDefToDescMap;
+ CLRDATA_ADDRESS MemberRefToDescMap;
+ CLRDATA_ADDRESS FileReferencesMap;
+ CLRDATA_ADDRESS ManifestModuleReferencesMap;
+
+ CLRDATA_ADDRESS pLookupTableHeap;
+ CLRDATA_ADDRESS pThunkHeap;
+
+ ULONG64 dwModuleIndex;
+
+ DacpModuleData()
+ {
+ }
+
+ HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
+ {
+ return sos->GetModuleData(addr, this);
+ }
+
+private:
+ // Ensure that this data structure is not copied.
+ DacpModuleData(const DacpModuleData&);
+ void operator=(const DacpModuleData&);
+};
+
+struct DacpMethodTableData : ZeroInit<DacpMethodTableData>
+{
+ BOOL bIsFree; // everything else is NULL if this is true.
+ CLRDATA_ADDRESS Module;
+ CLRDATA_ADDRESS Class;
+ CLRDATA_ADDRESS ParentMethodTable;
+ WORD wNumInterfaces;
+ WORD wNumMethods;
+ WORD wNumVtableSlots;
+ WORD wNumVirtuals;
+ DWORD BaseSize;
+ DWORD ComponentSize;
+ mdTypeDef cl; // Metadata token
+ DWORD dwAttrClass; // cached metadata
+ BOOL bIsShared; // flags & enum_flag_DomainNeutral
+ BOOL bIsDynamic;
+ BOOL bContainsPointers;
+
+ HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
+ {
+ return sos->GetMethodTableData(addr, this);
+ }
+};
+
+
+// Copied from util.hpp, for DacpThreadStoreData.fHostConfig below.
+#define CLRMEMORYHOSTED 0x1
+#define CLRTASKHOSTED 0x2
+#define CLRSYNCHOSTED 0x4
+#define CLRTHREADPOOLHOSTED 0x8
+#define CLRIOCOMPLETIONHOSTED 0x10
+#define CLRASSEMBLYHOSTED 0x20
+#define CLRGCHOSTED 0x40
+#define CLRSECURITYHOSTED 0x80
+#define CLRHOSTED 0x80000000
+
+struct DacpThreadStoreData : ZeroInit<DacpThreadStoreData>
+{
+ LONG threadCount;
+ LONG unstartedThreadCount;
+ LONG backgroundThreadCount;
+ LONG pendingThreadCount;
+ LONG deadThreadCount;
+ CLRDATA_ADDRESS firstThread;
+ CLRDATA_ADDRESS finalizerThread;
+ CLRDATA_ADDRESS gcThread;
+ DWORD fHostConfig; // Uses hosting flags defined above
+
+ HRESULT Request(ISOSDacInterface *sos)
+ {
+ return sos->GetThreadStoreData(this);
+ }
+};
+
+struct DacpAppDomainStoreData : ZeroInit<DacpAppDomainStoreData>
+{
+ CLRDATA_ADDRESS sharedDomain;
+ CLRDATA_ADDRESS systemDomain;
+ LONG DomainCount;
+
+ HRESULT Request(ISOSDacInterface *sos)
+ {
+ return sos->GetAppDomainStoreData(this);
+ }
+};
+
+struct DacpCOMInterfacePointerData : ZeroInit<DacpCOMInterfacePointerData>
+{
+ CLRDATA_ADDRESS methodTable;
+ CLRDATA_ADDRESS interfacePtr;
+ CLRDATA_ADDRESS comContext;
+};
+
+struct DacpRCWData : ZeroInit<DacpRCWData>
+{
+ CLRDATA_ADDRESS identityPointer;
+ CLRDATA_ADDRESS unknownPointer;
+ CLRDATA_ADDRESS managedObject;
+ CLRDATA_ADDRESS jupiterObject;
+ CLRDATA_ADDRESS vtablePtr;
+ CLRDATA_ADDRESS creatorThread;
+ CLRDATA_ADDRESS ctxCookie;
+
+ LONG refCount;
+ LONG interfaceCount;
+
+ BOOL isJupiterObject;
+ BOOL supportsIInspectable;
+ BOOL isAggregated;
+ BOOL isContained;
+ BOOL isFreeThreaded;
+ BOOL isDisconnected;
+
+ HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS rcw)
+ {
+ return sos->GetRCWData(rcw, this);
+ }
+
+ HRESULT IsDCOMProxy(ISOSDacInterface *sos, CLRDATA_ADDRESS rcw, BOOL* isDCOMProxy)
+ {
+ ISOSDacInterface2 *pSOS2 = nullptr;
+ HRESULT hr = sos->QueryInterface(__uuidof(ISOSDacInterface2), reinterpret_cast<LPVOID*>(&pSOS2));
+ if (SUCCEEDED(hr))
+ {
+ hr = pSOS2->IsRCWDCOMProxy(rcw, isDCOMProxy);
+ pSOS2->Release();
+ }
+
+ return hr;
+ }
+};
+
+struct DacpCCWData : ZeroInit<DacpCCWData>
+{
+ CLRDATA_ADDRESS outerIUnknown;
+ CLRDATA_ADDRESS managedObject;
+ CLRDATA_ADDRESS handle;
+ CLRDATA_ADDRESS ccwAddress;
+
+ LONG refCount;
+ LONG interfaceCount;
+ BOOL isNeutered;
+
+ LONG jupiterRefCount;
+ BOOL isPegged;
+ BOOL isGlobalPegged;
+ BOOL hasStrongRef;
+ BOOL isExtendsCOMObject;
+ BOOL isAggregated;
+
+ HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS ccw)
+ {
+ return sos->GetCCWData(ccw, this);
+ }
+};
+
+enum DacpAppDomainDataStage {
+ STAGE_CREATING,
+ STAGE_READYFORMANAGEDCODE,
+ STAGE_ACTIVE,
+ STAGE_OPEN,
+ STAGE_UNLOAD_REQUESTED,
+ STAGE_EXITING,
+ STAGE_EXITED,
+ STAGE_FINALIZING,
+ STAGE_FINALIZED,
+ STAGE_HANDLETABLE_NOACCESS,
+ STAGE_CLEARED,
+ STAGE_COLLECTED,
+ STAGE_CLOSED
+};
+
+// Information about a BaseDomain (AppDomain, SharedDomain or SystemDomain).
+// For types other than AppDomain, some fields (like dwID, DomainLocalBlock, etc.) will be 0/null.
+struct DacpAppDomainData : ZeroInit<DacpAppDomainData>
+{
+ // The pointer to the BaseDomain (not necessarily an AppDomain).
+ // It's useful to keep this around in the structure
+ CLRDATA_ADDRESS AppDomainPtr;
+ CLRDATA_ADDRESS AppSecDesc;
+ CLRDATA_ADDRESS pLowFrequencyHeap;
+ CLRDATA_ADDRESS pHighFrequencyHeap;
+ CLRDATA_ADDRESS pStubHeap;
+ CLRDATA_ADDRESS DomainLocalBlock;
+ CLRDATA_ADDRESS pDomainLocalModules;
+ // The creation sequence number of this app domain (starting from 1)
+ DWORD dwId;
+ LONG AssemblyCount;
+ LONG FailedAssemblyCount;
+ DacpAppDomainDataStage appDomainStage;
+
+ HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
+ {
+ return sos->GetAppDomainData(addr, this);
+ }
+};
+
+struct DacpAssemblyData : ZeroInit<DacpAssemblyData>
+{
+ CLRDATA_ADDRESS AssemblyPtr; //useful to have
+ CLRDATA_ADDRESS ClassLoader;
+ CLRDATA_ADDRESS ParentDomain;
+ CLRDATA_ADDRESS BaseDomainPtr;
+ CLRDATA_ADDRESS AssemblySecDesc;
+ BOOL isDynamic;
+ UINT ModuleCount;
+ UINT LoadContext;
+ BOOL isDomainNeutral;
+ DWORD dwLocationFlags;
+
+ HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr, CLRDATA_ADDRESS baseDomainPtr)
+ {
+ return sos->GetAssemblyData(baseDomainPtr, addr, this);
+ }
+
+ HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
+ {
+ return Request(sos, addr, NULL);
+ }
+};
+
+
+struct DacpThreadData : ZeroInit<DacpThreadData>
+{
+ DWORD corThreadId;
+ DWORD osThreadId;
+ int state;
+ ULONG preemptiveGCDisabled;
+ CLRDATA_ADDRESS allocContextPtr;
+ CLRDATA_ADDRESS allocContextLimit;
+ CLRDATA_ADDRESS context;
+ CLRDATA_ADDRESS domain;
+ CLRDATA_ADDRESS pFrame;
+ DWORD lockCount;
+ CLRDATA_ADDRESS firstNestedException; // Pass this pointer to DacpNestedExceptionInfo
+ CLRDATA_ADDRESS teb;
+ CLRDATA_ADDRESS fiberData;
+ CLRDATA_ADDRESS lastThrownObjectHandle;
+ CLRDATA_ADDRESS nextThread;
+
+ HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
+ {
+ return sos->GetThreadData(addr, this);
+ }
+};
+
+
+struct DacpReJitData : ZeroInit<DacpReJitData>
+{
+ enum Flags
+ {
+ kUnknown,
+ kRequested,
+ kActive,
+ kReverted,
+ };
+
+ CLRDATA_ADDRESS rejitID;
+ Flags flags;
+ CLRDATA_ADDRESS NativeCodeAddr;
+};
+
+struct DacpMethodDescData : ZeroInit<DacpMethodDescData>
+{
+ BOOL bHasNativeCode;
+ BOOL bIsDynamic;
+ WORD wSlotNumber;
+ CLRDATA_ADDRESS NativeCodeAddr;
+ // Useful for breaking when a method is jitted.
+ CLRDATA_ADDRESS AddressOfNativeCodeSlot;
+
+ CLRDATA_ADDRESS MethodDescPtr;
+ CLRDATA_ADDRESS MethodTablePtr;
+ CLRDATA_ADDRESS ModulePtr;
+
+ mdToken MDToken;
+ CLRDATA_ADDRESS GCInfo;
+ CLRDATA_ADDRESS GCStressCodeCopy;
+
+ // This is only valid if bIsDynamic is true
+ CLRDATA_ADDRESS managedDynamicMethodObject;
+
+ CLRDATA_ADDRESS requestedIP;
+
+ // Gives info for the single currently active version of a method
+ DacpReJitData rejitDataCurrent;
+
+ // Gives info corresponding to requestedIP (for !ip2md)
+ DacpReJitData rejitDataRequested;
+
+ // Total number of rejit versions that have been jitted
+ ULONG cJittedRejitVersions;
+
+ HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
+ {
+ return sos->GetMethodDescData(
+ addr,
+ NULL, // IP address
+ this,
+ 0, // cRejitData
+ NULL, // rejitData[]
+ NULL // pcNeededRejitData
+ );
+ }
+};
+
+struct DacpMethodDescTransparencyData : ZeroInit<DacpMethodDescTransparencyData>
+{
+ BOOL bHasCriticalTransparentInfo;
+ BOOL bIsCritical;
+ BOOL bIsTreatAsSafe;
+
+ HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
+ {
+ return sos->GetMethodDescTransparencyData(addr, this);
+ }
+};
+
+// for JITType
+enum JITTypes {TYPE_UNKNOWN=0,TYPE_JIT,TYPE_PJIT};
+
+struct DacpCodeHeaderData : ZeroInit<DacpCodeHeaderData>
+{
+ CLRDATA_ADDRESS GCInfo;
+ JITTypes JITType;
+ CLRDATA_ADDRESS MethodDescPtr;
+ CLRDATA_ADDRESS MethodStart;
+ DWORD MethodSize;
+ CLRDATA_ADDRESS ColdRegionStart;
+ DWORD ColdRegionSize;
+ DWORD HotRegionSize;
+
+ HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS IPAddr)
+ {
+ return sos->GetCodeHeaderData(IPAddr, this);
+ }
+};
+
+struct DacpWorkRequestData : ZeroInit<DacpWorkRequestData>
+{
+ CLRDATA_ADDRESS Function;
+ CLRDATA_ADDRESS Context;
+ CLRDATA_ADDRESS NextWorkRequest;
+
+ HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
+ {
+ return sos->GetWorkRequestData(addr, this);
+ }
+};
+
+struct DacpHillClimbingLogEntry : ZeroInit<DacpHillClimbingLogEntry>
+{
+ DWORD TickCount;
+ int Transition;
+ int NewControlSetting;
+ int LastHistoryCount;
+ double LastHistoryMean;
+
+ HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS entry)
+ {
+ return sos->GetHillClimbingLogEntry(entry, this);
+ }
+};
+
+
+// Used for CLR versions >= 4.0
+struct DacpThreadpoolData : ZeroInit<DacpThreadpoolData>
+{
+ LONG cpuUtilization;
+ int NumIdleWorkerThreads;
+ int NumWorkingWorkerThreads;
+ int NumRetiredWorkerThreads;
+ LONG MinLimitTotalWorkerThreads;
+ LONG MaxLimitTotalWorkerThreads;
+
+ CLRDATA_ADDRESS FirstUnmanagedWorkRequest;
+
+ CLRDATA_ADDRESS HillClimbingLog;
+ int HillClimbingLogFirstIndex;
+ int HillClimbingLogSize;
+
+ DWORD NumTimers;
+ // TODO: Add support to enumerate timers too.
+
+ LONG NumCPThreads;
+ LONG NumFreeCPThreads;
+ LONG MaxFreeCPThreads;
+ LONG NumRetiredCPThreads;
+ LONG MaxLimitTotalCPThreads;
+ LONG CurrentLimitTotalCPThreads;
+ LONG MinLimitTotalCPThreads;
+
+ CLRDATA_ADDRESS AsyncTimerCallbackCompletionFPtr;
+
+ HRESULT Request(ISOSDacInterface *sos)
+ {
+ return sos->GetThreadpoolData(this);
+ }
+};
+
+struct DacpGenerationData : ZeroInit<DacpGenerationData>
+{
+ CLRDATA_ADDRESS start_segment;
+ CLRDATA_ADDRESS allocation_start;
+
+ // These are examined only for generation 0, otherwise NULL
+ CLRDATA_ADDRESS allocContextPtr;
+ CLRDATA_ADDRESS allocContextLimit;
+};
+
+#define DAC_NUMBERGENERATIONS 4
+
+
+struct DacpAllocData : ZeroInit<DacpAllocData>
+{
+ CLRDATA_ADDRESS allocBytes;
+ CLRDATA_ADDRESS allocBytesLoh;
+};
+
+struct DacpGenerationAllocData : ZeroInit<DacpGenerationAllocData>
+{
+ DacpAllocData allocData[DAC_NUMBERGENERATIONS];
+};
+
+struct DacpGcHeapDetails : ZeroInit<DacpGcHeapDetails>
+{
+ CLRDATA_ADDRESS heapAddr; // Only filled in in server mode, otherwise NULL
+ CLRDATA_ADDRESS alloc_allocated;
+
+ CLRDATA_ADDRESS mark_array;
+ CLRDATA_ADDRESS current_c_gc_state;
+ CLRDATA_ADDRESS next_sweep_obj;
+ CLRDATA_ADDRESS saved_sweep_ephemeral_seg;
+ CLRDATA_ADDRESS saved_sweep_ephemeral_start;
+ CLRDATA_ADDRESS background_saved_lowest_address;
+ CLRDATA_ADDRESS background_saved_highest_address;
+
+ DacpGenerationData generation_table [DAC_NUMBERGENERATIONS];
+ CLRDATA_ADDRESS ephemeral_heap_segment;
+ CLRDATA_ADDRESS finalization_fill_pointers [DAC_NUMBERGENERATIONS + 3];
+ CLRDATA_ADDRESS lowest_address;
+ CLRDATA_ADDRESS highest_address;
+ CLRDATA_ADDRESS card_table;
+
+ // Use this for workstation mode (DacpGcHeapDat.bServerMode==FALSE).
+ HRESULT Request(ISOSDacInterface *sos)
+ {
+ return sos->GetGCHeapStaticData(this);
+ }
+
+ // Use this for Server mode, as there are multiple heaps,
+ // and you need to pass a heap address in addr.
+ HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
+ {
+ return sos->GetGCHeapDetails(addr, this);
+ }
+};
+
+struct DacpGcHeapData
+ : ZeroInit<DacpGcHeapData>
+{
+ BOOL bServerMode;
+ BOOL bGcStructuresValid;
+ UINT HeapCount;
+ UINT g_max_generation;
+
+ HRESULT Request(ISOSDacInterface *sos)
+ {
+ return sos->GetGCHeapData(this);
+ }
+};
+
+struct DacpHeapSegmentData
+ : ZeroInit<DacpHeapSegmentData>
+{
+ CLRDATA_ADDRESS segmentAddr;
+ CLRDATA_ADDRESS allocated;
+ CLRDATA_ADDRESS committed;
+ CLRDATA_ADDRESS reserved;
+ CLRDATA_ADDRESS used;
+ CLRDATA_ADDRESS mem;
+ // pass this to request if non-null to get the next segments.
+ CLRDATA_ADDRESS next;
+ CLRDATA_ADDRESS gc_heap; // only filled in in server mode, otherwise NULL
+ // computed field: if this is the ephemeral segment highMark includes the ephemeral generation
+ CLRDATA_ADDRESS highAllocMark;
+
+ size_t flags;
+ CLRDATA_ADDRESS background_allocated;
+
+ HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr, const DacpGcHeapDetails& heap)
+ {
+ HRESULT hr = sos->GetHeapSegmentData(addr, this);
+
+ // if this is the start segment, set highAllocMark too.
+ if (SUCCEEDED(hr))
+ {
+ // TODO: This needs to be put on the Dac side.
+ if (this->segmentAddr == heap.generation_table[0].start_segment)
+ highAllocMark = heap.alloc_allocated;
+ else
+ highAllocMark = allocated;
+ }
+ return hr;
+ }
+};
+
+struct DacpOomData : ZeroInit<DacpOomData>
+{
+ int reason;
+ ULONG64 alloc_size;
+ ULONG64 available_pagefile_mb;
+ ULONG64 gc_index;
+ int fgm;
+ ULONG64 size;
+ BOOL loh_p;
+
+ HRESULT Request(ISOSDacInterface *sos)
+ {
+ return sos->GetOOMStaticData(this);
+ }
+
+ // Use this for Server mode, as there are multiple heaps,
+ // and you need to pass a heap address in addr.
+ HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
+ {
+ return sos->GetOOMData(addr, this);
+ }
+};
+
+struct DacpGcHeapAnalyzeData
+ : ZeroInit<DacpGcHeapAnalyzeData>
+{
+ CLRDATA_ADDRESS heapAddr; // Only filled in in server mode, otherwise NULL
+
+ CLRDATA_ADDRESS internal_root_array;
+ ULONG64 internal_root_array_index;
+ BOOL heap_analyze_success;
+
+ // Use this for workstation mode (DacpGcHeapDat.bServerMode==FALSE).
+ HRESULT Request(ISOSDacInterface *sos)
+ {
+ return sos->GetHeapAnalyzeStaticData(this);
+ }
+
+ // Use this for Server mode, as there are multiple heaps,
+ // and you need to pass a heap address in addr.
+ HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
+ {
+ return sos->GetHeapAnalyzeData(addr, this);
+ }
+};
+
+
+#define SYNCBLOCKDATA_COMFLAGS_CCW 1
+#define SYNCBLOCKDATA_COMFLAGS_RCW 2
+#define SYNCBLOCKDATA_COMFLAGS_CF 4
+
+struct DacpSyncBlockData : ZeroInit<DacpSyncBlockData>
+{
+ CLRDATA_ADDRESS Object;
+ BOOL bFree; // if set, no other fields are useful
+
+ // fields below provide data from this, so it's just for display
+ CLRDATA_ADDRESS SyncBlockPointer;
+ DWORD COMFlags;
+ UINT MonitorHeld;
+ UINT Recursion;
+ CLRDATA_ADDRESS HoldingThread;
+ UINT AdditionalThreadCount;
+ CLRDATA_ADDRESS appDomainPtr;
+
+ // SyncBlockCount will always be filled in with the number of SyncBlocks.
+ // SyncBlocks may be requested from [1,SyncBlockCount]
+ UINT SyncBlockCount;
+
+ // SyncBlockNumber must be from [1,SyncBlockCount]
+ // If there are no SyncBlocks, a call to Request with SyncBlockCount = 1
+ // will return E_FAIL.
+ HRESULT Request(ISOSDacInterface *sos, UINT SyncBlockNumber)
+ {
+ return sos->GetSyncBlockData(SyncBlockNumber, this);
+ }
+};
+
+struct DacpSyncBlockCleanupData : ZeroInit<DacpSyncBlockCleanupData>
+{
+ CLRDATA_ADDRESS SyncBlockPointer;
+
+ CLRDATA_ADDRESS nextSyncBlock;
+ CLRDATA_ADDRESS blockRCW;
+ CLRDATA_ADDRESS blockClassFactory;
+ CLRDATA_ADDRESS blockCCW;
+
+ // Pass NULL on the first request to start a traversal.
+ HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS psyncBlock)
+ {
+ return sos->GetSyncBlockCleanupData(psyncBlock, this);
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////
+
+enum EHClauseType {EHFault, EHFinally, EHFilter, EHTyped, EHUnknown};
+
+struct DACEHInfo : ZeroInit<DACEHInfo>
+{
+ EHClauseType clauseType;
+ CLRDATA_ADDRESS tryStartOffset;
+ CLRDATA_ADDRESS tryEndOffset;
+ CLRDATA_ADDRESS handlerStartOffset;
+ CLRDATA_ADDRESS handlerEndOffset;
+ BOOL isDuplicateClause;
+ CLRDATA_ADDRESS filterOffset; // valid when clauseType is EHFilter
+ BOOL isCatchAllHandler; // valid when clauseType is EHTyped
+ CLRDATA_ADDRESS moduleAddr; // when == 0 mtCatch contains a MethodTable, when != 0 tokCatch contains a type token
+ CLRDATA_ADDRESS mtCatch; // the method table of the TYPED clause type
+ mdToken tokCatch; // the type token of the TYPED clause type
+};
+
+struct DacpGetModuleAddress : ZeroInit<DacpGetModuleAddress>
+{
+ CLRDATA_ADDRESS ModulePtr;
+ HRESULT Request(IXCLRDataModule* pDataModule)
+ {
+ return pDataModule->Request(DACDATAMODULEPRIV_REQUEST_GET_MODULEPTR,
+ 0, NULL,
+ sizeof(*this), (PBYTE) this);
+ }
+};
+
+struct DacpFrameData : ZeroInit<DacpFrameData>
+{
+ CLRDATA_ADDRESS frameAddr;
+
+ // Could also be implemented for IXCLRDataFrame if desired.
+ HRESULT Request(IXCLRDataStackWalk* dac)
+ {
+ return dac->Request(DACSTACKPRIV_REQUEST_FRAME_DATA,
+ 0, NULL,
+ sizeof(*this), (PBYTE)this);
+ }
+};
+
+struct DacpJitManagerInfo : ZeroInit<DacpJitManagerInfo>
+{
+ CLRDATA_ADDRESS managerAddr;
+ DWORD codeType; // for union below
+ CLRDATA_ADDRESS ptrHeapList; // A HeapList * if IsMiIL(codeType)
+};
+
+typedef enum CodeHeapType {CODEHEAP_LOADER=0,CODEHEAP_HOST,CODEHEAP_UNKNOWN};
+
+struct DacpJitCodeHeapInfo : ZeroInit<DacpJitCodeHeapInfo>
+{
+ DWORD codeHeapType; // for union below
+
+ union
+ {
+ CLRDATA_ADDRESS LoaderHeap; // if CODEHEAP_LOADER
+ struct
+ {
+ CLRDATA_ADDRESS baseAddr; // if CODEHEAP_HOST
+ CLRDATA_ADDRESS currentAddr;
+ } HostData;
+ };
+};
+
+#include "static_assert.h"
+
+/* DAC datastructures are frozen as of dev11 shipping. Do NOT add fields, remove fields, or change the fields of
+ * these structs in any way. The correct way to get new data out of the runtime is to create a new struct and
+ * add a new function to the latest Dac<-->SOS interface to produce this data.
+ */
+static_assert(sizeof(DacpAllocData) == 0x10, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpGenerationAllocData) == 0x40, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpSyncBlockCleanupData) == 0x28, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpThreadStoreData) == 0x38, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpAppDomainStoreData) == 0x18, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpAppDomainData) == 0x48, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpAssemblyData) == 0x40, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpThreadData) == 0x68, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpMethodDescData) == 0x98, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpCodeHeaderData) == 0x38, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpThreadpoolData) == 0x58, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpObjectData) == 0x60, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpMethodTableData) == 0x48, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpWorkRequestData) == 0x18, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpFieldDescData) == 0x40, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpModuleData) == 0xa0, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpGcHeapData) == 0x10, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpJitManagerInfo) == 0x18, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpHeapSegmentData) == 0x58, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpDomainLocalModuleData) == 0x30, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpUsefulGlobalsData) == 0x28, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DACEHInfo) == 0x58, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpRCWData) == 0x58, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpCCWData) == 0x48, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpMethodTableFieldData) == 0x18, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpMethodTableTransparencyData) == 0xc, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpThreadLocalModuleData) == 0x30, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpCOMInterfacePointerData) == 0x18, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpMethodDescTransparencyData) == 0xc, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpHillClimbingLogEntry) == 0x18, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpGenerationData) == 0x20, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpGcHeapDetails) == 0x120, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpOomData) == 0x38, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpGcHeapAnalyzeData) == 0x20, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpSyncBlockData) == 0x48, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpGetModuleAddress) == 0x8, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpFrameData) == 0x8, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpJitCodeHeapInfo) == 0x18, "Dacp structs cannot be modified due to backwards compatibility.");
+static_assert(sizeof(DacpExceptionObjectData) == 0x38, "Dacp structs cannot be modified due to backwards compatibility.");
+
+#endif // _DACPRIVATE_H_