summaryrefslogtreecommitdiff
path: root/src/debug/daccess/fntableaccess.h
blob: b5ea5452f65efddb57c906a8e18eeafc2cfba4c6 (plain)
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
217
218
219
// 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*
#if defined (FEATURE_GDBJIT)
    LPVOID              pCalledMethods;
#endif
    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