1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//
#ifdef _MSC_VER
#pragma once
#endif
#ifndef _FN_TABLE_ACCESS_H
#define _FN_TABLE_ACCESS_H
#if !defined(_TARGET_X86_)
#ifndef FEATURE_PAL
#define DEBUGSUPPORT_STUBS_HAVE_UNWIND_INFO
#endif // !FEATURE_PAL
#ifndef USE_INDIRECT_CODEHEADER
#define USE_INDIRECT_CODEHEADER
#endif // USE_INDIRECT_CODEHEADER
#endif
struct FakeEEJitManager
{
LPVOID __VFN_table;
LPVOID m_runtimeSupport;
LPVOID m_pCodeHeap;
// Nothing after this point matters: we only need the correct offset of m_pCodeHeap.
};
struct FakeHeapList
{
FakeHeapList* hpNext;
LPVOID pHeap; // changed type from LoaderHeap*
DWORD_PTR startAddress; // changed from PBYTE
DWORD_PTR endAddress; // changed from PBYTE
DWORD_PTR mapBase; // changed from PBYTE
DWORD_PTR pHdrMap; // changed from DWORD*
size_t maxCodeHeapSize;
DWORD cBlocks;
bool bFull; // Heap is considered full do not use for new allocations
bool bFullForJumpStubs; // Heap is considered full do not use for new allocations of jump stubs
};
typedef struct _FakeHpRealCodeHdr
{
LPVOID phdrDebugInfo;
LPVOID phdrJitEHInfo; // changed from EE_ILEXCEPTION*
LPVOID phdrJitGCInfo; // changed from BYTE*
LPVOID hdrMDesc; // changed from MethodDesc*
DWORD nUnwindInfos;
T_RUNTIME_FUNCTION unwindInfos[0];
} FakeRealCodeHeader;
typedef struct _FakeHpCodeHdr
{
LPVOID pRealCodeHeader;
} FakeCodeHeader;
#define FAKE_STUB_CODE_BLOCK_LAST 0xF
#ifdef DEBUGSUPPORT_STUBS_HAVE_UNWIND_INFO
struct FakeStubUnwindInfoHeaderSuffix
{
UCHAR nUnwindInfoSize;
};
// Variable-sized struct that preceeds a Stub when the stub requires unwind
// information. Followed by a StubUnwindInfoHeaderSuffix.
struct FakeStubUnwindInfoHeader
{
FakeStubUnwindInfoHeader *pNext;
T_RUNTIME_FUNCTION FunctionEntry;
UNWIND_INFO UnwindInfo; // variable length
};
// List of stub address ranges, in increasing address order.
struct FakeStubUnwindInfoHeapSegment
{
PBYTE pbBaseAddress;
SIZE_T cbSegment;
FakeStubUnwindInfoHeader *pUnwindHeaderList;
FakeStubUnwindInfoHeapSegment *pNext;
};
#define FAKE_STUB_EXTERNAL_ENTRY_BIT 0x40000000
#define FAKE_STUB_INTERCEPT_BIT 0x10000000
#define FAKE_STUB_UNWIND_INFO_BIT 0x08000000
#ifdef _DEBUG
#define FAKE_STUB_SIGNATURE 0x42555453
#endif
struct FakeStub
{
ULONG m_refcount;
ULONG m_patchOffset;
UINT m_numCodeBytes;
#ifdef _DEBUG
UINT32 m_signature;
#else
#ifdef _WIN64
//README ALIGNEMENT: in retail mode UINT m_numCodeBytes does not align to 16byte for the code
// after the Stub struct. This is to pad properly
UINT m_pad_code_bytes;
#endif // _WIN64
#endif // _DEBUG
};
#endif // DEBUGSUPPORT_STUBS_HAVE_UNWIND_INFO
enum FakeEEDynamicFunctionTableType
{
FAKEDYNFNTABLE_JIT = 0,
FAKEDYNFNTABLE_STUB = 1,
};
#ifdef CHECK_DUPLICATED_STRUCT_LAYOUTS
//
// These are the fields of the above structs that we use.
// We need to assert that their layout matches the layout
// in the EE.
//
class CheckDuplicatedStructLayouts
{
#define CHECK_OFFSET(cls, fld) CPP_ASSERT(cls##fld, offsetof(Fake##cls, fld) == offsetof(cls, fld))
CHECK_OFFSET(EEJitManager, m_pCodeHeap);
CHECK_OFFSET(HeapList, hpNext);
CHECK_OFFSET(HeapList, startAddress);
CHECK_OFFSET(HeapList, endAddress);
CHECK_OFFSET(HeapList, mapBase);
CHECK_OFFSET(HeapList, pHdrMap);
#if !defined(_TARGET_X86_)
CHECK_OFFSET(RealCodeHeader, nUnwindInfos);
CHECK_OFFSET(RealCodeHeader, unwindInfos);
#endif // !_TARGET_X86_
#ifdef DEBUGSUPPORT_STUBS_HAVE_UNWIND_INFO
CHECK_OFFSET(StubUnwindInfoHeader, pNext);
CHECK_OFFSET(StubUnwindInfoHeapSegment, pbBaseAddress);
CHECK_OFFSET(StubUnwindInfoHeapSegment, cbSegment);
CHECK_OFFSET(StubUnwindInfoHeapSegment, pUnwindHeaderList);
CHECK_OFFSET(StubUnwindInfoHeapSegment, pNext);
CHECK_OFFSET(Stub, m_refcount);
CHECK_OFFSET(Stub, m_patchOffset);
CHECK_OFFSET(Stub, m_numCodeBytes);
#ifdef _DEBUG
CHECK_OFFSET(Stub, m_signature);
#endif // _DEBUG
#endif // DEBUGSUPPORT_STUBS_HAVE_UNWIND_INFO
#undef CHECK_OFFSET
#ifdef DEBUGSUPPORT_STUBS_HAVE_UNWIND_INFO
static_assert_no_msg( Stub::EXTERNAL_ENTRY_BIT
== FAKE_STUB_EXTERNAL_ENTRY_BIT);
static_assert_no_msg( Stub::INTERCEPT_BIT
== FAKE_STUB_INTERCEPT_BIT);
static_assert_no_msg( Stub::UNWIND_INFO_BIT
== FAKE_STUB_UNWIND_INFO_BIT);
#ifdef _DEBUG
static_assert_no_msg( FAKE_STUB_SIGNATURE
== Stub::kUsedStub);
#endif
#endif // DEBUGSUPPORT_STUBS_HAVE_UNWIND_INFO
};
#ifdef DEBUGSUPPORT_STUBS_HAVE_UNWIND_INFO
static_assert_no_msg( FAKEDYNFNTABLE_JIT
== DYNFNTABLE_JIT);
static_assert_no_msg( FAKEDYNFNTABLE_STUB
== DYNFNTABLE_STUB);
#endif // DEBUGSUPPORT_STUBS_HAVE_UNWIND_INFO
#else // CHECK_DUPLICATED_STRUCT_LAYOUTS
BOOL WINAPI DllMain(HINSTANCE hDLL, DWORD dwReason, LPVOID pReserved);
//NTSTATUS OutOfProcessFindHeader(HANDLE hProcess, DWORD_PTR pMapIn, DWORD_PTR addr, DWORD_PTR &codeHead);
extern "C" NTSTATUS OutOfProcessFunctionTableCallback(IN HANDLE hProcess, IN PVOID TableAddress, OUT PULONG pnEntries, OUT PT_RUNTIME_FUNCTION* ppFunctions);
// OutOfProcessFunctionTableCallbackEx is like the standard OS-defined OutOfProcessFunctionTableCallback, but rather
// than take a handle to a process, it takes a callback function which can read from the target. This allows the API to work on
// targets other than live processes (such as TTT trace files).
// pUserContext is passed directly to fpReadMemory, and the semantics of all other ReadMemoryFunction arguments (and return value) are
// the same as those for kernel32!ReadProcessMemory.
typedef BOOL (ReadMemoryFunction)(PVOID pUserContext, LPCVOID lpBaseAddress, PVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesRead);
extern "C" NTSTATUS OutOfProcessFunctionTableCallbackEx(IN ReadMemoryFunction fpReadMemory, IN PVOID pUserContext, IN PVOID TableAddress, OUT PULONG pnEntries, OUT PT_RUNTIME_FUNCTION* ppFunctions);
#endif // CHECK_DUPLICATED_STRUCT_LAYOUTS
#endif //_FN_TABLE_ACCESS_H
|