debughlp.h 9.4 KB

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