1 //===- PrettyStackTrace.cpp - Pretty Crash Handling -----------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file defines some helpful functions for dealing with the possibility of
10 // Unix signals occurring while your program is running.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/Support/PrettyStackTrace.h"
15 #include "llvm-c/ErrorHandling.h"
16 #include "llvm/ADT/SmallString.h"
17 #include "llvm/Config/config.h" // Get autoconf configuration settings
18 #include "llvm/Support/Compiler.h"
19 #include "llvm/Support/Signals.h"
20 #include "llvm/Support/Watchdog.h"
21 #include "llvm/Support/raw_ostream.h"
27 #ifdef HAVE_CRASHREPORTERCLIENT_H
28 #include <CrashReporterClient.h>
33 // If backtrace support is not enabled, compile out support for pretty stack
34 // traces. This has the secondary effect of not requiring thread local storage
35 // when backtrace support is disabled.
36 #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
38 // We need a thread local pointer to manage the stack of our stack trace
39 // objects, but we *really* cannot tolerate destructors running and do not want
40 // to pay any overhead of synchronizing. As a consequence, we use a raw
41 // thread-local variable.
42 static LLVM_THREAD_LOCAL PrettyStackTraceEntry
*PrettyStackTraceHead
= nullptr;
45 PrettyStackTraceEntry
*ReverseStackTrace(PrettyStackTraceEntry
*Head
) {
46 PrettyStackTraceEntry
*Prev
= nullptr;
48 std::tie(Prev
, Head
, Head
->NextEntry
) =
49 std::make_tuple(Head
, Head
->NextEntry
, Prev
);
54 static void PrintStack(raw_ostream
&OS
) {
55 // Print out the stack in reverse order. To avoid recursion (which is likely
56 // to fail if we crashed due to stack overflow), we do an up-front pass to
57 // reverse the stack, then print it, then reverse it again.
59 PrettyStackTraceEntry
*ReversedStack
=
60 llvm::ReverseStackTrace(PrettyStackTraceHead
);
61 for (const PrettyStackTraceEntry
*Entry
= ReversedStack
; Entry
;
62 Entry
= Entry
->getNextEntry()) {
67 llvm::ReverseStackTrace(ReversedStack
);
70 /// PrintCurStackTrace - Print the current stack trace to the specified stream.
71 static void PrintCurStackTrace(raw_ostream
&OS
) {
72 // Don't print an empty trace.
73 if (!PrettyStackTraceHead
) return;
75 // If there are pretty stack frames registered, walk and emit them.
76 OS
<< "Stack dump:\n";
82 // Integrate with crash reporter libraries.
83 #if defined (__APPLE__) && defined(HAVE_CRASHREPORTERCLIENT_H)
84 // If any clients of llvm try to link to libCrashReporterClient.a themselves,
85 // only one crash info struct will be used.
87 CRASH_REPORTER_CLIENT_HIDDEN
88 struct crashreporter_annotations_t gCRAnnotations
89 __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION
)))
90 #if CRASHREPORTER_ANNOTATIONS_VERSION < 5
91 = { CRASHREPORTER_ANNOTATIONS_VERSION
, 0, 0, 0, 0, 0, 0 };
93 = { CRASHREPORTER_ANNOTATIONS_VERSION
, 0, 0, 0, 0, 0, 0, 0 };
96 #elif defined(__APPLE__) && HAVE_CRASHREPORTER_INFO
97 extern "C" const char *__crashreporter_info__
98 __attribute__((visibility("hidden"))) = 0;
99 asm(".desc ___crashreporter_info__, 0x10");
102 /// CrashHandler - This callback is run if a fatal signal is delivered to the
103 /// process, it prints the pretty stack trace.
104 static void CrashHandler(void *) {
106 // On non-apple systems, just emit the crash stack trace to stderr.
107 PrintCurStackTrace(errs());
109 // Otherwise, emit to a smallvector of chars, send *that* to stderr, but also
110 // put it into __crashreporter_info__.
111 SmallString
<2048> TmpStr
;
113 raw_svector_ostream
Stream(TmpStr
);
114 PrintCurStackTrace(Stream
);
117 if (!TmpStr
.empty()) {
118 #ifdef HAVE_CRASHREPORTERCLIENT_H
119 // Cast to void to avoid warning.
120 (void)CRSetCrashLogMessage(TmpStr
.c_str());
121 #elif HAVE_CRASHREPORTER_INFO
122 __crashreporter_info__
= strdup(TmpStr
.c_str());
124 errs() << TmpStr
.str();
130 // defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
133 PrettyStackTraceEntry::PrettyStackTraceEntry() {
134 #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
136 NextEntry
= PrettyStackTraceHead
;
137 PrettyStackTraceHead
= this;
141 PrettyStackTraceEntry::~PrettyStackTraceEntry() {
142 #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
143 assert(PrettyStackTraceHead
== this &&
144 "Pretty stack trace entry destruction is out of order");
145 PrettyStackTraceHead
= NextEntry
;
149 void PrettyStackTraceString::print(raw_ostream
&OS
) const { OS
<< Str
<< "\n"; }
151 PrettyStackTraceFormat::PrettyStackTraceFormat(const char *Format
, ...) {
153 va_start(AP
, Format
);
154 const int SizeOrError
= vsnprintf(nullptr, 0, Format
, AP
);
156 if (SizeOrError
< 0) {
160 const int Size
= SizeOrError
+ 1; // '\0'
162 va_start(AP
, Format
);
163 vsnprintf(Str
.data(), Size
, Format
, AP
);
167 void PrettyStackTraceFormat::print(raw_ostream
&OS
) const { OS
<< Str
<< "\n"; }
169 void PrettyStackTraceProgram::print(raw_ostream
&OS
) const {
170 OS
<< "Program arguments: ";
171 // Print the argument list.
172 for (unsigned i
= 0, e
= ArgC
; i
!= e
; ++i
)
173 OS
<< ArgV
[i
] << ' ';
177 #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
178 static bool RegisterCrashPrinter() {
179 sys::AddSignalHandler(CrashHandler
, nullptr);
184 void llvm::EnablePrettyStackTrace() {
185 #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
186 // The first time this is called, we register the crash printer.
187 static bool HandlerRegistered
= RegisterCrashPrinter();
188 (void)HandlerRegistered
;
192 const void *llvm::SavePrettyStackState() {
193 #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
194 return PrettyStackTraceHead
;
200 void llvm::RestorePrettyStackState(const void *Top
) {
201 #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
202 PrettyStackTraceHead
=
203 static_cast<PrettyStackTraceEntry
*>(const_cast<void *>(Top
));
207 void LLVMEnablePrettyStackTrace() {
208 EnablePrettyStackTrace();