PrettyStackTrace.cpp revision 195098
1//===- PrettyStackTrace.cpp - Pretty Crash Handling -----------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines some helpful functions for dealing with the possibility of
11// Unix signals occuring while your program is running.
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm/Support/PrettyStackTrace.h"
16#include "llvm/Support/raw_ostream.h"
17#include "llvm/System/Signals.h"
18#include "llvm/System/ThreadLocal.h"
19#include "llvm/ADT/SmallString.h"
20using namespace llvm;
21
22// FIXME: This should be thread local when llvm supports threads.
23static sys::ThreadLocal<const PrettyStackTraceEntry> PrettyStackTraceHead;
24
25static unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){
26  unsigned NextID = 0;
27  if (Entry->getNextEntry())
28    NextID = PrintStack(Entry->getNextEntry(), OS);
29  OS << NextID << ".\t";
30  Entry->print(OS);
31
32  return NextID+1;
33}
34
35/// PrintCurStackTrace - Print the current stack trace to the specified stream.
36static void PrintCurStackTrace(raw_ostream &OS) {
37  // Don't print an empty trace.
38  if (PrettyStackTraceHead.get() == 0) return;
39
40  // If there are pretty stack frames registered, walk and emit them.
41  OS << "Stack dump:\n";
42
43  PrintStack(PrettyStackTraceHead.get(), OS);
44  OS.flush();
45}
46
47// Integrate with crash reporter.
48#ifdef __APPLE__
49extern "C" const char *__crashreporter_info__;
50const char *__crashreporter_info__ = 0;
51#endif
52
53
54/// CrashHandler - This callback is run if a fatal signal is delivered to the
55/// process, it prints the pretty stack trace.
56static void CrashHandler(void *Cookie) {
57#ifndef __APPLE__
58  // On non-apple systems, just emit the crash stack trace to stderr.
59  PrintCurStackTrace(errs());
60#else
61  // Otherwise, emit to a smallvector of chars, send *that* to stderr, but also
62  // put it into __crashreporter_info__.
63  SmallString<2048> TmpStr;
64  {
65    raw_svector_ostream Stream(TmpStr);
66    PrintCurStackTrace(Stream);
67  }
68
69  if (!TmpStr.empty()) {
70    __crashreporter_info__ = strdup(TmpStr.c_str());
71    errs() << __crashreporter_info__;
72  }
73
74#endif
75}
76
77static bool RegisterCrashPrinter() {
78  sys::AddSignalHandler(CrashHandler, 0);
79  return false;
80}
81
82PrettyStackTraceEntry::PrettyStackTraceEntry() {
83  // The first time this is called, we register the crash printer.
84  static bool HandlerRegistered = RegisterCrashPrinter();
85  HandlerRegistered = HandlerRegistered;
86
87  // Link ourselves.
88  NextEntry = PrettyStackTraceHead.get();
89  PrettyStackTraceHead.set(this);
90}
91
92PrettyStackTraceEntry::~PrettyStackTraceEntry() {
93  assert(PrettyStackTraceHead.get() == this &&
94         "Pretty stack trace entry destruction is out of order");
95  PrettyStackTraceHead.set(getNextEntry());
96}
97
98void PrettyStackTraceString::print(raw_ostream &OS) const {
99  OS << Str << "\n";
100}
101
102void PrettyStackTraceProgram::print(raw_ostream &OS) const {
103  OS << "Program arguments: ";
104  // Print the argument list.
105  for (unsigned i = 0, e = ArgC; i != e; ++i)
106    OS << ArgV[i] << ' ';
107  OS << '\n';
108}
109
110