1 //===- PrettyStackTrace.cpp - Pretty Crash Handling -----------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines some helpful functions for dealing with the possibility of
11 // Unix signals occuring while your program is running.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/Config/config.h" // Get autoconf configuration settings
16 #include "llvm/Support/PrettyStackTrace.h"
17 #include "llvm/Support/raw_ostream.h"
18 #include "llvm/Support/Signals.h"
19 #include "llvm/Support/ThreadLocal.h"
20 #include "llvm/ADT/SmallString.h"
22 #ifdef HAVE_CRASHREPORTERCLIENT_H
23 #include <CrashReporterClient.h>
29 bool DisablePrettyStackTrace
= false;
32 // FIXME: This should be thread local when llvm supports threads.
33 static sys::ThreadLocal
<const PrettyStackTraceEntry
> PrettyStackTraceHead
;
35 static unsigned PrintStack(const PrettyStackTraceEntry
*Entry
, raw_ostream
&OS
){
37 if (Entry
->getNextEntry())
38 NextID
= PrintStack(Entry
->getNextEntry(), OS
);
39 OS
<< NextID
<< ".\t";
45 /// PrintCurStackTrace - Print the current stack trace to the specified stream.
46 static void PrintCurStackTrace(raw_ostream
&OS
) {
47 // Don't print an empty trace.
48 if (PrettyStackTraceHead
.get() == 0) return;
50 // If there are pretty stack frames registered, walk and emit them.
51 OS
<< "Stack dump:\n";
53 PrintStack(PrettyStackTraceHead
.get(), OS
);
57 // Integrate with crash reporter libraries.
58 #if defined (__APPLE__) && HAVE_CRASHREPORTERCLIENT_H
59 // If any clients of llvm try to link to libCrashReporterClient.a themselves,
60 // only one crash info struct will be used.
62 CRASH_REPORTER_CLIENT_HIDDEN
63 struct crashreporter_annotations_t gCRAnnotations
64 __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION
)))
65 = { CRASHREPORTER_ANNOTATIONS_VERSION
, 0, 0, 0, 0 };
67 #elif defined (__APPLE__) && HAVE_CRASHREPORTER_INFO
68 static const char *__crashreporter_info__
= 0;
69 asm(".desc ___crashreporter_info__, 0x10");
73 /// CrashHandler - This callback is run if a fatal signal is delivered to the
74 /// process, it prints the pretty stack trace.
75 static void CrashHandler(void *) {
77 // On non-apple systems, just emit the crash stack trace to stderr.
78 PrintCurStackTrace(errs());
80 // Otherwise, emit to a smallvector of chars, send *that* to stderr, but also
81 // put it into __crashreporter_info__.
82 SmallString
<2048> TmpStr
;
84 raw_svector_ostream
Stream(TmpStr
);
85 PrintCurStackTrace(Stream
);
88 if (!TmpStr
.empty()) {
89 #ifdef HAVE_CRASHREPORTERCLIENT_H
90 // Cast to void to avoid warning.
91 (void)CRSetCrashLogMessage(std::string(TmpStr
.str()).c_str());
92 #elif HAVE_CRASHREPORTER_INFO
93 __crashreporter_info__
= strdup(std::string(TmpStr
.str()).c_str());
95 errs() << TmpStr
.str();
101 static bool RegisterCrashPrinter() {
102 if (!DisablePrettyStackTrace
)
103 sys::AddSignalHandler(CrashHandler
, 0);
107 PrettyStackTraceEntry::PrettyStackTraceEntry() {
108 // The first time this is called, we register the crash printer.
109 static bool HandlerRegistered
= RegisterCrashPrinter();
110 (void)HandlerRegistered
;
113 NextEntry
= PrettyStackTraceHead
.get();
114 PrettyStackTraceHead
.set(this);
117 PrettyStackTraceEntry::~PrettyStackTraceEntry() {
118 assert(PrettyStackTraceHead
.get() == this &&
119 "Pretty stack trace entry destruction is out of order");
120 PrettyStackTraceHead
.set(getNextEntry());
123 void PrettyStackTraceString::print(raw_ostream
&OS
) const {
127 void PrettyStackTraceProgram::print(raw_ostream
&OS
) const {
128 OS
<< "Program arguments: ";
129 // Print the argument list.
130 for (unsigned i
= 0, e
= ArgC
; i
!= e
; ++i
)
131 OS
<< ArgV
[i
] << ' ';