summaryrefslogtreecommitdiffstats
path: root/base/debug_util_posix.cc
diff options
context:
space:
mode:
Diffstat (limited to 'base/debug_util_posix.cc')
-rw-r--r--base/debug_util_posix.cc67
1 files changed, 66 insertions, 1 deletions
diff --git a/base/debug_util_posix.cc b/base/debug_util_posix.cc
index 4b79d73..20916a0 100644
--- a/base/debug_util_posix.cc
+++ b/base/debug_util_posix.cc
@@ -13,6 +13,12 @@
#include <sys/types.h>
#include <unistd.h>
+#if defined(__GLIBCXX__)
+#include <cxxabi.h>
+#endif
+
+#include <string>
+
#if defined(OS_MACOSX)
#include <AvailabilityMacros.h>
#endif
@@ -25,6 +31,63 @@
#include "base/scoped_ptr.h"
#include "base/string_piece.h"
+namespace {
+// The prefix used for mangled symbols, per the Itanium C++ ABI:
+// http://www.codesourcery.com/cxx-abi/abi.html#mangling
+const char kMangledSymbolPrefix[] = "_Z";
+
+// Characters that can be used for symbols, generated by Ruby:
+// (('a'..'z').to_a+('A'..'Z').to_a+('0'..'9').to_a + ['_']).join
+const char kSymbolCharacters[] =
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
+
+// Demangles C++ symbols in the given text. Example:
+//
+// "sconsbuild/Debug/base_unittests(_ZN10StackTraceC1Ev+0x20) [0x817778c]"
+// =>
+// "sconsbuild/Debug/base_unittests(StackTrace::StackTrace()+0x20) [0x817778c]"
+void DemangleSymbols(std::string* text) {
+#if defined(__GLIBCXX__)
+
+ std::string::size_type search_from = 0;
+ while (search_from < text->size()) {
+ // Look for the start of a mangled symbol, from search_from.
+ std::string::size_type mangled_start =
+ text->find(kMangledSymbolPrefix, search_from);
+ if (mangled_start == std::string::npos) {
+ break; // Mangled symbol not found.
+ }
+
+ // Look for the end of the mangled symbol.
+ std::string::size_type mangled_end =
+ text->find_first_not_of(kSymbolCharacters, mangled_start);
+ if (mangled_end == std::string::npos) {
+ mangled_end = text->size();
+ }
+ std::string mangled_symbol =
+ text->substr(mangled_start, mangled_end - mangled_start);
+
+ // Try to demangle the mangled symbol candidate.
+ int status = 0;
+ scoped_ptr_malloc<char> demangled_symbol(
+ abi::__cxa_demangle(mangled_symbol.c_str(), NULL, 0, &status));
+ if (status == 0) { // Demangling is successful.
+ // Remove the mangled symbol.
+ text->erase(mangled_start, mangled_end - mangled_start);
+ // Insert the demangled symbol.
+ text->insert(mangled_start, demangled_symbol.get());
+ // Next time, we'll start right after the demangled symbol we inserted.
+ search_from = mangled_start + strlen(demangled_symbol.get());
+ } else {
+ // Failed to demangle. Retry after the "_Z" we just found.
+ search_from = mangled_start + 2;
+ }
+ }
+
+#endif // defined(__GLIBCXX__)
+}
+} // namespace
+
// static
bool DebugUtil::SpawnDebuggerOnProcess(unsigned /* process_id */) {
NOTIMPLEMENTED();
@@ -159,7 +222,9 @@ void StackTrace::OutputToStream(std::ostream* os) {
} else {
(*os) << "Backtrace:\n";
for (int i = 0; i < count_; ++i) {
- (*os) << "\t" << trace_symbols.get()[i] << "\n";
+ std::string trace_symbol(trace_symbols.get()[i]);
+ DemangleSymbols(&trace_symbol);
+ (*os) << "\t" << trace_symbol << "\n";
}
}
}