PrettyStackTrace.cpp revision 208599
1193323Sed//===- PrettyStackTrace.cpp - Pretty Crash Handling -----------------------===//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed//===----------------------------------------------------------------------===//
9193323Sed//
10193323Sed// This file defines some helpful functions for dealing with the possibility of
11193323Sed// Unix signals occuring while your program is running.
12193323Sed//
13193323Sed//===----------------------------------------------------------------------===//
14193323Sed
15193323Sed#include "llvm/Support/PrettyStackTrace.h"
16193323Sed#include "llvm/Support/raw_ostream.h"
17193323Sed#include "llvm/System/Signals.h"
18195098Sed#include "llvm/System/ThreadLocal.h"
19193323Sed#include "llvm/ADT/SmallString.h"
20193323Sedusing namespace llvm;
21193323Sed
22198090Srdivackynamespace llvm {
23198090Srdivacky  bool DisablePrettyStackTrace = false;
24198090Srdivacky}
25198090Srdivacky
26193323Sed// FIXME: This should be thread local when llvm supports threads.
27195098Sedstatic sys::ThreadLocal<const PrettyStackTraceEntry> PrettyStackTraceHead;
28193323Sed
29193323Sedstatic unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){
30193323Sed  unsigned NextID = 0;
31193323Sed  if (Entry->getNextEntry())
32193323Sed    NextID = PrintStack(Entry->getNextEntry(), OS);
33193323Sed  OS << NextID << ".\t";
34193323Sed  Entry->print(OS);
35193323Sed
36193323Sed  return NextID+1;
37193323Sed}
38193323Sed
39193323Sed/// PrintCurStackTrace - Print the current stack trace to the specified stream.
40193323Sedstatic void PrintCurStackTrace(raw_ostream &OS) {
41193323Sed  // Don't print an empty trace.
42195098Sed  if (PrettyStackTraceHead.get() == 0) return;
43193323Sed
44193323Sed  // If there are pretty stack frames registered, walk and emit them.
45193323Sed  OS << "Stack dump:\n";
46193323Sed
47195098Sed  PrintStack(PrettyStackTraceHead.get(), OS);
48193323Sed  OS.flush();
49193323Sed}
50193323Sed
51193323Sed// Integrate with crash reporter.
52193323Sed#ifdef __APPLE__
53208599Srdivackystatic const char *__crashreporter_info__ = 0;
54208599Srdivackyasm(".desc ___crashreporter_info__, 0x10");
55193323Sed#endif
56193323Sed
57193323Sed
58193323Sed/// CrashHandler - This callback is run if a fatal signal is delivered to the
59193323Sed/// process, it prints the pretty stack trace.
60193323Sedstatic void CrashHandler(void *Cookie) {
61193323Sed#ifndef __APPLE__
62193323Sed  // On non-apple systems, just emit the crash stack trace to stderr.
63193323Sed  PrintCurStackTrace(errs());
64193323Sed#else
65193323Sed  // Otherwise, emit to a smallvector of chars, send *that* to stderr, but also
66193323Sed  // put it into __crashreporter_info__.
67193323Sed  SmallString<2048> TmpStr;
68193323Sed  {
69193323Sed    raw_svector_ostream Stream(TmpStr);
70193323Sed    PrintCurStackTrace(Stream);
71193323Sed  }
72193323Sed
73193323Sed  if (!TmpStr.empty()) {
74198090Srdivacky    __crashreporter_info__ = strdup(std::string(TmpStr.str()).c_str());
75198090Srdivacky    errs() << TmpStr.str();
76193323Sed  }
77193323Sed
78193323Sed#endif
79193323Sed}
80193323Sed
81193323Sedstatic bool RegisterCrashPrinter() {
82198090Srdivacky  if (!DisablePrettyStackTrace)
83198090Srdivacky    sys::AddSignalHandler(CrashHandler, 0);
84193323Sed  return false;
85193323Sed}
86193323Sed
87193323SedPrettyStackTraceEntry::PrettyStackTraceEntry() {
88193323Sed  // The first time this is called, we register the crash printer.
89193323Sed  static bool HandlerRegistered = RegisterCrashPrinter();
90193323Sed  HandlerRegistered = HandlerRegistered;
91193323Sed
92193323Sed  // Link ourselves.
93195098Sed  NextEntry = PrettyStackTraceHead.get();
94195098Sed  PrettyStackTraceHead.set(this);
95193323Sed}
96193323Sed
97193323SedPrettyStackTraceEntry::~PrettyStackTraceEntry() {
98195098Sed  assert(PrettyStackTraceHead.get() == this &&
99193323Sed         "Pretty stack trace entry destruction is out of order");
100195098Sed  PrettyStackTraceHead.set(getNextEntry());
101193323Sed}
102193323Sed
103193323Sedvoid PrettyStackTraceString::print(raw_ostream &OS) const {
104193323Sed  OS << Str << "\n";
105193323Sed}
106193323Sed
107193323Sedvoid PrettyStackTraceProgram::print(raw_ostream &OS) const {
108193323Sed  OS << "Program arguments: ";
109193323Sed  // Print the argument list.
110193323Sed  for (unsigned i = 0, e = ArgC; i != e; ++i)
111193323Sed    OS << ArgV[i] << ' ';
112193323Sed  OS << '\n';
113193323Sed}
114193323Sed
115