Chromium Code Reviews| OLD | NEW | 
|---|---|
| 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "build/build_config.h" | 5 #include "build/build_config.h" | 
| 6 #include "base/debug_util.h" | 6 #include "base/debug_util.h" | 
| 7 | 7 | 
| 8 #include <errno.h> | 8 #include <errno.h> | 
| 9 #include <fcntl.h> | 9 #include <fcntl.h> | 
| 10 #include <stdio.h> | 10 #include <stdio.h> | 
| 11 #include <sys/stat.h> | 11 #include <sys/stat.h> | 
| 12 #include <sys/sysctl.h> | 12 #include <sys/sysctl.h> | 
| 13 #include <sys/types.h> | 13 #include <sys/types.h> | 
| 14 #include <unistd.h> | 14 #include <unistd.h> | 
| 15 | 15 | 
| 16 #if defined(__GLIBCXX__) | 16 #if defined(__GLIBCXX__) | 
| 17 #include <cxxabi.h> | 17 #include <cxxabi.h> | 
| 18 #endif | 18 #endif | 
| 19 | 19 | 
| 20 #include <iostream> | |
| 20 #include <string> | 21 #include <string> | 
| 21 | 22 | 
| 22 #if defined(OS_MACOSX) | 23 #if defined(OS_MACOSX) | 
| 23 #include <AvailabilityMacros.h> | 24 #include <AvailabilityMacros.h> | 
| 24 #endif | 25 #endif | 
| 25 | 26 | 
| 26 #include "base/basictypes.h" | 27 #include "base/basictypes.h" | 
| 27 #include "base/compat_execinfo.h" | 28 #include "base/compat_execinfo.h" | 
| 28 #include "base/eintr_wrapper.h" | 29 #include "base/eintr_wrapper.h" | 
| 29 #include "base/logging.h" | 30 #include "base/logging.h" | 
| 30 #include "base/safe_strerror_posix.h" | 31 #include "base/safe_strerror_posix.h" | 
| 31 #include "base/scoped_ptr.h" | 32 #include "base/scoped_ptr.h" | 
| 32 #include "base/string_piece.h" | 33 #include "base/string_piece.h" | 
| 34 #include "base/string_util.h" | |
| 35 | |
| 36 #if defined(USE_SYMBOLIZE) | |
| 37 #include "base/third_party/symbolize/symbolize.h" | |
| 
 
Evan Martin
2010/01/25 18:10:40
It seems this included file then then does
  #incl
 
satorux1
2010/01/25 21:15:50
That's a good question. I don't know the detail of
 
 | |
