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// DacDbiImpl.h
6//
7
8//
9// Implement the interface between the DAC and DBI.
10//*****************************************************************************
11
12#ifndef _DACDBI_IMPL_H_
13#define _DACDBI_IMPL_H_
14
15// Prototype for creation function
16STDAPI
17DacDbiInterfaceInstance(
18 ICorDebugDataTarget * pTarget,
19 CORDB_ADDRESS baseAddress,
20 IDacDbiInterface::IAllocator * pAllocator,
21 IDacDbiInterface::IMetaDataLookup * pMetaDataLookup,
22 IDacDbiInterface ** ppInterface);
23
24//---------------------------------------------------------------------------------------
25//
26// This implements the DAC/DBI interface. See that interface declaration for
27// full documentation on these methods.
28//
29// Assumptions:
30// This class is free-threaded and provides its own synchronization.
31//
32// Notes:
33// It inherits from ClrDataAccess to get the DAC-management implementation, and to
34// override GetMDImport.
35//
36class DacDbiInterfaceImpl :
37 public ClrDataAccess,
38 public IDacDbiInterface
39{
40public:
41 // Ctor to instantiate a DAC reader around a given data-target.
42 DacDbiInterfaceImpl(ICorDebugDataTarget * pTarget, CORDB_ADDRESS baseAddress, IAllocator * pAllocator, IMetaDataLookup * pLookup);
43
44 // Destructor.
45 virtual ~DacDbiInterfaceImpl(void);
46
47 // Overridden from ClrDataAccess. Gets an internal metadata importer for the file.
48 virtual IMDInternalImport* GetMDImport(
49 const PEFile* pPEFile,
50 const ReflectionModule * pReflectionModule,
51 bool fThrowEx);
52
53
54 // Check whether the version of the DBI matches the version of the runtime.
55 HRESULT CheckDbiVersion(const DbiVersion * pVersion);
56
57 // Flush the DAC cache. This should be called when target memory changes.
58 HRESULT FlushCache();
59
60 // enable or disable DAC target consistency checks
61 void DacSetTargetConsistencyChecks(bool fEnableAsserts);
62
63 // Destroy the interface object. The client should call this when it's done
64 // with the IDacDbiInterface to free up any resources.
65 void Destroy();
66
67 IAllocator * GetAllocator()
68 {
69 return m_pAllocator;
70 }
71
72
73 // Is Left-side started up?
74 BOOL IsLeftSideInitialized();
75
76 // Get an LS Appdomain via an AppDomain unique ID.
77 // Fails if the AD is not found or if the ID is invalid.
78 VMPTR_AppDomain GetAppDomainFromId(ULONG appdomainId);
79
80 // Get the AppDomain ID for an AppDomain.
81 ULONG GetAppDomainId(VMPTR_AppDomain vmAppDomain);
82
83 // Get the managed AppDomain object for an AppDomain.
84 VMPTR_OBJECTHANDLE GetAppDomainObject(VMPTR_AppDomain vmAppDomain);
85
86 // Determine if the specified AppDomain is the default domain
87 BOOL IsDefaultDomain(VMPTR_AppDomain vmAppDomain);
88
89 // Get the full AD friendly name for the appdomain.
90 void GetAppDomainFullName(
91 VMPTR_AppDomain vmAppDomain,
92 IStringHolder * pStrName);
93
94 // Get the values of the JIT Optimization and EnC flags.
95 void GetCompilerFlags (VMPTR_DomainFile vmDomainFile,
96 BOOL * pfAllowJITOpts,
97 BOOL * pfEnableEnC);
98
99 // Helper function for SetCompilerFlags to set EnC status
100 bool CanSetEnCBits(Module * pModule);
101
102 // Set the values of the JIT optimization and EnC flags.
103 HRESULT SetCompilerFlags(VMPTR_DomainFile vmDomainFile,
104 BOOL fAllowJitOpts,
105 BOOL fEnableEnC);
106
107
108 // Initialize the native/IL sequence points and native var info for a function.
109 void GetNativeCodeSequencePointsAndVarInfo(VMPTR_MethodDesc vmMethodDesc,
110 CORDB_ADDRESS startAddr,
111 BOOL fCodeAvailable,
112 NativeVarData * pNativeVarData,
113 SequencePoints * pSequencePoints);
114
115 bool IsThreadSuspendedOrHijacked(VMPTR_Thread vmThread);
116
117
118 bool AreGCStructuresValid();
119 HRESULT CreateHeapWalk(HeapWalkHandle *pHandle);
120 void DeleteHeapWalk(HeapWalkHandle handle);
121
122 HRESULT WalkHeap(HeapWalkHandle handle,
123 ULONG count,
124 OUT COR_HEAPOBJECT * objects,
125 OUT ULONG *fetched);
126
127 HRESULT GetHeapSegments(OUT DacDbiArrayList<COR_SEGMENT> *pSegments);
128
129
130 bool IsValidObject(CORDB_ADDRESS obj);
131
132 bool GetAppDomainForObject(CORDB_ADDRESS obj, OUT VMPTR_AppDomain * pApp, OUT VMPTR_Module *pModule, OUT VMPTR_DomainFile *mod);
133
134
135
136 HRESULT CreateRefWalk(RefWalkHandle * pHandle, BOOL walkStacks, BOOL walkFQ, UINT32 handleWalkMask);
137 void DeleteRefWalk(RefWalkHandle handle);
138 HRESULT WalkRefs(RefWalkHandle handle, ULONG count, OUT DacGcReference * objects, OUT ULONG *pFetched);
139
140 HRESULT GetTypeID(CORDB_ADDRESS obj, COR_TYPEID *pID);
141
142 HRESULT GetTypeIDForType(VMPTR_TypeHandle vmTypeHandle, COR_TYPEID *pID);
143
144 HRESULT GetObjectFields(COR_TYPEID id, ULONG32 celt, COR_FIELD *layout, ULONG32 *pceltFetched);
145 HRESULT GetTypeLayout(COR_TYPEID id, COR_TYPE_LAYOUT *pLayout);
146 HRESULT GetArrayLayout(COR_TYPEID id, COR_ARRAY_LAYOUT *pLayout);
147 void GetGCHeapInformation(COR_HEAPINFO * pHeapInfo);
148 HRESULT GetPEFileMDInternalRW(VMPTR_PEFile vmPEFile, OUT TADDR* pAddrMDInternalRW);
149 HRESULT GetReJitInfo(VMPTR_Module vmModule, mdMethodDef methodTk, OUT VMPTR_ReJitInfo* pReJitInfo);
150 HRESULT GetActiveRejitILCodeVersionNode(VMPTR_Module vmModule, mdMethodDef methodTk, OUT VMPTR_ILCodeVersionNode* pVmILCodeVersionNode);
151 HRESULT GetReJitInfo(VMPTR_MethodDesc vmMethod, CORDB_ADDRESS codeStartAddress, OUT VMPTR_ReJitInfo* pReJitInfo);
152 HRESULT GetNativeCodeVersionNode(VMPTR_MethodDesc vmMethod, CORDB_ADDRESS codeStartAddress, OUT VMPTR_NativeCodeVersionNode* pVmNativeCodeVersionNode);
153 HRESULT GetSharedReJitInfo(VMPTR_ReJitInfo vmReJitInfo, VMPTR_SharedReJitInfo* pSharedReJitInfo);
154 HRESULT GetILCodeVersionNode(VMPTR_NativeCodeVersionNode vmNativeCodeVersionNode, VMPTR_ILCodeVersionNode* pVmILCodeVersionNode);
155 HRESULT GetSharedReJitInfoData(VMPTR_SharedReJitInfo sharedReJitInfo, DacSharedReJitInfo* pData);
156 HRESULT GetILCodeVersionNodeData(VMPTR_ILCodeVersionNode vmILCodeVersionNode, DacSharedReJitInfo* pData);
157 HRESULT GetDefinesBitField(ULONG32 *pDefines);
158 HRESULT GetMDStructuresVersion(ULONG32* pMDStructuresVersion);
159 HRESULT EnableGCNotificationEvents(BOOL fEnable);
160
161private:
162 void TypeHandleToExpandedTypeInfoImpl(AreValueTypesBoxed boxed,
163 VMPTR_AppDomain vmAppDomain,
164 TypeHandle typeHandle,
165 DebuggerIPCE_ExpandedTypeData * pTypeInfo);
166
167 // Get the number of fixed arguments to a function, i.e., the explicit args and the "this" pointer.
168 SIZE_T GetArgCount(MethodDesc * pMD);
169
170 // Get locations and code offsets for local variables and arguments in a function
171 void GetNativeVarData(MethodDesc * pMethodDesc,
172 CORDB_ADDRESS startAddr,
173 SIZE_T fixedArgCount,
174 NativeVarData * pVarInfo);
175
176 // Get the native/IL sequence points for a function
177 void GetSequencePoints(MethodDesc * pMethodDesc,
178 CORDB_ADDRESS startAddr,
179 SequencePoints * pNativeMap);
180
181 // Helper to compose a IL->IL and IL->Native mapping
182 void ComposeMapping(const InstrumentedILOffsetMapping * pProfilerILMap, ICorDebugInfo::OffsetMapping nativeMap[], ULONG32* pEntryCount);
183
184 // Helper function to convert an instrumented IL offset to the corresponding original IL offset.
185 ULONG TranslateInstrumentedILOffsetToOriginal(ULONG ilOffset,
186 const InstrumentedILOffsetMapping * pMapping);
187
188public:
189//----------------------------------------------------------------------------------
190 // class MapSortILMap: A template class that will sort an array of DebuggerILToNativeMap.
191 // This class is intended to be instantiated on the stack / in temporary storage, and used
192 // to reorder the sequence map.
193 //----------------------------------------------------------------------------------
194 class MapSortILMap : public CQuickSort<DebuggerILToNativeMap>
195 {
196 public:
197 //Constructor
198 MapSortILMap(DebuggerILToNativeMap * map,
199 int count)
200 : CQuickSort<DebuggerILToNativeMap>(map, count) {}
201
202 // secondary key comparison--if two IL offsets are the same,
203 // we determine order based on native offset
204 int CompareInternal(DebuggerILToNativeMap * first,
205 DebuggerILToNativeMap * second);
206
207 //Comparison operator
208 int Compare(DebuggerILToNativeMap * first,
209 DebuggerILToNativeMap * second);
210 };
211
212
213 // GetILCodeAndSig returns the function's ILCode and SigToken given
214 // a module and a token. The info will come from a MethodDesc, if
215 // one exists or from metadata.
216 //
217 void GetILCodeAndSig(VMPTR_DomainFile vmDomainFile,
218 mdToken functionToken,
219 TargetBuffer * pCodeInfo,
220 mdToken * pLocalSigToken);
221
222 // Gets the following information about the native code blob for a function, if the native
223 // code is available:
224 // its method desc
225 // whether it's an instantiated generic
226 // its EnC version number
227 // hot and cold region information.
228 void GetNativeCodeInfo(VMPTR_DomainFile vmDomainFile,
229 mdToken functionToken,
230 NativeCodeFunctionData * pCodeInfo);
231
232 // Gets the following information about the native code blob for a function
233 // its method desc
234 // whether it's an instantiated generic
235 // its EnC version number
236 // hot and cold region information.
237 void GetNativeCodeInfoForAddr(VMPTR_MethodDesc vmMethodDesc,
238 CORDB_ADDRESS hotCodeStartAddr,
239 NativeCodeFunctionData * pCodeInfo);
240
241private:
242 // Get start addresses and sizes for hot and cold regions for a native code blob
243 void GetMethodRegionInfo(MethodDesc * pMethodDesc,
244 NativeCodeFunctionData * pCodeInfo);
245
246public:
247 // Determine if a type is a ValueType
248 BOOL IsValueType (VMPTR_TypeHandle th);
249
250 // Determine if a type has generic parameters
251 BOOL HasTypeParams (VMPTR_TypeHandle th);
252
253 // Get type information for a class
254 void GetClassInfo (VMPTR_AppDomain vmAppDomain,
255 VMPTR_TypeHandle thExact,
256 ClassInfo * pData);
257
258 // get field information and object size for an instantiated generic type
259 void GetInstantiationFieldInfo (VMPTR_DomainFile vmDomainFile,
260 VMPTR_TypeHandle vmThExact,
261 VMPTR_TypeHandle vmThApprox,
262 DacDbiArrayList<FieldData> * pFieldList,
263 SIZE_T * pObjectSize);
264
265
266 void GetObjectExpandedTypeInfo(AreValueTypesBoxed boxed,
267 VMPTR_AppDomain vmAppDomain,
268 CORDB_ADDRESS addr,
269 DebuggerIPCE_ExpandedTypeData *pTypeInfo);
270
271
272 void GetObjectExpandedTypeInfoFromID(AreValueTypesBoxed boxed,
273 VMPTR_AppDomain vmAppDomain,
274 COR_TYPEID id,
275 DebuggerIPCE_ExpandedTypeData *pTypeInfo);
276
277
278 // @dbgtodo Microsoft inspection: change DebuggerIPCE_ExpandedTypeData to DacDbiStructures type hierarchy
279 // once ICorDebugType and ICorDebugClass are DACized
280 // use a type handle to get the information needed to create the corresponding RS CordbType instance
281 void TypeHandleToExpandedTypeInfo(AreValueTypesBoxed boxed,
282 VMPTR_AppDomain vmAppDomain,
283 VMPTR_TypeHandle vmTypeHandle,
284 DebuggerIPCE_ExpandedTypeData * pTypeInfo);
285
286 // Get type handle for a TypeDef token, if one exists. For generics this returns the open type.
287 VMPTR_TypeHandle GetTypeHandle(VMPTR_Module vmModule,
288 mdTypeDef metadataToken);
289
290 // Get the approximate type handle for an instantiated type. This may be identical to the exact type handle,
291 // but if we have code sharing for generics,it may differ in that it may have canonical type parameters.
292 VMPTR_TypeHandle GetApproxTypeHandle(TypeInfoList * pTypeData);
293
294 // Get the exact type handle from type data
295 HRESULT GetExactTypeHandle(DebuggerIPCE_ExpandedTypeData * pTypeData,
296 ArgInfoList * pArgInfo,
297 VMPTR_TypeHandle& vmTypeHandle);
298
299 // Retrieve the generic type params for a given MethodDesc. This function is specifically
300 // for stackwalking because it requires the generic type token on the stack.
301 void GetMethodDescParams(VMPTR_AppDomain vmAppDomain,
302 VMPTR_MethodDesc vmMethodDesc,
303 GENERICS_TYPE_TOKEN genericsToken,
304 UINT32 * pcGenericClassTypeParams,
305 TypeParamsList * pGenericTypeParams);
306
307 // Get the target field address of a context or thread local static.
308 CORDB_ADDRESS GetThreadStaticAddress(VMPTR_FieldDesc vmField,
309 VMPTR_Thread vmRuntimeThread);
310
311 // Get the target field address of a collectible types static.
312 CORDB_ADDRESS GetCollectibleTypeStaticAddress(VMPTR_FieldDesc vmField,
313 VMPTR_AppDomain vmAppDomain);
314
315 // Get information about a field added with Edit And Continue.
316 void GetEnCHangingFieldInfo(const EnCHangingFieldInfo * pEnCFieldInfo,
317 FieldData * pFieldData,
318 BOOL * pfStatic);
319
320 // GetTypeHandleParams gets the necessary data for a type handle, i.e. its
321 // type parameters, e.g. "String" and "List<int>" from the type handle
322 // for "Dict<String,List<int>>", and sends it back to the right side.
323 // This should not fail except for OOM
324
325 void GetTypeHandleParams(VMPTR_AppDomain vmAppDomain,
326 VMPTR_TypeHandle vmTypeHandle,
327 TypeParamsList * pParams);
328
329 // DacDbi API: GetSimpleType
330 // gets the metadata token and domain file corresponding to a simple type
331 void GetSimpleType(VMPTR_AppDomain vmAppDomain,
332 CorElementType simpleType,
333 mdTypeDef * pMetadataToken,
334 VMPTR_Module * pVmModule,
335 VMPTR_DomainFile * pVmDomainFile);
336
337 BOOL IsExceptionObject(VMPTR_Object vmObject);
338
339 void GetStackFramesFromException(VMPTR_Object vmObject, DacDbiArrayList<DacExceptionCallStackData>& dacStackFrames);
340
341 // Returns true if the argument is a runtime callable wrapper
342 BOOL IsRcw(VMPTR_Object vmObject);
343
344 // retrieves the list of COM interfaces implemented by vmObject, as it is known at
345 // the time of the call (the list may change as new interface types become available
346 // in the runtime)
347 void GetRcwCachedInterfaceTypes(
348 VMPTR_Object vmObject,
349 VMPTR_AppDomain vmAppDomain,
350 BOOL bIInspectableOnly,
351 OUT DacDbiArrayList<DebuggerIPCE_ExpandedTypeData> * pDacInterfaces);
352
353 // retrieves the list of interfaces pointers implemented by vmObject, as it is known at
354 // the time of the call (the list may change as new interface types become available
355 // in the runtime)
356 void GetRcwCachedInterfacePointers(
357 VMPTR_Object vmObject,
358 BOOL bIInspectableOnly,
359 OUT DacDbiArrayList<CORDB_ADDRESS> * pDacItfPtrs);
360
361 // retrieves a list of interface types corresponding to the passed in
362 // list of IIDs. the interface types are retrieved from an app domain
363 // IID / Type cache, that is updated as new types are loaded. will
364 // have NULL entries corresponding to unknown IIDs in "iids"
365 void GetCachedWinRTTypesForIIDs(
366 VMPTR_AppDomain vmAppDomain,
367 DacDbiArrayList<GUID> & iids,
368 OUT DacDbiArrayList<DebuggerIPCE_ExpandedTypeData> * pTypes);
369
370 // retrieves the whole app domain cache of IID / Type mappings.
371 void GetCachedWinRTTypes(
372 VMPTR_AppDomain vmAppDomain,
373 OUT DacDbiArrayList<GUID> * pGuids,
374 OUT DacDbiArrayList<DebuggerIPCE_ExpandedTypeData> * pTypes);
375
376private:
377 BOOL IsExceptionObject(MethodTable* pMT);
378
379 // Get the approximate and exact type handles for a type
380 void GetTypeHandles(VMPTR_TypeHandle vmThExact,
381 VMPTR_TypeHandle vmThApprox,
382 TypeHandle * pThExact,
383 TypeHandle * pThApprox);
384
385 // Gets the total number of fields for a type.
386 unsigned int GetTotalFieldCount(TypeHandle thApprox);
387
388 // initializes various values of the ClassInfo data structure, including the
389 // field count, generic args count, size and value class flag
390 void InitClassData(TypeHandle thApprox,
391 BOOL fIsInstantiatedType,
392 ClassInfo * pData);
393
394 // Gets the base table addresses for both GC and non-GC statics
395 void GetStaticsBases(TypeHandle thExact,
396 AppDomain * pAppDomain,
397 PTR_BYTE * ppGCStaticsBase,
398 PTR_BYTE * ppNonGCStaticsBase);
399
400 // Computes the field info for pFD and stores it in pcurrentFieldData
401 void ComputeFieldData(PTR_FieldDesc pFD,
402 PTR_BYTE pGCStaticsBase,
403 PTR_BYTE pNonGCStaticsBase,
404 FieldData * pCurrentFieldData);
405
406 // Gets information for all the fields for a given type
407 void CollectFields(TypeHandle thExact,
408 TypeHandle thApprox,
409 AppDomain * pAppDomain,
410 DacDbiArrayList<FieldData> * pFieldList);
411
412 // Gets additional information to convert a type handle to an instance of CordbType if the type is E_T_ARRAY
413 void GetArrayTypeInfo(TypeHandle typeHandle,
414 DebuggerIPCE_ExpandedTypeData * pTypeInfo,
415 AppDomain * pAppDomain);
416
417 // Gets additional information to convert a type handle to an instance of CordbType if the type is
418 // E_T_PTR or E_T_BYREF
419 void GetPtrTypeInfo(AreValueTypesBoxed boxed,
420 TypeHandle typeHandle,
421 DebuggerIPCE_ExpandedTypeData * pTypeInfo,
422 AppDomain * pAppDomain);
423
424 // Gets additional information to convert a type handle to an instance of CordbType if the type is E_T_FNPTR
425 void GetFnPtrTypeInfo(AreValueTypesBoxed boxed,
426 TypeHandle typeHandle,
427 DebuggerIPCE_ExpandedTypeData * pTypeInfo,
428 AppDomain * pAppDomain);
429
430 // Gets additional information to convert a type handle to an instance of CordbType if the type is
431 // E_T_CLASS or E_T_VALUETYPE
432 void GetClassTypeInfo(TypeHandle typeHandle,
433 DebuggerIPCE_ExpandedTypeData * pTypeInfo,
434 AppDomain * pAppDomain);
435
436 // Gets the correct CorElementType value from a type handle
437 CorElementType GetElementType (TypeHandle typeHandle);
438
439 // Gets additional information to convert a type handle to an instance of CordbType for the referent of an
440 // E_T_BYREF or E_T_PTR or for the element type of an E_T_ARRAY or E_T_SZARRAY
441 void TypeHandleToBasicTypeInfo(TypeHandle typeHandle,
442 DebuggerIPCE_BasicTypeData * pTypeInfo,
443 AppDomain * pAppDomain);
444
445 // wrapper routines to set up for a call to ClassLoader functions to retrieve a type handle for a
446 // particular kind of type
447
448 // find a loaded type handle for a primitive type
449 static TypeHandle FindLoadedElementType(CorElementType elementType);
450
451 // find a loaded type handle for an array type (E_T_ARRAY or E_T_SZARRAY)
452 static TypeHandle FindLoadedArrayType(CorElementType elementType, TypeHandle typeArg, unsigned rank);
453
454 // find a loaded type handle for an address type (E_T_PTR or E_T_BYREF)
455 static TypeHandle FindLoadedPointerOrByrefType(CorElementType elementType, TypeHandle typeArg);
456
457 // find a loaded type handle for a function pointer type (E_T_FNPTR)
458 static TypeHandle FindLoadedFnptrType(DWORD numTypeArgs, TypeHandle * pInst);
459
460 // find a loaded type handle for a particular instantiation of a class type (E_T_CLASS or E_T_VALUETYPE)
461 static TypeHandle FindLoadedInstantiation(Module * pModule,
462 mdTypeDef mdToken,
463 DWORD nTypeArgs,
464 TypeHandle * pInst);
465
466
467 // TypeDataWalk
468 // This class provides functionality to allow us to read type handles for generic type parameters or the
469 // argument of an array or address type. It takes code sharing into account and allows us to get the canonical
470 // form where necessary. It operates on a list of type arguments gathered on the RS and passed to the constructor.
471 // See code:CordbType::GatherTypeData for more information.
472 //
473 class TypeDataWalk
474 {
475 private:
476 // list of type arguments
477 DebuggerIPCE_TypeArgData * m_pCurrentData;
478
479 // number of type arguments still to be processed
480 unsigned int m_nRemaining;
481
482 public:
483 typedef enum {kGetExact, kGetCanonical} TypeHandleReadType;
484 // constructor
485 TypeDataWalk(DebuggerIPCE_TypeArgData *pData, unsigned int nData);
486
487 // Compute the type handle for a given type.
488 // This is the top-level function that will return the type handle
489 // for an arbitrary type. It uses mutual recursion with ReadLoadedTypeArg to get
490 // the type handle for a (possibly parameterized) type. Note that the referent of
491 // address types or the element type of an array type are viewed as type parameters.
492 TypeHandle ReadLoadedTypeHandle(TypeHandleReadType retrieveWhich);
493
494 private:
495 // skip a single node from the list of type handles
496 void Skip();
497
498 // read and return a single node from the list of type parameters
499 DebuggerIPCE_TypeArgData * ReadOne();
500
501 //
502 // These are for type arguments. They return null if the item could not be found.
503 // They also optionally find the canonical form for the specified type
504 // (used if generic code sharing is enabled) even if the exact form has not
505 // yet been loaded for some reason
506 //
507
508 // Read a type handle when it is used in the position of a generic argument or
509 // argument of an array type. Take into account generic code sharing if we
510 // have been requested to find the canonical representation amongst a set of shared-
511 // code generic types. That is, if generics code sharing is enabled then return "Object"
512 // for all reference types, and canonicalize underneath value types, e.g. V<string> --> V<object>.
513 //
514 // Return TypeHandle() (null) if any of the type handles are not loaded.
515 TypeHandle ReadLoadedTypeArg(TypeHandleReadType retrieveWhich);
516
517 // Iterate through the type argument data, creating type handles as we go.
518 // Return FALSE if any of the type handles are not loaded.
519 BOOL ReadLoadedTypeHandles(TypeHandleReadType retrieveWhich, unsigned int nTypeArgs, TypeHandle *ppResults);
520
521 // Read an instantiation of a generic type if it has already been created.
522 TypeHandle ReadLoadedInstantiation(TypeHandleReadType retrieveWhich,
523 Module * pModule,
524 mdTypeDef mdToken,
525 unsigned int nTypeArgs);
526
527 // These are helper functions to get the type handle for specific classes of types
528 TypeHandle ArrayTypeArg(DebuggerIPCE_TypeArgData * pData, TypeHandleReadType retrieveWhich);
529 TypeHandle PtrOrByRefTypeArg(DebuggerIPCE_TypeArgData * pData, TypeHandleReadType retrieveWhich);
530 TypeHandle FnPtrTypeArg(DebuggerIPCE_TypeArgData * pData, TypeHandleReadType retrieveWhich);
531 TypeHandle ClassTypeArg(DebuggerIPCE_TypeArgData * pData, TypeHandleReadType retrieveWhich);
532 TypeHandle ObjRefOrPrimitiveTypeArg(DebuggerIPCE_TypeArgData * pData, CorElementType elementType);
533
534 }; // class TypeDataWalk
535
536 // get a typehandle for a class or valuetype from basic type data (metadata token
537 // and domain file
538 TypeHandle GetClassOrValueTypeHandle(DebuggerIPCE_BasicTypeData * pData);
539
540 // get an exact type handle for an array type
541 TypeHandle GetExactArrayTypeHandle(DebuggerIPCE_ExpandedTypeData * pTopLevelTypeData,
542 ArgInfoList * pArgInfo);
543
544 // get an exact type handle for a PTR or BYREF type
545 TypeHandle GetExactPtrOrByRefTypeHandle(DebuggerIPCE_ExpandedTypeData * pTopLevelTypeData,
546 ArgInfoList * pArgInfo);
547
548 // get an exact type handle for a CLASS or VALUETYPE type
549 TypeHandle GetExactClassTypeHandle(DebuggerIPCE_ExpandedTypeData * pTopLevelTypeData,
550 ArgInfoList * pArgInfo);
551
552 // get an exact type handle for a FNPTR type
553 TypeHandle GetExactFnPtrTypeHandle(ArgInfoList * pArgInfo);
554
555 // Convert basic type info for a type parameter that came from a top-level type to
556 // the corresponding type handle. If the type parameter is an array or pointer
557 // type, we simply extract the LS type handle from the VMPTR_TypeHandle that is
558 // part of the type information. If the type parameter is a class or value type,
559 // we use the metadata token and domain file in the type info to look up the
560 // appropriate type handle. If the type parameter is any other types, we get the
561 // type handle by having the loader look up the type handle for the element type.
562 TypeHandle BasicTypeInfoToTypeHandle(DebuggerIPCE_BasicTypeData * pArgTypeData);
563
564 // Convert type information for a top-level type to an exact type handle. This
565 // information includes information about the element type if the top-level type is
566 // an array type, the referent if the top-level type is a pointer type, or actual
567 // parameters if the top-level type is a generic class or value type.
568 TypeHandle ExpandedTypeInfoToTypeHandle(DebuggerIPCE_ExpandedTypeData * pTopLevelTypeData,
569 ArgInfoList * pArgInfo);
570
571 // Initialize information about a field added with EnC
572 void InitFieldData(const FieldDesc * pFD,
573 const PTR_CBYTE pORField,
574 const EnCHangingFieldInfo * pEncFieldData,
575 FieldData * pFieldData);
576
577 // Get the address of a field added with EnC.
578 PTR_CBYTE GetPtrToEnCField(FieldDesc * pFD, const EnCHangingFieldInfo * pEnCFieldInfo);
579
580 // Get the FieldDesc corresponding to a particular EnC field token
581 FieldDesc * GetEnCFieldDesc(const EnCHangingFieldInfo * pEnCFieldInfo);
582
583 // Finds information for a particular class field
584 PTR_FieldDesc FindField(TypeHandle thApprox, mdFieldDef fldToken);
585
586// ============================================================================
587// functions to get information about instances of ICDValue implementations
588// ============================================================================
589
590public:
591 // Get object information for a TypedByRef object. Initializes the objRef and typedByRefType fields of
592 // pObjectData (type info for the referent).
593 void GetTypedByRefInfo(CORDB_ADDRESS pTypedByRef,
594 VMPTR_AppDomain vmAppDomain,
595 DebuggerIPCE_ObjectData * pObjectData);
596
597 // Get the string length and offset to string base for a string object
598 void GetStringData(CORDB_ADDRESS objectAddress, DebuggerIPCE_ObjectData * pObjectData);
599
600 // Get information for an array type referent of an objRef, including rank, upper and lower bounds,
601 // element size and type, and the number of elements.
602 void GetArrayData(CORDB_ADDRESS objectAddress, DebuggerIPCE_ObjectData * pObjectData);
603
604 // Get information about an object for which we have a reference, including the object size and
605 // type information.
606 void GetBasicObjectInfo(CORDB_ADDRESS objectAddress,
607 CorElementType type,
608 VMPTR_AppDomain vmAppDomain,
609 DebuggerIPCE_ObjectData * pObjectData);
610
611 // Returns the thread which owns the monitor lock on an object and the acquisition count
612 MonitorLockInfo GetThreadOwningMonitorLock(VMPTR_Object vmObject);
613
614
615 // Enumerate all threads waiting on the monitor event for an object
616 void EnumerateMonitorEventWaitList(VMPTR_Object vmObject,
617 FP_THREAD_ENUMERATION_CALLBACK fpCallback,
618 CALLBACK_DATA pUserData);
619
620private:
621 // Helper function for CheckRef. Sanity check an object.
622 HRESULT FastSanityCheckObject(PTR_Object objPtr);
623
624 // Perform a sanity check on an object address to determine if this _could be_ a valid object. We can't
625 // tell this for certain without walking the GC heap, but we do some fast tests to rule out clearly
626 // invalid object addresses. See code:DacDbiInterfaceImpl::FastSanityCheckObject for more details.
627 bool CheckRef(PTR_Object objPtr);
628
629 // Initialize basic object information: type handle, object size, offset to fields and expanded type
630 // information.
631 void InitObjectData(PTR_Object objPtr,
632 VMPTR_AppDomain vmAppDomain,
633 DebuggerIPCE_ObjectData * pObjectData);
634
635// ============================================================================
636// Functions to test data safety. In these functions we determine whether a lock
637// is held in a code path we need to execute for inspection. If so, we throw an
638// exception.
639// ============================================================================
640
641#ifdef TEST_DATA_CONSISTENCY
642public:
643 void TestCrst(VMPTR_Crst vmCrst);
644 void TestRWLock(VMPTR_SimpleRWLock vmRWLock);
645#endif
646
647// ============================================================================
648// CordbAssembly, CordbModule
649// ============================================================================
650
651 using ClrDataAccess::GetModuleData;
652 using ClrDataAccess::GetAddressType;
653
654public:
655 // Get the full path and file name to the assembly's manifest module.
656 BOOL GetAssemblyPath(VMPTR_Assembly vmAssembly,
657 IStringHolder * pStrFilename);
658
659 void GetAssemblyFromDomainAssembly(VMPTR_DomainAssembly vmDomainAssembly, VMPTR_Assembly *vmAssembly);
660
661 // Determines whether the runtime security system has assigned full-trust to this assembly.
662 BOOL IsAssemblyFullyTrusted(VMPTR_DomainAssembly vmDomainAssembly);
663
664 // get a type def resolved across modules
665 void ResolveTypeReference(const TypeRefData * pTypeRefInfo,
666 TypeRefData * pTargetRefInfo);
667
668 // Get the full path and file name to the module (if any).
669 BOOL GetModulePath(VMPTR_Module vmModule,
670 IStringHolder * pStrFilename);
671
672 // Get the full path and file name to the ngen image for the module (if any).
673 BOOL GetModuleNGenPath(VMPTR_Module vmModule,
674 IStringHolder * pStrFilename);
675
676 // Implementation of IDacDbiInterface::GetModuleSimpleName
677 void GetModuleSimpleName(VMPTR_Module vmModule, IStringHolder * pStrFilename);
678
679 // Implementation of IDacDbiInterface::GetMetadata
680 void GetMetadata(VMPTR_Module vmModule, TargetBuffer * pTargetBuffer);
681
682 // Implementation of IDacDbiInterface::GetSymbolsBuffer
683 void GetSymbolsBuffer(VMPTR_Module vmModule, TargetBuffer * pTargetBuffer, SymbolFormat * pSymbolFormat);
684
685 // Gets properties for a module
686 void GetModuleData(VMPTR_Module vmModule, ModuleInfo * pData);
687
688 // Gets properties for a domainfile
689 void GetDomainFileData(VMPTR_DomainFile vmDomainFile, DomainFileInfo * pData);
690
691 void GetModuleForDomainFile(VMPTR_DomainFile vmDomainFile, OUT VMPTR_Module * pModule);
692
693 // Yields true if the adddress is a CLR stub.
694 BOOL IsTransitionStub(CORDB_ADDRESS address);
695
696 // Get the "type" of address.
697 AddressType GetAddressType(CORDB_ADDRESS address);
698
699
700 // Enumerate the appdomains
701 void EnumerateAppDomains(FP_APPDOMAIN_ENUMERATION_CALLBACK fpCallback,
702 void * pUserData);
703
704 // Enumerate the assemblies in the appdomain.
705 void EnumerateAssembliesInAppDomain(VMPTR_AppDomain vmAppDomain,
706 FP_ASSEMBLY_ENUMERATION_CALLBACK fpCallback,
707 void * pUserData);
708
709 // Enumerate the moduels in the given assembly.
710 void EnumerateModulesInAssembly(
711 VMPTR_DomainAssembly vmAssembly,
712 FP_MODULE_ENUMERATION_CALLBACK fpCallback,
713 void * pUserData
714 );
715
716 // When stopped at an event, request a synchronization.
717 void RequestSyncAtEvent();
718
719 //sets flag Debugger::m_sendExceptionsOutsideOfJMC on the LS
720 HRESULT SetSendExceptionsOutsideOfJMC(BOOL sendExceptionsOutsideOfJMC);
721
722 // Notify the debuggee that a debugger attach is pending.
723 void MarkDebuggerAttachPending();
724
725 // Notify the debuggee that a debugger is attached.
726 void MarkDebuggerAttached(BOOL fAttached);
727
728 // Enumerate connections in the process.
729 void EnumerateConnections(FP_CONNECTION_CALLBACK fpCallback, void * pUserData);
730
731 void EnumerateThreads(FP_THREAD_ENUMERATION_CALLBACK fpCallback, void * pUserData);
732
733 bool IsThreadMarkedDead(VMPTR_Thread vmThread);
734
735 // Return the handle of the specified thread.
736 HANDLE GetThreadHandle(VMPTR_Thread vmThread);
737
738 // Return the object handle for the managed Thread object corresponding to the specified thread.
739 VMPTR_OBJECTHANDLE GetThreadObject(VMPTR_Thread vmThread);
740
741 // Set and reset the TSNC_DebuggerUserSuspend bit on the state of the specified thread
742 // according to the CorDebugThreadState.
743 void SetDebugState(VMPTR_Thread vmThread,
744 CorDebugThreadState debugState);
745
746 // Returns TRUE if there is a current exception which is unhandled
747 BOOL HasUnhandledException(VMPTR_Thread vmThread);
748
749 // Return the user state of the specified thread.
750 CorDebugUserState GetUserState(VMPTR_Thread vmThread);
751
752 // Returns the user state of the specified thread except for USER_UNSAFE_POINT.
753 CorDebugUserState GetPartialUserState(VMPTR_Thread vmThread);
754
755 // Return the connection ID of the specified thread.
756 CONNID GetConnectionID(VMPTR_Thread vmThread);
757
758 // Return the task ID of the specified thread.
759 TASKID GetTaskID(VMPTR_Thread vmThread);
760
761 // Return the OS thread ID of the specified thread
762 DWORD TryGetVolatileOSThreadID(VMPTR_Thread vmThread);
763
764 // Return the unique thread ID of the specified thread.
765 DWORD GetUniqueThreadID(VMPTR_Thread vmThread);
766
767 // Return the object handle to the managed Exception object of the current exception
768 // on the specified thread. The return value could be NULL if there is no current exception.
769 VMPTR_OBJECTHANDLE GetCurrentException(VMPTR_Thread vmThread);
770
771 // Return the object handle to the managed object for a given CCW pointer.
772 VMPTR_OBJECTHANDLE GetObjectForCCW(CORDB_ADDRESS ccwPtr);
773
774 // Return the object handle to the managed CustomNotification object of the current notification
775 // on the specified thread. The return value could be NULL if there is no current notification.
776 // This will return non-null if and only if we are currently inside a CustomNotification Callback
777 // (or a dump was generated while in this callback)
778 VMPTR_OBJECTHANDLE GetCurrentCustomDebuggerNotification(VMPTR_Thread vmThread);
779
780
781 // Return the current appdomain the specified thread is in.
782 VMPTR_AppDomain GetCurrentAppDomain(VMPTR_Thread vmThread);
783
784 // Given an assembly ref token and metadata scope (via the DomainFile), resolve the assembly.
785 VMPTR_DomainAssembly ResolveAssembly(VMPTR_DomainFile vmScope, mdToken tkAssemblyRef);
786
787
788 // Hijack the thread
789 void Hijack(
790 VMPTR_Thread vmThread,
791 ULONG32 dwThreadId,
792 const EXCEPTION_RECORD * pRecord,
793 T_CONTEXT * pOriginalContext,
794 ULONG32 cbSizeContext,
795 EHijackReason::EHijackReason reason,
796 void * pUserData,
797 CORDB_ADDRESS * pRemoteContextAddr);
798
799 // Return the filter CONTEXT on the LS.
800 VMPTR_CONTEXT GetManagedStoppedContext(VMPTR_Thread vmThread);
801
802 // Create and return a stackwalker on the specified thread.
803 void CreateStackWalk(VMPTR_Thread vmThread,
804 DT_CONTEXT * pInternalContextBuffer,
805 StackWalkHandle * ppSFIHandle);
806
807 // Delete the stackwalk object
808 void DeleteStackWalk(StackWalkHandle ppSFIHandle);
809
810 // Get the CONTEXT of the current frame at which the stackwalker is stopped.
811 void GetStackWalkCurrentContext(StackWalkHandle pSFIHandle,
812 DT_CONTEXT * pContext);
813
814 void GetStackWalkCurrentContext(StackFrameIterator * pIter, DT_CONTEXT * pContext);
815
816 // Set the stackwalker to the specified CONTEXT.
817 void SetStackWalkCurrentContext(VMPTR_Thread vmThread,
818 StackWalkHandle pSFIHandle,
819 CorDebugSetContextFlag flag,
820 DT_CONTEXT * pContext);
821
822 // Unwind the stackwalker to the next frame.
823 BOOL UnwindStackWalkFrame(StackWalkHandle pSFIHandle);
824
825 HRESULT CheckContext(VMPTR_Thread vmThread,
826 const DT_CONTEXT * pContext);
827
828 // Retrieve information about the current frame from the stackwalker.
829 FrameType GetStackWalkCurrentFrameInfo(StackWalkHandle pSFIHandle,
830 DebuggerIPCE_STRData * pFrameData);
831
832 // Return the number of internal frames on the specified thread.
833 ULONG32 GetCountOfInternalFrames(VMPTR_Thread vmThread);
834
835 // Enumerate the internal frames on the specified thread and invoke the provided callback on each of them.
836 void EnumerateInternalFrames(VMPTR_Thread vmThread,
837 FP_INTERNAL_FRAME_ENUMERATION_CALLBACK fpCallback,
838 void * pUserData);
839
840 // Given the FramePointer of the parent frame and the FramePointer of the current frame,
841 // check if the current frame is the parent frame.
842 BOOL IsMatchingParentFrame(FramePointer fpToCheck, FramePointer fpParent);
843
844 // Return the stack parameter size of the given method.
845 ULONG32 GetStackParameterSize(CORDB_ADDRESS controlPC);
846
847 // Return the FramePointer of the current frame at which the stackwalker is stopped.
848 FramePointer GetFramePointer(StackWalkHandle pSFIHandle);
849
850 FramePointer GetFramePointerWorker(StackFrameIterator * pIter);
851
852 // Return TRUE if the specified CONTEXT is the CONTEXT of the leaf frame.
853 // @dbgtodo filter CONTEXT - Currently we check for the filter CONTEXT first.
854 BOOL IsLeafFrame(VMPTR_Thread vmThread,
855 const DT_CONTEXT * pContext);
856
857 // DacDbi API: Get the context for a particular thread of the target process
858 void GetContext(VMPTR_Thread vmThread, DT_CONTEXT * pContextBuffer);
859
860 // This is a simple helper function to convert a CONTEXT to a DebuggerREGDISPLAY. We need to do this
861 // inside DDI because the RS has no notion of REGDISPLAY.
862 void ConvertContextToDebuggerRegDisplay(const DT_CONTEXT * pInContext,
863 DebuggerREGDISPLAY * pOutDRD,
864 BOOL fActive);
865
866 // Check if the given method is an IL stub or an LCD method.
867 DynamicMethodType IsILStubOrLCGMethod(VMPTR_MethodDesc vmMethodDesc);
868
869 // Return a TargetBuffer for the raw vararg signature.
870 TargetBuffer GetVarArgSig(CORDB_ADDRESS VASigCookieAddr,
871 CORDB_ADDRESS * pArgBase);
872
873 // returns TRUE if the type requires 8-byte alignment
874 BOOL RequiresAlign8(VMPTR_TypeHandle thExact);
875
876 // Resolve the raw generics token to the real generics type token. The resolution is based on the
877 // given index.
878 GENERICS_TYPE_TOKEN ResolveExactGenericArgsToken(DWORD dwExactGenericArgsTokenIndex,
879 GENERICS_TYPE_TOKEN rawToken);
880
881 // Enumerate all monitors blocking a thread
882 void EnumerateBlockingObjects(VMPTR_Thread vmThread,
883 FP_BLOCKINGOBJECT_ENUMERATION_CALLBACK fpCallback,
884 CALLBACK_DATA pUserData);
885
886 // Returns a bitfield reflecting the managed debugging state at the time of
887 // the jit attach.
888 CLR_DEBUGGING_PROCESS_FLAGS GetAttachStateFlags();
889
890protected:
891 // This class used to be stateless, but we are relaxing the requirements
892 // slightly to gain perf. We should still be stateless in the sense that an API call
893 // should always return the same result regardless of the internal state. Hence
894 // a caller can not distinguish that we have any state. Internally however we are
895 // allowed to cache pieces of frequently used data to improve the perf of various
896 // operations. All of this cached data should be flushed when the DAC is flushed.
897
898 // But it can have helper methods.
899
900 // The allocator object is conceptually stateless. It lets us allocate data buffers to hand back.
901 IAllocator * m_pAllocator;
902
903 // Callback to DBI to get internal metadata.
904 IMetaDataLookup * m_pMetaDataLookup;
905
906
907 // Metadata lookups is just a property on the PEFile in the normal builds,
908 // and so VM code tends to access the same metadata importer many times in a row.
909 // Cache the most-recently used to avoid excessive redundant lookups.
910
911 // PEFile of Cached Importer. Invalidated between Flush calls. If this is Non-null,
912 // then the importer is m_pCachedImporter, and we can avoid using IMetaDataLookup
913 VMPTR_PEFile m_pCachedPEFile;
914
915 // Value of cached importer, corresponds with m_pCachedPEFile.
916 IMDInternalImport * m_pCachedImporter;
917
918 // Value of cached hijack function list, corresponds to g_pDebugger->m_rgHijackFunction
919 BOOL m_isCachedHijackFunctionValid;
920 TargetBuffer m_pCachedHijackFunction[Debugger::kMaxHijackFunctions];
921
922 // Helper to write structured data to target.
923 template<typename T>
924 void SafeWriteStructOrThrow(CORDB_ADDRESS pRemotePtr, const T * pLocalBuffer);
925
926 // Helper to read structured data from the target process.
927 template<typename T>
928 void SafeReadStructOrThrow(CORDB_ADDRESS pRemotePtr, T * pLocalBuffer);
929
930 TADDR GetHijackAddress();
931
932 void AlignStackPointer(CORDB_ADDRESS * pEsp);
933
934 template <class T>
935 CORDB_ADDRESS PushHelper(CORDB_ADDRESS * pEsp, const T * pData, BOOL fAlignStack);
936
937 // Write an EXCEPTION_RECORD structure to the remote target at the specified address while taking
938 // into account the number of exception parameters.
939 void WriteExceptionRecordHelper(CORDB_ADDRESS pRemotePtr, const EXCEPTION_RECORD * pExcepRecord);
940
941 typedef DPTR(struct DebuggerIPCControlBlock) PTR_DebuggerIPCControlBlock;
942
943 // Get the address of the Debugger control block on the helper thread. Returns
944 // NULL if the control block has not been successfully allocated
945 CORDB_ADDRESS GetDebuggerControlBlockAddress();
946
947 // Creates a VMPTR of an Object from a target address
948 VMPTR_Object GetObject(CORDB_ADDRESS ptr);
949
950 // sets state in the native binder
951 HRESULT EnableNGENPolicy(CorDebugNGENPolicy ePolicy);
952
953 // Sets the NGEN compiler flags. This restricts NGEN to only use images with certain
954 // types of pregenerated code.
955 HRESULT SetNGENCompilerFlags(DWORD dwFlags);
956
957 // Gets the NGEN compiler flags currently in effect.
958 HRESULT GetNGENCompilerFlags(DWORD *pdwFlags);
959
960 // Creates a VMPTR of an Object from a target address pointing to an OBJECTREF
961 VMPTR_Object GetObjectFromRefPtr(CORDB_ADDRESS ptr);
962
963 // Get the target address from a VMPTR_OBJECTHANDLE, i.e., the handle address
964 CORDB_ADDRESS GetHandleAddressFromVmHandle(VMPTR_OBJECTHANDLE vmHandle);
965
966 // Gets the target address of an VMPTR of an Object
967 TargetBuffer GetObjectContents(VMPTR_Object vmObj);
968
969 // Create a VMPTR_OBJECTHANDLE from a CORDB_ADDRESS pointing to an object handle
970 VMPTR_OBJECTHANDLE GetVmObjectHandle(CORDB_ADDRESS handleAddress);
971
972 // Validate that the VMPTR_OBJECTHANDLE refers to a legitimate managed object
973 BOOL IsVmObjectHandleValid(VMPTR_OBJECTHANDLE vmHandle);
974
975 // if the specified module is a WinRT module then isWinRT will equal TRUE
976 HRESULT IsWinRTModule(VMPTR_Module vmModule, BOOL& isWinRT);
977
978 // Determines the app domain id for the object refered to by a given VMPTR_OBJECTHANDLE
979 ULONG GetAppDomainIdFromVmObjectHandle(VMPTR_OBJECTHANDLE vmHandle);
980
981private:
982 bool IsThreadMarkedDeadWorker(Thread * pThread);
983
984 // Check whether the specified thread is at a GC-safe place, i.e. in an interruptible region.
985 BOOL IsThreadAtGCSafePlace(VMPTR_Thread vmThread);
986
987 // Fill in the structure with information about the current frame at which the stackwalker is stopped
988 void InitFrameData(StackFrameIterator * pIter,
989 FrameType ft,
990 DebuggerIPCE_STRData * pFrameData);
991
992 // Helper method to fill in the address and the size of the hot and cold regions.
993 void InitNativeCodeAddrAndSize(TADDR taStartAddr,
994 DebuggerIPCE_JITFuncData * pJITFuncData);
995
996 // Fill in the information about the parent frame.
997 void InitParentFrameInfo(CrawlFrame * pCF,
998 DebuggerIPCE_JITFuncData * pJITFuncData);
999
1000 // Return the stack parameter size of the given method.
1001 ULONG32 GetStackParameterSize(EECodeInfo * pCodeInfo);
1002
1003 typedef enum
1004 {
1005 kFromManagedToUnmanaged,
1006 kFromUnmanagedToManaged,
1007 } StackAdjustmentDirection;
1008
1009 // Adjust the stack pointer in the CONTEXT for the stack parameter.
1010 void AdjustRegDisplayForStackParameter(REGDISPLAY * pRD,
1011 DWORD cbStackParameterSize,
1012 BOOL fIsActiveFrame,
1013 StackAdjustmentDirection direction);
1014
1015 // Given an explicit frame, return the corresponding type in terms of CorDebugInternalFrameType.
1016 CorDebugInternalFrameType GetInternalFrameType(Frame * pFrame);
1017
1018 // Helper method to convert a REGDISPLAY to a CONTEXT.
1019 void UpdateContextFromRegDisp(REGDISPLAY * pRegDisp,
1020 T_CONTEXT * pContext);
1021
1022 // Check if a control PC is in one of the native functions which require special unwinding.
1023 bool IsRuntimeUnwindableStub(PCODE taControlPC);
1024
1025 // Given the REGDISPLAY of a stack frame for one of the redirect functions, retrieve the original CONTEXT
1026 // before the thread redirection.
1027 PTR_CONTEXT RetrieveHijackedContext(REGDISPLAY * pRD);
1028
1029 // Unwind special native stack frame which the runtime knows how to unwind.
1030 BOOL UnwindRuntimeStackFrame(StackFrameIterator * pIter);
1031
1032 // Look up the EnC version number of a particular jitted instance of a managed method.
1033 void LookupEnCVersions(Module* pModule,
1034 VMPTR_MethodDesc vmMethodDesc,
1035 mdMethodDef mdMethod,
1036 CORDB_ADDRESS pNativeStartAddress,
1037 SIZE_T * pLatestEnCVersion,
1038 SIZE_T * pJittedInstanceEnCVersion = NULL);
1039
1040 // @dbgtodo - This method should be removed once CordbFunctionBreakpoint and SetIP are moved OOP and
1041 // no longer use nativeCodeJITInfoToken.
1042 void SetDJIPointer(Module * pModule,
1043 MethodDesc * pMD,
1044 mdMethodDef mdMethod,
1045 DebuggerIPCE_JITFuncData * pJITFuncData);
1046
1047 // This is just a worker function for GetILCodeAndSig. It returns the function's ILCode and SigToken
1048 // given a module, a token, and the RVA. If a MethodDesc is provided, it has to be consistent with
1049 // the token and the RVA.
1050 mdSignature GetILCodeAndSigHelper(Module * pModule,
1051 MethodDesc * pMD,
1052 mdMethodDef mdMethodToken,
1053 RVA methodRVA,
1054 TargetBuffer * pIL);
1055
1056public:
1057 // APIs for picking up the info needed for a debugger to look up an ngen image or IL image
1058 // from it's search path.
1059 bool GetMetaDataFileInfoFromPEFile(VMPTR_PEFile vmPEFile,
1060 DWORD &dwTimeStamp,
1061 DWORD &dwSize,
1062 bool &isNGEN,
1063 IStringHolder* pStrFilename);
1064
1065 bool GetILImageInfoFromNgenPEFile(VMPTR_PEFile vmPEFile,
1066 DWORD &dwTimeStamp,
1067 DWORD &dwSize,
1068 IStringHolder* pStrFilename);
1069
1070};
1071
1072
1073// Global allocator for DD. Access is protected under the g_dacCritSec lock.
1074extern "C" IDacDbiInterface::IAllocator * g_pAllocator;
1075
1076
1077class DDHolder
1078{
1079public:
1080 DDHolder(DacDbiInterfaceImpl* pContainer, bool fAllowReentrant)
1081 {
1082 EnterCriticalSection(&g_dacCritSec);
1083
1084 // If we're not re-entrant, then assert.
1085 if (!fAllowReentrant)
1086 {
1087 _ASSERTE(g_dacImpl == NULL);
1088 }
1089
1090 // This cast is safe because ClrDataAccess can't call the DacDbi layer.
1091 m_pOldContainer = static_cast<DacDbiInterfaceImpl *> (g_dacImpl);
1092 m_pOldAllocator = g_pAllocator;
1093
1094 g_dacImpl = pContainer;
1095 g_pAllocator = pContainer->GetAllocator();
1096
1097 }
1098 ~DDHolder()
1099 {
1100 // If an exception is being thrown, we won't be in the PAL (but in normal return paths it will).
1101
1102 g_dacImpl = m_pOldContainer;
1103 g_pAllocator = m_pOldAllocator;
1104
1105 LeaveCriticalSection(&g_dacCritSec);
1106 }
1107
1108protected:
1109 DacDbiInterfaceImpl * m_pOldContainer;
1110 IDacDbiInterface::IAllocator * m_pOldAllocator;
1111};
1112
1113
1114// Use this macro at the start of each DD function.
1115// This may nest if a DD primitive takes in a callback that then calls another DD primitive.
1116#define DD_ENTER_MAY_THROW \
1117 DDHolder __dacHolder(this, true); \
1118
1119
1120// Non-reentrant version of DD_ENTER_MAY_THROW. Asserts non-reentrancy.
1121// Use this macro at the start of each DD function.
1122// This may nest if a DD primitive takes in a callback that then calls another DD primitive.
1123#define DD_NON_REENTRANT_MAY_THROW \
1124 DDHolder __dacHolder(this, false); \
1125
1126#include "dacdbiimpl.inl"
1127
1128class DacRefWalker
1129{
1130public:
1131 DacRefWalker(ClrDataAccess *dac, BOOL walkStacks, BOOL walkFQ, UINT32 handleMask);
1132 ~DacRefWalker();
1133
1134 HRESULT Init();
1135 HRESULT Next(ULONG celt, DacGcReference roots[], ULONG *pceltFetched);
1136
1137private:
1138 UINT32 GetHandleWalkerMask();
1139 void Clear();
1140 HRESULT NextThread();
1141
1142private:
1143 ClrDataAccess *mDac;
1144 BOOL mWalkStacks, mWalkFQ;
1145 UINT32 mHandleMask;
1146
1147 // Stacks
1148 DacStackReferenceWalker *mStackWalker;
1149
1150 // Handles
1151 DacHandleWalker *mHandleWalker;
1152
1153 // FQ
1154 PTR_PTR_Object mFQStart;
1155 PTR_PTR_Object mFQEnd;
1156 PTR_PTR_Object mFQCurr;
1157};
1158
1159#endif // _DACDBI_IMPL_H_
1160