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 |