From 8979566dd263d9f90ad71ffb1257bfe81578ba61 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 13 Mar 2016 02:03:48 +0100 Subject: [PATCH 1/8] Make wx/stackwalk.h self-sufficient Don't rely on wx/string.h being already included, but include it explicitly ourselves to fix compilation error when wx/stackwalk.h is the first wx header to be included. --- include/wx/stackwalk.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/wx/stackwalk.h b/include/wx/stackwalk.h index 1133d6ef7c..c0ba151d75 100644 --- a/include/wx/stackwalk.h +++ b/include/wx/stackwalk.h @@ -15,6 +15,8 @@ #if wxUSE_STACKWALKER +#include "wx/string.h" + class WXDLLIMPEXP_FWD_BASE wxStackFrame; #define wxSTACKWALKER_MAX_DEPTH (200) From 15c1b97786239b9eaee61e6fa62f5dc0b84325f9 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 15 Mar 2016 20:10:12 +0100 Subject: [PATCH 2/8] Explicitly include wx/dynlib.h from src/msw/dlmsw.cpp Don't rely on wx/dynlib.h being included implicitly via wx/msw/debughlp.h. --- src/msw/dlmsw.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/msw/dlmsw.cpp b/src/msw/dlmsw.cpp index dedc04ce2a..ff0bb127aa 100644 --- a/src/msw/dlmsw.cpp +++ b/src/msw/dlmsw.cpp @@ -24,6 +24,8 @@ #if wxUSE_DYNLIB_CLASS +#include "wx/dynlib.h" + #include "wx/msw/private.h" #include "wx/msw/debughlp.h" #include "wx/filename.h" From f62d6bf6fd456056028921699e5589f8bec04698 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 13 Mar 2016 16:03:28 +0100 Subject: [PATCH 3/8] Don't check MSW-specific configure options unless targeting MSW This doesn't really change much as these options are not used anyhow, but seems tidier. --- configure | 2 ++ configure.in | 2 ++ 2 files changed, 4 insertions(+) diff --git a/configure b/configure index dbe140008e..3be0ac29e5 100755 --- a/configure +++ b/configure @@ -7745,6 +7745,7 @@ fi eval "$wx_cv_use_threads" +if test "$wxUSE_MSW" = 1 ; then enablestring= defaultval= @@ -7803,6 +7804,7 @@ fi eval "$wx_cv_use_regkey" +fi if test "$wxUSE_GUI" = "yes"; then diff --git a/configure.in b/configure.in index 41d34cdcc2..d9021f9e5d 100644 --- a/configure.in +++ b/configure.in @@ -743,8 +743,10 @@ WX_ARG_FEATURE(protocol_file, [ --enable-protocol-file FILE support in wxProto WX_ARG_FEATURE(threads, [ --enable-threads use threads], wxUSE_THREADS) +if test "$wxUSE_MSW" = 1 ; then WX_ARG_ENABLE(iniconf, [ --enable-iniconf use wxIniConfig (Win32 only)], wxUSE_INICONF) WX_ARG_FEATURE(regkey, [ --enable-regkey use wxRegKey class (Win32 only)], wxUSE_REGKEY) +fi if test "$wxUSE_GUI" = "yes"; then From 841af5608407ab76ba20049b3c541c797766507c Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 14 Mar 2016 00:55:33 +0100 Subject: [PATCH 4/8] Allow using debug help API with non-MSVC compilers MinGW64 and TDM-GCC come with imagehlp.h and can compile the code using debug help API too, so enable wxUSE_DBGHELP when using these compilers by default and also allow enabling it via a configure option. --- configure | 88 ++++++++++++++++++++++++++++++++++++++ configure.in | 29 +++++++++++++ include/wx/gtk/setup0.h | 12 ++++++ include/wx/msw/debughlp.h | 25 ++--------- include/wx/msw/setup0.h | 14 +++++- include/wx/msw/setup_inc.h | 12 ++++++ setup.h.in | 6 +++ 7 files changed, 164 insertions(+), 22 deletions(-) diff --git a/configure b/configure index 3be0ac29e5..0b45fb4c8f 100755 --- a/configure +++ b/configure @@ -1195,6 +1195,7 @@ enable_protocol_http enable_protocol_ftp enable_protocol_file enable_threads +enable_dbghelp enable_iniconf enable_regkey enable_docview @@ -2127,6 +2128,7 @@ Optional Features: --enable-protocol-ftp FTP support in wxProtocol --enable-protocol-file FILE support in wxProtocol --enable-threads use threads + --enable-dbghelp use dbghelp.dll API (Win32 only) --enable-iniconf use wxIniConfig (Win32 only) --enable-regkey use wxRegKey class (Win32 only) --enable-docview use document view architecture @@ -7747,6 +7749,35 @@ fi if test "$wxUSE_MSW" = 1 ; then + enablestring=disable + defaultval= + if test -z "$defaultval"; then + if test x"$enablestring" = xdisable; then + defaultval=yes + else + defaultval=no + fi + fi + + # Check whether --enable-dbghelp was given. +if test "${enable_dbghelp+set}" = set; then : + enableval=$enable_dbghelp; + if test "$enableval" = yes; then + wx_cv_use_dbghelp='wxUSE_DBGHELP=yes' + else + wx_cv_use_dbghelp='wxUSE_DBGHELP=no' + fi + +else + + wx_cv_use_dbghelp='wxUSE_DBGHELP=${'DEFAULT_wxUSE_DBGHELP":-$defaultval}" + +fi + + + eval "$wx_cv_use_dbghelp" + + enablestring= defaultval= if test -z "$defaultval"; then @@ -35884,6 +35915,63 @@ if test "$wxUSE_AUTOID_MANAGEMENT" = "yes"; then fi if test "$USE_WIN32" = 1 ; then + if test "$wxUSE_DBGHELP" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if debug help API is available" >&5 +$as_echo_n "checking if debug help API is available... " >&6; } +if ${wx_cv_lib_debughlp+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include +int +main () +{ + + #ifndef API_VERSION_NUMBER + #error API_VERSION_NUMBER not defined! + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + wx_cv_lib_debughlp=yes +else + wx_cv_lib_debughlp=no + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $wx_cv_lib_debughlp" >&5 +$as_echo "$wx_cv_lib_debughlp" >&6; } + + if test "$wx_cv_lib_debughlp" = yes; then + $as_echo "#define wxUSE_DBGHELP 1" >>confdefs.h + + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Debug help API and wxStackWalker won't be available" >&5 +$as_echo "$as_me: WARNING: Debug help API and wxStackWalker won't be available" >&2;} + fi + fi + if test "$wxUSE_INICONF" = "yes"; then $as_echo "#define wxUSE_INICONF 1" >>confdefs.h diff --git a/configure.in b/configure.in index d9021f9e5d..3b30d65837 100644 --- a/configure.in +++ b/configure.in @@ -744,6 +744,7 @@ WX_ARG_FEATURE(protocol_file, [ --enable-protocol-file FILE support in wxProto WX_ARG_FEATURE(threads, [ --enable-threads use threads], wxUSE_THREADS) if test "$wxUSE_MSW" = 1 ; then +WX_ARG_DISABLE(dbghelp, [ --enable-dbghelp use dbghelp.dll API (Win32 only)], wxUSE_DBGHELP) WX_ARG_ENABLE(iniconf, [ --enable-iniconf use wxIniConfig (Win32 only)], wxUSE_INICONF) WX_ARG_FEATURE(regkey, [ --enable-regkey use wxRegKey class (Win32 only)], wxUSE_REGKEY) fi @@ -7159,6 +7160,34 @@ if test "$wxUSE_AUTOID_MANAGEMENT" = "yes"; then fi if test "$USE_WIN32" = 1 ; then + if test "$wxUSE_DBGHELP" = "yes"; then + AC_CACHE_CHECK([if debug help API is available], wx_cv_lib_debughlp, + [ + dnl we need just the header, not the library, as we load the + dnl DLL dynamically anyhow during run-time + AC_LANG_PUSH(C++) + AC_TRY_COMPILE( + [#include + #include ], + [ + #ifndef API_VERSION_NUMBER + #error API_VERSION_NUMBER not defined! + #endif + ], + wx_cv_lib_debughlp=yes, + wx_cv_lib_debughlp=no + ) + AC_LANG_POP() + ] + ) + + if test "$wx_cv_lib_debughlp" = yes; then + AC_DEFINE(wxUSE_DBGHELP) + else + AC_MSG_WARN([Debug help API and wxStackWalker won't be available]) + fi + fi + if test "$wxUSE_INICONF" = "yes"; then AC_DEFINE(wxUSE_INICONF) fi diff --git a/include/wx/gtk/setup0.h b/include/wx/gtk/setup0.h index 0ab4718bdf..277c2e4fd8 100644 --- a/include/wx/gtk/setup0.h +++ b/include/wx/gtk/setup0.h @@ -1668,6 +1668,18 @@ // Crash debugging helpers // ---------------------------------------------------------------------------- +// Set this to 1 to use dbghelp.dll for providing stack traces in crash +// reports. +// +// Default is 1 if the compiler supports it, 0 for old MinGW. +// +// Recommended setting: 1, there is not much gain in disabling this +#if defined(__VISUALC__) || defined(__MINGW64_TOOLCHAIN__) + #define wxUSE_DBGHELP 1 +#else + #define wxUSE_DBGHELP 0 +#endif + // Set this to 1 to be able to use wxCrashReport::Generate() to create mini // dumps of your program when it crashes (or at any other moment) // diff --git a/include/wx/msw/debughlp.h b/include/wx/msw/debughlp.h index b224c19a23..44d6d1ece2 100644 --- a/include/wx/msw/debughlp.h +++ b/include/wx/msw/debughlp.h @@ -10,8 +10,11 @@ #ifndef _WX_MSW_DEBUGHLPH_H_ #define _WX_MSW_DEBUGHLPH_H_ -#include "wx/dynlib.h" +#include "wx/defs.h" +#if wxUSE_DBGHELP + +#include "wx/dynlib.h" #include "wx/msw/wrapwin.h" #ifdef __VISUALC__ @@ -31,26 +34,6 @@ #include "wx/msw/private.h" -// wxUSE_DBGHELP can be predefined on the compiler command line to force using -// dbghelp.dll even if it's not detected or, on the contrary, avoid using even -// if it's available. -#ifndef wxUSE_DBGHELP - // The only compiler which is known to have the necessary headers is MSVC. - #ifdef __VISUALC__ - // MSVC7.1 shipped with API v9 and we don't support anything earlier - // anyhow. - #if API_VERSION_NUMBER >= 9 - #define wxUSE_DBGHELP 1 - #else - #define wxUSE_DBGHELP 0 - #endif - #else - #define wxUSE_DBGHELP 0 - #endif -#endif - -#if wxUSE_DBGHELP - /* The table below shows which functions are exported by dbghelp.dll. diff --git a/include/wx/msw/setup0.h b/include/wx/msw/setup0.h index 8ade54c2e9..abee9b51d4 100644 --- a/include/wx/msw/setup0.h +++ b/include/wx/msw/setup0.h @@ -1560,7 +1560,7 @@ // SDK components manually, you need to change this setting. // // Recommended setting: 1 -#if defined(_MSC_VER) && _MSC_VER >= 1700 && !defined(_USING_V110_SDK71_) +#if defined(_MSC_VER) && _MSC_VER >= 1700 #define wxUSE_WINRT 1 #else #define wxUSE_WINRT 0 @@ -1668,6 +1668,18 @@ // Crash debugging helpers // ---------------------------------------------------------------------------- +// Set this to 1 to use dbghelp.dll for providing stack traces in crash +// reports. +// +// Default is 1 if the compiler supports it, 0 for old MinGW. +// +// Recommended setting: 1, there is not much gain in disabling this +#if defined(__VISUALC__) || defined(__MINGW64_TOOLCHAIN__) + #define wxUSE_DBGHELP 1 +#else + #define wxUSE_DBGHELP 0 +#endif + // Set this to 1 to be able to use wxCrashReport::Generate() to create mini // dumps of your program when it crashes (or at any other moment) // diff --git a/include/wx/msw/setup_inc.h b/include/wx/msw/setup_inc.h index 639fbe6523..ff5fc00102 100644 --- a/include/wx/msw/setup_inc.h +++ b/include/wx/msw/setup_inc.h @@ -180,6 +180,18 @@ // Crash debugging helpers // ---------------------------------------------------------------------------- +// Set this to 1 to use dbghelp.dll for providing stack traces in crash +// reports. +// +// Default is 1 if the compiler supports it, 0 for old MinGW. +// +// Recommended setting: 1, there is not much gain in disabling this +#if defined(__VISUALC__) || defined(__MINGW64_TOOLCHAIN__) + #define wxUSE_DBGHELP 1 +#else + #define wxUSE_DBGHELP 0 +#endif + // Set this to 1 to be able to use wxCrashReport::Generate() to create mini // dumps of your program when it crashes (or at any other moment) // diff --git a/setup.h.in b/setup.h.in index 6929ae0a48..bca48a99f8 100644 --- a/setup.h.in +++ b/setup.h.in @@ -691,6 +691,12 @@ #define wxUSE_TIMEPICKCTRL_GENERIC 0 +#if defined(__VISUALC__) || defined(__MINGW64_TOOLCHAIN__) + #define wxUSE_DBGHELP 0 +#else + #define wxUSE_DBGHELP 0 +#endif + #define wxUSE_CRASHREPORT 0 /* --- end MSW options --- */ From 423b631dff41d45f3eca980744aed0cd8abe1a69 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 14 Mar 2016 01:03:21 +0100 Subject: [PATCH 5/8] Use 0 instead of NULL for a non-pointer SymEnumSymbols() argument The base DLL address passed to this function is not a pointer, so don't use NULL here to avoid warnings from gcc. --- src/msw/stackwalk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/msw/stackwalk.cpp b/src/msw/stackwalk.cpp index 4b59c4a381..c6c9f13bf5 100644 --- a/src/msw/stackwalk.cpp +++ b/src/msw/stackwalk.cpp @@ -170,7 +170,7 @@ void wxStackFrame::OnGetParam() if ( !wxDbgHelpDLL::CallSymEnumSymbols ( ::GetCurrentProcess(), - NULL, // DLL base: use current context + 0, // DLL base: use current context EnumSymbolsProc, // callback this // data to pass to it ) ) From 07dcfc52bf03c58c1c89d6ea597e2e4b3c2abf42 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 14 Mar 2016 01:05:35 +0100 Subject: [PATCH 6/8] Use depth argument in wxMSW wxStackWalker::Walk() There doesn't seem to be any reason to not pass it to WalkFrom(), it was probably just an oversight. --- src/msw/stackwalk.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/msw/stackwalk.cpp b/src/msw/stackwalk.cpp index c6c9f13bf5..04b6cde175 100644 --- a/src/msw/stackwalk.cpp +++ b/src/msw/stackwalk.cpp @@ -304,7 +304,7 @@ void wxStackWalker::WalkFromException(size_t maxDepth) #endif // wxUSE_ON_FATAL_EXCEPTION -void wxStackWalker::Walk(size_t skip, size_t WXUNUSED(maxDepth)) +void wxStackWalker::Walk(size_t skip, size_t maxDepth) { // to get a CONTEXT for the current location, simply force an exception and // get EXCEPTION_POINTERS from it @@ -318,7 +318,7 @@ void wxStackWalker::Walk(size_t skip, size_t WXUNUSED(maxDepth)) RaiseException(0x1976, 0, 0, NULL); } __except( WalkFrom((EXCEPTION_POINTERS *)GetExceptionInformation(), - skip + 2), EXCEPTION_CONTINUE_EXECUTION ) + skip + 2, maxDepth + 2), EXCEPTION_CONTINUE_EXECUTION ) { // never executed because the above expression always evaluates to // EXCEPTION_CONTINUE_EXECUTION From ccac9d05570447204e895da0b1bdc2270ec581c9 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 14 Mar 2016 01:08:40 +0100 Subject: [PATCH 7/8] Enable wxStackWalker in MinGW64 builds This class can be used even without SEH, provided debug help API is available, so just make wxUSE_STACKWALKER dependent on wxUSE_DBGHELP instead of unconditionally disabling it if SEH support is not available. --- docs/changes.txt | 1 + include/wx/msw/chkconf.h | 35 +++++++++++-- interface/wx/stackwalk.h | 11 +++-- src/msw/stackwalk.cpp | 104 ++++++++++++++------------------------- 4 files changed, 78 insertions(+), 73 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index a7fb5917f5..67c5b5caac 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -74,6 +74,7 @@ wxGTK: wxMSW: +- Enable wxStackWalker in MinGW64 builds. - Fix crash when using wxCHMHelpController() in 64 bit builds (Xlord2). - Fix MDI menu display after failure to create a child frame (troelsk). diff --git a/include/wx/msw/chkconf.h b/include/wx/msw/chkconf.h index 656ef98017..8571cc4607 100644 --- a/include/wx/msw/chkconf.h +++ b/include/wx/msw/chkconf.h @@ -38,6 +38,14 @@ # endif #endif /* !defined(wxUSE_CRASHREPORT) */ +#ifndef wxUSE_DBGHELP +# ifdef wxABORT_ON_CONFIG_ERROR +# error "wxUSE_DBGHELP must be defined" +# else +# define wxUSE_DBGHELP 1 +# endif +#endif /* wxUSE_DBGHELP */ + #ifndef wxUSE_DC_CACHEING # ifdef wxABORT_ON_CONFIG_ERROR # error "wxUSE_DC_CACHEING must be defined" @@ -146,9 +154,6 @@ # undef wxUSE_CRASHREPORT # define wxUSE_CRASHREPORT 0 - -# undef wxUSE_STACKWALKER -# define wxUSE_STACKWALKER 0 #endif /* compiler doesn't support SEH */ #if defined(__GNUWIN32__) @@ -292,6 +297,14 @@ #endif /* !wxUSE_DYNAMIC_LOADER */ #if !wxUSE_DYNLIB_CLASS +# if wxUSE_DBGHELP +# ifdef wxABORT_ON_CONFIG_ERROR +# error "wxUSE_DBGHELP requires wxUSE_DYNLIB_CLASS" +# else +# undef wxUSE_DBGHELP +# define wxUSE_DBGHELP 0 +# endif +# endif # if wxUSE_DC_TRANSFORM_MATRIX # ifdef wxABORT_ON_CONFIG_ERROR # error "wxUSE_DC_TRANSFORM_MATRIX requires wxUSE_DYNLIB_CLASS" @@ -383,6 +396,22 @@ # endif #endif /* wxUSE_ACTIVITYINDICATOR */ +#if wxUSE_STACKWALKER && !wxUSE_DBGHELP + /* + Don't give an error in this case because wxUSE_DBGHELP could be 0 + because the compiler just doesn't support it, there is really no other + choice than to disable wxUSE_STACKWALKER too in this case. + + Unfortunately we can't distinguish between the missing compiler support + and explicitly disabling wxUSE_DBGHELP (which would ideally result in + an error if wxUSE_STACKWALKER is not disabled too), but it's better to + avoid giving a compiler error in the former case even if it means not + giving it neither in the latter one. + */ + #undef wxUSE_STACKWALKER + #define wxUSE_STACKWALKER 0 +#endif /* wxUSE_STACKWALKER && !wxUSE_DBGHELP */ + #if !wxUSE_THREADS # if wxUSE_FSWATCHER # ifdef wxABORT_ON_CONFIG_ERROR diff --git a/interface/wx/stackwalk.h b/interface/wx/stackwalk.h index c27e9158da..808796583f 100644 --- a/interface/wx/stackwalk.h +++ b/interface/wx/stackwalk.h @@ -25,13 +25,18 @@ class from it and override this method. This class will not return anything except raw stack frame addresses if the - debug information is not available. Under Win32 this means that the PDB file - matching the program being executed should be present. + debug information is not available. Under Microsoft Windows this means that + the PDB file matching the program being executed should be present. Note that if you use Microsoft Visual C++ compiler, you can create PDB files even for the programs built in release mode and it doesn't affect the program size (at least if you don't forget to add @c /opt:ref option which is suppressed by using @c /debug linker option by default but should be always enabled for - release builds). + release builds). If your compiler doesn't provide a direct way of + generating PDB files but does produce debug information in the older "Code + View" format or compatible, which is the case for MinGW, you can use @c + cv2pdb tool available at https://github.com/rainers/cv2pdb to create PDB + for your binaries which will work well when using this class. + Under Unix, you need to compile your program with debugging information (usually using @c -g compiler and linker options) to get the file and line numbers information, however function names should be available even without it. diff --git a/src/msw/stackwalk.cpp b/src/msw/stackwalk.cpp index 04b6cde175..c96a12bdb6 100644 --- a/src/msw/stackwalk.cpp +++ b/src/msw/stackwalk.cpp @@ -31,8 +31,7 @@ #include "wx/stackwalk.h" #include "wx/msw/debughlp.h" - -#if wxUSE_DBGHELP +#include "wx/msw/seh.h" // ============================================================================ // implementation @@ -103,6 +102,8 @@ void wxStackFrame::OnParam(wxSYMBOL_INFO *pSymInfo) m_paramTypes.Add(wxEmptyString); m_paramNames.Add(pSymInfo->Name); + wxString value; + // if symbol information is corrupted and we crash, the exception is going // to be ignored when we're called from WalkFromException() because of the // exception handler there returning EXCEPTION_CONTINUE_EXECUTION, but we'd @@ -111,22 +112,23 @@ void wxStackFrame::OnParam(wxSYMBOL_INFO *pSymInfo) #ifdef _CPPUNWIND try #else - __try + wxSEH_TRY #endif { // as it is a parameter (and not a global var), it is always offset by // the frame address DWORD_PTR pValue = m_addrFrame + pSymInfo->Address; - m_paramValues.Add(wxDbgHelpDLL::DumpSymbol(pSymInfo, (void *)pValue)); + value = wxDbgHelpDLL::DumpSymbol(pSymInfo, (void *)pValue); } #ifdef _CPPUNWIND catch ( ... ) -#else - __except ( EXCEPTION_EXECUTE_HANDLER ) -#endif { - m_paramValues.Add(wxEmptyString); } +#else + wxSEH_IGNORE +#endif + + m_paramValues.Add(value); } BOOL CALLBACK @@ -306,6 +308,8 @@ void wxStackWalker::WalkFromException(size_t maxDepth) void wxStackWalker::Walk(size_t skip, size_t maxDepth) { + // We use it as a proxy for SEH support here. +#if wxUSE_ON_FATAL_EXCEPTION // to get a CONTEXT for the current location, simply force an exception and // get EXCEPTION_POINTERS from it // @@ -323,72 +327,38 @@ void wxStackWalker::Walk(size_t skip, size_t maxDepth) // never executed because the above expression always evaluates to // EXCEPTION_CONTINUE_EXECUTION } -} +#else // !wxUSE_ON_FATAL_EXCEPTION + // This code is based on frames.cpp from Edd Dawson's dbg library + // (https://bitbucket.org/edd/dbg/) which is distributed under Boost + // Software License. -#else // !wxUSE_DBGHELP + CONTEXT ctx; +#ifdef __WIN64__ + RtlCaptureContext(&ctx); +#else // Win32 + // RtlCaptureContext() is not implemented correctly for x86 and can even + // crash when frame pointer is omitted, don't use it. + wxZeroMemory(ctx); + ctx.ContextFlags = CONTEXT_CONTROL; -// ============================================================================ -// stubs -// ============================================================================ + #ifdef __GNUC__ + DWORD regEip, regEsp, regEbp; -// ---------------------------------------------------------------------------- -// wxStackFrame -// ---------------------------------------------------------------------------- + asm volatile ("call 1f\n\t" "1: pop %0" : "=g"(regEip)); + asm volatile ("movl %%esp, %0" : "=g"(regEsp)); + asm volatile ("movl %%ebp, %0" : "=g"(regEbp)); -void wxStackFrame::OnGetName() -{ -} + ctx.Eip = regEip; + ctx.Esp = regEsp; + ctx.Ebp = regEbp; + #else + #error Missing implementation of RtlCaptureContext() + #endif +#endif // Win64/32 -void wxStackFrame::OnGetLocation() -{ -} - -bool -wxStackFrame::GetParam(size_t WXUNUSED(n), - wxString * WXUNUSED(type), - wxString * WXUNUSED(name), - wxString * WXUNUSED(value)) const -{ - return false; -} - -void wxStackFrame::OnParam(wxSYMBOL_INFO * WXUNUSED(pSymInfo)) -{ -} - -void wxStackFrame::OnGetParam() -{ -} - -// ---------------------------------------------------------------------------- -// wxStackWalker -// ---------------------------------------------------------------------------- - -void -wxStackWalker::WalkFrom(const CONTEXT * WXUNUSED(pCtx), - size_t WXUNUSED(skip), - size_t WXUNUSED(maxDepth)) -{ -} - -void -wxStackWalker::WalkFrom(const _EXCEPTION_POINTERS * WXUNUSED(ep), - size_t WXUNUSED(skip), - size_t WXUNUSED(maxDepth)) -{ -} - -#if wxUSE_ON_FATAL_EXCEPTION -void wxStackWalker::WalkFromException(size_t WXUNUSED(maxDepth)) -{ -} + WalkFrom(&ctx, skip, maxDepth); #endif // wxUSE_ON_FATAL_EXCEPTION - -void wxStackWalker::Walk(size_t WXUNUSED(skip), size_t WXUNUSED(maxDepth)) -{ } -#endif // wxUSE_DBGHELP/!wxUSE_DBGHELP - #endif // wxUSE_STACKWALKER From e405bf160746f0fbf20fa29bbca5b3d0d99f9d0e Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 14 Mar 2016 02:26:44 +0100 Subject: [PATCH 8/8] Initialize CONTEXT ourselves in wxMSW wxStackWalker::Walk() As we do it for MinGW now, do it also for MSVC in a similar way: this is more straightforward and less annoying than raising an exception (which can be caught by a debugger and, at least, is logged by it) and ensures we use similar code for MinGW and MSVC which should hopefully minimizing the risk of breaking one or the other without noticing in the future. Normally there should be no changes in behaviour. --- src/msw/stackwalk.cpp | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/src/msw/stackwalk.cpp b/src/msw/stackwalk.cpp index c96a12bdb6..4c86de102c 100644 --- a/src/msw/stackwalk.cpp +++ b/src/msw/stackwalk.cpp @@ -308,26 +308,6 @@ void wxStackWalker::WalkFromException(size_t maxDepth) void wxStackWalker::Walk(size_t skip, size_t maxDepth) { - // We use it as a proxy for SEH support here. -#if wxUSE_ON_FATAL_EXCEPTION - // to get a CONTEXT for the current location, simply force an exception and - // get EXCEPTION_POINTERS from it - // - // note: - // 1. we additionally skip RaiseException() and WalkFrom() frames - // 2. explicit cast to EXCEPTION_POINTERS is needed with VC7.1 even if it - // shouldn't have been according to the docs - __try - { - RaiseException(0x1976, 0, 0, NULL); - } - __except( WalkFrom((EXCEPTION_POINTERS *)GetExceptionInformation(), - skip + 2, maxDepth + 2), EXCEPTION_CONTINUE_EXECUTION ) - { - // never executed because the above expression always evaluates to - // EXCEPTION_CONTINUE_EXECUTION - } -#else // !wxUSE_ON_FATAL_EXCEPTION // This code is based on frames.cpp from Edd Dawson's dbg library // (https://bitbucket.org/edd/dbg/) which is distributed under Boost // Software License. @@ -351,13 +331,21 @@ void wxStackWalker::Walk(size_t skip, size_t maxDepth) ctx.Eip = regEip; ctx.Esp = regEsp; ctx.Ebp = regEbp; + #elif __VISUALC__ + __asm + { + Here: + mov [ctx.Ebp], ebp + mov [ctx.Esp], esp + mov eax, [Here] + mov [ctx.Eip], eax + } #else #error Missing implementation of RtlCaptureContext() #endif #endif // Win64/32 WalkFrom(&ctx, skip, maxDepth); -#endif // wxUSE_ON_FATAL_EXCEPTION } #endif // wxUSE_STACKWALKER