summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Göttsche <cgzones@googlemail.com>2021-05-16 20:45:09 +0200
committerBenBE <BenBE@geshi.org>2021-09-21 09:06:30 +0200
commit29e1fcfa0517a7c5770b2a95fe7fbc0bc197c360 (patch)
tree2a927ead2f563394123c8d9b239b07e5af9a4614
parent29983ff83a7f2c900fadb10e6cb570d167df2d80 (diff)
Use libunwind for printing backtrace
-rw-r--r--CRT.c77
-rw-r--r--configure.ac36
2 files changed, 101 insertions, 12 deletions
diff --git a/CRT.c b/CRT.c
index 2533f613..5f1d5dd0 100644
--- a/CRT.c
+++ b/CRT.c
@@ -21,14 +21,22 @@ in the source distribution for its full text.
#include "ProvideCurses.h"
#include "XUtils.h"
-#ifdef HAVE_EXECINFO_H
-#include <execinfo.h>
-#endif
-
#if !defined(NDEBUG) && defined(HAVE_MEMFD_CREATE)
#include <sys/mman.h>
#endif
+#if defined(HAVE_LIBUNWIND_H) && defined(HAVE_LIBUNWIND)
+# define PRINT_BACKTRACE
+# define UNW_LOCAL_ONLY
+# include <libunwind.h>
+# if defined(HAVE_DLADDR)
+# include <dlfcn.h>
+# endif
+#elif defined(HAVE_EXECINFO_H)
+# define PRINT_BACKTRACE
+# include <execinfo.h>
+#endif
+
#define ColorIndex(i,j) ((7-(i))*8+(j))
@@ -1008,6 +1016,59 @@ void CRT_setColors(int colorScheme) {
CRT_colors = CRT_colorSchemes[colorScheme];
}
+#ifdef PRINT_BACKTRACE
+static void print_backtrace(void) {
+#if defined(HAVE_LIBUNWIND_H) && defined(HAVE_LIBUNWIND)
+ unw_context_t context;
+ unw_getcontext(&context);
+
+ unw_cursor_t cursor;
+ unw_init_local(&cursor, &context);
+
+ unsigned int item = 0;
+
+ while (unw_step(&cursor) > 0) {
+ unw_word_t pc;
+ unw_get_reg(&cursor, UNW_REG_IP, &pc);
+ if (pc == 0)
+ break;
+
+ char symbolName[256] = "?";
+ unw_word_t offset = 0;
+ unw_get_proc_name(&cursor, symbolName, sizeof(symbolName), &offset);
+
+ unw_proc_info_t pip;
+ pip.unwind_info = NULL;
+
+ const char* fname = "?";
+ const void* ptr = 0;
+ if (unw_get_proc_info(&cursor, &pip) == 0) {
+ ptr = (const void*)(pip.start_ip + offset);
+
+ #ifdef HAVE_DLADDR
+ Dl_info dlinfo;
+ if (dladdr(ptr, &dlinfo) && dlinfo.dli_fname && *dlinfo.dli_fname)
+ fname = dlinfo.dli_fname;
+ #endif
+ }
+
+ const char* frame = "";
+ if (unw_is_signal_frame(&cursor) > 0)
+ frame = "{signal frame}";
+
+ fprintf(stderr, "%2u: %#14lx %s (%s+%#lx) [%p]%s%s\n", item++, pc, fname, symbolName, offset, ptr, frame ? " " : "", frame);
+ }
+#elif defined(HAVE_EXECINFO_H)
+ void* backtraceArray[256];
+
+ size_t size = backtrace(backtraceArray, ARRAYSIZE(backtraceArray));
+ backtrace_symbols_fd(backtraceArray, size, STDERR_FILENO);
+#else
+#error No implementation for print_backtrace()!
+#endif
+}
+#endif
+
void CRT_handleSIGSEGV(int signal) {
CRT_done();
@@ -1022,7 +1083,7 @@ void CRT_handleSIGSEGV(int signal) {
" - Likely steps to reproduce (How did it happen?)\n"
);
-#ifdef HAVE_EXECINFO_H
+#ifdef PRINT_BACKTRACE
fprintf(stderr, " - Backtrace of the issue (see below)\n");
#endif
@@ -1048,16 +1109,14 @@ void CRT_handleSIGSEGV(int signal) {
Settings_write(CRT_crashSettings, true);
fprintf(stderr, "\n\n");
-#ifdef HAVE_EXECINFO_H
+#ifdef PRINT_BACKTRACE
fprintf(stderr,
"Backtrace information:\n"
"----------------------\n"
);
- void* backtraceArray[256];
+ print_backtrace();
- size_t size = backtrace(backtraceArray, ARRAYSIZE(backtraceArray));
- backtrace_symbols_fd(backtraceArray, size, STDERR_FILENO);
fprintf(stderr,
"\n"
"To make the above information more practical to work with, "
diff --git a/configure.ac b/configure.ac
index e93afbd9..b6361ead 100644
--- a/configure.ac
+++ b/configure.ac
@@ -253,6 +253,7 @@ AC_SEARCH_LIBS([clock_gettime], [rt])
AC_CHECK_FUNCS([ \
clock_gettime \
+ dladdr \
faccessat \
fstatat \
host_get_clock_service \
@@ -261,9 +262,6 @@ AC_CHECK_FUNCS([ \
readlinkat \
])
-# Add -lexecinfo if needed
-AC_SEARCH_LIBS([backtrace], [execinfo])
-
if test "$my_htop_platform" = darwin; then
AC_CHECK_FUNCS([mach_timebase_info])
fi
@@ -409,6 +407,36 @@ if test "x$enable_affinity" = xyes; then
fi
+AC_ARG_ENABLE([unwind],
+ [AS_HELP_STRING([--enable-unwind],
+ [enable unwind support for printing backtraces; requires libunwind @<:@default=check@:>@])],
+ [],
+ [enable_unwind=check])
+case "$enable_unwind" in
+ check)
+ enable_unwind=yes
+ if test "$enable_static" = yes; then
+ AC_CHECK_LIB([lzma], [lzma_index_buffer_decode])
+ fi
+ AC_CHECK_LIB([unwind], [backtrace], [], [enable_unwind=no])
+ AC_CHECK_HEADERS([libunwind.h], [], [enable_unwind=no])
+ ;;
+ no)
+ ;;
+ yes)
+ AC_CHECK_LIB([unwind], [backtrace], [], [AC_MSG_ERROR([can not find required library libunwind])])
+ AC_CHECK_HEADERS([libunwind.h], [], [AC_MSG_ERROR([can not find require header file libunwind.h])])
+ ;;
+ *)
+ AC_MSG_ERROR([bad value '$enable_unwind' for --enable-unwind])
+ ;;
+esac
+if test "x$enable_unwind" = xno; then
+ # Fall back to backtrace(3) and add -lexecinfo if needed
+ AC_SEARCH_LIBS([backtrace], [execinfo])
+fi
+
+
AC_ARG_ENABLE([hwloc],
[AS_HELP_STRING([--enable-hwloc],
[enable hwloc support for CPU affinity; disables affinity support; requires libhwloc @<:@default=no@:>@])],
@@ -426,6 +454,7 @@ case "$enable_hwloc" in
;;
esac
+
AC_ARG_WITH([os-release],
[AS_HELP_STRING([--with-os-release=FILE],
[location of an os-release file @<:@default=/etc/os-release@:>@])],
@@ -715,6 +744,7 @@ AC_MSG_RESULT([
(Linux) capabilities: $enable_capabilities
unicode: $enable_unicode
affinity: $enable_affinity
+ unwind: $enable_unwind
hwloc: $enable_hwloc
debug: $enable_debug
static: $enable_static

© 2014-2024 Faster IT GmbH | imprint | privacy policy