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