Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/util/windows/third_party/StackWalker/src/StackWalker.h
1695 views
1
#ifndef __STACKWALKER_H__
2
#define __STACKWALKER_H__
3
4
#if defined(_MSC_VER)
5
6
/**********************************************************************
7
*
8
* StackWalker.h
9
*
10
*
11
*
12
* LICENSE (http://www.opensource.org/licenses/bsd-license.php)
13
*
14
* Copyright (c) 2005-2009, Jochen Kalmbach
15
* All rights reserved.
16
*
17
* Redistribution and use in source and binary forms, with or without modification,
18
* are permitted provided that the following conditions are met:
19
*
20
* Redistributions of source code must retain the above copyright notice,
21
* this list of conditions and the following disclaimer.
22
* Redistributions in binary form must reproduce the above copyright notice,
23
* this list of conditions and the following disclaimer in the documentation
24
* and/or other materials provided with the distribution.
25
* Neither the name of Jochen Kalmbach nor the names of its contributors may be
26
* used to endorse or promote products derived from this software without
27
* specific prior written permission.
28
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
30
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
32
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
34
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
35
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
*
39
* **********************************************************************/
40
// #pragma once is supported starting with _MSC_VER 1000,
41
// so we need not to check the version (because we only support _MSC_VER >= 1100)!
42
#pragma once
43
44
#include <windows.h>
45
46
#if _MSC_VER >= 1900
47
#pragma warning(disable : 4091)
48
#endif
49
50
// special defines for VC5/6 (if no actual PSDK is installed):
51
#if _MSC_VER < 1300
52
typedef unsigned __int64 DWORD64, *PDWORD64;
53
#if defined(_WIN64)
54
typedef unsigned __int64 SIZE_T, *PSIZE_T;
55
#else
56
typedef unsigned long SIZE_T, *PSIZE_T;
57
#endif
58
#endif // _MSC_VER < 1300
59
60
class StackWalkerInternal; // forward
61
class StackWalker
62
{
63
public:
64
typedef enum StackWalkOptions
65
{
66
// No addition info will be retrieved
67
// (only the address is available)
68
RetrieveNone = 0,
69
70
// Try to get the symbol-name
71
RetrieveSymbol = 1,
72
73
// Try to get the line for this symbol
74
RetrieveLine = 2,
75
76
// Try to retrieve the module-infos
77
RetrieveModuleInfo = 4,
78
79
// Also retrieve the version for the DLL/EXE
80
RetrieveFileVersion = 8,
81
82
// Contains all the above
83
RetrieveVerbose = 0xF,
84
85
// Generate a "good" symbol-search-path
86
SymBuildPath = 0x10,
87
88
// Also use the public Microsoft-Symbol-Server
89
SymUseSymSrv = 0x20,
90
91
// Contains all the above "Sym"-options
92
SymAll = 0x30,
93
94
// Contains all options (default)
95
OptionsAll = 0x3F
96
} StackWalkOptions;
97
98
StackWalker(int options = OptionsAll, // 'int' is by design, to combine the enum-flags
99
LPCSTR szSymPath = NULL,
100
DWORD dwProcessId = GetCurrentProcessId(),
101
HANDLE hProcess = GetCurrentProcess());
102
StackWalker(DWORD dwProcessId, HANDLE hProcess);
103
virtual ~StackWalker();
104
105
typedef BOOL(__stdcall* PReadProcessMemoryRoutine)(
106
HANDLE hProcess,
107
DWORD64 qwBaseAddress,
108
PVOID lpBuffer,
109
DWORD nSize,
110
LPDWORD lpNumberOfBytesRead,
111
LPVOID pUserData // optional data, which was passed in "ShowCallstack"
112
);
113
114
BOOL LoadModules();
115
116
BOOL ShowCallstack(
117
HANDLE hThread = GetCurrentThread(),
118
const CONTEXT* context = NULL,
119
PReadProcessMemoryRoutine readMemoryFunction = NULL,
120
LPVOID pUserData = NULL // optional to identify some data in the 'readMemoryFunction'-callback
121
);
122
123
BOOL ShowObject(LPVOID pObject);
124
125
#if _MSC_VER >= 1300
126
// due to some reasons, the "STACKWALK_MAX_NAMELEN" must be declared as "public"
127
// in older compilers in order to use it... starting with VC7 we can declare it as "protected"
128
protected:
129
#endif
130
enum
131
{
132
STACKWALK_MAX_NAMELEN = 1024
133
}; // max name length for found symbols
134
135
protected:
136
// Entry for each Callstack-Entry
137
typedef struct CallstackEntry
138
{
139
DWORD64 offset; // if 0, we have no valid entry
140
CHAR name[STACKWALK_MAX_NAMELEN];
141
CHAR undName[STACKWALK_MAX_NAMELEN];
142
CHAR undFullName[STACKWALK_MAX_NAMELEN];
143
DWORD64 offsetFromSmybol;
144
DWORD offsetFromLine;
145
DWORD lineNumber;
146
CHAR lineFileName[STACKWALK_MAX_NAMELEN];
147
DWORD symType;
148
LPCSTR symTypeString;
149
CHAR moduleName[STACKWALK_MAX_NAMELEN];
150
DWORD64 baseOfImage;
151
CHAR loadedImageName[STACKWALK_MAX_NAMELEN];
152
} CallstackEntry;
153
154
typedef enum CallstackEntryType
155
{
156
firstEntry,
157
nextEntry,
158
lastEntry
159
} CallstackEntryType;
160
161
virtual void OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName);
162
virtual void OnLoadModule(LPCSTR img,
163
LPCSTR mod,
164
DWORD64 baseAddr,
165
DWORD size,
166
DWORD result,
167
LPCSTR symType,
168
LPCSTR pdbName,
169
ULONGLONG fileVersion);
170
virtual void OnCallstackEntry(CallstackEntryType eType, CallstackEntry& entry);
171
virtual void OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr);
172
virtual void OnOutput(LPCSTR szText);
173
174
StackWalkerInternal* m_sw;
175
HANDLE m_hProcess;
176
DWORD m_dwProcessId;
177
BOOL m_modulesLoaded;
178
LPSTR m_szSymPath;
179
180
int m_options;
181
int m_MaxRecursionCount;
182
183
static BOOL __stdcall myReadProcMem(HANDLE hProcess,
184
DWORD64 qwBaseAddress,
185
PVOID lpBuffer,
186
DWORD nSize,
187
LPDWORD lpNumberOfBytesRead);
188
189
friend StackWalkerInternal;
190
}; // class StackWalker
191
192
// The "ugly" assembler-implementation is needed for systems before XP
193
// If you have a new PSDK and you only compile for XP and later, then you can use
194
// the "RtlCaptureContext"
195
// Currently there is no define which determines the PSDK-Version...
196
// So we just use the compiler-version (and assumes that the PSDK is
197
// the one which was installed by the VS-IDE)
198
199
// INFO: If you want, you can use the RtlCaptureContext if you only target XP and later...
200
// But I currently use it in x64/IA64 environments...
201
//#if defined(_M_IX86) && (_WIN32_WINNT <= 0x0500) && (_MSC_VER < 1400)
202
203
#if defined(_M_IX86)
204
#ifdef CURRENT_THREAD_VIA_EXCEPTION
205
// TODO: The following is not a "good" implementation,
206
// because the callstack is only valid in the "__except" block...
207
#define GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX(c, contextFlags) \
208
do \
209
{ \
210
memset(&c, 0, sizeof(CONTEXT)); \
211
EXCEPTION_POINTERS* pExp = NULL; \
212
__try \
213
{ \
214
throw 0; \
215
} \
216
__except (((pExp = GetExceptionInformation()) ? EXCEPTION_EXECUTE_HANDLER \
217
: EXCEPTION_EXECUTE_HANDLER)) \
218
{ \
219
} \
220
if (pExp != NULL) \
221
memcpy(&c, pExp->ContextRecord, sizeof(CONTEXT)); \
222
c.ContextFlags = contextFlags; \
223
} while (0);
224
#else
225
// clang-format off
226
// The following should be enough for walking the callstack...
227
#define GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX(c, contextFlags) \
228
do \
229
{ \
230
memset(&c, 0, sizeof(CONTEXT)); \
231
c.ContextFlags = contextFlags; \
232
__asm call x \
233
__asm x: pop eax \
234
__asm mov c.Eip, eax \
235
__asm mov c.Ebp, ebp \
236
__asm mov c.Esp, esp \
237
} while (0)
238
// clang-format on
239
#endif
240
241
#else
242
243
// The following is defined for x86 (XP and higher), x64 and IA64:
244
#define GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX(c, contextFlags) \
245
do \
246
{ \
247
memset(&c, 0, sizeof(CONTEXT)); \
248
c.ContextFlags = contextFlags; \
249
RtlCaptureContext(&c); \
250
} while (0)
251
#endif
252
253
#endif //defined(_MSC_VER)
254
255
#endif // __STACKWALKER_H__
256
257