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