summaryrefslogtreecommitdiffstats
path: root/sca-cpp/trunk/kernel/monad.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'sca-cpp/trunk/kernel/monad.hpp')
-rw-r--r--sca-cpp/trunk/kernel/monad.hpp128
1 files changed, 113 insertions, 15 deletions
diff --git a/sca-cpp/trunk/kernel/monad.hpp b/sca-cpp/trunk/kernel/monad.hpp
index 657a809c1c..b67e92ad79 100644
--- a/sca-cpp/trunk/kernel/monad.hpp
+++ b/sca-cpp/trunk/kernel/monad.hpp
@@ -26,6 +26,8 @@
* Simple monad implementations.
*/
+#include <execinfo.h>
+#include <cxxabi.h>
#include "function.hpp"
#include "string.hpp"
#include "stream.hpp"
@@ -278,38 +280,134 @@ template<typename V, typename F, typename C> const lambda<failable<V, F, C>(cons
}
/**
+ * Demangle a C++ function name.
+ */
+const string demangleFrame(const char* fun) {
+ int status;
+ char* name = abi::__cxa_demangle(fun, 0, 0, &status);
+ if (name == NULL)
+ return fun;
+ const string s = name;
+ free(name);
+ return s;
+}
+
+/**
+ * Format a backtrace frame.
+ */
+const char* formatFrameFile(const char* file) {
+ const char* s = strrchr(file, '/');
+ return s == NULL? file : s + 1;
+}
+
+const string formatFrame(const char* symbol) {
+#ifdef __clang__
+ // Mac OS X CLang/LLVM stack frame format
+ // 0 kernel-test 0x000000010d440179 _ZN7tuscany9mkfailureINS_5valueENS_6stringEiEEKNS_8failableIT_T0_T1_EERKS5_RKS6_b + 265
+ char nb[3];
+ char file[256];
+ char addr[32];
+ char fun[256];
+ char offset[16];
+ if (sscanf(symbol, "%2s %255s %31s %255s %*[+] %15s", nb, file, addr, fun, offset) == 5) {
+ char buf[1024];
+ if (debug_islogging())
+ sprintf(buf, "%.255s %.31s %.511s + %.15s", formatFrameFile(file), addr, c_str(demangleFrame(fun)), offset);
+ else
+ sprintf(buf, "%.255s %.31s", formatFrameFile(file), addr);
+ return buf;
+ }
+#else
+ // Linux GCC stack frame format
+ // ./kernel-test(_ZN7tuscany9mkfailureINS_5valueENS_6stringEiEEKNS_8failableIT_T0_T1_EERKS5_RKS6_b+0x23d) [0xb7197afd]
+ char file[256];
+ char fun[256];
+ char offset[16];
+ char addr[32];
+ if (sscanf(symbol, "%[^(]%*[(]%[^+]%*[+]%[^)]%*[)] %*[[]%[^]]%*[]]", file, fun, offset, addr) == 4) {
+ char buf[1024];
+ if (debug_islogging())
+ sprintf(buf, "%.255s %.31s %.511s + %.15s", formatFrameFile(file), addr, c_str(demangleFrame(fun)), offset);
+ else
+ sprintf(buf, "%.255s %.31s", formatFrameFile(file), addr);
+ return buf;
+ }
+ if (sscanf(symbol, "%[^(]%*[(]%*[^)]%*[)] %*[[]%[^]]%*[]]", file, addr) == 2) {
+ char buf[512];
+ sprintf(buf, "%.255s %.31s", formatFrameFile(file), addr);
+ return buf;
+ }
+ if (sscanf(symbol, "%[^(]%*[(]%*[)] %*[[]%[^]]%*[]]", file, addr) == 2) {
+ char buf[512];
+ sprintf(buf, "%.255s %.31s", formatFrameFile(file), addr);
+ return buf;
+ }
+#endif
+ return symbol;
+}
+
+/**
+ * Log backtrace frames.
+ */
+const bool logFrames(char** symbols, const int frames, const bool log) {
+ if (frames == 0)
+ return true;
+#ifdef WANT_MAINTAINER_LOG
+ if (!log)
+ debug(formatFrame(*symbols), "failable::backtrace");
+#endif
+ if (log)
+ cfailure << "failable::backtrace: " << formatFrame(*symbols) << endl;
+ return logFrames(symbols + 1, frames - 1, log);
+}
+
+/**
+ * Log a backtrace.
+ */
+const bool logBacktrace(void** callstack, const int frames, const bool log) {
+ char** symbols = backtrace_symbols(callstack, frames);
+ logFrames(symbols, frames, log);
+ free(symbols);
+ return true;
+}
+
+/**
* Returns a failable monad with a failure in it.
*/
template<typename V, typename F, typename C> const failable<V, F, C> mkfailure(const F& f, const C& c, const bool log = true) {
#ifdef WANT_MAINTAINER_LOG
- if (!log)
+ if (!log) {
+ // Log the failure
debug(f, "failable::mkfailure");
+
+ // Log the call stack
+ void* callstack[16];
+ const int frames = backtrace(callstack, 16);
+ logBacktrace(callstack, frames, log);
+ }
#endif
if (log) {
ostringstream os;
os << f;
- if (length(str(os)) != 0)
- cfailure << "failable::mkfailure" << ": " << f << " : " << c << endl;
+ if (length(str(os)) != 0) {
+ // Log the failure
+ cfailure << "failable::mkfailure: " << f << " : " << c << endl;
+
+ // Print the call stack
+ void* callstack[16];
+ const int frames = backtrace(callstack, 16);
+ logBacktrace(callstack, frames, log);
+ }
}
return failable<V, F, C>(false, f, c);
}
template<typename V, typename F> const failable<V, F> mkfailure(const F& f, const int c = -1, const bool log = true) {
-#ifdef WANT_MAINTAINER_LOG
- if (!log)
- debug(f, c, "failable::mkfailure");
-#endif
- if (log) {
- ostringstream os;
- os << f;
- if (length(str(os)) != 0)
- cfailure << "failable::mkfailure: " << str(os) << " : " << c << endl;
- }
- return failable<V, F>(false, f, c);
+ return mkfailure<V, F, int>(f, c, log);
}
template<typename V> const failable<V> mkfailure(const char* f, const int c = -1, const bool log = true) {
- return mkfailure<V, string>(string(f), c, log);
+ return mkfailure<V, string, int>(string(f), c, log);
}
template<typename V> const failable<V> mkfailure() {