]>
Commit | Line | Data |
---|---|---|
3d8b5d85 | 1 | /////////////////////////////////////////////////////////////////////////////// |
80fdcdb9 | 2 | // Name: wx/msw/debughlp.h |
3d8b5d85 VZ |
3 | // Purpose: wraps dbghelp.h standard file |
4 | // Author: Vadim Zeitlin | |
5 | // Modified by: | |
6 | // Created: 2005-01-08 (extracted from msw/crashrpt.cpp) | |
7 | // RCS-ID: $Id$ | |
8 | // Copyright: (c) 2003-2005 Vadim Zeitlin <vadim@wxwindows.org> | |
9 | // Licence: wxWindows licence | |
10 | /////////////////////////////////////////////////////////////////////////////// | |
11 | ||
12 | #ifndef _WX_MSW_DEBUGHLPH_H_ | |
13 | #define _WX_MSW_DEBUGHLPH_H_ | |
14 | ||
15 | #include "wx/dynlib.h" | |
16 | ||
17 | #include "wx/msw/wrapwin.h" | |
23ee4b48 | 18 | #ifndef __WXWINCE__ |
3d8b5d85 | 19 | #include <imagehlp.h> |
23ee4b48 | 20 | #endif // __WXWINCE__ |
3d8b5d85 VZ |
21 | #include "wx/msw/private.h" |
22 | ||
7d8741ed VZ |
23 | // All known versions of imagehlp.h define API_VERSION_NUMBER but it's not |
24 | // documented, so deal with the possibility that it's not defined just in case. | |
25 | #ifndef API_VERSION_NUMBER | |
26 | #define API_VERSION_NUMBER 0 | |
27 | #endif | |
28 | ||
29 | // wxUSE_DBGHELP is a bit special as it is not defined in wx/setup.h and we try | |
30 | // to auto-detect whether we should be using debug help API or not ourselves | |
31 | // below. However if the auto-detection fails, you can always predefine it as 0 | |
32 | // to avoid even trying. | |
3d8b5d85 | 33 | #ifndef wxUSE_DBGHELP |
7d8741ed VZ |
34 | // The version of imagehlp.h from VC6 (7) is too old and is missing some |
35 | // required symbols while the version from VC7 (9) is good enough. As we | |
36 | // don't know anything about version 8, don't use it unless we can test it. | |
37 | #if API_VERSION_NUMBER >= 9 | |
3d8b5d85 VZ |
38 | #define wxUSE_DBGHELP 1 |
39 | #else | |
40 | #define wxUSE_DBGHELP 0 | |
41 | #endif | |
42 | #endif | |
43 | ||
44 | #if wxUSE_DBGHELP | |
45 | ||
46 | // ---------------------------------------------------------------------------- | |
47 | // wxDbgHelpDLL: dynamically load dbghelp.dll functions | |
48 | // ---------------------------------------------------------------------------- | |
49 | ||
50 | // wrapper for some functions from dbghelp.dll | |
51 | // | |
52 | // MT note: this class is not MT safe and should be only used from a single | |
53 | // thread at a time (this is so because dbghelp.dll is not MT-safe | |
54 | // itself anyhow) | |
55 | class wxDbgHelpDLL | |
56 | { | |
57 | public: | |
58 | // some useful constants not present in debughlp.h (stolen from DIA SDK) | |
59 | enum BasicType | |
60 | { | |
61 | BASICTYPE_NOTYPE = 0, | |
62 | BASICTYPE_VOID = 1, | |
63 | BASICTYPE_CHAR = 2, | |
64 | BASICTYPE_WCHAR = 3, | |
65 | BASICTYPE_INT = 6, | |
66 | BASICTYPE_UINT = 7, | |
67 | BASICTYPE_FLOAT = 8, | |
68 | BASICTYPE_BCD = 9, | |
69 | BASICTYPE_BOOL = 10, | |
70 | BASICTYPE_LONG = 13, | |
71 | BASICTYPE_ULONG = 14, | |
72 | BASICTYPE_CURRENCY = 25, | |
73 | BASICTYPE_DATE = 26, | |
74 | BASICTYPE_VARIANT = 27, | |
75 | BASICTYPE_COMPLEX = 28, | |
76 | BASICTYPE_BIT = 29, | |
77 | BASICTYPE_BSTR = 30, | |
78 | BASICTYPE_HRESULT = 31, | |
79 | BASICTYPE_MAX | |
80 | }; | |
81 | ||
82 | enum SymbolTag | |
83 | { | |
84 | SYMBOL_TAG_NULL, | |
85 | SYMBOL_TAG_EXE, | |
86 | SYMBOL_TAG_COMPILAND, | |
87 | SYMBOL_TAG_COMPILAND_DETAILS, | |
88 | SYMBOL_TAG_COMPILAND_ENV, | |
89 | SYMBOL_TAG_FUNCTION, | |
90 | SYMBOL_TAG_BLOCK, | |
91 | SYMBOL_TAG_DATA, | |
92 | SYMBOL_TAG_ANNOTATION, | |
93 | SYMBOL_TAG_LABEL, | |
94 | SYMBOL_TAG_PUBLIC_SYMBOL, | |
95 | SYMBOL_TAG_UDT, | |
96 | SYMBOL_TAG_ENUM, | |
97 | SYMBOL_TAG_FUNCTION_TYPE, | |
98 | SYMBOL_TAG_POINTER_TYPE, | |
99 | SYMBOL_TAG_ARRAY_TYPE, | |
100 | SYMBOL_TAG_BASE_TYPE, | |
101 | SYMBOL_TAG_TYPEDEF, | |
102 | SYMBOL_TAG_BASE_CLASS, | |
103 | SYMBOL_TAG_FRIEND, | |
104 | SYMBOL_TAG_FUNCTION_ARG_TYPE, | |
105 | SYMBOL_TAG_FUNC_DEBUG_START, | |
106 | SYMBOL_TAG_FUNC_DEBUG_END, | |
107 | SYMBOL_TAG_USING_NAMESPACE, | |
108 | SYMBOL_TAG_VTABLE_SHAPE, | |
109 | SYMBOL_TAG_VTABLE, | |
110 | SYMBOL_TAG_CUSTOM, | |
111 | SYMBOL_TAG_THUNK, | |
112 | SYMBOL_TAG_CUSTOM_TYPE, | |
113 | SYMBOL_TAG_MANAGED_TYPE, | |
114 | SYMBOL_TAG_DIMENSION, | |
115 | SYMBOL_TAG_MAX | |
116 | }; | |
117 | ||
118 | enum DataKind | |
119 | { | |
120 | DATA_UNKNOWN, | |
121 | DATA_LOCAL, | |
122 | DATA_STATIC_LOCAL, | |
123 | DATA_PARAM, | |
124 | DATA_OBJECT_PTR, // "this" pointer | |
125 | DATA_FILE_STATIC, | |
126 | DATA_GLOBAL, | |
127 | DATA_MEMBER, | |
128 | DATA_STATIC_MEMBER, | |
129 | DATA_CONSTANT, | |
130 | DATA_MAX | |
131 | }; | |
132 | ||
133 | enum UdtKind | |
134 | { | |
135 | UDT_STRUCT, | |
136 | UDT_CLASS, | |
137 | UDT_UNION, | |
138 | UDT_MAX | |
139 | }; | |
140 | ||
141 | ||
142 | // function types | |
143 | typedef DWORD (WINAPI *SymGetOptions_t)(); | |
144 | typedef DWORD (WINAPI *SymSetOptions_t)(DWORD); | |
145 | typedef BOOL (WINAPI *SymInitialize_t)(HANDLE, LPSTR, BOOL); | |
146 | typedef BOOL (WINAPI *StackWalk_t)(DWORD, HANDLE, HANDLE, LPSTACKFRAME, | |
147 | LPVOID, PREAD_PROCESS_MEMORY_ROUTINE, | |
148 | PFUNCTION_TABLE_ACCESS_ROUTINE, | |
149 | PGET_MODULE_BASE_ROUTINE, | |
150 | PTRANSLATE_ADDRESS_ROUTINE); | |
151 | typedef BOOL (WINAPI *SymFromAddr_t)(HANDLE, DWORD64, PDWORD64, PSYMBOL_INFO); | |
603c73db VZ |
152 | typedef LPVOID (WINAPI *SymFunctionTableAccess_t)(HANDLE, DWORD_PTR); |
153 | typedef DWORD_PTR (WINAPI *SymGetModuleBase_t)(HANDLE, DWORD_PTR); | |
154 | typedef BOOL (WINAPI *SymGetLineFromAddr_t)(HANDLE, DWORD_PTR, | |
3d8b5d85 VZ |
155 | PDWORD, PIMAGEHLP_LINE); |
156 | typedef BOOL (WINAPI *SymSetContext_t)(HANDLE, PIMAGEHLP_STACK_FRAME, | |
157 | PIMAGEHLP_CONTEXT); | |
158 | typedef BOOL (WINAPI *SymEnumSymbols_t)(HANDLE, ULONG64, PCSTR, | |
159 | PSYM_ENUMERATESYMBOLS_CALLBACK, PVOID); | |
160 | typedef BOOL (WINAPI *SymGetTypeInfo_t)(HANDLE, DWORD64, ULONG, | |
161 | IMAGEHLP_SYMBOL_TYPE_INFO, PVOID); | |
162 | typedef BOOL (WINAPI *SymCleanup_t)(HANDLE); | |
163 | typedef BOOL (WINAPI *EnumerateLoadedModules_t)(HANDLE, PENUMLOADED_MODULES_CALLBACK, PVOID); | |
164 | typedef BOOL (WINAPI *MiniDumpWriteDump_t)(HANDLE, DWORD, HANDLE, | |
165 | MINIDUMP_TYPE, | |
166 | CONST PMINIDUMP_EXCEPTION_INFORMATION, | |
167 | CONST PMINIDUMP_USER_STREAM_INFORMATION, | |
168 | CONST PMINIDUMP_CALLBACK_INFORMATION); | |
169 | ||
603c73db VZ |
170 | // The macro called by wxDO_FOR_ALL_SYM_FUNCS() below takes 2 arguments: |
171 | // the name of the function in the program code, which never has "64" | |
172 | // suffix, and the name of the function in the DLL which can have "64" | |
173 | // suffix in some cases. These 2 helper macros call the macro with the | |
174 | // correct arguments in both cases. | |
175 | #define wxSYM_CALL(what, name) what(name, name) | |
176 | #if defined(_M_AMD64) | |
177 | #define wxSYM_CALL_64(what, name) what(name, name ## 64) | |
178 | ||
179 | // Also undo all the "helpful" definitions done by imagehlp.h that map 32 | |
180 | // bit functions to 64 bit ones, we don't need this as we do it ourselves. | |
181 | #undef StackWalk | |
182 | #undef SymFunctionTableAccess | |
183 | #undef SymGetModuleBase | |
184 | #undef SymGetLineFromAddr | |
185 | #undef EnumerateLoadedModules | |
186 | #else | |
187 | #define wxSYM_CALL_64(what, name) what(name, name) | |
188 | #endif | |
189 | ||
3d8b5d85 | 190 | #define wxDO_FOR_ALL_SYM_FUNCS(what) \ |
603c73db VZ |
191 | wxSYM_CALL_64(what, StackWalk); \ |
192 | wxSYM_CALL_64(what, SymFunctionTableAccess); \ | |
193 | wxSYM_CALL_64(what, SymGetModuleBase); \ | |
194 | wxSYM_CALL_64(what, SymGetLineFromAddr); \ | |
195 | wxSYM_CALL_64(what, EnumerateLoadedModules); \ | |
196 | \ | |
197 | wxSYM_CALL(what, SymGetOptions); \ | |
198 | wxSYM_CALL(what, SymSetOptions); \ | |
199 | wxSYM_CALL(what, SymInitialize); \ | |
200 | wxSYM_CALL(what, SymFromAddr); \ | |
201 | wxSYM_CALL(what, SymSetContext); \ | |
202 | wxSYM_CALL(what, SymEnumSymbols); \ | |
203 | wxSYM_CALL(what, SymGetTypeInfo); \ | |
204 | wxSYM_CALL(what, SymCleanup); \ | |
205 | wxSYM_CALL(what, MiniDumpWriteDump) | |
206 | ||
207 | #define wxDECLARE_SYM_FUNCTION(func, name) static func ## _t func | |
3d8b5d85 VZ |
208 | |
209 | wxDO_FOR_ALL_SYM_FUNCS(wxDECLARE_SYM_FUNCTION); | |
210 | ||
211 | #undef wxDECLARE_SYM_FUNCTION | |
212 | ||
213 | // load all functions from DLL, return true if ok | |
214 | static bool Init(); | |
215 | ||
216 | // return the string with the error message explaining why Init() failed | |
217 | static const wxString& GetErrorMessage(); | |
218 | ||
219 | // log error returned by the given function to debug output | |
220 | static void LogError(const wxChar *func); | |
221 | ||
222 | // return textual representation of the value of given symbol | |
223 | static wxString DumpSymbol(PSYMBOL_INFO pSymInfo, void *pVariable); | |
224 | ||
225 | // return the name of the symbol with given type index | |
226 | static wxString GetSymbolName(PSYMBOL_INFO pSymInfo); | |
227 | ||
228 | private: | |
229 | // dereference the given symbol, i.e. return symbol which is not a | |
230 | // pointer/reference any more | |
231 | // | |
232 | // if ppData != NULL, dereference the pointer as many times as we | |
233 | // dereferenced the symbol | |
234 | // | |
235 | // return the tag of the dereferenced symbol | |
236 | static SymbolTag DereferenceSymbol(PSYMBOL_INFO pSymInfo, void **ppData); | |
237 | ||
238 | static wxString DumpField(PSYMBOL_INFO pSymInfo, | |
239 | void *pVariable, | |
240 | unsigned level); | |
241 | ||
242 | static wxString DumpBaseType(BasicType bt, DWORD64 length, void *pVariable); | |
243 | ||
244 | static wxString DumpUDT(PSYMBOL_INFO pSymInfo, | |
245 | void *pVariable, | |
246 | unsigned level = 0); | |
247 | }; | |
248 | ||
249 | #endif // wxUSE_DBGHELP | |
250 | ||
251 | #endif // _WX_MSW_DEBUGHLPH_H_ | |
252 |