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
11221345Sdim// Unix signals occurring while your program is running.
12193323Sed//
13193323Sed//===----------------------------------------------------------------------===//
14193323Sed
15249423Sdim#include "llvm/Support/PrettyStackTrace.h"
16296417Sdim#include "llvm-c/ErrorHandling.h"
17249423Sdim#include "llvm/ADT/SmallString.h"
18210299Sed#include "llvm/Config/config.h"     // Get autoconf configuration settings
19288943Sdim#include "llvm/Support/Compiler.h"
20218893Sdim#include "llvm/Support/Signals.h"
21249423Sdim#include "llvm/Support/Watchdog.h"
22249423Sdim#include "llvm/Support/raw_ostream.h"
23210299Sed
24210299Sed#ifdef HAVE_CRASHREPORTERCLIENT_H
25210299Sed#include <CrashReporterClient.h>
26210299Sed#endif
27210299Sed
28193323Sedusing namespace llvm;
29193323Sed
30288943Sdim// If backtrace support is not enabled, compile out support for pretty stack
31288943Sdim// traces.  This has the secondary effect of not requiring thread local storage
32288943Sdim// when backtrace support is disabled.
33288943Sdim#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
34198090Srdivacky
35288943Sdim// We need a thread local pointer to manage the stack of our stack trace
36288943Sdim// objects, but we *really* cannot tolerate destructors running and do not want
37288943Sdim// to pay any overhead of synchronizing. As a consequence, we use a raw
38288943Sdim// thread-local variable.
39288943Sdimstatic LLVM_THREAD_LOCAL const PrettyStackTraceEntry *PrettyStackTraceHead =
40288943Sdim    nullptr;
41288943Sdim
42193323Sedstatic unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){
43193323Sed  unsigned NextID = 0;
44193323Sed  if (Entry->getNextEntry())
45193323Sed    NextID = PrintStack(Entry->getNextEntry(), OS);
46193323Sed  OS << NextID << ".\t";
47249423Sdim  {
48249423Sdim    sys::Watchdog W(5);
49249423Sdim    Entry->print(OS);
50249423Sdim  }
51193323Sed
52193323Sed  return NextID+1;
53193323Sed}
54193323Sed
55193323Sed/// PrintCurStackTrace - Print the current stack trace to the specified stream.
56193323Sedstatic void PrintCurStackTrace(raw_ostream &OS) {
57193323Sed  // Don't print an empty trace.
58288943Sdim  if (!PrettyStackTraceHead) return;
59193323Sed
60193323Sed  // If there are pretty stack frames registered, walk and emit them.
61193323Sed  OS << "Stack dump:\n";
62193323Sed
63288943Sdim  PrintStack(PrettyStackTraceHead, OS);
64193323Sed  OS.flush();
65193323Sed}
66193323Sed
67210299Sed// Integrate with crash reporter libraries.
68218893Sdim#if defined (__APPLE__) && HAVE_CRASHREPORTERCLIENT_H
69210299Sed//  If any clients of llvm try to link to libCrashReporterClient.a themselves,
70210299Sed//  only one crash info struct will be used.
71210299Sedextern "C" {
72210299SedCRASH_REPORTER_CLIENT_HIDDEN
73210299Sedstruct crashreporter_annotations_t gCRAnnotations
74210299Sed        __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION)))
75226633Sdim        = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0 };
76210299Sed}
77218893Sdim#elif defined (__APPLE__) && HAVE_CRASHREPORTER_INFO
78208599Srdivackystatic const char *__crashreporter_info__ = 0;
79208599Srdivackyasm(".desc ___crashreporter_info__, 0x10");
80193323Sed#endif
81193323Sed
82193323Sed
83193323Sed/// CrashHandler - This callback is run if a fatal signal is delivered to the
84193323Sed/// process, it prints the pretty stack trace.
85212904Sdimstatic void CrashHandler(void *) {
86193323Sed#ifndef __APPLE__
87193323Sed  // On non-apple systems, just emit the crash stack trace to stderr.
88193323Sed  PrintCurStackTrace(errs());
89193323Sed#else
90193323Sed  // Otherwise, emit to a smallvector of chars, send *that* to stderr, but also
91193323Sed  // put it into __crashreporter_info__.
92193323Sed  SmallString<2048> TmpStr;
93193323Sed  {
94193323Sed    raw_svector_ostream Stream(TmpStr);
95193323Sed    PrintCurStackTrace(Stream);
96193323Sed  }
97193323Sed
98193323Sed  if (!TmpStr.empty()) {
99218893Sdim#ifdef HAVE_CRASHREPORTERCLIENT_H
100212904Sdim    // Cast to void to avoid warning.
101212904Sdim    (void)CRSetCrashLogMessage(std::string(TmpStr.str()).c_str());
102218893Sdim#elif HAVE_CRASHREPORTER_INFO
103218893Sdim    __crashreporter_info__ = strdup(std::string(TmpStr.str()).c_str());
104210299Sed#endif
105198090Srdivacky    errs() << TmpStr.str();
106193323Sed  }
107193323Sed
108193323Sed#endif
109193323Sed}
110193323Sed
111288943Sdim// defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
112288943Sdim#endif
113288943Sdim
114193323SedPrettyStackTraceEntry::PrettyStackTraceEntry() {
115288943Sdim#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
116193323Sed  // Link ourselves.
117288943Sdim  NextEntry = PrettyStackTraceHead;
118288943Sdim  PrettyStackTraceHead = this;
119288943Sdim#endif
120193323Sed}
121193323Sed
122193323SedPrettyStackTraceEntry::~PrettyStackTraceEntry() {
123288943Sdim#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
124288943Sdim  assert(PrettyStackTraceHead == this &&
125193323Sed         "Pretty stack trace entry destruction is out of order");
126288943Sdim  PrettyStackTraceHead = getNextEntry();
127288943Sdim#endif
128193323Sed}
129193323Sed
130193323Sedvoid PrettyStackTraceString::print(raw_ostream &OS) const {
131193323Sed  OS << Str << "\n";
132193323Sed}
133193323Sed
134193323Sedvoid PrettyStackTraceProgram::print(raw_ostream &OS) const {
135193323Sed  OS << "Program arguments: ";
136193323Sed  // Print the argument list.
137193323Sed  for (unsigned i = 0, e = ArgC; i != e; ++i)
138193323Sed    OS << ArgV[i] << ' ';
139193323Sed  OS << '\n';
140193323Sed}
141261991Sdim
142288943Sdim#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
143261991Sdimstatic bool RegisterCrashPrinter() {
144276479Sdim  sys::AddSignalHandler(CrashHandler, nullptr);
145261991Sdim  return false;
146261991Sdim}
147288943Sdim#endif
148261991Sdim
149261991Sdimvoid llvm::EnablePrettyStackTrace() {
150288943Sdim#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
151261991Sdim  // The first time this is called, we register the crash printer.
152261991Sdim  static bool HandlerRegistered = RegisterCrashPrinter();
153261991Sdim  (void)HandlerRegistered;
154288943Sdim#endif
155261991Sdim}
156261991Sdim
157296417Sdimconst void* llvm::SavePrettyStackState() {
158296417Sdim#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
159296417Sdim  return PrettyStackTraceHead;
160296417Sdim#else
161296417Sdim  return nullptr;
162296417Sdim#endif
163296417Sdim}
164296417Sdim
165296417Sdimvoid llvm::RestorePrettyStackState(const void* Top) {
166296417Sdim#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
167296417Sdim  PrettyStackTraceHead = (const PrettyStackTraceEntry*)Top;
168296417Sdim#endif
169296417Sdim}
170296417Sdim
171261991Sdimvoid LLVMEnablePrettyStackTrace() {
172261991Sdim  EnablePrettyStackTrace();
173261991Sdim}
174