diff options
author | satorux@chromium.org <satorux@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-25 10:52:28 +0000 |
---|---|---|
committer | satorux@chromium.org <satorux@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-25 10:52:28 +0000 |
commit | b84167f708bc75d06bb175850d292778426d701c (patch) | |
tree | 396662faf225ce79b3159437f600f824282bb113 /base/debug_util_posix.cc | |
parent | 5e9e3685204f9307b0b724a5064a31558e1455d5 (diff) | |
download | chromium_src-b84167f708bc75d06bb175850d292778426d701c.zip chromium_src-b84167f708bc75d06bb175850d292778426d701c.tar.gz chromium_src-b84167f708bc75d06bb175850d292778426d701c.tar.bz2 |
Import google-glog's Symbolize() and use it in debug_util_posix.cc.
Unlike glibc's backtrace_symbols(), google-glog's Symbolize() can
resolve symbols in binaries built with -fvisibility=hidden. This is
because Symbolize() uses both dynamic and regular symbols, while
backtrace_symbols() only uses dynamic symbols.
As shown below, the new backtrace is slightly less informative as it
does not have the binary name like out/Debug/base_unittests and the
distance information like +0x20, but it should be ok.
BUG=32762
TEST=out/Debug/base_unittests --gtest_filter='StackTrace*' --gtest_also_run_disabled_tests; and manually:
BEFORE
out/Debug/base_unittests(StackTrace::StackTrace()+0x20) [0x81d38f6]
out/Debug/base_unittests(StackTrace_DISABLED_DebugOutputToStream_Test::TestBody()+0x17) [0x806633d]
out/Debug/base_unittests(testing::Test::Run()+0x7a) [0x8242f96]
out/Debug/base_unittests(testing::internal::TestInfoImpl::Run()+0xb9) [0x824347b]
out/Debug/base_unittests(testing::TestCase::Run()+0xb7) [0x8243a7f]
out/Debug/base_unittests(testing::internal::UnitTestImpl::RunAllTests()+0x256) [0x824777e]
out/Debug/base_unittests(testing::UnitTest::Run()+0x14) [0x824680a]
out/Debug/base_unittests [0x8048cc5]
out/Debug/base_unittests(main+0x50) [0x80482a4]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6) [0xb6b41b56]
out/Debug/base_unittests [0x80481c1]
AFTER
% out/Debug/base_unittests --gtest_filter='*DebugOutputToStream' --gtest_also_run_disabled_tests
StackTrace::StackTrace() [0x81d3910]
StackTrace_DISABLED_DebugOutputToStream_Test::TestBody() [0x806633d]
testing::Test::Run() [0x8242f66]
testing::internal::TestInfoImpl::Run() [0x824344b]
testing::TestCase::Run() [0x8243a4f]
testing::internal::UnitTestImpl::RunAllTests() [0x824774e]
testing::UnitTest::Run() [0x82467da]
TestSuite::Run() [0x8048cc5]
main [0x80482a4]
0xb6c0db56
0x80481c1
Review URL: http://codereview.chromium.org/545148
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@36997 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/debug_util_posix.cc')
-rw-r--r-- | base/debug_util_posix.cc | 77 |
1 files changed, 61 insertions, 16 deletions
diff --git a/base/debug_util_posix.cc b/base/debug_util_posix.cc index 73b756b..a57f102 100644 --- a/base/debug_util_posix.cc +++ b/base/debug_util_posix.cc @@ -17,6 +17,7 @@ #include <cxxabi.h> #endif +#include <iostream> #include <string> #if defined(OS_MACOSX) @@ -30,6 +31,11 @@ #include "base/safe_strerror_posix.h" #include "base/scoped_ptr.h" #include "base/string_piece.h" +#include "base/string_util.h" + +#if defined(USE_SYMBOLIZE) +#include "base/third_party/symbolize/symbolize.h" +#endif namespace { // The prefix used for mangled symbols, per the Itanium C++ ABI: @@ -86,6 +92,48 @@ void DemangleSymbols(std::string* text) { #endif // defined(__GLIBCXX__) } + +// Gets the backtrace as a vector of strings. If possible, resolve symbol +// names and attach these. Otherwise just use raw addresses. Returns true +// if any symbol name is resolved. +bool GetBacktraceStrings(void **trace, int size, + std::vector<std::string>* trace_strings) { + bool symbolized = false; + +#if defined(USE_SYMBOLIZE) + for (int i = 0; i < size; ++i) { + char symbol[1024]; + // Subtract by one as return address of function may be in the next + // function when a function is annotated as noreturn. + if (google::Symbolize(static_cast<char *>(trace[i]) - 1, + symbol, sizeof(symbol))) { + // Don't call DemangleSymbols() here as the symbol is demangled by + // google::Symbolize(). + trace_strings->push_back(StringPrintf("%s [%p]", symbol, trace[i])); + symbolized = true; + } else { + trace_strings->push_back(StringPrintf("%p", trace[i])); + } + } +#else + scoped_ptr_malloc<char*> trace_symbols(backtrace_symbols(trace, size)); + if (trace_symbols.get()) { + for (int i = 0; i < size; ++i) { + std::string trace_symbol = trace_symbols.get()[i]; + DemangleSymbols(&trace_symbol); + trace_strings->push_back(trace_symbol); + } + symbolized = true; + } else { + for (int i = 0; i < size; ++i) { + trace_strings->push_back(StringPrintf("%p", trace[i])); + } + } +#endif // defined(USE_SYMBOLIZE) + + return symbolized; +} + } // namespace // static @@ -209,7 +257,11 @@ void StackTrace::PrintBacktrace() { return; #endif fflush(stderr); - backtrace_symbols_fd(trace_, count_, STDERR_FILENO); + std::vector<std::string> trace_strings; + GetBacktraceStrings(trace_, count_, &trace_strings); + for (size_t i = 0; i < trace_strings.size(); ++i) { + std::cerr << "\t" << trace_strings[i] << "\n"; + } } void StackTrace::OutputToStream(std::ostream* os) { @@ -217,22 +269,15 @@ void StackTrace::OutputToStream(std::ostream* os) { if (backtrace_symbols == NULL) return; #endif - scoped_ptr_malloc<char*> trace_symbols(backtrace_symbols(trace_, count_)); - - // If we can't retrieve the symbols, print an error and just dump the raw - // addresses. - if (trace_symbols.get() == NULL) { + std::vector<std::string> trace_strings; + if (GetBacktraceStrings(trace_, count_, &trace_strings)) { + (*os) << "Backtrace:\n"; + } else { (*os) << "Unable get symbols for backtrace (" << safe_strerror(errno) << "). Dumping raw addresses in trace:\n"; - for (int i = 0; i < count_; ++i) { - (*os) << "\t" << trace_[i] << "\n"; - } - } else { - (*os) << "Backtrace:\n"; - for (int i = 0; i < count_; ++i) { - std::string trace_symbol(trace_symbols.get()[i]); - DemangleSymbols(&trace_symbol); - (*os) << "\t" << trace_symbol << "\n"; - } + } + + for (size_t i = 0; i < trace_strings.size(); ++i) { + (*os) << "\t" << trace_strings[i] << "\n"; } } |