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 |
16 | STDAPI |
17 | DacDbiInterfaceInstance( |
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 | // |
36 | class DacDbiInterfaceImpl : |
37 | public ClrDataAccess, |
38 | public IDacDbiInterface |
39 | { |
40 | public: |
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 | |
161 | private: |
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 | |
188 | public: |
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 | |
241 | private: |
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 | |
246 | public: |
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 | |
376 | private: |
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 | |
590 | public: |
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 | |
620 | private: |
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 |
642 | public: |
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 | |
654 | public: |
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 | |
890 | protected: |
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 | |
981 | private: |
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 | |
1056 | public: |
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. |
1074 | extern "C" IDacDbiInterface::IAllocator * g_pAllocator; |
1075 | |
1076 | |
1077 | class DDHolder |
1078 | { |
1079 | public: |
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 | |
1108 | protected: |
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 | |
1128 | class DacRefWalker |
1129 | { |
1130 | public: |
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 | |
1137 | private: |
1138 | UINT32 GetHandleWalkerMask(); |
1139 | void Clear(); |
1140 | HRESULT NextThread(); |
1141 | |
1142 | private: |
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 | |