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:
@@ -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).
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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.
|
||||
|
@@ -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
|
||||
|
||||
|
Reference in New Issue
Block a user