1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4//*****************************************************************************
5//
6// Internal data access functionality.
7//
8//*****************************************************************************
9
10#ifndef _DACPRIVATE_H_
11#define _DACPRIVATE_H_
12
13#include <cor.h>
14#include <clrdata.h>
15#include <xclrdata.h>
16#include <sospriv.h>
17
18#ifndef FEATURE_PAL
19// It is unfortunate having to include this header just to get the definition of GenericModeBlock
20#include <msodw.h>
21#endif // FEATURE_PAL
22
23//
24// Whenever a structure is marshalled between different platforms, we need to ensure the
25// layout is the same in both cases. We tell GCC to use the MSVC-style packing with
26// the following attribute. The main thing this appears to control is whether
27// 8-byte values are aligned at 4-bytes (GCC default) or 8-bytes (MSVC default).
28// This attribute affects only the immediate struct it is applied to, you must also apply
29// it to any nested structs if you want their layout affected as well. You also must
30// apply this to unions embedded in other structures, since it can influence the starting
31// alignment.
32//
33// Note that there doesn't appear to be any disadvantage to applying this a little
34// more agressively than necessary, so we generally use it on all classes / structures
35// defined in a file that defines marshalled data types (eg. DacDbiStructures.h)
36// The -mms-bitfields compiler option also does this for the whole file, but we don't
37// want to go changing the layout of, for example, structures defined in OS header files
38// so we explicitly opt-in with this attribute.
39//
40#ifdef __GNUC__
41#define MSLAYOUT __attribute__((__ms_struct__))
42#else
43#define MSLAYOUT
44#endif
45
46//----------------------------------------------------------------------------
47//
48// Utility class to allow for zero initialization of our Dacp- structs.
49//
50//----------------------------------------------------------------------------
51
52template <class T>
53struct ZeroInit
54{
55 ZeroInit()
56 { memset(static_cast<T*>(this), 0, sizeof(T)); }
57};
58
59
60#include <livedatatarget.h>
61
62//----------------------------------------------------------------------------
63//
64// Internal CLRData requests.
65//
66//----------------------------------------------------------------------------
67
68
69// Private requests for DataModules
70enum
71{
72 DACDATAMODULEPRIV_REQUEST_GET_MODULEPTR = 0xf0000000,
73 DACDATAMODULEPRIV_REQUEST_GET_MODULEDATA = 0xf0000001
74};
75
76
77// Private requests for stack walkers.
78enum
79{
80 DACSTACKPRIV_REQUEST_FRAME_DATA = 0xf0000000
81};
82
83enum DacpObjectType { OBJ_STRING=0,OBJ_FREE,OBJ_OBJECT,OBJ_ARRAY,OBJ_OTHER };
84struct MSLAYOUT DacpObjectData : ZeroInit<DacpObjectData>
85{
86 CLRDATA_ADDRESS MethodTable;
87 DacpObjectType ObjectType;
88 ULONG64 Size;
89 CLRDATA_ADDRESS ElementTypeHandle;
90 CorElementType ElementType;
91 DWORD dwRank;
92 ULONG64 dwNumComponents;
93 ULONG64 dwComponentSize;
94 CLRDATA_ADDRESS ArrayDataPtr;
95 CLRDATA_ADDRESS ArrayBoundsPtr;
96 CLRDATA_ADDRESS ArrayLowerBoundsPtr;
97
98 CLRDATA_ADDRESS RCW;
99 CLRDATA_ADDRESS CCW;
100
101 HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
102 {
103 return sos->GetObjectData(addr, this);
104 }
105};
106
107struct MSLAYOUT DacpExceptionObjectData : ZeroInit<DacpExceptionObjectData>
108{
109 CLRDATA_ADDRESS Message;
110 CLRDATA_ADDRESS InnerException;
111 CLRDATA_ADDRESS StackTrace;
112 CLRDATA_ADDRESS WatsonBuckets;
113 CLRDATA_ADDRESS StackTraceString;
114 CLRDATA_ADDRESS RemoteStackTraceString;
115 INT32 HResult;
116 INT32 XCode;
117
118 HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
119 {
120 HRESULT hr;
121 ISOSDacInterface2 *psos2 = NULL;
122 if (SUCCEEDED(hr = sos->QueryInterface(__uuidof(ISOSDacInterface2), (void**) &psos2)))
123 {
124 hr = psos2->GetObjectExceptionData(addr, this);
125 psos2->Release();
126 }
127 return hr;
128 }
129};
130
131struct MSLAYOUT DacpUsefulGlobalsData : ZeroInit<DacpUsefulGlobalsData>
132{
133 CLRDATA_ADDRESS ArrayMethodTable;
134 CLRDATA_ADDRESS StringMethodTable;
135 CLRDATA_ADDRESS ObjectMethodTable;
136 CLRDATA_ADDRESS ExceptionMethodTable;
137 CLRDATA_ADDRESS FreeMethodTable;
138};
139
140struct MSLAYOUT DacpFieldDescData : ZeroInit<DacpFieldDescData>
141{
142 CorElementType Type;
143 CorElementType sigType; // ELEMENT_TYPE_XXX from signature. We need this to disply pretty name for String in minidump's case
144 CLRDATA_ADDRESS MTOfType; // NULL if Type is not loaded
145
146 CLRDATA_ADDRESS ModuleOfType;
147 mdTypeDef TokenOfType;
148
149 mdFieldDef mb;
150 CLRDATA_ADDRESS MTOfEnclosingClass;
151 DWORD dwOffset;
152 BOOL bIsThreadLocal;
153 BOOL bIsContextLocal;
154 BOOL bIsStatic;
155 CLRDATA_ADDRESS NextField;
156
157 HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
158 {
159 return sos->GetFieldDescData(addr, this);
160 }
161};
162
163struct MSLAYOUT DacpMethodTableFieldData : ZeroInit<DacpMethodTableFieldData>
164{
165 WORD wNumInstanceFields;
166 WORD wNumStaticFields;
167 WORD wNumThreadStaticFields;
168
169 CLRDATA_ADDRESS FirstField; // If non-null, you can retrieve more
170
171 WORD wContextStaticOffset;
172 WORD wContextStaticsSize;
173
174 HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
175 {
176 return sos->GetMethodTableFieldData(addr, this);
177 }
178};
179
180struct MSLAYOUT DacpMethodTableCollectibleData : ZeroInit<DacpMethodTableCollectibleData>
181{
182 CLRDATA_ADDRESS LoaderAllocatorObjectHandle;
183 BOOL bCollectible;
184
185 HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
186 {
187 HRESULT hr;
188 ISOSDacInterface6 *pSOS6 = NULL;
189 if (SUCCEEDED(hr = sos->QueryInterface(__uuidof(ISOSDacInterface6), (void**)&pSOS6)))
190 {
191 hr = pSOS6->GetMethodTableCollectibleData(addr, this);
192 pSOS6->Release();
193 }
194
195 return hr;
196 }
197};
198
199struct MSLAYOUT DacpMethodTableTransparencyData : ZeroInit<DacpMethodTableTransparencyData>
200{
201 BOOL bHasCriticalTransparentInfo;
202 BOOL bIsCritical;
203 BOOL bIsTreatAsSafe;
204
205 HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
206 {
207 return sos->GetMethodTableTransparencyData(addr, this);
208 }
209};
210
211struct MSLAYOUT DacpDomainLocalModuleData : ZeroInit<DacpDomainLocalModuleData>
212{
213 // These two parameters are used as input params when calling the
214 // no-argument form of Request below.
215 CLRDATA_ADDRESS appDomainAddr;
216 ULONG64 ModuleID;
217
218 CLRDATA_ADDRESS pClassData;
219 CLRDATA_ADDRESS pDynamicClassTable;
220 CLRDATA_ADDRESS pGCStaticDataStart;
221 CLRDATA_ADDRESS pNonGCStaticDataStart;
222
223 // Called when you have a pointer to the DomainLocalModule
224 HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
225 {
226 return sos->GetDomainLocalModuleData(addr, this);
227 }
228};
229
230
231struct MSLAYOUT DacpThreadLocalModuleData : ZeroInit<DacpThreadLocalModuleData>
232{
233 // These two parameters are used as input params when calling the
234 // no-argument form of Request below.
235 CLRDATA_ADDRESS threadAddr;
236 ULONG64 ModuleIndex;
237
238 CLRDATA_ADDRESS pClassData;
239 CLRDATA_ADDRESS pDynamicClassTable;
240 CLRDATA_ADDRESS pGCStaticDataStart;
241 CLRDATA_ADDRESS pNonGCStaticDataStart;
242};
243
244
245struct MSLAYOUT DacpModuleData : ZeroInit<DacpModuleData>
246{
247 CLRDATA_ADDRESS Address;
248 CLRDATA_ADDRESS File; // A PEFile addr
249 CLRDATA_ADDRESS ilBase;
250 CLRDATA_ADDRESS metadataStart;
251 ULONG64 metadataSize;
252 CLRDATA_ADDRESS Assembly; // Assembly pointer
253 BOOL bIsReflection;
254 BOOL bIsPEFile;
255 ULONG64 dwBaseClassIndex;
256 ULONG64 dwModuleID;
257
258 DWORD dwTransientFlags;
259
260 CLRDATA_ADDRESS TypeDefToMethodTableMap;
261 CLRDATA_ADDRESS TypeRefToMethodTableMap;
262 CLRDATA_ADDRESS MethodDefToDescMap;
263 CLRDATA_ADDRESS FieldDefToDescMap;
264 CLRDATA_ADDRESS MemberRefToDescMap;
265 CLRDATA_ADDRESS FileReferencesMap;
266 CLRDATA_ADDRESS ManifestModuleReferencesMap;
267
268 CLRDATA_ADDRESS pLookupTableHeap;
269 CLRDATA_ADDRESS pThunkHeap;
270
271 ULONG64 dwModuleIndex;
272
273 DacpModuleData()
274 {
275 }
276
277 HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
278 {
279 return sos->GetModuleData(addr, this);
280 }
281
282private:
283 // Ensure that this data structure is not copied.
284 DacpModuleData(const DacpModuleData&);
285 void operator=(const DacpModuleData&);
286};
287
288struct MSLAYOUT DacpMethodTableData : ZeroInit<DacpMethodTableData>
289{
290 BOOL bIsFree; // everything else is NULL if this is true.
291 CLRDATA_ADDRESS Module;
292 CLRDATA_ADDRESS Class;
293 CLRDATA_ADDRESS ParentMethodTable;
294 WORD wNumInterfaces;
295 WORD wNumMethods;
296 WORD wNumVtableSlots;
297 WORD wNumVirtuals;
298 DWORD BaseSize;
299 DWORD ComponentSize;
300 mdTypeDef cl; // Metadata token
301 DWORD dwAttrClass; // cached metadata
302 BOOL bIsShared; // Always false, preserved for backward compatibility
303 BOOL bIsDynamic;
304 BOOL bContainsPointers;
305
306 HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
307 {
308 return sos->GetMethodTableData(addr, this);
309 }
310};
311
312
313// Copied from util.hpp, for DacpThreadStoreData.fHostConfig below.
314#define CLRMEMORYHOSTED 0x1
315#define CLRTASKHOSTED 0x2
316#define CLRSYNCHOSTED 0x4
317#define CLRTHREADPOOLHOSTED 0x8
318#define CLRIOCOMPLETIONHOSTED 0x10
319#define CLRASSEMBLYHOSTED 0x20
320#define CLRGCHOSTED 0x40
321#define CLRSECURITYHOSTED 0x80
322#define CLRHOSTED 0x80000000
323
324struct MSLAYOUT DacpThreadStoreData : ZeroInit<DacpThreadStoreData>
325{
326 LONG threadCount;
327 LONG unstartedThreadCount;
328 LONG backgroundThreadCount;
329 LONG pendingThreadCount;
330 LONG deadThreadCount;
331 CLRDATA_ADDRESS firstThread;
332 CLRDATA_ADDRESS finalizerThread;
333 CLRDATA_ADDRESS gcThread;
334 DWORD fHostConfig; // Uses hosting flags defined above
335
336 HRESULT Request(ISOSDacInterface *sos)
337 {
338 return sos->GetThreadStoreData(this);
339 }
340};
341
342struct MSLAYOUT DacpAppDomainStoreData : ZeroInit<DacpAppDomainStoreData>
343{
344 CLRDATA_ADDRESS sharedDomain;
345 CLRDATA_ADDRESS systemDomain;
346 LONG DomainCount;
347
348 HRESULT Request(ISOSDacInterface *sos)
349 {
350 return sos->GetAppDomainStoreData(this);
351 }
352};
353
354struct MSLAYOUT DacpCOMInterfacePointerData : ZeroInit<DacpCOMInterfacePointerData>
355{
356 CLRDATA_ADDRESS methodTable;
357 CLRDATA_ADDRESS interfacePtr;
358 CLRDATA_ADDRESS comContext;
359};
360
361struct MSLAYOUT DacpRCWData : ZeroInit<DacpRCWData>
362{
363 CLRDATA_ADDRESS identityPointer;
364 CLRDATA_ADDRESS unknownPointer;
365 CLRDATA_ADDRESS managedObject;
366 CLRDATA_ADDRESS jupiterObject;
367 CLRDATA_ADDRESS vtablePtr;
368 CLRDATA_ADDRESS creatorThread;
369 CLRDATA_ADDRESS ctxCookie;
370
371 LONG refCount;
372 LONG interfaceCount;
373
374 BOOL isJupiterObject;
375 BOOL supportsIInspectable;
376 BOOL isAggregated;
377 BOOL isContained;
378 BOOL isFreeThreaded;
379 BOOL isDisconnected;
380
381 HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS rcw)
382 {
383 return sos->GetRCWData(rcw, this);
384 }
385
386 HRESULT IsDCOMProxy(ISOSDacInterface *sos, CLRDATA_ADDRESS rcw, BOOL* isDCOMProxy)
387 {
388 ISOSDacInterface2 *pSOS2 = nullptr;
389 HRESULT hr = sos->QueryInterface(__uuidof(ISOSDacInterface2), reinterpret_cast<LPVOID*>(&pSOS2));
390 if (SUCCEEDED(hr))
391 {
392 hr = pSOS2->IsRCWDCOMProxy(rcw, isDCOMProxy);
393 pSOS2->Release();
394 }
395
396 return hr;
397 }
398};
399
400struct MSLAYOUT DacpCCWData : ZeroInit<DacpCCWData>
401{
402 CLRDATA_ADDRESS outerIUnknown;
403 CLRDATA_ADDRESS managedObject;
404 CLRDATA_ADDRESS handle;
405 CLRDATA_ADDRESS ccwAddress;
406
407 LONG refCount;
408 LONG interfaceCount;
409 BOOL isNeutered;
410
411 LONG jupiterRefCount;
412 BOOL isPegged;
413 BOOL isGlobalPegged;
414 BOOL hasStrongRef;
415 BOOL isExtendsCOMObject;
416 BOOL isAggregated;
417
418 HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS ccw)
419 {
420 return sos->GetCCWData(ccw, this);
421 }
422};
423
424enum DacpAppDomainDataStage {
425 STAGE_CREATING,
426 STAGE_READYFORMANAGEDCODE,
427 STAGE_ACTIVE,
428 STAGE_OPEN,
429 STAGE_UNLOAD_REQUESTED,
430 STAGE_EXITING,
431 STAGE_EXITED,
432 STAGE_FINALIZING,
433 STAGE_FINALIZED,
434 STAGE_HANDLETABLE_NOACCESS,
435 STAGE_CLEARED,
436 STAGE_COLLECTED,
437 STAGE_CLOSED
438};
439
440// Information about a BaseDomain (AppDomain, SharedDomain or SystemDomain).
441// For types other than AppDomain, some fields (like dwID, DomainLocalBlock, etc.) will be 0/null.
442struct MSLAYOUT DacpAppDomainData : ZeroInit<DacpAppDomainData>
443{
444 // The pointer to the BaseDomain (not necessarily an AppDomain).
445 // It's useful to keep this around in the structure
446 CLRDATA_ADDRESS AppDomainPtr;
447 CLRDATA_ADDRESS AppSecDesc;
448 CLRDATA_ADDRESS pLowFrequencyHeap;
449 CLRDATA_ADDRESS pHighFrequencyHeap;
450 CLRDATA_ADDRESS pStubHeap;
451 CLRDATA_ADDRESS DomainLocalBlock;
452 CLRDATA_ADDRESS pDomainLocalModules;
453 // The creation sequence number of this app domain (starting from 1)
454 DWORD dwId;
455 LONG AssemblyCount;
456 LONG FailedAssemblyCount;
457 DacpAppDomainDataStage appDomainStage;
458
459 HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
460 {
461 return sos->GetAppDomainData(addr, this);
462 }
463};
464
465struct MSLAYOUT DacpAssemblyData : ZeroInit<DacpAssemblyData>
466{
467 CLRDATA_ADDRESS AssemblyPtr; //useful to have
468 CLRDATA_ADDRESS ClassLoader;
469 CLRDATA_ADDRESS ParentDomain;
470 CLRDATA_ADDRESS BaseDomainPtr;
471 CLRDATA_ADDRESS AssemblySecDesc;
472 BOOL isDynamic;
473 UINT ModuleCount;
474 UINT LoadContext;
475 BOOL isDomainNeutral; // Always false, preserved for backward compatibility
476 DWORD dwLocationFlags;
477
478 HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr, CLRDATA_ADDRESS baseDomainPtr)
479 {
480 return sos->GetAssemblyData(baseDomainPtr, addr, this);
481 }
482
483 HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
484 {
485 return Request(sos, addr, NULL);
486 }
487};
488
489
490struct MSLAYOUT DacpThreadData : ZeroInit<DacpThreadData>
491{
492 DWORD corThreadId;
493 DWORD osThreadId;
494 int state;
495 ULONG preemptiveGCDisabled;
496 CLRDATA_ADDRESS allocContextPtr;
497 CLRDATA_ADDRESS allocContextLimit;
498 CLRDATA_ADDRESS context;
499 CLRDATA_ADDRESS domain;
500 CLRDATA_ADDRESS pFrame;
501 DWORD lockCount;
502 CLRDATA_ADDRESS firstNestedException; // Pass this pointer to DacpNestedExceptionInfo
503 CLRDATA_ADDRESS teb;
504 CLRDATA_ADDRESS fiberData;
505 CLRDATA_ADDRESS lastThrownObjectHandle;
506 CLRDATA_ADDRESS nextThread;
507
508 HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
509 {
510 return sos->GetThreadData(addr, this);
511 }
512};
513
514
515struct MSLAYOUT DacpReJitData : ZeroInit<DacpReJitData>
516{
517 enum Flags
518 {
519 kUnknown,
520 kRequested,
521 kActive,
522 kReverted,
523 };
524
525 CLRDATA_ADDRESS rejitID;
526 Flags flags;
527 CLRDATA_ADDRESS NativeCodeAddr;
528};
529
530
531struct MSLAYOUT DacpMethodDescData : ZeroInit<DacpMethodDescData>
532{
533 BOOL bHasNativeCode;
534 BOOL bIsDynamic;
535 WORD wSlotNumber;
536 CLRDATA_ADDRESS NativeCodeAddr;
537 // Useful for breaking when a method is jitted.
538 CLRDATA_ADDRESS AddressOfNativeCodeSlot;
539
540 CLRDATA_ADDRESS MethodDescPtr;
541 CLRDATA_ADDRESS MethodTablePtr;
542 CLRDATA_ADDRESS ModulePtr;
543
544 mdToken MDToken;
545 CLRDATA_ADDRESS GCInfo;
546 CLRDATA_ADDRESS GCStressCodeCopy;
547
548 // This is only valid if bIsDynamic is true
549 CLRDATA_ADDRESS managedDynamicMethodObject;
550
551 CLRDATA_ADDRESS requestedIP;
552
553 // Gives info for the single currently active version of a method
554 DacpReJitData rejitDataCurrent;
555
556 // Gives info corresponding to requestedIP (for !ip2md)
557 DacpReJitData rejitDataRequested;
558
559 // Total number of rejit versions that have been jitted
560 ULONG cJittedRejitVersions;
561
562 HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
563 {
564 return sos->GetMethodDescData(
565 addr,
566 NULL, // IP address
567 this,
568 0, // cRejitData
569 NULL, // rejitData[]
570 NULL // pcNeededRejitData
571 );
572 }
573};
574
575
576struct MSLAYOUT DacpMethodDescTransparencyData : ZeroInit<DacpMethodDescTransparencyData>
577{
578 BOOL bHasCriticalTransparentInfo;
579 BOOL bIsCritical;
580 BOOL bIsTreatAsSafe;
581
582 HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
583 {
584 return sos->GetMethodDescTransparencyData(addr, this);
585 }
586};
587
588struct MSLAYOUT DacpTieredVersionData
589{
590 enum TieredState
591 {
592 NON_TIERED,
593 TIERED_0,
594 TIERED_1,
595 TIERED_UNKNOWN
596 };
597
598 CLRDATA_ADDRESS NativeCodeAddr;
599 TieredState TieredInfo;
600 CLRDATA_ADDRESS NativeCodeVersionNodePtr;
601};
602
603// for JITType
604enum JITTypes {TYPE_UNKNOWN=0,TYPE_JIT,TYPE_PJIT};
605
606struct MSLAYOUT DacpCodeHeaderData : ZeroInit<DacpCodeHeaderData>
607{
608 CLRDATA_ADDRESS GCInfo;
609 JITTypes JITType;
610 CLRDATA_ADDRESS MethodDescPtr;
611 CLRDATA_ADDRESS MethodStart;
612 DWORD MethodSize;
613 CLRDATA_ADDRESS ColdRegionStart;
614 DWORD ColdRegionSize;
615 DWORD HotRegionSize;
616
617 HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS IPAddr)
618 {
619 return sos->GetCodeHeaderData(IPAddr, this);
620 }
621};
622
623struct MSLAYOUT DacpWorkRequestData : ZeroInit<DacpWorkRequestData>
624{
625 CLRDATA_ADDRESS Function;
626 CLRDATA_ADDRESS Context;
627 CLRDATA_ADDRESS NextWorkRequest;
628
629 HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
630 {
631 return sos->GetWorkRequestData(addr, this);
632 }
633};
634
635struct MSLAYOUT DacpHillClimbingLogEntry : ZeroInit<DacpHillClimbingLogEntry>
636{
637 DWORD TickCount;
638 int Transition;
639 int NewControlSetting;
640 int LastHistoryCount;
641 double LastHistoryMean;
642
643 HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS entry)
644 {
645 return sos->GetHillClimbingLogEntry(entry, this);
646 }
647};
648
649
650// Used for CLR versions >= 4.0
651struct MSLAYOUT DacpThreadpoolData : ZeroInit<DacpThreadpoolData>
652{
653 LONG cpuUtilization;
654 int NumIdleWorkerThreads;
655 int NumWorkingWorkerThreads;
656 int NumRetiredWorkerThreads;
657 LONG MinLimitTotalWorkerThreads;
658 LONG MaxLimitTotalWorkerThreads;
659
660 CLRDATA_ADDRESS FirstUnmanagedWorkRequest;
661
662 CLRDATA_ADDRESS HillClimbingLog;
663 int HillClimbingLogFirstIndex;
664 int HillClimbingLogSize;
665
666 DWORD NumTimers;
667 // TODO: Add support to enumerate timers too.
668
669 LONG NumCPThreads;
670 LONG NumFreeCPThreads;
671 LONG MaxFreeCPThreads;
672 LONG NumRetiredCPThreads;
673 LONG MaxLimitTotalCPThreads;
674 LONG CurrentLimitTotalCPThreads;
675 LONG MinLimitTotalCPThreads;
676
677 CLRDATA_ADDRESS AsyncTimerCallbackCompletionFPtr;
678
679 HRESULT Request(ISOSDacInterface *sos)
680 {
681 return sos->GetThreadpoolData(this);
682 }
683};
684
685struct MSLAYOUT DacpGenerationData : ZeroInit<DacpGenerationData>
686{
687 CLRDATA_ADDRESS start_segment;
688 CLRDATA_ADDRESS allocation_start;
689
690 // These are examined only for generation 0, otherwise NULL
691 CLRDATA_ADDRESS allocContextPtr;
692 CLRDATA_ADDRESS allocContextLimit;
693};
694
695#define DAC_NUMBERGENERATIONS 4
696
697
698struct MSLAYOUT DacpAllocData : ZeroInit<DacpAllocData>
699{
700 CLRDATA_ADDRESS allocBytes;
701 CLRDATA_ADDRESS allocBytesLoh;
702};
703
704struct MSLAYOUT DacpGenerationAllocData : ZeroInit<DacpGenerationAllocData>
705{
706 DacpAllocData allocData[DAC_NUMBERGENERATIONS];
707};
708
709struct MSLAYOUT DacpGcHeapDetails : ZeroInit<DacpGcHeapDetails>
710{
711 CLRDATA_ADDRESS heapAddr; // Only filled in in server mode, otherwise NULL
712 CLRDATA_ADDRESS alloc_allocated;
713
714 CLRDATA_ADDRESS mark_array;
715 CLRDATA_ADDRESS current_c_gc_state;
716 CLRDATA_ADDRESS next_sweep_obj;
717 CLRDATA_ADDRESS saved_sweep_ephemeral_seg;
718 CLRDATA_ADDRESS saved_sweep_ephemeral_start;
719 CLRDATA_ADDRESS background_saved_lowest_address;
720 CLRDATA_ADDRESS background_saved_highest_address;
721
722 DacpGenerationData generation_table [DAC_NUMBERGENERATIONS];
723 CLRDATA_ADDRESS ephemeral_heap_segment;
724 CLRDATA_ADDRESS finalization_fill_pointers [DAC_NUMBERGENERATIONS + 3];
725 CLRDATA_ADDRESS lowest_address;
726 CLRDATA_ADDRESS highest_address;
727 CLRDATA_ADDRESS card_table;
728
729 // Use this for workstation mode (DacpGcHeapDat.bServerMode==FALSE).
730 HRESULT Request(ISOSDacInterface *sos)
731 {
732 return sos->GetGCHeapStaticData(this);
733 }
734
735 // Use this for Server mode, as there are multiple heaps,
736 // and you need to pass a heap address in addr.
737 HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
738 {
739 return sos->GetGCHeapDetails(addr, this);
740 }
741};
742
743struct MSLAYOUT DacpGcHeapData
744 : ZeroInit<DacpGcHeapData>
745{
746 BOOL bServerMode;
747 BOOL bGcStructuresValid;
748 UINT HeapCount;
749 UINT g_max_generation;
750
751 HRESULT Request(ISOSDacInterface *sos)
752 {
753 return sos->GetGCHeapData(this);
754 }
755};
756
757struct MSLAYOUT DacpHeapSegmentData
758 : ZeroInit<DacpHeapSegmentData>
759{
760 CLRDATA_ADDRESS segmentAddr;
761 CLRDATA_ADDRESS allocated;
762 CLRDATA_ADDRESS committed;
763 CLRDATA_ADDRESS reserved;
764 CLRDATA_ADDRESS used;
765 CLRDATA_ADDRESS mem;
766 // pass this to request if non-null to get the next segments.
767 CLRDATA_ADDRESS next;
768 CLRDATA_ADDRESS gc_heap; // only filled in in server mode, otherwise NULL
769 // computed field: if this is the ephemeral segment highMark includes the ephemeral generation
770 CLRDATA_ADDRESS highAllocMark;
771
772 size_t flags;
773 CLRDATA_ADDRESS background_allocated;
774
775 HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr, const DacpGcHeapDetails& heap)
776 {
777 HRESULT hr = sos->GetHeapSegmentData(addr, this);
778
779 // if this is the start segment, set highAllocMark too.
780 if (SUCCEEDED(hr))
781 {
782 // TODO: This needs to be put on the Dac side.
783 if (this->segmentAddr == heap.generation_table[0].start_segment)
784 highAllocMark = heap.alloc_allocated;
785 else
786 highAllocMark = allocated;
787 }
788 return hr;
789 }
790};
791
792struct MSLAYOUT DacpOomData : ZeroInit<DacpOomData>
793{
794 int reason;
795 ULONG64 alloc_size;
796 ULONG64 available_pagefile_mb;
797 ULONG64 gc_index;
798 int fgm;
799 ULONG64 size;
800 BOOL loh_p;
801
802 HRESULT Request(ISOSDacInterface *sos)
803 {
804 return sos->GetOOMStaticData(this);
805 }
806
807 // Use this for Server mode, as there are multiple heaps,
808 // and you need to pass a heap address in addr.
809 HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
810 {
811 return sos->GetOOMData(addr, this);
812 }
813};
814
815#define DAC_NUM_GC_DATA_POINTS 9
816#define DAC_MAX_COMPACT_REASONS_COUNT 11
817#define DAC_MAX_EXPAND_MECHANISMS_COUNT 6
818#define DAC_MAX_GC_MECHANISM_BITS_COUNT 2
819#define DAC_MAX_GLOBAL_GC_MECHANISMS_COUNT 6
820struct MSLAYOUT DacpGCInterestingInfoData : ZeroInit<DacpGCInterestingInfoData>
821{
822 size_t interestingDataPoints[DAC_NUM_GC_DATA_POINTS];
823 size_t compactReasons[DAC_MAX_COMPACT_REASONS_COUNT];
824 size_t expandMechanisms[DAC_MAX_EXPAND_MECHANISMS_COUNT];
825 size_t bitMechanisms[DAC_MAX_GC_MECHANISM_BITS_COUNT];
826 size_t globalMechanisms[DAC_MAX_GLOBAL_GC_MECHANISMS_COUNT];
827
828 HRESULT RequestGlobal(ISOSDacInterface *sos)
829 {
830 HRESULT hr;
831 ISOSDacInterface3 *psos3 = NULL;
832 if (SUCCEEDED(hr = sos->QueryInterface(__uuidof(ISOSDacInterface3), (void**) &psos3)))
833 {
834 hr = psos3->GetGCGlobalMechanisms(globalMechanisms);
835 psos3->Release();
836 }
837 return hr;
838 }
839
840 HRESULT Request(ISOSDacInterface *sos)
841 {
842 HRESULT hr;
843 ISOSDacInterface3 *psos3 = NULL;
844 if (SUCCEEDED(hr = sos->QueryInterface(__uuidof(ISOSDacInterface3), (void**) &psos3)))
845 {
846 hr = psos3->GetGCInterestingInfoStaticData(this);
847 psos3->Release();
848 }
849 return hr;
850 }
851
852 // Use this for Server mode, as there are multiple heaps,
853 // and you need to pass a heap address in addr.
854 HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
855 {
856 HRESULT hr;
857 ISOSDacInterface3 *psos3 = NULL;
858 if (SUCCEEDED(hr = sos->QueryInterface(__uuidof(ISOSDacInterface3), (void**) &psos3)))
859 {
860 hr = psos3->GetGCInterestingInfoData(addr, this);
861 psos3->Release();
862 }
863 return hr;
864 }
865};
866
867struct MSLAYOUT DacpGcHeapAnalyzeData
868 : ZeroInit<DacpGcHeapAnalyzeData>
869{
870 CLRDATA_ADDRESS heapAddr; // Only filled in in server mode, otherwise NULL
871
872 CLRDATA_ADDRESS internal_root_array;
873 ULONG64 internal_root_array_index;
874 BOOL heap_analyze_success;
875
876 // Use this for workstation mode (DacpGcHeapDat.bServerMode==FALSE).
877 HRESULT Request(ISOSDacInterface *sos)
878 {
879 return sos->GetHeapAnalyzeStaticData(this);
880 }
881
882 // Use this for Server mode, as there are multiple heaps,
883 // and you need to pass a heap address in addr.
884 HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
885 {
886 return sos->GetHeapAnalyzeData(addr, this);
887 }
888};
889
890
891#define SYNCBLOCKDATA_COMFLAGS_CCW 1
892#define SYNCBLOCKDATA_COMFLAGS_RCW 2
893#define SYNCBLOCKDATA_COMFLAGS_CF 4
894
895struct MSLAYOUT DacpSyncBlockData : ZeroInit<DacpSyncBlockData>
896{
897 CLRDATA_ADDRESS Object;
898 BOOL bFree; // if set, no other fields are useful
899
900 // fields below provide data from this, so it's just for display
901 CLRDATA_ADDRESS SyncBlockPointer;
902 DWORD COMFlags;
903 UINT MonitorHeld;
904 UINT Recursion;
905 CLRDATA_ADDRESS HoldingThread;
906 UINT AdditionalThreadCount;
907 CLRDATA_ADDRESS appDomainPtr;
908
909 // SyncBlockCount will always be filled in with the number of SyncBlocks.
910 // SyncBlocks may be requested from [1,SyncBlockCount]
911 UINT SyncBlockCount;
912
913 // SyncBlockNumber must be from [1,SyncBlockCount]
914 // If there are no SyncBlocks, a call to Request with SyncBlockCount = 1
915 // will return E_FAIL.
916 HRESULT Request(ISOSDacInterface *sos, UINT SyncBlockNumber)
917 {
918 return sos->GetSyncBlockData(SyncBlockNumber, this);
919 }
920};
921
922struct MSLAYOUT DacpSyncBlockCleanupData : ZeroInit<DacpSyncBlockCleanupData>
923{
924 CLRDATA_ADDRESS SyncBlockPointer;
925
926 CLRDATA_ADDRESS nextSyncBlock;
927 CLRDATA_ADDRESS blockRCW;
928 CLRDATA_ADDRESS blockClassFactory;
929 CLRDATA_ADDRESS blockCCW;
930
931 // Pass NULL on the first request to start a traversal.
932 HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS psyncBlock)
933 {
934 return sos->GetSyncBlockCleanupData(psyncBlock, this);
935 }
936};
937
938///////////////////////////////////////////////////////////////////////////
939
940enum EHClauseType {EHFault, EHFinally, EHFilter, EHTyped, EHUnknown};
941
942struct MSLAYOUT DACEHInfo : ZeroInit<DACEHInfo>
943{
944 EHClauseType clauseType;
945 CLRDATA_ADDRESS tryStartOffset;
946 CLRDATA_ADDRESS tryEndOffset;
947 CLRDATA_ADDRESS handlerStartOffset;
948 CLRDATA_ADDRESS handlerEndOffset;
949 BOOL isDuplicateClause;
950 CLRDATA_ADDRESS filterOffset; // valid when clauseType is EHFilter
951 BOOL isCatchAllHandler; // valid when clauseType is EHTyped
952 CLRDATA_ADDRESS moduleAddr; // when == 0 mtCatch contains a MethodTable, when != 0 tokCatch contains a type token
953 CLRDATA_ADDRESS mtCatch; // the method table of the TYPED clause type
954 mdToken tokCatch; // the type token of the TYPED clause type
955};
956
957struct MSLAYOUT DacpGetModuleAddress : ZeroInit<DacpGetModuleAddress>
958{
959 CLRDATA_ADDRESS ModulePtr;
960 HRESULT Request(IXCLRDataModule* pDataModule)
961 {
962 return pDataModule->Request(DACDATAMODULEPRIV_REQUEST_GET_MODULEPTR, 0, NULL, sizeof(*this), (PBYTE) this);
963 }
964};
965
966struct MSLAYOUT DacpGetModuleData : ZeroInit<DacpGetModuleData>
967{
968 BOOL IsDynamic;
969 BOOL IsInMemory;
970 BOOL IsFileLayout;
971 CLRDATA_ADDRESS PEFile;
972 CLRDATA_ADDRESS LoadedPEAddress;
973 ULONG64 LoadedPESize;
974 CLRDATA_ADDRESS InMemoryPdbAddress;
975 ULONG64 InMemoryPdbSize;
976
977 HRESULT Request(IXCLRDataModule* pDataModule)
978 {
979 return pDataModule->Request(DACDATAMODULEPRIV_REQUEST_GET_MODULEDATA, 0, NULL, sizeof(*this), (PBYTE) this);
980 }
981};
982
983struct MSLAYOUT DacpFrameData : ZeroInit<DacpFrameData>
984{
985 CLRDATA_ADDRESS frameAddr;
986
987 // Could also be implemented for IXCLRDataFrame if desired.
988 HRESULT Request(IXCLRDataStackWalk* dac)
989 {
990 return dac->Request(DACSTACKPRIV_REQUEST_FRAME_DATA,
991 0, NULL,
992 sizeof(*this), (PBYTE)this);
993 }
994};
995
996struct MSLAYOUT DacpJitManagerInfo : ZeroInit<DacpJitManagerInfo>
997{
998 CLRDATA_ADDRESS managerAddr;
999 DWORD codeType; // for union below
1000 CLRDATA_ADDRESS ptrHeapList; // A HeapList * if IsMiIL(codeType)
1001};
1002
1003enum CodeHeapType {CODEHEAP_LOADER=0,CODEHEAP_HOST,CODEHEAP_UNKNOWN};
1004
1005struct MSLAYOUT DacpJitCodeHeapInfo : ZeroInit<DacpJitCodeHeapInfo>
1006{
1007 DWORD codeHeapType; // for union below
1008
1009 union
1010 {
1011 CLRDATA_ADDRESS LoaderHeap; // if CODEHEAP_LOADER
1012 struct MSLAYOUT
1013 {
1014 CLRDATA_ADDRESS baseAddr; // if CODEHEAP_HOST
1015 CLRDATA_ADDRESS currentAddr;
1016 } HostData;
1017 };
1018};
1019
1020#include "static_assert.h"
1021
1022/* DAC datastructures are frozen as of dev11 shipping. Do NOT add fields, remove fields, or change the fields of
1023 * these structs in any way. The correct way to get new data out of the runtime is to create a new struct and
1024 * add a new function to the latest Dac<-->SOS interface to produce this data.
1025 */
1026static_assert(sizeof(DacpAllocData) == 0x10, "Dacp structs cannot be modified due to backwards compatibility.");
1027static_assert(sizeof(DacpGenerationAllocData) == 0x40, "Dacp structs cannot be modified due to backwards compatibility.");
1028static_assert(sizeof(DacpSyncBlockCleanupData) == 0x28, "Dacp structs cannot be modified due to backwards compatibility.");
1029static_assert(sizeof(DacpThreadStoreData) == 0x38, "Dacp structs cannot be modified due to backwards compatibility.");
1030static_assert(sizeof(DacpAppDomainStoreData) == 0x18, "Dacp structs cannot be modified due to backwards compatibility.");
1031static_assert(sizeof(DacpAppDomainData) == 0x48, "Dacp structs cannot be modified due to backwards compatibility.");
1032static_assert(sizeof(DacpAssemblyData) == 0x40, "Dacp structs cannot be modified due to backwards compatibility.");
1033static_assert(sizeof(DacpThreadData) == 0x68, "Dacp structs cannot be modified due to backwards compatibility.");
1034static_assert(sizeof(DacpMethodDescData) == 0x98, "Dacp structs cannot be modified due to backwards compatibility.");
1035static_assert(sizeof(DacpCodeHeaderData) == 0x38, "Dacp structs cannot be modified due to backwards compatibility.");
1036static_assert(sizeof(DacpThreadpoolData) == 0x58, "Dacp structs cannot be modified due to backwards compatibility.");
1037static_assert(sizeof(DacpObjectData) == 0x60, "Dacp structs cannot be modified due to backwards compatibility.");
1038static_assert(sizeof(DacpMethodTableData) == 0x48, "Dacp structs cannot be modified due to backwards compatibility.");
1039static_assert(sizeof(DacpWorkRequestData) == 0x18, "Dacp structs cannot be modified due to backwards compatibility.");
1040static_assert(sizeof(DacpFieldDescData) == 0x40, "Dacp structs cannot be modified due to backwards compatibility.");
1041static_assert(sizeof(DacpModuleData) == 0xa0, "Dacp structs cannot be modified due to backwards compatibility.");
1042static_assert(sizeof(DacpGcHeapData) == 0x10, "Dacp structs cannot be modified due to backwards compatibility.");
1043static_assert(sizeof(DacpJitManagerInfo) == 0x18, "Dacp structs cannot be modified due to backwards compatibility.");
1044static_assert(sizeof(DacpHeapSegmentData) == 0x58, "Dacp structs cannot be modified due to backwards compatibility.");
1045static_assert(sizeof(DacpDomainLocalModuleData) == 0x30, "Dacp structs cannot be modified due to backwards compatibility.");
1046static_assert(sizeof(DacpUsefulGlobalsData) == 0x28, "Dacp structs cannot be modified due to backwards compatibility.");
1047static_assert(sizeof(DACEHInfo) == 0x58, "Dacp structs cannot be modified due to backwards compatibility.");
1048static_assert(sizeof(DacpRCWData) == 0x58, "Dacp structs cannot be modified due to backwards compatibility.");
1049static_assert(sizeof(DacpCCWData) == 0x48, "Dacp structs cannot be modified due to backwards compatibility.");
1050static_assert(sizeof(DacpMethodTableFieldData) == 0x18, "Dacp structs cannot be modified due to backwards compatibility.");
1051static_assert(sizeof(DacpMethodTableTransparencyData) == 0xc, "Dacp structs cannot be modified due to backwards compatibility.");
1052static_assert(sizeof(DacpThreadLocalModuleData) == 0x30, "Dacp structs cannot be modified due to backwards compatibility.");
1053static_assert(sizeof(DacpCOMInterfacePointerData) == 0x18, "Dacp structs cannot be modified due to backwards compatibility.");
1054static_assert(sizeof(DacpMethodDescTransparencyData) == 0xc, "Dacp structs cannot be modified due to backwards compatibility.");
1055static_assert(sizeof(DacpHillClimbingLogEntry) == 0x18, "Dacp structs cannot be modified due to backwards compatibility.");
1056static_assert(sizeof(DacpGenerationData) == 0x20, "Dacp structs cannot be modified due to backwards compatibility.");
1057static_assert(sizeof(DacpGcHeapDetails) == 0x120, "Dacp structs cannot be modified due to backwards compatibility.");
1058static_assert(sizeof(DacpOomData) == 0x38, "Dacp structs cannot be modified due to backwards compatibility.");
1059static_assert(sizeof(DacpGcHeapAnalyzeData) == 0x20, "Dacp structs cannot be modified due to backwards compatibility.");
1060static_assert(sizeof(DacpSyncBlockData) == 0x48, "Dacp structs cannot be modified due to backwards compatibility.");
1061static_assert(sizeof(DacpGetModuleAddress) == 0x8, "Dacp structs cannot be modified due to backwards compatibility.");
1062static_assert(sizeof(DacpFrameData) == 0x8, "Dacp structs cannot be modified due to backwards compatibility.");
1063static_assert(sizeof(DacpJitCodeHeapInfo) == 0x18, "Dacp structs cannot be modified due to backwards compatibility.");
1064static_assert(sizeof(DacpExceptionObjectData) == 0x38, "Dacp structs cannot be modified due to backwards compatibility.");
1065static_assert(sizeof(DacpMethodTableCollectibleData) == 0x10, "Dacp structs cannot be modified due to backwards compatibility.");
1066
1067#endif // _DACPRIVATE_H_
1068