summaryrefslogtreecommitdiff
path: root/src/lib/util.cc
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2014-12-15 10:58:01 +0000
committerCarl Hetherington <cth@carlh.net>2014-12-15 10:58:01 +0000
commit815e4cf7441d83ffca6d4d797a1a313f7c6464ab (patch)
treea469fb8153fc83cc8e0b35ced4e32328d9fca8e9 /src/lib/util.cc
parent1e33ccb216e73d3ea94ed08aaa4766c856178757 (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.cc78
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 ()
{