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