]> git.saurik.com Git - wxWidgets.git/blob - include/wx/msw/debughlp.h
715814d0ae3304cf8fada62418250c86f8275c09
[wxWidgets.git] / include / wx / msw / debughlp.h
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