2828// <http://www.gnu.org/licenses/>.
2929
3030#pragma once
31+
3132#ifndef _FBBE_GNU_STACKTRACE
3233#define _FBBE_GNU_STACKTRACE 1
3334
@@ -60,13 +61,26 @@ using stacktrace = std::pmr::stacktrace;
6061
6162#pragma GCC system_header
6263
64+ #include < charconv>
65+ #include < cstring>
66+ #include < cunistd>
67+ #include < dlfcn.h>
6368#include < limits>
69+ #include < link.h>
70+ #include < linux/limits.h>
6471#include < memory>
6572#include < new>
6673#include < sstream>
6774#include < string>
6875#include < utility>
6976
77+ #if __ELF_NATIVE_CLASS == 32
78+ #define WORD_WIDTH 8
79+ #else
80+ /* We assume 64bits. */
81+ #define WORD_WIDTH 16
82+ #endif
83+
7084#if __has_include(<compare>)
7185#include < compare>
7286#endif
@@ -96,25 +110,24 @@ int backtrace_syminfo(backtrace_state *, __UINTPTR_TYPE__ addr,
96110#endif
97111
98112#if defined(_LIBCPP_VERSION) && __has_include(<__assert>)
99- # include < __assert>
100- # define _FBBE_ASSERT (pred ) _LIBCPP_ASSERT(pred, " " )
113+ #include < __assert>
114+ #define _FBBE_ASSERT (pred ) _LIBCPP_ASSERT(pred, " " )
101115#elif defined(__GLIBCXX__)
102- # define _FBBE_ASSERT (pred ) __glibcxx_assert(pred)
116+ #define _FBBE_ASSERT (pred ) __glibcxx_assert(pred)
103117#else
104- # include < cassert>
105- # define _FBBE_ASSERT (pred ) (assert ((pred)))
118+ #include < cassert>
119+ #define _FBBE_ASSERT (pred ) (assert ((pred)))
106120#endif
107121
108- #if defined(__GLIBCXX__) || ((defined(__MINGW32__) || defined(__CYGWIN__)) && !defined(__clang__))
109- #define _FBBE_TRY __try
110- #define _FBBE_CATCH (x ) __catch(x)
122+ #if defined(__GLIBCXX__) || \
123+ ((defined (__MINGW32__) || defined (__CYGWIN__)) && !defined (__clang__))
124+ #define _FBBE_TRY __try
125+ #define _FBBE_CATCH (x ) __catch(x)
111126#else
112- #define _FBBE_TRY try
113- #define _FBBE_CATCH (x ) catch (x)
127+ #define _FBBE_TRY try
128+ #define _FBBE_CATCH (x ) catch (x)
114129#endif
115130
116-
117-
118131namespace __cxxabiv1 {
119132extern " C" char *__cxa_demangle (const char *__mangled_name,
120133 char *__output_buffer, size_t *__length,
@@ -224,13 +237,34 @@ class stacktrace_entry {
224237 static void _S_err_handler (void *, const char *, int ) {}
225238
226239 static backtrace_state *_S_init () {
227- static backtrace_state *__state =
228- backtrace_create_state (nullptr , 1 , _S_err_handler, nullptr );
240+ static backtrace_state *__state = []() {
241+ auto getpath = []() -> std::string {
242+ char buf[PATH_MAX + 1 ];
243+ if (readlink (" /proc/self/exe" , buf, sizeof (buf) - 1 ) == -1 ) {
244+ return " " ;
245+ }
246+ std::string str (buf);
247+ return str.substr (0 , str.rfind (' /' ));
248+ };
249+
250+ auto exec_filename = getpath ();
251+ return backtrace_create_state (exec_filename.c_str (), 1 , _S_err_handler,
252+ nullptr );
253+ }();
229254 return __state;
230255 }
231256
232257 friend std::ostream &operator <<(std::ostream &, const stacktrace_entry &);
233258
259+ std::string _symbol (uintptr_t const pc) const {
260+ Dl_info info;
261+ int status;
262+ link_map *map;
263+ status = dladdr1 ((void const *)(pc), &info, reinterpret_cast <void **>(&map),
264+ RTLD_DL_LINKMAP);
265+ return std::string (info.dli_fname ?: " " );
266+ }
267+
234268 bool _M_get_info (std::string *__desc, std::string *__file,
235269 int *__line) const {
236270 if (!*this )
@@ -687,9 +721,7 @@ template <typename _Allocator> class basic_stacktrace {
687721 return nullptr ;
688722 _M_frames = static_cast <pointer>(__p);
689723 } else {
690- _FBBE_TRY {
691- _M_frames = __alloc.allocate (__n);
692- }
724+ _FBBE_TRY { _M_frames = __alloc.allocate (__n); }
693725 _FBBE_CATCH (const std::bad_alloc &) { return nullptr ; }
694726 }
695727 _M_capacity = __n;
@@ -706,7 +738,7 @@ template <typename _Allocator> class basic_stacktrace {
706738 _FBBE_GNU_OPERATOR_DELETE (static_cast <void *>(_M_frames),
707739 _M_capacity * sizeof (value_type));
708740#else
709- _FBBE_GNU_OPERATOR_DELETE (static_cast <void *>(_M_frames));
741+ _FBBE_GNU_OPERATOR_DELETE (static_cast <void *>(_M_frames));
710742#endif
711743 else
712744 __alloc.deallocate (_M_frames, _M_capacity);
@@ -803,7 +835,8 @@ inline std::ostream &operator<<(std::ostream &__os,
803835 int __line;
804836 if (__f._M_get_info (&__desc, &__file, &__line)) {
805837 __os.width (4 );
806- __os << __desc << " at " << __file << ' :' << __line;
838+ __os << __f._symbol (__f._M_pc ) << " (" << __desc << " ) at " << __file << ' :'
839+ << __line;
807840 }
808841 return __os;
809842}
0 commit comments