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// File: dacimpl.h
6//
7
8//
9// Central header file for external data access implementation.
10//
11//*****************************************************************************
12
13
14#ifndef __DACIMPL_H__
15#define __DACIMPL_H__
16
17#include "gcinterface.dac.h"
18
19#if defined(_TARGET_ARM_) || defined(FEATURE_CORESYSTEM) // @ARMTODO: STL breaks the build with current VC headers
20//---------------------------------------------------------------------------------------
21// Setting DAC_HASHTABLE tells the DAC to use the hand rolled hashtable for
22// storing code:DAC_INSTANCE . Otherwise, the DAC uses the STL unordered_map to.
23
24#define DAC_HASHTABLE
25#endif // _TARGET_ARM_|| FEATURE_CORESYSTEM
26
27#ifndef DAC_HASHTABLE
28#pragma push_macro("return")
29#undef return
30#include <unordered_map>
31#pragma pop_macro("return")
32#endif //DAC_HASHTABLE
33extern CRITICAL_SECTION g_dacCritSec;
34
35// Convert between CLRDATA_ADDRESS and TADDR.
36// Note that CLRDATA_ADDRESS is sign-extended (for compat with Windbg and OS conventions). Converting
37// from pointer-size values to CLRDATA_ADDRESS should ALWAYS use this TO_CDADDR macro to avoid bugs when
38// dealing with 3/4GB 32-bit address spaces. You must not rely on the compiler's implicit conversion
39// from ULONG32 to ULONG64 - it is incorrect. Ideally we'd use some compiler tricks or static analysis
40// to help detect such errors (they are nefarious since 3/4GB addresses aren't well tested) .
41//
42// Note: We're in the process of switching the implementation over to CORDB_ADDRESS instead, which is also
43// 64 bits, but 0-extended. This means that conversions between TADDR and CORDB_ADDRESS are simple and natural,
44// but as long as we have some legacy code, conversions involving CLRDATA_ADDRESS are a pain. Eventually we
45// should eliminate CLRDATA_ADDRESS entirely from the implementation, but that will require moving SOS off of
46// the old DAC stuff etc.
47//
48// Here are the possible conversions:
49// TADDR -> CLRDATA_ADDRESS: TO_CDADDR
50// CORDB_ADDRESS -> CLRDATA_ADDRESS: TO_CDADDR
51// CLRDATA_ADDRESS -> TADDR: CLRDATA_ADDRESS_TO_TADDR
52// CORDB_ADDRESS -> TADDR: CORDB_ADDRESS_TO_TADDR
53// TADDR -> CORDB_ADDRESS: implicit
54// CLRDATA_ADDRESS -> CORDB_ADDRESS: CLRDATA_ADDRESS_TO_TADDR
55//
56#define TO_CDADDR(taddr) ((CLRDATA_ADDRESS)(LONG_PTR)(taddr))
57
58// Convert a CLRDATA_ADDRESS (64-bit unsigned sign-extended target address) to a TADDR
59inline TADDR CLRDATA_ADDRESS_TO_TADDR(CLRDATA_ADDRESS cdAddr)
60{
61 SUPPORTS_DAC;
62#ifndef _WIN64
63 static_assert_no_msg(sizeof(TADDR)==sizeof(UINT));
64 INT64 iSignedAddr = (INT64)cdAddr;
65 if (iSignedAddr > INT_MAX || iSignedAddr < INT_MIN)
66 {
67 _ASSERTE_MSG(false, "CLRDATA_ADDRESS out of range for this platform");
68 DacError(E_INVALIDARG);
69 }
70#endif
71 return (TADDR)cdAddr;
72}
73
74// No throw, Convert a CLRDATA_ADDRESS (64-bit unsigned sign-extended target address) to a TADDR
75// Use this in places where we know windbg may pass in bad addresses
76inline HRESULT TRY_CLRDATA_ADDRESS_TO_TADDR(CLRDATA_ADDRESS cdAddr, TADDR* pOutTaddr)
77{
78 SUPPORTS_DAC;
79#ifndef _WIN64
80 static_assert_no_msg(sizeof(TADDR)==sizeof(UINT));
81 INT64 iSignedAddr = (INT64)cdAddr;
82 if (iSignedAddr > INT_MAX || iSignedAddr < INT_MIN)
83 {
84 *pOutTaddr = 0;
85 return E_INVALIDARG;
86 }
87#endif
88 *pOutTaddr = (TADDR)cdAddr;
89 return S_OK;
90}
91
92// Convert a CORDB_ADDRESS (64-bit unsigned 0-extended target address) to a TADDR
93inline TADDR CORDB_ADDRESS_TO_TADDR(CORDB_ADDRESS cdbAddr)
94{
95 SUPPORTS_DAC;
96#ifndef _WIN64
97 static_assert_no_msg(sizeof(TADDR)==sizeof(UINT));
98 if (cdbAddr > UINT_MAX)
99 {
100 _ASSERTE_MSG(false, "CORDB_ADDRESS out of range for this platform");
101 DacError(E_INVALIDARG);
102 }
103#endif
104 return (TADDR)cdbAddr;
105}
106
107// TO_TADDR is the old way of converting CLRDATA_ADDRESSes to TADDRs. Unfortunately,
108// this has been used in many places to also cast pointers (void* etc.) to TADDR, and
109// so we can't actually require the argument to be a valid CLRDATA_ADDRESS. New code
110// should use CLRDATA_ADDRESS_TO_TADDR instead.
111#define TO_TADDR(cdaddr) ((TADDR)(cdaddr))
112
113#define TO_CDENUM(ptr) ((CLRDATA_ENUM)(ULONG_PTR)(ptr))
114#define FROM_CDENUM(type, cdenum) ((type*)(ULONG_PTR)(cdenum))
115
116#define SIMPFRAME_ALL \
117 (CLRDATA_SIMPFRAME_UNRECOGNIZED | \
118 CLRDATA_SIMPFRAME_MANAGED_METHOD | \
119 CLRDATA_SIMPFRAME_RUNTIME_MANAGED_CODE | \
120 CLRDATA_SIMPFRAME_RUNTIME_UNMANAGED_CODE)
121
122enum DAC_USAGE_TYPE
123{
124 DAC_DPTR,
125 DAC_VPTR,
126 DAC_STRA,
127 DAC_STRW,
128 DAC_PAL,
129};
130
131// mscordacwks's module handle
132extern HINSTANCE g_thisModule;
133
134class ReflectionModule;
135
136struct DAC_MD_IMPORT
137{
138 DAC_MD_IMPORT* next; // list link field
139 TADDR peFile; // a TADDR for a PEFile* or a ReflectionModule*
140 IMDInternalImport* impl; // Associated metadata interface
141 bool isAlternate; // for NGEN images set to true if the metadata corresponds to the IL image
142
143 DAC_MD_IMPORT(TADDR peFile_,
144 IMDInternalImport* impl_,
145 bool isAlt_ = false,
146 DAC_MD_IMPORT* next_ = NULL)
147 : next(next_)
148 , peFile(peFile_)
149 , impl(impl_)
150 , isAlternate(isAlt_)
151 {
152 SUPPORTS_DAC_HOST_ONLY;
153 }
154};
155
156
157// This class maintains a cache of IMDInternalImport* and their corresponding
158// source (a PEFile* or a ReflectionModule*), as a singly-linked list of
159// DAC_MD_IMPORT nodes. The cache is flushed whenever the process state changes
160// by calling its Flush() member function.
161class MDImportsCache
162{
163public:
164
165 MDImportsCache()
166 : m_head(NULL)
167 {}
168
169 ~MDImportsCache()
170 {
171 Flush();
172 }
173
174 FORCEINLINE
175 IMDInternalImport* Get(TADDR key) const
176 {
177 SUPPORTS_DAC;
178 for (DAC_MD_IMPORT* importList = m_head; importList; importList = importList->next)
179 {
180 if (importList->peFile == key)
181 {
182 return importList->impl;
183 }
184 }
185 return NULL;
186 }
187
188 FORCEINLINE
189 DAC_MD_IMPORT* Add(TADDR peFile, IMDInternalImport* impl, bool isAlt)
190 {
191 SUPPORTS_DAC;
192 DAC_MD_IMPORT* importList = new (nothrow) DAC_MD_IMPORT(peFile, impl, isAlt, m_head);
193 if (!importList)
194 {
195 return NULL;
196 }
197
198 m_head = importList;
199 return importList;
200 }
201
202 void Flush()
203 {
204 DAC_MD_IMPORT* importList;
205
206 while (m_head)
207 {
208 importList = m_head;
209 m_head = importList->next;
210 importList->impl->Release();
211 delete importList;
212 }
213 }
214
215private:
216
217 DAC_MD_IMPORT* m_head; // the beginning of the list of cached MD imports
218
219};
220
221struct METH_EXTENTS
222{
223 ULONG32 numExtents;
224 ULONG32 curExtent;
225 // Currently only one is needed.
226 CLRDATA_ADDRESS_RANGE extents[1];
227};
228
229HRESULT ConvertUtf8(__in LPCUTF8 utf8,
230 ULONG32 bufLen,
231 ULONG32* nameLen,
232 __out_ecount_part_opt(bufLen, *nameLen) PWSTR buffer);
233HRESULT AllocUtf8(__in_opt LPCWSTR wstr,
234 ULONG32 srcChars,
235 __deref_out LPUTF8* utf8);
236
237HRESULT GetFullClassNameFromMetadata(IMDInternalImport* mdImport,
238 mdTypeDef classToken,
239 ULONG32 bufferChars,
240 __inout_ecount(bufferChars) LPUTF8 buffer);
241HRESULT GetFullMethodNameFromMetadata(IMDInternalImport* mdImport,
242 mdMethodDef methodToken,
243 ULONG32 bufferChars,
244 __inout_ecount(bufferChars) LPUTF8 buffer);
245
246enum SplitSyntax
247{
248 SPLIT_METHOD,
249 SPLIT_TYPE,
250 SPLIT_FIELD,
251 SPLIT_NO_NAME,
252};
253
254HRESULT SplitFullName(__in_z __in PCWSTR fullName,
255 SplitSyntax syntax,
256 ULONG32 memberDots,
257 __deref_out_opt LPUTF8* namespaceName,
258 __deref_out_opt LPUTF8* typeName,
259 __deref_out_opt LPUTF8* memberName,
260 __deref_out_opt LPUTF8* params);
261
262int CompareUtf8(__in LPCUTF8 str1, __in LPCUTF8 str2, __in ULONG32 nameFlags);
263
264#define INH_STATIC \
265 (CLRDATA_VALUE_ALL_KINDS | \
266 CLRDATA_VALUE_IS_INHERITED | CLRDATA_VALUE_FROM_STATIC)
267
268HRESULT InitFieldIter(DeepFieldDescIterator* fieldIter,
269 TypeHandle typeHandle,
270 bool canHaveFields,
271 ULONG32 flags,
272 IXCLRDataTypeInstance* fromType);
273
274ULONG32 GetTypeFieldValueFlags(TypeHandle typeHandle,
275 FieldDesc* fieldDesc,
276 ULONG32 otherFlags,
277 bool isDeref);
278
279//----------------------------------------------------------------------------
280//
281// MetaEnum.
282//
283//----------------------------------------------------------------------------
284
285class MetaEnum
286{
287public:
288 MetaEnum(void)
289 : m_domainIter(FALSE)
290 {
291 Clear();
292 m_appDomain = NULL;
293 }
294 ~MetaEnum(void)
295 {
296 End();
297 }
298
299 void Clear(void)
300 {
301 m_mdImport = NULL;
302 m_kind = 0;
303 m_lastToken = mdTokenNil;
304 }
305
306 HRESULT Start(IMDInternalImport* mdImport, ULONG32 kind,
307 mdToken container);
308 void End(void);
309
310 HRESULT NextToken(mdToken* token,
311 __deref_opt_out_opt LPCUTF8* namespaceName,
312 __deref_opt_out_opt LPCUTF8* name);
313 HRESULT NextDomainToken(AppDomain** appDomain,
314 mdToken* token);
315 HRESULT NextTokenByName(__in_opt LPCUTF8 namespaceName,
316 __in_opt LPCUTF8 name,
317 ULONG32 nameFlags,
318 mdToken* token);
319 HRESULT NextDomainTokenByName(__in_opt LPCUTF8 namespaceName,
320 __in_opt LPCUTF8 name,
321 ULONG32 nameFlags,
322 AppDomain** appDomain, mdToken* token);
323
324 static HRESULT CdNextToken(CLRDATA_ENUM* handle,
325 mdToken* token)
326 {
327 MetaEnum* iter = FROM_CDENUM(MetaEnum, *handle);
328 if (!iter)
329 {
330 return S_FALSE;
331 }
332
333 return iter->NextToken(token, NULL, NULL);
334 }
335 static HRESULT CdNextDomainToken(CLRDATA_ENUM* handle,
336 AppDomain** appDomain,
337 mdToken* token)
338 {
339 MetaEnum* iter = FROM_CDENUM(MetaEnum, *handle);
340 if (!iter)
341 {
342 return S_FALSE;
343 }
344
345 return iter->NextDomainToken(appDomain, token);
346 }
347 static HRESULT CdEnd(CLRDATA_ENUM handle)
348 {
349 MetaEnum* iter = FROM_CDENUM(MetaEnum, handle);
350 if (iter)
351 {
352 delete iter;
353 return S_OK;
354 }
355 else
356 {
357 return E_INVALIDARG;
358 }
359 }
360
361 IMDInternalImport* m_mdImport;
362 ULONG32 m_kind;
363 HENUMInternal m_enum;
364 AppDomain* m_appDomain;
365 AppDomainIterator m_domainIter;
366 mdToken m_lastToken;
367
368 static HRESULT New(Module* mod,
369 ULONG32 kind,
370 mdToken container,
371 IXCLRDataAppDomain* pubAppDomain,
372 MetaEnum** metaEnum,
373 CLRDATA_ENUM* handle);
374};
375
376//----------------------------------------------------------------------------
377//
378// SplitName.
379//
380//----------------------------------------------------------------------------
381
382class SplitName
383{
384public:
385 // Type of name and splitting being done in this instance.
386 SplitSyntax m_syntax;
387 ULONG32 m_nameFlags;
388 ULONG32 m_memberDots;
389
390 // Split fields.
391 LPUTF8 m_namespaceName;
392 LPUTF8 m_typeName;
393 mdTypeDef m_typeToken;
394 LPUTF8 m_memberName;
395 mdMethodDef m_memberToken;
396 LPUTF8 m_params;
397 // XXX Microsoft - Translated signature.
398
399 // Arbitrary extra data.
400 Thread* m_tlsThread;
401 Module* m_module;
402 MetaEnum m_metaEnum;
403 DeepFieldDescIterator m_fieldEnum;
404 ULONG64 m_objBase;
405 FieldDesc* m_lastField;
406
407 SplitName(SplitSyntax syntax, ULONG32 nameFlags,
408 ULONG32 memberDots);
409 ~SplitName(void)
410 {
411 Delete();
412 }
413
414 void Delete(void);
415 void Clear(void);
416
417 HRESULT SplitString(__in_opt PCWSTR fullName);
418
419 bool FindType(IMDInternalImport* mdInternal);
420 bool FindMethod(IMDInternalImport* mdInternal);
421 bool FindField(IMDInternalImport* mdInternal);
422
423 int Compare(LPCUTF8 str1, LPCUTF8 str2)
424 {
425 return CompareUtf8(str1, str2, m_nameFlags);
426 }
427
428 static HRESULT AllocAndSplitString(__in_opt PCWSTR fullName,
429 SplitSyntax syntax,
430 ULONG32 nameFlags,
431 ULONG32 memberDots,
432 SplitName** split);
433
434 static HRESULT CdStartMethod(__in_opt PCWSTR fullName,
435 ULONG32 nameFlags,
436 Module* mod,
437 mdTypeDef typeToken,
438 AppDomain* appDomain,
439 IXCLRDataAppDomain* pubAppDomain,
440 SplitName** split,
441 CLRDATA_ENUM* handle);
442 static HRESULT CdNextMethod(CLRDATA_ENUM* handle,
443 mdMethodDef* token);
444 static HRESULT CdNextDomainMethod(CLRDATA_ENUM* handle,
445 AppDomain** appDomain,
446 mdMethodDef* token);
447
448 static HRESULT CdStartField(__in_opt PCWSTR fullName,
449 ULONG32 nameFlags,
450 ULONG32 fieldFlags,
451 IXCLRDataTypeInstance* fromTypeInst,
452 TypeHandle typeHandle,
453 Module* mod,
454 mdTypeDef typeToken,
455 ULONG64 objBase,
456 Thread* tlsThread,
457 IXCLRDataTask* pubTlsThread,
458 AppDomain* appDomain,
459 IXCLRDataAppDomain* pubAppDomain,
460 SplitName** split,
461 CLRDATA_ENUM* handle);
462 static HRESULT CdNextField(ClrDataAccess* dac,
463 CLRDATA_ENUM* handle,
464 IXCLRDataTypeDefinition** fieldType,
465 ULONG32* fieldFlags,
466 IXCLRDataValue** value,
467 ULONG32 nameBufRetLen,
468 ULONG32* nameLenRet,
469 __out_ecount_part_opt(nameBufRetLen, *nameLenRet) WCHAR nameBufRet[ ],
470 IXCLRDataModule** tokenScopeRet,
471 mdFieldDef* tokenRet);
472 static HRESULT CdNextDomainField(ClrDataAccess* dac,
473 CLRDATA_ENUM* handle,
474 IXCLRDataValue** value);
475
476 static HRESULT CdStartType(__in_opt PCWSTR fullName,
477 ULONG32 nameFlags,
478 Module* mod,
479 AppDomain* appDomain,
480 IXCLRDataAppDomain* pubAppDomain,
481 SplitName** split,
482 CLRDATA_ENUM* handle);
483 static HRESULT CdNextType(CLRDATA_ENUM* handle,
484 mdTypeDef* token);
485 static HRESULT CdNextDomainType(CLRDATA_ENUM* handle,
486 AppDomain** appDomain,
487 mdTypeDef* token);
488
489 static HRESULT CdEnd(CLRDATA_ENUM handle)
490 {
491 SplitName* split = FROM_CDENUM(SplitName, handle);
492 if (split)
493 {
494 delete split;
495 return S_OK;
496 }
497 else
498 {
499 return E_INVALIDARG;
500 }
501 }
502};
503
504//----------------------------------------------------------------------------
505//
506// ProcessModIter.
507//
508//----------------------------------------------------------------------------
509
510struct ProcessModIter
511{
512 AppDomainIterator m_domainIter;
513 bool m_nextDomain;
514 AppDomain::AssemblyIterator m_assemIter;
515 Assembly* m_curAssem;
516 Assembly::ModuleIterator m_modIter;
517
518 ProcessModIter(void)
519 : m_domainIter(FALSE)
520 {
521 SUPPORTS_DAC;
522 m_nextDomain = true;
523 m_curAssem = NULL;
524 }
525
526 Assembly * NextAssem()
527 {
528 SUPPORTS_DAC;
529 for (;;)
530 {
531 if (m_nextDomain)
532 {
533 if (!m_domainIter.Next())
534 {
535 break;
536 }
537
538 m_nextDomain = false;
539
540 m_assemIter = m_domainIter.GetDomain()->IterateAssembliesEx((AssemblyIterationFlags)(
541 kIncludeLoaded | kIncludeExecution));
542 }
543
544 CollectibleAssemblyHolder<DomainAssembly *> pDomainAssembly;
545 if (!m_assemIter.Next(pDomainAssembly.This()))
546 {
547 m_nextDomain = true;
548 continue;
549 }
550
551 // Note: DAC doesn't need to keep the assembly alive - see code:CollectibleAssemblyHolder#CAH_DAC
552 CollectibleAssemblyHolder<Assembly *> pAssembly = pDomainAssembly->GetLoadedAssembly();
553 return pAssembly;
554 }
555 return NULL;
556 }
557
558 Module* NextModule(void)
559 {
560 SUPPORTS_DAC;
561 for (;;)
562 {
563 if (!m_curAssem)
564 {
565 m_curAssem = NextAssem();
566 if (!m_curAssem)
567 {
568 return NULL;
569 }
570
571 m_modIter = m_curAssem->IterateModules();
572 }
573
574 if (!m_modIter.Next())
575 {
576 m_curAssem = NULL;
577 continue;
578 }
579
580 return m_modIter.GetModule();
581 }
582 }
583};
584
585//----------------------------------------------------------------------------
586//
587// DacInstanceManager.
588//
589//----------------------------------------------------------------------------
590
591// The data for an access may have special alignment needs and
592// the cache must provide similar semantics.
593#define DAC_INSTANCE_ALIGN 16
594
595#define DAC_INSTANCE_SIG 0xdac1
596
597// The instance manager allocates large blocks and then
598// suballocates those for particular instances.
599struct DAC_INSTANCE_BLOCK
600{
601 DAC_INSTANCE_BLOCK* next;
602 ULONG32 bytesUsed;
603 ULONG32 bytesFree;
604};
605
606#define DAC_INSTANCE_BLOCK_ALLOCATION 0x40000
607
608// Sufficient memory is allocated to guarantee storage of the
609// instance header plus room for alignment padding.
610// Once the aligned pointer is found, this structure is prepended to
611// the aligned pointer and therefore doesn't affect the alignment
612// of the actual instance data.
613struct DAC_INSTANCE
614{
615 DAC_INSTANCE* next;
616 TADDR addr;
617 ULONG32 size;
618 // Identifying marker to give a simple
619 // check for host->taddr validity.
620 ULONG32 sig:16;
621 // DPTR or VPTR. See code:DAC_USAGE_TYPE
622 ULONG32 usage:2;
623
624 // Marker that can be used to prevent reporting this memory to the callback
625 // object (via ICLRDataEnumMemoryRegionsCallback:EnumMemoryRegion)
626 // more than once. This bit is checked only by the DacEnumHost?PtrMem
627 // macros, so consistent use of those macros ensures that the memory is
628 // reported at most once
629 ULONG32 enumMem:1;
630
631 // Marker to prevent metadata gets reported to mini-dump
632 ULONG32 noReport:1;
633
634 // Marker to determine if EnumMemoryRegions has been called on
635 // a method descriptor
636 ULONG32 MDEnumed:1;
637
638#ifdef _WIN64
639 // Keep DAC_INSTANCE a multiple of DAC_INSTANCE_ALIGN
640 // bytes in size.
641 ULONG32 pad[2];
642#endif
643};
644
645struct DAC_INSTANCE_PUSH
646{
647 DAC_INSTANCE_PUSH* next;
648 DAC_INSTANCE_BLOCK* blocks;
649 ULONG64 blockMemUsage;
650 ULONG32 numInst;
651 ULONG64 instMemUsage;
652};
653
654// The runtime will want the best access locality possible,
655// so it's likely that many instances will be clustered.
656// The hash function needs to spread near addresses across
657// hash entries, so hash on the low bits of the target address.
658// Not all the way down to the LSB, though, as there generally
659// won't be individual accesses at the byte level. Assume that
660// most accesses will be natural-word aligned.
661#define DAC_INSTANCE_HASH_BITS 10
662#define DAC_INSTANCE_HASH_SHIFT 2
663
664#define DAC_INSTANCE_HASH(addr) \
665 (((ULONG32)(ULONG_PTR)(addr) >> DAC_INSTANCE_HASH_SHIFT) & \
666 ((1 << DAC_INSTANCE_HASH_BITS) - 1))
667#define DAC_INSTANCE_HASH_SIZE (1 << DAC_INSTANCE_HASH_BITS)
668
669
670struct DumpMemoryReportStatics
671{
672 TSIZE_T m_cbStack; // number of bytes that we report directly for stack walk
673 TSIZE_T m_cbNgen; // number of bytes that we report directly for ngen images
674 TSIZE_T m_cbModuleList; // number of bytes that we report for module list directly
675 TSIZE_T m_cbClrStatics; // number of bytes that we report for CLR statics
676 TSIZE_T m_cbClrHeapStatics; // number of bytes that we report for CLR heap statics
677 TSIZE_T m_cbImplicity; // number of bytes that we report implicitly
678};
679
680
681class DacInstanceManager
682{
683public:
684 DacInstanceManager(void);
685 ~DacInstanceManager(void);
686
687 DAC_INSTANCE* Add(DAC_INSTANCE* inst);
688
689 DAC_INSTANCE* Alloc(TADDR addr, ULONG32 size, DAC_USAGE_TYPE usage);
690 void ReturnAlloc(DAC_INSTANCE* inst);
691 DAC_INSTANCE* Find(TADDR addr);
692 HRESULT Write(DAC_INSTANCE* inst, bool throwEx);
693 void Supersede(DAC_INSTANCE* inst);
694 void Flush(void);
695 void Flush(bool fSaveBlock);
696 void ClearEnumMemMarker(void);
697
698 void AddSuperseded(DAC_INSTANCE* inst)
699 {
700 SUPPORTS_DAC;
701 inst->next = m_superseded;
702 m_superseded = inst;
703 }
704
705 UINT DumpAllInstances(ICLRDataEnumMemoryRegionsCallback *pCallBack);
706
707private:
708
709 DAC_INSTANCE_BLOCK* FindInstanceBlock(DAC_INSTANCE* inst);
710 void FreeAllBlocks(bool fSaveBlock);
711
712 void InitEmpty(void)
713 {
714 m_blocks = NULL;
715 // m_unusedBlock is not NULLed here; it can contain one block we will use after
716 // a flush is complete.
717 m_blockMemUsage = 0;
718 m_numInst = 0;
719 m_instMemUsage = 0;
720#ifdef DAC_HASHTABLE
721 ZeroMemory(m_hash, sizeof(m_hash));
722#endif
723 m_superseded = NULL;
724 m_instPushed = NULL;
725 }
726
727#if defined(DAC_HASHTABLE)
728
729 typedef struct _HashInstanceKey {
730 TADDR addr;
731 DAC_INSTANCE* instance;
732 } HashInstanceKey;
733
734 typedef struct _HashInstanceKeyBlock {
735 // Blocks are chained in reverse order of allocation so that the most recently allocated
736 // block is searched first.
737 _HashInstanceKeyBlock* next;
738
739 // Entries to a block are added from the max index on down so that recently added
740 // entries are at the start of the block.
741 DWORD firstElement;
742 HashInstanceKey instanceKeys[] ;
743 } HashInstanceKeyBlock;
744
745// The hashing function does a good job of distributing the entries across buckets. To handle a
746// SO on x86, we have under 250 entries in a bucket. A 4K block size allows 511 entries on x86 and
747// about half that on x64. On x64, the number of entries added to the hash table is significantly
748// smaller than on x86 (and the max recursion depth for default stack sizes is also far less), so
749// 4K is generally adequate.
750
751#define HASH_INSTANCE_BLOCK_ALLOC_SIZE (4 * 1024)
752#define HASH_INSTANCE_BLOCK_NUM_ELEMENTS ((HASH_INSTANCE_BLOCK_ALLOC_SIZE - offsetof(_HashInstanceKeyBlock, instanceKeys))/sizeof(HashInstanceKey))
753#endif // #if defined(DAC_HASHTABLE)
754
755 DAC_INSTANCE_BLOCK* m_blocks;
756 DAC_INSTANCE_BLOCK* m_unusedBlock;
757 ULONG64 m_blockMemUsage;
758 ULONG32 m_numInst;
759 ULONG64 m_instMemUsage;
760
761#if defined(DAC_HASHTABLE)
762 HashInstanceKeyBlock* m_hash[DAC_INSTANCE_HASH_SIZE];
763#else //DAC_HASHTABLE
764
765 // We're going to use the STL unordered_map for our instance hash.
766 // This has the benefit of scaling to different workloads appropriately (as opposed to having a
767 // fixed number of buckets).
768
769 class DacHashCompare : public std::hash_compare<TADDR>
770 {
771 public:
772 // Custom hash function
773 // The default hash function uses a pseudo-randomizing function to get a random
774 // distribution. In our case, we'd actually like a more even distribution to get
775 // better access locality (see comments for DAC_INSTANCE_HASH_BITS).
776 //
777 // Also, when enumerating the hash during dump generation, clustering nearby addresses
778 // together can have a significant positive impact on the performance of the minidump
779 // library (at least the un-optimized version 6.5 linked into our dw20.exe - on Vista+
780 // we use the OS's version 6.7+ with radically improved perf characteristics). Having
781 // a random distribution is actually the worst-case because it means most blocks won't
782 // be merged until near the end, and a large number of intermediate blocks will have to
783 // be searched with each call.
784 //
785 // The default pseudo-randomizing function also requires a call to ldiv which shows up as
786 // a 3%-5% perf hit in most perf-sensitive scenarios, so this should also always be
787 // faster.
788 inline size_t operator()(const TADDR& keyval) const
789 {
790 return (unsigned)(keyval >>DAC_INSTANCE_HASH_SHIFT);
791 }
792
793 // Explicitly bring in the two-argument comparison function from the base class (just less-than)
794 // This is necessary because once we override one form of operator() above, we don't automatically
795 // get the others by C++ inheritance rules.
796 using std::hash_compare<TADDR>::operator();
797
798#ifdef NIDUMP_CUSTOMIZED_DAC_HASH // not set
799 //this particular number is supposed to be roughly the same amount of
800 //memory as the old code (buckets * number of entries in the old
801 //blocks.)
802 //disabled for now. May tweak implementation later. It turns out that
803 //having a large number of initial buckets is excellent for nidump, but it
804 // is terrible for most other scenarios due to the cost of clearing them at
805 // every Flush. Once there is a better perf suite, we can tweak these values more.
806 static const size_t min_buckets = DAC_INSTANCE_HASH_SIZE * 256;
807#endif
808
809 };
810 typedef std::unordered_map<TADDR, DAC_INSTANCE*, DacHashCompare > DacInstanceHash;
811 typedef DacInstanceHash::value_type DacInstanceHashValue;
812 typedef DacInstanceHash::iterator DacInstanceHashIterator;
813 DacInstanceHash m_hash;
814#endif //DAC_HASHTABLE
815
816 DAC_INSTANCE* m_superseded;
817 DAC_INSTANCE_PUSH* m_instPushed;
818};
819
820
821#ifdef FEATURE_MINIMETADATA_IN_TRIAGEDUMPS
822
823class DacStreamManager;
824
825#endif // FEATURE_MINIMETADATA_IN_TRIAGEDUMPS
826
827
828//----------------------------------------------------------------------------
829//
830// ClrDataAccess.
831//
832//----------------------------------------------------------------------------
833
834class ClrDataAccess
835 : public IXCLRDataProcess2,
836 public ICLRDataEnumMemoryRegions,
837 public ISOSDacInterface,
838 public ISOSDacInterface2,
839 public ISOSDacInterface3,
840 public ISOSDacInterface4,
841 public ISOSDacInterface5,
842 public ISOSDacInterface6
843{
844public:
845 ClrDataAccess(ICorDebugDataTarget * pTarget, ICLRDataTarget * pLegacyTarget=0);
846 virtual ~ClrDataAccess(void);
847
848 // IUnknown.
849 STDMETHOD(QueryInterface)(THIS_
850 IN REFIID interfaceId,
851 OUT PVOID* iface);
852 STDMETHOD_(ULONG, AddRef)(THIS);
853 STDMETHOD_(ULONG, Release)(THIS);
854
855 //
856 // IXCLRDataProcess.
857 //
858
859 virtual HRESULT STDMETHODCALLTYPE Flush( void);
860
861 virtual HRESULT STDMETHODCALLTYPE StartEnumTasks(
862 /* [out] */ CLRDATA_ENUM *handle);
863
864 virtual HRESULT STDMETHODCALLTYPE EnumTask(
865 /* [in, out] */ CLRDATA_ENUM* handle,
866 /* [out] */ IXCLRDataTask **task);
867
868 virtual HRESULT STDMETHODCALLTYPE EndEnumTasks(
869 /* [in] */ CLRDATA_ENUM handle);
870
871 virtual HRESULT STDMETHODCALLTYPE GetTaskByOSThreadID(
872 /* [in] */ ULONG32 OSThreadID,
873 /* [out] */ IXCLRDataTask **task);
874
875 virtual HRESULT STDMETHODCALLTYPE GetTaskByUniqueID(
876 /* [in] */ ULONG64 uniqueID,
877 /* [out] */ IXCLRDataTask **task);
878
879 virtual HRESULT STDMETHODCALLTYPE GetFlags(
880 /* [out] */ ULONG32 *flags);
881
882 virtual HRESULT STDMETHODCALLTYPE IsSameObject(
883 /* [in] */ IXCLRDataProcess *process);
884
885 virtual HRESULT STDMETHODCALLTYPE GetManagedObject(
886 /* [out] */ IXCLRDataValue **value);
887
888 virtual HRESULT STDMETHODCALLTYPE GetDesiredExecutionState(
889 /* [out] */ ULONG32 *state);
890
891 virtual HRESULT STDMETHODCALLTYPE SetDesiredExecutionState(
892 /* [in] */ ULONG32 state);
893
894 virtual HRESULT STDMETHODCALLTYPE GetAddressType(
895 /* [in] */ CLRDATA_ADDRESS address,
896 /* [out] */ CLRDataAddressType* type);
897
898 virtual HRESULT STDMETHODCALLTYPE GetRuntimeNameByAddress(
899 /* [in] */ CLRDATA_ADDRESS address,
900 /* [in] */ ULONG32 flags,
901 /* [in] */ ULONG32 bufLen,
902 /* [out] */ ULONG32 *nameLen,
903 /* [size_is][out] */ __out_ecount_opt(bufLen) WCHAR nameBuf[ ],
904 /* [out] */ CLRDATA_ADDRESS* displacement);
905
906 virtual HRESULT STDMETHODCALLTYPE StartEnumAppDomains(
907 /* [out] */ CLRDATA_ENUM *handle);
908
909 virtual HRESULT STDMETHODCALLTYPE EnumAppDomain(
910 /* [in, out] */ CLRDATA_ENUM* handle,
911 /* [out] */ IXCLRDataAppDomain **appDomain);
912
913 virtual HRESULT STDMETHODCALLTYPE EndEnumAppDomains(
914 /* [in] */ CLRDATA_ENUM handle);
915
916 virtual HRESULT STDMETHODCALLTYPE GetAppDomainByUniqueID(
917 /* [in] */ ULONG64 uniqueID,
918 /* [out] */ IXCLRDataAppDomain **appDomain);
919
920 virtual HRESULT STDMETHODCALLTYPE StartEnumAssemblies(
921 /* [out] */ CLRDATA_ENUM *handle);
922
923 virtual HRESULT STDMETHODCALLTYPE EnumAssembly(
924 /* [in, out] */ CLRDATA_ENUM* handle,
925 /* [out] */ IXCLRDataAssembly **assembly);
926
927 virtual HRESULT STDMETHODCALLTYPE EndEnumAssemblies(
928 /* [in] */ CLRDATA_ENUM handle);
929
930 virtual HRESULT STDMETHODCALLTYPE StartEnumModules(
931 /* [out] */ CLRDATA_ENUM *handle);
932
933 virtual HRESULT STDMETHODCALLTYPE EnumModule(
934 /* [in, out] */ CLRDATA_ENUM* handle,
935 /* [out] */ IXCLRDataModule **mod);
936
937 virtual HRESULT STDMETHODCALLTYPE EndEnumModules(
938 /* [in] */ CLRDATA_ENUM handle);
939
940 virtual HRESULT STDMETHODCALLTYPE GetModuleByAddress(
941 /* [in] */ CLRDATA_ADDRESS address,
942 /* [out] */ IXCLRDataModule** mod);
943
944 virtual HRESULT STDMETHODCALLTYPE StartEnumMethodDefinitionsByAddress(
945 /* [in] */ CLRDATA_ADDRESS address,
946 /* [out] */ CLRDATA_ENUM *handle);
947
948 virtual HRESULT STDMETHODCALLTYPE EnumMethodDefinitionByAddress(
949 /* [in] */ CLRDATA_ENUM* handle,
950 /* [out] */ IXCLRDataMethodDefinition **method);
951
952 virtual HRESULT STDMETHODCALLTYPE EndEnumMethodDefinitionsByAddress(
953 /* [in] */ CLRDATA_ENUM handle);
954
955 virtual HRESULT STDMETHODCALLTYPE StartEnumMethodInstancesByAddress(
956 /* [in] */ CLRDATA_ADDRESS address,
957 /* [in] */ IXCLRDataAppDomain* appDomain,
958 /* [out] */ CLRDATA_ENUM *handle);
959
960 virtual HRESULT STDMETHODCALLTYPE EnumMethodInstanceByAddress(
961 /* [in] */ CLRDATA_ENUM* handle,
962 /* [out] */ IXCLRDataMethodInstance **method);
963
964 virtual HRESULT STDMETHODCALLTYPE EndEnumMethodInstancesByAddress(
965 /* [in] */ CLRDATA_ENUM handle);
966
967 virtual HRESULT STDMETHODCALLTYPE GetDataByAddress(
968 /* [in] */ CLRDATA_ADDRESS address,
969 /* [in] */ ULONG32 flags,
970 /* [in] */ IXCLRDataAppDomain* appDomain,
971 /* [in] */ IXCLRDataTask* tlsTask,
972 /* [in] */ ULONG32 bufLen,
973 /* [out] */ ULONG32 *nameLen,
974 /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR nameBuf[ ],
975 /* [out] */ IXCLRDataValue **value,
976 /* [out] */ CLRDATA_ADDRESS *displacement);
977
978 virtual HRESULT STDMETHODCALLTYPE GetExceptionStateByExceptionRecord(
979 /* [in] */ EXCEPTION_RECORD64 *record,
980 /* [out] */ IXCLRDataExceptionState **exception);
981
982 virtual HRESULT STDMETHODCALLTYPE TranslateExceptionRecordToNotification(
983 /* [in] */ EXCEPTION_RECORD64 *record,
984 /* [in] */ IXCLRDataExceptionNotification *notify);
985
986 virtual HRESULT STDMETHODCALLTYPE CreateMemoryValue(
987 /* [in] */ IXCLRDataAppDomain* appDomain,
988 /* [in] */ IXCLRDataTask* tlsTask,
989 /* [in] */ IXCLRDataTypeInstance* type,
990 /* [in] */ CLRDATA_ADDRESS addr,
991 /* [out] */ IXCLRDataValue** value);
992
993 virtual HRESULT STDMETHODCALLTYPE SetAllTypeNotifications(
994 /* [in] */ IXCLRDataModule* mod,
995 /* [in] */ ULONG32 flags);
996
997 virtual HRESULT STDMETHODCALLTYPE SetAllCodeNotifications(
998 /* [in] */ IXCLRDataModule* mod,
999 /* [in] */ ULONG32 flags);
1000
1001 virtual HRESULT STDMETHODCALLTYPE GetTypeNotifications(
1002 /* [in] */ ULONG32 numTokens,
1003 /* [in, size_is(numTokens)] */ IXCLRDataModule* mods[],
1004 /* [in] */ IXCLRDataModule* singleMod,
1005 /* [in, size_is(numTokens)] */ mdTypeDef tokens[],
1006 /* [out, size_is(numTokens)] */ ULONG32 flags[]);
1007
1008 virtual HRESULT STDMETHODCALLTYPE SetTypeNotifications(
1009 /* [in] */ ULONG32 numTokens,
1010 /* [in, size_is(numTokens)] */ IXCLRDataModule* mods[],
1011 /* [in] */ IXCLRDataModule* singleMod,
1012 /* [in, size_is(numTokens)] */ mdTypeDef tokens[],
1013 /* [in, size_is(numTokens)] */ ULONG32 flags[],
1014 /* [in] */ ULONG32 singleFlags);
1015
1016 virtual HRESULT STDMETHODCALLTYPE GetCodeNotifications(
1017 /* [in] */ ULONG32 numTokens,
1018 /* [in, size_is(numTokens)] */ IXCLRDataModule* mods[],
1019 /* [in] */ IXCLRDataModule* singleMod,
1020 /* [in, size_is(numTokens)] */ mdMethodDef tokens[],
1021 /* [out, size_is(numTokens)] */ ULONG32 flags[]);
1022
1023 virtual HRESULT STDMETHODCALLTYPE SetCodeNotifications(
1024 /* [in] */ ULONG32 numTokens,
1025 /* [in, size_is(numTokens)] */ IXCLRDataModule* mods[],
1026 /* [in] */ IXCLRDataModule* singleMod,
1027 /* [in, size_is(numTokens)] */ mdMethodDef tokens[],
1028 /* [in, size_is(numTokens)] */ ULONG32 flags[],
1029 /* [in] */ ULONG32 singleFlags);
1030
1031 virtual HRESULT STDMETHODCALLTYPE GetOtherNotificationFlags(
1032 /* [out] */ ULONG32* flags);
1033
1034 virtual HRESULT STDMETHODCALLTYPE SetOtherNotificationFlags(
1035 /* [in] */ ULONG32 flags);
1036
1037 virtual HRESULT STDMETHODCALLTYPE FollowStub(
1038 /* [in] */ ULONG32 inFlags,
1039 /* [in] */ CLRDATA_ADDRESS inAddr,
1040 /* [in] */ CLRDATA_FOLLOW_STUB_BUFFER* inBuffer,
1041 /* [out] */ CLRDATA_ADDRESS* outAddr,
1042 /* [out] */ CLRDATA_FOLLOW_STUB_BUFFER* outBuffer,
1043 /* [out] */ ULONG32* outFlags);
1044
1045 virtual HRESULT STDMETHODCALLTYPE FollowStub2(
1046 /* [in] */ IXCLRDataTask* task,
1047 /* [in] */ ULONG32 inFlags,
1048 /* [in] */ CLRDATA_ADDRESS inAddr,
1049 /* [in] */ CLRDATA_FOLLOW_STUB_BUFFER* inBuffer,
1050 /* [out] */ CLRDATA_ADDRESS* outAddr,
1051 /* [out] */ CLRDATA_FOLLOW_STUB_BUFFER* outBuffer,
1052 /* [out] */ ULONG32* outFlags);
1053
1054 virtual HRESULT STDMETHODCALLTYPE Request(
1055 /* [in] */ ULONG32 reqCode,
1056 /* [in] */ ULONG32 inBufferSize,
1057 /* [size_is][in] */ BYTE *inBuffer,
1058 /* [in] */ ULONG32 outBufferSize,
1059 /* [size_is][out] */ BYTE *outBuffer);
1060
1061
1062 //
1063 // IXCLRDataProcess2.
1064 //
1065 STDMETHOD(GetGcNotification)(/* [out] */ GcEvtArgs* gcEvtArgs);
1066 STDMETHOD(SetGcNotification)(/* [in] */ GcEvtArgs gcEvtArgs);
1067
1068 //
1069 // ICLRDataEnumMemoryRegions.
1070 //
1071 virtual HRESULT STDMETHODCALLTYPE EnumMemoryRegions(
1072 /* [in] */ ICLRDataEnumMemoryRegionsCallback *callback,
1073 /* [in] */ ULONG32 miniDumpFlags,
1074 /* [in] */ CLRDataEnumMemoryFlags clrFlags);
1075
1076
1077 // ISOSDacInterface
1078 virtual HRESULT STDMETHODCALLTYPE GetThreadStoreData(struct DacpThreadStoreData *data);
1079 virtual HRESULT STDMETHODCALLTYPE GetAppDomainStoreData(struct DacpAppDomainStoreData *data);
1080 virtual HRESULT STDMETHODCALLTYPE GetAppDomainList(unsigned int count, CLRDATA_ADDRESS values[], unsigned int *pNeeded);
1081 virtual HRESULT STDMETHODCALLTYPE GetAppDomainData(CLRDATA_ADDRESS addr, struct DacpAppDomainData *data);
1082 virtual HRESULT STDMETHODCALLTYPE GetAppDomainName(CLRDATA_ADDRESS addr, unsigned int count, __out_z __inout_ecount(count) wchar_t *name, unsigned int *pNeeded);
1083 virtual HRESULT STDMETHODCALLTYPE GetAssemblyList(CLRDATA_ADDRESS appDomain, int count, CLRDATA_ADDRESS values[], int *fetched);
1084 virtual HRESULT STDMETHODCALLTYPE GetAssemblyData(CLRDATA_ADDRESS baseDomainPtr, CLRDATA_ADDRESS assembly, struct DacpAssemblyData *data);
1085 virtual HRESULT STDMETHODCALLTYPE GetAssemblyName(CLRDATA_ADDRESS assembly, unsigned int count, __out_z __inout_ecount(count) wchar_t *name, unsigned int *pNeeded);
1086 virtual HRESULT STDMETHODCALLTYPE GetThreadData(CLRDATA_ADDRESS thread, struct DacpThreadData *data);
1087 virtual HRESULT STDMETHODCALLTYPE GetThreadFromThinlockID(UINT thinLockId, CLRDATA_ADDRESS *pThread);
1088 virtual HRESULT STDMETHODCALLTYPE GetStackLimits(CLRDATA_ADDRESS threadPtr, CLRDATA_ADDRESS *lower, CLRDATA_ADDRESS *upper, CLRDATA_ADDRESS *fp);
1089 virtual HRESULT STDMETHODCALLTYPE GetDomainFromContext(CLRDATA_ADDRESS context, CLRDATA_ADDRESS *domain);
1090
1091 virtual HRESULT STDMETHODCALLTYPE GetMethodDescData(CLRDATA_ADDRESS methodDesc, CLRDATA_ADDRESS ip, struct DacpMethodDescData *data, ULONG cRevertedRejitVersions, DacpReJitData * rgRevertedRejitData, ULONG * pcNeededRevertedRejitData);
1092 virtual HRESULT STDMETHODCALLTYPE GetMethodDescPtrFromIP(CLRDATA_ADDRESS ip, CLRDATA_ADDRESS * ppMD);
1093 virtual HRESULT STDMETHODCALLTYPE GetMethodDescName(CLRDATA_ADDRESS methodDesc, unsigned int count, __out_z __inout_ecount(count) wchar_t *name, unsigned int *pNeeded);
1094 virtual HRESULT STDMETHODCALLTYPE GetMethodDescPtrFromFrame(CLRDATA_ADDRESS frameAddr, CLRDATA_ADDRESS * ppMD);
1095 virtual HRESULT STDMETHODCALLTYPE GetCodeHeaderData(CLRDATA_ADDRESS ip, struct DacpCodeHeaderData *data);
1096 virtual HRESULT STDMETHODCALLTYPE GetThreadpoolData(struct DacpThreadpoolData *data);
1097 virtual HRESULT STDMETHODCALLTYPE GetWorkRequestData(CLRDATA_ADDRESS addrWorkRequest, struct DacpWorkRequestData *data);
1098 virtual HRESULT STDMETHODCALLTYPE GetObjectData(CLRDATA_ADDRESS objAddr, struct DacpObjectData *data);
1099 virtual HRESULT STDMETHODCALLTYPE GetObjectStringData(CLRDATA_ADDRESS obj, unsigned int count, __out_z __inout_ecount(count) wchar_t *stringData, unsigned int *pNeeded);
1100 virtual HRESULT STDMETHODCALLTYPE GetObjectClassName(CLRDATA_ADDRESS obj, unsigned int count, __out_z __inout_ecount(count) wchar_t *className, unsigned int *pNeeded);
1101 virtual HRESULT STDMETHODCALLTYPE GetMethodTableName(CLRDATA_ADDRESS mt, unsigned int count, __out_z __inout_ecount(count) wchar_t *mtName, unsigned int *pNeeded);
1102 virtual HRESULT STDMETHODCALLTYPE GetMethodTableData(CLRDATA_ADDRESS mt, struct DacpMethodTableData *data);
1103 virtual HRESULT STDMETHODCALLTYPE GetMethodTableFieldData(CLRDATA_ADDRESS mt, struct DacpMethodTableFieldData *data);
1104 virtual HRESULT STDMETHODCALLTYPE GetMethodTableTransparencyData(CLRDATA_ADDRESS mt, struct DacpMethodTableTransparencyData *data);
1105 virtual HRESULT STDMETHODCALLTYPE GetMethodTableForEEClass(CLRDATA_ADDRESS eeClass, CLRDATA_ADDRESS *value);
1106 virtual HRESULT STDMETHODCALLTYPE GetFieldDescData(CLRDATA_ADDRESS fieldDesc, struct DacpFieldDescData *data);
1107 virtual HRESULT STDMETHODCALLTYPE GetFrameName(CLRDATA_ADDRESS vtable, unsigned int count, __out_z __inout_ecount(count) wchar_t *frameName, unsigned int *pNeeded);
1108 virtual HRESULT STDMETHODCALLTYPE GetModule(CLRDATA_ADDRESS addr, IXCLRDataModule **mod);
1109 virtual HRESULT STDMETHODCALLTYPE GetModuleData(CLRDATA_ADDRESS moduleAddr, struct DacpModuleData *data);
1110 virtual HRESULT STDMETHODCALLTYPE TraverseModuleMap(ModuleMapType mmt, CLRDATA_ADDRESS moduleAddr, MODULEMAPTRAVERSE pCallback, LPVOID token);
1111 virtual HRESULT STDMETHODCALLTYPE GetMethodDescFromToken(CLRDATA_ADDRESS moduleAddr, mdToken token, CLRDATA_ADDRESS *methodDesc);
1112 virtual HRESULT STDMETHODCALLTYPE GetPEFileBase(CLRDATA_ADDRESS addr, CLRDATA_ADDRESS *base);
1113 virtual HRESULT STDMETHODCALLTYPE GetPEFileName(CLRDATA_ADDRESS addr, unsigned int count, __out_z __inout_ecount(count) wchar_t *fileName, unsigned int *pNeeded);
1114 virtual HRESULT STDMETHODCALLTYPE GetAssemblyModuleList(CLRDATA_ADDRESS assembly, unsigned int count, CLRDATA_ADDRESS modules[], unsigned int *pNeeded);
1115 virtual HRESULT STDMETHODCALLTYPE GetGCHeapData(struct DacpGcHeapData *data);
1116 virtual HRESULT STDMETHODCALLTYPE GetGCHeapList(unsigned int count, CLRDATA_ADDRESS heaps[], unsigned int *pNeeded);
1117 virtual HRESULT STDMETHODCALLTYPE GetGCHeapDetails(CLRDATA_ADDRESS heap, struct DacpGcHeapDetails *details);
1118 virtual HRESULT STDMETHODCALLTYPE GetGCHeapStaticData(struct DacpGcHeapDetails *data);
1119 virtual HRESULT STDMETHODCALLTYPE GetHeapSegmentData(CLRDATA_ADDRESS seg, struct DacpHeapSegmentData *data);
1120 virtual HRESULT STDMETHODCALLTYPE GetDomainLocalModuleData(CLRDATA_ADDRESS addr, struct DacpDomainLocalModuleData *data);
1121 virtual HRESULT STDMETHODCALLTYPE GetDomainLocalModuleDataFromAppDomain(CLRDATA_ADDRESS appDomainAddr, int moduleID, struct DacpDomainLocalModuleData *data);
1122 virtual HRESULT STDMETHODCALLTYPE GetDomainLocalModuleDataFromModule(CLRDATA_ADDRESS moduleAddr, struct DacpDomainLocalModuleData *data);
1123 virtual HRESULT STDMETHODCALLTYPE GetSyncBlockData(unsigned int number, struct DacpSyncBlockData *data);
1124 virtual HRESULT STDMETHODCALLTYPE GetSyncBlockCleanupData(CLRDATA_ADDRESS addr, struct DacpSyncBlockCleanupData *data);
1125 virtual HRESULT STDMETHODCALLTYPE TraverseRCWCleanupList(CLRDATA_ADDRESS cleanupListPtr, VISITRCWFORCLEANUP pCallback, LPVOID token);
1126 virtual HRESULT STDMETHODCALLTYPE TraverseEHInfo(CLRDATA_ADDRESS ip, DUMPEHINFO pCallback, LPVOID token);
1127 virtual HRESULT STDMETHODCALLTYPE GetStressLogAddress(CLRDATA_ADDRESS *stressLog);
1128 virtual HRESULT STDMETHODCALLTYPE GetJitManagerList(unsigned int count, struct DacpJitManagerInfo managers[], unsigned int *pNeeded);
1129 virtual HRESULT STDMETHODCALLTYPE GetJitHelperFunctionName(CLRDATA_ADDRESS ip, unsigned int count, __out_z __inout_ecount(count) char *name, unsigned int *pNeeded);
1130 virtual HRESULT STDMETHODCALLTYPE GetJumpThunkTarget(T_CONTEXT *ctx, CLRDATA_ADDRESS *targetIP, CLRDATA_ADDRESS *targetMD);
1131 virtual HRESULT STDMETHODCALLTYPE TraverseLoaderHeap(CLRDATA_ADDRESS loaderHeapAddr, VISITHEAP pCallback);
1132 virtual HRESULT STDMETHODCALLTYPE GetCodeHeapList(CLRDATA_ADDRESS jitManager, unsigned int count, struct DacpJitCodeHeapInfo codeHeaps[], unsigned int *pNeeded);
1133 virtual HRESULT STDMETHODCALLTYPE GetMethodTableSlot(CLRDATA_ADDRESS mt, unsigned int slot, CLRDATA_ADDRESS *value);
1134 virtual HRESULT STDMETHODCALLTYPE TraverseVirtCallStubHeap(CLRDATA_ADDRESS pAppDomain, VCSHeapType heaptype, VISITHEAP pCallback);
1135 virtual HRESULT STDMETHODCALLTYPE GetNestedExceptionData(CLRDATA_ADDRESS exception, CLRDATA_ADDRESS *exceptionObject, CLRDATA_ADDRESS *nextNestedException);
1136 virtual HRESULT STDMETHODCALLTYPE GetUsefulGlobals(struct DacpUsefulGlobalsData *data);
1137 virtual HRESULT STDMETHODCALLTYPE GetILForModule(CLRDATA_ADDRESS moduleAddr, DWORD rva, CLRDATA_ADDRESS *il);
1138 virtual HRESULT STDMETHODCALLTYPE GetClrWatsonBuckets(CLRDATA_ADDRESS thread, void *pGenericModeBlock);
1139 virtual HRESULT STDMETHODCALLTYPE GetOOMData(CLRDATA_ADDRESS oomAddr, struct DacpOomData *data);
1140 virtual HRESULT STDMETHODCALLTYPE GetOOMStaticData(struct DacpOomData *data);
1141 virtual HRESULT STDMETHODCALLTYPE GetHeapAnalyzeData(CLRDATA_ADDRESS addr,struct DacpGcHeapAnalyzeData *data);
1142 virtual HRESULT STDMETHODCALLTYPE GetHeapAnalyzeStaticData(struct DacpGcHeapAnalyzeData *data);
1143 virtual HRESULT STDMETHODCALLTYPE GetMethodDescTransparencyData(CLRDATA_ADDRESS methodDesc, struct DacpMethodDescTransparencyData *data);
1144 virtual HRESULT STDMETHODCALLTYPE GetHillClimbingLogEntry(CLRDATA_ADDRESS addr, struct DacpHillClimbingLogEntry *data);
1145 virtual HRESULT STDMETHODCALLTYPE GetThreadLocalModuleData(CLRDATA_ADDRESS thread, unsigned int index, struct DacpThreadLocalModuleData *data);
1146 virtual HRESULT STDMETHODCALLTYPE GetRCWData(CLRDATA_ADDRESS addr, struct DacpRCWData *data);
1147 virtual HRESULT STDMETHODCALLTYPE GetRCWInterfaces(CLRDATA_ADDRESS rcw, unsigned int count, struct DacpCOMInterfacePointerData interfaces[], unsigned int *pNeeded);
1148 virtual HRESULT STDMETHODCALLTYPE GetCCWData(CLRDATA_ADDRESS ccw, struct DacpCCWData *data);
1149 virtual HRESULT STDMETHODCALLTYPE GetCCWInterfaces(CLRDATA_ADDRESS ccw, unsigned int count, struct DacpCOMInterfacePointerData interfaces[], unsigned int *pNeeded);
1150 virtual HRESULT STDMETHODCALLTYPE GetTLSIndex(ULONG *pIndex);
1151 virtual HRESULT STDMETHODCALLTYPE GetDacModuleHandle(HMODULE *phModule);
1152
1153 virtual HRESULT STDMETHODCALLTYPE GetFailedAssemblyList(CLRDATA_ADDRESS appDomain, int count, CLRDATA_ADDRESS values[], unsigned int *pNeeded);
1154 virtual HRESULT STDMETHODCALLTYPE GetPrivateBinPaths(CLRDATA_ADDRESS appDomain, int count, __out_z __inout_ecount(count) wchar_t *paths, unsigned int *pNeeded);
1155 virtual HRESULT STDMETHODCALLTYPE GetAssemblyLocation(CLRDATA_ADDRESS assembly, int count, __out_z __inout_ecount(count) wchar_t *location, unsigned int *pNeeded);
1156 virtual HRESULT STDMETHODCALLTYPE GetAppDomainConfigFile(CLRDATA_ADDRESS appDomain, int count, __out_z __inout_ecount(count) wchar_t *configFile, unsigned int *pNeeded);
1157 virtual HRESULT STDMETHODCALLTYPE GetApplicationBase(CLRDATA_ADDRESS appDomain, int count, __out_z __inout_ecount(count) wchar_t *base, unsigned int *pNeeded);
1158
1159 virtual HRESULT STDMETHODCALLTYPE GetFailedAssemblyData(CLRDATA_ADDRESS assembly, unsigned int *pContext, HRESULT *pResult);
1160 virtual HRESULT STDMETHODCALLTYPE GetFailedAssemblyLocation(CLRDATA_ADDRESS assembly, unsigned int count, __out_z __inout_ecount(count) wchar_t *location, unsigned int *pNeeded);
1161 virtual HRESULT STDMETHODCALLTYPE GetFailedAssemblyDisplayName(CLRDATA_ADDRESS assembly, unsigned int count, __out_z __inout_ecount(count) wchar_t *name, unsigned int *pNeeded);
1162
1163 virtual HRESULT STDMETHODCALLTYPE GetStackReferences(DWORD osThreadID, ISOSStackRefEnum **ppEnum);
1164 virtual HRESULT STDMETHODCALLTYPE GetRegisterName(int regNum, unsigned int count, __out_z __inout_ecount(count) wchar_t *buffer, unsigned int *pNeeded);
1165
1166 virtual HRESULT STDMETHODCALLTYPE GetHandleEnum(ISOSHandleEnum **ppHandleEnum);
1167 virtual HRESULT STDMETHODCALLTYPE GetHandleEnumForTypes(unsigned int types[], unsigned int count, ISOSHandleEnum **ppHandleEnum);
1168 virtual HRESULT STDMETHODCALLTYPE GetHandleEnumForGC(unsigned int gen, ISOSHandleEnum **ppHandleEnum);
1169
1170 virtual HRESULT STDMETHODCALLTYPE GetThreadAllocData(CLRDATA_ADDRESS thread, struct DacpAllocData *data);
1171 virtual HRESULT STDMETHODCALLTYPE GetHeapAllocData(unsigned int count, struct DacpGenerationAllocData *data, unsigned int *pNeeded);
1172
1173 // ISOSDacInterface2
1174 virtual HRESULT STDMETHODCALLTYPE GetObjectExceptionData(CLRDATA_ADDRESS objAddr, struct DacpExceptionObjectData *data);
1175 virtual HRESULT STDMETHODCALLTYPE IsRCWDCOMProxy(CLRDATA_ADDRESS rcwAddr, BOOL* isDCOMProxy);
1176
1177 // ISOSDacInterface3
1178 virtual HRESULT STDMETHODCALLTYPE GetGCInterestingInfoData(CLRDATA_ADDRESS interestingInfoAddr, struct DacpGCInterestingInfoData *data);
1179 virtual HRESULT STDMETHODCALLTYPE GetGCInterestingInfoStaticData(struct DacpGCInterestingInfoData *data);
1180 virtual HRESULT STDMETHODCALLTYPE GetGCGlobalMechanisms(size_t* globalMechanisms);
1181
1182 // ISOSDacInterface4
1183 virtual HRESULT STDMETHODCALLTYPE GetClrNotification(CLRDATA_ADDRESS arguments[], int count, int *pNeeded);
1184
1185 // ISOSDacInterface5
1186 virtual HRESULT STDMETHODCALLTYPE GetTieredVersions(CLRDATA_ADDRESS methodDesc, int rejitId, struct DacpTieredVersionData *nativeCodeAddrs, int cNativeCodeAddrs, int *pcNativeCodeAddrs);
1187
1188 // ISOSDacInterface6
1189 virtual HRESULT STDMETHODCALLTYPE GetMethodTableCollectibleData(CLRDATA_ADDRESS mt, struct DacpMethodTableCollectibleData *data);
1190
1191 //
1192 // ClrDataAccess.
1193 //
1194
1195 HRESULT Initialize(void);
1196
1197 BOOL IsExceptionFromManagedCode(EXCEPTION_RECORD * pExceptionRecord);
1198#ifndef FEATURE_PAL
1199 HRESULT GetWatsonBuckets(DWORD dwThreadId, GenericModeBlock * pGM);
1200#endif // FEATURE_PAL
1201
1202
1203 Thread* FindClrThreadByTaskId(ULONG64 taskId);
1204 HRESULT IsPossibleCodeAddress(IN TADDR address);
1205
1206 PCSTR GetJitHelperName(IN TADDR address,
1207 IN bool dynamicHelpersOnly = false);
1208 HRESULT GetFullMethodName(IN MethodDesc* methodDesc,
1209 IN ULONG32 symbolChars,
1210 IN ULONG32* symbolLen,
1211 __out_ecount_part_opt(symbolChars, *symbolLen) LPWSTR symbol);
1212 HRESULT RawGetMethodName(/* [in] */ CLRDATA_ADDRESS address,
1213 /* [in] */ ULONG32 flags,
1214 /* [in] */ ULONG32 bufLen,
1215 /* [out] */ ULONG32 *nameLen,
1216 /* [size_is][out] */ __out_ecount_opt(bufLen) WCHAR nameBuf[ ],
1217 /* [out] */ CLRDATA_ADDRESS* displacement);
1218
1219 HRESULT FollowStubStep(
1220 /* [in] */ Thread* thread,
1221 /* [in] */ ULONG32 inFlags,
1222 /* [in] */ TADDR inAddr,
1223 /* [in] */ union STUB_BUF* inBuffer,
1224 /* [out] */ TADDR* outAddr,
1225 /* [out] */ union STUB_BUF* outBuffer,
1226 /* [out] */ ULONG32* outFlags);
1227
1228 DebuggerJitInfo* GetDebuggerJitInfo(MethodDesc* methodDesc,
1229 TADDR addr)
1230 {
1231 if (g_pDebugger)
1232 {
1233 return g_pDebugger->GetJitInfo(methodDesc, (PBYTE)addr, NULL);
1234 }
1235
1236 return NULL;
1237 }
1238
1239 HRESULT GetMethodExtents(MethodDesc* methodDesc,
1240 METH_EXTENTS** extents);
1241 HRESULT GetMethodVarInfo(MethodDesc* methodDesc,
1242 TADDR address,
1243 ULONG32* numVarInfo,
1244 ICorDebugInfo::NativeVarInfo** varInfo,
1245 ULONG32* codeOffset);
1246
1247 // If the method has multiple copies of code (because of EnC or code-pitching),
1248 // this returns the info corresponding to address.
1249 // If 'address' and 'codeOffset' are both non-NULL, *codeOffset gets set to
1250 // the offset of 'address' from the start of the method.
1251 HRESULT GetMethodNativeMap(MethodDesc* methodDesc,
1252 TADDR address,
1253 ULONG32* numMap,
1254 DebuggerILToNativeMap** map,
1255 bool* mapAllocated,
1256 CLRDATA_ADDRESS* codeStart,
1257 ULONG32* codeOffset);
1258
1259 // Get the MethodDesc for a function
1260 MethodDesc * FindLoadedMethodRefOrDef(Module* pModule, mdToken memberRef);
1261
1262#ifndef FEATURE_PAL
1263 HRESULT GetClrWatsonBucketsWorker(Thread * pThread, GenericModeBlock * pGM);
1264#endif // FEATURE_PAL
1265
1266 HRESULT ServerGCHeapDetails(CLRDATA_ADDRESS heapAddr,
1267 DacpGcHeapDetails *detailsData);
1268 HRESULT GetServerAllocData(unsigned int count, struct DacpGenerationAllocData *data, unsigned int *pNeeded);
1269 HRESULT ServerOomData(CLRDATA_ADDRESS addr, DacpOomData *oomData);
1270 HRESULT ServerGCInterestingInfoData(CLRDATA_ADDRESS addr, DacpGCInterestingInfoData *interestingInfoData);
1271 HRESULT ServerGCHeapAnalyzeData(CLRDATA_ADDRESS heapAddr,
1272 DacpGcHeapAnalyzeData *analyzeData);
1273
1274 //
1275 // Memory enumeration.
1276 //
1277
1278 HRESULT EnumMemoryRegionsWrapper(CLRDataEnumMemoryFlags flags);
1279
1280 // skinny minidump functions
1281 HRESULT EnumMemoryRegionsWorkerSkinny(CLRDataEnumMemoryFlags flags);
1282 // triage minidump functions
1283 HRESULT EnumMemoryRegionsWorkerMicroTriage(CLRDataEnumMemoryFlags flags);
1284 HRESULT EnumMemoryRegionsWorkerHeap(CLRDataEnumMemoryFlags flags);
1285
1286 HRESULT EnumMemWalkStackHelper(CLRDataEnumMemoryFlags flags, IXCLRDataStackWalk *pStackWalk, Thread * pThread);
1287 HRESULT DumpManagedObject(CLRDataEnumMemoryFlags flags, OBJECTREF objRef);
1288 HRESULT DumpManagedExcepObject(CLRDataEnumMemoryFlags flags, OBJECTREF objRef);
1289 HRESULT DumpManagedStackTraceStringObject(CLRDataEnumMemoryFlags flags, STRINGREF orefStackTrace);
1290#ifdef FEATURE_COMINTEROP
1291 HRESULT DumpStowedExceptionObject(CLRDataEnumMemoryFlags flags, CLRDATA_ADDRESS ccwPtr);
1292 HRESULT EnumMemStowedException(CLRDataEnumMemoryFlags flags);
1293#endif
1294
1295 HRESULT EnumMemWriteDataSegment();
1296
1297 // Custom Dump
1298 HRESULT EnumMemoryRegionsWorkerCustom();
1299
1300 // helper function for dump code
1301 void EnumWksGlobalMemoryRegions(CLRDataEnumMemoryFlags flags);
1302 void EnumSvrGlobalMemoryRegions(CLRDataEnumMemoryFlags flags);
1303
1304 HRESULT EnumMemCollectImages();
1305 HRESULT EnumMemCLRStatic(CLRDataEnumMemoryFlags flags);
1306 HRESULT EnumMemCLRHeapCrticalStatic(CLRDataEnumMemoryFlags flags);
1307 HRESULT EnumMemDumpModuleList(CLRDataEnumMemoryFlags flags);
1308 HRESULT EnumMemDumpAppDomainInfo(CLRDataEnumMemoryFlags flags);
1309 HRESULT EnumMemDumpAllThreadsStack(CLRDataEnumMemoryFlags flags);
1310 HRESULT EnumMemCLRMainModuleInfo();
1311
1312 bool ReportMem(TADDR addr, TSIZE_T size, bool fExpectSuccess = true);
1313 bool DacUpdateMemoryRegion(TADDR addr, TSIZE_T bufferSize, BYTE* buffer);
1314
1315 void ClearDumpStats();
1316 JITNotification* GetHostJitNotificationTable();
1317 GcNotification* GetHostGcNotificationTable();
1318
1319 void* GetMetaDataFromHost(PEFile* peFile,
1320 bool* isAlternate);
1321
1322 virtual
1323 interface IMDInternalImport* GetMDImport(const PEFile* peFile,
1324 const ReflectionModule* reflectionModule,
1325 bool throwEx);
1326
1327 interface IMDInternalImport* GetMDImport(const PEFile* peFile,
1328 bool throwEx)
1329 {
1330 return GetMDImport(peFile, NULL, throwEx);
1331 }
1332
1333 interface IMDInternalImport* GetMDImport(const ReflectionModule* reflectionModule,
1334 bool throwEx)
1335 {
1336 return GetMDImport(NULL, reflectionModule, throwEx);
1337 }
1338
1339 //ClrDump support
1340 HRESULT STDMETHODCALLTYPE DumpNativeImage(CLRDATA_ADDRESS loadedBase,
1341 LPCWSTR name,
1342 IXCLRDataDisplay *display,
1343 IXCLRLibrarySupport *support,
1344 IXCLRDisassemblySupport *dis);
1345
1346 // Set whether inconsistencies in the target should raise asserts.
1347 void SetTargetConsistencyChecks(bool fEnableAsserts);
1348
1349 // Get whether inconsistencies in the target should raise asserts.
1350 bool TargetConsistencyAssertsEnabled();
1351
1352 // Get the ICLRDataTarget2 instance, if any
1353 ICLRDataTarget2 * GetLegacyTarget2() { return m_pLegacyTarget2; }
1354
1355 // Get the ICLRDataTarget3 instance, if any
1356 ICLRDataTarget3 * GetLegacyTarget3() { return m_pLegacyTarget3; }
1357
1358 //
1359 // Public Fields
1360 // Note that it would be nice if all of these were made private. However, the visibility
1361 // model of the DAC implementation is that the public surface area is declared in daccess.h
1362 // (implemented in dacfn.cpp), and the private surface area (like ClrDataAccess) is declared
1363 // in dacimpl.h which is only included by the DAC infrastructure. Therefore the DAC
1364 // infrastructure agressively uses these fields, and we don't get a huge amount of benefit from
1365 // reworking this model (since there is some form of encapsulation in place already).
1366 //
1367
1368 // The underlying data target - always present (strong reference)
1369 ICorDebugDataTarget * m_pTarget;
1370
1371 // Mutable version of the data target if any - optional (strong reference)
1372 ICorDebugMutableDataTarget * m_pMutableTarget;
1373
1374 TADDR m_globalBase;
1375 DacInstanceManager m_instances;
1376 ULONG32 m_instanceAge;
1377 bool m_debugMode;
1378
1379#ifdef FEATURE_MINIMETADATA_IN_TRIAGEDUMPS
1380
1381protected:
1382 DacStreamManager * m_streams;
1383
1384public:
1385 // Used to mark the point after which enumerated EE structs of interest
1386 // will get their names cached in the triage/mini-dump
1387 void InitStreamsForWriting(IN CLRDataEnumMemoryFlags flags);
1388
1389 // Used during triage/mini-dump collection to populate the map of
1390 // pointers to EE struct (MethodDesc* for now) to their corresponding
1391 // name.
1392 bool MdCacheAddEEName(TADDR taEEStruct, const SString& name);
1393
1394 // Used to mark the end point for the name caching. Will update streams
1395 // based on built caches
1396 void EnumStreams(IN CLRDataEnumMemoryFlags flags);
1397
1398 // Used during triage/mini-dump analysis to retrieve the name associated
1399 // with an EE struct pointer (MethodDesc* for now).
1400 bool MdCacheGetEEName(TADDR taEEStruct, SString & eeName);
1401
1402#endif // FEATURE_MINIMETADATA_IN_TRIAGEDUMPS
1403
1404private:
1405 // Read the DAC table and initialize g_dacGlobals
1406 HRESULT GetDacGlobals();
1407
1408 // Verify the target mscorwks.dll matches the version expected
1409 HRESULT VerifyDlls();
1410
1411 // Check whether a region of memory is fully readable.
1412 bool IsFullyReadable(TADDR addr, TSIZE_T size);
1413
1414 // Legacy target interfaces - optional
1415 ICLRDataTarget * m_pLegacyTarget;
1416 ICLRDataTarget2 * m_pLegacyTarget2;
1417 ICLRDataTarget3 * m_pLegacyTarget3;
1418 IXCLRDataTarget3 * m_target3;
1419 ICLRMetadataLocator * m_legacyMetaDataLocator;
1420
1421 LONG m_refs;
1422 MDImportsCache m_mdImports;
1423 ICLRDataEnumMemoryRegionsCallback* m_enumMemCb;
1424 ICLRDataEnumMemoryRegionsCallback2* m_updateMemCb;
1425 CLRDataEnumMemoryFlags m_enumMemFlags;
1426 JITNotification* m_jitNotificationTable;
1427 GcNotification* m_gcNotificationTable;
1428 TSIZE_T m_cbMemoryReported;
1429 DumpMemoryReportStatics m_dumpStats;
1430
1431 // If true, inconsistencies in the target will cause ASSERTs to be raised in DEBUG builds
1432 bool m_fEnableTargetConsistencyAsserts;
1433
1434#ifdef _DEBUG
1435protected:
1436 // If true, a mscorwks/mscordacwks mismatch will trigger a nice assert dialog
1437 bool m_fEnableDllVerificationAsserts;
1438private:
1439#endif
1440
1441#ifdef FEATURE_COMINTEROP
1442protected:
1443 // Returns CCW pointer based on a target address.
1444 PTR_ComCallWrapper DACGetCCWFromAddress(CLRDATA_ADDRESS addr);
1445
1446private:
1447 // Returns COM interface pointer corresponding to a given CCW and internal vtable
1448 // index. Returns NULL if the vtable is unused or not fully laid out.
1449 PTR_IUnknown DACGetCOMIPFromCCW(PTR_ComCallWrapper pCCW, int vtableIndex);
1450#endif
1451
1452 static LONG s_procInit;
1453
1454public:
1455 // APIs for picking up the info needed for a debugger to look up an ngen image or IL image
1456 // from it's search path.
1457 static bool GetMetaDataFileInfoFromPEFile(PEFile *pPEFile,
1458 DWORD &dwImageTimestamp,
1459 DWORD &dwImageSize,
1460 DWORD &dwDataSize,
1461 DWORD &dwRvaHint,
1462 bool &isNGEN,
1463 __out_ecount(cchFilePath) LPWSTR wszFilePath,
1464 DWORD cchFilePath);
1465
1466 static bool GetILImageInfoFromNgenPEFile(PEFile *peFile,
1467 DWORD &dwTimeStamp,
1468 DWORD &dwSize,
1469 __out_ecount(cchPath) LPWSTR wszPath,
1470 const DWORD cchPath);
1471#if defined(FEATURE_CORESYSTEM)
1472 static bool GetILImageNameFromNgenImage(LPCWSTR ilExtension,
1473 __out_ecount(cchFilePath) LPWSTR wszFilePath,
1474 const DWORD cchFilePath);
1475#endif // FEATURE_CORESYSTEM
1476};
1477
1478extern ClrDataAccess* g_dacImpl;
1479
1480/* DacHandleWalker.
1481 *
1482 * Iterates over the handle table, enumerating all handles of the requested type on the
1483 * handle table. This also will report the handle type, whether the handle is a strong
1484 * reference, the AppDomain the handle comes from, as well as the reference count (in
1485 * the case of a RefCount handle). Optionally this class can also be used to filter
1486 * based on GC generation that would be collected (that is, to emulate a GC scan of the
1487 * handle table).
1488 *
1489 * General implementation details:
1490 * We have four sets of variables:
1491 * 1. Overhead variables needed to operate in the Dac.
1492 * 2. Variables needed to walk the handle table. We walk the handle table one bucket
1493 * at a time, filling the array the user gave us until we have either enumerated
1494 * all handles, or filled the array.
1495 * 3. Storage variables to hold the overflow. That is, we were walking the handle
1496 * table, filled the array that the user gave us, then needed to store the extra
1497 * handles the handle table continued to enumerate to us. This is implmeneted
1498 * as a linked list of arrays (mHead, mHead.Next, etc).
1499 * 4. Variables which store the location of where we are in the overflow data.
1500 *
1501 * Note that "mHead" is a HandleChunkHead where we stuff the user's array. Everything
1502 * which follows mHead (mHead.Next, etc) is a HandleChunk containing overflow data.
1503 *
1504 * Lastly, note this does not do robust error handling. If we fail to allocate a
1505 * HandleChunk while walking the handle table, we will miss handles and not report
1506 * this to the user. Unfortunately this will have to be fixed in the next iteration
1507 * when we add more robust error handling to SOS's interface.
1508 */
1509 template <class T>
1510class DefaultCOMImpl : public T
1511{
1512public:
1513 DefaultCOMImpl()
1514 : mRef(0)
1515 {
1516 }
1517
1518 virtual ~DefaultCOMImpl() {}
1519
1520 ULONG STDMETHODCALLTYPE AddRef()
1521 {
1522 return ++mRef;
1523 }
1524
1525 ULONG STDMETHODCALLTYPE Release()
1526 {
1527 ULONG res = mRef--;
1528 if (res == 0)
1529 delete this;
1530 return res;
1531 }
1532
1533 HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppObj)
1534 {
1535 if (ppObj == NULL)
1536 return E_INVALIDARG;
1537
1538 if (IsEqualIID(riid, IID_IUnknown))
1539 {
1540 AddRef();
1541 *ppObj = static_cast<IUnknown*>(this);
1542 return S_OK;
1543 }
1544 else if (IsEqualIID(riid, __uuidof(T)))
1545 {
1546 AddRef();
1547 *ppObj = static_cast<T*>(this);
1548 return S_OK;
1549 }
1550
1551 *ppObj = NULL;
1552 return E_NOINTERFACE;
1553 }
1554
1555private:
1556 ULONG mRef;
1557};
1558
1559
1560// A stuct representing a thread's allocation context.
1561struct AllocInfo
1562{
1563 CORDB_ADDRESS Ptr;
1564 CORDB_ADDRESS Limit;
1565
1566 AllocInfo()
1567 : Ptr(0), Limit(0)
1568 {
1569 }
1570};
1571
1572// A struct representing a segment in the heap.
1573struct SegmentData
1574{
1575 CORDB_ADDRESS Start;
1576 CORDB_ADDRESS End;
1577
1578 // Whether this segment is part of the large object heap.
1579 int Generation;
1580
1581 SegmentData()
1582 : Start(0), End(0), Generation(0)
1583 {
1584 }
1585};
1586
1587// A struct representing a gc heap in the process.
1588struct HeapData
1589{
1590 CORDB_ADDRESS YoungestGenPtr;
1591 CORDB_ADDRESS YoungestGenLimit;
1592
1593 CORDB_ADDRESS Gen0Start;
1594 CORDB_ADDRESS Gen0End;
1595
1596 CORDB_ADDRESS Gen1Start;
1597 size_t EphemeralSegment;
1598
1599 size_t SegmentCount;
1600 SegmentData *Segments;
1601
1602 HeapData();
1603 ~HeapData();
1604};
1605
1606/* This cache is used to read data from the target process if the reads are known
1607 * to be sequential. This will object will read one page of memory out of the
1608 * process at a time, aligned to the page boundary, to
1609 */
1610class LinearReadCache
1611{
1612public:
1613 LinearReadCache();
1614 ~LinearReadCache();
1615
1616 /* Reads an address out of the target process, caching the page of memory read.
1617 * Params:
1618 * addr - The address to read out of the target process.
1619 * t - A pointer to the data to stuff it in. We will read sizeof(T) data
1620 * from the process and write it into the location t points to. This
1621 * parameter must be non-null.
1622 * Returns:
1623 * True if the read succeeded. False if it did not, usually as a result
1624 * of the memory simply not being present in the target process.
1625 * Note:
1626 * The state of *t is undefined if this function returns false. We may
1627 * have written partial data to it if we return false, so you must
1628 * absolutely NOT use it if Read returns false.
1629 */
1630 template <class T>
1631 bool Read(CORDB_ADDRESS addr, T *t)
1632 {
1633 _ASSERTE(t);
1634
1635 // Unfortunately the ctor can fail the alloc for the byte array. In this case
1636 // we'll just fall back to non-cached reads.
1637 if (mPage == NULL)
1638 return MisalignedRead(addr, t);
1639
1640 // Is addr on the current page? If not read the page of memory addr is on.
1641 // If this fails, we will fall back to a raw read out of the process (which
1642 // is what MisalignedRead does).
1643 if ((addr < mCurrPageStart) || (addr - mCurrPageStart > mCurrPageSize))
1644 if (!MoveToPage(addr))
1645 return MisalignedRead(addr, t);
1646
1647 // If MoveToPage succeeds, we MUST be on the right page.
1648 _ASSERTE(addr >= mCurrPageStart);
1649
1650 // However, the amount of data requested may fall off of the page. In that case,
1651 // fall back to MisalignedRead.
1652 CORDB_ADDRESS offset = addr - mCurrPageStart;
1653 if (offset + sizeof(T) > mCurrPageSize)
1654 return MisalignedRead(addr, t);
1655
1656 // If we reach here we know we are on the right page of memory in the cache, and
1657 // that the read won't fall off of the end of the page.
1658 *t = *reinterpret_cast<T*>(mPage+offset);
1659 return true;
1660 }
1661
1662 // helper used to read the MethodTable
1663 bool ReadMT(CORDB_ADDRESS addr, TADDR *mt)
1664 {
1665 if (!Read(addr, mt))
1666 return false;
1667
1668 // clear the GC flag bits off the MethodTable
1669 // equivalent to Object::GetGCSafeMethodTable()
1670 *mt &= ~3;
1671 return true;
1672 }
1673
1674private:
1675 /* Sets the cache to the page specified by addr, or false if we could not move to
1676 * that page.
1677 */
1678 bool MoveToPage(CORDB_ADDRESS addr);
1679
1680 /* Attempts to read from the target process if the data is possibly hanging off
1681 * the end of a page.
1682 */
1683 template<class T>
1684 inline bool MisalignedRead(CORDB_ADDRESS addr, T *t)
1685 {
1686 return SUCCEEDED(DacReadAll(TO_TADDR(addr), t, sizeof(T), false));
1687 }
1688
1689private:
1690 CORDB_ADDRESS mCurrPageStart;
1691 ULONG32 mPageSize, mCurrPageSize;
1692 BYTE *mPage;
1693};
1694
1695DWORD DacGetNumHeaps();
1696
1697/* The implementation of the dac heap walker. This class will enumerate all objects on
1698 * the heap with three important caveats:
1699 * - This class will skip all Free objects in the heap. Free objects are an
1700 * implementation detail of the GC, and ICorDebug does not have a mechanism
1701 * to expose them.
1702 * - This class does NOT guarantee that all objects will be enumerated. In
1703 * the event that we find heap corruption on a segment, or if the background
1704 * GC is modifying a segment, the remainder of that segment will be skipped
1705 * by design.
1706 * - The GC heap must be in a walkable state before you attempt to use this
1707 * class on it. The IDacDbiInterface::AreGCStructuresValid function will
1708 * tell you whether it is safe to walk the heap or not.
1709 */
1710class DacHeapWalker
1711{
1712 static CORDB_ADDRESS HeapStart;
1713 static CORDB_ADDRESS HeapEnd;
1714
1715public:
1716 DacHeapWalker();
1717 ~DacHeapWalker();
1718
1719 /* Initializes the heap walker. This must be called before Next or
1720 * HasMoreObjects. Returns false if the initialization was not successful.
1721 * (In practice this should only return false if we hit an OOM trying
1722 * to allocate space for data structures.) Limits the heap walk to be in the range
1723 * [start, end] (inclusive). Use DacHeapWalker::HeapStart, DacHeapWalker::HeapEnd
1724 * as start or end to start from the beginning or end.
1725 */
1726 HRESULT Init(CORDB_ADDRESS start=HeapStart, CORDB_ADDRESS end=HeapEnd);
1727
1728 /* Returns a CORDB_ADDRESS which points to the next value on the heap.
1729 * You must call HasMoreObjects on this class, and it must return true
1730 * before calling Next.
1731 */
1732 HRESULT Next(CORDB_ADDRESS *pValue, CORDB_ADDRESS *pMT, ULONG64 *size);
1733
1734 /* Returns true if there are more objects on the heap, false otherwise.
1735 */
1736 inline bool HasMoreObjects() const
1737 {
1738 return mCurrHeap < mHeapCount;
1739 }
1740
1741 HRESULT Reset(CORDB_ADDRESS start, CORDB_ADDRESS end);
1742
1743 static HRESULT InitHeapDataWks(HeapData *&pHeaps, size_t &count);
1744 static HRESULT InitHeapDataSvr(HeapData *&pHeaps, size_t &count);
1745
1746 HRESULT GetHeapData(HeapData **ppHeapData, size_t *pNumHeaps);
1747
1748 SegmentData *FindSegment(CORDB_ADDRESS obj);
1749
1750 HRESULT ListNearObjects(CORDB_ADDRESS obj, CORDB_ADDRESS *pPrev, CORDB_ADDRESS *pContaining, CORDB_ADDRESS *pNext);
1751
1752private:
1753 HRESULT MoveToNextObject();
1754
1755 bool GetSize(TADDR tMT, size_t &size);
1756
1757 inline static size_t Align(size_t size)
1758 {
1759 if (sizeof(TADDR) == 4)
1760 return (size+3) & ~3;
1761 else
1762 return (size+7) & ~7;
1763 }
1764
1765 inline static size_t AlignLarge(size_t size)
1766 {
1767 return (size + 7) & ~7;
1768 }
1769
1770 template <class T>
1771 static int GetSegmentCount(T seg_start)
1772 {
1773 int count = 0;
1774 while (seg_start)
1775 {
1776 // If we find this many segments, something is seriously wrong.
1777 if (count++ > 4096)
1778 break;
1779
1780 seg_start = seg_start->next;
1781 }
1782
1783 return count;
1784 }
1785
1786 HRESULT NextSegment();
1787 void CheckAllocAndSegmentRange();
1788
1789private:
1790 int mThreadCount;
1791 AllocInfo *mAllocInfo;
1792
1793 size_t mHeapCount;
1794 HeapData *mHeaps;
1795
1796 CORDB_ADDRESS mCurrObj;
1797 size_t mCurrSize;
1798 TADDR mCurrMT;
1799
1800 size_t mCurrHeap;
1801 size_t mCurrSeg;
1802
1803 CORDB_ADDRESS mStart;
1804 CORDB_ADDRESS mEnd;
1805
1806 LinearReadCache mCache;
1807 static CORDB_ADDRESS sFreeMT;
1808};
1809
1810struct DacGcReference;
1811struct SOSStackErrorList
1812{
1813 SOSStackRefError error;
1814 SOSStackErrorList *pNext;
1815
1816 SOSStackErrorList()
1817 : pNext(0)
1818 {
1819 }
1820};
1821
1822class DacStackReferenceWalker;
1823class DacStackReferenceErrorEnum : public DefaultCOMImpl<ISOSStackRefErrorEnum>
1824{
1825public:
1826 DacStackReferenceErrorEnum(DacStackReferenceWalker *pEnum, SOSStackErrorList *pErrors);
1827 ~DacStackReferenceErrorEnum();
1828
1829 HRESULT STDMETHODCALLTYPE Skip(unsigned int count);
1830 HRESULT STDMETHODCALLTYPE Reset();
1831 HRESULT STDMETHODCALLTYPE GetCount(unsigned int *pCount);
1832 HRESULT STDMETHODCALLTYPE Next(unsigned int count, SOSStackRefError ref[], unsigned int *pFetched);
1833
1834private:
1835 // The lifetime of the error list is tied to the enum, so we must addref/release it.
1836 DacStackReferenceWalker *mEnum;
1837 SOSStackErrorList *mHead;
1838 SOSStackErrorList *mCurr;
1839};
1840
1841// For GCCONTEXT
1842#include "gcenv.h"
1843
1844 /* DacStackReferenceWalker.
1845 */
1846class DacStackReferenceWalker : public DefaultCOMImpl<ISOSStackRefEnum>
1847{
1848 struct DacScanContext : public ScanContext
1849 {
1850 DacStackReferenceWalker *pWalker;
1851 Frame *pFrame;
1852 TADDR sp, pc;
1853 bool stop;
1854 GCEnumCallback pEnumFunc;
1855
1856 DacScanContext()
1857 : pWalker(NULL), pFrame(0), sp(0), pc(0), stop(false), pEnumFunc(0)
1858 {
1859 }
1860 };
1861
1862 typedef struct _StackRefChunkHead
1863 {
1864 struct _StackRefChunkHead *next; // Next chunk
1865 unsigned int count; // The count of how many StackRefs were written to pData
1866 unsigned int size; // The capacity of pData (in bytes)
1867 void *pData; // The overflow data
1868
1869 _StackRefChunkHead()
1870 : next(0), count(0), size(0), pData(0)
1871 {
1872 }
1873 } StackRefChunkHead;
1874
1875 // The actual struct used for storing overflow StackRefs
1876 typedef struct _StackRefChunk : public StackRefChunkHead
1877 {
1878 SOSStackRefData data[64];
1879
1880 _StackRefChunk()
1881 {
1882 pData = data;
1883 size = sizeof(data);
1884 }
1885 } StackRefChunk;
1886public:
1887 DacStackReferenceWalker(ClrDataAccess *dac, DWORD osThreadID);
1888 virtual ~DacStackReferenceWalker();
1889
1890 HRESULT Init();
1891
1892 HRESULT STDMETHODCALLTYPE Skip(unsigned int count);
1893 HRESULT STDMETHODCALLTYPE Reset();
1894 HRESULT STDMETHODCALLTYPE GetCount(unsigned int *pCount);
1895 HRESULT STDMETHODCALLTYPE Next(unsigned int count,
1896 SOSStackRefData refs[],
1897 unsigned int *pFetched);
1898
1899 // Dac-Dbi Functions
1900 HRESULT Next(ULONG celt, DacGcReference roots[], ULONG *pceltFetched);
1901 Thread *GetThread() const
1902 {
1903 return mThread;
1904 }
1905
1906 HRESULT STDMETHODCALLTYPE EnumerateErrors(ISOSStackRefErrorEnum **ppEnum);
1907
1908private:
1909 static StackWalkAction Callback(CrawlFrame *pCF, VOID *pData);
1910 static void GCEnumCallbackSOS(LPVOID hCallback, OBJECTREF *pObject, uint32_t flags, DacSlotLocation loc);
1911 static void GCReportCallbackSOS(PTR_PTR_Object ppObj, ScanContext *sc, uint32_t flags);
1912 static void GCEnumCallbackDac(LPVOID hCallback, OBJECTREF *pObject, uint32_t flags, DacSlotLocation loc);
1913 static void GCReportCallbackDac(PTR_PTR_Object ppObj, ScanContext *sc, uint32_t flags);
1914
1915 CLRDATA_ADDRESS ReadPointer(TADDR addr);
1916
1917 template <class StructType>
1918 StructType *GetNextObject(DacScanContext *ctx)
1919 {
1920 SUPPORTS_DAC;
1921
1922 // If we failed on a previous call (OOM) don't keep trying to allocate, it's not going to work.
1923 if (ctx->stop || !mCurr)
1924 return NULL;
1925
1926 // We've moved past the size of the current chunk. We'll allocate a new chunk
1927 // and stuff the references there. These are cleaned up by the destructor.
1928 if (mCurr->count >= mCurr->size/sizeof(StructType))
1929 {
1930 if (mCurr->next == NULL)
1931 {
1932 StackRefChunk *next = new (nothrow) StackRefChunk;
1933 if (next != NULL)
1934 {
1935 mCurr->next = next;
1936 }
1937 else
1938 {
1939 ctx->stop = true;
1940 return NULL;
1941 }
1942 }
1943
1944 mCurr = mCurr->next;
1945 }
1946
1947 // Fill the current ref.
1948 StructType *pData = (StructType*)mCurr->pData;
1949 return &pData[mCurr->count++];
1950 }
1951
1952
1953 template <class IntType, class StructType>
1954 IntType WalkStack(IntType count, StructType refs[], promote_func promote, GCEnumCallback enumFunc)
1955 {
1956 _ASSERTE(mThread);
1957 _ASSERTE(!mEnumerated);
1958
1959 // If this is the first time we were called, fill local data structures.
1960 // This will fill out the user's handles as well.
1961 _ASSERTE(mCurr == NULL);
1962 _ASSERTE(mHead.next == NULL);
1963
1964 // Get the current thread's context and set that as the filter context
1965 if (mThread->GetFilterContext() == NULL && mThread->GetProfilerFilterContext() == NULL)
1966 {
1967 T_CONTEXT ctx;
1968 mDac->m_pTarget->GetThreadContext(mThread->GetOSThreadId(), CONTEXT_FULL, sizeof(ctx), (BYTE*)&ctx);
1969 mThread->SetProfilerFilterContext(&ctx);
1970 }
1971
1972 // Setup GCCONTEXT structs for the stackwalk.
1973 GCCONTEXT gcctx;
1974 DacScanContext dsc;
1975 dsc.pWalker = this;
1976 dsc.pEnumFunc = enumFunc;
1977 gcctx.f = promote;
1978 gcctx.sc = &dsc;
1979
1980 // Put the user's array/count in the
1981 mHead.size = count*sizeof(StructType);
1982 mHead.pData = refs;
1983 mHead.count = 0;
1984
1985 mCurr = &mHead;
1986
1987 // Walk the stack, set mEnumerated to true to ensure we don't do it again.
1988 unsigned int flagsStackWalk = ALLOW_INVALID_OBJECTS|ALLOW_ASYNC_STACK_WALK|SKIP_GSCOOKIE_CHECK;
1989#if defined(WIN64EXCEPTIONS)
1990 flagsStackWalk |= GC_FUNCLET_REFERENCE_REPORTING;
1991#endif // defined(WIN64EXCEPTIONS)
1992
1993 mEnumerated = true;
1994 mThread->StackWalkFrames(DacStackReferenceWalker::Callback, &gcctx, flagsStackWalk);
1995
1996 // We have filled the user's array as much as we could. If there's more data than
1997 // could fit, mHead.Next will contain a linked list of refs to enumerate.
1998 mCurr = mHead.next;
1999
2000 // Return how many we put in the user's array.
2001 return mHead.count;
2002 }
2003
2004 template <class IntType, class StructType, promote_func PromoteFunc, GCEnumCallback EnumFunc>
2005 HRESULT DoStackWalk(IntType count, StructType stackRefs[], IntType *pFetched)
2006 {
2007 HRESULT hr = S_OK;
2008 IntType fetched = 0;
2009 if (!mEnumerated)
2010 {
2011 // If this is the first time we were called, fill local data structures.
2012 // This will fill out the user's handles as well.
2013 fetched = (IntType)WalkStack((unsigned int)count, stackRefs, PromoteFunc, EnumFunc);
2014 }
2015
2016 while (fetched < count)
2017 {
2018 if (mCurr == NULL)
2019 {
2020 // Case 1: We have no more refs to walk.
2021 hr = S_FALSE;
2022 break;
2023 }
2024 else if (mChunkIndex >= mCurr->count)
2025 {
2026 // Case 2: We have exhausted the current chunk.
2027 mCurr = mCurr->next;
2028 mChunkIndex = 0;
2029 }
2030 else
2031 {
2032 // Case 3: The last call to "Next" filled the user's array and had some ref
2033 // data leftover. Walk the linked-list of arrays copying them into the user's
2034 // buffer until we have either exhausted the user's array or the leftover data.
2035 IntType toCopy = count - fetched; // Fill the user's buffer...
2036
2037 // ...unless that would go past the bounds of the current chunk.
2038 if (toCopy + mChunkIndex > mCurr->count)
2039 toCopy = mCurr->count - mChunkIndex;
2040
2041 memcpy(stackRefs+fetched, (StructType*)mCurr->pData+mChunkIndex, toCopy*sizeof(StructType));
2042 mChunkIndex += toCopy;
2043 fetched += toCopy;
2044 }
2045 }
2046
2047 *pFetched = fetched;
2048
2049 return hr;
2050 }
2051
2052private:
2053 // Dac variables required for entering/leaving the dac.
2054 ClrDataAccess *mDac;
2055 ULONG32 m_instanceAge;
2056
2057 // Operational variables
2058 Thread *mThread;
2059 SOSStackErrorList *mErrors;
2060 bool mEnumerated;
2061
2062 // Storage variables
2063 StackRefChunkHead mHead;
2064 unsigned int mChunkIndex;
2065
2066 // Iterator variables
2067 StackRefChunkHead *mCurr;
2068 int mIteratorIndex;
2069
2070 // Heap. Used to resolve interior pointers.
2071 DacHeapWalker mHeap;
2072};
2073
2074
2075
2076struct DacGcReference;
2077class DacHandleWalker : public DefaultCOMImpl<ISOSHandleEnum>
2078{
2079 typedef struct _HandleChunkHead
2080 {
2081 struct _HandleChunkHead *Next; // Next chunk
2082 unsigned int Count; // The count of how many handles were written to pData
2083 unsigned int Size; // The capacity of pData
2084 void *pData; // The overflow data
2085
2086 _HandleChunkHead()
2087 : Next(0), Count(0), Size(0), pData(0)
2088 {
2089 }
2090 } HandleChunkHead;
2091
2092 // The actual struct used for storing overflow handles
2093 typedef struct _HandleChunk : public HandleChunkHead
2094 {
2095 SOSHandleData Data[128];
2096
2097 _HandleChunk()
2098 {
2099 pData = Data;
2100 Size = sizeof(Data);
2101 }
2102 } HandleChunk;
2103
2104 // Parameter used in HndEnumHandles callback.
2105 struct DacHandleWalkerParam
2106 {
2107 HandleChunkHead *Curr; // The current chunk to write to
2108 HRESULT Result; // HRESULT of the current enumeration
2109 CLRDATA_ADDRESS AppDomain; // The AppDomain for the current bucket we are walking
2110 unsigned int Type; // The type of handle we are currently walking
2111
2112 DacHandleWalkerParam(HandleChunk *curr)
2113 : Curr(curr), Result(S_OK), AppDomain(0), Type(0)
2114 {
2115 }
2116 };
2117
2118public:
2119 DacHandleWalker();
2120 virtual ~DacHandleWalker();
2121
2122 HRESULT Init(ClrDataAccess *dac, UINT types[], UINT typeCount);
2123 HRESULT Init(ClrDataAccess *dac, UINT types[], UINT typeCount, int gen);
2124 HRESULT Init(UINT32 typemask);
2125
2126 // SOS functions
2127 HRESULT STDMETHODCALLTYPE Skip(unsigned int count);
2128 HRESULT STDMETHODCALLTYPE Reset();
2129 HRESULT STDMETHODCALLTYPE GetCount(unsigned int *pCount);
2130 HRESULT STDMETHODCALLTYPE Next(unsigned int count,
2131 SOSHandleData handles[],
2132 unsigned int *pNeeded);
2133
2134 // Dac-Dbi Functions
2135 HRESULT Next(ULONG celt, DacGcReference roots[], ULONG *pceltFetched);
2136private:
2137 static void CALLBACK EnumCallback(PTR_UNCHECKED_OBJECTREF pref, LPARAM *pExtraInfo, LPARAM userParam, LPARAM type);
2138 static void GetRefCountedHandleInfo(
2139 OBJECTREF oref, unsigned int uType,
2140 unsigned int *pRefCount, unsigned int *pJupiterRefCount, BOOL *pIsPegged, BOOL *pIsStrong);
2141 static UINT32 BuildTypemask(UINT types[], UINT typeCount);
2142
2143private:
2144 static void CALLBACK EnumCallbackSOS(PTR_UNCHECKED_OBJECTREF pref, uintptr_t *pExtraInfo, uintptr_t userParam, uintptr_t type);
2145 static void CALLBACK EnumCallbackDac(PTR_UNCHECKED_OBJECTREF pref, uintptr_t *pExtraInfo, uintptr_t userParam, uintptr_t type);
2146
2147 bool FetchMoreHandles(HANDLESCANPROC proc);
2148 static inline bool IsAlwaysStrongReference(unsigned int type)
2149 {
2150 return type == HNDTYPE_STRONG || type == HNDTYPE_PINNED || type == HNDTYPE_ASYNCPINNED || type == HNDTYPE_SIZEDREF;
2151 }
2152
2153 template <class StructType, class IntType, HANDLESCANPROC EnumFunc>
2154 HRESULT DoHandleWalk(IntType celt, StructType handles[], IntType *pceltFetched)
2155 {
2156 SUPPORTS_DAC;
2157
2158 if (handles == NULL || pceltFetched == NULL)
2159 return E_POINTER;
2160
2161 HRESULT hr = S_OK;
2162 IntType fetched = 0;
2163 bool done = false;
2164
2165 // On each iteration of the loop, either fetch more handles (filling in
2166 // the user's data structure), or copy handles from previous calls to
2167 // FetchMoreHandles which we could not store in the user's data (or simply
2168 // advance the current chunk to the next chunk).
2169 while (fetched < celt)
2170 {
2171 if (mCurr == NULL)
2172 {
2173 // Case 1: We have no overflow data. Stuff the user's array/size into
2174 // mHead, fetch more handles. Additionally, if the previous call to
2175 // FetchMoreHandles returned false (mMap == NULL), break.
2176 if (mMap == NULL)
2177 break;
2178
2179 mHead.pData = handles+fetched;
2180 mHead.Size = (celt - fetched)*sizeof(StructType);
2181
2182 done = !FetchMoreHandles(EnumFunc);
2183 fetched += mHead.Count;
2184
2185 // Sanity check to make sure we haven't overflowed. This should not happen.
2186 _ASSERTE(fetched <= celt);
2187 }
2188 else if (mChunkIndex >= mCurr->Count)
2189 {
2190 // Case 2: We have overflow data, but the current index into the current
2191 // chunk is past the bounds. Move to the next. This could set mCurr to
2192 // null, which we'll catch on the next iteration.
2193 mCurr = mCurr->Next;
2194 mChunkIndex = 0;
2195 }
2196 else
2197 {
2198 // Case 3: The last call to "Next" filled the user's array and had some handle
2199 // data leftover. Walk the linked-list of arrays copying them into the user's
2200 // buffer until we have either exhausted the user's array or the leftover data.
2201 unsigned int toCopy = celt - fetched; // Fill the user's buffer...
2202
2203 // ...unless that would go past the bounds of the current chunk.
2204 if (toCopy + mChunkIndex > mCurr->Count)
2205 toCopy = mCurr->Count - mChunkIndex;
2206
2207 memcpy(handles+fetched, ((StructType*)(mCurr->pData))+mChunkIndex, toCopy*sizeof(StructType));
2208 mChunkIndex += toCopy;
2209 fetched += toCopy;
2210 }
2211 }
2212
2213 if (fetched < celt)
2214 hr = S_FALSE;
2215
2216 *pceltFetched = fetched;
2217
2218 return hr;
2219 }
2220
2221private:
2222 // Dac variables required for entering/leaving the dac.
2223 ClrDataAccess *mDac;
2224 ULONG32 m_instanceAge;
2225
2226 // Handle table walking variables.
2227 dac_handle_table_map *mMap;
2228 int mIndex;
2229 UINT32 mTypeMask;
2230 int mGenerationFilter;
2231
2232 // Storage variables
2233 HandleChunk mHead;
2234 unsigned int mChunkIndex;
2235
2236 // Iterator variables
2237 HandleChunkHead *mCurr;
2238 int mIteratorIndex;
2239};
2240
2241
2242//----------------------------------------------------------------------------
2243//
2244// ClrDataAppDomain.
2245//
2246//----------------------------------------------------------------------------
2247
2248class ClrDataAppDomain : public IXCLRDataAppDomain
2249{
2250public:
2251 ClrDataAppDomain(ClrDataAccess* dac,
2252 AppDomain* appDomain);
2253 virtual ~ClrDataAppDomain(void);
2254
2255 // IUnknown.
2256 STDMETHOD(QueryInterface)(THIS_
2257 IN REFIID interfaceId,
2258 OUT PVOID* iface);
2259 STDMETHOD_(ULONG, AddRef)(THIS);
2260 STDMETHOD_(ULONG, Release)(THIS);
2261
2262 //
2263 // IXCLRDataAppDomain.
2264 //
2265
2266 virtual HRESULT STDMETHODCALLTYPE GetProcess(
2267 /* [out] */ IXCLRDataProcess **process);
2268
2269 virtual HRESULT STDMETHODCALLTYPE GetName(
2270 /* [in] */ ULONG32 bufLen,
2271 /* [out] */ ULONG32 *nameLen,
2272 /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR name[ ]);
2273
2274 virtual HRESULT STDMETHODCALLTYPE GetUniqueID(
2275 /* [out] */ ULONG64 *id);
2276
2277 virtual HRESULT STDMETHODCALLTYPE GetFlags(
2278 /* [out] */ ULONG32 *flags);
2279
2280 virtual HRESULT STDMETHODCALLTYPE IsSameObject(
2281 /* [in] */ IXCLRDataAppDomain *appDomain);
2282
2283 virtual HRESULT STDMETHODCALLTYPE GetManagedObject(
2284 /* [out] */ IXCLRDataValue **value);
2285
2286 virtual HRESULT STDMETHODCALLTYPE Request(
2287 /* [in] */ ULONG32 reqCode,
2288 /* [in] */ ULONG32 inBufferSize,
2289 /* [size_is][in] */ BYTE *inBuffer,
2290 /* [in] */ ULONG32 outBufferSize,
2291 /* [size_is][out] */ BYTE *outBuffer);
2292
2293 AppDomain* GetAppDomain(void)
2294 {
2295 SUPPORTS_DAC;
2296 return m_appDomain;
2297 }
2298
2299private:
2300 LONG m_refs;
2301 ClrDataAccess* m_dac;
2302 ULONG32 m_instanceAge;
2303 AppDomain* m_appDomain;
2304};
2305
2306//----------------------------------------------------------------------------
2307//
2308// ClrDataAssembly.
2309//
2310//----------------------------------------------------------------------------
2311
2312class ClrDataAssembly : public IXCLRDataAssembly
2313{
2314public:
2315 ClrDataAssembly(ClrDataAccess* dac,
2316 Assembly* assembly);
2317 virtual ~ClrDataAssembly(void);
2318
2319 // IUnknown.
2320 STDMETHOD(QueryInterface)(THIS_
2321 IN REFIID interfaceId,
2322 OUT PVOID* iface);
2323 STDMETHOD_(ULONG, AddRef)(THIS);
2324 STDMETHOD_(ULONG, Release)(THIS);
2325
2326 //
2327 // IXCLRDataAssembly.
2328 //
2329
2330 virtual HRESULT STDMETHODCALLTYPE StartEnumModules(
2331 /* [out] */ CLRDATA_ENUM *handle);
2332
2333 virtual HRESULT STDMETHODCALLTYPE EnumModule(
2334 /* [in, out] */ CLRDATA_ENUM* handle,
2335 /* [out] */ IXCLRDataModule **mod);
2336
2337 virtual HRESULT STDMETHODCALLTYPE EndEnumModules(
2338 /* [in] */ CLRDATA_ENUM handle);
2339
2340 virtual HRESULT STDMETHODCALLTYPE StartEnumAppDomains(
2341 /* [out] */ CLRDATA_ENUM *handle);
2342
2343 virtual HRESULT STDMETHODCALLTYPE EnumAppDomain(
2344 /* [in, out] */ CLRDATA_ENUM* handle,
2345 /* [out] */ IXCLRDataAppDomain **appDomain);
2346
2347 virtual HRESULT STDMETHODCALLTYPE EndEnumAppDomains(
2348 /* [in] */ CLRDATA_ENUM handle);
2349
2350 virtual HRESULT STDMETHODCALLTYPE GetName(
2351 /* [in] */ ULONG32 bufLen,
2352 /* [out] */ ULONG32 *nameLen,
2353 /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR name[ ]);
2354
2355 virtual HRESULT STDMETHODCALLTYPE GetFileName(
2356 /* [in] */ ULONG32 bufLen,
2357 /* [out] */ ULONG32 *nameLen,
2358 /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR name[ ]);
2359
2360 virtual HRESULT STDMETHODCALLTYPE GetDisplayName(
2361 /* [in] */ ULONG32 bufLen,
2362 /* [out] */ ULONG32 *nameLen,
2363 /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR name[ ]);
2364
2365 virtual HRESULT STDMETHODCALLTYPE GetFlags(
2366 /* [out] */ ULONG32 *flags);
2367
2368 virtual HRESULT STDMETHODCALLTYPE IsSameObject(
2369 /* [in] */ IXCLRDataAssembly *assembly);
2370
2371 virtual HRESULT STDMETHODCALLTYPE Request(
2372 /* [in] */ ULONG32 reqCode,
2373 /* [in] */ ULONG32 inBufferSize,
2374 /* [size_is][in] */ BYTE *inBuffer,
2375 /* [in] */ ULONG32 outBufferSize,
2376 /* [size_is][out] */ BYTE *outBuffer);
2377
2378private:
2379 LONG m_refs;
2380 ClrDataAccess* m_dac;
2381 ULONG32 m_instanceAge;
2382 Assembly* m_assembly;
2383};
2384
2385//----------------------------------------------------------------------------
2386//
2387// ClrDataModule.
2388//
2389//----------------------------------------------------------------------------
2390
2391class ClrDataModule : public IXCLRDataModule, IXCLRDataModule2
2392{
2393public:
2394 ClrDataModule(ClrDataAccess* dac,
2395 Module* module);
2396 virtual ~ClrDataModule(void);
2397
2398 // IUnknown.
2399 STDMETHOD(QueryInterface)(THIS_
2400 IN REFIID interfaceId,
2401 OUT PVOID* iface);
2402 STDMETHOD_(ULONG, AddRef)(THIS);
2403 STDMETHOD_(ULONG, Release)(THIS);
2404
2405 //
2406 // IXCLRDataModule.
2407 //
2408
2409 virtual HRESULT STDMETHODCALLTYPE StartEnumAssemblies(
2410 /* [out] */ CLRDATA_ENUM *handle);
2411
2412 virtual HRESULT STDMETHODCALLTYPE EnumAssembly(
2413 /* [in, out] */ CLRDATA_ENUM* handle,
2414 /* [out] */ IXCLRDataAssembly **assembly);
2415
2416 virtual HRESULT STDMETHODCALLTYPE EndEnumAssemblies(
2417 /* [in] */ CLRDATA_ENUM handle);
2418
2419 virtual HRESULT STDMETHODCALLTYPE StartEnumAppDomains(
2420 /* [out] */ CLRDATA_ENUM *handle);
2421
2422 virtual HRESULT STDMETHODCALLTYPE EnumAppDomain(
2423 /* [in, out] */ CLRDATA_ENUM* handle,
2424 /* [out] */ IXCLRDataAppDomain **appDomain);
2425
2426 virtual HRESULT STDMETHODCALLTYPE EndEnumAppDomains(
2427 /* [in] */ CLRDATA_ENUM handle);
2428
2429 virtual HRESULT STDMETHODCALLTYPE StartEnumTypeDefinitions(
2430 /* [out] */ CLRDATA_ENUM *handle);
2431
2432 virtual HRESULT STDMETHODCALLTYPE EnumTypeDefinition(
2433 /* [in, out] */ CLRDATA_ENUM* handle,
2434 /* [out] */ IXCLRDataTypeDefinition **typeDefinition);
2435
2436 virtual HRESULT STDMETHODCALLTYPE EndEnumTypeDefinitions(
2437 /* [in] */ CLRDATA_ENUM handle);
2438
2439 virtual HRESULT STDMETHODCALLTYPE StartEnumTypeInstances(
2440 /* [in] */ IXCLRDataAppDomain* appDomain,
2441 /* [out] */ CLRDATA_ENUM *handle);
2442
2443 virtual HRESULT STDMETHODCALLTYPE EnumTypeInstance(
2444 /* [in, out] */ CLRDATA_ENUM* handle,
2445 /* [out] */ IXCLRDataTypeInstance **typeInstance);
2446
2447 virtual HRESULT STDMETHODCALLTYPE EndEnumTypeInstances(
2448 /* [in] */ CLRDATA_ENUM handle);
2449
2450 virtual HRESULT STDMETHODCALLTYPE StartEnumTypeDefinitionsByName(
2451 /* [in] */ LPCWSTR name,
2452 /* [in] */ ULONG32 flags,
2453 /* [out] */ CLRDATA_ENUM *handle);
2454
2455 virtual HRESULT STDMETHODCALLTYPE EnumTypeDefinitionByName(
2456 /* [out][in] */ CLRDATA_ENUM *handle,
2457 /* [out] */ IXCLRDataTypeDefinition **type);
2458
2459 virtual HRESULT STDMETHODCALLTYPE EndEnumTypeDefinitionsByName(
2460 /* [in] */ CLRDATA_ENUM handle);
2461
2462 virtual HRESULT STDMETHODCALLTYPE StartEnumTypeInstancesByName(
2463 /* [in] */ LPCWSTR name,
2464 /* [in] */ ULONG32 flags,
2465 /* [in] */ IXCLRDataAppDomain *appDomain,
2466 /* [out] */ CLRDATA_ENUM *handle);
2467
2468 virtual HRESULT STDMETHODCALLTYPE EnumTypeInstanceByName(
2469 /* [out][in] */ CLRDATA_ENUM *handle,
2470 /* [out] */ IXCLRDataTypeInstance **type);
2471
2472 virtual HRESULT STDMETHODCALLTYPE EndEnumTypeInstancesByName(
2473 /* [in] */ CLRDATA_ENUM handle);
2474
2475 virtual HRESULT STDMETHODCALLTYPE GetTypeDefinitionByToken(
2476 /* [in] */ mdTypeDef token,
2477 /* [out] */ IXCLRDataTypeDefinition **typeDefinition);
2478
2479 virtual HRESULT STDMETHODCALLTYPE StartEnumMethodDefinitionsByName(
2480 /* [in] */ LPCWSTR name,
2481 /* [in] */ ULONG32 flags,
2482 /* [out] */ CLRDATA_ENUM *handle);
2483
2484 virtual HRESULT STDMETHODCALLTYPE EnumMethodDefinitionByName(
2485 /* [in] */ CLRDATA_ENUM* handle,
2486 /* [out] */ IXCLRDataMethodDefinition **method);
2487
2488 virtual HRESULT STDMETHODCALLTYPE EndEnumMethodDefinitionsByName(
2489 /* [in] */ CLRDATA_ENUM handle);
2490
2491 virtual HRESULT STDMETHODCALLTYPE StartEnumMethodInstancesByName(
2492 /* [in] */ LPCWSTR name,
2493 /* [in] */ ULONG32 flags,
2494 /* [in] */ IXCLRDataAppDomain* appDomain,
2495 /* [out] */ CLRDATA_ENUM *handle);
2496
2497 virtual HRESULT STDMETHODCALLTYPE EnumMethodInstanceByName(
2498 /* [in] */ CLRDATA_ENUM* handle,
2499 /* [out] */ IXCLRDataMethodInstance **method);
2500
2501 virtual HRESULT STDMETHODCALLTYPE EndEnumMethodInstancesByName(
2502 /* [in] */ CLRDATA_ENUM handle);
2503
2504 virtual HRESULT STDMETHODCALLTYPE GetMethodDefinitionByToken(
2505 /* [in] */ mdMethodDef token,
2506 /* [out] */ IXCLRDataMethodDefinition **methodDefinition);
2507
2508 virtual HRESULT STDMETHODCALLTYPE StartEnumDataByName(
2509 /* [in] */ LPCWSTR name,
2510 /* [in] */ ULONG32 flags,
2511 /* [in] */ IXCLRDataAppDomain* appDomain,
2512 /* [in] */ IXCLRDataTask* tlsTask,
2513 /* [out] */ CLRDATA_ENUM *handle);
2514
2515 virtual HRESULT STDMETHODCALLTYPE EnumDataByName(
2516 /* [in] */ CLRDATA_ENUM* handle,
2517 /* [out] */ IXCLRDataValue **value);
2518
2519 virtual HRESULT STDMETHODCALLTYPE EndEnumDataByName(
2520 /* [in] */ CLRDATA_ENUM handle);
2521
2522 virtual HRESULT STDMETHODCALLTYPE GetName(
2523 /* [in] */ ULONG32 bufLen,
2524 /* [out] */ ULONG32 *nameLen,
2525 /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR name[ ]);
2526
2527 virtual HRESULT STDMETHODCALLTYPE GetFileName(
2528 /* [in] */ ULONG32 bufLen,
2529 /* [out] */ ULONG32 *nameLen,
2530 /* [size_is][out] */ __out_ecount_part(bufLen, *nameLen) WCHAR name[ ]);
2531
2532 virtual HRESULT STDMETHODCALLTYPE GetVersionId(
2533 /* [out] */ GUID* vid);
2534
2535 virtual HRESULT STDMETHODCALLTYPE GetFlags(
2536 /* [out] */ ULONG32 *flags);
2537
2538 virtual HRESULT STDMETHODCALLTYPE IsSameObject(
2539 /* [in] */ IXCLRDataModule *mod);
2540
2541 virtual HRESULT STDMETHODCALLTYPE StartEnumExtents(
2542 /* [out] */ CLRDATA_ENUM *handle);
2543
2544 virtual HRESULT STDMETHODCALLTYPE EnumExtent(
2545 /* [in, out] */ CLRDATA_ENUM* handle,
2546 /* [out] */ CLRDATA_MODULE_EXTENT *extent);
2547
2548 virtual HRESULT STDMETHODCALLTYPE EndEnumExtents(
2549 /* [in] */ CLRDATA_ENUM handle);
2550
2551 virtual HRESULT STDMETHODCALLTYPE Request(
2552 /* [in] */ ULONG32 reqCode,
2553 /* [in] */ ULONG32 inBufferSize,
2554 /* [size_is][in] */ BYTE *inBuffer,
2555 /* [in] */ ULONG32 outBufferSize,
2556 /* [size_is][out] */ BYTE *outBuffer);
2557
2558 HRESULT RequestGetModulePtr(IN ULONG32 inBufferSize,
2559 IN BYTE* inBuffer,
2560 IN ULONG32 outBufferSize,
2561 OUT BYTE* outBuffer);
2562
2563 HRESULT RequestGetModuleData(IN ULONG32 inBufferSize,
2564 IN BYTE* inBuffer,
2565 IN ULONG32 outBufferSize,
2566 OUT BYTE* outBuffer);
2567
2568 Module* GetModule(void)
2569 {
2570 return m_module;
2571 }
2572
2573 //
2574 // IXCLRDataModule2
2575 //
2576 virtual HRESULT STDMETHODCALLTYPE SetJITCompilerFlags(
2577 /* [in] */ DWORD dwFlags );
2578
2579private:
2580 // Returns an instance of IID_IMetaDataImport.
2581 HRESULT GetMdInterface(PVOID* retIface);
2582
2583 LONG m_refs;
2584 ClrDataAccess* m_dac;
2585 ULONG32 m_instanceAge;
2586 Module* m_module;
2587 IMetaDataImport* m_mdImport;
2588 bool m_setExtents;
2589 CLRDATA_MODULE_EXTENT m_extents[2];
2590 CLRDATA_MODULE_EXTENT* m_extentsEnd;
2591};
2592
2593//----------------------------------------------------------------------------
2594//
2595// ClrDataTypeDefinition.
2596//
2597//----------------------------------------------------------------------------
2598
2599class ClrDataTypeDefinition : public IXCLRDataTypeDefinition
2600{
2601public:
2602 ClrDataTypeDefinition(ClrDataAccess* dac,
2603 Module* module,
2604 mdTypeDef token,
2605 TypeHandle typeHandle);
2606 virtual ~ClrDataTypeDefinition(void);
2607
2608 // IUnknown.
2609 STDMETHOD(QueryInterface)(THIS_
2610 IN REFIID interfaceId,
2611 OUT PVOID* iface);
2612 STDMETHOD_(ULONG, AddRef)(THIS);
2613 STDMETHOD_(ULONG, Release)(THIS);
2614
2615 //
2616 // IXCLRDataTypeDefinition.
2617 //
2618
2619 virtual HRESULT STDMETHODCALLTYPE GetModule(
2620 /* [out] */ IXCLRDataModule **mod);
2621
2622 virtual HRESULT STDMETHODCALLTYPE StartEnumMethodDefinitions(
2623 /* [out] */ CLRDATA_ENUM *handle);
2624
2625 virtual HRESULT STDMETHODCALLTYPE EnumMethodDefinition(
2626 /* [in, out] */ CLRDATA_ENUM* handle,
2627 /* [out] */ IXCLRDataMethodDefinition **methodDefinition);
2628
2629 virtual HRESULT STDMETHODCALLTYPE EndEnumMethodDefinitions(
2630 /* [in] */ CLRDATA_ENUM handle);
2631
2632 virtual HRESULT STDMETHODCALLTYPE StartEnumMethodDefinitionsByName(
2633 /* [in] */ LPCWSTR name,
2634 /* [in] */ ULONG32 flags,
2635 /* [out] */ CLRDATA_ENUM *handle);
2636
2637 virtual HRESULT STDMETHODCALLTYPE EnumMethodDefinitionByName(
2638 /* [in] */ CLRDATA_ENUM* handle,
2639 /* [out] */ IXCLRDataMethodDefinition **method);
2640
2641 virtual HRESULT STDMETHODCALLTYPE EndEnumMethodDefinitionsByName(
2642 /* [in] */ CLRDATA_ENUM handle);
2643
2644 virtual HRESULT STDMETHODCALLTYPE GetMethodDefinitionByToken(
2645 /* [in] */ mdMethodDef token,
2646 /* [out] */ IXCLRDataMethodDefinition **methodDefinition);
2647
2648 virtual HRESULT STDMETHODCALLTYPE StartEnumInstances(
2649 /* [in] */ IXCLRDataAppDomain* appDomain,
2650 /* [out] */ CLRDATA_ENUM *handle);
2651
2652 virtual HRESULT STDMETHODCALLTYPE EnumInstance(
2653 /* [out][in] */ CLRDATA_ENUM *handle,
2654 /* [out] */ IXCLRDataTypeInstance **instance);
2655
2656 virtual HRESULT STDMETHODCALLTYPE EndEnumInstances(
2657 /* [in] */ CLRDATA_ENUM handle);
2658
2659 virtual HRESULT STDMETHODCALLTYPE GetNumFields(
2660 /* [in] */ ULONG32 flags,
2661 /* [out] */ ULONG32 *numFields);
2662
2663 virtual HRESULT STDMETHODCALLTYPE StartEnumFields(
2664 /* [in] */ ULONG32 flags,
2665 /* [out] */ CLRDATA_ENUM *handle);
2666
2667 virtual HRESULT STDMETHODCALLTYPE EnumField(
2668 /* [out][in] */ CLRDATA_ENUM *handle,
2669 /* [in] */ ULONG32 nameBufLen,
2670 /* [out] */ ULONG32 *nameLen,
2671 /* [size_is][out] */ __out_ecount_part_opt(nameBufLen, *nameLen) WCHAR nameBuf[ ],
2672 /* [out] */ IXCLRDataTypeDefinition **type,
2673 /* [out] */ ULONG32 *flags,
2674 /* [out] */ mdFieldDef *token);
2675
2676 virtual HRESULT STDMETHODCALLTYPE EnumField2(
2677 /* [out][in] */ CLRDATA_ENUM *handle,
2678 /* [in] */ ULONG32 nameBufLen,
2679 /* [out] */ ULONG32 *nameLen,
2680 /* [size_is][out] */ __out_ecount_part_opt(nameBufLen, *nameLen) WCHAR nameBuf[ ],
2681 /* [out] */ IXCLRDataTypeDefinition **type,
2682 /* [out] */ ULONG32 *flags,
2683 /* [out] */ IXCLRDataModule** tokenScope,
2684 /* [out] */ mdFieldDef *token);
2685
2686 virtual HRESULT STDMETHODCALLTYPE EndEnumFields(
2687 /* [in] */ CLRDATA_ENUM handle);
2688
2689 virtual HRESULT STDMETHODCALLTYPE StartEnumFieldsByName(
2690 /* [in] */ LPCWSTR name,
2691 /* [in] */ ULONG32 nameFlags,
2692 /* [in] */ ULONG32 fieldFlags,
2693 /* [out] */ CLRDATA_ENUM *handle);
2694
2695 virtual HRESULT STDMETHODCALLTYPE EnumFieldByName(
2696 /* [out][in] */ CLRDATA_ENUM *handle,
2697 /* [out] */ IXCLRDataTypeDefinition **type,
2698 /* [out] */ ULONG32 *flags,
2699 /* [out] */ mdFieldDef *token);
2700
2701 virtual HRESULT STDMETHODCALLTYPE EnumFieldByName2(
2702 /* [out][in] */ CLRDATA_ENUM *handle,
2703 /* [out] */ IXCLRDataTypeDefinition **type,
2704 /* [out] */ ULONG32 *flags,
2705 /* [out] */ IXCLRDataModule** tokenScope,
2706 /* [out] */ mdFieldDef *token);
2707
2708 virtual HRESULT STDMETHODCALLTYPE EndEnumFieldsByName(
2709 /* [in] */ CLRDATA_ENUM handle);
2710
2711 virtual HRESULT STDMETHODCALLTYPE GetFieldByToken(
2712 /* [in] */ mdFieldDef token,
2713 /* [in] */ ULONG32 nameBufLen,
2714 /* [out] */ ULONG32 *nameLen,
2715 /* [size_is][out] */ __out_ecount_part_opt(nameBufLen, *nameLen) WCHAR nameBuf[ ],
2716 /* [out] */ IXCLRDataTypeDefinition **type,
2717 /* [out] */ ULONG32* flags);
2718
2719 virtual HRESULT STDMETHODCALLTYPE GetFieldByToken2(
2720 /* [in] */ IXCLRDataModule* tokenScope,
2721 /* [in] */ mdFieldDef token,
2722 /* [in] */ ULONG32 nameBufLen,
2723 /* [out] */ ULONG32 *nameLen,
2724 /* [size_is][out] */ __out_ecount_part_opt(nameBufLen, *nameLen) WCHAR nameBuf[ ],
2725 /* [out] */ IXCLRDataTypeDefinition **type,
2726 /* [out] */ ULONG32* flags);
2727
2728 virtual HRESULT STDMETHODCALLTYPE GetName(
2729 /* [in] */ ULONG32 flags,
2730 /* [in] */ ULONG32 bufLen,
2731 /* [out] */ ULONG32 *nameLen,
2732 /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR nameBuf[ ]);
2733
2734 virtual HRESULT STDMETHODCALLTYPE GetTokenAndScope(
2735 /* [out] */ mdTypeDef *token,
2736 /* [out] */ IXCLRDataModule **mod);
2737
2738 virtual HRESULT STDMETHODCALLTYPE GetCorElementType(
2739 /* [out] */ CorElementType *type);
2740
2741 virtual HRESULT STDMETHODCALLTYPE GetFlags(
2742 /* [out] */ ULONG32 *flags);
2743
2744 virtual HRESULT STDMETHODCALLTYPE GetBase(
2745 /* [out] */ IXCLRDataTypeDefinition **base);
2746
2747 virtual HRESULT STDMETHODCALLTYPE IsSameObject(
2748 /* [in] */ IXCLRDataTypeDefinition *type);
2749
2750 virtual HRESULT STDMETHODCALLTYPE Request(
2751 /* [in] */ ULONG32 reqCode,
2752 /* [in] */ ULONG32 inBufferSize,
2753 /* [size_is][in] */ BYTE *inBuffer,
2754 /* [in] */ ULONG32 outBufferSize,
2755 /* [size_is][out] */ BYTE *outBuffer);
2756
2757 virtual HRESULT STDMETHODCALLTYPE GetArrayRank(
2758 /* [out] */ ULONG32* rank);
2759
2760 virtual HRESULT STDMETHODCALLTYPE GetTypeNotification(
2761 /* [out] */ ULONG32* flags);
2762
2763 virtual HRESULT STDMETHODCALLTYPE SetTypeNotification(
2764 /* [in] */ ULONG32 flags);
2765
2766 static HRESULT NewFromModule(ClrDataAccess* dac,
2767 Module* module,
2768 mdTypeDef token,
2769 ClrDataTypeDefinition** typeDef,
2770 IXCLRDataTypeDefinition** pubTypeDef);
2771
2772 TypeHandle GetTypeHandle(void)
2773 {
2774 return m_typeHandle;
2775 }
2776
2777private:
2778 LONG m_refs;
2779 ClrDataAccess* m_dac;
2780 ULONG32 m_instanceAge;
2781 Module* m_module;
2782 mdTypeDef m_token;
2783 TypeHandle m_typeHandle;
2784};
2785
2786//----------------------------------------------------------------------------
2787//
2788// ClrDataTypeInstance.
2789//
2790//----------------------------------------------------------------------------
2791
2792class ClrDataTypeInstance : public IXCLRDataTypeInstance
2793{
2794public:
2795 ClrDataTypeInstance(ClrDataAccess* dac,
2796 AppDomain* appDomain,
2797 TypeHandle typeHandle);
2798 virtual ~ClrDataTypeInstance(void);
2799
2800 // IUnknown.
2801 STDMETHOD(QueryInterface)(THIS_
2802 IN REFIID interfaceId,
2803 OUT PVOID* iface);
2804 STDMETHOD_(ULONG, AddRef)(THIS);
2805 STDMETHOD_(ULONG, Release)(THIS);
2806
2807 //
2808 // IXCLRDataTypeInstance.
2809 //
2810
2811 virtual HRESULT STDMETHODCALLTYPE StartEnumMethodInstances(
2812 /* [out] */ CLRDATA_ENUM *handle);
2813
2814 virtual HRESULT STDMETHODCALLTYPE EnumMethodInstance(
2815 /* [in, out] */ CLRDATA_ENUM* handle,
2816 /* [out] */ IXCLRDataMethodInstance **methodInstance);
2817
2818 virtual HRESULT STDMETHODCALLTYPE EndEnumMethodInstances(
2819 /* [in] */ CLRDATA_ENUM handle);
2820
2821 virtual HRESULT STDMETHODCALLTYPE StartEnumMethodInstancesByName(
2822 /* [in] */ LPCWSTR name,
2823 /* [in] */ ULONG32 flags,
2824 /* [out] */ CLRDATA_ENUM *handle);
2825
2826 virtual HRESULT STDMETHODCALLTYPE EnumMethodInstanceByName(
2827 /* [in] */ CLRDATA_ENUM* handle,
2828 /* [out] */ IXCLRDataMethodInstance **method);
2829
2830 virtual HRESULT STDMETHODCALLTYPE EndEnumMethodInstancesByName(
2831 /* [in] */ CLRDATA_ENUM handle);
2832
2833 virtual HRESULT STDMETHODCALLTYPE GetNumStaticFields(
2834 /* [out] */ ULONG32 *numFields);
2835
2836 virtual HRESULT STDMETHODCALLTYPE GetStaticFieldByIndex(
2837 /* [in] */ ULONG32 index,
2838 /* [in] */ IXCLRDataTask *tlsTask,
2839 /* [out] */ IXCLRDataValue **field,
2840 /* [in] */ ULONG32 bufLen,
2841 /* [out] */ ULONG32 *nameLen,
2842 /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR nameBuf[ ],
2843 /* [out] */ mdFieldDef *token);
2844
2845 virtual HRESULT STDMETHODCALLTYPE StartEnumStaticFieldsByName(
2846 /* [in] */ LPCWSTR name,
2847 /* [in] */ ULONG32 flags,
2848 /* [in] */ IXCLRDataTask *tlsTask,
2849 /* [out] */ CLRDATA_ENUM *handle);
2850
2851 virtual HRESULT STDMETHODCALLTYPE EnumStaticFieldByName(
2852 /* [out][in] */ CLRDATA_ENUM *handle,
2853 /* [out] */ IXCLRDataValue **value);
2854
2855 virtual HRESULT STDMETHODCALLTYPE EndEnumStaticFieldsByName(
2856 /* [in] */ CLRDATA_ENUM handle);
2857
2858 virtual HRESULT STDMETHODCALLTYPE GetNumStaticFields2(
2859 /* [in] */ ULONG32 flags,
2860 /* [out] */ ULONG32 *numFields);
2861
2862 virtual HRESULT STDMETHODCALLTYPE StartEnumStaticFields(
2863 /* [in] */ ULONG32 flags,
2864 /* [in] */ IXCLRDataTask *tlsTask,
2865 /* [out] */ CLRDATA_ENUM *handle);
2866
2867 virtual HRESULT STDMETHODCALLTYPE EnumStaticField(
2868 /* [out][in] */ CLRDATA_ENUM *handle,
2869 /* [out] */ IXCLRDataValue **value);
2870
2871 virtual HRESULT STDMETHODCALLTYPE EnumStaticField2(
2872 /* [out][in] */ CLRDATA_ENUM *handle,
2873 /* [out] */ IXCLRDataValue **value,
2874 /* [in] */ ULONG32 bufLen,
2875 /* [out] */ ULONG32 *nameLen,
2876 /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR nameBuf[ ],
2877 /* [out] */ IXCLRDataModule** tokenScope,
2878 /* [out] */ mdFieldDef *token);
2879
2880 virtual HRESULT STDMETHODCALLTYPE EndEnumStaticFields(
2881 /* [in] */ CLRDATA_ENUM handle);
2882
2883 virtual HRESULT STDMETHODCALLTYPE StartEnumStaticFieldsByName2(
2884 /* [in] */ LPCWSTR name,
2885 /* [in] */ ULONG32 nameFlags,
2886 /* [in] */ ULONG32 fieldFlags,
2887 /* [in] */ IXCLRDataTask *tlsTask,
2888 /* [out] */ CLRDATA_ENUM *handle);
2889
2890 virtual HRESULT STDMETHODCALLTYPE EnumStaticFieldByName3(
2891 /* [out][in] */ CLRDATA_ENUM *handle,
2892 /* [out] */ IXCLRDataValue **value,
2893 /* [out] */ IXCLRDataModule** tokenScope,
2894 /* [out] */ mdFieldDef *token);
2895
2896 virtual HRESULT STDMETHODCALLTYPE EnumStaticFieldByName2(
2897 /* [out][in] */ CLRDATA_ENUM *handle,
2898 /* [out] */ IXCLRDataValue **value);
2899
2900 virtual HRESULT STDMETHODCALLTYPE EndEnumStaticFieldsByName2(
2901 /* [in] */ CLRDATA_ENUM handle);
2902
2903 virtual HRESULT STDMETHODCALLTYPE GetStaticFieldByToken(
2904 /* [in] */ mdFieldDef token,
2905 /* [in] */ IXCLRDataTask *tlsTask,
2906 /* [out] */ IXCLRDataValue **field,
2907 /* [in] */ ULONG32 bufLen,
2908 /* [out] */ ULONG32 *nameLen,
2909 /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR nameBuf[ ]);
2910
2911 virtual HRESULT STDMETHODCALLTYPE GetStaticFieldByToken2(
2912 /* [in] */ IXCLRDataModule* tokenScope,
2913 /* [in] */ mdFieldDef token,
2914 /* [in] */ IXCLRDataTask *tlsTask,
2915 /* [out] */ IXCLRDataValue **field,
2916 /* [in] */ ULONG32 bufLen,
2917 /* [out] */ ULONG32 *nameLen,
2918 /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR nameBuf[ ]);
2919
2920 virtual HRESULT STDMETHODCALLTYPE GetName(
2921 /* [in] */ ULONG32 flags,
2922 /* [in] */ ULONG32 bufLen,
2923 /* [out] */ ULONG32 *nameLen,
2924 /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR nameBuf[ ]);
2925
2926 virtual HRESULT STDMETHODCALLTYPE GetModule(
2927 /* [out] */ IXCLRDataModule **mod);
2928
2929 virtual HRESULT STDMETHODCALLTYPE GetDefinition(
2930 /* [out] */ IXCLRDataTypeDefinition **typeDefinition);
2931
2932 virtual HRESULT STDMETHODCALLTYPE GetFlags(
2933 /* [out] */ ULONG32 *flags);
2934
2935 virtual HRESULT STDMETHODCALLTYPE GetBase(
2936 /* [out] */ IXCLRDataTypeInstance **base);
2937
2938 virtual HRESULT STDMETHODCALLTYPE IsSameObject(
2939 /* [in] */ IXCLRDataTypeInstance *type);
2940
2941 virtual HRESULT STDMETHODCALLTYPE GetNumTypeArguments(
2942 /* [out] */ ULONG32 *numTypeArgs);
2943
2944 virtual HRESULT STDMETHODCALLTYPE GetTypeArgumentByIndex(
2945 /* [in] */ ULONG32 index,
2946 /* [out] */ IXCLRDataTypeInstance **typeArg);
2947
2948 virtual HRESULT STDMETHODCALLTYPE Request(
2949 /* [in] */ ULONG32 reqCode,
2950 /* [in] */ ULONG32 inBufferSize,
2951 /* [size_is][in] */ BYTE *inBuffer,
2952 /* [in] */ ULONG32 outBufferSize,
2953 /* [size_is][out] */ BYTE *outBuffer);
2954
2955 static HRESULT NewFromModule(ClrDataAccess* dac,
2956 AppDomain* appDomain,
2957 Module* module,
2958 mdTypeDef token,
2959 ClrDataTypeInstance** typeInst,
2960 IXCLRDataTypeInstance** pubTypeInst);
2961
2962 TypeHandle GetTypeHandle(void)
2963 {
2964 return m_typeHandle;
2965 }
2966
2967private:
2968 LONG m_refs;
2969 ClrDataAccess* m_dac;
2970 ULONG32 m_instanceAge;
2971 AppDomain* m_appDomain;
2972 TypeHandle m_typeHandle;
2973};
2974
2975//----------------------------------------------------------------------------
2976//
2977// ClrDataMethodDefinition.
2978//
2979//----------------------------------------------------------------------------
2980
2981class ClrDataMethodDefinition : public IXCLRDataMethodDefinition
2982{
2983public:
2984 ClrDataMethodDefinition(ClrDataAccess* dac,
2985 Module* module,
2986 mdMethodDef token,
2987 MethodDesc* methodDesc);
2988 virtual ~ClrDataMethodDefinition(void);
2989
2990 // IUnknown.
2991 STDMETHOD(QueryInterface)(THIS_
2992 IN REFIID interfaceId,
2993 OUT PVOID* iface);
2994 STDMETHOD_(ULONG, AddRef)(THIS);
2995 STDMETHOD_(ULONG, Release)(THIS);
2996
2997 //
2998 // IXCLRDataMethodDefinition.
2999 //
3000
3001 virtual HRESULT STDMETHODCALLTYPE GetTypeDefinition(
3002 /* [out] */ IXCLRDataTypeDefinition **typeDefinition);
3003
3004 virtual HRESULT STDMETHODCALLTYPE StartEnumInstances(
3005 /* [in] */ IXCLRDataAppDomain* appDomain,
3006 /* [out] */ CLRDATA_ENUM *handle);
3007
3008 virtual HRESULT STDMETHODCALLTYPE EnumInstance(
3009 /* [out][in] */ CLRDATA_ENUM *handle,
3010 /* [out] */ IXCLRDataMethodInstance **instance);
3011
3012 virtual HRESULT STDMETHODCALLTYPE EndEnumInstances(
3013 /* [in] */ CLRDATA_ENUM handle);
3014
3015 virtual HRESULT STDMETHODCALLTYPE GetName(
3016 /* [in] */ ULONG32 flags,
3017 /* [in] */ ULONG32 bufLen,
3018 /* [out] */ ULONG32 *nameLen,
3019 /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR name[ ]);
3020
3021 virtual HRESULT STDMETHODCALLTYPE GetTokenAndScope(
3022 /* [out] */ mdMethodDef *token,
3023 /* [out] */ IXCLRDataModule **mod);
3024
3025 virtual HRESULT STDMETHODCALLTYPE GetFlags(
3026 /* [out] */ ULONG32 *flags);
3027
3028 virtual HRESULT STDMETHODCALLTYPE IsSameObject(
3029 /* [in] */ IXCLRDataMethodDefinition *method);
3030
3031 virtual HRESULT STDMETHODCALLTYPE GetLatestEnCVersion(
3032 /* [out] */ ULONG32* version);
3033
3034 virtual HRESULT STDMETHODCALLTYPE StartEnumExtents(
3035 /* [out] */ CLRDATA_ENUM *handle);
3036
3037 virtual HRESULT STDMETHODCALLTYPE EnumExtent(
3038 /* [out][in] */ CLRDATA_ENUM *handle,
3039 /* [out] */ CLRDATA_METHDEF_EXTENT *extent);
3040
3041 virtual HRESULT STDMETHODCALLTYPE EndEnumExtents(
3042 /* [in] */ CLRDATA_ENUM handle);
3043
3044 virtual HRESULT STDMETHODCALLTYPE GetCodeNotification(
3045 /* [out] */ ULONG32 *flags);
3046
3047 virtual HRESULT STDMETHODCALLTYPE SetCodeNotification(
3048 /* [in] */ ULONG32 flags);
3049
3050 virtual HRESULT STDMETHODCALLTYPE GetRepresentativeEntryAddress(
3051 /* [out] */ CLRDATA_ADDRESS* addr);
3052
3053 virtual HRESULT STDMETHODCALLTYPE HasClassOrMethodInstantiation(
3054 /*[out]*/ BOOL* bGeneric);
3055
3056 virtual HRESULT STDMETHODCALLTYPE Request(
3057 /* [in] */ ULONG32 reqCode,
3058 /* [in] */ ULONG32 inBufferSize,
3059 /* [size_is][in] */ BYTE *inBuffer,
3060 /* [in] */ ULONG32 outBufferSize,
3061 /* [size_is][out] */ BYTE *outBuffer);
3062
3063 COR_ILMETHOD* GetIlMethod(void);
3064
3065 static HRESULT NewFromModule(ClrDataAccess* dac,
3066 Module* module,
3067 mdMethodDef token,
3068 ClrDataMethodDefinition** methDef,
3069 IXCLRDataMethodDefinition** pubMethDef);
3070
3071 static HRESULT GetSharedMethodFlags(MethodDesc* methodDesc,
3072 ULONG32* flags);
3073
3074 // We don't need this if we are able to form name using token
3075 MethodDesc *GetMethodDesc() { return m_methodDesc;}
3076private:
3077 LONG m_refs;
3078 ClrDataAccess* m_dac;
3079 ULONG32 m_instanceAge;
3080 Module* m_module;
3081 mdMethodDef m_token;
3082 MethodDesc* m_methodDesc;
3083};
3084
3085//----------------------------------------------------------------------------
3086//
3087// ClrDataMethodInstance.
3088//
3089//----------------------------------------------------------------------------
3090
3091class ClrDataMethodInstance : public IXCLRDataMethodInstance
3092{
3093public:
3094 ClrDataMethodInstance(ClrDataAccess* dac,
3095 AppDomain* appDomain,
3096 MethodDesc* methodDesc);
3097 virtual ~ClrDataMethodInstance(void);
3098
3099 // IUnknown.
3100 STDMETHOD(QueryInterface)(THIS_
3101 IN REFIID interfaceId,
3102 OUT PVOID* iface);
3103 STDMETHOD_(ULONG, AddRef)(THIS);
3104 STDMETHOD_(ULONG, Release)(THIS);
3105
3106 //
3107 // IXCLRDataMethodInstance.
3108 //
3109
3110 virtual HRESULT STDMETHODCALLTYPE GetTypeInstance(
3111 /* [out] */ IXCLRDataTypeInstance **typeInstance);
3112
3113 virtual HRESULT STDMETHODCALLTYPE GetDefinition(
3114 /* [out] */ IXCLRDataMethodDefinition **methodDefinition);
3115
3116 virtual HRESULT STDMETHODCALLTYPE GetTokenAndScope(
3117 /* [out] */ mdMethodDef *token,
3118 /* [out] */ IXCLRDataModule **mod);
3119
3120 virtual HRESULT STDMETHODCALLTYPE GetName(
3121 /* [in] */ ULONG32 flags,
3122 /* [in] */ ULONG32 bufLen,
3123 /* [out] */ ULONG32 *nameLen,
3124 /* [size_is][out] */ __out_ecount_part(bufLen, *nameLen) WCHAR name[ ]);
3125
3126 virtual HRESULT STDMETHODCALLTYPE GetFlags(
3127 /* [out] */ ULONG32 *flags);
3128
3129 virtual HRESULT STDMETHODCALLTYPE IsSameObject(
3130 /* [in] */ IXCLRDataMethodInstance *method);
3131
3132 virtual HRESULT STDMETHODCALLTYPE GetEnCVersion(
3133 /* [out] */ ULONG32* version);
3134
3135 virtual HRESULT STDMETHODCALLTYPE GetNumTypeArguments(
3136 /* [out] */ ULONG32 *numTypeArgs);
3137
3138 virtual HRESULT STDMETHODCALLTYPE GetTypeArgumentByIndex(
3139 /* [in] */ ULONG32 index,
3140 /* [out] */ IXCLRDataTypeInstance **typeArg);
3141
3142 virtual HRESULT STDMETHODCALLTYPE GetILOffsetsByAddress(
3143 /* [in] */ CLRDATA_ADDRESS address,
3144 /* [in] */ ULONG32 offsetsLen,
3145 /* [out] */ ULONG32 *offsetsNeeded,
3146 /* [size_is][out] */ ULONG32 ilOffsets[ ]);
3147
3148 virtual HRESULT STDMETHODCALLTYPE GetAddressRangesByILOffset(
3149 /* [in] */ ULONG32 ilOffset,
3150 /* [in] */ ULONG32 rangesLen,
3151 /* [out] */ ULONG32 *rangesNeeded,
3152 /* [size_is][out] */ CLRDATA_ADDRESS_RANGE addressRanges[ ]);
3153
3154 virtual HRESULT STDMETHODCALLTYPE GetILAddressMap(
3155 /* [in] */ ULONG32 mapLen,
3156 /* [out] */ ULONG32 *mapNeeded,
3157 /* [size_is][out] */ CLRDATA_IL_ADDRESS_MAP maps[ ]);
3158
3159 virtual HRESULT STDMETHODCALLTYPE StartEnumExtents(
3160 /* [out] */ CLRDATA_ENUM *handle);
3161
3162 virtual HRESULT STDMETHODCALLTYPE EnumExtent(
3163 /* [out][in] */ CLRDATA_ENUM *handle,
3164 /* [out] */ CLRDATA_ADDRESS_RANGE *extent);
3165
3166 virtual HRESULT STDMETHODCALLTYPE EndEnumExtents(
3167 /* [in] */ CLRDATA_ENUM handle);
3168
3169 virtual HRESULT STDMETHODCALLTYPE GetRepresentativeEntryAddress(
3170 /* [out] */ CLRDATA_ADDRESS* addr);
3171
3172 virtual HRESULT STDMETHODCALLTYPE Request(
3173 /* [in] */ ULONG32 reqCode,
3174 /* [in] */ ULONG32 inBufferSize,
3175 /* [size_is][in] */ BYTE *inBuffer,
3176 /* [in] */ ULONG32 outBufferSize,
3177 /* [size_is][out] */ BYTE *outBuffer);
3178
3179 static HRESULT NewFromModule(ClrDataAccess* dac,
3180 AppDomain* appDomain,
3181 Module* module,
3182 mdMethodDef token,
3183 ClrDataMethodInstance** methInst,
3184 IXCLRDataMethodInstance** pubMethInst);
3185
3186private:
3187 friend class ClrDataAccess;
3188 LONG m_refs;
3189 ClrDataAccess* m_dac;
3190 ULONG32 m_instanceAge;
3191 AppDomain* m_appDomain;
3192 MethodDesc* m_methodDesc;
3193};
3194
3195//----------------------------------------------------------------------------
3196//
3197// ClrDataTask.
3198//
3199//----------------------------------------------------------------------------
3200
3201class ClrDataTask : public IXCLRDataTask
3202{
3203public:
3204 ClrDataTask(ClrDataAccess* dac,
3205 Thread* Thread);
3206 virtual ~ClrDataTask(void);
3207
3208 // IUnknown.
3209 STDMETHOD(QueryInterface)(THIS_
3210 IN REFIID interfaceId,
3211 OUT PVOID* iface);
3212 STDMETHOD_(ULONG, AddRef)(THIS);
3213 STDMETHOD_(ULONG, Release)(THIS);
3214
3215 //
3216 // IXCLRDataTask.
3217 //
3218
3219 virtual HRESULT STDMETHODCALLTYPE GetProcess(
3220 /* [out] */ IXCLRDataProcess **process);
3221
3222 virtual HRESULT STDMETHODCALLTYPE GetCurrentAppDomain(
3223 /* [out] */ IXCLRDataAppDomain **appDomain);
3224
3225 virtual HRESULT STDMETHODCALLTYPE GetName(
3226 /* [in] */ ULONG32 bufLen,
3227 /* [out] */ ULONG32 *nameLen,
3228 /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR name[ ]);
3229
3230 virtual HRESULT STDMETHODCALLTYPE GetUniqueID(
3231 /* [out] */ ULONG64 *id);
3232
3233 virtual HRESULT STDMETHODCALLTYPE GetFlags(
3234 /* [out] */ ULONG32 *flags);
3235
3236 virtual HRESULT STDMETHODCALLTYPE IsSameObject(
3237 /* [in] */ IXCLRDataTask *task);
3238
3239 virtual HRESULT STDMETHODCALLTYPE GetManagedObject(
3240 /* [out] */ IXCLRDataValue **value);
3241
3242 virtual HRESULT STDMETHODCALLTYPE GetDesiredExecutionState(
3243 /* [out] */ ULONG32 *state);
3244
3245 virtual HRESULT STDMETHODCALLTYPE SetDesiredExecutionState(
3246 /* [in] */ ULONG32 state);
3247
3248 virtual HRESULT STDMETHODCALLTYPE CreateStackWalk(
3249 /* [in] */ ULONG32 flags,
3250 /* [out] */ IXCLRDataStackWalk **stackWalk);
3251
3252 virtual HRESULT STDMETHODCALLTYPE GetOSThreadID(
3253 /* [out] */ ULONG32 *id);
3254
3255 virtual HRESULT STDMETHODCALLTYPE GetContext(
3256 /* [in] */ ULONG32 contextFlags,
3257 /* [in] */ ULONG32 contextBufSize,
3258 /* [out] */ ULONG32 *contextSize,
3259 /* [size_is][out] */ BYTE contextBuf[ ]);
3260
3261 virtual HRESULT STDMETHODCALLTYPE SetContext(
3262 /* [in] */ ULONG32 contextSize,
3263 /* [size_is][in] */ BYTE context[ ]);
3264
3265 virtual HRESULT STDMETHODCALLTYPE GetCurrentExceptionState(
3266 /* [out] */ IXCLRDataExceptionState **exception);
3267
3268 virtual HRESULT STDMETHODCALLTYPE GetLastExceptionState(
3269 /* [out] */ IXCLRDataExceptionState **exception);
3270
3271 virtual HRESULT STDMETHODCALLTYPE Request(
3272 /* [in] */ ULONG32 reqCode,
3273 /* [in] */ ULONG32 inBufferSize,
3274 /* [size_is][in] */ BYTE *inBuffer,
3275 /* [in] */ ULONG32 outBufferSize,
3276 /* [size_is][out] */ BYTE *outBuffer);
3277
3278 Thread* GetThread(void)
3279 {
3280 return m_thread;
3281 }
3282
3283private:
3284 LONG m_refs;
3285 ClrDataAccess* m_dac;
3286 ULONG32 m_instanceAge;
3287 Thread* m_thread;
3288};
3289
3290//----------------------------------------------------------------------------
3291//
3292// ClrDataStackWalk.
3293//
3294//----------------------------------------------------------------------------
3295
3296class ClrDataStackWalk : public IXCLRDataStackWalk
3297{
3298public:
3299 ClrDataStackWalk(ClrDataAccess* dac,
3300 Thread* Thread,
3301 ULONG32 flags);
3302 virtual ~ClrDataStackWalk(void);
3303
3304 // IUnknown.
3305 STDMETHOD(QueryInterface)(THIS_
3306 IN REFIID interfaceId,
3307 OUT PVOID* iface);
3308 STDMETHOD_(ULONG, AddRef)(THIS);
3309 STDMETHOD_(ULONG, Release)(THIS);
3310
3311 //
3312 // IXCLRDataStackWalk.
3313 //
3314
3315 virtual HRESULT STDMETHODCALLTYPE GetContext(
3316 /* [in] */ ULONG32 contextFlags,
3317 /* [in] */ ULONG32 contextBufSize,
3318 /* [out] */ ULONG32 *contextSize,
3319 /* [size_is][out] */ BYTE contextBuf[ ]);
3320
3321 virtual HRESULT STDMETHODCALLTYPE SetContext(
3322 /* [in] */ ULONG32 contextSize,
3323 /* [size_is][in] */ BYTE context[ ]);
3324
3325 virtual HRESULT STDMETHODCALLTYPE Next( void);
3326
3327 virtual HRESULT STDMETHODCALLTYPE GetStackSizeSkipped(
3328 /* [out] */ ULONG64 *stackSizeSkipped);
3329
3330 virtual HRESULT STDMETHODCALLTYPE GetFrameType(
3331 /* [out] */ CLRDataSimpleFrameType *simpleType,
3332 /* [out] */ CLRDataDetailedFrameType *detailedType);
3333
3334 virtual HRESULT STDMETHODCALLTYPE GetFrame(
3335 /* [out] */ IXCLRDataFrame **frame);
3336
3337 virtual HRESULT STDMETHODCALLTYPE Request(
3338 /* [in] */ ULONG32 reqCode,
3339 /* [in] */ ULONG32 inBufferSize,
3340 /* [size_is][in] */ BYTE *inBuffer,
3341 /* [in] */ ULONG32 outBufferSize,
3342 /* [size_is][out] */ BYTE *outBuffer);
3343
3344 virtual HRESULT STDMETHODCALLTYPE SetContext2(
3345 /* [in] */ ULONG32 flags,
3346 /* [in] */ ULONG32 contextSize,
3347 /* [size_is][in] */ BYTE context[ ]);
3348
3349 HRESULT Init(void);
3350
3351private:
3352 void FilterFrames(void);
3353 void RawGetFrameType(
3354 /* [out] */ CLRDataSimpleFrameType* simpleType,
3355 /* [out] */ CLRDataDetailedFrameType* detailedType);
3356
3357 LONG m_refs;
3358 ClrDataAccess* m_dac;
3359 ULONG32 m_instanceAge;
3360 Thread* m_thread;
3361 ULONG32 m_walkFlags;
3362 StackFrameIterator m_frameIter;
3363 REGDISPLAY m_regDisp;
3364 T_CONTEXT m_context;
3365 TADDR m_stackPrev;
3366
3367 // This is part of a test hook for debugging. Unless you're code:ClrDataStackWalk::Next
3368 // you should never do anything with this member.
3369 INDEBUG( int m_framesUnwound; )
3370
3371};
3372
3373//----------------------------------------------------------------------------
3374//
3375// ClrDataFrame.
3376//
3377//----------------------------------------------------------------------------
3378
3379class ClrDataFrame : public IXCLRDataFrame,
3380 IXCLRDataFrame2
3381{
3382 friend class ClrDataStackWalk;
3383
3384public:
3385 ClrDataFrame(ClrDataAccess* dac,
3386 CLRDataSimpleFrameType simpleType,
3387 CLRDataDetailedFrameType detailedType,
3388 AppDomain* appDomain,
3389 MethodDesc* methodDesc);
3390 virtual ~ClrDataFrame(void);
3391
3392 // IUnknown.
3393 STDMETHOD(QueryInterface)(THIS_
3394 IN REFIID interfaceId,
3395 OUT PVOID* iface);
3396 STDMETHOD_(ULONG, AddRef)(THIS);
3397 STDMETHOD_(ULONG, Release)(THIS);
3398
3399 //
3400 // IXCLRDataFrame.
3401 //
3402
3403 virtual HRESULT STDMETHODCALLTYPE GetContext(
3404 /* [in] */ ULONG32 contextFlags,
3405 /* [in] */ ULONG32 contextBufSize,
3406 /* [out] */ ULONG32 *contextSize,
3407 /* [size_is][out] */ BYTE contextBuf[ ]);
3408
3409 virtual HRESULT STDMETHODCALLTYPE GetFrameType(
3410 /* [out] */ CLRDataSimpleFrameType *simpleType,
3411 /* [out] */ CLRDataDetailedFrameType *detailedType);
3412
3413 virtual HRESULT STDMETHODCALLTYPE GetAppDomain(
3414 /* [out] */ IXCLRDataAppDomain **appDomain);
3415
3416 virtual HRESULT STDMETHODCALLTYPE GetNumArguments(
3417 /* [out] */ ULONG32 *numParams);
3418
3419 virtual HRESULT STDMETHODCALLTYPE GetArgumentByIndex(
3420 /* [in] */ ULONG32 index,
3421 /* [out] */ IXCLRDataValue **arg,
3422 /* [in] */ ULONG32 bufLen,
3423 /* [out] */ ULONG32 *nameLen,
3424 /* [size_is][out] */ __out_ecount_part(bufLen, *nameLen) WCHAR name[ ]);
3425
3426 virtual HRESULT STDMETHODCALLTYPE GetNumLocalVariables(
3427 /* [out] */ ULONG32 *numLocals);
3428
3429 virtual HRESULT STDMETHODCALLTYPE GetLocalVariableByIndex(
3430 /* [in] */ ULONG32 index,
3431 /* [out] */ IXCLRDataValue **localVariable,
3432 /* [in] */ ULONG32 bufLen,
3433 /* [out] */ ULONG32 *nameLen,
3434 /* [size_is][out] */ __out_ecount_part(bufLen, *nameLen) WCHAR name[ ]);
3435
3436 virtual HRESULT STDMETHODCALLTYPE GetNumTypeArguments(
3437 /* [out] */ ULONG32 *numTypeArgs);
3438
3439 virtual HRESULT STDMETHODCALLTYPE GetTypeArgumentByIndex(
3440 /* [in] */ ULONG32 index,
3441 /* [out] */ IXCLRDataTypeInstance **typeArg);
3442
3443 virtual HRESULT STDMETHODCALLTYPE GetCodeName(
3444 /* [in] */ ULONG32 flags,
3445 /* [in] */ ULONG32 bufLen,
3446 /* [out] */ ULONG32 *nameLen,
3447 /* [size_is][out] */ __out_ecount_opt(bufLen) WCHAR nameBuf[ ]);
3448
3449 virtual HRESULT STDMETHODCALLTYPE GetMethodInstance(
3450 /* [out] */ IXCLRDataMethodInstance **method);
3451
3452 virtual HRESULT STDMETHODCALLTYPE Request(
3453 /* [in] */ ULONG32 reqCode,
3454 /* [in] */ ULONG32 inBufferSize,
3455 /* [size_is][in] */ BYTE *inBuffer,
3456 /* [in] */ ULONG32 outBufferSize,
3457 /* [size_is][out] */ BYTE *outBuffer);
3458
3459 //
3460 // IXCLRDataFrame2.
3461 //
3462
3463 virtual HRESULT STDMETHODCALLTYPE GetExactGenericArgsToken(
3464 /* [out] */ IXCLRDataValue ** genericToken);
3465
3466private:
3467 HRESULT GetMethodSig(MetaSig** sig,
3468 ULONG32* count);
3469 HRESULT GetLocalSig(MetaSig** sig,
3470 ULONG32* count);
3471 HRESULT ValueFromDebugInfo(MetaSig* sig,
3472 bool isArg,
3473 DWORD sigIndex,
3474 DWORD varInfoSlot,
3475 IXCLRDataValue** value);
3476
3477 LONG m_refs;
3478 ClrDataAccess* m_dac;
3479 ULONG32 m_instanceAge;
3480 CLRDataSimpleFrameType m_simpleType;
3481 CLRDataDetailedFrameType m_detailedType;
3482 AppDomain* m_appDomain;
3483 MethodDesc* m_methodDesc;
3484 REGDISPLAY m_regDisp;
3485 T_CONTEXT m_context;
3486 MetaSig* m_methodSig;
3487 MetaSig* m_localSig;
3488};
3489
3490//----------------------------------------------------------------------------
3491//
3492// ClrDataExceptionState.
3493//
3494//----------------------------------------------------------------------------
3495
3496#ifdef WIN64EXCEPTIONS
3497typedef ExceptionTracker ClrDataExStateType;
3498#else // WIN64EXCEPTIONS
3499typedef ExInfo ClrDataExStateType;
3500#endif // WIN64EXCEPTIONS
3501
3502
3503class ClrDataExceptionState : public IXCLRDataExceptionState
3504{
3505public:
3506 ClrDataExceptionState(ClrDataAccess* dac,
3507 AppDomain* appDomain,
3508 Thread* thread,
3509 ULONG32 flags,
3510 ClrDataExStateType* exInfo,
3511 OBJECTHANDLE throwable,
3512 ClrDataExStateType* prevExInfo);
3513 virtual ~ClrDataExceptionState(void);
3514
3515 // IUnknown.
3516 STDMETHOD(QueryInterface)(THIS_
3517 IN REFIID interfaceId,
3518 OUT PVOID* iface);
3519 STDMETHOD_(ULONG, AddRef)(THIS);
3520 STDMETHOD_(ULONG, Release)(THIS);
3521
3522 //
3523 // IXCLRDataExceptionState.
3524 //
3525
3526 virtual HRESULT STDMETHODCALLTYPE GetFlags(
3527 /* [out] */ ULONG32 *flags);
3528
3529 virtual HRESULT STDMETHODCALLTYPE GetPrevious(
3530 /* [out] */ IXCLRDataExceptionState **exState);
3531
3532 virtual HRESULT STDMETHODCALLTYPE GetManagedObject(
3533 /* [out] */ IXCLRDataValue **value);
3534
3535 virtual HRESULT STDMETHODCALLTYPE GetBaseType(
3536 /* [out] */ CLRDataBaseExceptionType *type);
3537
3538 virtual HRESULT STDMETHODCALLTYPE GetCode(
3539 /* [out] */ ULONG32 *code);
3540
3541 virtual HRESULT STDMETHODCALLTYPE GetString(
3542 /* [in] */ ULONG32 bufLen,
3543 /* [out] */ ULONG32 *strLen,
3544 /* [size_is][out] */ __out_ecount_part(bufLen, *strLen) WCHAR str[ ]);
3545
3546 virtual HRESULT STDMETHODCALLTYPE IsSameState(
3547 /* [in] */ EXCEPTION_RECORD64 *exRecord,
3548 /* [in] */ ULONG32 contextSize,
3549 /* [size_is][in] */ BYTE cxRecord[ ]);
3550
3551 virtual HRESULT STDMETHODCALLTYPE IsSameState2(
3552 /* [in] */ ULONG32 flags,
3553 /* [in] */ EXCEPTION_RECORD64 *exRecord,
3554 /* [in] */ ULONG32 contextSize,
3555 /* [size_is][in] */ BYTE cxRecord[ ]);
3556
3557 virtual HRESULT STDMETHODCALLTYPE GetTask(
3558 /* [out] */ IXCLRDataTask** task);
3559
3560 virtual HRESULT STDMETHODCALLTYPE Request(
3561 /* [in] */ ULONG32 reqCode,
3562 /* [in] */ ULONG32 inBufferSize,
3563 /* [size_is][in] */ BYTE *inBuffer,
3564 /* [in] */ ULONG32 outBufferSize,
3565 /* [size_is][out] */ BYTE *outBuffer);
3566
3567 static HRESULT NewFromThread(ClrDataAccess* dac,
3568 Thread* thread,
3569 ClrDataExceptionState** exception,
3570 IXCLRDataExceptionState** pubException);
3571
3572 PTR_CONTEXT GetCurrentContextRecord();
3573 PTR_EXCEPTION_RECORD GetCurrentExceptionRecord();
3574
3575friend class ClrDataAccess;
3576private:
3577 LONG m_refs;
3578 ClrDataAccess* m_dac;
3579 ULONG32 m_instanceAge;
3580 AppDomain* m_appDomain;
3581 Thread* m_thread;
3582 ULONG32 m_flags;
3583 ClrDataExStateType* m_exInfo;
3584 OBJECTHANDLE m_throwable;
3585 ClrDataExStateType* m_prevExInfo;
3586};
3587
3588//----------------------------------------------------------------------------
3589//
3590// ClrDataValue.
3591//
3592//----------------------------------------------------------------------------
3593
3594class ClrDataValue : public IXCLRDataValue
3595{
3596public:
3597 ClrDataValue(ClrDataAccess* dac,
3598 AppDomain* appDomain,
3599 Thread* thread,
3600 ULONG32 flags,
3601 TypeHandle typeHandle,
3602 ULONG64 baseAddr,
3603 ULONG32 numLocs,
3604 NativeVarLocation* locs);
3605 virtual ~ClrDataValue(void);
3606
3607 // IUnknown.
3608 STDMETHOD(QueryInterface)(THIS_
3609 IN REFIID interfaceId,
3610 OUT PVOID* iface);
3611 STDMETHOD_(ULONG, AddRef)(THIS);
3612 STDMETHOD_(ULONG, Release)(THIS);
3613
3614 //
3615 // IXCLRDataValue.
3616 //
3617
3618 virtual HRESULT STDMETHODCALLTYPE GetFlags(
3619 /* [out] */ ULONG32 *flags);
3620
3621 virtual HRESULT STDMETHODCALLTYPE GetAddress(
3622 /* [out] */ CLRDATA_ADDRESS *address);
3623
3624 virtual HRESULT STDMETHODCALLTYPE GetSize(
3625 /* [out] */ ULONG64 *size);
3626
3627 virtual HRESULT STDMETHODCALLTYPE GetBytes(
3628 /* [in] */ ULONG32 bufLen,
3629 /* [out] */ ULONG32 *dataSize,
3630 /* [size_is][out] */ BYTE buffer[ ]);
3631
3632 virtual HRESULT STDMETHODCALLTYPE SetBytes(
3633 /* [in] */ ULONG32 bufLen,
3634 /* [out] */ ULONG32 *dataSize,
3635 /* [size_is][in] */ BYTE buffer[ ]);
3636
3637 virtual HRESULT STDMETHODCALLTYPE GetType(
3638 /* [out] */ IXCLRDataTypeInstance **typeInstance);
3639
3640 virtual HRESULT STDMETHODCALLTYPE GetNumFields(
3641 /* [out] */ ULONG32 *numFields);
3642
3643 virtual HRESULT STDMETHODCALLTYPE GetFieldByIndex(
3644 /* [in] */ ULONG32 index,
3645 /* [out] */ IXCLRDataValue **field,
3646 /* [in] */ ULONG32 bufLen,
3647 /* [out] */ ULONG32 *nameLen,
3648 /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR nameBuf[ ],
3649 /* [out] */ mdFieldDef *token);
3650
3651 virtual HRESULT STDMETHODCALLTYPE GetNumFields2(
3652 /* [in] */ ULONG32 flags,
3653 /* [in] */ IXCLRDataTypeInstance *fromType,
3654 /* [out] */ ULONG32 *numFields);
3655
3656 virtual HRESULT STDMETHODCALLTYPE StartEnumFields(
3657 /* [in] */ ULONG32 flags,
3658 /* [in] */ IXCLRDataTypeInstance *fromType,
3659 /* [out] */ CLRDATA_ENUM *handle);
3660
3661 virtual HRESULT STDMETHODCALLTYPE EnumField(
3662 /* [out][in] */ CLRDATA_ENUM *handle,
3663 /* [out] */ IXCLRDataValue **field,
3664 /* [in] */ ULONG32 nameBufLen,
3665 /* [out] */ ULONG32 *nameLen,
3666 /* [size_is][out] */ __out_ecount_part_opt(nameBufLen, *nameLen) WCHAR nameBuf[ ],
3667 /* [out] */ mdFieldDef *token);
3668
3669 virtual HRESULT STDMETHODCALLTYPE EnumField2(
3670 /* [out][in] */ CLRDATA_ENUM *handle,
3671 /* [out] */ IXCLRDataValue **field,
3672 /* [in] */ ULONG32 nameBufLen,
3673 /* [out] */ ULONG32 *nameLen,
3674 /* [size_is][out] */ __out_ecount_part_opt(nameBufLen, *nameLen) WCHAR nameBuf[ ],
3675 /* [out] */ IXCLRDataModule** tokenScope,
3676 /* [out] */ mdFieldDef *token);
3677
3678 virtual HRESULT STDMETHODCALLTYPE EndEnumFields(
3679 /* [in] */ CLRDATA_ENUM handle);
3680
3681 virtual HRESULT STDMETHODCALLTYPE StartEnumFieldsByName(
3682 /* [in] */ LPCWSTR name,
3683 /* [in] */ ULONG32 nameFlags,
3684 /* [in] */ ULONG32 fieldFlags,
3685 /* [in] */ IXCLRDataTypeInstance *fromType,
3686 /* [out] */ CLRDATA_ENUM *handle);
3687
3688 virtual HRESULT STDMETHODCALLTYPE EnumFieldByName(
3689 /* [out][in] */ CLRDATA_ENUM *handle,
3690 /* [out] */ IXCLRDataValue **field,
3691 /* [out] */ mdFieldDef *token);
3692
3693 virtual HRESULT STDMETHODCALLTYPE EnumFieldByName2(
3694 /* [out][in] */ CLRDATA_ENUM *handle,
3695 /* [out] */ IXCLRDataValue **field,
3696 /* [out] */ IXCLRDataModule** tokenScope,
3697 /* [out] */ mdFieldDef *token);
3698
3699 virtual HRESULT STDMETHODCALLTYPE EndEnumFieldsByName(
3700 /* [in] */ CLRDATA_ENUM handle);
3701
3702 virtual HRESULT STDMETHODCALLTYPE GetFieldByToken(
3703 /* [in] */ mdFieldDef token,
3704 /* [out] */ IXCLRDataValue **field,
3705 /* [in] */ ULONG32 bufLen,
3706 /* [out] */ ULONG32 *nameLen,
3707 /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR nameBuf[ ]);
3708
3709 virtual HRESULT STDMETHODCALLTYPE GetFieldByToken2(
3710 /* [in] */ IXCLRDataModule* tokenScope,
3711 /* [in] */ mdFieldDef token,
3712 /* [out] */ IXCLRDataValue **field,
3713 /* [in] */ ULONG32 bufLen,
3714 /* [out] */ ULONG32 *nameLen,
3715 /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR nameBuf[ ]);
3716
3717 virtual HRESULT STDMETHODCALLTYPE GetAssociatedValue(
3718 /* [out] */ IXCLRDataValue **assocValue);
3719
3720 virtual HRESULT STDMETHODCALLTYPE GetAssociatedType(
3721 /* [out] */ IXCLRDataTypeInstance **assocType);
3722
3723 virtual HRESULT STDMETHODCALLTYPE GetString(
3724 /* [in] */ ULONG32 bufLen,
3725 /* [out] */ ULONG32 *strLen,
3726 /* [size_is][out] */ __out_ecount_part(bufLen, *strLen) WCHAR str[ ]);
3727
3728 virtual HRESULT STDMETHODCALLTYPE GetArrayProperties(
3729 /* [out] */ ULONG32 *rank,
3730 /* [out] */ ULONG32 *totalElements,
3731 /* [in] */ ULONG32 numDim,
3732 /* [size_is][out] */ ULONG32 dims[ ],
3733 /* [in] */ ULONG32 numBases,
3734 /* [size_is][out] */ LONG32 bases[ ]);
3735
3736 virtual HRESULT STDMETHODCALLTYPE GetArrayElement(
3737 /* [in] */ ULONG32 numInd,
3738 /* [size_is][in] */ LONG32 indices[ ],
3739 /* [out] */ IXCLRDataValue **value);
3740
3741 virtual HRESULT STDMETHODCALLTYPE GetNumLocations(
3742 /* [out] */ ULONG32* numLocs);
3743
3744 virtual HRESULT STDMETHODCALLTYPE GetLocationByIndex(
3745 /* [in] */ ULONG32 loc,
3746 /* [out] */ ULONG32* flags,
3747 /* [out] */ CLRDATA_ADDRESS* arg);
3748
3749 virtual HRESULT STDMETHODCALLTYPE Request(
3750 /* [in] */ ULONG32 reqCode,
3751 /* [in] */ ULONG32 inBufferSize,
3752 /* [size_is][in] */ BYTE *inBuffer,
3753 /* [in] */ ULONG32 outBufferSize,
3754 /* [size_is][out] */ BYTE *outBuffer);
3755
3756 HRESULT GetRefAssociatedValue(IXCLRDataValue** assocValue);
3757
3758 static HRESULT NewFromFieldDesc(ClrDataAccess* dac,
3759 AppDomain* appDomain,
3760 ULONG32 flags,
3761 FieldDesc* fieldDesc,
3762 ULONG64 objBase,
3763 Thread* tlsThread,
3764 ClrDataValue** value,
3765 IXCLRDataValue** pubValue,
3766 ULONG32 nameBufRetLen,
3767 ULONG32* nameLenRet,
3768 __out_ecount_part_opt(nameBufRetLen, *nameLenRet) WCHAR nameBufRet[ ],
3769 IXCLRDataModule** tokenScopeRet,
3770 mdFieldDef* tokenRet);
3771
3772 HRESULT NewFromSubField(FieldDesc* fieldDesc,
3773 ULONG32 flags,
3774 ClrDataValue** value,
3775 IXCLRDataValue** pubValue,
3776 ULONG32 nameBufRetLen,
3777 ULONG32* nameLenRet,
3778 __out_ecount_part_opt(nameBufRetLen, *nameLenRet) WCHAR nameBufRet[ ],
3779 IXCLRDataModule** tokenScopeRet,
3780 mdFieldDef* tokenRet)
3781 {
3782 return ClrDataValue::NewFromFieldDesc(m_dac,
3783 m_appDomain,
3784 flags,
3785 fieldDesc,
3786 m_baseAddr,
3787 m_thread,
3788 value,
3789 pubValue,
3790 nameBufRetLen,
3791 nameLenRet,
3792 nameBufRet,
3793 tokenScopeRet,
3794 tokenRet);
3795 }
3796
3797 bool CanHaveFields(void)
3798 {
3799 return (m_flags & CLRDATA_VALUE_IS_REFERENCE) == 0;
3800 }
3801
3802 HRESULT IntGetBytes(
3803 /* [in] */ ULONG32 bufLen,
3804 /* [size_is][out] */ BYTE buffer[ ]);
3805
3806private:
3807 LONG m_refs;
3808 ClrDataAccess* m_dac;
3809 ULONG32 m_instanceAge;
3810 AppDomain* m_appDomain;
3811 Thread* m_thread;
3812 ULONG32 m_flags;
3813 TypeHandle m_typeHandle;
3814 ULONG64 m_totalSize;
3815 ULONG64 m_baseAddr;
3816 ULONG32 m_numLocs;
3817 NativeVarLocation m_locs[MAX_NATIVE_VAR_LOCS];
3818};
3819
3820//----------------------------------------------------------------------------
3821//
3822// EnumMethodDefinitions.
3823//
3824//----------------------------------------------------------------------------
3825
3826class EnumMethodDefinitions
3827{
3828public:
3829 HRESULT Start(Module* mod,
3830 bool useAddrFilter,
3831 CLRDATA_ADDRESS addrFilter);
3832 HRESULT Next(ClrDataAccess* dac,
3833 IXCLRDataMethodDefinition **method);
3834
3835 static HRESULT CdStart(Module* mod,
3836 bool useAddrFilter,
3837 CLRDATA_ADDRESS addrFilter,
3838 CLRDATA_ENUM* handle);
3839 static HRESULT CdNext(ClrDataAccess* dac,
3840 CLRDATA_ENUM* handle,
3841 IXCLRDataMethodDefinition** method);
3842 static HRESULT CdEnd(CLRDATA_ENUM handle);
3843
3844 Module* m_module;
3845 bool m_useAddrFilter;
3846 CLRDATA_ADDRESS m_addrFilter;
3847 MetaEnum m_typeEnum;
3848 mdToken m_typeToken;
3849 bool m_needMethodStart;
3850 MetaEnum m_methodEnum;
3851};
3852
3853//----------------------------------------------------------------------------
3854//
3855// EnumMethodInstances.
3856//
3857//----------------------------------------------------------------------------
3858
3859class EnumMethodInstances
3860{
3861public:
3862 EnumMethodInstances(MethodDesc* methodDesc,
3863 IXCLRDataAppDomain* givenAppDomain);
3864
3865 HRESULT Next(ClrDataAccess* dac,
3866 IXCLRDataMethodInstance **instance);
3867
3868 static HRESULT CdStart(MethodDesc* methodDesc,
3869 IXCLRDataAppDomain* appDomain,
3870 CLRDATA_ENUM* handle);
3871 static HRESULT CdNext(ClrDataAccess* dac,
3872 CLRDATA_ENUM* handle,
3873 IXCLRDataMethodInstance** method);
3874 static HRESULT CdEnd(CLRDATA_ENUM handle);
3875
3876 MethodDesc* m_methodDesc;
3877 AppDomain* m_givenAppDomain;
3878 bool m_givenAppDomainUsed;
3879 AppDomainIterator m_domainIter;
3880 AppDomain* m_appDomain;
3881 LoadedMethodDescIterator m_methodIter;
3882};
3883
3884//----------------------------------------------------------------------------
3885//
3886// Internal functions.
3887//
3888//----------------------------------------------------------------------------
3889
3890#define DAC_ENTER() \
3891 EnterCriticalSection(&g_dacCritSec); \
3892 ClrDataAccess* __prevDacImpl = g_dacImpl; \
3893 g_dacImpl = this;
3894
3895// When entering a child object we validate that
3896// the process's host instance cache hasn't been flushed
3897// since the child was created.
3898#define DAC_ENTER_SUB(dac) \
3899 EnterCriticalSection(&g_dacCritSec); \
3900 if (dac->m_instanceAge != m_instanceAge) \
3901 { \
3902 LeaveCriticalSection(&g_dacCritSec); \
3903 return E_INVALIDARG; \
3904 } \
3905 ClrDataAccess* __prevDacImpl = g_dacImpl; \
3906 g_dacImpl = (dac)
3907
3908#define DAC_LEAVE() \
3909 g_dacImpl = __prevDacImpl; \
3910 LeaveCriticalSection(&g_dacCritSec)
3911
3912
3913#define SOSHelperEnter() \
3914 DAC_ENTER_SUB(mDac); \
3915 HRESULT hr = S_OK; \
3916 EX_TRY \
3917 {
3918
3919#define SOSHelperLeave() \
3920 } \
3921 EX_CATCH \
3922 { \
3923 if (!DacExceptionFilter(GET_EXCEPTION(), mDac, &hr)) \
3924 { \
3925 EX_RETHROW; \
3926 } \
3927 } \
3928 EX_END_CATCH(SwallowAllExceptions) \
3929 DAC_LEAVE();
3930
3931HRESULT DacGetHostVtPtrs(void);
3932bool DacExceptionFilter(Exception* ex, ClrDataAccess* process,
3933 HRESULT* status);
3934Thread* __stdcall DacGetThread(ULONG32 osThread);
3935BOOL DacGetThreadContext(Thread* thread, T_CONTEXT* context);
3936
3937// Imports from request_svr.cpp, to provide data we need from the SVR namespace
3938int GCHeapCount();
3939HRESULT GetServerHeapData(CLRDATA_ADDRESS addr, DacpHeapSegmentData *pSegment);
3940HRESULT GetServerHeaps(CLRDATA_ADDRESS pGCHeaps[], ICorDebugDataTarget* pTarget);
3941
3942#if defined(DAC_MEASURE_PERF)
3943
3944#if defined(_TARGET_X86_)
3945
3946// Assume Pentium CPU
3947
3948#define CCNT_OVERHEAD_32 8
3949#define CCNT_OVERHEAD 13
3950
3951#pragma warning( disable: 4035 ) /* Don't complain about lack of return value */
3952
3953__inline unsigned __int64 GetCycleCount ()
3954{
3955__asm _emit 0x0F
3956__asm _emit 0x31 /* rdtsc */
3957 // return EDX:EAX causes annoying warning
3958};
3959
3960__inline unsigned GetCycleCount32 () // enough for about 40 seconds
3961{
3962 LIMITED_METHOD_CONTRACT;
3963
3964__asm push EDX
3965__asm _emit 0x0F
3966__asm _emit 0x31 /* rdtsc */
3967__asm pop EDX
3968 // return EAX causes annoying warning
3969};
3970
3971#pragma warning( default: 4035 )
3972
3973#else // #if defined(_TARGET_X86_)
3974
3975#define CCNT_OVERHEAD 0 // Don't know
3976
3977__inline unsigned __int64 GetCycleCount()
3978{
3979 LIMITED_METHOD_CONTRACT;
3980
3981 LARGE_INTEGER qwTmp;
3982 QueryPerformanceCounter(&qwTmp);
3983 return qwTmp.QuadPart;
3984}
3985
3986#endif // #if defined(_TARGET_X86_)
3987
3988extern unsigned __int64 g_nTotalTime;
3989extern unsigned __int64 g_nStackTotalTime;
3990extern unsigned __int64 g_nReadVirtualTotalTime;
3991extern unsigned __int64 g_nFindTotalTime;
3992extern unsigned __int64 g_nFindHashTotalTime;
3993extern unsigned __int64 g_nFindHits;
3994extern unsigned __int64 g_nFindCalls;
3995extern unsigned __int64 g_nFindFails;
3996extern unsigned __int64 g_nStackWalk;
3997extern unsigned __int64 g_nFindStackTotalTime;
3998
3999#endif // #if defined(DAC_MEASURE_PERF)
4000
4001#endif // #ifndef __DACIMPL_H__
4002