blob: 750de96d8dde6451f2e4525604f02ae89d15983e [file] [log] [blame]
Brian Silverman8fce7482020-01-05 13:18:21 -08001/**********************************************************************
2 *
3 * StackWalker.h
4 *
5 *
6 *
7 * LICENSE (http://www.opensource.org/licenses/bsd-license.php)
8 *
9 * Copyright (c) 2005-2009, Jochen Kalmbach
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without modification,
13 * are permitted provided that the following conditions are met:
14 *
15 * Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 * Redistributions in binary form must reproduce the above copyright notice,
18 * this list of conditions and the following disclaimer in the documentation
19 * and/or other materials provided with the distribution.
20 * Neither the name of Jochen Kalmbach nor the names of its contributors may be
21 * used to endorse or promote products derived from this software without
22 * specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
25 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 * **********************************************************************/
35#pragma once
36
37#include <windows.h>
38
39#if _MSC_VER >= 1900
40#pragma warning(disable : 4091)
41#endif
42
43class StackWalkerInternal; // forward
44class StackWalker
45{
46public:
47 typedef enum StackWalkOptions
48 {
49 // No addition info will be retrieved
50 // (only the address is available)
51 RetrieveNone = 0,
52
53 // Try to get the symbol-name
54 RetrieveSymbol = 1,
55
56 // Try to get the line for this symbol
57 RetrieveLine = 2,
58
59 // Try to retrieve the module-infos
60 RetrieveModuleInfo = 4,
61
62 // Also retrieve the version for the DLL/EXE
63 RetrieveFileVersion = 8,
64
65 // Contains all the above
66 RetrieveVerbose = 0xF,
67
68 // Generate a "good" symbol-search-path
69 SymBuildPath = 0x10,
70
71 // Also use the public Microsoft-Symbol-Server
72 SymUseSymSrv = 0x20,
73
74 // Contains all the above "Sym"-options
75 SymAll = 0x30,
76
77 // Contains all options (default)
78 OptionsAll = 0x3F
79 } StackWalkOptions;
80
81 StackWalker(int options = OptionsAll, // 'int' is by design, to combine the enum-flags
82 LPCTSTR szSymPath = NULL,
83 DWORD dwProcessId = GetCurrentProcessId(),
84 HANDLE hProcess = GetCurrentProcess());
85 StackWalker(DWORD dwProcessId, HANDLE hProcess);
86 virtual ~StackWalker();
87
88 typedef BOOL(__stdcall* PReadProcessMemoryRoutine)(
89 HANDLE hProcess,
90 DWORD64 qwBaseAddress,
91 PVOID lpBuffer,
92 DWORD nSize,
93 LPDWORD lpNumberOfBytesRead,
94 LPVOID pUserData // optional data, which was passed in "ShowCallstack"
95 );
96
97 BOOL LoadModules();
98
99 BOOL ShowCallstack(
100 HANDLE hThread = GetCurrentThread(),
101 const CONTEXT* context = NULL,
102 PReadProcessMemoryRoutine readMemoryFunction = NULL,
103 LPVOID pUserData = NULL // optional to identify some data in the 'readMemoryFunction'-callback
104 );
105
106 BOOL ShowObject(LPVOID pObject);
107
108protected:
109 enum
110 {
111 STACKWALK_MAX_NAMELEN = 1024
112 }; // max name length for found symbols
113
114protected:
115 // Entry for each Callstack-Entry
116 typedef struct CallstackEntry
117 {
118 DWORD64 offset; // if 0, we have no valid entry
119 TCHAR name[STACKWALK_MAX_NAMELEN];
120 TCHAR undName[STACKWALK_MAX_NAMELEN];
121 TCHAR undFullName[STACKWALK_MAX_NAMELEN];
122 DWORD64 offsetFromSmybol;
123 DWORD offsetFromLine;
124 DWORD lineNumber;
125 TCHAR lineFileName[STACKWALK_MAX_NAMELEN];
126 DWORD symType;
127 LPCSTR symTypeString;
128 TCHAR moduleName[STACKWALK_MAX_NAMELEN];
129 DWORD64 baseOfImage;
130 TCHAR loadedImageName[STACKWALK_MAX_NAMELEN];
131 } CallstackEntry;
132
133 typedef enum CallstackEntryType
134 {
135 firstEntry,
136 nextEntry,
137 lastEntry
138 } CallstackEntryType;
139
140 virtual void OnSymInit(LPCTSTR szSearchPath, DWORD symOptions, LPCTSTR szUserName);
141 virtual void OnLoadModule(LPCTSTR img,
142 LPCTSTR mod,
143 DWORD64 baseAddr,
144 DWORD size,
145 DWORD result,
146 LPCTSTR symType,
147 LPCTSTR pdbName,
148 ULONGLONG fileVersion);
149 virtual void OnCallstackEntry(CallstackEntryType eType, CallstackEntry& entry);
150 virtual void OnDbgHelpErr(LPCTSTR szFuncName, DWORD gle, DWORD64 addr);
151 virtual void OnOutput(LPCTSTR szText);
152
153 StackWalkerInternal* m_sw;
154 HANDLE m_hProcess;
155 DWORD m_dwProcessId;
156 BOOL m_modulesLoaded;
157 LPTSTR m_szSymPath;
158
159 int m_options;
160 int m_MaxRecursionCount;
161
162 static BOOL __stdcall myReadProcMem(HANDLE hProcess,
163 DWORD64 qwBaseAddress,
164 PVOID lpBuffer,
165 DWORD nSize,
166 LPDWORD lpNumberOfBytesRead);
167
168 friend StackWalkerInternal;
169}; // class StackWalker
170
171// The following is defined for x86 (XP and higher), x64 and IA64:
172#define GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX(c, contextFlags) \
173 do \
174 { \
175 memset(&c, 0, sizeof(CONTEXT)); \
176 c.ContextFlags = contextFlags; \
177 RtlCaptureContext(&c); \
178 } while (0);