1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/debug/stack_trace.h" 6 7 #include <errno.h> 8 #include <execinfo.h> 9 #include <fcntl.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <sys/param.h> 13 #include <sys/stat.h> 14 #include <sys/sysctl.h> 15 #include <sys/types.h> 16 #include <unistd.h> 17 18 #include <string> 19 #include <vector> 20 21 #if defined(__GLIBCXX__) 22 #include <cxxabi.h> 23 #endif 24 25 #if defined(OS_MACOSX) 26 #include <AvailabilityMacros.h> 27 #endif 28 29 #include <iostream> 30 31 #include "base/basictypes.h" 32 #include "base/eintr_wrapper.h" 33 #include "base/logging.h" 34 #include "base/memory/scoped_ptr.h" 35 #include "base/safe_strerror_posix.h" 36 #include "base/string_piece.h" 37 #include "base/stringprintf.h" 38 39 #if defined(USE_SYMBOLIZE) 40 #include "base/third_party/symbolize/symbolize.h" 41 #endif 42 43 namespace base { 44 namespace debug { 45 46 namespace { 47 48 // The prefix used for mangled symbols, per the Itanium C++ ABI: 49 // http://www.codesourcery.com/cxx-abi/abi.html#mangling 50 const char kMangledSymbolPrefix[] = "_Z"; 51 52 // Characters that can be used for symbols, generated by Ruby: 53 // (('a'..'z').to_a+('A'..'Z').to_a+('0'..'9').to_a + ['_']).join 54 const char kSymbolCharacters[] = 55 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; 56 57 #if !defined(USE_SYMBOLIZE) 58 // Demangles C++ symbols in the given text. Example: 59 // 60 // "out/Debug/base_unittests(_ZN10StackTraceC1Ev+0x20) [0x817778c]" 61 // => 62 // "out/Debug/base_unittests(StackTrace::StackTrace()+0x20) [0x817778c]" 63 void DemangleSymbols(std::string* text) { 64 #if defined(__GLIBCXX__) 65 66 std::string::size_type search_from = 0; 67 while (search_from < text->size()) { 68 // Look for the start of a mangled symbol, from search_from. 69 std::string::size_type mangled_start = 70 text->find(kMangledSymbolPrefix, search_from); 71 if (mangled_start == std::string::npos) { 72 break; // Mangled symbol not found. 73 } 74 75 // Look for the end of the mangled symbol. 76 std::string::size_type mangled_end = 77 text->find_first_not_of(kSymbolCharacters, mangled_start); 78 if (mangled_end == std::string::npos) { 79 mangled_end = text->size(); 80 } 81 std::string mangled_symbol = 82 text->substr(mangled_start, mangled_end - mangled_start); 83 84 // Try to demangle the mangled symbol candidate. 85 int status = 0; 86 scoped_ptr_malloc<char> demangled_symbol( 87 abi::__cxa_demangle(mangled_symbol.c_str(), NULL, 0, &status)); 88 if (status == 0) { // Demangling is successful. 89 // Remove the mangled symbol. 90 text->erase(mangled_start, mangled_end - mangled_start); 91 // Insert the demangled symbol. 92 text->insert(mangled_start, demangled_symbol.get()); 93 // Next time, we'll start right after the demangled symbol we inserted. 94 search_from = mangled_start + strlen(demangled_symbol.get()); 95 } else { 96 // Failed to demangle. Retry after the "_Z" we just found. 97 search_from = mangled_start + 2; 98 } 99 } 100 101 #endif // defined(__GLIBCXX__) 102 } 103 #endif // !defined(USE_SYMBOLIZE) 104 105 // Gets the backtrace as a vector of strings. If possible, resolve symbol 106 // names and attach these. Otherwise just use raw addresses. Returns true 107 // if any symbol name is resolved. Returns false on error and *may* fill 108 // in |error_message| if an error message is available. 109 bool GetBacktraceStrings(void *const *trace, int size, 110 std::vector<std::string>* trace_strings, 111 std::string* error_message) { 112 #ifdef ANDROID 113 return false; 114 #endif 115 bool symbolized = false; 116 117 #if defined(USE_SYMBOLIZE) 118 for (int i = 0; i < size; ++i) { 119 char symbol[1024]; 120 // Subtract by one as return address of function may be in the next 121 // function when a function is annotated as noreturn. 122 if (google::Symbolize(static_cast<char *>(trace[i]) - 1, 123 symbol, sizeof(symbol))) { 124 // Don't call DemangleSymbols() here as the symbol is demangled by 125 // google::Symbolize(). 126 trace_strings->push_back( 127 base::StringPrintf("%s [%p]", symbol, trace[i])); 128 symbolized = true; 129 } else { 130 trace_strings->push_back(base::StringPrintf("%p", trace[i])); 131 } 132 } 133 #else 134 scoped_ptr_malloc<char*> trace_symbols(backtrace_symbols(trace, size)); 135 if (trace_symbols.get()) { 136 for (int i = 0; i < size; ++i) { 137 std::string trace_symbol = trace_symbols.get()[i]; 138 DemangleSymbols(&trace_symbol); 139 trace_strings->push_back(trace_symbol); 140 } 141 symbolized = true; 142 } else { 143 if (error_message) 144 *error_message = safe_strerror(errno); 145 for (int i = 0; i < size; ++i) { 146 trace_strings->push_back(base::StringPrintf("%p", trace[i])); 147 } 148 } 149 #endif // defined(USE_SYMBOLIZE) 150 151 return symbolized; 152 } 153 154 } // namespace 155 156 StackTrace::StackTrace() { 157 #if (defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) || defined(ANDROID) 158 #if defined(ANDROID) 159 return; 160 #else 161 if (backtrace == NULL) { 162 count_ = 0; 163 return; 164 } 165 #endif // ANDROID 166 #endif 167 // Though the backtrace API man page does not list any possible negative 168 // return values, we take no chance. 169 count_ = std::max(backtrace(trace_, arraysize(trace_)), 0); 170 } 171 172 void StackTrace::PrintBacktrace() const { 173 #if (defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) || defined(ANDROID) 174 #if defined(ANDROID) 175 return; 176 #else 177 if (backtrace_symbols_fd == NULL) 178 return; 179 #endif // ANDROID 180 #endif 181 fflush(stderr); 182 std::vector<std::string> trace_strings; 183 GetBacktraceStrings(trace_, count_, &trace_strings, NULL); 184 for (size_t i = 0; i < trace_strings.size(); ++i) { 185 std::cerr << "\t" << trace_strings[i] << "\n"; 186 } 187 } 188 189 void StackTrace::OutputToStream(std::ostream* os) const { 190 #if (defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) || defined(ANDROID) 191 #if defined(ANDROID) 192 return; 193 #else 194 if (backtrace_symbols == NULL) 195 return; 196 #endif // ANDROID 197 #endif 198 std::vector<std::string> trace_strings; 199 std::string error_message; 200 if (GetBacktraceStrings(trace_, count_, &trace_strings, &error_message)) { 201 (*os) << "Backtrace:\n"; 202 } else { 203 if (!error_message.empty()) 204 error_message = " (" + error_message + ")"; 205 (*os) << "Unable to get symbols for backtrace" << error_message << ". " 206 << "Dumping raw addresses in trace:\n"; 207 } 208 209 for (size_t i = 0; i < trace_strings.size(); ++i) { 210 (*os) << "\t" << trace_strings[i] << "\n"; 211 } 212 } 213 214 } // namespace debug 215 } // namespace base 216