diff --git a/components/common/cpp/src/exception.cpp b/components/common/cpp/src/exception.cpp
index cf74b297ab3218a0786b66127c96ec4cc7d64ea1..46897adea1ef16ffa739a8fda961fd9d5fc6f70f 100644
--- a/components/common/cpp/src/exception.cpp
+++ b/components/common/cpp/src/exception.cpp
@@ -3,40 +3,84 @@
 #define LOGURU_REPLACE_GLOG 1
 #include <loguru.hpp>
 
-#ifndef WIN32
+#ifdef __GNUC__
 #include <execinfo.h>
+#include <dlfcn.h>
+#include <cxxabi.h>
 #endif
 
 using ftl::exception;
 using std::string;
 
-static std::string getBackTrace() {
-#ifndef WIN32
+static std::string demangle(const char* name) {
+	if (!name) {
+		return "[unknown symbol]";
+	}
+#ifdef __GNUC__
+	int status;
+	char* demangled = abi::__cxa_demangle(name, NULL, 0, &status);
+	if (!demangled) {
+		return std::string(name);
+	}
+	else {
+		auto result = string(demangled);
+		free(demangled);
+		return result;
+	}
+#else
+	return std::string(name);
+#endif
+}
 
+static std::string addr_to_string(const void* addr) {
+	std::stringstream ss;
+	ss << addr;
+	return ss.str();
+}
+
+static std::string getBackTrace() {
+#ifdef __GNUC__
 	string result;
-    void *trace[16];
-    int trace_size = 0;
+	void *trace[16];
+	int trace_size = 0;
+	trace_size = backtrace(trace, 16);
+	char **messages = backtrace_symbols(trace, trace_size);
 
-    trace_size = backtrace(trace, 16);
+	result = "[bt] Trace:\n";
 
-    result = "[bt] Trace:\n";
+	/* skip first stack frame (points here) */
+	for (int i=2; i < trace_size; ++i) {
+		result += string("[bt] #") + std::to_string(i-1) + string(" ");
 
-    char **messages = backtrace_symbols(trace, trace_size);
+		Dl_info info;
+		if (dladdr(trace[i], &info) && info.dli_saddr) {
+			auto name = demangle(info.dli_sname);
+			string fname = info.dli_fname ? info.dli_fname: "[unknown file]";
+
+			result += fname +
+				+ "           "
+				+ " [" + addr_to_string(info.dli_saddr) + "]" // exact address of symbol
+				+ string(", in ")
+				+ name;
+		}
+		else {
+			result += messages[i];
+		}
+		result += "\n";
+	}
 
-    /* skip first stack frame (points here) */
-    for (int i=2; i<trace_size; ++i) {
-        //printf("[bt] #%d %s\n", i, messages[i]);
-        result += string("[bt] #") + std::to_string(i-1) + string(" ") + messages[i] + string("\n");
-    }
+	free(messages);
 	return result;
 
+#elif _MSC_VER
+	return "";
 #else
 	return "";
 #endif
 }
 
 exception::exception(const char *msg) : msg_(msg), processed_(false) {
-   trace_ = std::move(getBackTrace());
+	trace_ = std::move(getBackTrace());
 }
 
 exception::exception(const ftl::Formatter &msg) : msg_(msg.str()), processed_(false) {
@@ -45,7 +89,7 @@ exception::exception(const ftl::Formatter &msg) : msg_(msg.str()), processed_(fa
 
 exception::~exception() {
 	if (!processed_) {
-		LOG(ERROR) << "Unreported exception: " << what();
+		LOG(ERROR) << "Unhandled exception: " << what();
 		LOG(ERROR) << trace_;
 	}
-}
\ No newline at end of file
+}