1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4//*****************************************************************************
5// File: DacDbiStructures.h
6//
7
8//
9// Declarations and inline functions for data structures shared between by the
10// DAC/DBI interface functions and the right side.
11//
12// Note that for MAC these structures are marshalled between Windows and Mac
13// and so their layout and size must be identical in both builds. Use the
14// MSLAYOUT macro on every structure to avoid compiler packing differences.
15//
16//*****************************************************************************
17
18#ifndef DACDBISTRUCTURES_H_
19#define DACDBISTRUCTURES_H_
20
21#include "./common.h"
22
23//-------------------------------------------------------------------------------
24// classes shared by the DAC/DBI interface functions and the right side
25//-------------------------------------------------------------------------------
26
27// DacDbiArrayList encapsulates an array and the number of elements in the array.
28// Notes:
29// - storage is always on the DacDbi heap
30// - this class owns the memory. Its dtor will free.
31// - Operations that initialize list elements use the assignment
32// operator defined for type T. If T is a pointer type or has pointer
33// type components and no assignment operator override, this will make a shallow copy of
34// the element. If T has an assignment operator override that makes a deep copy of pointer
35// types, T must also have a destructor that will deallocate any memory allocated.
36// - this is NOT thread safe!!!
37// - the array elements are always mutable, but the number of elements is fixed between allocations
38// - you can gain access to the array using &(list[0]) but this is NOT safe if the array is empty. You
39// can call IsEmpty to determine if it is safe to access the array portion
40// This list is not designed to have unused elements at the end of the array (extra space) nor to be growable
41
42// usage examples:
43// typedef DacDbiArrayList<Bar> BarList; // handy typedef
44// void GetAListOfBars(BarList * pBarList)
45// {
46// DacDbiArrayList<Foo> fooList; // fooList is an empty array of objects of type Foo
47// int elementCount = GetNumberOfFoos();
48// Bar * pBars = new Bar[elementCount];
49//
50// fooList.Alloc(elementCount); // get space for the list of Foo instances
51// for (int i = 0; i < fooList.Count(); ++i)
52// {
53// fooList[i] = GetNextFoo(); // copy elements into the list
54// }
55// ConvertFoosToBars(pBars, &fooList); // always pass by reference
56// pBarList->Init(pBars, fooList.Count()); // initialize a list
57// }
58//
59// void ConvertFoosToBars(Bar * pBars, DacDbiArrayList<Foo> * pFooList)
60// {
61// for (int i = 0; i < pFooList->Count(); ++i)
62// {
63// if ((*pFooList)[i].IsBaz())
64// pBars [i] = ConvertBazToBar(&(*pFooList)[i]);
65// else pBars [i] = (*pFooList)[i].barPart;
66// }
67// }
68//
69template<class T>
70class MSLAYOUT DacDbiArrayList
71{
72public:
73 // construct an empty list
74 DacDbiArrayList();
75
76 // deep copy constructor
77 DacDbiArrayList(const T * list, int count);
78
79 // destructor--sets list to empty state
80 ~DacDbiArrayList();
81
82 // explicitly deallocate the list and set it back to the empty state
83 void Dealloc();
84
85 // allocate a list with space for nElements items
86 void Alloc(int nElements);
87
88 // allocate and initialize a DacDbiArrayList from an array of type T and a count
89 void Init(const T * list, int count);
90
91 // predicate to indicate if the list is empty
92 bool IsEmpty() { return m_nEntries == 0; }
93
94 // read-only element accessor
95 const T & operator [](int index) const;
96
97 // writeable element accessor
98 T & operator [](int index);
99
100
101 // returns the number of elements in the list
102 int Count() const;
103
104 // @dbgtodo Mac - cleaner way to expose this for serialization?
105 void PrepareForDeserialize()
106 {
107 m_pList = NULL;
108 }
109private:
110 // because these are private (and unimplemented), calls will generate a compiler (or linker) error.
111 // This prevents accidentally invoking the default (shallow) copy ctor or assignment operator.
112 // This prevents having multiple instances point to the same list memory (eg. due to passing by value),
113 // which would result in memory corruption when the first copy is destroyed and the list memory is deallocated.
114 DacDbiArrayList(const DacDbiArrayList<T> & sourceList);
115 T & operator = (const DacDbiArrayList<T> & rhs);
116
117// data members
118protected:
119 T * m_pList; // the list
120
121 // - the count is managed by the member functions and is not settable, so (m_pList == NULL) == (m_nEntries == 0)
122 // is always true.
123 int m_nEntries; // the number of items in the list
124
125};
126
127
128// Describes a buffer in the target
129struct MSLAYOUT TargetBuffer
130{
131 TargetBuffer();
132 TargetBuffer(CORDB_ADDRESS pBuffer, ULONG cbSizeInput);
133
134 // @dbgtodo : This ctor form confuses target and host address spaces. This should probably be PTR_VOID instead of void*
135 TargetBuffer(void * pBuffer, ULONG cbSizeInput);
136
137 //
138 // Helper methods
139 //
140
141 // Return a sub-buffer that's starts at byteOffset within this buffer and runs to the end.
142 TargetBuffer SubBuffer(ULONG byteOffset) const;
143
144 // Return a sub-buffer that starts at byteOffset within this buffer and is byteLength long.
145 TargetBuffer SubBuffer(ULONG byteOffset, ULONG byteLength) const;
146
147 // Returns true if the buffer length is 0.
148 bool IsEmpty() const;
149
150 // Sets address to NULL and size to 0
151 // IsEmpty() will be true after this.
152 void Clear();
153
154 // Initialize fields
155 void Init(CORDB_ADDRESS address, ULONG size);
156
157 // Target address of buffer
158 CORDB_ADDRESS pAddress;
159
160 // Size of buffer in bytes
161 ULONG cbSize;
162};
163
164//===================================================================================
165// Module properties, retrieved by DAC.
166// Describes a VMPTR_DomainFile representing a module.
167// In the VM, a raw Module may be domain neutral and shared by many appdomains.
168// Whereas a DomainFile is like a { AppDomain, Module} pair. DomainFile corresponds
169// much more to ICorDebugModule (which also has appdomain affinity).
170//===================================================================================
171struct MSLAYOUT DomainFileInfo
172{
173 // The appdomain that the DomainFile is associated with.
174 // Although VMPTR_Module may be shared across multiple domains, a DomainFile has appdomain affinity.
175 VMPTR_AppDomain vmAppDomain;
176
177 // The assembly this module belongs to. All modules live in an assembly.
178 VMPTR_DomainAssembly vmDomainAssembly;
179};
180
181struct MSLAYOUT ModuleInfo
182{
183 // The non-domain specific assembly which this module resides in.
184 VMPTR_Assembly vmAssembly;
185
186 // The PE Base address and size of the module. These may be 0 if there is no image
187 // (such as for a dynamic module that's not persisted to disk).
188 CORDB_ADDRESS pPEBaseAddress;
189
190 // The PEFile associated with the module. Every module (even non-file-based ones) has a PEFile.
191 // This is critical because DAC may ask for a metadata importer via PE-file.
192 // a PEFile may have 1 or more PEImage child objects (1 for IL, 1 for native image, etc)
193 VMPTR_PEFile vmPEFile;
194
195 // The PE Base address and size of the module. These may be 0 if there is no image
196 // (such as for a dynamic module that's not persisted to disk).
197 ULONG nPESize;
198
199 // Is this a dynamic (reflection.emit) module?
200 // This means that new classes can be added to the module; and so
201 // the module's metadata and symbols can be updated. Debugger will have to do extra work
202 // to keep up with the updates.
203 // Dynamic modules may be transient (entirely in-memory) or persisted to disk (have a file associated with them).
204 BOOL fIsDynamic;
205
206 // Is this an inmemory module?
207 // Assemblies can be instantiated purely in-memory from just a Byte[].
208 // This means the module (and pdb) are not in files, and thus the debugger
209 // needs to do extra work to retrieve them from the Target's memory.
210 BOOL fInMemory;
211};
212
213// the following two classes track native offsets for local variables and sequence
214// points. This information is initialized on demand.
215
216
217//===================================================================================
218// NativeVarData holds a list of structs that provide the following information for
219// each local variable and fixed argument in a function: the offsets between which the
220// variable or argument lives in a particular location, the location itself, and the
221// variable number (ID). This allows us to determine where a value is at any given IP.
222
223// Lifetime management of the list is the responsibility of the NativeVarData class.
224// Callers that allocate memory for a new list should NOT maintain a separate pointer
225// to the list.
226
227// The arguments we track are the "fixed" arguments, specifically, the explicit arguments
228// that appear in the source code and the "this" pointer for non-static methods.
229// Varargs and other implicit arguments, such as the generic handle are counted in
230// CordbJITILFrame::m_allArgsCount.
231
232// Although logically, we really don't differentiate between arguments and locals when
233// all we want to know is where to find a value, we need to have two
234// separate counts. The full explanation is in the comment in rsthread.cpp in
235// CordbJITILFrame::ILVariableToNative, but the short version is that it allows us to
236// compute the correct ID for a value.
237
238// m_fixedArgsCount, accessed through GetFixedArgCount, is the actual number of fixed
239// arguments.
240// m_allArgsCount, accessed through GetAllArgsCount, is the number of fixed args plus the
241// number of varargs.
242
243// The number of entries in m_offsetInfo, accessed through Count(), is NOT the
244// number of locals, nor the number of locals plus the number of arguments. It is the
245// number of entries in the list. Any particular value may have an arbitrary number of
246// entries, depending on how many different places it is stored during the execution of
247// the method. The list is not sorted, so searches for data within it must be linear.
248//===================================================================================
249class MSLAYOUT NativeVarData
250{
251public:
252 // constructor
253 NativeVarData();
254 // destructor
255 ~NativeVarData();
256
257
258 // initialize the list of native var information structures, including the starting address of the list
259 // (m_pOffsetInfo, the number of entries (m_count) and the number of fixed args (m_fixedArgsCount).
260 // NativeVarData will manage the lifetime of the allocated memory for the list, so the caller should not
261 // hold on to its address.
262 void InitVarDataList(ICorDebugInfo::NativeVarInfo * plistStart, int fixedArgCount, int entryCount);
263
264private:
265 // non-existent copy constructor to disable the (shallow) compiler-generated
266 // one. If you attempt to use this, you will get a compiler or linker error.
267 NativeVarData(const NativeVarData & rhs) {};
268
269 // non-existent assignment operator to disable the (shallow) compiler-generated
270 // one. If you attempt to use this, you will get a compiler or linker error.
271 NativeVarData & operator=(const NativeVarData & rhs);
272
273//----------------------------------------------------------------------------------
274// Accessor Functions
275//----------------------------------------------------------------------------------
276public:
277
278 // get the list of native offset info
279 const DacDbiArrayList<ICorDebugInfo::NativeVarInfo> * GetOffsetInfoList() const
280 {
281 _ASSERTE(m_fInitialized);
282 return &m_offsetInfo;
283 }
284
285 // get the number of explicit arguments for this function--this
286 // includes the fixed arguments for vararg methods, but not the variable ones
287 ULONG32 GetFixedArgCount()
288 {
289 _ASSERTE(IsInitialized());
290 // this count includes explicit arguments plus one for the "this" pointer
291 // but doesn't count varargs
292 return m_fixedArgsCount;
293 }
294
295 // get the number of all arguments, including varargs
296 ULONG32 GetAllArgsCount()
297 {
298 _ASSERTE(IsInitialized());
299 return m_allArgsCount;
300 }
301
302 // set the number of all arguments, including varargs
303 void SetAllArgsCount(ULONG32 count)
304 {
305 m_allArgsCount = count;
306 }
307
308 // determine whether we have successfully initialized this
309 BOOL IsInitialized()
310 {
311 return m_fInitialized == true;
312 }
313
314
315//----------------------------------------------------------------------------------
316// Data Members
317//----------------------------------------------------------------------------------
318
319// @dbgtodo Mac - making this public for serializing for remote DAC on mac. Need to make this private again.
320public:
321 // contains a list of structs providing information about the location of a local
322 // variable or argument between a pair of offsets and the number of entries in the list
323 DacDbiArrayList<ICorDebugInfo::NativeVarInfo> m_offsetInfo;
324
325 // number of fixed arguments to the function i.e., the explicit arguments and "this" pointer
326 ULONG32 m_fixedArgsCount;
327
328 // number of fixed arguments plus number of varargs
329 ULONG32 m_allArgsCount;
330
331 // indicates whether an attempt has been made to initialize the var data already
332 bool m_fInitialized;
333}; // class NativeVarData
334
335//===================================================================================
336// SequencePoints holds a list of sequence points that map IL offsets to native offsets. In addition,
337// it keeps track of the number of entries in the list and whether the list is sorted.
338//===================================================================================
339class MSLAYOUT SequencePoints
340{
341public:
342 SequencePoints();
343
344 ~SequencePoints();
345
346 // Initialize the m_pMap data member to the address of an allocated chunk
347 // of memory (or to NULL if the count is zero). Set m_count as the
348 // number of entries in the map.
349 void InitSequencePoints(ULONG32 count);
350
351private:
352 // non-existent copy constructor to disable the (shallow) compiler-generated
353 // one. If you attempt to use this, you will get a compiler or linker error.
354 SequencePoints(const SequencePoints & rhs) {};
355
356 // non-existent assignment operator to disable the (shallow) compiler-generated
357 // one. If you attempt to use this, you will get a compiler or linker error.
358 SequencePoints & operator=(const SequencePoints & rhs);
359
360 //----------------------------------------------------------------------------------
361 // class MapSortILMap: A template class that will sort an array of DebuggerILToNativeMap.
362 // This class is intended to be instantiated on the stack / in temporary storage, and used
363 // to reorder the sequence map.
364 //----------------------------------------------------------------------------------
365 class MapSortILMap : public CQuickSort<DebuggerILToNativeMap>
366 {
367 public:
368 //Constructor
369 MapSortILMap(DebuggerILToNativeMap * map,
370 int count)
371 : CQuickSort<DebuggerILToNativeMap>(map, count) {}
372
373 // secondary key comparison--if two IL offsets are the same,
374 // we determine order based on native offset
375 int CompareInternal(DebuggerILToNativeMap * first,
376 DebuggerILToNativeMap * second);
377
378 //Comparison operator
379 int Compare(DebuggerILToNativeMap * first,
380 DebuggerILToNativeMap * second);
381 };
382
383//----------------------------------------------------------------------------------
384// Accessor Functions
385//----------------------------------------------------------------------------------
386public:
387 // @dbgtodo Microsoft inspection: It would be very nice not to need this at all. Ideally,
388 // it would be better to make ExportILToNativeMap expect a DacDbiArrayList instead of the
389 // array and size. At present, there's a call to ExportILToNativeMap in debugger.cpp where
390 // DacDbiArrayLists aren't available, so at present, we need to pass the array and size.
391 // We should be able to eliminate the debugger.cpp call when we get rid of in-proc
392 // inspection. At that point, we can delete this function too, as well as GetEntryCount.
393 // In the meantime, it would be great if no one else took a dependency on this.
394
395 // get value of m_pMap
396 DebuggerILToNativeMap * GetMapAddr()
397 {
398 // Please don't call this function
399 _ASSERTE(m_fInitialized);
400 return &(m_map[0]);
401 }
402
403 // get value of m_count
404 ULONG32 GetEntryCount()
405 {
406 _ASSERTE(m_fInitialized);
407 return m_mapCount;
408 }
409
410 ULONG32 GetCallsiteEntryCount()
411 {
412 _ASSERTE(m_fInitialized);
413 return m_map.Count() - m_mapCount; //m_map.Count();
414 }
415
416 DebuggerILToNativeMap * GetCallsiteMapAddr()
417 {
418 // Please don't call this function
419 _ASSERTE(m_fInitialized);
420
421 if (m_map.Count() == m_mapCount)
422 return NULL;
423
424 return &(m_map[m_mapCount]);
425 }
426
427
428
429 // determine whether we have initialized this
430 BOOL IsInitialized()
431 {
432 return m_fInitialized == true;
433 }
434
435 // Copy data from the VM map data to our own map structure and sort. The
436 // information comes to us in a data structure that differs slightly from the
437 // one we use out of process, so we have to copy it to the right-side struct.
438 void CopyAndSortSequencePoints(const ICorDebugInfo::OffsetMapping mapCopy[]);
439
440
441 // Set the IL offset of the last sequence point before the epilog.
442 // If a native offset maps to the epilog, we will return the this IL offset.
443 void SetLastILOffset(ULONG32 lastILOffset)
444 {
445 _ASSERTE(m_fInitialized);
446 m_lastILOffset = lastILOffset;
447 }
448
449 // Map the given native offset to IL offset. Also return the mapping type.
450 DWORD MapNativeOffsetToIL(DWORD dwNativeOffset,
451 CorDebugMappingResult *pMapType);
452
453//----------------------------------------------------------------------------------
454// Data Members
455//----------------------------------------------------------------------------------
456
457 // @dbgtodo Mac - making this public for serializing for remote DAC on mac. Need to make this private again.
458public:
459
460 // map of IL to native offsets for sequence points
461 DacDbiArrayList<DebuggerILToNativeMap> m_map;
462
463 //
464 ULONG32 m_mapCount;
465
466 // the IL offset of the last sequence point before the epilog
467 ULONG32 m_lastILOffset;
468 // indicates whether an attempt has been made to initialize the sequence points already
469 bool m_fInitialized;
470}; // class SequencePoints
471
472//----------------------------------------------------------------------------------
473// declarations needed for getting native code regions
474//----------------------------------------------------------------------------------
475
476// Code may be split into Hot & Cold regions, so we need an extra address & size.
477// The jitter doesn't do this optimization w/ debuggable code, so we'll
478// rarely see the cold region information as non-null values.
479
480// This enumeration provides symbolic indices into m_rgCodeRegions.
481typedef enum {kHot = 0, kCold, MAX_REGIONS} CodeBlobRegion;
482
483// This contains the information we need to initialize a CordbNativeCode object
484class MSLAYOUT NativeCodeFunctionData
485{
486public:
487 // set all fields to default values (NULL, FALSE, or zero as appropriate)
488 NativeCodeFunctionData();
489
490 // conversion constructor to convert from an instance of DebuggerIPCE_JITFUncData to an instance of
491 // NativeCodeFunctionData.
492 NativeCodeFunctionData(DebuggerIPCE_JITFuncData * source);
493
494 // The hot region start address could be NULL in the following circumstances:
495 // 1. We haven't yet tried to get the information
496 // 2. We tried to get the information, but the function hasn't been jitted yet
497 // 3. We tried to get the information, but the MethodDesc wasn't available yet (very early in
498 // module initialization), which implies that the code isn't available either.
499 // 4. We tried to get the information, but a method edit has reset the MethodDesc, but the
500 // method hasn't been jitted yet.
501 // In all cases, we can check the hot region start address to determine whether the rest of the
502 // the information is valid.
503 BOOL IsValid() { return (m_rgCodeRegions[kHot].pAddress != NULL); }
504 void Clear();
505
506 // data members
507 // start addresses and sizes of hot & cold regions
508 TargetBuffer m_rgCodeRegions[MAX_REGIONS];
509
510 // indicates whether the function is a generic function, or a method inside a generic class (or both).
511 BOOL isInstantiatedGeneric;
512
513 // MethodDesc for the function
514 VMPTR_MethodDesc vmNativeCodeMethodDescToken;
515
516 // EnC version number of the function
517 SIZE_T encVersion;
518};
519
520//----------------------------------------------------------------------------------
521// declarations needed for getting type information
522//----------------------------------------------------------------------------------
523
524// FieldData holds data for each field within a class or type. This data
525// is passed from the DAC to the DI in response to a request for class info.
526// This type is also used by CordbClass and CordbType to hold the list of fields for the
527// class.
528class MSLAYOUT FieldData
529{
530public:
531#ifndef RIGHT_SIDE_COMPILE
532 // initialize various fields of an instance of FieldData from information in a FieldDesc
533 void Initialize(BOOL fIsStatic, BOOL fIsPrimitive, mdFieldDef mdToken);
534#else
535 HRESULT GetFieldSignature(class CordbModule * pModule, /*OUT*/ SigParser * pSigParser);
536#endif
537
538 // clear various fields for a new instance of FieldData
539 void ClearFields();
540
541 // Make sure it's okay to get or set an instance field offset.
542 BOOL OkToGetOrSetInstanceOffset();
543
544 // Make sure it's okay to get or set a static field address.
545 BOOL OkToGetOrSetStaticAddress();
546
547 // If this is an instance field, store its offset
548 void SetInstanceOffset( SIZE_T offset );
549
550 // If this is a "normal" static, store its absolute address
551 void SetStaticAddress( TADDR addr );
552
553 // If this is an instance field, return its offset
554 // Note that this offset is allways a real offset (possibly larger than 22 bits), which isn't
555 // necessarily the same as the overloaded FieldDesc.dwOffset field which can have
556 // some special FIELD_OFFSET tokens.
557 SIZE_T GetInstanceOffset();
558
559 // If this is a "normal" static, get its absolute address
560 // TLS and context-specific statics are "special".
561 TADDR GetStaticAddress();
562
563//
564// Data members
565//
566 mdFieldDef m_fldMetadataToken;
567 // m_fFldStorageAvailable is true whenever the storage for this field is available.
568 // If this is a field that is newly added with EnC and hasn't had any storage
569 // allocated yet, then fldEnCAvailable will be false.
570 BOOL m_fFldStorageAvailable;
571
572 // Bits that specify what type of field this is
573 bool m_fFldIsStatic; // true if static field, false if instance field
574 bool m_fFldIsRVA; // true if static relative to module address
575 bool m_fFldIsTLS; // true if thread-specific static
576 bool m_fFldIsPrimitive; // Only true if this is a value type masquerading as a primitive.
577 bool m_fFldIsCollectibleStatic; // true if this is a static field on a collectible type
578
579private:
580 // The m_fldInstanceOffset and m_pFldStaticAddress are mutually exclusive. Only one is ever set at a time.
581 SIZE_T m_fldInstanceOffset; // The offset of a field within an object instance
582 // For EnC fields, this isn't actually within the object instance,
583 // but has been cooked to still be relative to the beginning of
584 // the object.
585 TADDR m_pFldStaticAddress; // The absolute target address of a static field
586
587 PCCOR_SIGNATURE m_fldSignatureCache; // This is passed across as null. It is a RS-only cache, and SHOULD
588 // NEVER BE ACCESSED DIRECTLY!
589 ULONG m_fldSignatureCacheSize; // This is passed across as 0. It is a RS-only cache, and SHOULD
590 // NEVER BE ACCESSED DIRECTLY!
591public:
592 VMPTR_FieldDesc m_vmFieldDesc;
593
594}; // class FieldData
595
596
597// ClassInfo holds information about a type (class or other structured type), including a list of its fields
598class MSLAYOUT ClassInfo
599{
600public:
601 ClassInfo();
602
603 ~ClassInfo();
604
605 void Clear();
606
607 // Size of object in bytes, for non-generic types. Note: this is NOT valid for constructed value types,
608 // e.g. value type Pair<DateTime,int>. Use CordbType::m_objectSize instead.
609 SIZE_T m_objectSize;
610
611 // list of structs containing information about all the fields in this Class, along with the number of entries
612 // in the list. Does not include inherited fields. DON'T KEEP POINTERS TO ELEMENTS OF m_fieldList AROUND!!
613 // This may be deleted if the class gets EnC'd.
614 DacDbiArrayList<FieldData> m_fieldList;
615}; // class ClassInfo
616
617// EnCHangingFieldInfo holds information describing a field added with Edit And Continue. This data
618// is passed from the DAC to the DI in response to a request for EnC field info.
619class MSLAYOUT EnCHangingFieldInfo
620{
621public:
622 // Init will initialize fields, taking into account whether the field is static or not.
623 void Init(VMPTR_Object pObject,
624 SIZE_T offset,
625 mdFieldDef fieldToken,
626 CorElementType elementType,
627 mdTypeDef metadataToken,
628 VMPTR_DomainFile vmDomainFile);
629
630 DebuggerIPCE_BasicTypeData GetObjectTypeData() const { return m_objectTypeData; };
631 mdFieldDef GetFieldToken() const { return m_fldToken; };
632 VMPTR_Object GetVmObject() const { return m_vmObject; };
633 SIZE_T GetOffsetToVars() const { return m_offsetToVars; };
634
635private:
636 DebuggerIPCE_BasicTypeData m_objectTypeData; // type data for the EnC field
637 VMPTR_Object m_vmObject; // object instance to which the field has been added--if the field is
638 // static, this will be NULL instead of pointing to an instance
639 SIZE_T m_offsetToVars; // offset to the beginning of variable storage in the object
640 mdFieldDef m_fldToken; // metadata token for the added field
641
642}; // EnCHangingFieldInfo
643
644// TypeHandleToExpandedTypeInfo returns different DebuggerIPCE_ExpandedTypeData objects
645// depending on whether the object value that the TypeData corresponds to is
646// boxed or not. Different parts of the API transfer objects in slightly different ways.
647// AllBoxed:
648// For GetAndSendObjectData all values are boxed,
649//
650// OnlyPrimitivesUnboxed:
651// When returning results from FuncEval only "true" structs
652// get boxed, i.e. primitives are unboxed.
653//
654// NoValueTypeBoxing:
655// TypeHandleToExpandedTypeInfo is also used to report type parameters,
656// and in this case none of the types are considered boxed (
657enum AreValueTypesBoxed { NoValueTypeBoxing, OnlyPrimitivesUnboxed, AllBoxed };
658
659// TypeRefData is used for resolving a type reference (see code:CordbModule::ResolveTypeRef and
660// code:DacDbiInterfaceImpl::ResolveTypeReference) to store relevant information about the type
661typedef struct MSLAYOUT
662{
663 // domain file for the type
664 VMPTR_DomainFile vmDomainFile;
665 // metadata token for the type. This may be a typeRef (for requests) or a typeDef (for responses).
666 mdToken typeToken;
667} TypeRefData;
668
669// @dbgtodo Microsoft inspection: get rid of IPCE type.
670// TypeInfoList encapsulates a list of type data instances and the length of the list.
671typedef DacDbiArrayList<DebuggerIPCE_TypeArgData> TypeInfoList;
672
673// ArgInfoList encapsulates a list of type data instances for arguments for a top-level
674// type and the length of the list.
675typedef DacDbiArrayList<DebuggerIPCE_BasicTypeData> ArgInfoList;
676
677// TypeParamsList encapsulate a list of type parameters and the length of the list
678typedef DacDbiArrayList<DebuggerIPCE_ExpandedTypeData> TypeParamsList;
679
680// A struct for passing version information from DBI to DAC.
681// See code:CordbProcess::CordbProcess#DBIVersionChecking for more information.
682const DWORD kCurrentDacDbiProtocolBreakingChangeCounter = 1;
683
684struct DbiVersion
685{
686 DWORD m_dwFormat; // the format of this DbiVersion instance
687 DWORD m_dwDbiVersionMS; // version of the DBI DLL, in the convention used by VS_FIXEDFILEINFO
688 DWORD m_dwDbiVersionLS;
689 DWORD m_dwProtocolBreakingChangeCounter; // initially this was reserved and always set to 0
690 // Now we use it as a counter to explicitly introduce breaking changes
691 // between DBI and DAC when we have our IPC transport in the middle
692 // If DBI and DAC don't agree on the same value CheckDbiVersion will return CORDBG_E_INCOMPATIBLE_PROTOCOL
693 // Please document every time this value changes
694 // 0 - initial value
695 // 1 - Indicates that the protocol now supports the GetRemoteInterfaceHashAndTimestamp message
696 // The message must have ID 2, with signature:
697 // OUT DWORD & hash1, OUT DWORD & hash2, OUT DWORD & hash3, OUT DWORD & hash4, OUT DWORD & timestamp1, OUT DWORD & timestamp2
698 // The hash can be used as an indicator of many other breaking changes providing
699 // easier automated enforcement during development. It is NOT recommended to use
700 // the hash as a release versioning mechanism however.
701 DWORD m_dwReservedMustBeZero1; // reserved for future use
702};
703
704// The way in which a thread is blocking on an object
705enum DacBlockingReason
706{
707 DacBlockReason_MonitorCriticalSection,
708 DacBlockReason_MonitorEvent
709};
710
711// Information about an object which is blocking a managed thread
712struct DacBlockingObject
713{
714 VMPTR_Object vmBlockingObject;
715 VMPTR_AppDomain vmAppDomain;
716 DWORD dwTimeout;
717 DacBlockingReason blockingReason;
718};
719
720// Opaque user defined data used in callbacks
721typedef void* CALLBACK_DATA;
722
723struct MonitorLockInfo
724{
725 VMPTR_Thread lockOwner;
726 DWORD acquisitionCount;
727};
728
729struct MSLAYOUT DacGcReference
730{
731 VMPTR_AppDomain vmDomain; // The AppDomain of the handle/object, may be null.
732 union
733 {
734 CORDB_ADDRESS pObject; // A managed object, with the low bit set.
735 VMPTR_OBJECTHANDLE objHnd; // A reference to the object, valid if (pAddress & 1) == 0
736 };
737 DWORD dwType; // Where the root came from.
738
739 /*
740 DependentSource - for HandleDependent
741 RefCount - for HandleStrongRefCount
742 Size - for HandleSizedByref
743 */
744 UINT64 i64ExtraData;
745}; // struct DacGcReference
746
747struct MSLAYOUT DacExceptionCallStackData
748{
749 VMPTR_AppDomain vmAppDomain;
750 VMPTR_DomainFile vmDomainFile;
751 CORDB_ADDRESS ip;
752 mdMethodDef methodDef;
753 BOOL isLastForeignExceptionFrame;
754};
755
756// These represent the various states a SharedReJitInfo can be in.
757enum DacSharedReJitInfoState
758{
759 // The profiler has requested a ReJit, so we've allocated stuff, but we haven't
760 // called back to the profiler to get any info or indicate that the ReJit has
761 // started. (This Info can be 'reused' for a new ReJit if the
762 // profiler calls RequestReJit again before we transition to the next state.)
763 kStateRequested = 0x00000000,
764
765 // We have asked the profiler about this method via ICorProfilerFunctionControl,
766 // and have thus stored the IL and codegen flags the profiler specified. Can only
767 // transition to kStateReverted from this state.
768 kStateActive = 0x00000001,
769
770 // The methoddef has been reverted, but not freed yet. It (or its instantiations
771 // for generics) *MAY* still be active on the stack someplace or have outstanding
772 // memory references.
773 kStateReverted = 0x00000002,
774
775
776 kStateMask = 0x0000000F,
777};
778
779struct MSLAYOUT DacSharedReJitInfo
780{
781 DWORD m_state;
782 CORDB_ADDRESS m_pbIL;
783 DWORD m_dwCodegenFlags;
784 ULONG m_cInstrumentedMapEntries;
785 CORDB_ADDRESS m_rgInstrumentedMapEntries;
786};
787
788#include "dacdbistructures.inl"
789#endif // DACDBISTRUCTURES_H_
790