diff options
author | evan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-14 03:01:44 +0000 |
---|---|---|
committer | evan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-14 03:01:44 +0000 |
commit | 79b6fa6123a8877eb25a600a01a8a0fd3de7560e (patch) | |
tree | 3e9d16818541dbbf8c0a40764549498d4a6d9913 /base | |
parent | 63596301ddb6f3f6192dce7e81cf5722312c1433 (diff) | |
download | chromium_src-79b6fa6123a8877eb25a600a01a8a0fd3de7560e.zip chromium_src-79b6fa6123a8877eb25a600a01a8a0fd3de7560e.tar.gz chromium_src-79b6fa6123a8877eb25a600a01a8a0fd3de7560e.tar.bz2 |
Demangle C++ symbols in stack traces for Linux.
My first Chromium linux build greeted me with a backtrace of mangled symbols
(FWIW, my /dev/shm permission was wrong). That made me write this patch.
BEFORE:
../sconsbuild/Debug/base_unittests(_ZN10StackTraceC1Ev+0x20) [0x817795e]
../sconsbuild/Debug/base_unittests(_ZN30StackTrace_OutputToStream_Test8TestBodyEv+0x18) [0x805fc98]
../sconsbuild/Debug/base_unittests(_ZN7testing4Test3RunEv+0x7e) [0x82005ea]
AFTER:
../sconsbuild/Debug/base_unittests(StackTrace::StackTrace()+0x20) [0x817778c]
../sconsbuild/Debug/base_unittests(StackTrace_OutputToStream_Test::TestBody()+0x18) [0x805fc98]
../sconsbuild/Debug/base_unittests(testing::Test::Run()+0x7e) [0x8200786]
BUG=none
TEST=manually tested. also ran base_unittests
Review URL: http://codereview.chromium.org/267074
Patch from Satoru Takabayashi <satorux@gmail.com>.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@28940 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r-- | base/debug_util_posix.cc | 67 | ||||
-rw-r--r-- | base/debug_util_unittest.cc | 9 |
2 files changed, 74 insertions, 2 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"; } } } diff --git a/base/debug_util_unittest.cc b/base/debug_util_unittest.cc index 01551d0..b9300a4 100644 --- a/base/debug_util_unittest.cc +++ b/base/debug_util_unittest.cc @@ -49,7 +49,14 @@ TEST(StackTrace, OutputToStream) { << "Expected to find start in backtrace:\n" << backtrace_message; -#else // defined(OS_MACOSX) +#elif defined(__GLIBCXX__) + + // Expect a demangled symbol. + EXPECT_TRUE(backtrace_message.find("testing::Test::Run()") != + std::string::npos) + << "Expected a demangled symbol in backtrace:\n" + << backtrace_message; +#else // defined(__GLIBCXX__) // Expect to at least find main. EXPECT_TRUE(backtrace_message.find("main") != std::string::npos) |