summaryrefslogtreecommitdiff
path: root/sal
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2017-02-09 10:37:25 +0100
committerStephan Bergmann <sbergman@redhat.com>2017-02-09 10:37:25 +0100
commitc71f4dc97b8927cc5690454006b8aa6136dbcce2 (patch)
tree56be72a32956eefbf2bcb6697239b6ebd9427aec /sal
parent8458ec8c9c93c8b3a6045c2b45cecadd345bbf4d (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.c20
-rw-r--r--sal/osl/unx/backtrace.h2
-rw-r--r--sal/osl/unx/backtraceapi.cxx43
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: */