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: daccess.h
6//
7
8//
9// Support for external access of runtime data structures. These
10// macros and templates hide the details of pointer and data handling
11// so that data structures and code can be compiled to work both
12// in-process and through a special memory access layer.
13//
14// This code assumes the existence of two different pieces of code,
15// the target, the runtime code that is going to be examined, and
16// the host, the code that's doing the examining. Access to the
17// target is abstracted so the target may be a live process on the
18// same machine, a live process on a different machine, a dump file
19// or whatever. No assumptions should be made about accessibility
20// of the target.
21//
22// This code assumes that the data in the target is static. Any
23// time the target's data changes the interfaces must be reset so
24// that potentially stale data is discarded.
25//
26// This code is intended for read access and there is no
27// way to write data back currently.
28//
29// DAC-ized code:
30// - is read-only (non-invasive). So DACized codepaths can not trigger a GC.
31// - has no Thread* object. In reality, DAC-ized codepaths are
32// ReadProcessMemory calls from out-of-process. Conceptually, they
33// are like a pure-native (preemptive) thread.
34////
35// This means that in particular, you cannot DACize a GCTRIGGERS function.
36// Neither can you DACize a function that throws if this will involve
37// allocating a new exception object. There may be
38// exceptions to these rules if you can guarantee that the DACized
39// part of the code path cannot cause a garbage collection (see
40// EditAndContinueModule::ResolveField for an example).
41// If you need to DACize a function that may trigger
42// a GC, it is probably best to refactor the function so that the DACized
43// part of the code path is in a separate function. For instance,
44// functions with GetOrCreate() semantics are hard to DAC-ize because
45// they the Create portion is inherently invasive. Instead, consider refactoring
46// into a GetOrFail() function that DAC can call; and then make GetOrCreate()
47// a wrapper around that.
48
49//
50// This code works by hiding the details of access to target memory.
51// Access is divided into two types:
52// 1. DPTR - access to a piece of data.
53// 2. VPTR - access to a class with a vtable. The class can only have
54// a single vtable pointer at the beginning of the class instance.
55// Things only need to be declared as VPTRs when it is necessary to
56// call virtual functions in the host. In that case the access layer
57// must do extra work to provide a host vtable for the object when
58// it is retrieved so that virtual functions can be called.
59//
60// When compiling with DACCESS_COMPILE the macros turn into templates
61// which replace pointers with smart pointers that know how to fetch
62// data from the target process and provide a host process version of it.
63// Normal data structure access will transparently receive a host copy
64// of the data and proceed, so code such as
65// typedef DPTR(Class) PTR_Class;
66// PTR_Class cls;
67// int val = cls->m_Int;
68// will work without modification. The appropriate operators are overloaded
69// to provide transparent access, such as the -> operator in this case.
70// Note that the convention is to create an appropriate typedef for
71// each type that will be accessed. This hides the particular details
72// of the type declaration and makes the usage look more like regular code.
73//
74// The ?PTR classes also have an implicit base type cast operator to
75// produce a host-pointer instance of the given type. For example
76// Class* cls = PTR_Class(addr);
77// works by implicit conversion from the PTR_Class created by wrapping
78// to a host-side Class instance. Again, this means that existing code
79// can work without modification.
80//
81// Code Example:
82//
83// typedef struct _rangesection
84// {
85// PTR_IJitManager pjit;
86// PTR_RangeSection pright;
87// PTR_RangeSection pleft;
88// ... Other fields omitted ...
89// } RangeSection;
90//
91// RangeSection* pRS = m_RangeTree;
92//
93// while (pRS != NULL)
94// {
95// if (currentPC < pRS->LowAddress)
96// pRS=pRS->pleft;
97// else if (currentPC > pRS->HighAddress)
98// pRS=pRS->pright;
99// else
100// {
101// return pRS->pjit;
102// }
103// }
104//
105// This code does not require any modifications. The global reference
106// provided by m_RangeTree will be a host version of the RangeSection
107// instantiated by conversion. The references to pRS->pleft and
108// pRS->pright will refer to DPTRs due to the modified declaration.
109// In the assignment statement the compiler will automatically use
110// the implicit conversion from PTR_RangeSection to RangeSection*,
111// causing a host instance to be created. Finally, if an appropriate
112// section is found the use of pRS->pjit will cause an implicit
113// conversion from PTR_IJitManager to IJitManager. The VPTR code
114// will look at target memory to determine the actual derived class
115// for the JitManager and instantiate the right class in the host so
116// that host virtual functions can be used just as they would in
117// the target.
118//
119// There are situations where code modifications are required, though.
120//
121// 1. Any time the actual value of an address matters, such as using
122// it as a search key in a tree, the target address must be used.
123//
124// An example of this is the RangeSection tree used to locate JIT
125// managers. A portion of this code is shown above. Each
126// RangeSection node in the tree describes a range of addresses
127// managed by the JitMan. These addresses are just being used as
128// values, not to dereference through, so there are not DPTRs. When
129// searching the range tree for an address the address used in the
130// search must be a target address as that's what values are kept in
131// the RangeSections. In the code shown above, currentPC must be a
132// target address as the RangeSections in the tree are all target
133// addresses. Use dac_cast<TADDR> to retrieve the target address
134// of a ?PTR, as well as to convert a host address to the
135// target address used to retrieve that particular instance. Do not
136// use dac_cast with any raw target pointer types (such as BYTE*).
137//
138// 2. Any time an address is modified, such as by address arithmetic,
139// the arithmetic must be performed on the target address.
140//
141// When a host instance is created it is created for the type in use.
142// There is no particular relation to any other instance, so address
143// arithmetic cannot be used to get from one instance to any other
144// part of memory. For example
145// char* Func(Class* cls)
146// {
147// // String follows the basic Class data.
148// return (char*)(cls + 1);
149// }
150// does not work with external access because the Class* used would
151// have retrieved only a Class worth of data. There is no string
152// following the host instance. Instead, this code should use
153// dac_cast<TADDR> to get the target address of the Class
154// instance, add sizeof(*cls) and then create a new ?PTR to access
155// the desired data. Note that the newly retrieved data will not
156// be contiguous with the Class instance, so address arithmetic
157// will still not work.
158//
159// Previous Code:
160//
161// BOOL IsTarget(LPVOID ip)
162// {
163// StubCallInstrs* pStubCallInstrs = GetStubCallInstrs();
164//
165// if (ip == (LPVOID) &(pStubCallInstrs->m_op))
166// {
167// return TRUE;
168// }
169//
170// Modified Code:
171//
172// BOOL IsTarget(LPVOID ip)
173// {
174// StubCallInstrs* pStubCallInstrs = GetStubCallInstrs();
175//
176// if ((TADDR)ip == dac_cast<TADDR>(pStubCallInstrs) +
177// (TADDR)offsetof(StubCallInstrs, m_op))
178// {
179// return TRUE;
180// }
181//
182// The parameter ip is a target address, so the host pStubCallInstrs
183// cannot be used to derive an address from. The member & reference
184// has to be replaced with a conversion from host to target address
185// followed by explicit offsetting for the field.
186//
187// PTR_HOST_MEMBER_TADDR is a convenience macro that encapsulates
188// these two operations, so the above code could also be:
189//
190// if ((TADDR)ip ==
191// PTR_HOST_MEMBER_TADDR(StubCallInstrs, pStubCallInstrs, m_op))
192//
193// 3. Any time the amount of memory referenced through an address
194// changes, such as by casting to a different type, a new ?PTR
195// must be created.
196//
197// Host instances are created and stored based on both the target
198// address and size of access. The access code has no way of knowing
199// all possible ways that data will be retrieved for a given address
200// so if code changes the way it accesses through an address a new
201// ?PTR must be used, which may lead to a difference instance and
202// different host address. This means that pointer identity does not hold
203// across casts, so code like
204// Class* cls = PTR_Class(addr);
205// Class2* cls2 = PTR_Class2(addr);
206// return cls == cls2;
207// will fail because the host-side instances have no relation to each
208// other. That isn't a problem, since by rule #1 you shouldn't be
209// relying on specific host address values.
210//
211// Previous Code:
212//
213// return (ArrayClass *) m_pMethTab->GetClass();
214//
215// Modified Code:
216//
217// return PTR_ArrayClass(m_pMethTab->GetClass());
218//
219// The ?PTR templates have an implicit conversion from a host pointer
220// to a target address, so the cast above constructs a new
221// PTR_ArrayClass by implicitly converting the host pointer result
222// from GetClass() to its target address and using that as the address
223// of the new PTR_ArrayClass. As mentioned, the actual host-side
224// pointer values may not be the same.
225//
226// Host pointer identity can be assumed as long as the type of access
227// is the same. In the example above, if both accesses were of type
228// Class then the host pointer will be the same, so it is safe to
229// retrieve the target address of an instance and then later get
230// a new host pointer for the target address using the same type as
231// the host pointer in that case will be the same. This is enabled
232// by caching all of the retrieved host instances. This cache is searched
233// by the addr:size pair and when there's a match the existing instance
234// is reused. This increases performance and also allows simple
235// pointer identity to hold. It does mean that host memory grows
236// in proportion to the amount of target memory being referenced,
237// so retrieving extraneous data should be avoided.
238// The host-side data cache grows until the Flush() method is called,
239// at which point all host-side data is discarded. No host
240// instance pointers should be held across a Flush().
241//
242// Accessing into an object can lead to some unusual behavior. For
243// example, the SList class relies on objects to contain an SLink
244// instance that it uses for list maintenance. This SLink can be
245// embedded anywhere in the larger object. The SList access is always
246// purely to an SLink, so when using the access layer it will only
247// retrieve an SLink's worth of data. The SList template will then
248// do some address arithmetic to determine the start of the real
249// object and cast the resulting pointer to the final object type.
250// When using the access layer this results in a new ?PTR being
251// created and used, so a new instance will result. The internal
252// SLink instance will have no relation to the new object instance
253// even though in target address terms one is embedded in the other.
254// The assumption of data stability means that this won't cause
255// a problem, but care must be taken with the address arithmetic,
256// as layed out in rules #2 and #3.
257//
258// 4. Global address references cannot be used. Any reference to a
259// global piece of code or data, such as a function address, global
260// variable or class static variable, must be changed.
261//
262// The external access code may load at a different base address than
263// the target process code. Global addresses are therefore not
264// meaningful and must be replaced with something else. There isn't
265// a single solution, so replacements must be done on a case-by-case
266// basis.
267//
268// The simplest case is a global or class static variable. All
269// declarations must be replaced with a special declaration that
270// compiles into a modified accessor template value when compiled for
271// external data access. Uses of the variable automatically are fixed
272// up by the template instance. Note that assignment to the global
273// must be independently ifdef'ed as the external access layer should
274// not make any modifications.
275//
276// Macros allow for simple declaration of a class static and global
277// values that compile into an appropriate templated value.
278//
279// Previous Code:
280//
281// static RangeSection* m_RangeTree;
282// RangeSection* ExecutionManager::m_RangeTree;
283//
284// extern ThreadStore* g_pThreadStore;
285// ThreadStore* g_pThreadStore = &StaticStore;
286// class SystemDomain : public BaseDomain {
287// ...
288// ArrayListStatic m_appDomainIndexList;
289// ...
290// }
291//
292// SystemDomain::m_appDomainIndexList;
293//
294// extern DWORD gThreadTLSIndex;
295//
296// DWORD gThreadTLSIndex = TLS_OUT_OF_INDEXES;
297//
298// Modified Code:
299//
300// typedef DPTR(RangeSection) PTR_RangeSection;
301// SPTR_DECL(RangeSection, m_RangeTree);
302// SPTR_IMPL(RangeSection, ExecutionManager, m_RangeTree);
303//
304// typedef DPTR(ThreadStore) PTR_ThreadStore
305// GPTR_DECL(ThreadStore, g_pThreadStore);
306// GPTR_IMPL_INIT(ThreadStore, g_pThreadStore, &StaticStore);
307//
308// class SystemDomain : public BaseDomain {
309// ...
310// SVAL_DECL(ArrayListStatic; m_appDomainIndexList);
311// ...
312// }
313//
314// SVAL_IMPL(ArrayListStatic, SystemDomain, m_appDomainIndexList);
315//
316// GVAL_DECL(DWORD, gThreadTLSIndex);
317//
318// GVAL_IMPL_INIT(DWORD, gThreadTLSIndex, TLS_OUT_OF_INDEXES);
319//
320// When declaring the variable, the first argument declares the
321// variable's type and the second argument declares the variable's
322// name. When defining the variable the arguments are similar, with
323// an extra class name parameter for the static class variable case.
324// If an initializer is needed the IMPL_INIT macro should be used.
325//
326// Things get slightly more complicated when declaring an embedded
327// array. In this case the data element is not a single element and
328// therefore cannot be represented by a ?PTR. In the case of a global
329// array, you should use the GARY_DECL and GARY_IMPL macros.
330// We durrently have no support for declaring static array data members
331// or initialized arrays. Array data members that are dynamically allocated
332// need to be treated as pointer members. To reference individual elements
333// you must use pointer arithmetic (see rule 2 above). An array declared
334// as a local variable within a function does not need to be DACized.
335//
336//
337// All uses of ?VAL_DECL must have a corresponding entry given in the
338// DacGlobals structure in src\inc\dacvars.h. For SVAL_DECL the entry
339// is class__name. For GVAL_DECL the entry is dac__name. You must add
340// these entries in dacvars.h using the DEFINE_DACVAR macro. Note that
341// these entries also are used for dumping memory in mini dumps and
342// heap dumps. If it's not appropriate to dump a variable, (e.g.,
343// it's an array or some other value that is not important to have
344// in a minidump) a second macro, DEFINE_DACVAR_NO_DUMP, will allow
345// you to make the required entry in the DacGlobals structure without
346// dumping its value.
347//
348// For convenience, here is a list of the various variable declaration and
349// initialization macros:
350// SVAL_DECL(type, name) static non-pointer data class MyClass
351// member declared within {
352// the class declaration // static int i;
353// SVAL_DECL(int, i);
354// }
355//
356// SVAL_IMPL(type, cls, name) static non-pointer data // int MyClass::i;
357// member defined outside SVAL_IMPL(int, MyClass, i);
358// the class declaration
359//
360// SVAL_IMPL_INIT(type, cls, static non-pointer data // int MyClass::i = 0;
361// name, val) member defined and SVAL_IMPL_INIT(int, MyClass, i, 0);
362// initialized outside the
363// class declaration
364// ------------------------------------------------------------------------------------------------
365// SPTR_DECL(type, name) static pointer data class MyClass
366// member declared within {
367// the class declaration // static int * pInt;
368// SPTR_DECL(int, pInt);
369// }
370//
371// SPTR_IMPL(type, cls, name) static pointer data // int * MyClass::pInt;
372// member defined outside SPTR_IMPL(int, MyClass, pInt);
373// the class declaration
374//
375// SPTR_IMPL_INIT(type, cls, static pointer data // int * MyClass::pInt = NULL;
376// name, val) member defined and SPTR_IMPL_INIT(int, MyClass, pInt, NULL);
377// initialized outside the
378// class declaration
379// ------------------------------------------------------------------------------------------------
380// GVAL_DECL(type, name) extern declaration of // extern int g_i
381// global non-pointer GVAL_DECL(int, g_i);
382// variable
383//
384// GVAL_IMPL(type, name) declaration of a // int g_i
385// global non-pointer GVAL_IMPL(int, g_i);
386// variable
387//
388// GVAL_IMPL_INIT (type, declaration and // int g_i = 0;
389// name, initialization of a GVAL_IMPL_INIT(int, g_i, 0);
390// val) global non-pointer
391// variable
392// ****Note****
393// If you use GVAL_? to declare a global variable of a structured type and you need to
394// access a member of the type, you cannot use the dot operator. Instead, you must take the
395// address of the variable and use the arrow operator. For example:
396// struct
397// {
398// int x;
399// char ch;
400// } MyStruct;
401// GVAL_IMPL(MyStruct, g_myStruct);
402// int i = (&g_myStruct)->x;
403// ------------------------------------------------------------------------------------------------
404// GPTR_DECL(type, name) extern declaration of // extern int * g_pInt
405// global pointer GPTR_DECL(int, g_pInt);
406// variable
407//
408// GPTR_IMPL(type, name) declaration of a // int * g_pInt
409// global pointer GPTR_IMPL(int, g_pInt);
410// variable
411//
412// GPTR_IMPL_INIT (type, declaration and // int * g_pInt = 0;
413// name, initialization of a GPTR_IMPL_INIT(int, g_pInt, NULL);
414// val) global pointer
415// variable
416// ------------------------------------------------------------------------------------------------
417// GARY_DECL(type, name) extern declaration of // extern int g_rgIntList[MAX_ELEMENTS];
418// a global array GPTR_DECL(int, g_rgIntList, MAX_ELEMENTS);
419// variable
420//
421// GARY_IMPL(type, name) declaration of a // int g_rgIntList[MAX_ELEMENTS];
422// global pointer GPTR_IMPL(int, g_rgIntList, MAX_ELEMENTS);
423// variable
424//
425//
426// Certain pieces of code, such as the stack walker, rely on identifying
427// an object from its vtable address. As the target vtable addresses
428// do not necessarily correspond to the vtables used in the host, these
429// references must be translated. The access layer maintains translation
430// tables for all classes used with VPTR and can return the target
431// vtable pointer for any host vtable in the known list of VPTR classes.
432//
433// ----- Errors:
434//
435// All errors in the access layer are reported via exceptions. The
436// formal access layer methods catch all such exceptions and turn
437// them into the appropriate error, so this generally isn't visible
438// to users of the access layer.
439//
440// ----- DPTR Declaration:
441//
442// Create a typedef for the type with typedef DPTR(type) PTR_type;
443// Replace type* with PTR_type.
444//
445// ----- VPTR Declaration:
446//
447// VPTR can only be used on classes that have a single vtable
448// pointer at the beginning of the object. This should be true
449// for a normal single-inheritance object.
450//
451// All of the classes that may be instantiated need to be identified
452// and marked. In the base class declaration add either
453// VPTR_BASE_VTABLE_CLASS if the class is abstract or
454// VPTR_BASE_CONCRETE_VTABLE_CLASS if the class is concrete. In each
455// derived class add VPTR_VTABLE_CLASS. If you end up with compile or
456// link errors for an unresolved method called VPtrSize you missed a
457// derived class declaration.
458//
459// As described above, dac can only handle classes with a single
460// vtable. However, there's a special case for multiple inheritance
461// situations when only one of the classes is needed for dac. If
462// the base class needed is the first class in the derived class's
463// layout then it can be used with dac via using the VPTR_MULTI_CLASS
464// macros. Use with extreme care.
465//
466// All classes to be instantiated must be listed in src\inc\vptr_list.h.
467//
468// Create a typedef for the type with typedef VPTR(type) PTR_type;
469// When using a VPTR, replace Class* with PTR_Class.
470//
471// ----- Specific Macros:
472//
473// PTR_TO_TADDR(ptr)
474// Retrieves the raw target address for a ?PTR.
475// See code:dac_cast for the preferred alternative
476//
477// PTR_HOST_TO_TADDR(host)
478// Given a host address of an instance produced by a ?PTR reference,
479// return the original target address. The host address must
480// be an exact match for an instance.
481// See code:dac_cast for the preferred alternative
482//
483// PTR_HOST_INT_TO_TADDR(host)
484// Given a host address which resides somewhere within an instance
485// produced by a ?PTR reference (a host interior pointer) return the
486// corresponding target address. This is useful for evaluating
487// relative pointers (e.g. RelativePointer<T>) where calculating the
488// target address requires knowledge of the target address of the
489// relative pointer field itself. This lookup is slower than that for
490// a non-interior host pointer so use it sparingly.
491//
492// VPTR_HOST_VTABLE_TO_TADDR(host)
493// Given the host vtable pointer for a known VPTR class, return
494// the target vtable pointer.
495//
496// PTR_HOST_MEMBER_TADDR(type, host, memb)
497// Retrieves the target address of a host instance pointer and
498// offsets it by the given member's offset within the type.
499//
500// PTR_HOST_INT_MEMBER_TADDR(type, host, memb)
501// As above but will work for interior host pointers (see the
502// description of PTR_HOST_INT_TO_TADDR for an explanation of host
503// interior pointers).
504//
505// PTR_READ(addr, size)
506// Reads a block of memory from the target and returns a host
507// pointer for it. Useful for reading blocks of data from the target
508// whose size is only known at runtime, such as raw code for a jitted
509// method. If the data being read is actually an object, use SPTR
510// instead to get better type semantics.
511//
512// DAC_EMPTY()
513// DAC_EMPTY_ERR()
514// DAC_EMPTY_RET(retVal)
515// DAC_UNEXPECTED()
516// Provides an empty method implementation when compiled
517// for DACCESS_COMPILE. For example, use to stub out methods needed
518// for vtable entries but otherwise unused.
519//
520// These macros are designed to turn into normal code when compiled
521// without DACCESS_COMPILE.
522//
523//*****************************************************************************
524
525
526#ifndef __daccess_h__
527#define __daccess_h__
528
529#include <stdint.h>
530
531#include "switches.h"
532#include "safemath.h"
533#include "corerror.h"
534
535#ifndef __in
536#include <specstrings.h>
537#endif
538
539#define DACCESS_TABLE_RESOURCE "COREXTERNALDATAACCESSRESOURCE"
540
541#ifdef PAL_STDCPP_COMPAT
542#include <type_traits>
543#else
544#include "clr_std/type_traits"
545#include "crosscomp.h"
546#endif
547
548// Information stored in the DAC table of interest to the DAC implementation
549// Note that this information is shared between all instantiations of ClrDataAccess, so initialize
550// it just once in code:ClrDataAccess.GetDacGlobals (rather than use fields in ClrDataAccess);
551struct DacTableInfo
552{
553 // On Windows, the first DWORD is the 32-bit timestamp read out of the runtime dll's debug directory.
554 // The remaining 3 DWORDS must all be 0.
555 // On Mac, this is the 16-byte UUID of the runtime dll.
556 // It is used to validate that mscorwks is the same version as mscordacwks
557 DWORD dwID0;
558 DWORD dwID1;
559 DWORD dwID2;
560 DWORD dwID3;
561};
562
563// The header of the DAC table. This includes the number of globals, the number of vptrs, and
564// the DacTableInfo structure. We need the DacTableInfo and DacTableHeader structs outside
565// of a DACCESS_COMPILE since soshost walks the Dac table headers to find the UUID of CoreCLR
566// in the target process.
567struct DacTableHeader
568{
569 ULONG numGlobals;
570 ULONG numVptrs;
571 DacTableInfo info;
572};
573
574//
575// This version of things wraps pointer access in
576// templates which understand how to retrieve data
577// through an access layer. In this case no assumptions
578// can be made that the current compilation processor or
579// pointer types match the target's processor or pointer types.
580//
581
582// Define TADDR as a non-pointer value so use of it as a pointer
583// will not work properly. Define it as unsigned so
584// pointer comparisons aren't affected by sign.
585// This requires special casting to ULONG64 to sign-extend if necessary.
586typedef ULONG_PTR TADDR;
587
588// TSIZE_T used for counts or ranges that need to span the size of a
589// target pointer. For cross-plat, this may be different than SIZE_T
590// which reflects the host pointer size.
591typedef SIZE_T TSIZE_T;
592
593
594//
595// The following table contains all the global information that data access needs to begin
596// operation. All of the values stored here are RVAs. DacGlobalBase() returns the current
597// base address to combine with to get a full target address.
598//
599
600typedef struct _DacGlobals
601{
602#ifdef FEATURE_PAL
603 static void Initialize();
604 void InitializeEntries(TADDR baseAddress);
605#endif // FEATURE_PAL
606
607// These will define all of the dac related mscorwks static and global variables
608#define DEFINE_DACVAR(id_type, size, id, var) id_type id;
609#define DEFINE_DACVAR_NO_DUMP(id_type, size, id, var) id_type id;
610#include "dacvars.h"
611
612 // Global functions.
613 ULONG fn__ThreadpoolMgr__AsyncTimerCallbackCompletion;
614 ULONG fn__DACNotifyCompilationFinished;
615 ULONG fn__ThePreStub;
616
617#ifdef _TARGET_ARM_
618 ULONG fn__ThePreStubCompactARM;
619#endif // _TARGET_ARM_
620
621 ULONG fn__ThePreStubPatchLabel;
622 ULONG fn__PrecodeFixupThunk;
623 ULONG fn__StubDispatchFixupStub;
624 ULONG fn__StubDispatchFixupPatchLabel;;
625#ifdef FEATURE_COMINTEROP
626 ULONG fn__Unknown_AddRef;
627 ULONG fn__Unknown_AddRefSpecial;
628 ULONG fn__Unknown_AddRefInner;
629#endif
630
631 // Vtable pointer values for all classes that must
632 // be instanted using vtable pointers as the identity.
633#define VPTR_CLASS(name) ULONG name##__vtAddr;
634#define VPTR_MULTI_CLASS(name, keyBase) ULONG name##__##keyBase##__mvtAddr;
635#include <vptr_list.h>
636#undef VPTR_CLASS
637#undef VPTR_MULTI_CLASS
638} DacGlobals;
639
640#ifdef DACCESS_COMPILE
641
642extern DacTableInfo g_dacTableInfo;
643extern DacGlobals g_dacGlobals;
644
645#ifdef __cplusplus
646extern "C" {
647#endif
648
649// These two functions are largely just for marking code
650// that is not fully converted. DacWarning prints a debug
651// message, while DacNotImpl throws a not-implemented exception.
652void __cdecl DacWarning(__in __in_z char* format, ...);
653void DacNotImpl(void);
654
655void DacError(HRESULT err);
656void DECLSPEC_NORETURN DacError_NoRet(HRESULT err);
657TADDR DacGlobalBase(void);
658HRESULT DacReadAll(TADDR addr, PVOID buffer, ULONG32 size, bool throwEx);
659HRESULT DacWriteAll(TADDR addr, PVOID buffer, ULONG32 size, bool throwEx);
660HRESULT DacAllocVirtual(TADDR addr, ULONG32 size,
661 ULONG32 typeFlags, ULONG32 protectFlags,
662 bool throwEx, TADDR* mem);
663HRESULT DacFreeVirtual(TADDR mem, ULONG32 size, ULONG32 typeFlags,
664 bool throwEx);
665PVOID DacInstantiateTypeByAddress(TADDR addr, ULONG32 size, bool throwEx);
666PVOID DacInstantiateTypeByAddressNoReport(TADDR addr, ULONG32 size, bool throwEx);
667PVOID DacInstantiateClassByVTable(TADDR addr, ULONG32 minSize, bool throwEx);
668
669// Copy a null-terminated ascii or unicode string from the target to the host.
670// Note that most of the work here is to find the null terminator. If you know the exact length,
671// then you can also just call DacInstantiateTypebyAddress.
672PSTR DacInstantiateStringA(TADDR addr, ULONG32 maxChars, bool throwEx);
673PWSTR DacInstantiateStringW(TADDR addr, ULONG32 maxChars, bool throwEx);
674
675TADDR DacGetTargetAddrForHostAddr(LPCVOID ptr, bool throwEx);
676TADDR DacGetTargetAddrForHostInteriorAddr(LPCVOID ptr, bool throwEx);
677TADDR DacGetTargetVtForHostVt(LPCVOID vtHost, bool throwEx);
678PWSTR DacGetVtNameW(TADDR targetVtable);
679
680// Report a region of memory to the debugger
681bool DacEnumMemoryRegion(TADDR addr, TSIZE_T size, bool fExpectSuccess = true);
682
683// Report a region of memory to the debugger
684bool DacUpdateMemoryRegion(TADDR addr, TSIZE_T bufferSize, BYTE* buffer);
685
686HRESULT DacWriteHostInstance(PVOID host, bool throwEx);
687
688// This is meant to mimic the RethrowTerminalExceptions/
689// SwallowAllExceptions/RethrowTransientExceptions macros to allow minidump
690// gathering cancelation for details see
691// code:ClrDataAccess.EnumMemoryRegionsWrapper
692
693// This is usable in EX_TRY exactly how RethrowTerminalExceptions et cetera
694#define RethrowCancelExceptions \
695 if (GET_EXCEPTION()->GetHR() == COR_E_OPERATIONCANCELED) \
696 { \
697 EX_RETHROW; \
698 }
699
700// Occasionally it's necessary to allocate some host memory for
701// instance data that's created on the fly and so doesn't directly
702// correspond to target memory. These are held and freed on flush
703// like other instances but can't be looked up by address.
704PVOID DacAllocHostOnlyInstance(ULONG32 size, bool throwEx);
705
706// Determines whether ASSERTs should be raised when inconsistencies in the target are detected
707bool DacTargetConsistencyAssertsEnabled();
708
709// Host instances can be marked as they are enumerated in
710// order to break cycles. This function returns true if
711// the instance is already marked, otherwise it marks the
712// instance and returns false.
713bool DacHostPtrHasEnumMark(LPCVOID host);
714
715// Determines if EnumMemoryRegions has been called on a method descriptor.
716// This helps perf for minidumps of apps with large managed stacks.
717bool DacHasMethodDescBeenEnumerated(LPCVOID pMD);
718
719// Sets a flag indicating that EnumMemoryRegions on a method desciptor
720// has been successfully called. The function returns true if
721// this flag had been previously set.
722bool DacSetMethodDescEnumerated(LPCVOID pMD);
723
724// Determines if a method descriptor is valid
725BOOL DacValidateMD(LPCVOID pMD);
726
727// Enumerate the instructions around a call site to help debugger stack walking heuristics
728void DacEnumCodeForStackwalk(TADDR taCallEnd);
729
730// Given the address and the size of a memory range which is stored in the buffer, replace all the patches
731// in the buffer with the real opcodes. This is especially important on X64 where the unwinder needs to
732// disassemble the native instructions.
733class MemoryRange;
734HRESULT DacReplacePatchesInHostMemory(MemoryRange range, PVOID pBuffer);
735
736//
737// Convenience macros for EnumMemoryRegions implementations.
738//
739
740// Enumerate the given host instance and return
741// true if the instance hasn't already been enumerated.
742#define DacEnumHostDPtrMem(host) \
743 (!DacHostPtrHasEnumMark(host) ? \
744 (DacEnumMemoryRegion(PTR_HOST_TO_TADDR(host), sizeof(*host)), \
745 true) : false)
746#define DacEnumHostSPtrMem(host, type) \
747 (!DacHostPtrHasEnumMark(host) ? \
748 (DacEnumMemoryRegion(PTR_HOST_TO_TADDR(host), \
749 type::DacSize(PTR_HOST_TO_TADDR(host))), \
750 true) : false)
751#define DacEnumHostVPtrMem(host) \
752 (!DacHostPtrHasEnumMark(host) ? \
753 (DacEnumMemoryRegion(PTR_HOST_TO_TADDR(host), (host)->VPtrSize()), \
754 true) : false)
755
756// Check enumeration of 'this' and return if this has already been
757// enumerated. Making this the first line of an object's EnumMemoryRegions
758// method will prevent cycles.
759#define DAC_CHECK_ENUM_THIS() \
760 if (DacHostPtrHasEnumMark(this)) return
761#define DAC_ENUM_DTHIS() \
762 if (!DacEnumHostDPtrMem(this)) return
763#define DAC_ENUM_STHIS(type) \
764 if (!DacEnumHostSPtrMem(this, type)) return
765#define DAC_ENUM_VTHIS() \
766 if (!DacEnumHostVPtrMem(this)) return
767
768#ifdef __cplusplus
769}
770class ReflectionModule;
771interface IMDInternalImport* DacGetMDImport(const class PEFile* peFile,
772 bool throwEx);
773interface IMDInternalImport* DacGetMDImport(const ReflectionModule* reflectionModule,
774 bool throwEx);
775
776int DacGetIlMethodSize(TADDR methAddr);
777struct COR_ILMETHOD* DacGetIlMethod(TADDR methAddr);
778#ifdef WIN64EXCEPTIONS
779struct _UNWIND_INFO * DacGetUnwindInfo(TADDR taUnwindInfo);
780
781// virtually unwind a CONTEXT out-of-process
782struct _KNONVOLATILE_CONTEXT_POINTERS;
783BOOL DacUnwindStackFrame(T_CONTEXT * pContext, T_KNONVOLATILE_CONTEXT_POINTERS* pContextPointers);
784#endif // WIN64EXCEPTIONS
785
786#if defined(FEATURE_PAL)
787// call back through data target to unwind out-of-process
788HRESULT DacVirtualUnwind(ULONG32 threadId, PT_CONTEXT context, PT_KNONVOLATILE_CONTEXT_POINTERS contextPointers);
789#endif // FEATURE_PAL
790
791#ifdef FEATURE_MINIMETADATA_IN_TRIAGEDUMPS
792class SString;
793void DacMdCacheAddEEName(TADDR taEE, const SString& ssEEName);
794bool DacMdCacheGetEEName(TADDR taEE, SString & ssEEName);
795#endif // FEATURE_MINIMETADATA_IN_TRIAGEDUMPS
796
797//
798// Computes (taBase + (dwIndex * dwElementSize()), with overflow checks.
799//
800// Arguments:
801// taBase the base TADDR value
802// dwIndex the index of the offset
803// dwElementSize the size of each element (to multiply the offset by)
804//
805// Return value:
806// The resulting TADDR, or throws CORDB_E_TARGET_INCONSISTENT on overlow.
807//
808// Notes:
809// The idea here is that overflows during address arithmetic suggest that we're operating on corrupt
810// pointers. It helps to improve reliability to detect the cases we can (like overflow) and fail. Note
811// that this is just a heuristic, not a security measure. We can't trust target data regardless -
812// failing on overflow is just one easy case of corruption to detect. There is no need to use checked
813// arithmetic everywhere in the DAC infrastructure, this is intended just for the places most likely to
814// help catch bugs (eg. __DPtr::operator[]).
815//
816inline TADDR DacTAddrOffset( TADDR taBase, TSIZE_T dwIndex, TSIZE_T dwElementSize )
817{
818 ClrSafeInt<TADDR> t(taBase);
819 t += ClrSafeInt<TSIZE_T>(dwIndex) * ClrSafeInt<TSIZE_T>(dwElementSize);
820 if( t.IsOverflow() )
821 {
822 // Pointer arithmetic overflow - probably due to corrupt target data
823 DacError(CORDBG_E_TARGET_INCONSISTENT);
824 }
825 return t.Value();
826}
827
828
829// Base pointer wrapper which provides common behavior.
830class __TPtrBase
831{
832public:
833 __TPtrBase(void)
834 {
835 // Make uninitialized pointers obvious.
836 m_addr = (TADDR)-1;
837 }
838 __TPtrBase(TADDR addr)
839 {
840 m_addr = addr;
841 }
842
843 bool operator!() const
844 {
845 return m_addr == 0;
846 }
847 // We'd like to have an implicit conversion to bool here since the C++
848 // standard says all pointer types are implicitly converted to bool.
849 // Unfortunately, that would cause ambiguous overload errors for uses
850 // of operator== and operator!=. Instead callers will have to compare
851 // directly against NULL.
852
853 bool operator==(TADDR addr) const
854 {
855 return m_addr == addr;
856 }
857 bool operator!=(TADDR addr) const
858 {
859 return m_addr != addr;
860 }
861 bool operator<(TADDR addr) const
862 {
863 return m_addr < addr;
864 }
865 bool operator>(TADDR addr) const
866 {
867 return m_addr > addr;
868 }
869 bool operator<=(TADDR addr) const
870 {
871 return m_addr <= addr;
872 }
873 bool operator>=(TADDR addr) const
874 {
875 return m_addr >= addr;
876 }
877
878 TADDR GetAddr(void) const
879 {
880 return m_addr;
881 }
882 TADDR SetAddr(TADDR addr)
883 {
884 m_addr = addr;
885 return addr;
886 }
887
888protected:
889 TADDR m_addr;
890};
891
892// Pointer wrapper base class for various forms of normal data.
893// This has the common functionality between __DPtr and __ArrayDPtr.
894// The DPtrType type parameter is the actual derived type in use. This is necessary so that
895// inhereted functions preserve exact return types.
896template<typename type, typename DPtrType>
897class __DPtrBase : public __TPtrBase
898{
899public:
900 typedef type _Type;
901 typedef type* _Ptr;
902
903protected:
904 // Constructors
905 // All protected - this type should not be used directly - use one of the derived types instead.
906 __DPtrBase< type, DPtrType >(void) : __TPtrBase() {}
907 __DPtrBase< type, DPtrType >(TADDR addr) : __TPtrBase(addr) {}
908
909 explicit __DPtrBase< type, DPtrType >(__TPtrBase addr)
910 {
911 m_addr = addr.GetAddr();
912 }
913 explicit __DPtrBase< type, DPtrType >(type const * host)
914 {
915 m_addr = DacGetTargetAddrForHostAddr(host, true);
916 }
917
918public:
919 DPtrType& operator=(const __TPtrBase& ptr)
920 {
921 m_addr = ptr.GetAddr();
922 return DPtrType(m_addr);
923 }
924 DPtrType& operator=(TADDR addr)
925 {
926 m_addr = addr;
927 return DPtrType(m_addr);
928 }
929
930 type& operator*(void) const
931 {
932 return *(type*)DacInstantiateTypeByAddress(m_addr, sizeof(type), true);
933 }
934
935 bool operator==(const DPtrType& ptr) const
936 {
937 return m_addr == ptr.GetAddr();
938 }
939 bool operator==(TADDR addr) const
940 {
941 return m_addr == addr;
942 }
943 bool operator!=(const DPtrType& ptr) const
944 {
945 return !operator==(ptr);
946 }
947 bool operator!=(TADDR addr) const
948 {
949 return m_addr != addr;
950 }
951 bool operator<(const DPtrType& ptr) const
952 {
953 return m_addr < ptr.GetAddr();
954 }
955 bool operator>(const DPtrType& ptr) const
956 {
957 return m_addr > ptr.GetAddr();
958 }
959 bool operator<=(const DPtrType& ptr) const
960 {
961 return m_addr <= ptr.GetAddr();
962 }
963 bool operator>=(const DPtrType& ptr) const
964 {
965 return m_addr >= ptr.GetAddr();
966 }
967
968 // Array index operator
969 // we want an operator[] for all possible numeric types (rather than rely on
970 // implicit numeric conversions on the argument) to prevent ambiguity with
971 // DPtr's implicit conversion to type* and the built-in operator[].
972 // @dbgtodo : we could also use this technique to simplify other operators below.
973 template<typename indexType>
974 type& operator[](indexType index)
975 {
976 // Compute the address of the element.
977 TADDR elementAddr;
978 if( index >= 0 )
979 {
980 elementAddr = DacTAddrOffset(m_addr, index, sizeof(type));
981 }
982 else
983 {
984 // Don't bother trying to do overflow checking for negative indexes - they are rare compared to
985 // positive ones. ClrSafeInt doesn't support signed datatypes yet (although we should be able to add it
986 // pretty easily).
987 elementAddr = m_addr + index * sizeof(type);
988 }
989
990 // Marshal over a single instance and return a reference to it.
991 return *(type*) DacInstantiateTypeByAddress(elementAddr, sizeof(type), true);
992 }
993
994 template<typename indexType>
995 type const & operator[](indexType index) const
996 {
997 return (*const_cast<__DPtrBase*>(this))[index];
998 }
999
1000 //-------------------------------------------------------------------------
1001 // operator+
1002
1003 DPtrType operator+(unsigned short val)
1004 {
1005 return DPtrType(DacTAddrOffset(m_addr, val, sizeof(type)));
1006 }
1007 DPtrType operator+(short val)
1008 {
1009 return DPtrType(m_addr + val * sizeof(type));
1010 }
1011 // size_t is unsigned int on Win32, so we need
1012 // to ifdef here to make sure the unsigned int
1013 // and size_t overloads don't collide. size_t
1014 // is marked __w64 so a simple unsigned int
1015 // will not work on Win32, it has to be size_t.
1016 DPtrType operator+(size_t val)
1017 {
1018 return DPtrType(DacTAddrOffset(m_addr, val, sizeof(type)));
1019 }
1020#if defined (_WIN64)
1021 DPtrType operator+(unsigned int val)
1022 {
1023 return DPtrType(DacTAddrOffset(m_addr, val, sizeof(type)));
1024 }
1025#endif
1026 DPtrType operator+(int val)
1027 {
1028 return DPtrType(m_addr + val * sizeof(type));
1029 }
1030 // Because of the size difference between long and int on non MS compilers,
1031 // we only need to define these operators on Windows. These provide compatible
1032 // overloads for DWORD addition operations.
1033#ifdef _MSC_VER
1034 DPtrType operator+(unsigned long val)
1035 {
1036 return DPtrType(DacTAddrOffset(m_addr, val, sizeof(type)));
1037 }
1038 DPtrType operator+(long val)
1039 {
1040 return DPtrType(m_addr + val * sizeof(type));
1041 }
1042#endif
1043
1044 //-------------------------------------------------------------------------
1045 // operator-
1046
1047 DPtrType operator-(unsigned short val)
1048 {
1049 return DPtrType(m_addr - val * sizeof(type));
1050 }
1051 DPtrType operator-(short val)
1052 {
1053 return DPtrType(m_addr - val * sizeof(type));
1054 }
1055 // size_t is unsigned int on Win32, so we need
1056 // to ifdef here to make sure the unsigned int
1057 // and size_t overloads don't collide. size_t
1058 // is marked __w64 so a simple unsigned int
1059 // will not work on Win32, it has to be size_t.
1060 DPtrType operator-(size_t val)
1061 {
1062 return DPtrType(m_addr - val * sizeof(type));
1063 }
1064#ifdef _WIN64
1065 DPtrType operator-(unsigned int val)
1066 {
1067 return DPtrType(m_addr - val * sizeof(type));
1068 }
1069#endif
1070 DPtrType operator-(int val)
1071 {
1072 return DPtrType(m_addr - val * sizeof(type));
1073 }
1074 // Because of the size difference between long and int on non MS compilers,
1075 // we only need to define these operators on Windows. These provide compatible
1076 // overloads for DWORD addition operations.
1077#ifdef _MSC_VER // for now, everything else is 32 bit
1078 DPtrType operator-(unsigned long val)
1079 {
1080 return DPtrType(m_addr - val * sizeof(type));
1081 }
1082 DPtrType operator-(long val)
1083 {
1084 return DPtrType(m_addr - val * sizeof(type));
1085 }
1086#endif
1087 size_t operator-(const DPtrType& val)
1088 {
1089 return (m_addr - val.m_addr) / sizeof(type);
1090 }
1091
1092 //-------------------------------------------------------------------------
1093
1094 DPtrType& operator+=(size_t val)
1095 {
1096 m_addr += val * sizeof(type);
1097 return static_cast<DPtrType&>(*this);
1098 }
1099 DPtrType& operator-=(size_t val)
1100 {
1101 m_addr -= val * sizeof(type);
1102 return static_cast<DPtrType&>(*this);
1103 }
1104
1105 DPtrType& operator++()
1106 {
1107 m_addr += sizeof(type);
1108 return static_cast<DPtrType&>(*this);
1109 }
1110 DPtrType& operator--()
1111 {
1112 m_addr -= sizeof(type);
1113 return static_cast<DPtrType&>(*this);
1114 }
1115 DPtrType operator++(int postfix)
1116 {
1117 DPtrType orig = DPtrType(*this);
1118 m_addr += sizeof(type);
1119 return orig;
1120 }
1121 DPtrType operator--(int postfix)
1122 {
1123 DPtrType orig = DPtrType(*this);
1124 m_addr -= sizeof(type);
1125 return orig;
1126 }
1127
1128 bool IsValid(void) const
1129 {
1130 return m_addr &&
1131 DacInstantiateTypeByAddress(m_addr, sizeof(type),
1132 false) != NULL;
1133 }
1134 void EnumMem(void) const
1135 {
1136 DacEnumMemoryRegion(m_addr, sizeof(type));
1137 }
1138};
1139
1140// forward declaration
1141template<typename acc_type, typename store_type>
1142class __GlobalPtr;
1143
1144// Pointer wrapper for objects which are just plain data
1145// and need no special handling.
1146template<typename type>
1147class __DPtr : public __DPtrBase<type,__DPtr<type> >
1148{
1149public:
1150 // constructors - all chain to __DPtrBase constructors
1151 __DPtr< type >(void) : __DPtrBase<type,__DPtr<type> >() {}
1152 __DPtr< type >(TADDR addr) : __DPtrBase<type,__DPtr<type> >(addr) {}
1153
1154 // construct const from non-const
1155 typedef typename std::remove_const<type>::type mutable_type;
1156 __DPtr< type >(__DPtr<mutable_type> const & rhs) : __DPtrBase<type,__DPtr<type> >(rhs.GetAddr()) {}
1157
1158 // construct from GlobalPtr
1159 explicit __DPtr< type >(__GlobalPtr< type*, __DPtr< type > > globalPtr) :
1160 __DPtrBase<type,__DPtr<type> >(globalPtr.GetAddr()) {}
1161
1162 explicit __DPtr< type >(__TPtrBase addr) : __DPtrBase<type,__DPtr<type> >(addr) {}
1163 explicit __DPtr< type >(type const * host) : __DPtrBase<type,__DPtr<type> >(host) {}
1164
1165 operator type*() const
1166 {
1167 return (type*)DacInstantiateTypeByAddress(this->m_addr, sizeof(type), true);
1168 }
1169 type* operator->() const
1170 {
1171 return (type*)DacInstantiateTypeByAddress(this->m_addr, sizeof(type), true);
1172 }
1173};
1174
1175#define DPTR(type) __DPtr< type >
1176
1177// A restricted form of DPtr that doesn't have any conversions to pointer types.
1178// This is useful for pointer types that almost always represent arrays, as opposed
1179// to pointers to single instances (eg. PTR_BYTE). In these cases, allowing implicit
1180// conversions to (for eg.) BYTE* would usually result in incorrect usage (eg. pointer
1181// arithmetic and array indexing), since only a single instance has been marshalled to the host.
1182// If you really must marshal a single instance (eg. converting T* to PTR_T is too painful for now),
1183// then use code:DacUnsafeMarshalSingleElement so we can identify such unsafe code.
1184template<typename type>
1185class __ArrayDPtr : public __DPtrBase<type,__ArrayDPtr<type> >
1186{
1187public:
1188 // constructors - all chain to __DPtrBase constructors
1189 __ArrayDPtr< type >(void) : __DPtrBase<type,__ArrayDPtr<type> >() {}
1190 __ArrayDPtr< type >(TADDR addr) : __DPtrBase<type,__ArrayDPtr<type> >(addr) {}
1191
1192 // construct const from non-const
1193 typedef typename std::remove_const<type>::type mutable_type;
1194 __ArrayDPtr< type >(__ArrayDPtr<mutable_type> const & rhs) : __DPtrBase<type,__ArrayDPtr<type> >(rhs.GetAddr()) {}
1195
1196 explicit __ArrayDPtr< type >(__TPtrBase addr) : __DPtrBase<type,__ArrayDPtr<type> >(addr) {}
1197
1198 // Note that there is also no explicit constructor from host instances (type*).
1199 // Going this direction is less problematic, but often still represents risky coding.
1200};
1201
1202#define ArrayDPTR(type) __ArrayDPtr< type >
1203
1204
1205// Pointer wrapper for objects which are just plain data
1206// but whose size is not the same as the base type size.
1207// This can be used for prefetching data for arrays or
1208// for cases where an object has a variable size.
1209template<typename type>
1210class __SPtr : public __TPtrBase
1211{
1212public:
1213 typedef type _Type;
1214 typedef type* _Ptr;
1215
1216 __SPtr< type >(void) : __TPtrBase() {}
1217 __SPtr< type >(TADDR addr) : __TPtrBase(addr) {}
1218 explicit __SPtr< type >(__TPtrBase addr)
1219 {
1220 m_addr = addr.GetAddr();
1221 }
1222 explicit __SPtr< type >(type* host)
1223 {
1224 m_addr = DacGetTargetAddrForHostAddr(host, true);
1225 }
1226
1227 __SPtr< type >& operator=(const __TPtrBase& ptr)
1228 {
1229 m_addr = ptr.GetAddr();
1230 return *this;
1231 }
1232 __SPtr< type >& operator=(TADDR addr)
1233 {
1234 m_addr = addr;
1235 return *this;
1236 }
1237
1238 operator type*() const
1239 {
1240 if (m_addr)
1241 {
1242 return (type*)DacInstantiateTypeByAddress(m_addr,
1243 type::DacSize(m_addr),
1244 true);
1245 }
1246 else
1247 {
1248 return (type*)NULL;
1249 }
1250 }
1251 type* operator->() const
1252 {
1253 if (m_addr)
1254 {
1255 return (type*)DacInstantiateTypeByAddress(m_addr,
1256 type::DacSize(m_addr),
1257 true);
1258 }
1259 else
1260 {
1261 return (type*)NULL;
1262 }
1263 }
1264 type& operator*(void) const
1265 {
1266 if (!m_addr)
1267 {
1268 DacError(E_INVALIDARG);
1269 }
1270
1271 return *(type*)DacInstantiateTypeByAddress(m_addr,
1272 type::DacSize(m_addr),
1273 true);
1274 }
1275
1276 bool IsValid(void) const
1277 {
1278 return m_addr &&
1279 DacInstantiateTypeByAddress(m_addr, type::DacSize(m_addr),
1280 false) != NULL;
1281 }
1282 void EnumMem(void) const
1283 {
1284 if (m_addr)
1285 {
1286 DacEnumMemoryRegion(m_addr, type::DacSize(m_addr));
1287 }
1288 }
1289};
1290
1291#define SPTR(type) __SPtr< type >
1292
1293// Pointer wrapper for objects which have a single leading
1294// vtable, such as objects in a single-inheritance tree.
1295// The base class of all such trees must have use
1296// VPTR_BASE_VTABLE_CLASS in their declaration and all
1297// instantiable members of the tree must be listed in vptr_list.h.
1298template<class type>
1299class __VPtr : public __TPtrBase
1300{
1301public:
1302 // VPtr::_Type has to be a pointer as
1303 // often the type is an abstract class.
1304 // This type is not expected to be used anyway.
1305 typedef type* _Type;
1306 typedef type* _Ptr;
1307
1308 __VPtr< type >(void) : __TPtrBase() {}
1309 __VPtr< type >(TADDR addr) : __TPtrBase(addr) {}
1310 explicit __VPtr< type >(__TPtrBase addr)
1311 {
1312 m_addr = addr.GetAddr();
1313 }
1314 explicit __VPtr< type >(type* host)
1315 {
1316 m_addr = DacGetTargetAddrForHostAddr(host, true);
1317 }
1318
1319 __VPtr< type >& operator=(const __TPtrBase& ptr)
1320 {
1321 m_addr = ptr.GetAddr();
1322 return *this;
1323 }
1324 __VPtr< type >& operator=(TADDR addr)
1325 {
1326 m_addr = addr;
1327 return *this;
1328 }
1329
1330 operator type*() const
1331 {
1332 return (type*)DacInstantiateClassByVTable(m_addr, sizeof(type), true);
1333 }
1334 type* operator->() const
1335 {
1336 return (type*)DacInstantiateClassByVTable(m_addr, sizeof(type), true);
1337 }
1338
1339 bool operator==(const __VPtr< type >& ptr) const
1340 {
1341 return m_addr == ptr.m_addr;
1342 }
1343 bool operator==(TADDR addr) const
1344 {
1345 return m_addr == addr;
1346 }
1347 bool operator!=(const __VPtr< type >& ptr) const
1348 {
1349 return !operator==(ptr);
1350 }
1351 bool operator!=(TADDR addr) const
1352 {
1353 return m_addr != addr;
1354 }
1355
1356 bool IsValid(void) const
1357 {
1358 return m_addr &&
1359 DacInstantiateClassByVTable(m_addr, sizeof(type), false) != NULL;
1360 }
1361 void EnumMem(void) const
1362 {
1363 if (IsValid())
1364 {
1365 DacEnumMemoryRegion(m_addr, (operator->())->VPtrSize());
1366 }
1367 }
1368};
1369
1370#define VPTR(type) __VPtr< type >
1371
1372// Pointer wrapper for 8-bit strings.
1373template<typename type, ULONG32 maxChars = 32760>
1374class __Str8Ptr : public __DPtr<char>
1375{
1376public:
1377 typedef type _Type;
1378 typedef type* _Ptr;
1379
1380 __Str8Ptr< type, maxChars >(void) : __DPtr<char>() {}
1381 __Str8Ptr< type, maxChars >(TADDR addr) : __DPtr<char>(addr) {}
1382 explicit __Str8Ptr< type, maxChars >(__TPtrBase addr)
1383 {
1384 m_addr = addr.GetAddr();
1385 }
1386 explicit __Str8Ptr< type, maxChars >(type* host)
1387 {
1388 m_addr = DacGetTargetAddrForHostAddr(host, true);
1389 }
1390
1391 __Str8Ptr< type, maxChars >& operator=(const __TPtrBase& ptr)
1392 {
1393 m_addr = ptr.GetAddr();
1394 return *this;
1395 }
1396 __Str8Ptr< type, maxChars >& operator=(TADDR addr)
1397 {
1398 m_addr = addr;
1399 return *this;
1400 }
1401
1402 operator type*() const
1403 {
1404 return (type*)DacInstantiateStringA(m_addr, maxChars, true);
1405 }
1406
1407 bool IsValid(void) const
1408 {
1409 return m_addr &&
1410 DacInstantiateStringA(m_addr, maxChars, false) != NULL;
1411 }
1412 void EnumMem(void) const
1413 {
1414 char* str = DacInstantiateStringA(m_addr, maxChars, false);
1415 if (str)
1416 {
1417 DacEnumMemoryRegion(m_addr, strlen(str) + 1);
1418 }
1419 }
1420};
1421
1422#define S8PTR(type) __Str8Ptr< type >
1423#define S8PTRMAX(type, maxChars) __Str8Ptr< type, maxChars >
1424
1425// Pointer wrapper for 16-bit strings.
1426template<typename type, ULONG32 maxChars = 32760>
1427class __Str16Ptr : public __DPtr<WCHAR>
1428{
1429public:
1430 typedef type _Type;
1431 typedef type* _Ptr;
1432
1433 __Str16Ptr< type, maxChars >(void) : __DPtr<WCHAR>() {}
1434 __Str16Ptr< type, maxChars >(TADDR addr) : __DPtr<WCHAR>(addr) {}
1435 explicit __Str16Ptr< type, maxChars >(__TPtrBase addr)
1436 {
1437 m_addr = addr.GetAddr();
1438 }
1439 explicit __Str16Ptr< type, maxChars >(type* host)
1440 {
1441 m_addr = DacGetTargetAddrForHostAddr(host, true);
1442 }
1443
1444 __Str16Ptr< type, maxChars >& operator=(const __TPtrBase& ptr)
1445 {
1446 m_addr = ptr.GetAddr();
1447 return *this;
1448 }
1449 __Str16Ptr< type, maxChars >& operator=(TADDR addr)
1450 {
1451 m_addr = addr;
1452 return *this;
1453 }
1454
1455 operator type*() const
1456 {
1457 return (type*)DacInstantiateStringW(m_addr, maxChars, true);
1458 }
1459
1460 bool IsValid(void) const
1461 {
1462 return m_addr &&
1463 DacInstantiateStringW(m_addr, maxChars, false) != NULL;
1464 }
1465 void EnumMem(void) const
1466 {
1467 char* str = DacInstantiateStringW(m_addr, maxChars, false);
1468 if (str)
1469 {
1470 DacEnumMemoryRegion(m_addr, strlen(str) + 1);
1471 }
1472 }
1473};
1474
1475#define S16PTR(type) __Str16Ptr< type >
1476#define S16PTRMAX(type, maxChars) __Str16Ptr< type, maxChars >
1477
1478template<typename type>
1479class __GlobalVal
1480{
1481public:
1482 __GlobalVal< type >(PULONG rvaPtr)
1483 {
1484 m_rvaPtr = rvaPtr;
1485 }
1486
1487 operator type() const
1488 {
1489 return (type)*__DPtr< type >(DacGlobalBase() + *m_rvaPtr);
1490 }
1491
1492 __DPtr< type > operator&() const
1493 {
1494 return __DPtr< type >(DacGlobalBase() + *m_rvaPtr);
1495 }
1496
1497 // @dbgtodo dac support: This updates values in the host. This seems extremely dangerous
1498 // to do silently. I'd prefer that a specific (searchable) write function
1499 // was used. Try disabling this and see what fails...
1500 __GlobalVal<type> & operator=(const type & val)
1501 {
1502 type* ptr = __DPtr< type >(DacGlobalBase() + *m_rvaPtr);
1503 // Update the host copy;
1504 *ptr = val;
1505 // Write back to the target.
1506 DacWriteHostInstance(ptr, true);
1507 return *this;
1508 }
1509
1510 bool IsValid(void) const
1511 {
1512 return __DPtr< type >(DacGlobalBase() + *m_rvaPtr).IsValid();
1513 }
1514 void EnumMem(void) const
1515 {
1516 TADDR p = DacGlobalBase() + *m_rvaPtr;
1517 __DPtr< type >(p).EnumMem();
1518 }
1519
1520private:
1521 PULONG m_rvaPtr;
1522};
1523
1524template<typename type, size_t size>
1525class __GlobalArray
1526{
1527public:
1528 __GlobalArray< type, size >(PULONG rvaPtr)
1529 {
1530 m_rvaPtr = rvaPtr;
1531 }
1532
1533 __DPtr< type > operator&() const
1534 {
1535 return __DPtr< type >(DacGlobalBase() + *m_rvaPtr);
1536 }
1537
1538 type& operator[](unsigned int index) const
1539 {
1540 return __DPtr< type >(DacGlobalBase() + *m_rvaPtr)[index];
1541 }
1542
1543 bool IsValid(void) const
1544 {
1545 // Only validates the base pointer, not the full array range.
1546 return __DPtr< type >(DacGlobalBase() + *m_rvaPtr).IsValid();
1547 }
1548 void EnumMem(void) const
1549 {
1550 DacEnumMemoryRegion(DacGlobalBase() + *m_rvaPtr, sizeof(type) * size);
1551 }
1552
1553private:
1554 PULONG m_rvaPtr;
1555};
1556
1557template<typename acc_type, typename store_type>
1558class __GlobalPtr
1559{
1560public:
1561 __GlobalPtr< acc_type, store_type >(PULONG rvaPtr)
1562 {
1563 m_rvaPtr = rvaPtr;
1564 }
1565
1566 __DPtr< store_type > operator&() const
1567 {
1568 return __DPtr< store_type >(DacGlobalBase() + *m_rvaPtr);
1569 }
1570
1571 store_type & operator=(store_type & val)
1572 {
1573 store_type* ptr = __DPtr< store_type >(DacGlobalBase() + *m_rvaPtr);
1574 // Update the host copy;
1575 *ptr = val;
1576 // Write back to the target.
1577 DacWriteHostInstance(ptr, true);
1578 return val;
1579 }
1580
1581 acc_type operator->() const
1582 {
1583 return (acc_type)*__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr);
1584 }
1585 operator acc_type() const
1586 {
1587 return (acc_type)*__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr);
1588 }
1589 operator store_type() const
1590 {
1591 return *__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr);
1592 }
1593 bool operator!() const
1594 {
1595 return !*__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr);
1596 }
1597
1598 typename store_type::_Type& operator[](int index)
1599 {
1600 return (*__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr))[index];
1601 }
1602
1603 typename store_type::_Type& operator[](unsigned int index)
1604 {
1605 return (*__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr))[index];
1606 }
1607
1608 TADDR GetAddr() const
1609 {
1610 return (*__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr)).GetAddr();
1611 }
1612
1613 TADDR GetAddrRaw () const
1614 {
1615 return DacGlobalBase() + *m_rvaPtr;
1616 }
1617
1618 // This is only testing the the pointer memory is available but does not verify
1619 // the memory that it points to.
1620 //
1621 bool IsValidPtr(void) const
1622 {
1623 return __DPtr< store_type >(DacGlobalBase() + *m_rvaPtr).IsValid();
1624 }
1625
1626 bool IsValid(void) const
1627 {
1628 return __DPtr< store_type >(DacGlobalBase() + *m_rvaPtr).IsValid() &&
1629 (*__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr)).IsValid();
1630 }
1631 void EnumMem(void) const
1632 {
1633 __DPtr< store_type > ptr(DacGlobalBase() + *m_rvaPtr);
1634 ptr.EnumMem();
1635 if (ptr.IsValid())
1636 {
1637 (*ptr).EnumMem();
1638 }
1639 }
1640
1641 PULONG m_rvaPtr;
1642};
1643
1644template<typename acc_type, typename store_type>
1645inline bool operator==(const __GlobalPtr<acc_type, store_type>& gptr,
1646 acc_type host)
1647{
1648 return DacGetTargetAddrForHostAddr(host, true) ==
1649 *__DPtr< TADDR >(DacGlobalBase() + *gptr.m_rvaPtr);
1650}
1651template<typename acc_type, typename store_type>
1652inline bool operator!=(const __GlobalPtr<acc_type, store_type>& gptr,
1653 acc_type host)
1654{
1655 return !operator==(gptr, host);
1656}
1657
1658template<typename acc_type, typename store_type>
1659inline bool operator==(acc_type host,
1660 const __GlobalPtr<acc_type, store_type>& gptr)
1661{
1662 return DacGetTargetAddrForHostAddr(host, true) ==
1663 *__DPtr< TADDR >(DacGlobalBase() + *gptr.m_rvaPtr);
1664}
1665template<typename acc_type, typename store_type>
1666inline bool operator!=(acc_type host,
1667 const __GlobalPtr<acc_type, store_type>& gptr)
1668{
1669 return !operator==(host, gptr);
1670}
1671
1672
1673//
1674// __VoidPtr is a type that behaves like void* but for target pointers.
1675// Behavior of PTR_VOID:
1676// * has void* semantics. Will compile to void* in non-DAC builds (just like
1677// other PTR types. Unlike TADDR, we want pointer semantics.
1678// * NOT assignable from host pointer types or convertible to host pointer
1679// types - ensures we can't confuse host and target pointers (we'll get
1680// compiler errors if we try and cast between them).
1681// * like void*, no pointer arithmetic or dereferencing is allowed
1682// * like TADDR, can be used to construct any __DPtr / __VPtr instance
1683// * representation is the same as a void* (for marshalling / casting)
1684//
1685// One way in which __VoidPtr is unlike void* is that it can't be cast to
1686// pointer or integer types. On the one hand, this is a good thing as it forces
1687// us to keep target pointers separate from other data types. On the other hand
1688// in practice this means we have to use dac_cast<TADDR> in places where we used
1689// to use a (TADDR) cast. Unfortunately C++ provides us no way to allow the
1690// explicit cast to primitive types without also allowing implicit conversions.
1691//
1692// This is very similar in spirit to TADDR. The primary difference is that
1693// PTR_VOID has pointer semantics, where TADDR has integer semantics. When
1694// dacizing uses of void* to TADDR, casts must be inserted everywhere back to
1695// pointer types. If we switch a use of TADDR to PTR_VOID, those casts in
1696// DACCESS_COMPILE regions no longer compile (see above). Also, TADDR supports
1697// pointer arithmetic, but that might not be necessary (could use PTR_BYTE
1698// instead etc.). Ideally we'd probably have just one type for this purpose
1699// (named TADDR but with the semantics of PTR_VOID), but outright conversion
1700// would require too much work.
1701//
1702class __VoidPtr : public __TPtrBase
1703{
1704public:
1705 __VoidPtr(void) : __TPtrBase() {}
1706 __VoidPtr(TADDR addr) : __TPtrBase(addr) {}
1707
1708 // Note, unlike __DPtr, this ctor form is not explicit. We allow implicit
1709 // conversions from any pointer type (just like for void*).
1710 __VoidPtr(__TPtrBase addr)
1711 {
1712 m_addr = addr.GetAddr();
1713 }
1714
1715 // Like TPtrBase, VoidPtrs can also be created impicitly from all GlobalPtrs
1716 template<typename acc_type, typename store_type>
1717 __VoidPtr(__GlobalPtr<acc_type, store_type> globalPtr)
1718 {
1719 m_addr = globalPtr.GetAddr();
1720 }
1721
1722 // Note, unlike __DPtr, there is no explicit conversion from host pointer
1723 // types. Since void* cannot be marshalled, there is no such thing as
1724 // a void* DAC instance in the host.
1725
1726 // Also, we don't want an implicit conversion to TADDR because then the
1727 // compiler will allow pointer arithmetic (which it wouldn't allow for
1728 // void*). Instead, callers can use dac_cast<TADDR> if they want.
1729
1730 // Note, unlike __DPtr, any pointer type can be assigned to a __VoidPtr
1731 // This is to mirror the assignability of any pointer type to a void*
1732 __VoidPtr& operator=(const __TPtrBase& ptr)
1733 {
1734 m_addr = ptr.GetAddr();
1735 return *this;
1736 }
1737 __VoidPtr& operator=(TADDR addr)
1738 {
1739 m_addr = addr;
1740 return *this;
1741 }
1742
1743 // note, no marshalling operators (type* conversion, operator ->, operator*)
1744 // A void* can't be marshalled because we don't know how much to copy
1745
1746 // PTR_Void can be compared to any other pointer type (because conceptually,
1747 // any other pointer type should be implicitly convertible to void*)
1748 bool operator==(const __TPtrBase& ptr) const
1749 {
1750 return m_addr == ptr.GetAddr();
1751 }
1752 bool operator==(TADDR addr) const
1753 {
1754 return m_addr == addr;
1755 }
1756 bool operator!=(const __TPtrBase& ptr) const
1757 {
1758 return !operator==(ptr);
1759 }
1760 bool operator!=(TADDR addr) const
1761 {
1762 return m_addr != addr;
1763 }
1764 bool operator<(const __TPtrBase& ptr) const
1765 {
1766 return m_addr < ptr.GetAddr();
1767 }
1768 bool operator>(const __TPtrBase& ptr) const
1769 {
1770 return m_addr > ptr.GetAddr();
1771 }
1772 bool operator<=(const __TPtrBase& ptr) const
1773 {
1774 return m_addr <= ptr.GetAddr();
1775 }
1776 bool operator>=(const __TPtrBase& ptr) const
1777 {
1778 return m_addr >= ptr.GetAddr();
1779 }
1780};
1781
1782typedef __VoidPtr PTR_VOID;
1783typedef DPTR(PTR_VOID) PTR_PTR_VOID;
1784
1785// For now we treat pointers to const and non-const void the same in DAC
1786// builds. In general, DAC is read-only anyway and so there isn't a danger of
1787// writing to these pointers. Also, the non-dac builds will ensure
1788// const-correctness. However, if we wanted to support true void* / const void*
1789// behavior, we could probably build the follow functionality by templating
1790// __VoidPtr:
1791// * A PTR_VOID would be implicitly convertable to PTR_CVOID
1792// * An explicit coercion (ideally const_cast) would be required to convert a
1793// PTR_CVOID to a PTR_VOID
1794// * Similarily, an explicit coercion would be required to convert a cost PTR
1795// type (eg. PTR_CBYTE) to a PTR_VOID.
1796typedef __VoidPtr PTR_CVOID;
1797
1798
1799// The special empty ctor declared here allows the whole
1800// class hierarchy to be instantiated easily by the
1801// external access code. The actual class body will be
1802// read externally so no members should be initialized.
1803
1804//
1805// VPTR_ANY_CLASS_METHODS - Defines the following methods for all VPTR classes
1806//
1807// VPtrSize
1808// Returns the size of the dynamic type of the object (as opposed to sizeof
1809// which is based only on the static type).
1810//
1811// VPtrHostVTable
1812// Returns the address of the vtable for this type.
1813// We create a temporary instance of this type in order to read it's vtable pointer
1814// (at offset 0). For this temporary instance, we do not want to initialize any fields,
1815// so we use the marshalling ctor. Since we didn't initialize any fields, we also don't
1816// wan't to run the dtor (marshaled data structures don't normally expect their destructor
1817// or non-DAC constructors to be called in DAC builds anyway). So, rather than create a
1818// normal stack object, or put the object on the heap, we create the temporary object
1819// on the stack using placement-new and alloca, and don't destruct it.
1820//
1821#define VPTR_ANY_CLASS_METHODS(name) \
1822 virtual ULONG32 VPtrSize(void) { SUPPORTS_DAC; return sizeof(name); } \
1823 static PVOID VPtrHostVTable() { \
1824 void * pBuf = _alloca(sizeof(name)); \
1825 name * dummy = new (pBuf) name((TADDR)0, (TADDR)0); \
1826 return *((PVOID*)dummy); }
1827
1828#define VPTR_CLASS_METHODS(name) \
1829 VPTR_ANY_CLASS_METHODS(name) \
1830 static TADDR VPtrTargetVTable() { \
1831 SUPPORTS_DAC; \
1832 return DacGlobalBase() + g_dacGlobals.name##__vtAddr; }
1833
1834#define VPTR_MULTI_CLASS_METHODS(name, keyBase) \
1835 VPTR_ANY_CLASS_METHODS(name) \
1836 static TADDR VPtrTargetVTable() { \
1837 SUPPORTS_DAC; \
1838 return DacGlobalBase() + g_dacGlobals.name##__##keyBase##__mvtAddr; }
1839
1840#define VPTR_VTABLE_CLASS(name, base) \
1841public: name(TADDR addr, TADDR vtAddr) : base(addr, vtAddr) {} \
1842 VPTR_CLASS_METHODS(name)
1843
1844#define VPTR_VTABLE_CLASS_AND_CTOR(name, base) \
1845 VPTR_VTABLE_CLASS(name, base)
1846
1847#define VPTR_MULTI_VTABLE_CLASS(name, base) \
1848public: name(TADDR addr, TADDR vtAddr) : base(addr, vtAddr) {} \
1849 VPTR_MULTI_CLASS_METHODS(name, base)
1850
1851// Used for base classes that can be instantiated directly.
1852// The fake vfn is still used to force a vtable even when
1853// all the normal vfns are ifdef'ed out.
1854#define VPTR_BASE_CONCRETE_VTABLE_CLASS(name) \
1855public: name(TADDR addr, TADDR vtAddr) {} \
1856 VPTR_CLASS_METHODS(name)
1857
1858#define VPTR_BASE_CONCRETE_VTABLE_CLASS_NO_CTOR_BODY(name) \
1859public: name(TADDR addr, TADDR vtAddr); \
1860 VPTR_CLASS_METHODS(name)
1861
1862// The pure virtual method forces all derivations to use
1863// VPTR_VTABLE_CLASS to compile.
1864#define VPTR_BASE_VTABLE_CLASS(name) \
1865public: name(TADDR addr, TADDR vtAddr) {} \
1866 virtual ULONG32 VPtrSize(void) = 0;
1867
1868#define VPTR_BASE_VTABLE_CLASS_AND_CTOR(name) \
1869 VPTR_BASE_VTABLE_CLASS(name)
1870
1871#define VPTR_BASE_VTABLE_CLASS_NO_CTOR_BODY(name) \
1872public: name(TADDR addr, TADDR vtAddr); \
1873 virtual ULONG32 VPtrSize(void) = 0;
1874
1875#define VPTR_ABSTRACT_VTABLE_CLASS(name, base) \
1876public: name(TADDR addr, TADDR vtAddr) : base(addr, vtAddr) {}
1877
1878#define VPTR_ABSTRACT_VTABLE_CLASS_AND_CTOR(name, base) \
1879 VPTR_ABSTRACT_VTABLE_CLASS(name, base)
1880
1881#define VPTR_ABSTRACT_VTABLE_CLASS_NO_CTOR_BODY(name, base) \
1882public: name(TADDR addr, TADDR vtAddr);
1883
1884// helper macro to make the vtables unique for DAC
1885#define VPTR_UNIQUE(unique)
1886
1887// Safe access for retrieving the target address of a PTR.
1888#define PTR_TO_TADDR(ptr) ((ptr).GetAddr())
1889
1890#define GFN_TADDR(name) (DacGlobalBase() + g_dacGlobals.fn__ ## name)
1891
1892#define GVAL_ADDR(g) \
1893 ((g).operator&())
1894
1895//
1896// References to class static and global data.
1897// These all need to be redirected through the global
1898// data table.
1899//
1900
1901#define _SPTR_DECL(acc_type, store_type, var) \
1902 static __GlobalPtr< acc_type, store_type > var
1903#define _SPTR_IMPL(acc_type, store_type, cls, var) \
1904 __GlobalPtr< acc_type, store_type > cls::var(&g_dacGlobals.cls##__##var)
1905#define _SPTR_IMPL_INIT(acc_type, store_type, cls, var, init) \
1906 __GlobalPtr< acc_type, store_type > cls::var(&g_dacGlobals.cls##__##var)
1907#define _SPTR_IMPL_NS(acc_type, store_type, ns, cls, var) \
1908 __GlobalPtr< acc_type, store_type > cls::var(&g_dacGlobals.ns##__##cls##__##var)
1909#define _SPTR_IMPL_NS_INIT(acc_type, store_type, ns, cls, var, init) \
1910 __GlobalPtr< acc_type, store_type > cls::var(&g_dacGlobals.ns##__##cls##__##var)
1911
1912#define _GPTR_DECL(acc_type, store_type, var) \
1913 extern __GlobalPtr< acc_type, store_type > var
1914#define _GPTR_IMPL(acc_type, store_type, var) \
1915 __GlobalPtr< acc_type, store_type > var(&g_dacGlobals.dac__##var)
1916#define _GPTR_IMPL_INIT(acc_type, store_type, var, init) \
1917 __GlobalPtr< acc_type, store_type > var(&g_dacGlobals.dac__##var)
1918
1919#define SVAL_DECL(type, var) \
1920 static __GlobalVal< type > var
1921#define SVAL_IMPL(type, cls, var) \
1922 __GlobalVal< type > cls::var(&g_dacGlobals.cls##__##var)
1923#define SVAL_IMPL_INIT(type, cls, var, init) \
1924 __GlobalVal< type > cls::var(&g_dacGlobals.cls##__##var)
1925#define SVAL_IMPL_NS(type, ns, cls, var) \
1926 __GlobalVal< type > cls::var(&g_dacGlobals.ns##__##cls##__##var)
1927#define SVAL_IMPL_NS_INIT(type, ns, cls, var, init) \
1928 __GlobalVal< type > cls::var(&g_dacGlobals.ns##__##cls##__##var)
1929
1930#define GVAL_DECL(type, var) \
1931 extern __GlobalVal< type > var
1932#define GVAL_IMPL(type, var) \
1933 __GlobalVal< type > var(&g_dacGlobals.dac__##var)
1934#define GVAL_IMPL_INIT(type, var, init) \
1935 __GlobalVal< type > var(&g_dacGlobals.dac__##var)
1936
1937#define GARY_DECL(type, var, size) \
1938 extern __GlobalArray< type, size > var
1939#define GARY_IMPL(type, var, size) \
1940 __GlobalArray< type, size > var(&g_dacGlobals.dac__##var)
1941
1942// Translation from a host pointer back to the target address
1943// that was used to retrieve the data for the host pointer.
1944#define PTR_HOST_TO_TADDR(host) DacGetTargetAddrForHostAddr(host, true)
1945// Translation from a host interior pointer back to the corresponding
1946// target address. The host address must reside within a previously
1947// retrieved instance.
1948#define PTR_HOST_INT_TO_TADDR(host) DacGetTargetAddrForHostInteriorAddr(host, true)
1949// Translation from a host vtable pointer to a target vtable pointer.
1950#define VPTR_HOST_VTABLE_TO_TADDR(host) DacGetTargetVtForHostVt(host, true)
1951
1952// Construct a pointer to a member of the given type.
1953#define PTR_HOST_MEMBER_TADDR(type, host, memb) \
1954 (PTR_HOST_TO_TADDR(host) + (TADDR)offsetof(type, memb))
1955
1956// Construct a pointer to a member of the given type given an interior
1957// host address.
1958#define PTR_HOST_INT_MEMBER_TADDR(type, host, memb) \
1959 (PTR_HOST_INT_TO_TADDR(host) + (TADDR)offsetof(type, memb))
1960
1961#define PTR_TO_MEMBER_TADDR(type, ptr, memb) \
1962 (PTR_TO_TADDR(ptr) + (TADDR)offsetof(type, memb))
1963
1964// Constructs an arbitrary data instance for a piece of
1965// memory in the target.
1966#define PTR_READ(addr, size) \
1967 DacInstantiateTypeByAddress(addr, size, true)
1968
1969// This value is used to intiailize target pointers to NULL. We want this to be TADDR type
1970// (as opposed to, say, __TPtrBase) so that it can be used in the non-explicit ctor overloads,
1971// eg. as an argument default value.
1972// We can't always just use NULL because that's 0 which (in C++) can be any integer or pointer
1973// type (causing an ambiguous overload compiler error when used in explicit ctor forms).
1974#define PTR_NULL ((TADDR)0)
1975
1976// Provides an empty method implementation when compiled
1977// for DACCESS_COMPILE. For example, use to stub out methods needed
1978// for vtable entries but otherwise unused.
1979// Note that these functions are explicitly NOT marked SUPPORTS_DAC so that we'll get a
1980// DacCop warning if any calls to them are detected.
1981// @dbgtodo : It's probably almost always wrong to call any such function, so
1982// we should probably throw a better error (DacNotImpl), and ideally mark the function
1983// DECLSPEC_NORETURN so we don't have to deal with fabricating return values and we can
1984// get compiler warnings (unreachable code) anytime functions marked this way are called.
1985#define DAC_EMPTY() { LIMITED_METHOD_CONTRACT; }
1986#define DAC_EMPTY_ERR() { LIMITED_METHOD_CONTRACT; DacError(E_UNEXPECTED); }
1987#define DAC_EMPTY_RET(retVal) { LIMITED_METHOD_CONTRACT; DacError(E_UNEXPECTED); return retVal; }
1988#define DAC_UNEXPECTED() { LIMITED_METHOD_CONTRACT; DacError_NoRet(E_UNEXPECTED); }
1989
1990#endif // #ifdef __cplusplus
1991
1992// Implementation details for dac_cast, should never be accessed directly.
1993// See code:dac_cast for details and discussion.
1994namespace dac_imp
1995{
1996 // Helper functions to get the target address of specific types
1997 inline TADDR getTaddr(TADDR addr) { return addr; }
1998 inline TADDR getTaddr(__TPtrBase const &tptr) { return PTR_TO_TADDR(tptr); }
1999 inline TADDR getTaddr(void const * host) { return PTR_HOST_TO_TADDR((void *)host); }
2000 template<typename acc_type, typename store_type>
2001 inline TADDR getTaddr(__GlobalPtr<acc_type, store_type> const &gptr) { return PTR_TO_TADDR(gptr); }
2002
2003 // It is an error to try dac_cast on a __GlobalVal or a __GlobalArray. Declare
2004 // but do not define the methods so that a compile-time error results.
2005 template<typename type>
2006 TADDR getTaddr(__GlobalVal<type> const &gval);
2007 template<typename type, size_t size>
2008 TADDR getTaddr(__GlobalArray<type, size> const &garr);
2009
2010 // Helper class to instantiate DAC instances from a TADDR
2011 // The default implementation assumes we want to create an instance of a PTR type
2012 template<typename T> struct makeDacInst
2013 {
2014 static inline T fromTaddr(TADDR addr)
2015 {
2016 static_assert((std::is_base_of<__TPtrBase, T>::value), "is_base_of constraint violation");
2017 return T(addr);
2018 }
2019 };
2020
2021 // Partial specialization for creating TADDRs
2022 // This is the only other way to create a DAC type instance other than PTR types (above)
2023 template<> struct makeDacInst<TADDR>
2024 {
2025 static inline TADDR fromTaddr(TADDR addr) { return addr; }
2026 };
2027} // namespace dac_imp
2028
2029
2030// DacCop in-line exclusion mechanism
2031
2032// Warnings - official home is DacCop\Shared\Warnings.cs, but we want a way for users to indicate
2033// warning codes in a way that is descriptive to readers (not just code numbers). The names here
2034// don't matter - DacCop just looks at the value
2035enum DacCopWarningCode
2036{
2037 // General Rules
2038 FieldAccess = 1,
2039 PointerArith = 2,
2040 PointerComparison = 3,
2041 InconsistentMarshalling = 4,
2042 CastBetweenAddressSpaces = 5,
2043 CastOfMarshalledType = 6,
2044 VirtualCallToNonVPtr = 7,
2045 UndacizedGlobalVariable = 8,
2046
2047 // Function graph related
2048 CallUnknown = 701,
2049 CallNonDac = 702,
2050 CallVirtualUnknown = 704,
2051 CallVirtualNonDac = 705,
2052};
2053
2054// DACCOP_IGNORE is a mechanism to suppress DacCop violations from within the source-code.
2055// See the DacCop wiki for guidance on how best to use this: http://mswikis/clr/dev/Pages/DacCop.aspx
2056//
2057// DACCOP_IGNORE will suppress a DacCop violation for the following (non-compound) statement.
2058// For example:
2059// // The "dual-mode DAC problem" occurs in a few places where a class is used both
2060// // in the host, and marshalled from the target ... <further details>
2061// DACCOP_IGNORE(CastBetweenAddressSpaces,"SBuffer has the dual-mode DAC problem");
2062// TADDR bufAddr = (TADDR)m_buffer;
2063//
2064// A call to DACCOP_IGNORE must occur as it's own statement, and can apply only to following
2065// single-statements (not to compound statement blocks). Occasionally it is necessary to hoist
2066// violation-inducing code out to its own statement (e.g., if it occurs in the conditional of an
2067// if).
2068//
2069// Arguments:
2070// code: a literal value from DacCopWarningCode indicating which violation should be suppressed.
2071// szReasonString: a short description of why this exclusion is necessary. This is intended just
2072// to help readers of the code understand the source of the problem, and what would be required
2073// to fix it. More details can be provided in comments if desired.
2074//
2075inline void DACCOP_IGNORE(DacCopWarningCode code, const char * szReasonString)
2076{
2077 // DacCop detects calls to this function. No implementation is necessary.
2078}
2079
2080#else // #ifdef DACCESS_COMPILE
2081
2082//
2083// This version of the macros turns into normal pointers
2084// for unmodified in-proc compilation.
2085
2086// *******************************************************
2087// !!!!!!!!!!!!!!!!!!!!!!!!!NOTE!!!!!!!!!!!!!!!!!!!!!!!!!!
2088//
2089// Please search this file for the type name to find the
2090// DAC versions of these definitions
2091//
2092// !!!!!!!!!!!!!!!!!!!!!!!!!NOTE!!!!!!!!!!!!!!!!!!!!!!!!!!
2093// *******************************************************
2094
2095
2096// Declare TADDR as a non-pointer type so that arithmetic
2097// can be done on it directly, as with the DACCESS_COMPILE definition.
2098// This also helps expose pointer usage that may need to be changed.
2099typedef ULONG_PTR TADDR;
2100
2101typedef void* PTR_VOID;
2102typedef LPVOID* PTR_PTR_VOID;
2103typedef const void* PTR_CVOID;
2104
2105#define DPTR(type) type*
2106#define ArrayDPTR(type) type*
2107#define SPTR(type) type*
2108#define VPTR(type) type*
2109#define S8PTR(type) type*
2110#define S8PTRMAX(type, maxChars) type*
2111#define S16PTR(type) type*
2112#define S16PTRMAX(type, maxChars) type*
2113
2114#if defined(FEATURE_PAL)
2115
2116#define VPTR_VTABLE_CLASS(name, base) \
2117 friend struct _DacGlobals; \
2118public: name(int dummy) : base(dummy) {}
2119
2120#define VPTR_VTABLE_CLASS_AND_CTOR(name, base) \
2121 VPTR_VTABLE_CLASS(name, base) \
2122 name() : base() {}
2123
2124#define VPTR_MULTI_VTABLE_CLASS(name, base) \
2125 friend struct _DacGlobals; \
2126public: name(int dummy) : base(dummy) {}
2127
2128#define VPTR_BASE_CONCRETE_VTABLE_CLASS(name) \
2129 friend struct _DacGlobals; \
2130public: name(int dummy) {}
2131
2132#define VPTR_BASE_VTABLE_CLASS(name) \
2133 friend struct _DacGlobals; \
2134public: name(int dummy) {}
2135
2136#define VPTR_BASE_VTABLE_CLASS_AND_CTOR(name) \
2137 VPTR_BASE_VTABLE_CLASS(name) \
2138 name() {}
2139
2140#define VPTR_ABSTRACT_VTABLE_CLASS(name, base) \
2141 friend struct _DacGlobals; \
2142public: name(int dummy) : base(dummy) {}
2143
2144#define VPTR_ABSTRACT_VTABLE_CLASS_AND_CTOR(name, base) \
2145 VPTR_ABSTRACT_VTABLE_CLASS(name, base) \
2146 name() : base() {}
2147
2148#else // FEATURE_PAL
2149
2150#define VPTR_VTABLE_CLASS(name, base)
2151#define VPTR_VTABLE_CLASS_AND_CTOR(name, base)
2152#define VPTR_MULTI_VTABLE_CLASS(name, base)
2153#define VPTR_BASE_CONCRETE_VTABLE_CLASS(name)
2154#define VPTR_BASE_VTABLE_CLASS(name)
2155#define VPTR_BASE_VTABLE_CLASS_AND_CTOR(name)
2156#define VPTR_ABSTRACT_VTABLE_CLASS(name, base)
2157#define VPTR_ABSTRACT_VTABLE_CLASS_AND_CTOR(name, base)
2158
2159#endif // FEATURE_PAL
2160
2161// helper macro to make the vtables unique for DAC
2162#define VPTR_UNIQUE(unique) virtual int MakeVTableUniqueForDAC() { STATIC_CONTRACT_SO_TOLERANT; return unique; }
2163#define VPTR_UNIQUE_BaseDomain (100000)
2164#define VPTR_UNIQUE_SystemDomain (VPTR_UNIQUE_BaseDomain + 1)
2165#define VPTR_UNIQUE_ComMethodFrame (VPTR_UNIQUE_SystemDomain + 1)
2166#define VPTR_UNIQUE_StubHelperFrame (VPTR_UNIQUE_ComMethodFrame + 1)
2167#define VPTR_UNIQUE_RedirectedThreadFrame (VPTR_UNIQUE_StubHelperFrame + 1)
2168#define VPTR_UNIQUE_HijackFrame (VPTR_UNIQUE_RedirectedThreadFrame + 1)
2169
2170#define PTR_TO_TADDR(ptr) ((TADDR)(ptr))
2171#define GFN_TADDR(name) ((TADDR)(name))
2172
2173#define GVAL_ADDR(g) (&(g))
2174#define _SPTR_DECL(acc_type, store_type, var) \
2175 static store_type var
2176#define _SPTR_IMPL(acc_type, store_type, cls, var) \
2177 store_type cls::var
2178#define _SPTR_IMPL_INIT(acc_type, store_type, cls, var, init) \
2179 store_type cls::var = init
2180#define _SPTR_IMPL_NS(acc_type, store_type, ns, cls, var) \
2181 store_type cls::var
2182#define _SPTR_IMPL_NS_INIT(acc_type, store_type, ns, cls, var, init) \
2183 store_type cls::var = init
2184#define _GPTR_DECL(acc_type, store_type, var) \
2185 extern store_type var
2186#define _GPTR_IMPL(acc_type, store_type, var) \
2187 store_type var
2188#define _GPTR_IMPL_INIT(acc_type, store_type, var, init) \
2189 store_type var = init
2190#define SVAL_DECL(type, var) \
2191 static type var
2192#define SVAL_IMPL(type, cls, var) \
2193 type cls::var
2194#define SVAL_IMPL_INIT(type, cls, var, init) \
2195 type cls::var = init
2196#define SVAL_IMPL_NS(type, ns, cls, var) \
2197 type cls::var
2198#define SVAL_IMPL_NS_INIT(type, ns, cls, var, init) \
2199 type cls::var = init
2200#define GVAL_DECL(type, var) \
2201 extern type var
2202#define GVAL_IMPL(type, var) \
2203 type var
2204#define GVAL_IMPL_INIT(type, var, init) \
2205 type var = init
2206#define GARY_DECL(type, var, size) \
2207 extern type var[size]
2208#define GARY_IMPL(type, var, size) \
2209 type var[size]
2210#define PTR_HOST_TO_TADDR(host) ((TADDR)(host))
2211#define PTR_HOST_INT_TO_TADDR(host) ((TADDR)(host))
2212#define VPTR_HOST_VTABLE_TO_TADDR(host) ((TADDR)(host))
2213#define PTR_HOST_MEMBER_TADDR(type, host, memb) ((TADDR)&(host)->memb)
2214#define PTR_HOST_INT_MEMBER_TADDR(type, host, memb) ((TADDR)&(host)->memb)
2215#define PTR_TO_MEMBER_TADDR(type, ptr, memb) ((TADDR)&((ptr)->memb))
2216#define PTR_READ(addr, size) ((PVOID)(addr))
2217
2218#define PTR_NULL NULL
2219
2220#define DAC_EMPTY()
2221#define DAC_EMPTY_ERR()
2222#define DAC_EMPTY_RET(retVal)
2223#define DAC_UNEXPECTED()
2224
2225#define DACCOP_IGNORE(warningCode, reasonString)
2226
2227#endif // #ifdef DACCESS_COMPILE
2228
2229//----------------------------------------------------------------------------
2230// dac_cast
2231// Casting utility, to be used for casting one class pointer type to another.
2232// Use as you would use static_cast
2233//
2234// dac_cast is designed to act just as static_cast does when
2235// dealing with pointers and their DAC abstractions. Specifically,
2236// it handles these coversions:
2237//
2238// dac_cast<TargetType>(SourceTypeVal)
2239//
2240// where TargetType <- SourceTypeVal are
2241//
2242// ?PTR(Tgt) <- TADDR - Create PTR type (DPtr etc.) from TADDR
2243// ?PTR(Tgt) <- ?PTR(Src) - Convert one PTR type to another
2244// ?PTR(Tgt) <- Src * - Create PTR type from dac host object instance
2245// TADDR <- ?PTR(Src) - Get TADDR of PTR object (DPtr etc.)
2246// TADDR <- Src * - Get TADDR of dac host object instance
2247//
2248// Note that there is no direct convertion to other host-pointer types (because we don't
2249// know if you want a DPTR or VPTR etc.). However, due to the implicit DAC conversions,
2250// you can just use dac_cast<PTR_Foo> and assign that to a Foo*.
2251//
2252// The beauty of this syntax is that it is consistent regardless
2253// of source and target casting types. You just use dac_cast
2254// and the partial template specialization will do the right thing.
2255//
2256// One important thing to realise is that all "Foo *" types are
2257// assumed to be pointers to host instances that were marshalled by DAC. This should
2258// fail at runtime if it's not the case.
2259//
2260// Some examples would be:
2261//
2262// - Host pointer of one type to a related host pointer of another
2263// type, i.e., MethodDesc * <-> InstantiatedMethodDesc *
2264// Syntax: with MethodDesc *pMD, InstantiatedMethodDesc *pInstMD
2265// pInstMd = dac_cast<PTR_InstantiatedMethodDesc>(pMD)
2266// pMD = dac_cast<PTR_MethodDesc>(pInstMD)
2267//
2268// - (D|V)PTR of one encapsulated pointer type to a (D|V)PTR of
2269// another type, i.e., PTR_AppDomain <-> PTR_BaseDomain
2270// Syntax: with PTR_AppDomain pAD, PTR_BaseDomain pBD
2271// dac_cast<PTR_AppDomain>(pBD)
2272// dac_cast<PTR_BaseDomain>(pAD)
2273//
2274// Example comparsions of some old and new syntax, where
2275// h is a host pointer, such as "Foo *h;"
2276// p is a DPTR, such as "PTR_Foo p;"
2277//
2278// PTR_HOST_TO_TADDR(h) ==> dac_cast<TADDR>(h)
2279// PTR_TO_TADDR(p) ==> dac_cast<TADDR>(p)
2280// PTR_Foo(PTR_HOST_TO_TADDR(h)) ==> dac_cast<PTR_Foo>(h)
2281//
2282//----------------------------------------------------------------------------
2283template <typename Tgt, typename Src>
2284inline Tgt dac_cast(Src src)
2285{
2286#ifdef DACCESS_COMPILE
2287 // In DAC builds, first get a TADDR for the source, then create the
2288 // appropriate destination instance.
2289 TADDR addr = dac_imp::getTaddr(src);
2290 return dac_imp::makeDacInst<Tgt>::fromTaddr(addr);
2291#else
2292 // In non-DAC builds, dac_cast is the same as a C-style cast because we need to support:
2293 // - casting away const
2294 // - conversions between pointers and TADDR
2295 // Perhaps we should more precisely restrict it's usage, but we get the precise
2296 // restrictions in DAC builds, so it wouldn't buy us much.
2297 return (Tgt)(src);
2298#endif
2299}
2300
2301//----------------------------------------------------------------------------
2302//
2303// Convenience macros which work for either mode.
2304//
2305//----------------------------------------------------------------------------
2306
2307#define SPTR_DECL(type, var) _SPTR_DECL(type*, PTR_##type, var)
2308#define SPTR_IMPL(type, cls, var) _SPTR_IMPL(type*, PTR_##type, cls, var)
2309#define SPTR_IMPL_INIT(type, cls, var, init) _SPTR_IMPL_INIT(type*, PTR_##type, cls, var, init)
2310#define SPTR_IMPL_NS(type, ns, cls, var) _SPTR_IMPL_NS(type*, PTR_##type, ns, cls, var)
2311#define SPTR_IMPL_NS_INIT(type, ns, cls, var, init) _SPTR_IMPL_NS_INIT(type*, PTR_##type, ns, cls, var, init)
2312#define GPTR_DECL(type, var) _GPTR_DECL(type*, PTR_##type, var)
2313#define GPTR_IMPL(type, var) _GPTR_IMPL(type*, PTR_##type, var)
2314#define GPTR_IMPL_INIT(type, var, init) _GPTR_IMPL_INIT(type*, PTR_##type, var, init)
2315
2316
2317// If you want to marshal a single instance of an ArrayDPtr over to the host and
2318// return a pointer to it, you can use this function. However, this is unsafe because
2319// users of value may assume they can do pointer arithmetic on it. This is exactly
2320// the bugs ArrayDPtr is designed to prevent. See code:__ArrayDPtr for details.
2321template<typename type>
2322inline type* DacUnsafeMarshalSingleElement( ArrayDPTR(type) arrayPtr )
2323{
2324 return (DPTR(type))(arrayPtr);
2325}
2326
2327//----------------------------------------------------------------------------
2328//
2329// Forward typedefs for system types. This is a convenient place
2330// to declare things for system types, plus it gives us a central
2331// place to look at when deciding what types may cause issues for
2332// cross-platform compilation.
2333//
2334//----------------------------------------------------------------------------
2335
2336typedef ArrayDPTR(BYTE) PTR_BYTE;
2337typedef ArrayDPTR(uint8_t) PTR_uint8_t;
2338typedef DPTR(PTR_BYTE) PTR_PTR_BYTE;
2339typedef DPTR(PTR_uint8_t) PTR_PTR_uint8_t;
2340typedef DPTR(PTR_PTR_BYTE) PTR_PTR_PTR_BYTE;
2341typedef ArrayDPTR(signed char) PTR_SBYTE;
2342typedef ArrayDPTR(const BYTE) PTR_CBYTE;
2343typedef DPTR(INT8) PTR_INT8;
2344typedef DPTR(INT16) PTR_INT16;
2345typedef DPTR(UINT16) PTR_UINT16;
2346typedef DPTR(WORD) PTR_WORD;
2347typedef DPTR(USHORT) PTR_USHORT;
2348typedef DPTR(DWORD) PTR_DWORD;
2349typedef DPTR(uint32_t) PTR_uint32_t;
2350typedef DPTR(LONG) PTR_LONG;
2351typedef DPTR(ULONG) PTR_ULONG;
2352typedef DPTR(INT32) PTR_INT32;
2353typedef DPTR(UINT32) PTR_UINT32;
2354typedef DPTR(ULONG64) PTR_ULONG64;
2355typedef DPTR(INT64) PTR_INT64;
2356typedef DPTR(UINT64) PTR_UINT64;
2357typedef DPTR(SIZE_T) PTR_SIZE_T;
2358typedef DPTR(size_t) PTR_size_t;
2359typedef DPTR(TADDR) PTR_TADDR;
2360typedef DPTR(int) PTR_int;
2361typedef DPTR(BOOL) PTR_BOOL;
2362typedef DPTR(unsigned) PTR_unsigned;
2363
2364typedef S8PTR(char) PTR_STR;
2365typedef S8PTR(const char) PTR_CSTR;
2366typedef S8PTR(char) PTR_UTF8;
2367typedef S8PTR(const char) PTR_CUTF8;
2368typedef S16PTR(WCHAR) PTR_WSTR;
2369typedef S16PTR(const WCHAR) PTR_CWSTR;
2370
2371typedef DPTR(T_CONTEXT) PTR_CONTEXT;
2372typedef DPTR(PTR_CONTEXT) PTR_PTR_CONTEXT;
2373typedef DPTR(struct _EXCEPTION_POINTERS) PTR_EXCEPTION_POINTERS;
2374typedef DPTR(struct _EXCEPTION_RECORD) PTR_EXCEPTION_RECORD;
2375
2376typedef DPTR(struct _EXCEPTION_REGISTRATION_RECORD) PTR_EXCEPTION_REGISTRATION_RECORD;
2377
2378typedef DPTR(struct IMAGE_COR_VTABLEFIXUP) PTR_IMAGE_COR_VTABLEFIXUP;
2379typedef DPTR(IMAGE_DATA_DIRECTORY) PTR_IMAGE_DATA_DIRECTORY;
2380typedef DPTR(IMAGE_DEBUG_DIRECTORY) PTR_IMAGE_DEBUG_DIRECTORY;
2381typedef DPTR(IMAGE_DOS_HEADER) PTR_IMAGE_DOS_HEADER;
2382typedef DPTR(IMAGE_NT_HEADERS) PTR_IMAGE_NT_HEADERS;
2383typedef DPTR(IMAGE_NT_HEADERS32) PTR_IMAGE_NT_HEADERS32;
2384typedef DPTR(IMAGE_NT_HEADERS64) PTR_IMAGE_NT_HEADERS64;
2385typedef DPTR(IMAGE_SECTION_HEADER) PTR_IMAGE_SECTION_HEADER;
2386typedef DPTR(IMAGE_TLS_DIRECTORY) PTR_IMAGE_TLS_DIRECTORY;
2387
2388#if defined(DACCESS_COMPILE)
2389#include <corhdr.h>
2390#include <clrdata.h>
2391#include <xclrdata.h>
2392#endif
2393
2394#if defined(_TARGET_X86_) && defined(FEATURE_PAL)
2395typedef DPTR(struct _UNWIND_INFO) PTR_UNWIND_INFO;
2396#endif
2397
2398#ifdef _TARGET_64BIT_
2399typedef DPTR(T_RUNTIME_FUNCTION) PTR_RUNTIME_FUNCTION;
2400typedef DPTR(struct _UNWIND_INFO) PTR_UNWIND_INFO;
2401#if defined(_TARGET_AMD64_)
2402typedef DPTR(union _UNWIND_CODE) PTR_UNWIND_CODE;
2403#endif // _TARGET_AMD64_
2404#endif // _TARGET_64BIT_
2405
2406#ifdef _TARGET_ARM_
2407typedef DPTR(T_RUNTIME_FUNCTION) PTR_RUNTIME_FUNCTION;
2408#endif
2409
2410//----------------------------------------------------------------------------
2411//
2412// A PCODE is a valid PC/IP value -- a pointer to an instruction, possibly including some processor mode bits.
2413// (On ARM, for example, a PCODE value should have the low-order THUMB_CODE bit set if the code should
2414// be executed in that mode.)
2415//
2416typedef TADDR PCODE;
2417typedef DPTR(PCODE) PTR_PCODE;
2418typedef DPTR(PTR_PCODE) PTR_PTR_PCODE;
2419
2420// There is another concept we should have, "pointer to the start of an instruction" -- a PCODE with any mode bits masked off.
2421// Attempts to introduce this concept, and classify uses of PCODE as one or the other,
2422// turned out to be too hard: either name choice required *many* code changes, and decisions in unfamiliar code. So despite the
2423// the comment above, the PCODE is currently sometimes used for the PINSTR concept.
2424
2425// See PCODEToPINSTR in utilcode.h for conversion from PCODE to PINSTR.
2426
2427//----------------------------------------------------------------------------
2428//
2429// The access code compile must compile data structures that exactly
2430// match the real structures for access to work. The access code
2431// doesn't want all of the debugging validation code, though, so
2432// distinguish between _DEBUG, for declaring general debugging data
2433// and always-on debug code, and _DEBUG_IMPL, for debugging code
2434// which will be disabled when compiling for external access.
2435//
2436//----------------------------------------------------------------------------
2437
2438#if !defined(_DEBUG_IMPL) && defined(_DEBUG) && !defined(DACCESS_COMPILE)
2439#define _DEBUG_IMPL 1
2440#endif
2441
2442// Helper macro for tracking EnumMemoryRegions progress.
2443#if 0
2444#define EMEM_OUT(args) DacWarning args
2445#else
2446#define EMEM_OUT(args)
2447#endif
2448
2449// Macros like MAIN_CLR_MODULE_NAME* for the DAC module
2450#define MAIN_DAC_MODULE_NAME_W W("mscordaccore")
2451#define MAIN_DAC_MODULE_DLL_NAME_W W("mscordaccore.dll")
2452
2453// TARGET_CONSISTENCY_CHECK represents a condition that should not fail unless the DAC target is corrupt.
2454// This is in contrast to ASSERTs in DAC infrastructure code which shouldn't fail regardless of the memory
2455// read from the target. At the moment we treat these the same, but in the future we will want a mechanism
2456// for disabling just the target consistency checks (eg. for tests that intentionally use corrupted targets).
2457// @dbgtodo : Separating asserts and target consistency checks is tracked by DevDiv Bugs 31674
2458#define TARGET_CONSISTENCY_CHECK(expr,msg) _ASSERTE_MSG(expr,msg)
2459
2460#endif // #ifndef __daccess_h__
2461