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.
This commit is contained in:
Vadim Zeitlin
2016-03-14 01:08:40 +01:00
parent 07dcfc52bf
commit ccac9d0557
4 changed files with 78 additions and 73 deletions

View File

@@ -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).

View File

@@ -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

View File

@@ -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.

View File

@@ -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