From c71f4dc97b8927cc5690454006b8aa6136dbcce2 Mon Sep 17 00:00:00 2001 From: Stephan Bergmann Date: Thu, 9 Feb 2017 10:37:25 +0100 Subject: Implement SAL_DEBUG_BACKTRACE for Linux ...by using glibc's backtrace_symbols(3). If this is ever implemented for other platforms, backtrace_symbols' interface may turn out to be awkward; but just use it directly for now. Also, the output from backtrace_symbols isn't too useful in itself, as for non-exported symbols it only prints soname+offset, but some addr2line postprocessing can turn that into something half-way decent. Change-Id: I58cc7912aa7d8031729fc116a82a409c1c16977a --- sal/osl/unx/backtrace.c | 20 ++++++++++++++++++++ sal/osl/unx/backtrace.h | 2 ++ sal/osl/unx/backtraceapi.cxx | 43 ++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 62 insertions(+), 3 deletions(-) (limited to 'sal') diff --git a/sal/osl/unx/backtrace.c b/sal/osl/unx/backtrace.c index 1945f0315b99..b32fbefb3ffc 100644 --- a/sal/osl/unx/backtrace.c +++ b/sal/osl/unx/backtrace.c @@ -94,6 +94,11 @@ int backtrace( void **buffer, int max_frames ) return i; } +char ** backtrace_symbols(void * const * buffer, int size) +{ + return NULL; /*TODO*/ +} + void backtrace_symbols_fd( void **buffer, int size, int fd ) { FILE *fp = fdopen( fd, "w" ); @@ -171,6 +176,11 @@ int backtrace( void **buffer, int max_frames ) return i; } +char ** backtrace_symbols(void * const * buffer, int size) +{ + return NULL; /*TODO*/ +} + void backtrace_symbols_fd( void **buffer, int size, int fd ) { FILE *fp = fdopen( fd, "w" ); @@ -239,6 +249,11 @@ int backtrace( void **buffer, int max_frames ) return i; } +char ** backtrace_symbols(void * const * buffer, int size) +{ + return NULL; /*TODO*/ +} + void backtrace_symbols_fd( void **buffer, int size, int fd ) { FILE *fp = fdopen( fd, "w" ); @@ -282,6 +297,11 @@ int backtrace( void **buffer, int max_frames ) return 0; } +char ** backtrace_symbols(void * const * buffer, int size) +{ + return NULL; /*TODO*/ +} + void backtrace_symbols_fd( void **buffer, int size, int fd ) { } diff --git a/sal/osl/unx/backtrace.h b/sal/osl/unx/backtrace.h index 7cc574bfb867..4695fd2d2fcc 100644 --- a/sal/osl/unx/backtrace.h +++ b/sal/osl/unx/backtrace.h @@ -28,6 +28,8 @@ extern "C" { int backtrace( void **buffer, int max_frames ); +char ** backtrace_symbols(void * const * buffer, int size); + void backtrace_symbols_fd( void **buffer, int size, int fd ); /* no frame.h on FreeBSD */ diff --git a/sal/osl/unx/backtraceapi.cxx b/sal/osl/unx/backtraceapi.cxx index c212184ceb55..267a331ae1c1 100644 --- a/sal/osl/unx/backtraceapi.cxx +++ b/sal/osl/unx/backtraceapi.cxx @@ -9,13 +9,50 @@ #include +#include +#include +#include + +#include +#include #include + +#include "backtrace.h" #include "backtraceasstring.hxx" -// FIXME: no-op for now; it needs implementing, cf. above. -OUString osl::detail::backtraceAsString(int /*maxNoStackFramesToDisplay*/) +namespace { + +struct FreeGuard { + FreeGuard(char ** theBuffer): buffer(theBuffer) {} + + ~FreeGuard() { std::free(buffer); } + + char ** buffer; +}; + +} + +OUString osl::detail::backtraceAsString(int maxNoStackFramesToDisplay) { - return OUString(); + assert(maxNoStackFramesToDisplay >= 0); + if (maxNoStackFramesToDisplay == 0) { + return OUString(); + } + auto b1 = std::unique_ptr(new void *[maxNoStackFramesToDisplay]); + int n = backtrace(b1.get(), maxNoStackFramesToDisplay); + FreeGuard b2(backtrace_symbols(b1.get(), n)); + b1.reset(); + if (b2.buffer == nullptr) { + return OUString(); + } + OUStringBuffer b3; + for (int i = 0; i != n; ++i) { + if (i != 0) { + b3.append("\n"); + } + b3.append(o3tl::runtimeToOUString(b2.buffer[i])); + } + return b3.makeStringAndClear(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit