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