From ebeea3fa9992d5ceb71806b24ae94c8601638717 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Mon, 27 May 2019 22:43:59 +0300 Subject: Add backtrace() --- libbutl/backtrace.cxx | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 libbutl/backtrace.cxx (limited to 'libbutl/backtrace.cxx') 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 +#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 // free() +# include +#endif + +#include + +#ifndef __cpp_lib_modules_ts +#include + +#ifdef LIBBUTL_BACKTRACE +# include // unique_ptr +# include // size_t +#endif + +#include +#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 deleter ( + fs, [] (char** s) {::free (s);}); + + for (size_t i (0); i != static_cast (n); ++i) + { + r += fs[i]; + r += '\n'; + } + } + +#endif + + return r; + } + catch (const std::exception&) + { + return string (); + } +} -- cgit v1.1