aboutsummaryrefslogtreecommitdiff
path: root/libbutl/backtrace.cxx
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2019-05-27 22:43:59 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2019-05-28 16:00:00 +0300
commitebeea3fa9992d5ceb71806b24ae94c8601638717 (patch)
tree4167dc1ca41c7b84d6d4d89c57c3020560d353da /libbutl/backtrace.cxx
parenta8582e25936da4343966c91761d686c4933e3f6b (diff)
Add backtrace()
Diffstat (limited to 'libbutl/backtrace.cxx')
-rw-r--r--libbutl/backtrace.cxx101
1 files changed, 101 insertions, 0 deletions
diff --git a/libbutl/backtrace.cxx b/libbutl/backtrace.cxx
new file mode 100644
index 0000000..7a8d615
--- /dev/null
+++ b/libbutl/backtrace.cxx
@@ -0,0 +1,101 @@
+// file : libbutl/backtrace.cxx -*- C++ -*-
+// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#ifndef __cpp_modules_ts
+#include <libbutl/backtrace.mxx>
+#endif
+
+// We only enable backtrace during bootstrap if we can do it without any
+// complications of the build scripts/makefiles.
+//
+// With glibc linking with -rdynamic gives (non-static) function names.
+// FreeBSD requires explicitly linking -lexecinfo.
+//
+#ifndef BUILD2_BOOTSTRAP
+# if defined(__linux__) || \
+ defined(__APPLE__) || \
+ defined(__FreeBSD__)
+# define LIBBUTL_BACKTRACE
+# endif
+#else
+# if defined(__linux__) || \
+ defined(__APPLE__)
+# define LIBBUTL_BACKTRACE
+# endif
+#endif
+
+#ifdef LIBBUTL_BACKTRACE
+# include <stdlib.h> // free()
+# include <execinfo.h>
+#endif
+
+#include <cassert>
+
+#ifndef __cpp_lib_modules_ts
+#include <string>
+
+#ifdef LIBBUTL_BACKTRACE
+# include <memory> // unique_ptr
+# include <cstddef> // size_t
+#endif
+
+#include <exception>
+#endif
+
+// Other includes.
+
+#ifdef __cpp_modules_ts
+module butl.backtrace;
+
+// Only imports additional to interface.
+#ifdef __clang__
+#ifdef __cpp_lib_modules_ts
+import std.core;
+#endif
+#endif
+
+#endif
+
+using namespace std;
+
+namespace butl
+{
+ string
+ backtrace () noexcept
+ try
+ {
+ string r;
+
+#ifdef LIBBUTL_BACKTRACE
+
+ // Note: backtrace() returns int on Linux and MacOS and size_t on FreeBSD.
+ //
+ void* buf[1024];
+ auto n (::backtrace (buf, 1024));
+
+ assert (n >= 0);
+
+ char** fs (backtrace_symbols (buf, n)); // Note: returns NULL on error.
+
+ if (fs != nullptr)
+ {
+ unique_ptr<char*, void (*)(char**)> deleter (
+ fs, [] (char** s) {::free (s);});
+
+ for (size_t i (0); i != static_cast<size_t> (n); ++i)
+ {
+ r += fs[i];
+ r += '\n';
+ }
+ }
+
+#endif
+
+ return r;
+ }
+ catch (const std::exception&)
+ {
+ return string ();
+ }
+}