2 // Copyright (c) Microsoft. All rights reserved.
3 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
5 //*****************************************************************************
10 // Support for external access of runtime data structures. These
11 // macros and templates hide the details of pointer and data handling
12 // so that data structures and code can be compiled to work both
13 // in-process and through a special memory access layer.
15 // This code assumes the existence of two different pieces of code,
16 // the target, the runtime code that is going to be examined, and
17 // the host, the code that's doing the examining. Access to the
18 // target is abstracted so the target may be a live process on the
19 // same machine, a live process on a different machine, a dump file
20 // or whatever. No assumptions should be made about accessibility
23 // This code assumes that the data in the target is static. Any
24 // time the target's data changes the interfaces must be reset so
25 // that potentially stale data is discarded.
27 // This code is intended for read access and there is no
28 // way to write data back currently.
31 // - is read-only (non-invasive). So DACized codepaths can not trigger a GC.
32 // - has no Thread* object. In reality, DAC-ized codepaths are
33 // ReadProcessMemory calls from out-of-process. Conceptually, they
34 // are like a pure-native (preemptive) thread.
36 // This means that in particular, you cannot DACize a GCTRIGGERS function.
37 // Neither can you DACize a function that throws if this will involve
38 // allocating a new exception object. There may be
39 // exceptions to these rules if you can guarantee that the DACized
40 // part of the code path cannot cause a garbage collection (see
41 // EditAndContinueModule::ResolveField for an example).
42 // If you need to DACize a function that may trigger
43 // a GC, it is probably best to refactor the function so that the DACized
44 // part of the code path is in a separate function. For instance,
45 // functions with GetOrCreate() semantics are hard to DAC-ize because
46 // they the Create portion is inherently invasive. Instead, consider refactoring
47 // into a GetOrFail() function that DAC can call; and then make GetOrCreate()
48 // a wrapper around that.
51 // This code works by hiding the details of access to target memory.
52 // Access is divided into two types:
53 // 1. DPTR - access to a piece of data.
54 // 2. VPTR - access to a class with a vtable. The class can only have
55 // a single vtable pointer at the beginning of the class instance.
56 // Things only need to be declared as VPTRs when it is necessary to
57 // call virtual functions in the host. In that case the access layer
58 // must do extra work to provide a host vtable for the object when
59 // it is retrieved so that virtual functions can be called.
61 // When compiling with DACCESS_COMPILE the macros turn into templates
62 // which replace pointers with smart pointers that know how to fetch
63 // data from the target process and provide a host process version of it.
64 // Normal data structure access will transparently receive a host copy
65 // of the data and proceed, so code such as
66 // typedef DPTR(Class) PTR_Class;
68 // int val = cls->m_Int;
69 // will work without modification. The appropriate operators are overloaded
70 // to provide transparent access, such as the -> operator in this case.
71 // Note that the convention is to create an appropriate typedef for
72 // each type that will be accessed. This hides the particular details
73 // of the type declaration and makes the usage look more like regular code.
75 // The ?PTR classes also have an implicit base type cast operator to
76 // produce a host-pointer instance of the given type. For example
77 // Class* cls = PTR_Class(addr);
78 // works by implicit conversion from the PTR_Class created by wrapping
79 // to a host-side Class instance. Again, this means that existing code
80 // can work without modification.
84 // typedef struct _rangesection
86 // PTR_IJitManager pjit;
87 // PTR_RangeSection pright;
88 // PTR_RangeSection pleft;
89 // ... Other fields omitted ...
92 // RangeSection* pRS = m_RangeTree;
94 // while (pRS != NULL)
96 // if (currentPC < pRS->LowAddress)
98 // else if (currentPC > pRS->HighAddress)
106 // This code does not require any modifications. The global reference
107 // provided by m_RangeTree will be a host version of the RangeSection
108 // instantiated by conversion. The references to pRS->pleft and
109 // pRS->pright will refer to DPTRs due to the modified declaration.
110 // In the assignment statement the compiler will automatically use
111 // the implicit conversion from PTR_RangeSection to RangeSection*,
112 // causing a host instance to be created. Finally, if an appropriate
113 // section is found the use of pRS->pjit will cause an implicit
114 // conversion from PTR_IJitManager to IJitManager. The VPTR code
115 // will look at target memory to determine the actual derived class
116 // for the JitManager and instantiate the right class in the host so
117 // that host virtual functions can be used just as they would in
120 // There are situations where code modifications are required, though.
122 // 1. Any time the actual value of an address matters, such as using
123 // it as a search key in a tree, the target address must be used.
125 // An example of this is the RangeSection tree used to locate JIT
126 // managers. A portion of this code is shown above. Each
127 // RangeSection node in the tree describes a range of addresses
128 // managed by the JitMan. These addresses are just being used as
129 // values, not to dereference through, so there are not DPTRs. When
130 // searching the range tree for an address the address used in the
131 // search must be a target address as that's what values are kept in
132 // the RangeSections. In the code shown above, currentPC must be a
133 // target address as the RangeSections in the tree are all target
134 // addresses. Use dac_cast<TADDR> to retrieve the target address
135 // of a ?PTR, as well as to convert a host address to the
136 // target address used to retrieve that particular instance. Do not
137 // use dac_cast with any raw target pointer types (such as BYTE*).
139 // 2. Any time an address is modified, such as by address arithmetic,
140 // the arithmetic must be performed on the target address.
142 // When a host instance is created it is created for the type in use.
143 // There is no particular relation to any other instance, so address
144 // arithmetic cannot be used to get from one instance to any other
145 // part of memory. For example
146 // char* Func(Class* cls)
148 // // String follows the basic Class data.
149 // return (char*)(cls + 1);
151 // does not work with external access because the Class* used would
152 // have retrieved only a Class worth of data. There is no string
153 // following the host instance. Instead, this code should use
154 // dac_cast<TADDR> to get the target address of the Class
155 // instance, add sizeof(*cls) and then create a new ?PTR to access
156 // the desired data. Note that the newly retrieved data will not
157 // be contiguous with the Class instance, so address arithmetic
158 // will still not work.
162 // BOOL IsTarget(LPVOID ip)
164 // StubCallInstrs* pStubCallInstrs = GetStubCallInstrs();
166 // if (ip == (LPVOID) &(pStubCallInstrs->m_op))
173 // BOOL IsTarget(LPVOID ip)
175 // StubCallInstrs* pStubCallInstrs = GetStubCallInstrs();
177 // if ((TADDR)ip == dac_cast<TADDR>(pStubCallInstrs) +
178 // (TADDR)offsetof(StubCallInstrs, m_op))
183 // The parameter ip is a target address, so the host pStubCallInstrs
184 // cannot be used to derive an address from. The member & reference
185 // has to be replaced with a conversion from host to target address
186 // followed by explicit offsetting for the field.
188 // PTR_HOST_MEMBER_TADDR is a convenience macro that encapsulates
189 // these two operations, so the above code could also be:
192 // PTR_HOST_MEMBER_TADDR(StubCallInstrs, pStubCallInstrs, m_op))
194 // 3. Any time the amount of memory referenced through an address
195 // changes, such as by casting to a different type, a new ?PTR
198 // Host instances are created and stored based on both the target
199 // address and size of access. The access code has no way of knowing
200 // all possible ways that data will be retrieved for a given address
201 // so if code changes the way it accesses through an address a new
202 // ?PTR must be used, which may lead to a difference instance and
203 // different host address. This means that pointer identity does not hold
204 // across casts, so code like
205 // Class* cls = PTR_Class(addr);
206 // Class2* cls2 = PTR_Class2(addr);
207 // return cls == cls2;
208 // will fail because the host-side instances have no relation to each
209 // other. That isn't a problem, since by rule #1 you shouldn't be
210 // relying on specific host address values.
214 // return (ArrayClass *) m_pMethTab->GetClass();
218 // return PTR_ArrayClass(m_pMethTab->GetClass());
220 // The ?PTR templates have an implicit conversion from a host pointer
221 // to a target address, so the cast above constructs a new
222 // PTR_ArrayClass by implicitly converting the host pointer result
223 // from GetClass() to its target address and using that as the address
224 // of the new PTR_ArrayClass. As mentioned, the actual host-side
225 // pointer values may not be the same.
227 // Host pointer identity can be assumed as long as the type of access
228 // is the same. In the example above, if both accesses were of type
229 // Class then the host pointer will be the same, so it is safe to
230 // retrieve the target address of an instance and then later get
231 // a new host pointer for the target address using the same type as
232 // the host pointer in that case will be the same. This is enabled
233 // by caching all of the retrieved host instances. This cache is searched
234 // by the addr:size pair and when there's a match the existing instance
235 // is reused. This increases performance and also allows simple
236 // pointer identity to hold. It does mean that host memory grows
237 // in proportion to the amount of target memory being referenced,
238 // so retrieving extraneous data should be avoided.
239 // The host-side data cache grows until the Flush() method is called,
240 // at which point all host-side data is discarded. No host
241 // instance pointers should be held across a Flush().
243 // Accessing into an object can lead to some unusual behavior. For
244 // example, the SList class relies on objects to contain an SLink
245 // instance that it uses for list maintenance. This SLink can be
246 // embedded anywhere in the larger object. The SList access is always
247 // purely to an SLink, so when using the access layer it will only
248 // retrieve an SLink's worth of data. The SList template will then
249 // do some address arithmetic to determine the start of the real
250 // object and cast the resulting pointer to the final object type.
251 // When using the access layer this results in a new ?PTR being
252 // created and used, so a new instance will result. The internal
253 // SLink instance will have no relation to the new object instance
254 // even though in target address terms one is embedded in the other.
255 // The assumption of data stability means that this won't cause
256 // a problem, but care must be taken with the address arithmetic,
257 // as layed out in rules #2 and #3.
259 // 4. Global address references cannot be used. Any reference to a
260 // global piece of code or data, such as a function address, global
261 // variable or class static variable, must be changed.
263 // The external access code may load at a different base address than
264 // the target process code. Global addresses are therefore not
265 // meaningful and must be replaced with something else. There isn't
266 // a single solution, so replacements must be done on a case-by-case
269 // The simplest case is a global or class static variable. All
270 // declarations must be replaced with a special declaration that
271 // compiles into a modified accessor template value when compiled for
272 // external data access. Uses of the variable automatically are fixed
273 // up by the template instance. Note that assignment to the global
274 // must be independently ifdef'ed as the external access layer should
275 // not make any modifications.
277 // Macros allow for simple declaration of a class static and global
278 // values that compile into an appropriate templated value.
282 // static RangeSection* m_RangeTree;
283 // RangeSection* ExecutionManager::m_RangeTree;
285 // extern ThreadStore* g_pThreadStore;
286 // ThreadStore* g_pThreadStore = &StaticStore;
287 // class SystemDomain : public BaseDomain {
289 // ArrayListStatic m_appDomainIndexList;
293 // SystemDomain::m_appDomainIndexList;
295 // extern DWORD gThreadTLSIndex;
297 // DWORD gThreadTLSIndex = TLS_OUT_OF_INDEXES;
301 // typedef DPTR(RangeSection) PTR_RangeSection;
302 // SPTR_DECL(RangeSection, m_RangeTree);
303 // SPTR_IMPL(RangeSection, ExecutionManager, m_RangeTree);
305 // typedef DPTR(ThreadStore) PTR_ThreadStore
306 // GPTR_DECL(ThreadStore, g_pThreadStore);
307 // GPTR_IMPL_INIT(ThreadStore, g_pThreadStore, &StaticStore);
309 // class SystemDomain : public BaseDomain {
311 // SVAL_DECL(ArrayListStatic; m_appDomainIndexList);
315 // SVAL_IMPL(ArrayListStatic, SystemDomain, m_appDomainIndexList);
317 // GVAL_DECL(DWORD, gThreadTLSIndex);
319 // GVAL_IMPL_INIT(DWORD, gThreadTLSIndex, TLS_OUT_OF_INDEXES);
321 // When declaring the variable, the first argument declares the
322 // variable's type and the second argument declares the variable's
323 // name. When defining the variable the arguments are similar, with
324 // an extra class name parameter for the static class variable case.
325 // If an initializer is needed the IMPL_INIT macro should be used.
327 // Things get slightly more complicated when declaring an embedded
328 // array. In this case the data element is not a single element and
329 // therefore cannot be represented by a ?PTR. In the case of a global
330 // array, you should use the GARY_DECL and GARY_IMPL macros.
331 // We durrently have no support for declaring static array data members
332 // or initialized arrays. Array data members that are dynamically allocated
333 // need to be treated as pointer members. To reference individual elements
334 // you must use pointer arithmetic (see rule 2 above). An array declared
335 // as a local variable within a function does not need to be DACized.
338 // All uses of ?VAL_DECL must have a corresponding entry given in the
339 // DacGlobals structure in src\inc\dacvars.h. For SVAL_DECL the entry
340 // is class__name. For GVAL_DECL the entry is dac__name. You must add
341 // these entries in dacvars.h using the DEFINE_DACVAR macro. Note that
342 // these entries also are used for dumping memory in mini dumps and
343 // heap dumps. If it's not appropriate to dump a variable, (e.g.,
344 // it's an array or some other value that is not important to have
345 // in a minidump) a second macro, DEFINE_DACVAR_NO_DUMP, will allow
346 // you to make the required entry in the DacGlobals structure without
347 // dumping its value.
349 // For convenience, here is a list of the various variable declaration and
350 // initialization macros:
351 // SVAL_DECL(type, name) static non-pointer data class MyClass
352 // member declared within {
353 // the class declaration // static int i;
354 // SVAL_DECL(int, i);
357 // SVAL_IMPL(type, cls, name) static non-pointer data // int MyClass::i;
358 // member defined outside SVAL_IMPL(int, MyClass, i);
359 // the class declaration
361 // SVAL_IMPL_INIT(type, cls, static non-pointer data // int MyClass::i = 0;
362 // name, val) member defined and SVAL_IMPL_INIT(int, MyClass, i, 0);
363 // initialized outside the
365 // ------------------------------------------------------------------------------------------------
366 // SPTR_DECL(type, name) static pointer data class MyClass
367 // member declared within {
368 // the class declaration // static int * pInt;
369 // SPTR_DECL(int, pInt);
372 // SPTR_IMPL(type, cls, name) static pointer data // int * MyClass::pInt;
373 // member defined outside SPTR_IMPL(int, MyClass, pInt);
374 // the class declaration
376 // SPTR_IMPL_INIT(type, cls, static pointer data // int * MyClass::pInt = NULL;
377 // name, val) member defined and SPTR_IMPL_INIT(int, MyClass, pInt, NULL);
378 // initialized outside the
380 // ------------------------------------------------------------------------------------------------
381 // GVAL_DECL(type, name) extern declaration of // extern int g_i
382 // global non-pointer GVAL_DECL(int, g_i);
385 // GVAL_IMPL(type, name) declaration of a // int g_i
386 // global non-pointer GVAL_IMPL(int, g_i);
389 // GVAL_IMPL_INIT (type, declaration and // int g_i = 0;
390 // name, initialization of a GVAL_IMPL_INIT(int, g_i, 0);
391 // val) global non-pointer
394 // If you use GVAL_? to declare a global variable of a structured type and you need to
395 // access a member of the type, you cannot use the dot operator. Instead, you must take the
396 // address of the variable and use the arrow operator. For example:
402 // GVAL_IMPL(MyStruct, g_myStruct);
403 // int i = (&g_myStruct)->x;
404 // ------------------------------------------------------------------------------------------------
405 // GPTR_DECL(type, name) extern declaration of // extern int * g_pInt
406 // global pointer GPTR_DECL(int, g_pInt);
409 // GPTR_IMPL(type, name) declaration of a // int * g_pInt
410 // global pointer GPTR_IMPL(int, g_pInt);
413 // GPTR_IMPL_INIT (type, declaration and // int * g_pInt = 0;
414 // name, initialization of a GPTR_IMPL_INIT(int, g_pInt, NULL);
415 // val) global pointer
417 // ------------------------------------------------------------------------------------------------
418 // GARY_DECL(type, name) extern declaration of // extern int g_rgIntList[MAX_ELEMENTS];
419 // a global array GPTR_DECL(int, g_rgIntList, MAX_ELEMENTS);
422 // GARY_IMPL(type, name) declaration of a // int g_rgIntList[MAX_ELEMENTS];
423 // global pointer GPTR_IMPL(int, g_rgIntList, MAX_ELEMENTS);
427 // Certain pieces of code, such as the stack walker, rely on identifying
428 // an object from its vtable address. As the target vtable addresses
429 // do not necessarily correspond to the vtables used in the host, these
430 // references must be translated. The access layer maintains translation
431 // tables for all classes used with VPTR and can return the target
432 // vtable pointer for any host vtable in the known list of VPTR classes.
436 // All errors in the access layer are reported via exceptions. The
437 // formal access layer methods catch all such exceptions and turn
438 // them into the appropriate error, so this generally isn't visible
439 // to users of the access layer.
441 // ----- DPTR Declaration:
443 // Create a typedef for the type with typedef DPTR(type) PTR_type;
444 // Replace type* with PTR_type.
446 // ----- VPTR Declaration:
448 // VPTR can only be used on classes that have a single vtable
449 // pointer at the beginning of the object. This should be true
450 // for a normal single-inheritance object.
452 // All of the classes that may be instantiated need to be identified
453 // and marked. In the base class declaration add either
454 // VPTR_BASE_VTABLE_CLASS if the class is abstract or
455 // VPTR_BASE_CONCRETE_VTABLE_CLASS if the class is concrete. In each
456 // derived class add VPTR_VTABLE_CLASS. If you end up with compile or
457 // link errors for an unresolved method called VPtrSize you missed a
458 // derived class declaration.
460 // As described above, dac can only handle classes with a single
461 // vtable. However, there's a special case for multiple inheritance
462 // situations when only one of the classes is needed for dac. If
463 // the base class needed is the first class in the derived class's
464 // layout then it can be used with dac via using the VPTR_MULTI_CLASS
465 // macros. Use with extreme care.
467 // All classes to be instantiated must be listed in src\inc\vptr_list.h.
469 // Create a typedef for the type with typedef VPTR(type) PTR_type;
470 // When using a VPTR, replace Class* with PTR_Class.
472 // ----- Specific Macros:
475 // Retrieves the raw target address for a ?PTR.
476 // See code:dac_cast for the preferred alternative
478 // PTR_HOST_TO_TADDR(host)
479 // Given a host address of an instance produced by a ?PTR reference,
480 // return the original target address. The host address must
481 // be an exact match for an instance.
482 // See code:dac_cast for the preferred alternative
484 // PTR_HOST_INT_TO_TADDR(host)
485 // Given a host address which resides somewhere within an instance
486 // produced by a ?PTR reference (a host interior pointer) return the
487 // corresponding target address. This is useful for evaluating
488 // relative pointers (e.g. RelativePointer<T>) where calculating the
489 // target address requires knowledge of the target address of the
490 // relative pointer field itself. This lookup is slower than that for
491 // a non-interior host pointer so use it sparingly.
493 // VPTR_HOST_VTABLE_TO_TADDR(host)
494 // Given the host vtable pointer for a known VPTR class, return
495 // the target vtable pointer.
497 // PTR_HOST_MEMBER_TADDR(type, host, memb)
498 // Retrieves the target address of a host instance pointer and
499 // offsets it by the given member's offset within the type.
501 // PTR_HOST_INT_MEMBER_TADDR(type, host, memb)
502 // As above but will work for interior host pointers (see the
503 // description of PTR_HOST_INT_TO_TADDR for an explanation of host
504 // interior pointers).
506 // PTR_READ(addr, size)
507 // Reads a block of memory from the target and returns a host
508 // pointer for it. Useful for reading blocks of data from the target
509 // whose size is only known at runtime, such as raw code for a jitted
510 // method. If the data being read is actually an object, use SPTR
511 // instead to get better type semantics.
515 // DAC_EMPTY_RET(retVal)
517 // Provides an empty method implementation when compiled
518 // for DACCESS_COMPILE. For example, use to stub out methods needed
519 // for vtable entries but otherwise unused.
521 // These macros are designed to turn into normal code when compiled
522 // without DACCESS_COMPILE.
524 //*****************************************************************************
527 #ifndef __daccess_h__
528 #define __daccess_h__
530 #include "switches.h"
531 #include "safemath.h"
532 #include "corerror.h"
535 #include <specstrings.h>
538 #define DACCESS_TABLE_RESOURCE "COREXTERNALDATAACCESSRESOURCE"
540 #include "clr_std/type_traits"
541 #include "crosscomp.h"
543 // Information stored in the DAC table of interest to the DAC implementation
544 // Note that this information is shared between all instantiations of ClrDataAccess, so initialize
545 // it just once in code:ClrDataAccess.GetDacGlobals (rather than use fields in ClrDataAccess);
548 // On Windows, the first DWORD is the 32-bit timestamp read out of the runtime dll's debug directory.
549 // The remaining 3 DWORDS must all be 0.
550 // On Mac, this is the 16-byte UUID of the runtime dll.
551 // It is used to validate that mscorwks is the same version as mscordacwks
558 // The header of the DAC table. This includes the number of globals, the number of vptrs, and
559 // the DacTableInfo structure. We need the DacTableInfo and DacTableHeader structs outside
560 // of a DACCESS_COMPILE since soshost walks the Dac table headers to find the UUID of CoreCLR
561 // in the target process.
562 struct DacTableHeader
570 // This version of things wraps pointer access in
571 // templates which understand how to retrieve data
572 // through an access layer. In this case no assumptions
573 // can be made that the current compilation processor or
574 // pointer types match the target's processor or pointer types.
577 // Define TADDR as a non-pointer value so use of it as a pointer
578 // will not work properly. Define it as unsigned so
579 // pointer comparisons aren't affected by sign.
580 // This requires special casting to ULONG64 to sign-extend if necessary.
581 typedef ULONG_PTR TADDR;
583 // TSIZE_T used for counts or ranges that need to span the size of a
584 // target pointer. For cross-plat, this may be different than SIZE_T
585 // which reflects the host pointer size.
586 typedef SIZE_T TSIZE_T;
590 // The following table contains all the global information that data access needs to begin
591 // operation. All of the values stored here are RVAs. DacGlobalBase() returns the current
592 // base address to combine with to get a full target address.
595 typedef struct _DacGlobals
598 static void Initialize();
599 void InitializeEntries(TADDR baseAddress);
600 #ifdef FEATURE_SVR_GC
601 void InitializeSVREntries(TADDR baseAddress);
602 #endif // FEATURE_SVR_GC
603 #endif // FEATURE_PAL
605 // These will define all of the dac related mscorwks static and global variables
606 #define DEFINE_DACVAR(id_type, size, id, var) id_type id;
607 #define DEFINE_DACVAR_SVR(id_type, size, id, var) id_type id;
608 #define DEFINE_DACVAR_NO_DUMP(id_type, size, id, var) id_type id;
612 ULONG fn__ThreadpoolMgr__AsyncTimerCallbackCompletion;
613 ULONG fn__DACNotifyCompilationFinished;
614 ULONG fn__ThePreStub;
615 ULONG fn__ThePreStubPatchLabel;
616 ULONG fn__PrecodeFixupThunk;
617 ULONG fn__StubDispatchFixupStub;
618 ULONG fn__StubDispatchFixupPatchLabel;;
619 #ifdef FEATURE_COMINTEROP
620 ULONG fn__Unknown_AddRef;
621 ULONG fn__Unknown_AddRefSpecial;
622 ULONG fn__Unknown_AddRefInner;
625 // Vtable pointer values for all classes that must
626 // be instanted using vtable pointers as the identity.
627 #define VPTR_CLASS(name) ULONG name##__vtAddr;
628 #define VPTR_MULTI_CLASS(name, keyBase) ULONG name##__##keyBase##__mvtAddr;
629 #include <vptr_list.h>
631 #undef VPTR_MULTI_CLASS
634 #ifdef DACCESS_COMPILE
636 extern DacTableInfo g_dacTableInfo;
637 extern DacGlobals g_dacGlobals;
643 // These two functions are largely just for marking code
644 // that is not fully converted. DacWarning prints a debug
645 // message, while DacNotImpl throws a not-implemented exception.
646 void __cdecl DacWarning(__in __in_z char* format, ...);
647 void DacNotImpl(void);
649 void DacError(HRESULT err);
650 void DECLSPEC_NORETURN DacError_NoRet(HRESULT err);
651 TADDR DacGlobalBase(void);
652 HRESULT DacReadAll(TADDR addr, PVOID buffer, ULONG32 size, bool throwEx);
653 HRESULT DacWriteAll(TADDR addr, PVOID buffer, ULONG32 size, bool throwEx);
654 HRESULT DacAllocVirtual(TADDR addr, ULONG32 size,
655 ULONG32 typeFlags, ULONG32 protectFlags,
656 bool throwEx, TADDR* mem);
657 HRESULT DacFreeVirtual(TADDR mem, ULONG32 size, ULONG32 typeFlags,
659 PVOID DacInstantiateTypeByAddress(TADDR addr, ULONG32 size, bool throwEx);
660 PVOID DacInstantiateTypeByAddressNoReport(TADDR addr, ULONG32 size, bool throwEx);
661 PVOID DacInstantiateClassByVTable(TADDR addr, ULONG32 minSize, bool throwEx);
663 // Copy a null-terminated ascii or unicode string from the target to the host.
664 // Note that most of the work here is to find the null terminator. If you know the exact length,
665 // then you can also just call DacInstantiateTypebyAddress.
666 PSTR DacInstantiateStringA(TADDR addr, ULONG32 maxChars, bool throwEx);
667 PWSTR DacInstantiateStringW(TADDR addr, ULONG32 maxChars, bool throwEx);
669 TADDR DacGetTargetAddrForHostAddr(LPCVOID ptr, bool throwEx);
670 TADDR DacGetTargetAddrForHostInteriorAddr(LPCVOID ptr, bool throwEx);
671 TADDR DacGetTargetVtForHostVt(LPCVOID vtHost, bool throwEx);
672 PWSTR DacGetVtNameW(TADDR targetVtable);
674 // Report a region of memory to the debugger
675 bool DacEnumMemoryRegion(TADDR addr, TSIZE_T size, bool fExpectSuccess = true);
677 // Report a region of memory to the debugger
678 bool DacUpdateMemoryRegion(TADDR addr, TSIZE_T bufferSize, BYTE* buffer);
680 HRESULT DacWriteHostInstance(PVOID host, bool throwEx);
682 // This is meant to mimic the RethrowTerminalExceptions/
683 // SwallowAllExceptions/RethrowTransientExceptions macros to allow minidump
684 // gathering cancelation for details see
685 // code:ClrDataAccess.EnumMemoryRegionsWrapper
687 // This is usable in EX_TRY exactly how RethrowTerminalExceptions et cetera
688 #define RethrowCancelExceptions \
689 if (GET_EXCEPTION()->GetHR() == COR_E_OPERATIONCANCELED) \
694 // Occasionally it's necessary to allocate some host memory for
695 // instance data that's created on the fly and so doesn't directly
696 // correspond to target memory. These are held and freed on flush
697 // like other instances but can't be looked up by address.
698 PVOID DacAllocHostOnlyInstance(ULONG32 size, bool throwEx);
700 // Determines whether ASSERTs should be raised when inconsistencies in the target are detected
701 bool DacTargetConsistencyAssertsEnabled();
703 // Host instances can be marked as they are enumerated in
704 // order to break cycles. This function returns true if
705 // the instance is already marked, otherwise it marks the
706 // instance and returns false.
707 bool DacHostPtrHasEnumMark(LPCVOID host);
709 // Determines if EnumMemoryRegions has been called on a method descriptor.
710 // This helps perf for minidumps of apps with large managed stacks.
711 bool DacHasMethodDescBeenEnumerated(LPCVOID pMD);
713 // Sets a flag indicating that EnumMemoryRegions on a method desciptor
714 // has been successfully called. The function returns true if
715 // this flag had been previously set.
716 bool DacSetMethodDescEnumerated(LPCVOID pMD);
718 // Determines if a method descriptor is valid
719 BOOL DacValidateMD(LPCVOID pMD);
721 // Enumerate the instructions around a call site to help debugger stack walking heuristics
722 void DacEnumCodeForStackwalk(TADDR taCallEnd);
724 // Given the address and the size of a memory range which is stored in the buffer, replace all the patches
725 // in the buffer with the real opcodes. This is especially important on X64 where the unwinder needs to
726 // disassemble the native instructions.
728 HRESULT DacReplacePatchesInHostMemory(MemoryRange range, PVOID pBuffer);
731 // Convenience macros for EnumMemoryRegions implementations.
734 // Enumerate the given host instance and return
735 // true if the instance hasn't already been enumerated.
736 #define DacEnumHostDPtrMem(host) \
737 (!DacHostPtrHasEnumMark(host) ? \
738 (DacEnumMemoryRegion(PTR_HOST_TO_TADDR(host), sizeof(*host)), \
740 #define DacEnumHostSPtrMem(host, type) \
741 (!DacHostPtrHasEnumMark(host) ? \
742 (DacEnumMemoryRegion(PTR_HOST_TO_TADDR(host), \
743 type::DacSize(PTR_HOST_TO_TADDR(host))), \
745 #define DacEnumHostVPtrMem(host) \
746 (!DacHostPtrHasEnumMark(host) ? \
747 (DacEnumMemoryRegion(PTR_HOST_TO_TADDR(host), (host)->VPtrSize()), \
750 // Check enumeration of 'this' and return if this has already been
751 // enumerated. Making this the first line of an object's EnumMemoryRegions
752 // method will prevent cycles.
753 #define DAC_CHECK_ENUM_THIS() \
754 if (DacHostPtrHasEnumMark(this)) return
755 #define DAC_ENUM_DTHIS() \
756 if (!DacEnumHostDPtrMem(this)) return
757 #define DAC_ENUM_STHIS(type) \
758 if (!DacEnumHostSPtrMem(this, type)) return
759 #define DAC_ENUM_VTHIS() \
760 if (!DacEnumHostVPtrMem(this)) return
764 class ReflectionModule;
765 interface IMDInternalImport* DacGetMDImport(const class PEFile* peFile,
767 interface IMDInternalImport* DacGetMDImport(const ReflectionModule* reflectionModule,
770 int DacGetIlMethodSize(TADDR methAddr);
771 struct COR_ILMETHOD* DacGetIlMethod(TADDR methAddr);
772 #if defined(WIN64EXCEPTIONS)
773 struct _UNWIND_INFO * DacGetUnwindInfo(TADDR taUnwindInfo);
775 // virtually unwind a CONTEXT out-of-process
776 struct _KNONVOLATILE_CONTEXT_POINTERS;
777 BOOL DacUnwindStackFrame(T_CONTEXT * pContext, T_KNONVOLATILE_CONTEXT_POINTERS* pContextPointers);
780 #ifdef FEATURE_MINIMETADATA_IN_TRIAGEDUMPS
782 void DacMdCacheAddEEName(TADDR taEE, const SString& ssEEName);
783 bool DacMdCacheGetEEName(TADDR taEE, SString & ssEEName);
784 #endif // FEATURE_MINIMETADATA_IN_TRIAGEDUMPS
787 // Computes (taBase + (dwIndex * dwElementSize()), with overflow checks.
790 // taBase the base TADDR value
791 // dwIndex the index of the offset
792 // dwElementSize the size of each element (to multiply the offset by)
795 // The resulting TADDR, or throws CORDB_E_TARGET_INCONSISTENT on overlow.
798 // The idea here is that overflows during address arithmetic suggest that we're operating on corrupt
799 // pointers. It helps to improve reliability to detect the cases we can (like overflow) and fail. Note
800 // that this is just a heuristic, not a security measure. We can't trust target data regardless -
801 // failing on overflow is just one easy case of corruption to detect. There is no need to use checked
802 // arithmetic everywhere in the DAC infrastructure, this is intended just for the places most likely to
803 // help catch bugs (eg. __DPtr::operator[]).
805 inline TADDR DacTAddrOffset( TADDR taBase, TSIZE_T dwIndex, TSIZE_T dwElementSize )
807 ClrSafeInt<TADDR> t(taBase);
808 t += ClrSafeInt<TSIZE_T>(dwIndex) * ClrSafeInt<TSIZE_T>(dwElementSize);
811 // Pointer arithmetic overflow - probably due to corrupt target data
812 DacError(CORDBG_E_TARGET_INCONSISTENT);
818 // Base pointer wrapper which provides common behavior.
824 // Make uninitialized pointers obvious.
827 __TPtrBase(TADDR addr)
832 bool operator!() const
836 // We'd like to have an implicit conversion to bool here since the C++
837 // standard says all pointer types are implicitly converted to bool.
838 // Unfortunately, that would cause ambiguous overload errors for uses
839 // of operator== and operator!=. Instead callers will have to compare
840 // directly against NULL.
842 bool operator==(TADDR addr) const
844 return m_addr == addr;
846 bool operator!=(TADDR addr) const
848 return m_addr != addr;
850 bool operator<(TADDR addr) const
852 return m_addr < addr;
854 bool operator>(TADDR addr) const
856 return m_addr > addr;
858 bool operator<=(TADDR addr) const
860 return m_addr <= addr;
862 bool operator>=(TADDR addr) const
864 return m_addr >= addr;
867 TADDR GetAddr(void) const
871 TADDR SetAddr(TADDR addr)
881 // Pointer wrapper base class for various forms of normal data.
882 // This has the common functionality between __DPtr and __ArrayDPtr.
883 // The DPtrType type parameter is the actual derived type in use. This is necessary so that
884 // inhereted functions preserve exact return types.
885 template<typename type, typename DPtrType>
886 class __DPtrBase : public __TPtrBase
894 // All protected - this type should not be used directly - use one of the derived types instead.
895 __DPtrBase< type, DPtrType >(void) : __TPtrBase() {}
896 __DPtrBase< type, DPtrType >(TADDR addr) : __TPtrBase(addr) {}
898 explicit __DPtrBase< type, DPtrType >(__TPtrBase addr)
900 m_addr = addr.GetAddr();
902 explicit __DPtrBase< type, DPtrType >(type const * host)
904 m_addr = DacGetTargetAddrForHostAddr(host, true);
908 DPtrType& operator=(const __TPtrBase& ptr)
910 m_addr = ptr.GetAddr();
911 return DPtrType(m_addr);
913 DPtrType& operator=(TADDR addr)
916 return DPtrType(m_addr);
919 type& operator*(void) const
921 return *(type*)DacInstantiateTypeByAddress(m_addr, sizeof(type), true);
924 bool operator==(const DPtrType& ptr) const
926 return m_addr == ptr.GetAddr();
928 bool operator==(TADDR addr) const
930 return m_addr == addr;
932 bool operator!=(const DPtrType& ptr) const
934 return !operator==(ptr);
936 bool operator!=(TADDR addr) const
938 return m_addr != addr;
940 bool operator<(const DPtrType& ptr) const
942 return m_addr < ptr.GetAddr();
944 bool operator>(const DPtrType& ptr) const
946 return m_addr > ptr.GetAddr();
948 bool operator<=(const DPtrType& ptr) const
950 return m_addr <= ptr.GetAddr();
952 bool operator>=(const DPtrType& ptr) const
954 return m_addr >= ptr.GetAddr();
957 // Array index operator
958 // we want an operator[] for all possible numeric types (rather than rely on
959 // implicit numeric conversions on the argument) to prevent ambiguity with
960 // DPtr's implicit conversion to type* and the built-in operator[].
961 // @dbgtodo : we could also use this technique to simplify other operators below.
962 template<typename indexType>
963 type& operator[](indexType index)
965 // Compute the address of the element.
969 elementAddr = DacTAddrOffset(m_addr, index, sizeof(type));
973 // Don't bother trying to do overflow checking for negative indexes - they are rare compared to
974 // positive ones. ClrSafeInt doesn't support signed datatypes yet (although we should be able to add it
976 elementAddr = m_addr + index * sizeof(type);
979 // Marshal over a single instance and return a reference to it.
980 return *(type*) DacInstantiateTypeByAddress(elementAddr, sizeof(type), true);
983 template<typename indexType>
984 type const & operator[](indexType index) const
986 return (*const_cast<__DPtrBase*>(this))[index];
989 //-------------------------------------------------------------------------
992 DPtrType operator+(unsigned short val)
994 return DPtrType(DacTAddrOffset(m_addr, val, sizeof(type)));
996 DPtrType operator+(short val)
998 return DPtrType(m_addr + val * sizeof(type));
1000 // size_t is unsigned int on Win32, so we need
1001 // to ifdef here to make sure the unsigned int
1002 // and size_t overloads don't collide. size_t
1003 // is marked __w64 so a simple unsigned int
1004 // will not work on Win32, it has to be size_t.
1005 DPtrType operator+(size_t val)
1007 return DPtrType(DacTAddrOffset(m_addr, val, sizeof(type)));
1009 #if defined (_WIN64)
1010 DPtrType operator+(unsigned int val)
1012 return DPtrType(DacTAddrOffset(m_addr, val, sizeof(type)));
1015 DPtrType operator+(int val)
1017 return DPtrType(m_addr + val * sizeof(type));
1019 // Because of the size difference between long and int on non MS compilers,
1020 // we only need to define these operators on Windows. These provide compatible
1021 // overloads for DWORD addition operations.
1023 DPtrType operator+(unsigned long val)
1025 return DPtrType(DacTAddrOffset(m_addr, val, sizeof(type)));
1027 DPtrType operator+(long val)
1029 return DPtrType(m_addr + val * sizeof(type));
1033 //-------------------------------------------------------------------------
1036 DPtrType operator-(unsigned short val)
1038 return DPtrType(m_addr - val * sizeof(type));
1040 DPtrType operator-(short val)
1042 return DPtrType(m_addr - val * sizeof(type));
1044 // size_t is unsigned int on Win32, so we need
1045 // to ifdef here to make sure the unsigned int
1046 // and size_t overloads don't collide. size_t
1047 // is marked __w64 so a simple unsigned int
1048 // will not work on Win32, it has to be size_t.
1049 DPtrType operator-(size_t val)
1051 return DPtrType(m_addr - val * sizeof(type));
1054 DPtrType operator-(unsigned int val)
1056 return DPtrType(m_addr - val * sizeof(type));
1059 DPtrType operator-(int val)
1061 return DPtrType(m_addr - val * sizeof(type));
1063 // Because of the size difference between long and int on non MS compilers,
1064 // we only need to define these operators on Windows. These provide compatible
1065 // overloads for DWORD addition operations.
1066 #ifdef _MSC_VER // for now, everything else is 32 bit
1067 DPtrType operator-(unsigned long val)
1069 return DPtrType(m_addr - val * sizeof(type));
1071 DPtrType operator-(long val)
1073 return DPtrType(m_addr - val * sizeof(type));
1076 size_t operator-(const DPtrType& val)
1078 return (m_addr - val.m_addr) / sizeof(type);
1081 //-------------------------------------------------------------------------
1083 DPtrType& operator+=(size_t val)
1085 m_addr += val * sizeof(type);
1086 return static_cast<DPtrType&>(*this);
1088 DPtrType& operator-=(size_t val)
1090 m_addr -= val * sizeof(type);
1091 return static_cast<DPtrType&>(*this);
1094 DPtrType& operator++()
1096 m_addr += sizeof(type);
1097 return static_cast<DPtrType&>(*this);
1099 DPtrType& operator--()
1101 m_addr -= sizeof(type);
1102 return static_cast<DPtrType&>(*this);
1104 DPtrType operator++(int postfix)
1106 DPtrType orig = DPtrType(*this);
1107 m_addr += sizeof(type);
1110 DPtrType operator--(int postfix)
1112 DPtrType orig = DPtrType(*this);
1113 m_addr -= sizeof(type);
1117 bool IsValid(void) const
1120 DacInstantiateTypeByAddress(m_addr, sizeof(type),
1123 void EnumMem(void) const
1125 DacEnumMemoryRegion(m_addr, sizeof(type));
1129 // forward declaration
1130 template<typename acc_type, typename store_type>
1133 // Pointer wrapper for objects which are just plain data
1134 // and need no special handling.
1135 template<typename type>
1136 class __DPtr : public __DPtrBase<type,__DPtr<type> >
1139 // constructors - all chain to __DPtrBase constructors
1140 __DPtr< type >(void) : __DPtrBase<type,__DPtr<type> >() {}
1141 __DPtr< type >(TADDR addr) : __DPtrBase<type,__DPtr<type> >(addr) {}
1143 // construct const from non-const
1144 typedef typename std::remove_const<type>::type mutable_type;
1145 __DPtr< type >(__DPtr<mutable_type> const & rhs) : __DPtrBase<type,__DPtr<type> >(rhs.GetAddr()) {}
1147 // construct from GlobalPtr
1148 explicit __DPtr< type >(__GlobalPtr< type*, __DPtr< type > > globalPtr) :
1149 __DPtrBase<type,__DPtr<type> >(globalPtr.GetAddr()) {}
1151 explicit __DPtr< type >(__TPtrBase addr) : __DPtrBase<type,__DPtr<type> >(addr) {}
1152 explicit __DPtr< type >(type const * host) : __DPtrBase<type,__DPtr<type> >(host) {}
1154 operator type*() const
1156 return (type*)DacInstantiateTypeByAddress(this->m_addr, sizeof(type), true);
1158 type* operator->() const
1160 return (type*)DacInstantiateTypeByAddress(this->m_addr, sizeof(type), true);
1164 #define DPTR(type) __DPtr< type >
1166 // A restricted form of DPtr that doesn't have any conversions to pointer types.
1167 // This is useful for pointer types that almost always represent arrays, as opposed
1168 // to pointers to single instances (eg. PTR_BYTE). In these cases, allowing implicit
1169 // conversions to (for eg.) BYTE* would usually result in incorrect usage (eg. pointer
1170 // arithmetic and array indexing), since only a single instance has been marshalled to the host.
1171 // If you really must marshal a single instance (eg. converting T* to PTR_T is too painful for now),
1172 // then use code:DacUnsafeMarshalSingleElement so we can identify such unsafe code.
1173 template<typename type>
1174 class __ArrayDPtr : public __DPtrBase<type,__ArrayDPtr<type> >
1177 // constructors - all chain to __DPtrBase constructors
1178 __ArrayDPtr< type >(void) : __DPtrBase<type,__ArrayDPtr<type> >() {}
1179 __ArrayDPtr< type >(TADDR addr) : __DPtrBase<type,__ArrayDPtr<type> >(addr) {}
1181 // construct const from non-const
1182 typedef typename std::remove_const<type>::type mutable_type;
1183 __ArrayDPtr< type >(__ArrayDPtr<mutable_type> const & rhs) : __DPtrBase<type,__ArrayDPtr<type> >(rhs.GetAddr()) {}
1185 explicit __ArrayDPtr< type >(__TPtrBase addr) : __DPtrBase<type,__ArrayDPtr<type> >(addr) {}
1187 // Note that there is also no explicit constructor from host instances (type*).
1188 // Going this direction is less problematic, but often still represents risky coding.
1191 #define ArrayDPTR(type) __ArrayDPtr< type >
1194 // Pointer wrapper for objects which are just plain data
1195 // but whose size is not the same as the base type size.
1196 // This can be used for prefetching data for arrays or
1197 // for cases where an object has a variable size.
1198 template<typename type>
1199 class __SPtr : public __TPtrBase
1205 __SPtr< type >(void) : __TPtrBase() {}
1206 __SPtr< type >(TADDR addr) : __TPtrBase(addr) {}
1207 explicit __SPtr< type >(__TPtrBase addr)
1209 m_addr = addr.GetAddr();
1211 explicit __SPtr< type >(type* host)
1213 m_addr = DacGetTargetAddrForHostAddr(host, true);
1216 __SPtr< type >& operator=(const __TPtrBase& ptr)
1218 m_addr = ptr.GetAddr();
1221 __SPtr< type >& operator=(TADDR addr)
1227 operator type*() const
1231 return (type*)DacInstantiateTypeByAddress(m_addr,
1232 type::DacSize(m_addr),
1240 type* operator->() const
1244 return (type*)DacInstantiateTypeByAddress(m_addr,
1245 type::DacSize(m_addr),
1253 type& operator*(void) const
1257 DacError(E_INVALIDARG);
1260 return *(type*)DacInstantiateTypeByAddress(m_addr,
1261 type::DacSize(m_addr),
1265 bool IsValid(void) const
1268 DacInstantiateTypeByAddress(m_addr, type::DacSize(m_addr),
1271 void EnumMem(void) const
1275 DacEnumMemoryRegion(m_addr, type::DacSize(m_addr));
1280 #define SPTR(type) __SPtr< type >
1282 // Pointer wrapper for objects which have a single leading
1283 // vtable, such as objects in a single-inheritance tree.
1284 // The base class of all such trees must have use
1285 // VPTR_BASE_VTABLE_CLASS in their declaration and all
1286 // instantiable members of the tree must be listed in vptr_list.h.
1287 template<class type>
1288 class __VPtr : public __TPtrBase
1291 // VPtr::_Type has to be a pointer as
1292 // often the type is an abstract class.
1293 // This type is not expected to be used anyway.
1294 typedef type* _Type;
1297 __VPtr< type >(void) : __TPtrBase() {}
1298 __VPtr< type >(TADDR addr) : __TPtrBase(addr) {}
1299 explicit __VPtr< type >(__TPtrBase addr)
1301 m_addr = addr.GetAddr();
1303 explicit __VPtr< type >(type* host)
1305 m_addr = DacGetTargetAddrForHostAddr(host, true);
1308 __VPtr< type >& operator=(const __TPtrBase& ptr)
1310 m_addr = ptr.GetAddr();
1313 __VPtr< type >& operator=(TADDR addr)
1319 operator type*() const
1321 return (type*)DacInstantiateClassByVTable(m_addr, sizeof(type), true);
1323 type* operator->() const
1325 return (type*)DacInstantiateClassByVTable(m_addr, sizeof(type), true);
1328 bool operator==(const __VPtr< type >& ptr) const
1330 return m_addr == ptr.m_addr;
1332 bool operator==(TADDR addr) const
1334 return m_addr == addr;
1336 bool operator!=(const __VPtr< type >& ptr) const
1338 return !operator==(ptr);
1340 bool operator!=(TADDR addr) const
1342 return m_addr != addr;
1345 bool IsValid(void) const
1348 DacInstantiateClassByVTable(m_addr, sizeof(type), false) != NULL;
1350 void EnumMem(void) const
1354 DacEnumMemoryRegion(m_addr, (operator->())->VPtrSize());
1359 #define VPTR(type) __VPtr< type >
1361 // Pointer wrapper for 8-bit strings.
1362 template<typename type, ULONG32 maxChars = 32760>
1363 class __Str8Ptr : public __DPtr<char>
1369 __Str8Ptr< type, maxChars >(void) : __DPtr<char>() {}
1370 __Str8Ptr< type, maxChars >(TADDR addr) : __DPtr<char>(addr) {}
1371 explicit __Str8Ptr< type, maxChars >(__TPtrBase addr)
1373 m_addr = addr.GetAddr();
1375 explicit __Str8Ptr< type, maxChars >(type* host)
1377 m_addr = DacGetTargetAddrForHostAddr(host, true);
1380 __Str8Ptr< type, maxChars >& operator=(const __TPtrBase& ptr)
1382 m_addr = ptr.GetAddr();
1385 __Str8Ptr< type, maxChars >& operator=(TADDR addr)
1391 operator type*() const
1393 return (type*)DacInstantiateStringA(m_addr, maxChars, true);
1396 bool IsValid(void) const
1399 DacInstantiateStringA(m_addr, maxChars, false) != NULL;
1401 void EnumMem(void) const
1403 char* str = DacInstantiateStringA(m_addr, maxChars, false);
1406 DacEnumMemoryRegion(m_addr, strlen(str) + 1);
1411 #define S8PTR(type) __Str8Ptr< type >
1412 #define S8PTRMAX(type, maxChars) __Str8Ptr< type, maxChars >
1414 // Pointer wrapper for 16-bit strings.
1415 template<typename type, ULONG32 maxChars = 32760>
1416 class __Str16Ptr : public __DPtr<wchar_t>
1422 __Str16Ptr< type, maxChars >(void) : __DPtr<wchar_t>() {}
1423 __Str16Ptr< type, maxChars >(TADDR addr) : __DPtr<wchar_t>(addr) {}
1424 explicit __Str16Ptr< type, maxChars >(__TPtrBase addr)
1426 m_addr = addr.GetAddr();
1428 explicit __Str16Ptr< type, maxChars >(type* host)
1430 m_addr = DacGetTargetAddrForHostAddr(host, true);
1433 __Str16Ptr< type, maxChars >& operator=(const __TPtrBase& ptr)
1435 m_addr = ptr.GetAddr();
1438 __Str16Ptr< type, maxChars >& operator=(TADDR addr)
1444 operator type*() const
1446 return (type*)DacInstantiateStringW(m_addr, maxChars, true);
1449 bool IsValid(void) const
1452 DacInstantiateStringW(m_addr, maxChars, false) != NULL;
1454 void EnumMem(void) const
1456 char* str = DacInstantiateStringW(m_addr, maxChars, false);
1459 DacEnumMemoryRegion(m_addr, strlen(str) + 1);
1464 #define S16PTR(type) __Str16Ptr< type >
1465 #define S16PTRMAX(type, maxChars) __Str16Ptr< type, maxChars >
1467 template<typename type>
1471 __GlobalVal< type >(PULONG rvaPtr)
1476 operator type() const
1478 return (type)*__DPtr< type >(DacGlobalBase() + *m_rvaPtr);
1481 __DPtr< type > operator&() const
1483 return __DPtr< type >(DacGlobalBase() + *m_rvaPtr);
1486 // @dbgtodo dac support: This updates values in the host. This seems extremely dangerous
1487 // to do silently. I'd prefer that a specific (searchable) write function
1488 // was used. Try disabling this and see what fails...
1489 __GlobalVal<type> & operator=(const type & val)
1491 type* ptr = __DPtr< type >(DacGlobalBase() + *m_rvaPtr);
1492 // Update the host copy;
1494 // Write back to the target.
1495 DacWriteHostInstance(ptr, true);
1499 bool IsValid(void) const
1501 return __DPtr< type >(DacGlobalBase() + *m_rvaPtr).IsValid();
1503 void EnumMem(void) const
1505 TADDR p = DacGlobalBase() + *m_rvaPtr;
1506 __DPtr< type >(p).EnumMem();
1513 template<typename type, size_t size>
1517 __GlobalArray< type, size >(PULONG rvaPtr)
1522 __DPtr< type > operator&() const
1524 return __DPtr< type >(DacGlobalBase() + *m_rvaPtr);
1527 type& operator[](unsigned int index) const
1529 return __DPtr< type >(DacGlobalBase() + *m_rvaPtr)[index];
1532 bool IsValid(void) const
1534 // Only validates the base pointer, not the full array range.
1535 return __DPtr< type >(DacGlobalBase() + *m_rvaPtr).IsValid();
1537 void EnumMem(void) const
1539 DacEnumMemoryRegion(DacGlobalBase() + *m_rvaPtr, sizeof(type) * size);
1546 template<typename acc_type, typename store_type>
1550 __GlobalPtr< acc_type, store_type >(PULONG rvaPtr)
1555 __DPtr< store_type > operator&() const
1557 return __DPtr< store_type >(DacGlobalBase() + *m_rvaPtr);
1560 store_type & operator=(store_type & val)
1562 store_type* ptr = __DPtr< store_type >(DacGlobalBase() + *m_rvaPtr);
1563 // Update the host copy;
1565 // Write back to the target.
1566 DacWriteHostInstance(ptr, true);
1570 acc_type operator->() const
1572 return (acc_type)*__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr);
1574 operator acc_type() const
1576 return (acc_type)*__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr);
1578 operator store_type() const
1580 return *__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr);
1582 bool operator!() const
1584 return !*__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr);
1587 typename store_type::_Type& operator[](int index)
1589 return (*__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr))[index];
1592 typename store_type::_Type& operator[](unsigned int index)
1594 return (*__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr))[index];
1597 TADDR GetAddr() const
1599 return (*__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr)).GetAddr();
1602 TADDR GetAddrRaw () const
1604 return DacGlobalBase() + *m_rvaPtr;
1607 // This is only testing the the pointer memory is available but does not verify
1608 // the memory that it points to.
1610 bool IsValidPtr(void) const
1612 return __DPtr< store_type >(DacGlobalBase() + *m_rvaPtr).IsValid();
1615 bool IsValid(void) const
1617 return __DPtr< store_type >(DacGlobalBase() + *m_rvaPtr).IsValid() &&
1618 (*__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr)).IsValid();
1620 void EnumMem(void) const
1622 __DPtr< store_type > ptr(DacGlobalBase() + *m_rvaPtr);
1633 template<typename acc_type, typename store_type>
1634 inline bool operator==(const __GlobalPtr<acc_type, store_type>& gptr,
1637 return DacGetTargetAddrForHostAddr(host, true) ==
1638 *__DPtr< TADDR >(DacGlobalBase() + *gptr.m_rvaPtr);
1640 template<typename acc_type, typename store_type>
1641 inline bool operator!=(const __GlobalPtr<acc_type, store_type>& gptr,
1644 return !operator==(gptr, host);
1647 template<typename acc_type, typename store_type>
1648 inline bool operator==(acc_type host,
1649 const __GlobalPtr<acc_type, store_type>& gptr)
1651 return DacGetTargetAddrForHostAddr(host, true) ==
1652 *__DPtr< TADDR >(DacGlobalBase() + *gptr.m_rvaPtr);
1654 template<typename acc_type, typename store_type>
1655 inline bool operator!=(acc_type host,
1656 const __GlobalPtr<acc_type, store_type>& gptr)
1658 return !operator==(host, gptr);
1663 // __VoidPtr is a type that behaves like void* but for target pointers.
1664 // Behavior of PTR_VOID:
1665 // * has void* semantics. Will compile to void* in non-DAC builds (just like
1666 // other PTR types. Unlike TADDR, we want pointer semantics.
1667 // * NOT assignable from host pointer types or convertible to host pointer
1668 // types - ensures we can't confuse host and target pointers (we'll get
1669 // compiler errors if we try and cast between them).
1670 // * like void*, no pointer arithmetic or dereferencing is allowed
1671 // * like TADDR, can be used to construct any __DPtr / __VPtr instance
1672 // * representation is the same as a void* (for marshalling / casting)
1674 // One way in which __VoidPtr is unlike void* is that it can't be cast to
1675 // pointer or integer types. On the one hand, this is a good thing as it forces
1676 // us to keep target pointers separate from other data types. On the other hand
1677 // in practice this means we have to use dac_cast<TADDR> in places where we used
1678 // to use a (TADDR) cast. Unfortunately C++ provides us no way to allow the
1679 // explicit cast to primitive types without also allowing implicit conversions.
1681 // This is very similar in spirit to TADDR. The primary difference is that
1682 // PTR_VOID has pointer semantics, where TADDR has integer semantics. When
1683 // dacizing uses of void* to TADDR, casts must be inserted everywhere back to
1684 // pointer types. If we switch a use of TADDR to PTR_VOID, those casts in
1685 // DACCESS_COMPILE regions no longer compile (see above). Also, TADDR supports
1686 // pointer arithmetic, but that might not be necessary (could use PTR_BYTE
1687 // instead etc.). Ideally we'd probably have just one type for this purpose
1688 // (named TADDR but with the semantics of PTR_VOID), but outright conversion
1689 // would require too much work.
1691 class __VoidPtr : public __TPtrBase
1694 __VoidPtr(void) : __TPtrBase() {}
1695 __VoidPtr(TADDR addr) : __TPtrBase(addr) {}
1697 // Note, unlike __DPtr, this ctor form is not explicit. We allow implicit
1698 // conversions from any pointer type (just like for void*).
1699 __VoidPtr(__TPtrBase addr)
1701 m_addr = addr.GetAddr();
1704 // Like TPtrBase, VoidPtrs can also be created impicitly from all GlobalPtrs
1705 template<typename acc_type, typename store_type>
1706 __VoidPtr(__GlobalPtr<acc_type, store_type> globalPtr)
1708 m_addr = globalPtr.GetAddr();
1711 // Note, unlike __DPtr, there is no explicit conversion from host pointer
1712 // types. Since void* cannot be marshalled, there is no such thing as
1713 // a void* DAC instance in the host.
1715 // Also, we don't want an implicit conversion to TADDR because then the
1716 // compiler will allow pointer arithmetic (which it wouldn't allow for
1717 // void*). Instead, callers can use dac_cast<TADDR> if they want.
1719 // Note, unlike __DPtr, any pointer type can be assigned to a __VoidPtr
1720 // This is to mirror the assignability of any pointer type to a void*
1721 __VoidPtr& operator=(const __TPtrBase& ptr)
1723 m_addr = ptr.GetAddr();
1726 __VoidPtr& operator=(TADDR addr)
1732 // note, no marshalling operators (type* conversion, operator ->, operator*)
1733 // A void* can't be marshalled because we don't know how much to copy
1735 // PTR_Void can be compared to any other pointer type (because conceptually,
1736 // any other pointer type should be implicitly convertible to void*)
1737 bool operator==(const __TPtrBase& ptr) const
1739 return m_addr == ptr.GetAddr();
1741 bool operator==(TADDR addr) const
1743 return m_addr == addr;
1745 bool operator!=(const __TPtrBase& ptr) const
1747 return !operator==(ptr);
1749 bool operator!=(TADDR addr) const
1751 return m_addr != addr;
1753 bool operator<(const __TPtrBase& ptr) const
1755 return m_addr < ptr.GetAddr();
1757 bool operator>(const __TPtrBase& ptr) const
1759 return m_addr > ptr.GetAddr();
1761 bool operator<=(const __TPtrBase& ptr) const
1763 return m_addr <= ptr.GetAddr();
1765 bool operator>=(const __TPtrBase& ptr) const
1767 return m_addr >= ptr.GetAddr();
1771 typedef __VoidPtr PTR_VOID;
1772 typedef DPTR(PTR_VOID) PTR_PTR_VOID;
1774 // For now we treat pointers to const and non-const void the same in DAC
1775 // builds. In general, DAC is read-only anyway and so there isn't a danger of
1776 // writing to these pointers. Also, the non-dac builds will ensure
1777 // const-correctness. However, if we wanted to support true void* / const void*
1778 // behavior, we could probably build the follow functionality by templating
1780 // * A PTR_VOID would be implicitly convertable to PTR_CVOID
1781 // * An explicit coercion (ideally const_cast) would be required to convert a
1782 // PTR_CVOID to a PTR_VOID
1783 // * Similarily, an explicit coercion would be required to convert a cost PTR
1784 // type (eg. PTR_CBYTE) to a PTR_VOID.
1785 typedef __VoidPtr PTR_CVOID;
1788 // The special empty ctor declared here allows the whole
1789 // class hierarchy to be instantiated easily by the
1790 // external access code. The actual class body will be
1791 // read externally so no members should be initialized.
1794 // VPTR_ANY_CLASS_METHODS - Defines the following methods for all VPTR classes
1797 // Returns the size of the dynamic type of the object (as opposed to sizeof
1798 // which is based only on the static type).
1801 // Returns the address of the vtable for this type.
1802 // We create a temporary instance of this type in order to read it's vtable pointer
1803 // (at offset 0). For this temporary instance, we do not want to initialize any fields,
1804 // so we use the marshalling ctor. Since we didn't initialize any fields, we also don't
1805 // wan't to run the dtor (marshaled data structures don't normally expect their destructor
1806 // or non-DAC constructors to be called in DAC builds anyway). So, rather than create a
1807 // normal stack object, or put the object on the heap, we create the temporary object
1808 // on the stack using placement-new and alloca, and don't destruct it.
1810 #define VPTR_ANY_CLASS_METHODS(name) \
1811 virtual ULONG32 VPtrSize(void) { SUPPORTS_DAC; return sizeof(name); } \
1812 static PVOID VPtrHostVTable() { \
1813 void * pBuf = _alloca(sizeof(name)); \
1814 name * dummy = new (pBuf) name((TADDR)0, (TADDR)0); \
1815 return *((PVOID*)dummy); }
1817 #define VPTR_CLASS_METHODS(name) \
1818 VPTR_ANY_CLASS_METHODS(name) \
1819 static TADDR VPtrTargetVTable() { \
1821 return DacGlobalBase() + g_dacGlobals.name##__vtAddr; }
1823 #define VPTR_MULTI_CLASS_METHODS(name, keyBase) \
1824 VPTR_ANY_CLASS_METHODS(name) \
1825 static TADDR VPtrTargetVTable() { \
1827 return DacGlobalBase() + g_dacGlobals.name##__##keyBase##__mvtAddr; }
1829 #define VPTR_VTABLE_CLASS(name, base) \
1830 public: name(TADDR addr, TADDR vtAddr) : base(addr, vtAddr) {} \
1831 VPTR_CLASS_METHODS(name)
1833 #define VPTR_VTABLE_CLASS_AND_CTOR(name, base) \
1834 VPTR_VTABLE_CLASS(name, base)
1836 #define VPTR_MULTI_VTABLE_CLASS(name, base) \
1837 public: name(TADDR addr, TADDR vtAddr) : base(addr, vtAddr) {} \
1838 VPTR_MULTI_CLASS_METHODS(name, base)
1840 // Used for base classes that can be instantiated directly.
1841 // The fake vfn is still used to force a vtable even when
1842 // all the normal vfns are ifdef'ed out.
1843 #define VPTR_BASE_CONCRETE_VTABLE_CLASS(name) \
1844 public: name(TADDR addr, TADDR vtAddr) {} \
1845 VPTR_CLASS_METHODS(name)
1847 #define VPTR_BASE_CONCRETE_VTABLE_CLASS_NO_CTOR_BODY(name) \
1848 public: name(TADDR addr, TADDR vtAddr); \
1849 VPTR_CLASS_METHODS(name)
1851 // The pure virtual method forces all derivations to use
1852 // VPTR_VTABLE_CLASS to compile.
1853 #define VPTR_BASE_VTABLE_CLASS(name) \
1854 public: name(TADDR addr, TADDR vtAddr) {} \
1855 virtual ULONG32 VPtrSize(void) = 0;
1857 #define VPTR_BASE_VTABLE_CLASS_AND_CTOR(name) \
1858 VPTR_BASE_VTABLE_CLASS(name)
1860 #define VPTR_BASE_VTABLE_CLASS_NO_CTOR_BODY(name) \
1861 public: name(TADDR addr, TADDR vtAddr); \
1862 virtual ULONG32 VPtrSize(void) = 0;
1864 #define VPTR_ABSTRACT_VTABLE_CLASS(name, base) \
1865 public: name(TADDR addr, TADDR vtAddr) : base(addr, vtAddr) {}
1867 #define VPTR_ABSTRACT_VTABLE_CLASS_NO_CTOR_BODY(name, base) \
1868 public: name(TADDR addr, TADDR vtAddr);
1870 // helper macro to make the vtables unique for DAC
1871 #define VPTR_UNIQUE(unique)
1873 // Safe access for retrieving the target address of a PTR.
1874 #define PTR_TO_TADDR(ptr) ((ptr).GetAddr())
1876 #define GFN_TADDR(name) (DacGlobalBase() + g_dacGlobals.fn__ ## name)
1878 // ROTORTODO - g++ 3 doesn't like the use of the operator& in __GlobalVal
1879 // here. Putting GVAL_ADDR in to get things to compile while I discuss
1880 // this matter with the g++ authors.
1882 #define GVAL_ADDR(g) \
1886 // References to class static and global data.
1887 // These all need to be redirected through the global
1891 #define _SPTR_DECL(acc_type, store_type, var) \
1892 static __GlobalPtr< acc_type, store_type > var
1893 #define _SPTR_IMPL(acc_type, store_type, cls, var) \
1894 __GlobalPtr< acc_type, store_type > cls::var(&g_dacGlobals.cls##__##var)
1895 #define _SPTR_IMPL_INIT(acc_type, store_type, cls, var, init) \
1896 __GlobalPtr< acc_type, store_type > cls::var(&g_dacGlobals.cls##__##var)
1897 #define _SPTR_IMPL_NS(acc_type, store_type, ns, cls, var) \
1898 __GlobalPtr< acc_type, store_type > cls::var(&g_dacGlobals.ns##__##cls##__##var)
1899 #define _SPTR_IMPL_NS_INIT(acc_type, store_type, ns, cls, var, init) \
1900 __GlobalPtr< acc_type, store_type > cls::var(&g_dacGlobals.ns##__##cls##__##var)
1902 #define _GPTR_DECL(acc_type, store_type, var) \
1903 extern __GlobalPtr< acc_type, store_type > var
1904 #define _GPTR_IMPL(acc_type, store_type, var) \
1905 __GlobalPtr< acc_type, store_type > var(&g_dacGlobals.dac__##var)
1906 #define _GPTR_IMPL_INIT(acc_type, store_type, var, init) \
1907 __GlobalPtr< acc_type, store_type > var(&g_dacGlobals.dac__##var)
1909 #define SVAL_DECL(type, var) \
1910 static __GlobalVal< type > var
1911 #define SVAL_IMPL(type, cls, var) \
1912 __GlobalVal< type > cls::var(&g_dacGlobals.cls##__##var)
1913 #define SVAL_IMPL_INIT(type, cls, var, init) \
1914 __GlobalVal< type > cls::var(&g_dacGlobals.cls##__##var)
1915 #define SVAL_IMPL_NS(type, ns, cls, var) \
1916 __GlobalVal< type > cls::var(&g_dacGlobals.ns##__##cls##__##var)
1917 #define SVAL_IMPL_NS_INIT(type, ns, cls, var, init) \
1918 __GlobalVal< type > cls::var(&g_dacGlobals.ns##__##cls##__##var)
1920 #define GVAL_DECL(type, var) \
1921 extern __GlobalVal< type > var
1922 #define GVAL_IMPL(type, var) \
1923 __GlobalVal< type > var(&g_dacGlobals.dac__##var)
1924 #define GVAL_IMPL_INIT(type, var, init) \
1925 __GlobalVal< type > var(&g_dacGlobals.dac__##var)
1927 #define GARY_DECL(type, var, size) \
1928 extern __GlobalArray< type, size > var
1929 #define GARY_IMPL(type, var, size) \
1930 __GlobalArray< type, size > var(&g_dacGlobals.dac__##var)
1932 // Translation from a host pointer back to the target address
1933 // that was used to retrieve the data for the host pointer.
1934 #define PTR_HOST_TO_TADDR(host) DacGetTargetAddrForHostAddr(host, true)
1935 // Translation from a host interior pointer back to the corresponding
1936 // target address. The host address must reside within a previously
1937 // retrieved instance.
1938 #define PTR_HOST_INT_TO_TADDR(host) DacGetTargetAddrForHostInteriorAddr(host, true)
1939 // Translation from a host vtable pointer to a target vtable pointer.
1940 #define VPTR_HOST_VTABLE_TO_TADDR(host) DacGetTargetVtForHostVt(host, true)
1942 // Construct a pointer to a member of the given type.
1943 #define PTR_HOST_MEMBER_TADDR(type, host, memb) \
1944 (PTR_HOST_TO_TADDR(host) + (TADDR)offsetof(type, memb))
1946 // Construct a pointer to a member of the given type given an interior
1948 #define PTR_HOST_INT_MEMBER_TADDR(type, host, memb) \
1949 (PTR_HOST_INT_TO_TADDR(host) + (TADDR)offsetof(type, memb))
1951 #define PTR_TO_MEMBER_TADDR(type, ptr, memb) \
1952 (PTR_TO_TADDR(ptr) + (TADDR)offsetof(type, memb))
1954 // Constructs an arbitrary data instance for a piece of
1955 // memory in the target.
1956 #define PTR_READ(addr, size) \
1957 DacInstantiateTypeByAddress(addr, size, true)
1959 // This value is used to intiailize target pointers to NULL. We want this to be TADDR type
1960 // (as opposed to, say, __TPtrBase) so that it can be used in the non-explicit ctor overloads,
1961 // eg. as an argument default value.
1962 // We can't always just use NULL because that's 0 which (in C++) can be any integer or pointer
1963 // type (causing an ambiguous overload compiler error when used in explicit ctor forms).
1964 #define PTR_NULL ((TADDR)0)
1966 // Provides an empty method implementation when compiled
1967 // for DACCESS_COMPILE. For example, use to stub out methods needed
1968 // for vtable entries but otherwise unused.
1969 // Note that these functions are explicitly NOT marked SUPPORTS_DAC so that we'll get a
1970 // DacCop warning if any calls to them are detected.
1971 // @dbgtodo : It's probably almost always wrong to call any such function, so
1972 // we should probably throw a better error (DacNotImpl), and ideally mark the function
1973 // DECLSPEC_NORETURN so we don't have to deal with fabricating return values and we can
1974 // get compiler warnings (unreachable code) anytime functions marked this way are called.
1975 #define DAC_EMPTY() { LIMITED_METHOD_CONTRACT; }
1976 #define DAC_EMPTY_ERR() { LIMITED_METHOD_CONTRACT; DacError(E_UNEXPECTED); }
1977 #define DAC_EMPTY_RET(retVal) { LIMITED_METHOD_CONTRACT; DacError(E_UNEXPECTED); return retVal; }
1978 #define DAC_UNEXPECTED() { LIMITED_METHOD_CONTRACT; DacError_NoRet(E_UNEXPECTED); }
1980 #endif // #ifdef __cplusplus
1982 // Implementation details for dac_cast, should never be accessed directly.
1983 // See code:dac_cast for details and discussion.
1986 // Helper functions to get the target address of specific types
1987 inline TADDR getTaddr(TADDR addr) { return addr; }
1988 inline TADDR getTaddr(__TPtrBase const &tptr) { return PTR_TO_TADDR(tptr); }
1989 inline TADDR getTaddr(void const * host) { return PTR_HOST_TO_TADDR((void *)host); }
1990 template<typename acc_type, typename store_type>
1991 inline TADDR getTaddr(__GlobalPtr<acc_type, store_type> const &gptr) { return PTR_TO_TADDR(gptr); }
1993 // It is an error to try dac_cast on a __GlobalVal or a __GlobalArray. Declare
1994 // but do not define the methods so that a compile-time error results.
1995 template<typename type>
1996 TADDR getTaddr(__GlobalVal<type> const &gval);
1997 template<typename type, size_t size>
1998 TADDR getTaddr(__GlobalArray<type, size> const &garr);
2000 // Helper class to instantiate DAC instances from a TADDR
2001 // The default implementation assumes we want to create an instance of a PTR type
2002 template<typename T> struct makeDacInst
2004 static inline T fromTaddr(TADDR addr)
2006 static_assert((std::is_base_of<__TPtrBase, T>::value), "is_base_of constraint violation");
2011 // Partial specialization for creating TADDRs
2012 // This is the only other way to create a DAC type instance other than PTR types (above)
2013 template<> struct makeDacInst<TADDR>
2015 static inline TADDR fromTaddr(TADDR addr) { return addr; }
2017 } // namespace dac_imp
2020 // DacCop in-line exclusion mechanism
2022 // Warnings - official home is DacCop\Shared\Warnings.cs, but we want a way for users to indicate
2023 // warning codes in a way that is descriptive to readers (not just code numbers). The names here
2024 // don't matter - DacCop just looks at the value
2025 enum DacCopWarningCode
2030 PointerComparison = 3,
2031 InconsistentMarshalling = 4,
2032 CastBetweenAddressSpaces = 5,
2033 CastOfMarshalledType = 6,
2034 VirtualCallToNonVPtr = 7,
2035 UndacizedGlobalVariable = 8,
2037 // Function graph related
2040 CallVirtualUnknown = 704,
2041 CallVirtualNonDac = 705,
2044 // DACCOP_IGNORE is a mechanism to suppress DacCop violations from within the source-code.
2045 // See the DacCop wiki for guidance on how best to use this: http://mswikis/clr/dev/Pages/DacCop.aspx
2047 // DACCOP_IGNORE will suppress a DacCop violation for the following (non-compound) statement.
2049 // // The "dual-mode DAC problem" occurs in a few places where a class is used both
2050 // // in the host, and marshalled from the target ... <further details>
2051 // DACCOP_IGNORE(CastBetweenAddressSpaces,"SBuffer has the dual-mode DAC problem");
2052 // TADDR bufAddr = (TADDR)m_buffer;
2054 // A call to DACCOP_IGNORE must occur as it's own statement, and can apply only to following
2055 // single-statements (not to compound statement blocks). Occasionally it is necessary to hoist
2056 // violation-inducing code out to its own statement (e.g., if it occurs in the conditional of an
2060 // code: a literal value from DacCopWarningCode indicating which violation should be suppressed.
2061 // szReasonString: a short description of why this exclusion is necessary. This is intended just
2062 // to help readers of the code understand the source of the problem, and what would be required
2063 // to fix it. More details can be provided in comments if desired.
2065 inline void DACCOP_IGNORE(DacCopWarningCode code, const char * szReasonString)
2067 // DacCop detects calls to this function. No implementation is necessary.
2070 #else // #ifdef DACCESS_COMPILE
2073 // This version of the macros turns into normal pointers
2074 // for unmodified in-proc compilation.
2076 // *******************************************************
2077 // !!!!!!!!!!!!!!!!!!!!!!!!!NOTE!!!!!!!!!!!!!!!!!!!!!!!!!!
2079 // Please search this file for the type name to find the
2080 // DAC versions of these definitions
2082 // !!!!!!!!!!!!!!!!!!!!!!!!!NOTE!!!!!!!!!!!!!!!!!!!!!!!!!!
2083 // *******************************************************
2086 // Declare TADDR as a non-pointer type so that arithmetic
2087 // can be done on it directly, as with the DACCESS_COMPILE definition.
2088 // This also helps expose pointer usage that may need to be changed.
2089 typedef ULONG_PTR TADDR;
2091 typedef void* PTR_VOID;
2092 typedef LPVOID* PTR_PTR_VOID;
2093 typedef const void* PTR_CVOID;
2095 #define DPTR(type) type*
2096 #define ArrayDPTR(type) type*
2097 #define SPTR(type) type*
2098 #define VPTR(type) type*
2099 #define S8PTR(type) type*
2100 #define S8PTRMAX(type, maxChars) type*
2101 #define S16PTR(type) type*
2102 #define S16PTRMAX(type, maxChars) type*
2104 #if defined(FEATURE_PAL)
2106 #define VPTR_VTABLE_CLASS(name, base) \
2107 friend struct _DacGlobals; \
2108 public: name(int dummy) : base(dummy) {}
2110 #define VPTR_VTABLE_CLASS_AND_CTOR(name, base) \
2111 VPTR_VTABLE_CLASS(name, base) \
2114 #define VPTR_MULTI_VTABLE_CLASS(name, base) \
2115 friend struct _DacGlobals; \
2116 public: name(int dummy) : base(dummy) {}
2118 #define VPTR_BASE_CONCRETE_VTABLE_CLASS(name) \
2119 friend struct _DacGlobals; \
2120 public: name(int dummy) {}
2122 #define VPTR_BASE_VTABLE_CLASS(name) \
2123 friend struct _DacGlobals; \
2124 public: name(int dummy) {}
2126 #define VPTR_BASE_VTABLE_CLASS_AND_CTOR(name) \
2127 VPTR_BASE_VTABLE_CLASS(name) \
2130 #define VPTR_ABSTRACT_VTABLE_CLASS(name, base) \
2131 friend struct _DacGlobals; \
2132 public: name(int dummy) : base(dummy) {}
2134 #else // FEATURE_PAL
2136 #define VPTR_VTABLE_CLASS(name, base)
2137 #define VPTR_VTABLE_CLASS_AND_CTOR(name, base)
2138 #define VPTR_MULTI_VTABLE_CLASS(name, base)
2139 #define VPTR_BASE_CONCRETE_VTABLE_CLASS(name)
2140 #define VPTR_BASE_VTABLE_CLASS(name)
2141 #define VPTR_BASE_VTABLE_CLASS_AND_CTOR(name)
2142 #define VPTR_ABSTRACT_VTABLE_CLASS(name, base)
2144 #endif // FEATURE_PAL
2146 // helper macro to make the vtables unique for DAC
2147 #define VPTR_UNIQUE(unique) virtual int MakeVTableUniqueForDAC() { STATIC_CONTRACT_SO_TOLERANT; return unique; }
2148 #define VPTR_UNIQUE_BaseDomain (100000)
2149 #define VPTR_UNIQUE_SystemDomain (VPTR_UNIQUE_BaseDomain + 1)
2150 #define VPTR_UNIQUE_ComMethodFrame (VPTR_UNIQUE_SystemDomain + 1)
2151 #define VPTR_UNIQUE_StubHelperFrame (VPTR_UNIQUE_ComMethodFrame + 1)
2152 #define VPTR_UNIQUE_RedirectedThreadFrame (VPTR_UNIQUE_StubHelperFrame + 1)
2153 #define VPTR_UNIQUE_HijackFrame (VPTR_UNIQUE_RedirectedThreadFrame + 1)
2155 #define PTR_TO_TADDR(ptr) ((TADDR)(ptr))
2156 #define GFN_TADDR(name) ((TADDR)(name))
2158 #define GVAL_ADDR(g) (&(g))
2159 #define _SPTR_DECL(acc_type, store_type, var) \
2160 static store_type var
2161 #define _SPTR_IMPL(acc_type, store_type, cls, var) \
2163 #define _SPTR_IMPL_INIT(acc_type, store_type, cls, var, init) \
2164 store_type cls::var = init
2165 #define _SPTR_IMPL_NS(acc_type, store_type, ns, cls, var) \
2167 #define _SPTR_IMPL_NS_INIT(acc_type, store_type, ns, cls, var, init) \
2168 store_type cls::var = init
2169 #define _GPTR_DECL(acc_type, store_type, var) \
2170 extern store_type var
2171 #define _GPTR_IMPL(acc_type, store_type, var) \
2173 #define _GPTR_IMPL_INIT(acc_type, store_type, var, init) \
2174 store_type var = init
2175 #define SVAL_DECL(type, var) \
2177 #define SVAL_IMPL(type, cls, var) \
2179 #define SVAL_IMPL_INIT(type, cls, var, init) \
2180 type cls::var = init
2181 #define SVAL_IMPL_NS(type, ns, cls, var) \
2183 #define SVAL_IMPL_NS_INIT(type, ns, cls, var, init) \
2184 type cls::var = init
2185 #define GVAL_DECL(type, var) \
2187 #define GVAL_IMPL(type, var) \
2189 #define GVAL_IMPL_INIT(type, var, init) \
2191 #define GARY_DECL(type, var, size) \
2192 extern type var[size]
2193 #define GARY_IMPL(type, var, size) \
2195 #define PTR_HOST_TO_TADDR(host) ((TADDR)(host))
2196 #define PTR_HOST_INT_TO_TADDR(host) ((TADDR)(host))
2197 #define VPTR_HOST_VTABLE_TO_TADDR(host) ((TADDR)(host))
2198 #define PTR_HOST_MEMBER_TADDR(type, host, memb) ((TADDR)&(host)->memb)
2199 #define PTR_HOST_INT_MEMBER_TADDR(type, host, memb) ((TADDR)&(host)->memb)
2200 #define PTR_TO_MEMBER_TADDR(type, ptr, memb) ((TADDR)&((ptr)->memb))
2201 #define PTR_READ(addr, size) ((PVOID)(addr))
2203 #define PTR_NULL NULL
2206 #define DAC_EMPTY_ERR()
2207 #define DAC_EMPTY_RET(retVal)
2208 #define DAC_UNEXPECTED()
2210 #define DACCOP_IGNORE(warningCode, reasonString)
2212 #endif // #ifdef DACCESS_COMPILE
2214 //----------------------------------------------------------------------------
2216 // Casting utility, to be used for casting one class pointer type to another.
2217 // Use as you would use static_cast
2219 // dac_cast is designed to act just as static_cast does when
2220 // dealing with pointers and their DAC abstractions. Specifically,
2221 // it handles these coversions:
2223 // dac_cast<TargetType>(SourceTypeVal)
2225 // where TargetType <- SourceTypeVal are
2227 // ?PTR(Tgt) <- TADDR - Create PTR type (DPtr etc.) from TADDR
2228 // ?PTR(Tgt) <- ?PTR(Src) - Convert one PTR type to another
2229 // ?PTR(Tgt) <- Src * - Create PTR type from dac host object instance
2230 // TADDR <- ?PTR(Src) - Get TADDR of PTR object (DPtr etc.)
2231 // TADDR <- Src * - Get TADDR of dac host object instance
2233 // Note that there is no direct convertion to other host-pointer types (because we don't
2234 // know if you want a DPTR or VPTR etc.). However, due to the implicit DAC conversions,
2235 // you can just use dac_cast<PTR_Foo> and assign that to a Foo*.
2237 // The beauty of this syntax is that it is consistent regardless
2238 // of source and target casting types. You just use dac_cast
2239 // and the partial template specialization will do the right thing.
2241 // One important thing to realise is that all "Foo *" types are
2242 // assumed to be pointers to host instances that were marshalled by DAC. This should
2243 // fail at runtime if it's not the case.
2245 // Some examples would be:
2247 // - Host pointer of one type to a related host pointer of another
2248 // type, i.e., MethodDesc * <-> InstantiatedMethodDesc *
2249 // Syntax: with MethodDesc *pMD, InstantiatedMethodDesc *pInstMD
2250 // pInstMd = dac_cast<PTR_InstantiatedMethodDesc>(pMD)
2251 // pMD = dac_cast<PTR_MethodDesc>(pInstMD)
2253 // - (D|V)PTR of one encapsulated pointer type to a (D|V)PTR of
2254 // another type, i.e., PTR_AppDomain <-> PTR_BaseDomain
2255 // Syntax: with PTR_AppDomain pAD, PTR_BaseDomain pBD
2256 // dac_cast<PTR_AppDomain>(pBD)
2257 // dac_cast<PTR_BaseDomain>(pAD)
2259 // Example comparsions of some old and new syntax, where
2260 // h is a host pointer, such as "Foo *h;"
2261 // p is a DPTR, such as "PTR_Foo p;"
2263 // PTR_HOST_TO_TADDR(h) ==> dac_cast<TADDR>(h)
2264 // PTR_TO_TADDR(p) ==> dac_cast<TADDR>(p)
2265 // PTR_Foo(PTR_HOST_TO_TADDR(h)) ==> dac_cast<PTR_Foo>(h)
2267 //----------------------------------------------------------------------------
2268 template <typename Tgt, typename Src>
2269 inline Tgt dac_cast(Src src)
2271 #ifdef DACCESS_COMPILE
2272 // In DAC builds, first get a TADDR for the source, then create the
2273 // appropriate destination instance.
2274 TADDR addr = dac_imp::getTaddr(src);
2275 return dac_imp::makeDacInst<Tgt>::fromTaddr(addr);
2277 // In non-DAC builds, dac_cast is the same as a C-style cast because we need to support:
2278 // - casting away const
2279 // - conversions between pointers and TADDR
2280 // Perhaps we should more precisely restrict it's usage, but we get the precise
2281 // restrictions in DAC builds, so it wouldn't buy us much.
2286 //----------------------------------------------------------------------------
2288 // Convenience macros which work for either mode.
2290 //----------------------------------------------------------------------------
2292 #define SPTR_DECL(type, var) _SPTR_DECL(type*, PTR_##type, var)
2293 #define SPTR_IMPL(type, cls, var) _SPTR_IMPL(type*, PTR_##type, cls, var)
2294 #define SPTR_IMPL_INIT(type, cls, var, init) _SPTR_IMPL_INIT(type*, PTR_##type, cls, var, init)
2295 #define SPTR_IMPL_NS(type, ns, cls, var) _SPTR_IMPL_NS(type*, PTR_##type, ns, cls, var)
2296 #define SPTR_IMPL_NS_INIT(type, ns, cls, var, init) _SPTR_IMPL_NS_INIT(type*, PTR_##type, ns, cls, var, init)
2297 #define GPTR_DECL(type, var) _GPTR_DECL(type*, PTR_##type, var)
2298 #define GPTR_IMPL(type, var) _GPTR_IMPL(type*, PTR_##type, var)
2299 #define GPTR_IMPL_INIT(type, var, init) _GPTR_IMPL_INIT(type*, PTR_##type, var, init)
2302 // If you want to marshal a single instance of an ArrayDPtr over to the host and
2303 // return a pointer to it, you can use this function. However, this is unsafe because
2304 // users of value may assume they can do pointer arithmetic on it. This is exactly
2305 // the bugs ArrayDPtr is designed to prevent. See code:__ArrayDPtr for details.
2306 template<typename type>
2307 inline type* DacUnsafeMarshalSingleElement( ArrayDPTR(type) arrayPtr )
2309 return (DPTR(type))(arrayPtr);
2312 //----------------------------------------------------------------------------
2314 // Forward typedefs for system types. This is a convenient place
2315 // to declare things for system types, plus it gives us a central
2316 // place to look at when deciding what types may cause issues for
2317 // cross-platform compilation.
2319 //----------------------------------------------------------------------------
2321 typedef ArrayDPTR(BYTE) PTR_BYTE;
2322 typedef DPTR(PTR_BYTE) PTR_PTR_BYTE;
2323 typedef DPTR(PTR_PTR_BYTE) PTR_PTR_PTR_BYTE;
2324 typedef ArrayDPTR(signed char) PTR_SBYTE;
2325 typedef ArrayDPTR(const BYTE) PTR_CBYTE;
2326 typedef DPTR(INT8) PTR_INT8;
2327 typedef DPTR(INT16) PTR_INT16;
2328 typedef DPTR(WORD) PTR_WORD;
2329 typedef DPTR(USHORT) PTR_USHORT;
2330 typedef DPTR(DWORD) PTR_DWORD;
2331 typedef DPTR(LONG) PTR_LONG;
2332 typedef DPTR(ULONG) PTR_ULONG;
2333 typedef DPTR(INT32) PTR_INT32;
2334 typedef DPTR(UINT32) PTR_UINT32;
2335 typedef DPTR(ULONG64) PTR_ULONG64;
2336 typedef DPTR(INT64) PTR_INT64;
2337 typedef DPTR(UINT64) PTR_UINT64;
2338 typedef DPTR(SIZE_T) PTR_SIZE_T;
2339 typedef DPTR(size_t) PTR_size_t;
2340 typedef DPTR(TADDR) PTR_TADDR;
2341 typedef DPTR(int) PTR_int;
2342 typedef DPTR(BOOL) PTR_BOOL;
2343 typedef DPTR(unsigned) PTR_unsigned;
2345 typedef S8PTR(char) PTR_STR;
2346 typedef S8PTR(const char) PTR_CSTR;
2347 typedef S8PTR(char) PTR_UTF8;
2348 typedef S8PTR(const char) PTR_CUTF8;
2349 typedef S16PTR(wchar_t) PTR_WSTR;
2350 typedef S16PTR(const wchar_t) PTR_CWSTR;
2352 typedef DPTR(T_CONTEXT) PTR_CONTEXT;
2353 typedef DPTR(PTR_CONTEXT) PTR_PTR_CONTEXT;
2354 typedef DPTR(struct _EXCEPTION_POINTERS) PTR_EXCEPTION_POINTERS;
2355 typedef DPTR(struct _EXCEPTION_RECORD) PTR_EXCEPTION_RECORD;
2357 typedef DPTR(struct _EXCEPTION_REGISTRATION_RECORD) PTR_EXCEPTION_REGISTRATION_RECORD;
2359 typedef DPTR(struct IMAGE_COR_VTABLEFIXUP) PTR_IMAGE_COR_VTABLEFIXUP;
2360 typedef DPTR(IMAGE_DATA_DIRECTORY) PTR_IMAGE_DATA_DIRECTORY;
2361 typedef DPTR(IMAGE_DEBUG_DIRECTORY) PTR_IMAGE_DEBUG_DIRECTORY;
2362 typedef DPTR(IMAGE_DOS_HEADER) PTR_IMAGE_DOS_HEADER;
2363 typedef DPTR(IMAGE_NT_HEADERS) PTR_IMAGE_NT_HEADERS;
2364 typedef DPTR(IMAGE_NT_HEADERS32) PTR_IMAGE_NT_HEADERS32;
2365 typedef DPTR(IMAGE_NT_HEADERS64) PTR_IMAGE_NT_HEADERS64;
2366 typedef DPTR(IMAGE_SECTION_HEADER) PTR_IMAGE_SECTION_HEADER;
2367 typedef DPTR(IMAGE_TLS_DIRECTORY) PTR_IMAGE_TLS_DIRECTORY;
2369 #if defined(DACCESS_COMPILE)
2371 #include <clrdata.h>
2372 #include <xclrdata.h>
2376 typedef DPTR(T_RUNTIME_FUNCTION) PTR_RUNTIME_FUNCTION;
2377 typedef DPTR(struct _UNWIND_INFO) PTR_UNWIND_INFO;
2378 #if defined(_TARGET_AMD64_)
2379 typedef DPTR(union _UNWIND_CODE) PTR_UNWIND_CODE;
2380 #endif // _TARGET_AMD64_
2384 typedef DPTR(RUNTIME_FUNCTION) PTR_RUNTIME_FUNCTION;
2387 //----------------------------------------------------------------------------
2389 // A PCODE is a valid PC/IP value -- a pointer to an instruction, possibly including some processor mode bits.
2390 // (On ARM, for example, a PCODE value should should have the low-order THUMB_CODE bit set if the code should
2391 // be executed in that mode.)
2393 typedef TADDR PCODE;
2394 typedef DPTR(PCODE) PTR_PCODE;
2395 typedef DPTR(PTR_PCODE) PTR_PTR_PCODE;
2397 // There is another concept we should have, "pointer to the start of an instruction" -- a PCODE with any mode bits masked off.
2398 // Attempts to introduce this concept, and classify uses of PCODE as one or the other,
2399 // turned out to be too hard: either name choice required *many* code changes, and decisions in unfamiliar code. So despite the
2400 // the comment above, the PCODE is currently sometimes used for the PINSTR concept.
2402 // See PCODEToPINSTR in utilcode.h for conversion from PCODE to PINSTR.
2404 //----------------------------------------------------------------------------
2406 // The access code compile must compile data structures that exactly
2407 // match the real structures for access to work. The access code
2408 // doesn't want all of the debugging validation code, though, so
2409 // distinguish between _DEBUG, for declaring general debugging data
2410 // and always-on debug code, and _DEBUG_IMPL, for debugging code
2411 // which will be disabled when compiling for external access.
2413 //----------------------------------------------------------------------------
2415 #if !defined(_DEBUG_IMPL) && defined(_DEBUG) && !defined(DACCESS_COMPILE)
2416 #define _DEBUG_IMPL 1
2419 // Helper macro for tracking EnumMemoryRegions progress.
2421 #define EMEM_OUT(args) DacWarning args
2423 #define EMEM_OUT(args)
2426 // Macros like MAIN_CLR_MODULE_NAME* for the DAC module
2427 #ifdef FEATURE_MAIN_CLR_MODULE_USES_CORE_NAME
2428 #define MAIN_DAC_MODULE_NAME_W W("mscordaccore")
2429 #define MAIN_DAC_MODULE_DLL_NAME_W W("mscordaccore.dll")
2431 #define MAIN_DAC_MODULE_NAME_W W("mscordacwks")
2432 #define MAIN_DAC_MODULE_DLL_NAME_W W("mscordacwks.dll")
2435 // TARGET_CONSISTENCY_CHECK represents a condition that should not fail unless the DAC target is corrupt.
2436 // This is in contrast to ASSERTs in DAC infrastructure code which shouldn't fail regardless of the memory
2437 // read from the target. At the moment we treat these the same, but in the future we will want a mechanism
2438 // for disabling just the target consistency checks (eg. for tests that intentionally use corrupted targets).
2439 // @dbgtodo : Separating asserts and target consistency checks is tracked by DevDiv Bugs 31674
2440 #define TARGET_CONSISTENCY_CHECK(expr,msg) _ASSERTE_MSG(expr,msg)
2442 #endif // #ifndef __daccess_h__