From bf9ce7b55ec8d1e4a8f2dd8ca2c2b6e9f86b57b7 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 15 Sep 2013 00:16:34 +0000 Subject: [PATCH] Make wxMSW stack walking methods work with Unicode identifiers. This allows to show the stack properly for e.g. Japanese programs. Closes #15138. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74817 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 1 + include/wx/msw/debughlp.h | 156 +++++++++++++---- include/wx/msw/stackwalk.h | 9 +- src/msw/debughlp.cpp | 351 +++++++++++++++++++++++++++++++++++-- src/msw/dlmsw.cpp | 38 ++-- src/msw/stackwalk.cpp | 53 +++--- 6 files changed, 520 insertions(+), 88 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 865271b1e8..df77c872d8 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -589,6 +589,7 @@ wxMSW: - Fix launching some types of files under Windows 7 and later (Steven Houchins). - Don't use an icon for items inserted without one into wxListCtrl (Chuddah). - Handle custom configurations when using MSVC autolinking (tinman). +- Fix wxStackWalker to work with Unicode identifiers (suzumizaki). wxOSX: diff --git a/include/wx/msw/debughlp.h b/include/wx/msw/debughlp.h index 715814d0ae..cceb8b99b5 100644 --- a/include/wx/msw/debughlp.h +++ b/include/wx/msw/debughlp.h @@ -2,7 +2,7 @@ // Name: wx/msw/debughlp.h // Purpose: wraps dbghelp.h standard file // Author: Vadim Zeitlin -// Modified by: +// Modified by: Suzumizaki-kimitaka 2013-04-10 // Created: 2005-01-08 (extracted from msw/crashrpt.cpp) // Copyright: (c) 2003-2005 Vadim Zeitlin // Licence: wxWindows licence @@ -42,6 +42,54 @@ #if wxUSE_DBGHELP +/* + +The table below shows which functions are exported by dbghelp.dll. +On 64 bit Windows, it looks no difference between 32bit dll and +64bit one. +Vista-64 and Win8-64 looks same, but in fact, "Ex" and "ExW" +versions are exist only in Windows 8. + +Make sure SymGetLineFromAddrW and EnumerateLoadedModulesW DON'T +exists. + +functions | Windows | XP-32 Vista-64 Win8-64 +SymEnumSymbolsW n/a v v +SymFromAddrW n/a v v +SymInitializeW n/a v v + +SymEnumSymbols v v v +SymFromAddr v v v +SymInitialize v v v + +SymGetLineFromAddrW64 n/a v v +SymGetLineFromAddr64 v v v +SymGetLineFromAddrW n/a n/a n/a +SymGetLineFromAddr v v v + +EnumerateLoadedModulesW64 n/a v v +EnumerateLoadedModules64 v v v +EnumerateLoadedModulesW n/a n/a n/a +EnumerateLoadedModules v v v + +*/ + +#ifdef UNICODE +#define wxPENUMLOADED_MODULES_CALLBACK64 PENUMLOADED_MODULES_CALLBACKW64 +#define wxPSYMBOL_INFO PSYMBOL_INFOW +#define wxSYMBOL_INFO SYMBOL_INFOW +#define wxPIMAGEHLP_LINE PIMAGEHLP_LINEW64 +#define wxIMAGEHLP_LINE IMAGEHLP_LINEW64 +#define wxPSYM_ENUMERATESYMBOLS_CALLBACK PSYM_ENUMERATESYMBOLS_CALLBACKW +#else +#define wxPENUMLOADED_MODULES_CALLBACK64 PENUMLOADED_MODULES_CALLBACK64 +#define wxPSYMBOL_INFO PSYMBOL_INFO +#define wxSYMBOL_INFO SYMBOL_INFO +#define wxPIMAGEHLP_LINE PIMAGEHLP_LINE64 +#define wxIMAGEHLP_LINE IMAGEHLP_LINE64 +#define wxPSYM_ENUMERATESYMBOLS_CALLBACK PSYM_ENUMERATESYMBOLS_CALLBACK +#endif + // ---------------------------------------------------------------------------- // wxDbgHelpDLL: dynamically load dbghelp.dll functions // ---------------------------------------------------------------------------- @@ -141,31 +189,47 @@ public: // function types typedef DWORD (WINAPI *SymGetOptions_t)(); typedef DWORD (WINAPI *SymSetOptions_t)(DWORD); - typedef BOOL (WINAPI *SymInitialize_t)(HANDLE, LPSTR, BOOL); typedef BOOL (WINAPI *StackWalk_t)(DWORD, HANDLE, HANDLE, LPSTACKFRAME, LPVOID, PREAD_PROCESS_MEMORY_ROUTINE, PFUNCTION_TABLE_ACCESS_ROUTINE, PGET_MODULE_BASE_ROUTINE, PTRANSLATE_ADDRESS_ROUTINE); - typedef BOOL (WINAPI *SymFromAddr_t)(HANDLE, DWORD64, PDWORD64, PSYMBOL_INFO); typedef LPVOID (WINAPI *SymFunctionTableAccess_t)(HANDLE, DWORD_PTR); typedef DWORD_PTR (WINAPI *SymGetModuleBase_t)(HANDLE, DWORD_PTR); - typedef BOOL (WINAPI *SymGetLineFromAddr_t)(HANDLE, DWORD_PTR, - PDWORD, PIMAGEHLP_LINE); typedef BOOL (WINAPI *SymSetContext_t)(HANDLE, PIMAGEHLP_STACK_FRAME, PIMAGEHLP_CONTEXT); - typedef BOOL (WINAPI *SymEnumSymbols_t)(HANDLE, ULONG64, PCSTR, - PSYM_ENUMERATESYMBOLS_CALLBACK, PVOID); typedef BOOL (WINAPI *SymGetTypeInfo_t)(HANDLE, DWORD64, ULONG, IMAGEHLP_SYMBOL_TYPE_INFO, PVOID); typedef BOOL (WINAPI *SymCleanup_t)(HANDLE); - typedef BOOL (WINAPI *EnumerateLoadedModules_t)(HANDLE, PENUMLOADED_MODULES_CALLBACK, PVOID); typedef BOOL (WINAPI *MiniDumpWriteDump_t)(HANDLE, DWORD, HANDLE, MINIDUMP_TYPE, CONST PMINIDUMP_EXCEPTION_INFORMATION, CONST PMINIDUMP_USER_STREAM_INFORMATION, CONST PMINIDUMP_CALLBACK_INFORMATION); + typedef BOOL (WINAPI *EnumerateLoadedModules_t)(HANDLE, PENUMLOADED_MODULES_CALLBACK, PVOID); + typedef BOOL (WINAPI *SymGetLineFromAddr_t)(HANDLE, DWORD, PDWORD, PIMAGEHLP_LINE); + + typedef BOOL (WINAPI *EnumerateLoadedModules64_t)(HANDLE, PENUMLOADED_MODULES_CALLBACK64, PVOID); + typedef BOOL (WINAPI *SymInitialize_t)(HANDLE, LPCSTR, BOOL); + typedef BOOL (WINAPI *SymFromAddr_t)(HANDLE, DWORD64, PDWORD64, PSYMBOL_INFO); + typedef BOOL (WINAPI *SymGetLineFromAddr64_t)(HANDLE, DWORD64, PDWORD, PIMAGEHLP_LINE64); + typedef BOOL (WINAPI *SymEnumSymbols_t)(HANDLE, ULONG64, PCSTR, + PSYM_ENUMERATESYMBOLS_CALLBACK, const PVOID); + + typedef BOOL (WINAPI *EnumerateLoadedModulesW64_t)(HANDLE, PENUMLOADED_MODULES_CALLBACKW64, PVOID); + typedef BOOL (WINAPI *SymInitializeW_t)(HANDLE, LPCWSTR, BOOL); + typedef BOOL (WINAPI *SymFromAddrW_t)(HANDLE, DWORD64, PDWORD64, PSYMBOL_INFOW); + typedef BOOL (WINAPI *SymGetLineFromAddrW64_t)(HANDLE, DWORD64, PDWORD, PIMAGEHLP_LINEW64); + typedef BOOL (WINAPI *SymEnumSymbolsW_t)(HANDLE, ULONG64, PCWSTR, + PSYM_ENUMERATESYMBOLS_CALLBACKW, const PVOID); + + static BOOL EnumerateLoadedModulesT(HANDLE, wxPENUMLOADED_MODULES_CALLBACK64, PVOID); + static BOOL SymInitializeT(HANDLE, LPCTSTR, BOOL); + static BOOL SymFromAddrT(HANDLE, DWORD64, PDWORD64, wxPSYMBOL_INFO); + static BOOL SymGetLineFromAddrT(HANDLE, DWORD64, PDWORD, wxPIMAGEHLP_LINE); + static BOOL SymEnumSymbolsT(HANDLE, ULONG64, PCTSTR, wxPSYM_ENUMERATESYMBOLS_CALLBACK, const PVOID); + // The macro called by wxDO_FOR_ALL_SYM_FUNCS() below takes 2 arguments: // the name of the function in the program code, which never has "64" // suffix, and the name of the function in the DLL which can have "64" @@ -174,7 +238,6 @@ public: #define wxSYM_CALL(what, name) what(name, name) #if defined(_M_AMD64) #define wxSYM_CALL_64(what, name) what(name, name ## 64) - // Also undo all the "helpful" definitions done by imagehlp.h that map 32 // bit functions to 64 bit ones, we don't need this as we do it ourselves. #undef StackWalk @@ -186,26 +249,56 @@ public: #define wxSYM_CALL_64(what, name) what(name, name) #endif - #define wxDO_FOR_ALL_SYM_FUNCS(what) \ - wxSYM_CALL_64(what, StackWalk); \ - wxSYM_CALL_64(what, SymFunctionTableAccess); \ - wxSYM_CALL_64(what, SymGetModuleBase); \ - wxSYM_CALL_64(what, SymGetLineFromAddr); \ - wxSYM_CALL_64(what, EnumerateLoadedModules); \ - \ - wxSYM_CALL(what, SymGetOptions); \ - wxSYM_CALL(what, SymSetOptions); \ - wxSYM_CALL(what, SymInitialize); \ - wxSYM_CALL(what, SymFromAddr); \ - wxSYM_CALL(what, SymSetContext); \ - wxSYM_CALL(what, SymEnumSymbols); \ - wxSYM_CALL(what, SymGetTypeInfo); \ - wxSYM_CALL(what, SymCleanup); \ + #define wxSYM_CALL_ALWAYS_W(what, name) what(name ## W, name ## W) + + #define wxSYM_CALL_ALTERNATIVES(what, name) \ + what(name, name); \ + what(name ## 64, name ## 64); \ + what(name ## W64, name ## W64) + + #define wxDO_FOR_ALL_SYM_FUNCS_REQUIRED_PUBLIC(what) \ + wxSYM_CALL_64(what, StackWalk); \ + wxSYM_CALL_64(what, SymFunctionTableAccess); \ + wxSYM_CALL_64(what, SymGetModuleBase); \ + \ + wxSYM_CALL(what, SymGetOptions); \ + wxSYM_CALL(what, SymSetOptions); \ + wxSYM_CALL(what, SymSetContext); \ + wxSYM_CALL(what, SymGetTypeInfo); \ + wxSYM_CALL(what, SymCleanup); \ wxSYM_CALL(what, MiniDumpWriteDump) + #define wxDO_FOR_ALL_SYM_FUNCS_REQUIRED_PRIVATE(what) \ + wxSYM_CALL(what, SymInitialize); \ + wxSYM_CALL(what, SymFromAddr); \ + wxSYM_CALL(what, SymEnumSymbols) + + #define wxDO_FOR_ALL_SYM_FUNCS_REQUIRED(what) \ + wxDO_FOR_ALL_SYM_FUNCS_REQUIRED_PRIVATE(what); \ + wxDO_FOR_ALL_SYM_FUNCS_REQUIRED_PUBLIC(what) + + // Alternation will work when the following functions are not found, + // therefore they are not included in REQUIRED version. + #define wxDO_FOR_ALL_SYM_FUNCS_OPTIONAL(what) \ + wxSYM_CALL_ALTERNATIVES(what, SymGetLineFromAddr); \ + wxSYM_CALL_ALTERNATIVES(what, EnumerateLoadedModules); \ + wxSYM_CALL_ALWAYS_W(what, SymInitialize); \ + wxSYM_CALL_ALWAYS_W(what, SymFromAddr); \ + wxSYM_CALL_ALWAYS_W(what, SymEnumSymbols) + + #define wxDO_FOR_ALL_SYM_FUNCS(what) \ + wxDO_FOR_ALL_SYM_FUNCS_REQUIRED(what); \ + wxDO_FOR_ALL_SYM_FUNCS_OPTIONAL(what) + #define wxDECLARE_SYM_FUNCTION(func, name) static func ## _t func - wxDO_FOR_ALL_SYM_FUNCS(wxDECLARE_SYM_FUNCTION); + wxDO_FOR_ALL_SYM_FUNCS_REQUIRED_PUBLIC(wxDECLARE_SYM_FUNCTION); + +private: + wxDO_FOR_ALL_SYM_FUNCS_REQUIRED_PRIVATE(wxDECLARE_SYM_FUNCTION); + wxDO_FOR_ALL_SYM_FUNCS_OPTIONAL(wxDECLARE_SYM_FUNCTION); + +public: #undef wxDECLARE_SYM_FUNCTION @@ -219,10 +312,10 @@ public: static void LogError(const wxChar *func); // return textual representation of the value of given symbol - static wxString DumpSymbol(PSYMBOL_INFO pSymInfo, void *pVariable); + static wxString DumpSymbol(wxPSYMBOL_INFO pSymInfo, void *pVariable); // return the name of the symbol with given type index - static wxString GetSymbolName(PSYMBOL_INFO pSymInfo); + static wxString GetSymbolName(wxPSYMBOL_INFO pSymInfo); private: // dereference the given symbol, i.e. return symbol which is not a @@ -232,17 +325,20 @@ private: // dereferenced the symbol // // return the tag of the dereferenced symbol - static SymbolTag DereferenceSymbol(PSYMBOL_INFO pSymInfo, void **ppData); + static SymbolTag DereferenceSymbol(wxPSYMBOL_INFO pSymInfo, void **ppData); - static wxString DumpField(PSYMBOL_INFO pSymInfo, + static wxString DumpField(wxPSYMBOL_INFO pSymInfo, void *pVariable, unsigned level); static wxString DumpBaseType(BasicType bt, DWORD64 length, void *pVariable); - static wxString DumpUDT(PSYMBOL_INFO pSymInfo, + static wxString DumpUDT(wxPSYMBOL_INFO pSymInfo, void *pVariable, unsigned level = 0); + + static bool BindDbgHelpFunctions(const wxDynamicLibrary& dllDbgHelp); + static bool DoInit(); }; #endif // wxUSE_DBGHELP diff --git a/include/wx/msw/stackwalk.h b/include/wx/msw/stackwalk.h index 6ff467205e..57eeca9761 100644 --- a/include/wx/msw/stackwalk.h +++ b/include/wx/msw/stackwalk.h @@ -2,7 +2,7 @@ // Name: wx/msw/stackwalk.h // Purpose: wxStackWalker for MSW // Author: Vadim Zeitlin -// Modified by: +// Modified by: Suzumizaki-kimitaka 2013-04-09 // Created: 2005-01-08 // Copyright: (c) 2005 Vadim Zeitlin // Licence: wxWindows licence @@ -19,6 +19,7 @@ struct _EXCEPTION_POINTERS; // and these in dbghelp.h struct _SYMBOL_INFO; +struct _SYMBOL_INFOW; // ---------------------------------------------------------------------------- // wxStackFrame @@ -52,7 +53,11 @@ public: GetParam(size_t n, wxString *type, wxString *name, wxString *value) const; // callback used by OnGetParam(), don't call directly - void OnParam(_SYMBOL_INFO *pSymInfo); +#ifdef UNICODE + void OnParam(_SYMBOL_INFOW * pSymInfo); +#else + void OnParam(_SYMBOL_INFO * pSymInfo); +#endif protected: virtual void OnGetName(); diff --git a/src/msw/debughlp.cpp b/src/msw/debughlp.cpp index 161a532933..8a76027c76 100644 --- a/src/msw/debughlp.cpp +++ b/src/msw/debughlp.cpp @@ -2,7 +2,7 @@ // Name: src/msw/debughlp.cpp // Purpose: various Win32 debug helpers // Author: Vadim Zeitlin -// Modified by: +// Modified by: Suzumizaki-kimitaka 2013-04-10 // Created: 2005-01-08 (extracted from crashrpt.cpp) // Copyright: (c) 2003-2005 Vadim Zeitlin // Licence: wxWindows licence @@ -62,7 +62,8 @@ wxDO_FOR_ALL_SYM_FUNCS(DEFINE_SYM_FUNCTION); // load all function we need from the DLL -static bool BindDbgHelpFunctions(const wxDynamicLibrary& dllDbgHelp) +/* static */ +bool wxDbgHelpDLL::BindDbgHelpFunctions(const wxDynamicLibrary& dllDbgHelp) { #define LOAD_SYM_FUNCTION(func, name) \ wxDbgHelpDLL::func = (wxDbgHelpDLL::func ## _t) \ @@ -73,15 +74,27 @@ static bool BindDbgHelpFunctions(const wxDynamicLibrary& dllDbgHelp) return false; \ } - wxDO_FOR_ALL_SYM_FUNCS(LOAD_SYM_FUNCTION); + wxDO_FOR_ALL_SYM_FUNCS_REQUIRED(LOAD_SYM_FUNCTION); #undef LOAD_SYM_FUNCTION + #define LOAD_SYM_FUNCTION_OPTIONAL(func, name) \ + if ( dllDbgHelp.HasSymbol(wxT(#name)) ) \ + { \ + wxDbgHelpDLL::func = (wxDbgHelpDLL::func ## _t) \ + dllDbgHelp.GetSymbol(wxT(#name)); \ + } + + wxDO_FOR_ALL_SYM_FUNCS_OPTIONAL(LOAD_SYM_FUNCTION_OPTIONAL); + + #undef LOAD_SYM_FUNCTION_CAN_FAIL + return true; } // called by Init() if we hadn't done this before -static bool DoInit() +/* static */ +bool wxDbgHelpDLL::DoInit() { wxDynamicLibrary dllDbgHelp(wxT("dbghelp.dll"), wxDL_VERBATIM); if ( dllDbgHelp.IsLoaded() ) @@ -170,13 +183,13 @@ DoGetTypeInfo(DWORD64 base, ULONG ti, IMAGEHLP_SYMBOL_TYPE_INFO type, void *rc) static inline bool -DoGetTypeInfo(PSYMBOL_INFO pSym, IMAGEHLP_SYMBOL_TYPE_INFO type, void *rc) +DoGetTypeInfo(wxPSYMBOL_INFO pSym, IMAGEHLP_SYMBOL_TYPE_INFO type, void *rc) { return DoGetTypeInfo(pSym->ModBase, pSym->TypeIndex, type, rc); } static inline -wxDbgHelpDLL::BasicType GetBasicType(PSYMBOL_INFO pSym) +wxDbgHelpDLL::BasicType GetBasicType(wxPSYMBOL_INFO pSym) { wxDbgHelpDLL::BasicType bt; return DoGetTypeInfo(pSym, TI_GET_BASETYPE, &bt) @@ -185,7 +198,7 @@ wxDbgHelpDLL::BasicType GetBasicType(PSYMBOL_INFO pSym) } /* static */ -wxString wxDbgHelpDLL::GetSymbolName(PSYMBOL_INFO pSym) +wxString wxDbgHelpDLL::GetSymbolName(wxPSYMBOL_INFO pSym) { wxString s; @@ -289,7 +302,7 @@ wxDbgHelpDLL::DumpBaseType(BasicType bt, DWORD64 length, PVOID pAddress) } wxString -wxDbgHelpDLL::DumpField(PSYMBOL_INFO pSym, void *pVariable, unsigned level) +wxDbgHelpDLL::DumpField(wxPSYMBOL_INFO pSym, void *pVariable, unsigned level) { wxString s; @@ -336,7 +349,7 @@ wxDbgHelpDLL::DumpField(PSYMBOL_INFO pSym, void *pVariable, unsigned level) // now pass to the type representing the type of this member - SYMBOL_INFO sym = *pSym; + wxSYMBOL_INFO sym = *pSym; if ( !DoGetTypeInfo(pSym, TI_GET_TYPEID, &sym.TypeIndex) ) break; @@ -387,7 +400,7 @@ wxDbgHelpDLL::DumpField(PSYMBOL_INFO pSym, void *pVariable, unsigned level) } /* static */ wxString -wxDbgHelpDLL::DumpUDT(PSYMBOL_INFO pSym, void *pVariable, unsigned level) +wxDbgHelpDLL::DumpUDT(wxPSYMBOL_INFO pSym, void *pVariable, unsigned level) { wxString s; @@ -454,7 +467,7 @@ wxDbgHelpDLL::DumpUDT(PSYMBOL_INFO pSym, void *pVariable, unsigned level) s << wxT(" {\n"); // Iterate through all children - SYMBOL_INFO sym; + wxSYMBOL_INFO sym; wxZeroMemory(sym); sym.ModBase = pSym->ModBase; for ( unsigned i = 0; i < dwChildrenCount; i++ ) @@ -486,7 +499,7 @@ wxDbgHelpDLL::DumpUDT(PSYMBOL_INFO pSym, void *pVariable, unsigned level) /* static */ wxDbgHelpDLL::SymbolTag -wxDbgHelpDLL::DereferenceSymbol(PSYMBOL_INFO pSym, void **ppData) +wxDbgHelpDLL::DereferenceSymbol(wxPSYMBOL_INFO pSym, void **ppData) { SymbolTag tag = SYMBOL_TAG_NULL; for ( ;; ) @@ -523,10 +536,10 @@ wxDbgHelpDLL::DereferenceSymbol(PSYMBOL_INFO pSym, void **ppData) } /* static */ wxString -wxDbgHelpDLL::DumpSymbol(PSYMBOL_INFO pSym, void *pVariable) +wxDbgHelpDLL::DumpSymbol(wxPSYMBOL_INFO pSym, void *pVariable) { wxString s; - SYMBOL_INFO symDeref = *pSym; + wxSYMBOL_INFO symDeref = *pSym; switch ( DereferenceSymbol(&symDeref, &pVariable) ) { default: @@ -552,6 +565,316 @@ wxDbgHelpDLL::DumpSymbol(PSYMBOL_INFO pSym, void *pVariable) return s; } +// ---------------------------------------------------------------------------- +// do the best functions and structures +// ---------------------------------------------------------------------------- + +struct wxMswEnmLddMdlsHelperStruct +{ +public: + wxMswEnmLddMdlsHelperStruct(wxPENUMLOADED_MODULES_CALLBACK64 ptr, PVOID content) + : m_pointer_to_callback(ptr), m_user_content(content) + { } + wxPENUMLOADED_MODULES_CALLBACK64 m_pointer_to_callback; + PVOID m_user_content; +}; + +#ifdef UNICODE + +static BOOL CALLBACK wxMswEnmLddMdlsCallback1( + PCSTR ModuleName, DWORD64 ModuleBase, ULONG ModuleSize, PVOID UserContext) +{ + wxMswEnmLddMdlsHelperStruct& alternate = + *(wxMswEnmLddMdlsHelperStruct*)(UserContext); + + const wxWCharBuffer buf = wxConvLocal.cMB2WC(ModuleName, wxNO_LEN, NULL); + return (*alternate.m_pointer_to_callback) + (buf.data(), ModuleBase, ModuleSize, alternate.m_user_content); +} + +static BOOL CALLBACK wxMswEnmLddMdlsCallback2( + PCSTR ModuleName, DWORD_PTR ModuleBase, ULONG ModuleSize, PVOID UserContext) +{ + wxMswEnmLddMdlsHelperStruct& alternate = + *(wxMswEnmLddMdlsHelperStruct*)(UserContext); + + const wxWCharBuffer buf = wxConvLocal.cMB2WC(ModuleName, wxNO_LEN, NULL); + return (*alternate.m_pointer_to_callback) + (buf.data(), ModuleBase, ModuleSize, alternate.m_user_content); +} + +#else + +static BOOL CALLBACK wxMswEnmLddMdlsCallback( + PCSTR ModuleName, DWORD_PTR ModuleBase, ULONG ModuleSize, PVOID UserContext) +{ + wxMswEnmLddMdlsHelperStruct& alternate = + *(wxMswEnmLddMdlsHelperStruct*)(UserContext); + + return (*alternate.m_pointer_to_callback) + (ModuleName, ModuleBase, ModuleSize, alternate.m_user_content); +} + +#endif // UNICODE + +/* static */ +BOOL wxDbgHelpDLL::EnumerateLoadedModulesT( + HANDLE handle, wxPENUMLOADED_MODULES_CALLBACK64 callback, PVOID pvoid) +{ +#ifdef UNICODE + if (EnumerateLoadedModulesW64) + { + const BOOL retVal = (*EnumerateLoadedModulesW64)(handle, callback, pvoid); + if (retVal) + return retVal; + } + if (EnumerateLoadedModules64) + { + wxMswEnmLddMdlsHelperStruct p(callback, pvoid); + const BOOL retVal = + (*EnumerateLoadedModules64) + (handle, &wxMswEnmLddMdlsCallback1, (PVOID)(&p)); + if (retVal) + return retVal; + } + if (EnumerateLoadedModules) + { + wxMswEnmLddMdlsHelperStruct p(callback, pvoid); + const BOOL retVal = + (*EnumerateLoadedModules) + (handle, &wxMswEnmLddMdlsCallback2, (PVOID)(&p)); + if (retVal) + return retVal; + } + return FALSE; +#else + if (EnumerateLoadedModules64) + { + const BOOL retVal = (*EnumerateLoadedModules64)(handle, callback, pvoid); + if (retVal) + return retVal; + } + if (EnumerateLoadedModules) + { + wxMswEnmLddMdlsHelperStruct p(callback, pvoid); + const BOOL retVal = + (*EnumerateLoadedModules) + (handle, &wxMswEnmLddMdlsCallback, (PVOID)(&p)); + if (retVal) + return retVal; + } + return FALSE; +#endif +} + +/* static */ +BOOL wxDbgHelpDLL::SymInitializeT(HANDLE hProcess, LPCTSTR UserSearchPath, BOOL fInvadeProcess) +{ +#ifdef UNICODE + if (SymInitializeW) + { + const BOOL retVal = (*SymInitializeW)(hProcess, UserSearchPath, fInvadeProcess); + if (retVal) + return retVal; + } + if (SymInitialize) + { + BOOL retVal; + if (UserSearchPath) + { + const wxCharBuffer buf = wxConvLocal.cWC2MB(UserSearchPath, wxNO_LEN, NULL); + retVal = (*SymInitialize)(hProcess, buf.data(), fInvadeProcess); + } + else + { + retVal = (*SymInitialize)(hProcess, NULL, fInvadeProcess); + } + return retVal; + } + return FALSE; +#else + if (SymInitialize) + { + return (*SymInitialize)(hProcess, UserSearchPath, fInvadeProcess); + } + return FALSE; +#endif +} + +/* static */ +BOOL wxDbgHelpDLL::SymFromAddrT(HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, wxPSYMBOL_INFO Symbol) +{ +#ifdef UNICODE + if (SymFromAddrW) + { + const BOOL retVal = (*SymFromAddrW)(hProcess, Address, Displacement, Symbol); + if (retVal) + return retVal; + } + if (SymFromAddr) + { + BYTE* symbolBuffer = new BYTE[sizeof(SYMBOL_INFO) + Symbol->MaxNameLen*sizeof(CHAR)]; + PSYMBOL_INFO data = (SYMBOL_INFO*)(symbolBuffer); + wxZeroMemory(*data); + data->SizeOfStruct = sizeof(SYMBOL_INFO); + data->MaxNameLen = Symbol->MaxNameLen; + if (! (*SymFromAddr)(hProcess, Address, Displacement, data)) + { + delete [] symbolBuffer; + return FALSE; + } + + // We can't refer data->NameLen. It seems to be unmodified. + const wxWCharBuffer buf = wxConvLocal.cMB2WC(data->Name, wxNO_LEN, NULL); + + // FIXME: I know too brute but some header names SYMBOL_INFO::Index + // and the other one defines it as SYMBOL_INFO::info. + const ULONG dstSize = Symbol->SizeOfStruct; + CopyMemory(Symbol, data, sizeof(SYMBOL_INFO)-sizeof(CHAR)); + Symbol->SizeOfStruct = dstSize; + Symbol->NameLen = buf.length(); + wxStrncpy(Symbol->Name, buf.data(), Symbol->MaxNameLen); + delete [] symbolBuffer; + return TRUE; + } + return FALSE; +#else + if (SymFromAddr) + { + return (*SymFromAddr)(hProcess, Address, Displacement, Symbol); + } + return FALSE; +#endif +} + +/* static */ +BOOL wxDbgHelpDLL::SymGetLineFromAddrT(HANDLE hProcess, DWORD64 dwAddr, PDWORD pdrDisplacement, wxPIMAGEHLP_LINE Line) +{ +#ifdef UNICODE + if (SymGetLineFromAddrW64) + { + const BOOL retVal = (*SymGetLineFromAddrW64)(hProcess, dwAddr, pdrDisplacement, Line); + if (retVal) + return retVal; + // TODO: seems always fail with GetLastError() returns 487 with 32bit binary on 64 bit Windows. + } + static WCHAR staticBuf[MAX_PATH]; + if (SymGetLineFromAddr64) + { + IMAGEHLP_LINE64 LineAlternate; + LineAlternate.SizeOfStruct = sizeof(IMAGEHLP_LINE64); + if ((*SymGetLineFromAddr64)(hProcess, dwAddr, pdrDisplacement, &LineAlternate)) + { + const wxWCharBuffer ConvBuf = + wxConvLocal.cMB2WC(LineAlternate.FileName, wxNO_LEN, NULL); + wxStrncpy(staticBuf, ConvBuf.data(), MAX_PATH); + Line->Key = LineAlternate.Key; + Line->LineNumber = LineAlternate.LineNumber; + Line->FileName = staticBuf; + Line->Address = LineAlternate.Address; + return TRUE; + } + } + if (SymGetLineFromAddr) + { + IMAGEHLP_LINE LineAlternate; + LineAlternate.SizeOfStruct = sizeof(IMAGEHLP_LINE); + if ((*SymGetLineFromAddr)(hProcess, dwAddr, pdrDisplacement, &LineAlternate)) + { + const wxWCharBuffer ConvBuf = + wxConvLocal.cMB2WC(LineAlternate.FileName, wxNO_LEN, NULL); + wxStrncpy(staticBuf, ConvBuf.data(), MAX_PATH); + Line->Key = LineAlternate.Key; + Line->LineNumber = LineAlternate.LineNumber; + Line->FileName = staticBuf; + Line->Address = LineAlternate.Address; + return TRUE; + } + } + return FALSE; +#else + if (SymGetLineFromAddr64) + { + return (*SymGetLineFromAddr64)(hProcess, dwAddr, pdrDisplacement, Line); + } + if (SymGetLineFromAddr) + { + IMAGEHLP_LINE LineAlternate; + LineAlternate.SizeOfStruct = sizeof(IMAGEHLP_LINE); + if ((*SymGetLineFromAddr)(hProcess, dwAddr, pdrDisplacement, &LineAlternate)) + { + Line->Key = LineAlternate.Key; + Line->LineNumber = LineAlternate.LineNumber; + Line->FileName = LineAlternate.FileName; + Line->Address = LineAlternate.Address; + return TRUE; + } + } + return FALSE; +#endif +} + +struct wxMswSymEnumSymbolsHelperStruct +{ +public: + wxMswSymEnumSymbolsHelperStruct(PSYM_ENUMERATESYMBOLS_CALLBACKW ptr, PVOID content) + : m_pointer_to_callback(ptr), m_user_content(content) + { } + PSYM_ENUMERATESYMBOLS_CALLBACKW m_pointer_to_callback; + PVOID m_user_content; +}; + +#ifdef UNICODE + +static BOOL CALLBACK wxMswSymEnumSymbolsHelperCallback( + PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext) +{ + wxMswSymEnumSymbolsHelperStruct& alternate = + *(wxMswSymEnumSymbolsHelperStruct*)(UserContext); + const wxWCharBuffer buf = wxConvLocal.cMB2WC(pSymInfo->Name, pSymInfo->MaxNameLen, NULL); + BYTE* symbolBuffer = new BYTE[sizeof(SYMBOL_INFOW) + buf.length()*sizeof(WCHAR)]; + SYMBOL_INFOW* data = (SYMBOL_INFOW*)(symbolBuffer); + + // FIXME: I know too brute but some header names SYMBOL_INFO::Index + // and the other one defines it as SYMBOL_INFO::info. + CopyMemory(data, pSymInfo, sizeof(SYMBOL_INFO)-sizeof(CHAR)); + data->SizeOfStruct = sizeof(SYMBOL_INFOW); + wxStrncpy(data->Name, buf.data(), buf.length()); + BOOL retVal = (*alternate.m_pointer_to_callback)(data, SymbolSize, alternate.m_user_content); + delete [] symbolBuffer; + return retVal; +} + +#endif // UNICODE + +/* static */ +BOOL wxDbgHelpDLL::SymEnumSymbolsT(HANDLE hProcess, ULONG64 baseOfDll, PCTSTR Mask, + wxPSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, const PVOID UserContext) +{ +#ifdef UNICODE + if (SymEnumSymbolsW) + { + const BOOL retVal = (*SymEnumSymbolsW)(hProcess, baseOfDll, Mask, EnumSymbolsCallback, UserContext); + if (retVal) + return retVal; + } + if (SymEnumSymbols) + { + wxMswSymEnumSymbolsHelperStruct p(EnumSymbolsCallback, UserContext); + const wxCharBuffer buf = wxConvLocal.cWC2MB(Mask ? Mask : L"", wxNO_LEN, NULL); + return (*SymEnumSymbols)(hProcess, baseOfDll, buf.data(), + wxMswSymEnumSymbolsHelperCallback, (PVOID)(&p)); + } + return FALSE; +#else + if (SymEnumSymbols) + { + return (*SymEnumSymbols)(hProcess, baseOfDll, Mask, EnumSymbolsCallback, UserContext); + } + return FALSE; +#endif +} + // ---------------------------------------------------------------------------- // debugging helpers // ---------------------------------------------------------------------------- diff --git a/src/msw/dlmsw.cpp b/src/msw/dlmsw.cpp index 5957086cb4..00cd88b5cd 100644 --- a/src/msw/dlmsw.cpp +++ b/src/msw/dlmsw.cpp @@ -2,7 +2,7 @@ // Name: src/msw/dlmsw.cpp // Purpose: Win32-specific part of wxDynamicLibrary and related classes // Author: Vadim Zeitlin -// Modified by: +// Modified by: Suzumizaki-kimitaka 2013-04-09 // Created: 2005-01-10 (partly extracted from common/dynlib.cpp) // Copyright: (c) 1998-2005 Vadim Zeitlin // Licence: wxWindows licence @@ -28,6 +28,11 @@ #include "wx/msw/debughlp.h" #include "wx/filename.h" +// defined for TDM's GCC/mingw32 +#ifndef PCTSTR +#define PCTSTR LPCTSTR +#endif + // ---------------------------------------------------------------------------- // private classes // ---------------------------------------------------------------------------- @@ -77,15 +82,8 @@ public: wxVersionDLL *verDLL; }; - // TODO: fix EnumerateLoadedModules() to use EnumerateLoadedModules64() - #ifdef __WIN64__ - typedef DWORD64 DWORD_32_64; - #else - typedef DWORD DWORD_32_64; - #endif - static BOOL CALLBACK - EnumModulesProc(PCSTR name, DWORD_32_64 base, ULONG size, void *data); + EnumModulesProc(PCTSTR name, DWORD64 base, ULONG size, PVOID data); }; // ============================================================================ @@ -113,7 +111,7 @@ wxVersionDLL::wxVersionDLL() #endif // UNICODE/ANSI #define LOAD_VER_FUNCTION(name) \ - m_pfn ## name = (name ## _t)m_dll.GetSymbol(wxT(#name SUFFIX)); \ + m_pfn ## name = (name ## _t)m_dll.GetSymbol(wxT(#name SUFFIX)); \ if ( !m_pfn ## name ) \ { \ m_dll.Unload(); \ @@ -172,17 +170,21 @@ wxString wxVersionDLL::GetFileVersion(const wxString& filename) const /* static */ BOOL CALLBACK -wxDynamicLibraryDetailsCreator::EnumModulesProc(PCSTR name, - DWORD_32_64 base, +wxDynamicLibraryDetailsCreator::EnumModulesProc(PCTSTR name, + DWORD64 base, ULONG size, - void *data) + PVOID data) { EnumModulesProcParams *params = (EnumModulesProcParams *)data; wxDynamicLibraryDetails *details = new wxDynamicLibraryDetails; // fill in simple properties +#ifdef UNICODE details->m_name = name; +#else + details->m_name = wxString(name, wxConvLocal); +#endif details->m_address = wxUIntToPtr(base); details->m_length = size; @@ -320,20 +322,14 @@ wxDynamicLibraryDetailsArray wxDynamicLibrary::ListLoaded() params.dlls = &dlls; params.verDLL = &verDLL; - // Note that the cast of EnumModulesProc is needed because the type of - // PENUMLOADED_MODULES_CALLBACK changed: in old SDK versions its first - // argument was non-const PSTR while now it's PCSTR. By explicitly - // casting to whatever the currently used headers require we ensure - // that the code compilers in any case. - if ( !wxDbgHelpDLL::EnumerateLoadedModules + if ( !wxDbgHelpDLL::EnumerateLoadedModulesT ( ::GetCurrentProcess(), - (PENUMLOADED_MODULES_CALLBACK) wxDynamicLibraryDetailsCreator::EnumModulesProc, ¶ms ) ) { - wxLogLastError(wxT("EnumerateLoadedModules")); + wxLogLastError(wxT("EnumerateLoadedModulesT")); } } #endif // wxUSE_DBGHELP diff --git a/src/msw/stackwalk.cpp b/src/msw/stackwalk.cpp index f9c8ca986e..6fc987623d 100644 --- a/src/msw/stackwalk.cpp +++ b/src/msw/stackwalk.cpp @@ -2,7 +2,8 @@ // Name: src/msw/stackwalk.cpp // Purpose: wxStackWalker implementation for Win32 // Author: Vadim Zeitlin -// Modified by: Artur Bac 2010-10-01 AMD64 Port +// Modified by: Artur Bac 2010-10-01 AMD64 Port, +// Suzumizaki-kimitaka 2013-04-09 // Created: 2005-01-08 // Copyright: (c) 2003-2005 Vadim Zeitlin // Licence: wxWindows licence @@ -51,15 +52,15 @@ void wxStackFrame::OnGetName() // get the name of the function for this stack frame entry static const size_t MAX_NAME_LEN = 1024; - BYTE symbolBuffer[sizeof(SYMBOL_INFO) + MAX_NAME_LEN]; + BYTE symbolBuffer[sizeof(wxSYMBOL_INFO) + MAX_NAME_LEN*sizeof(TCHAR)]; wxZeroMemory(symbolBuffer); - PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuffer; - pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); + wxPSYMBOL_INFO pSymbol = (wxPSYMBOL_INFO)symbolBuffer; + pSymbol->SizeOfStruct = sizeof(wxSYMBOL_INFO); pSymbol->MaxNameLen = MAX_NAME_LEN; DWORD64 symDisplacement = 0; - if ( !wxDbgHelpDLL::SymFromAddr + if ( !wxDbgHelpDLL::SymFromAddrT ( ::GetCurrentProcess(), GetSymAddr(), @@ -67,11 +68,14 @@ void wxStackFrame::OnGetName() pSymbol ) ) { - wxDbgHelpDLL::LogError(wxT("SymFromAddr")); + wxDbgHelpDLL::LogError(wxT("SymFromAddrT")); return; } - - m_name = wxString::FromAscii(pSymbol->Name); +#ifdef UNICODE + m_name = pSymbol->Name; +#else + m_name = wxString(pSymbol->Name, wxConvLocal); +#endif m_offset = symDisplacement; } @@ -83,9 +87,9 @@ void wxStackFrame::OnGetLocation() m_hasLocation = true; // get the source line for this stack frame entry - IMAGEHLP_LINE lineInfo = { sizeof(IMAGEHLP_LINE) }; + wxIMAGEHLP_LINE lineInfo = { sizeof(wxIMAGEHLP_LINE) }; DWORD dwLineDisplacement; - if ( !wxDbgHelpDLL::SymGetLineFromAddr + if ( !wxDbgHelpDLL::SymGetLineFromAddrT ( ::GetCurrentProcess(), GetSymAddr(), @@ -95,11 +99,14 @@ void wxStackFrame::OnGetLocation() { // it is normal that we don't have source info for some symbols, // notably all the ones from the system DLLs... - //wxDbgHelpDLL::LogError(wxT("SymGetLineFromAddr")); + //wxDbgHelpDLL::LogError(wxT("SymGetLineFromAddr64")); return; } - - m_filename = wxString::FromAscii(lineInfo.FileName); +#ifdef UNICODE + m_filename = lineInfo.FileName; +#else + m_filename = wxString(lineInfo.FileName, wxConvLocal); +#endif m_line = lineInfo.LineNumber; } @@ -125,11 +132,15 @@ wxStackFrame::GetParam(size_t n, return true; } -void wxStackFrame::OnParam(PSYMBOL_INFO pSymInfo) +void wxStackFrame::OnParam(wxPSYMBOL_INFO pSymInfo) { m_paramTypes.Add(wxEmptyString); - m_paramNames.Add(wxString::FromAscii(pSymInfo->Name)); +#ifdef UNICODE + m_paramNames.Add(pSymInfo->Name); +#else + m_paramNames.Add(wxString(pSymInfo->Name, wxConvLocal)); +#endif // if symbol information is corrupted and we crash, the exception is going // to be ignored when we're called from WalkFromException() because of the @@ -158,7 +169,7 @@ void wxStackFrame::OnParam(PSYMBOL_INFO pSymInfo) } BOOL CALLBACK -EnumSymbolsProc(PSYMBOL_INFO pSymInfo, ULONG WXUNUSED(SymSize), PVOID data) +EnumSymbolsProc(wxPSYMBOL_INFO pSymInfo, ULONG WXUNUSED(SymSize), PVOID data) { wxStackFrame *frame = static_cast(data); @@ -195,7 +206,7 @@ void wxStackFrame::OnGetParam() return; } - if ( !wxDbgHelpDLL::SymEnumSymbols + if ( !wxDbgHelpDLL::SymEnumSymbolsT ( ::GetCurrentProcess(), NULL, // DLL base: use current context @@ -204,7 +215,7 @@ void wxStackFrame::OnGetParam() this // data to pass to it ) ) { - wxDbgHelpDLL::LogError(wxT("SymEnumSymbols")); + wxDbgHelpDLL::LogError(wxT("SymEnumSymbolsT")); } } @@ -232,14 +243,14 @@ void wxStackWalker::WalkFrom(const CONTEXT *pCtx, size_t skip, size_t maxDepth) // below which should be a real handle... so this is what we use const HANDLE hProcess = ::GetCurrentProcess(); - if ( !wxDbgHelpDLL::SymInitialize + if ( !wxDbgHelpDLL::SymInitializeT ( hProcess, NULL, // use default symbol search path TRUE // load symbols for all loaded modules ) ) { - wxDbgHelpDLL::LogError(wxT("SymInitialize")); + wxDbgHelpDLL::LogError(wxT("SymInitializeT")); return; } @@ -382,7 +393,7 @@ wxStackFrame::GetParam(size_t WXUNUSED(n), return false; } -void wxStackFrame::OnParam(_SYMBOL_INFO * WXUNUSED(pSymInfo)) +void wxStackFrame::OnParam(wxPSYMBOL_INFO WXUNUSED(pSymInfo)) { } -- 2.45.2