diff --git a/Makefile.am b/Makefile.am index 17c87e7b..6bd28b17 100644 --- a/Makefile.am +++ b/Makefile.am @@ -277,10 +277,11 @@ endif endif endif -src_libzmq_la_CPPFLAGS = $(CODE_COVERAGE_CPPFLAGS) -src_libzmq_la_CFLAGS = $(CODE_COVERAGE_CFLAGS) -src_libzmq_la_CXXFLAGS = @LIBZMQ_EXTRA_CXXFLAGS@ $(CODE_COVERAGE_CXXFLAGS) -src_libzmq_la_LIBADD = $(CODE_COVERAGE_LDFLAGS) +src_libzmq_la_CPPFLAGS = $(CODE_COVERAGE_CPPFLAGS) $(LIBUNWIND_CFLAGS) +src_libzmq_la_CFLAGS = $(CODE_COVERAGE_CFLAGS) $(LIBUNWIND_CFLAGS) +src_libzmq_la_CXXFLAGS = @LIBZMQ_EXTRA_CXXFLAGS@ $(CODE_COVERAGE_CXXFLAGS) \ + $(LIBUNWIND_CFLAGS) +src_libzmq_la_LIBADD = $(CODE_COVERAGE_LDFLAGS) $(LIBUNWIND_LIBS) if USE_LIBSODIUM src_libzmq_la_CPPFLAGS += ${sodium_CFLAGS} diff --git a/configure.ac b/configure.ac index bad8a18e..bb3f872b 100644 --- a/configure.ac +++ b/configure.ac @@ -632,6 +632,16 @@ else AC_SUBST(pkg_config_defines, "") fi +PKG_CHECK_MODULES(LIBUNWIND, [libunwind], + [ + AC_DEFINE(HAVE_LIBUNWIND, 1, [The libunwind library is to be used]) + AC_SUBST([LIBUNWIND_CFLAGS]) + AC_SUBST([LIBUNWIND_LIBS]) + ], + [ + AC_MSG_WARN([Cannot find libunwind]) + ]) + # Subst LIBZMQ_EXTRA_CFLAGS & CXXFLAGS & LDFLAGS AC_SUBST(LIBZMQ_EXTRA_CFLAGS) AC_SUBST(LIBZMQ_EXTRA_CXXFLAGS) diff --git a/src/err.cpp b/src/err.cpp index 8ca58e51..e2363be8 100644 --- a/src/err.cpp +++ b/src/err.cpp @@ -81,6 +81,7 @@ void zmq::zmq_abort(const char *errmsg_) RaiseException (0x40000015, EXCEPTION_NONCONTINUABLE, 1, extra_info); #else (void)errmsg_; + print_backtrace(); abort (); #endif } @@ -384,3 +385,61 @@ int zmq::wsa_error_to_errno (int errcode) } #endif + +#ifdef HAVE_LIBUNWIND + +#define UNW_LOCAL_ONLY +#include +#include +#include + +void zmq::print_backtrace (void) +{ + Dl_info dl_info; + unw_cursor_t cursor; + unw_context_t ctx; + unsigned frame_n = 0; + + unw_getcontext (&ctx); + unw_init_local (&cursor, &ctx); + + while (unw_step (&cursor) > 0) { + unw_word_t offset; + unw_proc_info_t p_info; + const char *file_name; + char *demangled_name; + char func_name[256] = ""; + void *addr; + int rc; + + if (unw_get_proc_info (&cursor, &p_info)) + break; + + addr = (void *)(p_info.start_ip + offset); + + if (dladdr (addr, &dl_info) && dl_info.dli_fname) + file_name = dl_info.dli_fname; + else + file_name = "?"; + + rc = unw_get_proc_name (&cursor, func_name, 256, &offset); + if (rc == -UNW_ENOINFO) + strcpy(func_name, "?"); + + demangled_name = abi::__cxa_demangle (func_name, NULL, NULL, &rc); + + printf ("#%u %p in %s (%s+0x%lx)\n", frame_n++, addr, file_name, + rc ? func_name : demangled_name, (unsigned long) offset); + free (demangled_name); + } + + fflush (stdout); +} + +#else + +void zmq::print_backtrace (void) +{ +} + +#endif diff --git a/src/err.hpp b/src/err.hpp index 8854fc31..0565f7f6 100644 --- a/src/err.hpp +++ b/src/err.hpp @@ -62,6 +62,7 @@ namespace zmq { const char *errno_to_string (int errno_); void zmq_abort (const char *errmsg_); + void print_backtrace (void); } #ifdef ZMQ_HAVE_WINDOWS