// file : libbutl/backtrace.cxx -*- C++ -*- // 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/NetBSD requires explicitly linking -lexecinfo. // // Note that some libc implementation on Linux (most notably, musl), don't // support this, at least not out of the box. // #ifndef BUILD2_BOOTSTRAP # if defined(__GLIBC__) || \ defined(__APPLE__) || \ defined(__FreeBSD__) || \ defined(__NetBSD__) # define LIBBUTL_BACKTRACE # endif #else # if defined(__GLIBC__) || \ 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 *BSD. // 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 (); } }