| 38 #endif | |
| 33 | 39 | 
| 34 namespace { | 40 namespace { | 
| 35 // The prefix used for mangled symbols, per the Itanium C++ ABI: | 41 // The prefix used for mangled symbols, per the Itanium C++ ABI: | 
| 36 // http://www.codesourcery.com/cxx-abi/abi.html#mangling | 42 // http://www.codesourcery.com/cxx-abi/abi.html#mangling | 
| 37 const char kMangledSymbolPrefix[] = "_Z"; | 43 const char kMangledSymbolPrefix[] = "_Z"; | 
| 38 | 44 | 
| 39 // Characters that can be used for symbols, generated by Ruby: | 45 // Characters that can be used for symbols, generated by Ruby: | 
| 40 // (('a'..'z').to_a+('A'..'Z').to_a+('0'..'9').to_a + ['_']).join | 46 // (('a'..'z').to_a+('A'..'Z').to_a+('0'..'9').to_a + ['_']).join | 
| 41 const char kSymbolCharacters[] = | 47 const char kSymbolCharacters[] = | 
| 42 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; | 48 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; | 
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 79 // Next time, we'll start right after the demangled symbol we inserted. | 85 // Next time, we'll start right after the demangled symbol we inserted. | 
| 80 search_from = mangled_start + strlen(demangled_symbol.get()); | 86 search_from = mangled_start + strlen(demangled_symbol.get()); | 
| 81 } else { | 87 } else { | 
| 82 // Failed to demangle. Retry after the "_Z" we just found. | 88 // Failed to demangle. Retry after the "_Z" we just found. | 
| 83 search_from = mangled_start + 2; | 89 search_from = mangled_start + 2; | 
| 84 } | 90 } | 
| 85 } | 91 } | 
| 86 | 92 | 
| 87 #endif // defined(__GLIBCXX__) | 93 #endif // defined(__GLIBCXX__) | 
| 88 } | 94 } | 
| 95 | |
| 96 // Gets the backtrace as a vector of strings. If possible, resolve symbol | |
| 97 // names and attach these. Otherwise just use raw addresses. Returns true | |
| 98 // if any symbol name is resolved. | |
| 99 bool GetBacktraceStrings(void **trace, int size, | |
| 100 std::vector<std::string>* trace_strings) { | |
| 101 bool symbolized = false; | |
| 102 | |
| 103 #if defined(USE_SYMBOLIZE) | |
| 104 for (int i = 0; i < size; ++i) { | |
| 105 char symbol[1024]; | |
| 106 // Subtract by one as return address of function may be in the next | |
| 107 // function when a function is annotated as noreturn. | |
| 108 if (google::Symbolize(static_cast<char *>(trace[i]) - 1, | |
| 109 symbol, sizeof(symbol))) { | |
| 110 // Don't call DemangleSymbols() here as the symbol is demangled by | |
| 111 // google::Symbolize(). | |
| 112 trace_strings->push_back(StringPrintf("%s [%p]", symbol, trace[i])); | |
| 113 symbolized = true; | |
| 114 } else { | |
| 115 trace_strings->push_back(StringPrintf("%p", trace[i])); | |
| 116 } | |
| 117 } | |
| 118 #else | |
| 119 scoped_ptr_malloc<char*> trace_symbols(backtrace_symbols(trace, size)); | |
| 120 if (trace_symbols.get()) { | |
| 121 for (int i = 0; i < size; ++i) { | |
| 122 std::string trace_symbol = trace_symbols.get()[i]; | |
| 123 DemangleSymbols(&trace_symbol); | |
| 124 trace_strings->push_back(trace_symbol); | |
| 125 } | |
| 126 symbolized = true; | |
| 127 } else { | |
| 128 for (int i = 0; i < size; ++i) { | |
| 129 trace_strings->push_back(StringPrintf("%p", trace[i])); | |
| 130 } | |
| 131 } | |
| 132 #endif // defined(USE_SYMBOLIZE) | |
| 133 | |
| 134 return symbolized; | |
| 135 } | |
| 136 | |
| 89 } // namespace | 137 } // namespace | 
| 90 | 138 | 
| 91 // static | 139 // static | 
| 92 bool DebugUtil::SpawnDebuggerOnProcess(unsigned /* process_id */) { | 140 bool DebugUtil::SpawnDebuggerOnProcess(unsigned /* process_id */) { | 
| 93 NOTIMPLEMENTED(); | 141 NOTIMPLEMENTED(); | 
| 94 return false; | 142 return false; | 
| 95 } | 143 } | 
| 96 | 144 | 
| 97 #if defined(OS_MACOSX) | 145 #if defined(OS_MACOSX) | 
| 98 | 146 | 
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 202 // return values, we take no chance. | 250 // return values, we take no chance. | 
| 203 count_ = std::max(backtrace(trace_, arraysize(trace_)), 0); | 251 count_ = std::max(backtrace(trace_, arraysize(trace_)), 0); | 
| 204 } | 252 } | 
| 205 | 253 | 
| 206 void StackTrace::PrintBacktrace() { | 254 void StackTrace::PrintBacktrace() { | 
| 207 #if defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 | 255 #if defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 | 
| 208 if (backtrace_symbols_fd == NULL) | 256 if (backtrace_symbols_fd == NULL) | 
| 209 return; | 257 return; | 
| 210 #endif | 258 #endif | 
| 211 fflush(stderr); | 259 fflush(stderr); | 
| 212 backtrace_symbols_fd(trace_, count_, STDERR_FILENO); | 260 std::vector<std::string> trace_strings; | 
| 261 GetBacktraceStrings(trace_, count_, &trace_strings); | |
| 262 for (size_t i = 0; i < trace_strings.size(); ++i) { | |
| 263 std::cerr << "\t" << trace_strings[i] << "\n"; | |
| 264 } | |
| 213 } | 265 } | 
| 214 | 266 | 
| 215 void StackTrace::OutputToStream(std::ostream* os) { | 267 void StackTrace::OutputToStream(std::ostream* os) { | 
| 216 #if defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 | 268 #if defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 | 
| 217 if (backtrace_symbols == NULL) | 269 if (backtrace_symbols == NULL) | 
| 218 return; | 270 return; | 
| 219 #endif | 271 #endif | 
| 220 scoped_ptr_malloc<char*> trace_symbols(backtrace_symbols(trace_, count_)); | 272 std::vector<std::string> trace_strings; | 
| 221 | 273 if (GetBacktraceStrings(trace_, count_, &trace_strings)) { | 
| 222 // If we can't retrieve the symbols, print an error and just dump the raw | 274 (*os) << "Backtrace:\n"; | 
| 223 // addresses. | 275 } else { | 
| 224 if (trace_symbols.get() == NULL) { | |
| 225 (*os) << "Unable get symbols for backtrace (" << safe_strerror(errno) | 276 (*os) << "Unable get symbols for backtrace (" << safe_strerror(errno) | 
| 226 << "). Dumping raw addresses in trace:\n"; | 277 << "). Dumping raw addresses in trace:\n"; | 
| 227 for (int i = 0; i < count_; ++i) { | 278 } | 
| 228 (*os) << "\t" << trace_[i] << "\n"; | 279 | 
| 229 } | 280 for (size_t i = 0; i < trace_strings.size(); ++i) { | 
| 230 } else { | 281 (*os) << "\t" << trace_strings[i] << "\n"; | 
| 231 (*os) << "Backtrace:\n"; | |
| 232 for (int i = 0; i < count_; ++i) { | |
| 233 std::string trace_symbol(trace_symbols.get()[i]); | |
| 234 DemangleSymbols(&trace_symbol); | |
| 235 (*os) << "\t" << trace_symbol << "\n"; | |
| 236 } | |
| 237 } | 282 } | 
| 238 } | 283 } | 
| OLD | NEW |