blob: 89be951624836f4cfaf37d713267dce855287ab9 [file] [log] [blame]
James Kuszmaulcf324122023-01-14 14:07:17 -08001#ifndef __STACKWALKER_H__
2#define __STACKWALKER_H__
3
4#if defined(_MSC_VER)
5
Brian Silverman8fce7482020-01-05 13:18:21 -08006/**********************************************************************
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 * **********************************************************************/
James Kuszmaulcf324122023-01-14 14:07:17 -080040// #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)!
Brian Silverman8fce7482020-01-05 13:18:21 -080042#pragma once
43
44#include <windows.h>
45
46#if _MSC_VER >= 1900
47#pragma warning(disable : 4091)
48#endif
49
50class StackWalkerInternal; // forward
51class StackWalker
52{
53public:
54 typedef enum StackWalkOptions
55 {
56 // No addition info will be retrieved
57 // (only the address is available)
58 RetrieveNone = 0,
59
60 // Try to get the symbol-name
61 RetrieveSymbol = 1,
62
63 // Try to get the line for this symbol
64 RetrieveLine = 2,
65
66 // Try to retrieve the module-infos
67 RetrieveModuleInfo = 4,
68
69 // Also retrieve the version for the DLL/EXE
70 RetrieveFileVersion = 8,
71
72 // Contains all the above
73 RetrieveVerbose = 0xF,
74
75 // Generate a "good" symbol-search-path
76 SymBuildPath = 0x10,
77
78 // Also use the public Microsoft-Symbol-Server
79 SymUseSymSrv = 0x20,
80
81 // Contains all the above "Sym"-options
82 SymAll = 0x30,
83
84 // Contains all options (default)
85 OptionsAll = 0x3F
86 } StackWalkOptions;
87
88 StackWalker(int options = OptionsAll, // 'int' is by design, to combine the enum-flags
89 LPCTSTR szSymPath = NULL,
90 DWORD dwProcessId = GetCurrentProcessId(),
91 HANDLE hProcess = GetCurrentProcess());
92 StackWalker(DWORD dwProcessId, HANDLE hProcess);
93 virtual ~StackWalker();
94
95 typedef BOOL(__stdcall* PReadProcessMemoryRoutine)(
96 HANDLE hProcess,
97 DWORD64 qwBaseAddress,
98 PVOID lpBuffer,
99 DWORD nSize,
100 LPDWORD lpNumberOfBytesRead,
101 LPVOID pUserData // optional data, which was passed in "ShowCallstack"
102 );
103
104 BOOL LoadModules();
105
106 BOOL ShowCallstack(
107 HANDLE hThread = GetCurrentThread(),
108 const CONTEXT* context = NULL,
109 PReadProcessMemoryRoutine readMemoryFunction = NULL,
110 LPVOID pUserData = NULL // optional to identify some data in the 'readMemoryFunction'-callback
111 );
112
113 BOOL ShowObject(LPVOID pObject);
114
James Kuszmaulcf324122023-01-14 14:07:17 -0800115#if _MSC_VER >= 1300
116 // due to some reasons, the "STACKWALK_MAX_NAMELEN" must be declared as "public"
117 // in older compilers in order to use it... starting with VC7 we can declare it as "protected"
Brian Silverman8fce7482020-01-05 13:18:21 -0800118protected:
James Kuszmaulcf324122023-01-14 14:07:17 -0800119#endif
Brian Silverman8fce7482020-01-05 13:18:21 -0800120 enum
121 {
122 STACKWALK_MAX_NAMELEN = 1024
123 }; // max name length for found symbols
124
125protected:
126 // Entry for each Callstack-Entry
127 typedef struct CallstackEntry
128 {
129 DWORD64 offset; // if 0, we have no valid entry
130 TCHAR name[STACKWALK_MAX_NAMELEN];
131 TCHAR undName[STACKWALK_MAX_NAMELEN];
132 TCHAR undFullName[STACKWALK_MAX_NAMELEN];
133 DWORD64 offsetFromSmybol;
134 DWORD offsetFromLine;
135 DWORD lineNumber;
136 TCHAR lineFileName[STACKWALK_MAX_NAMELEN];
137 DWORD symType;
138 LPCSTR symTypeString;
139 TCHAR moduleName[STACKWALK_MAX_NAMELEN];
140 DWORD64 baseOfImage;
141 TCHAR loadedImageName[STACKWALK_MAX_NAMELEN];
142 } CallstackEntry;
143
144 typedef enum CallstackEntryType
145 {
146 firstEntry,
147 nextEntry,
148 lastEntry
149 } CallstackEntryType;
150
151 virtual void OnSymInit(LPCTSTR szSearchPath, DWORD symOptions, LPCTSTR szUserName);
152 virtual void OnLoadModule(LPCTSTR img,
153 LPCTSTR mod,
154 DWORD64 baseAddr,
155 DWORD size,
156 DWORD result,
157 LPCTSTR symType,
158 LPCTSTR pdbName,
159 ULONGLONG fileVersion);
160 virtual void OnCallstackEntry(CallstackEntryType eType, CallstackEntry& entry);
161 virtual void OnDbgHelpErr(LPCTSTR szFuncName, DWORD gle, DWORD64 addr);
162 virtual void OnOutput(LPCTSTR szText);
163
164 StackWalkerInternal* m_sw;
165 HANDLE m_hProcess;
166 DWORD m_dwProcessId;
167 BOOL m_modulesLoaded;
168 LPTSTR m_szSymPath;
169
170 int m_options;
171 int m_MaxRecursionCount;
172
173 static BOOL __stdcall myReadProcMem(HANDLE hProcess,
174 DWORD64 qwBaseAddress,
175 PVOID lpBuffer,
176 DWORD nSize,
177 LPDWORD lpNumberOfBytesRead);
178
179 friend StackWalkerInternal;
180}; // class StackWalker
181
182// The following is defined for x86 (XP and higher), x64 and IA64:
183#define GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX(c, contextFlags) \
184 do \
185 { \
186 memset(&c, 0, sizeof(CONTEXT)); \
187 c.ContextFlags = contextFlags; \
188 RtlCaptureContext(&c); \
189 } while (0);
James Kuszmaulcf324122023-01-14 14:07:17 -0800190
191#endif //defined(_MSC_VER)
192
193#endif // __STACKWALKER_H__