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 |
33 | extern 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 |
59 | inline 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 |
76 | inline 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 |
93 | inline 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 | |
122 | enum 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 |
132 | extern HINSTANCE g_thisModule; |
133 | |
134 | class ReflectionModule; |
135 | |
136 | struct 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. |
161 | class MDImportsCache |
162 | { |
163 | public: |
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 | |
215 | private: |
216 | |
217 | DAC_MD_IMPORT* m_head; // the beginning of the list of cached MD imports |
218 | |
219 | }; |
220 | |
221 | struct METH_EXTENTS |
222 | { |
223 | ULONG32 numExtents; |
224 | ULONG32 curExtent; |
225 | // Currently only one is needed. |
226 | CLRDATA_ADDRESS_RANGE extents[1]; |
227 | }; |
228 | |
229 | HRESULT ConvertUtf8(__in LPCUTF8 utf8, |
230 | ULONG32 bufLen, |
231 | ULONG32* nameLen, |
232 | __out_ecount_part_opt(bufLen, *nameLen) PWSTR buffer); |
233 | HRESULT AllocUtf8(__in_opt LPCWSTR wstr, |
234 | ULONG32 srcChars, |
235 | __deref_out LPUTF8* utf8); |
236 | |
237 | HRESULT GetFullClassNameFromMetadata(IMDInternalImport* mdImport, |
238 | mdTypeDef classToken, |
239 | ULONG32 bufferChars, |
240 | __inout_ecount(bufferChars) LPUTF8 buffer); |
241 | HRESULT GetFullMethodNameFromMetadata(IMDInternalImport* mdImport, |
242 | mdMethodDef methodToken, |
243 | ULONG32 bufferChars, |
244 | __inout_ecount(bufferChars) LPUTF8 buffer); |
245 | |
246 | enum SplitSyntax |
247 | { |
248 | SPLIT_METHOD, |
249 | SPLIT_TYPE, |
250 | SPLIT_FIELD, |
251 | SPLIT_NO_NAME, |
252 | }; |
253 | |
254 | HRESULT 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 | |
262 | int 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 | |
268 | HRESULT InitFieldIter(DeepFieldDescIterator* fieldIter, |
269 | TypeHandle typeHandle, |
270 | bool canHaveFields, |
271 | ULONG32 flags, |
272 | IXCLRDataTypeInstance* fromType); |
273 | |
274 | ULONG32 GetTypeFieldValueFlags(TypeHandle typeHandle, |
275 | FieldDesc* fieldDesc, |
276 | ULONG32 otherFlags, |
277 | bool isDeref); |
278 | |
279 | //---------------------------------------------------------------------------- |
280 | // |
281 | // MetaEnum. |
282 | // |
283 | //---------------------------------------------------------------------------- |
284 | |
285 | class MetaEnum |
286 | { |
287 | public: |
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 | |
382 | class SplitName |
383 | { |
384 | public: |
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 | |
510 | struct 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. |
599 | struct 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. |
613 | struct 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 | |
645 | struct 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 | |
670 | struct 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 | |
681 | class DacInstanceManager |
682 | { |
683 | public: |
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 | |
707 | private: |
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 | |
823 | class DacStreamManager; |
824 | |
825 | #endif // FEATURE_MINIMETADATA_IN_TRIAGEDUMPS |
826 | |
827 | |
828 | //---------------------------------------------------------------------------- |
829 | // |
830 | // ClrDataAccess. |
831 | // |
832 | //---------------------------------------------------------------------------- |
833 | |
834 | class 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 | { |
844 | public: |
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 (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 | |
1381 | protected: |
1382 | DacStreamManager * m_streams; |
1383 | |
1384 | public: |
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 | |
1404 | private: |
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 |
1435 | protected: |
1436 | // If true, a mscorwks/mscordacwks mismatch will trigger a nice assert dialog |
1437 | bool m_fEnableDllVerificationAsserts; |
1438 | private: |
1439 | #endif |
1440 | |
1441 | #ifdef FEATURE_COMINTEROP |
1442 | protected: |
1443 | // Returns CCW pointer based on a target address. |
1444 | PTR_ComCallWrapper DACGetCCWFromAddress(CLRDATA_ADDRESS addr); |
1445 | |
1446 | private: |
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 | |
1454 | public: |
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 | |
1478 | extern 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> |
1510 | class DefaultCOMImpl : public T |
1511 | { |
1512 | public: |
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 | |
1555 | private: |
1556 | ULONG mRef; |
1557 | }; |
1558 | |
1559 | |
1560 | // A stuct representing a thread's allocation context. |
1561 | struct 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. |
1573 | struct 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. |
1588 | struct 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 | */ |
1610 | class LinearReadCache |
1611 | { |
1612 | public: |
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 | |
1674 | private: |
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 | |
1689 | private: |
1690 | CORDB_ADDRESS mCurrPageStart; |
1691 | ULONG32 mPageSize, mCurrPageSize; |
1692 | BYTE *mPage; |
1693 | }; |
1694 | |
1695 | DWORD 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 | */ |
1710 | class DacHeapWalker |
1711 | { |
1712 | static CORDB_ADDRESS HeapStart; |
1713 | static CORDB_ADDRESS HeapEnd; |
1714 | |
1715 | public: |
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 | |
1752 | private: |
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 | |
1789 | private: |
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 | |
1810 | struct DacGcReference; |
1811 | struct SOSStackErrorList |
1812 | { |
1813 | SOSStackRefError error; |
1814 | SOSStackErrorList *pNext; |
1815 | |
1816 | SOSStackErrorList() |
1817 | : pNext(0) |
1818 | { |
1819 | } |
1820 | }; |
1821 | |
1822 | class DacStackReferenceWalker; |
1823 | class DacStackReferenceErrorEnum : public DefaultCOMImpl<ISOSStackRefErrorEnum> |
1824 | { |
1825 | public: |
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 | |
1834 | private: |
1835 | // The lifetime of the error list is tied to the enum, so we must addref/release it. |
1836 | DacStackReferenceWalker *; |
1837 | SOSStackErrorList *mHead; |
1838 | SOSStackErrorList *mCurr; |
1839 | }; |
1840 | |
1841 | // For GCCONTEXT |
1842 | #include "gcenv.h" |
1843 | |
1844 | /* DacStackReferenceWalker. |
1845 | */ |
1846 | class 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; |
1886 | public: |
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 | |
1908 | private: |
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 | |
2052 | private: |
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 ; |
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 | |
2076 | struct DacGcReference; |
2077 | class 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 | |
2118 | public: |
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); |
2136 | private: |
2137 | static void CALLBACK EnumCallback(PTR_UNCHECKED_OBJECTREF pref, LPARAM *, 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 | |
2143 | private: |
2144 | static void CALLBACK EnumCallbackSOS(PTR_UNCHECKED_OBJECTREF pref, uintptr_t *, uintptr_t userParam, uintptr_t type); |
2145 | static void CALLBACK EnumCallbackDac(PTR_UNCHECKED_OBJECTREF pref, uintptr_t *, 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 | |
2221 | private: |
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 | |
2248 | class ClrDataAppDomain : public IXCLRDataAppDomain |
2249 | { |
2250 | public: |
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 | |
2299 | private: |
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 | |
2312 | class ClrDataAssembly : public IXCLRDataAssembly |
2313 | { |
2314 | public: |
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 | |
2378 | private: |
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 | |
2391 | class ClrDataModule : public IXCLRDataModule, IXCLRDataModule2 |
2392 | { |
2393 | public: |
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 | |
2579 | private: |
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 | |
2599 | class ClrDataTypeDefinition : public IXCLRDataTypeDefinition |
2600 | { |
2601 | public: |
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 | |
2777 | private: |
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 | |
2792 | class ClrDataTypeInstance : public IXCLRDataTypeInstance |
2793 | { |
2794 | public: |
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 | |
2967 | private: |
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 | |
2981 | class ClrDataMethodDefinition : public IXCLRDataMethodDefinition |
2982 | { |
2983 | public: |
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;} |
3076 | private: |
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 | |
3091 | class ClrDataMethodInstance : public IXCLRDataMethodInstance |
3092 | { |
3093 | public: |
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 | |
3186 | private: |
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 | |
3201 | class ClrDataTask : public IXCLRDataTask |
3202 | { |
3203 | public: |
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 | |
3283 | private: |
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 | |
3296 | class ClrDataStackWalk : public IXCLRDataStackWalk |
3297 | { |
3298 | public: |
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 | |
3351 | private: |
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 | |
3379 | class ClrDataFrame : public IXCLRDataFrame, |
3380 | IXCLRDataFrame2 |
3381 | { |
3382 | friend class ClrDataStackWalk; |
3383 | |
3384 | public: |
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 | |
3466 | private: |
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 |
3497 | typedef ExceptionTracker ClrDataExStateType; |
3498 | #else // WIN64EXCEPTIONS |
3499 | typedef ExInfo ClrDataExStateType; |
3500 | #endif // WIN64EXCEPTIONS |
3501 | |
3502 | |
3503 | class ClrDataExceptionState : public IXCLRDataExceptionState |
3504 | { |
3505 | public: |
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 | |
3575 | friend class ClrDataAccess; |
3576 | private: |
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 | |
3594 | class ClrDataValue : public IXCLRDataValue |
3595 | { |
3596 | public: |
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 | |
3806 | private: |
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 | |
3826 | class EnumMethodDefinitions |
3827 | { |
3828 | public: |
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 | |
3859 | class EnumMethodInstances |
3860 | { |
3861 | public: |
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 | |
3931 | HRESULT DacGetHostVtPtrs(void); |
3932 | bool DacExceptionFilter(Exception* ex, ClrDataAccess* process, |
3933 | HRESULT* status); |
3934 | Thread* __stdcall DacGetThread(ULONG32 osThread); |
3935 | BOOL DacGetThreadContext(Thread* thread, T_CONTEXT* context); |
3936 | |
3937 | // Imports from request_svr.cpp, to provide data we need from the SVR namespace |
3938 | int GCHeapCount(); |
3939 | HRESULT GetServerHeapData(CLRDATA_ADDRESS addr, DacpHeapSegmentData *pSegment); |
3940 | HRESULT 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 | |
3988 | extern unsigned __int64 g_nTotalTime; |
3989 | extern unsigned __int64 g_nStackTotalTime; |
3990 | extern unsigned __int64 g_nReadVirtualTotalTime; |
3991 | extern unsigned __int64 g_nFindTotalTime; |
3992 | extern unsigned __int64 g_nFindHashTotalTime; |
3993 | extern unsigned __int64 g_nFindHits; |
3994 | extern unsigned __int64 g_nFindCalls; |
3995 | extern unsigned __int64 g_nFindFails; |
3996 | extern unsigned __int64 g_nStackWalk; |
3997 | extern unsigned __int64 g_nFindStackTotalTime; |
3998 | |
3999 | #endif // #if defined(DAC_MEASURE_PERF) |
4000 | |
4001 | #endif // #ifndef __DACIMPL_H__ |
4002 | |