diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2017-02-09 10:37:25 +0100 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2017-02-09 10:37:25 +0100 |
commit | c71f4dc97b8927cc5690454006b8aa6136dbcce2 (patch) | |
tree | 56be72a32956eefbf2bcb6697239b6ebd9427aec /sal | |
parent | 8458ec8c9c93c8b3a6045c2b45cecadd345bbf4d (diff) |
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
Diffstat (limited to 'sal')
-rw-r--r-- | sal/osl/unx/backtrace.c | 20 | ||||
-rw-r--r-- | sal/osl/unx/backtrace.h | 2 | ||||
-rw-r--r-- | sal/osl/unx/backtraceapi.cxx | 43 |
3 files changed, 62 insertions, 3 deletions
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 <sal/config.h> +#include <cassert> +#include <cstdlib> +#include <memory> + +#include <o3tl/runtimetooustring.hxx> +#include <rtl/ustrbuf.hxx> #include <rtl/ustring.hxx> + +#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<void *[]>(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: */ |