summaryrefslogtreecommitdiffstats
path: root/src/common/BackTrace.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/BackTrace.cc')
-rw-r--r--src/common/BackTrace.cc74
1 files changed, 74 insertions, 0 deletions
diff --git a/src/common/BackTrace.cc b/src/common/BackTrace.cc
new file mode 100644
index 000000000..42a8da2ae
--- /dev/null
+++ b/src/common/BackTrace.cc
@@ -0,0 +1,74 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include <ostream>
+#include <cxxabi.h>
+#include <string.h>
+
+#include "BackTrace.h"
+#include "common/version.h"
+#include "common/Formatter.h"
+
+namespace ceph {
+
+void BackTrace::print(std::ostream& out) const
+{
+ out << " " << pretty_version_to_str() << std::endl;
+ for (size_t i = skip; i < size; i++) {
+ out << " " << (i-skip+1) << ": " << demangle(strings[i]) << std::endl;
+ }
+}
+
+void BackTrace::dump(Formatter *f) const
+{
+ f->open_array_section("backtrace");
+ for (size_t i = skip; i < size; i++) {
+ // out << " " << (i-skip+1) << ": " << strings[i] << std::endl;
+ f->dump_string("frame", demangle(strings[i]));
+ }
+ f->close_section();
+}
+
+std::string BackTrace::demangle(const char* name)
+{
+ // find the parentheses and address offset surrounding the mangled name
+#ifdef __FreeBSD__
+ static constexpr char OPEN = '<';
+#else
+ static constexpr char OPEN = '(';
+#endif
+ const char* begin = nullptr;
+ const char* end = nullptr;
+ for (const char *j = name; *j; ++j) {
+ if (*j == OPEN) {
+ begin = j + 1;
+ } else if (*j == '+') {
+ end = j;
+ }
+ }
+ if (begin && end && begin < end) {
+ std::string mangled(begin, end);
+ int status;
+ // only demangle a C++ mangled name
+ if (mangled.compare(0, 2, "_Z") == 0) {
+ // let __cxa_demangle do the malloc
+ char* demangled = abi::__cxa_demangle(mangled.c_str(), nullptr, nullptr, &status);
+ if (!status) {
+ std::string full_name{OPEN};
+ full_name += demangled;
+ full_name += end;
+ // buf could be reallocated, so free(demangled) instead
+ free(demangled);
+ return full_name;
+ }
+ // demangle failed, just pretend it's a C function with no args
+ }
+ // C function
+ return mangled + "()";
+ } else {
+ // didn't find the mangled name, just print the whole line
+ return name;
+ }
+}
+
+}