]> git.saurik.com Git - wxWidgets.git/blob - include/wx/msw/debughlp.h
Reuse wxMessageOutputStderr for wxLogStderr implementation.
[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 // 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"
18 #ifndef __WXWINCE__
19 #include <imagehlp.h>
20 #endif // __WXWINCE__
21 #include "wx/msw/private.h"
22
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.
33 #ifndef wxUSE_DBGHELP
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
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);
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,
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
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
190 #define wxDO_FOR_ALL_SYM_FUNCS(what) \
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
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