1e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner//===- PrettyStackTrace.cpp - Pretty Crash Handling -----------------------===//
2e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner//
3e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner//                     The LLVM Compiler Infrastructure
4e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner//
5e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner// This file is distributed under the University of Illinois Open Source
6e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner// License. See LICENSE.TXT for details.
7e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner//
8e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner//===----------------------------------------------------------------------===//
9e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner//
10e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner// This file defines some helpful functions for dealing with the possibility of
117a2bdde0a0eebcd2125055e0eacaca040f0b766cChris Lattner// Unix signals occurring while your program is running.
12e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner//
13e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner//===----------------------------------------------------------------------===//
14e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner
15e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner#include "llvm/Support/PrettyStackTrace.h"
16d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/ADT/SmallString.h"
17d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Config/config.h"     // Get autoconf configuration settings
181f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Signals.h"
191f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/ThreadLocal.h"
20d5e1be03eda2e8036f136fdf12a5f5d9e1e684d8Nick Lewycky#include "llvm/Support/Watchdog.h"
21d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Support/raw_ostream.h"
22654dee487555a3cf21bcbca38ef5a2687fd18ea7Eric Christopher
23654dee487555a3cf21bcbca38ef5a2687fd18ea7Eric Christopher#ifdef HAVE_CRASHREPORTERCLIENT_H
24654dee487555a3cf21bcbca38ef5a2687fd18ea7Eric Christopher#include <CrashReporterClient.h>
25654dee487555a3cf21bcbca38ef5a2687fd18ea7Eric Christopher#endif
26654dee487555a3cf21bcbca38ef5a2687fd18ea7Eric Christopher
27e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattnerusing namespace llvm;
28e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner
2990bb3f3706cdf4e26df5e2c977d9232ba7b89c4eChris Lattnernamespace llvm {
3090bb3f3706cdf4e26df5e2c977d9232ba7b89c4eChris Lattner  bool DisablePrettyStackTrace = false;
3190bb3f3706cdf4e26df5e2c977d9232ba7b89c4eChris Lattner}
3290bb3f3706cdf4e26df5e2c977d9232ba7b89c4eChris Lattner
33e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner// FIXME: This should be thread local when llvm supports threads.
340b49c32c56443a41f76c415bddc226488217da2fOwen Andersonstatic sys::ThreadLocal<const PrettyStackTraceEntry> PrettyStackTraceHead;
35e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner
36d56786f79a00fd47a805a17276853ffd9dc4e921Chris Lattnerstatic unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){
37d56786f79a00fd47a805a17276853ffd9dc4e921Chris Lattner  unsigned NextID = 0;
38d56786f79a00fd47a805a17276853ffd9dc4e921Chris Lattner  if (Entry->getNextEntry())
39d56786f79a00fd47a805a17276853ffd9dc4e921Chris Lattner    NextID = PrintStack(Entry->getNextEntry(), OS);
40d56786f79a00fd47a805a17276853ffd9dc4e921Chris Lattner  OS << NextID << ".\t";
41d5e1be03eda2e8036f136fdf12a5f5d9e1e684d8Nick Lewycky  {
42d5e1be03eda2e8036f136fdf12a5f5d9e1e684d8Nick Lewycky    sys::Watchdog W(5);
43d5e1be03eda2e8036f136fdf12a5f5d9e1e684d8Nick Lewycky    Entry->print(OS);
44d5e1be03eda2e8036f136fdf12a5f5d9e1e684d8Nick Lewycky  }
45d56786f79a00fd47a805a17276853ffd9dc4e921Chris Lattner
46d56786f79a00fd47a805a17276853ffd9dc4e921Chris Lattner  return NextID+1;
47d56786f79a00fd47a805a17276853ffd9dc4e921Chris Lattner}
48d56786f79a00fd47a805a17276853ffd9dc4e921Chris Lattner
4949155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner/// PrintCurStackTrace - Print the current stack trace to the specified stream.
5049155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattnerstatic void PrintCurStackTrace(raw_ostream &OS) {
51d56786f79a00fd47a805a17276853ffd9dc4e921Chris Lattner  // Don't print an empty trace.
520b49c32c56443a41f76c415bddc226488217da2fOwen Anderson  if (PrettyStackTraceHead.get() == 0) return;
53d56786f79a00fd47a805a17276853ffd9dc4e921Chris Lattner
54e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner  // If there are pretty stack frames registered, walk and emit them.
55e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner  OS << "Stack dump:\n";
56e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner
570b49c32c56443a41f76c415bddc226488217da2fOwen Anderson  PrintStack(PrettyStackTraceHead.get(), OS);
58e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner  OS.flush();
59e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner}
60e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner
614411fbe25e9625ca4dd7c94aebc7ffd70b0e5bebEric Christopher// Integrate with crash reporter libraries.
62481d402ab03e163e180d2650fae13704858f8d81Eric Christopher#if defined (__APPLE__) && HAVE_CRASHREPORTERCLIENT_H
634411fbe25e9625ca4dd7c94aebc7ffd70b0e5bebEric Christopher//  If any clients of llvm try to link to libCrashReporterClient.a themselves,
644411fbe25e9625ca4dd7c94aebc7ffd70b0e5bebEric Christopher//  only one crash info struct will be used.
657d59a9766c1a48ea359e8014f9e7e7d01a57b593Eric Christopherextern "C" {
664411fbe25e9625ca4dd7c94aebc7ffd70b0e5bebEric ChristopherCRASH_REPORTER_CLIENT_HIDDEN
674411fbe25e9625ca4dd7c94aebc7ffd70b0e5bebEric Christopherstruct crashreporter_annotations_t gCRAnnotations
684411fbe25e9625ca4dd7c94aebc7ffd70b0e5bebEric Christopher        __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION)))
69ce4984f86e910575e2bc7045189218466e00c93aEric Christopher        = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0 };
707d59a9766c1a48ea359e8014f9e7e7d01a57b593Eric Christopher}
71481d402ab03e163e180d2650fae13704858f8d81Eric Christopher#elif defined (__APPLE__) && HAVE_CRASHREPORTER_INFO
724ef6730632f5e9e5958173b707230ff57b3c5dacDaniel Dunbarstatic const char *__crashreporter_info__ = 0;
734ef6730632f5e9e5958173b707230ff57b3c5dacDaniel Dunbarasm(".desc ___crashreporter_info__, 0x10");
7449155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner#endif
7549155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner
7649155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner
7749155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner/// CrashHandler - This callback is run if a fatal signal is delivered to the
7849155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner/// process, it prints the pretty stack trace.
79371e5774c7cc4e78338d9da9dbcdcd9bb8785c1cEric Christopherstatic void CrashHandler(void *) {
8049155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner#ifndef __APPLE__
8149155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner  // On non-apple systems, just emit the crash stack trace to stderr.
8249155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner  PrintCurStackTrace(errs());
8349155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner#else
8449155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner  // Otherwise, emit to a smallvector of chars, send *that* to stderr, but also
8549155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner  // put it into __crashreporter_info__.
8649155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner  SmallString<2048> TmpStr;
8749155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner  {
8849155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner    raw_svector_ostream Stream(TmpStr);
8949155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner    PrintCurStackTrace(Stream);
9049155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner  }
9149155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner
9249155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner  if (!TmpStr.empty()) {
93481d402ab03e163e180d2650fae13704858f8d81Eric Christopher#ifdef HAVE_CRASHREPORTERCLIENT_H
94371e5774c7cc4e78338d9da9dbcdcd9bb8785c1cEric Christopher    // Cast to void to avoid warning.
95371e5774c7cc4e78338d9da9dbcdcd9bb8785c1cEric Christopher    (void)CRSetCrashLogMessage(std::string(TmpStr.str()).c_str());
96481d402ab03e163e180d2650fae13704858f8d81Eric Christopher#elif HAVE_CRASHREPORTER_INFO
97481d402ab03e163e180d2650fae13704858f8d81Eric Christopher    __crashreporter_info__ = strdup(std::string(TmpStr.str()).c_str());
98654dee487555a3cf21bcbca38ef5a2687fd18ea7Eric Christopher#endif
99dddfd34e32ff081409e5a1c95b991a898d63dff2Daniel Dunbar    errs() << TmpStr.str();
10049155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner  }
10149155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner
10249155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner#endif
10349155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner}
10449155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner
105e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattnerstatic bool RegisterCrashPrinter() {
10690bb3f3706cdf4e26df5e2c977d9232ba7b89c4eChris Lattner  if (!DisablePrettyStackTrace)
10790bb3f3706cdf4e26df5e2c977d9232ba7b89c4eChris Lattner    sys::AddSignalHandler(CrashHandler, 0);
108e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner  return false;
109e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner}
110e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner
111e97c73354101507af0bc804c5c049a084c0c0c86Chris LattnerPrettyStackTraceEntry::PrettyStackTraceEntry() {
112e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner  // The first time this is called, we register the crash printer.
113e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner  static bool HandlerRegistered = RegisterCrashPrinter();
1148e68c3873549ca31533e2e3e40dda3a43cb79566Jeffrey Yasskin  (void)HandlerRegistered;
115e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner
116e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner  // Link ourselves.
1170b49c32c56443a41f76c415bddc226488217da2fOwen Anderson  NextEntry = PrettyStackTraceHead.get();
1180b49c32c56443a41f76c415bddc226488217da2fOwen Anderson  PrettyStackTraceHead.set(this);
119e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner}
120e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner
121e97c73354101507af0bc804c5c049a084c0c0c86Chris LattnerPrettyStackTraceEntry::~PrettyStackTraceEntry() {
1220b49c32c56443a41f76c415bddc226488217da2fOwen Anderson  assert(PrettyStackTraceHead.get() == this &&
123e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner         "Pretty stack trace entry destruction is out of order");
1240b49c32c56443a41f76c415bddc226488217da2fOwen Anderson  PrettyStackTraceHead.set(getNextEntry());
125e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner}
126e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner
127e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattnervoid PrettyStackTraceString::print(raw_ostream &OS) const {
128e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner  OS << Str << "\n";
129e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner}
130e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner
131e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattnervoid PrettyStackTraceProgram::print(raw_ostream &OS) const {
132fcba7cd630f0d974ae5ade4c1e74d6fc55e8764eChris Lattner  OS << "Program arguments: ";
133e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner  // Print the argument list.
134e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner  for (unsigned i = 0, e = ArgC; i != e; ++i)
135e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner    OS << ArgV[i] << ' ';
136e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner  OS << '\n';
137fcba7cd630f0d974ae5ade4c1e74d6fc55e8764eChris Lattner}
138