--- /dev/null
+#include <string>
+#if !defined(_WIN32) && defined(__GLIBC__)
+#include <dlfcn.h>
+#endif
+#include "backtrace.h"
+#include "exceptiontrace.h"
+
+using namespace std;
+
+namespace {
+
+#if defined(WITH_EXCEPTION_TRACE) && !defined(_WIN32) && defined(__GLIBC__)
+typedef void CxaThrowType(void *, type_info *, void (*)(void *));
+CxaThrowType *orig_cxa_throw;
+
+struct HookThrow
+{
+ HookThrow();
+};
+
+HookThrow::HookThrow()
+{
+ void *handle = dlopen(0, RTLD_LAZY);
+ orig_cxa_throw = reinterpret_cast<CxaThrowType *>(dlvsym(handle, "__cxa_throw", "CXXABI_1.3"));
+ dlclose(handle);
+}
+
+HookThrow hook;
+#endif
+
+bool trace_enabled = false;
+
+Msp::Debug::Backtrace &get_thread_backtrace()
+{
+#if __cplusplus>=201103L
+ static thread_local Msp::Debug::Backtrace backtrace;
+#elif defined(__GNUC__)
+ static __thread Msp::Debug::Backtrace backtrace;
+#else
+ static Msp::Debug::Backtrace backtrace;
+#endif
+ return backtrace;
+}
+
+}
+
+namespace Msp {
+namespace Debug {
+
+void enable_exception_trace(bool e)
+{
+ trace_enabled = e;
+}
+
+const Backtrace &get_exception_trace()
+{
+ return get_thread_backtrace();
+}
+
+} // namespace Debug
+} // namespace Msp
+
+#if defined(WITH_EXCEPTION_TRACE) && !defined(_WIN32) && defined(__GLIBC__)
+extern "C" void __cxa_throw(void *exc, std::type_info *type, void (*dest) (void *))
+{
+ if(trace_enabled)
+ get_thread_backtrace() = Msp::Debug::Backtrace::create();
+ orig_cxa_throw(exc, type, dest);
+ std::terminate();
+}
+#endif
--- /dev/null
+#ifndef MSP_DEBUG_EXCEPTIONTRACE_H_
+#define MSP_DEBUG_EXCEPTIONTRACE_H_
+
+namespace Msp {
+namespace Debug {
+
+class Backtrace;
+
+void enable_exception_trace(bool);
+const Backtrace &get_exception_trace();
+
+} // namespace Debug
+} // namespace Msp
+
+#endif