diff --git a/itanium/include/fbbe/stacktrace.h b/itanium/include/fbbe/stacktrace.h index b3290b1..096c53b 100644 --- a/itanium/include/fbbe/stacktrace.h +++ b/itanium/include/fbbe/stacktrace.h @@ -28,6 +28,7 @@ // . #pragma once + #ifndef _FBBE_GNU_STACKTRACE #define _FBBE_GNU_STACKTRACE 1 @@ -60,13 +61,26 @@ using stacktrace = std::pmr::stacktrace; #pragma GCC system_header +#include +#include +#include +#include #include +#include +#include #include #include #include #include #include +#if __ELF_NATIVE_CLASS == 32 +#define WORD_WIDTH 8 +#else +/* We assume 64bits. */ +#define WORD_WIDTH 16 +#endif + #if __has_include() #include #endif @@ -96,25 +110,24 @@ int backtrace_syminfo(backtrace_state *, __UINTPTR_TYPE__ addr, #endif #if defined(_LIBCPP_VERSION) && __has_include(<__assert>) -# include <__assert> -# define _FBBE_ASSERT(pred) _LIBCPP_ASSERT(pred, "") +#include <__assert> +#define _FBBE_ASSERT(pred) _LIBCPP_ASSERT(pred, "") #elif defined(__GLIBCXX__) -# define _FBBE_ASSERT(pred) __glibcxx_assert(pred) +#define _FBBE_ASSERT(pred) __glibcxx_assert(pred) #else -# include -# define _FBBE_ASSERT(pred) (assert((pred))) +#include +#define _FBBE_ASSERT(pred) (assert((pred))) #endif -#if defined(__GLIBCXX__) || ((defined(__MINGW32__) || defined(__CYGWIN__)) && !defined(__clang__)) - #define _FBBE_TRY __try - #define _FBBE_CATCH(x) __catch(x) +#if defined(__GLIBCXX__) || \ + ((defined(__MINGW32__) || defined(__CYGWIN__)) && !defined(__clang__)) +#define _FBBE_TRY __try +#define _FBBE_CATCH(x) __catch(x) #else - #define _FBBE_TRY try - #define _FBBE_CATCH(x) catch(x) +#define _FBBE_TRY try +#define _FBBE_CATCH(x) catch (x) #endif - - namespace __cxxabiv1 { extern "C" char *__cxa_demangle(const char *__mangled_name, char *__output_buffer, size_t *__length, @@ -224,13 +237,34 @@ class stacktrace_entry { static void _S_err_handler(void *, const char *, int) {} static backtrace_state *_S_init() { - static backtrace_state *__state = - backtrace_create_state(nullptr, 1, _S_err_handler, nullptr); + static backtrace_state *__state = []() { + auto getpath = []() -> std::string { + char buf[PATH_MAX + 1]; + if (readlink("/proc/self/exe", buf, sizeof(buf) - 1) == -1) { + return ""; + } + std::string str(buf); + return str.substr(0, str.rfind('/')); + }; + + auto exec_filename = getpath(); + return backtrace_create_state(exec_filename.c_str(), 1, _S_err_handler, + nullptr); + }(); return __state; } friend std::ostream &operator<<(std::ostream &, const stacktrace_entry &); + std::string _symbol(uintptr_t const pc) const { + Dl_info info; + int status; + link_map *map; + status = dladdr1((void const *)(pc), &info, reinterpret_cast(&map), + RTLD_DL_LINKMAP); + return std::string(info.dli_fname ?: ""); + } + bool _M_get_info(std::string *__desc, std::string *__file, int *__line) const { if (!*this) @@ -687,9 +721,7 @@ template class basic_stacktrace { return nullptr; _M_frames = static_cast(__p); } else { - _FBBE_TRY { - _M_frames = __alloc.allocate(__n); - } + _FBBE_TRY { _M_frames = __alloc.allocate(__n); } _FBBE_CATCH(const std::bad_alloc &) { return nullptr; } } _M_capacity = __n; @@ -706,7 +738,7 @@ template class basic_stacktrace { _FBBE_GNU_OPERATOR_DELETE(static_cast(_M_frames), _M_capacity * sizeof(value_type)); #else - _FBBE_GNU_OPERATOR_DELETE(static_cast(_M_frames)); + _FBBE_GNU_OPERATOR_DELETE(static_cast(_M_frames)); #endif else __alloc.deallocate(_M_frames, _M_capacity); @@ -803,7 +835,8 @@ inline std::ostream &operator<<(std::ostream &__os, int __line; if (__f._M_get_info(&__desc, &__file, &__line)) { __os.width(4); - __os << __desc << " at " << __file << ':' << __line; + __os << __f._symbol(__f._M_pc) << "(" << __desc << ") at " << __file << ':' + << __line; } return __os; }