diff options
| author | Carl Hetherington <cth@carlh.net> | 2014-12-15 10:58:01 +0000 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2014-12-15 10:58:01 +0000 |
| commit | 815e4cf7441d83ffca6d4d797a1a313f7c6464ab (patch) | |
| tree | a469fb8153fc83cc8e0b35ced4e32328d9fca8e9 /src/lib/util.cc | |
| parent | 1e33ccb216e73d3ea94ed08aaa4766c856178757 (diff) | |
Hand-apply 155b4b9f615f42b5cc26e2953860aba34b17bbc0; allow build of Windows debug version using gdb.
Diffstat (limited to 'src/lib/util.cc')
| -rw-r--r-- | src/lib/util.cc | 78 |
1 files changed, 69 insertions, 9 deletions
diff --git a/src/lib/util.cc b/src/lib/util.cc index e03b47568..502393094 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -37,9 +37,6 @@ #include "md5_digester.h" #include "audio_processor.h" #include "safe_stringstream.h" -#ifdef DCPOMATIC_WINDOWS -#include "stack.hpp" -#endif #include <dcp/version.h> #include <dcp/util.h> #include <dcp/signer.h> @@ -69,6 +66,7 @@ extern "C" { #include <boost/filesystem.hpp> #ifdef DCPOMATIC_WINDOWS #include <boost/locale.hpp> +#include <dbghelp.h> #endif #include <signal.h> #include <iomanip> @@ -103,6 +101,10 @@ using boost::optional; using dcp::Size; using dcp::raw_convert; +/** Path to our executable, required by the stacktrace stuff and filled + * in during App::onInit(). + */ +string program_name; static boost::thread::id ui_thread; static boost::filesystem::path backtrace_file; @@ -263,15 +265,69 @@ seconds (struct timeval t) } #ifdef DCPOMATIC_WINDOWS + +/** Resolve symbol name and source location given the path to the executable */ +int +addr2line (void const * const adr) +{ + char addr2line_cmd[512] = { 0 }; + sprintf (addr2line_cmd, "addr2line -f -p -e %.256s %p > %s", program_name.c_str(), addr, backtrace_file.string().c_str()); + return system(addr2line_cmd); +} + +/** This is called when C signals occur on Windows (e.g. SIGSEGV) + * (NOT C++ exceptions!). We write a backtrace to backtrace_file by dark means. + * Adapted from code here: http://spin.atomicobject.com/2013/01/13/exceptions-stack-traces-c/ + */ LONG WINAPI exception_handler(struct _EXCEPTION_POINTERS *) { - dbg::stack s; FILE* f = fopen_boost (backtrace_file, "w"); - fprintf (f, "Exception thrown:"); - for (dbg::stack::const_iterator i = s.begin(); i != s.end(); ++i) { - fprintf (f, "%p %s %d %s\n", i->instruction, i->function.c_str(), i->line, i->module.c_str()); + fprintf (f, "C-style exception %d\n", info->ExceptionRecord->ExceptionCode); + fclose(f); + + if (info->ExceptionRecord->ExceptionCode != EXCEPTION_STACK_OVERFLOW) { + CONTEXT* context = info->ContextRecord; + SymInitialize (GetCurrentProcess (), 0, true); + + STACKFRAME frame = { 0 }; + + /* setup initial stack frame */ +#if _WIN64 + frame.AddrPC.Offset = context->Rip; + frame.AddrStack.Offset = context->Rsp; + frame.AddrFrame.Offset = context->Rbp; +#else + frame.AddrPC.Offset = context->Eip; + frame.AddrStack.Offset = context->Esp; + frame.AddrFrame.Offset = context->Ebp; +#endif + frame.AddrPC.Mode = AddrModeFlat; + frame.AddrStack.Mode = AddrModeFlat; + frame.AddrFrame.Mode = AddrModeFlat; + + while ( + StackWalk ( + IMAGE_FILE_MACHINE_I386, + GetCurrentProcess (), + GetCurrentThread (), + &frame, + context, + 0, + SymFunctionTableAccess, + SymGetModuleBase, + 0 + ) + ) { + addr2line((void *) frame.AddrPC.Offset); + } + } else { +#ifdef _WIN64 + addr2line ((void *) info->ContextRecord->Rip); +#else + addr2line ((void *) info->ContextRecord->Eip); +#endif } - fclose (f); + return EXCEPTION_CONTINUE_SEARCH; } #endif @@ -282,7 +338,11 @@ set_backtrace_file (boost::filesystem::path p) backtrace_file = p; } -/* From http://stackoverflow.com/questions/2443135/how-do-i-find-where-an-exception-was-thrown-in-c */ +/** This is called when there is an unhandled exception. Any + * backtrace in this function is useless on Windows as the stack has + * already been unwound from the throw; we have the gdb wrap hack to + * cope with that. + */ void terminate () { |
