1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: wx/msw/debughlp.h
3 // Purpose: wraps dbghelp.h standard file
4 // Author: Vadim Zeitlin
5 // Modified by: Suzumizaki-kimitaka 2013-04-10
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 ///////////////////////////////////////////////////////////////////////////////
11 #ifndef _WX_MSW_DEBUGHLPH_H_
12 #define _WX_MSW_DEBUGHLPH_H_
14 #include "wx/dynlib.h"
16 #include "wx/msw/wrapwin.h"
20 #include "wx/msw/private.h"
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
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.
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
39 #define wxUSE_DBGHELP 0
47 The table below shows which functions are exported by dbghelp.dll.
48 On 64 bit Windows, it looks no difference between 32bit dll and
50 Vista-64 and Win8-64 looks same, but in fact, "Ex" and "ExW"
51 versions are exist only in Windows 8.
53 Make sure SymGetLineFromAddrW and EnumerateLoadedModulesW DON'T
56 functions | Windows | XP-32 Vista-64 Win8-64
57 SymEnumSymbolsW n/a v v
59 SymInitializeW n/a v v
65 SymGetLineFromAddrW64 n/a v v
66 SymGetLineFromAddr64 v v v
67 SymGetLineFromAddrW n/a n/a n/a
68 SymGetLineFromAddr v v v
70 EnumerateLoadedModulesW64 n/a v v
71 EnumerateLoadedModules64 v v v
72 EnumerateLoadedModulesW n/a n/a n/a
73 EnumerateLoadedModules v v v
78 #define wxPENUMLOADED_MODULES_CALLBACK64 PENUMLOADED_MODULES_CALLBACKW64
79 #define wxPSYMBOL_INFO PSYMBOL_INFOW
80 #define wxSYMBOL_INFO SYMBOL_INFOW
81 #define wxPIMAGEHLP_LINE PIMAGEHLP_LINEW64
82 #define wxIMAGEHLP_LINE IMAGEHLP_LINEW64
83 #define wxPSYM_ENUMERATESYMBOLS_CALLBACK PSYM_ENUMERATESYMBOLS_CALLBACKW
85 #define wxPENUMLOADED_MODULES_CALLBACK64 PENUMLOADED_MODULES_CALLBACK64
86 #define wxPSYMBOL_INFO PSYMBOL_INFO
87 #define wxSYMBOL_INFO SYMBOL_INFO
88 #define wxPIMAGEHLP_LINE PIMAGEHLP_LINE64
89 #define wxIMAGEHLP_LINE IMAGEHLP_LINE64
90 #define wxPSYM_ENUMERATESYMBOLS_CALLBACK PSYM_ENUMERATESYMBOLS_CALLBACK
93 // ----------------------------------------------------------------------------
94 // wxDbgHelpDLL: dynamically load dbghelp.dll functions
95 // ----------------------------------------------------------------------------
97 // wrapper for some functions from dbghelp.dll
99 // MT note: this class is not MT safe and should be only used from a single
100 // thread at a time (this is so because dbghelp.dll is not MT-safe
105 // some useful constants not present in debughlp.h (stolen from DIA SDK)
108 BASICTYPE_NOTYPE
= 0,
118 BASICTYPE_ULONG
= 14,
119 BASICTYPE_CURRENCY
= 25,
121 BASICTYPE_VARIANT
= 27,
122 BASICTYPE_COMPLEX
= 28,
125 BASICTYPE_HRESULT
= 31,
133 SYMBOL_TAG_COMPILAND
,
134 SYMBOL_TAG_COMPILAND_DETAILS
,
135 SYMBOL_TAG_COMPILAND_ENV
,
139 SYMBOL_TAG_ANNOTATION
,
141 SYMBOL_TAG_PUBLIC_SYMBOL
,
144 SYMBOL_TAG_FUNCTION_TYPE
,
145 SYMBOL_TAG_POINTER_TYPE
,
146 SYMBOL_TAG_ARRAY_TYPE
,
147 SYMBOL_TAG_BASE_TYPE
,
149 SYMBOL_TAG_BASE_CLASS
,
151 SYMBOL_TAG_FUNCTION_ARG_TYPE
,
152 SYMBOL_TAG_FUNC_DEBUG_START
,
153 SYMBOL_TAG_FUNC_DEBUG_END
,
154 SYMBOL_TAG_USING_NAMESPACE
,
155 SYMBOL_TAG_VTABLE_SHAPE
,
159 SYMBOL_TAG_CUSTOM_TYPE
,
160 SYMBOL_TAG_MANAGED_TYPE
,
161 SYMBOL_TAG_DIMENSION
,
171 DATA_OBJECT_PTR
, // "this" pointer
190 typedef DWORD (WINAPI
*SymGetOptions_t
)();
191 typedef DWORD (WINAPI
*SymSetOptions_t
)(DWORD
);
192 typedef BOOL (WINAPI
*StackWalk_t
)(DWORD
, HANDLE
, HANDLE
, LPSTACKFRAME
,
193 LPVOID
, PREAD_PROCESS_MEMORY_ROUTINE
,
194 PFUNCTION_TABLE_ACCESS_ROUTINE
,
195 PGET_MODULE_BASE_ROUTINE
,
196 PTRANSLATE_ADDRESS_ROUTINE
);
197 typedef LPVOID (WINAPI
*SymFunctionTableAccess_t
)(HANDLE
, DWORD_PTR
);
198 typedef DWORD_PTR (WINAPI
*SymGetModuleBase_t
)(HANDLE
, DWORD_PTR
);
199 typedef BOOL (WINAPI
*SymSetContext_t
)(HANDLE
, PIMAGEHLP_STACK_FRAME
,
201 typedef BOOL (WINAPI
*SymGetTypeInfo_t
)(HANDLE
, DWORD64
, ULONG
,
202 IMAGEHLP_SYMBOL_TYPE_INFO
, PVOID
);
203 typedef BOOL (WINAPI
*SymCleanup_t
)(HANDLE
);
204 typedef BOOL (WINAPI
*MiniDumpWriteDump_t
)(HANDLE
, DWORD
, HANDLE
,
206 CONST PMINIDUMP_EXCEPTION_INFORMATION
,
207 CONST PMINIDUMP_USER_STREAM_INFORMATION
,
208 CONST PMINIDUMP_CALLBACK_INFORMATION
);
210 typedef BOOL (WINAPI
*EnumerateLoadedModules_t
)(HANDLE
, PENUMLOADED_MODULES_CALLBACK
, PVOID
);
211 typedef BOOL (WINAPI
*SymGetLineFromAddr_t
)(HANDLE
, DWORD
, PDWORD
, PIMAGEHLP_LINE
);
213 typedef BOOL (WINAPI
*EnumerateLoadedModules64_t
)(HANDLE
, PENUMLOADED_MODULES_CALLBACK64
, PVOID
);
214 typedef BOOL (WINAPI
*SymInitialize_t
)(HANDLE
, LPCSTR
, BOOL
);
215 typedef BOOL (WINAPI
*SymFromAddr_t
)(HANDLE
, DWORD64
, PDWORD64
, PSYMBOL_INFO
);
216 typedef BOOL (WINAPI
*SymGetLineFromAddr64_t
)(HANDLE
, DWORD64
, PDWORD
, PIMAGEHLP_LINE64
);
217 typedef BOOL (WINAPI
*SymEnumSymbols_t
)(HANDLE
, ULONG64
, PCSTR
,
218 PSYM_ENUMERATESYMBOLS_CALLBACK
, const PVOID
);
220 typedef BOOL (WINAPI
*EnumerateLoadedModulesW64_t
)(HANDLE
, PENUMLOADED_MODULES_CALLBACKW64
, PVOID
);
221 typedef BOOL (WINAPI
*SymInitializeW_t
)(HANDLE
, LPCWSTR
, BOOL
);
222 typedef BOOL (WINAPI
*SymFromAddrW_t
)(HANDLE
, DWORD64
, PDWORD64
, PSYMBOL_INFOW
);
223 typedef BOOL (WINAPI
*SymGetLineFromAddrW64_t
)(HANDLE
, DWORD64
, PDWORD
, PIMAGEHLP_LINEW64
);
224 typedef BOOL (WINAPI
*SymEnumSymbolsW_t
)(HANDLE
, ULONG64
, PCWSTR
,
225 PSYM_ENUMERATESYMBOLS_CALLBACKW
, const PVOID
);
227 static BOOL
EnumerateLoadedModulesT(HANDLE
, wxPENUMLOADED_MODULES_CALLBACK64
, PVOID
);
228 static BOOL
SymInitializeT(HANDLE
, LPCTSTR
, BOOL
);
229 static BOOL
SymFromAddrT(HANDLE
, DWORD64
, PDWORD64
, wxPSYMBOL_INFO
);
230 static BOOL
SymGetLineFromAddrT(HANDLE
, DWORD64
, PDWORD
, wxPIMAGEHLP_LINE
);
231 static BOOL
SymEnumSymbolsT(HANDLE
, ULONG64
, PCTSTR
, wxPSYM_ENUMERATESYMBOLS_CALLBACK
, const PVOID
);
233 // The macro called by wxDO_FOR_ALL_SYM_FUNCS() below takes 2 arguments:
234 // the name of the function in the program code, which never has "64"
235 // suffix, and the name of the function in the DLL which can have "64"
236 // suffix in some cases. These 2 helper macros call the macro with the
237 // correct arguments in both cases.
238 #define wxSYM_CALL(what, name) what(name, name)
239 #if defined(_M_AMD64)
240 #define wxSYM_CALL_64(what, name) what(name, name ## 64)
241 // Also undo all the "helpful" definitions done by imagehlp.h that map 32
242 // bit functions to 64 bit ones, we don't need this as we do it ourselves.
244 #undef SymFunctionTableAccess
245 #undef SymGetModuleBase
246 #undef SymGetLineFromAddr
247 #undef EnumerateLoadedModules
249 #define wxSYM_CALL_64(what, name) what(name, name)
252 #define wxSYM_CALL_ALWAYS_W(what, name) what(name ## W, name ## W)
254 #define wxSYM_CALL_ALTERNATIVES(what, name) \
256 what(name ## 64, name ## 64); \
257 what(name ## W64, name ## W64)
259 #define wxDO_FOR_ALL_SYM_FUNCS_REQUIRED_PUBLIC(what) \
260 wxSYM_CALL_64(what, StackWalk); \
261 wxSYM_CALL_64(what, SymFunctionTableAccess); \
262 wxSYM_CALL_64(what, SymGetModuleBase); \
264 wxSYM_CALL(what, SymGetOptions); \
265 wxSYM_CALL(what, SymSetOptions); \
266 wxSYM_CALL(what, SymSetContext); \
267 wxSYM_CALL(what, SymGetTypeInfo); \
268 wxSYM_CALL(what, SymCleanup); \
269 wxSYM_CALL(what, MiniDumpWriteDump)
271 #define wxDO_FOR_ALL_SYM_FUNCS_REQUIRED_PRIVATE(what) \
272 wxSYM_CALL(what, SymInitialize); \
273 wxSYM_CALL(what, SymFromAddr); \
274 wxSYM_CALL(what, SymEnumSymbols)
276 #define wxDO_FOR_ALL_SYM_FUNCS_REQUIRED(what) \
277 wxDO_FOR_ALL_SYM_FUNCS_REQUIRED_PRIVATE(what); \
278 wxDO_FOR_ALL_SYM_FUNCS_REQUIRED_PUBLIC(what)
280 // Alternation will work when the following functions are not found,
281 // therefore they are not included in REQUIRED version.
282 #define wxDO_FOR_ALL_SYM_FUNCS_OPTIONAL(what) \
283 wxSYM_CALL_ALTERNATIVES(what, SymGetLineFromAddr); \
284 wxSYM_CALL_ALTERNATIVES(what, EnumerateLoadedModules); \
285 wxSYM_CALL_ALWAYS_W(what, SymInitialize); \
286 wxSYM_CALL_ALWAYS_W(what, SymFromAddr); \
287 wxSYM_CALL_ALWAYS_W(what, SymEnumSymbols)
289 #define wxDO_FOR_ALL_SYM_FUNCS(what) \
290 wxDO_FOR_ALL_SYM_FUNCS_REQUIRED(what); \
291 wxDO_FOR_ALL_SYM_FUNCS_OPTIONAL(what)
293 #define wxDECLARE_SYM_FUNCTION(func, name) static func ## _t func
295 wxDO_FOR_ALL_SYM_FUNCS_REQUIRED_PUBLIC(wxDECLARE_SYM_FUNCTION
);
298 wxDO_FOR_ALL_SYM_FUNCS_REQUIRED_PRIVATE(wxDECLARE_SYM_FUNCTION
);
299 wxDO_FOR_ALL_SYM_FUNCS_OPTIONAL(wxDECLARE_SYM_FUNCTION
);
303 #undef wxDECLARE_SYM_FUNCTION
305 // load all functions from DLL, return true if ok
308 // return the string with the error message explaining why Init() failed
309 static const wxString
& GetErrorMessage();
311 // log error returned by the given function to debug output
312 static void LogError(const wxChar
*func
);
314 // return textual representation of the value of given symbol
315 static wxString
DumpSymbol(wxPSYMBOL_INFO pSymInfo
, void *pVariable
);
317 // return the name of the symbol with given type index
318 static wxString
GetSymbolName(wxPSYMBOL_INFO pSymInfo
);
321 // dereference the given symbol, i.e. return symbol which is not a
322 // pointer/reference any more
324 // if ppData != NULL, dereference the pointer as many times as we
325 // dereferenced the symbol
327 // return the tag of the dereferenced symbol
328 static SymbolTag
DereferenceSymbol(wxPSYMBOL_INFO pSymInfo
, void **ppData
);
330 static wxString
DumpField(wxPSYMBOL_INFO pSymInfo
,
334 static wxString
DumpBaseType(BasicType bt
, DWORD64 length
, void *pVariable
);
336 static wxString
DumpUDT(wxPSYMBOL_INFO pSymInfo
,
340 static bool BindDbgHelpFunctions(const wxDynamicLibrary
& dllDbgHelp
);
341 static bool DoInit();
344 #endif // wxUSE_DBGHELP
346 #endif // _WX_MSW_DEBUGHLPH_H_