1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// found in the LICENSE file. 4513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 5513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/debug/stack_trace.h" 6513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 7513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include <errno.h> 83f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include <execinfo.h> 9513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include <fcntl.h> 10513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include <stdio.h> 11513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include <stdlib.h> 12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <sys/param.h> 13513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include <sys/stat.h> 14513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include <sys/sysctl.h> 15513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include <sys/types.h> 16513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include <unistd.h> 17513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 18513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include <string> 19513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include <vector> 20513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 21513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#if defined(__GLIBCXX__) 22513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include <cxxabi.h> 23513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#endif 24513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 25513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#if defined(OS_MACOSX) 26513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include <AvailabilityMacros.h> 27513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#endif 28513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 29513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include <iostream> 30513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 31513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/basictypes.h" 32513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/eintr_wrapper.h" 33513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/logging.h" 34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h" 35513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/safe_strerror_posix.h" 36513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/string_piece.h" 37513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/stringprintf.h" 38513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 39513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#if defined(USE_SYMBOLIZE) 40513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/third_party/symbolize/symbolize.h" 41513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#endif 42513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 43513209b27ff55e2841eac0e4120199c23acce758Ben Murdochnamespace base { 44513209b27ff55e2841eac0e4120199c23acce758Ben Murdochnamespace debug { 45513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 46513209b27ff55e2841eac0e4120199c23acce758Ben Murdochnamespace { 47513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 48513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// The prefix used for mangled symbols, per the Itanium C++ ABI: 49513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// http://www.codesourcery.com/cxx-abi/abi.html#mangling 50513209b27ff55e2841eac0e4120199c23acce758Ben Murdochconst char kMangledSymbolPrefix[] = "_Z"; 51513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 52513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Characters that can be used for symbols, generated by Ruby: 53513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// (('a'..'z').to_a+('A'..'Z').to_a+('0'..'9').to_a + ['_']).join 54513209b27ff55e2841eac0e4120199c23acce758Ben Murdochconst char kSymbolCharacters[] = 55513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; 56513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 57513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#if !defined(USE_SYMBOLIZE) 58513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Demangles C++ symbols in the given text. Example: 59513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// 6021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// "out/Debug/base_unittests(_ZN10StackTraceC1Ev+0x20) [0x817778c]" 61513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// => 6221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// "out/Debug/base_unittests(StackTrace::StackTrace()+0x20) [0x817778c]" 63513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid DemangleSymbols(std::string* text) { 64513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#if defined(__GLIBCXX__) 65513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 66513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::string::size_type search_from = 0; 67513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch while (search_from < text->size()) { 68513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Look for the start of a mangled symbol, from search_from. 69513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::string::size_type mangled_start = 70513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch text->find(kMangledSymbolPrefix, search_from); 71513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (mangled_start == std::string::npos) { 72513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch break; // Mangled symbol not found. 73513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 74513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 75513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Look for the end of the mangled symbol. 76513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::string::size_type mangled_end = 77513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch text->find_first_not_of(kSymbolCharacters, mangled_start); 78513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (mangled_end == std::string::npos) { 79513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch mangled_end = text->size(); 80513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 81513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::string mangled_symbol = 82513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch text->substr(mangled_start, mangled_end - mangled_start); 83513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 84513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Try to demangle the mangled symbol candidate. 85513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int status = 0; 86513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch scoped_ptr_malloc<char> demangled_symbol( 87513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch abi::__cxa_demangle(mangled_symbol.c_str(), NULL, 0, &status)); 88513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (status == 0) { // Demangling is successful. 89513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Remove the mangled symbol. 90513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch text->erase(mangled_start, mangled_end - mangled_start); 91513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Insert the demangled symbol. 92513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch text->insert(mangled_start, demangled_symbol.get()); 93513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Next time, we'll start right after the demangled symbol we inserted. 94513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch search_from = mangled_start + strlen(demangled_symbol.get()); 95513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else { 96513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Failed to demangle. Retry after the "_Z" we just found. 97513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch search_from = mangled_start + 2; 98513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 99513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 100513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 101513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#endif // defined(__GLIBCXX__) 102513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 103513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#endif // !defined(USE_SYMBOLIZE) 104513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 105513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Gets the backtrace as a vector of strings. If possible, resolve symbol 106513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// names and attach these. Otherwise just use raw addresses. Returns true 107513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// if any symbol name is resolved. Returns false on error and *may* fill 108513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// in |error_message| if an error message is available. 109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool GetBacktraceStrings(void *const *trace, int size, 110513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::vector<std::string>* trace_strings, 111513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::string* error_message) { 11234b5a0345856ab7743b6daa5a1fea1dcbe0c3394Ben Murdoch#ifdef ANDROID 11334b5a0345856ab7743b6daa5a1fea1dcbe0c3394Ben Murdoch return false; 11434b5a0345856ab7743b6daa5a1fea1dcbe0c3394Ben Murdoch#endif 115513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool symbolized = false; 116513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 117513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#if defined(USE_SYMBOLIZE) 118513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch for (int i = 0; i < size; ++i) { 119513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch char symbol[1024]; 120513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Subtract by one as return address of function may be in the next 121513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // function when a function is annotated as noreturn. 122513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (google::Symbolize(static_cast<char *>(trace[i]) - 1, 123513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch symbol, sizeof(symbol))) { 124513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Don't call DemangleSymbols() here as the symbol is demangled by 125513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // google::Symbolize(). 126513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch trace_strings->push_back( 127513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch base::StringPrintf("%s [%p]", symbol, trace[i])); 128513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch symbolized = true; 129513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else { 130513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch trace_strings->push_back(base::StringPrintf("%p", trace[i])); 131513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 132513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 133513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#else 134513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch scoped_ptr_malloc<char*> trace_symbols(backtrace_symbols(trace, size)); 135513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (trace_symbols.get()) { 136513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch for (int i = 0; i < size; ++i) { 137513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::string trace_symbol = trace_symbols.get()[i]; 138513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DemangleSymbols(&trace_symbol); 139513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch trace_strings->push_back(trace_symbol); 140513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 141513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch symbolized = true; 142513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else { 143513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (error_message) 144513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch *error_message = safe_strerror(errno); 145513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch for (int i = 0; i < size; ++i) { 146513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch trace_strings->push_back(base::StringPrintf("%p", trace[i])); 147513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 148513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 149513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#endif // defined(USE_SYMBOLIZE) 150513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 151513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return symbolized; 152513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 153513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 154513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} // namespace 155513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 156513209b27ff55e2841eac0e4120199c23acce758Ben MurdochStackTrace::StackTrace() { 15734b5a0345856ab7743b6daa5a1fea1dcbe0c3394Ben Murdoch#if (defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) || defined(ANDROID) 15834b5a0345856ab7743b6daa5a1fea1dcbe0c3394Ben Murdoch#if defined(ANDROID) 15934b5a0345856ab7743b6daa5a1fea1dcbe0c3394Ben Murdoch return; 16034b5a0345856ab7743b6daa5a1fea1dcbe0c3394Ben Murdoch#else 161513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (backtrace == NULL) { 162513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch count_ = 0; 163513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return; 164513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 16534b5a0345856ab7743b6daa5a1fea1dcbe0c3394Ben Murdoch#endif // ANDROID 166513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#endif 167513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Though the backtrace API man page does not list any possible negative 168513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // return values, we take no chance. 169513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch count_ = std::max(backtrace(trace_, arraysize(trace_)), 0); 170513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 171513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 172206cf38d173e938a20bbee623af570db81e7ff8dKristian Monsenvoid StackTrace::PrintBacktrace() const { 17334b5a0345856ab7743b6daa5a1fea1dcbe0c3394Ben Murdoch#if (defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) || defined(ANDROID) 17434b5a0345856ab7743b6daa5a1fea1dcbe0c3394Ben Murdoch#if defined(ANDROID) 17534b5a0345856ab7743b6daa5a1fea1dcbe0c3394Ben Murdoch return; 17634b5a0345856ab7743b6daa5a1fea1dcbe0c3394Ben Murdoch#else 177513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (backtrace_symbols_fd == NULL) 178513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return; 17934b5a0345856ab7743b6daa5a1fea1dcbe0c3394Ben Murdoch#endif // ANDROID 180513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#endif 181513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch fflush(stderr); 182513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::vector<std::string> trace_strings; 183513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch GetBacktraceStrings(trace_, count_, &trace_strings, NULL); 184513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch for (size_t i = 0; i < trace_strings.size(); ++i) { 185513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::cerr << "\t" << trace_strings[i] << "\n"; 186513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 187513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 188513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 189206cf38d173e938a20bbee623af570db81e7ff8dKristian Monsenvoid StackTrace::OutputToStream(std::ostream* os) const { 19034b5a0345856ab7743b6daa5a1fea1dcbe0c3394Ben Murdoch#if (defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) || defined(ANDROID) 19134b5a0345856ab7743b6daa5a1fea1dcbe0c3394Ben Murdoch#if defined(ANDROID) 19234b5a0345856ab7743b6daa5a1fea1dcbe0c3394Ben Murdoch return; 19334b5a0345856ab7743b6daa5a1fea1dcbe0c3394Ben Murdoch#else 194513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (backtrace_symbols == NULL) 195513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return; 19634b5a0345856ab7743b6daa5a1fea1dcbe0c3394Ben Murdoch#endif // ANDROID 197513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#endif 198513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::vector<std::string> trace_strings; 199513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::string error_message; 200513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (GetBacktraceStrings(trace_, count_, &trace_strings, &error_message)) { 201513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch (*os) << "Backtrace:\n"; 202513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else { 203513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!error_message.empty()) 204513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch error_message = " (" + error_message + ")"; 205513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch (*os) << "Unable to get symbols for backtrace" << error_message << ". " 206513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << "Dumping raw addresses in trace:\n"; 207513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 208513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 209513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch for (size_t i = 0; i < trace_strings.size(); ++i) { 210513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch (*os) << "\t" << trace_strings[i] << "\n"; 211513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 212513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 213513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 214513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} // namespace debug 215513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} // namespace base 216